#include <sys/stat.h> /* for S_IFLNK */
+#if defined(WIN32_NATIVE) || defined(CYGWIN)
+#define WIN32_FILENAMES
+#endif
+
/* First char after start of absolute filename. */
#define ABS_START(name) (name + ABS_LENGTH (name))
# define system_readlink win32_readlink
#else
# ifdef CYGWIN
-# define ABS_LENGTH(name) (IS_DIRECTORY_SEP (*name) ? \
- (IS_DIRECTORY_SEP (name[1]) ? 2 : 1) : 0)
+# ifdef WIN32_FILENAMES
+# define ABS_LENGTH(name) (win32_abs_start (name))
+static int win32_abs_start (const char * name);
+# else
+# define ABS_LENGTH(name) (IS_DIRECTORY_SEP (*name) ? \
+ (IS_DIRECTORY_SEP (name[1]) ? 2 : 1) : 0)
+# endif
# define system_readlink cygwin_readlink
# else
# define ABS_LENGTH(name) (IS_DIRECTORY_SEP (*name) ? 1 : 0)
assert (*name);
/* Sort of check we have a valid filename. */
- if (strpbrk (name, "*?|<>\"") || strlen (name) >= MAX_PATH)
+ /* #### can we have escaped shell operators in a Windows filename? */
+ if (strpbrk (name, "|<>\"") || strlen (name) >= MAX_PATH)
{
errno = EIO;
return -1;
}
+ /* #### can we have escaped wildcards in a Windows filename? */
+ else if (strpbrk (name, "*?"))
+ {
+ errno = EINVAL; /* this valid path can't be a symlink */
+ return -1;
+ }
/* Find start of filename */
lastname = name + strlen (name);
cygwin_readlink (const char * name, char * buf, int size)
{
int n = readlink (name, buf, size);
- if (n < 0)
+ if (n < 0 && errno == EINVAL)
{
/* The file may exist, but isn't a symlink. Try to find the
right name. */
}
#endif /* CYGWIN */
-#ifdef WIN32_NATIVE
+#ifdef WIN32_FILENAMES
#ifndef ELOOP
#define ELOOP 10062 /* = WSAELOOP in winsock.h */
#endif
path = copy_path;
max_path = copy_path + PATH_MAX - 2;
-#ifdef WIN32_NATIVE
+ if (0)
+ ;
+#ifdef WIN32_FILENAMES
/* Check for c:/... or //server/... */
- if (abslen == 2 || abslen == 3)
+ else if (abslen == 3 || abslen == 2)
{
- strncpy (new_path, path, abslen);
- new_path += abslen;
- path += abslen;
+ /* Make sure drive letter is lowercased. */
+ if (abslen == 3) {
+ *new_path = tolower (*path);
+ new_path++;
+ path++;
+ abslen--;
+ }
+ /* Coerce directory chars. */
+ while (abslen-- > 0) {
+ if (IS_DIRECTORY_SEP (*path))
+ *new_path++ = DIRECTORY_SEP;
+ else
+ *new_path++ = *path;
+ path++;
+ }
}
+#endif
+#ifdef WIN32_NATIVE
/* No drive letter, but a beginning slash? Prepend drive letter. */
else if (abslen == 1)
{
path++;
}
/* Just a path name, prepend the current directory */
- else
+ else if (1)
{
getcwd (new_path, PATH_MAX - 1);
new_path += strlen (new_path);
}
#else
/* If it's a relative pathname use getcwd for starters. */
- if (abslen == 0)
+ else if (abslen == 0)
{
getcwd (new_path, PATH_MAX - 1);
new_path += strlen (new_path);
if (n < 0)
{
/* EINVAL means the file exists but isn't a symlink. */
- if (errno != EINVAL)
+#ifdef CYGWIN
+ if (errno != EINVAL && errno != ENOENT)
+#else
+ if (errno != EINVAL)
+#endif
return NULL;
}
else
/* Make sure it's null terminated. */
*new_path = '\0';
-#ifdef WIN32_NATIVE
- if (ABS_LENGTH (resolved_path) == 3)
- /* Lowercase drive letter. */
- *resolved_path = tolower (*resolved_path);
-#endif
return resolved_path;
}