1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (c) Zilogic Systems Pvt. Ltd., 2018 4f08c3bdfSopenharmony_ci * Email : code@zilogic.com 5f08c3bdfSopenharmony_ci */ 6f08c3bdfSopenharmony_ci 7f08c3bdfSopenharmony_ci/*\ 8f08c3bdfSopenharmony_ci * [Description] 9f08c3bdfSopenharmony_ci * 10f08c3bdfSopenharmony_ci * Test the following file timestamps of statx syscall: 11f08c3bdfSopenharmony_ci * 12f08c3bdfSopenharmony_ci * - btime - The time before and after the execution of the create system call is noted. 13f08c3bdfSopenharmony_ci * 14f08c3bdfSopenharmony_ci * - mtime - The time before and after the execution of the write system call is noted. 15f08c3bdfSopenharmony_ci * 16f08c3bdfSopenharmony_ci * - atime - The time before and after the execution of the read system call is noted. 17f08c3bdfSopenharmony_ci * 18f08c3bdfSopenharmony_ci * - ctime - The time before and after the execution of the chmod system call is noted. 19f08c3bdfSopenharmony_ci */ 20f08c3bdfSopenharmony_ci 21f08c3bdfSopenharmony_ci#define _GNU_SOURCE 22f08c3bdfSopenharmony_ci#include <stdio.h> 23f08c3bdfSopenharmony_ci#include <time.h> 24f08c3bdfSopenharmony_ci 25f08c3bdfSopenharmony_ci#include "tst_test.h" 26f08c3bdfSopenharmony_ci#include "tst_safe_clocks.h" 27f08c3bdfSopenharmony_ci#include "tst_safe_macros.h" 28f08c3bdfSopenharmony_ci#include "tst_timer.h" 29f08c3bdfSopenharmony_ci#include "lapi/stat.h" 30f08c3bdfSopenharmony_ci#include "lapi/mount.h" 31f08c3bdfSopenharmony_ci#include "lapi/fcntl.h" 32f08c3bdfSopenharmony_ci 33f08c3bdfSopenharmony_ci#define MOUNT_POINT "mount_ext" 34f08c3bdfSopenharmony_ci#define TEST_FILE MOUNT_POINT"/test_file.txt" 35f08c3bdfSopenharmony_ci#define SIZE 2 36f08c3bdfSopenharmony_ci 37f08c3bdfSopenharmony_cistatic int fd; 38f08c3bdfSopenharmony_ci 39f08c3bdfSopenharmony_cistatic void timestamp_to_timespec(const struct statx_timestamp *timestamp, 40f08c3bdfSopenharmony_ci struct timespec *timespec) 41f08c3bdfSopenharmony_ci{ 42f08c3bdfSopenharmony_ci timespec->tv_sec = timestamp->tv_sec; 43f08c3bdfSopenharmony_ci timespec->tv_nsec = timestamp->tv_nsec; 44f08c3bdfSopenharmony_ci} 45f08c3bdfSopenharmony_ci 46f08c3bdfSopenharmony_cistatic void clock_wait_tick(void) 47f08c3bdfSopenharmony_ci{ 48f08c3bdfSopenharmony_ci struct timespec res; 49f08c3bdfSopenharmony_ci unsigned int usecs; 50f08c3bdfSopenharmony_ci 51f08c3bdfSopenharmony_ci SAFE_CLOCK_GETRES(CLOCK_REALTIME_COARSE, &res); 52f08c3bdfSopenharmony_ci usecs = tst_timespec_to_us(res); 53f08c3bdfSopenharmony_ci 54f08c3bdfSopenharmony_ci usleep(usecs); 55f08c3bdfSopenharmony_ci} 56f08c3bdfSopenharmony_ci 57f08c3bdfSopenharmony_cistatic void create_file(void) 58f08c3bdfSopenharmony_ci{ 59f08c3bdfSopenharmony_ci if (fd > 0) { 60f08c3bdfSopenharmony_ci SAFE_CLOSE(fd); 61f08c3bdfSopenharmony_ci SAFE_UNLINK(TEST_FILE); 62f08c3bdfSopenharmony_ci } 63f08c3bdfSopenharmony_ci fd = SAFE_OPEN(TEST_FILE, O_CREAT | O_RDWR, 0666); 64f08c3bdfSopenharmony_ci} 65f08c3bdfSopenharmony_ci 66f08c3bdfSopenharmony_cistatic void write_file(void) 67f08c3bdfSopenharmony_ci{ 68f08c3bdfSopenharmony_ci char data[SIZE] = "hi"; 69f08c3bdfSopenharmony_ci 70f08c3bdfSopenharmony_ci SAFE_WRITE(SAFE_WRITE_ANY, fd, data, sizeof(data)); 71f08c3bdfSopenharmony_ci} 72f08c3bdfSopenharmony_ci 73f08c3bdfSopenharmony_cistatic void read_file(void) 74f08c3bdfSopenharmony_ci{ 75f08c3bdfSopenharmony_ci char data[SIZE]; 76f08c3bdfSopenharmony_ci 77f08c3bdfSopenharmony_ci SAFE_READ(0, fd, data, sizeof(data)); 78f08c3bdfSopenharmony_ci} 79f08c3bdfSopenharmony_ci 80f08c3bdfSopenharmony_cistatic void change_mode(void) 81f08c3bdfSopenharmony_ci{ 82f08c3bdfSopenharmony_ci SAFE_CHMOD(TEST_FILE, 0777); 83f08c3bdfSopenharmony_ci} 84f08c3bdfSopenharmony_ci 85f08c3bdfSopenharmony_cistatic struct test_case { 86f08c3bdfSopenharmony_ci void (*operation)(void); 87f08c3bdfSopenharmony_ci char *op_name; 88f08c3bdfSopenharmony_ci} tcases[] = { 89f08c3bdfSopenharmony_ci {.operation = create_file, 90f08c3bdfSopenharmony_ci .op_name = "Birth time"}, 91f08c3bdfSopenharmony_ci {.operation = write_file, 92f08c3bdfSopenharmony_ci .op_name = "Modified time"}, 93f08c3bdfSopenharmony_ci {.operation = read_file, 94f08c3bdfSopenharmony_ci .op_name = "Access time"}, 95f08c3bdfSopenharmony_ci {.operation = change_mode, 96f08c3bdfSopenharmony_ci .op_name = "Change time"} 97f08c3bdfSopenharmony_ci}; 98f08c3bdfSopenharmony_ci 99f08c3bdfSopenharmony_cistatic void test_statx(unsigned int test_nr) 100f08c3bdfSopenharmony_ci{ 101f08c3bdfSopenharmony_ci struct statx buff; 102f08c3bdfSopenharmony_ci struct timespec before_time; 103f08c3bdfSopenharmony_ci struct timespec after_time; 104f08c3bdfSopenharmony_ci struct timespec statx_time = {0, 0}; 105f08c3bdfSopenharmony_ci 106f08c3bdfSopenharmony_ci struct test_case *tc = &tcases[test_nr]; 107f08c3bdfSopenharmony_ci 108f08c3bdfSopenharmony_ci SAFE_CLOCK_GETTIME(CLOCK_REALTIME_COARSE, &before_time); 109f08c3bdfSopenharmony_ci clock_wait_tick(); 110f08c3bdfSopenharmony_ci tc->operation(); 111f08c3bdfSopenharmony_ci clock_wait_tick(); 112f08c3bdfSopenharmony_ci SAFE_CLOCK_GETTIME(CLOCK_REALTIME, &after_time); 113f08c3bdfSopenharmony_ci 114f08c3bdfSopenharmony_ci TEST(statx(AT_FDCWD, TEST_FILE, 0, STATX_BASIC_STATS | STATX_BTIME, &buff)); 115f08c3bdfSopenharmony_ci if (TST_RET != 0) { 116f08c3bdfSopenharmony_ci tst_brk(TFAIL | TTERRNO, 117f08c3bdfSopenharmony_ci "statx(AT_FDCWD, %s, 0, STATX_BASIC_STATS | STATX_BTIME, &buff)", 118f08c3bdfSopenharmony_ci TEST_FILE); 119f08c3bdfSopenharmony_ci } 120f08c3bdfSopenharmony_ci 121f08c3bdfSopenharmony_ci switch (test_nr) { 122f08c3bdfSopenharmony_ci case 0: 123f08c3bdfSopenharmony_ci timestamp_to_timespec(&buff.stx_btime, &statx_time); 124f08c3bdfSopenharmony_ci break; 125f08c3bdfSopenharmony_ci case 1: 126f08c3bdfSopenharmony_ci timestamp_to_timespec(&buff.stx_mtime, &statx_time); 127f08c3bdfSopenharmony_ci break; 128f08c3bdfSopenharmony_ci case 2: 129f08c3bdfSopenharmony_ci timestamp_to_timespec(&buff.stx_atime, &statx_time); 130f08c3bdfSopenharmony_ci break; 131f08c3bdfSopenharmony_ci case 3: 132f08c3bdfSopenharmony_ci timestamp_to_timespec(&buff.stx_ctime, &statx_time); 133f08c3bdfSopenharmony_ci break; 134f08c3bdfSopenharmony_ci } 135f08c3bdfSopenharmony_ci if (tst_timespec_lt(statx_time, before_time)) 136f08c3bdfSopenharmony_ci tst_res(TFAIL, "%s < before time", tc->op_name); 137f08c3bdfSopenharmony_ci else if (tst_timespec_lt(after_time, statx_time)) 138f08c3bdfSopenharmony_ci tst_res(TFAIL, "%s > after_time", tc->op_name); 139f08c3bdfSopenharmony_ci else 140f08c3bdfSopenharmony_ci tst_res(TPASS, "%s Passed", tc->op_name); 141f08c3bdfSopenharmony_ci} 142f08c3bdfSopenharmony_ci 143f08c3bdfSopenharmony_ci 144f08c3bdfSopenharmony_cistatic void cleanup(void) 145f08c3bdfSopenharmony_ci{ 146f08c3bdfSopenharmony_ci if (fd > 0) 147f08c3bdfSopenharmony_ci SAFE_CLOSE(fd); 148f08c3bdfSopenharmony_ci} 149f08c3bdfSopenharmony_ci 150f08c3bdfSopenharmony_cistatic struct tst_test test = { 151f08c3bdfSopenharmony_ci .cleanup = cleanup, 152f08c3bdfSopenharmony_ci .tcnt = ARRAY_SIZE(tcases), 153f08c3bdfSopenharmony_ci .test = test_statx, 154f08c3bdfSopenharmony_ci .min_kver = "4.11", 155f08c3bdfSopenharmony_ci .needs_root = 1, 156f08c3bdfSopenharmony_ci .mntpoint = MOUNT_POINT, 157f08c3bdfSopenharmony_ci .mount_device = 1, 158f08c3bdfSopenharmony_ci .dev_fs_type = "ext4", 159f08c3bdfSopenharmony_ci .dev_fs_opts = (const char *const []){"-I", "256", NULL}, 160f08c3bdfSopenharmony_ci .mnt_flags = MS_STRICTATIME, 161f08c3bdfSopenharmony_ci}; 162