xref: /aosp_15_r20/external/ltp/testcases/kernel/syscalls/ftruncate/ftruncate04.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1*49cdfc7eSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0-or-later
2*49cdfc7eSAndroid Build Coastguard Worker  /*
3*49cdfc7eSAndroid Build Coastguard Worker   * Copyright (c) International Business Machines  Corp., 2002
4*49cdfc7eSAndroid Build Coastguard Worker   * Copyright (c) 2015 Cyril Hrubis <[email protected]>
5*49cdfc7eSAndroid Build Coastguard Worker   * Copyright (c) 2019 FUJITSU LIMITED. All rights reserved.
6*49cdfc7eSAndroid Build Coastguard Worker   *
7*49cdfc7eSAndroid Build Coastguard Worker   * Robbie Williamson <[email protected]>
8*49cdfc7eSAndroid Build Coastguard Worker   * Roy Lee <[email protected]>
9*49cdfc7eSAndroid Build Coastguard Worker   */
10*49cdfc7eSAndroid Build Coastguard Worker /*
11*49cdfc7eSAndroid Build Coastguard Worker  * Test Description:
12*49cdfc7eSAndroid Build Coastguard Worker  *
13*49cdfc7eSAndroid Build Coastguard Worker  * Tests truncate and mandatory record locking.
14*49cdfc7eSAndroid Build Coastguard Worker  *
15*49cdfc7eSAndroid Build Coastguard Worker  * Parent creates a file, child locks a region and sleeps.
16*49cdfc7eSAndroid Build Coastguard Worker  *
17*49cdfc7eSAndroid Build Coastguard Worker  * Parent checks that ftruncate before the locked region and inside the region
18*49cdfc7eSAndroid Build Coastguard Worker  * fails while ftruncate after the region succeds.
19*49cdfc7eSAndroid Build Coastguard Worker  *
20*49cdfc7eSAndroid Build Coastguard Worker  * Parent wakes up child, child exits, lock is unlocked.
21*49cdfc7eSAndroid Build Coastguard Worker  *
22*49cdfc7eSAndroid Build Coastguard Worker  * Parent checks that ftruncate now works in all cases.
23*49cdfc7eSAndroid Build Coastguard Worker  *
24*49cdfc7eSAndroid Build Coastguard Worker  */
25*49cdfc7eSAndroid Build Coastguard Worker 
26*49cdfc7eSAndroid Build Coastguard Worker #include <stdio.h>
27*49cdfc7eSAndroid Build Coastguard Worker #include <errno.h>
28*49cdfc7eSAndroid Build Coastguard Worker #include <sys/types.h>
29*49cdfc7eSAndroid Build Coastguard Worker #include <sys/stat.h>
30*49cdfc7eSAndroid Build Coastguard Worker #include <sys/mount.h>
31*49cdfc7eSAndroid Build Coastguard Worker #include <unistd.h>
32*49cdfc7eSAndroid Build Coastguard Worker #include <stdlib.h>
33*49cdfc7eSAndroid Build Coastguard Worker #include <sys/statvfs.h>
34*49cdfc7eSAndroid Build Coastguard Worker 
35*49cdfc7eSAndroid Build Coastguard Worker #include "tst_test.h"
36*49cdfc7eSAndroid Build Coastguard Worker 
37*49cdfc7eSAndroid Build Coastguard Worker #define RECLEN	100
38*49cdfc7eSAndroid Build Coastguard Worker #define MNTPOINT	"mntpoint"
39*49cdfc7eSAndroid Build Coastguard Worker #define TESTFILE	MNTPOINT"/testfile"
40*49cdfc7eSAndroid Build Coastguard Worker 
41*49cdfc7eSAndroid Build Coastguard Worker static int len = 8 * 1024;
42*49cdfc7eSAndroid Build Coastguard Worker static int recstart, reclen;
43*49cdfc7eSAndroid Build Coastguard Worker 
ftruncate_expect_fail(int fd,off_t offset,const char * msg)44*49cdfc7eSAndroid Build Coastguard Worker static void ftruncate_expect_fail(int fd, off_t offset, const char *msg)
45*49cdfc7eSAndroid Build Coastguard Worker {
46*49cdfc7eSAndroid Build Coastguard Worker 	TEST(ftruncate(fd, offset));
47*49cdfc7eSAndroid Build Coastguard Worker 
48*49cdfc7eSAndroid Build Coastguard Worker 	if (TST_RET == 0) {
49*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TFAIL, "ftruncate() %s succeeded unexpectedly", msg);
50*49cdfc7eSAndroid Build Coastguard Worker 		return;
51*49cdfc7eSAndroid Build Coastguard Worker 	}
52*49cdfc7eSAndroid Build Coastguard Worker 
53*49cdfc7eSAndroid Build Coastguard Worker 	if (TST_ERR != EAGAIN) {
54*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TFAIL | TTERRNO,
55*49cdfc7eSAndroid Build Coastguard Worker 			"ftruncate() %s failed unexpectedly, expected EAGAIN",
56*49cdfc7eSAndroid Build Coastguard Worker 			msg);
57*49cdfc7eSAndroid Build Coastguard Worker 		return;
58*49cdfc7eSAndroid Build Coastguard Worker 	}
59*49cdfc7eSAndroid Build Coastguard Worker 
60*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TPASS, "ftruncate() %s failed with EAGAIN", msg);
61*49cdfc7eSAndroid Build Coastguard Worker }
62*49cdfc7eSAndroid Build Coastguard Worker 
ftruncate_expect_success(int fd,off_t offset,const char * msg)63*49cdfc7eSAndroid Build Coastguard Worker static void ftruncate_expect_success(int fd, off_t offset, const char *msg)
64*49cdfc7eSAndroid Build Coastguard Worker {
65*49cdfc7eSAndroid Build Coastguard Worker 	struct stat sb;
66*49cdfc7eSAndroid Build Coastguard Worker 
67*49cdfc7eSAndroid Build Coastguard Worker 	TEST(ftruncate(fd, offset));
68*49cdfc7eSAndroid Build Coastguard Worker 
69*49cdfc7eSAndroid Build Coastguard Worker 	if (TST_RET != 0) {
70*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TFAIL | TTERRNO,
71*49cdfc7eSAndroid Build Coastguard Worker 			"ftruncate() %s failed unexpectedly", msg);
72*49cdfc7eSAndroid Build Coastguard Worker 		return;
73*49cdfc7eSAndroid Build Coastguard Worker 	}
74*49cdfc7eSAndroid Build Coastguard Worker 
75*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_FSTAT(fd, &sb);
76*49cdfc7eSAndroid Build Coastguard Worker 
77*49cdfc7eSAndroid Build Coastguard Worker 	if (sb.st_size != offset) {
78*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TFAIL,
79*49cdfc7eSAndroid Build Coastguard Worker 			"ftruncate() to %li bytes succeded but fstat() reports size %li",
80*49cdfc7eSAndroid Build Coastguard Worker 			(long)offset, (long)sb.st_size);
81*49cdfc7eSAndroid Build Coastguard Worker 		return;
82*49cdfc7eSAndroid Build Coastguard Worker 	}
83*49cdfc7eSAndroid Build Coastguard Worker 
84*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TPASS, "ftruncate() %s succeded", msg);
85*49cdfc7eSAndroid Build Coastguard Worker }
86*49cdfc7eSAndroid Build Coastguard Worker 
doparent(void)87*49cdfc7eSAndroid Build Coastguard Worker static void doparent(void)
88*49cdfc7eSAndroid Build Coastguard Worker {
89*49cdfc7eSAndroid Build Coastguard Worker 	int fd;
90*49cdfc7eSAndroid Build Coastguard Worker 
91*49cdfc7eSAndroid Build Coastguard Worker 	TST_CHECKPOINT_WAIT(0);
92*49cdfc7eSAndroid Build Coastguard Worker 
93*49cdfc7eSAndroid Build Coastguard Worker 	fd = SAFE_OPEN(TESTFILE, O_RDWR | O_NONBLOCK);
94*49cdfc7eSAndroid Build Coastguard Worker 
95*49cdfc7eSAndroid Build Coastguard Worker 	ftruncate_expect_fail(fd, RECLEN, "offset before lock");
96*49cdfc7eSAndroid Build Coastguard Worker 	ftruncate_expect_fail(fd, recstart + RECLEN/2, "offset in lock");
97*49cdfc7eSAndroid Build Coastguard Worker 	ftruncate_expect_success(fd, recstart + RECLEN, "offset after lock");
98*49cdfc7eSAndroid Build Coastguard Worker 
99*49cdfc7eSAndroid Build Coastguard Worker 	TST_CHECKPOINT_WAKE(0);
100*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_WAIT(NULL);
101*49cdfc7eSAndroid Build Coastguard Worker 
102*49cdfc7eSAndroid Build Coastguard Worker 	ftruncate_expect_success(fd, recstart + RECLEN/2, "offset in lock");
103*49cdfc7eSAndroid Build Coastguard Worker 	ftruncate_expect_success(fd, recstart, "offset before lock");
104*49cdfc7eSAndroid Build Coastguard Worker 	ftruncate_expect_success(fd, recstart + RECLEN, "offset after lock");
105*49cdfc7eSAndroid Build Coastguard Worker 
106*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_CLOSE(fd);
107*49cdfc7eSAndroid Build Coastguard Worker }
108*49cdfc7eSAndroid Build Coastguard Worker 
dochild(void)109*49cdfc7eSAndroid Build Coastguard Worker void dochild(void)
110*49cdfc7eSAndroid Build Coastguard Worker {
111*49cdfc7eSAndroid Build Coastguard Worker 	int fd;
112*49cdfc7eSAndroid Build Coastguard Worker 	struct flock flocks;
113*49cdfc7eSAndroid Build Coastguard Worker 
114*49cdfc7eSAndroid Build Coastguard Worker 	fd = SAFE_OPEN(TESTFILE, O_RDWR);
115*49cdfc7eSAndroid Build Coastguard Worker 
116*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TINFO, "Child locks file");
117*49cdfc7eSAndroid Build Coastguard Worker 
118*49cdfc7eSAndroid Build Coastguard Worker 	flocks.l_type = F_WRLCK;
119*49cdfc7eSAndroid Build Coastguard Worker 	flocks.l_whence = SEEK_CUR;
120*49cdfc7eSAndroid Build Coastguard Worker 	flocks.l_start = recstart;
121*49cdfc7eSAndroid Build Coastguard Worker 	flocks.l_len = reclen;
122*49cdfc7eSAndroid Build Coastguard Worker 
123*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_FCNTL(fd, F_SETLKW, &flocks);
124*49cdfc7eSAndroid Build Coastguard Worker 
125*49cdfc7eSAndroid Build Coastguard Worker 	TST_CHECKPOINT_WAKE_AND_WAIT(0);
126*49cdfc7eSAndroid Build Coastguard Worker 
127*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TINFO, "Child unlocks file");
128*49cdfc7eSAndroid Build Coastguard Worker 
129*49cdfc7eSAndroid Build Coastguard Worker 	exit(0);
130*49cdfc7eSAndroid Build Coastguard Worker }
131*49cdfc7eSAndroid Build Coastguard Worker 
verify_ftruncate(void)132*49cdfc7eSAndroid Build Coastguard Worker static void verify_ftruncate(void)
133*49cdfc7eSAndroid Build Coastguard Worker {
134*49cdfc7eSAndroid Build Coastguard Worker 	int pid;
135*49cdfc7eSAndroid Build Coastguard Worker 
136*49cdfc7eSAndroid Build Coastguard Worker 	if (tst_fill_file(TESTFILE, 0, 1024, 8))
137*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TBROK, "Failed to create test file");
138*49cdfc7eSAndroid Build Coastguard Worker 
139*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_CHMOD(TESTFILE, 02666);
140*49cdfc7eSAndroid Build Coastguard Worker 
141*49cdfc7eSAndroid Build Coastguard Worker 	reclen = RECLEN;
142*49cdfc7eSAndroid Build Coastguard Worker 	recstart = RECLEN + rand() % (len - 3 * RECLEN);
143*49cdfc7eSAndroid Build Coastguard Worker 
144*49cdfc7eSAndroid Build Coastguard Worker 	pid = SAFE_FORK();
145*49cdfc7eSAndroid Build Coastguard Worker 
146*49cdfc7eSAndroid Build Coastguard Worker 	if (pid == 0)
147*49cdfc7eSAndroid Build Coastguard Worker 		dochild();
148*49cdfc7eSAndroid Build Coastguard Worker 
149*49cdfc7eSAndroid Build Coastguard Worker 	doparent();
150*49cdfc7eSAndroid Build Coastguard Worker }
151*49cdfc7eSAndroid Build Coastguard Worker 
setup(void)152*49cdfc7eSAndroid Build Coastguard Worker static void setup(void)
153*49cdfc7eSAndroid Build Coastguard Worker {
154*49cdfc7eSAndroid Build Coastguard Worker 	 /*
155*49cdfc7eSAndroid Build Coastguard Worker 	  * Kernel returns EPERM when CONFIG_MANDATORY_FILE_LOCKING is not
156*49cdfc7eSAndroid Build Coastguard Worker 	  * supported - to avoid false negatives, mount the fs first without
157*49cdfc7eSAndroid Build Coastguard Worker 	  * flags and then remount it as MS_MANDLOCK
158*49cdfc7eSAndroid Build Coastguard Worker 	  */
159*49cdfc7eSAndroid Build Coastguard Worker 	if (mount(NULL, MNTPOINT, NULL, MS_REMOUNT|MS_MANDLOCK, NULL) == -1) {
160*49cdfc7eSAndroid Build Coastguard Worker 		if (errno == EPERM) {
161*49cdfc7eSAndroid Build Coastguard Worker 			tst_brk(TCONF,
162*49cdfc7eSAndroid Build Coastguard Worker 				"Mandatory lock not supported by this system");
163*49cdfc7eSAndroid Build Coastguard Worker 		} else {
164*49cdfc7eSAndroid Build Coastguard Worker 			tst_brk(TBROK | TTERRNO,
165*49cdfc7eSAndroid Build Coastguard Worker 				"Remount with MS_MANDLOCK failed");
166*49cdfc7eSAndroid Build Coastguard Worker 		}
167*49cdfc7eSAndroid Build Coastguard Worker 	}
168*49cdfc7eSAndroid Build Coastguard Worker }
169*49cdfc7eSAndroid Build Coastguard Worker 
170*49cdfc7eSAndroid Build Coastguard Worker static struct tst_test test = {
171*49cdfc7eSAndroid Build Coastguard Worker 	.needs_kconfigs = (const char *[]) {
172*49cdfc7eSAndroid Build Coastguard Worker 		"CONFIG_MANDATORY_FILE_LOCKING=y",
173*49cdfc7eSAndroid Build Coastguard Worker 		NULL
174*49cdfc7eSAndroid Build Coastguard Worker 	},
175*49cdfc7eSAndroid Build Coastguard Worker 	.test_all = verify_ftruncate,
176*49cdfc7eSAndroid Build Coastguard Worker 	.setup = setup,
177*49cdfc7eSAndroid Build Coastguard Worker 	.needs_checkpoints = 1,
178*49cdfc7eSAndroid Build Coastguard Worker 	.forks_child = 1,
179*49cdfc7eSAndroid Build Coastguard Worker 	.mount_device = 1,
180*49cdfc7eSAndroid Build Coastguard Worker 	.needs_root = 1,
181*49cdfc7eSAndroid Build Coastguard Worker 	.mntpoint = MNTPOINT,
182*49cdfc7eSAndroid Build Coastguard Worker };
183