blob: 63f32f9bb934411876b69a49e84382164a49bdb7 [file] [log] [blame]
plars865695b2001-08-27 22:15:12 +00001/*
2 *
3 * Copyright (c) International Business Machines Corp., 2001
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13 * the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20/*
21 * Test Name: ftruncate03
22 *
23 * Test Description:
24 * Verify that,
plars0b3d5f52001-10-23 12:32:55 +000025 * 1) ftruncate(2) returns -1 and sets errno to EINVAL if the specified
robbiew06d067e2001-09-11 17:37:01 +000026 * file descriptor has an attempt to write, when open for read only.
plars865695b2001-08-27 22:15:12 +000027 * 2) ftruncate(2) returns -1 and sets errno to EBADF if the file descriptor
28 * of the specified file is not valid.
29 *
30 * Expected Result:
31 * ftruncate() should fail with return value -1 and set expected errno.
32 *
33 * Algorithm:
34 * Setup:
35 * Setup signal handling.
36 * Create temporary directory.
37 * Pause for SIGUSR1 if option specified.
38 *
39 * Test:
40 * Loop if the proper options are given.
41 * Execute system call
42 * Check return code, if system call failed (return=-1)
43 * if errno set == expected errno
44 * Issue sys call fails with expected return value and errno.
45 * Otherwise,
46 * Issue sys call fails with unexpected errno.
47 * Otherwise,
48 * Issue sys call returns unexpected value.
49 *
50 * Cleanup:
51 * Print errno log and/or timing stats if options given
52 * Delete the temporary directory(s)/file(s) created.
53 *
54 * Usage: <for command-line>
55 * ftruncate03 [-c n] [-e] [-i n] [-I x] [-P x] [-t]
56 * where, -c n : Run n copies concurrently.
57 * -e : Turn on errno logging.
58 * -i n : Execute test n times.
59 * -I x : Execute test for x seconds.
60 * -P x : Pause for x seconds between iterations.
61 * -t : Turn on syscall timing.
62 *
63 * HISTORY
64 * 07/2001 Ported by Wayne Boyer
65 *
66 * RESTRICTIONS:
plars865695b2001-08-27 22:15:12 +000067 */
68
69#include <stdio.h>
70#include <sys/types.h>
71#include <sys/stat.h>
72#include <sys/fcntl.h>
73#include <errno.h>
74#include <string.h>
75#include <signal.h>
robbiew77cad852001-08-31 17:55:19 +000076#include <pwd.h>
plars865695b2001-08-27 22:15:12 +000077
78#include "test.h"
79#include "usctest.h"
80
81#define TEST_FILE1 "test_file1" /* file under test */
82#define TEST_FILE2 "test_file2" /* file under test */
83#define FILE_MODE S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH
84#define BUF_SIZE 256 /* buffer size */
85#define FILE_SIZE 1024 /* test file size */
86
87int no_setup();
88int setup1(); /* setup function to test chmod for EBADF */
89int setup2(); /* setup function to test chmod for EINVAL */
90
91int fd1; /* File descriptor for testfile1 */
92int fd2; /* File descriptor for testfile2 */
93
94struct test_case_t { /* test case struct. to hold ref. test cond's*/
95 int fd;
96 char *desc;
97 int exp_errno;
98 int len;
99 int (*setupfunc)();
100} Test_cases[] = {
plars0b3d5f52001-10-23 12:32:55 +0000101 { 1, "File descriptor not open for writing", EINVAL, -1, setup1 },
plars865695b2001-08-27 22:15:12 +0000102 { 2, "File descriptor is not valid", EBADF, 256, setup2 },
103 { 0, NULL, 0, 0, no_setup }
104};
105
106char *TCID="ftruncate03"; /* Test program identifier. */
107int TST_TOTAL=2; /* Total number of test conditions */
108extern int Tst_count; /* Test Case counter for tst_* routines */
109int exp_enos[]={EINVAL, EBADF, 0};
110
robbiew77cad852001-08-31 17:55:19 +0000111char nobody_uid[] = "nobody";
112struct passwd *ltpuser;
113
114
plars865695b2001-08-27 22:15:12 +0000115void setup(); /* Main setup function for the test */
116void cleanup(); /* Main cleanup function for the test */
117
118int
119main(int ac, char **av)
120{
121 int lc; /* loop counter */
122 char *msg; /* message returned from parse_opts */
123 char *test_desc; /* test specific error message */
124 int fildes; /* File descriptor of testfile */
125 off_t trunc_len; /* truncate length */
126 int ind;
127
128 /* Parse standard options given to run the test. */
129 msg = parse_opts(ac, av, (option_t *) NULL, NULL);
130 if (msg != (char *) NULL) {
131 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
132 tst_exit();
133 }
134
135 /*
136 * Perform global setup for test to call individual test specific
137 * setup functions.
138 */
139 setup();
140
141 /* set the expected errnos... */
142 TEST_EXP_ENOS(exp_enos);
143
144 /* Check looping state if -i option given */
145 for (lc = 0; TEST_LOOPING(lc); lc++) {
146 /* Reset Tst_count in case we are looping. */
147 Tst_count = 0;
148
149 for (ind = 0; Test_cases[ind].desc != NULL; ind++) {
150 fildes = Test_cases[ind].fd;
151 test_desc = Test_cases[ind].desc;
152 trunc_len = Test_cases[ind].len;
153
154 if (fildes == 1) {
155 fildes = fd1;
156 } else {
157 fildes = fd2;
158 }
159
160 /*
161 * Call ftruncate(2) to test different test conditions.
162 * verify that it fails with return code -1 and sets
163 * appropriate errno.
164 */
165 TEST(ftruncate(fildes, trunc_len));
166
167 /* check return code of ftruncate(2) */
168 if (TEST_RETURN == -1) {
169 TEST_ERROR_LOG(TEST_ERRNO);
170 if (TEST_ERRNO == Test_cases[ind].exp_errno) {
171 tst_resm(TPASS, "ftruncate() fails, %s,"
172 " errno=%d", test_desc,
173 TEST_ERRNO);
174 } else {
175 tst_resm(TFAIL, "ftruncate() fails, %s,"
176 " errno=%d, expected errno:%d",
177 test_desc, TEST_ERRNO,
178 Test_cases[ind].exp_errno);
179 }
180 } else {
181 tst_resm(TFAIL, "ftruncate() returned %d, "
182 "expected -1, errno:%d", TEST_RETURN,
183 Test_cases[ind].exp_errno);
184 }
185 } /* End of TEST CASE LOOPING. */
186 } /* End for TEST_LOOPING */
187
188 /* Call cleanup() to undo setup done for the test. */
189 cleanup();
190
191 /*NOTREACHED*/
192} /* End main */
193
194/*
195 * void
196 * setup() - performs all ONE TIME setup for this test.
197 * Create a temporary directory and change directory to it.
198 * Fill the test buffer with some date used to fill test file(s).
199 * Call individual test specific setup functions.
200 */
201void
202setup()
203{
204 int ind;
205
206 /* capture signals */
207 tst_sig(NOFORK, DEF_HANDLER, cleanup);
208
robbiew77cad852001-08-31 17:55:19 +0000209 /* Switch to nobody user for correct error code collection */
210 if (geteuid() != 0) {
211 tst_brkm(TBROK, tst_exit, "Test must be run as root");
212 }
213 ltpuser = getpwnam(nobody_uid);
robbiew06d067e2001-09-11 17:37:01 +0000214 if (setgid(ltpuser->pw_uid) == -1) {
215 tst_resm(TINFO, "setgid failed to "
robbiew77cad852001-08-31 17:55:19 +0000216 "to set the effective uid to %d",
217 ltpuser->pw_uid);
robbiew06d067e2001-09-11 17:37:01 +0000218 perror("setgid");
219 }
220 if (setuid(ltpuser->pw_uid) == -1) {
221 tst_resm(TINFO, "setuid failed to "
222 "to set the effective uid to %d",
223 ltpuser->pw_uid);
224 perror("setuid");
robbiew77cad852001-08-31 17:55:19 +0000225 }
226
plars865695b2001-08-27 22:15:12 +0000227
228 /* Pause if that option was specified */
229 TEST_PAUSE;
230
231 /* make a temp directory and cd to it */
232 tst_tmpdir();
233
234 /* call individual setup functions */
235 for (ind = 0; Test_cases[ind].desc != NULL; ind++) {
236 Test_cases[ind].setupfunc();
237 }
238} /* End of setup */
239
240/*
241 * int
242 * setup1() - setup function for a test condition for which ftruncate(2)
plars0b3d5f52001-10-23 12:32:55 +0000243 * returns -1 and sets errno to EINVAL.
robbiew06d067e2001-09-11 17:37:01 +0000244 * Create a test file and open it for reading only.
plars865695b2001-08-27 22:15:12 +0000245 */
246int
247setup1()
248{
robbiew06d067e2001-09-11 17:37:01 +0000249 /* Open the testfile in read-only mode */
250 if ((fd1 = open(TEST_FILE1, O_RDONLY|O_CREAT, 0644)) == -1) {
plars865695b2001-08-27 22:15:12 +0000251 tst_brkm(TBROK, cleanup,
robbiew06d067e2001-09-11 17:37:01 +0000252 "open(%s, O_RDONLY) Failed, errno=%d : %s",
plars865695b2001-08-27 22:15:12 +0000253 TEST_FILE1, errno, strerror(errno));
254 }
255 return 0;
256} /* End setup1() */
257
258/*
259 * int
260 * setup2() - setup function for a test condition for which ftruncate(2)
261 * returns -1 and sets errno to EBADF.
262 * Create a test file and open it for reading/writing, and fill the
263 * testfile with the contents of test buffer.
264 * Close the test file.
265 *
266 */
267int
268setup2()
269{
270 int c, i, c_total = 0;
271 char tst_buff[BUF_SIZE]; /* buffer to hold testfile contents */
272
273 /* Fill the test buffer with the known data */
274 for (i = 0; i < BUF_SIZE; i++) {
275 tst_buff[i] = 'a';
276 }
277
278 /* open a testfile for reading/writing */
279 if ((fd2 = open(TEST_FILE2, O_RDWR|O_CREAT, FILE_MODE)) == -1) {
280 tst_brkm(TBROK, cleanup,
281 "open(%s, O_RDWR|O_CREAT, %o) Failed, errno=%d : %s",
282 TEST_FILE2, FILE_MODE, errno, strerror(errno));
283 }
284
285 /* Write to the file 1k data from the buffer */
286 while (c_total < FILE_SIZE) {
287 if ((c = write(fd2, tst_buff, sizeof(tst_buff))) <= 0) {
288 tst_brkm(TBROK, cleanup,
289 "write(2) on %s Failed, errno=%d : %s",
290 TEST_FILE2, errno, strerror(errno));
291 } else {
292 c_total += c;
293 }
294 }
295
296 /* Close the testfile after writing data into it */
297 if (close(fd2) == -1) {
298 tst_brkm(TBROK, cleanup,
299 "close(%s) Failed, errno=%d : %s",
300 TEST_FILE2, errno, strerror(errno));
301 }
302 return 0;
303} /* End of setup2 */
304
305/*
306 * int
307 * no_setup() - This function just returns 0.
308 */
309int
310no_setup()
311{
312 return 0;
313}
314
315/*
316 * void
317 * cleanup() - performs all ONE TIME cleanup for this test at
318 * completion or premature exit.
319 * Close the temporary file.
320 * Remove the test directory and testfile created in the setup.
321 */
322void
323cleanup()
324{
325 /*
326 * print timing stats if that option was specified.
327 */
328 TEST_CLEANUP;
329
330 /* Close the testfile after opening it read-only in setup1 */
331 if (close(fd1) == -1) {
332 tst_brkm(TFAIL, NULL,
333 "close(%s) Failed, errno=%d : %s",
334 TEST_FILE1, errno, strerror(errno));
335 }
336
337 /* Remove tmp dir and all files in it */
338 tst_rmdir();
339
340 /* exit with return code appropriate for results */
341 tst_exit();
342} /* End cleanup() */