]> git.ipfire.org Git - thirdparty/krb5.git/commitdiff
Permit exporting profile file data into a buffer
authorKen Raeburn <raeburn@mit.edu>
Wed, 27 Oct 2004 00:07:20 +0000 (00:07 +0000)
committerKen Raeburn <raeburn@mit.edu>
Wed, 27 Oct 2004 00:07:20 +0000 (00:07 +0000)
* prof_file.c (profile_flush_file_data_to_buffer): New function.
* profi_init.c (profile_flush_to_buffer, profile_free_buffer): New functions.
* prof_parse.c (output_quoted_string): Use a callback instead of stdio calls.
(dump_profile): Renamed from dump_profile_to_file.  Use a callback instead of
stdio calls.
(dump_profile_to_file_cb): New function.
(profile_write_tree_file): Updated to new internal interface.
(struct prof_buf): New type.
(add_data_to_buffer, dump_profile_to_buffer_cb, profile_write_tree_to_buffer):
New functions.
* prof_int.h (profile_write_tree_to_buffer, profile_flush_file_data_to_buffer):
Declare.
* profile.hin (profile_flush_to_buffer, profile_free_buffer): Declare.
* libprofile.exports: Export profile_flush_to_buffer and profile_free_buffer.
* profile.swg (profile_flush_to_buffer): Declare.
* profile_tcl.c: Regenerated.

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@16838 dc483132-0cff-0310-8789-dd5450dbe970

src/util/profile/ChangeLog
src/util/profile/libprofile.exports
src/util/profile/prof_file.c
src/util/profile/prof_init.c
src/util/profile/prof_int.h
src/util/profile/prof_parse.c
src/util/profile/profile.hin
src/util/profile/profile.swg
src/util/profile/profile_tcl.c

index f48a24c3386658b4812d6e90daf022009259d406..1366bd4d1cbbb0063966a3082b67724a4311d42e 100644 (file)
@@ -1,3 +1,27 @@
+2004-10-26  Ken Raeburn  <raeburn@mit.edu>
+
+       Permit exporting profile file data into a buffer.
+       * prof_file.c (profile_flush_file_data_to_buffer): New function.
+       * profi_init.c (profile_flush_to_buffer, profile_free_buffer): New
+       functions.
+       * prof_parse.c (output_quoted_string): Use a callback instead of
+       stdio calls.
+       (dump_profile): Renamed from dump_profile_to_file.  Use a callback
+       instead of stdio calls.
+       (dump_profile_to_file_cb): New function.
+       (profile_write_tree_file): Updated to new internal interface.
+       (struct prof_buf): New type.
+       (add_data_to_buffer, dump_profile_to_buffer_cb,
+       profile_write_tree_to_buffer): New functions.
+       * prof_int.h (profile_write_tree_to_buffer,
+       profile_flush_file_data_to_buffer): Declare.
+       * profile.hin (profile_flush_to_buffer, profile_free_buffer):
+       Declare.
+       * libprofile.exports: Export profile_flush_to_buffer and
+       profile_free_buffer.
+       * profile.swg (profile_flush_to_buffer): Declare.
+       * profile_tcl.c: Regenerated.
+
 2004-10-22  Ken Raeburn  <raeburn@mit.edu>
 
        * prof_file.c (profile_update_file_data): When resetting flags,
index 2df95fe25579983f9758bee0b237b66fa65ae937..26db5e8983613856951e9a41c3421dab06bde236 100644 (file)
@@ -51,3 +51,5 @@ profile_update_relation
 profile_verify_node
 profile_write_tree_file
 profile_flush_to_file
+profile_flush_to_buffer
+profile_free_buffer
index 17f943a66011f074bdc186ccd41cbf1987079888..f47e5404be92b050ab9a796d697e4f5d65dd7cd1 100644 (file)
@@ -452,6 +452,17 @@ errout:
        return retval;
 }
 
