Subject: Re: bug#79130: Change/feature requests chcon/chgrp/chmod/chown/touch

From: Martin D Kealey <[email-masked]>
Date: Sat, 2 Aug 2025 19:43:41 +1000

On Thu, 31 Jul 2025 at 07:51, Pádraig Brady <[email-masked]> wrote:

> For consistency it probably makes sense for `chmod -h` to also
> not follow a symlink given as --reference=.
> I know mode bits are less supported on symlinks on various systems,
> but for consistency it probably makes sense.
>
[and I wrote]

> > (functionality subject to whether the underlying FS supports
> fchmodat(..., AT_SYMLINK_NOFOLLOW) aka lchmod),
>

Funny you should mention that; it's already in my patch set (wrapped in
#ifdef CAN_CHMOD_SYMLINK).

> An alternative (or additional) approach would be to add new explicit
> > options (such as '--symlink-reference' and '--follow-reference') to all
> of
> > the inode metadata manipulation commands including 'chcon', 'chgrp',
> > 'chmod', 'chown', & 'touch'.
>
> That would only be needed if mixing metadata between symlinks and non
> symlinks, which I don't see as that useful.
>

I don't mean that those options would *only* take symlinks, rather that
they would be guaranteed to follow or not follow one if it happened to be
provided.

On the whole I prefer the suggestion to have
--no-dereference=[none|src|dest|all] except for the unnecessary negative.
I suggest «--derefence=[n[one]|s[rc]|d[est]|a[ll]]» and the corresponding
version «-D[n|s|d|a]», with --no-dereference being a synonym for
«--dereference=none»/«-Dn» or «--dereference=src»/«-Ds» whichever matches
«-h» behaviour in each command.

(I'll grant that «-D*mode*» is a bit clunky, but it avoids a profusion of
new single-letter options, and I've often wished that cp, mv, ln, etc had
«-B*mode*» (corresponding to «--backup=*mode*», rather than just «-b».)

> Stepping back, I'm wondered about regularising the options available to
> all
> > the file manipulation commands, so 'touch' would gain '-R', '-H', '-L', &
> > '-P', and 'chmod' would gain '-h', '-H', '-L', & '-P' (functionality
> > subject to whether the underlying FS supports
> > fchmodat(..., AT_SYMLINK_NOFOLLOW) aka lchmod), plus the corresponding
> long
> > options.
>
> chmod(1) got those options in coreutils 9.5 as mentioned above.
> That was because it already had the -R option.
>

Oh, I was looking at v9.1, since that's what was shipping with Debian 12.11
(stable) released 2 months ago.
I should have looked at the newer git branches in Savannah, sorry.

It's best to avoid adding -R functionality to commands in general, so I'd
> leave touch as is

Fair point.

I had also been pondering adding --ref-prefix= where each target file would
obtain its reference from the corresponding file in another tree, which
would only really be useful with --recurse. (Doing that with internal
recursion would be a *lot* faster than, say «find . -type f -exec touch -h
--ref=/other/path/{} {} \;» since that needs a separate invocation of
«touch» for every target file.

In the same bucket of regularisation: every inode metadata command uses
«-c» to mean "verbose but only if it changes", EXCEPT «touch», where it's
"don't create". I don't suppose we could have a uniform
«--verbose=ifchanged»?

> Secondly, I note that 'touch -r' copies the atime and mtime separately;
> it would be nice to be able to have --atime= and --mtime= as separate
> options, as an alternative to both combined as --time=.
> > Again, I can provide a patch if this would be acceptable.
>
> I don't understand this request.
>

Currently it takes two invocations of ‘touch’ to change the atime and mtime
to different values, UNLESS you're using -r in which case just one
invocation will suffice: touch -r copies the reference's mtime onto the
target's mtime, and the reference's atime onto the target's atime.

The idea would be to be able to perform this using explicit values for
atime and mtime separately rather than using a reference file.

> Is it just an interface change to existing functionality?
>

Not really.

> If so that wouldn't be warranted IMHO.
>

Does my explanation make more sense?

-Martin