--- 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 +#include +#include +#include +#include + +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 +// 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__ */