Home | History | Annotate | Download | only in lchown
      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