Add "path.h" include throughout, where needed. Use new path_conv methods and
operators to simplify testing for directory and attributes, throughout. * path.h (path_conv::exists): New method. (path_conv::has_attribute): Ditto. (path_conv::isdir): Ditto. (path_conv::DWORD &): New operator. (path_conv::int &): Ditto. * dir.cc (rmdir): Eliminate a goto. * dtable.cc (dtable::build_fhandler): Accept opt and suffix info for path_conv.check. Return fh == NULL on path_conv error. Pass unit to set_name as appropriate. (dtable::reset_unix_path_name): New method. * dtable.h (dtable): Declare new method. Reflect arg changes to build_fhandler. * fhandler.cc (fhandler_disk_dummy_name): Eliminate. (fhandler_base::set_name): Expect paths to be NULL. Build unix_path_name from win32_path_name when it is a device. (fhandler_base::reset_unix_path_name): New method. (fhandler_base::raw_read): Report EISDIR when ERROR_INVALID_FUNCTION or ERROR_INVALID_PARAMETER and reading a directory. (fhandler_disk_file::fstat): Don't call stat_dev since we should now never be calling fhandler_disk_file methods with devices. (fhandler_base::fhandler_base): Clear {unix,win32}_path_name. (fhandler_base::~fhandler_base): Always free {unix,win32}_path_name. (fhandler_disk_file::fhandler_disk_file): Remove set_no_free_names kludge. (fhandler_disk_file::open): Ditto. * fhandler.h (fhandler_base::no_free_names): Eliminate. (fhandler_base::set_no_free_names): Ditto. * fhandler_tty.cc (fhandler_tty_slave::fhandler_tty_slave): Don't set unix_path_name here. * path.cc (fchdir): Lock fd table throughout. Use new dtable::reset_unix_path_name method to reset path. * syscalls.cc (stat_worker): Reorganize to always call fstat method. Pass path_conv method to fhandler_*::open. (chroot): Elminate a goto.
This commit is contained in:
@@ -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'", (DWORD) real_path,
|
||||
(char *) real_path);
|
||||
|
||||
debug_printf ("%d = file_attributes for '%s'", atts, real_path.get_win32 ());
|
||||
|
||||
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;
|
||||
}
|
||||
oret = fh->open (real_path, open_flags, 0);
|
||||
set_file_attribute (TRUE, real_path, ntsec_atts);
|
||||
}
|
||||
}
|
||||
if (atts != -1 && (oret || (!oret && get_errno () != ENOENT
|
||||
&& get_errno () != ENOSHARE)))
|
||||
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;
|
||||
|
Reference in New Issue
Block a user