Home | History | Annotate | Download | only in fchown
      1 /*
      2  * Copyright (c) International Business Machines  Corp., 2001
      3  *  07/2001 Ported by Wayne Boyer
      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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     18  */
     19 /*
     20  * Test Description:
     21  *  Verify that, fchown(2) succeeds to change the owner and group of a file
     22  *  specified by file descriptor to any numeric owner(uid)/group(gid) values
     23  *  when invoked by super-user.
     24  */
     25 
     26 #include <stdio.h>
     27 #include <sys/types.h>
     28 #include <sys/stat.h>
     29 #include <sys/fcntl.h>
     30 #include <errno.h>
     31 #include <string.h>
     32 #include <signal.h>
     33 
     34 #include "test.h"
     35 #include "safe_macros.h"
     36 #include "compat_16.h"
     37 
     38 #define FILE_MODE	S_IFREG | S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH
     39 #define TESTFILE	"testfile"
     40 
     41 TCID_DEFINE(fchown05);
     42 
     43 static struct test_case_t {
     44 	char *desc;
     45 	uid_t user_id;
     46 	gid_t group_id;
     47 } tc[] = {
     48 	{"Change Owner/Group ids", 700, 701},
     49 	{"Change Owner id only", 702, -1},
     50 	{"Change Owner id only", 703, 701},
     51 	{"Change Group id only", -1, 704},
     52 	{"Change Group id only", 703, 705},
     53 	{NULL, 0, 0}
     54 };
     55 
     56 int TST_TOTAL = ARRAY_SIZE(tc);
     57 
     58 static void setup(void);
     59 static void cleanup(void);
     60 static int fildes;
     61 
     62 int main(int ac, char **av)
     63 {
     64 	struct stat stat_buf;
     65 	int i, lc;
     66 	uid_t user_id;
     67 	gid_t group_id;
     68 
     69 	tst_parse_opts(ac, av, NULL, NULL);
     70 
     71 	setup();
     72 
     73 	for (lc = 0; TEST_LOOPING(lc); lc++) {
     74 		tst_count = 0;
     75 
     76 		for (i = 0; tc[i].desc != NULL; i++) {
     77 			user_id = tc[i].user_id;
     78 			group_id = tc[i].group_id;
     79 
     80 			TEST(FCHOWN(cleanup, fildes, user_id, group_id));
     81 
     82 			if (TEST_RETURN == -1) {
     83 				tst_resm(TFAIL | TTERRNO,
     84 					 "fchown() Fails to %s", tc[i].desc);
     85 				continue;
     86 			}
     87 
     88 			SAFE_FSTAT(cleanup, fildes, &stat_buf);
     89 
     90 			if (user_id == (uid_t)-1)
     91 				user_id = tc[i - 1].user_id;
     92 
     93 			if (group_id == (gid_t)-1)
     94 				group_id = tc[i - 1].group_id;
     95 
     96 			if ((stat_buf.st_uid != user_id) ||
     97 			    (stat_buf.st_gid != group_id)) {
     98 				tst_resm(TFAIL, "%s: Incorrect owner"
     99 					 "ship set, Expected %d %d",
    100 					 TESTFILE, user_id, group_id);
    101 			} else {
    102 				tst_resm(TPASS,
    103 					 "fchown() succeeds to %s of %s",
    104 					 tc[i].desc, TESTFILE);
    105 			}
    106 		}
    107 	}
    108 
    109 	cleanup();
    110 	tst_exit();
    111 }
    112 
    113 static void setup(void)
    114 {
    115 	tst_sig(NOFORK, DEF_HANDLER, cleanup);
    116 
    117 	tst_require_root();
    118 
    119 	TEST_PAUSE;
    120 
    121 	tst_tmpdir();
    122 
    123 	fildes = SAFE_OPEN(cleanup, TESTFILE, O_RDWR | O_CREAT, FILE_MODE);
    124 }
    125 
    126 static void cleanup(void)
    127 {
    128 	if (fildes > 0 && close(fildes))
    129 		tst_resm(TWARN | TERRNO, "close(%s) Failed", TESTFILE);
    130 
    131 	tst_rmdir();
    132 }
    133