Parece que has encontrado un error en MacOS. La penúltima versión del sistema operativo funciona según el manual, pero la última versión no.
O bien la página del manual está anticuada, o el software tiene un error (lo más probable).
Puedes enviar tus comentarios a Apple como usuario general aquí:'
https://www.apple.com/feedback/MacOS.html
O bien, si eres un desarrollador, puedes utilizar el Asistente de comentarios para presentar un informe de error como se describe aquí:
https://developer.apple.com/bug-reporting/
Actualmente no hay una versión más nueva de touch
disponible en Apple, por lo que no se puede, como tal, actualizar para salir del problema. Como tú mismo indicas, puedes utilizar en su lugar la versión GNU de touch
para hacer el trabajo. Puedes encontrarlo en Homebrew instalando coreutils
.
La versión GNU de touch
funciona llamando al nuevo futimens()
/ utimensat()
(en este último caso con el flag
con el argumento de AT_SYMLINK_NOFOLLOW
para cambiar la marca de tiempo del propio enlace).
La versión de Catalina de touch
( 287.100.2 ) funciona llamando al antiguo lutimes()
que establece explícitamente la marca de tiempo en el propio enlace. Una de las principales diferencias entre las APIs más nuevas y las más antiguas es que la más nueva soporta marcas de tiempo en nanosegundos, mientras que la más antigua tiene una resolución menor.
El lutimes()
en Big Sur en realidad no implementa una llamada al sistema en sí misma, sino que en realidad está contenida completamente en la biblioteca de estándares, utilizando la función setattrlist()
(que da lugar a una llamada al sistema) para realizar realmente la modificación del sistema de archivos. setattrlist()
depende en gran medida del sistema de archivos (es decir, la forma en que funciona en los sistemas de archivos HFS+ sería diferente de cómo funciona en los sistemas de archivos APFS).
La versión de Big Sur de touch
( 321.100.11 ) funciona llamando al setattrlist()
directamente, y sólo si eso falla, recurrir a la función lutimes
. Por desgracia, parece que el programador se olvidó de la necesidad de especificar que cuando -h
se especifica, la modificación debe tener lugar en el propio enlace.
El error real está en la línea 219 de touch.c donde esta línea:
if (!setattrlist(*argv, &ts_req, &ts_struct, sizeof(ts_struct), 0))
debería haber sido:
if (!setattrlist(*argv, &ts_req, &ts_struct, sizeof(ts_struct), utimes_f == lutimes ? FSOPT_NOFOLLOW : 0))
Puedes cambiar eso en touch.c, recompilarlo y obtener un binario que funcione.