diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index f4465b6ea..4522fe6ef 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,14 @@ +2010-04-29 Corinna Vinschen + + * external.cc (cygwin_internal): Add CW_CVT_MNT_OPTS to allow mount + flag parsing. Add CW_LST_MNT_OPTS case to allow mount flag listing. + * mount.cc (fstab_read_flags): Rename from read_flags. Make externally + available. Change input string to char ** to allow returning faulty + option. Add flag for avoiding debug output. + (fstab_list_flags): New function to create list of options. + * include/sys/cygwin.h (cygwin_getinfo_types): Add CW_CVT_MNT_OPTS and + CW_LST_MNT_OPTS. + 2010-04-28 Corinna Vinschen * mount.cc (compare_flags): New function. diff --git a/winsup/cygwin/external.cc b/winsup/cygwin/external.cc index bbf675a64..c8cbd9370 100644 --- a/winsup/cygwin/external.cc +++ b/winsup/cygwin/external.cc @@ -474,6 +474,40 @@ cygwin_internal (cygwin_getinfo_types t, ...) internal_setlocale (); res = 0; } + break; + case CW_CVT_MNT_OPTS: + { + extern bool fstab_read_flags (char **, unsigned &, bool); + char **option_string = va_arg (arg, char **); + if (!option_string || !*option_string) + set_errno (EINVAL); + else + { + unsigned *pflags = va_arg (arg, unsigned *); + unsigned flags = 0; + if (fstab_read_flags (option_string, flags, true)) + { + if (pflags) + *pflags = flags; + res = 0; + } + } + } + break; + case CW_LST_MNT_OPTS: + { + extern char *fstab_list_flags (); + char **option_string = va_arg (arg, char **); + if (!option_string) + set_errno (EINVAL); + else + { + *option_string = fstab_list_flags (); + if (*option_string) + res = 0; + } + } + break; default: set_errno (ENOSYS); diff --git a/winsup/cygwin/include/sys/cygwin.h b/winsup/cygwin/include/sys/cygwin.h index 6c04dc8e1..425fd82fd 100644 --- a/winsup/cygwin/include/sys/cygwin.h +++ b/winsup/cygwin/include/sys/cygwin.h @@ -146,7 +146,9 @@ typedef enum CW_EXIT_PROCESS, CW_SET_EXTERNAL_TOKEN, CW_GET_INSTKEY, - CW_INT_SETLOCALE + CW_INT_SETLOCALE, + CW_CVT_MNT_OPTS, + CW_LST_MNT_OPTS } cygwin_getinfo_types; /* Token type for CW_SET_EXTERNAL_TOKEN */ diff --git a/winsup/cygwin/mount.cc b/winsup/cygwin/mount.cc index 528c8b65a..a11ed34a8 100644 --- a/winsup/cygwin/mount.cc +++ b/winsup/cygwin/mount.cc @@ -953,36 +953,60 @@ compare_flags (const void *a, const void *b) return strcmp (oa->name, ob->name); } -static bool -read_flags (char *options, unsigned &flags) +extern "C" bool +fstab_read_flags (char **options, unsigned &flags, bool external) { opt key; - while (*options) + while (**options) { - char *p = strchr (options, ','); + char *p = strchr (*options, ','); if (p) *p++ = '\0'; else - p = strchr (options, '\0'); + p = strchr (*options, '\0'); - key.name = options; - opt *o = (opt *) bsearch (&key, oopts, sizeof oopts / sizeof (opt), + key.name = *options; + opt *o = (opt *) bsearch (&key, oopts, + sizeof oopts / sizeof (opt), sizeof (opt), compare_flags); if (!o) { - system_printf ("invalid fstab option - '%s'", options); + if (!external) + system_printf ("invalid fstab option - '%s'", *options); return false; } if (o->clear) flags &= ~o->val; else flags |= o->val; - options = p; + *options = p; } return true; } +extern "C" char * +fstab_list_flags () +{ + size_t len = 0; + opt *o; + + for (o = oopts; o < (oopts + (sizeof (oopts) / sizeof (oopts[0]))); o++) + len += strlen (o->name) + 1; + char *buf = (char *) malloc (len); + if (buf) + { + char *bp = buf; + for (o = oopts; o < (oopts + (sizeof (oopts) / sizeof (oopts[0]))); o++) + { + bp = stpcpy (bp, o->name); + *bp++ = ','; + } + *--bp = '\0'; + } + return buf; +} + bool mount_info::from_fstab_line (char *line, bool user) { @@ -1021,7 +1045,7 @@ mount_info::from_fstab_line (char *line, bool user) unsigned mount_flags = MOUNT_SYSTEM | MOUNT_BINARY; if (!strcmp (fs_type, "cygdrive")) mount_flags |= MOUNT_NOPOSIX; - if (!read_flags (c, mount_flags)) + if (!fstab_read_flags (&c, mount_flags, false)) return true; if (user) mount_flags &= ~MOUNT_SYSTEM;