La incapacidad de stat
mostrar el tiempo de creación se debe a la limitación de la stat(2)
llamada al sistema , cuya estructura de retorno no incluyó un campo para el tiempo de creación. A partir de Linux 4.11 (es decir, 17.10 y posterior *), sin embargo, la nueva statx(2)
llamada del sistema está disponible, lo que incluye un tiempo de creación en su estructura de retorno.
* Y posiblemente en versiones anteriores de LTS utilizando los núcleos de la pila de habilitación de hardware (HWE). Verifique uname -r
si está utilizando un núcleo al menos a 4.11 para confirmar.
Desafortunadamente, no es fácil llamar a las llamadas del sistema directamente en un programa en C. Por lo general, glibc proporciona un contenedor que facilita el trabajo, pero glibc solo agregó un contenedor para statx(2)
agosto de 2018 (versión 2.28 , disponible en 18.10). Afortunadamente, @whotwagner escribió un programa C de muestra que muestra cómo usar la statx(2)
llamada del sistema en sistemas x86 y x86-64. Su salida es el mismo formato que stat
el predeterminado, sin ninguna opción de formato, pero es simple modificarlo para imprimir solo la hora de nacimiento.
Primero, clónalo:
git clone https://github.com/whotwagner/statx-fun
Puede compilar el statx.c
código o, si solo desea la hora de nacimiento, crear un birth.c
en el directorio clonado con el siguiente código (que es una versión mínima de statx.c
impresión solo la marca de tiempo de creación, incluida la precisión de nanosegundos):
#define _GNU_SOURCE
#define _ATFILE_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include "statx.h"
#include <time.h>
#include <getopt.h>
#include <string.h>
// does not (yet) provide a wrapper for the statx() system call
#include <sys/syscall.h>
/* this code works ony with x86 and x86_64 */
#if __x86_64__
#define __NR_statx 332
#else
#define __NR_statx 383
#endif
#define statx(a,b,c,d,e) syscall(__NR_statx,(a),(b),(c),(d),(e))
int main(int argc, char *argv[])
{
int dirfd = AT_FDCWD;
int flags = AT_SYMLINK_NOFOLLOW;
unsigned int mask = STATX_ALL;
struct statx stxbuf;
long ret = 0;
int opt = 0;
while(( opt = getopt(argc, argv, "alfd")) != -1)
{
switch(opt) {
case 'a':
flags |= AT_NO_AUTOMOUNT;
break;
case 'l':
flags &= ~AT_SYMLINK_NOFOLLOW;
break;
case 'f':
flags &= ~AT_STATX_SYNC_TYPE;
flags |= AT_STATX_FORCE_SYNC;
break;
case 'd':
flags &= ~AT_STATX_SYNC_TYPE;
flags |= AT_STATX_DONT_SYNC;
break;
default:
exit(EXIT_SUCCESS);
break;
}
}
if (optind >= argc) {
exit(EXIT_FAILURE);
}
for (; optind < argc; optind++) {
memset(&stxbuf, 0xbf, sizeof(stxbuf));
ret = statx(dirfd, argv[optind], flags, mask, &stxbuf);
if( ret < 0)
{
perror("statx");
return EXIT_FAILURE;
}
printf("%lld.%u\n", *&stxbuf.stx_btime.tv_sec, *&stxbuf.stx_btime.tv_nsec);
}
return EXIT_SUCCESS;
}
Entonces:
$ make birth
$ ./birth ./birth.c
1511793291.254337149
$ ./birth ./birth.c | xargs -I {} date -d @{}
Mon Nov 27 14:34:51 UTC 2017
En teoría, esto debería hacer que el tiempo de creación sea más accesible:
- Se deben admitir más sistemas de archivos que solo los ext * (
debugfs
es una herramienta para sistemas de archivos ext2 / 3/4, e inutilizable en otros)
- no necesita root para usar esto (excepto para instalar algunos paquetes requeridos, como
make
y linux-libc-dev
).
Probar un sistema xfs, por ejemplo:
$ truncate -s 1G temp; mkfs -t xfs temp; mkdir foo; sudo mount temp foo; sudo chown $USER foo
$ touch foo/bar
$ # some time later
$ echo > foo/bar
$ chmod og-w foo/bar
$ ./birth foo/bar | xargs -I {} date -d @{}
Mon Nov 27 14:43:21 UTC 2017
$ stat foo/bar
File: foo/bar
Size: 1 Blocks: 8 IO Block: 4096 regular file
Device: 700h/1792d Inode: 99 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 1000/ muru) Gid: ( 1000/ muru)
Access: 2017-11-27 14:43:32.845579010 +0000
Modify: 2017-11-27 14:44:38.809696644 +0000
Change: 2017-11-27 14:44:45.536112317 +0000
Birth: -
Sin embargo, esto no funcionó para NTFS y exfat. Supongo que los sistemas de archivos FUSE para aquellos no incluyeron el tiempo de creación.
Si, o más bien cuándo, glibc agrega soporte para la statx(2)
llamada al sistema, stat
seguirá pronto y podremos usar el stat
comando anterior para esto. Pero no creo que esto sea compatible con las versiones de LTS, incluso si obtienen núcleos más nuevos. Por lo tanto, no espero que stat
en cualquier corriente versión LTS (14.04, 16.04 y 18.04) para imprimir cada vez el tiempo de creación sin intervención manual.
Sin embargo, en 18.10, puede usar directamente la statx
función como se describe en man 2 statx
(tenga en cuenta que la página de manual 18.10 es incorrecta al indicar que glibc aún no ha agregado el contenedor).