summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2008-04-02 17:45:32 +0000
committerCorinna Vinschen <corinna@vinschen.de>2008-04-02 17:45:32 +0000
commit85340bc03d4d0e137ab77f7efe09d2e1cc16b395 (patch)
treed2b465bcc8c1366c498b555c78d8df148f6b7ad1
parentc8cd2f2255167288a31293e21576b8d8ae1347ba (diff)
downloadcygnal-85340bc03d4d0e137ab77f7efe09d2e1cc16b395.tar.gz
cygnal-85340bc03d4d0e137ab77f7efe09d2e1cc16b395.tar.bz2
cygnal-85340bc03d4d0e137ab77f7efe09d2e1cc16b395.zip
* path.cc (mount_info::init): First try to fetch mount points from
fstab files. Fallback to registry if none exists. (skip_ws): New inline function. (find_ws): Ditto. (struct opt): New structure for mount options. (read_flags): New static function to convert a mount flags string into a flag value. (mount_info::from_fstab_line): New method to create a mount table entry from a fstab line. (mount_info::from_fstab): New method to read fstab file. * shared_info.h (mount_info::from_fstab_line): Declare. (mount_info::from_fstab): Declare.
-rw-r--r--winsup/cygwin/ChangeLog15
-rw-r--r--winsup/cygwin/path.cc198
-rw-r--r--winsup/cygwin/shared_info.h2
3 files changed, 215 insertions, 0 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 5682b9632..3d9f36849 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,5 +1,20 @@
2008-04-02 Corinna Vinschen <corinna@vinschen.de>
+ * path.cc (mount_info::init): First try to fetch mount points from
+ fstab files. Fallback to registry if none exists.
+ (skip_ws): New inline function.
+ (find_ws): Ditto.
+ (struct opt): New structure for mount options.
+ (read_flags): New static function to convert a mount flags string into
+ a flag value.
+ (mount_info::from_fstab_line): New method to create a mount table
+ entry from a fstab line.
+ (mount_info::from_fstab): New method to read fstab file.
+ * shared_info.h (mount_info::from_fstab_line): Declare.
+ (mount_info::from_fstab): Declare.
+
+2008-04-02 Corinna Vinschen <corinna@vinschen.de>
+
* path.cc (enum symlink_t): Rename from shortcut_t.
2008-04-02 Corinna Vinschen <corinna@vinschen.de>
diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc
index 83ce8017e..c4da23c8f 100644
--- a/winsup/cygwin/path.cc
+++ b/winsup/cygwin/path.cc
@@ -1638,8 +1638,11 @@ mount_info::init ()
{
nmounts = 0;
+ if (from_fstab (false) | from_fstab (true)) /* The single | is correct! */
+ return;
/* Fetch the mount table and cygdrive-related information from
the registry. */
+ system_printf ("Fallback to fetching mounts from registry");
from_registry ();
}
@@ -2298,6 +2301,201 @@ mount_info::set_flags_from_win32_path (const char *p)
return PATH_BINARY;
}
+inline char *
+skip_ws (char *in)
+{
+ while (*in == ' ' || *in == '\t')
+ ++in;
+ return in;
+}
+
+inline char *
+find_ws (char *in)
+{
+ while (*in && *in != ' ' && *in != '\t')
+ ++in;
+ return in;
+}
+
+struct opt
+{
+ const char *name;
+ unsigned val;
+ bool clear;
+} oopts[] =
+{
+ {"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}
+};
+
+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;
+ }
+ system_printf ("invalid fstab option - '%s'", options);
+ return false;
+
+ gotit:
+ options = p;
+ }
+ return true;
+}
+
+bool
+mount_info::from_fstab_line (char *line, bool user)
+{
+ tmp_pathbuf tp;
+ char *native_path = tp.c_get ();
+ /* FIXME */
+ char posix_path[CYG_MAX_PATH];
+
+ /* First field: Native path. */
+ char *c = skip_ws (line);
+ if (!*c || *c == '#')
+ return true;
+ char *cend = find_ws (c);
+ *cend = '\0';
+ *native_path = '\0';
+ strncat (native_path, c, NT_MAX_PATH - 1);
+ /* Second field: POSIX path. */
+ c = skip_ws (cend + 1);
+ if (!*c || *c == '#')
+ return true;
+ cend = find_ws (c);
+ *cend = '\0';
+ *posix_path = '\0';
+ strncat (posix_path, c, CYG_MAX_PATH - 1);
+ /* Third field: FS type. Ignored. */
+ c = skip_ws (cend + 1);
+ if (!*c || *c == '#')
+ return true;
+ cend = find_ws (c);
+ *cend = '\0';
+ /* Forth field: Flags. */
+ c = skip_ws (cend + 1);
+ if (!*c || *c == '#')
+ return true;
+ cend = find_ws (c);
+ *cend = '\0';
+ unsigned mount_flags = 0;
+ if (!read_flags (c, mount_flags))
+ return true;
+ if (user)
+ mount_flags &= ~MOUNT_SYSTEM;
+ else
+ mount_flags |= MOUNT_SYSTEM;
+ if (!strcmp (native_path, "cygdrive"))
+ {
+ cygdrive_flags = mount_flags;
+ slashify (posix_path, cygdrive, 1);
+ cygdrive_len = strlen (cygdrive);
+ }
+ else
+ {
+ int res = mount_table->add_item (native_path, posix_path, mount_flags,
+ false);
+ if (res && get_errno () == EMFILE)
+ return false;
+ }
+ return true;
+}
+
+bool
+mount_info::from_fstab (bool user)
+{
+ tmp_pathbuf tp;
+ PWCHAR path = tp.w_get ();
+ PWCHAR w;
+
+ if (!GetModuleFileNameW (NULL, path, NT_MAX_PATH))
+ {
+ debug_printf ("GetModuleFileNameW, %E");
+ return false;
+ }
+ w = wcsrchr (path, L'\\');
+ if (w)
+ {
+ *w = L'\0';
+ w = wcsrchr (path, L'\\');
+ }
+ if (!w)
+ {
+ debug_printf ("Invalid DLL path");
+ return false;
+ }
+ w = wcpcpy (w, L"\\etc\\fstab");
+ if (user)
+ cygheap->user.get_windows_id (wcpcpy (w, L"."));
+ debug_printf ("Try to read mounts from %W", path);
+ HANDLE h = CreateFileW (path, GENERIC_READ, FILE_SHARE_READ, &sec_none_nih,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (h == INVALID_HANDLE_VALUE)
+ {
+ debug_printf ("CreateFileW, %E");
+ return false;
+ }
+ char *const buf = reinterpret_cast<char *const> (path);
+ char *got = buf;
+ DWORD len = 0;
+ /* Using NT_MAX_PATH-1 leaves space to append two \0. */
+ while (ReadFile (h, got, (NT_MAX_PATH - 1) * sizeof (WCHAR) - (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 (got, user))
+ goto done;
+ got = end + 1;
+ }
+ if (len < (NT_MAX_PATH - 1) * sizeof (WCHAR))
+ 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 (got, user);
+done:
+ CloseHandle (h);
+ return true;
+}
+
/* read_mounts: Given a specific regkey, read mounts from under its
key. */
diff --git a/winsup/cygwin/shared_info.h b/winsup/cygwin/shared_info.h
index d1091f7e2..23c267430 100644
--- a/winsup/cygwin/shared_info.h
+++ b/winsup/cygwin/shared_info.h
@@ -74,6 +74,8 @@ class mount_info
int add_item (const char *dev, const char *path, unsigned flags, int reg_p);
int del_item (const char *path, unsigned flags, int reg_p);
+ bool from_fstab_line (char *line, bool user);
+ bool from_fstab (bool user);
void from_registry ();
int add_reg_mount (const char * native_path, const char * posix_path,
unsigned mountflags);