1 /* 2 * 3 * Copyright (c) International Business Machines Corp., 2001 4 * Author: Wayne Boyer 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 14 * the GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 */ 20 21 /* 22 * Test that fchmod() fails and sets the proper errno values. 23 */ 24 25 #ifndef _GNU_SOURCE 26 # define _GNU_SOURCE 27 #endif 28 29 #include <sys/types.h> 30 #include <sys/stat.h> 31 #include <stdio.h> 32 #include <stdlib.h> 33 #include <unistd.h> 34 #include <fcntl.h> 35 #include <errno.h> 36 #include <string.h> 37 #include <signal.h> 38 #include <unistd.h> 39 #include <grp.h> 40 #include <pwd.h> 41 #include <sys/mount.h> 42 43 #include "test.h" 44 #include "safe_macros.h" 45 46 static int fd1; 47 static int fd2; 48 static int fd3; 49 static const char *device; 50 static int mount_flag; 51 52 static struct test_case_t { 53 char *name; 54 int *fd; 55 int mode; 56 int exp_errno; 57 } test_cases[] = { 58 {"EPERM", &fd1, 0644, EPERM}, 59 {"EBADF", &fd2, 0644, EBADF}, 60 {"EROFS", &fd3, 0644, EROFS}, 61 }; 62 63 char *TCID = "fchmod06"; 64 int TST_TOTAL = ARRAY_SIZE(test_cases); 65 66 static void setup(void); 67 static void cleanup(void); 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 80 tst_count = 0; 81 82 for (i = 0; i < TST_TOTAL; i++) { 83 84 TEST(fchmod(*test_cases[i].fd, test_cases[i].mode)); 85 86 if (TEST_RETURN == -1) { 87 if (TEST_ERRNO == test_cases[i].exp_errno) { 88 tst_resm(TPASS | TTERRNO, 89 "fchmod: test %s success", 90 test_cases[i].name); 91 } else { 92 tst_resm(TFAIL | TTERRNO, 93 "fchmod: test %s FAILED with " 94 "unexpect errno: %d", 95 test_cases[i].name, 96 TEST_ERRNO); 97 } 98 } else { 99 tst_resm(TFAIL, 100 "fchmod: test %s success unexpectly", 101 test_cases[i].name); 102 } 103 } 104 105 } 106 107 cleanup(); 108 tst_exit(); 109 } 110 111 static void setup(void) 112 { 113 struct passwd *ltpuser; 114 const char *fs_type; 115 116 tst_sig(FORK, DEF_HANDLER, cleanup); 117 118 tst_require_root(); 119 120 TEST_PAUSE; 121 122 tst_tmpdir(); 123 124 fs_type = tst_dev_fs_type(); 125 device = tst_acquire_device(cleanup); 126 127 if (!device) 128 tst_brkm(TCONF, cleanup, "Failed to obtain block device"); 129 130 tst_mkfs(cleanup, device, fs_type, NULL, NULL); 131 132 SAFE_MKDIR(cleanup, "mntpoint", 0755); 133 134 if (mount(device, "mntpoint", fs_type, 0, NULL) < 0) { 135 tst_brkm(TBROK | TERRNO, cleanup, 136 "mount device:%s failed", device); 137 } 138 mount_flag = 1; 139 140 /* Create a file in the file system, then remount it as read-only */ 141 SAFE_TOUCH(cleanup, "mntpoint/tfile_3", 0644, NULL); 142 143 if (mount(device, "mntpoint", fs_type, 144 MS_REMOUNT | MS_RDONLY, NULL) < 0) { 145 tst_brkm(TBROK | TERRNO, cleanup, 146 "mount device:%s failed", device); 147 } 148 149 fd3 = SAFE_OPEN(cleanup, "mntpoint/tfile_3", O_RDONLY); 150 151 fd1 = SAFE_OPEN(cleanup, "tfile_1", O_RDWR | O_CREAT, 0666); 152 153 fd2 = SAFE_OPEN(cleanup, "tfile_2", O_RDWR | O_CREAT, 0666); 154 155 SAFE_CLOSE(cleanup, fd2); 156 157 ltpuser = SAFE_GETPWNAM(cleanup, "nobody"); 158 159 SAFE_SETEUID(cleanup, ltpuser->pw_uid); 160 } 161 162 static void cleanup(void) 163 { 164 if (seteuid(0)) 165 tst_resm(TWARN | TERRNO, "seteuid(0) failed"); 166 167 if (fd1 > 0 && close(fd1)) 168 tst_resm(TWARN | TERRNO, "close(fd1) failed"); 169 170 if (fd3 > 0 && close(fd3)) 171 tst_resm(TWARN | TERRNO, "close(fd1) failed"); 172 173 if (mount_flag && tst_umount("mntpoint") < 0) { 174 tst_brkm(TBROK | TERRNO, NULL, 175 "umount device:%s failed", device); 176 } 177 178 if (device) 179 tst_release_device(device); 180 181 tst_rmdir(); 182 } 183