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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 */ 19 20 /* 21 * Test Name: utime03 22 * 23 * Test Description: 24 * Verify that the system call utime() successfully sets the modification 25 * and access times of a file to the current time, under the following 26 * constraints, 27 * - The times argument is null. 28 * - The user ID of the process is not "root". 29 * - The file is not owned by the user ID of the process. 30 * - The user ID of the process has write access to the file. 31 * 32 * Expected Result: 33 * utime succeeds returning zero and sets the access and modificatio 34 * times of the file to the current time. 35 * 36 * Algorithm: 37 * Setup: 38 * Setup signal handling. 39 * Create temporary directory. 40 * Pause for SIGUSR1 if option specified. 41 * 42 * Test: 43 * Loop if the proper options are given. 44 * Execute system call 45 * Check return code, if system call failed (return=-1) 46 * Log the errno and Issue a FAIL message. 47 * Otherwise, 48 * Verify the Functionality of system call 49 * if successful, 50 * Issue Functionality-Pass message. 51 * Otherwise, 52 * Issue Functionality-Fail message. 53 * Cleanup: 54 * Print errno log and/or timing stats if options given 55 * Delete the temporary directory created. 56 * 57 * Usage: <for command-line> 58 * utime03 [-c n] [-e] [-f] [-i n] [-I x] [-p x] [-t] 59 * where, -c n : Run n copies concurrently. 60 * -e : Turn on errno logging. 61 * -f : Turn off functionality Testing. 62 * -i n : Execute test n times. 63 * -I x : Execute test for x seconds. 64 * -P x : Pause for x seconds between iterations. 65 * -t : Turn on syscall timing. 66 * 67 * History 68 * 07/2001 John George 69 * -Ported 70 * 71 * Restrictions: 72 * This test should be run by root only. 73 * nobody and bin must be valid users. 74 * 75 */ 76 77 #include <errno.h> 78 #include <fcntl.h> 79 #include <pwd.h> 80 #include <signal.h> 81 #include <stdio.h> 82 #include <stdlib.h> 83 #include <string.h> 84 #include <unistd.h> 85 #include <utime.h> 86 #include <wait.h> 87 #include <sys/stat.h> 88 #include <sys/types.h> 89 #include <time.h> 90 91 #include "test.h" 92 #include "safe_macros.h" 93 94 #define TEMP_FILE "tmp_file" 95 #define FILE_MODE S_IRWXU | S_IRGRP | S_IWGRP| S_IROTH | S_IWOTH 96 #define LTPUSER1 "nobody" 97 #ifndef ANDROID 98 #define LTPUSER2 "bin" 99 #else 100 // user "bin" does not exist in Android kernel 101 #define LTPUSER2 "everybody" 102 #endif 103 104 char *TCID = "utime03"; 105 int TST_TOTAL = 1; 106 time_t curr_time; /* current time in seconds */ 107 108 struct passwd *ltpuser; /* password struct for ltpusers */ 109 uid_t user_uid; /* user id of ltpuser */ 110 gid_t group_gid; /* group id of ltpuser */ 111 int status; 112 113 void setup(); /* Main setup function of test */ 114 void cleanup(); /* cleanup function for the test */ 115 116 int main(int ac, char **av) 117 { 118 struct stat stat_buf; /* struct buffer to hold file info. */ 119 int lc; 120 long type; 121 time_t modf_time, access_time; 122 time_t pres_time; /* file modification/access/present time */ 123 pid_t pid; 124 125 tst_parse_opts(ac, av, NULL, NULL); 126 127 setup(); 128 129 switch ((type = tst_fs_type(cleanup, "."))) { 130 case TST_NFS_MAGIC: 131 if (tst_kvercmp(2, 6, 18) < 0) 132 tst_brkm(TCONF, cleanup, "Cannot do utime on a file" 133 " on %s filesystem before 2.6.18", 134 tst_fs_type_name(type)); 135 break; 136 case TST_V9FS_MAGIC: 137 tst_brkm(TCONF, cleanup, 138 "Cannot do utime on a file on %s filesystem", 139 tst_fs_type_name(type)); 140 break; 141 } 142 143 pid = FORK_OR_VFORK(); 144 145 if (pid == -1) { 146 tst_brkm(TBROK, cleanup, "fork() failed"); 147 } else if (pid == 0) { 148 if ((ltpuser = getpwnam(LTPUSER1)) == NULL) { 149 tst_brkm(TBROK, cleanup, "%s not found in /etc/passwd", 150 LTPUSER1); 151 } 152 153 /* get uid/gid of user accordingly */ 154 user_uid = ltpuser->pw_uid; 155 156 seteuid(user_uid); 157 158 for (lc = 0; TEST_LOOPING(lc); lc++) { 159 160 tst_count = 0; 161 162 /* 163 * Invoke utime(2) to set TEMP_FILE access and 164 * modification times to the current time. 165 */ 166 TEST(utime(TEMP_FILE, NULL)); 167 168 if (TEST_RETURN == -1) { 169 tst_resm(TFAIL|TTERRNO, 170 "utime(%s) failed", TEMP_FILE); 171 } else { 172 /* 173 * Sleep for a second so that mod time 174 * and access times will be different 175 * from the current time. 176 */ 177 sleep(2); 178 179 /* 180 * Get the current time now, after 181 * calling utime(2) 182 */ 183 pres_time = time(NULL); 184 185 /* 186 * Get the modification and access 187 * times of temporary file using 188 * stat(2). 189 */ 190 SAFE_STAT(cleanup, TEMP_FILE, &stat_buf); 191 modf_time = stat_buf.st_mtime; 192 access_time = stat_buf.st_atime; 193 194 /* Now do the actual verification */ 195 if (modf_time <= curr_time || 196 modf_time >= pres_time || 197 access_time <= curr_time || 198 access_time >= pres_time) { 199 tst_resm(TFAIL, "%s access and " 200 "modification times " 201 "not set", TEMP_FILE); 202 } else { 203 tst_resm(TPASS, "Functionality " 204 "of utime(%s, NULL) " 205 "successful", 206 TEMP_FILE); 207 } 208 } 209 tst_count++; /* incr. TEST_LOOP counter */ 210 } 211 } else { 212 waitpid(pid, &status, 0); 213 _exit(0); /* 214 * Exit here and let the child clean up. 215 * This allows the errno information set 216 * by the TEST_ERROR_LOG macro and the 217 * PASS/FAIL status to be preserved for 218 * use during cleanup. 219 */ 220 } 221 222 cleanup(); 223 tst_exit(); 224 225 } 226 227 /* 228 * void 229 * setup() - performs all ONE TIME setup for this test. 230 * Create a temporary directory and change directory to it. 231 * Create a test file under temporary directory and close it 232 * Change the ownership of testfile to that of "bin" user. 233 * Record the current time. 234 */ 235 void setup(void) 236 { 237 int fildes; /* file handle for temp file */ 238 char *tmpd = NULL; 239 240 tst_require_root(); 241 242 tst_sig(FORK, DEF_HANDLER, cleanup); 243 244 /* Pause if that option was specified 245 * TEST_PAUSE contains the code to fork the test with the -i option. 246 * You want to make sure you do this before you create your temporary 247 * directory. 248 */ 249 TEST_PAUSE; 250 251 tst_tmpdir(); 252 253 /* get the name of the temporary directory */ 254 tmpd = SAFE_GETCWD(NULL, tmpd, 0); 255 256 /* Creat a temporary file under above directory */ 257 fildes = SAFE_CREAT(cleanup, TEMP_FILE, FILE_MODE); 258 259 /* Close the temporary file created */ 260 SAFE_CLOSE(cleanup, fildes); 261 262 /* 263 * Make sure that specified Mode permissions set as 264 * umask value may be different. 265 */ 266 SAFE_CHMOD(cleanup, TEMP_FILE, FILE_MODE); 267 SAFE_CHMOD(cleanup, tmpd, 0711); 268 269 ltpuser = SAFE_GETPWNAM(cleanup, LTPUSER2); 270 271 /* get uid/gid of user accordingly */ 272 user_uid = ltpuser->pw_uid; 273 group_gid = ltpuser->pw_gid; 274 275 /* 276 * Change the ownership of test directory/file specified by 277 * pathname to that of user_uid and group_gid. 278 */ 279 SAFE_CHOWN(cleanup, TEMP_FILE, user_uid, group_gid); 280 281 /* Get the current time */ 282 curr_time = time(NULL); 283 284 /* 285 * Sleep for a second so that mod time and access times will be 286 * different from the current time 287 */ 288 sleep(2); /* sleep(1) on IA64 sometimes sleeps < 1 sec!! */ 289 290 } 291 292 /* 293 * void 294 * cleanup() - performs all ONE TIME cleanup for this test at 295 * completion or premature exit. 296 * Remove the test directory and testfile created in the setup. 297 */ 298 void cleanup(void) 299 { 300 seteuid(0); 301 302 tst_rmdir(); 303 304 } 305