libc/winsup/utils/mount.cc

286 lines
6.7 KiB
C++

/* mount.cc
Copyright 1996, 1997, 1998, 1999 Cygnus Solutions.
This file is part of Cygwin.
This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#include <stdio.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <mntent.h>
#include <windows.h>
#include <sys/cygwin.h>
#include <stdlib.h>
#ifdef errno
#undef errno
#endif
#include <errno.h>
static void show_mounts (void);
static void show_cygdrive_prefixes (void);
static void change_cygdrive_prefix (const char *new_prefix, int flags);
static int mount_already_exists (const char *posix_path, int flags);
// static short create_missing_dirs = FALSE;
static short force = FALSE;
static const char *progname;
static void
error (const char *path)
{
fprintf (stderr, "%s: %s: %s\n", progname, path,
(errno == EMFILE) ? "Too many mount entries" : strerror (errno));
exit (1);
}
/* FIXME: do_mount should also print a warning message if the dev arg
is a non-existent Win32 path. */
static void
do_mount (const char *dev, const char *where, int flags)
{
struct stat statbuf;
char win32_path[MAX_PATH];
int statres;
cygwin_conv_to_win32_path (where, win32_path);
statres = stat (win32_path, &statbuf);
#if 0
if (statres == -1)
{
/* FIXME: this'll fail if mount dir is missing any parent dirs */
if (create_missing_dirs == TRUE)
{
if (mkdir (where, 0755) == -1)
fprintf (stderr, "Warning: unable to create %s!\n", where);
else
statres = 0; /* Pretend stat succeeded if we could mkdir. */
}
}
#endif
if (mount (dev, where, flags))
error (where);
if (statres == -1)
{
if (force == FALSE)
fprintf (stderr, "%s: warning - %s does not exist.\n", progname, where);
}
else if (!(statbuf.st_mode & S_IFDIR))
{
if (force == FALSE)
fprintf (stderr, "%s: warning: %s is not a directory.\n", progname, where);
}
exit (0);
}
static void
usage (void)
{
fprintf (stderr, "usage %s [-bfstux] <win32path> <posixpath>
-b text files are equivalent to binary files (newline = \\n)
-f force mount, don't warn about missing mount point directories
-s add mount point to system-wide registry location
-t text files get \\r\\n line endings (default)
-u add mount point to user registry location (default)
-x treat all files under mount point as executables
[-bs] --change-cygdrive-prefix <posixpath>
change the cygdrive path prefix to <posixpath>
--show-cygdrive-prefixes
show user and/or system cygdrive path prefixes
--import-old-mounts
copy old registry mount table mounts into the current mount areas
", progname);
exit (1);
}
int
main (int argc, const char **argv)
{
int i;
int flags = 0;
progname = argv[0];
if (argc == 1)
{
show_mounts ();
exit (0);
}
for (i = 1; i < argc; ++i)
{
if (argv[i][0] != '-')
break;
if (strcmp (argv[i], "--change-cygdrive-prefix") == 0)
{
if ((i + 2) != argc)
usage ();
change_cygdrive_prefix (argv[i+1], flags);
}
else if (strcmp (argv[i], "--import-old-mounts") == 0)
{
if ((i + 1) != argc)
usage ();
cygwin_internal (CW_READ_V1_MOUNT_TABLES);
exit (0);
}
else if (strcmp (argv[i], "--show-cygdrive-prefixes") == 0)
{
if ((i + 1) != argc)
usage ();
show_cygdrive_prefixes ();
}
else if (strcmp (argv[i], "-b") == 0)
flags |= MOUNT_BINARY;
else if (strcmp (argv[i], "-t") == 0)
flags &= ~MOUNT_BINARY;
else if (strcmp (argv[i], "-X") == 0)
flags |= MOUNT_CYGWIN_EXEC;
#if 0
else if (strcmp (argv[i], "-x") == 0)
create_missing_dirs = TRUE;
#endif
else if (strcmp (argv[i], "-s") == 0)
flags |= MOUNT_SYSTEM;
else if (strcmp (argv[i], "-u") == 0)
flags &= ~MOUNT_SYSTEM;
else if (strcmp (argv[i], "-x") == 0)
flags |= MOUNT_EXEC;
else if (strcmp (argv[i], "-f") == 0)
force = TRUE;
else
usage ();
}
if ((i + 2) != argc)
usage ();
if ((force == FALSE) && (mount_already_exists (argv[i + 1], flags)))
{
errno = EBUSY;
error (argv[i + 1]);
}
else
do_mount (argv[i], argv[i + 1], flags);
/* NOTREACHED */
return 0;
}
static void
show_mounts (void)
{
FILE *m = setmntent ("/-not-used-", "r");
struct mntent *p;
const char *format = "%-18s %-18s %-11s %s\n";
printf (format, "Device", "Directory", "Type", "Flags");
while ((p = getmntent (m)) != NULL)
{
printf (format,
p->mnt_fsname,
p->mnt_dir,
p->mnt_type,
p->mnt_opts);
}
endmntent (m);
}
/* Return 1 if mountpoint from the same registry area is already in
mount table. Otherwise return 0. */
static int
mount_already_exists (const char *posix_path, int flags)
{
int found_matching = 0;
FILE *m = setmntent ("/-not-used-", "r");
struct mntent *p;
while ((p = getmntent (m)) != NULL)
{
/* if the paths match, and they're both the same type of mount. */
if (strcmp (p->mnt_dir, posix_path) == 0)
{
if (p->mnt_type[0] == 'u')
{
if (!(flags & MOUNT_SYSTEM)) /* both current_user */
found_matching = 1;
else
fprintf (stderr,
"%s: warning: system mount point of '%s' "
"will always be masked by user mount.\n",
progname, posix_path);
break;
}
else if (p->mnt_type[0] == 's')
{
if (flags & MOUNT_SYSTEM) /* both system */
found_matching = 1;
else
fprintf (stderr,
"%s: warning: user mount point of '%s' "
"masks system mount.\n",
progname, posix_path);
break;
}
else
{
fprintf (stderr, "%s: warning: couldn't determine mount type.\n", progname);
break;
}
}
}
endmntent (m);
return found_matching;
}
/* change_cygdrive_prefix: Change the cygdrive prefix */
static void
change_cygdrive_prefix (const char *new_prefix, int flags)
{
flags |= MOUNT_AUTO;
if (mount (NULL, new_prefix, flags))
error (new_prefix);
exit (0);
}
/* show_cygdrive_prefixes: Show the user and/or cygdrive path prefixes */
static void
show_cygdrive_prefixes ()
{
/* Get the Cygdrive user and system path prefixes */
char user[MAX_PATH];
char system[MAX_PATH];
cygwin_internal (CW_GET_CYGDRIVE_PREFIXES, user, system);
/* Display the user and system cygdrive path prefixes, if necessary
(ie, not empty) */
const char *format = "%-18s %-11s\n";
printf (format, "Prefix", "Type");
if (strlen (user) > 0)
printf (format, user, "user");
if (strlen (system) > 0)
printf (format, system, "system");
exit (0);
}