From: Ken Raeburn Date: Mon, 18 Oct 2004 23:14:51 +0000 (+0000) Subject: Allow profile library caller to write the modified data to a different X-Git-Tag: krb5-1.4-beta1~19 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=fb8314743c17c15ebcfcebee3565069079a819fc;p=krb5.git Allow profile library caller to write the modified data to a different file than was originally read. * prof_file.c (write_data_to_file): New function, split out from profile_flush_file_data. Add argument can_create indicating whether the old file should already exist or not. (profile_flush_file_data): Call it. (profile_flush_file_data_to_file): New function. * prof_int.h (profile_flush_file_data_to_file): Declare it. (profile_flush_file_to_file): New macro. * prof_init.c (profile_flush_to_file): New function. * profile.hin (profile_flush_to_file): Declare. * profile.swg (profile_flush_to_file): Declare. * profile_tcl.c: Regenerated. * prof_test1: Use profile_flush_to_file instead of profile_flush, and reload from the new filename. git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@16825 dc483132-0cff-0310-8789-dd5450dbe970 --- diff --git a/src/util/profile/ChangeLog b/src/util/profile/ChangeLog index 54533de88..3ebbb45b9 100644 --- a/src/util/profile/ChangeLog +++ b/src/util/profile/ChangeLog @@ -1,3 +1,19 @@ +2004-10-18 Ken Raeburn + + * prof_file.c (write_data_to_file): New function, split out from + profile_flush_file_data. Add argument can_create indicating + whether the old file should already exist or not. + (profile_flush_file_data): Call it. + (profile_flush_file_data_to_file): New function. + * prof_int.h (profile_flush_file_data_to_file): Declare it. + (profile_flush_file_to_file): New macro. + * prof_init.c (profile_flush_to_file): New function. + * profile.hin (profile_flush_to_file): Declare. + * profile.swg (profile_flush_to_file): Declare. + * profile_tcl.c: Regenerated. + * prof_test1: Use profile_flush_to_file instead of profile_flush, + and reload from the new filename. + 2004-10-15 Ken Raeburn * prof_file.c, prof_int.h, prof_set.c: Remove support for diff --git a/src/util/profile/prof_file.c b/src/util/profile/prof_file.c index d8386dcbb..55fd34502 100644 --- a/src/util/profile/prof_file.c +++ b/src/util/profile/prof_file.c @@ -367,37 +367,26 @@ make_hard_link(const char *oldpath, const char *newpath) #endif } -errcode_t profile_flush_file_data(prf_data_t data) +static errcode_t write_data_to_file(prf_data_t data, const char *outfile, + int can_create) { FILE *f; profile_filespec_t new_file; profile_filespec_t old_file; errcode_t retval = 0; - if (!data || data->magic != PROF_MAGIC_FILE_DATA) - return PROF_MAGIC_FILE_DATA; - - retval = k5_mutex_lock(&data->lock); - if (retval) - return retval; - - if ((data->flags & PROFILE_FILE_DIRTY) == 0) { - k5_mutex_unlock(&data->lock); - return 0; - } - retval = ENOMEM; new_file = old_file = 0; - new_file = malloc(strlen(data->filespec) + 5); + new_file = malloc(strlen(outfile) + 5); if (!new_file) goto errout; - old_file = malloc(strlen(data->filespec) + 5); + old_file = malloc(strlen(outfile) + 5); if (!old_file) goto errout; - sprintf(new_file, "%s.$$$", data->filespec); - sprintf(old_file, "%s.bak", data->filespec); + sprintf(new_file, "%s.$$$", outfile); + sprintf(old_file, "%s.bak", outfile); errno = 0; @@ -416,17 +405,22 @@ errcode_t profile_flush_file_data(prf_data_t data) } unlink(old_file); - if (make_hard_link(data->filespec, old_file) == 0) { + if (make_hard_link(outfile, old_file) == 0) { /* Okay, got the hard link. Yay. Now we've got our backup version, so just put the new version in place. */ - if (rename(new_file, data->filespec)) { + if (rename(new_file, outfile)) { /* Weird, the rename didn't work. But the old version should still be in place, so no special cleanup is needed. */ retval = errno; goto errout; } + } else if (errno == ENOENT && can_create) { + if (rename(new_file, outfile)) { + retval = errno; + goto errout; + } } else { /* Couldn't make the hard link, so there's going to be a small window where data->filespec does not refer to @@ -434,24 +428,23 @@ errcode_t profile_flush_file_data(prf_data_t data) #ifndef _WIN32 sync(); #endif - if (rename(data->filespec, old_file)) { + if (rename(outfile, old_file)) { retval = errno; goto errout; } - if (rename(new_file, data->filespec)) { + if (rename(new_file, outfile)) { retval = errno; - rename(old_file, data->filespec); /* back out... */ + rename(old_file, outfile); /* back out... */ goto errout; } } data->flags = 0; - if (rw_access(data->filespec)) + if (rw_access(outfile)) data->flags |= PROFILE_FILE_RW; retval = 0; - + errout: - k5_mutex_unlock(&data->lock); if (new_file) free(new_file); if (old_file) @@ -459,6 +452,43 @@ errout: return retval; } +errcode_t profile_flush_file_data(prf_data_t data) +{ + errcode_t retval = 0; + + if (!data || data->magic != PROF_MAGIC_FILE_DATA) + return PROF_MAGIC_FILE_DATA; + + retval = k5_mutex_lock(&data->lock); + if (retval) + return retval; + + if ((data->flags & PROFILE_FILE_DIRTY) == 0) { + k5_mutex_unlock(&data->lock); + return 0; + } + + retval = write_data_to_file(data, data->filespec, 0); + k5_mutex_unlock(&data->lock); + return retval; +} + +errcode_t profile_flush_file_data_to_file(prf_data_t data, const char *outfile) +{ + errcode_t retval = 0; + + if (!data || data->magic != PROF_MAGIC_FILE_DATA) + return PROF_MAGIC_FILE_DATA; + + retval = k5_mutex_lock(&data->lock); + if (retval) + return retval; + retval = write_data_to_file(data, outfile, 1); + k5_mutex_unlock(&data->lock); + return retval; +} + + void profile_dereference_data(prf_data_t data) { diff --git a/src/util/profile/prof_init.c b/src/util/profile/prof_init.c index b65cf0d6a..6b04d61e5 100644 --- a/src/util/profile/prof_init.c +++ b/src/util/profile/prof_init.c @@ -132,6 +132,19 @@ profile_flush(profile_t profile) return 0; } +errcode_t KRB5_CALLCONV +profile_flush_to_file(profile_t profile, const_profile_filespec_t outfile) +{ + if (!profile || profile->magic != PROF_MAGIC_PROFILE) + return PROF_MAGIC_PROFILE; + + if (profile->first_file) + return profile_flush_file_to_file(profile->first_file, + outfile); + + return 0; +} + 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 32d71f218..60cadbdf0 100644 --- a/src/util/profile/prof_int.h +++ b/src/util/profile/prof_int.h @@ -189,6 +189,10 @@ errcode_t profile_update_file_data errcode_t profile_flush_file_data (prf_data_t data); +#define profile_flush_file_to_file(P,F) (((P) && (P)->magic == PROF_MAGIC_FILE) ? profile_flush_file_data_to_file((P)->data, (F)) : PROF_MAGIC_FILE) +errcode_t profile_flush_file_data_to_file + (prf_data_t data, const char *outfile); + void profile_free_file (prf_file_t profile); diff --git a/src/util/profile/prof_test1 b/src/util/profile/prof_test1 index 42a6021f8..d7d5fa8d1 100644 --- a/src/util/profile/prof_test1 +++ b/src/util/profile/prof_test1 @@ -35,10 +35,12 @@ proc test1 {} { } if $verbose { puts "" } #profile_iterator_free $iter - profile_flush $p + catch {file delete $wd/test3.ini} + profile_flush_to_file $p $wd/test3.ini + profile_release $p - if $verbose { puts "Reloading profile" } - set p [profile_init_path $wd/test2.ini] + if $verbose { puts "Reloading new profile" } + set p [profile_init_path $wd/test3.ini] set iter [profile_iterator_create $p $sect 0] set done 0 if $verbose { puts "Iterating again:" } diff --git a/src/util/profile/profile.hin b/src/util/profile/profile.hin index e8515dd79..d5a1b5e9e 100644 --- a/src/util/profile/profile.hin +++ b/src/util/profile/profile.hin @@ -47,6 +47,8 @@ long KRB5_CALLCONV profile_init_path long KRB5_CALLCONV profile_flush (profile_t profile); +long KRB5_CALLCONV profile_flush_to_file + (profile_t profile, const_profile_filespec_t outfile); void KRB5_CALLCONV profile_abandon (profile_t profile); diff --git a/src/util/profile/profile.swg b/src/util/profile/profile.swg index 960734302..d6f16b7fe 100644 --- a/src/util/profile/profile.swg +++ b/src/util/profile/profile.swg @@ -151,6 +151,7 @@ typedef struct _profile_t *profile_t; errcode_t profile_init_path(const char *path = NULL, profile_t *OUTPUT); errcode_t profile_init(const char **nullterm = NULL, profile_t *OUTPUT); errcode_t profile_flush(profile_t); +errcode_t profile_flush_to_file(profile_t, const char *path); /* Nota bene: There is nothing at all in this code to prevent a script from accessing a profile object after calling one of these routines to destroy it! */ diff --git a/src/util/profile/profile_tcl.c b/src/util/profile/profile_tcl.c index eb74f85d2..a4c37906c 100644 --- a/src/util/profile/profile_tcl.c +++ b/src/util/profile/profile_tcl.c @@ -1326,6 +1326,31 @@ _wrap_profile_flush(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj } +static int +_wrap_profile_flush_to_file(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { + profile_t arg1 = (profile_t) 0 ; + char *arg2 ; + errcode_t result; + + if (SWIG_GetArgs(interp, objc, objv,"os:profile_flush_to_file profile_t path ",0,&arg2) == 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_file(arg1,(char const *)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; + } + } + return TCL_OK; + fail: + return TCL_ERROR; +} + + static int _wrap_profile_abandon(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { profile_t arg1 = (profile_t) 0 ; @@ -1991,6 +2016,7 @@ static swig_command_info swig_commands[] = { { SWIG_prefix "profile_init_path", (swig_wrapper_func) _wrap_profile_init_path, NULL}, { SWIG_prefix "profile_init", (swig_wrapper_func) _wrap_profile_init, NULL}, { SWIG_prefix "profile_flush", (swig_wrapper_func) _wrap_profile_flush, NULL}, + { SWIG_prefix "profile_flush_to_file", (swig_wrapper_func) _wrap_profile_flush_to_file, NULL}, { SWIG_prefix "profile_abandon", (swig_wrapper_func) _wrap_profile_abandon, NULL}, { SWIG_prefix "profile_release", (swig_wrapper_func) _wrap_profile_release, NULL}, { SWIG_prefix "profile_get_values", (swig_wrapper_func) _wrap_profile_get_values, NULL},