lchown01.c revision 43088e16aa60d69e3ec5a69cdd8bdd45b8891127
1/* 2 * 3 * Copyright (c) International Business Machines Corp., 2001 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 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 */ 19 20/* 21 * Test Name: lchown01 22 * 23 * Test Description: 24 * Verify that, lchown(2) succeeds to change the owner and group of a file 25 * specified by path to any numeric owner(uid)/group(gid) values when invoked 26 * by super-user. 27 * 28 * Expected Result: 29 * lchown(2) should return 0 and the ownership set on the file should match 30 * the numeric values contained in owner and group respectively. 31 * 32 * Algorithm: 33 * Setup: 34 * Setup signal handling. 35 * Create temporary directory. 36 * Pause for SIGUSR1 if option specified. 37 * 38 * Test: 39 * Loop if the proper options are given. 40 * Execute system call 41 * Check return code, if system call failed (return=-1) 42 * Log the errno and Issue a FAIL message. 43 * Otherwise, 44 * Verify the Functionality of system call 45 * if successful, 46 * Issue Functionality-Pass message. 47 * Otherwise, 48 * Issue Functionality-Fail message. 49 * Cleanup: 50 * Print errno log and/or timing stats if options given 51 * Delete the temporary directory created. 52 * 53 * Usage: <for command-line> 54 * lchown01 [-c n] [-e] [-f] [-i n] [-I x] [-P x] [-t] 55 * where, -c n : Run n copies concurrently. 56 * -e : Turn on errno logging. 57 * -f : Turn off functionality Testing. 58 * -i n : Execute test n times. 59 * -I x : Execute test for x seconds. 60 * -P x : Pause for x seconds between iterations. 61 * -t : Turn on syscall timing. 62 * 63 * HISTORY 64 * 07/2001 Ported by Wayne Boyer 65 * 11/2010 Code cleanup by Cyril Hrubis chrubis@suse.cz 66 * 67 * RESTRICTIONS: 68 * This test should be run by 'super-user' (root) only. 69 * 70 */ 71 72#include <stdio.h> 73#include <sys/types.h> 74#include <sys/stat.h> 75#include <sys/fcntl.h> 76#include <errno.h> 77#include <string.h> 78#include <signal.h> 79 80#include "test.h" 81#include "usctest.h" 82 83#define FILE_MODE (S_IFREG|S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) 84#define TESTFILE "testfile" 85#define SFILE "slink_file" 86 87char *TCID = "lchown01"; 88int TST_TOTAL = 5; 89extern int Tst_count; 90 91struct test_case_t { 92 char *desc; 93 uid_t user_id; 94 gid_t group_id; 95}; 96 97static struct test_case_t test_cases[] = { 98 {"Change Owner/Group ids", 700, 701}, 99 {"Change Owner id only", 702, -1}, 100 {"Change Owner/Group ids", 703, 701}, 101 {"Change Group id only", -1, 704}, 102 {"Change Group/Group ids", 703, 705}, 103 {"Change none", -1, -1}, 104 {NULL, 0, 0} 105}; 106 107void setup(void); 108void cleanup(void); 109 110int main(int argc, char *argv[]) 111{ 112 struct stat stat_buf; 113 int lc; 114 char *msg; 115 int i; 116 uid_t user_id; 117 gid_t group_id; 118 char *test_desc; 119 120 if ((msg = parse_opts(ac, av, (option_t *) NULL, NULL)) != NULL) 121 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); 122 123 setup(); 124 125 for (lc = 0; TEST_LOOPING(lc); lc++) { 126 /* Reset Tst_count in case we are looping. */ 127 Tst_count = 0; 128 129 for (i = 0; test_cases[i].desc != NULL; i++) { 130 uid_t user_id = test_cases[i].user_id; 131 gid_t group_id = test_cases[i].group_id; 132 char *test_desc = test_cases[i].desc; 133 134 /* 135 * Call lchown(2) with different user id and 136 * group id (numeric values) to set it on 137 * symlink of testfile. 138 */ 139 TEST(lchown(SFILE, user_id, group_id)); 140 141 if (TEST_RETURN == -1) { 142 tst_resm(TFAIL, 143 "lchown() Fails to %s, errno %d", 144 test_desc, TEST_ERRNO); 145 continue; 146 } 147 /* 148 * Perform functional verification if test 149 * executed without (-f) option. 150 */ 151 if (STD_FUNCTIONAL_TEST) { 152 /* 153 * Get the testfile information using 154 * lstat(2). 155 */ 156 if (lstat(SFILE, &stat_buf) < 0) { 157 tst_brkm(TFAIL, cleanup, "lstat(2) " 158 "%s failed, errno %d", 159 SFILE, TEST_ERRNO); 160 } 161 if (user_id == -1) { 162 if (i > 0) 163 user_id = test_cases[i-1].user_id; 164 else 165 user_id = geteuid(); 166 } 167 if (group_id == -1) { 168 if (i > 0) 169 group_id = test_cases[i-1].group_id; 170 else 171 group_id = getegid(); 172 } 173 174 /* 175 * Check for expected Ownership ids 176 * set on testfile. 177 */ 178 if ((stat_buf.st_uid != user_id) || 179 (stat_buf.st_gid != group_id)) { 180 tst_resm(TFAIL, 181 "%s: incorrect ownership set, " 182 "Expected %d %d", SFILE, 183 user_id, group_id); 184 } else { 185 tst_resm(TPASS, "lchown() succeeds to " 186 "%s of %s", test_desc, SFILE); 187 } 188 } else { 189 tst_resm(TPASS, "call succeeded"); 190 } 191 } 192 } 193 194 cleanup(); 195 196 tst_exit(); 197} 198 199/* 200 * setup() - performs all ONE TIME setup for this test. 201 * Create a temporary directory and change directory to it. 202 * Create a test file under temporary directory and close it 203 * Create a symlink of testfile under temporary directory. 204 */ 205void setup(void) 206{ 207 int fd; 208 209 /* capture signals */ 210 tst_sig(NOFORK, DEF_HANDLER, cleanup); 211 212 tst_require_root(NULL); 213 214 TEST_PAUSE; 215 tst_tmpdir(); 216 217 if ((fd = open(TESTFILE, O_RDWR | O_CREAT, FILE_MODE)) == -1) { 218 tst_brkm(TBROK, cleanup, "open(%s, O_RDWR|O_CREAT, %o) failed", 219 TESTFILE, FILE_MODE); 220 } 221 if (close(fd) == -1) { 222 tst_brkm(TBROK|TERRNO, cleanup, "close(%s) failed", TESTFILE); 223 } 224 225 if (close(fd) == -1) 226 tst_brkm(TBROK|TERRNO, cleanup, "close(2) %s", TESTFILE); 227 228 if (symlink(TESTFILE, SFILE) < 0) { 229 tst_brkm(TBROK|TERRNO, cleanup, "symlink(2) %s to %s failed", 230 TESTFILE, SFILE); 231 } 232} 233 234/* 235 * cleanup() - performs all ONE TIME cleanup for this test at 236 * completion or premature exit. 237 * Remove the test directory and testfile created in the setup. 238 */ 239void cleanup(void) 240{ 241 TEST_CLEANUP; 242 243 tst_rmdir(); 244} 245