Birth is empty on ext4 Announcing the arrival of Valued Associate #679: Cesar Manara Planned maintenance scheduled April 17/18, 2019 at 00:00UTC (8:00pm US/Eastern) 2019 Community Moderator Election Results Why I closed the “Why is Kali so hard” questionGetting file crtime under ext4 file systemWhy is time of birth of file unknown?Get file created/creation time?How do I do a ls and then sort the results by date created?Changing a file's “Date Created” and “Last Modified” attributes to another file'sWhat file systems on Linux store the creation time?How to reliably get timestamp at which the system booted?How to find what device a file is on (and use that in a script)?Does Linux have system calls to access all the features of the file systems it supports?Find the time of the file received in a particular directoryext4 used space (not -m option, not deleted files)Disk problems prevent me from booting, or set the disk to read-only. How do I fix the disk?Ext2 block structure: size of reserved GDT BlocksDisk usage in stat output and inodeFilesystem errors when restoring many filesPartition Errors and Remounts Read-Only when Accessing Specific FileIs the slash (/) part of the name of the Linux root directory?How to calculate the correct size of a loopback device filesystem image for debootstrap?I/O error after power failure, filesystem remounting as read-onlyHow to use ext4 inline_data to store empty directories?
What are the performance impacts of 'functional' Rust?
Typsetting diagram chases (with TikZ?)
How to set letter above or below the symbol?
Why don't the Weasley twins use magic outside of school if the Trace can only find the location of spells cast?
Who can trigger ship-wide alerts in Star Trek?
What is the order of Mitzvot in Rambam's Sefer Hamitzvot?
What do I do if technical issues prevent me from filing my return on time?
Did the new image of black hole confirm the general theory of relativity?
Stop battery usage [Ubuntu 18]
What did Darwin mean by 'squib' here?
Determine whether f is a function, an injection, a surjection
Why does tar appear to skip file contents when output file is /dev/null?
Slither Like a Snake
Why is there no army of Iron-Mans in the MCU?
How should I respond to a player wanting to catch a sword between their hands?
How is simplicity better than precision and clarity in prose?
What is the electric potential inside a point charge?
Direct Experience of Meditation
90's book, teen horror
Is it possible to ask for a hotel room without minibar/extra services?
Can a monk deflect thrown melee weapons?
Cauchy Sequence Characterized only By Directly Neighbouring Sequence Members
How to politely respond to generic emails requesting a PhD/job in my lab? Without wasting too much time
What to do with post with dry rot?
Birth is empty on ext4
Announcing the arrival of Valued Associate #679: Cesar Manara
Planned maintenance scheduled April 17/18, 2019 at 00:00UTC (8:00pm US/Eastern)
2019 Community Moderator Election Results
Why I closed the “Why is Kali so hard” questionGetting file crtime under ext4 file systemWhy is time of birth of file unknown?Get file created/creation time?How do I do a ls and then sort the results by date created?Changing a file's “Date Created” and “Last Modified” attributes to another file'sWhat file systems on Linux store the creation time?How to reliably get timestamp at which the system booted?How to find what device a file is on (and use that in a script)?Does Linux have system calls to access all the features of the file systems it supports?Find the time of the file received in a particular directoryext4 used space (not -m option, not deleted files)Disk problems prevent me from booting, or set the disk to read-only. How do I fix the disk?Ext2 block structure: size of reserved GDT BlocksDisk usage in stat output and inodeFilesystem errors when restoring many filesPartition Errors and Remounts Read-Only when Accessing Specific FileIs the slash (/) part of the name of the Linux root directory?How to calculate the correct size of a loopback device filesystem image for debootstrap?I/O error after power failure, filesystem remounting as read-onlyHow to use ext4 inline_data to store empty directories?
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;
I was just reading up on the Birth
section of stat
and it appears ext4 should support it, but even a file I just created leaves it empty.
~ % 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
Why doesn't my ext4
partition populate this field?
filesystems ext4 stat
add a comment |
I was just reading up on the Birth
section of stat
and it appears ext4 should support it, but even a file I just created leaves it empty.
~ % 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
Why doesn't my ext4
partition populate this field?
filesystems ext4 stat
add a comment |
I was just reading up on the Birth
section of stat
and it appears ext4 should support it, but even a file I just created leaves it empty.
~ % 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
Why doesn't my ext4
partition populate this field?
filesystems ext4 stat
I was just reading up on the Birth
section of stat
and it appears ext4 should support it, but even a file I just created leaves it empty.
~ % 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
Why doesn't my ext4
partition populate this field?
filesystems ext4 stat
filesystems ext4 stat
asked Oct 8 '12 at 3:48
xenoterracidexenoterracide
26.2k54159222
26.2k54159222
add a comment |
add a comment |
5 Answers
5
active
oldest
votes
The field gets populated (see below) only coreutils stat
does not display it. Apparently they're waiting1 for the xstat()
interface.
coreutils patches - aug. 2012 - TODO
stat(1) and ls(1) support for birth time. Dependent on xstat() being
provided by the kernel
You can get the creation time via debugfs
:
debugfs -R 'stat <inode_number>' DEVICE
e.g. for my /etc/profile
which is on /dev/sda2
(see How to find out what device a file is on):
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
1Linus' reply on LKML thread
sudo debugfs -R 'stat /path/to/foo' /dev/sda2
gives me/path/to/foo: File not found by ext2_lookup
.stat /path/to/foo
works (with Birth empty). Also,ext2
?
– Sparhawk
Nov 9 '13 at 3:01
4
@Sparhawk: I had this problem too with a file/home/user/path/to/file
because/home
was on a separate partition. In that case, the path provided tostat
must be relative to/home
. Example:sudo debugfs -R 'stat user/path/to/file' /dev/sda2
. To get rid of the path handling, we can provide tostat
the inode number instead of the path:sudo debugfs -R "stat <$(stat -c %i /home/user/path/to/file)>" /dev/sda5
– jpfleury
Apr 17 '14 at 2:39
Equivalent ofstat /home/richard
issudo debugfs -R 'stat /richard' /dev/disk/by-label/home
— assuming that/home
is a separate file-system, and you file-systems are labelled.
– ctrl-alt-delor
Aug 11 '14 at 11:27
2
Can this be used to get creation time of files from a network-mounted filesystem?
– taranaki
Sep 20 '18 at 18:32
1
So this is not a time stamp that goes beyond the creation of the file system. It means that if a file was created 25 years ago and copied through lots of different physical or mounted systems, there is no way at all to find the information of the date of creation in any of the metadata? So the only way to know when a file was made is to type it into the file name? Or inside the content? Is there any reason for this seemingly odd non implementation?
– sinekonata
Mar 1 at 3:10
|
show 7 more comments
I combined this into a simple shell function:
get_crtime()
grep -oP 'crtime.*--s*K.*')
printf "%st%sn" "$target" "$crtime"
done
You can then run it with
$ 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
is there a particular reason for not usinginode=$(stat -c %i "$target")
instead? It's easier and simpler..
– yat0
Oct 10 '15 at 17:33
@BrunoCasteleiro basically because that was the one that occurred to me and I like the chance to safely parsels
. It doesn't happen often :). You're right though,stat
is probably better, thanks.
– terdon♦
Oct 12 '15 at 11:39
1
Thanks for having all the steps combined into one function.
– WinEunuuchs2Unix
Dec 23 '18 at 18:38
add a comment |
The xstat
function never got merged into mainline. However, a new statx
call was proposed later on, and was merged in Linux 4.11. The new statx(2)
system call does include a creation time in its return struct.
However, userland has yet to catch up - it's not easy to call system calls directly in a C program. Typically glibc provides a wrapper that makes the job easy, but glibc added a wrapper for statx(2)
only in 2.28 (release August 2018). Luckily, @whotwagner wrote a sample C program that shows how to use the statx(2)
system call on x86 and x86-64 systems. Its output is the same format as stat
's default, without any formatting options, but it's simple to modify it to print just the birth time. (If you have a new enough glibc, you won't need this - you can use statx
directly as described in man 2 statx
).
First, clone it:
git clone https://github.com/whotwagner/statx-fun
You can compile the statx.c
code, or, if you just want the birth time, create a birth.c
in the cloned directory with the following code (which is a minimal version of statx.c
printing just the creation timestamp including nanosecond precision):
#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) = AT_STATX_FORCE_SYNC;
break;
case 'd':
flags &= ~AT_STATX_SYNC_TYPE;
flags
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.%un", *&stxbuf.stx_btime.tv_sec, *&stxbuf.stx_btime.tv_nsec);
return EXIT_SUCCESS;
Then:
$ make birth
$ ./birth ./birth.c
1511793291.254337149
$ ./birth ./birth.c | xargs -I date -d @
Mon Nov 27 14:34:51 UTC 2017
In theory this should make the creation time accessible on more filesystems than just the ext* ones (debugfs
is a tool for ext2/3/4 filesystems, and unusable on others). It did work for an XFS system, but not for NTFS and exfat. I guess the FUSE filesystems for those didn't include the creation time.
Now that glibc has support for the statx(2)
system call, stat
will follow soon and we'll be able to use the plain old stat
command for this.
add a comment |
There's another case where Birth time will be empty/zero/dash: Ext4's Inode size has to be at least 256bytes to store crtime
. The problem occur if you initially created the filesystem smaller than 512MB ( the default Inode size will be 128 bytes, see /etc/mke2fs.conf
and mkfs.ext4
manpage).
stat -c '%n: %w' testfile
testfile: -
and/or
stat -c '%n: %W' testfile
testfile: 0
Now check the filesystem inode (is it big enough to store crtime
?):
tune2fs -l $(df . --output=source | grep ^/) | grep "Inode size:"
Inode size: 128
Technical information: On the Ext4 Disk Layout page, note that some attributes of the inode tables are beyond 0x80 (128).
Correct (I remember reading about this on vger). The 512MB limit is defined inmke2fs.c
at line 1275
– don_crissti
Mar 27 '15 at 23:22
add a comment |
For what it's worth I was feeling pedantic so wrote a bash wrapper around stat to silently support crtime using debugfs to fetch it from an underlying ext4 filesystem if available. I hope it's robust. Find it here:
https://github.com/bernd-wechner/Linux-Tools/blob/master/xstat
Note that a fix is ostensibly on the todo list for Linux as documented in that script. So this wrapper has a nominal lifespan only until that is done and is more an exercise in what's doable.
1
Note thatxstat()
has eventually been added to Linux, so it's only a matter of time before the GNU libc andfind
add support for it.
– Stéphane Chazelas
Jun 3 '17 at 9:35
1
Awesome! Good news indeed.
– Bernd Wechner
Jun 3 '17 at 10:18
5
With apologies for being pedantic, you seem not to understand the meaning of "pedantic".
– Nick
Sep 22 '17 at 9:53
"overly concerned with minute details or formalisms" - as in, the accepted answer is fine, but ... let's formalise it. ;-)
– Bernd Wechner
Aug 30 '18 at 7:09
add a comment |
Your Answer
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "106"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f50177%2fbirth-is-empty-on-ext4%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
5 Answers
5
active
oldest
votes
5 Answers
5
active
oldest
votes
active
oldest
votes
active
oldest
votes
The field gets populated (see below) only coreutils stat
does not display it. Apparently they're waiting1 for the xstat()
interface.
coreutils patches - aug. 2012 - TODO
stat(1) and ls(1) support for birth time. Dependent on xstat() being
provided by the kernel
You can get the creation time via debugfs
:
debugfs -R 'stat <inode_number>' DEVICE
e.g. for my /etc/profile
which is on /dev/sda2
(see How to find out what device a file is on):
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
1Linus' reply on LKML thread
sudo debugfs -R 'stat /path/to/foo' /dev/sda2
gives me/path/to/foo: File not found by ext2_lookup
.stat /path/to/foo
works (with Birth empty). Also,ext2
?
– Sparhawk
Nov 9 '13 at 3:01
4
@Sparhawk: I had this problem too with a file/home/user/path/to/file
because/home
was on a separate partition. In that case, the path provided tostat
must be relative to/home
. Example:sudo debugfs -R 'stat user/path/to/file' /dev/sda2
. To get rid of the path handling, we can provide tostat
the inode number instead of the path:sudo debugfs -R "stat <$(stat -c %i /home/user/path/to/file)>" /dev/sda5
– jpfleury
Apr 17 '14 at 2:39
Equivalent ofstat /home/richard
issudo debugfs -R 'stat /richard' /dev/disk/by-label/home
— assuming that/home
is a separate file-system, and you file-systems are labelled.
– ctrl-alt-delor
Aug 11 '14 at 11:27
2
Can this be used to get creation time of files from a network-mounted filesystem?
– taranaki
Sep 20 '18 at 18:32
1
So this is not a time stamp that goes beyond the creation of the file system. It means that if a file was created 25 years ago and copied through lots of different physical or mounted systems, there is no way at all to find the information of the date of creation in any of the metadata? So the only way to know when a file was made is to type it into the file name? Or inside the content? Is there any reason for this seemingly odd non implementation?
– sinekonata
Mar 1 at 3:10
|
show 7 more comments
The field gets populated (see below) only coreutils stat
does not display it. Apparently they're waiting1 for the xstat()
interface.
coreutils patches - aug. 2012 - TODO
stat(1) and ls(1) support for birth time. Dependent on xstat() being
provided by the kernel
You can get the creation time via debugfs
:
debugfs -R 'stat <inode_number>' DEVICE
e.g. for my /etc/profile
which is on /dev/sda2
(see How to find out what device a file is on):
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
1Linus' reply on LKML thread
sudo debugfs -R 'stat /path/to/foo' /dev/sda2
gives me/path/to/foo: File not found by ext2_lookup
.stat /path/to/foo
works (with Birth empty). Also,ext2
?
– Sparhawk
Nov 9 '13 at 3:01
4
@Sparhawk: I had this problem too with a file/home/user/path/to/file
because/home
was on a separate partition. In that case, the path provided tostat
must be relative to/home
. Example:sudo debugfs -R 'stat user/path/to/file' /dev/sda2
. To get rid of the path handling, we can provide tostat
the inode number instead of the path:sudo debugfs -R "stat <$(stat -c %i /home/user/path/to/file)>" /dev/sda5
– jpfleury
Apr 17 '14 at 2:39
Equivalent ofstat /home/richard
issudo debugfs -R 'stat /richard' /dev/disk/by-label/home
— assuming that/home
is a separate file-system, and you file-systems are labelled.
– ctrl-alt-delor
Aug 11 '14 at 11:27
2
Can this be used to get creation time of files from a network-mounted filesystem?
– taranaki
Sep 20 '18 at 18:32
1
So this is not a time stamp that goes beyond the creation of the file system. It means that if a file was created 25 years ago and copied through lots of different physical or mounted systems, there is no way at all to find the information of the date of creation in any of the metadata? So the only way to know when a file was made is to type it into the file name? Or inside the content? Is there any reason for this seemingly odd non implementation?
– sinekonata
Mar 1 at 3:10
|
show 7 more comments
The field gets populated (see below) only coreutils stat
does not display it. Apparently they're waiting1 for the xstat()
interface.
coreutils patches - aug. 2012 - TODO
stat(1) and ls(1) support for birth time. Dependent on xstat() being
provided by the kernel
You can get the creation time via debugfs
:
debugfs -R 'stat <inode_number>' DEVICE
e.g. for my /etc/profile
which is on /dev/sda2
(see How to find out what device a file is on):
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
1Linus' reply on LKML thread
The field gets populated (see below) only coreutils stat
does not display it. Apparently they're waiting1 for the xstat()
interface.
coreutils patches - aug. 2012 - TODO
stat(1) and ls(1) support for birth time. Dependent on xstat() being
provided by the kernel
You can get the creation time via debugfs
:
debugfs -R 'stat <inode_number>' DEVICE
e.g. for my /etc/profile
which is on /dev/sda2
(see How to find out what device a file is on):
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
1Linus' reply on LKML thread
edited Apr 13 '17 at 12:37
Community♦
1
1
answered Oct 8 '12 at 5:04
don_crisstidon_crissti
52k15141169
52k15141169
sudo debugfs -R 'stat /path/to/foo' /dev/sda2
gives me/path/to/foo: File not found by ext2_lookup
.stat /path/to/foo
works (with Birth empty). Also,ext2
?
– Sparhawk
Nov 9 '13 at 3:01
4
@Sparhawk: I had this problem too with a file/home/user/path/to/file
because/home
was on a separate partition. In that case, the path provided tostat
must be relative to/home
. Example:sudo debugfs -R 'stat user/path/to/file' /dev/sda2
. To get rid of the path handling, we can provide tostat
the inode number instead of the path:sudo debugfs -R "stat <$(stat -c %i /home/user/path/to/file)>" /dev/sda5
– jpfleury
Apr 17 '14 at 2:39
Equivalent ofstat /home/richard
issudo debugfs -R 'stat /richard' /dev/disk/by-label/home
— assuming that/home
is a separate file-system, and you file-systems are labelled.
– ctrl-alt-delor
Aug 11 '14 at 11:27
2
Can this be used to get creation time of files from a network-mounted filesystem?
– taranaki
Sep 20 '18 at 18:32
1
So this is not a time stamp that goes beyond the creation of the file system. It means that if a file was created 25 years ago and copied through lots of different physical or mounted systems, there is no way at all to find the information of the date of creation in any of the metadata? So the only way to know when a file was made is to type it into the file name? Or inside the content? Is there any reason for this seemingly odd non implementation?
– sinekonata
Mar 1 at 3:10
|
show 7 more comments
sudo debugfs -R 'stat /path/to/foo' /dev/sda2
gives me/path/to/foo: File not found by ext2_lookup
.stat /path/to/foo
works (with Birth empty). Also,ext2
?
– Sparhawk
Nov 9 '13 at 3:01
4
@Sparhawk: I had this problem too with a file/home/user/path/to/file
because/home
was on a separate partition. In that case, the path provided tostat
must be relative to/home
. Example:sudo debugfs -R 'stat user/path/to/file' /dev/sda2
. To get rid of the path handling, we can provide tostat
the inode number instead of the path:sudo debugfs -R "stat <$(stat -c %i /home/user/path/to/file)>" /dev/sda5
– jpfleury
Apr 17 '14 at 2:39
Equivalent ofstat /home/richard
issudo debugfs -R 'stat /richard' /dev/disk/by-label/home
— assuming that/home
is a separate file-system, and you file-systems are labelled.
– ctrl-alt-delor
Aug 11 '14 at 11:27
2
Can this be used to get creation time of files from a network-mounted filesystem?
– taranaki
Sep 20 '18 at 18:32
1
So this is not a time stamp that goes beyond the creation of the file system. It means that if a file was created 25 years ago and copied through lots of different physical or mounted systems, there is no way at all to find the information of the date of creation in any of the metadata? So the only way to know when a file was made is to type it into the file name? Or inside the content? Is there any reason for this seemingly odd non implementation?
– sinekonata
Mar 1 at 3:10
sudo debugfs -R 'stat /path/to/foo' /dev/sda2
gives me /path/to/foo: File not found by ext2_lookup
. stat /path/to/foo
works (with Birth empty). Also, ext2
?– Sparhawk
Nov 9 '13 at 3:01
sudo debugfs -R 'stat /path/to/foo' /dev/sda2
gives me /path/to/foo: File not found by ext2_lookup
. stat /path/to/foo
works (with Birth empty). Also, ext2
?– Sparhawk
Nov 9 '13 at 3:01
4
4
@Sparhawk: I had this problem too with a file
/home/user/path/to/file
because /home
was on a separate partition. In that case, the path provided to stat
must be relative to /home
. Example: sudo debugfs -R 'stat user/path/to/file' /dev/sda2
. To get rid of the path handling, we can provide to stat
the inode number instead of the path: sudo debugfs -R "stat <$(stat -c %i /home/user/path/to/file)>" /dev/sda5
– jpfleury
Apr 17 '14 at 2:39
@Sparhawk: I had this problem too with a file
/home/user/path/to/file
because /home
was on a separate partition. In that case, the path provided to stat
must be relative to /home
. Example: sudo debugfs -R 'stat user/path/to/file' /dev/sda2
. To get rid of the path handling, we can provide to stat
the inode number instead of the path: sudo debugfs -R "stat <$(stat -c %i /home/user/path/to/file)>" /dev/sda5
– jpfleury
Apr 17 '14 at 2:39
Equivalent of
stat /home/richard
is sudo debugfs -R 'stat /richard' /dev/disk/by-label/home
— assuming that /home
is a separate file-system, and you file-systems are labelled.– ctrl-alt-delor
Aug 11 '14 at 11:27
Equivalent of
stat /home/richard
is sudo debugfs -R 'stat /richard' /dev/disk/by-label/home
— assuming that /home
is a separate file-system, and you file-systems are labelled.– ctrl-alt-delor
Aug 11 '14 at 11:27
2
2
Can this be used to get creation time of files from a network-mounted filesystem?
– taranaki
Sep 20 '18 at 18:32
Can this be used to get creation time of files from a network-mounted filesystem?
– taranaki
Sep 20 '18 at 18:32
1
1
So this is not a time stamp that goes beyond the creation of the file system. It means that if a file was created 25 years ago and copied through lots of different physical or mounted systems, there is no way at all to find the information of the date of creation in any of the metadata? So the only way to know when a file was made is to type it into the file name? Or inside the content? Is there any reason for this seemingly odd non implementation?
– sinekonata
Mar 1 at 3:10
So this is not a time stamp that goes beyond the creation of the file system. It means that if a file was created 25 years ago and copied through lots of different physical or mounted systems, there is no way at all to find the information of the date of creation in any of the metadata? So the only way to know when a file was made is to type it into the file name? Or inside the content? Is there any reason for this seemingly odd non implementation?
– sinekonata
Mar 1 at 3:10
|
show 7 more comments
I combined this into a simple shell function:
get_crtime()
grep -oP 'crtime.*--s*K.*')
printf "%st%sn" "$target" "$crtime"
done
You can then run it with
$ 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
is there a particular reason for not usinginode=$(stat -c %i "$target")
instead? It's easier and simpler..
– yat0
Oct 10 '15 at 17:33
@BrunoCasteleiro basically because that was the one that occurred to me and I like the chance to safely parsels
. It doesn't happen often :). You're right though,stat
is probably better, thanks.
– terdon♦
Oct 12 '15 at 11:39
1
Thanks for having all the steps combined into one function.
– WinEunuuchs2Unix
Dec 23 '18 at 18:38
add a comment |
I combined this into a simple shell function:
get_crtime()
grep -oP 'crtime.*--s*K.*')
printf "%st%sn" "$target" "$crtime"
done
You can then run it with
$ 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
is there a particular reason for not usinginode=$(stat -c %i "$target")
instead? It's easier and simpler..
– yat0
Oct 10 '15 at 17:33
@BrunoCasteleiro basically because that was the one that occurred to me and I like the chance to safely parsels
. It doesn't happen often :). You're right though,stat
is probably better, thanks.
– terdon♦
Oct 12 '15 at 11:39
1
Thanks for having all the steps combined into one function.
– WinEunuuchs2Unix
Dec 23 '18 at 18:38
add a comment |
I combined this into a simple shell function:
get_crtime()
grep -oP 'crtime.*--s*K.*')
printf "%st%sn" "$target" "$crtime"
done
You can then run it with
$ 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
I combined this into a simple shell function:
get_crtime()
grep -oP 'crtime.*--s*K.*')
printf "%st%sn" "$target" "$crtime"
done
You can then run it with
$ 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
edited 17 hours ago
dessert
1,262724
1,262724
answered May 21 '14 at 15:37
terdon♦terdon
134k33270450
134k33270450
is there a particular reason for not usinginode=$(stat -c %i "$target")
instead? It's easier and simpler..
– yat0
Oct 10 '15 at 17:33
@BrunoCasteleiro basically because that was the one that occurred to me and I like the chance to safely parsels
. It doesn't happen often :). You're right though,stat
is probably better, thanks.
– terdon♦
Oct 12 '15 at 11:39
1
Thanks for having all the steps combined into one function.
– WinEunuuchs2Unix
Dec 23 '18 at 18:38
add a comment |
is there a particular reason for not usinginode=$(stat -c %i "$target")
instead? It's easier and simpler..
– yat0
Oct 10 '15 at 17:33
@BrunoCasteleiro basically because that was the one that occurred to me and I like the chance to safely parsels
. It doesn't happen often :). You're right though,stat
is probably better, thanks.
– terdon♦
Oct 12 '15 at 11:39
1
Thanks for having all the steps combined into one function.
– WinEunuuchs2Unix
Dec 23 '18 at 18:38
is there a particular reason for not using
inode=$(stat -c %i "$target")
instead? It's easier and simpler..– yat0
Oct 10 '15 at 17:33
is there a particular reason for not using
inode=$(stat -c %i "$target")
instead? It's easier and simpler..– yat0
Oct 10 '15 at 17:33
@BrunoCasteleiro basically because that was the one that occurred to me and I like the chance to safely parse
ls
. It doesn't happen often :). You're right though, stat
is probably better, thanks.– terdon♦
Oct 12 '15 at 11:39
@BrunoCasteleiro basically because that was the one that occurred to me and I like the chance to safely parse
ls
. It doesn't happen often :). You're right though, stat
is probably better, thanks.– terdon♦
Oct 12 '15 at 11:39
1
1
Thanks for having all the steps combined into one function.
– WinEunuuchs2Unix
Dec 23 '18 at 18:38
Thanks for having all the steps combined into one function.
– WinEunuuchs2Unix
Dec 23 '18 at 18:38
add a comment |
The xstat
function never got merged into mainline. However, a new statx
call was proposed later on, and was merged in Linux 4.11. The new statx(2)
system call does include a creation time in its return struct.
However, userland has yet to catch up - it's not easy to call system calls directly in a C program. Typically glibc provides a wrapper that makes the job easy, but glibc added a wrapper for statx(2)
only in 2.28 (release August 2018). Luckily, @whotwagner wrote a sample C program that shows how to use the statx(2)
system call on x86 and x86-64 systems. Its output is the same format as stat
's default, without any formatting options, but it's simple to modify it to print just the birth time. (If you have a new enough glibc, you won't need this - you can use statx
directly as described in man 2 statx
).
First, clone it:
git clone https://github.com/whotwagner/statx-fun
You can compile the statx.c
code, or, if you just want the birth time, create a birth.c
in the cloned directory with the following code (which is a minimal version of statx.c
printing just the creation timestamp including nanosecond precision):
#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) = AT_STATX_FORCE_SYNC;
break;
case 'd':
flags &= ~AT_STATX_SYNC_TYPE;
flags
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.%un", *&stxbuf.stx_btime.tv_sec, *&stxbuf.stx_btime.tv_nsec);
return EXIT_SUCCESS;
Then:
$ make birth
$ ./birth ./birth.c
1511793291.254337149
$ ./birth ./birth.c | xargs -I date -d @
Mon Nov 27 14:34:51 UTC 2017
In theory this should make the creation time accessible on more filesystems than just the ext* ones (debugfs
is a tool for ext2/3/4 filesystems, and unusable on others). It did work for an XFS system, but not for NTFS and exfat. I guess the FUSE filesystems for those didn't include the creation time.
Now that glibc has support for the statx(2)
system call, stat
will follow soon and we'll be able to use the plain old stat
command for this.
add a comment |
The xstat
function never got merged into mainline. However, a new statx
call was proposed later on, and was merged in Linux 4.11. The new statx(2)
system call does include a creation time in its return struct.
However, userland has yet to catch up - it's not easy to call system calls directly in a C program. Typically glibc provides a wrapper that makes the job easy, but glibc added a wrapper for statx(2)
only in 2.28 (release August 2018). Luckily, @whotwagner wrote a sample C program that shows how to use the statx(2)
system call on x86 and x86-64 systems. Its output is the same format as stat
's default, without any formatting options, but it's simple to modify it to print just the birth time. (If you have a new enough glibc, you won't need this - you can use statx
directly as described in man 2 statx
).
First, clone it:
git clone https://github.com/whotwagner/statx-fun
You can compile the statx.c
code, or, if you just want the birth time, create a birth.c
in the cloned directory with the following code (which is a minimal version of statx.c
printing just the creation timestamp including nanosecond precision):
#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) = AT_STATX_FORCE_SYNC;
break;
case 'd':
flags &= ~AT_STATX_SYNC_TYPE;
flags
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.%un", *&stxbuf.stx_btime.tv_sec, *&stxbuf.stx_btime.tv_nsec);
return EXIT_SUCCESS;
Then:
$ make birth
$ ./birth ./birth.c
1511793291.254337149
$ ./birth ./birth.c | xargs -I date -d @
Mon Nov 27 14:34:51 UTC 2017
In theory this should make the creation time accessible on more filesystems than just the ext* ones (debugfs
is a tool for ext2/3/4 filesystems, and unusable on others). It did work for an XFS system, but not for NTFS and exfat. I guess the FUSE filesystems for those didn't include the creation time.
Now that glibc has support for the statx(2)
system call, stat
will follow soon and we'll be able to use the plain old stat
command for this.
add a comment |
The xstat
function never got merged into mainline. However, a new statx
call was proposed later on, and was merged in Linux 4.11. The new statx(2)
system call does include a creation time in its return struct.
However, userland has yet to catch up - it's not easy to call system calls directly in a C program. Typically glibc provides a wrapper that makes the job easy, but glibc added a wrapper for statx(2)
only in 2.28 (release August 2018). Luckily, @whotwagner wrote a sample C program that shows how to use the statx(2)
system call on x86 and x86-64 systems. Its output is the same format as stat
's default, without any formatting options, but it's simple to modify it to print just the birth time. (If you have a new enough glibc, you won't need this - you can use statx
directly as described in man 2 statx
).
First, clone it:
git clone https://github.com/whotwagner/statx-fun
You can compile the statx.c
code, or, if you just want the birth time, create a birth.c
in the cloned directory with the following code (which is a minimal version of statx.c
printing just the creation timestamp including nanosecond precision):
#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) = AT_STATX_FORCE_SYNC;
break;
case 'd':
flags &= ~AT_STATX_SYNC_TYPE;
flags
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.%un", *&stxbuf.stx_btime.tv_sec, *&stxbuf.stx_btime.tv_nsec);
return EXIT_SUCCESS;
Then:
$ make birth
$ ./birth ./birth.c
1511793291.254337149
$ ./birth ./birth.c | xargs -I date -d @
Mon Nov 27 14:34:51 UTC 2017
In theory this should make the creation time accessible on more filesystems than just the ext* ones (debugfs
is a tool for ext2/3/4 filesystems, and unusable on others). It did work for an XFS system, but not for NTFS and exfat. I guess the FUSE filesystems for those didn't include the creation time.
Now that glibc has support for the statx(2)
system call, stat
will follow soon and we'll be able to use the plain old stat
command for this.
The xstat
function never got merged into mainline. However, a new statx
call was proposed later on, and was merged in Linux 4.11. The new statx(2)
system call does include a creation time in its return struct.
However, userland has yet to catch up - it's not easy to call system calls directly in a C program. Typically glibc provides a wrapper that makes the job easy, but glibc added a wrapper for statx(2)
only in 2.28 (release August 2018). Luckily, @whotwagner wrote a sample C program that shows how to use the statx(2)
system call on x86 and x86-64 systems. Its output is the same format as stat
's default, without any formatting options, but it's simple to modify it to print just the birth time. (If you have a new enough glibc, you won't need this - you can use statx
directly as described in man 2 statx
).
First, clone it:
git clone https://github.com/whotwagner/statx-fun
You can compile the statx.c
code, or, if you just want the birth time, create a birth.c
in the cloned directory with the following code (which is a minimal version of statx.c
printing just the creation timestamp including nanosecond precision):
#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) = AT_STATX_FORCE_SYNC;
break;
case 'd':
flags &= ~AT_STATX_SYNC_TYPE;
flags
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.%un", *&stxbuf.stx_btime.tv_sec, *&stxbuf.stx_btime.tv_nsec);
return EXIT_SUCCESS;
Then:
$ make birth
$ ./birth ./birth.c
1511793291.254337149
$ ./birth ./birth.c | xargs -I date -d @
Mon Nov 27 14:34:51 UTC 2017
In theory this should make the creation time accessible on more filesystems than just the ext* ones (debugfs
is a tool for ext2/3/4 filesystems, and unusable on others). It did work for an XFS system, but not for NTFS and exfat. I guess the FUSE filesystems for those didn't include the creation time.
Now that glibc has support for the statx(2)
system call, stat
will follow soon and we'll be able to use the plain old stat
command for this.
edited Nov 20 '18 at 9:59
answered Nov 27 '17 at 15:24
murumuru
37.9k590166
37.9k590166
add a comment |
add a comment |
There's another case where Birth time will be empty/zero/dash: Ext4's Inode size has to be at least 256bytes to store crtime
. The problem occur if you initially created the filesystem smaller than 512MB ( the default Inode size will be 128 bytes, see /etc/mke2fs.conf
and mkfs.ext4
manpage).
stat -c '%n: %w' testfile
testfile: -
and/or
stat -c '%n: %W' testfile
testfile: 0
Now check the filesystem inode (is it big enough to store crtime
?):
tune2fs -l $(df . --output=source | grep ^/) | grep "Inode size:"
Inode size: 128
Technical information: On the Ext4 Disk Layout page, note that some attributes of the inode tables are beyond 0x80 (128).
Correct (I remember reading about this on vger). The 512MB limit is defined inmke2fs.c
at line 1275
– don_crissti
Mar 27 '15 at 23:22
add a comment |
There's another case where Birth time will be empty/zero/dash: Ext4's Inode size has to be at least 256bytes to store crtime
. The problem occur if you initially created the filesystem smaller than 512MB ( the default Inode size will be 128 bytes, see /etc/mke2fs.conf
and mkfs.ext4
manpage).
stat -c '%n: %w' testfile
testfile: -
and/or
stat -c '%n: %W' testfile
testfile: 0
Now check the filesystem inode (is it big enough to store crtime
?):
tune2fs -l $(df . --output=source | grep ^/) | grep "Inode size:"
Inode size: 128
Technical information: On the Ext4 Disk Layout page, note that some attributes of the inode tables are beyond 0x80 (128).
Correct (I remember reading about this on vger). The 512MB limit is defined inmke2fs.c
at line 1275
– don_crissti
Mar 27 '15 at 23:22
add a comment |
There's another case where Birth time will be empty/zero/dash: Ext4's Inode size has to be at least 256bytes to store crtime
. The problem occur if you initially created the filesystem smaller than 512MB ( the default Inode size will be 128 bytes, see /etc/mke2fs.conf
and mkfs.ext4
manpage).
stat -c '%n: %w' testfile
testfile: -
and/or
stat -c '%n: %W' testfile
testfile: 0
Now check the filesystem inode (is it big enough to store crtime
?):
tune2fs -l $(df . --output=source | grep ^/) | grep "Inode size:"
Inode size: 128
Technical information: On the Ext4 Disk Layout page, note that some attributes of the inode tables are beyond 0x80 (128).
There's another case where Birth time will be empty/zero/dash: Ext4's Inode size has to be at least 256bytes to store crtime
. The problem occur if you initially created the filesystem smaller than 512MB ( the default Inode size will be 128 bytes, see /etc/mke2fs.conf
and mkfs.ext4
manpage).
stat -c '%n: %w' testfile
testfile: -
and/or
stat -c '%n: %W' testfile
testfile: 0
Now check the filesystem inode (is it big enough to store crtime
?):
tune2fs -l $(df . --output=source | grep ^/) | grep "Inode size:"
Inode size: 128
Technical information: On the Ext4 Disk Layout page, note that some attributes of the inode tables are beyond 0x80 (128).
edited Mar 28 '15 at 6:14
answered Mar 27 '15 at 20:59
Franklin PiatFranklin Piat
1,9182028
1,9182028
Correct (I remember reading about this on vger). The 512MB limit is defined inmke2fs.c
at line 1275
– don_crissti
Mar 27 '15 at 23:22
add a comment |
Correct (I remember reading about this on vger). The 512MB limit is defined inmke2fs.c
at line 1275
– don_crissti
Mar 27 '15 at 23:22
Correct (I remember reading about this on vger). The 512MB limit is defined in
mke2fs.c
at line 1275– don_crissti
Mar 27 '15 at 23:22
Correct (I remember reading about this on vger). The 512MB limit is defined in
mke2fs.c
at line 1275– don_crissti
Mar 27 '15 at 23:22
add a comment |
For what it's worth I was feeling pedantic so wrote a bash wrapper around stat to silently support crtime using debugfs to fetch it from an underlying ext4 filesystem if available. I hope it's robust. Find it here:
https://github.com/bernd-wechner/Linux-Tools/blob/master/xstat
Note that a fix is ostensibly on the todo list for Linux as documented in that script. So this wrapper has a nominal lifespan only until that is done and is more an exercise in what's doable.
1
Note thatxstat()
has eventually been added to Linux, so it's only a matter of time before the GNU libc andfind
add support for it.
– Stéphane Chazelas
Jun 3 '17 at 9:35
1
Awesome! Good news indeed.
– Bernd Wechner
Jun 3 '17 at 10:18
5
With apologies for being pedantic, you seem not to understand the meaning of "pedantic".
– Nick
Sep 22 '17 at 9:53
"overly concerned with minute details or formalisms" - as in, the accepted answer is fine, but ... let's formalise it. ;-)
– Bernd Wechner
Aug 30 '18 at 7:09
add a comment |
For what it's worth I was feeling pedantic so wrote a bash wrapper around stat to silently support crtime using debugfs to fetch it from an underlying ext4 filesystem if available. I hope it's robust. Find it here:
https://github.com/bernd-wechner/Linux-Tools/blob/master/xstat
Note that a fix is ostensibly on the todo list for Linux as documented in that script. So this wrapper has a nominal lifespan only until that is done and is more an exercise in what's doable.
1
Note thatxstat()
has eventually been added to Linux, so it's only a matter of time before the GNU libc andfind
add support for it.
– Stéphane Chazelas
Jun 3 '17 at 9:35
1
Awesome! Good news indeed.
– Bernd Wechner
Jun 3 '17 at 10:18
5
With apologies for being pedantic, you seem not to understand the meaning of "pedantic".
– Nick
Sep 22 '17 at 9:53
"overly concerned with minute details or formalisms" - as in, the accepted answer is fine, but ... let's formalise it. ;-)
– Bernd Wechner
Aug 30 '18 at 7:09
add a comment |
For what it's worth I was feeling pedantic so wrote a bash wrapper around stat to silently support crtime using debugfs to fetch it from an underlying ext4 filesystem if available. I hope it's robust. Find it here:
https://github.com/bernd-wechner/Linux-Tools/blob/master/xstat
Note that a fix is ostensibly on the todo list for Linux as documented in that script. So this wrapper has a nominal lifespan only until that is done and is more an exercise in what's doable.
For what it's worth I was feeling pedantic so wrote a bash wrapper around stat to silently support crtime using debugfs to fetch it from an underlying ext4 filesystem if available. I hope it's robust. Find it here:
https://github.com/bernd-wechner/Linux-Tools/blob/master/xstat
Note that a fix is ostensibly on the todo list for Linux as documented in that script. So this wrapper has a nominal lifespan only until that is done and is more an exercise in what's doable.
edited Jun 3 '17 at 10:18
answered Jun 3 '17 at 9:31
Bernd WechnerBernd Wechner
1113
1113
1
Note thatxstat()
has eventually been added to Linux, so it's only a matter of time before the GNU libc andfind
add support for it.
– Stéphane Chazelas
Jun 3 '17 at 9:35
1
Awesome! Good news indeed.
– Bernd Wechner
Jun 3 '17 at 10:18
5
With apologies for being pedantic, you seem not to understand the meaning of "pedantic".
– Nick
Sep 22 '17 at 9:53
"overly concerned with minute details or formalisms" - as in, the accepted answer is fine, but ... let's formalise it. ;-)
– Bernd Wechner
Aug 30 '18 at 7:09
add a comment |
1
Note thatxstat()
has eventually been added to Linux, so it's only a matter of time before the GNU libc andfind
add support for it.
– Stéphane Chazelas
Jun 3 '17 at 9:35
1
Awesome! Good news indeed.
– Bernd Wechner
Jun 3 '17 at 10:18
5
With apologies for being pedantic, you seem not to understand the meaning of "pedantic".
– Nick
Sep 22 '17 at 9:53
"overly concerned with minute details or formalisms" - as in, the accepted answer is fine, but ... let's formalise it. ;-)
– Bernd Wechner
Aug 30 '18 at 7:09
1
1
Note that
xstat()
has eventually been added to Linux, so it's only a matter of time before the GNU libc and find
add support for it.– Stéphane Chazelas
Jun 3 '17 at 9:35
Note that
xstat()
has eventually been added to Linux, so it's only a matter of time before the GNU libc and find
add support for it.– Stéphane Chazelas
Jun 3 '17 at 9:35
1
1
Awesome! Good news indeed.
– Bernd Wechner
Jun 3 '17 at 10:18
Awesome! Good news indeed.
– Bernd Wechner
Jun 3 '17 at 10:18
5
5
With apologies for being pedantic, you seem not to understand the meaning of "pedantic".
– Nick
Sep 22 '17 at 9:53
With apologies for being pedantic, you seem not to understand the meaning of "pedantic".
– Nick
Sep 22 '17 at 9:53
"overly concerned with minute details or formalisms" - as in, the accepted answer is fine, but ... let's formalise it. ;-)
– Bernd Wechner
Aug 30 '18 at 7:09
"overly concerned with minute details or formalisms" - as in, the accepted answer is fine, but ... let's formalise it. ;-)
– Bernd Wechner
Aug 30 '18 at 7:09
add a comment |
Thanks for contributing an answer to Unix & Linux Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f50177%2fbirth-is-empty-on-ext4%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
-ext4, filesystems, stat