]> sourceware.org Git - newlib-cygwin.git/blob - winsup/utils/mount.cc
* mount.cc (do_mount): Remove MOUNT_ENC code.
[newlib-cygwin.git] / winsup / utils / mount.cc
1 /* mount.cc
2
3 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005,
4 2008 Red Hat, Inc.
5
6 This file is part of Cygwin.
7
8 This software is a copyrighted work licensed under the terms of the
9 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
10 details. */
11
12 #include <stdio.h>
13 #include <sys/mount.h>
14 #include <sys/stat.h>
15 #include <mntent.h>
16 #include <windows.h>
17 #include <sys/cygwin.h>
18 #include <stdlib.h>
19 #include <getopt.h>
20 #include <dirent.h>
21
22 #ifdef errno
23 #undef errno
24 #endif
25 #include <errno.h>
26
27 #define EXEC_FLAGS (MOUNT_EXEC | MOUNT_NOTEXEC | MOUNT_CYGWIN_EXEC)
28
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);
34
35 // static short create_missing_dirs = FALSE;
36 static short force = FALSE;
37
38 static const char version[] = "$Revision$";
39 static const char *progname;
40
41 static void
42 error (const char *path)
43 {
44 fprintf (stderr, "%s: %s: %s\n", progname, path,
45 (errno == EMFILE) ? "Too many mount entries" : strerror (errno));
46 exit (1);
47 }
48
49 /* FIXME: do_mount should also print a warning message if the dev arg
50 is a non-existent Win32 path. */
51
52 static void
53 do_mount (const char *dev, const char *where, int flags)
54 {
55 struct stat statbuf;
56 int statres;
57
58 statres = stat (where, &statbuf);
59
60 #if 0
61 if (statres == -1)
62 {
63 /* FIXME: this'll fail if mount dir is missing any parent dirs */
64 if (create_missing_dirs == TRUE)
65 {
66 if (mkdir (where, 0755) == -1)
67 fprintf (stderr, "Warning: unable to create %s!\n", where);
68 else
69 statres = 0; /* Pretend stat succeeded if we could mkdir. */
70 }
71 }
72 #endif
73
74 if (statres == -1)
75 {
76 if (!force)
77 fprintf (stderr, "%s: warning - %s does not exist.\n", progname, where);
78 }
79 else if (!(statbuf.st_mode & S_IFDIR))
80 {
81 if (!force)
82 fprintf (stderr, "%s: warning: %s is not a directory.\n", progname, where);
83 }
84
85 if (!force && !(flags & EXEC_FLAGS) && strlen (dev))
86 {
87 char devtmp[1 + 2 * strlen (dev)];
88 strcpy (devtmp, dev);
89 char c = strchr (devtmp, '\0')[-1];
90 if (c == '/' || c == '\\')
91 strcat (devtmp, ".");
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)
98 {
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;
103 }
104 }
105
106 if (mount (dev, where, flags))
107 error (where);
108
109 exit (0);
110 }
111
112 static struct option longopts[] =
113 {
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'},
128 {NULL, 0, NULL, 0}
129 };
130
131 static char opts[] = "bcfhmpstuvxEXo:";
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 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\
155 non-executables\n\
156 -X, --cygwin-executable treat all files under mount point as cygwin\n\
157 executables\n\
158 ", progname);
159 exit (where == stderr ? 1 : 0);
160 }
161
162 struct opt
163 {
164 const char *name;
165 unsigned val;
166 bool clear;
167 } oopts[] =
168 {
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},
176 {"nosuid", 0, 0}
177 };
178
179 static void
180 print_version ()
181 {
182 const char *v = strchr (version, ':');
183 int len;
184 if (!v)
185 {
186 v = "?";
187 len = 1;
188 }
189 else
190 {
191 v += 2;
192 len = strchr (v, ' ') - v;
193 }
194 printf ("\
195 %s (cygwin) %.*s\n\
196 Filesystem Utility\n\
197 Copyright 1996-2008 Red Hat, Inc.\n\
198 Compiled on %s\n\
199 ", progname, len, v, __DATE__);
200 }
201
202 static char *
203 concat3 (char *a, const char *b, const char *c)
204 {
205 size_t totlen = strlen (a) + strlen (b) + strlen (c) + 1;
206 a = (char *) realloc (a, totlen);
207 return strcat (strcat (a, b), c);
208 }
209
210 int
211 main (int argc, char **argv)
212 {
213 int i;
214 int flags = MOUNT_BINARY;
215 char *options = strdup ("");
216 enum do_what
217 {
218 nada,
219 saw_change_cygdrive_prefix,
220 saw_show_cygdrive_prefix,
221 saw_mount_commands
222 } do_what = nada;
223
224 progname = strrchr (argv[0], '/');
225 if (progname == NULL)
226 progname = strrchr (argv[0], '\\');
227 if (progname == NULL)
228 progname = argv[0];
229 else
230 progname++;
231
232 if (argc == 1)
233 {
234 show_mounts ();
235 exit (0);
236 }
237
238 while ((i = getopt_long (argc, argv, opts, longopts, NULL)) != EOF)
239 switch (i)
240 {
241 case 'b':
242 flags |= MOUNT_BINARY;
243 break;
244 case 'c':
245 if (do_what == nada)
246 do_what = saw_change_cygdrive_prefix;
247 else
248 usage ();
249 break;
250 case 'f':
251 force = TRUE;
252 break;
253 case 'h':
254 usage (stdout);
255 break;
256 case 'm':
257 if (do_what == nada)
258 do_what = saw_mount_commands;
259 else
260 usage ();
261 break;
262 case 'o':
263 if (*options)
264 options = concat3 (options, ",", optarg);
265 else
266 options = strdup (optarg);
267 break;
268 case 'p':
269 if (do_what == nada)
270 do_what = saw_show_cygdrive_prefix;
271 else
272 usage ();
273 break;
274 case 's':
275 break;
276 case 't':
277 flags &= ~MOUNT_BINARY;
278 break;
279 case 'u':
280 break;
281 case 'v':
282 print_version ();
283 return 0;
284 break;
285 case 'x':
286 flags |= MOUNT_EXEC;
287 break;
288 case 'E':
289 flags |= MOUNT_NOTEXEC;
290 break;
291 case 'X':
292 flags |= MOUNT_CYGWIN_EXEC;
293 break;
294 default:
295 usage ();
296 }
297
298 while (*options)
299 {
300 char *p = strchr (options, ',');
301 if (p)
302 *p++ = '\0';
303 else
304 p = strchr (options, '\0');
305
306 for (opt *o = oopts; o < (oopts + (sizeof (oopts) / sizeof (oopts[0]))); o++)
307 if (strcmp (options, o->name) == 0)
308 {
309 if (o->clear)
310 flags &= ~o->val;
311 else
312 flags |= o->val;
313 goto gotit;
314 }
315 fprintf (stderr, "%s: invalid option - '%s'\n", progname, options);
316 exit (1);
317
318 gotit:
319 options = p;
320 }
321
322 if (flags & MOUNT_NOTEXEC && flags & (MOUNT_EXEC | MOUNT_CYGWIN_EXEC))
323 {
324 fprintf (stderr, "%s: invalid combination of executable options\n", progname);
325 exit (1);
326 }
327
328 cygwin_internal (CW_SET_DOS_FILE_WARNING, false);
329
330 argc--;
331 switch (do_what)
332 {
333 case saw_change_cygdrive_prefix:
334 if (optind != argc)
335 usage ();
336 change_cygdrive_prefix (argv[optind], flags);
337 break;
338 case saw_show_cygdrive_prefix:
339 if (optind <= argc)
340 usage ();
341 show_cygdrive_info ();
342 break;
343 case saw_mount_commands:
344 if (optind <= argc)
345 usage ();
346 mount_commands ();
347 break;
348 default:
349 if (optind != (argc - 1))
350 {
351 if (optind >= argc)
352 fprintf (stderr, "%s: not enough arguments\n", progname);
353 else
354 fprintf (stderr, "%s: too many arguments\n", progname);
355 usage ();
356 }
357 if (force || !mount_already_exists (argv[optind + 1], flags))
358 do_mount (argv[optind], argv[optind + 1], flags);
359 else
360 {
361 errno = EBUSY;
362 error (argv[optind + 1]);
363 }
364 }
365
366 /* NOTREACHED */
367 return 0;
368 }
369
370 static void
371 mount_commands (void)
372 {
373 FILE *m = setmntent ("/-not-used-", "r");
374 struct mntent *p;
375 char *c;
376 const char *format_mnt = "mount%s \"%s\" \"%s\"\n";
377 const char *format_cyg = "mount%s --change-cygdrive-prefix \"%s\"\n";
378 char opts[MAX_PATH];
379 char user[MAX_PATH];
380 char system[MAX_PATH];
381 char user_flags[MAX_PATH];
382 char system_flags[MAX_PATH];
383
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"))
388 {
389 strcpy(opts, " -f");
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)
401 *c = '/';
402 printf (format_mnt, opts, p->mnt_fsname, p->mnt_dir);
403 }
404 endmntent (m);
405
406 // write mount commands for cygdrive prefixes
407 cygwin_internal (CW_GET_CYGDRIVE_INFO, user, system, user_flags,
408 system_flags);
409
410 if (strlen (user) > 0)
411 {
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);
418 }
419
420 if (strlen (system) > 0)
421 {
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);
428 }
429
430 exit(0);
431 }
432
433 static void
434 show_mounts (void)
435 {
436 FILE *m = setmntent ("/-not-used-", "r");
437 struct mntent *p;
438 const char *format = "%s on %s type %s (%s)\n";
439
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);
443 endmntent (m);
444 }
445
446 /* Return 1 if mountpoint from the same registry area is already in
447 mount table. Otherwise return 0. */
448 static int
449 mount_already_exists (const char *posix_path, int flags)
450 {
451 int found_matching = 0;
452
453 FILE *m = setmntent ("/-not-used-", "r");
454 struct mntent *p;
455
456 while ((p = getmntent (m)) != NULL)
457 {
458 /* if the paths match, and they're both the same type of mount. */
459 if (strcmp (p->mnt_dir, posix_path) == 0)
460 {
461 if (p->mnt_type[0] == 'u')
462 {
463 if (!(flags & MOUNT_SYSTEM)) /* both current_user */
464 found_matching = 1;
465 else
466 fprintf (stderr,
467 "%s: warning: system mount point of '%s' "
468 "will always be masked by user mount.\n",
469 progname, posix_path);
470 break;
471 }
472 else if (p->mnt_type[0] == 's')
473 {
474 if (flags & MOUNT_SYSTEM) /* both system */
475 found_matching = 1;
476 else
477 fprintf (stderr,
478 "%s: warning: user mount point of '%s' "
479 "masks system mount.\n",
480 progname, posix_path);
481 break;
482 }
483 else
484 {
485 fprintf (stderr, "%s: warning: couldn't determine mount type.\n", progname);
486 break;
487 }
488 }
489 }
490 endmntent (m);
491
492 return found_matching;
493 }
494
495 /* change_cygdrive_prefix: Change the cygdrive prefix */
496 static void
497 change_cygdrive_prefix (const char *new_prefix, int flags)
498 {
499 flags |= MOUNT_CYGDRIVE;
500
501 if (mount (NULL, new_prefix, flags))
502 error (new_prefix);
503
504 exit (0);
505 }
506
507 /* show_cygdrive_info: Show the user and/or cygdrive info, i.e., prefix and
508 flags.*/
509 static void
510 show_cygdrive_info ()
511 {
512 /* Get the cygdrive info */
513 char user[MAX_PATH];
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,
518 system_flags);
519
520 /* Display the user and system cygdrive path prefix, if necessary
521 (ie, not empty) */
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);
528
529 exit (0);
530 }
This page took 0.061492 seconds and 6 git commands to generate.