1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
2f08c3bdfSopenharmony_ci/*
3f08c3bdfSopenharmony_ci * Copyright (c) International Business Machines  Corp., 2002
4f08c3bdfSopenharmony_ci * Author: Cyril Hrubis
5f08c3bdfSopenharmony_ci *
6f08c3bdfSopenharmony_ci * Test Description:
7f08c3bdfSopenharmony_ci *  This test verifies that flock() cannot unlock a file locked by another
8f08c3bdfSopenharmony_ci *  task.
9f08c3bdfSopenharmony_ci *
10f08c3bdfSopenharmony_ci * Test Steps:
11f08c3bdfSopenharmony_ci *  Fork a child processes The parent flocks a file with LOCK_EX Child waits
12f08c3bdfSopenharmony_ci *  for that to happen, then checks to make sure it is locked.  Child then
13f08c3bdfSopenharmony_ci *  tries to unlock the file. If the unlock succeeds, the child attempts to
14f08c3bdfSopenharmony_ci *  lock the file with LOCK_EX. The test passes if the child is able to lock
15f08c3bdfSopenharmony_ci *  the file.
16f08c3bdfSopenharmony_ci */
17f08c3bdfSopenharmony_ci
18f08c3bdfSopenharmony_ci#include <errno.h>
19f08c3bdfSopenharmony_ci#include <stdlib.h>
20f08c3bdfSopenharmony_ci#include <sys/file.h>
21f08c3bdfSopenharmony_ci
22f08c3bdfSopenharmony_ci#include "tst_test.h"
23f08c3bdfSopenharmony_ci
24f08c3bdfSopenharmony_cistatic void childfunc(int fd)
25f08c3bdfSopenharmony_ci{
26f08c3bdfSopenharmony_ci	int fd2;
27f08c3bdfSopenharmony_ci	TST_CHECKPOINT_WAIT(0);
28f08c3bdfSopenharmony_ci
29f08c3bdfSopenharmony_ci	fd2 = SAFE_OPEN("testfile", O_RDWR);
30f08c3bdfSopenharmony_ci	if (flock(fd2, LOCK_EX | LOCK_NB) != -1)
31f08c3bdfSopenharmony_ci		tst_brk(TBROK, "CHILD: The file was not already locked");
32f08c3bdfSopenharmony_ci
33f08c3bdfSopenharmony_ci	TEST(flock(fd, LOCK_UN));
34f08c3bdfSopenharmony_ci	if (TST_RET == -1) {
35f08c3bdfSopenharmony_ci		tst_res(TFAIL, "CHILD: Unable to unlock file locked by "
36f08c3bdfSopenharmony_ci			"parent: %s", tst_strerrno(TST_ERR));
37f08c3bdfSopenharmony_ci		exit(1);
38f08c3bdfSopenharmony_ci	} else {
39f08c3bdfSopenharmony_ci		tst_res(TPASS, "CHILD: File locked by parent unlocked");
40f08c3bdfSopenharmony_ci	}
41f08c3bdfSopenharmony_ci
42f08c3bdfSopenharmony_ci	TEST(flock(fd2, LOCK_EX | LOCK_NB));
43f08c3bdfSopenharmony_ci	if (TST_RET == -1) {
44f08c3bdfSopenharmony_ci		tst_res(TFAIL, "CHILD: Unable to unlock file after "
45f08c3bdfSopenharmony_ci			"unlocking: %s", tst_strerrno(TST_ERR));
46f08c3bdfSopenharmony_ci		exit(1);
47f08c3bdfSopenharmony_ci	} else {
48f08c3bdfSopenharmony_ci		tst_res(TPASS, "Locking after unlock passed");
49f08c3bdfSopenharmony_ci	}
50f08c3bdfSopenharmony_ci
51f08c3bdfSopenharmony_ci	SAFE_CLOSE(fd);
52f08c3bdfSopenharmony_ci	SAFE_CLOSE(fd2);
53f08c3bdfSopenharmony_ci
54f08c3bdfSopenharmony_ci	exit(0);
55f08c3bdfSopenharmony_ci}
56f08c3bdfSopenharmony_ci
57f08c3bdfSopenharmony_cistatic void verify_flock(void)
58f08c3bdfSopenharmony_ci{
59f08c3bdfSopenharmony_ci	int fd1;
60f08c3bdfSopenharmony_ci	pid_t pid;
61f08c3bdfSopenharmony_ci
62f08c3bdfSopenharmony_ci	fd1 = SAFE_OPEN("testfile", O_RDWR);
63f08c3bdfSopenharmony_ci
64f08c3bdfSopenharmony_ci	pid = SAFE_FORK();
65f08c3bdfSopenharmony_ci	if (pid == 0)
66f08c3bdfSopenharmony_ci		childfunc(fd1);
67f08c3bdfSopenharmony_ci
68f08c3bdfSopenharmony_ci	TEST(flock(fd1, LOCK_EX | LOCK_NB));
69f08c3bdfSopenharmony_ci	if (TST_RET != 0) {
70f08c3bdfSopenharmony_ci		tst_res(TFAIL | TTERRNO,
71f08c3bdfSopenharmony_ci			"Parent: Initial attempt to flock() failed");
72f08c3bdfSopenharmony_ci	} else {
73f08c3bdfSopenharmony_ci		tst_res(TPASS,
74f08c3bdfSopenharmony_ci			"Parent: Initial attempt to flock() passed");
75f08c3bdfSopenharmony_ci	}
76f08c3bdfSopenharmony_ci
77f08c3bdfSopenharmony_ci	TST_CHECKPOINT_WAKE(0);
78f08c3bdfSopenharmony_ci
79f08c3bdfSopenharmony_ci	tst_reap_children();
80f08c3bdfSopenharmony_ci
81f08c3bdfSopenharmony_ci	SAFE_CLOSE(fd1);
82f08c3bdfSopenharmony_ci}
83f08c3bdfSopenharmony_ci
84f08c3bdfSopenharmony_cistatic void setup(void)
85f08c3bdfSopenharmony_ci{
86f08c3bdfSopenharmony_ci	int fd;
87f08c3bdfSopenharmony_ci
88f08c3bdfSopenharmony_ci	fd = SAFE_OPEN("testfile", O_CREAT | O_TRUNC | O_RDWR, 0666);
89f08c3bdfSopenharmony_ci	SAFE_CLOSE(fd);
90f08c3bdfSopenharmony_ci}
91f08c3bdfSopenharmony_ci
92f08c3bdfSopenharmony_cistatic struct tst_test test = {
93f08c3bdfSopenharmony_ci	.test_all = verify_flock,
94f08c3bdfSopenharmony_ci	.needs_checkpoints = 1,
95f08c3bdfSopenharmony_ci	.forks_child = 1,
96f08c3bdfSopenharmony_ci	.setup = setup,
97f08c3bdfSopenharmony_ci};
98