1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1985-2009 AT&T Intellectual Property * 5 * and is licensed under the * 6 * Common Public License, Version 1.0 * 7 * by AT&T Intellectual Property * 8 * * 9 * A copy of the License is available at * 10 * http://www.opensource.org/licenses/cpl1.0.txt * 11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 12 * * 13 * Information and Software Systems Research * 14 * AT&T Research * 15 * Florham Park NJ * 16 * * 17 * Glenn Fowler <gsf@research.att.com> * 18 * David Korn <dgk@research.att.com> * 19 * Phong Vo <kpv@research.att.com> * 20 * * 21 ***********************************************************************/ 22 #pragma prototyped 23 /* 24 * Glenn Fowler 25 * AT&T Research 26 * 27 * Tv_t conversion support 28 */ 29 30 #if defined(__STDPP__directive) && defined(__STDPP__hide) 31 __STDPP__directive pragma pp:hide utime 32 #else 33 #define utime ______utime 34 #endif 35 36 #ifndef _ATFILE_SOURCE 37 #define _ATFILE_SOURCE 1 38 #endif 39 40 #include <ast.h> 41 #include <ls.h> 42 #include <tv.h> 43 #include <times.h> 44 #include <error.h> 45 46 #include "FEATURE/tvlib" 47 48 #if _hdr_utime && _lib_utime 49 #include <utime.h> 50 #endif 51 52 #if defined(__STDPP__directive) && defined(__STDPP__hide) 53 __STDPP__directive pragma pp:nohide utime 54 #else 55 #undef utime 56 #endif 57 58 #if _lib_utime 59 #if _hdr_utime 60 extern int utime(const char*, const struct utimbuf*); 61 #else 62 extern int utime(const char*, const time_t*); 63 #endif 64 #endif 65 66 #define NS(n) (((uint32_t)(n))<1000000000L?(n):0) 67 68 /* 69 * touch path <atime,mtime,ctime> 70 * Tv_t==0 uses current time 71 * Tv_t==TV_TOUCH_RETAIN retains path value if it exists, current time otherwise 72 * otherwise it is exact time 73 * file created if it doesn't exist and (flags&1) 74 * symlink not followed if (flags&2) 75 * cv most likely ignored on most implementations 76 * 77 * NOTE: when *at() calls are integrated we need macros for the flags! 78 */ 79 80 int 81 tvtouch(const char* path, register const Tv_t* av, register const Tv_t* mv, const Tv_t* cv, int flags) 82 { 83 int fd; 84 int mode; 85 int oerrno; 86 struct stat st; 87 88 #if _lib_utimensat 89 struct timespec ts[2]; 90 91 errno = oerrno; 92 if (!av) 93 { 94 ts[0].tv_sec = 0; 95 ts[0].tv_nsec = UTIME_NOW; 96 } 97 else if (av == TV_TOUCH_RETAIN) 98 { 99 ts[0].tv_sec = 0; 100 ts[0].tv_nsec = UTIME_OMIT; 101 } 102 else 103 { 104 ts[0].tv_sec = av->tv_sec; 105 ts[0].tv_nsec = NS(av->tv_nsec); 106 } 107 if (!mv) 108 { 109 ts[1].tv_sec = 0; 110 ts[1].tv_nsec = UTIME_NOW; 111 } 112 else if (mv == TV_TOUCH_RETAIN) 113 { 114 ts[1].tv_sec = 0; 115 ts[1].tv_nsec = UTIME_OMIT; 116 } 117 else 118 { 119 ts[1].tv_sec = mv->tv_sec; 120 ts[1].tv_nsec = NS(mv->tv_nsec); 121 } 122 if (!cv && av == TV_TOUCH_RETAIN && mv == TV_TOUCH_RETAIN && !stat(path, &st) && !chmod(path, st.st_mode & S_IPERM)) 123 return 0; 124 if (!utimensat(AT_FDCWD, path, ts[0].tv_nsec == UTIME_NOW && ts[1].tv_nsec == UTIME_NOW ? (struct timespec*)0 : ts, (flags & 2) ? AT_SYMLINK_NOFOLLOW : 0)) 125 return 0; 126 if (errno != ENOENT || !(flags & 1)) 127 return -1; 128 umask(mode = umask(0)); 129 mode = (~mode) & (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH); 130 if ((fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, mode)) < 0) 131 return -1; 132 close(fd); 133 errno = oerrno; 134 if ((ts[0].tv_nsec != UTIME_NOW || ts[1].tv_nsec != UTIME_NOW) && utimensat(AT_FDCWD, path, ts, (flags & 2) ? AT_SYMLINK_NOFOLLOW : 0)) 135 return -1; 136 return 0; 137 #else 138 Tv_t now; 139 #if _lib_utimets 140 struct timespec am[2]; 141 #else 142 #if _lib_utimes 143 struct timeval am[2]; 144 #else 145 #if _hdr_utime 146 struct utimbuf am; 147 #else 148 time_t am[2]; 149 #endif 150 #endif 151 #endif 152 153 oerrno = errno; 154 if ((av == TV_TOUCH_RETAIN || mv == TV_TOUCH_RETAIN) && stat(path, &st)) 155 { 156 errno = oerrno; 157 if (av == TV_TOUCH_RETAIN) 158 av = 0; 159 if (mv == TV_TOUCH_RETAIN) 160 mv = 0; 161 } 162 if (!av || !mv) 163 { 164 tvgettime(&now); 165 if (!av) 166 av = (const Tv_t*)&now; 167 if (!mv) 168 mv = (const Tv_t*)&now; 169 } 170 #if _lib_utimets 171 if (av == TV_TOUCH_RETAIN) 172 { 173 am[0].tv_sec = st.st_atime; 174 am[0].tv_nsec = ST_ATIME_NSEC_GET(&st); 175 } 176 else 177 { 178 am[0].tv_sec = av->tv_sec; 179 am[0].tv_nsec = NS(av->tv_nsec); 180 } 181 if (mv == TV_TOUCH_RETAIN) 182 { 183 am[1].tv_sec = st.st_mtime; 184 am[1].tv_nsec = ST_MTIME_NSEC_GET(&st); 185 } 186 else 187 { 188 am[1].tv_sec = mv->tv_sec; 189 am[1].tv_nsec = NS(mv->tv_nsec); 190 } 191 if (!utimets(path, am)) 192 return 0; 193 if (errno != ENOENT && av == (const Tv_t*)&now && mv == (const Tv_t*)&now && !utimets(path, NiL)) 194 { 195 errno = oerrno; 196 return 0; 197 } 198 #else 199 #if _lib_utimes 200 if (av == TV_TOUCH_RETAIN) 201 { 202 am[0].tv_sec = st.st_atime; 203 am[0].tv_usec = ST_ATIME_NSEC_GET(&st) / 1000; 204 } 205 else 206 { 207 am[0].tv_sec = av->tv_sec; 208 am[0].tv_usec = NS(av->tv_nsec) / 1000; 209 } 210 if (mv == TV_TOUCH_RETAIN) 211 { 212 am[1].tv_sec = st.st_mtime; 213 am[1].tv_usec = ST_MTIME_NSEC_GET(&st) / 1000; 214 } 215 else 216 { 217 am[1].tv_sec = mv->tv_sec; 218 am[1].tv_usec = NS(mv->tv_nsec) / 1000; 219 } 220 if (!utimes(path, am)) 221 return 0; 222 if (errno != ENOENT && av == (const Tv_t*)&now && mv == (const Tv_t*)&now && !utimes(path, NiL)) 223 { 224 errno = oerrno; 225 return 0; 226 } 227 #else 228 #if _lib_utime 229 am.actime = (av == TV_TOUCH_RETAIN) ? st.st_atime : av->tv_sec; 230 am.modtime = (mv == TV_TOUCH_RETAIN) ? st.st_mtime : mv->tv_sec; 231 if (!utime(path, &am)) 232 return 0; 233 #if _lib_utime_now 234 if (errno != ENOENT && av == (const Tv_t*)&now && mv == (const Tv_t*)&now && !utime(path, NiL)) 235 { 236 errno = oerrno; 237 return 0; 238 } 239 #endif 240 #endif 241 #endif 242 if (!access(path, F_OK)) 243 { 244 if (av != (const Tv_t*)&now || mv != (const Tv_t*)&now) 245 { 246 errno = EINVAL; 247 return -1; 248 } 249 if ((fd = open(path, O_RDWR)) >= 0) 250 { 251 char c; 252 253 if (read(fd, &c, 1) == 1) 254 { 255 if (c = (lseek(fd, 0L, 0) == 0L && write(fd, &c, 1) == 1)) 256 errno = oerrno; 257 close(fd); 258 if (c) 259 return 0; 260 } 261 close(fd); 262 } 263 } 264 #endif 265 if (errno != ENOENT || !(flags & 1)) 266 return -1; 267 umask(mode = umask(0)); 268 mode = (~mode) & (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH); 269 if ((fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, mode)) < 0) 270 return -1; 271 close(fd); 272 errno = oerrno; 273 if (av == (const Tv_t*)&now && mv == (const Tv_t*)&now) 274 return 0; 275 #if _lib_utimets 276 return utimets(path, am); 277 #else 278 #if _lib_utimes 279 return utimes(path, am); 280 #else 281 #if _lib_utime 282 return utime(path, &am); 283 #else 284 errno = EINVAL; 285 return -1; 286 #endif 287 #endif 288 #endif 289 #endif 290 291 } 292