Allow profile library caller to write the modified data to a different
authorKen Raeburn <raeburn@mit.edu>
Mon, 18 Oct 2004 23:14:51 +0000 (23:14 +0000)
committerKen Raeburn <raeburn@mit.edu>
Mon, 18 Oct 2004 23:14:51 +0000 (23:14 +0000)
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

src/util/profile/ChangeLog
src/util/profile/prof_file.c
src/util/profile/prof_init.c
src/util/profile/prof_int.h
src/util/profile/prof_test1
src/util/profile/profile.hin
src/util/profile/profile.swg
src/util/profile/profile_tcl.c

index 54533de88573c977bea84b4a31c85b811652712c..3ebbb45b90271f4039d91899a6cf9747670bd44e 100644 (file)
@@ -1,3 +1,19 @@
+2004-10-18  Ken Raeburn  <raeburn@mit.edu>
+
+       * 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  <raeburn@mit.edu>
 
        * prof_file.c, prof_int.h, prof_set.c: Remove support for
index d8386dcbb835db2aafe2ca294d8dead71b7a2a89..55fd34502aa5ee1c0ba60f5dcc97fc65058abae9 100644 (file)
@@ -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)
 {
index b65cf0d6aa87c47b7a2ec2210ad2425c64190093..6b04d61e500a2f7d3020a6148066ae69bdba0ccb 100644 (file)
@@ -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)
 {
index 32d71f218180d30d54d8169b76b27d6e192fdcb6..60cadbdf0910d0bd1cafc7d6eded623b2f88b03e 100644 (file)
@@ -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);
 
index 42a6021f8939069fc9538df7c51016df4215ef2c..d7d5fa8d16cd4c7a39a45c46cfb7a328b73ea15d 100644 (file)
@@ -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:" }
index e8515dd799b3c15c46ed0ae090a058642b70b6e4..d5a1b5e9e7ba789b557ec47977e43771bd2d229e 100644 (file)
@@ -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);
index 9607343022476199363b5f824a85a6e271d032b2..d6f16b7fef91306ab7115b9e6fa84b508278b7ab 100644 (file)
@@ -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!  */
index eb74f85d27e7966be5b2b314b26ec3ccda117671..a4c37906cd0bb7751e378dc1a23874e68ea354f3 100644 (file)
@@ -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},