]> sourceware.org Git - newlib-cygwin.git/blob - winsup/utils/mount.cc
* cygcheck.cc (usage) Add description output.
[newlib-cygwin.git] / winsup / utils / mount.cc
1 /* mount.cc
2
3 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
4
5 This file is part of Cygwin.
6
7 This software is a copyrighted work licensed under the terms of the
8 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
9 details. */
10
11 #include <stdio.h>
12 #include <sys/mount.h>
13 #include <sys/stat.h>
14 #include <mntent.h>
15 #include <windows.h>
16 #include <sys/cygwin.h>
17 #include <stdlib.h>
18 #include <getopt.h>
19
20 #ifdef errno
21 #undef errno
22 #endif
23 #include <errno.h>
24
25 #define EXEC_FLAGS (MOUNT_EXEC | MOUNT_NOTEXEC | MOUNT_CYGWIN_EXEC)
26
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);
32
33 // static short create_missing_dirs = FALSE;
34 static short force = FALSE;
35
36 static const char version[] = "$Revision$";
37 static const char *progname;
38
39 static void
40 error (const char *path)
41 {
42 fprintf (stderr, "%s: %s: %s\n", progname, path,
43 (errno == EMFILE) ? "Too many mount entries" : strerror (errno));
44 exit (1);
45 }
46
47 /* FIXME: do_mount should also print a warning message if the dev arg
48 is a non-existent Win32 path. */
49
50 static void
51 do_mount (const char *dev, const char *where, int flags)
52 {
53 struct stat statbuf;
54 char win32_path[MAX_PATH];
55 int statres;
56
57 cygwin_conv_to_win32_path (where, win32_path);
58
59 statres = stat (win32_path, &statbuf);
60
61 #if 0
62 if (statres == -1)
63 {
64 /* FIXME: this'll fail if mount dir is missing any parent dirs */
65 if (create_missing_dirs == TRUE)
66 {
67 if (mkdir (where, 0755) == -1)
68 fprintf (stderr, "Warning: unable to create %s!\n", where);
69 else
70 statres = 0; /* Pretend stat succeeded if we could mkdir. */
71 }
72 }
73 #endif
74
75 if (statres == -1)
76 {
77 if (!force)
78 fprintf (stderr, "%s: warning - %s does not exist.\n", progname, where);
79 }
80 else if (!(statbuf.st_mode & S_IFDIR))
81 {
82 if (!force)
83 fprintf (stderr, "%s: warning: %s is not a directory.\n", progname, where);
84 }
85
86 if (!force && !(flags & EXEC_FLAGS) && strlen (dev))
87 {
88 char devtmp[1 + 2 * strlen (dev)];
89 strcpy (devtmp, dev);
90 char c = strchr (devtmp, '\0')[-1];
91 if (c == '/' || c == '\\')
92 strcat (devtmp, ".");
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)
99 {
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;
104 }
105 }
106
107 if (mount (dev, where, flags))
108 error (where);
109
110 exit (0);
111 }
112
113 static struct option longopts[] =
114 {
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'},
128 {NULL, 0, NULL, 0}
129 };
130
131 static char opts[] = "bcfhmpstuvxEX";
132
133 static void
134 usage (FILE *where = stderr)
135 {
136 fprintf (where, "Usage: %s [OPTION] [<win32path> <posixpath>]\n\
137 Display information about mounted filesystems, or mount a filesystem\n\
138 \n\
139 -b, --binary (default) text files are equivalent to binary files\n\
140 (newline = \\n)\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\
143 point directories\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\
154 non-executables\n\
155 -X, --cygwin-executable treat all files under mount point as cygwin\n\
156 executables\n\
157 ", progname);
158 exit (where == stderr ? 1 : 0);
159 }
160
161 static void
162 print_version ()
163 {
164 const char *v = strchr (version, ':');
165 int len;
166 if (!v)
167 {
168 v = "?";
169 len = 1;
170 }
171 else
172 {
173 v += 2;
174 len = strchr (v, ' ') - v;
175 }
176 printf ("\
177 %s (cygwin) %.*s\n\
178 Filesystem Utility\n\
179 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.\n\
180 Compiled on %s\n\
181 ", progname, len, v, __DATE__);
182 }
183
184 int
185 main (int argc, char **argv)
186 {
187 int i;
188 int flags = MOUNT_BINARY;
189 int default_flag = MOUNT_SYSTEM;
190 enum do_what
191 {
192 nada,
193 saw_change_cygdrive_prefix,
194 saw_show_cygdrive_prefix,
195 saw_mount_commands
196 } do_what = nada;
197
198 progname = strrchr (argv[0], '/');
199 if (progname == NULL)
200 progname = strrchr (argv[0], '\\');
201 if (progname == NULL)
202 progname = argv[0];
203 else
204 progname++;
205
206 if (argc == 1)
207 {
208 show_mounts ();
209 exit (0);
210 }
211
212 while ((i = getopt_long (argc, argv, opts, longopts, NULL)) != EOF)
213 switch (i)
214 {
215 case 'b':
216 flags |= MOUNT_BINARY;
217 break;
218 case 'c':
219 if (do_what == nada)
220 do_what = saw_change_cygdrive_prefix;
221 else
222 usage ();
223 break;
224 case 'f':
225 force = TRUE;
226 break;
227 case 'h':
228 usage (stdout);
229 break;
230 case 'm':
231 if (do_what == nada)
232 do_what = saw_mount_commands;
233 else
234 usage ();
235 break;
236 case 'p':
237 if (do_what == nada)
238 do_what = saw_show_cygdrive_prefix;
239 else
240 usage ();
241 break;
242 case 's':
243 flags |= MOUNT_SYSTEM;
244 break;
245 case 't':
246 flags &= ~MOUNT_BINARY;
247 break;
248 case 'u':
249 flags &= ~MOUNT_SYSTEM;
250 default_flag = 0;
251 break;
252 case 'v':
253 print_version ();
254 return 0;
255 break;
256 case 'x':
257 flags |= MOUNT_EXEC;
258 break;
259 case 'E':
260 flags |= MOUNT_NOTEXEC;
261 break;
262 case 'X':
263 flags |= MOUNT_CYGWIN_EXEC;
264 break;
265 default:
266 usage ();
267 }
268
269 if (flags & MOUNT_NOTEXEC && flags & (MOUNT_EXEC | MOUNT_CYGWIN_EXEC))
270 {
271 fprintf (stderr, "%s: invalid combination of executable options\n", progname);
272 exit (1);
273 }
274
275 argc--;
276 switch (do_what)
277 {
278 case saw_change_cygdrive_prefix:
279 if (optind != argc)
280 usage ();
281 change_cygdrive_prefix (argv[optind], flags | default_flag);
282 break;
283 case saw_show_cygdrive_prefix:
284 if (optind <= argc)
285 usage ();
286 show_cygdrive_info ();
287 break;
288 case saw_mount_commands:
289 if (optind <= argc)
290 usage ();
291 mount_commands ();
292 break;
293 default:
294 if (optind != (argc - 1))
295 {
296 if (optind >= argc)
297 fprintf (stderr, "%s: not enough arguments\n", progname);
298 else
299 fprintf (stderr, "%s: too many arguments\n", progname);
300 usage ();
301 }
302 if (force || !mount_already_exists (argv[optind + 1], flags | default_flag))
303 do_mount (argv[optind], argv[optind + 1], flags | default_flag);
304 else
305 {
306 errno = EBUSY;
307 error (argv[optind + 1]);
308 }
309 }
310
311 /* NOTREACHED */
312 return 0;
313 }
314
315 static void
316 mount_commands (void)
317 {
318 FILE *m = setmntent ("/-not-used-", "r");
319 struct mntent *p;
320 char *c;
321 const char *format_mnt = "mount%s \"%s\" \"%s\"\n";
322 const char *format_cyg = "mount%s --change-cygdrive-prefix \"%s\"\n";
323 char opts[MAX_PATH];
324 char user[MAX_PATH];
325 char system[MAX_PATH];
326 char user_flags[MAX_PATH];
327 char system_flags[MAX_PATH];
328
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")) {
333 strcpy(opts, " -f");
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)
347 *c = '/';
348 printf (format_mnt, opts, p->mnt_fsname, p->mnt_dir);
349 }
350 }
351 endmntent (m);
352
353 // write mount commands for cygdrive prefixes
354 cygwin_internal (CW_GET_CYGDRIVE_INFO, user, system, user_flags,
355 system_flags);
356 if (strlen (user) > 0) {
357 strcpy (opts, " ");
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);
363 }
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);
371 }
372
373 exit(0);
374 }
375
376 static void
377 show_mounts (void)
378 {
379 FILE *m = setmntent ("/-not-used-", "r");
380 struct mntent *p;
381 const char *format = "%s on %s type %s (%s)\n";
382
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);
386 endmntent (m);
387 }
388
389 /* Return 1 if mountpoint from the same registry area is already in
390 mount table. Otherwise return 0. */
391 static int
392 mount_already_exists (const char *posix_path, int flags)
393 {
394 int found_matching = 0;
395
396 FILE *m = setmntent ("/-not-used-", "r");
397 struct mntent *p;
398
399 while ((p = getmntent (m)) != NULL)
400 {
401 /* if the paths match, and they're both the same type of mount. */
402 if (strcmp (p->mnt_dir, posix_path) == 0)
403 {
404 if (p->mnt_type[0] == 'u')
405 {
406 if (!(flags & MOUNT_SYSTEM)) /* both current_user */
407 found_matching = 1;
408 else
409 fprintf (stderr,
410 "%s: warning: system mount point of '%s' "
411 "will always be masked by user mount.\n",
412 progname, posix_path);
413 break;
414 }
415 else if (p->mnt_type[0] == 's')
416 {
417 if (flags & MOUNT_SYSTEM) /* both system */
418 found_matching = 1;
419 else
420 fprintf (stderr,
421 "%s: warning: user mount point of '%s' "
422 "masks system mount.\n",
423 progname, posix_path);
424 break;
425 }
426 else
427 {
428 fprintf (stderr, "%s: warning: couldn't determine mount type.\n", progname);
429 break;
430 }
431 }
432 }
433 endmntent (m);
434
435 return found_matching;
436 }
437
438 /* change_cygdrive_prefix: Change the cygdrive prefix */
439 static void
440 change_cygdrive_prefix (const char *new_prefix, int flags)
441 {
442 flags |= MOUNT_CYGDRIVE;
443
444 if (mount (NULL, new_prefix, flags))
445 error (new_prefix);
446
447 exit (0);
448 }
449
450 /* show_cygdrive_info: Show the user and/or cygdrive info, i.e., prefix and
451 flags.*/
452 static void
453 show_cygdrive_info ()
454 {
455 /* Get the cygdrive info */
456 char user[MAX_PATH];
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,
461 system_flags);
462
463 /* Display the user and system cygdrive path prefix, if necessary
464 (ie, not empty) */
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);
471
472 exit (0);
473 }
This page took 0.067025 seconds and 6 git commands to generate.