diff options
author | trhodes <trhodes@FreeBSD.org> | 2003-06-14 13:41:31 +0000 |
---|---|---|
committer | trhodes <trhodes@FreeBSD.org> | 2003-06-14 13:41:31 +0000 |
commit | 23174ba968d72735a3fdf0b790b14ccabdc40946 (patch) | |
tree | 7393e5d31b83afe0cddea6237f8e73918cbda739 /usr.bin/compress/compress.c | |
parent | d84e6f299c6d13559693af99d2046ebf0b7496a2 (diff) | |
download | FreeBSD-src-23174ba968d72735a3fdf0b790b14ccabdc40946.zip FreeBSD-src-23174ba968d72735a3fdf0b790b14ccabdc40946.tar.gz |
Don't truncate the output file before making sure that we can
read at least 1 byte from the input file without problems. This
fixes a bug in uncompress(1) that causes the accidental removal
of files that happen to have the same name as the output file,
even when the uncompression fails and is aborted, i.e.:
$ echo hello world > hello
$ touch hello.Z
$ ls -l hello*
-rw-rw-r-- 1 giorgos giorgos 12 Jun 14 13:33 hello
-rw-rw-r-- 1 giorgos giorgos 0 Jun 14 13:33 hello.Z
$ ./uncompress -f hello
uncompress: hello.Z: Inappropriate file type or format
$ ls -l hello*
-rw-rw-r-- 1 giorgos giorgos 0 Jun 14 13:33 hello.Z
$
PR: 46787
Submitted by: keramida
Diffstat (limited to 'usr.bin/compress/compress.c')
-rw-r--r-- | usr.bin/compress/compress.c | 23 |
1 files changed, 17 insertions, 6 deletions
diff --git a/usr.bin/compress/compress.c b/usr.bin/compress/compress.c index ceaac87..584f283 100644 --- a/usr.bin/compress/compress.c +++ b/usr.bin/compress/compress.c @@ -300,14 +300,9 @@ decompress(const char *in, const char *out, int bits) isreg = oreg = !exists || S_ISREG(sb.st_mode); ifp = ofp = NULL; - if ((ofp = fopen(out, "w")) == NULL) { - cwarn("%s", out); - return; - } - if ((ifp = zopen(in, "r", bits)) == NULL) { cwarn("%s", in); - goto err; + return; } if (stat(in, &sb)) { cwarn("%s", in); @@ -316,6 +311,22 @@ decompress(const char *in, const char *out, int bits) if (!S_ISREG(sb.st_mode)) isreg = 0; + /* + * Try to read the first few uncompressed bytes from the input file + * before blindly truncating the output file. + */ + if ((nr = fread(buf, 1, sizeof(buf), ifp)) == 0) { + cwarn("%s", in); + (void)fclose(ifp); + return; + } + if ((ofp = fopen(out, "w")) == NULL || + (nr != 0 && fwrite(buf, 1, nr, ofp) != nr)) { + cwarn("%s", out); + (void)fclose(ifp); + return; + } + while ((nr = fread(buf, 1, sizeof(buf), ifp)) != 0) if (fwrite(buf, 1, nr, ofp) != nr) { cwarn("%s", out); |