mtime and ctime is not updated after truncate operation if file length was not changed
From: Vyacheslav Kovalevsky
Date: Fri Dec 12 2025 - 04:34:13 EST
Detailed description
====================
Last data modification and last file status change timestamps are not updated after truncate operation if the file content was not changed (truncate length == file length).
ext4 updates both mtime and ctime. But many (if not all?) other file systems (btrfs, xfs, nilfs2, f2fs, ???) do not update any timestamps.
The latter behavior seems to violate the POSIX.1-2024 standard. Documentation for `truncate()`: “Upon successful completion, truncate() shall mark for update the last data modification and last file status change timestamps of the file". No special cases described for (not) updating timestamps. `ftruncate` behaves as expected though.
Maybe I should also report this to the developers of other file systems.
System info
===========
Linux version 6.18.
How to reproduce
================
```
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
int main() {
int status;
struct stat file_stat;
status = creat("file", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
printf("CREAT: %d\n", status);
close(status);
status = stat("file", &file_stat);
printf("STAT: %d\n", status);
printf("atime=%ld\n", file_stat.st_atim.tv_nsec);
printf("mtime=%ld\n", file_stat.st_mtim.tv_nsec);
printf("ctime=%ld\n", file_stat.st_ctim.tv_nsec);
status = truncate("file", 0);
printf("TRUNCATE: %d\n", status);
status = stat("file", &file_stat);
printf("STAT: %d\n", status);
printf("atime=%ld\n", file_stat.st_atim.tv_nsec);
printf("mtime=%ld\n", file_stat.st_mtim.tv_nsec);
printf("ctime=%ld\n", file_stat.st_ctim.tv_nsec);
}
```
Expected output (ext4):
```
CREAT: 3
STAT: 0
atime=122561651
mtime=122561651
ctime=122561651
TRUNCATE: 0
STAT: 0
atime=122561651
mtime=124063093
ctime=124063093
```
Actual output (Btrfs):
```
CREAT: 3
STAT: 0
atime=502902570
mtime=502902570
ctime=502902570
TRUNCATE: 0
STAT: 0
atime=502902570
mtime=502902570
ctime=502902570
```