Home | History | Annotate | Download | only in utime
      1 /*
      2  * Copyright (c) International Business Machines  Corp., 2001
      3  *	07/2001 John George
      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 /*
     21  * Test Description:
     22  * 1. Verify that the system call utime() fails to set the modification
     23  *    and access times of a file to the current time, under the following
     24  *    constraints,
     25  *	 - The times argument is null.
     26  *	 - The user ID of the process is not "root".
     27  * 2. Verify that the system call utime() fails to set the modification
     28  *    and access times of a file if the specified file doesn't exist.
     29  * 3. Verify that the system call utime() fails to set the modification
     30  *    and access times of a file to the current time, under the following
     31  *    constraints,
     32  *	 - The times argument is not null.
     33  *	 - The user ID of the process is not "root".
     34  * 4. Verify that the system call utime() fails to set the modification
     35  *    and access times of a file that resides on a read-only file system.
     36  */
     37 
     38 #include <errno.h>
     39 #include <fcntl.h>
     40 #include <pwd.h>
     41 #include <stdio.h>
     42 #include <stdlib.h>
     43 #include <signal.h>
     44 #include <string.h>
     45 #include <unistd.h>
     46 #include <utime.h>
     47 #include <wait.h>
     48 #include <sys/stat.h>
     49 #include <sys/types.h>
     50 #include <sys/mount.h>
     51 
     52 #include "test.h"
     53 #include "safe_macros.h"
     54 
     55 #define TEMP_FILE	"tmp_file"
     56 #define MNT_POINT	"mntpoint"
     57 
     58 char *TCID = "utime06";
     59 static struct passwd *ltpuser;
     60 static const struct utimbuf times;
     61 static const char *dev;
     62 static int mount_flag;
     63 static void setup_nobody(void);
     64 static void cleanup_nobody(void);
     65 
     66 struct test_case_t {
     67 	char *pathname;
     68 	int exp_errno;
     69 	const struct utimbuf *times;
     70 	void (*setup_func)(void);
     71 	void (*cleanup_func)(void);
     72 } Test_cases[] = {
     73 	{TEMP_FILE, EACCES, NULL, setup_nobody, cleanup_nobody},
     74 	{"", ENOENT, NULL, NULL, NULL},
     75 	{TEMP_FILE, EPERM, &times, setup_nobody, cleanup_nobody},
     76 	{MNT_POINT, EROFS, NULL, NULL, NULL},
     77 };
     78 
     79 int TST_TOTAL = ARRAY_SIZE(Test_cases);
     80 static void setup(void);
     81 static void utime_verify(const struct test_case_t *);
     82 static void cleanup(void);
     83 
     84 int main(int ac, char **av)
     85 {
     86 	int lc;
     87 	int i;
     88 
     89 	tst_parse_opts(ac, av, NULL, NULL);
     90 
     91 	setup();
     92 
     93 	for (lc = 0; TEST_LOOPING(lc); lc++) {
     94 		tst_count = 0;
     95 		for (i = 0; i < TST_TOTAL; i++)
     96 			utime_verify(&Test_cases[i]);
     97 	}
     98 
     99 	cleanup();
    100 	tst_exit();
    101 }
    102 
    103 static void setup(void)
    104 {
    105 	const char *fs_type;
    106 
    107 	tst_sig(NOFORK, DEF_HANDLER, cleanup);
    108 
    109 	tst_require_root();
    110 
    111 	TEST_PAUSE;
    112 
    113 	tst_tmpdir();
    114 
    115 	SAFE_TOUCH(cleanup, TEMP_FILE, 0644, NULL);
    116 
    117 	fs_type = tst_dev_fs_type();
    118 	dev = tst_acquire_device(cleanup);
    119 	if (!dev)
    120 		tst_brkm(TCONF, cleanup, "Failed to acquire test device");
    121 
    122 	tst_mkfs(cleanup, dev, fs_type, NULL, NULL);
    123 
    124 	SAFE_MKDIR(cleanup, MNT_POINT, 0644);
    125 	if (mount(dev, MNT_POINT, fs_type, MS_RDONLY, NULL) < 0) {
    126 		tst_brkm(TBROK | TERRNO, cleanup,
    127 			 "mount device:%s failed", dev);
    128 	}
    129 	mount_flag = 1;
    130 
    131 	ltpuser = SAFE_GETPWNAM(cleanup, "nobody");
    132 }
    133 
    134 static void utime_verify(const struct test_case_t *test)
    135 {
    136 	if (test->setup_func != NULL)
    137 		test->setup_func();
    138 
    139 	TEST(utime(test->pathname, test->times));
    140 
    141 	if (test->cleanup_func != NULL)
    142 		test->cleanup_func();
    143 
    144 	if (TEST_RETURN != -1) {
    145 		tst_resm(TFAIL, "utime succeeded unexpectedly");
    146 		return;
    147 	}
    148 
    149 	if (TEST_ERRNO == test->exp_errno) {
    150 		tst_resm(TPASS | TTERRNO, "utime failed as expected");
    151 	} else {
    152 		tst_resm(TFAIL | TTERRNO,
    153 			 "utime failed unexpectedly; expected: %d - %s",
    154 			 test->exp_errno, strerror(test->exp_errno));
    155 	}
    156 }
    157 
    158 static void setup_nobody(void)
    159 {
    160 	SAFE_SETEUID(cleanup, ltpuser->pw_uid);
    161 }
    162 
    163 static void cleanup_nobody(void)
    164 {
    165 	SAFE_SETEUID(cleanup, 0);
    166 }
    167 
    168 static void cleanup(void)
    169 {
    170 	if (mount_flag && tst_umount(MNT_POINT) < 0)
    171 		tst_resm(TWARN | TERRNO, "umount device:%s failed", dev);
    172 
    173 	if (dev)
    174 		tst_release_device(dev);
    175 
    176 	tst_rmdir();
    177 }
    178