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);
|