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