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