3 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002 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>
25 #define EXEC_FLAGS (MOUNT_EXEC | MOUNT_NOTEXEC | MOUNT_CYGWIN_EXEC)
27 static void mount_commands (void);
28 static void show_mounts (void);
29 static void show_cygdrive_info (void);
30 static void change_cygdrive_prefix (const char *new_prefix
, int flags
);
31 static int mount_already_exists (const char *posix_path
, int flags
);
33 // static short create_missing_dirs = FALSE;
34 static short force
= FALSE
;
36 static const char version
[] = "$Revision$";
37 static const char *progname
;
40 error (const char *path
)
42 fprintf (stderr
, "%s: %s: %s\n", progname
, path
,
43 (errno
== EMFILE
) ? "Too many mount entries" : strerror (errno
));
47 /* FIXME: do_mount should also print a warning message if the dev arg
48 is a non-existent Win32 path. */
51 do_mount (const char *dev
, const char *where
, int flags
)
54 char win32_path
[MAX_PATH
];
57 cygwin_conv_to_win32_path (where
, win32_path
);
59 statres
= stat (win32_path
, &statbuf
);
64 /* FIXME: this'll fail if mount dir is missing any parent dirs */
65 if (create_missing_dirs
== TRUE
)
67 if (mkdir (where
, 0755) == -1)
68 fprintf (stderr
, "Warning: unable to create %s!\n", where
);
70 statres
= 0; /* Pretend stat succeeded if we could mkdir. */
78 fprintf (stderr
, "%s: warning - %s does not exist.\n", progname
, where
);
80 else if (!(statbuf
.st_mode
& S_IFDIR
))
83 fprintf (stderr
, "%s: warning: %s is not a directory.\n", progname
, where
);
86 if (!force
&& !(flags
& EXEC_FLAGS
) && strlen (dev
))
88 char devtmp
[1 + 2 * strlen (dev
)];
90 char c
= strchr (devtmp
, '\0')[-1];
91 if (c
== '/' || c
== '\\')
93 /* Use a curious property of Windows which allows the use of \.. even
94 on non-directory paths. */
95 for (const char *p
= dev
; (p
= strpbrk (p
, "/\\")); p
++)
96 strcat (devtmp
, "\\..");
97 strcat (devtmp
, "\\");
98 if (GetDriveType (devtmp
) == DRIVE_REMOTE
)
100 fprintf (stderr
, "%s: defaulting to '--no-executable' flag for speed since native path\n"
101 "%*creferences a remote share. Use '-f' option to override.\n", progname
,
102 strlen(progname
) + 2, ' ');
103 flags
|= MOUNT_NOTEXEC
;
107 if (mount (dev
, where
, flags
))
113 static struct option longopts
[] =
115 {"binary", no_argument
, NULL
, 'b'},
116 {"change-cygdrive-prefix", no_argument
, NULL
, 'c'},
117 {"cygwin-executable", no_argument
, NULL
, 'X'},
118 {"executable", no_argument
, NULL
, 'x'},
119 {"force", no_argument
, NULL
, 'f'},
120 {"help", no_argument
, NULL
, 'h' },
121 {"mount-commands", no_argument
, NULL
, 'm'},
122 {"no-executable", no_argument
, NULL
, 'E'},
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
[] = "bcfhmpstuvxEX";
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 replace user and\n\
146 system mount points and cygdrive prefixes\n\
147 -p, --show-cygdrive-prefix show user and/or system cygdrive path prefix\n\
148 -s, --system (default) add system-wide mount point\n\
149 -t, --text text files get \\r\\n line endings\n\
150 -u, --user add user-only mount point\n\
151 -v, --version output version information and exit\n\
152 -x, --executable treat all files under mount point as executables\n\
153 -E, --no-executable treat all files under mount point as \n\
155 -X, --cygwin-executable treat all files under mount point as cygwin\n\
158 exit (where
== stderr
? 1 : 0);
164 const char *v
= strchr (version
, ':');
174 len
= strchr (v
, ' ') - v
;
178 Filesystem Utility\n\
179 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.\n\
181 ", progname
, len
, v
, __DATE__
);
185 main (int argc
, char **argv
)
188 int flags
= MOUNT_BINARY
;
189 int default_flag
= MOUNT_SYSTEM
;
193 saw_change_cygdrive_prefix
,
194 saw_show_cygdrive_prefix
,
198 progname
= strrchr (argv
[0], '/');
199 if (progname
== NULL
)
200 progname
= strrchr (argv
[0], '\\');
201 if (progname
== NULL
)
212 while ((i
= getopt_long (argc
, argv
, opts
, longopts
, NULL
)) != EOF
)
216 flags
|= MOUNT_BINARY
;
220 do_what
= saw_change_cygdrive_prefix
;
232 do_what
= saw_mount_commands
;
238 do_what
= saw_show_cygdrive_prefix
;
243 flags
|= MOUNT_SYSTEM
;
246 flags
&= ~MOUNT_BINARY
;
249 flags
&= ~MOUNT_SYSTEM
;
260 flags
|= MOUNT_NOTEXEC
;
263 flags
|= MOUNT_CYGWIN_EXEC
;
269 if (flags
& MOUNT_NOTEXEC
&& flags
& (MOUNT_EXEC
| MOUNT_CYGWIN_EXEC
))
271 fprintf (stderr
, "%s: invalid combination of executable options\n", progname
);
278 case saw_change_cygdrive_prefix
:
281 change_cygdrive_prefix (argv
[optind
], flags
| default_flag
);
283 case saw_show_cygdrive_prefix
:
286 show_cygdrive_info ();
288 case saw_mount_commands
:
294 if (optind
!= (argc
- 1))
297 fprintf (stderr
, "%s: not enough arguments\n", progname
);
299 fprintf (stderr
, "%s: too many arguments\n", progname
);
302 if (force
|| !mount_already_exists (argv
[optind
+ 1], flags
| default_flag
))
303 do_mount (argv
[optind
], argv
[optind
+ 1], flags
| default_flag
);
307 error (argv
[optind
+ 1]);
316 mount_commands (void)
318 FILE *m
= setmntent ("/-not-used-", "r");
321 const char *format_mnt
= "mount%s \"%s\" \"%s\"\n";
322 const char *format_cyg
= "mount%s --change-cygdrive-prefix \"%s\"\n";
325 char system
[MAX_PATH
];
326 char user_flags
[MAX_PATH
];
327 char system_flags
[MAX_PATH
];
329 // write mount commands for user and system mount points
330 while ((p
= getmntent (m
)) != NULL
) {
331 // Only list non-cygdrives
332 if (!strstr (p
->mnt_opts
, ",noumount")) {
334 if (p
->mnt_type
[0] == 'u')
335 strcat (opts
, " -u");
336 else if (p
->mnt_type
[0] == 's')
337 strcat (opts
, " -s");
338 if (p
->mnt_opts
[0] == 'b')
339 strcat (opts
, " -b");
340 else if (p
->mnt_opts
[0] == 't')
341 strcat (opts
, " -t");
342 if (strstr (p
->mnt_opts
, ",exec"))
343 strcat (opts
, " -x");
344 if (strstr (p
->mnt_opts
, ",noexec"))
345 strcat (opts
, " -E");
346 while ((c
= strchr (p
->mnt_fsname
, '\\')) != NULL
)
348 printf (format_mnt
, opts
, p
->mnt_fsname
, p
->mnt_dir
);
353 // write mount commands for cygdrive prefixes
354 cygwin_internal (CW_GET_CYGDRIVE_INFO
, user
, system
, user_flags
,
356 if (strlen (user
) > 0) {
358 if (user_flags
[0] == 'b')
359 strcat (opts
, " -b");
360 else if (user_flags
[0] == 't')
361 strcat (opts
, " -t");
362 printf (format_cyg
, opts
, user
);
364 if (strlen (system
) > 0) {
365 strcpy (opts
, " -s");
366 if (system_flags
[0] == 'b')
367 strcat (opts
, " -b");
368 else if (system_flags
[0] == 't')
369 strcat (opts
, " -t");
370 printf (format_cyg
, opts
, system
);
379 FILE *m
= setmntent ("/-not-used-", "r");
381 const char *format
= "%s on %s type %s (%s)\n";
383 // printf (format, "Device", "Directory", "Type", "Flags");
384 while ((p
= getmntent (m
)) != NULL
)
385 printf (format
, p
->mnt_fsname
, p
->mnt_dir
, p
->mnt_type
, p
->mnt_opts
);
389 /* Return 1 if mountpoint from the same registry area is already in
390 mount table. Otherwise return 0. */
392 mount_already_exists (const char *posix_path
, int flags
)
394 int found_matching
= 0;
396 FILE *m
= setmntent ("/-not-used-", "r");
399 while ((p
= getmntent (m
)) != NULL
)
401 /* if the paths match, and they're both the same type of mount. */
402 if (strcmp (p
->mnt_dir
, posix_path
) == 0)
404 if (p
->mnt_type
[0] == 'u')
406 if (!(flags
& MOUNT_SYSTEM
)) /* both current_user */
410 "%s: warning: system mount point of '%s' "
411 "will always be masked by user mount.\n",
412 progname
, posix_path
);
415 else if (p
->mnt_type
[0] == 's')
417 if (flags
& MOUNT_SYSTEM
) /* both system */
421 "%s: warning: user mount point of '%s' "
422 "masks system mount.\n",
423 progname
, posix_path
);
428 fprintf (stderr
, "%s: warning: couldn't determine mount type.\n", progname
);
435 return found_matching
;
438 /* change_cygdrive_prefix: Change the cygdrive prefix */
440 change_cygdrive_prefix (const char *new_prefix
, int flags
)
442 flags
|= MOUNT_CYGDRIVE
;
444 if (mount (NULL
, new_prefix
, flags
))
450 /* show_cygdrive_info: Show the user and/or cygdrive info, i.e., prefix and
453 show_cygdrive_info ()
455 /* Get the cygdrive info */
457 char system
[MAX_PATH
];
458 char user_flags
[MAX_PATH
];
459 char system_flags
[MAX_PATH
];
460 cygwin_internal (CW_GET_CYGDRIVE_INFO
, user
, system
, user_flags
,
463 /* Display the user and system cygdrive path prefix, if necessary
465 const char *format
= "%-18s %-11s %s\n";
466 printf (format
, "Prefix", "Type", "Flags");
467 if (strlen (user
) > 0)
468 printf (format
, user
, "user", user_flags
);
469 if (strlen (system
) > 0)
470 printf (format
, system
, "system", system_flags
);