409 lines
		
	
	
		
			9.8 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			409 lines
		
	
	
		
			9.8 KiB
		
	
	
	
		
			C++
		
	
	
	
| /* mount.cc
 | |
| 
 | |
|    Copyright 1996, 1997, 1998, 1999, 2000, 2001 Red Hat, Inc.
 | |
| 
 | |
| This file is part of Cygwin.
 | |
| 
 | |
| This software is a copyrighted work licensed under the terms of the
 | |
| Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
 | |
| details. */
 | |
| 
 | |
| #include <stdio.h>
 | |
| #include <sys/mount.h>
 | |
| #include <sys/stat.h>
 | |
| #include <mntent.h>
 | |
| #include <windows.h>
 | |
| #include <sys/cygwin.h>
 | |
| #include <stdlib.h>
 | |
| #include <getopt.h>
 | |
| 
 | |
| #ifdef errno
 | |
| #undef errno
 | |
| #endif
 | |
| #include <errno.h>
 | |
| 
 | |
| static void mount_commands (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 const char *progname;
 | |
| 
 | |
| static void
 | |
| error (const char *path)
 | |
| {
 | |
|   fprintf (stderr, "%s: %s: %s\n", progname, path,
 | |
| 	   (errno == EMFILE) ? "Too many mount entries" : strerror (errno));
 | |
|   exit (1);
 | |
| }
 | |
| 
 | |
| /* FIXME: do_mount should also print a warning message if the dev arg
 | |
|    is a non-existent Win32 path. */
 | |
| 
 | |
| 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);
 | |
| 
 | |
| #if 0
 | |
|   if (statres == -1)
 | |
|     {
 | |
|       /* FIXME: this'll fail if mount dir is missing any parent dirs */
 | |
|       if (create_missing_dirs == TRUE)
 | |
| 	{
 | |
| 	  if (mkdir (where, 0755) == -1)
 | |
| 	    fprintf (stderr, "Warning: unable to create %s!\n", where);
 | |
| 	  else
 | |
| 	    statres = 0; /* Pretend stat succeeded if we could mkdir. */
 | |
| 	}
 | |
|     }
 | |
| #endif
 | |
| 
 | |
|   if (mount (dev, where, flags))
 | |
|     error (where);
 | |
| 
 | |
|   if (statres == -1)
 | |
|     {
 | |
|       if (force == FALSE)
 | |
| 	fprintf (stderr, "%s: warning - %s does not exist.\n", progname, where);
 | |
|     }
 | |
|   else if (!(statbuf.st_mode & S_IFDIR))
 | |
|     {
 | |
|       if (force == FALSE)
 | |
| 	fprintf (stderr, "%s: warning: %s is not a directory.\n", progname, where);
 | |
|     }
 | |
| 
 | |
|   exit (0);
 | |
| }
 | |
| 
 | |
| struct option longopts[] =
 | |
| {
 | |
|   {"help", no_argument, NULL, 'h' },
 | |
|   {"binary", no_argument, NULL, 'b'},
 | |
|   {"force", no_argument, NULL, 'f'},
 | |
|   {"system", no_argument, NULL, 's'},
 | |
|   {"text", no_argument, NULL, 't'},
 | |
|   {"user", no_argument, NULL, 'u'},
 | |
|   {"executable", no_argument, NULL, 'x'},
 | |
|   {"change-cygdrive-prefix", no_argument, NULL, 'c'},
 | |
|   {"cygwin-executable", no_argument, NULL, 'X'},
 | |
|   {"show-cygdrive-prefix", no_argument, NULL, 'p'},
 | |
|   {"import-old-mounts", no_argument, NULL, 'i'},
 | |
|   {"mount-commands", no_argument, NULL, 'm'},
 | |
|   {NULL, 0, NULL, 0}
 | |
| };
 | |
| 
 | |
| char opts[] = "hbfstuxXpicm";
 | |
| 
 | |
| static void
 | |
| usage (void)
 | |
