summaryrefslogtreecommitdiff
path: root/sponge.c
diff options
context:
space:
mode:
authorJoey Hess <joey@kitenet.net>2010-09-13 16:08:01 -0400
committerJoey Hess <joey@kitenet.net>2010-09-13 16:08:13 -0400
commit1ac3e2c08bae4bd8e5e771dab94564d79638d414 (patch)
tree9f2c49a7a3d32316819f23af2ca25b10d6c26add /sponge.c
parent067b7a5419db8e78eeeee9ad62f798cb33be1e05 (diff)
downloadmoreutils-1ac3e2c08bae4bd8e5e771dab94564d79638d414.tar.gz
sponge: Ensure that output file permissions are always preserved if it already exists.
Diffstat (limited to 'sponge.c')
-rw-r--r--sponge.c58
1 files changed, 30 insertions, 28 deletions
diff --git a/sponge.c b/sponge.c
index f9a521d..4d5a1f4 100644
--- a/sponge.c
+++ b/sponge.c
@@ -262,7 +262,6 @@ int main (int argc, char **argv) {
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();
@@ -309,41 +308,44 @@ int main (int argc, char **argv) {
}
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);