* path.cc (cwd_win32): Eliminate.

(cwd_posix): Eliminate.
(cwd_hash): Eliminate.
(cwdstuff::init): Rename from cwd_init.
(cwdstuff::fixup_after_exec): Rename from cwd_fixup_after_exec.
(cwdstuff::get): Rename from get_cwd_inner.
(normalize_posix_path): Eliminate cwd argument.  Just calculate when necessary.
(normalize_win32_path): Ditto.
(mount_info::conv_to_win32_path): Eliminate cwd retrieval here.
(mount_info::conv_to_posix_path): Ditto.
(hash_path_name): Accomodate additional methods in cwdstuff.
(get_cwd_win32): Eliminate.
(getcwd): Use cwdstuff methods.  Properly handle case where buf == NULL and len
< 0.
(cwdstuff::get_hash): New method.
(cwdstuff::get_initial): New method.
(cwdstuff::set): New method.
(cwdstuff::get): New method.
(cwdstuff::copy): New method.
* path.h: Move cwdstuff struct here.  Add a bunch of stuff to cwdstuff.  Make
cygcwd an extern.
* spawn.cc (spawn_guts): Use copy method to get copies of cwd info to pass to
execed process.
* dcrt0.cc (dll_crt0_1): Use cygcwd methods for cwd initialization.
This commit is contained in:
Christopher Faylor 2000-09-05 03:16:28 +00:00
parent 108952ea1d
commit 7e24f1bf3a
6 changed files with 275 additions and 318 deletions

View File

@ -1,3 +1,31 @@
Mon Sep 4 22:53:58 2000 Christopher Faylor <cgf@cygnus.com>
* path.cc (cwd_win32): Eliminate.
(cwd_posix): Eliminate.
(cwd_hash): Eliminate.
(cwdstuff::init): Rename from cwd_init.
(cwdstuff::fixup_after_exec): Rename from cwd_fixup_after_exec.
(cwdstuff::get): Rename from get_cwd_inner.
(normalize_posix_path): Eliminate cwd argument. Just calculate when
necessary.
(normalize_win32_path): Ditto.
(mount_info::conv_to_win32_path): Eliminate cwd retrieval here.
(mount_info::conv_to_posix_path): Ditto.
(hash_path_name): Accomodate additional methods in cwdstuff.
(get_cwd_win32): Eliminate.
(getcwd): Use cwdstuff methods. Properly handle case where buf == NULL
and len < 0.
(cwdstuff::get_hash): New method.
(cwdstuff::get_initial): New method.
(cwdstuff::set): New method.
(cwdstuff::get): New method.
(cwdstuff::copy): New method.
* path.h: Move cwdstuff struct here. Add a bunch of stuff to cwdstuff.
Make cygcwd an extern.
* spawn.cc (spawn_guts): Use copy method to get copies of cwd info to
pass to execed process.
* dcrt0.cc (dll_crt0_1): Use cygcwd methods for cwd initialization.
2000-09-03 Egor Duda <deo@logos-m.ru>
* path.cc (readlink): Check if buffer length is positive.

View File

@ -111,13 +111,18 @@ _cfree (void *ptr)
static void *__stdcall
_crealloc (void *ptr, int size)
{
char *newptr;
int oldsize = bucket2size[*(int *) ((char *) ptr - 4)];
if (size <= oldsize)
return ptr;
newptr = (char *) _cmalloc (size);
memcpy (newptr, ptr, oldsize);
_cfree (ptr);
void *newptr;
if (ptr == NULL)
newptr = _cmalloc (size);
else
{
int oldsize = bucket2size[*(int *) ((char *) ptr - 4)];
if (size <= oldsize)
return ptr;
newptr = _cmalloc (size);
memcpy (newptr, ptr, oldsize);
_cfree (ptr);
}
return newptr;
}

View File

