La naissance est vide sur ext4

83

Je viens de lire sur la Birthsection de statet il semble que ext4 devrait la supporter, mais même un fichier que je viens de créer la laisse vide.

 ~  % touch test                                                       slave-iv
 ~  % stat test.pl                                                     slave-iv
  File: ‘test.pl’
  Size: 173             Blocks: 8          IO Block: 4096   regular file
Device: 903h/2307d      Inode: 41943086    Links: 1
Access: (0600/-rw-------)  Uid: ( 1000/xenoterracide)   Gid: (  100/   users)
Access: 2012-09-22 18:22:16.924634497 -0500
Modify: 2012-09-22 18:22:16.924634497 -0500
Change: 2012-09-22 18:22:16.947967935 -0500
 Birth: -

 ~  % sudo tune2fs -l /dev/md3 | psp4                                  slave-iv
tune2fs 1.42.5 (29-Jul-2012)
Filesystem volume name:   home
Last mounted on:          /home
Filesystem UUID:          ab2e39fb-acdd-416a-9e10-b501498056de
Filesystem magic number:  0xEF53
Filesystem revision #:    1 (dynamic)
Filesystem features:      has_journal ext_attr resize_inode dir_index filetype needs_recovery extent flex_bg sparse_super large_file huge_file uninit_bg dir_nlink extra_isize
Filesystem flags:         signed_directory_hash 
Default mount options:    journal_data
Filesystem state:         clean
Errors behavior:          Continue
Filesystem OS type:       Linux
Inode count:              59736064
Block count:              238920960
Reserved block count:     11946048
Free blocks:              34486248
Free inodes:              59610013
First block:              0
Block size:               4096
Fragment size:            4096
Reserved GDT blocks:      967
Blocks per group:         32768
Fragments per group:      32768
Inodes per group:         8192
Inode blocks per group:   512
RAID stride:              128
RAID stripe width:        256
Flex block group size:    16
Filesystem created:       Mon May 31 20:36:30 2010
Last mount time:          Sat Oct  6 11:01:01 2012
Last write time:          Sat Oct  6 11:01:01 2012
Mount count:              14
Maximum mount count:      34
Last checked:             Tue Jul 10 08:26:37 2012
Check interval:           15552000 (6 months)
Next check after:         Sun Jan  6 07:26:37 2013
Lifetime writes:          7255 GB
Reserved blocks uid:      0 (user root)
Reserved blocks gid:      0 (group root)
First inode:              11
Inode size:           256
Required extra isize:     28
Desired extra isize:      28
Journal inode:            8
First orphan inode:       55313243
Default directory hash:   half_md4
Directory Hash Seed:      442c66e8-8b67-4a8c-92a6-2e2d0c220044
Journal backup:           inode blocks

Pourquoi ma ext4partition ne remplit-elle pas ce champ?

xénoterracide
la source

Réponses:

93

Le champ est rempli (voir ci-dessous), mais coreutils statne l'affiche pas. Apparemment , ils attendent 1 pour l' xstat()interface de .

patchs coreutils - août 2012 - TODO

stat (1) et ls (1) support pour l'heure de naissance. Dépend de xstat () fourni par le noyau

Vous pouvez obtenir le temps de création via debugfs:

debugfs -R 'stat <inode_number>' DEVICE

par exemple pour mon /etc/profilequi est allumé /dev/sda2(voir Comment savoir sur quel périphérique se trouve un fichier ):

stat -c% i / etc / profile
398264
debugfs -R 'stat <398264>' /dev/sda2
debugfs 1.42.5 (29-Jul-2012)
Inode: 398264   Type: regular    Mode:  0644   Flags: 0x80000
Generation: 2058737571    Version: 0x00000000:00000001
User:     0   Group:     0   Size: 562
File ACL: 0    Directory ACL: 0
Links: 1   Blockcount: 8
Fragment:  Address: 0    Number: 0    Size: 0
 ctime: 0x506b860b:19fa3c34 -- Wed Oct  3 02:25:47 2012
 atime: 0x50476677:dcd84978 -- Wed Sep  5 16:49:27 2012
 mtime: 0x506b860b:19fa3c34 -- Wed Oct  3 02:25:47 2012
