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.
This commit is contained in:
parent
607f9f98ae
commit
cd4fe97852
|
@ -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"),
|
||||
|
|
Loading…
Reference in New Issue