--- ls.c.old	Sun Apr 29 11:42:48 2001
+++ ls.c	Fri Sep 21 23:24:14 2001
@@ -118,6 +118,18 @@
 #include "strverscmp.h"
 #include "xstrtol.h"
 
+#ifdef __CYGWIN__
+#include <stdio.h>
+#include <sys/cygwin.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <mntent.h>
+
+static uintmax_t gobble_mount (const char *name);
+static char * ls_cygwin_scan(const char *base_list_path);
+static int ls_cygwin_loop(const char *base_list_path);
+#endif /* __CYGWIN__ */
+
 /* Use access control lists only under all the following conditions.
    Some systems (OSF4, Irix5, Irix6) have the acl function, but not
    sys/acl.h or don't define the GETACLCNT macro.  */
@@ -1747,6 +1759,7 @@
   register uintmax_t total_blocks = 0;
 
   errno = 0;
+
   reading = opendir (name);
   if (!reading)
     {
@@ -1760,6 +1773,11 @@
 
   clear_files ();
 
+#ifdef __CYGWIN__
+/* Loop to the Cygwin-specific subroutine (which will put visible mount points in the files table */
+  ls_cygwin_loop(name);
+#endif 
+
   while ((next = readdir (reading)) != NULL)
     if (file_interesting (next))
       {
@@ -1924,9 +1942,17 @@
 
       if (val < 0)
 	{
+#ifdef __CYGWIN__
+        if (ls_cygwin_loop(name) == -1) {
+	    error (0, errno, "%s", quotearg_colon (path));
+	    exit_status = 1;
+	    return 0;
+        } else return(0);
+#else /* !__CYGWIN__ */
 	  error (0, errno, "%s", quotearg_colon (path));
 	  exit_status = 1;
 	  return 0;
+#endif /* !__CYGWIN__ */
 	}
 
 #if USE_ACL
@@ -3336,3 +3362,267 @@
     }
   exit (status);
 }
