diff options
Diffstat (limited to 'compat')
-rw-r--r-- | compat/mingw.c | 56 | ||||
-rw-r--r-- | compat/mingw.h | 36 |
2 files changed, 77 insertions, 15 deletions
diff --git a/compat/mingw.c b/compat/mingw.c index f2d9e1fd97..6590f33cc8 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -127,7 +127,7 @@ int mingw_open (const char *filename, int oflags, ...) mode = va_arg(args, int); va_end(args); - if (!strcmp(filename, "/dev/null")) + if (filename && !strcmp(filename, "/dev/null")) filename = "nul"; fd = open(filename, oflags, mode); @@ -160,7 +160,7 @@ ssize_t mingw_write(int fd, const void *buf, size_t count) #undef fopen 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, otype); } @@ -192,8 +192,11 @@ static inline time_t filetime_to_time_t(const FILETIME *ft) /* 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) { WIN32_FILE_ATTRIBUTE_DATA fdata; @@ -209,6 +212,25 @@ 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; } return -1; @@ -220,12 +242,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; @@ -244,7 +266,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 @@ -873,6 +904,11 @@ void mingw_execvp(const char *cmd, char *const *argv) free_path_split(path); } +void mingw_execv(const char *cmd, char *const *argv) +{ + mingw_execve(cmd, argv, environ); +} + static char **copy_environ(void) { char **env; @@ -1386,6 +1422,7 @@ void mingw_open_html(const char *unixpath) const char *, const char *, const char *, INT); T ShellExecute; HMODULE shell32; + int r; shell32 = LoadLibrary("shell32.dll"); if (!shell32) @@ -1395,9 +1432,12 @@ void mingw_open_html(const char *unixpath) die("cannot run browser"); printf("Launching default browser to display HTML ...\n"); - ShellExecute(NULL, "open", htmlpath, NULL, "\\", 0); - + r = (int)ShellExecute(NULL, "open", htmlpath, NULL, "\\", SW_SHOWNORMAL); FreeLibrary(shell32); + /* see the MSDN documentation referring to the result codes here */ + if (r <= 32) { + die("failed to launch browser for %.*s", MAX_PATH, unixpath); + } } int link(const char *oldpath, const char *newpath) diff --git a/compat/mingw.h b/compat/mingw.h index 3b2477be5f..83e35e833b 100644 --- a/compat/mingw.h +++ b/compat/mingw.h @@ -6,17 +6,30 @@ */ typedef int pid_t; +typedef int uid_t; #define hstrerror strerror #define S_IFLNK 0120000 /* Symbolic link */ #define S_ISLNK(x) (((x) & S_IFMT) == S_IFLNK) #define S_ISSOCK(x) 0 + +#ifndef _STAT_H_ +#define S_IRUSR 0 +#define S_IWUSR 0 +#define S_IXUSR 0 +#define S_IRWXU (S_IRUSR | S_IWUSR | S_IXUSR) +#endif #define S_IRGRP 0 #define S_IWGRP 0 #define S_IXGRP 0 -#define S_ISGID 0 +#define S_IRWXG (S_IRGRP | S_IWGRP | S_IXGRP) #define S_IROTH 0 +#define S_IWOTH 0 #define S_IXOTH 0 +#define S_IRWXO (S_IROTH | S_IWOTH | S_IXOTH) +#define S_ISUID 0 +#define S_ISGID 0 +#define S_ISVTX 0 #define WIFEXITED(x) 1 #define WIFSIGNALED(x) 0 @@ -66,6 +79,12 @@ struct itimerval { #define ITIMER_REAL 0 /* + * sanitize preprocessor namespace polluted by Windows headers defining + * macros which collide with git local versions + */ +#undef HELP_COMMAND /* from winuser.h */ + +/* * trivial stubs */ @@ -75,17 +94,17 @@ static inline int symlink(const char *oldpath, const char *newpath) { errno = ENOSYS; return -1; } static inline int fchmod(int fildes, mode_t mode) { errno = ENOSYS; return -1; } -static inline int fork(void) +static inline pid_t fork(void) { errno = ENOSYS; return -1; } static inline unsigned int alarm(unsigned int seconds) { return 0; } static inline int fsync(int fd) { return _commit(fd); } -static inline int getppid(void) +static inline pid_t getppid(void) { return 1; } static inline void sync(void) {} -static inline int getuid() +static inline uid_t getuid(void) { return 1; } static inline struct passwd *getpwnam(const char *name) { return NULL; } @@ -117,7 +136,7 @@ static inline int mingw_unlink(const char *pathname) } #define unlink mingw_unlink -static inline int waitpid(pid_t pid, int *status, unsigned options) +static inline pid_t waitpid(pid_t pid, int *status, unsigned options) { if (options == 0) return _cwait(status, pid, 0); @@ -158,7 +177,7 @@ int poll(struct pollfd *ufds, unsigned int nfds, int timeout); struct tm *gmtime_r(const time_t *timep, struct tm *result); struct tm *localtime_r(const time_t *timep, struct tm *result); int getpagesize(void); /* defined in MinGW's libgcc.a */ -struct passwd *getpwuid(int uid); +struct passwd *getpwuid(uid_t uid); int setitimer(int type, struct itimerval *in, struct itimerval *out); int sigaction(int sig, struct sigaction *in, struct sigaction *out); int link(const char *oldpath, const char *newpath); @@ -222,10 +241,11 @@ int mingw_getpagesize(void); #ifndef ALREADY_DECLARED_STAT_FUNCS #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 fstat mingw_fstat #define lstat mingw_lstat -#define _stati64(x,y) mingw_lstat(x,y) +#define _stati64(x,y) mingw_stat(x,y) #endif int mingw_utime(const char *file_name, const struct utimbuf *times); @@ -236,6 +256,8 @@ pid_t mingw_spawnvpe(const char *cmd, const char **argv, char **env, int fhin, int fhout, int fherr); void mingw_execvp(const char *cmd, char *const *argv); #define execvp mingw_execvp +void mingw_execv(const char *cmd, char *const *argv); +#define execv mingw_execv static inline unsigned int git_ntohl(unsigned int x) { return (unsigned int)ntohl(x); } |