2

I wonder if there are ways to copy or restore crtime (creation time) for inodes/files/directories in Linux in 2020. I've accidentally deleted a folder while I still have a full disk backup, but neither cp -a, nor rsync can restore/copy files/directories crtimes.

I have found a way to achieve it using debugfs but it's super complicated and I need to automate it (I have hundreds of deleted files/directories).

For the source disk you do this:

# debugfs /dev/sdXX
# stat /path
Inode: 432772   Type: directory    Mode:  0700   Flags: 0x80000
Generation: 3810862225    Version: 0x00000000:00000006
User:  1000   Group:  1000   Project:     0   Size: 4096
File ACL: 0
Links: 5   Blockcount: 8
Fragment:  Address: 0    Number: 0    Size: 0
 ctime: 0x5db96479:184bb16c -- Wed Oct 30 15:22:49 2019
 atime: 0x5b687c70:ee4dff18 -- Mon Aug  6 21:50:56 2018
 mtime: 0x5db96479:184bb16c -- Wed Oct 30 15:22:49 2019
crtime: 0x5b687c70:d35d1348 -- Mon Aug  6 21:50:56 2018
Size of extra inode fields: 32
Extended attributes:
  security.selinux (40)
EXTENTS:
(0):1737229

Remember the crtime, these are two fields, crtime_lo (yes, the first) and crtime_hi (the second)

Then for the destination disk you do this:

# debugfs -w /dev/sdYY
# set_inode_field /path crtime_lo 0x${1st_value_from_earlier}
# set_inode_field /path crtime_hi 0x${2nd_value_from_earlier}

Maybe there's something else I'm missing in the debugfs manual which could help me do that, so I'd be glad if people could help.

-f cmd_file surely seems like a nice way to start but still a little bit too difficult for me.

Artem S. Tashkinov
  • 26,392
  • 4
  • 33
  • 64

2 Answers2

5

I've actually solved it on my own. You never know what you can do till you try :-)

It must be safe to run even when all the filesystems are mounted read-write.

#! /bin/bash

dsk_src=/dev/sdc4 # source disk with original timestamps
mnt_src=/mnt/sdc4 # source disk mounted at this path
dsk_dst=/dev/sda4 # destination disk
directory=user/.thunderbird # the leading slash _must_ be omitted

cd $mnt_src || exit 1

find $directory -depth | while read name; do
    read crtime_lo crtime_hi < <(debugfs -R "stat \"/$name\"" $dsk_src 2>/dev/null | awk '/crtime:/{print $2}' | sed 's/0x//;s/:/ /')

    echo "File: $name"
    echo "crtime_lo: $crtime_lo"
    echo "crtime_hi: $crtime_hi"

    debugfs -w $dsk_dst -R "set_inode_field \"/$name\" crtime_lo 0x$crtime_lo"
    debugfs -w $dsk_dst -R "set_inode_field \"/$name\" crtime_hi 0x$crtime_hi"
done

If people are interested I can adjust the script to allow to use it within one partition as well, e.g. after running cp -a. It's quite easy actually.

Artem S. Tashkinov
  • 26,392
  • 4
  • 33
  • 64
  • This works if you copy a disk and it does not look nice. It does not work when restoring a backup. – schily Jun 07 '20 at 17:30
  • 1
    Note that using `debugfs -w` is *not* safe to use on a mounted filesystem. This is modifying the blocks of the filesystem beneath the kernel, and can result in filesystem corruption (e.g. overwriting other inodes in the same block that may have been modified by the kernel). On the read side, you can use `statx()` with kernels > 3.10 (IIRC) to read the `stx_btime` (birth time) field, but there is no kernel interface for _storing_ the crtime/btime on a live filesystem, nor are the ext4 maintainers interested to add one. – LustreOne Jun 08 '20 at 23:42
  • 1
    Using debugfs as shown above is OK for an unmounted filesystem, but using separate debugfs commands can become very inefficient as the filesystem grows large and reading all of the metadata takes a long time. Instead, to make the above more efficient, you can generate just the list of commands, like "`echo set_inode_field $name crtime_lo 0x$crtime_lo`" and then pipe the whole while loop into "`debugfs -w -f /dev/stdin $dsk_dst`" so that it runs all of the commands in a single invocation. You could also dump the commands to a file first, to review them before execution. – LustreOne Jun 08 '20 at 23:45
  • 1
    I haven't checked the kernel code but altering crtime on a mounted filesystem shouldn't be be an issue because you're editing existing inodes internal attributes (not deleting or creating them) which must be safe. I've also confirmed that applying them to over two hundred files haven't caused any issues as a e2fsck run was clean. Piping debugfs commands surely looks like a nice idea but I just needed a quick hack and it worked perfectly. – Artem S. Tashkinov Jun 09 '20 at 13:47
1

If you have a modern tar archive that includes all time stamps, you can do this with star -xp -ctime ... in case you call star as root.

Note that this leẗ́s star cause time storms and should not be done in a serious multi user mode.

See http://schilytools.sourceforge.net/man/man1/star.1.html for moreinformation.

schily
  • 18,806
  • 5
  • 38
  • 60
  • It does it through the arse though. From the manual: ```If star is run as root and if -ctime is used with the extract command and the same archive formats, this causes star to try to restore even the ctime of a file by generating time storms.``` – Artem S. Tashkinov Jun 07 '20 at 15:56
  • Well, this is the only fs and OS independent method to do that job and it works with a backup.... – schily Jun 07 '20 at 17:28
  • I agree however it only does the job with a relatively low precision. The script I wrote for Linux restores crtime with nanosecond precision. – Artem S. Tashkinov Jun 07 '20 at 18:53
  • The precision is better than microseconds if your OS is halfway decent. Note that this is 30 year old code and at that time many OS did not yet give better file time stamp resolution than seconds. – schily Jun 07 '20 at 20:47
  • 1
    @schily Perhaps it's a good time to add a Linux-specific code path to restore `ctime` to `star`! – FUZxxl Jun 12 '20 at 12:09
  • @FUZxxl is there such an interface? From the OP, there seems to be just a debug program (that seems to be a bad idea on a buzy filesystem), but no programming interface. – schily Jun 12 '20 at 12:48
  • @schily Good question! I'll try to find out. – FUZxxl Jun 12 '20 at 18:11
  • @FUZxxl Have you found out anything? – Artem S. Tashkinov Dec 13 '20 at 09:31
  • @ArtemS.Tashkinov Nope. – FUZxxl Dec 13 '20 at 11:16