summaryrefslogtreecommitdiffstats
path: root/winsup/cygwin/syscalls.cc
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/syscalls.cc')
-rw-r--r--winsup/cygwin/syscalls.cc222
1 files changed, 98 insertions, 124 deletions
diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index 9f5c8ac88..9aa1dd739 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -116,16 +116,13 @@ _unlink (const char *ourname)
syscall_printf ("_unlink (%s)", win32_name.get_win32 ());
- DWORD atts;
- atts = win32_name.file_attributes ();
- if (atts == 0xffffffff)
+ if (!win32_name.exists ())
{
- syscall_printf ("unlinking a nonexistant file");
+ syscall_printf ("unlinking a nonexistent file");
set_errno (ENOENT);
goto done;
}
-
- if (atts & FILE_ATTRIBUTE_DIRECTORY)
+ else if (win32_name.isdir ())
{
syscall_printf ("unlinking a directory");
set_errno (EPERM);
@@ -140,11 +137,11 @@ _unlink (const char *ourname)
}
/* Check for shortcut as symlink condition. */
- if (atts & FILE_ATTRIBUTE_READONLY)
+ if (win32_name.has_attribute (FILE_ATTRIBUTE_READONLY))
{
int len = strlen (win32_name);
- if (len > 4 && strcasematch (win32_name + len - 4, ".lnk"))
- SetFileAttributes (win32_name, atts & ~FILE_ATTRIBUTE_READONLY);
+ if (len > 4 && strcasematch ((char *) win32_name + len - 4, ".lnk"))
+ SetFileAttributes (win32_name, (DWORD) win32_name & ~FILE_ATTRIBUTE_READONLY);
}
DWORD lasterr;
@@ -249,11 +246,7 @@ remove (const char *ourname)
return -1;
}
- DWORD atts = win32_name.file_attributes ();
- if (atts != 0xffffffff && atts & FILE_ATTRIBUTE_DIRECTORY)
- return rmdir (ourname);
-
- return _unlink (ourname);
+ return win32_name.isdir () ? rmdir (ourname) : _unlink (ourname);
}
extern "C" pid_t
@@ -619,7 +612,7 @@ _link (const char *a, const char *b)
goto done;
}
- if (real_b.file_attributes () != (DWORD)-1)
+ if (real_b.exists ())
{
syscall_printf ("file '%s' exists?", (char *)real_b);
set_errno (EEXIST);
@@ -779,7 +772,7 @@ chown_worker (const char *name, unsigned fmode, uid_t uid, gid_t gid)
}
DWORD attrib = 0;
- if (win32_path.file_attributes () & FILE_ATTRIBUTE_DIRECTORY)
+ if (win32_path.isdir ())
attrib |= S_IFDIR;
res = get_file_attribute (win32_path.has_acls (),
win32_path.get_win32 (),
@@ -792,12 +785,10 @@ chown_worker (const char *name, unsigned fmode, uid_t uid, gid_t gid)
uid = old_uid;
if (gid == (gid_t) -1)
gid = old_gid;
- if (win32_path.file_attributes () & FILE_ATTRIBUTE_DIRECTORY)
+ if (win32_path.isdir())
attrib |= S_IFDIR;
- res = set_file_attribute (win32_path.has_acls (),
- win32_path.get_win32 (),
- uid, gid, attrib,
- cygheap->user.logsrv ());
+ res = set_file_attribute (win32_path.has_acls (), win32_path, uid,
+ gid, attrib, cygheap->user.logsrv ());
}
if (res != 0 && (!win32_path.has_acls () || !allow_ntsec))
{
@@ -886,28 +877,25 @@ chmod (const char *path, mode_t mode)
goto done;
}
- if (win32_path.file_attributes () == (DWORD)-1)
+ if (!win32_path.exists ())
__seterrno ();
else
{
- DWORD attr = win32_path.file_attributes ();
/* temporary erase read only bit, to be able to set file security */
- SetFileAttributesA (win32_path.get_win32 (),
- attr & ~FILE_ATTRIBUTE_READONLY);
+ SetFileAttributes (win32_path, (DWORD) win32_path & ~FILE_ATTRIBUTE_READONLY);
uid_t uid;
gid_t gid;
- if (win32_path.file_attributes () & FILE_ATTRIBUTE_DIRECTORY)
+ if (win32_path.isdir ())
mode |= S_IFDIR;
get_file_attribute (win32_path.has_acls (),
win32_path.get_win32 (),
NULL, &uid, &gid);
- if (win32_path.file_attributes () & FILE_ATTRIBUTE_DIRECTORY)
+ /* FIXME: Do we really need this to be specified twice? */
+ if (win32_path.isdir ())
mode |= S_IFDIR;
- if (!set_file_attribute (win32_path.has_acls (),
- win32_path.get_win32 (),
- uid, gid,
+ if (!set_file_attribute (win32_path.has_acls (), win32_path, uid, gid,
mode, cygheap->user.logsrv ())
&& allow_ntsec)
res = 0;
@@ -915,14 +903,14 @@ chmod (const char *path, mode_t mode)
/* if the mode we want has any write bits set, we can't
be read only. */
if (mode & (S_IWUSR | S_IWGRP | S_IWOTH))
- attr &= ~FILE_ATTRIBUTE_READONLY;
+ (DWORD) win32_path &= ~FILE_ATTRIBUTE_READONLY;
else
- attr |= FILE_ATTRIBUTE_READONLY;
+ (DWORD) win32_path |= FILE_ATTRIBUTE_READONLY;
if (S_ISLNK (mode) || S_ISSOCK (mode))
- attr |= FILE_ATTRIBUTE_SYSTEM;
+ (DWORD) win32_path |= FILE_ATTRIBUTE_SYSTEM;
- if (!SetFileAttributesA (win32_path.get_win32 (), attr))
+ if (!SetFileAttributes (win32_path, win32_path))
__seterrno ();
else
{
@@ -1084,22 +1072,24 @@ stat_worker (const char *caller, const char *name, struct stat *buf,
int nofollow)
{
int res = -1;
- int oret = 1;
- int atts;
-
- int attribute = 0;
+ int oret;
uid_t uid;
gid_t gid;
-
- UINT dtype;
- fhandler_disk_file fh (NULL);
+ path_conv real_path;
+ fhandler_base *fh = NULL;
MALLOC_CHECK;
+ int open_flags = O_RDONLY | O_BINARY | O_DIROPEN
+ | (nofollow ? O_NOSYMLINK : 0);
debug_printf ("%s (%s, %p)", caller, name, buf);
- path_conv real_path (name, (nofollow ? PC_SYM_NOFOLLOW : PC_SYM_FOLLOW) |
- PC_FULL, stat_suffixes);
+ if (check_null_invalid_struct_errno (buf))
+ goto done;
+
+ fh = cygheap->fdtab.build_fhandler (-1, name, NULL, &real_path,
+ (nofollow ? PC_SYM_NOFOLLOW : PC_SYM_FOLLOW)
+ | PC_FULL, stat_suffixes);
if (real_path.error)
{
@@ -1107,83 +1097,66 @@ stat_worker (const char *caller, const char *name, struct stat *buf,
goto done;
}
- if (check_null_invalid_struct_errno (buf))
- goto done;
-
memset (buf, 0, sizeof (struct stat));
if (real_path.is_device ())
return stat_dev (real_path.get_devn (), real_path.get_unitn (),
hash_path_name (0, real_path.get_win32 ()), buf);
- atts = real_path.file_attributes ();
-
- debug_printf ("%d = file_attributes for '%s'", atts, real_path.get_win32 ());
+ debug_printf ("%d = file_attributes for '%s'", (DWORD) real_path,
+ (char *) real_path);
- dtype = real_path.get_drive_type ();
-
- if ((atts == -1 || ! (atts & FILE_ATTRIBUTE_DIRECTORY) ||
- (wincap.can_open_directories ()
- && dtype != DRIVE_NO_ROOT_DIR
- && dtype != DRIVE_UNKNOWN)))
+ if ((oret = fh->open (real_path, open_flags, 0)))
+ /* ok */;
+ else
{
- oret = fh.open (real_path, O_RDONLY | O_BINARY | O_DIROPEN |
- (nofollow ? O_NOSYMLINK : 0), 0);
+ 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. */
- if (!oret)
- {
- fh.set_query_open (TRUE);
- oret = fh.open (real_path, O_RDONLY | O_BINARY | O_DIROPEN |
- (nofollow ? O_NOSYMLINK : 0), 0);
- }
- /* 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. */
- if (!oret && allow_ntsec && get_errno () == EACCES
- && !get_file_attribute (TRUE, real_path, &attribute, &uid, &gid)
- && !attribute && uid == myself->uid && gid == myself->gid)
- {
+ fh->set_query_open (TRUE);
+ if ((oret = fh->open (real_path, open_flags, 0)))
+ /* ok */;
+ else if (allow_ntsec && real_path.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 (real_path, O_RDONLY | O_BINARY | O_DIROPEN |
- (nofollow ? O_NOSYMLINK : 0), 0);
- set_file_attribute (TRUE, real_path.get_win32 (), 0);
- }
- if (oret)
- {
- res = fh.fstat (buf);
- fh.close ();
- /* 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 (atts != -1 && (atts & FILE_ATTRIBUTE_DIRECTORY))
- buf->st_nlink = (dtype == DRIVE_REMOTE
- ? 1
- : num_entries (real_path.get_win32 ()));
- goto done;
- }
- }
- if (atts != -1 && (oret || (!oret && get_errno () != ENOENT
- && get_errno () != ENOSHARE)))
+ oret = fh->open (real_path, 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 (real_path.isdir ())
+ buf->st_nlink = (real_path.isremote ()
+ ? 1 : num_entries (real_path.get_win32 ()));
+ fh->close ();
+ }
+ else if (real_path.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 (atts != -1
- && (atts & FILE_ATTRIBUTE_DIRECTORY)
- && dtype != DRIVE_REMOTE)
+ if (real_path.isdir () && real_path.isremote ())
buf->st_nlink = num_entries (real_path.get_win32 ());
buf->st_dev = FHDEVN (FH_DISK) << 8;
buf->st_ino = hash_path_name (0, real_path.get_win32 ());
- if (atts != -1 && (atts & FILE_ATTRIBUTE_DIRECTORY))
+ if (real_path.isdir ())
buf->st_mode = S_IFDIR;
else if (real_path.issymlink ())
buf->st_mode = S_IFLNK;
@@ -1197,7 +1170,7 @@ stat_worker (const char *caller, const char *name, struct stat *buf,
&buf->st_uid, &buf->st_gid))
{
buf->st_mode |= STD_RBITS | STD_XBITS;
- if ((atts & FILE_ATTRIBUTE_READONLY) == 0)
+ if (!(real_path.has_attribute (FILE_ATTRIBUTE_READONLY)))
buf->st_mode |= STD_WBITS;
if (real_path.issymlink ())
buf->st_mode |= S_IRWXU | S_IRWXG | S_IRWXO;
@@ -1220,6 +1193,8 @@ stat_worker (const char *caller, const char *name, struct stat *buf,
}
done:
+ if (fh)
+ delete fh;
MALLOC_CHECK;
syscall_printf ("%d = %s (%s, %p)", res, caller, name, buf);
return res;
@@ -1360,7 +1335,7 @@ _rename (const char *oldpath, const char *newpath)
return -1;
}
- if (real_old.file_attributes () == (DWORD) -1) /* file to move doesn't exist */
+ if (!real_old.exists ()) /* file to move doesn't exist */
{
syscall_printf ("file to move doesn't exist");
set_errno (ENOENT);
@@ -1369,10 +1344,8 @@ _rename (const char *oldpath, const char *newpath)
/* Destination file exists and is read only, change that or else
the rename won't work. */
- if (real_new.file_attributes () != (DWORD) -1 &&
- real_new.file_attributes () & FILE_ATTRIBUTE_READONLY)
- SetFileAttributesA (real_new.get_win32 (),
- real_new.file_attributes () & ~FILE_ATTRIBUTE_READONLY);
+ if (real_new.has_attribute (FILE_ATTRIBUTE_READONLY))
+ SetFileAttributes (real_new, (DWORD) real_new & ~FILE_ATTRIBUTE_READONLY);
/* Shortcut hack No. 2, part 1 */
if (!real_old.issymlink () && !real_new.error && real_new.issymlink () &&
@@ -1421,14 +1394,13 @@ done:
{
__seterrno ();
/* Reset R/O attributes if neccessary. */
- if (real_new.file_attributes () != (DWORD) -1 &&
- real_new.file_attributes () & FILE_ATTRIBUTE_READONLY)
- SetFileAttributesA (real_new.get_win32 (), real_new.file_attributes ());
+ if (real_new.has_attribute (FILE_ATTRIBUTE_READONLY))
+ SetFileAttributes (real_new, real_new);
}
else
{
/* make the new file have the permissions of the old one */
- SetFileAttributesA (real_new.get_win32 (), real_old.file_attributes ());
+ SetFileAttributes (real_new, real_old);
/* Shortcut hack, No. 2, part 2 */
/* if the new filename was an existing shortcut, remove it now if the
@@ -1436,12 +1408,12 @@ done:
if (lnk_suffix)
{
*lnk_suffix = '.';
- DeleteFile (real_new.get_win32 ());
+ DeleteFile (real_new);
}
}
- syscall_printf ("%d = rename (%s, %s)", res, real_old.get_win32 (),
- real_new.get_win32 ());
+ syscall_printf ("%d = rename (%s, %s)", res, (char *) real_old,
+ (char *) real_new);
return res;
}
@@ -2317,27 +2289,29 @@ extern "C" int
chroot (const char *newroot)
{
sigframe thisframe (mainthread);
- int ret = -1;
path_conv path (newroot, PC_SYM_FOLLOW | PC_FULL);
+ int ret;
if (path.error)
- goto done;
- if (path.file_attributes () == (DWORD)-1)
+ ret = -1;
+ else if (!path.exists ())
{
set_errno (ENOENT);
- goto done;
+ ret = -1;
}
- if (!(path.file_attributes () & FILE_ATTRIBUTE_DIRECTORY))
+ else if (!path.isdir ())
{
set_errno (ENOTDIR);
- goto done;
+ ret = -1;
+ }
+ else
+ {
+ char buf[MAX_PATH];
+ normalize_posix_path (newroot, buf);
+ cygheap->root.set (buf, path);
+ ret = 0;
}
- char buf[MAX_PATH];
- normalize_posix_path (newroot, buf);
- cygheap->root.set (buf, path);
- ret = 0;
-done:
syscall_printf ("%d = chroot (%s)", ret ? get_errno () : 0,
newroot ? newroot : "NULL");
return ret;