From f9f2117d5b7057f986850741b85bde5c30590b02 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Fri, 30 Mar 2012 16:11:26 +0100 Subject: Update mingw.c from latest git/compat --- Config.in | 1 + configs/mingw32_defconfig | 6 +- coreutils/cp.c | 5 -- coreutils/libcoreutils/cp_mv_stat.c | 5 -- include/mingw.h | 13 ++-- libbb/copy_file.c | 5 -- libbb/recursive_action.c | 5 -- win32/mingw.c | 115 ++++++++++++++++++++---------------- 8 files changed, 75 insertions(+), 80 deletions(-) diff --git a/Config.in b/Config.in index cd51e2b45..1ed1bc0d4 100644 --- a/Config.in +++ b/Config.in @@ -20,6 +20,7 @@ config PLATFORM_POSIX config PLATFORM_MINGW32 bool "MS Windows (MinGW port)" + select LFS endchoice diff --git a/configs/mingw32_defconfig b/configs/mingw32_defconfig index 444b31145..cabb0b4f0 100644 --- a/configs/mingw32_defconfig +++ b/configs/mingw32_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit # Busybox version: 1.20.0.git -# Fri Mar 23 12:07:27 2012 +# Tue Mar 27 11:53:57 2012 # CONFIG_HAVE_DOT_CONFIG=y # CONFIG_PLATFORM_POSIX is not set @@ -63,7 +63,7 @@ CONFIG_BUSYBOX_EXEC_PATH="" # CONFIG_BUILD_LIBBUSYBOX is not set # CONFIG_FEATURE_INDIVIDUAL is not set # CONFIG_FEATURE_SHARED_BUSYBOX is not set -# CONFIG_LFS is not set +CONFIG_LFS=y CONFIG_CROSS_COMPILER_PREFIX="i686-pc-mingw32-" CONFIG_SYSROOT="" CONFIG_EXTRA_CFLAGS="-g -O0" @@ -187,7 +187,7 @@ CONFIG_FEATURE_DATE_COMPAT=y CONFIG_TEST=y CONFIG_FEATURE_TEST_64=y CONFIG_TOUCH=y -# CONFIG_FEATURE_TOUCH_SUSV3 is not set +CONFIG_FEATURE_TOUCH_SUSV3=y CONFIG_TR=y CONFIG_FEATURE_TR_CLASSES=y CONFIG_FEATURE_TR_EQUIV=y diff --git a/coreutils/cp.c b/coreutils/cp.c index 45efaba72..de2e512be 100644 --- a/coreutils/cp.c +++ b/coreutils/cp.c @@ -148,13 +148,8 @@ int cp_main(int argc, char **argv) last = argv[argc - 1]; /* If there are only two arguments and... */ if (argc == 2) { -#if ENABLE_PLATFORM_MINGW32 - /* stat can't be aliased, and MinGW uses lstat anyway */ - s_flags = cp_mv_stat2(*argv, &source_stat, lstat); -#else s_flags = cp_mv_stat2(*argv, &source_stat, (flags & FILEUTILS_DEREFERENCE) ? stat : lstat); -#endif if (s_flags < 0) return EXIT_FAILURE; d_flags = cp_mv_stat(last, &dest_stat); diff --git a/coreutils/libcoreutils/cp_mv_stat.c b/coreutils/libcoreutils/cp_mv_stat.c index 1af2ebb71..5ba07ecc3 100644 --- a/coreutils/libcoreutils/cp_mv_stat.c +++ b/coreutils/libcoreutils/cp_mv_stat.c @@ -46,10 +46,5 @@ int FAST_FUNC cp_mv_stat2(const char *fn, struct stat *fn_stat, stat_func sf) int FAST_FUNC cp_mv_stat(const char *fn, struct stat *fn_stat) { -#if ENABLE_PLATFORM_MINGW32 - /* stat can't be aliased, and MinGW uses lstat anyway */ - return cp_mv_stat2(fn, fn_stat, lstat); -#else return cp_mv_stat2(fn, fn_stat, stat); -#endif } diff --git a/include/mingw.h b/include/mingw.h index 138275588..fd0b09b15 100644 --- a/include/mingw.h +++ b/include/mingw.h @@ -234,19 +234,20 @@ typedef int nlink_t; NOIMPL(fchmod,int fildes UNUSED_PARAM, mode_t mode UNUSED_PARAM); NOIMPL(fchown,int fd UNUSED_PARAM, uid_t uid UNUSED_PARAM, gid_t gid UNUSED_PARAM); int mingw_mkdir(const char *path, int mode); +#define mkdir mingw_mkdir -/* Use mingw_lstat() instead of lstat()/stat() and +/* Use mingw_lstat()/mingw_stat() instead of lstat()/stat() and * mingw_fstat() instead of fstat() on Windows. */ +#define off_t off64_t +#define lseek _lseeki64 +#define stat _stati64 int mingw_lstat(const char *file_name, struct stat *buf); +int mingw_stat(const char *file_name, struct stat *buf); int mingw_fstat(int fd, struct stat *buf); - -#define mkdir mingw_mkdir -#define stat(x,y) mingw_lstat(x,y) -#define lseek _lseeki64 #define fstat mingw_fstat #define lstat mingw_lstat -#define _stati64 mingw_lstat +#define _stati64(x,y) mingw_stat(x,y) /* * sys/sysmacros.h diff --git a/libbb/copy_file.c b/libbb/copy_file.c index 48aaf481d..be65c4b47 100644 --- a/libbb/copy_file.c +++ b/libbb/copy_file.c @@ -85,12 +85,7 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags) /* Inverse of cp -d ("cp without -d") */ #define FLAGS_DEREF (flags & (FILEUTILS_DEREFERENCE + FILEUTILS_DEREFERENCE_L0)) -#if ENABLE_PLATFORM_MINGW32 - /* stat can't be aliased, and MinGW uses lstat anyway */ - if (lstat(source, &source_stat) < 0) { -#else if ((FLAGS_DEREF ? stat : lstat)(source, &source_stat) < 0) { -#endif /* This may be a dangling symlink. * Making [sym]links to dangling symlinks works, so... */ if (flags & (FILEUTILS_MAKE_SOFTLINK|FILEUTILS_MAKE_HARDLINK)) diff --git a/libbb/recursive_action.c b/libbb/recursive_action.c index 560c93cad..b5cf7c0ab 100644 --- a/libbb/recursive_action.c +++ b/libbb/recursive_action.c @@ -73,12 +73,7 @@ int FAST_FUNC recursive_action(const char *fileName, if (depth == 0) follow = ACTION_FOLLOWLINKS | ACTION_FOLLOWLINKS_L0; follow &= flags; -#if ENABLE_PLATFORM_MINGW32 - /* stat can't be aliased, and MinGW uses lstat anyway */ - status = lstat(fileName, &statbuf); -#else status = (follow ? stat : lstat)(fileName, &statbuf); -#endif if (status < 0) { #ifdef DEBUG_RECURS_ACTION bb_error_msg("status=%d flags=%x", status, flags); 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, ...) errno = ENOSYS; return -1; } - if (!strcmp(filename, "/dev/null")) + if (filename && !strcmp(filename, "/dev/null")) filename = "nul"; fd = open(filename, oflags, mode); if (fd < 0 && (oflags & O_CREAT) && errno == EACCES) { @@ -142,11 +142,11 @@ int mingw_open (const char *filename, int oflags, ...) } #undef fopen -FILE *mingw_fopen (const char *filename, const char *mode) +FILE *mingw_fopen (const char *filename, const char *otype) { - if (!strcmp(filename, "/dev/null")) + if (filename && !strcmp(filename, "/dev/null")) filename = "nul"; - return fopen(filename, mode); + return fopen(filename, otype); } #undef dup2 @@ -156,12 +156,20 @@ int mingw_dup2 (int fd, int fdto) return ret != -1 ? fdto : -1; } -static inline time_t filetime_to_time_t(const FILETIME *ft) +/* + * The unit of FILETIME is 100-nanoseconds since January 1, 1601, UTC. + * Returns the 100-nanoseconds ("hekto nanoseconds") since the epoch. + */ +static inline long long filetime_to_hnsec(const FILETIME *ft) { long long winTime = ((long long)ft->dwHighDateTime << 32) + ft->dwLowDateTime; - winTime -= 116444736000000000LL; /* Windows to Unix Epoch conversion */ - winTime /= 10000000; /* Nano to seconds resolution */ - return (time_t)winTime; + /* Windows to Unix Epoch conversion */ + return winTime - 116444736000000000LL; +} + +static inline time_t filetime_to_time_t(const FILETIME *ft) +{ + return (time_t)(filetime_to_hnsec(ft) / 10000000); } 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 /* We keep the do_lstat code in a separate function to avoid recursion. * When a path ends with a slash, the stat will fail with ENOENT. In * this case, we strip the trailing slashes and stat again. + * + * If follow is true then act like stat() and report on the link + * target. Otherwise report on the link itself. */ -static int do_lstat(const char *file_name, struct stat *buf) +static int do_lstat(int follow, const char *file_name, struct stat *buf) { + int err; WIN32_FILE_ATTRIBUTE_DATA fdata; - if (!(errno = get_file_attr(file_name, &fdata))) { + if (!(err = get_file_attr(file_name, &fdata))) { int len = strlen(file_name); buf->st_ino = 0; @@ -220,8 +232,28 @@ static int do_lstat(const char *file_name, struct stat *buf) buf->st_atime = filetime_to_time_t(&(fdata.ftLastAccessTime)); buf->st_mtime = filetime_to_time_t(&(fdata.ftLastWriteTime)); buf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime)); + if (fdata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { + WIN32_FIND_DATAA findbuf; + HANDLE handle = FindFirstFileA(file_name, &findbuf); + if (handle != INVALID_HANDLE_VALUE) { + if ((findbuf.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) && + (findbuf.dwReserved0 == IO_REPARSE_TAG_SYMLINK)) { + if (follow) { + char buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; + buf->st_size = readlink(file_name, buffer, MAXIMUM_REPARSE_DATA_BUFFER_SIZE); + } else { + buf->st_mode = S_IFLNK; + } + buf->st_mode |= S_IREAD; + if (!(findbuf.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) + buf->st_mode |= S_IWRITE; + } + FindClose(handle); + } + } return 0; } + errno = err; return -1; } @@ -231,12 +263,12 @@ static int do_lstat(const char *file_name, struct stat *buf) * complete. Note that Git stat()s are redirected to mingw_lstat() * too, since Windows doesn't really handle symlinks that well. */ -int mingw_lstat(const char *file_name, struct stat *buf) +static int do_stat_internal(int follow, const char *file_name, struct stat *buf) { int namelen; static char alt_name[PATH_MAX]; - if (!do_lstat(file_name, buf)) + if (!do_lstat(follow, file_name, buf)) return 0; /* if file_name ended in a '/', Windows returned ENOENT; @@ -255,7 +287,16 @@ int mingw_lstat(const char *file_name, struct stat *buf) memcpy(alt_name, file_name, namelen); alt_name[namelen] = 0; - return do_lstat(alt_name, buf); + return do_lstat(follow, alt_name, buf); +} + +int mingw_lstat(const char *file_name, struct stat *buf) +{ + return do_stat_internal(0, file_name, buf); +} +int mingw_stat(const char *file_name, struct stat *buf) +{ + return do_stat_internal(1, file_name, buf); } #undef fstat @@ -374,43 +415,15 @@ int mkstemp(char *template) return open(filename, O_RDWR | O_CREAT, 0600); } -/* - * This is like mktime, but without normalization of tm_wday and tm_yday. - */ -static time_t tm_to_time_t(const struct tm *tm) +int gettimeofday(struct timeval *tv, void *tz UNUSED_PARAM) { - static const int mdays[] = { - 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 - }; - int year = tm->tm_year - 70; - int month = tm->tm_mon; - int day = tm->tm_mday; + FILETIME ft; + long long hnsec; - if (year < 0 || year > 129) /* algo only works for 1970-2099 */ - return -1; - if (month < 0 || month > 11) /* array bounds */ - return -1; - if (month < 2 || (year + 2) % 4) - day--; - return (year * 365 + (year + 1) / 4 + mdays[month] + day) * 24*60*60UL + - tm->tm_hour * 60*60 + tm->tm_min * 60 + tm->tm_sec; -} - -int gettimeofday(struct timeval *tv, void *tz) -{ - SYSTEMTIME st; - struct tm tm; - GetSystemTime(&st); - tm.tm_year = st.wYear-1900; - tm.tm_mon = st.wMonth-1; - tm.tm_mday = st.wDay; - tm.tm_hour = st.wHour; - tm.tm_min = st.wMinute; - tm.tm_sec = st.wSecond; - tv->tv_sec = tm_to_time_t(&tm); - if (tv->tv_sec < 0) - return -1; - tv->tv_usec = st.wMilliseconds*1000; + GetSystemTimeAsFileTime(&ft); + hnsec = filetime_to_hnsec(&ft); + tv->tv_sec = hnsec / 10000000; + tv->tv_usec = (hnsec % 10000000) / 10; return 0; } @@ -482,7 +495,7 @@ int mingw_rename(const char *pold, const char *pnew) return -1; } -struct passwd *getpwuid(int uid) +struct passwd *getpwuid(int uid UNUSED_PARAM) { static char user_name[100]; static struct passwd p; @@ -622,7 +635,7 @@ sighandler_t mingw_signal(int sig, sighandler_t handler) int link(const char *oldpath, const char *newpath) { - typedef BOOL WINAPI (*T)(const char*, const char*, LPSECURITY_ATTRIBUTES); + typedef BOOL (WINAPI *T)(const char*, const char*, LPSECURITY_ATTRIBUTES); static T create_hard_link = NULL; if (!create_hard_link) { create_hard_link = (T) GetProcAddress( @@ -702,7 +715,7 @@ int mingw_unlink(const char *pathname) return unlink(pathname); } -char *strptime(const char *s, const char *format, struct tm *tm) +char *strptime(const char *s UNUSED_PARAM, const char *format UNUSED_PARAM, struct tm *tm UNUSED_PARAM) { return NULL; } -- cgit v1.2.3-55-g6feb