]> sourceware.org Git - newlib-cygwin.git/blobdiff - winsup/utils/mount.cc
Cygwin: add 3.2.1 release file and add fixes up to this point
[newlib-cygwin.git] / winsup / utils / mount.cc
index 89220f20f4b92ba15689e85d56452ab3b70e8df3..a65a6e5776653cd1709a3523c36ebcb702b8f3a1 100644 (file)
@@ -1,7 +1,5 @@
 /* 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
@@ -14,27 +12,28 @@ details. */
 #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
@@ -52,12 +51,9 @@ 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)
@@ -81,10 +77,11 @@ do_mount (const char *dev, const char *where, int flags)
   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);
@@ -98,127 +95,153 @@ do_mount (const char *dev, const char *where, int flags)
       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 replicate 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 *
@@ -233,24 +256,18 @@ int
 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)
     {
@@ -261,8 +278,11 @@ main (int argc, char **argv)
   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)
@@ -271,7 +291,7 @@ main (int argc, char **argv)
          usage ();
        break;
       case 'f':
-       force = TRUE;
+       force = true;
        break;
       case 'h':
        usage (stdout);
@@ -283,7 +303,9 @@ main (int argc, char **argv)
          usage ();
        break;
       case 'o':
-       if (*options)
+       if (do_what == saw_mount_all)
+         usage ();
+       else if (*options)
          options = concat3 (options, ",", optarg);
        else
          options = strdup (optarg);
@@ -294,70 +316,37 @@ main (int argc, char **argv)
        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)
@@ -367,19 +356,23 @@ main (int argc, char **argv)
     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;
@@ -391,69 +384,72 @@ main (int argc, char **argv)
   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);
 }
@@ -504,13 +500,13 @@ mount_already_exists (const char *posix_path, int flags)
              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;
            }
        }
@@ -552,7 +548,7 @@ show_cygdrive_info ()
   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);
 }
This page took 0.037548 seconds and 5 git commands to generate.