function set_file_dates
Sets all file timestamps (creation time, modification time, access time, and change time) to a specified Unix timestamp by directly modifying the file's inode using debugfs.
/tf/active/vicechatdev/mailsearch/fix_file_dates.py
45 - 91
complex
Purpose
This function provides low-level timestamp manipulation for files on Linux ext filesystems. It bypasses normal filesystem APIs to set all four timestamp types (crtime, mtime, atime, ctime) simultaneously at the inode level, which is useful for forensic analysis, file restoration, or timestamp synchronization tasks where standard methods cannot modify all timestamps (particularly ctime and crtime).
Source Code
def set_file_dates(filepath, timestamp):
"""
Set all file dates (birth/crtime, modified/mtime, accessed/atime, changed/ctime) to the specified timestamp.
Uses debugfs to set all timestamps at the inode level.
"""
# Convert timestamp to datetime
dt = datetime.fromtimestamp(timestamp)
# Convert to POSIX seconds and split into 32-bit lo/hi parts
posix_seconds = int(timestamp)
time_lo = posix_seconds & 0xFFFFFFFF # Lower 32 bits
time_hi = (posix_seconds >> 32) & 0xFFFFFFFF # Higher 32 bits
# Get the device that contains the file
try:
result = subprocess.run(
['df', '--output=source', filepath],
capture_output=True,
text=True,
check=True
)
device = result.stdout.strip().split('\n')[1]
except (subprocess.CalledProcessError, IndexError) as e:
print(f" ✗ Failed to get device: {e}")
return False
# Use debugfs to set all timestamp fields at inode level
cmd = f"""debugfs -w {device} << EOF
set_inode_field "{filepath}" ctime_lo {time_lo}
set_inode_field "{filepath}" ctime_hi {time_hi}
set_inode_field "{filepath}" atime_lo {time_lo}
set_inode_field "{filepath}" atime_hi {time_hi}
set_inode_field "{filepath}" mtime_lo {time_lo}
set_inode_field "{filepath}" mtime_hi {time_hi}
set_inode_field "{filepath}" crtime_lo {time_lo}
set_inode_field "{filepath}" crtime_hi {time_hi}
quit
EOF
"""
try:
result = subprocess.run(cmd, shell=True, capture_output=True, text=True, check=True)
print(f" ✓ Set all timestamps to {dt.strftime('%Y-%m-%d %H:%M:%S')}")
return True
except subprocess.CalledProcessError as e:
print(f" ✗ Failed to set timestamps: {e.stderr}")
return False
Parameters
| Name | Type | Default | Kind |
|---|---|---|---|
filepath |
- | - | positional_or_keyword |
timestamp |
- | - | positional_or_keyword |
Parameter Details
filepath: String or path-like object representing the absolute or relative path to the file whose timestamps should be modified. The file must exist on an ext2/ext3/ext4 filesystem.
timestamp: Unix timestamp (float or int) representing the desired date/time in seconds since epoch (January 1, 1970). This value will be applied to all four timestamp fields (ctime, atime, mtime, crtime).
Return Value
Returns a boolean value: True if all timestamps were successfully set, False if any error occurred (such as failure to determine the device, permission issues, or debugfs command failure). The function also prints status messages to stdout indicating success or failure.
Dependencies
subprocessdatetimedebugfs (system utility)df (system utility)
Required Imports
from datetime import datetime
import subprocess
Usage Example
from datetime import datetime
import subprocess
def set_file_dates(filepath, timestamp):
dt = datetime.fromtimestamp(timestamp)
posix_seconds = int(timestamp)
time_lo = posix_seconds & 0xFFFFFFFF
time_hi = (posix_seconds >> 32) & 0xFFFFFFFF
try:
result = subprocess.run(['df', '--output=source', filepath], capture_output=True, text=True, check=True)
device = result.stdout.strip().split('\n')[1]
except (subprocess.CalledProcessError, IndexError) as e:
print(f" ✗ Failed to get device: {e}")
return False
cmd = f"""debugfs -w {device} << EOF
set_inode_field "{filepath}" ctime_lo {time_lo}
set_inode_field "{filepath}" ctime_hi {time_hi}
set_inode_field "{filepath}" atime_lo {time_lo}
set_inode_field "{filepath}" atime_hi {time_hi}
set_inode_field "{filepath}" mtime_lo {time_lo}
set_inode_field "{filepath}" mtime_hi {time_hi}
set_inode_field "{filepath}" crtime_lo {time_lo}
set_inode_field "{filepath}" crtime_hi {time_hi}
quit
EOF
"""
try:
result = subprocess.run(cmd, shell=True, capture_output=True, text=True, check=True)
print(f" ✓ Set all timestamps to {dt.strftime('%Y-%m-%d %H:%M:%S')}")
return True
except subprocess.CalledProcessError as e:
print(f" ✗ Failed to set timestamps: {e.stderr}")
return False
# Example usage (requires root privileges)
target_timestamp = datetime(2020, 1, 1, 12, 0, 0).timestamp()
success = set_file_dates('/path/to/file.txt', target_timestamp)
Best Practices
- This function requires root/sudo privileges to execute debugfs with write access
- Only works on ext2/ext3/ext4 filesystems - will fail on other filesystem types (NTFS, FAT32, Btrfs, etc.)
- Always backup important data before modifying inode-level metadata
- The function uses shell=True in subprocess.run which can be a security risk - ensure filepath is validated/sanitized
- Timestamps are split into 32-bit lo/hi parts to support 64-bit timestamps on modern filesystems
- The function prints status messages directly - consider capturing or redirecting output in production environments
- Modifying ctime (change time) is normally impossible through standard APIs - this is one of the few ways to do it
- Consider unmounting or remounting the filesystem after timestamp changes to ensure changes are fully committed
- Error handling catches subprocess errors but may not catch all edge cases (e.g., invalid timestamp values)
Tags
Similar Components
AI-powered semantic similarity - components with related functionality:
-
function fix_file_dates 68.8% similar
-
function get_file_times 64.8% similar
-
function main_v112 57.6% similar
-
function copy_file_with_date 57.4% similar
-
function modify_test_document 48.5% similar