This is the mail archive of the cygwin@cygwin.com mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Finding exact case of paths


Hi,

> Oh, I see, add a modifier similar to '-s', so that it verifies the case of
> each element in the path...  Yeah, that could work, something like:
>   -e, --exact-case      print exact case of NAME

Yep, exactly. Now, cygpath seems to generally not hit the filesystem - cygpath
c:/complete/crap gives me /c/complete/crap so using that switch will
necessarily involve a performance hit. Given that, I think I'm happy with my
solution based on dirent/strcasecmp. I've attached a stand-alone utility that
seems to work (just on cygwin paths), although it has the side effect of
squishing down multiple slashes ///like////this//path down to /like/this/path.

I think it would be ok to restrict --exact-case to cygwin paths.

Paul
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>
#include <limits.h>
#include <string.h>

#include <stdio.h> /* Only needed for test code */

/***
 * Main subroutine is just for testing
 **/
int main(int argc, char *argv[])
{
  char path[PATH_MAX];
  if(argc == 2)
  {
    strcpy(path, argv[1]);
    if(exact_case(path)) printf("OUTPUT: %s\n", path);
    else printf("ERROR: %s\n", strerror(errno));
  }
  return 0;
}

/***
 * Vague attempt to make code independent of path type
 **/
#define DLM_STR "/"
#define DLM_CHR '/'
#define CWD_STR "."
#define IS_ABSOLUTE(X) (X[0] == DLM_CHR)

/***
 * Determine the correct case for a cygwin path, fill-in in place
 * Returns TRUE/FALSE - success/failure
 **/
int exact_case(char *path)
{
  char work[PATH_MAX], *part, path_strtok[PATH_MAX];

  if(strlen(path) > (PATH_MAX - 1)) /* PATH_MAX allows for the NUL */
  {
    errno = ENAMETOOLONG;
    return 0;
  }

  strcpy(path_strtok, path);
  part = strtok(path_strtok, DLM_STR);

  if(IS_ABSOLUTE(path))
  {
    if(!exact_case_part(DLM_STR, part)) return 0;
    strcpy(work, DLM_STR);
    strcat(work, part);
  }
  else
  {
    if(!exact_case_part(CWD_STR, part)) return 0;
    strcpy(work, part);
  }

  while(part = strtok(NULL, DLM_STR))
  {
    if(!exact_case_part(work, part)) return 0;
    strcat(work, DLM_STR);
    strcat(work, part);
  }

  strcpy(path, work);
  return 1;
}

/***
 * Search a directory for an entry; fill-in it's correct case
 * Returns TRUE/FALSE - success/failure
 **/
int exact_case_part(const char *base, char *part)
{
  struct dirent *de;
  DIR *dh = opendir(base);
  if(!dh) return 0;
  while(de = readdir(dh))
  {
    if(strcasecmp(part, de->d_name) == 0) break;
  }
  closedir(dh);
  if(de) strcpy(part, de->d_name);
  else errno = ENOENT;
  return (int) de;
}

--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Bug reporting:         http://cygwin.com/bugs.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]