1 /* 2 * Copyright (c) International Business Machines Corp., 2001 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 12 * the GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 */ 18 19 /* 20 * Test Description: 21 * Verify that, lchown(2) succeeds to change the owner and group of a file 22 * specified by path to any numeric owner(uid)/group(gid) values when invoked 23 * by super-user. 24 * 25 * Expected Result: 26 * lchown(2) should return 0 and the ownership set on the file should match 27 * the numeric values contained in owner and group respectively. 28 * 29 * HISTORY 30 * 07/2001 Ported by Wayne Boyer 31 * 11/2010 Code cleanup by Cyril Hrubis chrubis (at) suse.cz 32 */ 33 34 #include <stdio.h> 35 #include <sys/types.h> 36 #include <sys/stat.h> 37 #include <sys/fcntl.h> 38 #include <errno.h> 39 #include <string.h> 40 #include <signal.h> 41 42 #include "test.h" 43 #include "compat_16.h" 44 45 #define FILE_MODE (S_IFREG|S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) 46 #define TESTFILE "testfile" 47 #define SFILE "slink_file" 48 49 TCID_DEFINE(lchown01); 50 int TST_TOTAL = 5; 51 52 struct test_case_t { 53 char *desc; 54 uid_t user_id; 55 gid_t group_id; 56 }; 57 58 static struct test_case_t test_cases[] = { 59 {"Change Owner/Group ids", 700, 701}, 60 {"Change Owner id only", 702, -1}, 61 {"Change Owner/Group ids", 703, 701}, 62 {"Change Group id only", -1, 704}, 63 {"Change Group/Group ids", 703, 705}, 64 {"Change none", -1, -1}, 65 {NULL, 0, 0} 66 }; 67 68 static void setup(void); 69 static void cleanup(void); 70 71 int main(int argc, char *argv[]) 72 { 73 struct stat stat_buf; 74 int lc; 75 int i; 76 77 tst_parse_opts(argc, argv, NULL, NULL); 78 79 setup(); 80 81 for (lc = 0; TEST_LOOPING(lc); lc++) { 82 83 tst_count = 0; 84 85 for (i = 0; test_cases[i].desc != NULL; i++) { 86 uid_t user_id = test_cases[i].user_id; 87 gid_t group_id = test_cases[i].group_id; 88 char *test_desc = test_cases[i].desc; 89 90 /* 91 * Call lchown(2) with different user id and 92 * group id (numeric values) to set it on 93 * symlink of testfile. 94 */ 95 TEST(LCHOWN(cleanup, SFILE, user_id, group_id)); 96 97 if (TEST_RETURN == -1) { 98 tst_resm(TFAIL, 99 "lchown() Fails to %s, errno %d", 100 test_desc, TEST_ERRNO); 101 continue; 102 } 103 104 if (lstat(SFILE, &stat_buf) < 0) { 105 tst_brkm(TFAIL, cleanup, "lstat(2) " 106 "%s failed, errno %d", 107 SFILE, TEST_ERRNO); 108 } 109 110 if (user_id == -1) { 111 if (i > 0) 112 user_id = 113 test_cases[i - 1].user_id; 114 else 115 user_id = geteuid(); 116 } 117 118 if (group_id == -1) { 119 if (i > 0) 120 group_id = 121 test_cases[i - 1].group_id; 122 else 123 group_id = getegid(); 124 } 125 126 /* 127 * Check for expected Ownership ids 128 * set on testfile. 129 */ 130 if ((stat_buf.st_uid != user_id) || 131 (stat_buf.st_gid != group_id)) { 132 tst_resm(TFAIL, 133 "%s: incorrect ownership set, " 134 "Expected %d %d", SFILE, 135 user_id, group_id); 136 } else { 137 tst_resm(TPASS, "lchown() succeeds to " 138 "%s of %s", test_desc, SFILE); 139 } 140 } 141 } 142 143 cleanup(); 144 tst_exit(); 145 } 146 147 static void setup(void) 148 { 149 int fd; 150 151 tst_sig(NOFORK, DEF_HANDLER, cleanup); 152 153 tst_require_root(); 154 155 TEST_PAUSE; 156 tst_tmpdir(); 157 158 if ((fd = open(TESTFILE, O_RDWR | O_CREAT, FILE_MODE)) == -1) { 159 tst_brkm(TBROK, cleanup, "open failed"); 160 } 161 if (close(fd) == -1) { 162 tst_brkm(TBROK | TERRNO, cleanup, "close failed"); 163 } 164 165 if (symlink(TESTFILE, SFILE) < 0) { 166 tst_brkm(TBROK | TERRNO, cleanup, "symlink failed"); 167 } 168 } 169 170 static void cleanup(void) 171 { 172 tst_rmdir(); 173 } 174