forked from Lainports/freebsd-ports
It can be used to write mail messages to a qmail-style maildir, or to write data to a "spool" directory reliably.
89 lines
3.1 KiB
Text
89 lines
3.1 KiB
Text
--- safecat.c 2000/11/21 08:57:15 1.1.1.1
|
|
+++ safecat.c 2000/11/21 10:25:22 1.2
|
|
@@ -36,7 +36,6 @@
|
|
int outfd = 0;
|
|
stralloc dstpath = {0};
|
|
stralloc outfile = {0};
|
|
- stralloc outpath = {0};
|
|
struct stat filestat;
|
|
unsigned int count = 0;
|
|
|
|
@@ -57,43 +56,40 @@
|
|
stat_dir(tempdir);
|
|
stat_dir(destdir);
|
|
|
|
- /* Step 2: Stat the temporary file. Wait for ENOENT as a response. */
|
|
+ /* Step 2: Create the temporary file. */
|
|
+ alarm(86400);
|
|
for(count=0;;count++) {
|
|
/* Get the temporary filename to use now for dumping data. */
|
|
mk_tempfile(&outfile);
|
|
- if (!stralloc_cats(&outpath,tempdir)) die_nomem();
|
|
- if (!stralloc_append(&outpath, "/")) die_nomem();
|
|
- if (!stralloc_cat(&outpath,&outfile)) die_nomem();
|
|
- if(stat(outfile.s,&filestat) == -1 && errno == ENOENT) {
|
|
+ if (!stralloc_cats(&tmppath,tempdir)) die_nomem();
|
|
+ if (!stralloc_append(&tmppath, "/")) die_nomem();
|
|
+ if (!stralloc_cat(&tmppath,&outfile)) die_nomem();
|
|
+
|
|
+ outfd = open_excl(tmppath.s);
|
|
+ if (outfd >= 0) {
|
|
+ /* file created successfully */
|
|
if (!stralloc_cats(&dstpath, destdir)) die_nomem();
|
|
if (!stralloc_append(&dstpath, "/")) die_nomem();
|
|
if (!stralloc_cat(&dstpath,&outfile)) die_nomem();
|
|
-
|
|
- if (!stralloc_cats(&tmppath, tempdir)) die_nomem();
|
|
- if (!stralloc_append(&tmppath, "/")) die_nomem();
|
|
- if (!stralloc_cat(&tmppath,&outfile)) die_nomem();
|
|
break;
|
|
}
|
|
+ if (errno != EEXIST) {
|
|
+ /* a "real" error occured, bail out */
|
|
+ strerr_die2x(111, "safecat: fatal: ","could not create temporary file");
|
|
+ }
|
|
|
|
- /* Try up to 5 times, every 2 seconds. */
|
|
+ /* Step 3: try up to 5 times, every 2 seconds. */
|
|
if(count == 5) {
|
|
- strerr_die2x(111, "safecat: fatal: ","could not stat temporary file");
|
|
+ strerr_die2x(111, "safecat: fatal: ","could not create temporary file");
|
|
}
|
|
|
|
/* Wait 2 seconds, and try again. */
|
|
stralloc_copys(&outfile,"");
|
|
- stralloc_copys(&outpath,"");
|
|
+ stralloc_copys(&tmppath,"");
|
|
sleep(2);
|
|
}
|
|
|
|
- /* Step 4: Create the file tempdir/time.pid.host */
|
|
- alarm(86400);
|
|
- outfd = open(tmppath.s,O_WRONLY | O_EXCL | O_CREAT,0644);
|
|
- if(outfd == -1) {
|
|
- strerr_die2sys(111,"safecat: fatal: ","couldn't create output file: ");
|
|
- }
|
|
-
|
|
- /* Step 5: Copy stdin to the temp file. */
|
|
+ /* Step 4: Copy stdin to the temp file. */
|
|
writefile(outfd);
|
|
|
|
/* Close the file, checking the return value. */
|
|
@@ -102,11 +98,16 @@
|
|
strerr_die2sys(111,"safecat: fatal: ","can't fsync/close output file: ");
|
|
}
|
|
|
|
- /* Step 6: Link the temp file to its final destination. */
|
|
+ /* Step 5: Link the temp file to its final destination. */
|
|
if(link(tmppath.s,dstpath.s) == -1) {
|
|
strerr_die2sys(111,"safecat: fatal: ","can't link output file: ");
|
|
}
|
|
/* We've succeeded! Now, no matter what, we return "success" */
|
|
+
|
|
+ /* Kill the alarm() just in case the 24 hours expire at a most unfortunate
|
|
+ time - just after a successful completion (e.g. unlink() over NFS could
|
|
+ be slow) */
|
|
+ alarm(0);
|
|
|
|
/* Okay, delete the temporary file. */
|
|
unlink(tmppath.s);
|