* 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
+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,
profile_verify_node
profile_write_tree_file
profile_flush_to_file
+profile_flush_to_buffer
+profile_free_buffer
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;
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)
{
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 */
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);
* 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);
}
#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;
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;
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;
}
(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);
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"
}
+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},
{ 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}
};