3 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005,
6 This file is part of Cygwin.
8 This software is a copyrighted work licensed under the terms of the
9 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
13 #include <sys/mount.h>
17 #include <sys/cygwin.h>
27 #define EXEC_FLAGS (MOUNT_EXEC | MOUNT_NOTEXEC | MOUNT_CYGWIN_EXEC)
29 static void mount_commands (void);
30 static void show_mounts (void);
31 static void show_cygdrive_info (void);
32 static void change_cygdrive_prefix (const char *new_prefix
, int flags
);
33 static int mount_already_exists (const char *posix_path
, int flags
);
35 // static short create_missing_dirs = FALSE;
36 static short force
= FALSE
;
38 static const char version
[] = "$Revision$";
39 static const char *progname
;
42 error (const char *path
)
44 fprintf (stderr
, "%s: %s: %s\n", progname
, path
,
45 (errno
== EMFILE
) ? "Too many mount entries" : strerror (errno
));
49 /* FIXME: do_mount should also print a warning message if the dev arg
50 is a non-existent Win32 path. */
53 do_mount (const char *dev
, const char *where
, int flags
)
58 statres
= stat (where
, &statbuf
);
63 /* FIXME: this'll fail if mount dir is missing any parent dirs */
64 if (create_missing_dirs
== TRUE
)
66 if (mkdir (where
, 0755) == -1)
67 fprintf (stderr
, "Warning: unable to create %s!\n", where
);
69 statres
= 0; /* Pretend stat succeeded if we could mkdir. */
77 fprintf (stderr
, "%s: warning - %s does not exist.\n", progname
, where
);
79 else if (!(statbuf
.st_mode
& S_IFDIR
))
82 fprintf (stderr
, "%s: warning: %s is not a directory.\n", progname
, where
);
85 if (!force
&& !(flags
& EXEC_FLAGS
) && strlen (dev
))
87 char devtmp
[1 + 2 * strlen (dev
)];
89 char c
= strchr (devtmp
, '\0')[-1];
90 if (c
== '/' || c
== '\\')
92 /* Use a curious property of Windows which allows the use of \.. even
93 on non-directory paths. */
94 for (const char *p
= dev
; (p
= strpbrk (p
, "/\\")); p
++)
95 strcat (devtmp
, "\\..");
96 strcat (devtmp
, "\\");
97 if (GetDriveType (devtmp
) == DRIVE_REMOTE
)
99 fprintf (stderr
, "%s: defaulting to '--no-executable' flag for speed since native path\n"
100 "%*creferences a remote share. Use '-f' option to override.\n", progname
,
101 strlen(progname
) + 2, ' ');
102 flags
|= MOUNT_NOTEXEC
;
106 if (mount (dev
, where
, flags
))
112 static struct option longopts
[] =
114 {"binary", no_argument
, NULL
, 'b'},
115 {"change-cygdrive-prefix", no_argument
, NULL
, 'c'},
116 {"cygwin-executable", no_argument
, NULL
, 'X'},
117 {"executable", no_argument
, NULL
, 'x'},
118 {"force", no_argument
, NULL
, 'f'},
119 {"help", no_argument
, NULL
, 'h' },
120 {"mount-commands", no_argument
, NULL
, 'm'},
121 {"no-executable", no_argument
, NULL
, 'E'},
122 {"options", required_argument
, NULL
, 'o'},
123 {"show-cygdrive-prefix", no_argument
, NULL
, 'p'},
124 {"system", no_argument
, NULL
, 's'},
125 {"text", no_argument
, NULL
, 't'},
126 {"user", no_argument
, NULL
, 'u'},
127 {"version", no_argument
, NULL
, 'v'},
131 static char opts
[] = "bcfhmpstuvxEXo:";
134 usage (FILE *where
= stderr
)
136 fprintf (where
, "Usage: %s [OPTION] [<win32path> <posixpath>]\n\
137 Display information about mounted filesystems, or mount a filesystem\n\
139 -b, --binary (default) text files are equivalent to binary files\n\
141 -c, --change-cygdrive-prefix change the cygdrive path prefix to <posixpath>\n\
142 -f, --force force mount, don't warn about missing mount\n\
144 -h, --help output usage information and exit\n\
145 -m, --mount-commands write mount commands to replicate user and\n\
146 system mount points and cygdrive prefixes\n\
147 -o, --options X[,X...] specify mount options\n\
148 -p, --show-cygdrive-prefix show user and/or system cygdrive path prefix\n\
149 -s, --system (ignored)\n\
150 -t, --text text files get \\r\\n line endings\n\
151 -u, --user (ignored)\n\
152 -v, --version output version information and exit\n\
153 -x, --executable treat all files under mount point as executables\n\
154 -E, --no-executable treat all files under mount point as \n\
156 -X, --cygwin-executable treat all files under mount point as cygwin\n\
159 exit (where
== stderr
? 1 : 0);
169 {"user", MOUNT_SYSTEM
, 1},
170 {"system", MOUNT_SYSTEM
, 0},
171 {"binary", MOUNT_BINARY
, 0},
172 {"text", MOUNT_BINARY
, 1},
173 {"exec", MOUNT_EXEC
, 0},
174 {"notexec", MOUNT_NOTEXEC
, 0},
175 {"cygexec", MOUNT_CYGWIN_EXEC
, 0},
182 const char *v
= strchr (version
, ':');
192 len
= strchr (v
, ' ') - v
;
196 Filesystem Utility\n\
197 Copyright 1996-2008 Red Hat, Inc.\n\
199 ", progname
, len
, v
, __DATE__
);
203 concat3 (char *a
, const char *b
, const char *c
)
205 size_t totlen
= strlen (a
) + strlen (b
) + strlen (c
) + 1;
206 a
= (char *) realloc (a
, totlen
);
207 return strcat (strcat (a
, b
), c
);
211 main (int argc
, char **argv
)
214 int flags
= MOUNT_BINARY
;
215 char *options
= strdup ("");
219 saw_change_cygdrive_prefix
,
220 saw_show_cygdrive_prefix
,
224 progname
= strrchr (argv
[0], '/');
225 if (progname
== NULL
)
226 progname
= strrchr (argv
[0], '\\');
227 if (progname
== NULL
)
238 while ((i
= getopt_long (argc
, argv
, opts
, longopts
, NULL
)) != EOF
)
242 flags
|= MOUNT_BINARY
;
246 do_what
= saw_change_cygdrive_prefix
;
258 do_what
= saw_mount_commands
;
264 options
= concat3 (options
, ",", optarg
);
266 options
= strdup (optarg
);
270 do_what
= saw_show_cygdrive_prefix
;
277 flags
&= ~MOUNT_BINARY
;
289 flags
|= MOUNT_NOTEXEC
;
292 flags
|= MOUNT_CYGWIN_EXEC
;
300 char *p
= strchr (options
, ',');
304 p
= strchr (options
, '\0');
306 for (opt
*o
= oopts
; o
< (oopts
+ (sizeof (oopts
) / sizeof (oopts
[0]))); o
++)
307 if (strcmp (options
, o
->name
) == 0)
315 fprintf (stderr
, "%s: invalid option - '%s'\n", progname
, options
);
322 if (flags
& MOUNT_NOTEXEC
&& flags
& (MOUNT_EXEC
| MOUNT_CYGWIN_EXEC
))
324 fprintf (stderr
, "%s: invalid combination of executable options\n", progname
);
328 cygwin_internal (CW_SET_DOS_FILE_WARNING
, false);
333 case saw_change_cygdrive_prefix
:
336 change_cygdrive_prefix (argv
[optind
], flags
);
338 case saw_show_cygdrive_prefix
:
341 show_cygdrive_info ();
343 case saw_mount_commands
:
349 if (optind
!= (argc
- 1))
352 fprintf (stderr
, "%s: not enough arguments\n", progname
);
354 fprintf (stderr
, "%s: too many arguments\n", progname
);
357 if (force
|| !mount_already_exists (argv
[optind
+ 1], flags
))
358 do_mount (argv
[optind
], argv
[optind
+ 1], flags
);
362 error (argv
[optind
+ 1]);
371 mount_commands (void)
373 FILE *m
= setmntent ("/-not-used-", "r");
376 const char *format_mnt
= "mount%s \"%s\" \"%s\"\n";
377 const char *format_cyg
= "mount%s --change-cygdrive-prefix \"%s\"\n";
380 char system
[MAX_PATH
];
381 char user_flags
[MAX_PATH
];
382 char system_flags
[MAX_PATH
];
384 // write mount commands for user and system mount points
385 while ((p
= getmntent (m
)) != NULL
)
386 // Only list non-cygdrives
387 if (!strstr (p
->mnt_opts
, ",noumount"))
390 if (p
->mnt_opts
[0] == 'b')
391 strcat (opts
, " -b");
392 else if (p
->mnt_opts
[0] == 't')
393 strcat (opts
, " -t");
394 if (strstr (p
->mnt_opts
, ",exec"))
395 strcat (opts
, " -x");
396 if (strstr (p
->mnt_opts
, ",noexec"))
397 strcat (opts
, " -E");
398 if (strstr (p
->mnt_opts
, ",cygexec"))
399 strcat (opts
, " -X");
400 while ((c
= strchr (p
->mnt_fsname
, '\\')) != NULL
)
402 printf (format_mnt
, opts
, p
->mnt_fsname
, p
->mnt_dir
);
406 // write mount commands for cygdrive prefixes
407 cygwin_internal (CW_GET_CYGDRIVE_INFO
, user
, system
, user_flags
,
410 if (strlen (user
) > 0)
412 strcpy (opts
, " -u");
413 if (user_flags
[0] == 'b')
414 strcat (opts
, " -b");
415 else if (user_flags
[0] == 't')
416 strcat (opts
, " -t");
417 printf (format_cyg
, opts
, user
);
420 if (strlen (system
) > 0)
422 strcpy (opts
, " -s");
423 if (system_flags
[0] == 'b')
424 strcat (opts
, " -b");
425 else if (system_flags
[0] == 't')
426 strcat (opts
, " -t");
427 printf (format_cyg
, opts
, system
);
436 FILE *m
= setmntent ("/-not-used-", "r");
438 const char *format
= "%s on %s type %s (%s)\n";
440 // printf (format, "Device", "Directory", "Type", "Flags");
441 while ((p
= getmntent (m
)) != NULL
)
442 printf (format
, p
->mnt_fsname
, p
->mnt_dir
, p
->mnt_type
, p
->mnt_opts
);
446 /* Return 1 if mountpoint from the same registry area is already in
447 mount table. Otherwise return 0. */
449 mount_already_exists (const char *posix_path
, int flags
)
451 int found_matching
= 0;
453 FILE *m
= setmntent ("/-not-used-", "r");
456 while ((p
= getmntent (m
)) != NULL
)
458 /* if the paths match, and they're both the same type of mount. */
459 if (strcmp (p
->mnt_dir
, posix_path
) == 0)
461 if (p
->mnt_type
[0] == 'u')
463 if (!(flags
& MOUNT_SYSTEM
)) /* both current_user */
467 "%s: warning: system mount point of '%s' "
468 "will always be masked by user mount.\n",
469 progname
, posix_path
);
472 else if (p
->mnt_type
[0] == 's')
474 if (flags
& MOUNT_SYSTEM
) /* both system */
478 "%s: warning: user mount point of '%s' "
479 "masks system mount.\n",
480 progname
, posix_path
);
485 fprintf (stderr
, "%s: warning: couldn't determine mount type.\n", progname
);
492 return found_matching
;
495 /* change_cygdrive_prefix: Change the cygdrive prefix */
497 change_cygdrive_prefix (const char *new_prefix
, int flags
)
499 flags
|= MOUNT_CYGDRIVE
;
501 if (mount (NULL
, new_prefix
, flags
))
507 /* show_cygdrive_info: Show the user and/or cygdrive info, i.e., prefix and
510 show_cygdrive_info ()
512 /* Get the cygdrive info */
514 char system
[MAX_PATH
];
515 char user_flags
[MAX_PATH
];
516 char system_flags
[MAX_PATH
];
517 cygwin_internal (CW_GET_CYGDRIVE_INFO
, user
, system
, user_flags
,
520 /* Display the user and system cygdrive path prefix, if necessary
522 const char *format
= "%-18s %-11s %s\n";
523 printf (format
, "Prefix", "Type", "Flags");
524 if (strlen (user
) > 0)
525 printf (format
, user
, "user", user_flags
);
526 if (strlen (system
) > 0)
527 printf (format
, system
, "system", system_flags
);