Il semble que vous ayez trouvé un bogue dans macOS. La version quasi-finale du système d'exploitation fonctionne selon la page du manuel, mais la dernière version ne le fait pas.
Soit la page du manuel est obsolète, soit le logiciel a un bogue (le plus probable).
Vous pouvez envoyer des commentaires à Apple en tant qu'utilisateur général ici :
https://www.apple.com/feedback/macos.html
Ou si vous êtes un développeur, vous pouvez utiliser l'Assistant de rétroaction pour soumettre un rapport de bogue tel que décrit ici :
https://developer.apple.com/bug-reporting/
Il n'y a actuellement aucune version plus récente de touch
disponible chez Apple, donc vous ne pouvez pas mettre à jour pour résoudre le problème. Comme vous l'avez indiqué vous-même, vous pouvez plutôt utiliser la version GNU de touch
pour effectuer la tâche. Vous pouvez la trouver dans Homebrew en installant coreutils
.
La version GNU de touch
fonctionne en appelant les nouvelles fonctions futimens()
/utimensat()
(dans le dernier cas avec l'argument flag
défini sur AT_SYMLINK_NOFOLLOW
pour changer l'horodatage du lien lui-même).
La version Catalina de touch
(287.100.2) fonctionne en appelant la fonction plus ancienne lutimes()
, qui définit explicitement l'horodatage sur le lien lui-même. Une des différences essentielles entre les API plus récentes et plus anciennes est que les plus récentes prennent en charge les horodatages en nanosecondes, tandis que les plus anciennes ont une résolution plus faible.
La fonction lutimes()
sur Big Sur ne met en œuvre aucun appel système en elle-même, mais est entièrement contenue dans la bibliothèque des normes, utilisant la fonction setattrlist()
(qui entraîne un appel système) pour effectuer réellement la modification du système de fichiers. setattrlist()
dépend fortement du système de fichiers (c'est-à-dire que son fonctionnement sur les systèmes de fichiers HFS+ serait différent de son fonctionnement sur les systèmes de fichiers APFS).
La version Big Sur de touch
(321.100.11) fonctionne en appelant directement la fonction setattrlist()
, et seulement en cas d'échec, elle se rabat sur lutimes
. Malheureusement, il semble que le programmeur ait oublié de spécifier que lorsque -h
est spécifié, la modification doit avoir lieu sur le lien lui-même.
Le bogue réel se situe à la ligne 219 de touch.c, où cette ligne se trouve :
if (!setattrlist(*argv, &ts_req, &ts_struct, sizeof(ts_struct), 0))
aurait dû être :
if (!setattrlist(*argv, &ts_req, &ts_struct, sizeof(ts_struct), utimes_f == lutimes ? FSOPT_NOFOLLOW : 0))
Vous pourriez modifier cela dans touch.c, le recompiler, et obtenir un exécutable fonctionnel.