aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--winsup/utils/ChangeLog10
-rw-r--r--winsup/utils/Makefile.in16
-rw-r--r--winsup/utils/cygcheck.cc60
-rw-r--r--winsup/utils/path.cc350
4 files changed, 423 insertions, 13 deletions
diff --git a/winsup/utils/ChangeLog b/winsup/utils/ChangeLog
index 56db805..960282d 100644
--- a/winsup/utils/ChangeLog
+++ b/winsup/utils/ChangeLog
@@ -1,3 +1,13 @@
+2001-11-10 Christopher Faylor <cgf@redhat.com>
+
+ * Makefile.in (cygcheck.exe): Compile as -mno-cygwin executable.
+ * path.cc: New file.
+ * cygcheck.cc (init_paths): Use MS-DOS path syntax.
+ (cygwin_info): Properly display cygwin version numbers. Prettify some
+ output.
+ (dump_sysinfo): Calculate max names of posix and ms-dos paths for
+ prettier output.
+
2001-11-09 Corinna Vinschen <corinna@vinschen.de>
* cygcheck.cc (dump_sysinfo): Print more detailed OS information string.
diff --git a/winsup/utils/Makefile.in b/winsup/utils/Makefile.in
index deee3bd..7becee8 100644
--- a/winsup/utils/Makefile.in
+++ b/winsup/utils/Makefile.in
@@ -94,6 +94,14 @@ else
$(CXX) $(MINGW_CXXFLAGS) -o $@ ${wordlist 1,2,$^} -B$(mingw_build)/ $(MINGW_LDFLAGS)
endif
+cygcheck.exe: cygcheck.cc mingw_getopt.o path.o $(MINGW_DEP_LDLIBS)
+ifdef VERBOSE
+ $(CXX) $(MINGW_CXXFLAGS) -o $@ ${wordlist 1,3,$^} -B$(mingw_build)/ $(MINGW_LDFLAGS)
+else
+ @echo $(CXX) -o $@ ${wordlist 1,2,$^} ${filter-out -B%, $(MINGW_CXXFLAGS) $(MINGW_LDFLAGS)};\
+ $(CXX) $(MINGW_CXXFLAGS) -o $@ ${wordlist 1,3,$^} -B$(mingw_build)/ $(MINGW_LDFLAGS)
+endif
+
dumper.o: dumper.cc dumper.h
ifdef VERBOSE
${filter-out -nostdinc,$(COMPILE_CXX)} $c -o $@ $(DUMPER_INCLUDES) ${firstword $^}
@@ -127,6 +135,14 @@ else
${filter-out -I$(newlib_source)/%,$(COMPILE_CC)} $c -o $(@D)/$(basename $@)$o $(MINGW_CFLAGS) $<
endif
+path.o: path.cc
+ifdef VERBOSE
+ ${filter-out -I$(newlib_source)/%,$(COMPILE_CC)} $c -o $(@D)/$(basename $@)$o $(MINGW_CFLAGS) $<
+else
+ @echo $(CC) $c -o $(@D)/$(basename $@)$o $(MINGW_CFLAGS) ... $^;\
+ ${filter-out -I$(newlib_source)/%,$(COMPILE_CC)} $c -o $(@D)/$(basename $@)$o $(MINGW_CFLAGS) $<
+endif
+
clean:
rm -f *.o $(CLEAN_PROGS)
diff --git a/winsup/utils/cygcheck.cc b/winsup/utils/cygcheck.cc
index 11a04d4..0f905a9 100644
--- a/winsup/utils/cygcheck.cc
+++ b/winsup/utils/cygcheck.cc
@@ -8,6 +8,8 @@
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
+typedef unsigned short uid_t;
+typedef unsigned short gid_t;
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -16,6 +18,7 @@
#include <mntent.h>
#include <time.h>
#include <getopt.h>
+#include <ctype.h>
int verbose = 0;
int registry = 0;
@@ -134,18 +137,14 @@ init_paths ()
GetWindowsDirectory (tmp, 4000);
add_path (tmp, strlen (tmp));
- char *path = getenv ("PATH");
- if (path)
+ char *wpath = getenv ("PATH");
+ if (wpath)
{
- char wpath[4000];
- cygwin_posix_to_win32_path_list (path, wpath);
- char *b, *e, sep = ':';
- if (strchr (wpath, ';'))
- sep = ';';
+ char *b, *e;
b = wpath;
while (1)
{
- for (e = b; *e && *e != sep; e++);
+ for (e = b; *e && *e != ';'; e++);
add_path (b, e - b);
if (!*e)
break;
@@ -350,6 +349,7 @@ cygwin_info (HANDLE h)
return;
}
+ char *dll_major;
bufend = buf + size;
while (buf < bufend)
if ((buf = (char *) memchr (buf, '%', bufend - buf)) == NULL)
@@ -361,9 +361,33 @@ cygwin_info (HANDLE h)
char *p = strchr (buf += CYGPREFIX, '\n');
if (!p)
break;
- fputs (hello, stdout);
- fputs (" ", stdout);
- fwrite (buf, 1 + p - buf, 1, stdout);
+ if (strncasecmp (buf, "dll major:", 10) == 0)
+ {
+ dll_major = buf + 11;
+ continue;
+ }
+ char *s, pbuf[80];
+ int len;
+ len = 1 + p - buf;
+ if (strncasecmp (buf, "dll minor:", 10) != 0)
+ s = buf;
+ else
+ {
+ char c = dll_major[1];
+ dll_major[1] = '\0';
+ int maj = atoi (dll_major);
+ dll_major[1] = c;
+ int min = atoi (dll_major + 1);
+ sprintf (pbuf, "DLL version: %d.%d.%.*s", maj, min, len - 11, buf + 11);
+ len = strlen (s = pbuf);
+ }
+ if (strncmp (s, "dll", 3) == 0)
+ memcpy (s, "DLL", 3);
+ else if (strncmp (s, "api", 3) == 0)
+ memcpy (s, "API", 3);
+ else if (islower (*s))
+ *s = toupper (*s);
+ fprintf (stdout, "%s %.*s", hello, len, s);
hello = "";
}
@@ -987,6 +1011,18 @@ dump_sysinfo ()
unsigned int ml_fsname = 4, ml_dir = 7, ml_type = 6;
+ struct mntent *mnt;
+ setmntent (0, 0);
+ while ((mnt = getmntent (0)))
+ {
+ int n = (int) strlen (mnt->mnt_fsname);
+ if (ml_fsname < n)
+ ml_fsname = n;
+ n = (int) strlen (mnt->mnt_dir);
+ if (ml_dir < n)
+ ml_dir = n;
+ }
+
if (givehelp)
{
printf
@@ -995,9 +1031,7 @@ dump_sysinfo ()
ml_type, "-Type-", "-Flags-");
}
- struct mntent *mnt;
setmntent (0, 0);
-
while ((mnt = getmntent (0)))
{
printf ("%-*s %-*s %-*s %s\n",
diff --git a/winsup/utils/path.cc b/winsup/utils/path.cc
new file mode 100644
index 0000000..7670904
--- /dev/null
+++ b/winsup/utils/path.cc
@@ -0,0 +1,350 @@
+/*
+ * Copyright (c) 2000, Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * A copy of the GNU General Public License can be found at
+ * http://www.gnu.org/
+ *
+ * Written by DJ Delorie <dj@cygnus.com>
+ *
+ */
+
+/* The purpose of this file is to hide all the details about accessing
+ Cygwin's mount table. If the format or location of the mount table
+ changes, this is the file to change to match it. */
+
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <cygwin/version.h>
+#include <sys/mount.h>
+#include <mntent.h>
+
+/* Used when treating / and \ as equivalent. */
+#define SLASH_P(ch) \
+ ({ \
+ char __c = (ch); \
+ ((__c) == '/' || (__c) == '\\'); \
+ })
+
+
+static struct mnt
+ {
+ const char *native;
+ char *posix;
+ unsigned flags;
+ int issys;
+ } mount_table[255];
+
+struct mnt *root_here = NULL;
+
+static char *
+find2 (HKEY rkey, unsigned *flags, char *what)
+{
+ char *retval = 0;
+ DWORD retvallen = 0;
+ DWORD type;
+ HKEY key;
+
+ if (RegOpenKeyEx (rkey, what, 0, KEY_READ, &key) != ERROR_SUCCESS)
+ return 0;
+
+ if (RegQueryValueEx (key, "native", 0, &type, 0, &retvallen)
+ == ERROR_SUCCESS)
+ {
+ retval = (char *) malloc (MAX_PATH + 1);
+ if (RegQueryValueEx (key, "native", 0, &type, (BYTE *) retval, &retvallen)
+ != ERROR_SUCCESS)
+ {
+ free (retval);
+ retval = 0;
+ }
+ }
+
+ retvallen = sizeof (flags);
+ RegQueryValueEx (key, "flags", 0, &type, (BYTE *)flags, &retvallen);
+
+ RegCloseKey (key);
+
+ return retval;
+}
+
+static LONG
+get_cygdrive0 (HKEY key, const char *what, void *val, DWORD len)
+{
+ LONG status = RegQueryValueEx (key, what, 0, 0, (BYTE *)val, &len);
+ return status;
+}
+
+static mnt *
+get_cygdrive (HKEY key, mnt *m, int issystem)
+{
+
+ if (get_cygdrive0 (key, CYGWIN_INFO_CYGDRIVE_FLAGS, &m->flags,
+ sizeof (m->flags)) != ERROR_SUCCESS) {
+ free (m->posix);
+ return m;
+ }
+ get_cygdrive0 (key, CYGWIN_INFO_CYGDRIVE_PREFIX, m->posix, MAX_PATH);
+ m->native = strdup (".");
+ return m + 1;
+}
+
+void
+read_mounts ()
+{
+ DWORD posix_path_size;
+ int res;
+ struct mnt *m = mount_table;
+ DWORD disposition;
+ char buf[10000];
+
+ root_here = NULL;
+ for (mnt *m1 = mount_table; m1->posix; m1++)
+ {
+ free (m1->posix);
+ if (m1->native)
+ free ((char *) m1->native);
+ m1->posix = NULL;
+ }
+
+ /* Loop through subkeys */
+ /* FIXME: we would like to not check MAX_MOUNTS but the heap in the
+ shared area is currently statically allocated so we can't have an
+ arbitrarily large number of mounts. */
+ for (int issystem = 0; issystem <= 1; issystem++)
+ {
+ sprintf (buf, "Software\\%s\\%s\\%s",
+ CYGWIN_INFO_CYGNUS_REGISTRY_NAME,
+ CYGWIN_INFO_CYGWIN_REGISTRY_NAME,
+ CYGWIN_INFO_CYGWIN_MOUNT_REGISTRY_NAME);
+
+ HKEY key = issystem ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
+ if (RegCreateKeyEx (key, buf, 0, (LPTSTR) "Cygwin", 0, KEY_ALL_ACCESS,
+ 0, &key, &disposition) != ERROR_SUCCESS)
+ break;
+ for (int i = 0; ;i++, m++)
+ {
+ m->posix = (char *) malloc (MAX_PATH + 1);
+ posix_path_size = MAX_PATH;
+ /* FIXME: if maximum posix_path_size is 256, we're going to
+ run into problems if we ever try to store a mount point that's
+ over 256 but is under MAX_PATH. */
+ res = RegEnumKeyEx (key, i, m->posix, &posix_path_size, NULL,
+ NULL, NULL, NULL);
+
+ if (res == ERROR_NO_MORE_ITEMS)
+ {
+ m = get_cygdrive (key, m, issystem);
+ m->posix = NULL;
+ break;
+ }
+
+ if (!*m->posix)
+ goto no_go;
+ else if (res != ERROR_SUCCESS)
+ break;
+ else
+ {
+ m->native = find2 (key, &m->flags, m->posix);
+ m->issys = issystem;
+ if (!m->native)
+ goto no_go;
+ }
+ continue;
+ no_go:
+ free (m->posix);
+ m->posix = NULL;
+ m--;
+ }
+ RegCloseKey (key);
+ }
+}
+
+/* Return non-zero if PATH1 is a prefix of PATH2.
+ Both are assumed to be of the same path style and / vs \ usage.
+ Neither may be "".
+ LEN1 = strlen (PATH1). It's passed because often it's already known.
+
+ Examples:
+ /foo/ is a prefix of /foo <-- may seem odd, but desired
+ /foo is a prefix of /foo/
+ / is a prefix of /foo/bar
+ / is not a prefix of foo/bar
+ foo/ is a prefix foo/bar
+ /foo is not a prefix of /foobar
+*/
+
+static int
+path_prefix_p (const char *path1, const char *path2, int len1)
+{
+ /* Handle case where PATH1 has trailing '/' and when it doesn't. */
+ if (len1 > 0 && SLASH_P (path1[len1 - 1]))
+ len1--;
+
+ if (len1 == 0)
+ return SLASH_P (path2[0]) && !SLASH_P (path2[1]);
+
+ if (strncasecmp (path1, path2, len1) != 0)
+ return 0;
+
+ return SLASH_P (path2[len1]) || path2[len1] == 0 || path1[len1 - 1] == ':';
+}
+
+static char *
+vconcat (const char *s, va_list v)
+{
+ int len;
+ char *rv, *arg;
+ va_list save_v = v;
+ int unc;
+
+ if (!s)
+ return 0;
+
+ len = strlen (s);
+
+ unc = SLASH_P (*s) && SLASH_P (s[1]);
+
+ while (1)
+ {
+ arg = va_arg (v, char *);
+ if (arg == 0)
+ break;
+ len += strlen (arg);
+ }
+ va_end (v);
+
+ rv = (char *) malloc (len + 1);
+ strcpy (rv, s);
+ v = save_v;
+ while (1)
+ {
+ arg = va_arg (v, char *);
+ if (arg == 0)
+ break;
+ strcat (rv, arg);
+ }
+ va_end (v);
+
+ char *d, *p;
+ for (p = rv; *p; p++)
+ if (*p == '\\')
+ *p = '/';
+
+ /* concat is only used for urls and files, so we can safely
+ canonicalize the results */
+ for (p = d = rv; *p; p++)
+ {
+ *d++ = *p;
+ /* special case for URLs */
+ if (*p == ':' && p[1] == '/' && p[2] == '/' && p > rv + 1)
+ {
+ *d++ = *++p;
+ *d++ = *++p;
+ }
+ else if (*p == '/' || *p == '\\')
+ {
+ if (p == rv && unc)
+ p++;
+ while (p[1] == '/')
+ p++;
+ }
+ }
+ *d = 0;
+
+ return rv;
+}
+
+static char *
+concat (const char *s, ...)
+{
+ va_list v;
+
+ va_start (v, s);
+
+ return vconcat (s, v);
+}
+
+char *
+cygpath (const char *s, ...)
+{
+ va_list v;
+ int max_len = -1;
+ struct mnt *m, *match = NULL;
+
+ va_start (v, s);
+ char *path = vconcat (s, v);
+ if (strncmp (path, "./", 2) == 0)
+ memmove (path, path + 2, strlen (path + 2) + 1);
+ if (strncmp (path, "/./", 3) == 0)
+ memmove (path + 1, path + 3, strlen (path + 3) + 1);
+
+ for (m = mount_table; m->posix ; m++)
+ {
+ int n = strlen (m->posix);
+ if (n < max_len || !path_prefix_p (m->posix, path, n))
+ continue;
+ max_len = n;
+ match = m;
+ }
+
+ char *native;
+ if (match == NULL)
+ native = strdup (path);
+ else if (max_len == (int) strlen (path))
+ native = strdup (match->native);
+ else
+ native = concat (match->native, "/", path + max_len, NULL);
+ free (path);
+
+ return native;
+}
+
+static mnt *m = NULL;
+
+extern "C" FILE *
+setmntent (const char *, const char *)
+{
+ m = mount_table;
+ if (!m->posix)
+ read_mounts ();
+ return NULL;
+}
+
+extern "C" struct mntent *
+getmntent (FILE *)
+{
+ static mntent mnt;
+ if (!m->posix)
+ return NULL;
+
+ mnt.mnt_fsname = (char *) m->native;
+ mnt.mnt_dir = (char *) m->posix;
+ if (!mnt.mnt_type)
+ mnt.mnt_type = (char *) malloc (1024);
+ if (!mnt.mnt_opts)
+ mnt.mnt_opts = (char *) malloc (1024);
+ if (!m->issys)
+ strcpy (mnt.mnt_type, (char *) "user");
+ else
+ strcpy (mnt.mnt_type, (char *) "system");
+ if (!(m->flags & MOUNT_BINARY))
+ strcpy (mnt.mnt_opts, (char *) "textmode");
+ else
+ strcpy (mnt.mnt_opts, (char *) "binmode");
+ if (m->flags & MOUNT_CYGWIN_EXEC)
+ strcat (mnt.mnt_opts, (char *) ",cygexec");
+ else if (m->flags & MOUNT_EXEC)
+ strcat (mnt.mnt_opts, (char *) ",exec");
+ if ((m->flags & MOUNT_AUTO)) /* cygdrive */
+ strcat (mnt.mnt_opts, (char *) ",noumount");
+ mnt.mnt_freq = 1;
+ mnt.mnt_passno = 1;
+ m++;
+ return &mnt;
+}