aboutsummaryrefslogtreecommitdiffstats
path: root/sysutils/safecat/files/patch-ad
blob: f754c680d2607535ec6635418bcf629e54279729 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
--- 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);