1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1985-2007 AT&T Knowledge Ventures * 5 * and is licensed under the * 6 * Common Public License, Version 1.0 * 7 * by AT&T Knowledge Ventures * 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 #include <ast.h> 37 #include <ls.h> 38 #include <tv.h> 39 #include <times.h> 40 #include <error.h> 41 42 #include "FEATURE/tvlib" 43 44 #if _hdr_utime && _lib_utime 45 #include <utime.h> 46 #endif 47 48 #if defined(__STDPP__directive) && defined(__STDPP__hide) 49 __STDPP__directive pragma pp:nohide utime 50 #else 51 #undef utime 52 #endif 53 54 #if _lib_utime 55 #if _hdr_utime 56 extern int utime(const char*, const struct utimbuf*); 57 #else 58 extern int utime(const char*, const time_t*); 59 #endif 60 #endif 61 62 #define NS(n) (((uint32_t)(n))<1000000000L?(n):0) 63 64 /* 65 * touch path <atime,mtime,ctime> 66 * Tv_t==0 uses current time 67 * Tv_t==TV_TOUCH_RETAIN retains path value if it exists, current time otherwise 68 * otherwise it is exact time 69 * file created if it doesn't exist and (flags&1) 70 * cv most likely ignored on most implementations 71 */ 72 73 int 74 tvtouch(const char* path, register const Tv_t* av, register const Tv_t* mv, const Tv_t* cv, int flags) 75 { 76 struct stat st; 77 Tv_t now; 78 int fd; 79 int mode; 80 int oerrno; 81 #if _lib_utimets 82 struct timespec am[2]; 83 #else 84 #if _lib_utimes 85 struct timeval am[2]; 86 #else 87 #if _hdr_utime 88 struct utimbuf am; 89 #else 90 time_t am[2]; 91 #endif 92 #endif 93 #endif 94 95 oerrno = errno; 96 if ((av == TV_TOUCH_RETAIN || mv == TV_TOUCH_RETAIN) && stat(path, &st)) 97 { 98 errno = oerrno; 99 if (av == TV_TOUCH_RETAIN) 100 av = 0; 101 if (mv == TV_TOUCH_RETAIN) 102 mv = 0; 103 } 104 if (!av || !mv) 105 { 106 tvgettime(&now); 107 if (!av) 108 av = (const Tv_t*)&now; 109 if (!mv) 110 mv = (const Tv_t*)&now; 111 } 112 #if _lib_utimets 113 if (av == TV_TOUCH_RETAIN) 114 { 115 am[0].tv_sec = st.st_atime; 116 am[0].tv_nsec = ST_ATIME_NSEC_GET(&st); 117 } 118 else 119 { 120 am[0].tv_sec = av->tv_sec; 121 am[0].tv_nsec = NS(av->tv_nsec); 122 } 123 if (mv == TV_TOUCH_RETAIN) 124 { 125 am[1].tv_sec = st.st_mtime; 126 am[1].tv_nsec = ST_MTIME_NSEC_GET(&st); 127 } 128 else 129 { 130 am[1].tv_sec = mv->tv_sec; 131 am[1].tv_nsec = NS(mv->tv_nsec); 132 } 133 if (!utimets(path, am)) 134 return 0; 135 if (errno != ENOENT && av == (const Tv_t*)&now && mv == (const Tv_t*)&now && !utimets(path, NiL)) 136 { 137 errno = oerrno; 138 return 0; 139 } 140 #else 141 #if _lib_utimes 142 if (av == TV_TOUCH_RETAIN) 143 { 144 am[0].tv_sec = st.st_atime; 145 am[0].tv_usec = ST_ATIME_NSEC_GET(&st) / 1000; 146 } 147 else 148 { 149 am[0].tv_sec = av->tv_sec; 150 am[0].tv_usec = NS(av->tv_nsec) / 1000; 151 } 152 if (mv == TV_TOUCH_RETAIN) 153 { 154 am[1].tv_sec = st.st_mtime; 155 am[1].tv_usec = ST_MTIME_NSEC_GET(&st) / 1000; 156 } 157 else 158 { 159 am[1].tv_sec = mv->tv_sec; 160 am[1].tv_usec = NS(mv->tv_nsec) / 1000; 161 } 162 if (!utimes(path, am)) 163 return 0; 164 if (errno != ENOENT && av == (const Tv_t*)&now && mv == (const Tv_t*)&now && !utimes(path, NiL)) 165 { 166 errno = oerrno; 167 return 0; 168 } 169 #else 170 #if _lib_utime 171 am.actime = (av == TV_TOUCH_RETAIN) ? st.st_atime : av->tv_sec; 172 am.modtime = (mv == TV_TOUCH_RETAIN) ? st.st_mtime : mv->tv_sec; 173 if (!utime(path, &am)) 174 return 0; 175 #if _lib_utime_now 176 if (errno != ENOENT && av == (const Tv_t*)&now && mv == (const Tv_t*)&now && !utime(path, NiL)) 177 { 178 errno = oerrno; 179 return 0; 180 } 181 #endif 182 #endif 183 #endif 184 if (!access(path, F_OK)) 185 { 186 if (av != (const Tv_t*)&now || mv != (const Tv_t*)&now) 187 { 188 errno = EINVAL; 189 return -1; 190 } 191 if ((fd = open(path, O_RDWR)) >= 0) 192 { 193 char c; 194 195 if (read(fd, &c, 1) == 1) 196 { 197 if (c = (lseek(fd, 0L, 0) == 0L && write(fd, &c, 1) == 1)) 198 errno = oerrno; 199 close(fd); 200 if (c) 201 return 0; 202 } 203 close(fd); 204 } 205 } 206 #endif 207 if (errno != ENOENT || !(flags & 1)) 208 return -1; 209 umask(mode = umask(0)); 210 mode = (~mode) & (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH); 211 if ((fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, mode)) < 0) 212 return -1; 213 close(fd); 214 errno = oerrno; 215 if (av == (const Tv_t*)&now && mv == (const Tv_t*)&now) 216 return 0; 217 #if _lib_utimets 218 return utimets(path, am); 219 #else 220 #if _lib_utimes 221 return utimes(path, am); 222 #else 223 #if _lib_utime 224 return utime(path, &am); 225 #else 226 errno = EINVAL; 227 return -1; 228 #endif 229 #endif 230 #endif 231 232 } 233