1 /* 2 * Copyright (c) International Business Machines Corp., 2001 3 * 07/2001 John George 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 Foundation, 17 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 */ 19 /* 20 * Test Description: 21 * Verify that, 22 * 1) truncate(2) returns -1 and sets errno to EACCES if search/write 23 * permission denied for the process on the component of the path prefix 24 * or named file. 25 * 2) truncate(2) returns -1 and sets errno to ENOTDIR if the component of 26 * the path prefix is not a directory. 27 * 3) truncate(2) returns -1 and sets errno to EFAULT if pathname points 28 * outside user's accessible address space. 29 * 4) truncate(2) returns -1 and sets errno to ENAMETOOLONG if the component 30 * of a pathname exceeded 255 characters or entire pathname exceeds 1023 31 * characters. 32 * 5) truncate(2) returns -1 and sets errno to ENOENT if the named file 33 * does not exist. 34 * 6) truncate(2) returns -1 and sets errno to EISDIR if the named file 35 * is a directory. 36 * 7) truncate(2) returns -1 and sets errno to EFBIG if the argument length 37 * is larger than the maximum file size. 38 * 8) truncate(2) returns -1 and sets errno to ELOOP if too many symbolic 39 * links were encountered in translating the pathname. 40 */ 41 42 #define _GNU_SOURCE 43 44 #include <stdio.h> 45 #include <sys/types.h> 46 #include <sys/stat.h> 47 #include <sys/fcntl.h> 48 #include <sys/mman.h> 49 #include <errno.h> 50 #include <string.h> 51 #include <signal.h> 52 #include <pwd.h> 53 #include <sys/resource.h> 54 55 #include "test.h" 56 #include "safe_macros.h" 57 58 #define TEST_FILE1 "testfile" 59 #define TEST_FILE2 "t_file/testfile" 60 #define TEST_FILE3 "testfile3" 61 #define TEST_SYM1 "testsymlink1" 62 #define TEST_SYM2 "testsymlink2" 63 #define TEST_DIR1 "testdir" 64 #define FILE_MODE S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH 65 #define NEW_MODE S_IRUSR | S_IRGRP | S_IROTH 66 #define DIR_MODE S_IRWXU 67 #define TRUNC_LEN 256 68 #define MAX_FSIZE (16*1024*1024) 69 70 static char long_pathname[PATH_MAX + 2]; 71 72 static struct test_case_t { 73 char *pathname; 74 off_t length; 75 int exp_errno; 76 } test_cases[] = { 77 { TEST_FILE1, TRUNC_LEN, EACCES }, 78 { TEST_FILE2, TRUNC_LEN, ENOTDIR }, 79 #if !defined(UCLINUX) 80 { NULL, TRUNC_LEN, EFAULT }, 81 { (char *)-1, TRUNC_LEN, EFAULT }, 82 #endif 83 { long_pathname, TRUNC_LEN, ENAMETOOLONG }, 84 { "", TRUNC_LEN, ENOENT }, 85 { TEST_DIR1, TRUNC_LEN, EISDIR }, 86 { TEST_FILE3, MAX_FSIZE*2, EFBIG }, 87 { TEST_SYM1, TRUNC_LEN, ELOOP } 88 }; 89 90 static void setup(void); 91 static void cleanup(void); 92 static void truncate_verify(struct test_case_t *); 93 94 char *TCID = "truncate03"; 95 int TST_TOTAL = ARRAY_SIZE(test_cases); 96 97 int main(int ac, char **av) 98 { 99 int i, lc; 100 101 tst_parse_opts(ac, av, NULL, NULL); 102 103 setup(); 104 105 for (lc = 0; TEST_LOOPING(lc); lc++) { 106 tst_count = 0; 107 108 for (i = 0; i < TST_TOTAL; i++) 109 truncate_verify(&test_cases[i]); 110 111 } 112 113 cleanup(); 114 tst_exit(); 115 } 116 117 void setup(void) 118 { 119 struct passwd *ltpuser; 120 char *bad_addr; 121 struct rlimit rlim; 122 sigset_t sigset; 123 124 tst_sig(NOFORK, DEF_HANDLER, cleanup); 125 126 tst_require_root(); 127 128 ltpuser = SAFE_GETPWNAM(cleanup, "nobody"); 129 SAFE_SETEUID(cleanup, ltpuser->pw_uid); 130 131 TEST_PAUSE; 132 133 tst_tmpdir(); 134 135 SAFE_TOUCH(cleanup, TEST_FILE1, NEW_MODE, NULL); 136 137 SAFE_TOUCH(cleanup, "t_file", FILE_MODE, NULL); 138 139 #if !defined(UCLINUX) 140 test_cases[2].pathname = (char *)get_high_address(); 141 142 bad_addr = SAFE_MMAP(cleanup, 0, 1, PROT_NONE, 143 MAP_PRIVATE_EXCEPT_UCLINUX | MAP_ANONYMOUS, 0, 0); 144 test_cases[3].pathname = bad_addr; 145 #endif 146 147 memset(long_pathname, 'a', PATH_MAX + 1); 148 149 SAFE_MKDIR(cleanup, TEST_DIR1, DIR_MODE); 150 151 SAFE_TOUCH(cleanup, TEST_FILE3, FILE_MODE, NULL); 152 153 SAFE_SYMLINK(cleanup, TEST_SYM1, TEST_SYM2); 154 SAFE_SYMLINK(cleanup, TEST_SYM2, TEST_SYM1); 155 156 rlim.rlim_cur = MAX_FSIZE; 157 rlim.rlim_max = MAX_FSIZE; 158 SAFE_SETRLIMIT(cleanup, RLIMIT_FSIZE, &rlim); 159 160 sigemptyset(&sigset); 161 sigaddset(&sigset, SIGXFSZ); 162 TEST(sigprocmask(SIG_BLOCK, &sigset, NULL)); 163 if (TEST_RETURN != 0) 164 tst_brkm(TBROK | TTERRNO, cleanup, "sigprocmask"); 165 } 166 167 void truncate_verify(struct test_case_t *tc) 168 { 169 TEST(truncate(tc->pathname, tc->length)); 170 171 if (TEST_RETURN != -1) { 172 tst_resm(TFAIL, "truncate() returned %ld, " 173 "expected -1, errno:%d", TEST_RETURN, 174 tc->exp_errno); 175 return; 176 } 177 178 if (TEST_ERRNO == tc->exp_errno) { 179 tst_resm(TPASS | TTERRNO, "truncate() failed as expected"); 180 } else { 181 tst_resm(TFAIL | TTERRNO, 182 "truncate() failed unexpectedly; expected: %d - %s", 183 tc->exp_errno, strerror(tc->exp_errno)); 184 } 185 } 186 187 void cleanup(void) 188 { 189 tst_rmdir(); 190 } 191