/* mount.cc
- Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 Red Hat, Inc.
-
This file is part of Cygwin.
This software is a copyrighted work licensed under the terms of the
#include <mntent.h>
#include <windows.h>
#include <sys/cygwin.h>
+#include <cygwin/version.h>
#include <stdlib.h>
+#include <unistd.h>
#include <getopt.h>
#include <dirent.h>
+#include "path.h"
-#ifdef errno
-#undef errno
-#endif
#include <errno.h>
+#define NT_MAX_PATH 32768
+
#define EXEC_FLAGS (MOUNT_EXEC | MOUNT_NOTEXEC | MOUNT_CYGWIN_EXEC)
-static void mount_commands (void);
+static void mount_entries (void);
static void show_mounts (void);
static void show_cygdrive_info (void);
static void change_cygdrive_prefix (const char *new_prefix, int flags);
static int mount_already_exists (const char *posix_path, int flags);
// static short create_missing_dirs = FALSE;
-static short force = FALSE;
+static bool force = false;
-static const char version[] = "$Revision$";
static const char *progname;
static void
do_mount (const char *dev, const char *where, int flags)
{
struct stat statbuf;
- char win32_path[MAX_PATH];
int statres;
- cygwin_conv_to_win32_path (where, win32_path);
-
- statres = stat (win32_path, &statbuf);
+ statres = stat (where, &statbuf);
#if 0
if (statres == -1)
else if (!(statbuf.st_mode & S_IFDIR))
{
if (!force)
- fprintf (stderr, "%s: warning: %s is not a directory.\n", progname, where);
+ fprintf (stderr, "%s: warning: %s is not a directory.\n",
+ progname, where);
}
- if (!force && !(flags & EXEC_FLAGS) && strlen (dev))
+ if (!force && !(flags & (EXEC_FLAGS | MOUNT_BIND)) && strlen (dev))
{
char devtmp[1 + 2 * strlen (dev)];
strcpy (devtmp, dev);
strcat (devtmp, "\\");
if (GetDriveType (devtmp) == DRIVE_REMOTE)
{
- fprintf (stderr, "%s: defaulting to '--no-executable' flag for speed since native path\n"
- "%*creferences a remote share. Use '-f' option to override.\n", progname,
- strlen(progname) + 2, ' ');
+ fprintf (stderr,
+ "%s: defaulting to 'notexec' mount option for speed since native path\n"
+ "%*creferences a remote share. Use '-f' option to override.\n",
+ progname, (int) strlen(progname) + 2, ' ');
flags |= MOUNT_NOTEXEC;
}
}
- if (!force && flags & MOUNT_ENC)
- {
- DIR *dd = opendir (dev);
- if (dd)
- {
- struct dirent *d;
- while ((d = readdir (dd)))
- {
- if (d->d_name[0] != '.')
- /* fall through */;
- else if (d->d_name[1] == '\0'
- || (d->d_name[1] == '.' && d->d_name[2] == '\0'))
- continue;
- fprintf (stderr, "%s: error: don't use \"-o managed\" on non-empty directories\n", progname);
- exit (1);
- }
- }
- }
-
if (mount (dev, where, flags))
error (where);
+}
- exit (0);
+static void
+from_fstab (bool user)
+{
+ char path[PATH_MAX];
+ char buf[65536];
+ mnt_t *m = mount_table + max_mount_entry;
+
+ strcpy (path, "/etc/fstab");
+ if (user)
+ {
+ strcat (path, ".d/");
+ strcat (path, getlogin ());
+ }
+ FILE *fh = fopen (path, "rt");
+ if (!fh)
+ return;
+ while (fgets (buf, 65536, fh))
+ {
+ char *c = strrchr (buf, '\n');
+ if (c)
+ *c = '\0';
+ if (from_fstab_line (m, buf, user))
+ ++m;
+ }
+ max_mount_entry = m - mount_table;
+ fclose (fh);
+}
+
+static void
+do_mount_from_fstab (const char *where)
+{
+ force = true;
+ /* Read fstab entries. */
+ from_fstab (false);
+ from_fstab (true);
+ /* Loop through fstab entries and see if it matches `where'. If `where'
+ is NULL, all entries match. */
+ bool exists = false;
+ for (mnt_t *m = mount_table; m - mount_table < max_mount_entry; ++m)
+ if (!where || !strcmp (where, m->posix))
+ {
+ if (m->flags & MOUNT_CYGDRIVE)
+ {
+ /* Get the cygdrive info */
+ char user[MAX_PATH];
+ char system[MAX_PATH];
+ char user_flags[MAX_PATH];
+ char system_flags[MAX_PATH];
+
+ exists = true;
+ cygwin_internal (CW_GET_CYGDRIVE_INFO, user, system, user_flags,
+ system_flags);
+ if ((*user && strcmp (user, m->posix) != 0)
+ || (*system && strcmp (system, m->posix) != 0))
+ if (mount (NULL, m->posix, m->flags))
+ error (m->posix);
+ }
+ else
+ {
+ exists = true;
+ /* Compare with existing mount table. If the entry doesn't exist,
+ mount it. */
+ FILE *mt = setmntent ("/-not-used-", "r");
+ struct mntent *p;
+
+ while ((p = getmntent (mt)) != NULL)
+ if (!strcmp (m->posix, p->mnt_dir))
+ break;
+ if (!p)
+ do_mount (m->native, m->posix, m->flags);
+ endmntent (mt);
+ if (where)
+ break;
+ }
+ }
+ if (!exists && where)
+ fprintf (stderr,
+ "%s: can't find %s in /etc/fstab or in /etc/fstab.d/$USER\n",
+ progname, where);
}
static struct option longopts[] =
{
- {"binary", no_argument, NULL, 'b'},
+ {"all", no_argument, NULL, 'a'},
{"change-cygdrive-prefix", no_argument, NULL, 'c'},
- {"cygwin-executable", no_argument, NULL, 'X'},
- {"executable", no_argument, NULL, 'x'},
{"force", no_argument, NULL, 'f'},
{"help", no_argument, NULL, 'h' },
- {"mount-commands", no_argument, NULL, 'm'},
- {"no-executable", no_argument, NULL, 'E'},
- {"options", required_argument, NULL, 'E'},
+ {"mount-entries", no_argument, NULL, 'm'},
+ {"options", required_argument, NULL, 'o'},
{"show-cygdrive-prefix", no_argument, NULL, 'p'},
- {"system", no_argument, NULL, 's'},
- {"text", no_argument, NULL, 't'},
- {"user", no_argument, NULL, 'u'},
- {"version", no_argument, NULL, 'v'},
+ {"version", no_argument, NULL, 'V'},
{NULL, 0, NULL, 0}
};
-static char opts[] = "bcfhmpstuvxEXo:";
+static char opts[] = "acfhmpVo:";
-static void
+static void __attribute__ ((__noreturn__))
usage (FILE *where = stderr)
{
- fprintf (where, "Usage: %s [OPTION] [<win32path> <posixpath>]\n\
+ char *options;
+
+ fprintf (where, "Usage: %1$s [OPTION] [<win32path> <posixpath>]\n\
+ %1$s -a\n\
+ %1$s <posixpath>\n\
+\n\
Display information about mounted filesystems, or mount a filesystem\n\
\n\
- -b, --binary (default) text files are equivalent to binary files\n\
- (newline = \\n)\n\
+ -a, --all mount all filesystems mentioned in fstab\n\
-c, --change-cygdrive-prefix change the cygdrive path prefix to <posixpath>\n\
-f, --force force mount, don't warn about missing mount\n\
point directories\n\
-h, --help output usage information and exit\n\
- -m, --mount-commands write mount commands to replace user and\n\
- system mount points and cygdrive prefixes\n\
+ -m, --mount-entries write fstab entries to replicate mount points\n\
+ and cygdrive prefixes\n\
-o, --options X[,X...] specify mount options\n\
-p, --show-cygdrive-prefix show user and/or system cygdrive path prefix\n\
- -s, --system (default) add system-wide mount point\n\
- -t, --text text files get \\r\\n line endings\n\
- -u, --user add user-only mount point\n\
- -v, --version output version information and exit\n\
- -x, --executable treat all files under mount point as executables\n\
- -E, --no-executable treat all files under mount point as \n\
- non-executables\n\
- -X, --cygwin-executable treat all files under mount point as cygwin\n\
- executables\n\
-", progname);
+ -V, --version output version information and exit\n\n",
+ progname);
+ if (!cygwin_internal (CW_LST_MNT_OPTS, &options))
+ fprintf (where, "Valid options are: %s\n\n", options);
exit (where == stderr ? 1 : 0);
}
-struct opt
-{
- const char *name;
- unsigned val;
- bool clear;
-} oopts[] =
-{
- {"user", MOUNT_SYSTEM, 1},
- {"system", 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}
-};
-
static void
print_version ()
{
- const char *v = strchr (version, ':');
- int len;
- if (!v)
- {
- v = "?";
- len = 1;
- }
- else
- {
- v += 2;
- len = strchr (v, ' ') - v;
- }
- printf ("\
-%s (cygwin) %.*s\n\
-Filesystem Utility\n\
-Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.\n\
-Compiled on %s\n\
-", progname, len, v, __DATE__);
+ printf ("mount (cygwin) %d.%d.%d\n"
+ "Mount filesystem utility\n"
+ "Copyright (C) 1996 - %s Cygwin Authors\n"
+ "This is free software; see the source for copying conditions. There is NO\n"
+ "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n",
+ CYGWIN_VERSION_DLL_MAJOR / 1000,
+ CYGWIN_VERSION_DLL_MAJOR % 1000,
+ CYGWIN_VERSION_DLL_MINOR,
+ strrchr (__DATE__, ' ') + 1);
}
static char *
main (int argc, char **argv)
{
int i;
- int flags = MOUNT_BINARY;
- int default_flag = MOUNT_SYSTEM;
+ int flags = 0;
char *options = strdup ("");
enum do_what
{
nada,
saw_change_cygdrive_prefix,
saw_show_cygdrive_prefix,
- saw_mount_commands
+ saw_mount_commands,
+ saw_mount_all,
} do_what = nada;
- progname = strrchr (argv[0], '/');
- if (progname == NULL)
- progname = strrchr (argv[0], '\\');
- if (progname == NULL)
- progname = argv[0];
- else
- progname++;
+ progname = program_invocation_short_name;
if (argc == 1)
{
while ((i = getopt_long (argc, argv, opts, longopts, NULL)) != EOF)
switch (i)
{
- case 'b':
- flags |= MOUNT_BINARY;
+ case 'a':
+ if (do_what == nada)
+ do_what = saw_mount_all;
+ else
+ usage ();
break;
case 'c':
if (do_what == nada)
usage ();
break;
case 'f':
- force = TRUE;
+ force = true;
break;
case 'h':
usage (stdout);
usage ();
break;
case 'o':
- if (*options)
+ if (do_what == saw_mount_all)
+ usage ();
+ else if (*options)
options = concat3 (options, ",", optarg);
else
options = strdup (optarg);
else
usage ();
break;
- case 's':
- flags |= MOUNT_SYSTEM;
- break;
- case 't':
- flags &= ~MOUNT_BINARY;
- break;
- case 'u':
- flags &= ~MOUNT_SYSTEM;
- default_flag = 0;
- break;
- case 'v':
+ case 'V':
print_version ();
return 0;
break;
- case 'x':
- flags |= MOUNT_EXEC;
- break;
- case 'E':
- flags |= MOUNT_NOTEXEC;
- break;
- case 'X':
- flags |= MOUNT_CYGWIN_EXEC;
- break;
default:
- usage ();
+ fprintf (stderr, "Try `%s --help' for more information.\n", progname);
+ return 1;
}
- while (*options)
+ if (cygwin_internal (CW_CVT_MNT_OPTS, &options, &flags))
{
- 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;
- }
fprintf (stderr, "%s: invalid option - '%s'\n", progname, options);
exit (1);
-
- gotit:
- options = p;
}
if (flags & MOUNT_NOTEXEC && flags & (MOUNT_EXEC | MOUNT_CYGWIN_EXEC))
{
- fprintf (stderr, "%s: invalid combination of executable options\n", progname);
+ fprintf (stderr, "%s: invalid combination of executable options\n",
+ progname);
exit (1);
}
+ cygwin_internal (CW_SET_DOS_FILE_WARNING, false);
+
argc--;
switch (do_what)
{
case saw_change_cygdrive_prefix:
if (optind != argc)
usage ();
- change_cygdrive_prefix (argv[optind], flags | default_flag);
+ change_cygdrive_prefix (argv[optind], flags);
break;
case saw_show_cygdrive_prefix:
if (optind <= argc)
case saw_mount_commands:
if (optind <= argc)
usage ();
- mount_commands ();
+ mount_entries ();
+ break;
+ case saw_mount_all:
+ if (optind <= argc)
+ usage ();
+ do_mount_from_fstab (NULL);
break;
default:
- if (optind != (argc - 1))
+ if (optind == argc)
+ do_mount_from_fstab (argv[optind]);
+ else if (optind != (argc - 1))
{
- if (optind >= argc)
- fprintf (stderr, "%s: not enough arguments\n", progname);
- else
- fprintf (stderr, "%s: too many arguments\n", progname);
+ fprintf (stderr, "%s: too many arguments\n", progname);
usage ();
}
- if (force || !mount_already_exists (argv[optind + 1], flags | default_flag))
- do_mount (argv[optind], argv[optind + 1], flags | default_flag);
+ else if (force || !mount_already_exists (argv[optind + 1], flags))
+ do_mount (argv[optind], argv[optind + 1], flags);
else
{
errno = EBUSY;
return 0;
}
+static char *
+convert_spaces (char *tgt, const char *src)
+{
+ char *tp, *spacep;
+ const char *sp;
+
+ tp = tgt;
+ for (sp = src; (spacep = strchr (sp, ' ')); sp = spacep + 1)
+ {
+ tp = stpncpy (tp, sp, spacep - sp);
+ tp = stpcpy (tp, "\\040");
+ }
+ stpcpy (tp, sp);
+ return tgt;
+}
+
static void
-mount_commands (void)
+mount_entries (void)
{
FILE *m = setmntent ("/-not-used-", "r");
struct mntent *p;
- char *c;
- const char *format_mnt = "mount%s \"%s\" \"%s\"\n";
- const char *format_cyg = "mount%s --change-cygdrive-prefix \"%s\"\n";
- char opts[MAX_PATH];
- char user[MAX_PATH];
- char system[MAX_PATH];
- char user_flags[MAX_PATH];
- char system_flags[MAX_PATH];
+ const char *format_mnt = "%s %s %s %s 0 0\n";
+ const char *format_cyg = "none %s cygdrive %s 0 0\n";
- // write mount commands for user and system mount points
+ // write fstab entries for normal mount points
while ((p = getmntent (m)) != NULL)
- // Only list non-cygdrives
- if (!strstr (p->mnt_opts, ",noumount"))
+ // Only list non-cygdrives and non-automounts
+ if (!strstr (p->mnt_opts, ",noumount") && !strstr (p->mnt_opts, ",auto"))
{
- strcpy(opts, " -f");
- if (p->mnt_type[0] == 'u')
- strcat (opts, " -u");
- else if (p->mnt_type[0] == 's')
- strcat (opts, " -s");
- if (p->mnt_opts[0] == 'b')
- strcat (opts, " -b");
- else if (p->mnt_opts[0] == 't')
- strcat (opts, " -t");
- if (strstr (p->mnt_opts, ",exec"))
- strcat (opts, " -x");
- if (strstr (p->mnt_opts, ",noexec"))
- strcat (opts, " -E");
- if (strstr (p->mnt_opts, ",managed"))
- strcat (opts, " -o managed");
- while ((c = strchr (p->mnt_fsname, '\\')) != NULL)
- *c = '/';
- printf (format_mnt, opts, p->mnt_fsname, p->mnt_dir);
+ char fsname[NT_MAX_PATH], dirname[NT_MAX_PATH];
+ /* Drop the "bind" option since it can't be reverted. */
+ char *c = strstr (p->mnt_opts, ",bind");
+ if (c)
+ memmove (c, c + 5, strlen (c + 5) + 1);
+ printf (format_mnt, convert_spaces (fsname, p->mnt_fsname),
+ convert_spaces (dirname, p->mnt_dir),
+ p->mnt_type, p->mnt_opts);
}
endmntent (m);
- // write mount commands for cygdrive prefixes
- cygwin_internal (CW_GET_CYGDRIVE_INFO, user, system, user_flags,
- system_flags);
-
- if (strlen (user) > 0)
+ // write fstab entry for cygdrive prefix
+ m = setmntent ("/-not-used-", "r");
+ while ((p = getmntent (m)) != NULL)
{
- strcpy (opts, " -u");
- if (user_flags[0] == 'b')
- strcat (opts, " -b");
- else if (user_flags[0] == 't')
- strcat (opts, " -t");
- printf (format_cyg, opts, user);
- }
+ char *noumount;
+ if ((noumount = strstr (p->mnt_opts, ",noumount")))
+ {
+ char dirname[NT_MAX_PATH];
+ char opts[strlen (p->mnt_opts) + 1];
- if (strlen (system) > 0)
- {
- strcpy (opts, " -s");
- if (system_flags[0] == 'b')
- strcat (opts, " -b");
- else if (system_flags[0] == 't')
- strcat (opts, " -t");
- printf (format_cyg, opts, system);
+ convert_spaces (dirname, p->mnt_dir);
+ // remove trailing slash
+ char *ls = strrchr (dirname, '/');
+ if (ls)
+ {
+ // last slash == leading slash? cygdrive prefix == "/"
+ if (ls == dirname)
+ ++ls;
+ *ls = '\0';
+ }
+ *stpncpy (opts, p->mnt_opts, noumount - p->mnt_opts) = '\0';
+ printf (format_cyg, dirname, opts);
+ break;
+ }
}
+ endmntent (m);
exit(0);
}
else
fprintf (stderr,
"%s: warning: user mount point of '%s' "
- "masks system mount.\n",
- progname, posix_path);
+ "masks system mount.\n", progname, posix_path);
break;
}
else
{
- fprintf (stderr, "%s: warning: couldn't determine mount type.\n", progname);
+ fprintf (stderr, "%s: warning: couldn't determine mount type.\n",
+ progname);
break;
}
}
if (strlen (user) > 0)
printf (format, user, "user", user_flags);
if (strlen (system) > 0)
- printf (format, system, "system", system_flags);
+ printf (format, system, "nouser", system_flags);
exit (0);
}