Home | History | Annotate | Download | only in truncate
      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