1/*++ 2/* NAME 3/* edit_file 3 4/* SUMMARY 5/* simple cooperative file updating protocol 6/* SYNOPSIS 7/* #include <edit_file.h> 8/* 9/* typedef struct { 10/* .in +4 11/* char *tmp_path; /* temp. pathname */ 12/* VSTREAM *tmp_fp; /* temp. stream */ 13/* /* private members... */ 14/* .in -4 15/* } EDIT_FILE; 16/* 17/* EDIT_FILE *edit_file_open(original_path, output_flags, output_mode) 18/* const char *original_path; 19/* int output_flags; 20/* mode_t output_mode; 21/* 22/* int edit_file_close(edit_file) 23/* EDIT_FILE *edit_file; 24/* 25/* void edit_file_cleanup(edit_file) 26/* EDIT_FILE *edit_file; 27/* DESCRIPTION 28/* This module implements a simple protocol for cooperative 29/* processes to update one file. The idea is to 1) create a 30/* new file under a deterministic temporary pathname, 2) 31/* populate the new file with updated information, and 3) 32/* rename the new file into the place of the original file. 33/* This module provides 1) and 3), and leaves 2) to the 34/* application. The temporary pathname is deterministic to 35/* avoid accumulation of thrash after program crashes. 36/* 37/* edit_file_open() implements the first phase of the protocol. 38/* It creates or opens an output file with a deterministic 39/* temporary pathname, obtained by appending the suffix defined 40/* with EDIT_FILE_SUFFIX to the specified original file pathname. 41/* The original file itself is not opened. edit_file_open() 42/* then locks the output file for exclusive access, and verifies 43/* that the file still exists under the temporary pathname. 44/* At this point in the protocol, the current process controls 45/* both the output file content and its temporary pathname. 46/* 47/* In the second phase, the application opens the original 48/* file if needed, and updates the output file via the 49/* \fBtmp_fp\fR member of the EDIT_FILE data structure. This 50/* phase is not implemented by the edit_file() module. 51/* 52/* edit_file_close() implements the third and final phase of 53/* the protocol. It flushes the output file to persistent 54/* storage, and renames the output file from its temporary 55/* pathname into the place of the original file. When any of 56/* these operations fails, edit_file_close() behaves as if 57/* edit_file_cleanup() was called. Regardless of whether these 58/* operations suceed, edit_file_close() releases the exclusive 59/* lock, closes the output file, and frees up memory that was 60/* allocated by edit_file_open(). 61/* 62/* edit_file_cleanup() aborts the protocol. It discards the 63/* output file, releases the exclusive lock, closes the output 64/* file, and frees up memory that was allocated by edit_file_open(). 65/* 66/* Arguments: 67/* .IP original_path 68/* The pathname of the original file that will be replaced by 69/* the output file. The temporary pathname for the output file 70/* is obtained by appending the suffix defined with EDIT_FILE_SUFFIX 71/* to a copy of the specified original file pathname, and is 72/* made available via the \fBtmp_path\fR member of the EDIT_FILE 73/* data structure. 74/* .IP output_flags 75/* Flags for opening the output file. These are as with open(2), 76/* except that the O_TRUNC flag is ignored. edit_file_open() 77/* always truncates the output file after it has obtained 78/* exclusive control over the output file content and temporary 79/* pathname. 80/* .IP output_mode 81/* Permissions for the output file. These are as with open(2), 82/* except that the output file is initially created with no 83/* group or other access permissions. The specified output 84/* file permissions are applied by edit_file_close(). 85/* .IP edit_file 86/* Pointer to data structure that is returned upon successful 87/* completion by edit_file_open(), and that must be passed to 88/* edit_file_close() or edit_file_cleanup(). 89/* DIAGNOSTICS 90/* Fatal errors: memory allocation failure, fstat() failure, 91/* unlink() failure, lock failure, ftruncate() failure. 92/* 93/* edit_file_open() immediately returns a null pointer when 94/* it cannot open the output file. 95/* 96/* edit_file_close() returns zero on success, VSTREAM_EOF on 97/* failure. 98/* 99/* With both functions, the global errno variable indicates 100/* the nature of the problem. All errors are relative to the 101/* temporary output's pathname. With both functions, this 102/* pathname is not available via the EDIT_FILE data structure, 103/* because that structure was already destroyed, or not created. 104/* BUGS 105/* In the non-error case, edit_file_open() will not return 106/* until it obtains exclusive control over the output file 107/* content and temporary pathname. Applications that are 108/* concerned about deadlock should protect the edit_file_open() 109/* call with a watchdog timer. 110/* 111/* When interrupted, edit_file_close() may leave behind a 112/* world-readable output file under the temporary pathname. 113/* On some systems this can be used to inflict a shared-lock 114/* DOS on the protocol. Applications that are concerned about 115/* maximal safety should protect the edit_file_close() call 116/* with sigdelay() and sigresume() calls, but this introduces 117/* the risk that the program will get stuck forever. 118/* LICENSE 119/* .ad 120/* .fi 121/* The Secure Mailer license must be distributed with this software. 122/* AUTHOR(S) 123/* Based on code originally by: 124/* Victor Duchovni 125/* Morgan Stanley 126/* 127/* Packaged into one module with minor improvements by: 128/* Wietse Venema 129/* IBM T.J. Watson Research 130/* P.O. Box 704 131/* Yorktown Heights, NY 10598, USA 132/*--*/ 133 134/* System library. */ 135 136#include <sys_defs.h> 137#include <sys/stat.h> 138#include <stdio.h> /* rename(2) */ 139#include <errno.h> 140 141 /* 142 * This mask selects all permission bits in the st_mode stat data. There is 143 * no portable definition (unlike S_IFMT, which is defined for the file type 144 * bits). For example, BSD / Linux have ALLPERMS, while Solaris has S_IAMB. 145 */ 146#define FILE_PERM_MASK \ 147 (S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO) 148 149/* Utility Library. */ 150 151#include <msg.h> 152#include <vstream.h> 153#include <mymalloc.h> 154#include <stringops.h> 155#include <myflock.h> 156#include <edit_file.h> 157#include <warn_stat.h> 158 159 /* 160 * Do we reuse and truncate an output file that persists after a crash, or 161 * do we unlink it and create a new file? 162 */ 163#define EDIT_FILE_REUSE_AFTER_CRASH 164 165 /* 166 * Protocol internals: the temporary file permissions. 167 */ 168#define EDIT_FILE_MODE (S_IRUSR | S_IWUSR) /* temp file mode */ 169 170 /* 171 * Make complex operations more readable. We could use functions, instead. 172 * The main thing is that we keep the _alloc and _free code together. 173 */ 174#define EDIT_FILE_ALLOC(ep, path, mode) do { \ 175 (ep) = (EDIT_FILE *) mymalloc(sizeof(EDIT_FILE)); \ 176 (ep)->final_path = mystrdup(path); \ 177 (ep)->final_mode = (mode); \ 178 (ep)->tmp_path = concatenate((path), EDIT_FILE_SUFFIX, (char *) 0); \ 179 (ep)->tmp_fp = 0; \ 180 } while (0) 181 182#define EDIT_FILE_FREE(ep) do { \ 183 myfree((ep)->final_path); \ 184 myfree((ep)->tmp_path); \ 185 myfree((char *) (ep)); \ 186 } while (0) 187 188/* edit_file_open - open and lock file with deterministic temporary pathname */ 189 190EDIT_FILE *edit_file_open(const char *path, int flags, mode_t mode) 191{ 192 struct stat before_lock; 193 struct stat after_lock; 194 int saved_errno; 195 EDIT_FILE *ep; 196 197 /* 198 * Initialize. Do not bother to optimize for the error case. 199 */ 200 EDIT_FILE_ALLOC(ep, path, mode); 201 202 /* 203 * As long as the output file can be opened under the temporary pathname, 204 * this code can loop or block forever. 205 * 206 * Applications that are concerned about deadlock should protect the 207 * edit_file_open() call with a watchdog timer. 208 */ 209 for ( /* void */ ; /* void */ ; (void) vstream_fclose(ep->tmp_fp)) { 210 211 /* 212 * Try to open the output file under the temporary pathname. This 213 * succeeds or fails immediately. To avoid creating a shared-lock DOS 214 * opportunity after we crash, we create the output file with no 215 * group or other permissions, and set the final permissions at the 216 * end (this is one reason why we try to get exclusive control over 217 * the output file instead of the original file). We postpone file 218 * truncation until we have obtained exclusive control over the file 219 * content and temporary pathname. If the open operation fails, we 220 * give up immediately. The caller can retry the call if desirable. 221 * 222 * XXX If we replace the vstream_fopen() call by safe_open(), then we 223 * should replace the stat() call below by lstat(). 224 */ 225 if ((ep->tmp_fp = vstream_fopen(ep->tmp_path, flags & ~(O_TRUNC), 226 EDIT_FILE_MODE)) == 0) { 227 saved_errno = errno; 228 EDIT_FILE_FREE(ep); 229 errno = saved_errno; 230 return (0); 231 } 232 233 /* 234 * At this point we may have opened an existing output file that was 235 * already locked. Try to lock the open file exclusively. This may 236 * take some time. 237 */ 238 if (myflock(vstream_fileno(ep->tmp_fp), INTERNAL_LOCK, 239 MYFLOCK_OP_EXCLUSIVE) < 0) 240 msg_fatal("lock %s: %m", ep->tmp_path); 241 242 /* 243 * At this point we have an exclusive lock, but some other process 244 * may have renamed or removed the output file while we were waiting 245 * for the lock. If that is the case, back out and try again. 246 */ 247 if (fstat(vstream_fileno(ep->tmp_fp), &before_lock) < 0) 248 msg_fatal("open %s: %m", ep->tmp_path); 249 if (stat(ep->tmp_path, &after_lock) < 0 250 || before_lock.st_dev != after_lock.st_dev 251 || before_lock.st_ino != after_lock.st_ino 252#ifdef HAS_ST_GEN 253 || before_lock.st_gen != after_lock.st_gen 254#endif 255 /* No need to compare st_rdev or st_nlink here. */ 256 ) { 257 continue; 258 } 259 260 /* 261 * At this point we have exclusive control over the output file 262 * content and its temporary pathname (within the rules of the 263 * cooperative protocol). But wait, there is more. 264 * 265 * There are many opportunies for trouble when opening a pre-existing 266 * output file. Here are just a few. 267 * 268 * - Victor observes that a system crash in the middle of the 269 * final-phase rename() operation may result in the output file 270 * having both the temporary pathname and the final pathname. In that 271 * case we must not write to the output file. 272 * 273 * - Wietse observes that crashes may also leave the output file in 274 * other inconsistent states. To avoid permission-related trouble, we 275 * simply refuse to work with an output file that has the wrong 276 * temporary permissions. This won't stop the shared-lock DOS if we 277 * crash after changing the file permissions, though. 278 * 279 * To work around these crash-related problems, remove the temporary 280 * pathname, back out, and try again. 281 */ 282 if (!S_ISREG(after_lock.st_mode) 283#ifndef EDIT_FILE_REUSE_AFTER_CRASH 284 || after_lock.st_size > 0 285#endif 286 || after_lock.st_nlink > 1 287 || (after_lock.st_mode & FILE_PERM_MASK) != EDIT_FILE_MODE) { 288 if (unlink(ep->tmp_path) < 0 && errno != ENOENT) 289 msg_fatal("unlink %s: %m", ep->tmp_path); 290 continue; 291 } 292 293 /* 294 * Settle the final details. 295 */ 296#ifdef EDIT_FILE_REUSE_AFTER_CRASH 297 if (ftruncate(vstream_fileno(ep->tmp_fp), 0) < 0) 298 msg_fatal("truncate %s: %m", ep->tmp_path); 299#endif 300 return (ep); 301 } 302} 303 304/* edit_file_cleanup - clean up without completing the protocol */ 305 306void edit_file_cleanup(EDIT_FILE *ep) 307{ 308 309 /* 310 * Don't touch the file after we lose the exclusive lock! 311 */ 312 if (unlink(ep->tmp_path) < 0 && errno != ENOENT) 313 msg_fatal("unlink %s: %m", ep->tmp_path); 314 (void) vstream_fclose(ep->tmp_fp); 315 EDIT_FILE_FREE(ep); 316} 317 318/* edit_file_close - rename the file into place and and close the file */ 319 320int edit_file_close(EDIT_FILE *ep) 321{ 322 VSTREAM *fp = ep->tmp_fp; 323 int fd = vstream_fileno(fp); 324 int saved_errno; 325 326 /* 327 * The rename/unlock portion of the protocol is relatively simple. The 328 * only things that really matter here are that we change permissions as 329 * late as possible, and that we rename the file to its final pathname 330 * before we lose the exclusive lock. 331 * 332 * Applications that are concerned about maximal safety should protect the 333 * edit_file_close() call with sigdelay() and sigresume() calls. It is 334 * not safe for us to call these functions directly, because the calls do 335 * not nest. It is also not nice to force every caller to run with 336 * interrupts turned off. 337 */ 338 if (vstream_fflush(fp) < 0 339 || fchmod(fd, ep->final_mode) < 0 340#ifdef HAS_FSYNC 341 || fsync(fd) < 0 342#endif 343 || rename(ep->tmp_path, ep->final_path) < 0) { 344 saved_errno = errno; 345 edit_file_cleanup(ep); 346 errno = saved_errno; 347 return (VSTREAM_EOF); 348 } else { 349 (void) vstream_fclose(ep->tmp_fp); 350 EDIT_FILE_FREE(ep); 351 return (0); 352 } 353} 354