Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian Dessent <brian@dessent.net>2008-03-16 20:04:02 +0300
committerBrian Dessent <brian@dessent.net>2008-03-16 20:04:02 +0300
commitbff091bcfefcb3a129591796e85706075cd48561 (patch)
tree036c6e9ace3285edc3a18ae834f1f50b155cc308 /winsup/utils/path.cc
parent615d9a06968df6e9fa68cd247d631b6478967f75 (diff)
* path.cc: Include malloc.h for alloca.
(is_symlink): Rewrite. Just read the whole file in memory rather than by parts. Account for an ITEMIDLIST if present, as well as the new style of Cygwin shortcut supporting targets > MAX_PATH.
Diffstat (limited to 'winsup/utils/path.cc')
-rw-r--r--winsup/utils/path.cc94
1 files changed, 46 insertions, 48 deletions
diff --git a/winsup/utils/path.cc b/winsup/utils/path.cc
index 4a29d14e9..33ecf70ba 100644
--- a/winsup/utils/path.cc
+++ b/winsup/utils/path.cc
@@ -18,6 +18,7 @@ details. */
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
+#include <malloc.h>
#include "path.h"
#include "cygwin/include/cygwin/version.h"
#include "cygwin/include/sys/mount.h"
@@ -172,60 +173,57 @@ is_symlink (HANDLE fh)
bool
readlink (HANDLE fh, char *path, int maxlen)
{
- int got;
- int magic = get_word (fh, 0x0);
+ DWORD rv;
+ char *buf, *cp;
+ unsigned short len;
+ win_shortcut_hdr *file_header;
+ BY_HANDLE_FILE_INFORMATION fi;
+
+ if (!GetFileInformationByHandle (fh, &fi)
+ || fi.nFileSizeHigh != 0
+ || fi.nFileSizeLow > 8192)
+ return false;
- if (magic == SHORTCUT_MAGIC)
- {
- int offset = get_word (fh, 0x4c);
- int slen = get_word (fh, 0x4c + offset + 2);
- if (slen >= maxlen)
- {
- SetLastError (ERROR_FILENAME_EXCED_RANGE);
- return false;
- }
- if (SetFilePointer (fh, 0x4c + offset + 4, 0, FILE_BEGIN) ==
- INVALID_SET_FILE_POINTER && GetLastError () != NO_ERROR)
- return false;
+ buf = (char *) alloca (fi.nFileSizeLow + 1);
+ file_header = (win_shortcut_hdr *) buf;
- if (!ReadFile (fh, path, slen, (DWORD *) &got, 0))
- return false;
- else if (got < slen)
- {
- SetLastError (ERROR_READ_FAULT);
- return false;
- }
- else
- path[got] = '\0';
- }
- else if (magic == SYMLINK_MAGIC)
+ if (SetFilePointer (fh, 0L, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER
+ || !ReadFile (fh, buf, fi.nFileSizeLow, &rv, NULL)
+ || rv != fi.nFileSizeLow)
+ return false;
+
+ if (fi.nFileSizeLow > sizeof (file_header)
+ && cmp_shortcut_header (file_header))
{
- char cookie_buf[sizeof (SYMLINK_COOKIE) - 1];
-
- if (SetFilePointer (fh, 0, 0, FILE_BEGIN) == INVALID_SET_FILE_POINTER
- && GetLastError () != NO_ERROR)
- return false;
-
- if (!ReadFile (fh, cookie_buf, sizeof (cookie_buf), (DWORD *) &got, 0))
- return false;
- else if (got == sizeof (cookie_buf)
- && memcmp (cookie_buf, SYMLINK_COOKIE, sizeof (cookie_buf)) == 0)
- {
- if (!ReadFile (fh, path, maxlen, (DWORD *) &got, 0))
- return false;
- else if (got >= maxlen)
- {
- SetLastError (ERROR_FILENAME_EXCED_RANGE);
- path[0] = '\0';
- return false;
- }
- else
- path[got] = '\0';
- }
+ cp = buf + sizeof (win_shortcut_hdr);
+ if (file_header->flags & WSH_FLAG_IDLIST) /* Skip ITEMIDLIST */
+ cp += *(unsigned short *) cp + 2;
+ if (!(len = *(unsigned short *) cp))
+ return false;
+ cp += 2;
+ /* Has appended full path? If so, use it instead of description. */
+ unsigned short relpath_len = *(unsigned short *) (cp + len);
+ if (cp + len + 2 + relpath_len < buf + fi.nFileSizeLow)
+ {
+ cp += len + 2 + relpath_len;
+ len = *(unsigned short *) cp;
+ cp += 2;
+ }
+ if (len + 1 > maxlen)
+ return false;
+ memcpy (path, cp, len);
+ path[len] = '\0';
+ return true;
}
+ else if (strncmp (buf, SYMLINK_COOKIE, strlen (SYMLINK_COOKIE)) == 0
+ && fi.nFileSizeLow - strlen (SYMLINK_COOKIE) <= (unsigned) maxlen
+ && buf[fi.nFileSizeLow - 1] == '\0')
+ {
+ strcpy (path, &buf[strlen (SYMLINK_COOKIE)]);
+ return true;
+ }
else
return false;
- return true;
}
typedef struct mnt