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:
authorCorinna Vinschen <corinna@vinschen.de>2008-04-22 18:42:05 +0400
committerCorinna Vinschen <corinna@vinschen.de>2008-04-22 18:42:05 +0400
commitb677a99b34031a72dcb6fa696a28d01259abaf83 (patch)
tree2ef429fa7f46c649cd8e0b975b1c6dca66b828e9
parentb1138f3d4bc00c4d99efabdc50fc6ef35bffa734 (diff)
* cygcheck.cc (dump_sysinfo): Fix multiple Cygwin DLL test.
* path.cc: Fetch mount points from fstab files instead of from registry. Use adapted functions copied from Cygwin DLL. (mnt_t): Drop issys member. Define as "mnt_t" instead of "struct mnt_t" subsequently. (max_mount_entry): New variable. (unconvert_slashes): Move to earlier location in file. Make inline. (find2): Remove. (get_cygdrive0): Remove. (get_cygdrive): Remove. (skip_ws): New function. (find_ws): Ditto. (conv_fstab_spaces): Ditto. (read_flags): Ditto. (from_fstab_line): Ditto. (get_user): Ditto. (from_fstab): Ditto. (mnt_sort): Ditto. (read_mounts): Drop old registry code. Fetch "Software\Cygwin\Setup\rootdir" value from HKCU or HKLM key. Use rootdir extracted from module path as fallback. Call from_fstab for nouser and user mount points. (setmntent): Check max_mount_entry to test if read_mounts must be called. (getmntent): Use MOUNT_SYSTEM flag instead of mnt_t's issys member.
-rw-r--r--winsup/utils/ChangeLog28
-rw-r--r--winsup/utils/cygcheck.cc7
-rw-r--r--winsup/utils/path.cc420
3 files changed, 339 insertions, 116 deletions
diff --git a/winsup/utils/ChangeLog b/winsup/utils/ChangeLog
index 82f1e195a..a846fe2e9 100644
--- a/winsup/utils/ChangeLog
+++ b/winsup/utils/ChangeLog
@@ -1,3 +1,31 @@
+2008-03-22 Corinna Vinschen <corinna@vinschen.de>
+
+ * cygcheck.cc (dump_sysinfo): Fix multiple Cygwin DLL test.
+ * path.cc: Fetch mount points from fstab files instead of from
+ registry. Use adapted functions copied from Cygwin DLL.
+ (mnt_t): Drop issys member. Define as "mnt_t" instead of "struct mnt_t"
+ subsequently.
+ (max_mount_entry): New variable.
+ (unconvert_slashes): Move to earlier location in file. Make inline.
+ (find2): Remove.
+ (get_cygdrive0): Remove.
+ (get_cygdrive): Remove.
+ (skip_ws): New function.
+ (find_ws): Ditto.
+ (conv_fstab_spaces): Ditto.
+ (read_flags): Ditto.
+ (from_fstab_line): Ditto.
+ (get_user): Ditto.
+ (from_fstab): Ditto.
+ (mnt_sort): Ditto.
+ (read_mounts): Drop old registry code. Fetch
+ "Software\Cygwin\Setup\rootdir" value from HKCU or HKLM key. Use
+ rootdir extracted from module path as fallback. Call from_fstab for
+ nouser and user mount points.
+ (setmntent): Check max_mount_entry to test if read_mounts must be
+ called.
+ (getmntent): Use MOUNT_SYSTEM flag instead of mnt_t's issys member.
+
2008-03-16 Brian Dessent <brian@dessent.net>
* path.cc: Include malloc.h for alloca.
diff --git a/winsup/utils/cygcheck.cc b/winsup/utils/cygcheck.cc
index 4d79e3140..84ee45f9a 100644
--- a/winsup/utils/cygcheck.cc
+++ b/winsup/utils/cygcheck.cc
@@ -1669,6 +1669,7 @@ dump_sysinfo ()
if (givehelp)
printf ("Looking for various Cygwin DLLs... (-v gives version info)\n");
int cygwin_dll_count = 0;
+ char cygdll_path[32768];
for (pathlike *pth = paths; pth->dir; pth++)
{
WIN32_FIND_DATA ffinfo;
@@ -1686,7 +1687,11 @@ dump_sysinfo ()
sprintf (tmp, "%s%s", pth->dir, f);
if (strcasecmp (f, "cygwin1.dll") == 0)
{
- cygwin_dll_count++;
+ if (!cygwin_dll_count)
+ strcpy (cygdll_path, pth->dir);
+ if (!cygwin_dll_count
+ || strcasecmp (cygdll_path, pth->dir) != 0)
+ cygwin_dll_count++;
found_cygwin_dll = strdup (tmp);
}
else
diff --git a/winsup/utils/path.cc b/winsup/utils/path.cc
index 33ecf70ba..6e6b76039 100644
--- a/winsup/utils/path.cc
+++ b/winsup/utils/path.cc
@@ -16,9 +16,11 @@ details. */
#define str(a) #a
#define scat(a,b) str(a##b)
#include <windows.h>
+#include <lmcons.h>
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
+#include <wchar.h>
#include "path.h"
#include "cygwin/include/cygwin/version.h"
#include "cygwin/include/sys/mount.h"
@@ -226,152 +228,347 @@ readlink (HANDLE fh, char *path, int maxlen)
return false;
}
-typedef struct mnt
- {
- const char *native;
- char *posix;
- unsigned flags;
- int issys;
- } mnt_t;
+struct mnt_t
+{
+ char *native;
+ char *posix;
+ unsigned flags;
+};
#ifndef TESTSUITE
static mnt_t mount_table[255];
+static int max_mount_entry;
#else
# define TESTSUITE_MOUNT_TABLE
# include "testsuite.h"
# undef TESTSUITE_MOUNT_TABLE
#endif
-struct mnt *root_here = NULL;
+mnt_t *root_here = NULL;
+
+inline void
+unconvert_slashes (char* name)
+{
+ while ((name = strchr (name, '/')) != NULL)
+ *name++ = '\\';
+}
/* These functions aren't called when defined(TESTSUITE) which results
in a compiler warning. */
#ifndef TESTSUITE
-static char *
-find2 (HKEY rkey, unsigned *flags, char *what)
+inline char *
+skip_ws (char *in)
{
- char *retval = 0;
- DWORD retvallen = 0;
- DWORD type;
- HKEY key;
+ while (*in == ' ' || *in == '\t')
+ ++in;
+ return in;
+}
- if (RegOpenKeyEx (rkey, what, 0, KEY_READ, &key) != ERROR_SUCCESS)
- return 0;
+inline char *
+find_ws (char *in)
+{
+ while (*in && *in != ' ' && *in != '\t')
+ ++in;
+ return in;
+}
- if (RegQueryValueEx (key, "native", 0, &type, 0, &retvallen)
- == ERROR_SUCCESS)
+inline char *
+conv_fstab_spaces (char *field)
+{
+ register char *sp = field;
+ while (sp = strstr (sp, "\\040"))
{
- retval = (char *) malloc (MAX_PATH + 1);
- if (RegQueryValueEx (key, "native", 0, &type, (BYTE *) retval, &retvallen)
- != ERROR_SUCCESS)
- {
- free (retval);
- retval = 0;
- }
+ *sp++ = ' ';
+ memmove (sp, sp + 3, strlen (sp + 3) + 1);
}
+ return field;
+}
- retvallen = sizeof (flags);
- RegQueryValueEx (key, "flags", 0, &type, (BYTE *)flags, &retvallen);
+struct opt
+{
+ const char *name;
+ unsigned val;
+ bool clear;
+} oopts[] =
+{
+ {"user", MOUNT_SYSTEM, 1},
+ {"nouser", MOUNT_SYSTEM, 0},
+ {"binary", MOUNT_BINARY, 0},
+ {"text", MOUNT_BINARY, 1},
+ {"exec", MOUNT_EXEC, 0},
+ {"notexec", MOUNT_NOTEXEC, 0},
+ {"cygexec", MOUNT_CYGWIN_EXEC, 0},
+ {"nosuid", 0, 0},
+ {"managed", MOUNT_ENC, 0}
+};
- RegCloseKey (key);
+static bool
+read_flags (char *options, unsigned &flags)
+{
+ while (*options)
+ {
+ char *p = strchr (options, ',');
+ if (p)
+ *p++ = '\0';
+ else
+ p = strchr (options, '\0');
+
+ for (opt *o = oopts;
+ o < (oopts + (sizeof (oopts) / sizeof (oopts[0])));
+ o++)
+ if (strcmp (options, o->name) == 0)
+ {
+ if (o->clear)
+ flags &= ~o->val;
+ else
+ flags |= o->val;
+ goto gotit;
+ }
+ return false;
+
+ gotit:
+ options = p;
+ }
+ return true;
+}
- return retval;
+static bool
+from_fstab_line (mnt_t *m, char *line, bool user)
+{
+ char *native_path, *posix_path, *fs_type;
+
+ /* First field: Native path. */
+ char *c = skip_ws (line);
+ if (!*c || *c == '#')
+ return false;
+ char *cend = find_ws (c);
+ *cend = '\0';
+ native_path = conv_fstab_spaces (c);
+ /* Second field: POSIX path. */
+ c = skip_ws (cend + 1);
+ if (!*c)
+ return false;
+ cend = find_ws (c);
+ *cend = '\0';
+ posix_path = conv_fstab_spaces (c);
+ /* Third field: FS type. */
+ c = skip_ws (cend + 1);
+ if (!*c)
+ return false;
+ cend = find_ws (c);
+ *cend = '\0';
+ fs_type = c;
+ /* Forth field: Flags. */
+ c = skip_ws (cend + 1);
+ if (!*c)
+ return false;
+ cend = find_ws (c);
+ *cend = '\0';
+ unsigned mount_flags = MOUNT_SYSTEM;
+ if (!read_flags (c, mount_flags))
+ return false;
+ if (user)
+ mount_flags &= ~MOUNT_SYSTEM;
+ if (!strcmp (fs_type, "cygdrive"))
+ {
+ for (mnt_t *sm = mount_table; sm < m; ++sm)
+ if (sm->flags & MOUNT_CYGDRIVE)
+ {
+ if ((mount_flags & MOUNT_SYSTEM) || !(sm->flags & MOUNT_SYSTEM))
+ {
+ if (sm->posix)
+ free (sm->posix);
+ sm->posix = strdup (posix_path);
+ sm->flags = mount_flags | MOUNT_CYGDRIVE;
+ }
+ return false;
+ }
+ m->posix = strdup (posix_path);
+ m->native = strdup (".");
+ m->flags = mount_flags | MOUNT_CYGDRIVE;
+ }
+ else
+ {
+ for (mnt_t *sm = mount_table; sm < m; ++sm)
+ if (!strcasecmp (sm->posix, posix_path))
+ {
+ if ((mount_flags & MOUNT_SYSTEM) || !(sm->flags & MOUNT_SYSTEM))
+ {
+ if (sm->native)
+ free (sm->native);
+ sm->native = strdup (native_path);
+ sm->flags = mount_flags;
+ }
+ return false;
+ }
+ m->posix = strdup (posix_path);
+ unconvert_slashes (native_path);
+ m->native = strdup (native_path);
+ m->flags = mount_flags;
+ }
+ return true;
}
-static LONG
-get_cygdrive0 (HKEY key, const char *what, void *val, DWORD len)
+#define BUFSIZE 65536
+
+static char *
+get_user ()
{
- LONG status = RegQueryValueEx (key, what, 0, 0, (BYTE *)val, &len);
- return status;
+ static char user[UNLEN + 1];
+ char *userenv;
+
+ user[0] = '\0';
+ if ((userenv = getenv ("USER")) || (userenv = getenv ("USERNAME")))
+ strncat (user, userenv, UNLEN);
+ return user;
}
-static mnt *
-get_cygdrive (HKEY key, mnt *m, int issystem)
+void
+from_fstab (bool user, PWCHAR path, PWCHAR path_end)
{
- if (get_cygdrive0 (key, CYGWIN_INFO_CYGDRIVE_FLAGS, &m->flags,
- sizeof (m->flags)) != ERROR_SUCCESS) {
- free (m->posix);
- return m;
- }
- get_cygdrive0 (key, CYGWIN_INFO_CYGDRIVE_PREFIX, m->posix, MAX_PATH);
- m->native = strdup (".");
- m->issys = issystem;
- return m + 1;
+ mnt_t *m = mount_table + max_mount_entry;
+ char buf[BUFSIZE];
+
+ if (!user)
+ {
+ /* Create a default root dir from path. */
+ WideCharToMultiByte (GetACP (), 0, path, -1, buf, BUFSIZE,
+ NULL, NULL);
+ unconvert_slashes (buf);
+ char *native_path = buf;
+ if (!strncmp (native_path, "\\\\?\\", 4))
+ native_path += 4;
+ if (!strncmp (native_path, "UNC\\", 4))
+ *(native_path += 2) = '\\';
+ m->posix = strdup ("/");
+ m->native = strdup (native_path);
+ m->flags = MOUNT_SYSTEM | MOUNT_BINARY;
+ ++m;
+ /* Create a default cygdrive entry. Note that this is a user entry.
+ This allows to override it with mount, unless the sysadmin created
+ a cygdrive entry in /etc/fstab. */
+ m->posix = strdup (CYGWIN_INFO_CYGDRIVE_DEFAULT_PREFIX);
+ m->native = strdup (".");
+ m->flags = MOUNT_BINARY | MOUNT_CYGDRIVE;
+ ++m;
+ max_mount_entry = m - mount_table;
+ }
+
+ PWCHAR u = wcscpy (path_end, L"\\etc\\fstab") + 10;
+ if (user)
+ MultiByteToWideChar (GetACP (), 0, get_user (), -1,
+ wcscpy (u, L".d\\") + 3, BUFSIZE - (u - path));
+ HANDLE h = CreateFileW (path, GENERIC_READ, FILE_SHARE_READ, NULL,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (h == INVALID_HANDLE_VALUE)
+ return;
+ char *got = buf;
+ DWORD len = 0;
+ /* Using BUFSIZE-1 leaves space to append two \0. */
+ while (ReadFile (h, got, BUFSIZE - 1 - (got - buf),
+ &len, NULL))
+ {
+ char *end;
+
+ /* Set end marker. */
+ got[len] = got[len + 1] = '\0';
+ /* Set len to the absolute len of bytes in buf. */
+ len += got - buf;
+ /* Reset got to start reading at the start of the buffer again. */
+ got = buf;
+ while (got < buf + len && (end = strchr (got, '\n')))
+ {
+ end[end[-1] == '\r' ? -1 : 0] = '\0';
+ if (from_fstab_line (m, got, user))
+ ++m;
+ got = end + 1;
+ }
+ if (len < BUFSIZE - 1)
+ break;
+ /* We have to read once more. Move remaining bytes to the start of
+ the buffer and reposition got so that it points to the end of
+ the remaining bytes. */
+ len = buf + len - got;
+ memmove (buf, got, len);
+ got = buf + len;
+ buf[len] = buf[len + 1] = '\0';
+ }
+ if (got > buf && from_fstab_line (m, got, user))
+ ++m;
+ max_mount_entry = m - mount_table;
+ CloseHandle (h);
}
#endif
+int
+mnt_sort (const void *a, const void *b)
+{
+ const mnt_t *ma = (const mnt_t *) a;
+ const mnt_t *mb = (const mnt_t *) b;
+ int ret;
+
+ ret = (ma->flags & MOUNT_CYGDRIVE) - (mb->flags & MOUNT_CYGDRIVE);
+ if (ret)
+ return ret;
+ ret = (ma->flags & MOUNT_SYSTEM) - (mb->flags & MOUNT_SYSTEM);
+ if (ret)
+ return ret;
+ return strcmp (ma->posix, mb->posix);
+}
+
static void
read_mounts ()
{
/* If TESTSUITE is defined, bypass this whole function as a harness
mount table will be provided. */
#ifndef TESTSUITE
- DWORD posix_path_size;
- int res;
- struct mnt *m = mount_table;
- DWORD disposition;
- char buf[10000];
-
- root_here = NULL;
- for (mnt *m1 = mount_table; m1->posix; m1++)
+ HKEY setup_key;
+ LONG ret;
+ DWORD len;
+ WCHAR path[32768];
+ PWCHAR path_end;
+
+ for (mnt_t *m1 = mount_table; m1->posix; m1++)
{
free (m1->posix);
if (m1->native)
free ((char *) m1->native);
m1->posix = NULL;
}
-
- /* Loop through subkeys */
- /* FIXME: we would like to not check MAX_MOUNTS but the heap in the
- shared area is currently statically allocated so we can't have an
- arbitrarily large number of mounts. */
- for (int issystem = 0; issystem <= 1; issystem++)
+ max_mount_entry = 0;
+
+ for (int i = 0; i < 2; ++i)
+ if ((ret = RegOpenKeyExW (i ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER,
+ L"Software\\Cygwin\\setup", 0,
+ KEY_READ, &setup_key)) == ERROR_SUCCESS)
+ {
+ len = 32768 * sizeof (WCHAR);
+ ret = RegQueryValueExW (setup_key, L"rootdir", NULL, NULL,
+ (PBYTE) path, &len);
+ RegCloseKey (setup_key);
+ if (ret == ERROR_SUCCESS)
+ break;
+ }
+ if (ret == ERROR_SUCCESS)
+ path_end = wcschr (path, L'\0');
+ else
{
- sprintf (buf, "Software\\%s\\%s\\%s",
- CYGWIN_INFO_CYGNUS_REGISTRY_NAME,
- CYGWIN_INFO_CYGWIN_REGISTRY_NAME,
- CYGWIN_INFO_CYGWIN_MOUNT_REGISTRY_NAME);
-
- HKEY key = issystem ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
- if (RegCreateKeyEx (key, buf, 0, (LPTSTR) "Cygwin", 0, KEY_READ,
- 0, &key, &disposition) != ERROR_SUCCESS)
- break;
- for (int i = 0; ;i++, m++)
+ if (!GetModuleFileNameW (NULL, path, 32768))
+ return;
+ path_end = wcsrchr (path, L'\\');
+ if (path_end)
{
- m->posix = (char *) malloc (MAX_PATH + 1);
- posix_path_size = MAX_PATH;
- /* FIXME: if maximum posix_path_size is 256, we're going to
- run into problems if we ever try to store a mount point that's
- over 256 but is under MAX_PATH. */
- res = RegEnumKeyEx (key, i, m->posix, &posix_path_size, NULL,
- NULL, NULL, NULL);
-
- if (res == ERROR_NO_MORE_ITEMS)
- {
- m = get_cygdrive (key, m, issystem);
- m->posix = NULL;
- break;
- }
-
- if (!*m->posix)
- goto no_go;
- else if (res != ERROR_SUCCESS)
- break;
- else
- {
- m->native = find2 (key, &m->flags, m->posix);
- m->issys = issystem;
- if (!m->native)
- goto no_go;
- }
- continue;
- no_go:
- free (m->posix);
- m->posix = NULL;
- m--;
+ *path_end = L'\0';
+ path_end = wcsrchr (path, L'\\');
}
- RegCloseKey (key);
}
+ if (!path_end)
+ return;
+ *path_end = L'\0';
+
+ from_fstab (false, path, path_end);
+ from_fstab (true, path, path_end);
+ qsort (mount_table, max_mount_entry, sizeof (mnt_t), mnt_sort);
#endif /* !defined(TESTSUITE) */
}
@@ -477,13 +674,6 @@ concat (const char *s, ...)
return vconcat (s, v);
}
-static void
-unconvert_slashes (char* name)
-{
- while ((name = strchr (name, '/')) != NULL)
- *name++ = '\\';
-}
-
/* This is a helper function for when vcygpath is passed what appears
to be a relative POSIX path. We take a Win32 CWD (either as specified
in 'cwd' or as retrieved with GetCurrentDirectory() if 'cwd' is NULL)
@@ -504,7 +694,7 @@ rel_vconcat (const char *cwd, const char *s, va_list v)
}
int max_len = -1;
- struct mnt *m, *match = NULL;
+ mnt_t *m, *match = NULL;
for (m = mount_table; m->posix; m++)
{
@@ -547,9 +737,9 @@ static char *
vcygpath (const char *cwd, const char *s, va_list v)
{
int max_len = -1;
- struct mnt *m, *match = NULL;
+ mnt_t *m, *match = NULL;
- if (!mount_table[0].posix)
+ if (!max_mount_entry)
read_mounts ();
char *path;
if (s[0] == '.' && isslash (s[1]))
@@ -615,13 +805,13 @@ cygpath (const char *s, ...)
return vcygpath (NULL, s, v);
}
-static mnt *m = NULL;
+static mnt_t *m = NULL;
extern "C" FILE *
setmntent (const char *, const char *)
{
m = mount_table;
- if (!m->posix)
+ if (!max_mount_entry)
read_mounts ();
return NULL;
}
@@ -639,10 +829,10 @@ getmntent (FILE *)
mnt.mnt_type = (char *) malloc (1024);
if (!mnt.mnt_opts)
mnt.mnt_opts = (char *) malloc (1024);
- if (!m->issys)
- strcpy (mnt.mnt_type, (char *) "user");
- else
+ if (m->flags & MOUNT_SYSTEM)
strcpy (mnt.mnt_type, (char *) "system");
+ else
+ strcpy (mnt.mnt_type, (char *) "user");
if (!(m->flags & MOUNT_BINARY))
strcpy (mnt.mnt_opts, (char *) "textmode");
else