+errcode_t profile_flush_file_data_to_buffer (prf_data_t data, char **bufp)
+{
+       errcode_t       retval;
+       retval = k5_mutex_lock(&data->lock);
+       if (retval)
+               return retval;
+       retval = profile_write_tree_to_buffer(data->root, bufp);
+       k5_mutex_unlock(&data->lock);
+       return retval;
+}
+
 errcode_t profile_flush_file_data(prf_data_t data)
 {
        errcode_t       retval = 0;
index 6b04d61e500a2f7d3020a6148066ae69bdba0ccb..02d61ee1f54b50f597da9f820f2decd62b972720 100644 (file)
@@ -145,6 +145,18 @@ profile_flush_to_file(profile_t profile, const_profile_filespec_t outfile)
        return 0;
 }
 
+errcode_t KRB5_CALLCONV
+profile_flush_to_buffer(profile_t profile, char **buf)
+{
+    return profile_flush_file_data_to_buffer(profile->first_file->data, buf);
+}
+
+void KRB5_CALLCONV
+profile_free_buffer(profile_t profile, char *buf)
+{
+    free(buf);
+}
+
 void KRB5_CALLCONV
 profile_abandon(profile_t profile)
 {
index 60cadbdf0910d0bd1cafc7d6eded623b2f88b03e..d2761228cb5205a0df7b597a46aeba8ee1fdb9ee 100644 (file)
@@ -99,6 +99,9 @@ errcode_t profile_parse_file
 errcode_t profile_write_tree_file
        (struct profile_node *root, FILE *dstfile);
 
+errcode_t profile_write_tree_to_buffer
+       (struct profile_node *root, char **buf);
+
 
 /* prof_tree.c */
 
@@ -193,6 +196,9 @@ errcode_t profile_flush_file_data
 errcode_t profile_flush_file_data_to_file
        (prf_data_t data, const char *outfile);
 
+errcode_t profile_flush_file_data_to_buffer
+       (prf_data_t data, char **bufp);
+
 void profile_free_file
        (prf_file_t profile);
 
index 042379dd25f2b838e80a6016afd8c7e8e3471822..d229bbb3ad9a0e30cca7b6f315f289568cc75d9f 100644 (file)
@@ -319,35 +319,42 @@ static int need_double_quotes(char *str)
  * Output a string with double quotes, doing appropriate backquoting
  * of characters as necessary.
  */
-static void output_quoted_string(char *str, FILE *f)
+static void output_quoted_string(char *str, void (*cb)(const char *,void *),
+                                void *data)
 {
        char    ch;
-       
-       fputc('"', f);
+       char buf[2];
+
+       cb("\"", data);
        if (!str) {
-               fputc('"', f);
+               cb("\"", data);
                return;
        }
+       buf[1] = 0;
        while ((ch = *str++)) {
                switch (ch) {
                case '\\':
-                       fputs("\\\\", f);
+                       cb("\\\\", data);
                        break;
                case '\n':
-                       fputs("\\n", f);
+                       cb("\\n", data);
                        break;
                case '\t':
-                       fputs("\\t", f);
+                       cb("\\t", data);
                        break;
                case '\b':
-                       fputs("\\b", f);
+                       cb("\\b", data);
                        break;
                default:
-                       fputc(ch, f);
+                       /* This would be a lot faster if we scanned
+                          forward for the next "interesting"
+                          character.  */
+                       buf[0] = ch;
+                       cb(buf, data);
                        break;
                }
        }
-       fputc('"', f);
+       cb("\"", data);
 }
 
 
@@ -360,8 +367,9 @@ static void output_quoted_string(char *str, FILE *f)
 #define EOL "\n"
 #endif
 
-static void dump_profile_to_file(struct profile_node *root, int level,
-                                FILE *dstfile)
+/* Errors should be returned, not ignored!  */
+static void dump_profile(struct profile_node *root, int level,
+                        void (*cb)(const char *, void *), void *data)
 {
        int i;
        struct profile_node *p;
@@ -376,14 +384,18 @@ static void dump_profile_to_file(struct profile_node *root, int level,
                if (retval)
                        break;
                for (i=0; i < level; i++)
-                       fprintf(dstfile, "\t");
+                       cb("\t", data);
                if (need_double_quotes(value)) {
-                       fputs(name, dstfile);
-                       fputs(" = ", dstfile);
-                       output_quoted_string(value, dstfile);
-                       fputs(EOL, dstfile);
-               } else
-                       fprintf(dstfile, "%s = %s%s", name, value, EOL);
+                       cb(name, data);
+                       cb(" = ", data);
+                       output_quoted_string(value, cb, data);
+                       cb(EOL, data);
+               } else {
+                       cb(name, data);
+                       cb(" = ", data);
+                       cb(value, data);
+                       cb(EOL, data);
+               }
        } while (iter != 0);
 
        iter = 0;
@@ -393,27 +405,88 @@ static void dump_profile_to_file(struct profile_node *root, int level,
                if (retval)
                        break;
                if (level == 0) { /* [xxx] */
-                       for (i=0; i < level; i++)
-                               fprintf(dstfile, "\t");
-                       fprintf(dstfile, "[%s]%s%s", name,
-                               profile_is_node_final(p) ? "*" : "", EOL);
-                       dump_profile_to_file(p, level+1, dstfile);
-                       fprintf(dstfile, EOL);
+                       cb("[", data);
+                       cb(name, data);
+                       cb("]", data);
+                       cb(profile_is_node_final(p) ? "*" : "", data);
+                       cb(EOL, data);
+                       dump_profile(p, level+1, cb, data);
+                       cb(EOL, data);
                } else {        /* xxx = { ... } */
                        for (i=0; i < level; i++)
-                               fprintf(dstfile, "\t");
-                       fprintf(dstfile, "%s = {%s", name, EOL);
-                       dump_profile_to_file(p, level+1, dstfile);
+                               cb("\t", data);
+                       cb(name, data);
+                       cb(" = {", data);
+                       cb(EOL, data);
+                       dump_profile(p, level+1, cb, data);
                        for (i=0; i < level; i++)
-                               fprintf(dstfile, "\t");
-                       fprintf(dstfile, "}%s%s",
-                               profile_is_node_final(p) ? "*" : "", EOL);
+                               cb("\t", data);
+                       cb("}", data);
+                       cb(profile_is_node_final(p) ? "*" : "", data);
+                       cb(EOL, data);
                }
        } while (iter != 0);
 }
 
