A incapacidade de stat
mostrar o tempo de criação é devido à limitação da stat(2)
chamada do sistema , cuja estrutura de retorno não incluiu um campo para o tempo de criação. A partir do Linux 4.11 (ou seja, 17.10 e mais recente *), no entanto, a nova statx(2)
chamada do sistema está disponível, o que inclui um tempo de criação em sua estrutura de retorno.
* E possivelmente em versões mais antigas do LTS usando os kernels da pilha de habilitação de hardware (HWE). Verifique uname -r
se você está usando um kernel pelo menos em 4.11 para confirmar.
Infelizmente, não é fácil fazer chamadas do sistema diretamente em um programa C. Normalmente, a glibc fornece um wrapper que facilita o trabalho, mas a glibc adicionou um wrapper apenas statx(2)
em agosto de 2018 (versão 2.28 , disponível em 18.10). Felizmente, o @whotwagner escreveu um programa C de amostra que mostra como usar a statx(2)
chamada do sistema nos sistemas x86 e x86-64. Sua saída é do mesmo formato que stat
o padrão, sem nenhuma opção de formatação, mas é simples modificá-la para imprimir apenas a hora do nascimento.
Primeiro, clone-o:
git clone https://github.com/whotwagner/statx-fun
Você pode compilar o statx.c
código ou, se desejar apenas a hora do nascimento, criar um birth.c
no diretório clonado com o seguinte código (que é uma versão mínima da statx.c
impressão, apenas o carimbo de data / hora da criação, incluindo 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 usá-lo (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, o glibc adicionar suporte à statx(2)
chamada do sistema, stat
seguirá em breve e poderemos usar o stat
comando antigo simples para isso. Mas acho que isso não será suportado nos lançamentos do LTS, mesmo que eles tenham novos kernels. Portanto, não espero que stat
em nenhuma versão atual do LTS (14.04, 16.04 ou 18.04) imprima o tempo de criação sem intervenção manual.
No 18.10, no entanto, você pode usar diretamente a statx
função conforme descrito em man 2 statx
(observe que a página de manual 18.10 está incorreta ao afirmar que a glibc ainda não adicionou o wrapper).