| {
 | |
|   fprintf (stderr, "Usage: %s [OPTION] [<win32path> <posixpath>]\n\
 | |
|   -b, --binary                  text files are equivalent to binary files\n\
 | |
| 				(newline = \\n)\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\
 | |
|   -i, --import-old-mounts       copy old registry mount table mounts into the\n\
 | |
|                                 current mount areas\n\
 | |
|   -p, --show-cygdrive-prefix    show user and/or system cygdrive path prefix\n\
 | |
|   -s, --system                  add mount point to system-wide registry location\n\
 | |
|   -t, --text       (default)    text files get \\r\\n line endings\n\
 | |
|   -u, --user       (default)    add mount point to user registry location\n\
 | |
|   -x, --executable              treat all files under mount point as executables\n\
 | |
|   -X, --cygwin-executable       treat all files under mount point as cygwin\n\
 | |
| 				executables\n\
 | |
|   -m, --mount-commands          write mount commands to replace user and\n\
 | |
| 				system mount points and cygdrive prefixes\n\
 | |
| ", progname);
 | |
|   exit (1);
 | |
| }
 | |
| 
 | |
| int
 | |
| main (int argc, char **argv)
 | |
| {
 | |
|   int i;
 | |
|   int flags = 0;
 | |
|   enum do_what
 | |
|   {
 | |
|     nada,
 | |
|     saw_change_cygdrive_prefix,
 | |
|     saw_import_old_mounts,
 | |
|     saw_show_cygdrive_prefix,
 | |
|     saw_mount_commands
 | |
|   } do_what = nada;
 | |
| 
 | |
|   progname = argv[0];
 | |
| 
 | |
|   if (argc == 1)
 | |
|     {
 | |
|       show_mounts ();
 | |
|       exit (0);
 | |
|     }
 | |
| 
 | |
|   while ((i = getopt_long (argc, argv, opts, longopts, NULL)) != EOF)
 | |
|     switch (i)
 | |
|       {
 | |
|       case 'b':
 | |
| 	flags |= MOUNT_BINARY;
 | |
| 	break;
 | |
|       case 'c':
 | |
| 	if (do_what == nada)
 | |
| 	  do_what = saw_change_cygdrive_prefix;
 | |
| 	else
 | |
| 	  usage ();
 | |
| 	break;
 | |
|       case 'f':
 | |
| 	force = TRUE;
 | |
| 	break;
 | |
|       case 'i':
 | |
| 	if (do_what == nada)
 | |
| 	  do_what = saw_import_old_mounts;
 | |
| 	else
 | |
| 	  usage ();
 | |
| 	break;
 | |
|       case 'p':
 | |
| 	if (do_what == nada)
 | |
| 	  do_what = saw_show_cygdrive_prefix;
 | |
| 	else
 | |
| 	  usage ();
 | |
| 	break;
 | |
|       case 's':
 | |
| 	flags |= MOUNT_SYSTEM;
 | |
| 	break;
 | |
|       case 't':
 | |
| 	flags &= ~MOUNT_BINARY;
 | |
| 	break;
 | |
|       case 'u':
 | |
| 	flags &= ~MOUNT_SYSTEM;
 | |
| 	break;
 | |
|       case 'X':
 | |
| 	flags |= MOUNT_CYGWIN_EXEC;
 | |
| 	break;
 | |
|       case 'x':
 | |
| 	flags |= MOUNT_EXEC;
 | |
| 	break;
 | |
|       case 'm':
 | |
| 	if (do_what == nada)
 | |
| 	  do_what = saw_mount_commands;
 | |
| 	else
 | |
| 	  usage ();
 | |
| 	break;
 | |
|       default:
 | |
| 	usage ();
 | |
|       }
 | |
| 
 | |
|   argc--;
 | |
|   switch (do_what)
 | |
|     {
 | |
|     case saw_change_cygdrive_prefix:
 | |
|       if (optind != argc)
 | |
| 	usage ();
 | |
|       change_cygdrive_prefix (argv[optind], flags);
 | |
|       break;
 | |
|     case saw_import_old_mounts:
 | |
|       if (optind <= argc)
 | |
| 	usage ();
 | |
|       else
 | |
| 	cygwin_internal (CW_READ_V1_MOUNT_TABLES);
 | |
|       break;
 | |
|     case saw_show_cygdrive_prefix:
 | |
|       if (optind <= argc)
 | |
| 	usage ();
 | |
|       show_cygdrive_info ();
 | |
|       break;
 | |
|     case saw_mount_commands:
 | |
|       if (optind <= argc)
 | |
| 	usage ();
 | |
|       mount_commands ();
 | |
|       break;
 | |
|     default:
 | |
|       if (optind != (argc - 1))
 | |
| 	{
 | |
| 	  if (optind >= argc)
 | |
| 	    fprintf (stderr, "%s: not enough arguments\n", progname);
 | |
| 	  else
 | |
| 	    fprintf (stderr, "%s: too many arguments\n", progname);
 | |
| 	  usage ();
 | |
| 	}
 | |
|       if (force || !mount_already_exists (argv[optind + 1], flags))
 | |
| 	do_mount (argv[optind], argv[optind + 1], flags);
 | |
|       else
 | |
| 	{
 | |
| 	  errno = EBUSY;
 | |
| 	  error (argv[optind + 1]);
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|   /* NOTREACHED */
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| static void
 | |
| mount_commands (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];
 | |
| 
 | |
|   // write mount commands for user and system mount points
 | |
|   while ((p = getmntent (m)) != NULL) {
 | |
|     // Only list non-cygdrives
 | |
|     if (!strstr (p->mnt_opts, ",noumount")) {
 | |
|       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");
 | |
|       while ((c = strchr (p->mnt_fsname, '\\')) != NULL)
 | |
|         *c = '/';
 | |
|       printf (format_mnt, opts, p->mnt_fsname, p->mnt_dir);
 | |
|     }
 | |
|   }
 | |
|   endmntent (m);
 | |
| 
 | |
|   // write mount commands for cygdrive prefixes
 | |
|   cygwin_internal (CW_GET_CYGDRIVE_INFO, user, system, user_flags,
 | |
| 		   system_flags);
 | |
|   if (strlen (user) > 0) {
 | |
|     strcpy (opts, "   ");
 | |
|     if      (user_flags[0] == 'b')
 | |
|       strcat (opts, " -b");
 | |
|     else if (user_flags[0] == 't')
 | |
|       strcat (opts, " -t");
 | |
|     printf (format_cyg, opts, user);
 | |
|   }
 | |
|   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);
 | |
|   }
 | |
| 
 | |
|   exit(0);
 | |
| }
 | |
| 
 | |
| static void
 | |
| show_mounts (void)
 | |
| {
 | |
|   FILE *m = setmntent ("/-not-used-", "r");
 | |
|   struct mntent *p;
 | |
|   const char *format = "%s on %s type %s (%s)\n";
 | |
| 
 | |
|   // printf (format, "Device", "Directory", "Type", "Flags");
 | |
|   while ((p = getmntent (m)) != NULL)
 | |
|     printf (format, p->mnt_fsname, p->mnt_dir, p->mnt_type, p->mnt_opts);
 | |
|   endmntent (m);
 | |
| }
 | |
| 
 | |
| /* Return 1 if mountpoint from the same registry area is already in
 | |
|    mount table.  Otherwise return 0. */
 | |
| static int
 | |
| mount_already_exists (const char *posix_path, int flags)
 | |
| {
 | |
|   int found_matching = 0;
 | |
| 
 | |
|   FILE *m = setmntent ("/-not-used-", "r");
 | |
|   struct mntent *p;
 | |
| 
 | |
|   while ((p = getmntent (m)) != NULL)
 | |
|     {
 | |
|       /* if the paths match, and they're both the same type of mount. */
 | |
|       if (strcmp (p->mnt_dir, posix_path) == 0)
 | |
| 	{
 | |
| 	  if (p->mnt_type[0] == 'u')
 | |
| 	    {
 | |
| 	      if (!(flags & MOUNT_SYSTEM)) /* both current_user */
 | |
| 		found_matching = 1;
 | |
| 	      else
 | |
| 		fprintf (stderr,
 | |
| 			 "%s: warning: system mount point of '%s' "
 | |
| 			 "will always be masked by user mount.\n",
 | |
| 			 progname, posix_path);
 | |
| 	      break;
 | |
| 	    }
 | |
| 	  else if (p->mnt_type[0] == 's')
 | |
| 	    {
 | |
| 	      if (flags & MOUNT_SYSTEM) /* both system */
 | |
| 		found_matching = 1;
 | |
| 	      else
 | |
| 		fprintf (stderr,
 | |
| 			 "%s: warning: user mount point of '%s' "
 | |
| 			 "masks system mount.\n",
 | |
| 			 progname, posix_path);
 | |
| 	      break;
 | |
| 	    }
 | |
| 	  else
 | |
| 	    {
 | |
| 	      fprintf (stderr, "%s: warning: couldn't determine mount type.\n", progname);
 | |
| 	      break;
 | |
| 	    }
 | |
| 	}
 | |
|     }
 | |
|   endmntent (m);
 | |
| 
 | |
|   return found_matching;
 | |
| }
 | |
| 
 | |
| /* change_cygdrive_prefix: Change the cygdrive prefix */
 | |
| static void
 | |
| change_cygdrive_prefix (const char *new_prefix, int flags)
 | |
| {
 | |
|   flags |= MOUNT_AUTO;
 | |
| 
 | |
|   if (mount (NULL, new_prefix, flags))
 | |
|     error (new_prefix);
 | |
| 
 | |
|   exit (0);
 | |
| }
 | |
| 
 | |
| /* show_cygdrive_info: Show the user and/or cygdrive info, i.e., prefix and
 | |
|    flags.*/
 | |
| static void
 | |
| show_cygdrive_info ()
 | |
| {
 | |
|   /* Get the cygdrive info */
 | |
|   char user[MAX_PATH];
 | |
|   char system[MAX_PATH];
 | |
|   char user_flags[MAX_PATH];
 | |
|   char system_flags[MAX_PATH];
 | |
|   cygwin_internal (CW_GET_CYGDRIVE_INFO, user, system, user_flags,
 | |
| 		   system_flags);
 | |
| 
 | |
|   /* Display the user and system cygdrive path prefix, if necessary
 | |
|      (ie, not empty) */
 | |
|   const char *format = "%-18s  %-11s  %s\n";
 | |
|   printf (format, "Prefix", "Type", "Flags");
 | |
|   if (strlen (user) > 0)
 | |
|     printf (format, user, "user", user_flags);
 | |
|   if (strlen (system) > 0)
 | |
|     printf (format, system, "system", system_flags);
 | |
| 
 | |
|   exit (0);
 | |
| }
 |