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.
This commit is contained in:
parent
291ae2c1e7
commit
8d817b0f9e
|
@ -1,3 +1,29 @@
|
|||
Thu Oct 4 23:17:49 2001 Christopher Faylor <cgf@cygnus.com>
|
||||
|
||||
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 <cgf@cygnus.com>
|
||||
|
||||
* spawn.cc (perhaps_suffix): Return NULL on non-existence of file as
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -24,6 +24,8 @@ details. */
|
|||
#include "dtable.h"
|
||||
#include "cygheap.h"
|
||||
#include "shared_info.h"
|
||||
#include "sigproc.h"
|
||||
#include "pinfo.h"
|
||||
#include <assert.h>
|
||||
|
||||
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++)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue