3 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005 Red Hat, Inc.
5 This file is part of Cygwin.
7 This software is a copyrighted work licensed under the terms of the
8 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
12 #include <sys/mount.h>
16 #include <sys/cygwin.h>
26 #define EXEC_FLAGS (MOUNT_EXEC | MOUNT_NOTEXEC | MOUNT_CYGWIN_EXEC)
28 static void mount_commands (void);
29 static void show_mounts (void);
30 static void show_cygdrive_info (void);
31 static void change_cygdrive_prefix (const char *new_prefix
, int flags
);
32 static int mount_already_exists (const char *posix_path
, int flags
);
34 // static short create_missing_dirs = FALSE;
35 static short force
= FALSE
;
37 static const char version
[] = "$Revision$";
38 static const char *progname
;
41 error (const char *path
)
43 fprintf (stderr
, "%s: %s: %s\n", progname
, path
,
44 (errno
== EMFILE
) ? "Too many mount entries" : strerror (errno
));
48 /* FIXME: do_mount should also print a warning message if the dev arg
49 is a non-existent Win32 path. */
52 do_mount (const char *dev
, const char *where
, int flags
)
55 char win32_path
[MAX_PATH
];
58 cygwin_conv_to_win32_path (where
, win32_path
);
60 statres
= stat (win32_path
, &statbuf
);
65 /* FIXME: this'll fail if mount dir is missing any parent dirs */
66 if (create_missing_dirs
== TRUE
)
68 if (mkdir (where
, 0755) == -1)
69 fprintf (stderr
, "Warning: unable to create %s!\n", where
);
71 statres
= 0; /* Pretend stat succeeded if we could mkdir. */
79 fprintf (stderr
, "%s: warning - %s does not exist.\n", progname
, where
);
81 else if (!(statbuf
.st_mode
& S_IFDIR
))
84 fprintf (stderr
, "%s: warning: %s is not a directory.\n", progname
, where
);
87 if (!force
&& !(flags
& EXEC_FLAGS
) && strlen (dev
))
89 char devtmp
[1 + 2 * strlen (dev
)];
91 char c
= strchr (devtmp
, '\0')[-1];
92 if (c
== '/' || c
== '\\')
94 /* Use a curious property of Windows which allows the use of \.. even
95 on non-directory paths. */
96 for (const char *p
= dev
; (p
= strpbrk (p
, "/\\")); p
++)
97 strcat (devtmp
, "\\..");
98 strcat (devtmp
, "\\");
99 if (GetDriveType (devtmp
) == DRIVE_REMOTE
)
101 fprintf (stderr
, "%s: defaulting to '--no-executable' flag for speed since native path\n"
102 "%*creferences a remote share. Use '-f' option to override.\n", progname
,
103 strlen(progname
) + 2, ' ');
104 flags
|= MOUNT_NOTEXEC
;
108 if (!force
&& flags
& MOUNT_ENC
)
110 DIR *dd
= opendir (dev
);
114 while ((d
= readdir (dd
)))
116 if (d
->d_name
[0] != '.')
118 else if (d
->d_name
[1] == '\0'
119 || (d
->d_name
[1] == '.' && d
->d_name
[2] == '\0'))
121 fprintf (stderr
, "%s: error: don't use \"-o managed\" on non-empty directories\n", progname
);
127 if (mount (dev
, where
, flags
))
133 static struct option longopts
[] =
135 {"binary", no_argument
, NULL
, 'b'},
136 {"change-cygdrive-prefix", no_argument
, NULL
, 'c'},
137 {"cygwin-executable", no_argument
, NULL
, 'X'},
138 {"executable", no_argument
, NULL
, 'x'},
139 {"force", no_argument
, NULL
, 'f'},
140 {"help", no_argument
, NULL
, 'h' },
141 {"mount-commands", no_argument
, NULL
, 'm'},
142 {"no-executable", no_argument
, NULL
, 'E'},
143 {"options", required_argument
, NULL
, 'o'},
144 {"show-cygdrive-prefix", no_argument
, NULL
, 'p'},
145 {"system", no_argument
, NULL
, 's'},
146 {"text", no_argument
, NULL
, 't'},
147 {"user", no_argument
, NULL
, 'u'},
148 {"version", no_argument
, NULL
, 'v'},
152 static char opts
[] = "bcfhmpstuvxEXo:";
155 usage (FILE *where
= stderr
)
157 fprintf (where
, "Usage: %s [OPTION] [<win32path> <posixpath>]\n\
158 Display information about mounted filesystems, or mount a filesystem\n\
160 -b, --binary (default) text files are equivalent to binary files\n\
162 -c, --change-cygdrive-prefix change the cygdrive path prefix to <posixpath>\n\
163 -f, --force force mount, don't warn about missing mount\n\
165 -h, --help output usage information and exit\n\
166 -m, --mount-commands write mount commands to replicate user and\n\
167 system mount points and cygdrive prefixes\n\
168 -o, --options X[,X...] specify mount options\n\
169 -p, --show-cygdrive-prefix show user and/or system cygdrive path prefix\n\
170 -s, --system (default) add system-wide mount point\n\
171 -t, --text text files get \\r\\n line endings\n\
172 -u, --user add user-only mount point\n\
173 -v, --version output version information and exit\n\
174 -x, --executable treat all files under mount point as executables\n\
175 -E, --no-executable treat all files under mount point as \n\
177 -X, --cygwin-executable treat all files under mount point as cygwin\n\
180 exit (where
== stderr
? 1 : 0);
190 {"user", MOUNT_SYSTEM
, 1},
191 {"system", MOUNT_SYSTEM
, 0},
192 {"binary", MOUNT_BINARY
, 0},
193 {"text", MOUNT_BINARY
, 1},
194 {"exec", MOUNT_EXEC
, 0},
195 {"notexec", MOUNT_NOTEXEC
, 0},
196 {"cygexec", MOUNT_CYGWIN_EXEC
, 0},
198 {"managed", MOUNT_ENC
, 0}
204 const char *v
= strchr (version
, ':');
214 len
= strchr (v
, ' ') - v
;
218 Filesystem Utility\n\
219 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.\n\
221 ", progname
, len
, v
, __DATE__
);
225 concat3 (char *a
, const char *b
, const char *c
)
227 size_t totlen
= strlen (a
) + strlen (b
) + strlen (c
) + 1;
228 a
= (char *) realloc (a
, totlen
);
229 return strcat (strcat (a
, b
), c
);
233 main (int argc
, char **argv
)
236 int flags
= MOUNT_BINARY
;
237 int default_flag
= MOUNT_SYSTEM
;
238 char *options
= strdup ("");
242 saw_change_cygdrive_prefix
,
243 saw_show_cygdrive_prefix
,
247 progname
= strrchr (argv
[0], '/');
248 if (progname
== NULL
)
249 progname
= strrchr (argv
[0], '\\');
250 if (progname
== NULL
)
261 while ((i
= getopt_long (argc
, argv
, opts
, longopts
, NULL
)) != EOF
)
265 flags
|= MOUNT_BINARY
;
269 do_what
= saw_change_cygdrive_prefix
;
281 do_what
= saw_mount_commands
;
287 options
= concat3 (options
, ",", optarg
);
289 options
= strdup (optarg
);
293 do_what
= saw_show_cygdrive_prefix
;
298 flags
|= MOUNT_SYSTEM
;
301 flags
&= ~MOUNT_BINARY
;
304 flags
&= ~MOUNT_SYSTEM
;
315 flags
|= MOUNT_NOTEXEC
;
318 flags
|= MOUNT_CYGWIN_EXEC
;
326 char *p
= strchr (options
, ',');
330 p
= strchr (options
, '\0');
332 for (opt
*o
= oopts
; o
< (oopts
+ (sizeof (oopts
) / sizeof (oopts
[0]))); o
++)
333 if (strcmp (options
, o
->name
) == 0)
341 fprintf (stderr
, "%s: invalid option - '%s'\n", progname
, options
);
348 if (flags
& MOUNT_NOTEXEC
&& flags
& (MOUNT_EXEC
| MOUNT_CYGWIN_EXEC
))
350 fprintf (stderr
, "%s: invalid combination of executable options\n", progname
);
357 case saw_change_cygdrive_prefix
:
360 change_cygdrive_prefix (argv
[optind
], flags
| default_flag
);
362 case saw_show_cygdrive_prefix
:
365 show_cygdrive_info ();
367 case saw_mount_commands
:
373 if (optind
!= (argc
- 1))
376 fprintf (stderr
, "%s: not enough arguments\n", progname
);
378 fprintf (stderr
, "%s: too many arguments\n", progname
);
381 if (force
|| !mount_already_exists (argv
[optind
+ 1], flags
| default_flag
))
382 do_mount (argv
[optind
], argv
[optind
+ 1], flags
| default_flag
);
386 error (argv
[optind
+ 1]);
395 mount_commands (void)
397 FILE *m
= setmntent ("/-not-used-", "r");
400 const char *format_mnt
= "mount%s \"%s\" \"%s\"\n";
401 const char *format_cyg
= "mount%s --change-cygdrive-prefix \"%s\"\n";
404 char system
[MAX_PATH
];
405 char user_flags
[MAX_PATH
];
406 char system_flags
[MAX_PATH
];
408 // write mount commands for user and system mount points
409 while ((p
= getmntent (m
)) != NULL
)
410 // Only list non-cygdrives
411 if (!strstr (p
->mnt_opts
, ",noumount"))
414 if (p
->mnt_type
[0] == 'u')
415 strcat (opts
, " -u");
416 else if (p
->mnt_type
[0] == 's')
417 strcat (opts
, " -s");
418 if (p
->mnt_opts
[0] == 'b')
419 strcat (opts
, " -b");
420 else if (p
->mnt_opts
[0] == 't')
421 strcat (opts
, " -t");
422 if (strstr (p
->mnt_opts
, ",exec"))
423 strcat (opts
, " -x");
424 if (strstr (p
->mnt_opts
, ",noexec"))
425 strcat (opts
, " -E");
426 if (strstr (p
->mnt_opts
, ",cygexec"))
427 strcat (opts
, " -X");
428 if (strstr (p
->mnt_opts
, ",managed"))
429 strcat (opts
, " -o managed");
430 while ((c
= strchr (p
->mnt_fsname
, '\\')) != NULL
)
432 printf (format_mnt
, opts
, p
->mnt_fsname
, p
->mnt_dir
);
436 // write mount commands for cygdrive prefixes
437 cygwin_internal (CW_GET_CYGDRIVE_INFO
, user
, system
, user_flags
,
440 if (strlen (user
) > 0)
442 strcpy (opts
, " -u");
443 if (user_flags
[0] == 'b')
444 strcat (opts
, " -b");
445 else if (user_flags
[0] == 't')
446 strcat (opts
, " -t");
447 printf (format_cyg
, opts
, user
);
450 if (strlen (system
) > 0)
452 strcpy (opts
, " -s");
453 if (system_flags
[0] == 'b')
454 strcat (opts
, " -b");
455 else if (system_flags
[0] == 't')
456 strcat (opts
, " -t");
457 printf (format_cyg
, opts
, system
);
466 FILE *m
= setmntent ("/-not-used-", "r");
468 const char *format
= "%s on %s type %s (%s)\n";
470 // printf (format, "Device", "Directory", "Type", "Flags");
471 while ((p
= getmntent (m
)) != NULL
)
472 printf (format
, p
->mnt_fsname
, p
->mnt_dir
, p
->mnt_type
, p
->mnt_opts
);
476 /* Return 1 if mountpoint from the same registry area is already in
477 mount table. Otherwise return 0. */
479 mount_already_exists (const char *posix_path
, int flags
)
481 int found_matching
= 0;
483 FILE *m
= setmntent ("/-not-used-", "r");
486 while ((p
= getmntent (m
)) != NULL
)
488 /* if the paths match, and they're both the same type of mount. */
489 if (strcmp (p
->mnt_dir
, posix_path
) == 0)
491 if (p
->mnt_type
[0] == 'u')
493 if (!(flags
& MOUNT_SYSTEM
)) /* both current_user */
497 "%s: warning: system mount point of '%s' "
498 "will always be masked by user mount.\n",
499 progname
, posix_path
);
502 else if (p
->mnt_type
[0] == 's')
504 if (flags
& MOUNT_SYSTEM
) /* both system */
508 "%s: warning: user mount point of '%s' "
509 "masks system mount.\n",
510 progname
, posix_path
);
515 fprintf (stderr
, "%s: warning: couldn't determine mount type.\n", progname
);
522 return found_matching
;
525 /* change_cygdrive_prefix: Change the cygdrive prefix */
527 change_cygdrive_prefix (const char *new_prefix
, int flags
)
529 flags
|= MOUNT_CYGDRIVE
;
531 if (mount (NULL
, new_prefix
, flags
))
537 /* show_cygdrive_info: Show the user and/or cygdrive info, i.e., prefix and
540 show_cygdrive_info ()
542 /* Get the cygdrive info */
544 char system
[MAX_PATH
];
545 char user_flags
[MAX_PATH
];
546 char system_flags
[MAX_PATH
];
547 cygwin_internal (CW_GET_CYGDRIVE_INFO
, user
, system
, user_flags
,
550 /* Display the user and system cygdrive path prefix, if necessary
552 const char *format
= "%-18s %-11s %s\n";
553 printf (format
, "Prefix", "Type", "Flags");
554 if (strlen (user
) > 0)
555 printf (format
, user
, "user", user_flags
);
556 if (strlen (system
) > 0)
557 printf (format
, system
, "system", system_flags
);