On 2020-12-28 Sebastian Andrzej Siewior wrote: > xz refuses to decompress a file which has more than one hard link. It > can be reproduced by (as per Vincent): > |$ echo foo > file1 > |$ xz file1 > |$ ln file1.xz file2.xz > |$ xz -dk file1.xz > |xz: file1.xz: Input file has more than one hard link, skipping > > This behaviour is consistent with `gzip' and `bzip2' but it is not > documented. The `--force' option would ignore this restriction.
The behavior is documented on the xz man page: Unless writing to standard output, xz will display a warning and skip the file if any of the following applies: o File is not a regular file. Symbolic links are not followed, and thus they are not considered to be regular files. o File has more than one hard link. o File has setuid, setgid, or sticky bit set. The reason why it's done is indeed missing. I don't have any better guesses than what you already listed in other messages. > Ignore hard link count on input. I'm fine with the patch since the suggested behavior makes sense to me too. There's always a risk that some specific use case can break due to this change but I guess that is acceptably low risk. I wonder if it were more logical if --keep also allowed processing of files with setuid, setgid, or sticky bit set. The same reasoning applies to all these cases, I suppose, and they are all within the same if-block in the code so it would still be a single-line change. What about symlinks or files that aren't regular files (like block devices)? I guess requiring --force for non-regular files makes sense still but perhaps symlinks that point to regular files are OK to process with --keep. Any thoughts on this patch? diff --git a/src/xz/file_io.c b/src/xz/file_io.c index e1a37d5..80b56d3 100644 --- a/src/xz/file_io.c +++ b/src/xz/file_io.c @@ -536,8 +536,9 @@ io_open_src_real(file_pair *pair) } // Symlinks are not followed unless writing to stdout or --force - // was used. - const bool follow_symlinks = opt_stdout || opt_force; + // or --keep was used. + const bool follow_symlinks + = opt_stdout || opt_force || opt_keep_original; // We accept only regular files if we are writing the output // to disk too. bzip2 allows overriding this with --force but @@ -674,7 +675,7 @@ io_open_src_real(file_pair *pair) } #ifndef TUKLIB_DOSLIKE - if (reg_files_only && !opt_force) { + if (reg_files_only && !opt_force && !opt_keep_original) { if (pair->src_st.st_mode & (S_ISUID | S_ISGID)) { // gzip rejects setuid and setgid files even // when --force was used. bzip2 doesn't check @@ -683,7 +684,7 @@ io_open_src_real(file_pair *pair) // and setgid bits there. // // We accept setuid and setgid files if - // --force was used. We drop these bits + // --force or --keep was used. We drop these bits // explicitly in io_copy_attr(). message_warning(_("%s: File has setuid or " "setgid bit set, skipping"), diff --git a/src/xz/xz.1 b/src/xz/xz.1 index db9de4f..e50e762 100644 --- a/src/xz/xz.1 +++ b/src/xz/xz.1 @@ -392,6 +392,20 @@ should be used. .TP .BR \-k ", " \-\-keep Don't delete the input files. +.IP "" +Since +.B xz +5.4.0, +this option also makes +.B xz +compress or decompress even if the input is +a symbolic link to a regular file, +has more than one hard link, +or has the setuid, setgid, or sticky bit set. +The setuid, setgid, and sticky bits are not copied +to the target file. +In earlier versions this was only done with +.BR \-\-force . .TP .BR \-f ", " \-\-force This option has several effects: -- Lasse Collin | IRC: Larhzu @ IRCnet & Freenode