1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 28 #include <sys/types.h> 29 #include <sys/stat.h> 30 #include <utime.h> 31 #include <stdio.h> 32 #include <stdlib.h> 33 #include <unistd.h> 34 #include <string.h> 35 #include <errno.h> 36 #include <fcntl.h> 37 38 #define ST_ATIME 0 39 #define ST_CTIME 1 40 #define ST_MTIME 2 41 42 #define ALL_MODE (mode_t)(S_IRWXU|S_IRWXG|S_IRWXO) 43 44 typedef struct timetest { 45 int type; 46 char *name; 47 int (*func)(const char *pfile); 48 } timetest_t; 49 50 #ifdef __stc_assertion__ 51 52 /* 53 * ID: ctime_001_pos 54 * 55 * DESCRIPTION: 56 * Verify time will be changed correctly according to relevant operating. 57 * 58 * STRATEGY: 59 * 1. Define time test array. 60 * 2. loop each item in this array. 61 * 3. Verify the time will be changed after relevant operating. 62 * 63 * TESTABILITY: explicit 64 * 65 * TEST_AUTOMATION_LEVEL: automated 66 * 67 * CODING_STATUS: COMPLETED (2007-01-30) 68 * 69 */ 70 71 #endif /* __stc_assertion__ */ 72 73 /* 74 * Get file specific time information. 75 */ 76 int get_file_time(char *pfile, int what, time_t *ptr); 77 78 int do_read(const char *pfile); 79 int do_write(const char *pfile); 80 int do_link(const char *pfile); 81 int do_creat(const char *pfile); 82 int do_utime(const char *pfile); 83 int do_chmod(const char *pfile); 84 int do_chown(const char *pfile); 85 86 static char tfile[BUFSIZ] = { 0 }; 87 static char msg[BUFSIZ] = { 0 }; 88 89 static timetest_t timetest_table[] = { 90 { ST_ATIME, "st_atime", do_read }, 91 { ST_ATIME, "st_atime", do_utime }, 92 { ST_MTIME, "st_mtime", do_creat }, 93 { ST_MTIME, "st_mtime", do_write }, 94 { ST_MTIME, "st_mtime", do_utime }, 95 { ST_CTIME, "st_ctime", do_creat }, 96 { ST_CTIME, "st_ctime", do_write }, 97 { ST_CTIME, "st_ctime", do_chmod }, 98 { ST_CTIME, "st_ctime", do_chown }, 99 { ST_CTIME, "st_ctime", do_link }, 100 { ST_CTIME, "st_ctime", do_utime }, 101 }; 102 103 #define NCOMMAND (sizeof (timetest_table) / sizeof (timetest_table[0])) 104 105 int 106 main(int argc, char *argv[]) 107 { 108 int i, ret, fd; 109 const char *env_names[2] = {"TESTDIR", "TESTFILE"}; 110 char *env_vals[2]; 111 112 /* 113 * Get envirnment variable value 114 */ 115 for (i = 0; i < sizeof (env_names) / sizeof (char *); i++) { 116 if ((env_vals[i] = getenv(env_names[i])) == NULL) { 117 fprintf(stderr, "getenv(%s) returned NULL\n", 118 env_names[i]); 119 exit(1); 120 } 121 } 122 (void) snprintf(tfile, sizeof (tfile), "%s/%s", env_vals[0], 123 env_vals[1]); 124 125 /* 126 * If the test file is existing, remove it firstly 127 */ 128 if (access(tfile, F_OK) == 0) { 129 unlink(tfile); 130 } 131 fd = open(tfile, O_WRONLY | O_CREAT | O_TRUNC, ALL_MODE); 132 if (fd < 0) { 133 perror("open"); 134 exit(1); 135 } 136 (void) close(fd); 137 138 for (i = 0; i < NCOMMAND; i++) { 139 time_t t1, t2; 140 141 /* 142 * Get original time before operating. 143 */ 144 ret = get_file_time(tfile, timetest_table[i].type, &t1); 145 if (ret != 0) { 146 fprintf(stderr, 147 "ERROR: get_file_time(%s, %d, &t1) returned %d\n", 148 tfile, timetest_table[i].type, ret); 149 exit(1); 150 } 151 152 /* 153 * Sleep 2 seconds to be sure that the timeofday has changed, 154 * then invoke command on given file 155 */ 156 sleep(2); 157 timetest_table[i].func(tfile); 158 159 /* 160 * Get time after operating. 161 */ 162 ret = get_file_time(tfile, timetest_table[i].type, &t2); 163 if (ret != 0) { 164 fprintf(stderr, "get_file_time(%s, %d, &t2)\n", 165 tfile, timetest_table[i].type); 166 exit(1); 167 } 168 169 if (t1 == t2) { 170 fprintf(stderr, "%s: t1(%ld) == t2(%ld)\n", 171 timetest_table[i].name, (long)t1, (long)t2); 172 exit(1); 173 } 174 } 175 176 (void) unlink(tfile); 177 178 return (0); 179 } 180 181 int 182 get_file_time(char *pfile, int what, time_t *ptr) 183 { 184 struct stat stat_buf; 185 186 if (pfile == NULL || ptr == NULL) { 187 return (-1); 188 } 189 190 if (stat(pfile, &stat_buf) == -1) { 191 return (-1); 192 } 193 194 switch (what) { 195 case ST_ATIME: 196 *ptr = stat_buf.st_atime; 197 return (0); 198 case ST_CTIME: 199 *ptr = stat_buf.st_ctime; 200 return (0); 201 case ST_MTIME: 202 *ptr = stat_buf.st_mtime; 203 return (0); 204 default: 205 return (-1); 206 } 207 } 208 209 int 210 do_read(const char *pfile) 211 { 212 int fd, ret = 0; 213 char buf[BUFSIZ] = { 0 }; 214 215 if (pfile == NULL) { 216 return (-1); 217 } 218 219 if ((fd = open(pfile, O_RDONLY, ALL_MODE)) == -1) { 220 return (-1); 221 } 222 if (read(fd, buf, sizeof (buf)) == -1) { 223 ret = errno; 224 } 225 (void) close(fd); 226 227 if (ret != 0) { 228 fprintf(stderr, "read(%d, buf, %zu)\n", fd, sizeof (buf)); 229 exit(1); 230 } 231 232 return (ret); 233 } 234 235 int 236 do_write(const char *pfile) 237 { 238 int fd, ret = 0; 239 char buf[BUFSIZ] = "call function do_write()"; 240 241 if (pfile == NULL) { 242 return (-1); 243 } 244 245 if ((fd = open(pfile, O_WRONLY, ALL_MODE)) == -1) { 246 return (-1); 247 } 248 if (write(fd, buf, strlen(buf)) == -1) { 249 ret = errno; 250 } 251 (void) close(fd); 252 253 if (ret != 0) { 254 fprintf(stderr, "write(%d, buf, %zu)\n", fd, strlen(buf)); 255 exit(1); 256 } 257 258 return (ret); 259 } 260 261 int 262 do_link(const char *pfile) 263 { 264 int ret = 0; 265 char link_file[BUFSIZ] = { 0 }; 266 char *ptr = link_file; 267 268 if (pfile == NULL) { 269 return (-1); 270 } 271 272 /* 273 * Figure out source file directory name, and create 274 * the link file in the same directory. 275 */ 276 snprintf(link_file, sizeof (link_file), "%s", pfile); 277 ptr = strrchr(link_file, '/'); 278 snprintf(ptr + 1, 279 sizeof (link_file) - (ptr + 1 - link_file), "link_file"); 280 281 if (link(pfile, link_file) == -1) { 282 ret = errno; 283 } 284 if (ret != 0) { 285 fprintf(stderr, "link(%s, %s)\n", pfile, link_file); 286 exit(1); 287 } 288 289 unlink(link_file); 290 return (ret); 291 } 292 293 int 294 do_creat(const char *pfile) 295 { 296 int fd, ret = 0; 297 298 if (pfile == NULL) { 299 return (-1); 300 } 301 302 if ((fd = creat(pfile, ALL_MODE)) == -1) { 303 ret = errno; 304 } 305 if (fd != -1) { 306 (void) close(fd); 307 } 308 309 if (ret != 0) { 310 fprintf(stderr, "creat(%s, ALL_MODE)\n", pfile); 311 exit(1); 312 } 313 314 return (ret); 315 } 316 317 int 318 do_utime(const char *pfile) 319 { 320 int ret = 0; 321 322 if (pfile == NULL) { 323 return (-1); 324 } 325 326 /* 327 * Times of the file are set to the current time 328 */ 329 if (utime(pfile, NULL) == -1) { 330 ret = errno; 331 } 332 if (ret != 0) { 333 fprintf(stderr, "utime(%s, NULL)\n", pfile); 334 exit(1); 335 } 336 337 return (ret); 338 } 339 340 int 341 do_chmod(const char *pfile) 342 { 343 int ret = 0; 344 345 if (pfile == NULL) { 346 return (-1); 347 } 348 349 if (chmod(pfile, ALL_MODE) == -1) { 350 ret = errno; 351 } 352 if (ret != 0) { 353 fprintf(stderr, "chmod(%s, ALL_MODE)\n", pfile); 354 exit(1); 355 } 356 357 return (ret); 358 } 359 360 int 361 do_chown(const char *pfile) 362 { 363 int ret = 0; 364 365 if (pfile == NULL) { 366 return (-1); 367 } 368 369 if (chown(pfile, getuid(), getgid()) == -1) { 370 ret = errno; 371 } 372 if (ret != 0) { 373 fprintf(stderr, "chown(%s, %d, %d)\n", pfile, (int)getuid(), 374 (int)getgid()); 375 exit(1); 376 } 377 378 return (ret); 379 } 380