blob: 87bace72058160f1d1f870e3c62f493253f50454 [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: truncate03
22 *
23 * Test Description:
24 * Verify that,
25 * 1) truncate(2) returns -1 and sets errno to EACCES if search/write
26 * permission denied for the process on the component of the path prefix
27 * or named file.
28 * 2) truncate(2) returns -1 and sets errno to ENOTDIR if the component of
29 * the path prefix is not a directory.
30 * 3) truncate(2) returns -1 and sets errno to EFAULT if pathname points
31 * outside user's accessible address space.
32 * 4) truncate(2) returns -1 and sets errno to ENAMETOOLONG if the component
33 * of a pathname exceeded 255 characters or entire pathname exceeds 1023
34 * characters.
35 * 5) truncate(2) returns -1 and sets errno to ENOENT if the named file
36 * does not exist.
37 *
38 * Expected Result:
39 * truncate() should fail with return value -1 and set expected errno.
40 *
41 * Algorithm:
42 * Setup:
43 * Setup signal handling.
44 * Create temporary directory.
45 * Pause for SIGUSR1 if option specified.
46 *
47 * Test:
48 * Loop if the proper options are given.
49 * Execute system call
50 * Check return code, if system call failed (return=-1)
51 * if errno set == expected errno
52 * Issue sys call fails with expected return value and errno.
53 * Otherwise,
54 * Issue sys call fails with unexpected errno.
55 * Otherwise,
56 * Issue sys call returns unexpected value.
57 *
58 * Cleanup:
59 * Print errno log and/or timing stats if options given
60 * Delete the temporary directory(s)/file(s) created.
61 *
62 * Usage: <for command-line>
63 * truncate03 [-c n] [-e] [-f] [-i n] [-I x] [-p x] [-t]
64 * where, -c n : Run n copies concurrently.
65 * -e : Turn on errno logging.
66 * -f : Turn off functionality Testing.
67 * -i n : Execute test n times.
68 * -I x : Execute test for x seconds.
69 * -P x : Pause for x seconds between iterations.
70 * -t : Turn on syscall timing.
71 *
72 * History
73 * 07/2001 John George
74 * -Ported
75 *
76 * Restrictions:
77 * This test should be executed by 'non-super-user' only.
78 *
79 */
80
81#include <stdio.h>
82#include <sys/types.h>
83#include <sys/stat.h>
84#include <sys/fcntl.h>
plars1ad84512002-07-23 13:11:18 +000085#include <sys/mman.h>
plars865695b2001-08-27 22:15:12 +000086#include <errno.h>
87#include <string.h>
88#include <signal.h>
robbiew5ed4d212001-08-28 16:10:11 +000089#include <pwd.h>
plars865695b2001-08-27 22:15:12 +000090
91#include "test.h"
92#include "usctest.h"
93
94#define TEST_FILE1 "testfile" /* file under test */
95#define TEST_FILE2 "t_file/testfile" /* file under test */
96#define FILE_MODE S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH
97#define NEW_MODE S_IRUSR | S_IRGRP | S_IROTH
98#define BUF_SIZE 256 /* buffer size */
99#define FILE_SIZE 1024 /* test file size */
100#define TRUNC_LEN 256 /* truncation length */
robbiew5ed4d212001-08-28 16:10:11 +0000101char nobody_uid[] = "nobody";
102struct passwd *ltpuser;
plars865695b2001-08-27 22:15:12 +0000103
104int no_setup();
105int setup1(); /* setup function to test chmod for EACCES */
106int setup2(); /* setup function to test chmod for ENOTDIR */
107int longpath_setup(); /* setup function to test chmod for ENAMETOOLONG */
108
109char *TCID="truncate03"; /* Test program identifier. */
110int TST_TOTAL=5; /* Total number of test conditions */
111extern int Tst_count; /* Test Case counter for tst_* routines */
112int exp_enos[]={EACCES, ENOTDIR, EFAULT, ENAMETOOLONG, ENOENT, 0};
113
plars1ad84512002-07-23 13:11:18 +0000114char * bad_addr = 0;
115
plars865695b2001-08-27 22:15:12 +0000116char Longpathname[PATH_MAX+2];
117char High_address_node[64];
118
119struct test_case_t { /* test case struct. to hold ref. test cond's*/
120 char *pathname;
121 char *desc;
122 int exp_errno;
123 int (*setupfunc)();
124} Test_cases[] = {
125 { TEST_FILE1, "No Search permissions to process", EACCES, setup1 },
126 { TEST_FILE2, "Path contains regular file", ENOTDIR, setup2 },
robbiewd34d5812005-07-11 22:28:09 +0000127#if !defined(UCLINUX)
plars865695b2001-08-27 22:15:12 +0000128 { High_address_node, "Address beyond address space", EFAULT, no_setup},
robbiewd34d5812005-07-11 22:28:09 +0000129#endif
plars865695b2001-08-27 22:15:12 +0000130 { (char *)-1, "Negative address", EFAULT, no_setup },
131 { Longpathname, "Pathname too long", ENAMETOOLONG, longpath_setup },
132 { "", "Pathname is empty", ENOENT, no_setup },
133 { NULL, NULL, 0, no_setup }
134};
135
136void setup(); /* Main setup function for the test */
137void cleanup(); /* Main cleanup function for the test */
138
139int
140main(int ac, char **av)
141{
142 int lc; /* loop counter */
143 char *msg; /* message returned from parse_opts */
144 char *file_name; /* testfile name */
145 char *test_desc; /* test specific error message */
146 int ind;
147
148 /* Parse standard options given to run the test. */
149 msg = parse_opts(ac, av, (option_t *) NULL, NULL);
150 if (msg != (char *) NULL) {
151 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
152 tst_exit();
153 }
154
155 /*
156 * Perform global setup for test to call individual test specific
157 * setup functions.
158 */
159 setup();
160
161 /* set the expected errnos... */
162 TEST_EXP_ENOS(exp_enos);
163
164 /* Check looping state if -i option given */
165 for (lc = 0; TEST_LOOPING(lc); lc++) {
166 /* Reset Tst_count in case we are looping. */
167 Tst_count = 0;
168
169 for (ind = 0; Test_cases[ind].desc != NULL; ind++) {
170 file_name = Test_cases[ind].pathname;
171 test_desc = Test_cases[ind].desc;
172
robbiewd34d5812005-07-11 22:28:09 +0000173#if !defined(UCLINUX)
plars865695b2001-08-27 22:15:12 +0000174 if (file_name == High_address_node) {
175 file_name = (char *)get_high_address();
176 }
robbiewd34d5812005-07-11 22:28:09 +0000177#endif
plars865695b2001-08-27 22:15:12 +0000178
179 /*
180 * Call truncate(2) to test different test conditions.
181 * verify that it fails with return code -1 and sets
182 * appropriate errno.
183 */
184 TEST(truncate(file_name, TRUNC_LEN));
185
186 /* check return code of truncate(2) */
187 if (TEST_RETURN == -1) {
188 TEST_ERROR_LOG(TEST_ERRNO);
189 if (TEST_ERRNO == \
190 Test_cases[ind].exp_errno) {
191 tst_resm(TPASS, "truncate() fails, %s, "
192 "errno=%d", test_desc,
193 TEST_ERRNO);
194 } else {
195 tst_resm(TFAIL, "truncate() fails, %s, "
196 "errno=%d, expected errno:%d",
197 test_desc, TEST_ERRNO,
198 Test_cases[ind].exp_errno);
199 }
200 } else {
201 tst_resm(TFAIL, "truncate() returned %d, "
202 "expected -1, errno:%d",
203 TEST_RETURN,
204 Test_cases[ind].exp_errno);
205 }
206 } /* End of TEST CASE LOOPING. */
207 Tst_count++; /* incr TEST_LOOP counter */
208 } /* End for TEST_LOOPING */
209
210 /* Call cleanup() to undo setup done for the test. */
211 cleanup();
212 /*NOTREACHED*/
213
robbiew9a66de12003-03-27 22:16:14 +0000214
215 return(0);
216
plars865695b2001-08-27 22:15:12 +0000217} /* End main */
218
219/*
220 * void
221 * setup() - performs all ONE TIME setup for this test.
222 * Create a temporary directory and change directory to it.
223 * Create a test file under temporary directory and write some data
224 * into it, close it.
225 * Call individual test specific setup functions.
226 */
227void
228setup()
229{
230 int fd, i, ind; /* file handler for testfile */
231 int c, c_total = 0; /* no. of bytes written to file */
232 char tst_buff[BUF_SIZE]; /* buffer to hold data */
233
234 /* capture signals */
235 tst_sig(FORK, DEF_HANDLER, cleanup);
236
robbiew5ed4d212001-08-28 16:10:11 +0000237 /* Switch to nobody user for correct error code collection */
238 if (geteuid() != 0) {
239 tst_brkm(TBROK, tst_exit, "Test must be run as root");
240 }
241 ltpuser = getpwnam(nobody_uid);
242 if (setuid(ltpuser->pw_uid) == -1) {
243 tst_resm(TINFO, "setuid failed to "
244 "to set the effective uid to %d",
245 ltpuser->pw_uid);
246 perror("setuid");
247 }
248
plars865695b2001-08-27 22:15:12 +0000249
250 /* Pause if that option was specified
251 * TEST_PAUSE contains the code to fork the test with the -i option.
252 * You want to make sure you do this before you create your temporary
253 * directory.
254 */
255 TEST_PAUSE;
256
257 /* make a temp directory and cd to it */
258 tst_tmpdir();
259
260 /* Fill the test buffer with the known data */
261 for (i = 0; i < BUF_SIZE; i++) {
262 tst_buff[i] = 'a';
263 }
264
265 /* Creat a testfile and open it for reading/writing */
266 if ((fd = open(TEST_FILE1, O_RDWR|O_CREAT, FILE_MODE)) == -1) {
267 tst_brkm(TBROK, cleanup,
268 "open(%s, O_RDWR|O_CREAT, %o) Failed, errno=%d : %s",
269 TEST_FILE1, FILE_MODE, errno, strerror(errno));
270 /*NOTREACHED*/
271 }
272
273 /* Write to the file 1k data from the buffer */
274 while (c_total < FILE_SIZE) {
275 if ((c = write(fd, tst_buff, sizeof(tst_buff))) <= 0) {
276 tst_brkm(TBROK, cleanup,
277 "write(2) on %s Failed, errno=%d : %s",
278 TEST_FILE1, errno, strerror(errno));
279 /*NOTREACHED*/
280 } else {
281 c_total += c;
282 }
283 }
284
285 /* Close the testfile after writing data into it */
286 if (close(fd) == -1) {
287 tst_brkm(TBROK, cleanup,
288 "close(%s) Failed, errno=%d : %s",
289 TEST_FILE1, errno, strerror(errno));
290 /*NOTREACHED*/
291 }
292
robbiewd34d5812005-07-11 22:28:09 +0000293 bad_addr = mmap(0, 1, PROT_NONE,
294 MAP_PRIVATE_EXCEPT_UCLINUX|MAP_ANONYMOUS, 0, 0);
vapier0722a2b2006-05-12 15:44:11 +0000295 if (bad_addr == MAP_FAILED) {
plars1ad84512002-07-23 13:11:18 +0000296 tst_brkm(TBROK, cleanup, "mmap failed");
297 }
plars1ad84512002-07-23 13:11:18 +0000298
mreed1081534c32006-08-03 05:21:24 +0000299#if !defined(UCLINUX)
300 Test_cases[3].pathname = bad_addr;
301#else
302 Test_cases[2].pathname = bad_addr;
303#endif
plars865695b2001-08-27 22:15:12 +0000304 /* call individual setup functions */
305 for (ind = 0; Test_cases[ind].desc != NULL; ind++) {
306 Test_cases[ind].setupfunc();
307 }
308} /* End setup() */
309
310/*
311 * int
312 * no_setup() - Some test conditions for mknod(2) do not any setup.
313 * Hence, this function just returns 0.
314 * This function simply returns 0.
315 */
316int
317no_setup()
318{
319 return 0;
320}
321
322/*
323 * int
324 * setup1() - setup function for a test condition for which truncate(2)
325 * returns -1 and sets errno to EACCES.
326 * Modify the mode permissions on testfile such that process will not
327 * have write permissions on it.
328 *
329 * The function returns 0.
330 */
331int
332setup1()
333{
334 /* Change mode permissions on test file */
335 if (chmod(TEST_FILE1, NEW_MODE) < 0) {
336 tst_brkm(TBROK, cleanup, "chmod(2) of %s failed", TEST_FILE1);
337 /*NOTREACHED*/
338 }
339
340 return 0;
341} /* End setup() */
342
343/*
344 * int
345 * setup2() - setup function for a test condition for which truncate(2)
346 * returns -1 and sets errno to ENOTDIR.
347 *
348 * Create a test file under temporary directory so that test tries to
349 * truncate testfile under "t_file" which happens to be another regular file.
350 * The function returns 0.
351 */
352int
353setup2()
354{
355 int fildes;
356
357 /* creat/open a test file under temporary directory */
358 if ((fildes = open("t_file", O_RDWR|O_CREAT, FILE_MODE)) == -1) {
359 tst_brkm(TBROK, cleanup,
360 "open(2) on t_file failed, errno=%d : %s",
361 errno, strerror(errno));
362 /*NOTREACHED*/
363 }
364 /* Close the file created above */
365 if (close(fildes) == -1) {
366 tst_brkm(TBROK, cleanup,
367 "close(t_file) Failed, errno=%d : %s",
368 errno, strerror(errno));
369 /*NOTREACHED*/
370 }
371 return 0;
372}
373
374/*
375 * int
376 * longpath_setup() - setup to create a node with a name length exceeding
377 * the MAX. length of PATH_MAX.
378 * This function retruns 0.
379 */
380int
381longpath_setup()
382{
383 int ind; /* counter variable */
384
385 for (ind = 0; ind <= (PATH_MAX + 1); ind++) {
386 Longpathname[ind] = 'a';
387 }
388 return 0;
389}
390
391/*
392 * void
393 * cleanup() - performs all ONE TIME cleanup for this test at
394 * completion or premature exit.
395 * Remove the test directory and testfile created in the setup.
396 */
397void
398cleanup()
399{
400 /*
401 * print timing stats if that option was specified.
402 */
403 TEST_CLEANUP;
404
405 /* Remove tmp dir and all files in it */
406 tst_rmdir();
407
408 /* exit with return code appropriate for results */
409 tst_exit();
410} /* End cleanup() */