+static void dump_profile_to_file_cb(const char *str, void *data)
+{
+       fputs(str, data);
+}
+
 errcode_t profile_write_tree_file(struct profile_node *root, FILE *dstfile)
 {
-       dump_profile_to_file(root, 0, dstfile);
+       dump_profile(root, 0, dump_profile_to_file_cb, dstfile);
+       return 0;
+}
+
+struct prof_buf {
+       char *base;
+       size_t cur, max;
+       int err;
+};
+
+static void add_data_to_buffer(struct prof_buf *b, const void *d, size_t len)
+{
+       if (b->err)
+               return;
+       if (b->max - b->cur < len) {
+               size_t newsize;
+               char *newptr;
+
+               newsize = b->max + (b->max >> 1) + len + 1024;
+               newptr = realloc(b->base, newsize);
+               if (newptr == NULL) {
+                       b->err = 1;
+                       return;
+               }
+               b->base = newptr;
+               b->max = newsize;
+       }
+       memcpy(b->base + b->cur, d, len);
+       b->cur += len;          /* ignore overflow */
+}
+
+static void dump_profile_to_buffer_cb(const char *str, void *data)
+{
+       add_data_to_buffer((struct prof_buf *)data, str, strlen(str));
+}
+
+errcode_t profile_write_tree_to_buffer(struct profile_node *root,
+                                      char **buf)
+{
+       struct prof_buf prof_buf = { 0, 0, 0, 0 };
+
+       dump_profile(root, 0, dump_profile_to_buffer_cb, &prof_buf);
+       if (prof_buf.err) {
+               *buf = NULL;
+               return ENOMEM;
+       }
+       add_data_to_buffer(&prof_buf, "", 1); /* append nul */
+       if (prof_buf.max - prof_buf.cur > (prof_buf.max >> 3)) {
+               char *newptr = realloc(prof_buf.base, prof_buf.cur);
+               if (newptr)
+                       prof_buf.base = newptr;
+       }
+       *buf = prof_buf.base;
        return 0;
 }
