1 /* 2 * Copyright (c) International Business Machines Corp., 2006 3 * AUTHOR: Yi Yang <yyangcdl (at) cn.ibm.com> 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 * DESCRIPTION 21 * This test case will verify basic function of fchownat 22 * added by kernel 2.6.16 or up. 23 */ 24 25 #define _GNU_SOURCE 26 27 #include <sys/types.h> 28 #include <sys/stat.h> 29 #include <fcntl.h> 30 #include <unistd.h> 31 #include <stdlib.h> 32 #include <errno.h> 33 #include <string.h> 34 #include <signal.h> 35 36 #include "test.h" 37 #include "safe_macros.h" 38 #include "fchownat.h" 39 #include "lapi/fcntl.h" 40 41 #define TESTFILE "testfile" 42 43 static void setup(void); 44 static void cleanup(void); 45 46 static int dir_fd; 47 static int fd; 48 static int no_fd = -1; 49 static int cu_fd = AT_FDCWD; 50 51 static struct test_case_t { 52 int exp_ret; 53 int exp_errno; 54 int flag; 55 int *fds; 56 char *filenames; 57 } test_cases[] = { 58 {0, 0, 0, &dir_fd, TESTFILE}, 59 {-1, ENOTDIR, 0, &fd, TESTFILE}, 60 {-1, EBADF, 0, &no_fd, TESTFILE}, 61 {-1, EINVAL, 9999, &dir_fd, TESTFILE}, 62 {0, 0, 0, &cu_fd, TESTFILE}, 63 }; 64 65 char *TCID = "fchownat01"; 66 int TST_TOTAL = ARRAY_SIZE(test_cases); 67 static void fchownat_verify(const struct test_case_t *); 68 69 int main(int ac, char **av) 70 { 71 int lc; 72 int i; 73 74 tst_parse_opts(ac, av, NULL, NULL); 75 76 setup(); 77 78 for (lc = 0; TEST_LOOPING(lc); lc++) { 79 tst_count = 0; 80 for (i = 0; i < TST_TOTAL; i++) 81 fchownat_verify(&test_cases[i]); 82 } 83 84 cleanup(); 85 tst_exit(); 86 } 87 88 static void setup(void) 89 { 90 if ((tst_kvercmp(2, 6, 16)) < 0) 91 tst_brkm(TCONF, NULL, "This test needs kernel 2.6.16 or newer"); 92 93 tst_sig(NOFORK, DEF_HANDLER, cleanup); 94 95 TEST_PAUSE; 96 97 tst_tmpdir(); 98 99 dir_fd = SAFE_OPEN(cleanup, "./", O_DIRECTORY); 100 101 SAFE_TOUCH(cleanup, TESTFILE, 0600, NULL); 102 103 fd = SAFE_OPEN(cleanup, "testfile2", O_CREAT | O_RDWR, 0600); 104 } 105 106 static void fchownat_verify(const struct test_case_t *test) 107 { 108 TEST(fchownat(*(test->fds), test->filenames, geteuid(), 109 getegid(), test->flag)); 110 111 if (TEST_RETURN != test->exp_ret) { 112 tst_resm(TFAIL | TTERRNO, 113 "fchownat() returned %ld, expected %d, errno=%d", 114 TEST_RETURN, test->exp_ret, test->exp_errno); 115 return; 116 } 117 118 if (TEST_ERRNO == test->exp_errno) { 119 tst_resm(TPASS | TTERRNO, 120 "fchownat() returned the expected errno %d: %s", 121 test->exp_ret, strerror(test->exp_errno)); 122 } else { 123 tst_resm(TFAIL | TTERRNO, 124 "fchownat() failed unexpectedly; expected: %d - %s", 125 test->exp_errno, strerror(test->exp_errno)); 126 } 127 } 128 129 static void cleanup(void) 130 { 131 if (fd > 0) 132 close(fd); 133 134 if (dir_fd > 0) 135 close(dir_fd); 136 137 tst_rmdir(); 138 } 139