Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Faylor <me@cgf.cx>2001-04-29 03:48:28 +0400
committerChristopher Faylor <me@cgf.cx>2001-04-29 03:48:28 +0400
commitb98ebf5470da68c0ab4a3877c453ac82c12974ae (patch)
treeb53116bef4a3e4ff86a02d59c3aad37ca7a2cd2c /winsup/cygwin/path.cc
parent0ca66974933232188d8d347b225abacf77d241cf (diff)
Throughout, change 'tty_attached' to 'real_tty_attached', for clarity.
Throughout, change 'OutputStopped' to 'output_stopped', for consistency. * dtable.cc (stdio_init): Set controlling tty if not set by stdio opens. * exceptions.cc (ctrl_c_handler): Avoid special pgid checking if no tty is associated with the process. (Suggested by Tim Baker <dbaker@direct.ca>) * external.cc (fillout_pinfo): Return actual tty number for ctty. * fhandler_console.cc (get_tty_stuff): Set ctty when shared memory is allocated. Accept flags input from open(). (set_console_ctty): New function. (fhandler_console::open): Pass flags to get_tty_stuff and rely on this function to set the ctty, if appropriate. * fhandler_termios.cc (fhandler_termios::set_ctty): Move to tty_min class. * fhandler_tty.cc (fhandler_tty_slave::open): Use tc field to access set_ctty(). * tty.h (TTY_CONSOLE): Move to include/sys/cygwin.h. (tty_min): Add set_ctty class here. * include/sys/cygwin.h (TTY_CONSOLE): New home here. * path.cc (symlink_info): Make contents an actual buffer. Pass more flags to case_check. (path_conv::check): Reorganize to do parsing based on posix path rather than native path. (symlink_info::check): Expect posix path as input. Translate to native path here. Accept path_conv flags. Stop parsing if not a symlink regardless of whether previous path was a symlink.
Diffstat (limited to 'winsup/cygwin/path.cc')
-rw-r--r--winsup/cygwin/path.cc404
1 files changed, 206 insertions, 198 deletions
diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc
index c218a1606..a0e8640a1 100644
--- a/winsup/cygwin/path.cc
+++ b/winsup/cygwin/path.cc
@@ -93,19 +93,18 @@ static int path_prefix_p_ (const char *path1, const char *path2, int len1);
struct symlink_info
{
- char buf[3 + MAX_PATH * 3];
+ char contents[MAX_PATH + 4];
char *ext_here;
int extn;
- char *contents;
unsigned pflags;
DWORD fileattr;
int is_symlink;
bool ext_tacked_on;
int error;
BOOL case_clash;
- symlink_info (): contents (buf + MAX_PATH + 1) {}
int check (const char *path, const suffix_info *suffixes,
- char *orig_path, BOOL sym_ignore);
+ char *orig_path, unsigned opt,
+ DWORD& devn, int& unit, unsigned& path_flags);
BOOL case_check (const char *path, char *orig_path);
};
@@ -178,6 +177,123 @@ pathmatch (const char *path1, const char *path2)
: strcasematch (path1, path2);
}
+/* Normalize a POSIX path.
+ \'s are converted to /'s in the process.
+ All duplicate /'s, except for 2 leading /'s, are deleted.
+ The result is 0 for success, or an errno error value. */
+
+#define isslash(c) ((c) == '/')
+
+static int
+normalize_posix_path (const char *src, char *dst)
+{
+ const char *src_start = src;
+ char *dst_start = dst;
+
+ syscall_printf ("src %s", src);
+ if (isdrive (src) || strpbrk (src, "\\:"))
+ {
+ cygwin_conv_to_full_posix_path (src, dst);
+ return 0;
+ }
+ if (!isslash (src[0]))
+ {
+ if (!cygheap->cwd.get (dst))
+ return get_errno ();
+ dst = strchr (dst, '\0');
+ if (*src == '.')
+ {
+ if (dst == dst_start + 1 && *dst_start == '/')
+ --dst;
+ goto sawdot;
+ }
+ if (dst > dst_start && !isslash (dst[-1]))
+ *dst++ = '/';
+ }
+ /* Two leading /'s? If so, preserve them. */
+ else if (isslash (src[1]))
+ {
+ if (cygheap->root.length ())
+ {
+ debug_printf ("ENOENT = normalize_posix_path (%s)", src);
+ return ENOENT;
+ }
+ *dst++ = '/';
+ *dst++ = '/';
+ src += 2;
+ if (isslash (*src))
+ { /* Starts with three or more slashes - reset. */
+ dst = dst_start;
+ *dst++ = '/';
+ src = src_start + 1;
+ }
+ }
+ /* Exactly one leading slash. Absolute path. Check for chroot. */
+ else if (cygheap->root.length ())
+ {
+ strcpy (dst, cygheap->root.path ());
+ dst += cygheap->root.length ();
+ }
+ else
+ *dst = '\0';
+
+ while (*src)
+ {
+ /* Strip runs of /'s. */
+ if (!isslash (*src))
+ *dst++ = *src++;
+ else
+ {
+ while (*++src)
+ {
+ if (isslash (*src))
+ continue;
+
+ if (*src != '.')
+ break;
+
+ sawdot:
+ if (src[1] != '.')
+ {
+ if (!src[1])
+ {
+ if (dst == dst_start)
+ *dst++ = '/';
+ goto done;
+ }
+ if (!isslash (src[1]))
+ break;
+ }
+ else if (src[2] && !isslash (src[2]))
+ break;
+ else
+ {
+ if (!ischrootpath (dst_start) ||
+ dst - dst_start != (int) cygheap->root.length ())
+ while (dst > dst_start && !isslash (*--dst))
+ continue;
+ src++;
+ }
+ }
+
+ *dst++ = '/';
+ }
+ if ((dst - dst_start) >= MAX_PATH)
+ {
+ debug_printf ("ENAMETOOLONG = normalize_posix_path (%s)", src);
+ return ENAMETOOLONG;
+ }
+ }
+
+done:
+ *dst = '\0';
+ if (--dst > dst_start && isslash (*dst))
+ *dst = '\0';
+
+ debug_printf ("%s = normalize_posix_path (%s)", dst_start, src_start);
+ return 0;
+}
+
inline void
path_conv::add_ext_from_sym (symlink_info &sym)
{
@@ -209,9 +325,8 @@ path_conv::check (const char *src, unsigned opt,
/* This array is used when expanding symlinks. It is MAX_PATH * 2
in length so that we can hold the expanded symlink plus a
trailer. */
- char path_buf[MAX_PATH];
- char path_copy[MAX_PATH];
- char tmp_buf[MAX_PATH];
+ char path_copy[MAX_PATH + 3];
+ char tmp_buf[2 * MAX_PATH + 3];
symlink_info sym;
bool need_directory = 0;
bool saw_symlinks = 0;
@@ -227,8 +342,6 @@ path_conv::check (const char *src, unsigned opt,
}
#endif
- char *rel_path, *full_path;
-
int loop = 0;
path_flags = 0;
known_suffix = NULL;
@@ -241,11 +354,6 @@ path_conv::check (const char *src, unsigned opt,
else if ((error = check_null_empty_path (src)))
return;
- if (opt & PC_FULL)
- rel_path = path_buf, full_path = this->path;
- else
- rel_path = this->path, full_path = path_buf;
-
/* This loop handles symlink expansion. */
for (;;)
{
@@ -260,39 +368,14 @@ path_conv::check (const char *src, unsigned opt,
else if ((p = strrchr (src, '\\')) &&
(p[1] == '\0' || strcmp (p, "\\.") == 0))
need_directory = 1;
- /* Must look up path in mount table, etc. */
- error = mount_table->conv_to_win32_path (src, rel_path, full_path, devn,
- unit, &path_flags);
- MALLOC_CHECK;
+
+ error = normalize_posix_path (src, path_copy);
if (error)
return;
- if (devn != FH_BAD)
- {
- fileattr = 0;
- return;
- }
- /* Eat trailing slashes */
- char *tail = strchr (full_path, '\0');
- /* If path is only a drivename, Windows interprets it as
- the current working directory on this drive instead of
- the root dir which is what we want. So we need
- the trailing backslash in this case. */
- while (tail > full_path + 3 && (*--tail == '\\'))
- *tail = '\0';
- if (full_path[0] && full_path[1] == ':' && full_path[2] == '\0')
- strcat (full_path, "\\");
-
- if ((opt & PC_SYM_IGNORE) && pcheck_case == PCHECK_RELAXED)
- {
- fileattr = GetFileAttributesA (path);
- goto out;
- }
-
- /* Make a copy of the path that we can munge up */
- strcpy (path_copy, full_path);
-
- tail = path_copy + 1 + (tail - full_path); // Point to end of copy
+ char *tail = strchr (path_copy, '\0'); // Point to end of copy
+ char *path_end = tail;
+ tail[1] = '\0';
/* Scan path_copy from right to left looking either for a symlink
or an actual existing file. If an existing file is found, just
@@ -306,6 +389,8 @@ path_conv::check (const char *src, unsigned opt,
for (;;)
{
const suffix_info *suff;
+ char pathbuf[MAX_PATH];
+ char *full_path;
/* Don't allow symlink.check to set anything in the path_conv
class if we're working on an inner component of the path */
@@ -313,14 +398,17 @@ path_conv::check (const char *src, unsigned opt,
{
suff = NULL;
sym.pflags = 0;
+ full_path = pathbuf;
}
else
{
suff = suffixes;
sym.pflags = path_flags;
+ full_path = this->path;
}
- int len = sym.check (path_copy, suff, full_path, opt & PC_SYM_IGNORE);
+ int len = sym.check (path_copy, suff, full_path, opt,
+ devn, unit, path_flags);
if (sym.case_clash)
{
@@ -391,10 +479,15 @@ path_conv::check (const char *src, unsigned opt,
}
- if (!(tail = strrchr (path_copy, '\\')) ||
- (tail > path_copy && tail[-1] == ':'))
+ char *newtail = strrchr (path_copy, '/');
+ if (tail != path_end)
+ *tail = '/';
+
+ if (!newtail)
goto out; // all done
+ tail = newtail;
+
/* Haven't found an existing pathname component yet.
Pinch off the tail and try again. */
*tail = '\0';
@@ -407,10 +500,10 @@ path_conv::check (const char *src, unsigned opt,
error = ELOOP; // Eep.
return;
}
+
MALLOC_CHECK;
- tail = full_path + (tail - path_copy);
- int taillen = strlen (tail);
+ int taillen = strlen (tail + 1);
int buflen = strlen (sym.contents);
if (buflen + taillen > MAX_PATH)
{
@@ -419,31 +512,33 @@ path_conv::check (const char *src, unsigned opt,
return;
}
- /* Copy tail of full_path to discovered symlink. */
- for (p = sym.contents + buflen; *tail; tail++)
- *p++ = *tail == '\\' ? '/' : *tail;
+ if ((p = strrchr (path_copy, '/')) == NULL)
+ p = path_copy;
*p = '\0';
- /* If symlink referred to an absolute path, then we
- just use sym.contents and loop. Otherwise tack the head of
- path_copy before sym.contents and translate it back from a
- Win32-style path to a POSIX-style one. */
+ char *headptr;
if (isabspath (sym.contents))
- src = sym.contents;
- else if (!(tail = strrchr (path_copy, '\\')))
- system_printf ("problem parsing %s - '%s'", src, full_path);
+ headptr = tmp_buf;
else
{
- int headlen = 1 + tail - path_copy;
- p = sym.contents - headlen;
- memcpy (p, path_copy, headlen);
- MALLOC_CHECK;
- error = mount_table->conv_to_posix_path (p, tmp_buf, 1);
- MALLOC_CHECK;
- if (error)
- return;
- src = tmp_buf;
+ strcpy (tmp_buf, path_copy);
+ headptr = strchr (tmp_buf, '\0');
}
+
+ if (headptr > tmp_buf && headptr[-1] != '/')
+ *headptr++ = '/';
+
+ for (p = sym.contents; *p; p++)
+ *headptr++ = *p == '\\' ? '/' : *p;
+ if (tail == path_end)
+ *headptr = '\0';
+ else
+ {
+ *headptr++ = '/';
+ strcpy (headptr, tail);
+ }
+
+ src = tmp_buf;
}
/*fillin:*/
@@ -467,21 +562,21 @@ out:
DWORD serial, volflags;
char fs_name[16];
- strcpy (tmp_buf, full_path);
+ strcpy (tmp_buf, this->path);
if (!rootdir (tmp_buf) ||
!GetVolumeInformation (tmp_buf, NULL, 0, &serial, NULL,
&volflags, fs_name, 16))
{
- debug_printf ("GetVolumeInformation(%s) = ERR, full_path(%s), set_has_acls(FALSE)",
- tmp_buf, full_path, GetLastError ());
+ debug_printf ("GetVolumeInformation(%s) = ERR, this->path(%s), set_has_acls(FALSE)",
+ tmp_buf, this->path, GetLastError ());
set_has_acls (FALSE);
set_has_buggy_open (FALSE);
}
else
{
set_isdisk ();
- debug_printf ("GetVolumeInformation(%s) = OK, full_path(%s), set_has_acls(%d)",
- tmp_buf, full_path, volflags & FS_PERSISTENT_ACLS);
+ debug_printf ("GetVolumeInformation(%s) = OK, this->path(%s), set_has_acls(%d)",
+ tmp_buf, this->path, volflags & FS_PERSISTENT_ACLS);
if (!allow_smbntsec
&& ((tmp_buf[0] == '\\' && tmp_buf[1] == '\\')
|| GetDriveType (tmp_buf) == DRIVE_REMOTE))
@@ -594,7 +689,7 @@ get_device_number (const char *name, int &unit, BOOL from_conv)
name += 5;
if (deveq ("tty"))
{
- if (tty_attached (myself))
+ if (real_tty_attached (myself))
{
unit = myself->ctty;
devn = FH_TTYS;
@@ -683,123 +778,6 @@ win32_device_name (const char *src_path, char *win32_path,
return TRUE;
}
-/* Normalize a POSIX path.
- \'s are converted to /'s in the process.
- All duplicate /'s, except for 2 leading /'s, are deleted.
- The result is 0 for success, or an errno error value. */
-
-#define isslash(c) ((c) == '/')
-
-static int
-normalize_posix_path (const char *src, char *dst)
-{
- const char *src_start = src;
- char *dst_start = dst;
-
- syscall_printf ("src %s", src);
- if (isdrive (src) || strpbrk (src, "\\:"))
- {
- cygwin_conv_to_full_posix_path (src, dst);
- return 0;
- }
- if (!isslash (src[0]))
- {
- if (!cygheap->cwd.get (dst))
- return get_errno ();
- dst = strchr (dst, '\0');
- if (*src == '.')
- {
- if (dst == dst_start + 1 && *dst_start == '/')
- --dst;
- goto sawdot;
- }
- if (dst > dst_start && !isslash (dst[-1]))
- *dst++ = '/';
- }
- /* Two leading /'s? If so, preserve them. */
- else if (isslash (src[1]))
- {
- if (cygheap->root.length ())
- {
- debug_printf ("ENOENT = normalize_posix_path (%s)", src);
- return ENOENT;
- }
- *dst++ = '/';
- *dst++ = '/';
- src += 2;
- if (isslash (*src))
- { /* Starts with three or more slashes - reset. */
- dst = dst_start;
- *dst++ = '/';
- src = src_start + 1;
- }
- }
- /* Exactly one leading slash. Absolute path. Check for chroot. */
- else if (cygheap->root.length ())
- {
- strcpy (dst, cygheap->root.path ());
- dst += cygheap->root.length ();
- }
- else
- *dst = '\0';
-
- while (*src)
- {
- /* Strip runs of /'s. */
- if (!isslash (*src))
- *dst++ = *src++;
- else
- {
- while (*++src)
- {
- if (isslash (*src))
- continue;
-
- if (*src != '.')
- break;
-
- sawdot:
- if (src[1] != '.')
- {
- if (!src[1])
- {
- if (dst == dst_start)
- *dst++ = '/';
- goto done;
- }
- if (!isslash (src[1]))
- break;
- }
- else if (src[2] && !isslash (src[2]))
- break;
- else
- {
- if (!ischrootpath (dst_start) ||
- dst - dst_start != (int) cygheap->root.length ())
- while (dst > dst_start && !isslash (*--dst))
- continue;
- src++;
- }
- }
-
- *dst++ = '/';
- }
- if ((dst - dst_start) >= MAX_PATH)
- {
- debug_printf ("ENAMETOOLONG = normalize_posix_path (%s)", src);
- return ENAMETOOLONG;
- }
- }
-
-done:
- *dst = '\0';
- if (--dst > dst_start && isslash (*dst))
- *dst = '\0';
-
- debug_printf ("%s = normalize_posix_path (%s)", dst_start, src_start);
- return 0;
-}
-
/* Normalize a Win32 path.
/'s are converted to \'s in the process.
All duplicate \'s, except for 2 leading \'s, are deleted.
@@ -2643,15 +2621,45 @@ suffix_scan::next ()
int
symlink_info::check (const char *path, const suffix_info *suffixes,
- char *orig_path, BOOL sym_ignore)
+ char *full_path, unsigned opt,
+ DWORD& devn, int& unit, unsigned& path_flags)
{
HANDLE h;
int res = 0;
suffix_scan suffix;
+ contents[0] = '\0';
+ char *tail;
+
+ error = mount_table->conv_to_win32_path (path, NULL, full_path, devn,
+ unit, &path_flags);
+
+ if (devn != FH_BAD)
+ {
+ fileattr = 0;
+ goto out; /* Found a device. Stop parsing. */
+ }
+
+ /* Eat trailing slashes */
+ tail = strchr (full_path, '\0');
+
+ /* If path is only a drivename, Windows interprets it as the current working
+ directory on this drive instead of the root dir which is what we want. So
+ we need the trailing backslash in this case. */
+ while (tail > full_path + 3 && (*--tail == '\\'))
+ *tail = '\0';
+
+ if (full_path[0] && full_path[1] == ':' && full_path[2] == '\0')
+ strcat (full_path, "\\");
+
+ if ((opt & PC_SYM_IGNORE) && pcheck_case == PCHECK_RELAXED)
+ {
+ fileattr = GetFileAttributesA (path);
+ goto out;
+ }
is_symlink = TRUE;
- ext_here = suffix.has (path, suffixes);
- extn = ext_here - path;
+ ext_here = suffix.has (full_path, suffixes);
+ extn = ext_here - full_path;
ext_tacked_on = !*ext_here;
@@ -2671,8 +2679,8 @@ symlink_info::check (const char *path, const suffix_info *suffixes,
continue;
}
- if (pcheck_case != PCHECK_RELAXED && !case_check (path, orig_path)
- || sym_ignore)
+ if (pcheck_case != PCHECK_RELAXED && !case_check (path, full_path)
+ || (opt & PC_SYM_IGNORE))
goto file_not_symlink;
int sym_check = 0;
@@ -2684,13 +2692,13 @@ symlink_info::check (const char *path, const suffix_info *suffixes,
if (suffix.lnk_match ())
sym_check = 1;
- /* The old Cygwin method creating symlinks: */
+ /* This is the old Cygwin method creating symlinks: */
/* A symlink will have the `system' file attribute. */
/* Only files can be symlinks (which can be symlinks to directories). */
if (fileattr & FILE_ATTRIBUTE_SYSTEM)
sym_check = 2;
- if (!sym_check && !(pflags & PATH_SYMLINK))
+ if (!sym_check)
goto file_not_symlink;
/* Open the file. */