Die Unfähigkeit stat
, die Erstellungszeit anzuzeigen, ist auf die Beschränkung des stat(2)
Systemaufrufs zurückzuführen , dessen Rückgabestruktur kein Feld für die Erstellungszeit enthielt. Ab Linux 4.11 (dh 17.10 und neuer *) ist jedoch der neue statx(2)
Systemaufruf verfügbar, der in seiner Rückgabestruktur eine Erstellungszeit enthält.
* Und möglicherweise auf älteren LTS-Releases, die den Hardware-Enablement-Stack-Kernel (HWE-Kernel) verwenden. Überprüfen Sie uname -r
, ob Sie mindestens bei 4.11 einen Kernel verwenden, um dies zu bestätigen.
Leider ist es nicht einfach, Systemaufrufe direkt in einem C-Programm aufzurufen. Normalerweise bietet glibc einen Wrapper, der die Arbeit erleichtert, aber glibc hat erst statx(2)
im August 2018 einen Wrapper hinzugefügt (Version 2.28 , verfügbar ab 18.10). Zum Glück hat @whotwagner ein C-Beispielprogramm geschrieben, das zeigt, wie der statx(2)
Systemaufruf auf x86- und x86-64-Systemen verwendet wird. Die Ausgabe hat dasselbe Format wie stat
die Standardausgabe, jedoch ohne Formatierungsoptionen. Es ist jedoch einfach, das Format so zu ändern, dass nur die Geburtszeit gedruckt wird.
Zuerst klonen Sie es:
git clone https://github.com/whotwagner/statx-fun
Sie können den statx.c
Code kompilieren oder, wenn Sie nur die Geburtszeit möchten, birth.c
im geklonten Verzeichnis einen mit folgendem Code erstellen (dies ist eine minimale Version des statx.c
Ausdrucks nur des Erstellungszeitstempels einschließlich der Genauigkeit von Nanosekunden):
#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;
}
Dann:
$ make birth
$ ./birth ./birth.c
1511793291.254337149
$ ./birth ./birth.c | xargs -I {} date -d @{}
Mon Nov 27 14:34:51 UTC 2017
Theoretisch sollte dies die Erstellungszeit zugänglicher machen:
- es sollten mehr Dateisysteme unterstützt werden als nur die ext * -Dateisysteme (
debugfs
ist ein Tool für ext2 / 3/4-Dateisysteme und für andere nicht verwendbar)
- Sie benötigen kein root, um dies zu verwenden (außer zum Installieren einiger erforderlicher Pakete, wie
make
und linux-libc-dev
).
Testen eines XFS-Systems, zum Beispiel:
$ 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: -
Dies funktionierte jedoch nicht für NTFS und exfat. Ich denke, die FUSE-Dateisysteme für diese enthielten nicht die Erstellungszeit.
Ob oder wann glibc Unterstützung für den statx(2)
Systemaufruf hinzufügt , stat
wird in Kürze folgen, und wir können dafür den einfachen alten stat
Befehl verwenden. Aber ich glaube nicht, dass dies auf LTS-Releases zurückportiert wird, selbst wenn sie neuere Kernel bekommen. Daher erwarte ich stat
in keinem aktuellen LTS-Release (14.04, 16.04 oder 18.04), dass die Erstellungszeit jemals ohne manuelles Eingreifen gedruckt wird.
Am 18.10 können Sie die statx
Funktion jedoch direkt wie in beschrieben verwenden man 2 statx
(beachten Sie, dass die Manpage 18.10 nicht korrekt besagt, dass glibc den Wrapper noch nicht hinzugefügt hat).