From 8d817b0f9ed20cfa5e9482074999c2973a2a9543 Mon Sep 17 00:00:00 2001 From: Christopher Faylor Date: Fri, 5 Oct 2001 04:21:41 +0000 Subject: [PATCH] Add second path_conv * argument to fstat()s throughout. * fhandler.h: Change read and fstat to regparm/stdcall throughout. (fhandler_base::fstat): Just declare. Don't define. (fhandler_disk_file::fstat_helper): Declare. * fhandler.cc (fhandler_base::fstat): Move here from fhandler.h, adapt from former stat_dev(). (fhandler_disk_file::fstat): Move most of the disk-file-specific logic from stat_worker to here. Use fstat_helper to derive final fstat output. (fhandler_disk_file::fstat_helper): New method, renamed from former fstat method. (num_entries): Moved here from syscalls.cc. * fhandler_mem.cc (fhandler_dev_mem::fstat): Use base class to initialize most stuff. Invert has_physical_mem_access test for establishing permissions. * fhandler_raw.cc (fhandler_dev_raw::fstat): Eliminate unneed test and memory clearing. Use base class to initialize most stuff. * syscalls.cc (stat_dev): Eliminate. (stat_worker): Simply call fstat method to generate fstat output. Move all device specific code to appropriate fstats. * dir.cc (opendir): Pass correct arg to stat_worker to allow following symlinks. --- winsup/cygwin/ChangeLog | 26 +++++ winsup/cygwin/dir.cc | 2 +- winsup/cygwin/fhandler.cc | 161 ++++++++++++++++++++++++++++++- winsup/cygwin/fhandler.h | 45 ++++----- winsup/cygwin/fhandler_mem.cc | 14 +-- winsup/cygwin/fhandler_raw.cc | 16 +--- winsup/cygwin/fhandler_tape.cc | 4 +- winsup/cygwin/syscalls.cc | 168 ++------------------------------- 8 files changed, 223 insertions(+), 213 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index e125866c4..d09b8a5c5 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,29 @@ +Thu Oct 4 23:17:49 2001 Christopher Faylor + + Add second path_conv * argument to fstat()s throughout. + * fhandler.h: Change read and fstat to regparm/stdcall throughout. + (fhandler_base::fstat): Just declare. Don't define. + (fhandler_disk_file::fstat_helper): Declare. + * fhandler.cc (fhandler_base::fstat): Move here from fhandler.h, adapt + from former stat_dev(). + (fhandler_disk_file::fstat): Move most of the disk-file-specific logic + from stat_worker to here. Use fstat_helper to derive final fstat + output. + (fhandler_disk_file::fstat_helper): New method, renamed from former + fstat method. + (num_entries): Moved here from syscalls.cc. + * fhandler_mem.cc (fhandler_dev_mem::fstat): Use base class to + initialize most stuff. Invert has_physical_mem_access test for + establishing permissions. + * fhandler_raw.cc (fhandler_dev_raw::fstat): Eliminate unneed test and + memory clearing. Use base class to initialize most stuff. + * syscalls.cc (stat_dev): Eliminate. + (stat_worker): Simply call fstat method to generate fstat output. Move + all device specific code to appropriate fstats. + + * dir.cc (opendir): Pass correct arg to stat_worker to allow following + symlinks. + Thu Oct 4 21:37:57 2001 Christopher Faylor * spawn.cc (perhaps_suffix): Return NULL on non-existence of file as diff --git a/winsup/cygwin/dir.cc b/winsup/cygwin/dir.cc index 39ec9e9d9..6ca1695ed 100644 --- a/winsup/cygwin/dir.cc +++ b/winsup/cygwin/dir.cc @@ -85,7 +85,7 @@ opendir (const char *dirname) path_conv real_dirname; - if (stat_worker (dirname, &statbuf, 1, &real_dirname) == -1) + if (stat_worker (dirname, &statbuf, 0, &real_dirname) == -1) goto failed; if (!(statbuf.st_mode & S_IFDIR)) diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc index 0bad75cc9..6e2db18df 100644 --- a/winsup/cygwin/fhandler.cc +++ b/winsup/cygwin/fhandler.cc @@ -24,6 +24,8 @@ details. */ #include "dtable.h" #include "cygheap.h" #include "shared_info.h" +#include "sigproc.h" +#include "pinfo.h" #include static NO_COPY const int CHUNK_SIZE = 1024; /* Used for crlf conversions */ @@ -847,15 +849,168 @@ rootdir(char *full_path) return root; } +int __stdcall +fhandler_base::fstat (struct stat *buf, path_conv *) +{ + switch (get_device ()) + { + case FH_PIPEW: + buf->st_mode = STD_WBITS | S_IWGRP | S_IWOTH; + break; + case FH_PIPER: + buf->st_mode = STD_RBITS; + break; + default: + buf->st_mode = STD_RBITS | STD_WBITS | S_IWGRP | S_IWOTH; + break; + } + + buf->st_mode |= get_device () == FH_FLOPPY ? S_IFBLK : S_IFCHR; + buf->st_nlink = 1; + buf->st_blksize = S_BLKSIZE; + buf->st_dev = buf->st_rdev = FHDEVN (get_device ()) << 8 | (get_unit () & 0xff); + buf->st_ino = get_namehash (); + buf->st_atime = buf->st_mtime = buf->st_ctime = time (NULL); + return 0; +} + +static int +num_entries (const char *win32_name) +{ + WIN32_FIND_DATA buf; + HANDLE handle; + char buf1[MAX_PATH]; + int count = 0; + + strcpy (buf1, win32_name); + int len = strlen (buf1); + if (len == 0 || isdirsep (buf1[len - 1])) + strcat (buf1, "*"); + else + strcat (buf1, "/*"); /* */ + + handle = FindFirstFileA (buf1, &buf); + + if (handle == INVALID_HANDLE_VALUE) + return 0; + count ++; + while (FindNextFileA (handle, &buf)) + { + if ((buf.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) + count ++; + } + FindClose (handle); + return count; +} + int -fhandler_disk_file::fstat (struct stat *buf) +fhandler_disk_file::fstat (struct stat *buf, path_conv *pc) +{ + int res = -1; + int oret; + uid_t uid; + gid_t gid; + int open_flags = O_RDONLY | O_BINARY | O_DIROPEN; + + if (!pc) + return fstat_helper (buf); + + if ((oret = open (pc, open_flags, 0))) + /* ok */; + else + { + int ntsec_atts = 0; + /* If we couldn't open the file, try a "query open" with no permissions. + This will allow us to determine *some* things about the file, at least. */ + set_query_open (TRUE); + if ((oret = open (pc, open_flags, 0))) + /* ok */; + else if (allow_ntsec && pc->has_acls () && get_errno () == EACCES + && !get_file_attribute (TRUE, get_win32_name (), &ntsec_atts, &uid, &gid) + && !ntsec_atts && uid == myself->uid && gid == myself->gid) + { + /* Check a special case here. If ntsec is ON it happens + that a process creates a file using mode 000 to disallow + other processes access. In contrast to UNIX, this results + in a failing open call in the same process. Check that + case. */ + set_file_attribute (TRUE, get_win32_name (), 0400); + oret = open (pc, open_flags, 0); + set_file_attribute (TRUE, get_win32_name (), ntsec_atts); + } + } + if (oret) + { + res = fstat_helper (buf); + /* The number of links to a directory includes the + number of subdirectories in the directory, since all + those subdirectories point to it. + This is too slow on remote drives, so we do without it and + set the number of links to 2. */ + /* Unfortunately the count of 2 confuses `find (1)' command. So + let's try it with `1' as link count. */ + if (pc->isdir ()) + buf->st_nlink = (pc->isremote () + ? 1 : num_entries (pc->get_win32 ())); + close (); + } + else if (pc->exists ()) + { + /* Unfortunately, the above open may fail if the file exists, though. + So we have to care for this case here, too. */ + WIN32_FIND_DATA wfd; + HANDLE handle; + buf->st_nlink = 1; + if (pc->isdir () && pc->isremote ()) + buf->st_nlink = num_entries (pc->get_win32 ()); + buf->st_dev = FHDEVN (FH_DISK) << 8; + buf->st_ino = hash_path_name (0, pc->get_win32 ()); + if (pc->isdir ()) + buf->st_mode = S_IFDIR; + else if (pc->issymlink ()) + buf->st_mode = S_IFLNK; + else if (pc->issocket ()) + buf->st_mode = S_IFSOCK; + else + buf->st_mode = S_IFREG; + if (!pc->has_acls () + || get_file_attribute (TRUE, pc->get_win32 (), + &buf->st_mode, + &buf->st_uid, &buf->st_gid)) + { + buf->st_mode |= STD_RBITS | STD_XBITS; + if (!(pc->has_attribute (FILE_ATTRIBUTE_READONLY))) + buf->st_mode |= STD_WBITS; + if (pc->issymlink ()) + buf->st_mode |= S_IRWXU | S_IRWXG | S_IRWXO; + get_file_attribute (FALSE, pc->get_win32 (), + NULL, &buf->st_uid, &buf->st_gid); + } + if ((handle = FindFirstFile (pc->get_win32 (), &wfd)) + != INVALID_HANDLE_VALUE) + { + buf->st_atime = to_time_t (&wfd.ftLastAccessTime); + buf->st_mtime = to_time_t (&wfd.ftLastWriteTime); + buf->st_ctime = to_time_t (&wfd.ftCreationTime); + buf->st_size = wfd.nFileSizeLow; + buf->st_blksize = S_BLKSIZE; + buf->st_blocks = ((unsigned long) buf->st_size + + S_BLKSIZE-1) / S_BLKSIZE; + FindClose (handle); + } + res = 0; + } + + return res; +} + +int +fhandler_disk_file::fstat_helper (struct stat *buf) { int res = 0; // avoid a compiler warning BY_HANDLE_FILE_INFORMATION local; save_errno saved_errno; - memset (buf, 0, sizeof (*buf)); - /* NT 3.51 seems to have a bug when attempting to get vol serial numbers. This loop gets around this. */ for (int i = 0; i < 2; i++) diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index 6f80b61b5..5a07c43c9 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -313,11 +313,11 @@ public: virtual int open (path_conv * real_path, int flags, mode_t mode = 0); virtual int close (); - virtual int fstat (struct stat *buf) { return stat_dev (get_device (), get_unit (), get_namehash (), buf); } + virtual int __stdcall fstat (struct stat *buf, path_conv *) __attribute__ ((regparm (2))); virtual int ioctl (unsigned int cmd, void *); virtual int fcntl (int cmd, void *); virtual char const * ttyname () { return get_name(); } - virtual int read (void *ptr, size_t len); + virtual int __stdcall read (void *ptr, size_t len) __attribute__ ((regparm (2))); virtual int write (const void *ptr, size_t len); virtual off_t lseek (off_t offset, int whence); virtual int lock (int, struct flock *); @@ -397,7 +397,7 @@ public: void set_shutdown_write () {FHSETF (SHUTWR);} int write (const void *ptr, size_t len); - int read (void *ptr, size_t len); + int __stdcall read (void *ptr, size_t len) __attribute__ ((regparm (2))); int ioctl (unsigned int cmd, void *); int fcntl (int cmd, void *); off_t lseek (off_t, int) { return 0; } @@ -438,7 +438,7 @@ public: select_record *select_except (select_record *s); int ready_for_read (int fd, DWORD howlong, int ignra); void set_close_on_exec (int val); - int read (void *ptr, size_t len); + int __stdcall read (void *ptr, size_t len) __attribute__ ((regparm (2))); int close (); void create_guard (SECURITY_ATTRIBUTES *sa) {guard = CreateMutex (sa, FALSE, NULL);} int dup (fhandler_base *child); @@ -481,7 +481,7 @@ public: int raw_read (void *ptr, size_t ulen); int raw_write (const void *ptr, size_t ulen); - int fstat (struct stat *buf); + int __stdcall fstat (struct stat *buf, path_conv *) __attribute__ ((regparm (2))); int dup (fhandler_base *child); @@ -522,16 +522,16 @@ protected: public: fhandler_dev_tape (const char *name, int unit); - virtual int open (path_conv *, int flags, mode_t mode = 0); - virtual int close (void); + int open (path_conv *, int flags, mode_t mode = 0); + int close (void); - virtual off_t lseek (off_t offset, int whence); + off_t lseek (off_t offset, int whence); - virtual int fstat (struct stat *buf); + int __stdcall fstat (struct stat *buf, path_conv *) __attribute__ ((regparm (2))); - virtual int dup (fhandler_base *child); + int dup (fhandler_base *child); - virtual int ioctl (unsigned int cmd, void *buf); + int ioctl (unsigned int cmd, void *buf); private: int tape_write_marks (int marktype, DWORD len); @@ -557,7 +557,8 @@ public: int close (); int lock (int, struct flock *); BOOL is_device () { return FALSE; } - int fstat (struct stat *buf); + int __stdcall fstat (struct stat *buf, path_conv *pc) __attribute__ ((regparm (2))); + int __stdcall fstat_helper (struct stat *buf) __attribute__ ((regparm (1))); HANDLE mmap (caddr_t *addr, size_t len, DWORD access, int flags, off_t off); int munmap (HANDLE h, caddr_t addr, size_t len); @@ -747,7 +748,7 @@ public: int write (const void *ptr, size_t len); void doecho (const void *str, DWORD len) { (void) write (str, len); } - int read (void *ptr, size_t len); + int __stdcall read (void *ptr, size_t len) __attribute__ ((regparm (2))); int close (); int tcflush (int); @@ -818,7 +819,7 @@ public: int open (path_conv *, int flags, mode_t mode = 0); int write (const void *ptr, size_t len); - int read (void *ptr, size_t len); + int __stdcall read (void *ptr, size_t len) __attribute__ ((regparm (2))); void init (HANDLE, DWORD, mode_t); int tcsetattr (int a, const struct termios *t); @@ -845,7 +846,7 @@ public: int accept_input (); int open (path_conv *, int flags, mode_t mode = 0); int write (const void *ptr, size_t len); - int read (void *ptr, size_t len); + int __stdcall read (void *ptr, size_t len) __attribute__ ((regparm (2))); int close (); int tcsetattr (int a, const struct termios *t); @@ -891,7 +892,7 @@ public: fhandler_dev_zero (const char *name); int open (path_conv *, int flags, mode_t mode = 0); int write (const void *ptr, size_t len); - int read (void *ptr, size_t len); + int __stdcall read (void *ptr, size_t len) __attribute__ ((regparm (2))); off_t lseek (off_t offset, int whence); int close (void); @@ -914,7 +915,7 @@ public: int get_unit () { return unit; } int open (path_conv *, int flags, mode_t mode = 0); int write (const void *ptr, size_t len); - int read (void *ptr, size_t len); + int __stdcall read (void *ptr, size_t len) __attribute__ ((regparm (2))); off_t lseek (off_t offset, int whence); int close (void); int dup (fhandler_base *child); @@ -935,10 +936,10 @@ public: int open (path_conv *, int flags, mode_t mode = 0); int write (const void *ptr, size_t ulen); - int read (void *ptr, size_t ulen); + int __stdcall read (void *ptr, size_t len) __attribute__ ((regparm (2))); off_t lseek (off_t offset, int whence); int close (void); - int fstat (struct stat *buf); + int __stdcall fstat (struct stat *buf, path_conv *) __attribute__ ((regparm (2))); int dup (fhandler_base *child); HANDLE mmap (caddr_t *addr, size_t len, DWORD access, int flags, off_t off); @@ -957,7 +958,7 @@ public: int is_windows (void) { return 1; } int open (path_conv *, int flags, mode_t mode = 0); int write (const void *ptr, size_t len); - int read (void *ptr, size_t len); + int __stdcall read (void *ptr, size_t len) __attribute__ ((regparm (2))); off_t lseek (off_t offset, int whence); int close (void); @@ -982,7 +983,7 @@ public: int is_windows (void) { return 1; } int open (path_conv *, int flags, mode_t mode = 0); int write (const void *ptr, size_t len); - int read (void *ptr, size_t len); + int __stdcall read (void *ptr, size_t len) __attribute__ ((regparm (2))); int ioctl (unsigned int cmd, void *); off_t lseek (off_t, int) { return 0; } int close (void) { return 0; } @@ -1009,7 +1010,7 @@ public: int open (path_conv *, int flags, mode_t mode = 0); int write (const void *ptr, size_t len); - int read (void *ptr, size_t len); + int __stdcall read (void *ptr, size_t len) __attribute__ ((regparm (2))); int ioctl (unsigned int cmd, void *); off_t lseek (off_t, int); int close (void); diff --git a/winsup/cygwin/fhandler_mem.cc b/winsup/cygwin/fhandler_mem.cc index d99ab1c3d..7a839e99d 100644 --- a/winsup/cygwin/fhandler_mem.cc +++ b/winsup/cygwin/fhandler_mem.cc @@ -403,23 +403,15 @@ fhandler_dev_mem::fixup_mmap_after_fork (HANDLE h, DWORD access, DWORD offset, } int -fhandler_dev_mem::fstat (struct stat *buf) +fhandler_dev_mem::fstat (struct stat *buf, path_conv *pc) { - if (!buf) - { - set_errno (EINVAL); - return -1; - } - - memset (buf, 0, sizeof *buf); + this->fhandler_base::fstat (buf, pc); buf->st_mode = S_IFCHR; - if (!wincap.has_physical_mem_access ()) + if (wincap.has_physical_mem_access ()) buf->st_mode |= S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; - buf->st_nlink = 1; buf->st_blksize = getpagesize (); - buf->st_dev = buf->st_rdev = get_device () << 8 | (unit & 0xff); return 0; } diff --git a/winsup/cygwin/fhandler_raw.cc b/winsup/cygwin/fhandler_raw.cc index 53d59060a..f487ddd3b 100644 --- a/winsup/cygwin/fhandler_raw.cc +++ b/winsup/cygwin/fhandler_raw.cc @@ -156,22 +156,10 @@ fhandler_dev_raw::close (void) } int -fhandler_dev_raw::fstat (struct stat *buf) +fhandler_dev_raw::fstat (struct stat *buf, path_conv *pc) { - if (!buf) - { - set_errno (EINVAL); - return -1; - } - - memset (buf, 0, sizeof *buf); - buf->st_mode = S_IFCHR | - S_IRUSR | S_IWUSR | - S_IRGRP | S_IWGRP | - S_IROTH | S_IWOTH; - buf->st_nlink = 1; + this->fhandler_base::fstat (buf, pc); buf->st_blksize = devbuf ? devbufsiz : 1; - buf->st_dev = buf->st_rdev = get_device () << 8 | (unit & 0xff); return 0; } diff --git a/winsup/cygwin/fhandler_tape.cc b/winsup/cygwin/fhandler_tape.cc index 8b658924e..a2bf46b8e 100644 --- a/winsup/cygwin/fhandler_tape.cc +++ b/winsup/cygwin/fhandler_tape.cc @@ -148,11 +148,11 @@ fhandler_dev_tape::close (void) } int -fhandler_dev_tape::fstat (struct stat *buf) +fhandler_dev_tape::fstat (struct stat *buf, path_conv *pc) { int ret; - if (! (ret = fhandler_dev_raw::fstat (buf))) + if (!(ret = fhandler_dev_raw::fstat (buf, pc))) { struct mtget get; diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc index aa5afc35a..d41cb2b10 100644 --- a/winsup/cygwin/syscalls.cc +++ b/winsup/cygwin/syscalls.cc @@ -952,36 +952,6 @@ fchmod (int fd, mode_t mode) return chmod (path, mode); } -/* Cygwin internal */ -static int -num_entries (const char *win32_name) -{ - WIN32_FIND_DATA buf; - HANDLE handle; - char buf1[MAX_PATH]; - int count = 0; - - strcpy (buf1, win32_name); - int len = strlen (buf1); - if (len == 0 || isdirsep (buf1[len - 1])) - strcat (buf1, "*"); - else - strcat (buf1, "/*"); /* */ - - handle = FindFirstFileA (buf1, &buf); - - if (handle == INVALID_HANDLE_VALUE) - return 0; - count ++; - while (FindNextFileA (handle, &buf)) - { - if ((buf.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) - count ++; - } - FindClose (handle); - return count; -} - extern "C" int _fstat (int fd, struct stat *buf) { @@ -997,7 +967,7 @@ _fstat (int fd, struct stat *buf) else { memset (buf, 0, sizeof (struct stat)); - r = cygheap->fdtab[fd]->fstat (buf); + r = cygheap->fdtab[fd]->fstat (buf, NULL); syscall_printf ("%d = fstat (%d, %x)", r, fd, buf); } @@ -1033,32 +1003,6 @@ sync () return 0; } -int __stdcall -stat_dev (DWORD devn, int unit, unsigned long ino, struct stat *buf) -{ - sigframe thisframe (mainthread); - switch (devn) - { - case FH_PIPEW: - buf->st_mode = STD_WBITS | S_IWGRP | S_IWOTH; - break; - case FH_PIPER: - buf->st_mode = STD_RBITS; - break; - default: - buf->st_mode = STD_RBITS | STD_WBITS | S_IWGRP | S_IWOTH; - break; - } - - buf->st_mode |= devn == FH_FLOPPY ? S_IFBLK : S_IFCHR; - buf->st_blksize = S_BLKSIZE; - buf->st_nlink = 1; - buf->st_dev = buf->st_rdev = FHDEVN (devn) << 8 | (unit & 0xff); - buf->st_ino = ino; - buf->st_atime = buf->st_mtime = buf->st_ctime = time (NULL); - return 0; -} - suffix_info stat_suffixes[] = { suffix_info ("", 1), @@ -1071,18 +1015,13 @@ int __stdcall stat_worker (const char *name, struct stat *buf, int nofollow, path_conv *pc) { int res = -1; - int oret; - uid_t uid; - gid_t gid; path_conv real_path; fhandler_base *fh = NULL; if (!pc) pc = &real_path; - MALLOC_CHECK; - int open_flags = O_RDONLY | O_BINARY | O_DIROPEN - | (nofollow ? O_NOSYMLINK : 0); + MALLOC_CHECK; if (check_null_invalid_struct_errno (buf)) goto done; @@ -1093,110 +1032,19 @@ stat_worker (const char *name, struct stat *buf, int nofollow, path_conv *pc) | PC_FULL, stat_suffixes); if (pc->error) { + debug_printf ("got %d error from build_fhandler_from_name", pc->error); set_errno (pc->error); - goto done; } - - debug_printf ("(%s, %p, %d, %p)", name, buf, nofollow, pc); - - memset (buf, 0, sizeof (struct stat)); - - if (pc->is_device ()) - return stat_dev (pc->get_devn (), pc->get_unitn (), - hash_path_name (0, pc->get_win32 ()), buf); - - debug_printf ("%d = file_attributes for '%s'", (DWORD) real_path, - (char *) real_path); - - if ((oret = fh->open (pc, open_flags, 0))) - /* ok */; else { - int ntsec_atts = 0; - /* If we couldn't open the file, try a "query open" with no permissions. - This will allow us to determine *some* things about the file, at least. */ - fh->set_query_open (TRUE); - if ((oret = fh->open (pc, open_flags, 0))) - /* ok */; - else if (allow_ntsec && pc->has_acls () && get_errno () == EACCES - && !get_file_attribute (TRUE, real_path, &ntsec_atts, &uid, &gid) - && !ntsec_atts && uid == myself->uid && gid == myself->gid) - { - /* Check a special case here. If ntsec is ON it happens - that a process creates a file using mode 000 to disallow - other processes access. In contrast to UNIX, this results - in a failing open call in the same process. Check that - case. */ - set_file_attribute (TRUE, real_path, 0400); - oret = fh->open (pc, open_flags, 0); - set_file_attribute (TRUE, real_path, ntsec_atts); - } - } - if (oret) - { - res = fh->fstat (buf); - /* The number of links to a directory includes the - number of subdirectories in the directory, since all - those subdirectories point to it. - This is too slow on remote drives, so we do without it and - set the number of links to 2. */ - /* Unfortunately the count of 2 confuses `find (1)' command. So - let's try it with `1' as link count. */ - if (pc->isdir ()) - buf->st_nlink = (pc->isremote () - ? 1 : num_entries (pc->get_win32 ())); - fh->close (); - } - else if (pc->exists ()) - { - /* Unfortunately, the above open may fail if the file exists, though. - So we have to care for this case here, too. */ - WIN32_FIND_DATA wfd; - HANDLE handle; - buf->st_nlink = 1; - if (pc->isdir () && pc->isremote ()) - buf->st_nlink = num_entries (pc->get_win32 ()); - buf->st_dev = FHDEVN (FH_DISK) << 8; - buf->st_ino = hash_path_name (0, pc->get_win32 ()); - if (pc->isdir ()) - buf->st_mode = S_IFDIR; - else if (pc->issymlink ()) - buf->st_mode = S_IFLNK; - else if (pc->issocket ()) - buf->st_mode = S_IFSOCK; - else - buf->st_mode = S_IFREG; - if (!pc->has_acls () - || get_file_attribute (TRUE, pc->get_win32 (), - &buf->st_mode, - &buf->st_uid, &buf->st_gid)) - { - buf->st_mode |= STD_RBITS | STD_XBITS; - if (!(pc->has_attribute (FILE_ATTRIBUTE_READONLY))) - buf->st_mode |= STD_WBITS; - if (pc->issymlink ()) - buf->st_mode |= S_IRWXU | S_IRWXG | S_IRWXO; - get_file_attribute (FALSE, pc->get_win32 (), - NULL, &buf->st_uid, &buf->st_gid); - } - if ((handle = FindFirstFile (pc->get_win32 (), &wfd)) - != INVALID_HANDLE_VALUE) - { - buf->st_atime = to_time_t (&wfd.ftLastAccessTime); - buf->st_mtime = to_time_t (&wfd.ftLastWriteTime); - buf->st_ctime = to_time_t (&wfd.ftCreationTime); - buf->st_size = wfd.nFileSizeLow; - buf->st_blksize = S_BLKSIZE; - buf->st_blocks = ((unsigned long) buf->st_size + - S_BLKSIZE-1) / S_BLKSIZE; - FindClose (handle); - } - res = 0; + debug_printf ("(%s, %p, %d, %p), file_attributes %d", name, buf, nofollow, + pc, (DWORD) real_path); + memset (buf, 0, sizeof (struct stat)); + res = fh->fstat (buf, pc); + delete fh; } done: - if (fh) - delete fh; MALLOC_CHECK; syscall_printf ("%d = (%s, %p)", res, name, buf); return res;