crtime: 0x50476677:dcd84978 -- Wed Sep  5 16:49:27 2012
Size of extra inode fields: 28
EXTENTS:
(0):3308774

1 Réponse de Linus sur le fil de discussion LKML

don_crissti
la source
7
@Sparhawk: J'ai eu ce problème aussi avec un fichier /home/user/path/to/fileparce qu'il /homeétait sur une partition séparée. Dans ce cas, le chemin fourni à statdoit être relatif à /home. Exemple: sudo debugfs -R 'stat user/path/to/file' /dev/sda2. Pour se débarrasser de la gestion du chemin, nous pouvons fournir statle numéro d'inode au lieu du chemin:sudo debugfs -R "stat <$(stat -c %i /home/user/path/to/file)>" /dev/sda5
jpfleury
3
Cela peut-il être utilisé pour obtenir le temps de création de fichiers à partir d'un système de fichiers monté sur le réseau?
taranaki
1
Ce n’est donc pas un horodatage qui va au-delà de la création du système de fichiers. Cela signifie que si un fichier a été créé il y a 25 ans et copié sur de nombreux systèmes physiques ou montés, il est impossible de trouver l'information de la date de création dans les métadonnées. Donc, la seule façon de savoir quand un fichier a été créé est de le taper dans le nom du fichier? Ou à l'intérieur du contenu? Y a-t-il une raison pour cette non-application apparemment étrange?
sinekonata
2
Les métadonnées du fichier @sinekonata dépendent beaucoup du système (comme le montre cette réponse, chaque couche du système d'exploitation doit pouvoir le traiter) et sa conservation sur les copies entre machines repose sur la prise en charge de ce format de métadonnées par les systèmes et l'outil de copie. Cela signifie que vous êtes chanceux si vous obtenez même le nom du fichier non mutilé. Certains formats de fichier vous permettent également d’insérer des métadonnées dans le fichier (par exemple, ID3 ), ce qui est généralement efficace, mais de nombreux formats n’ont pas cette caractéristique. Enfin, vous pouvez placer le fichier dans un fichier d’archive de la manière suivante:
André Paramés
1
Notez que le <et >autour du numéro d'inode sont obligatoires. Ils sont souvent utilisés dans des exemples pour entourer une variable qui doit être ajustée, mais dans ce cas, ils doivent être entrés littéralement. Sans eux, le numéro d'inode est traité comme un chemin et vous obtenez une File not found by ext2_lookuperreur.
mardi
31

J'ai combiné cela dans une simple fonction shell:

get_crtime() {
  for target in "${@}"; do
    inode=$(stat -c %i "${target}")
    fs=$(df  --output=source "${target}"  | tail -1)
    crtime=$(sudo debugfs -R 'stat <'"${inode}"'>' "${fs}" 2>/dev/null | 
    grep -oP 'crtime.*--\s*\K.*')
    printf "%s\t%s\n" "${target}" "${crtime}"
  done
    }

Vous pouvez ensuite le lancer avec

$ get_crtime foo foo/file /etc/
foo Wed May 21 17:11:08 2014
foo/file    Wed May 21 17:11:27 2014
/etc/   Wed Aug  1 20:42:03 2012
terdon
la source
22

La xstatfonction n'a jamais été fusionnée dans Mainline. Cependant, un nouvel statxappel a été proposé ultérieurement et a été fusionné dans Linux 4.11 . Le nouvel statx(2)appel système inclut une heure de création dans sa structure de retour. Une enveloppe pour a statx(2)été ajoutée à la glibc uniquement en 2.28 (sortie en août 2018) . Et le support pour l'utilisation de ce wrapper a été ajouté dans GNU coreutils 8.31 (publié en mars 2019):

stat affiche maintenant l'heure de création du fichier pris en charge par le système de fichiers, sur les systèmes GNU Linux avec glibc> = 2.28 et kernel> = 4.11.

% stat --version
stat (GNU coreutils) 8.31
Copyright (C) 2019 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Michael Meskes.
% stat /
  File: /
  Size: 4096            Blocks: 8          IO Block: 4096   directory
Device: b302h/45826d    Inode: 2           Links: 17
Access: (0755/drwxr-xr-x)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2019-06-06 20:03:12.898725626 +0900
Modify: 2019-05-28 05:15:44.452651395 +0900
Change: 2019-05-28 05:15:44.452651395 +0900
 Birth: 2018-06-07 20:35:54.000000000 +0900

Ce qui suit est une démonstration de l’ statxendroit où l’utilisateur n’a pas encore rattrapé son retard (ancien glibc ou coreutils). Il n'est pas facile d'appeler des appels système directement dans un programme C. En général, glibc fournit un wrapper qui facilite le travail, mais Heureusement, @whotwagner a écrit un exemple de programme en C qui montre comment utiliser l' statx(2)appel système sur les systèmes x86 et x86-64. Sa sortie est au même format que celui statpar défaut, sans aucune option de formatage, mais il est simple de le modifier pour n’imprimer que l’heure de naissance. (Si vous avez assez de nouvelle glibc, vous n'en aurez pas besoin - vous pouvez utiliser statxdirectement comme décrit dans man 2 statx).

