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@suse.cz 32 */ 33 34#include <stdio.h> 35#include <sys/types.h> 36#include <sys/stat.h> 37#include <fcntl.h> 38#include <errno.h> 39#include <string.h> 40#include <signal.h> 41 42#include "test.h" 43#include "safe_macros.h" 44#include "compat_16.h" 45 46#define FILE_MODE (S_IFREG|S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) 47#define TESTFILE "testfile" 48#define SFILE "slink_file" 49 50TCID_DEFINE(lchown01); 51int TST_TOTAL = 5; 52 53struct test_case_t { 54 char *desc; 55 uid_t user_id; 56 gid_t group_id; 57}; 58 59static struct test_case_t test_cases[] = { 60 {"Change Owner/Group ids", 700, 701}, 61 {"Change Owner id only", 702, -1}, 62 {"Change Owner/Group ids", 703, 701}, 63 {"Change Group id only", -1, 704}, 64 {"Change Group/Group ids", 703, 705}, 65 {"Change none", -1, -1}, 66 {NULL, 0, 0} 67}; 68 69static void setup(void); 70static void cleanup(void); 71 72int main(int argc, char *argv[]) 73{ 74 struct stat stat_buf; 75 int lc; 76 int i; 77 78 tst_parse_opts(argc, argv, NULL, NULL); 79 80 setup(); 81 82 for (lc = 0; TEST_LOOPING(lc); lc++) { 83 84 tst_count = 0; 85 86 for (i = 0; test_cases[i].desc != NULL; i++) { 87 uid_t user_id = test_cases[i].user_id; 88 gid_t group_id = test_cases[i].group_id; 89 char *test_desc = test_cases[i].desc; 90 91 /* 92 * Call lchown(2) with different user id and 93 * group id (numeric values) to set it on 94 * symlink of testfile. 95 */ 96 TEST(LCHOWN(cleanup, SFILE, user_id, group_id)); 97 98 if (TEST_RETURN == -1) { 99 tst_resm(TFAIL, 100 "lchown() Fails to %s, errno %d", 101 test_desc, TEST_ERRNO); 102 continue; 103 } 104 105 if (lstat(SFILE, &stat_buf) < 0) { 106 tst_brkm(TFAIL, cleanup, "lstat(2) " 107 "%s failed, errno %d", 108 SFILE, TEST_ERRNO); 109 } 110 111 if (user_id == -1) { 112 if (i > 0) 113 user_id = 114 test_cases[i - 1].user_id; 115 else 116 user_id = geteuid(); 117 } 118 119 if (group_id == -1) { 120 if (i > 0) 121 group_id = 122 test_cases[i - 1].group_id; 123 else 124 group_id = getegid(); 125 } 126 127 /* 128 * Check for expected Ownership ids 129 * set on testfile. 130 */ 131 if ((stat_buf.st_uid != user_id) || 132 (stat_buf.st_gid != group_id)) { 133 tst_resm(TFAIL, 134 "%s: incorrect ownership set, " 135 "Expected %d %d", SFILE, 136 user_id, group_id); 137 } else { 138 tst_resm(TPASS, "lchown() succeeds to " 139 "%s of %s", test_desc, SFILE); 140 } 141 } 142 } 143 144 cleanup(); 145 tst_exit(); 146} 147 148static void setup(void) 149{ 150 int fd; 151 152 tst_sig(NOFORK, DEF_HANDLER, cleanup); 153 154 tst_require_root(); 155 156 TEST_PAUSE; 157 tst_tmpdir(); 158 159 if ((fd = open(TESTFILE, O_RDWR | O_CREAT, FILE_MODE)) == -1) { 160 tst_brkm(TBROK, cleanup, "open failed"); 161 } 162 SAFE_CLOSE(cleanup, fd); 163 164 SAFE_SYMLINK(cleanup, TESTFILE, SFILE); 165} 166 167static void cleanup(void) 168{ 169 tst_rmdir(); 170} 171