Setting creation or change timestamps
Asked Answered
A

5

32

Using utimes, futimes, futimens, etc., it is possible to set the access and modification timestamps on a file.

Modification time is the last time the file data changed. Similarly, "ctime" or change time, is the last time attributes on the file, such as permissions, were changed. (Linux/POSIX maintains three timestamps: mtime and ctime, already discussed, and 'atime', or access time.)

Is there a function to set change timestamps? (Where "change" is the attribute modification or 'ctime', not modification time 'mtime'.) (I understand the cyclic nature of wanting to change the change timestamp, but think archiving software - it would be nice to restore a file exactly as it was.)

Are there any functions at all for creation timestamps? (I realize that ext2 does not support this, but I was wondering if Linux did, for those filesystems that do support it.)

If it's not possible, what is the reasoning behind it not being so?

Assyriology answered 27/12, 2010 at 7:45 Comment(9)
Isn't touch command takes a parameter to do it ?Straightlaced
@Madhur Ahuja: He wants to know how to do it from a C program.Jog
@Madhur Ahuja: touch does not have a parameter (at least, my version does not or is not documented to have one) for changing creation or change times. touch will change modification or access times, however.Assyriology
Strange, this page suggests otherwise: en.wikipedia.org/wiki/Touch_(Unix)Straightlaced
I see nothing on that page to indicate that touch has the capability to set change timestamps in any way. Note that I'm looking for change timestamps, which are a different beast from modification timestamps. I've tried to clarify my post on this point, if this is what is confusing. If it is not, what passage from that page gives you that suggestion?Assyriology
Ok, Pardon my lack of knowledge in linuxStraightlaced
@Madhur Ahuja: And pardon my unclear post. I will re-read it in a bit, to see if I can improve it once I've let myself get unfamiliar with it.Assyriology
I'm also looking for this, but my use case is for a FUSE based file cache which should have the exact same mtime/ctime as the file it is caching. Doesn't look like it is possible without either modifying the kernel or changing system time (very bad). I suppose I'll store it in an extended attribute instead...Deaconess
Related: unix.stackexchange.com/questions/36021/…Phthalein
F
32

For ext2/3 and possibly for ext4 you can do this with debugfs tool, assuming you want to change the ctime of file /tmp/foo which resides in disk /dev/sda1 we want to set ctime to 201001010101 which means 01 January 2010, time 01:01:

Warning: Disk must be unmounted before this operation

# Update ctime
debugfs -w -R 'set_inode_field /tmp/foo ctime 201001010101' /dev/sda1

# Drop vm cache so ctime update is reflected
echo 2 > /proc/sys/vm/drop_caches

Information taken from Command Line Kung Fu blog.

Fellner answered 27/12, 2010 at 9:5 Comment(4)
Why must the disk be unmounted?Spruill
@eitan27 AFAIK debugfs will refuse to work if the disk is mounted, given it can harm the data on the disk.Fellner
@Spruill , because there is also disk and/or fs cache.Lipoprotein
@Eitan: Because you're changing bytes on disk, not going through the kernel's VFS cache. So the kernel's in-memory data could get out of sync with the data structures on disk.Fourchette
S
10

I had a similar issue, and wrote my answer here.

https://mcmap.net/q/454789/-setting-changing-the-ctime-or-quot-change-time-quot-attribute-on-a-file

There are essentially two options:

  1. Slight change in kernel (code included in link)
  2. Change the system clock to the desired ctime, touch the file, then restore current time. (shell script for that included in link).
Spruill answered 12/6, 2013 at 13:9 Comment(0)
P
7

According to http://lists.gnu.org/archive/html/coreutils/2010-08/msg00010.html ctime cannot be faked (at least it's not intended to be fakeable):

POSIX says that atime and mtime are user-settable to arbitrary times via the utimensat() family of syscalls, but that ctime must unfakeably track the current time of any action that changes a file's metadata or contents.

If you just need to change a file's ctime for some testing/debugging, bindfs might be helpful. It's a FUSE filesystem which mounts one directory into another place, and can do some transformation on the file attributes. With option --ctime-from-mtime the ctime of each file is the same as its mtime, which you can set with touch -t.

Placenta answered 1/7, 2013 at 12:14 Comment(3)
And, I think I gather, Linux (/POSIX) has no concept of a file creation time?Assyriology
I'm not experienced in that area; but according to unix.stackexchange.com/a/20464 the various standards don't require file creation time to be stored. Some filesystems store creation time anyway, and it can be accessed with nonstandard ways.Placenta
ctime is not create-time but file attributes' change-time. For example, the file size is such an attribute. Hence if you modify a file, ctime and mtime get altered. So backup tools can rely on ctime, as it cannot be faked (except if you warp the system time).Bruell
T
2

The easiest way:

1) change System time
2) copy paste a file on another location.

I tried this on windows 7 and I succeed to change all three timestamps. The stat command on linux shows that all three timestamps are changed.

Toady answered 19/4, 2016 at 8:38 Comment(0)
A
1

The script below automates running debugfs ... set_inode_field ... ctime ... in ismail's answer for many files. It will copy ctime values from files in /media/MYUSER/MYFS/FOO/BAR (recursively) to /media/MYUSER/MYFS2/FOO/BAR, and umount /media/MYUSER/MYFS2 as a side effect. It will work only if the filesystem of /media/MYUSER/MYFS2 is ext2, ext3 or ext4 (because debugfs works only for these filesystems).

mydev2="$(df /media/MYUSER/MYFS2 | perl -ne '$x = $1 if !m@^Filesystem @ and m@([^ ]+) @; END { print "$x\n" }')"
cd /media/MYUSER/MYFS
find FOO/BAR -type f | perl -ne 'chomp; my @st = lstat($_); if (@st and -f(_)) { s@"@""@g; print "set_inode_field \"/$_\" ctime \@$st[10]\n" }' >/tmp/sif.out
sudo umount /media/MYUSER/MYFS2  # Repeat until success.
sudo debugfs -w -f /tmp/sif.out /dev/"$mydev2"

It handles filenames with whitespace and special characters correctly.

It works independently of time zones. As a limitation of debugfs, its precision is seconds, it ignores anything smaller (e.g. milliseconds, microseconds, nanoseconds). Depending the version of debugfs used, it may use 32-bit timestamps, thus it works correctly with dates before 2038-01-19.

If the current user doesn't have enough read permissions for /media/MYUSER/MYFS, then the commands above should be run as root (sudo bash).

Alleneallentown answered 16/3, 2021 at 7:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.