From: Ken Raeburn Date: Thu, 9 Jan 2003 00:20:20 +0000 (+0000) Subject: Try to do atomic file swap on UNIX when updating profile X-Git-Tag: krb5-1.3-alpha1~176 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=990d918736af2612c82e8e9191e19721523f28ff;p=krb5.git Try to do atomic file swap on UNIX when updating profile * prof_file.c (make_hard_link): New function. (profile_flush_file_data): Use it to attempt a safe profile file replacement. ticket: 1301 status: open git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@15101 dc483132-0cff-0310-8789-dd5450dbe970 --- diff --git a/src/util/profile/ChangeLog b/src/util/profile/ChangeLog index 3d71969e5..7dfe046c8 100644 --- a/src/util/profile/ChangeLog +++ b/src/util/profile/ChangeLog @@ -1,5 +1,9 @@ 2003-01-08 Ken Raeburn + * prof_file.c (make_hard_link): New function. + (profile_flush_file_data): Use it to attempt a safe profile file + replacement. + * prof_parse.c (profile_parse_file) [PROFILE_SUPPORTS_FOREIGN_NEWLINES]: Look for \r and treat it as a line break. diff --git a/src/util/profile/prof_file.c b/src/util/profile/prof_file.c index 749a7550d..22470cc6e 100644 --- a/src/util/profile/prof_file.c +++ b/src/util/profile/prof_file.c @@ -217,6 +217,16 @@ errcode_t profile_update_file_data(prf_data_t data) return 0; } +static int +make_hard_link(const char *oldpath, const char *newpath) +{ +#ifdef _WIN32 + return -1; +#else + return link(oldpath, newpath); +#endif +} + errcode_t profile_flush_file_data(data) prf_data_t data; { @@ -279,14 +289,31 @@ errcode_t profile_flush_file_data(data) #endif unlink(old_file); - if (rename(data->filespec, old_file)) { + if (make_hard_link(data->filespec, 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)) { + /* 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; - } - if (rename(new_file, data->filespec)) { + } + } else { + /* Couldn't make the hard link, so there's going to be a + small window where data->filespec does not refer to + either version. */ + sync(); + if (rename(data->filespec, old_file)) { + retval = errno; + goto errout; + } + if (rename(new_file, data->filespec)) { retval = errno; rename(old_file, data->filespec); /* back out... */ goto errout; + } } data->flags = 0;