aboutsummaryrefslogtreecommitdiff
path: root/win32
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2012-03-30 16:11:26 +0100
committerRon Yorston <rmy@pobox.com>2012-03-30 16:11:26 +0100
commitf9f2117d5b7057f986850741b85bde5c30590b02 (patch)
tree5a069c443649f216bd1fe4474e80ebc37c72a38d /win32
parent40b68b6ecaf47c6a68bfa4158a61ce41bffa8284 (diff)
downloadbusybox-w32-f9f2117d5b7057f986850741b85bde5c30590b02.tar.gz
busybox-w32-f9f2117d5b7057f986850741b85bde5c30590b02.tar.bz2
busybox-w32-f9f2117d5b7057f986850741b85bde5c30590b02.zip
Update mingw.c from latest git/compat
Diffstat (limited to 'win32')
-rw-r--r--win32/mingw.c115
1 files changed, 64 insertions, 51 deletions
diff --git a/win32/mingw.c b/win32/mingw.c
index df413d18e..219ef96b8 100644
--- a/win32/mingw.c
+++ b/win32/mingw.c
@@ -130,7 +130,7 @@ int mingw_open (const char *filename, int oflags, ...)
130 errno = ENOSYS; 130 errno = ENOSYS;
131 return -1; 131 return -1;
132 } 132 }
133 if (!strcmp(filename, "/dev/null")) 133 if (filename && !strcmp(filename, "/dev/null"))
134 filename = "nul"; 134 filename = "nul";
135 fd = open(filename, oflags, mode); 135 fd = open(filename, oflags, mode);
136 if (fd < 0 && (oflags & O_CREAT) && errno == EACCES) { 136 if (fd < 0 && (oflags & O_CREAT) && errno == EACCES) {
@@ -142,11 +142,11 @@ int mingw_open (const char *filename, int oflags, ...)
142} 142}
143 143
144#undef fopen 144#undef fopen
145FILE *mingw_fopen (const char *filename, const char *mode) 145FILE *mingw_fopen (const char *filename, const char *otype)
146{ 146{
147 if (!strcmp(filename, "/dev/null")) 147 if (filename && !strcmp(filename, "/dev/null"))
148 filename = "nul"; 148 filename = "nul";
149 return fopen(filename, mode); 149 return fopen(filename, otype);
150} 150}
151 151
152#undef dup2 152#undef dup2
@@ -156,12 +156,20 @@ int mingw_dup2 (int fd, int fdto)
156 return ret != -1 ? fdto : -1; 156 return ret != -1 ? fdto : -1;
157} 157}
158 158
159static inline time_t filetime_to_time_t(const FILETIME *ft) 159/*
160 * The unit of FILETIME is 100-nanoseconds since January 1, 1601, UTC.
161 * Returns the 100-nanoseconds ("hekto nanoseconds") since the epoch.
162 */
163static inline long long filetime_to_hnsec(const FILETIME *ft)
160{ 164{
161 long long winTime = ((long long)ft->dwHighDateTime << 32) + ft->dwLowDateTime; 165 long long winTime = ((long long)ft->dwHighDateTime << 32) + ft->dwLowDateTime;
162 winTime -= 116444736000000000LL; /* Windows to Unix Epoch conversion */ 166 /* Windows to Unix Epoch conversion */
163 winTime /= 10000000; /* Nano to seconds resolution */ 167 return winTime - 116444736000000000LL;
164 return (time_t)winTime; 168}
169
170static inline time_t filetime_to_time_t(const FILETIME *ft)
171{
172 return (time_t)(filetime_to_hnsec(ft) / 10000000);
165} 173}
166 174
167static inline int file_attr_to_st_mode (DWORD attr) 175static inline int file_attr_to_st_mode (DWORD attr)
@@ -199,12 +207,16 @@ static inline int get_file_attr(const char *fname, WIN32_FILE_ATTRIBUTE_DATA *fd
199/* We keep the do_lstat code in a separate function to avoid recursion. 207/* We keep the do_lstat code in a separate function to avoid recursion.
200 * When a path ends with a slash, the stat will fail with ENOENT. In 208 * When a path ends with a slash, the stat will fail with ENOENT. In
201 * this case, we strip the trailing slashes and stat again. 209 * this case, we strip the trailing slashes and stat again.
210 *
211 * If follow is true then act like stat() and report on the link
212 * target. Otherwise report on the link itself.
202 */ 213 */
203static int do_lstat(const char *file_name, struct stat *buf) 214static int do_lstat(int follow, const char *file_name, struct stat *buf)
204{ 215{
216 int err;
205 WIN32_FILE_ATTRIBUTE_DATA fdata; 217 WIN32_FILE_ATTRIBUTE_DATA fdata;
206 218
207 if (!(errno = get_file_attr(file_name, &fdata))) { 219 if (!(err = get_file_attr(file_name, &fdata))) {
208 int len = strlen(file_name); 220 int len = strlen(file_name);
209 221
210 buf->st_ino = 0; 222 buf->st_ino = 0;
@@ -220,8 +232,28 @@ static int do_lstat(const char *file_name, struct stat *buf)
220 buf->st_atime = filetime_to_time_t(&(fdata.ftLastAccessTime)); 232 buf->st_atime = filetime_to_time_t(&(fdata.ftLastAccessTime));
221 buf->st_mtime = filetime_to_time_t(&(fdata.ftLastWriteTime)); 233 buf->st_mtime = filetime_to_time_t(&(fdata.ftLastWriteTime));
222 buf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime)); 234 buf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime));
235 if (fdata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
236 WIN32_FIND_DATAA findbuf;
237 HANDLE handle = FindFirstFileA(file_name, &findbuf);
238 if (handle != INVALID_HANDLE_VALUE) {
239 if ((findbuf.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
240 (findbuf.dwReserved0 == IO_REPARSE_TAG_SYMLINK)) {
241 if (follow) {
242 char buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
243 buf->st_size = readlink(file_name, buffer, MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
244 } else {
245 buf->st_mode = S_IFLNK;
246 }
247 buf->st_mode |= S_IREAD;
248 if (!(findbuf.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
249 buf->st_mode |= S_IWRITE;
250 }
251 FindClose(handle);
252 }
253 }
223 return 0; 254 return 0;
224 } 255 }
256 errno = err;
225 return -1; 257 return -1;
226} 258}
227 259
@@ -231,12 +263,12 @@ static int do_lstat(const char *file_name, struct stat *buf)
231 * complete. Note that Git stat()s are redirected to mingw_lstat() 263 * complete. Note that Git stat()s are redirected to mingw_lstat()
232 * too, since Windows doesn't really handle symlinks that well. 264 * too, since Windows doesn't really handle symlinks that well.
233 */ 265 */
234int mingw_lstat(const char *file_name, struct stat *buf) 266static int do_stat_internal(int follow, const char *file_name, struct stat *buf)
235{ 267{
236 int namelen; 268 int namelen;
237 static char alt_name[PATH_MAX]; 269 static char alt_name[PATH_MAX];
238 270
239 if (!do_lstat(file_name, buf)) 271 if (!do_lstat(follow, file_name, buf))
240 return 0; 272 return 0;
241 273
242 /* if file_name ended in a '/', Windows returned ENOENT; 274 /* if file_name ended in a '/', Windows returned ENOENT;
@@ -255,7 +287,16 @@ int mingw_lstat(const char *file_name, struct stat *buf)
255 287
256 memcpy(alt_name, file_name, namelen); 288 memcpy(alt_name, file_name, namelen);
257 alt_name[namelen] = 0; 289 alt_name[namelen] = 0;
258 return do_lstat(alt_name, buf); 290 return do_lstat(follow, alt_name, buf);
291}
292
293int mingw_lstat(const char *file_name, struct stat *buf)
294{
295 return do_stat_internal(0, file_name, buf);
296}
297int mingw_stat(const char *file_name, struct stat *buf)
298{
299 return do_stat_internal(1, file_name, buf);
259} 300}
260 301
261#undef fstat 302#undef fstat
@@ -374,43 +415,15 @@ int mkstemp(char *template)
374 return open(filename, O_RDWR | O_CREAT, 0600); 415 return open(filename, O_RDWR | O_CREAT, 0600);
375} 416}
376 417
377/* 418int gettimeofday(struct timeval *tv, void *tz UNUSED_PARAM)
378 * This is like mktime, but without normalization of tm_wday and tm_yday.
379 */
380static time_t tm_to_time_t(const struct tm *tm)
381{ 419{
382 static const int mdays[] = { 420 FILETIME ft;
383 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 421 long long hnsec;
384 };
385 int year = tm->tm_year - 70;
386 int month = tm->tm_mon;
387 int day = tm->tm_mday;
388 422
389 if (year < 0 || year > 129) /* algo only works for 1970-2099 */ 423 GetSystemTimeAsFileTime(&ft);
390 return -1; 424 hnsec = filetime_to_hnsec(&ft);
391 if (month < 0 || month > 11) /* array bounds */ 425 tv->tv_sec = hnsec / 10000000;
392 return -1; 426 tv->tv_usec = (hnsec % 10000000) / 10;
393 if (month < 2 || (year + 2) % 4)
394 day--;
395 return (year * 365 + (year + 1) / 4 + mdays[month] + day) * 24*60*60UL +
396 tm->tm_hour * 60*60 + tm->tm_min * 60 + tm->tm_sec;
397}
398
399int gettimeofday(struct timeval *tv, void *tz)
400{
401 SYSTEMTIME st;
402 struct tm tm;
403 GetSystemTime(&st);
404 tm.tm_year = st.wYear-1900;
405 tm.tm_mon = st.wMonth-1;
406 tm.tm_mday = st.wDay;
407 tm.tm_hour = st.wHour;
408 tm.tm_min = st.wMinute;
409 tm.tm_sec = st.wSecond;
410 tv->tv_sec = tm_to_time_t(&tm);
411 if (tv->tv_sec < 0)
412 return -1;
413 tv->tv_usec = st.wMilliseconds*1000;
414 return 0; 427 return 0;
415} 428}
416 429
@@ -482,7 +495,7 @@ int mingw_rename(const char *pold, const char *pnew)
482 return -1; 495 return -1;
483} 496}
484 497
485struct passwd *getpwuid(int uid) 498struct passwd *getpwuid(int uid UNUSED_PARAM)
486{ 499{
487 static char user_name[100]; 500 static char user_name[100];
488 static struct passwd p; 501 static struct passwd p;
@@ -622,7 +635,7 @@ sighandler_t mingw_signal(int sig, sighandler_t handler)
622 635
623int link(const char *oldpath, const char *newpath) 636int link(const char *oldpath, const char *newpath)
624{ 637{
625 typedef BOOL WINAPI (*T)(const char*, const char*, LPSECURITY_ATTRIBUTES); 638 typedef BOOL (WINAPI *T)(const char*, const char*, LPSECURITY_ATTRIBUTES);
626 static T create_hard_link = NULL; 639 static T create_hard_link = NULL;
627 if (!create_hard_link) { 640 if (!create_hard_link) {
628 create_hard_link = (T) GetProcAddress( 641 create_hard_link = (T) GetProcAddress(
@@ -702,7 +715,7 @@ int mingw_unlink(const char *pathname)
702 return unlink(pathname); 715 return unlink(pathname);
703} 716}
704 717
705char *strptime(const char *s, const char *format, struct tm *tm) 718char *strptime(const char *s UNUSED_PARAM, const char *format UNUSED_PARAM, struct tm *tm UNUSED_PARAM)
706{ 719{
707 return NULL; 720 return NULL;
708} 721}