diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2008-03-07 14:24:51 +0300 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2008-03-07 14:24:51 +0300 |
commit | 752b16ce359bb46948b8aa2bc88f7c32bf2cc95b (patch) | |
tree | 1ed3d9abb89e7e21ee47faf099632cf05b3a05be /winsup/cygwin/path.cc | |
parent | d8e218442b004997287aaf202af88d9f1f86074e (diff) |
* Makefile.in (DLL_OFILES): Add tls_pbuf.o.
* autoload.cc (CreateDesktopW): Replace CreateDesktopA.
(CreateWindowStationW): Replace CreateWindowStationA.
(GetUserObjectInformationW): Replace GetUserObjectInformationA.
* cygheap.h (cwdstuff::get): Assume default buffer size NT_MAX_PATH.
* cygtls.cc (_cygtls::remove): Free temporary TLS path buffers.
* cygtls.h (TP_NUM_C_BUFS): Define.
(TP_NUM_W_BUFS): Define.
(class tls_pathbuf): New class to store pointers to thread local
temporary path buffers.
(_local_storage::pathbufs): New member.
* environ.cc (win_env::add_cache): Use temporary TLS path buffer instead
of stack based buffer.
(posify): Get temporary outenv buffer from calling function.
(environ_init): Create temporary TLS path buffer for posify.
(build_env): Create Windows environment block as WCHAR buffer.
* environ.h (build_env): Change declaration accordingly.
* external.cc (sync_winenv): Accommodate build_env change.
* fhandler_console.cc (fhandler_console::need_invisible): Use
GetUserObjectInformationW and CreateWindowStationW.
* fhandler_process.cc (format_process_maps): Use temporary TLS path
buffer instead of stack based buffer.
* fork.cc (frok::parent): Convert to use CreateProcessW.
* path.cc: Throughout use temporary TLS path buffers instead of stack
based buffer. Replace checks for CYG_MAX_PATH by checks for
NT_MAX_PATH.
(getfileattr): New function to replace GetFileAttributesA.
(normalize_win32_path): Remove Win32 and NT long path prefixes.
(getwd): Assume PATH_MAX + 1 buffer per SUSv3.
* path.h (class path_conv): Set path buffer to size NT_MAX_PATH.
(iswdrive): Define.
* pinfo.cc (commune_process): Use temporary TLS path buffer instead of
stack based buffer.
* registry.cc (get_registry_hive_path): Ditto.
(load_registry_hive): Ditto.
* spawn.cc (spawn_guts): Convert to use CreateProcessW and
CreateProcessAsUserW.
(av::fixup): Open/close file using NtOpenFile/NtClose.
* syscalls.cc (mknod_worker): Allow PATH_MAX file name.
(mknod32): Ditto.
(getusershell): Ditto.
* tls_pbuf.cc: New file implementing tls_pathbuf and tmp_pathbuf
methods.
* tls_pbuf.h: New header for files using tmp_pathbuf.
* tlsoffsets.h: Regenerate.
* winsup.h (NT_MAX_PATH): Define as 32767 to avoid USHORT overflow.
Diffstat (limited to 'winsup/cygwin/path.cc')
-rw-r--r-- | winsup/cygwin/path.cc | 151 |
1 files changed, 115 insertions, 36 deletions
diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index 4c4ce2966..11d01bc47 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -76,6 +76,7 @@ details. */ #include "shared_info.h" #include "registry.h" #include "cygtls.h" +#include "tls_pbuf.h" #include "environ.h" #include <assert.h> #include <ntdll.h> @@ -319,7 +320,7 @@ normalize_posix_path (const char *src, char *dst, char *&tail) *tail++ = '/'; } - if ((tail - dst) >= CYG_MAX_PATH) + if ((tail - dst) >= NT_MAX_PATH) { debug_printf ("ENAMETOOLONG = normalize_posix_path (%s)", src); return ENAMETOOLONG; @@ -355,7 +356,8 @@ static void __stdcall mkrelpath (char *dst) __attribute__ ((regparm (2))); static void __stdcall mkrelpath (char *path) { - char cwd_win32[CYG_MAX_PATH]; + tmp_pathbuf tp; + char *cwd_win32 = tp.c_get (); if (!cygheap->cwd.get (cwd_win32, 0)) return; @@ -647,7 +649,8 @@ warn_msdos (const char *src) { if (user_shared->warned_msdos || !dos_file_warning) return; - char posix_path[CYG_MAX_PATH]; + tmp_pathbuf tp; + char *posix_path = tp.c_get (); small_printf ("cygwin warning:\n"); if (cygwin_conv_to_full_posix_path (src, posix_path)) small_printf (" MS-DOS style path detected: %s\n POSIX equivalent preferred.\n", @@ -662,6 +665,56 @@ warn_msdos (const char *src) user_shared->warned_msdos = true; } +static DWORD +getfileattr (const char *path) /* path has to be always absolute. */ +{ + tmp_pathbuf tp; + UNICODE_STRING upath; + OBJECT_ATTRIBUTES attr; + FILE_BASIC_INFORMATION fbi; + NTSTATUS status; + IO_STATUS_BLOCK io; + + RtlInitEmptyUnicodeString (&upath, tp.w_get (), NT_MAX_PATH * sizeof (WCHAR)); + InitializeObjectAttributes (&attr, &upath, OBJ_CASE_INSENSITIVE, NULL, NULL); + get_nt_native_path (path, upath); + + status = NtQueryAttributesFile (&attr, &fbi); + if (NT_SUCCESS (status)) + return fbi.FileAttributes; + + if (status != STATUS_OBJECT_NAME_NOT_FOUND + && status != STATUS_NO_SUCH_FILE) /* File not found on 9x share */ + { + /* File exists but access denied. Try to get attribute through + directory query. */ + UNICODE_STRING dirname, basename; + HANDLE dir; + FILE_DIRECTORY_INFORMATION fdi; + + RtlSplitUnicodePath (&upath, &dirname, &basename); + InitializeObjectAttributes (&attr, &dirname, + OBJ_CASE_INSENSITIVE, NULL, NULL); + status = NtOpenFile (&dir, SYNCHRONIZE | FILE_LIST_DIRECTORY, + &attr, &io, FILE_SHARE_VALID_FLAGS, + FILE_SYNCHRONOUS_IO_NONALERT + | FILE_OPEN_FOR_BACKUP_INTENT + | FILE_DIRECTORY_FILE); + if (NT_SUCCESS (status)) + { + status = NtQueryDirectoryFile (dir, NULL, NULL, 0, &io, + &fdi, sizeof fdi, + FileDirectoryInformation, + TRUE, &basename, TRUE); + NtClose (dir); + if (NT_SUCCESS (status) || status == STATUS_BUFFER_OVERFLOW) + return fdi.FileAttributes; + } + } + SetLastError (RtlNtStatusToDosError (status)); + return INVALID_FILE_ATTRIBUTES; +} + /* Convert an arbitrary path SRC to a pure Win32 path, suitable for passing to Win32 API routines. @@ -685,10 +738,11 @@ void path_conv::check (PUNICODE_STRING src, unsigned opt, const suffix_info *suffixes) { - char path[CYG_MAX_PATH]; + tmp_pathbuf tp; + char *path = tp.c_get (); user_shared->warned_msdos = true; - sys_wcstombs (path, CYG_MAX_PATH, src->Buffer, src->Length / 2); + sys_wcstombs (path, NT_MAX_PATH, src->Buffer, src->Length / 2); path_conv::check (path, opt, suffixes); } @@ -696,11 +750,12 @@ void path_conv::check (const char *src, unsigned opt, const suffix_info *suffixes) { - /* This array is used when expanding symlinks. It is CYG_MAX_PATH * 2 - in length so that we can hold the expanded symlink plus a - trailer. */ - char path_copy[CYG_MAX_PATH + 3]; - char tmp_buf[2 * CYG_MAX_PATH + 3]; + /* The tmp_buf array is used when expanding symlinks. It is NT_MAX_PATH * 2 + in length so that we can hold the expanded symlink plus a trailer. */ + tmp_pathbuf tp; + char *path_copy = tp.c_get (); + char *pathbuf = tp.c_get (); + char *tmp_buf = tp.t_get (); symlink_info sym; bool need_directory = 0; bool saw_symlinks = 0; @@ -785,7 +840,6 @@ path_conv::check (const char *src, unsigned opt, for (unsigned pflags_or = opt & PC_NO_ACCESS_CHECK; ; pflags_or = 0) { const suffix_info *suff; - char pathbuf[CYG_MAX_PATH]; char *full_path; /* Don't allow symlink.check to set anything in the path_conv @@ -818,7 +872,7 @@ path_conv::check (const char *src, unsigned opt, fileattr = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_READONLY; else { - fileattr = GetFileAttributes (this->path); + fileattr = getfileattr (this->path); dev.devn = FH_FS; } goto out; @@ -827,7 +881,7 @@ path_conv::check (const char *src, unsigned opt, { dev.devn = FH_FS; #if 0 - fileattr = GetFileAttributes (this->path); + fileattr = getfileattr (this->path); if (!component && fileattr == INVALID_FILE_ATTRIBUTES) { fileattr = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_READONLY; @@ -1050,7 +1104,7 @@ virtual_component_retry: } /* Make sure there is enough space */ - if (headptr + symlen >= tmp_buf + sizeof (tmp_buf)) + if (headptr + symlen >= tmp_buf + (2 * NT_MAX_PATH)) { too_long: error = ENAMETOOLONG; @@ -1071,7 +1125,7 @@ virtual_component_retry: if (*(headptr - 1) != '/') *headptr++ = '/'; int taillen = path_end - tail + 1; - if (headptr + taillen > tmp_buf + sizeof (tmp_buf)) + if (headptr + taillen > tmp_buf + (2 * NT_MAX_PATH)) goto too_long; memcpy (headptr, tail, taillen); } @@ -1239,11 +1293,12 @@ path_conv::~path_conv () bool path_conv::is_binary () { + tmp_pathbuf tp; + PWCHAR bintest = tp.w_get (); DWORD bin; - PBYTE bintest[get_nt_native_path ()->Length + sizeof (WCHAR)]; return exec_state () == is_executable && RtlEqualUnicodePathSuffix (get_nt_native_path (), L".exe", TRUE) - && GetBinaryTypeW (get_wide_win32_path ((PWCHAR) bintest), &bin); + && GetBinaryTypeW (get_wide_win32_path (bintest), &bin); } /* Return true if src_path is a valid, internally supported device name. @@ -1286,6 +1341,19 @@ normalize_win32_path (const char *src, char *dst, char *&tail) bool beg_src_slash = isdirsep (src[0]); tail = dst; + /* Skip long path name prefixes in Win32 or NT syntax. */ + if (beg_src_slash && (src[1] == '?' || isdirsep (src[1])) + && src[2] == '?' && isdirsep (src[3])) + { + src += 4; + if (ascii_strncasematch (src, "UNC", 3)) + { + src += 2; /* Fortunately the first char is not copied... */ + beg_src_slash = true; + } + else + beg_src_slash = isdirsep (src[0]); + } if (beg_src_slash && isdirsep (src[1])) { if (isdirsep (src[2])) @@ -1360,7 +1428,7 @@ normalize_win32_path (const char *src, char *dst, char *&tail) *tail++ = *src; src++; } - if ((tail - dst) >= CYG_MAX_PATH) + if ((tail - dst) >= NT_MAX_PATH) return ENAMETOOLONG; } if (tail > dst + 1 && tail[-1] == '.' && tail[-2] == '\\') @@ -1463,7 +1531,7 @@ conv_path_list (const char *src, char *dst, int to_posix) { char *s = strccpy (srcbuf, &src, src_delim); int len = s - srcbuf; - if (len >= CYG_MAX_PATH) + if (len >= NT_MAX_PATH) { err = ENAMETOOLONG; break; @@ -1704,14 +1772,14 @@ mount_item::build_win32 (char *dst, const char *src, unsigned *outflags, unsigne dst[n++] = '\\'; if (!*p || !(flags & MOUNT_ENC)) { - if ((n + strlen (p)) >= CYG_MAX_PATH) + if ((n + strlen (p)) >= NT_MAX_PATH) err = ENAMETOOLONG; else backslashify (p, dst + n, 0); } else { - int left = CYG_MAX_PATH - n; + int left = NT_MAX_PATH - n; while (*p) { char slash = 0; @@ -1743,7 +1811,7 @@ mount_item::build_win32 (char *dst, const char *src, unsigned *outflags, unsigne The result is zero for success, or an errno value. - {,full_}win32_path must have sufficient space (i.e. CYG_MAX_PATH bytes). */ + {,full_}win32_path must have sufficient space (i.e. NT_MAX_PATH bytes). */ int mount_info::conv_to_win32_path (const char *src_path, char *dst, device& dev, @@ -1983,7 +2051,7 @@ mount_info::cygdrive_win32_path (const char *src, char *dst, int& unit) /* conv_to_posix_path: Ensure src_path is a POSIX path. The result is zero for success, or an errno value. - posix_path must have sufficient space (i.e. CYG_MAX_PATH bytes). + posix_path must have sufficient space (i.e. NT_MAX_PATH bytes). If keep_rel_p is non-zero, relative paths stay that way. */ /* TODO: Change conv_to_posix_path to work with native paths. */ @@ -2004,7 +2072,8 @@ mount_info::conv_to_posix_path (PWCHAR src_path, char *posix_path, changed = true; } } - char buf[NT_MAX_PATH]; + tmp_pathbuf tp; + char *buf = tp.c_get (); sys_wcstombs (buf, NT_MAX_PATH, src_path); int ret = conv_to_posix_path (buf, posix_path, keep_rel_p); if (changed) @@ -2033,7 +2102,7 @@ mount_info::conv_to_posix_path (const char *src_path, char *posix_path, trailing_slash_p ? "add-slash" : "no-add-slash"); MALLOC_CHECK; - if (src_path_len >= CYG_MAX_PATH) + if (src_path_len >= NT_MAX_PATH) { debug_printf ("ENAMETOOLONG"); return ENAMETOOLONG; @@ -2049,7 +2118,8 @@ mount_info::conv_to_posix_path (const char *src_path, char *posix_path, return 0; } - char pathbuf[CYG_MAX_PATH]; + tmp_pathbuf tp; + char *pathbuf = tp.c_get (); char *tail; int rc = normalize_win32_path (src_path, pathbuf, tail); if (rc != 0) @@ -2059,6 +2129,7 @@ mount_info::conv_to_posix_path (const char *src_path, char *posix_path, } int pathbuflen = tail - pathbuf; + char *tmpbuf = tp.c_get (); for (int i = 0; i < nmounts; ++i) { mount_item &mi = mount[native_sorted[i]]; @@ -2080,7 +2151,7 @@ mount_info::conv_to_posix_path (const char *src_path, char *posix_path, nextchar = 1; int addslash = nextchar > 0 ? 1 : 0; - if ((mi.posix_pathlen + (pathbuflen - mi.native_pathlen) + addslash) >= CYG_MAX_PATH) + if ((mi.posix_pathlen + (pathbuflen - mi.native_pathlen) + addslash) >= NT_MAX_PATH) return ENAMETOOLONG; strcpy (posix_path, mi.posix_path); if (addslash) @@ -2097,7 +2168,6 @@ mount_info::conv_to_posix_path (const char *src_path, char *posix_path, } if (mi.flags & MOUNT_ENC) { - char tmpbuf[CYG_MAX_PATH]; if (fnunmunge (tmpbuf, posix_path)) strcpy (posix_path, tmpbuf); } @@ -2161,6 +2231,10 @@ mount_info::set_flags_from_win32_path (const char *p) void mount_info::read_mounts (reg_key& r) { + tmp_pathbuf tp; + char *native_path = tp.c_get (); + /* FIXME: The POSIX path is stored as value name right now, which is + restricted to 256 bytes. */ char posix_path[CYG_MAX_PATH]; HKEY key = r.get_key (); DWORD i, posix_path_size; @@ -2172,7 +2246,6 @@ mount_info::read_mounts (reg_key& r) arbitrarily large number of mounts. */ for (i = 0; ; i++) { - char native_path[CYG_MAX_PATH]; int mount_flags; posix_path_size = sizeof (posix_path); @@ -2194,7 +2267,7 @@ mount_info::read_mounts (reg_key& r) reg_key subkey = reg_key (key, KEY_READ, posix_path, NULL); /* Fetch info from the subkey. */ - subkey.get_string ("native", native_path, sizeof (native_path), ""); + subkey.get_string ("native", native_path, NT_MAX_PATH, ""); mount_flags = subkey.get_int ("flags", 0); /* Add mount_item corresponding to registry mount point. */ @@ -2533,7 +2606,10 @@ mount_info::sort () int mount_info::add_item (const char *native, const char *posix, unsigned mountflags, int reg_p) { - char nativetmp[CYG_MAX_PATH]; + tmp_pathbuf tp; + char *nativetmp = tp.c_get (); + /* FIXME: The POSIX path is stored as value name right now, which is + restricted to 256 bytes. */ char posixtmp[CYG_MAX_PATH]; char *nativetail, *posixtail, error[] = "error"; int nativeerr, posixerr; @@ -2607,7 +2683,8 @@ mount_info::add_item (const char *native, const char *posix, unsigned mountflags int mount_info::del_item (const char *path, unsigned flags, int reg_p) { - char pathtmp[CYG_MAX_PATH]; + tmp_pathbuf tp; + char *pathtmp = tp.c_get (); int posix_path_p = false; /* Something's wrong if path is NULL or empty. */ @@ -3969,11 +4046,11 @@ getcwd (char *buf, size_t ulen) return res; } -/* getwd: standards? */ +/* getwd: Legacy. */ extern "C" char * getwd (char *buf) { - return getcwd (buf, CYG_MAX_PATH); + return getcwd (buf, PATH_MAX + 1); /*Per SuSv3!*/ } /* chdir: POSIX 5.2.1.1 */ @@ -4558,9 +4635,10 @@ cwdstuff::set (PUNICODE_STRING nat_cwd, const char *posix_cwd, bool doit) else drive_length = 0; + tmp_pathbuf tp; if (!posix_cwd) { - posix_cwd = (const char *) alloca (NT_MAX_PATH); + posix_cwd = (const char *) tp.c_get (); mount_table->conv_to_posix_path (win32.Buffer, (char *) posix_cwd, 0); } posix = (char *) crealloc_abort (posix, strlen (posix_cwd) + 1); @@ -4578,6 +4656,7 @@ cwdstuff::get (char *buf, int need_posix, int with_chroot, unsigned ulen) { MALLOC_CHECK; + tmp_pathbuf tp; if (ulen) /* nothing */; else if (buf == NULL) @@ -4593,7 +4672,7 @@ cwdstuff::get (char *buf, int need_posix, int with_chroot, unsigned ulen) char *tocopy; if (!need_posix) { - tocopy = (char *) alloca (NT_MAX_PATH); + tocopy = tp.c_get (); sys_wcstombs (tocopy, NT_MAX_PATH, win32.Buffer, win32.Length); } else |