summaryrefslogtreecommitdiffstats
path: root/src/util/profile
diff options
context:
space:
mode:
authorKen Raeburn <raeburn@mit.edu>2004-10-27 00:07:20 +0000
committerKen Raeburn <raeburn@mit.edu>2004-10-27 00:07:20 +0000
commitb5781e4174975388a7c3f077723bff66b974b538 (patch)
tree9a8a6458f81f2680acc7900ebe73bb4f4ed3db01 /src/util/profile
parentd4c65184e13ab5c027df4698375a68293ab67cf0 (diff)
downloadkrb5-b5781e4174975388a7c3f077723bff66b974b538.tar.gz
krb5-b5781e4174975388a7c3f077723bff66b974b538.tar.xz
krb5-b5781e4174975388a7c3f077723bff66b974b538.zip
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. git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@16838 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/util/profile')
-rw-r--r--src/util/profile/ChangeLog24
-rw-r--r--src/util/profile/libprofile.exports2
-rw-r--r--src/util/profile/prof_file.c11
-rw-r--r--src/util/profile/prof_init.c12
-rw-r--r--src/util/profile/prof_int.h6
-rw-r--r--src/util/profile/prof_parse.c137
-rw-r--r--src/util/profile/profile.hin4
-rw-r--r--src/util/profile/profile.swg2
-rw-r--r--src/util/profile/profile_tcl.c49
9 files changed, 215 insertions, 32 deletions
diff --git a/src/util/profile/ChangeLog b/src/util/profile/ChangeLog
index f48a24c338..1366bd4d1c 100644
--- a/src/util/profile/ChangeLog
+++ b/src/util/profile/ChangeLog
@@ -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,
diff --git a/src/util/profile/libprofile.exports b/src/util/profile/libprofile.exports
index 2df95fe255..26db5e8983 100644
--- a/src/util/profile/libprofile.exports
+++ b/src/util/profile/libprofile.exports
@@ -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
diff --git a/src/util/profile/prof_file.c b/src/util/profile/prof_file.c
index 17f943a660..f47e5404be 100644
--- a/src/util/profile/prof_file.c
+++ b/src/util/profile/prof_file.c
@@ -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;
diff --git a/src/util/profile/prof_init.c b/src/util/profile/prof_init.c
index 6b04d61e50..02d61ee1f5 100644
--- a/src/util/profile/prof_init.c
+++ b/src/util/profile/prof_init.c
@@ -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)
{
diff --git a/src/util/profile/prof_int.h b/src/util/profile/prof_int.h
index 60cadbdf09..d2761228cb 100644
--- a/src/util/profile/prof_int.h
+++ b/src/util/profile/prof_int.h
@@ -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);
diff --git a/src/util/profile/prof_parse.c b/src/util/profile/prof_parse.c
index 042379dd25..d229bbb3ad 100644
--- a/src/util/profile/prof_parse.c
+++ b/src/util/profile/prof_parse.c
@@ -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;
}
diff --git a/src/util/profile/profile.hin b/src/util/profile/profile.hin
index d5a1b5e9e7..ec822ca8b9 100644
--- a/src/util/profile/profile.hin
+++ b/src/util/profile/profile.hin
@@ -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);
diff --git a/src/util/profile/profile.swg b/src/util/profile/profile.swg
index d6f16b7fef..7398e14a00 100644
--- a/src/util/profile/profile.swg
+++ b/src/util/profile/profile.swg
@@ -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"
diff --git a/src/util/profile/profile_tcl.c b/src/util/profile/profile_tcl.c
index a4c37906cd..9b75e74b4d 100644
--- a/src/util/profile/profile_tcl.c
+++ b/src/util/profile/profile_tcl.c
@@ -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}
};