index d5a1b5e9e7ba789b557ec47977e43771bd2d229e..ec822ca8b91fc47a98ad5dd33dcb0e104a1894f5 100644 (file)
@@ -49,6 +49,10 @@ long KRB5_CALLCONV profile_flush
        (profile_t profile);
 long KRB5_CALLCONV profile_flush_to_file
        (profile_t profile, const_profile_filespec_t outfile);
+long KRB5_CALLCONV profile_flush_to_buffer
+       (profile_t profile, char **bufp);
+void KRB5_CALLCONV profile_free_buffer
+       (profile_t profile, char *buf);
 
 void KRB5_CALLCONV profile_abandon
        (profile_t profile);
index d6f16b7fef91306ab7115b9e6fa84b508278b7ab..7398e14a0025b6612447844ab0f4e3ccc7cc94b3 100644 (file)
@@ -250,6 +250,8 @@ errcode_t profile_rename_section(profile_t p, const char **nullterm,
                                 const char *new_name = NULL);
 errcode_t profile_add_relation(profile_t p, const char **nullterm,
                               const char *new_val = NULL);
+/* XXX Should be using profile_free_buffer blah.  */
+errcode_t profile_flush_to_buffer(profile_t p, char **OUTPUT);
 
 #ifdef SWIGTCL
 %include "tclsh.i"
index a4c37906cd0bb7751e378dc1a23874e68ea354f3..9b75e74b4d3407d092f0ff63379eb438596c8e24 100644 (file)
@@ -2011,6 +2011,54 @@ _wrap_profile_add_relation(ClientData clientData, Tcl_Interp *interp, int objc,
 }
 
 
+static int
+_wrap_profile_flush_to_buffer(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
+    profile_t arg1 = (profile_t) 0 ;
+    char **arg2 = (char **) 0 ;
+    errcode_t result;
+    char *tmp2 ;
+    
+    {
+        /* in char **OUTPUT */
+        tmp2 = NULL;
+        arg2 = &tmp2;
+    }
+    if (SWIG_GetArgs(interp, objc, objv,"o:profile_flush_to_buffer p ",0) == TCL_ERROR) SWIG_fail;
+    if ((SWIG_ConvertPtr(objv[1], (void **) &arg1, SWIGTYPE_profile_t,SWIG_POINTER_EXCEPTION | 0) != TCL_OK)) SWIG_fail;
+    result = (errcode_t)profile_flush_to_buffer(arg1,arg2);
+    
+    {
+        /* out errcode_t result */
+        if (result) {
+            /* There could be a memory leak here in the SWIG-Tcl layer,
+                  I'm not sure.  Not going to worry about it though.  */
+            Tcl_SetResult(interp, error_message(result), TCL_STATIC);
+            SWIG_fail;
+        }
+    }
+    {
+        /* argout char **OUTPUT */
+        /*    Tcl_SetResult(interp, *arg2, TCL_DYNAMIC); */
+        char *s = (arg2 && *arg2) ? *arg2 : "";
+        Tcl_ListObjAppendElement(interp, Tcl_GetObjResult(interp),
+        Tcl_NewStringObj(s, strlen(s)));
+    }
+    {
+        /* There may be a memory leak here.  Investigate later, if anyone
+               cares.  */
+        /*    profile_release_string(*arg2); */
+    }
+    return TCL_OK;
+    fail:
+    {
+        /* There may be a memory leak here.  Investigate later, if anyone
+               cares.  */
+        /*    profile_release_string(*arg2); */
+    }
+    return TCL_ERROR;
+}
+
+
 
 static swig_command_info swig_commands[] = {
     { SWIG_prefix "profile_init_path", (swig_wrapper_func) _wrap_profile_init_path, NULL},
@@ -2032,6 +2080,7 @@ static swig_command_info swig_commands[] = {
     { SWIG_prefix "profile_clear_relation", (swig_wrapper_func) _wrap_profile_clear_relation, NULL},
     { SWIG_prefix "profile_rename_section", (swig_wrapper_func) _wrap_profile_rename_section, NULL},
     { SWIG_prefix "profile_add_relation", (swig_wrapper_func) _wrap_profile_add_relation, NULL},
+    { SWIG_prefix "profile_flush_to_buffer", (swig_wrapper_func) _wrap_profile_flush_to_buffer, NULL},
     {0, 0, 0}
 };