1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (c) Linux Test Project, 2021 4f08c3bdfSopenharmony_ci * Copyright (c) International Business Machines Corp., 2001 5f08c3bdfSopenharmony_ci * 07/2001 Ported by Wayne Boyer 6f08c3bdfSopenharmony_ci * MODIFIED: - mridge@us.ibm.com -- changed getpid to syscall(get thread ID) 7f08c3bdfSopenharmony_ci * for unique ID on NPTL threading 8f08c3bdfSopenharmony_ci */ 9f08c3bdfSopenharmony_ci 10f08c3bdfSopenharmony_ci/*\ 11f08c3bdfSopenharmony_ci * [Description] 12f08c3bdfSopenharmony_ci * 13f08c3bdfSopenharmony_ci * Check that file locks are removed when a file descriptor is closed, three 14f08c3bdfSopenharmony_ci * different tests are implemented. 15f08c3bdfSopenharmony_ci * 16f08c3bdfSopenharmony_ci * Parent opens a file and duplicates the file descriptor, places locks using 17f08c3bdfSopenharmony_ci * both file descriptors then closes one descriptor, all locks should be 18f08c3bdfSopenharmony_ci * removed. 19f08c3bdfSopenharmony_ci * 20f08c3bdfSopenharmony_ci * Open same file twice using open, place locks using both descriptors then 21f08c3bdfSopenharmony_ci * close one descriptor, all lock should be removed. 22f08c3bdfSopenharmony_ci * 23f08c3bdfSopenharmony_ci * Open file twice, each in a different process, set the locks and the child 24f08c3bdfSopenharmony_ci * check the locks. Close the first file descriptor and have child check locks 25f08c3bdfSopenharmony_ci * again. Only locks set on first file descriptor should have been removed. 26f08c3bdfSopenharmony_ci */ 27f08c3bdfSopenharmony_ci 28f08c3bdfSopenharmony_ci#include <signal.h> 29f08c3bdfSopenharmony_ci#include <fcntl.h> 30f08c3bdfSopenharmony_ci#include <sys/types.h> 31f08c3bdfSopenharmony_ci#include <sys/wait.h> 32f08c3bdfSopenharmony_ci#include <sys/syscall.h> 33f08c3bdfSopenharmony_ci#include <stdlib.h> 34f08c3bdfSopenharmony_ci#include <stdio.h> 35f08c3bdfSopenharmony_ci#include "tst_test.h" 36f08c3bdfSopenharmony_ci#include "lapi/syscalls.h" 37f08c3bdfSopenharmony_ci 38f08c3bdfSopenharmony_ci#define DATA "ABCDEFGHIJ" 39f08c3bdfSopenharmony_ci#define DUP 0 40f08c3bdfSopenharmony_ci#define OPEN 1 41f08c3bdfSopenharmony_ci#define FORK_ 2 42f08c3bdfSopenharmony_ci 43f08c3bdfSopenharmony_cistatic char tmpname[10] = "testfile"; 44f08c3bdfSopenharmony_cistatic int fd[2]; 45f08c3bdfSopenharmony_ci 46f08c3bdfSopenharmony_cistatic const struct flock lock_one = { 47f08c3bdfSopenharmony_ci .l_type = F_WRLCK, 48f08c3bdfSopenharmony_ci .l_whence = 0, 49f08c3bdfSopenharmony_ci .l_start = 0L, 50f08c3bdfSopenharmony_ci .l_len = 5L, 51f08c3bdfSopenharmony_ci}; 52f08c3bdfSopenharmony_ci 53f08c3bdfSopenharmony_cistatic const struct flock lock_two = { 54f08c3bdfSopenharmony_ci .l_type = F_WRLCK, 55f08c3bdfSopenharmony_ci .l_whence = 0, 56f08c3bdfSopenharmony_ci .l_start = 5L, 57f08c3bdfSopenharmony_ci .l_len = 5L, 58f08c3bdfSopenharmony_ci}; 59f08c3bdfSopenharmony_ci 60f08c3bdfSopenharmony_cistatic struct tcase { 61f08c3bdfSopenharmony_ci int dup_flag; 62f08c3bdfSopenharmony_ci int test_num; 63f08c3bdfSopenharmony_ci char *dup_flag_name; 64f08c3bdfSopenharmony_ci} tcases[] = { 65f08c3bdfSopenharmony_ci {DUP, 1, "dup"}, 66f08c3bdfSopenharmony_ci {OPEN, 2, "open"}, 67f08c3bdfSopenharmony_ci {FORK_, 3, "fork"} 68f08c3bdfSopenharmony_ci}; 69f08c3bdfSopenharmony_ci 70f08c3bdfSopenharmony_cistatic void lock_region_two(int file_flag, int file_mode) 71f08c3bdfSopenharmony_ci{ 72f08c3bdfSopenharmony_ci int fd; 73f08c3bdfSopenharmony_ci 74f08c3bdfSopenharmony_ci fd = SAFE_OPEN(tmpname, file_flag, file_mode); 75f08c3bdfSopenharmony_ci 76f08c3bdfSopenharmony_ci SAFE_FCNTL(fd, F_SETLK, &lock_two); 77f08c3bdfSopenharmony_ci 78f08c3bdfSopenharmony_ci TST_CHECKPOINT_WAKE_AND_WAIT(1); 79f08c3bdfSopenharmony_ci 80f08c3bdfSopenharmony_ci SAFE_CLOSE(fd); 81f08c3bdfSopenharmony_ci} 82f08c3bdfSopenharmony_ci 83f08c3bdfSopenharmony_cistatic void do_test(int file_flag, int file_mode, int dup_flag) 84f08c3bdfSopenharmony_ci{ 85f08c3bdfSopenharmony_ci int ret, fd; 86f08c3bdfSopenharmony_ci 87f08c3bdfSopenharmony_ci fd = SAFE_OPEN(tmpname, file_flag, file_mode); 88f08c3bdfSopenharmony_ci 89f08c3bdfSopenharmony_ci if (!fcntl(fd, F_SETLK, &lock_one)) 90f08c3bdfSopenharmony_ci tst_res(TFAIL, "Succeeded to lock already locked region one"); 91f08c3bdfSopenharmony_ci else 92f08c3bdfSopenharmony_ci tst_res(TPASS, "Failed to lock already locked region one"); 93f08c3bdfSopenharmony_ci 94f08c3bdfSopenharmony_ci if (!fcntl(fd, F_SETLK, &lock_two)) 95f08c3bdfSopenharmony_ci tst_res(TFAIL, "Succeeded to lock already locked region two"); 96f08c3bdfSopenharmony_ci else 97f08c3bdfSopenharmony_ci tst_res(TPASS, "Failed to lock already locked region two"); 98f08c3bdfSopenharmony_ci 99f08c3bdfSopenharmony_ci TST_CHECKPOINT_WAKE_AND_WAIT(0); 100f08c3bdfSopenharmony_ci 101f08c3bdfSopenharmony_ci if (fcntl(fd, F_SETLK, &lock_one)) 102f08c3bdfSopenharmony_ci tst_res(TFAIL | TERRNO, "Failed to lock now unlocked region one"); 103f08c3bdfSopenharmony_ci else 104f08c3bdfSopenharmony_ci tst_res(TPASS, "Succeeded to lock now ulocked region two"); 105f08c3bdfSopenharmony_ci 106f08c3bdfSopenharmony_ci ret = fcntl(fd, F_SETLK, &lock_two); 107f08c3bdfSopenharmony_ci 108f08c3bdfSopenharmony_ci if (dup_flag == FORK_) { 109f08c3bdfSopenharmony_ci if (ret) 110f08c3bdfSopenharmony_ci tst_res(TPASS, "Failed to lock already locked region two"); 111f08c3bdfSopenharmony_ci else 112f08c3bdfSopenharmony_ci tst_res(TFAIL, "Succeeded to lock already locked region two"); 113f08c3bdfSopenharmony_ci } else { 114f08c3bdfSopenharmony_ci if (ret) 115f08c3bdfSopenharmony_ci tst_res(TFAIL, "Failed to lock now ulocked region two"); 116f08c3bdfSopenharmony_ci else 117f08c3bdfSopenharmony_ci tst_res(TPASS, "Succeeded to lock now ulocked region two"); 118f08c3bdfSopenharmony_ci } 119f08c3bdfSopenharmony_ci 120f08c3bdfSopenharmony_ci SAFE_CLOSE(fd); 121f08c3bdfSopenharmony_ci TST_CHECKPOINT_WAKE(0); 122f08c3bdfSopenharmony_ci} 123f08c3bdfSopenharmony_ci 124f08c3bdfSopenharmony_cistatic int run_test(int file_flag, int file_mode, int dup_flag) 125f08c3bdfSopenharmony_ci{ 126f08c3bdfSopenharmony_ci fd[0] = SAFE_OPEN(tmpname, file_flag, file_mode); 127f08c3bdfSopenharmony_ci SAFE_WRITE(SAFE_WRITE_ALL, fd[0], DATA, 10); 128f08c3bdfSopenharmony_ci 129f08c3bdfSopenharmony_ci switch (dup_flag) { 130f08c3bdfSopenharmony_ci case FORK_: 131f08c3bdfSopenharmony_ci if (!SAFE_FORK()) { 132f08c3bdfSopenharmony_ci lock_region_two(file_flag, file_mode); 133f08c3bdfSopenharmony_ci exit(0); 134f08c3bdfSopenharmony_ci } 135f08c3bdfSopenharmony_ci break; 136f08c3bdfSopenharmony_ci case OPEN: 137f08c3bdfSopenharmony_ci fd[1] = SAFE_OPEN(tmpname, file_flag, file_mode); 138f08c3bdfSopenharmony_ci break; 139f08c3bdfSopenharmony_ci case DUP: 140f08c3bdfSopenharmony_ci fd[1] = SAFE_FCNTL(fd[0], F_DUPFD, 0); 141f08c3bdfSopenharmony_ci break; 142f08c3bdfSopenharmony_ci } 143f08c3bdfSopenharmony_ci 144f08c3bdfSopenharmony_ci SAFE_FCNTL(fd[0], F_SETLK, &lock_one); 145f08c3bdfSopenharmony_ci 146f08c3bdfSopenharmony_ci // Lock region two or wait until the child locked it 147f08c3bdfSopenharmony_ci if (dup_flag != FORK_) 148f08c3bdfSopenharmony_ci SAFE_FCNTL(fd[1], F_SETLK, &lock_two); 149f08c3bdfSopenharmony_ci else 150f08c3bdfSopenharmony_ci TST_CHECKPOINT_WAIT(1); 151f08c3bdfSopenharmony_ci 152f08c3bdfSopenharmony_ci if (!SAFE_FORK()) { 153f08c3bdfSopenharmony_ci do_test(file_flag, file_mode, dup_flag); 154f08c3bdfSopenharmony_ci exit(0); 155f08c3bdfSopenharmony_ci } 156f08c3bdfSopenharmony_ci 157f08c3bdfSopenharmony_ci TST_CHECKPOINT_WAIT(0); 158f08c3bdfSopenharmony_ci 159f08c3bdfSopenharmony_ci tst_res(TINFO, "Closing a file descriptor in parent"); 160f08c3bdfSopenharmony_ci 161f08c3bdfSopenharmony_ci SAFE_CLOSE(fd[0]); 162f08c3bdfSopenharmony_ci 163f08c3bdfSopenharmony_ci TST_CHECKPOINT_WAKE_AND_WAIT(0); 164f08c3bdfSopenharmony_ci 165f08c3bdfSopenharmony_ci if (dup_flag != FORK_) 166f08c3bdfSopenharmony_ci SAFE_CLOSE(fd[1]); 167f08c3bdfSopenharmony_ci else 168f08c3bdfSopenharmony_ci TST_CHECKPOINT_WAKE(1); 169f08c3bdfSopenharmony_ci 170f08c3bdfSopenharmony_ci SAFE_UNLINK(tmpname); 171f08c3bdfSopenharmony_ci return 0; 172f08c3bdfSopenharmony_ci} 173f08c3bdfSopenharmony_ci 174f08c3bdfSopenharmony_cistatic void verify_fcntl(unsigned int n) 175f08c3bdfSopenharmony_ci{ 176f08c3bdfSopenharmony_ci struct tcase *tc = &tcases[n]; 177f08c3bdfSopenharmony_ci 178f08c3bdfSopenharmony_ci tst_res(TINFO, "Running test with %s", tc->dup_flag_name); 179f08c3bdfSopenharmony_ci 180f08c3bdfSopenharmony_ci run_test(O_CREAT | O_RDWR | O_TRUNC, 0777, tc->dup_flag); 181f08c3bdfSopenharmony_ci} 182f08c3bdfSopenharmony_ci 183f08c3bdfSopenharmony_cistatic void cleanup(void) 184f08c3bdfSopenharmony_ci{ 185f08c3bdfSopenharmony_ci size_t i; 186f08c3bdfSopenharmony_ci 187f08c3bdfSopenharmony_ci for (i = 0; i < ARRAY_SIZE(fd); i++) { 188f08c3bdfSopenharmony_ci if (fd[i] > 0) 189f08c3bdfSopenharmony_ci SAFE_CLOSE(fd[i]); 190f08c3bdfSopenharmony_ci } 191f08c3bdfSopenharmony_ci} 192f08c3bdfSopenharmony_ci 193f08c3bdfSopenharmony_cistatic struct tst_test test = { 194f08c3bdfSopenharmony_ci .tcnt = ARRAY_SIZE(tcases), 195f08c3bdfSopenharmony_ci .forks_child = 1, 196f08c3bdfSopenharmony_ci .test = verify_fcntl, 197f08c3bdfSopenharmony_ci .needs_checkpoints = 1, 198f08c3bdfSopenharmony_ci .cleanup = cleanup, 199f08c3bdfSopenharmony_ci}; 200