Setting/Changing the Ctime or "Change Time" Attribute on a File

Setting/changing the ctime or Change time attribute on a file

I was able to modify the ctime with two different methods:

  1. Changing the kernel so that ctime matches the mtime
  2. Writing a simple (but hacky) shell script.

1st Method: Changing the kernel.

I tweaked just a few lines in KERNEL_SRC/fs/attr.c This modification updates the ctime to match the mtime whenever the mtime is "explicitly defined."

There are many ways to "explicitly define" the mtime, for example:

In Linux:

touch -m --date="Wed Jun 12 14:00:00 IDT 2013" filename

In Java (using Java 6 or 7, and presumably others):

long newModificationTime = TIME_IN_MILLIS_SINCE_EPOCH;
File myFile = new File(myPath);
newmeta.setLastModified(newModificationTime);

Here is the change to KERNEL_SRC/fs/attr.c in the notify_change function:

    now = current_fs_time(inode->i_sb);

//attr->ia_ctime = now; (1) Comment this out
if (!(ia_valid & ATTR_ATIME_SET))
attr->ia_atime = now;
if (!(ia_valid & ATTR_MTIME_SET)) {
attr->ia_mtime = now;
}
else { //mtime is modified to a specific time. (2) Add these lines
attr->ia_ctime = attr->ia_mtime; //Sets the ctime
attr->ia_atime = attr->ia_mtime; //Sets the atime (optional)
}

(1) This line, uncommented, would update the ctime to the current clock time upon a change to the file. We don't want that, since we want to set the ctime ourselves. Thus, we comment this line out. (This isn't mandatory)

(2) This is really the crux of the solution. The notify_change function is executed after a file has been changed, where the time metadata needs to be updated. If no mtime was specified, then the mtime is set to the current time. Else, if the mtime was set to a specific value, we also set the ctime and the atime to that value.

2nd method: Simple (but hacky) shell script.

Brief explanation:

  1. Change the system time to your target time
  2. Perform a chmod on the file, file ctime now reflects target time
  3. Revert the system time back.

changectime.sh

#!/bin/sh
now=$(date)
echo $now
sudo date --set="Sat May 11 06:00:00 IDT 2013"
chmod 777 $1
sudo date --set="$now"

Run this as follows:
./changectime.sh MYFILE

The file's ctime will now reflect the time in the file.

Of course, you probably don't want the file with 777 permissions. Ensure that you modify this script to your needs before using it.

How to modify 'last status change' (ctime) property of a file in Unix?

ctime is the time the file's inode was last changed. mtime is the last time the file's CONTENTS were changed. To modify ctime, you'll have to do something to the inode, such as doing a chmod or chown on the file.

Changing the file's contents will necessarily also update ctime, as the atime/mtime/ctime values are stored in the inode. Modifying mtime means ctime also gets updated.

Why does the change time(ctime) of a directory change when creating a new file in it?

According to stat() system call specification:

The stat() function shall update any time-related fields (as described in XBD File Times Update), before writing into the stat structure.

In the corresponding File Times Update document:

Each function or utility in POSIX.1-2017 that reads or writes data (even if the data does not change) or performs an operation to change file status (even if the file status does not change) indicates which of the appropriate timestamps shall be marked for update.

The list of POSIX system calls contains the following calls related to creation of objects inside a directory:

  • link()

    Upon successful completion, link() shall mark for update the last file status change timestamp of the file. Also, the last data modification and last file status change timestamps of the directory that contains the new entry shall be marked for update.

  • mkdir()

    Upon successful completion, mkdir() shall mark for update the last data access, last data modification, and last file status change timestamps of the directory. Also, the last data modification and last file status change timestamps of the directory that contains the new entry shall be marked for update.

  • mkfifo()

    Upon successful completion, mkfifo() shall mark for update the last data access, last data modification, and last file status change timestamps of the file. Also, the last data modification and last file status change timestamps of the directory that contains the new entry shall be marked for update.

  • mknod()

    Upon successful completion, mknod() shall mark for update the last data access, last data modification, and last file status change timestamps of the file. Also, the last data modification and last file status change timestamps of the directory that contains the new entry shall be marked for update.

  • open()

    If O_CREAT is set and the file did not previously exist, upon successful completion, open() shall mark for update the last data access, last data modification, and last file status change timestamps of the file and the last data modification and last file status change timestamps of the parent directory.

  • symlink()

    Upon successful completion, symlink() shall mark for update the last data access, last data modification, and last file status change timestamps of the symbolic link. Also, the last data modification and last file status change timestamps of the directory that contains the new entry shall be marked for update.

API to set the timestamps on files & directories in btrfs

From C, the mtime and atime can be set using utime(2) and its relatives. utime(2) itself gives you seconds precision, utimes(2) has microseconds, and utimensat(2) gives you nanoseconds. There are variants like futime if you have a file handle instead of a file name.

Python can provide the same via the os.utime function.

Traditionally it is not possible to arbitrarily modify the otime or ctime, other than by manually editing the raw filesystem. I am not aware that Linux has provided any kernel API to modify them. Of course, you can update the ctime to the current time by changing its status in some way, and you can update the otime to the current time by deleting and recreating the file. In principle you can set them to a different time by changing the system clock first (if you are root), but this is likely to mess up lots of other stuff on the system and is probably a bad idea.

How do I get file creation and modification date/times?

In Python 3.4 and above, you can use the object oriented pathlib module interface which includes wrappers for much of the os module. Here is an example of getting the file stats.

>>> import pathlib
>>> fname = pathlib.Path('test.py')
>>> assert fname.exists(), f'No such file: {fname}' # check that the file exists
>>> print(fname.stat())
os.stat_result(st_mode=33206, st_ino=5066549581564298, st_dev=573948050, st_nlink=1, st_uid=0, st_gid=0, st_size=413, st_atime=1523480272, st_mtime=1539787740, st_ctime=1523480272)

For more information about what os.stat_result contains, refer to the documentation. For the modification time you want fname.stat().st_mtime:

>>> import datetime
>>> mtime = datetime.datetime.fromtimestamp(fname.stat().st_mtime, tz=datetime.timezone.utc)
>>> print(mtime)
datetime.datetime(2018, 10, 17, 10, 49, 0, 249980)

If you want the creation time on Windows, or the most recent metadata change on Unix, you would use fname.stat().st_ctime:

>>> ctime = datetime.datetime.fromtimestamp(fname.stat().st_ctime, tz=datetime.timezone.utc)
>>> print(ctime)
datetime.datetime(2018, 4, 11, 16, 57, 52, 151953)

This article has more helpful info and examples for the pathlib module.

How do I change the file creation date of a Windows file?

Yak shaving for the win.

import pywintypes, win32file, win32con
def changeFileCreationTime(fname, newtime):
wintime = pywintypes.Time(newtime)
winfile = win32file.CreateFile(
fname, win32con.GENERIC_WRITE,
win32con.FILE_SHARE_READ | win32con.FILE_SHARE_WRITE | win32con.FILE_SHARE_DELETE,
None, win32con.OPEN_EXISTING,
win32con.FILE_ATTRIBUTE_NORMAL, None)

win32file.SetFileTime(winfile, wintime, None, None)

winfile.close()

PHP - How to set ctime of a file in Unix system

You cannot change the ctime by ordinary means. This is by design:

The ctime is always updated to the current when you change any of the
file's metadata, and there is no way to impose a different ctime.

To change the ctime of a file, you can:

  • Set the system time to the ctime you want to impose, then touch the
    file, then reset the system time.


Related Topics



Leave a reply



Submit