diff options
author | Lasse Collin <lasse.collin@tukaani.org> | 2011-04-10 12:47:47 +0300 |
---|---|---|
committer | Lasse Collin <lasse.collin@tukaani.org> | 2011-04-10 12:47:47 +0300 |
commit | cd4fe97852bcaeffe674ee51b4613709292a0972 (patch) | |
tree | c953e2ecb479ff2b183dce5e7f7ac97a4d184277 | |
parent | Update THANKS. (diff) | |
download | xz-cd4fe97852bcaeffe674ee51b4613709292a0972.tar.xz |
xz/DOS: Be more careful with the destination file.
Try to avoid overwriting the source file if --force is
used and the generated destination filename refers to
the source file. This can happen with 8.3 filenames where
extra characters are ignored.
If the generated output file refers to a special file
like "con" or "prn", refuse to write to it even if --force
is used.
Diffstat (limited to '')
-rw-r--r-- | src/xz/file_io.c | 35 |
1 files changed, 33 insertions, 2 deletions
diff --git a/src/xz/file_io.c b/src/xz/file_io.c index 5eba9d87..5555891b 100644 --- a/src/xz/file_io.c +++ b/src/xz/file_io.c @@ -68,8 +68,7 @@ io_init(void) #ifdef __DJGPP__ // Avoid doing useless things when statting files. // This isn't important but doesn't hurt. - _djstat_flags = _STAT_INODE | _STAT_EXEC_EXT - | _STAT_EXEC_MAGIC | _STAT_DIRSIZE; + _djstat_flags = _STAT_EXEC_EXT | _STAT_EXEC_MAGIC | _STAT_DIRSIZE; #endif return; @@ -452,8 +451,18 @@ io_open_src_real(file_pair *pair) // Stat the source file. We need the result also when we copy // the permissions, and when unlinking. + // + // NOTE: Use stat() instead of fstat() with DJGPP, because + // then we have a better chance to get st_ino value that can + // be used in io_open_dest_real() to prevent overwriting the + // source file. +#ifdef __DJGPP__ + if (stat(pair->src_name, &pair->src_st)) + goto error_msg; +#else if (fstat(pair->src_fd, &pair->src_st)) goto error_msg; +#endif if (S_ISDIR(pair->src_st.st_mode)) { message_warning(_("%s: Is a directory, skipping"), @@ -599,6 +608,28 @@ io_open_dest_real(file_pair *pair) if (pair->dest_name == NULL) return true; +#ifdef __DJGPP__ + struct stat st; + if (stat(pair->dest_name, &st) == 0) { + // Check that it isn't a special file like "prn". + if (st.st_dev == -1) { + message_error("%s: Refusing to write to " + "a DOS special file", + pair->dest_name); + return true; + } + + // Check that we aren't overwriting the source file. + if (st.st_dev == pair->src_st.st_dev + && st.st_ino == pair->src_st.st_ino) { + message_error("%s: Output file is the same " + "as the input file", + pair->dest_name); + return true; + } + } +#endif + // If --force was used, unlink the target file first. if (opt_force && unlink(pair->dest_name) && errno != ENOENT) { message_error(_("%s: Cannot remove: %s"), |