| // SPDX-License-Identifier: GPL-2.0 |
| /* |
| * Test ctime and mtime are updated on truncate(2) and ftruncate(2) |
| * Copyright (c) 2013 Red Hat, Inc. All Rights Reserved. |
| */ |
| |
| #include <sys/stat.h> |
| #include <sys/types.h> |
| #include <fcntl.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <unistd.h> |
| |
| #define TEST_MSG "this is a test string" |
| |
| int do_test(const char *file, int is_ftrunc) |
| { |
| int ret; |
| int fd; |
| struct stat statbuf1; |
| struct stat statbuf2; |
| |
| ret = 0; |
| fd = open(file, O_RDWR | O_CREAT | O_TRUNC, 0644); |
| if (fd == -1) { |
| perror("open(2) failed"); |
| exit(EXIT_FAILURE); |
| } |
| |
| ret = write(fd, TEST_MSG, sizeof(TEST_MSG)); |
| if (ret == -1) { |
| perror("write(2) failed"); |
| exit(EXIT_FAILURE); |
| } |
| |
| /* Get timestamps before [f]truncate(2) */ |
| ret = fstat(fd, &statbuf1); |
| if (ret == -1) { |
| perror("fstat(2) failed"); |
| exit(EXIT_FAILURE); |
| } |
| |
| /* Test [f]truncate(2) down */ |
| sleep(1); |
| if (is_ftrunc) { |
| ret = ftruncate(fd, 0); |
| if (ret == -1) { |
| perror("ftruncate(2) down failed"); |
| exit(EXIT_FAILURE); |
| } |
| } else { |
| ret = truncate(file, 0); |
| if (ret == -1) { |
| perror("truncate(2) down failed"); |
| exit(EXIT_FAILURE); |
| } |
| } |
| |
| /* Get timestamps after [f]truncate(2) */ |
| ret = fstat(fd, &statbuf2); |
| if (ret == -1) { |
| perror("fstat(2) failed"); |
| exit(EXIT_FAILURE); |
| } |
| |
| /* Check whether timestamps got updated on [f]truncate(2) down */ |
| if (statbuf1.st_ctime == statbuf2.st_ctime) { |
| fprintf(stderr, "ctime not updated after %s\n", |
| is_ftrunc ? "ftruncate" : "truncate" " down"); |
| ret++; |
| } |
| if (statbuf1.st_mtime == statbuf2.st_mtime) { |
| fprintf(stderr, "mtime not updated after %s\n", |
| is_ftrunc ? "ftruncate" : "truncate" " down"); |
| ret++; |
| } |
| |
| /* Test [f]truncate(2) up */ |
| sleep(1); |
| if (is_ftrunc) { |
| ret = ftruncate(fd, 123); |
| if (ret == -1) { |
| perror("ftruncate(2) up failed"); |
| exit(EXIT_FAILURE); |
| } |
| } else { |
| ret = truncate(file, 123); |
| if (ret == -1) { |
| perror("truncate(2) up failed"); |
| exit(EXIT_FAILURE); |
| } |
| } |
| ret = fstat(fd, &statbuf1); |
| if (ret == -1) { |
| perror("fstat(2) failed"); |
| exit(EXIT_FAILURE); |
| } |
| /* Check whether timestamps got updated on [f]truncate(2) up */ |
| if (statbuf1.st_ctime == statbuf2.st_ctime) { |
| fprintf(stderr, "ctime not updated after %s\n", |
| is_ftrunc ? "ftruncate" : "truncate" " up"); |
| ret++; |
| } |
| if (statbuf1.st_mtime == statbuf2.st_mtime) { |
| fprintf(stderr, "mtime not updated after %s\n", |
| is_ftrunc ? "ftruncate" : "truncate" " up"); |
| ret++; |
| } |
| |
| close(fd); |
| return ret; |
| } |
| |
| int main(int argc, char *argv[]) |
| { |
| int ret; |
| char *testfile; |
| |
| ret = 0; |
| if (argc != 2) { |
| fprintf(stderr, "Usage: %s <filename>\n", argv[0]); |
| exit(EXIT_FAILURE); |
| } |
| testfile = argv[1]; |
| |
| ret = do_test(testfile, 0); |
| ret += do_test(testfile, 1); |
| |
| exit(ret); |
| } |