+
+/* contribution to ls by Ronald Landheer <info@rlsystems.net>
+// This allows ls to see the cygdrive magic dir, whatever it's called, and the mounted drives.
+// Copyright (c) Ronald Landheer (unless otherwise stated below)
+// Published under GNU Public License (see COPYING for details)
+// no warranties offered - at all.
+*/
+/*only compile if in Cygwin*/
+#ifdef __CYGWIN__
+/* Unlike when gobble_file() is called, gobble_mount() expects the path to still be there (so it's removed) */
+/* Lifted off strings.c from the Real Life Systems Swing library */
+static char *invert(char *s) {
+  short k, j;
+  char c;
+
+  j = strlen(s) - 1;
+  k = 0;
+  while (k < j) {
+    c = s[k]; s[k++] = s[j]; s[j--] = c;
+  } // while
+
+  return(s);
+} // invert()
+
+static uintmax_t
+gobble_mount (const char *name)
+{
+  char *inverted_name = NULL;
+  char *c;
+  struct fileinfo *mount_info;
+
+  if ((inverted_name = (char*)malloc(strlen(name) + 1)) == NULL) {
+    fprintf(stderr, "Out of memory!");
+    exit(1);
+  }
+  strcpy(inverted_name, name);
+  inverted_name = invert(inverted_name);
+  if (c = strchr(inverted_name, '/')) {
+    *c = 0;
+  }
+  inverted_name = invert(inverted_name);
+
+  if ((mount_info = (struct fileinfo*)malloc(sizeof(struct fileinfo))) == NULL) {
+    fprintf(stderr, "Out of memory!");
+    exit(1);
+  }
+  if ((mount_info->name = (char*)malloc(strlen(name) + 1)) == NULL) {
+    fprintf(stderr, "Out of memory!");
+    exit(1);
+  }
+
+  strcpy(mount_info->name, inverted_name);
+  mount_info->linkname = 0;
+  mount_info->linkok = 0;
+  mount_info->filetype = unknown;
+#if USE_ACL
+  mount_info->have_acl = 0; /* The thing doesn't really exist, so it doesn't have an ACL*/
+#endif  
+
+  if (files_index == nfiles)
+    {
+      nfiles *= 2;
+      files = (struct fileinfo *) xrealloc ((char *) files,
+					    sizeof (*files) * nfiles);
+    }
+  memcpy(&(files[files_index]), mount_info, sizeof(struct fileinfo));
+
+  files_index++;
+
+  return(0);
+}
+
+/* ls_cygwin_scan() 
+   Returns a pointer to an internal static string holding the visible mount 
+   points, space-separated, null-terminated. NULL is returned if there are
+   no visible mount points in BASE_LIST_PATH
+*/
+static char *
+ls_cygwin_scan(const char *base_list_path)
+{
+  static char *rVal = NULL;
+  char *cygdrive, *magic_cygdrive;
+  char cygdrive_basedir[MAXPATHLEN];
+  int i;
+  struct stat stat_info;
+/*
+   Copyright 1996, 1997, 1998, 1999 Cygnus Solutions.
+   Lifted off: cygwin-1.3.3-2/winsup/utils/mount.cc
+*/
+  FILE *m = setmntent ("/-not-used-", "r");
+  struct mntent *p;
+  char user[MAXPATHLEN];
+  char system[MAXPATHLEN];
+  char user_flags[MAXPATHLEN];
+  char system_flags[MAXPATHLEN];
+
+  /*get cygdrive info*/
+  cygwin_internal (CW_GET_CYGDRIVE_INFO, user, system, user_flags, system_flags);
+/* end copyright Cygnus Solutions */
+  /* We now have the cygdrive path in either user or system - and will put 
+     it in the cygdrive var.*/
+  if (strlen(user) > 0) {
+    magic_cygdrive = cygdrive = user;
+  } else if (strlen(system) > 0) {
+    magic_cygdrive = cygdrive = system;
+  } else return(NULL);
+  strncpy(cygdrive_basedir, cygdrive, MAXPATHLEN);
+  for (i = strlen(cygdrive_basedir) - 1; (i > 0) && (cygdrive_basedir[i] != '/'); i--) cygdrive_basedir[i] = 0;
+  if (strcmp(cygdrive_basedir, base_list_path) == 0) {
+    if (stat(cygdrive, &stat_info) != 0) {
+      /* Here, rVal can only be NULL */
+      if ((rVal = (char*)malloc(strlen(cygdrive) + 2)) == NULL) {
+        fprintf(stderr, "Error: out of memory.\n");
+        exit(1);
+      } else sprintf(rVal, " %s", cygdrive);
+    }
+  } else {
+    /* Remove trailing slash from cygdrive_basedir and try again */
+    cygdrive_basedir[strlen(cygdrive_basedir) - 1] = 0;
+    if (strcmp(cygdrive_basedir, base_list_path) == 0) {
+      if (stat(cygdrive, &stat_info) != 0) {
+        /* Here, rVal can only be NULL */
+        if ((rVal = (char*)malloc(strlen(cygdrive) + 2)) == NULL) {
+          fprintf(stderr, "Error: out of memory.\n");
+          exit(1);
+        } else sprintf(rVal, " %s", cygdrive);
+      }
+    }
+  }
+  if (strcmp(cygdrive, base_list_path) == 0) {
+    if (stat(cygdrive, &stat_info) != 0) {
+      /* Here, rVal can only be NULL */
+      if ((rVal = (char*)malloc(strlen(cygdrive) + 2)) == NULL) {
+        fprintf(stderr, "Error: out of memory.\n");
+        exit(1);
+      } else sprintf(rVal, " %s", cygdrive);
+    }
+  }
+  
+/*
+   Copyright 1996, 1997, 1998, 1999 Cygnus Solutions.
+   Lifted off: cygwin-1.3.3-2/winsup/utils/mount.cc
+*/
+  while ((p = getmntent (m)) != NULL) {
+/* end copyright Cygnus Solutions */
+    /* We now have a mountpoint in p->mnt_dir */
+    cygdrive=p->mnt_dir;
+    /* .. with which we'll do the same thing as above .. */
+    strncpy(cygdrive_basedir, cygdrive, MAXPATHLEN);
+    for (i = strlen(cygdrive_basedir) - 1; (i > 0) && (cygdrive_basedir[i] != '/'); i--) cygdrive_basedir[i] = 0;
+    if (strcmp(cygdrive_basedir, base_list_path) == 0) {
+      if (stat(cygdrive, &stat_info) != 0) {
+        /* Here, rVal might be ! NULL */
+        if (rVal) {
+          if ((rVal = (char*)realloc(rVal, strlen(rVal) + strlen(cygdrive) + 2)) == NULL) {
+            fprintf(stderr, "Error: out of memory.\n");
+          } else sprintf(rVal, "%s %s", ((rVal) ? (rVal) : ("")), cygdrive);
+        } else {
+          if ((rVal = (char*)malloc(strlen(cygdrive) + 2)) == NULL) {
+            fprintf(stderr, "Error: out of memory.\n");
+          } else sprintf(rVal, " %s", cygdrive);
+        }
+      } else { 
+        /* cygdrive drives come through stat() as a directory, 
+           but they are not shown when scanning the cygdrive 
+           magicdir for them.
+           This is fixed by checking to see if what just passed
+           through the stat() call is rooted in the cygdrive 
+           magic dir.
+           FIXME: things may pass through because they actually 
+                  exist (i.e. the magic dir is mounted over a 
+                  real tree, or something similar). This should 
+                  be checked, but I don't know how.. (yet).
+        */
+        if (strcmp(cygdrive_basedir, magic_cygdrive) == 0) {
+          if (rVal) {
+            if ((rVal = (char*)realloc(rVal, strlen(rVal) + strlen(cygdrive) + 2)) == NULL) {
+              fprintf(stderr, "Error: out of memory.\n");
+            } else sprintf(rVal, "%s %s", ((rVal) ? (rVal) : ("")), cygdrive);
+          } else {
+            if ((rVal = (char*)malloc(strlen(cygdrive) + 2)) == NULL) {
+              fprintf(stderr, "Error: out of memory.\n");
+            } else sprintf(rVal, " %s", cygdrive);
+          }
+        } else { /* remove trailing slash and try again */
+          cygdrive_basedir[strlen(cygdrive_basedir) - 1] = 0;
+          if (strcmp(cygdrive_basedir, magic_cygdrive) == 0) {
+            if (rVal) {
+              if ((rVal = (char*)realloc(rVal, strlen(rVal) + strlen(cygdrive) + 2)) == NULL) {
+                fprintf(stderr, "Error: out of memory.\n");
+              } else sprintf(rVal, "%s %s", ((rVal) ? (rVal) : ("")), cygdrive);
+            } else {
+              if ((rVal = (char*)malloc(strlen(cygdrive) + 2)) == NULL) {
+                fprintf(stderr, "Error: out of memory.\n");
+              } else sprintf(rVal, " %s", cygdrive);
+            }
+          }
+        }
+      }
+    } else {
+      /* Remove trailing slash from basedir and try again */
+      cygdrive_basedir[strlen(cygdrive_basedir) - 1] = 0;
+      if (strcmp(cygdrive_basedir, base_list_path) == 0) {
+        if (stat(cygdrive, &stat_info) != 0) {
+          /* Here, rVal might be ! NULL */
+          if (rVal) {
+            if ((rVal = (char*)realloc(rVal, strlen(rVal) + strlen(cygdrive) + 2)) == NULL) {
+              fprintf(stderr, "Error: out of memory.\n");
+            } else sprintf(rVal, "%s %s", ((rVal) ? (rVal) : ("")), cygdrive);
+          } else {
+            if ((rVal = (char*)malloc(strlen(cygdrive) + 2)) == NULL) {
+              fprintf(stderr, "Error: out of memory.\n");
+            } else sprintf(rVal, " %s", cygdrive);
+          }
+        } /* Note that the cygdrive magic dir shows up as a file when scanned w/o trailing '/' */
+      }
+    }
+    if (strcmp(cygdrive, base_list_path) == 0) {
+      if (stat(cygdrive, &stat_info) != 0) {
+        /* Here, rVal can only be NULL */
+        if ((rVal = (char*)malloc(strlen(cygdrive) + 2)) == NULL) {
+          fprintf(stderr, "Error: out of memory.\n");
+          exit(1);
+        } else sprintf(rVal, " %s", cygdrive);
+      }
+    }
+  }
+/*
+   Copyright 1996, 1997, 1998, 1999 Cygnus Solutions.
+   Lifted off: cygwin-1.3.3-2/winsup/utils/mount.cc
+*/
+  endmntent (m);
+/* end copyright Cygnus Solutions */
+
+
+  if (rVal && strlen(rVal)) {
+    return(rVal);
+  } else return(NULL);
+} /* ls_cygwin_scan() */
+
+static int 
+ls_cygwin_loop(const char *base_list_path) 
+{
+  char *mount_list = NULL;
+  char *spaceFound, *nextSpace;
+  char mount_name[MAXPATHLEN];
+  char *c = NULL;
+
+  if (mount_list = ls_cygwin_scan(base_list_path)) {
+    /* Note that the mount_list *starts* with a space, but does not end with one! */
+    spaceFound = mount_list;
+    while (spaceFound = strchr(spaceFound, ' ')) {
+      spaceFound++; /* Get rid of the leading space */
+      strcpy(mount_name, spaceFound);
+      if (c = strchr(mount_name, ' ')) {
+        *c = 0;
+      }
+      gobble_mount(mount_name);
+    }
+  } else return(-1);
+
+  return(0);
+} /* ls_cygwin_loop() */
+#endif /* defined __CYGWIN__ */

