Besides, the output of the fast stat and lstat is not compatible with cygwin's fstat with regard to uid, gid and ctime fields. Signed-off-by: Alex Riesen <raa.lkml@xxxxxxxxx> --- This is not strictly related to the other stat patches. The fstat code is shamelessly stolen from the mingw port, sorry. BTW, why do we have to #undef fstat, but not stat/lstat? compat/cygwin.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++--- compat/cygwin.h | 2 + 2 files changed, 58 insertions(+), 4 deletions(-) diff --git a/compat/cygwin.c b/compat/cygwin.c index ebac148..e91af4f 100644 --- a/compat/cygwin.c +++ b/compat/cygwin.c @@ -15,6 +15,18 @@ static inline void filetime_to_timespec(const FILETIME *ft, struct timespec *ts) #define size_to_blocks(s) (((s)+511)/512) +/* + * Initialize the fields of struct stat which this implementation + * considers constant on this platform. See also mingw.c + */ +static void dosify_statbuf(struct stat *buf) +{ + buf->st_dev = buf->st_rdev = 0; /* not used by Git */ + buf->st_ino = 0; + buf->st_nlink = 1; + buf->st_uid = buf->st_gid = 0; +} + /* do_stat is a common implementation for cygwin_lstat and cygwin_stat. * * To simplify its logic, in the case of cygwin symlinks, this implementation @@ -41,11 +53,8 @@ static int do_stat(const char *file_name, struct stat *buf, stat_fn_t cygstat) return cygstat(file_name, buf); /* fill out the stat structure */ - buf->st_dev = buf->st_rdev = 0; /* not used by Git */ - buf->st_ino = 0; + dosify_statbuf(buf); buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes); - buf->st_nlink = 1; - buf->st_uid = buf->st_gid = 0; #ifdef __CYGWIN_USE_BIG_TYPES__ buf->st_size = ((_off64_t)fdata.nFileSizeHigh << 32) + fdata.nFileSizeLow; @@ -85,6 +94,41 @@ static int cygwin_stat(const char *path, struct stat *buf) return do_stat(path, buf, stat); } +#undef fstat +static int cygwin_fstat(int fd, struct stat *buf) +{ + HANDLE fh = (HANDLE)_get_osfhandle(fd); + BY_HANDLE_FILE_INFORMATION fdata; + + if (fh == INVALID_HANDLE_VALUE) { + errno = EBADF; + return -1; + } + /* direct non-file handles to cygwin's fstat() */ + if (GetFileType(fh) != FILE_TYPE_DISK) + return fstat(fd, buf); + + if (!buf) { + errno = EINVAL; + return -1; + } + if (GetFileInformationByHandle(fh, &fdata)) { + dosify_statbuf(buf); + buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes); +#ifdef __CYGWIN_USE_BIG_TYPES__ + buf->st_size = ((_off64_t)fdata.nFileSizeHigh << 32) + + fdata.nFileSizeLow; +#else + buf->st_size = (off_t)fdata.nFileSizeLow; +#endif + filetime_to_timespec(&fdata.ftLastAccessTime, &buf->st_atim); + filetime_to_timespec(&fdata.ftLastWriteTime, &buf->st_mtim); + filetime_to_timespec(&fdata.ftCreationTime, &buf->st_ctim); + return 0; + } + errno = EBADF; + return -1; +} /* * At start up, we are trying to determine whether Win32 API or cygwin stat @@ -119,9 +163,11 @@ static int init_stat(void) if (!core_filemode && native_stat) { cygwin_stat_fn = cygwin_stat; cygwin_lstat_fn = cygwin_lstat; + cygwin_fstat_fn = cygwin_fstat; } else { cygwin_stat_fn = stat; cygwin_lstat_fn = lstat; + cygwin_fstat_fn = fstat; } return 0; } @@ -138,6 +184,12 @@ static int cygwin_lstat_stub(const char *file_name, struct stat *buf) return (init_stat() ? lstat : *cygwin_lstat_fn)(file_name, buf); } +static int cygwin_fstat_stub(int fd, struct stat *buf) +{ + return (init_stat() ? fstat : *cygwin_fstat_fn)(fd, buf); +} + stat_fn_t cygwin_stat_fn = cygwin_stat_stub; stat_fn_t cygwin_lstat_fn = cygwin_lstat_stub; +int (*cygwin_fstat_fn)(int fd, struct stat *) = cygwin_fstat_stub; diff --git a/compat/cygwin.h b/compat/cygwin.h index a3229f5..fd54c82 100644 --- a/compat/cygwin.h +++ b/compat/cygwin.h @@ -4,6 +4,8 @@ typedef int (*stat_fn_t)(const char*, struct stat*); extern stat_fn_t cygwin_stat_fn; extern stat_fn_t cygwin_lstat_fn; +extern int (*cygwin_fstat_fn)(int fd, struct stat *); #define stat(path, buf) (*cygwin_stat_fn)(path, buf) #define lstat(path, buf) (*cygwin_lstat_fn)(path, buf) +#define fstat(fd, buf) (*cygwin_fstat_fn)(fd, buf) -- 1.6.2.142.gaf8db
Attachment:
0001-Add-a-fast-version-of-fstat-to-cygwin-port.diff
Description: Binary data