A incapacidade de stat
de mostrar o tempo de criação é devido à limitação do stat(2)
system call , cuja estrutura de retorno não incluiu um campo para o tempo de criação. Começando com o Linux 4.11 (ie, 17.10 e mais recente *), no entanto, o novo statx(2)
chamada de sistema está disponível, o que inclui uma hora de criação em sua estrutura de retorno.
* E possivelmente em versões mais antigas do LTS usando os kernels da pilha de ativação de hardware (HWE). Verifique uname -r
para ver se você está usando um kernel pelo menos em 4.11 para confirmar.
Infelizmente, não é fácil chamar chamadas do sistema diretamente em um programa em C. Normalmente, a glibc fornece um wrapper que facilita o trabalho, mas a glibc apenas adicionou um wrapper para statx(2)
em agosto de 2018 (versão 2.28 , disponível em 18.10). Felizmente, @whotwagner escreveu um exemplo de programa em C que mostra como usar a chamada do sistema statx(2)
em x86 e x86-64 sistemas. Sua saída é o mesmo formato que o padrão stat
, sem nenhuma opção de formatação, mas é simples modificá-lo para imprimir apenas a hora de nascimento.
Primeiro, clone-o:
git clone https://github.com/whotwagner/statx-fun
Você pode compilar o código statx.c
ou, se desejar apenas a hora de nascimento, criar um birth.c
no diretório clonado com o código a seguir (que é uma versão mínima de statx.c
imprimindo apenas o timestamp de criação incluindo a precisão de nanossegundos):
#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;
}
Então:
$ make birth
$ ./birth ./birth.c
1511793291.254337149
$ ./birth ./birth.c | xargs -I {} date -d @{}
Mon Nov 27 14:34:51 UTC 2017
Em teoria, isso deve tornar o tempo de criação mais acessível:
- mais sistemas de arquivos devem ser suportados do que apenas os ext * (
debugfs
é uma ferramenta para sistemas de arquivos ext2 / 3/4 e inutilizável em outros)
- você não precisa do root para usar isso (exceto para instalar alguns pacotes necessários, como
make
e linux-libc-dev
).
Testando um sistema xfs, por exemplo:
$ 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: -
No entanto, isso não funcionou para NTFS e exfat. Eu acho que os sistemas de arquivos FUSE para aqueles não incluíram o tempo de criação.
Se, ou melhor, quando, a glibc adicionar suporte para a chamada do sistema statx(2)
, stat
seguirá em breve e poderemos usar o comando antigo stat
para isso. Mas eu não acho que isso será backportado para as versões LTS, mesmo se eles tiverem novos kernels. Então, eu não espero que stat
em qualquer versão atual do LTS (14.04, 16.04 ou 18.04) imprima o tempo de criação sem intervenção manual.
Em 18.10, no entanto, você pode usar diretamente a função statx
, conforme descrito em man 2 statx
(observe que a página do manual 18.10 está incorreta em afirmar que a glibc ainda não adicionou o wrapper).