diff options
author | Ron Yorston <rmy@pobox.com> | 2012-03-30 16:11:26 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2012-03-30 16:11:26 +0100 |
commit | f9f2117d5b7057f986850741b85bde5c30590b02 (patch) | |
tree | 5a069c443649f216bd1fe4474e80ebc37c72a38d /win32 | |
parent | 40b68b6ecaf47c6a68bfa4158a61ce41bffa8284 (diff) | |
download | busybox-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.c | 115 |
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 |
145 | FILE *mingw_fopen (const char *filename, const char *mode) | 145 | FILE *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 | ||
159 | static 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 | */ | ||
163 | static 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 | |||
170 | static inline time_t filetime_to_time_t(const FILETIME *ft) | ||
171 | { | ||
172 | return (time_t)(filetime_to_hnsec(ft) / 10000000); | ||
165 | } | 173 | } |
166 | 174 | ||
167 | static inline int file_attr_to_st_mode (DWORD attr) | 175 | static 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 | */ |
203 | static int do_lstat(const char *file_name, struct stat *buf) | 214 | static 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 | */ |
234 | int mingw_lstat(const char *file_name, struct stat *buf) | 266 | static 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 | |||
293 | int mingw_lstat(const char *file_name, struct stat *buf) | ||
294 | { | ||
295 | return do_stat_internal(0, file_name, buf); | ||
296 | } | ||
297 | int 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 | /* | 418 | int gettimeofday(struct timeval *tv, void *tz UNUSED_PARAM) |
378 | * This is like mktime, but without normalization of tm_wday and tm_yday. | ||
379 | */ | ||
380 | static 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 | |||
399 | int 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 | ||
485 | struct passwd *getpwuid(int uid) | 498 | struct 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 | ||
623 | int link(const char *oldpath, const char *newpath) | 636 | int 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 | ||
705 | char *strptime(const char *s, const char *format, struct tm *tm) | 718 | char *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 | } |