FILE *outfile, *tmpfile = 0;
ssize_t i = 0;
size_t mem_available = default_sponge_size();
- struct stat statbuf;
if (argc > 2 || (argc == 2 && strcmp(argv[1], "-h") == 0)) {
usage();
}
if (outname) {
+ mode_t mode;
+ struct stat statbuf;
+ int exists = (lstat(outname, &statbuf) == 0);
+
+ /* Set temp file mode to match either
+ * the old file mode, or the default file
+ * mode for a newly created file. */
+ if (exists) {
+ mode = statbuf.st_mode;
+ }
+ else {
+ mode_t mask = umask(0);
+ umask(mask);
+ mode = 0666 & ~mask;
+ }
+ if (chmod(tmpname, mode) != 0) {
+ perror("chmod");
+ exit(1);
+ }
+
/* If it's a regular file, or does not yet exist,
* attempt a fast rename of the temp file. */
- if (((lstat(outname, &statbuf) == 0 &&
+ if (((exists &&
S_ISREG(statbuf.st_mode) &&
! S_ISLNK(statbuf.st_mode)
- ) || errno == ENOENT) &&
+ ) || ! exists) &&
rename(tmpname, outname) == 0) {
- tmpname=NULL;
- /* Fix renamed file mode to match either
- * the old file mode, or the default file
- * mode for a newly created file. */
- mode_t mode;
- if (errno != ENOENT) {
- mode = statbuf.st_mode;
- }
- else {
- mode_t mask = umask(0);
- umask(mask);
- mode = 0666 & ~mask;
- }
- if (chmod(outname, mode) != 0) {
- perror("chmod");
+ tmpname=NULL; /* don't try to cleanup tmpname */
+ }
+ else {
+ /* Fall back to slow copy. */
+ outfile = fopen(outname, "w");
+ if (!outfile) {
+ perror("error opening output file");
exit(1);
}
- return(0);
- }
-
- /* Fall back to slow copy. */
- outfile = fopen(outname, "w");
- if (!outfile) {
- perror("error opening output file");
- exit(1);
+ copy_tmpfile(tmpfile, outfile, bufstart, bufsize);
}
- copy_tmpfile(tmpfile, outfile, bufstart, bufsize);
- fclose(outfile);
}
else {
copy_tmpfile(tmpfile, stdout, bufstart, bufsize);
redirect, sponge soaks up all its input before
opening the output file. This allows constricting
pipelines that read from and write to
- the same file. It also creates the output file
- atomically by renaming a temp file into place.</para>
+ the same file.</para>
+ <para>
+ It also creates the output file
+ atomically by renaming a temp file into place.
+ If the output file is a special file or symlink,
+ the data will be written to it.</para>
<para>If no output file is specified, sponge outputs to
stdout.</para>