Commencez par le cloner:

git clone https://github.com/whotwagner/statx-fun

Vous pouvez compiler le statx.ccode ou, si vous voulez seulement l'heure de naissance, créer un birth.cdans le répertoire cloné avec le code suivant (qui est une version minimale de l' statx.cimpression uniquement de l'horodatage de création avec une précision à la nanoseconde):

#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;
}

Ensuite:

$ make birth
$ ./birth ./birth.c
1511793291.254337149
$ ./birth ./birth.c | xargs -I {} date -d @{}
Mon Nov 27 14:34:51 UTC 2017

En théorie, cela devrait rendre le temps de création accessible sur plus de systèmes de fichiers que les seuls systèmes ext * ( debugfsest un outil pour les systèmes de fichiers ext2 / 3/4 et inutilisable pour les autres). Cela a fonctionné pour un système XFS, mais pas pour NTFS et exfat. Je suppose que les systèmes de fichiers FUSE pour ceux-ci n'incluaient pas le moment de la création.

muru
la source
5

Il existe un autre cas où l'heure de naissance sera vide / zéro / tiret: la taille de l'inode d'Ext4 doit être d'au moins 256 octets à stocker crtime. Le problème se produit si vous avez initialement créé un système de fichiers inférieur à 512 Mo (la taille par défaut d’Inode sera de 128 octets, voir /etc/mke2fs.confet la mkfs.ext4page de manuel).

stat -c '%n: %w' testfile
testfile: -  

et / ou

stat -c '%n: %W' testfile
testfile: 0

Maintenant, vérifiez l’inode du système de fichiers (est-il assez grand pour être stocké crtime?):

tune2fs -l $(df . --output=source | grep ^/) | grep "Inode size:"
Inode size:           128

Informations techniques: Sur la page Disposition du disque Ext4 , notez que certains attributs des tables inode sont supérieurs à 0x80 (128).

Franklin Piat
la source
Correct (je me rappelle avoir lu à ce sujet sur vger ). La limite de 512 Mo est définie mke2fs.cà la ligne 1275
don_crissti
2

Pour ce que ça vaut, je me sentais pédant alors j'ai écrit un wrapper bash autour de stat pour prendre en charge silencieusement crtime en utilisant debugfs pour le récupérer à partir d'un système de fichiers ext4 sous-jacent, le cas échéant. J'espère que c'est robuste. Trouvez le ici .

Notez qu'un correctif est apparemment dans la liste de tâches pour Linux, comme indiqué dans ce script. Cette enveloppe a donc une durée de vie nominale jusqu'à ce que cela soit fait et constitue davantage un exercice réalisable.

Bernd Wechner
la source
3
Notez que cela xstat()a finalement été ajouté à Linux, ce n’est donc qu’une question de temps avant que la GNU libc et le findsupporte.
Stéphane Chazelas
1
Impressionnant! Bonne nouvelle en effet.
Bernd Wechner
6
Avec des excuses pour être pédant, vous semblez ne pas comprendre le sens de "pédant".
Nick
"excessivement préoccupé par les détails ou les formalismes" - comme dans, la réponse acceptée convient, mais ... formalisons-la. ;-)
Bernd Wechner