diff options
author | Robert Collins <rbtcollins@hotmail.com> | 2001-10-02 16:09:56 +0400 |
---|---|---|
committer | Robert Collins <rbtcollins@hotmail.com> | 2001-10-02 16:09:56 +0400 |
commit | c1be6b3e98688bc62400192397224afa907dd3f4 (patch) | |
tree | 35a573e1e7af5a48a4b4c4e902f2a3af66a05f08 /winsup/cygwin | |
parent | 5896255627608c9b120b9383a51da72e235c1ea8 (diff) |
Merged changes from HEAD
Diffstat (limited to 'winsup/cygwin')
40 files changed, 434 insertions, 372 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index b2a822f9e..3b2ea16ad 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -167,6 +167,84 @@ Tue Sep 25 16:22:00 2001 Robert Collins <rbtcollins@hotmail.com> * include/sys/ipc.h: New file. * include/sys/shm.h: New file. +Mon Oct 1 16:52:23 2001 Christopher Faylor <cgf@cygnus.com> + + * dtable.h (dtable::build_fhandler): Make path_conv parameter + non-optional. + (dtable::init_std_file_from_handle): Eliminate name parameter. + * dtable.cc (stdio_init): Don't pass bogus name to + init_std_file_from_handle. The function will figure out the name + itself. + (dtable::init_std_file_from_handle): Eliminate name parameter. Assume + that we're always called with an appropriate fd. Pass name as NULL if + we can't simply figure it out from context. + (cygwin_attach_handle_to_fd): Pass path_conv argument to + build_fhandler. + (dtable::build_fhandler): Make path_conv argument mandatory. Eliminate + specific call to get_device_number. With unknown device names, set + name from handle context for parsing by path_conv. + (dtable::build_fhandler): Pass path_conv argument to build_fhandler. + * path.h (path_conv::set_isdisk): Set disk device type. + (path_conv::is_device): Don't consider FH_DISK a "device". + * syscalls.cc (_open): Pass path_conv argument by reference. + (stat_worker): Ditto. + (_rename): Use path_conv operators. Add bounds to DeleteFile/MoveFile + for loop. + +Mon Oct 1 14:25:00 2001 Charles Wilson <cwilson@ece.gatech.edu> + + * cygwin.din: export strtoll and strtoull + +Sun Sep 30 22:51:41 2001 Christopher Faylor <cgf@cygnus.com> + + 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. + +Sun Sep 30 17:37:43 2001 Christopher Faylor <cgf@cygnus.com> + + * environ.cc (winenv): Allocate exact amount of space needed for forced + windows environment variable rather than just using MAX_PATH. + +Sun Sep 30 17:10:18 2001 Christopher Faylor <cgf@cygnus.com> + + * Makefile.in: Depend on stamp to ensure rebuilding. Remove stamp file + when we've just built the DLL. + Mon Oct 1 00:34:00 2001 Robert Collins <rbtcollins@hotmail.com> * thread.cc (pthread_cond_dowait): Hopefully eliminate a race on multiple thread diff --git a/winsup/cygwin/Makefile.in b/winsup/cygwin/Makefile.in index 7918c47f8..6aaca814f 100644 --- a/winsup/cygwin/Makefile.in +++ b/winsup/cygwin/Makefile.in @@ -202,10 +202,14 @@ new-$(DLL_NAME): $(LDSCRIPT) $(DLL_OFILES) $(DEF_FILE) $(DLL_IMPORTS) $(LIBC) $( -e $(DLL_ENTRY) $(DEF_FILE) $(DLL_OFILES) version.o winver.o \ $(DLL_IMPORTS) $(MALLOC_OBJ) $(LIBM) $(LIBC) \ -lstdc++ -lgcc -lshell32 -luuid + @rm -f stamp-cygwin-lib -$(LIB_NAME): new-$(DLL_NAME) $(LIBCOS) +$(LIB_NAME): new-$(DLL_NAME) $(LIBCOS) stamp-cygwin-lib $(AR) rcv $(LIB_NAME) $(LIBCOS) +stamp-cygwin-lib: + @touch stamp-cygwin-lib + dll_ofiles: $(DLL_OFILES) $(LIBGMON_A): $(GMON_OFILES) $(GMON_START) diff --git a/winsup/cygwin/cygheap.cc b/winsup/cygwin/cygheap.cc index c5f6af776..a0e00d3c7 100644 --- a/winsup/cygwin/cygheap.cc +++ b/winsup/cygwin/cygheap.cc @@ -15,8 +15,8 @@ #include <stdlib.h> #include "security.h" #include "fhandler.h" -#include "dtable.h" #include "path.h" +#include "dtable.h" #include "cygheap.h" #include "child_info.h" #include "heap.h" diff --git a/winsup/cygwin/cygwin.din b/winsup/cygwin/cygwin.din index e614d7831..690f4aec3 100644 --- a/winsup/cygwin/cygwin.din +++ b/winsup/cygwin/cygwin.din @@ -789,8 +789,12 @@ strtok_r _strtok_r = strtok_r strtol _strtol = strtol +strtoll +_strtoll = strtoll strtoul _strtoul = strtoul +strtoull +_strtoull = strtoull strupr _strupr = strupr strxfrm diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc index ec8968756..9fb6ca906 100644 --- a/winsup/cygwin/dcrt0.cc +++ b/winsup/cygwin/dcrt0.cc @@ -26,8 +26,8 @@ details. */ #include "perprocess.h" #include "security.h" #include "fhandler.h" -#include "dtable.h" #include "path.h" +#include "dtable.h" #include "cygheap.h" #include "child_info.h" #include "perthread.h" @@ -837,7 +837,12 @@ _dll_crt0 () if (_cygwin_testing) fork_info = NULL; else if ((fork_info->type & PROC_MAGIC_MASK) == PROC_MAGIC_GENERIC) - api_fatal ("conflicting versions of cygwin1.dll detected. Use only the most recent version.\n"); + api_fatal ("\ +You have multiple copies of cygwin1.dll on your system.\n\ +Search for cygwin1.dll using the Windows Start->Find/Search facility\n\ +and delete all but the most recent version. This will probably be\n\ +the one that resides in x:\\cygwin\\bin, where 'x' is the drive on which\n\ +you have installed the cygwin distribution.\n"); break; } } diff --git a/winsup/cygwin/dir.cc b/winsup/cygwin/dir.cc index 7b9b2d6b6..079c5c4fe 100644 --- a/winsup/cygwin/dir.cc +++ b/winsup/cygwin/dir.cc @@ -367,79 +367,76 @@ rmdir (const char *dir) if (real_dir.error) { set_errno (real_dir.error); - goto done; + res = -1; } - - /* Does the file exist? */ - if (real_dir.file_attributes () == (DWORD) -1) + else if (!real_dir.exists ()) { set_errno (ENOENT); - goto done; + res = -1; } - - /* Is `dir' a directory? */ - if (!(real_dir.file_attributes () & FILE_ATTRIBUTE_DIRECTORY)) + else if (!real_dir.isdir ()) { set_errno (ENOTDIR); - goto done; - } - - /* Even own directories can't be removed if R/O attribute is set. */ - if (real_dir.file_attributes () & FILE_ATTRIBUTE_READONLY) - SetFileAttributes (real_dir.get_win32 (), real_dir.file_attributes () & - ~FILE_ATTRIBUTE_READONLY); - - if (RemoveDirectoryA (real_dir.get_win32 ())) - { - /* RemoveDirectory on a samba drive doesn't return an error if the - directory can't be removed because it's not empty. Checking for - existence afterwards keeps us informed about success. */ - if (GetFileAttributesA (real_dir.get_win32 ()) != (DWORD) -1) - set_errno (ENOTEMPTY); - else - res = 0; + res = -1; } else { - /* This kludge detects if we are attempting to remove the current working - directory. If so, we will move elsewhere to potentially allow the - rmdir to succeed. This means that cygwin's concept of the current working - directory != Windows concept but, hey, whaddaregonnado? - Note that this will not cause something like the following to work: - $ cd foo - $ rmdir . - since the shell will have foo "open" in the above case and so Windows will - not allow the deletion. - FIXME: A potential workaround for this is for cygwin apps to *never* call - SetCurrentDirectory. */ - if (strcasematch (real_dir, cygheap->cwd.win32) - && !strcasematch ("c:\\", cygheap->cwd.win32)) + /* Even own directories can't be removed if R/O attribute is set. */ + if (real_dir.has_attribute (FILE_ATTRIBUTE_READONLY)) + SetFileAttributes (real_dir, + (DWORD) real_dir & ~FILE_ATTRIBUTE_READONLY); + + if (RemoveDirectory (real_dir)) { - DWORD err = GetLastError (); - if (!SetCurrentDirectory ("c:\\")) - SetLastError (err); + /* RemoveDirectory on a samba drive doesn't return an error if the + directory can't be removed because it's not empty. Checking for + existence afterwards keeps us informed about success. */ + if (GetFileAttributes (real_dir) != (DWORD) -1) + set_errno (ENOTEMPTY); else - return rmdir (dir); + res = 0; } - if (GetLastError() == ERROR_ACCESS_DENIED) + else { + /* This kludge detects if we are attempting to remove the current working + directory. If so, we will move elsewhere to potentially allow the + rmdir to succeed. This means that cygwin's concept of the current working + directory != Windows concept but, hey, whaddaregonnado? + Note that this will not cause something like the following to work: + $ cd foo + $ rmdir . + since the shell will have foo "open" in the above case and so Windows will + not allow the deletion. + FIXME: A potential workaround for this is for cygwin apps to *never* call + SetCurrentDirectory. */ + if (strcasematch (real_dir, cygheap->cwd.win32) + && !strcasematch ("c:\\", cygheap->cwd.win32)) + { + DWORD err = GetLastError (); + if (!SetCurrentDirectory ("c:\\")) + SetLastError (err); + else if ((res = rmdir (dir))) + SetCurrentDirectory (cygheap->cwd.win32); + } + if (GetLastError () == ERROR_ACCESS_DENIED) + { - /* On 9X ERROR_ACCESS_DENIED is returned if you try to remove - a non-empty directory. */ - if (wincap.access_denied_on_delete ()) - set_errno (ENOTEMPTY); + /* On 9X ERROR_ACCESS_DENIED is returned if you try to remove + a non-empty directory. */ + if (wincap.access_denied_on_delete ()) + set_errno (ENOTEMPTY); + else + __seterrno (); + } else __seterrno (); - } - else - __seterrno (); - /* If directory still exists, restore R/O attribute. */ - if (real_dir.file_attributes () & FILE_ATTRIBUTE_READONLY) - SetFileAttributes (real_dir.get_win32 (), real_dir.file_attributes ()); + /* If directory still exists, restore R/O attribute. */ + if (real_dir.has_attribute (FILE_ATTRIBUTE_READONLY)) + SetFileAttributes (real_dir, real_dir); + } } -done: syscall_printf ("%d = rmdir (%s)", res, dir); return res; } diff --git a/winsup/cygwin/dll_init.cc b/winsup/cygwin/dll_init.cc index 96bf1bc18..d4dcca0e9 100644 --- a/winsup/cygwin/dll_init.cc +++ b/winsup/cygwin/dll_init.cc @@ -15,6 +15,7 @@ details. */ #include "environ.h" #include "security.h" #include "fhandler.h" +#include "path.h" #include "dtable.h" #include "cygheap.h" diff --git a/winsup/cygwin/dtable.cc b/winsup/cygwin/dtable.cc index e08ed4209..96ee5a503 100644 --- a/winsup/cygwin/dtable.cc +++ b/winsup/cygwin/dtable.cc @@ -106,7 +106,7 @@ stdio_init (void) HANDLE out = GetStdHandle (STD_OUTPUT_HANDLE); HANDLE err = GetStdHandle (STD_ERROR_HANDLE); - cygheap->fdtab.init_std_file_from_handle (0, in, GENERIC_READ, "{stdin}"); + cygheap->fdtab.init_std_file_from_handle (0, in, GENERIC_READ); /* STD_ERROR_HANDLE has been observed to be the same as STD_OUTPUT_HANDLE. We need separate handles (e.g. using pipes @@ -124,8 +124,8 @@ stdio_init (void) } } - cygheap->fdtab.init_std_file_from_handle (1, out, GENERIC_WRITE, "{stdout}"); - cygheap->fdtab.init_std_file_from_handle (2, err, GENERIC_WRITE, "{stderr}"); + cygheap->fdtab.init_std_file_from_handle (1, out, GENERIC_WRITE); + cygheap->fdtab.init_std_file_from_handle (2, err, GENERIC_WRITE); /* Assign the console as the controlling tty for this process if we actually have a console and no other controlling tty has been assigned. */ if (myself->ctty < 0 && GetConsoleCP () > 0) @@ -170,47 +170,48 @@ dtable::release (int fd) void dtable::init_std_file_from_handle (int fd, HANDLE handle, - DWORD myaccess, const char *name) + DWORD myaccess) { int bin; + const char *name = NULL; if (__fmode) bin = __fmode; else bin = binmode ?: 0; - /* Check to see if we're being redirected - if not then - we open then as consoles */ - if (fd == 0 || fd == 1 || fd == 2) + first_fd_for_open = 0; + /* See if we can consoleify it - if it is a console, + don't open it in binary. That will screw up our crlfs*/ + CONSOLE_SCREEN_BUFFER_INFO buf; + if (GetConsoleScreenBufferInfo (handle, &buf)) { - first_fd_for_open = 0; - /* See if we can consoleify it - if it is a console, - don't open it in binary. That will screw up our crlfs*/ - CONSOLE_SCREEN_BUFFER_INFO buf; - if (GetConsoleScreenBufferInfo (handle, &buf)) - { - bin = 0; - if (ISSTATE (myself, PID_USETTY)) - name = "/dev/tty"; - else - name = "/dev/conout"; - } - else if (FlushConsoleInputBuffer (handle)) - { - bin = 0; - if (ISSTATE (myself, PID_USETTY)) - name = "/dev/tty"; - else - name = "/dev/conin"; - } - else if (GetFileType (handle) == FILE_TYPE_PIPE) - { - if (bin == 0) - bin = O_BINARY; - } + if (ISSTATE (myself, PID_USETTY)) + name = "/dev/tty"; + else + name = "/dev/conout"; + bin = 0; + } + else if (FlushConsoleInputBuffer (handle)) + { + if (ISSTATE (myself, PID_USETTY)) + name = "/dev/tty"; + else + name = "/dev/conin"; + bin = 0; + } + else if (GetFileType (handle) == FILE_TYPE_PIPE) + { + if (fd == 0) + name = "/dev/piper"; + else if (fd == 1 || fd == 2) + name = "/dev/pipew"; + if (bin == 0) + bin = O_BINARY; } - build_fhandler (fd, name, handle)->init (handle, myaccess, bin); + path_conv pc; + build_fhandler (fd, name, handle, pc)->init (handle, myaccess, bin); set_std_handle (fd); paranoid_printf ("fd %d, handle %p", fd, handle); } @@ -218,57 +219,50 @@ dtable::init_std_file_from_handle (int fd, HANDLE handle, extern "C" int cygwin_attach_handle_to_fd (char *name, int fd, HANDLE handle, mode_t bin, - DWORD myaccess) + DWORD myaccess) { if (fd == -1) fd = cygheap->fdtab.find_unused_handle (); - fhandler_base *res = cygheap->fdtab.build_fhandler (fd, name, handle); + path_conv pc; + fhandler_base *res = cygheap->fdtab.build_fhandler (fd, name, handle, pc); res->init (handle, myaccess, bin); return fd; } fhandler_base * -dtable::build_fhandler (int fd, const char *name, HANDLE handle, path_conv *pc) +dtable::build_fhandler (int fd, const char *name, HANDLE handle, path_conv& pc, + unsigned opt, suffix_info *si) { - int unit; - DWORD devn; - fhandler_base *fh; - - if (!pc) - devn = get_device_number (name, unit); - else - { - pc->check (name); - devn = pc->get_devn (); - unit = pc->get_unitn (); - } - - if (devn == FH_BAD) + if (!name && handle) { struct sockaddr sa; int sal = sizeof (sa); CONSOLE_SCREEN_BUFFER_INFO cinfo; DCB dcb; - if (handle == NULL) - devn = FH_DISK; - else if (GetNumberOfConsoleInputEvents (handle, (DWORD *) &cinfo)) - devn = FH_CONIN; + if (GetNumberOfConsoleInputEvents (handle, (DWORD *) &cinfo)) + name = "/dev/conin"; else if (GetConsoleScreenBufferInfo (handle, &cinfo)) - devn= FH_CONOUT; + name = "/dev/conout"; else if (wsock_started && getpeername ((SOCKET) handle, &sa, &sal) == 0) - devn = FH_SOCKET; + name = "/dev/socket"; else if (GetFileType (handle) == FILE_TYPE_PIPE) - devn = FH_PIPE; + name = "/dev/pipe"; else if (GetCommState (handle, &dcb)) - devn = FH_SERIAL; + name = "/dev/ttyS0"; // FIXME - determine correct device else - devn = FH_DISK; + name = "some disk file"; } - fh = build_fhandler (fd, devn, name, unit); - if (pc) - fh->set_name (name, *pc); + pc.check (name, opt | PC_NULLEMPTY, si); + if (pc.error) + { + set_errno (pc.error); + return NULL; + } + + fhandler_base *fh = build_fhandler (fd, pc.get_devn (), name, pc.get_unitn ()); + fh->set_name (name, pc, pc.get_unitn ()); return fh; } @@ -341,8 +335,11 @@ dtable::build_fhandler (int fd, DWORD dev, const char *name, int unit) fh = new (buf) fhandler_dev_dsp (name); break; default: - /* FIXME - this could recurse forever */ - return build_fhandler (fd, name, NULL); + { + /* FIXME - this could recurse forever */ + path_conv pc; + return build_fhandler (fd, name, NULL, pc); + } } debug_printf ("%s - cb %d, fd %d, fh %p", fh->get_name () ?: "", fh->cb, @@ -434,6 +431,14 @@ done: return res; } +void +dtable::reset_unix_path_name (int fd, const char *name) +{ + SetResourceLock (LOCK_FD_LIST, WRITE_LOCK | READ_LOCK, "reset_unix_name"); + fds[fd]->reset_unix_path_name (name); + ReleaseResourceLock (LOCK_FD_LIST, WRITE_LOCK | READ_LOCK, "reset_unix_name"); +} + select_record * dtable::select_read (int fd, select_record *s) { diff --git a/winsup/cygwin/dtable.h b/winsup/cygwin/dtable.h index 7e27bf657..0a00d91f5 100644 --- a/winsup/cygwin/dtable.h +++ b/winsup/cygwin/dtable.h @@ -13,6 +13,7 @@ details. */ #include "thread.h" +class suffix_info; class dtable { fhandler_base **fds; @@ -49,8 +50,9 @@ public: void fixup_after_fork (HANDLE); fhandler_base *build_fhandler (int fd, DWORD dev, const char *name, int unit = -1); - fhandler_base *build_fhandler (int fd, const char *name, HANDLE h = NULL, - path_conv *pc = NULL); + fhandler_base *build_fhandler (int fd, const char *name, HANDLE h, + path_conv& pc, unsigned opts = PC_SYM_FOLLOW, + suffix_info *si = NULL); inline int not_open (int fd) { SetResourceLock (LOCK_FD_LIST, READ_LOCK, "not_open"); @@ -60,10 +62,11 @@ public: ReleaseResourceLock (LOCK_FD_LIST, READ_LOCK, "not open"); return res; } + void reset_unix_path_name (int fd, const char *name); int find_unused_handle (int start); int find_unused_handle () { return find_unused_handle (first_fd_for_open);} void release (int fd); - void init_std_file_from_handle (int fd, HANDLE handle, DWORD access, const char *name); + void init_std_file_from_handle (int fd, HANDLE handle, DWORD access); int dup2 (int oldfd, int newfd); void fixup_after_exec (HANDLE); inline fhandler_base *operator [](int fd) const { return fds[fd]; } diff --git a/winsup/cygwin/environ.cc b/winsup/cygwin/environ.cc index 1be0b79b5..c1529e704 100644 --- a/winsup/cygwin/environ.cc +++ b/winsup/cygwin/environ.cc @@ -806,14 +806,17 @@ winenv (const char * const *envp, int keep_posix) saw_forced_winenv[i] = strncasematch (forced_winenv_vars[i], *srcp, len); } + char dum[1]; for (int i = 0; forced_winenv_vars[i]; i++) if (!saw_forced_winenv[i]) { - len = strlen (forced_winenv_vars[i]); - p = (char *) alloca (len + MAX_PATH + 1); + int namelen = strlen (forced_winenv_vars[i]) + 1; + int vallen = GetEnvironmentVariable (forced_winenv_vars[i], dum, 0) + 1; + p = (char *) alloca (namelen + vallen); strcpy (p, forced_winenv_vars[i]); strcat (p, "="); - if (!GetEnvironmentVariable (forced_winenv_vars[i], p + len + 1, MAX_PATH)) + if (!GetEnvironmentVariable (forced_winenv_vars[i], p + namelen, + vallen + 1)) debug_printf ("warning: %s not present in environment", *srcp); else { diff --git a/winsup/cygwin/fcntl.cc b/winsup/cygwin/fcntl.cc index 517cf6e6a..b531218f6 100644 --- a/winsup/cygwin/fcntl.cc +++ b/winsup/cygwin/fcntl.cc @@ -15,6 +15,7 @@ details. */ #include <unistd.h> #include "security.h" #include "fhandler.h" +#include "path.h" #include "dtable.h" #include "cygheap.h" #include "cygerrno.h" diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc index a670e7860..54adc8dc2 100644 --- a/winsup/cygwin/fhandler.cc +++ b/winsup/cygwin/fhandler.cc @@ -20,15 +20,14 @@ details. */ #include "security.h" #include "cygwin/version.h" #include "fhandler.h" +#include "path.h" #include "dtable.h" #include "cygheap.h" -#include "path.h" #include "shared_info.h" +#include <assert.h> static NO_COPY const int CHUNK_SIZE = 1024; /* Used for crlf conversions */ -static NO_COPY char fhandler_disk_dummy_name[] = "some disk file"; - struct __cygwin_perfile *perfile_table; DWORD binmode; @@ -146,31 +145,13 @@ fhandler_base::get_readahead_into_buffer (char *buf, size_t buflen) /* Record the file name. Filenames are used mostly for debugging messages, and it's hoped that in cases where the name is really required, the filename wouldn't ever - be too long (e.g. devices or some such). -*/ - + be too long (e.g. devices or some such). */ void fhandler_base::set_name (const char *unix_path, const char *win32_path, int unit) { - if (!no_free_names ()) - { - if (unix_path_name != NULL && unix_path_name != fhandler_disk_dummy_name) - cfree (unix_path_name); - if (win32_path_name != NULL && unix_path_name != fhandler_disk_dummy_name) - cfree (win32_path_name); - } - - unix_path_name = win32_path_name = NULL; if (unix_path == NULL || !*unix_path) return; - unix_path_name = cstrdup (unix_path); - if (unix_path_name == NULL) - { - system_printf ("fatal error. strdup failed"); - exit (ENOMEM); - } - if (win32_path) win32_path_name = cstrdup (win32_path); else @@ -185,6 +166,34 @@ fhandler_base::set_name (const char *unix_path, const char *win32_path, int unit system_printf ("fatal error. strdup failed"); exit (ENOMEM); } + + assert (unix_path_name == NULL); + /* FIXME: This isn't really right. It ignores the first argument if we're + building names for a device and just converts the device name from the + win32 name since it has theoretically been previously detected by + path_conv. Ideally, we should pass in a format string and build the + unix_path, too. */ + if (!is_device () || *win32_path_name != '\\') + unix_path_name = cstrdup (unix_path); + else + { + unix_path_name = cstrdup (win32_path_name); + for (char *p = unix_path_name; (p = strchr (p, '\\')); p++) + *p = '/'; + } + + if (unix_path_name == NULL) + { + system_printf ("fatal error. strdup failed"); + exit (ENOMEM); + } +} + +void +fhandler_base::reset_unix_path_name (const char *unix_path) +{ + cfree (unix_path_name); + unix_path_name = cstrdup (unix_path); } /* Detect if we are sitting at EOF for conditions where Windows @@ -235,6 +244,13 @@ fhandler_base::raw_read (void *ptr, size_t ulen) case ERROR_NOACCESS: if (is_at_eof (get_handle (), errcode)) return 0; + case ERROR_INVALID_FUNCTION: + case ERROR_INVALID_PARAMETER: + if (openflags & O_DIROPEN) + { + set_errno (EISDIR); + return -1; + } default: syscall_printf ("ReadFile %s failed, %E", unix_path_name); __seterrno_from_win_error (errcode); @@ -316,44 +332,28 @@ fhandler_base::open (int flags, mode_t mode) } if (get_query_open ()) - { - access = 0; - } + access = 0; else if (get_device () == FH_TAPE) - { - access = GENERIC_READ | GENERIC_WRITE; - } + access = GENERIC_READ | GENERIC_WRITE; else if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_RDONLY) - { - access = GENERIC_READ; - } + access = GENERIC_READ; else if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_WRONLY) - { - access = GENERIC_WRITE; - } + access = GENERIC_WRITE; else - { - access = GENERIC_READ | GENERIC_WRITE; - } + access = GENERIC_READ | GENERIC_WRITE; /* Allow reliable lseek on disk devices. */ if (get_device () == FH_FLOPPY) - { - access |= GENERIC_READ; - } + access |= GENERIC_READ; /* FIXME: O_EXCL handling? */ if ((flags & O_TRUNC) && ((flags & O_ACCMODE) != O_RDONLY)) { if (flags & O_CREAT) - { - creation_distribution = CREATE_ALWAYS; - } + creation_distribution = CREATE_ALWAYS; else - { - creation_distribution = TRUNCATE_EXISTING; - } + creation_distribution = TRUNCATE_EXISTING; } else if (flags & O_CREAT) creation_distribution = OPEN_ALWAYS; @@ -361,9 +361,7 @@ fhandler_base::open (int flags, mode_t mode) creation_distribution = OPEN_EXISTING; if ((flags & O_EXCL) && (flags & O_CREAT)) - { - creation_distribution = CREATE_NEW; - } + creation_distribution = CREATE_NEW; if (flags & O_APPEND) set_append_p(); @@ -868,9 +866,6 @@ fhandler_disk_file::fstat (struct stat *buf) memset (buf, 0, sizeof (*buf)); - if (is_device ()) - return stat_dev (get_device (), get_unit (), get_namehash (), 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++) @@ -1199,6 +1194,8 @@ fhandler_base::fhandler_base (DWORD devtype, const char *name, int unit): raixget (0), raixput (0), rabuflen (0), + unix_path_name (NULL), + win32_path_name (NULL), open_status (0) { status = devtype; @@ -1210,20 +1207,15 @@ fhandler_base::fhandler_base (DWORD devtype, const char *name, int unit): if (!get_w_binset ()) set_w_binary (bin); } - unix_path_name = win32_path_name = NULL; - set_name (name, NULL, unit); } /* Normal I/O destructor */ fhandler_base::~fhandler_base (void) { - if (!no_free_names ()) - { - if (unix_path_name != NULL && unix_path_name != fhandler_disk_dummy_name) - cfree (unix_path_name); - if (win32_path_name != NULL && win32_path_name != fhandler_disk_dummy_name) - cfree (win32_path_name); - } + if (unix_path_name != NULL) + cfree (unix_path_name); + if (win32_path_name != NULL) + cfree (win32_path_name); if (rabuf) free (rabuf); unix_path_name = win32_path_name = NULL; @@ -1236,8 +1228,6 @@ fhandler_disk_file::fhandler_disk_file (const char *name) : fhandler_base (FH_DISK, name) { set_cb (sizeof *this); - set_no_free_names (); - unix_path_name = win32_path_name = fhandler_disk_dummy_name; } int @@ -1260,19 +1250,12 @@ fhandler_disk_file::open (const char *path, int flags, mode_t mode) } set_name (path, real_path.get_win32 ()); - set_no_free_names (0); return open (real_path, flags, mode); } int fhandler_disk_file::open (path_conv& real_path, int flags, mode_t mode) { - if (get_win32_name () == fhandler_disk_dummy_name) - { - win32_path_name = real_path.get_win32 (); - set_no_free_names (); - } - if (real_path.isbinary ()) { set_r_binary (1); @@ -1282,8 +1265,7 @@ fhandler_disk_file::open (path_conv& real_path, int flags, mode_t mode) set_has_acls (real_path.has_acls ()); set_isremote (real_path.isremote ()); - if (real_path.file_attributes () != (DWORD)-1 - && (real_path.file_attributes () & FILE_ATTRIBUTE_DIRECTORY)) + if (real_path.isdir ()) flags |= O_DIROPEN; int res = this->fhandler_base::open (flags, mode); diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index dfd97a0fd..753508266 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -65,8 +65,7 @@ enum FH_W95LSBUG = 0x00400000, /* set when lseek is called as a flag that * _write should check if we've moved beyond * EOF, zero filling if so. */ - FH_NOFRNAME = 0x00800000, /* Set if shouldn't free unix_path_name and - windows_path_name_ on destruction. */ + FH_UNUSED = 0x00800000, /* currently unused. */ FH_NOEINTR = 0x01000000, /* Set if I/O should be uninterruptible. */ FH_FFIXUP = 0x02000000, /* Set if need to fixup after fork. */ FH_LOCAL = 0x04000000, /* File is unix domain socket */ @@ -187,6 +186,7 @@ public: void set_name (const char * unix_path, const char * win32_path = NULL, int unit = 0); + void reset_unix_path_name (const char *); virtual fhandler_base& operator =(fhandler_base &x); fhandler_base (DWORD dev, const char *name = 0, int unit = 0); virtual ~fhandler_base (); @@ -301,10 +301,6 @@ public: int isremote () { return FHISSETF (ISREMOTE); } void set_isremote (int val) { FHCONDSETF (val, ISREMOTE); } - int no_free_names () { return FHISSETF (NOFRNAME); } - void set_no_free_names (int val) { FHCONDSETF (val, NOFRNAME); } - void set_no_free_names () { FHSETF (NOFRNAME); } - const char *get_name () { return unix_path_name; } const char *get_win32_name () { return win32_path_name; } unsigned long get_namehash () { return namehash; } diff --git a/winsup/cygwin/fhandler_console.cc b/winsup/cygwin/fhandler_console.cc index d061dee2f..9dd98e7f8 100644 --- a/winsup/cygwin/fhandler_console.cc +++ b/winsup/cygwin/fhandler_console.cc @@ -24,6 +24,7 @@ details. */ #include "cygerrno.h" #include "security.h" #include "fhandler.h" +#include "path.h" #include "dtable.h" #include "cygheap.h" #include "sync.h" diff --git a/winsup/cygwin/fhandler_raw.cc b/winsup/cygwin/fhandler_raw.cc index 7ed439b52..20f2de513 100644 --- a/winsup/cygwin/fhandler_raw.cc +++ b/winsup/cygwin/fhandler_raw.cc @@ -20,9 +20,9 @@ #include "perprocess.h" #include "security.h" #include "fhandler.h" +#include "path.h" #include "dtable.h" #include "cygheap.h" -#include "path.h" /* static wrapper functions to hide the effect of media changes and bus resets which occurs after a new media is inserted. This is diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc index dbf284ec5..a34272f6a 100644 --- a/winsup/cygwin/fhandler_socket.cc +++ b/winsup/cygwin/fhandler_socket.cc @@ -27,6 +27,7 @@ #include "cygwin/version.h" #include "perprocess.h" #include "fhandler.h" +#include "path.h" #include "dtable.h" #include "cygheap.h" #include "sigproc.h" diff --git a/winsup/cygwin/fhandler_tape.cc b/winsup/cygwin/fhandler_tape.cc index 5acbf0fb6..48561351a 100644 --- a/winsup/cygwin/fhandler_tape.cc +++ b/winsup/cygwin/fhandler_tape.cc @@ -19,9 +19,9 @@ details. */ #include "perprocess.h" #include "security.h" #include "fhandler.h" +#include "path.h" #include "dtable.h" #include "cygheap.h" -#include "path.h" /**********************************************************************/ /* fhandler_dev_tape */ diff --git a/winsup/cygwin/fhandler_tty.cc b/winsup/cygwin/fhandler_tty.cc index e0ceecd5c..62d0c91d9 100644 --- a/winsup/cygwin/fhandler_tty.cc +++ b/winsup/cygwin/fhandler_tty.cc @@ -19,6 +19,7 @@ details. */ #include "cygerrno.h" #include "security.h" #include "fhandler.h" +#include "path.h" #include "dtable.h" #include "sync.h" #include "sigproc.h" @@ -443,11 +444,6 @@ fhandler_tty_slave::fhandler_tty_slave (int num, const char *name) : { set_cb (sizeof *this); ttynum = num; - /* FIXME: This is wasteful. We should rewrite the set_name path to eliminate the - need for double allocates. */ - unix_path_name = (char *) crealloc (unix_path_name, strlen (win32_path_name) + 1); - strcpy (unix_path_name, win32_path_name); - unix_path_name[0] = unix_path_name[4] = '/'; debug_printf ("unix '%s', win32 '%s'", unix_path_name, win32_path_name); inuse = NULL; } diff --git a/winsup/cygwin/fork.cc b/winsup/cygwin/fork.cc index 0903ae9a5..e0d9445ac 100644 --- a/winsup/cygwin/fork.cc +++ b/winsup/cygwin/fork.cc @@ -17,6 +17,7 @@ details. */ #include <errno.h> #include "security.h" #include "fhandler.h" +#include "path.h" #include "dtable.h" #include "cygerrno.h" #include "sync.h" diff --git a/winsup/cygwin/grp.cc b/winsup/cygwin/grp.cc index d9e7b02b4..87cc4b484 100644 --- a/winsup/cygwin/grp.cc +++ b/winsup/cygwin/grp.cc @@ -22,8 +22,8 @@ details. */ #include "pinfo.h" #include "security.h" #include "fhandler.h" -#include "dtable.h" #include "path.h" +#include "dtable.h" #include "cygheap.h" #include "cygerrno.h" #include "pwdgrp.h" diff --git a/winsup/cygwin/heap.cc b/winsup/cygwin/heap.cc index 1a3c2a8e9..eaa500c62 100644 --- a/winsup/cygwin/heap.cc +++ b/winsup/cygwin/heap.cc @@ -18,6 +18,7 @@ details. */ #include "shared_info.h" #include "security.h" #include "fhandler.h" +#include "path.h" #include "dtable.h" #include "cygheap.h" diff --git a/winsup/cygwin/ioctl.cc b/winsup/cygwin/ioctl.cc index f02c71ca0..93fe9ddf5 100644 --- a/winsup/cygwin/ioctl.cc +++ b/winsup/cygwin/ioctl.cc @@ -17,6 +17,7 @@ details. */ #include "cygerrno.h" #include "security.h" #include "fhandler.h" +#include "path.h" #include "dtable.h" #include "cygheap.h" #include <sys/termios.h> diff --git a/winsup/cygwin/malloc_wrapper.cc b/winsup/cygwin/malloc_wrapper.cc index 1cbe43c61..2fa93b1a1 100644 --- a/winsup/cygwin/malloc_wrapper.cc +++ b/winsup/cygwin/malloc_wrapper.cc @@ -16,6 +16,7 @@ details. */ #include <assert.h> #include "security.h" #include "fhandler.h" +#include "path.h" #include "dtable.h" #include "cygheap.h" #include "heap.h" diff --git a/winsup/cygwin/mmap.cc b/winsup/cygwin/mmap.cc index 4ebc017b1..c13a3f365 100644 --- a/winsup/cygwin/mmap.cc +++ b/winsup/cygwin/mmap.cc @@ -16,6 +16,7 @@ details. */ #include <errno.h> #include "security.h" #include "fhandler.h" +#include "path.h" #include "dtable.h" #include "cygerrno.h" #include "cygheap.h" diff --git a/winsup/cygwin/passwd.cc b/winsup/cygwin/passwd.cc index 092473b12..2f52473c7 100644 --- a/winsup/cygwin/passwd.cc +++ b/winsup/cygwin/passwd.cc @@ -16,8 +16,8 @@ details. */ #include "cygerrno.h" #include "security.h" #include "fhandler.h" -#include "dtable.h" #include "path.h" +#include "dtable.h" #include "sync.h" #include "sigproc.h" #include "pinfo.h" diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index 1c7c554af..2aa19e1aa 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -2428,8 +2428,7 @@ symlink (const char *topath, const char *frompath) syscall_printf ("symlink (%s, %s)", topath, win32_path.get_win32 ()); - if (win32_path.is_device () || - win32_path.file_attributes () != (DWORD) -1) + if (win32_path.is_device () || win32_path.exists ()) { set_errno (EEXIST); goto done; @@ -2897,7 +2896,7 @@ readlink (const char *path, char *buf, int buflen) return -1; } - if (pathbuf.file_attributes () == (DWORD) -1) + if (!pathbuf.exists ()) { set_errno (ENOENT); return -1; @@ -3106,8 +3105,9 @@ fchdir (int fd) set_errno (EBADF); return -1; } + SetResourceLock (LOCK_FD_LIST, WRITE_LOCK | READ_LOCK, "fchdir"); int ret = chdir (cygheap->fdtab[fd]->get_name ()); - if (!ret) + if (ret == 0) { /* The name in the fhandler is explicitely overwritten with the full path. Otherwise fchmod() to a path originally given as a relative path could @@ -3119,13 +3119,11 @@ fchdir (int fd) The 2nd fchmod should chdir to the same dir as the first call, not to it's parent dir. */ - char path[MAX_PATH]; char posix_path[MAX_PATH]; - mount_table->conv_to_posix_path (cygheap->cwd.get (path, 0, 1), - posix_path, 0); - cygheap->fdtab[fd]->set_name (path, posix_path); + cygheap->fdtab.reset_unix_path_name (fd, cygheap->cwd.get (posix_path, 1, 1)); } + ReleaseResourceLock (LOCK_FD_LIST, WRITE_LOCK | READ_LOCK, "fchdir"); syscall_printf ("%d = fchdir (%d)", ret, fd); return ret; } diff --git a/winsup/cygwin/path.h b/winsup/cygwin/path.h index a3e94c18f..1052debda 100644 --- a/winsup/cygwin/path.h +++ b/winsup/cygwin/path.h @@ -69,6 +69,12 @@ class path_conv public: unsigned path_flags; + char *known_suffix; + int error; + DWORD devn; + int unit; + DWORD fileattr; + BOOL case_clash; int isdisk () const { return path_flags & PATH_ISDISK;} int isremote () const {return is_remote_drive;} @@ -80,6 +86,9 @@ class path_conv int issymlink () const {return path_flags & PATH_SYMLINK;} int issocket () const {return path_flags & PATH_SOCKET;} int iscygexec () const {return path_flags & PATH_CYGWIN_EXEC;} + bool exists () const {return fileattr != (DWORD) -1;} + bool has_attribute (DWORD x) const {return exists () && (fileattr & x);} + int isdir () const {return has_attribute (FILE_ATTRIBUTE_DIRECTORY);} executable_states exec_state () { extern int _check_for_executable; @@ -95,21 +104,11 @@ class path_conv void set_binary () {path_flags |= PATH_BINARY;} void set_symlink () {path_flags |= PATH_SYMLINK;} void set_has_symlinks () {path_flags |= PATH_HAS_SYMLINKS;} - void set_isdisk () {path_flags |= PATH_ISDISK;} + void set_isdisk () {path_flags |= PATH_ISDISK; devn = FH_DISK;} void set_exec (int x = 1) {path_flags |= x ? PATH_EXEC : PATH_NOTEXEC;} void set_has_acls (int x = 1) {path_flags |= x ? PATH_HASACLS : PATH_NOTHING;} void set_has_buggy_open (int x = 1) {path_flags |= x ? PATH_HASBUGGYOPEN : PATH_NOTHING;} - char *known_suffix; - - int error; - DWORD devn; - int unit; - - DWORD fileattr; - - BOOL case_clash; - void check (const char *src, unsigned opt = PC_SYM_FOLLOW, const suffix_info *suffixes = NULL) __attribute__ ((regparm(3))); @@ -129,7 +128,9 @@ class path_conv inline char *get_win32 () { return path; } operator char *() {return path; } - BOOL is_device () {return devn != FH_BAD;} + operator DWORD &() {return fileattr; } + operator int &() {return (int) fileattr; } + BOOL is_device () {return devn != FH_BAD && devn != FH_DISK;} DWORD get_devn () {return devn == FH_BAD ? (DWORD) FH_DISK : devn;} short get_unitn () {return devn == FH_BAD ? 0 : unit;} DWORD file_attributes () {return fileattr;} diff --git a/winsup/cygwin/pinfo.cc b/winsup/cygwin/pinfo.cc index 14eba9b92..6e66e47a1 100644 --- a/winsup/cygwin/pinfo.cc +++ b/winsup/cygwin/pinfo.cc @@ -15,6 +15,7 @@ details. */ #include <limits.h> #include "security.h" #include "fhandler.h" +#include "path.h" #include "dtable.h" #include "cygerrno.h" #include "sync.h" diff --git a/winsup/cygwin/pipe.cc b/winsup/cygwin/pipe.cc index 03af86228..099aa37b3 100644 --- a/winsup/cygwin/pipe.cc +++ b/winsup/cygwin/pipe.cc @@ -15,6 +15,7 @@ details. */ #include "cygerrno.h" #include "security.h" #include "fhandler.h" +#include "path.h" #include "dtable.h" #include "cygheap.h" #include "thread.h" diff --git a/winsup/cygwin/poll.cc b/winsup/cygwin/poll.cc index 9b85f20ee..2ac606849 100644 --- a/winsup/cygwin/poll.cc +++ b/winsup/cygwin/poll.cc @@ -14,6 +14,7 @@ #include <errno.h> #include "security.h" #include "fhandler.h" +#include "path.h" #include "dtable.h" #include "cygheap.h" #include "cygerrno.h" diff --git a/winsup/cygwin/select.cc b/winsup/cygwin/select.cc index 2307e297e..e66d078c8 100644 --- a/winsup/cygwin/select.cc +++ b/winsup/cygwin/select.cc @@ -36,6 +36,7 @@ details. */ #include "cygerrno.h" #include "security.h" #include "fhandler.h" +#include "path.h" #include "dtable.h" #include "cygheap.h" #include "sync.h" diff --git a/winsup/cygwin/shared.cc b/winsup/cygwin/shared.cc index 8ce88d240..81d39e3ed 100644 --- a/winsup/cygwin/shared.cc +++ b/winsup/cygwin/shared.cc @@ -19,6 +19,7 @@ details. */ #include "pinfo.h" #include "security.h" #include "fhandler.h" +#include "path.h" #include "dtable.h" #include "cygheap.h" #include "heap.h" diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc index 7f621d3ea..7b55487bb 100644 --- a/winsup/cygwin/sigproc.cc +++ b/winsup/cygwin/sigproc.cc @@ -23,6 +23,7 @@ details. */ #include "pinfo.h" #include "security.h" #include "fhandler.h" +#include "path.h" #include "dtable.h" #include "cygheap.h" #include "child_info.h" diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc index 248dd426e..0a0a84deb 100644 --- a/winsup/cygwin/spawn.cc +++ b/winsup/cygwin/spawn.cc @@ -63,10 +63,10 @@ perhaps_suffix (const char *prog, path_conv &buf) debug_printf ("prog '%s'", prog); buf.check (prog, PC_SYM_FOLLOW | PC_FULL, std_suffixes); - if (buf.file_attributes () & FILE_ATTRIBUTE_DIRECTORY) + if (buf.isdir ()) ext = NULL; else if (buf.known_suffix) - ext = buf + (buf.known_suffix - buf.get_win32 ()); + ext = (char *) buf + (buf.known_suffix - buf.get_win32 ()); else ext = strchr (buf, '\0'); diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc index 9f5c8ac88..f4e53db50 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 @@ -506,7 +499,7 @@ _open (const char *unix_path, int flags, ...) else { path_conv pc; - if (!(fh = cygheap->fdtab.build_fhandler (fd, unix_path, NULL, &pc))) + if (!(fh = cygheap->fdtab.build_fhandler (fd, unix_path, NULL, pc))) res = -1; // errno already set else if (!fh->open (pc, flags, (mode & 07777) & ~cygheap->umask)) { @@ -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 ()); - - dtype = real_path.get_drive_type (); + debug_printf ("%d = file_attributes for '%s'", (DWORD) real_path, + (char *) real_path); - 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; @@ -1352,15 +1327,14 @@ _rename (const char *oldpath, const char *newpath) return -1; } - if (!writable_directory (real_old.get_win32 ()) - || !writable_directory (real_new.get_win32 ())) + if (!writable_directory (real_old) || !writable_directory (real_new)) { syscall_printf ("-1 = rename (%s, %s)", oldpath, newpath); set_errno (EACCES); 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 +1343,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 () && @@ -1380,7 +1352,7 @@ _rename (const char *oldpath, const char *newpath) (lnk_suffix = strrchr (real_new.get_win32 (), '.'))) *lnk_suffix = '\0'; - if (!MoveFile (real_old.get_win32 (), real_new.get_win32 ())) + if (!MoveFile (real_old, real_new)) res = -1; if (res == 0 || (GetLastError () != ERROR_ALREADY_EXISTS @@ -1396,7 +1368,7 @@ _rename (const char *oldpath, const char *newpath) else { syscall_printf ("try win95 hack"); - for (;;) + for (int i = 0; i < 2; i++) { if (!DeleteFileA (real_new.get_win32 ()) && GetLastError () != ERROR_FILE_NOT_FOUND) @@ -1405,13 +1377,10 @@ _rename (const char *oldpath, const char *newpath) real_new.get_win32 ()); break; } - else + else if (MoveFile (real_old.get_win32 (), real_new.get_win32 ())) { - if (MoveFile (real_old.get_win32 (), real_new.get_win32 ())) - { - res = 0; - break; - } + res = 0; + break; } } } @@ -1421,14 +1390,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 +1404,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 +2285,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; diff --git a/winsup/cygwin/sysconf.cc b/winsup/cygwin/sysconf.cc index aa1909141..5e1d91ba6 100644 --- a/winsup/cygwin/sysconf.cc +++ b/winsup/cygwin/sysconf.cc @@ -16,6 +16,7 @@ details. */ #include <ntdef.h> #include "security.h" #include "fhandler.h" +#include "path.h" #include "dtable.h" #include "cygheap.h" #include "cygerrno.h" diff --git a/winsup/cygwin/syslog.cc b/winsup/cygwin/syslog.cc index c11ff1170..66e9ed1cc 100644 --- a/winsup/cygwin/syslog.cc +++ b/winsup/cygwin/syslog.cc @@ -16,6 +16,7 @@ details. */ #include <unistd.h> #include "security.h" #include "fhandler.h" +#include "path.h" #include "dtable.h" #include "cygerrno.h" #include "cygheap.h" diff --git a/winsup/cygwin/termios.cc b/winsup/cygwin/termios.cc index a2674aae7..5488185c4 100644 --- a/winsup/cygwin/termios.cc +++ b/winsup/cygwin/termios.cc @@ -17,6 +17,7 @@ details. */ #include "cygerrno.h" #include "security.h" #include "fhandler.h" +#include "path.h" #include "dtable.h" #include "cygheap.h" #include "cygwin/version.h" diff --git a/winsup/cygwin/tty.cc b/winsup/cygwin/tty.cc index fd4afb388..3e3a3c3b1 100644 --- a/winsup/cygwin/tty.cc +++ b/winsup/cygwin/tty.cc @@ -18,6 +18,7 @@ details. */ #include "cygerrno.h" #include "security.h" #include "fhandler.h" +#include "path.h" #include "dtable.h" #include "cygheap.h" #include "sync.h" diff --git a/winsup/cygwin/uinfo.cc b/winsup/cygwin/uinfo.cc index a6b94c803..9bbbe9e9c 100644 --- a/winsup/cygwin/uinfo.cc +++ b/winsup/cygwin/uinfo.cc @@ -23,6 +23,7 @@ details. */ #include "pinfo.h" #include "security.h" #include "fhandler.h" +#include "path.h" #include "dtable.h" #include "cygheap.h" #include "registry.h" |