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:
authorCorinna Vinschen <corinna@vinschen.de>2008-03-07 14:24:51 +0300
committerCorinna Vinschen <corinna@vinschen.de>2008-03-07 14:24:51 +0300
commit752b16ce359bb46948b8aa2bc88f7c32bf2cc95b (patch)
tree1ed3d9abb89e7e21ee47faf099632cf05b3a05be /winsup/cygwin/path.cc
parentd8e218442b004997287aaf202af88d9f1f86074e (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.cc151
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