@ -671,9 +671,9 @@ dll_crt0_1 ()
__argc = spawn_info->moreinfo->argc;
__argv = spawn_info->moreinfo->argv;
envp = spawn_info->moreinfo->environ;
cwd_fixup_after_exec (spawn_info->moreinfo->cwd_win32,
spawn_info->moreinfo->cwd_posix,
spawn_info->moreinfo->cwd_hash);
cygcwd.fixup_after_exec (spawn_info->moreinfo->cwd_win32,
spawn_info->moreinfo->cwd_posix,
spawn_info->moreinfo->cwd_hash);
fdtab.fixup_after_exec (spawn_info->parent, spawn_info->moreinfo->nfds,
spawn_info->moreinfo->fds);
CloseHandle (spawn_info->parent);
@ -733,7 +733,7 @@ dll_crt0_1 ()
}
cygheap_init (); /* Initialize cygwin's heap */
cwd_init ();
cygcwd.init ();
/* Initialize our process table entry. */
pinfo_init (envp);

View File

@ -1,6 +1,6 @@
/* path.cc: path support.
Copyright 1996, 1997, 1998, 1999, 2000 Cygnus Solutions.
Copyright 1996, 1997, 1998, 1999, 2000 Red Hat, Inc.
This file is part of Cygwin.
@ -15,46 +15,22 @@ details. */
Pathnames are handled as follows:
- / is equivalent to \
- A \ or : in a path denotes a pure windows spec.
- Paths beginning with // (or \\) are not translated (i.e. looked
up in the mount table) and are assumed to be UNC path names.
- Paths containing a : are not translated (paths like
/foo/bar/baz:qux: don't make much sense but having the rule written
this way allows one to use strchr).
The goal in the above set of rules is to allow both POSIX and Win32
flavors of pathnames without either interfering. The rules are
intended to be as close to a superset of both as possible.
A possible future enhancement would be to allow people to
disable/enable the mount table handling to support pure Win32
pathnames. Hopefully this won't be needed. The suggested way to
do this would be an environment variable because
a) we need something that is inherited from parent to child,
b) environment variables can be passed from the DOS shell to a
cygwin app,
c) it allows disabling the feature on an app by app basis within
the same session (whereas playing about with the registry wouldn't
-- without getting too complicated). Example:
CYGWIN=pathrules[=@]{win32,posix}. If CYGWIN=pathrules=win32,
mount table handling is disabled. [The intent is to have CYGWIN be
a catchall for tweaking various cygwin.dll features].
Note that you can have more than one path to a file. The mount
table is always prefered when translating Win32 paths to POSIX
paths. Win32 paths in mount table entries may be UNC paths or
standard Win32 paths starting with <drive-letter>:
Text vs Binary issues are not considered here in path style
decisions.
/ and \ are treated as equivalent. One or the other is prefered in
certain situations (e.g. / is preferred in result of getcwd, \ is
preferred in arguments to Win32 api calls), but this code will
translate as necessary.
Apps wishing to translate to/from pure Win32 and POSIX-like
pathnames can use cygwin_foo.
decisions, although the appropriate flags are retrieved and
stored in various structures.
Removing mounted filesystem support would simplify things greatly,
but having it gives us a mechanism of treating disk that lives on a
@ -68,7 +44,7 @@ details. */
Each DOS drive is defined to have a current directory. Supporting
this would complicate things so for now things are defined so that
c: means c:\.
c: means c:\. FIXME: Is this still true?
*/
#include "winsup.h"
@ -90,14 +66,10 @@ details. */
#include "pinfo.h"
#include "cygheap.h"
static int normalize_win32_path (const char *cwd, const char *src, char *dst);
static char *getcwd_inner (char *buf, size_t ulen, int posix_p, int with_chroot);
static int normalize_win32_path (const char *src, char *dst);
static void slashify (const char *src, char *dst, int trailing_slash_p);
static void backslashify (const char *src, char *dst, int trailing_slash_p);
static int path_prefix_p_ (const char *path1, const char *path2, int len1);
static int get_cwd_win32 ();
static NO_COPY const char escape_char = '^';
struct symlink_info
{
@ -113,7 +85,7 @@ struct symlink_info
int check (const char *path, const suffix_info *suffixes);
};
/********************** Path Helper Functions *************************/
cwdstuff cygcwd; /* The current working directory. */
#define path_prefix_p(p1, p2, l1) \
((tolower(*(p1))==tolower(*(p2))) && \
@ -123,6 +95,20 @@ struct symlink_info
(((x) & (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_DIRECTORY)) == \
FILE_ATTRIBUTE_SYSTEM)
/* Determine if path prefix matches current cygdrive */
#define iscygdrive(path) \
(path_prefix_p (cygwin_shared->mount.cygdrive, (path), cygwin_shared->mount.cygdrive_len))
#define iscygdrive_device(path) \
(iscygdrive(path) && isalpha(path[cygwin_shared->mount.cygdrive_len]) && \
(isdirsep(path[cygwin_shared->mount.cygdrive_len + 1]) || \
!path[cygwin_shared->mount.cygdrive_len + 1]))
#define ischrootpath(path) \
(myself->rootlen && \
strncasematch (myself->root, path, myself->rootlen) && \
(path[myself->rootlen] == '/' || path[myself->rootlen] == '\0'))
/* Return non-zero if PATH1 is a prefix of PATH2.
Both are assumed to be of the same path style and / vs \ usage.
Neither may be "".
@ -137,91 +123,6 @@ struct symlink_info
/foo is not a prefix of /foobar
*/
/* Determine if path prefix matches current cygdrive */
#define iscygdrive(path) \
(path_prefix_p (cygwin_shared->mount.cygdrive, (path), cygwin_shared->mount.cygdrive_len))
#define iscygdrive_device(path) \
(iscygdrive(path) && isalpha(path[cygwin_shared->mount.cygdrive_len]) && \
(isdirsep(path[cygwin_shared->mount.cygdrive_len + 1]) || \
!path[cygwin_shared->mount.cygdrive_len + 1]))
/******************** Directory-related Support **************************/
/* Cache getcwd value. FIXME: We need a lock for these in order to
support multiple threads. */
#define TMPCWD ((char *) alloca (MAX_PATH + 1))
struct cwdstuff
{
char *posix;
char *win32;
DWORD hash;
muto *lock;
};
cwdstuff cwd;
char * __stdcall
cwd_win32 (char *buf)
{
char *ret;
cwd.lock->acquire ();
if (cwd.win32 == NULL)
ret = NULL;
else if (buf == NULL)
ret = cwd.win32;
else
ret = strcpy (buf, cwd.win32);
cwd.lock->release ();
return ret;
}
char * __stdcall
cwd_posix (char *buf)
{
char *ret;
cwd.lock->acquire ();
if (cwd.posix == NULL)
ret = NULL;
else if (buf == NULL)
ret = cwd.posix;
else
ret = strcpy (buf, cwd.posix);
cwd.lock->release ();
return ret;
}
DWORD __stdcall
cwd_hash ()
{
DWORD hashnow;
cwd.lock->acquire ();
hashnow = cwd.hash;
cwd.lock->release ();
return hashnow;
}
void __stdcall
cwd_init ()
{
cwd.lock = new_muto (FALSE, "cwd");
}
void __stdcall
cwd_fixup_after_exec (char *win32, char *posix, DWORD hash)
{
cwd.win32 = win32;
cwd.posix = posix;
cwd.hash = hash;
}
#define ischrootpath(path) \
(myself->rootlen && \
strncasematch (myself->root, path, myself->rootlen) && \
(path[myself->rootlen] == '/' || path[myself->rootlen] == '\0'))
static int
path_prefix_p_ (const char *path1, const char *path2, int len1)
{
@ -621,12 +522,12 @@ win32_device_name (const char *src_path, char *win32_path,
#define isslash(c) ((c) == '/')
static int
normalize_posix_path (const char *cwd, const char *src, char *dst)
normalize_posix_path (const char *src, char *dst)
{
const char *src_start = src;
char *dst_start = dst;
syscall_printf ("cwd %s, src %s", cwd, src);
syscall_printf ("src %s", src);
if (isdrive (src) || strpbrk (src, "\\:"))
{
cygwin_conv_to_full_posix_path (src, dst);
@ -634,6 +535,8 @@ normalize_posix_path (const char *cwd, const char *src, char *dst)
}
if (!isslash (src[0]))
{
char cwd[MAX_PATH];
cygcwd.get (cwd); /* FIXME: check return value */
if (strlen (cwd) + 1 + strlen (src) >= MAX_PATH)
{
debug_printf ("ENAMETOOLONG = normalize_posix_path (%s)", src);
@ -727,7 +630,7 @@ normalize_posix_path (const char *cwd, const char *src, char *dst)
The result is 0 for success, or an errno error value.
FIXME: A lot of this should be mergeable with the POSIX critter. */
static int
normalize_win32_path (const char *cwd, const char *src, char *dst)
normalize_win32_path (const char *src, char *dst)
{
const char *src_start = src;
char *dst_start = dst;
@ -735,6 +638,8 @@ normalize_win32_path (const char *cwd, const char *src, char *dst)
if (!SLASH_P (src[0]) && strchr (src, ':') == NULL)
{
char cwd[MAX_PATH];
cygcwd.get (cwd, 0); /* FIXME: check return value */
if (strlen (cwd) + 1 + strlen (src) >= MAX_PATH)
{
debug_printf ("ENAMETOOLONG = normalize_win32_path (%s)", src);
@ -1005,9 +910,6 @@ mount_info::conv_to_win32_path (const char *src_path, char *win32_path,
mount_item *mi = NULL; /* initialized to avoid compiler warning */
char pathbuf[MAX_PATH];
char cwd[MAX_PATH];
getcwd_inner (cwd, MAX_PATH, TRUE, 0); /* FIXME: check rc */
/* Determine where the destination should be placed. */
if (full_win32_path != NULL)
dst = full_win32_path;
@ -1022,7 +924,7 @@ mount_info::conv_to_win32_path (const char *src_path, char *win32_path,
if (strpbrk (src_path, ":\\") != NULL)
{
debug_printf ("%s already win32", src_path);
rc = normalize_win32_path (cwd_win32 (TMPCWD), src_path, dst);
rc = normalize_win32_path (src_path, dst);
if (rc)
{
debug_printf ("normalize_win32_path failed, rc %d", rc);
@ -1065,10 +967,7 @@ mount_info::conv_to_win32_path (const char *src_path, char *win32_path,
converting it to a DOS-style path, looking up the appropriate drive
in the mount table. */
/* No need to fetch cwd if path is absolute. */
isrelpath = !isslash (*src_path);
rc = normalize_posix_path (cwd, src_path, pathbuf);
rc = normalize_posix_path (src_path, pathbuf);
if (rc)
{
@ -1077,6 +976,8 @@ mount_info::conv_to_win32_path (const char *src_path, char *win32_path,
return rc;
}
isrelpath = !isslash (*src_path);
/* See if this is a cygwin "device" */
if (win32_device_name (pathbuf, dst, devn, unit))
{
@ -1137,31 +1038,32 @@ mount_info::conv_to_win32_path (const char *src_path, char *win32_path,
fillin:
/* Compute relative path if asked to and able to. */
unsigned cwdlen;
cwdlen = 0; /* avoid a (hopefully) bogus compiler warning */
char *cwd_win32_now;
cwd_win32_now = cwd_win32 (TMPCWD);
if (win32_path == NULL)
/* nothing to do */;
else if (isrelpath &&
path_prefix_p (cwd_win32_now, dst, cwdlen = strlen (cwd_win32_now)))
else if (isrelpath)
{
size_t n = strlen (dst);
if (n < cwdlen)
strcpy (win32_path, dst);
else
char cwd_win32[MAX_PATH];
cygcwd.get (cwd_win32, 0); /* FIXME: check return value someday */
unsigned cwdlen = strlen (cwd_win32);
if (path_prefix_p (cwd_win32, dst, cwdlen))
{
if (n == cwdlen)
dst += cwdlen;
size_t n = strlen (dst);
if (n < cwdlen)
strcpy (win32_path, dst);
else
dst += isdirsep (cwd_win32_now[cwdlen - 1]) ? cwdlen : cwdlen + 1;
memmove (win32_path, dst, strlen (dst) + 1);
if (!*win32_path)
{
strcpy (win32_path, ".");
if (trailing_slash_p)
strcat (win32_path, "\\");
if (n == cwdlen)
dst += cwdlen;
else
dst += isdirsep (cwd_win32[cwdlen - 1]) ? cwdlen : cwdlen + 1;
memmove (win32_path, dst, strlen (dst) + 1);
if (!*win32_path)
{
strcpy (win32_path, ".");
if (trailing_slash_p)
strcat (win32_path, "\\");
}
}
}
}
@ -1273,15 +1175,7 @@ mount_info::conv_to_posix_path (const char *src_path, char *posix_path,
}
char pathbuf[MAX_PATH];
char cwd[MAX_PATH];
/* No need to fetch cwd if path is absolute. */
if (relative_path_p)
getcwd_inner (cwd, MAX_PATH, 0, 0); /* FIXME: check rc */
else
strcpy (cwd, "/"); /* some innocuous value */
int rc = normalize_win32_path (cwd, src_path, pathbuf);
int rc = normalize_win32_path (src_path, pathbuf);
if (rc != 0)
{
debug_printf ("%d = conv_to_posix_path (%s)", rc, src_path);
@ -2513,9 +2407,9 @@ hash_path_name (unsigned long hash, const char *name)
Otherwise the inodes same will differ depending on whether a file is
referenced with an absolute value or relatively. */
if (*name != '\\' && (cwd_win32 (TMPCWD) == NULL || get_cwd_win32 ()))
if (*name != '\\')
{
hash = cwd_hash ();
hash = cygcwd.get_hash ();
if (name[0] == '.' && name[1] == '\0')
return hash;
hash = hash_path_name (hash, "\\");
@ -2535,134 +2429,38 @@ hashit:
return hash;
}
static int
get_cwd_win32 ()
{
DWORD dlen, len;
cwd.lock->acquire ();
for (dlen = 256; ; dlen *= 2)
{
cwd.win32 = (char *) crealloc (cwd.win32, dlen + 2);
if ((len = GetCurrentDirectoryA (dlen, cwd.win32)) < dlen)
break;
}
if (len == 0)
__seterrno ();
else
cwd.hash = hash_path_name (0, cwd.win32);
cwd.lock->release ();
return len;
}
/* getcwd */
char *
getcwd_inner (char *buf, size_t ulen, int posix_p, int with_chroot)
{
char *resbuf = NULL;
size_t len = ulen;
if (cwd_win32 (TMPCWD) == NULL && !get_cwd_win32 ())
return NULL;
char *cwd_win32_now = cwd_win32 (TMPCWD);
char *cwd_posix_now = cwd_posix (TMPCWD);
if (!posix_p)
{
if (strlen (cwd_win32_now) >= len)
set_errno (ERANGE);
else
{
strcpy (buf, cwd_win32_now);
resbuf = buf;
}
syscall_printf ("%p (%s) = getcwd_inner (%p, %d, win32) (cached)",
resbuf, resbuf ? resbuf : "", buf, len);
return resbuf;
}
else if (cwd_posix_now != NULL)
{
debug_printf("myself->root: %s, cwd_posix: %s", myself->root, cwd_posix_now);
if (strlen (cwd_posix_now) >= len)
set_errno (ERANGE);
else if (with_chroot && ischrootpath(cwd_posix_now))
{
strcpy (buf, cwd_posix_now + myself->rootlen);
if (!buf[0])
strcpy (buf, "/");
resbuf = buf;
}
else
{
strcpy (buf, cwd_posix_now);
resbuf = buf;
}
syscall_printf ("%p (%s) = getcwd_inner (%p, %d, posix) (cached)",
resbuf, resbuf ? resbuf : "", buf, len);
return resbuf;
}
/* posix_p required and cwd_posix == NULL */
char temp[MAX_PATH];
/* Turn from Win32 style to our style. */
cygwin_shared->mount.conv_to_posix_path (cwd_win32_now, temp, 0);
size_t tlen = strlen (temp);
if (with_chroot && ischrootpath (temp))
tlen -= myself->rootlen;
cwd.lock->acquire ();
cwd.posix = (char *) crealloc (cwd.posix, tlen + 1);
if (cwd.posix != NULL)
if (with_chroot && ischrootpath (temp))
{
strcpy (cwd.posix, temp + myself->rootlen);
if (!buf[0])
strcpy (buf, "/");
}
else
strcpy (cwd.posix, temp);
cwd.lock->release ();
if (tlen >= ulen)
set_errno (ERANGE); /* len was too small */
else
{
strcpy (buf, temp);
resbuf = buf;
}
syscall_printf ("%p (%s) = getcwd_inner (%p, %d, %s)",
resbuf, resbuf ? resbuf : "",
buf, len, posix_p ? "posix" : "win32");
return resbuf;
}
char *
getcwd (char *buf, size_t ulen)
{
char *res;
char *usebuf, uselen;
if (buf == NULL || ulen == 0)
if (buf != NULL)
{
buf = (char *) alloca (MAX_PATH);
res = getcwd_inner (buf, MAX_PATH, 1, 1);
res = strdup (buf);
usebuf = buf;
uselen = TRUE;
}
else
{
res = getcwd_inner (buf, ulen, 1, 1);
if (ulen >= 0)
uselen = TRUE;
else
{
uselen = FALSE;
ulen = MAX_PATH + 1;
}
usebuf = (char *) malloc (ulen);
usebuf [ulen - 1] = '\0';
}
res = cygcwd.get (usebuf, 1, 1, ulen);
if (res && !uselen)
usebuf = (char *) realloc (usebuf, strlen (usebuf) + 1);
else if (!res && buf == NULL)
free (usebuf);
return res;
}
@ -2704,27 +2502,12 @@ chdir (const char *dir)
if (res == -1)
__seterrno ();
else
{
cwd.lock->acquire ();
/* Store new cache information */
cfree (cwd.win32);
cwd.win32 = cstrdup (path);
cygcwd.set (path);
char pathbuf[MAX_PATH];
(void) normalize_posix_path (cwd.posix, dir, pathbuf);
/* Look for trailing path component consisting entirely of dots. This
is needed only in case of chdir since Windows simply ignores count
of dots > 2 here instead of returning an error code. Counts of dots
<= 2 are already eliminated by normalize_posix_path. */
char *last_slash = strrchr (pathbuf, '/');
if (last_slash > pathbuf && strspn (last_slash + 1, ".") == strlen (last_slash + 1))
*last_slash = '\0';
cfree (cwd.posix);
cwd.posix = cstrdup (pathbuf);
cwd.lock->release ();
}
syscall_printf ("%d = chdir() cwd.posix '%s' native '%s'", res, cwd.posix, native_dir);
/* Note that we're accessing cwd.posix without a lock here. I didn't think
it was worth locking just for strace. */
syscall_printf ("%d = chdir() cygcwd.posix '%s' native '%s'", res,
cygcwd.posix, native_dir);
return res;
}
@ -3065,3 +2848,130 @@ check_null_empty_path (const char *name)
return 0;
}
/* Return the hash value for the current win32 value.
This is used when constructing inodes. */
DWORD
cwdstuff::get_hash ()
{
DWORD hashnow;
lock->acquire ();
hashnow = hash;
lock->release ();
return hashnow;
}
/* Initialize cygcwd 'muto' for serializing access to cwd info. */
void
cwdstuff::init ()
{
lock = new_muto (FALSE, "cwd");
}
/* Called to fill in cwd values after an exec. */
void
cwdstuff::fixup_after_exec (char *win32_cwd, char *posix_cwd, DWORD hash_cwd)
{
win32 = win32_cwd;
posix = posix_cwd;
hash = hash_cwd;
}
/* Get initial cwd. Should only be called once in a
process tree. */
bool
cwdstuff::get_initial ()
{
lock->acquire ();
DWORD len, dlen;
int i;
for (i = 0, dlen = MAX_PATH, len = 0; i < 3; dlen *= 2, i++)
{
win32 = (char *) crealloc (win32, dlen + 2);
if ((len = GetCurrentDirectoryA (dlen, win32)) < dlen)
break;
}
if (len == 0)
{
__seterrno ();
lock->release ();
debug_printf ("get_initial_cwd failed, %E");
return 0;
}
set (NULL);
return 1; /* Leaves cwd lock unreleased */
}
/* Fill out the elements of a cwdstuff struct.
It is assumed that the lock for the cwd is acquired if
win32_cwd == NULL. */
void
cwdstuff::set (char *win32_cwd)
{
if (win32_cwd)
{
lock->acquire ();
win32 = (char *) crealloc (win32, strlen (win32_cwd) + 1);
strcpy (win32, win32_cwd);
}
hash = hash_path_name (0, win32);
/* Turn from Win32 style to our style. */
char temp[MAX_PATH];
cygwin_shared->mount.conv_to_posix_path (win32, temp, 0);
posix = (char *) crealloc (posix, strlen (temp) + 1);
strcpy (posix, temp);
if (win32_cwd)
lock->release ();
return;
}
/* Copy the value for either the posix or the win32 cwd into a buffer. */
char *
cwdstuff::get (char *buf, int need_posix, int with_chroot, unsigned ulen)
{
size_t len = ulen;
if (!get_initial ()) /* Get initial cwd and set cwd lock */
return NULL;
char *tocopy;
if (!need_posix)
tocopy = win32;
else
tocopy = with_chroot && ischrootpath(posix) ?
posix + myself->rootlen : posix;
debug_printf("myself->root: %s, posix: %s", myself->root, posix);
if (strlen (tocopy) >= ulen)
set_errno (ERANGE);
else
{
strcpy (buf, tocopy);
if (!buf[0]) /* Should only happen when chroot */
strcpy (buf, "/");
}
lock->release ();
syscall_printf ("(%s) = cwdstuff::get (%p, %d, %d, %d)",
buf, buf, len, need_posix, with_chroot);
return buf;
}
/* Get copies of all cwdstuff elements. Used by spawn_guts. */
void
cwdstuff::copy (char * &posix_cwd, char * &win32_cwd, DWORD hash_cwd)
{
lock->acquire ();
get_initial (); /* FIXME: Check return someday */
posix_cwd = cstrdup (posix);
win32_cwd = cstrdup (win32);
hash_cwd = hash;
lock->release ();
}

View File

@ -110,11 +110,6 @@ int __stdcall check_null_empty_path (const char *name);
const char * __stdcall find_exec (const char *name, path_conv& buf, const char *winenv = "PATH=",
int null_if_notfound = 0, const char **known_suffix = NULL);
void __stdcall cwd_init ();
char * __stdcall cwd_posix (char *);
char * __stdcall cwd_win32 (char *);
DWORD __stdcall cwd_hash ();
void __stdcall cwd_fixup_after_exec (char *, char *, DWORD);
/* Common macros for checking for invalid path names */
@ -127,3 +122,24 @@ void __stdcall cwd_fixup_after_exec (char *, char *, DWORD);
})
#define isdrive(s) (isalpha (*(s)) && (s)[1] == ':')
/* cwd cache stuff. */
class muto;
struct cwdstuff
{
char *posix;
char *win32;
DWORD hash;
muto *lock;
char *get (char *buf, int need_posix = 1, int with_chroot = 0, unsigned ulen = MAX_PATH);
DWORD get_hash ();
void init ();
void fixup_after_exec (char *win32, char *posix, DWORD hash);
bool get_initial ();
void copy (char * &posix_cwd, char * &win32_cwd, DWORD hash_cwd);
void set (char *win32_cwd);
};
extern cwdstuff cygcwd;

View File

@ -505,10 +505,8 @@ spawn_guts (HANDLE hToken, const char * prog_arg, const char *const *argv,
ciresrv.moreinfo->argc = newargv.argc;
ciresrv.moreinfo->argv = newargv;
/* FIXME: Should lock cwd access here. */
ciresrv.moreinfo->cwd_posix = cwd_posix (NULL);
ciresrv.moreinfo->cwd_win32 = cwd_win32 (NULL);
ciresrv.moreinfo->cwd_hash = cwd_hash ();
cygcwd.copy (ciresrv.moreinfo->cwd_posix, ciresrv.moreinfo->cwd_win32,
ciresrv.moreinfo->cwd_hash);
ciresrv.moreinfo->environ = (char **) cmalloc (HEAP_ARGV, envsize (envp, 1));
char **c;