1 /* path.cc: path support.
3 Copyright 1996, 1997, 1998, 1999, 2000 Red Hat, Inc.
5 This file is part of Cygwin.
7 This software is a copyrighted work licensed under the terms of the
8 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
11 /* This module's job is to
12 - convert between POSIX and Win32 style filenames,
13 - support the `mount' functionality,
14 - support symlinks for files and directories
16 Pathnames are handled as follows:
18 - A \ or : in a path denotes a pure windows spec.
19 - Paths beginning with // (or \\) are not translated (i.e. looked
20 up in the mount table) and are assumed to be UNC path names.
22 The goal in the above set of rules is to allow both POSIX and Win32
23 flavors of pathnames without either interfering. The rules are
24 intended to be as close to a superset of both as possible.
26 Note that you can have more than one path to a file. The mount
27 table is always prefered when translating Win32 paths to POSIX
28 paths. Win32 paths in mount table entries may be UNC paths or
29 standard Win32 paths starting with <drive-letter>:
31 Text vs Binary issues are not considered here in path style
32 decisions, although the appropriate flags are retrieved and
33 stored in various structures.
35 Removing mounted filesystem support would simplify things greatly,
36 but having it gives us a mechanism of treating disk that lives on a
37 UNIX machine as having UNIX semantics [it allows one to edit a text
38 file on that disk and not have cr's magically appear and perhaps
39 break apps running on UNIX boxes]. It also useful to be able to
40 layout a hierarchy without changing the underlying directories.
42 The semantics of mounting file systems is not intended to precisely
43 follow normal UNIX systems.
45 Each DOS drive is defined to have a current directory. Supporting
46 this would complicate things so for now things are defined so that
47 c: means c:\. FIXME: Is this still true?
53 #include <sys/mount.h>
60 #include <sys/cygwin.h>
61 #include <cygwin/version.h>
69 #include "shared_info.h"
74 static int normalize_win32_path (const char *src, char *dst);
75 static void slashify (const char *src, char *dst, int trailing_slash_p);
76 static void backslashify (const char *src, char *dst, int trailing_slash_p);
77 static int path_prefix_p_ (const char *path1, const char *path2, int len1);
81 char buf[3 + MAX_PATH * 3];
89 symlink_info (): known_suffix (NULL), contents (buf + MAX_PATH + 1) {}
90 int check (const char *path, const suffix_info *suffixes);
93 cwdstuff cygcwd; /* The current working directory. */
95 #define path_prefix_p(p1, p2, l1) \
96 ((tolower(*(p1))==tolower(*(p2))) && \
97 path_prefix_p_(p1, p2, l1))
99 #define SYMLINKATTR(x) \
100 (((x) & (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_DIRECTORY)) == \
101 FILE_ATTRIBUTE_SYSTEM)
103 /* Determine if path prefix matches current cygdrive */
104 #define iscygdrive(path) \
105 (path_prefix_p (cygwin_shared->mount.cygdrive, (path), cygwin_shared->mount.cygdrive_len))
107 #define iscygdrive_device(path) \
108 (iscygdrive(path) && isalpha(path[cygwin_shared->mount.cygdrive_len]) && \
109 (isdirsep(path[cygwin_shared->mount.cygdrive_len + 1]) || \
110 !path[cygwin_shared->mount.cygdrive_len + 1]))
112 #define ischrootpath(path) \
113 (myself->rootlen && \
114 strncasematch (myself->root, path, myself->rootlen) && \
115 (path[myself->rootlen] == '/' || path[myself->rootlen] == '\0'))
117 /* Return non-zero if PATH1 is a prefix of PATH2.
118 Both are assumed to be of the same path style and / vs \ usage.
120 LEN1 = strlen (PATH1). It's passed because often it's already known.
123 /foo/ is a prefix of /foo <-- may seem odd, but desired
124 /foo is a prefix of /foo/
125 / is a prefix of /foo/bar
126 / is not a prefix of foo/bar
127 foo/ is a prefix foo/bar
128 /foo is not a prefix of /foobar
132 path_prefix_p_ (const char *path1, const char *path2, int len1)
134 /* Handle case where PATH1 has trailing '/' and when it doesn't. */
135 if (len1 > 0 && SLASH_P (path1[len1 - 1]))
139 return SLASH_P (path2[0]) && !SLASH_P (path2[1]);
141 if (!strncasematch (path1, path2, len1))
144 return SLASH_P (path2[len1]) || path2[len1] == 0 || path1[len1 - 1] == ':';
147 /* Convert an arbitrary path SRC to a pure Win32 path, suitable for
148 passing to Win32 API routines.
150 If an error occurs, `error' is set to the errno value.
151 Otherwise it is set to 0.
154 SYMLINK_FOLLOW - convert to PATH symlink points to
155 SYMLINK_NOFOLLOW - convert to PATH of symlink itself
156 SYMLINK_IGNORE - do not check PATH for symlinks
157 SYMLINK_CONTENTS - just return symlink contents
161 path_conv::check (const char *src, unsigned opt,
162 const suffix_info *suffixes)
164 /* This array is used when expanding symlinks. It is MAX_PATH * 2
165 in length so that we can hold the expanded symlink plus a
167 char path_buf[MAX_PATH];
168 char path_copy[MAX_PATH];
169 char tmp_buf[MAX_PATH];
171 bool need_directory = 0;
173 char *rel_path, *full_path;
175 if (!(opt & PC_NULLEMPTY))
177 else if ((error = check_null_empty_path (src)))
181 rel_path = path_buf, full_path = this->path;
183 rel_path = this->path, full_path = path_buf;
185 /* This loop handles symlink expansion. */
189 fileattr = (DWORD) -1;
194 char *p = strrchr (src, '/');
197 if (p[1] == '\0' || strcmp (p, "/.") == 0)
200 else if ((p = strrchr (src, '\\')) &&
201 (p[1] == '\0' || strcmp (p, "\\.") == 0))
203 /* Must look up path in mount table, etc. */
204 error = cygwin_shared->mount.conv_to_win32_path (src, rel_path,
206 devn, unit, &path_flags);
216 /* Eat trailing slashes */
217 char *tail = strchr (full_path, '\0');
218 /* If path is only a drivename, Windows interprets it as
219 the current working directory on this drive instead of
220 the root dir which is what we want. So we need
221 the trailing backslash in this case. */
222 while (tail > full_path + 3 && (*--tail == '\\'))
224 if (full_path[0] && full_path[1] == ':' && full_path[2] == '\0')
225 strcat (full_path, "\\");
227 if (opt & PC_SYM_IGNORE)
229 fileattr = GetFileAttributesA (path);
233 /* Make a copy of the path that we can munge up */
234 strcpy (path_copy, full_path);
236 tail = path_copy + 1 + (tail - full_path); // Point to end of copy
238 /* Scan path_copy from right to left looking either for a symlink
239 or an actual existing file. If an existing file is found, just
240 return. If a symlink is found exit the for loop.
241 Also: be careful to preserve the errno returned from
242 symlink.check as the caller may need it. */
243 /* FIXME: Do we have to worry about multiple \'s here? */
244 int component = 0; // Number of translated components
245 sym.contents[0] = '\0';
249 const suffix_info *suff;
251 /* Don't allow symlink.check to set anything in the path_conv
252 class if we're working on an inner component of the path */
261 sym.pflags = path_flags;
264 int len = sym.check (path_copy, suff);
267 path_flags = sym.pflags;
269 /* If symlink.check found an existing non-symlink file, then
270 it sets the appropriate flag. It also sets any suffix found
272 if (!sym.is_symlink && sym.fileattr != (DWORD) -1)
277 fileattr = sym.fileattr;
280 goto out; // file found
282 /* Found a symlink if len > 0. If component == 0, then the
283 src path itself was a symlink. If !follow_mode then
284 we're done. Otherwise we have to insert the path found
285 into the full path that we are building and perform all of
286 these operations again on the newly derived path. */
289 if (component == 0 && !need_directory && !(opt & PC_SYM_FOLLOW))
291 set_symlink (); // last component of path is a symlink.
292 fileattr = sym.fileattr;
293 if (opt & PC_SYM_CONTENTS)
294 strcpy (path, sym.contents);
300 /* No existing file found. */
302 if (!(tail = strrchr (path_copy, '\\')) ||
303 (tail > path_copy && tail[-1] == ':'))
304 goto out; // all done
306 /* Haven't found a valid pathname component yet.
307 Pinch off the tail and try again. */
312 /* Arrive here if above loop detected a symlink. */
313 if (++loop > MAX_LINK_DEPTH)
315 error = ELOOP; // Eep.
320 tail = full_path + (tail - path_copy);
321 int taillen = strlen (tail);
322 int buflen = strlen (sym.contents);
323 if (buflen + taillen > MAX_PATH)
325 error = ENAMETOOLONG;
326 strcpy (path, "::ENAMETOOLONG::");
330 /* Copy tail of full_path to discovered symlink. */
331 for (p = sym.contents + buflen; *tail; tail++)
332 *p++ = *tail == '\\' ? '/' : *tail;
335 /* If symlink referred to an absolute path, then we
336 just use sym.contents and loop. Otherwise tack the head of
337 path_copy before sym.contents and translate it back from a
338 Win32-style path to a POSIX-style one. */
339 if (isabspath (sym.contents))
341 else if (!(tail = strrchr (path_copy, '\\')))
342 system_printf ("problem parsing %s - '%s'", src, full_path);
345 int headlen = 1 + tail - path_copy;
346 p = sym.contents - headlen;
347 memcpy (p, path_copy, headlen);
349 error = cygwin_shared->mount.conv_to_posix_path (p, tmp_buf, 1);
358 if (sym.known_suffix)
359 known_suffix = this->path + (sym.known_suffix - path_copy);
360 else if (sym.ext_here && !(opt & PC_SYM_CONTENTS))
362 known_suffix = strchr (this->path, '\0');
363 strcpy (known_suffix, sym.ext_here);
367 /* Deal with Windows stupidity which considers filename\. to be valid
368 even when "filename" is not a directory. */
369 if (!need_directory || error)
371 else if (fileattr & FILE_ATTRIBUTE_DIRECTORY)
372 path_flags &= ~PATH_SYMLINK;
375 debug_printf ("%s is a non-directory", path);
379 DWORD serial, volflags;
381 strcpy (tmp_buf, full_path);
382 if (!rootdir (tmp_buf) ||
383 !GetVolumeInformation (tmp_buf, NULL, 0, &serial, NULL, &volflags, NULL, 0))
385 debug_printf ("GetVolumeInformation(%s) = ERR, full_path(%s), set_has_acls(FALSE)",
386 tmp_buf, full_path, GetLastError ());
387 set_has_acls (FALSE);
391 debug_printf ("GetVolumeInformation(%s) = OK, full_path(%s), set_has_acls(%d)",
392 tmp_buf, full_path, volflags & FS_PERSISTENT_ACLS);
393 set_has_acls (volflags & FS_PERSISTENT_ACLS);
397 #define deveq(s) (strcasematch (name, (s)))
398 #define deveqn(s, n) (strncasematch (name, (s), (n)))
401 digits (const char *name)
404 int n = strtol(name, &p, 10);
406 return p > name && !*p ? n : -1;
409 const char *windows_device_names[] =
437 get_raw_device_number (const char *uxname, const char *w32path, int &unit)
441 if (strncasematch (w32path, "\\\\.\\tape", 8))
444 unit = digits (w32path + 8);
445 // norewind tape devices have leading n in name
446 if (strncasematch (uxname, "/dev/n", 6))
449 else if (isdrive (w32path + 4))
452 unit = tolower (w32path[4]) - 'a';
454 else if (strncasematch (w32path, "\\\\.\\physicaldrive", 17))
457 unit = digits (w32path + 17) + 128;
463 get_device_number (const char *name, int &unit, BOOL from_conv)
468 if ((*name == '/' && deveqn ("/dev/", 5)) ||
469 (*name == '\\' && deveqn ("\\dev\\", 5)))
474 if (tty_attached (myself))
479 else if (myself->ctty > 0)
482 else if (deveqn ("tty", 3) && (unit = digits (name + 3)) >= 0)
484 else if (deveq ("ttym"))
486 else if (deveq ("ptmx"))
488 else if (deveq ("windows"))
490 else if (deveq ("conin"))
492 else if (deveq ("conout"))
494 else if (deveq ("null"))
496 else if (deveq ("zero"))
498 else if (deveq ("random") || deveq ("urandom"))
501 unit = 8 + (deveqn ("u", 1) ? 1 : 0); /* Keep unit Linux conformant */
503 else if (deveq ("mem"))
508 else if (deveq ("port"))
513 else if (deveqn ("com", 3) && (unit = digits (name + 3)) >= 0)
515 else if (deveq ("pipe") || deveq ("piper") || deveq ("pipew"))
517 else if (deveq ("tcp") || deveq ("udp") || deveq ("streamsocket")
518 || deveq ("dgsocket"))
520 else if (! from_conv)
521 devn = get_raw_device_number (name - 5,
523 PC_SYM_IGNORE).get_win32 (),
526 else if (deveqn ("com", 3) && (unit = digits (name + 3)) >= 0)
532 /* Return TRUE if src_path is a Win32 device name, filling out the device
533 name in win32_path */
536 win32_device_name (const char *src_path, char *win32_path,
537 DWORD &devn, int &unit)
541 devn = get_device_number (src_path, unit, TRUE);
546 if ((devfmt = windows_device_names[FHDEVN (devn)]) == NULL)
548 if (devn == FH_RANDOM)
549 __small_sprintf (win32_path, devfmt, unit == 8 ? "" : "u");
551 __small_sprintf (win32_path, devfmt, unit);
555 /* Normalize a POSIX path.
556 \'s are converted to /'s in the process.
557 All duplicate /'s, except for 2 leading /'s, are deleted.
558 The result is 0 for success, or an errno error value. */
560 #define isslash(c) ((c) == '/')
563 normalize_posix_path (const char *src, char *dst)
565 const char *src_start = src;
566 char *dst_start = dst;
568 syscall_printf ("src %s", src);
569 if (isdrive (src) || strpbrk (src, "\\:"))
571 cygwin_conv_to_full_posix_path (src, dst);
574 if (!isslash (src[0]))
576 if (!cygcwd.get (dst))
578 if (strlen (dst) + 1 + strlen (src) >= MAX_PATH)
580 debug_printf ("ENAMETOOLONG = normalize_posix_path (%s)", src);
583 dst = strchr (dst, '\0');
586 if (dst > dst_start && !isslash (dst[-1]))
589 /* Two leading /'s? If so, preserve them. */
590 else if (isslash (src[1]))
594 debug_printf ("ENOENT = normalize_posix_path (%s)", src);
601 { /* Starts with three or more slashes - reset. */
607 /* Exactly one leading slash. Absolute path. Check for chroot. */
608 else if (myself->rootlen)
610 strcpy (dst, myself->root);
611 dst += myself->rootlen;
616 /* Strip runs of /'s. */
634 if (dst == dst_start)
638 if (!isslash (src[1]))
641 else if (src[2] && !isslash (src[2]))
645 if (!ischrootpath (dst_start) ||
646 dst - dst_start != (int) myself->rootlen)
647 while (dst > dst_start && !isslash (*--dst))
659 if (--dst > dst_start && isslash (*dst))
662 debug_printf ("%s = normalize_posix_path (%s)", dst_start, src_start);
666 /* Normalize a Win32 path.
667 /'s are converted to \'s in the process.
668 All duplicate \'s, except for 2 leading \'s, are deleted.
670 The result is 0 for success, or an errno error value.
671 FIXME: A lot of this should be mergeable with the POSIX critter. */
673 normalize_win32_path (const char *src, char *dst)
675 const char *src_start = src;
676 char *dst_start = dst;
677 char *dst_root_start = dst;
679 if (!SLASH_P (src[0]) && strchr (src, ':') == NULL)
681 if (!cygcwd.get (dst, 0))
683 if (strlen (dst) + 1 + strlen (src) >= MAX_PATH)
685 debug_printf ("ENAMETOOLONG = normalize_win32_path (%s)", src);
689 if (!SLASH_P (dst[-1]))
692 /* Two leading \'s? If so, preserve them. */
693 else if (SLASH_P (src[0]) && SLASH_P (src[1]))
697 debug_printf ("ENOENT = normalize_win32_path (%s)", src);
703 /* If absolute path, care for chroot. */
704 else if (SLASH_P (src[0]) && !SLASH_P (src[1]) && myself->rootlen)
706 strcpy (dst, myself->root);
708 while ((c = strchr (dst, '/')) != NULL)
710 dst += myself->rootlen;
711 dst_root_start = dst;
717 /* Strip duplicate /'s. */
718 if (SLASH_P (src[0]) && SLASH_P (src[1]))
721 else if (src[0] == '.' && SLASH_P (src[1])
722 && (src == src_start || SLASH_P (src[-1])))
727 /* Backup if "..". */
728 else if (src[0] == '.' && src[1] == '.'
729 /* dst must be greater than dst_start */
731 && (SLASH_P (src[2]) || src[2] == 0))
733 /* Back up over /, but not if it's the first one. */
734 if (dst > dst_root_start + 1)
736 /* Now back up to the next /. */
737 while (dst > dst_root_start + 1 && dst[-1] != '\\' && dst[-2] != ':')
743 /* Otherwise, add char to result. */
754 debug_printf ("%s = normalize_win32_path (%s)", dst_start, src_start);
759 /* Various utilities. */
761 /* slashify: Convert all back slashes in src path to forward slashes
762 in dst path. Add a trailing slash to dst when trailing_slash_p arg
766 slashify (const char *src, char *dst, int trailing_slash_p)
768 const char *start = src;
780 && !isdirsep (src[-1]))
785 /* backslashify: Convert all forward slashes in src path to back slashes
786 in dst path. Add a trailing slash to dst when trailing_slash_p arg
790 backslashify (const char *src, char *dst, int trailing_slash_p)
792 const char *start = src;
804 && !isdirsep (src[-1]))
809 /* nofinalslash: Remove trailing / and \ from SRC (except for the
810 first one). It is ok for src == dst. */
813 nofinalslash (const char *src, char *dst)
815 int len = strlen (src);
817 memcpy (dst, src, len + 1);
818 while (len > 1 && SLASH_P (dst[--len]))
822 /* slash_drive_prefix_p: Return non-zero if PATH begins with
826 slash_drive_prefix_p (const char *path)
828 return (isdirsep(path[0])
831 && (path[3] == 0 || path[3] == '/'));
834 /* slash_unc_prefix_p: Return non-zero if PATH begins with //UNC/SHARE */
837 slash_unc_prefix_p (const char *path)
840 int ret = (isdirsep (path[0])
841 && isdirsep (path[1])
844 && !isdirsep (path[3])
845 && ((p = strchr(&path[3], '/')) != NULL));
846 if (!ret || p == NULL)
848 return ret && isalnum (p[1]);
851 /* conv_path_list: Convert a list of path names to/from Win32/POSIX.
853 SRC is not a const char * because we temporarily modify it to ease
856 I believe Win32 always has '.' in $PATH. POSIX obviously doesn't.
857 We certainly don't want to handle that here, but it is something for
858 the caller to think about. */
861 conv_path_list (const char *src, char *dst, int to_posix_p)
865 char src_delim = to_posix_p ? ';' : ':';
866 char dst_delim = to_posix_p ? ':' : ';';
867 int (*conv_fn) (const char *, char *) = (to_posix_p
868 ? cygwin_conv_to_posix_path
869 : cygwin_conv_to_win32_path);
873 s = strchr (src, src_delim);
877 (*conv_fn) (src[0] != 0 ? src : ".", d);
886 (*conv_fn) (src[0] != 0 ? src : ".", d);
892 /************************* mount_info class ****************************/
894 /* init: Initialize the mount table. */
900 had_to_create_mount_areas = 0;
902 /* Fetch the mount table and cygdrive-related information from
907 /* conv_to_win32_path: Ensure src_path is a pure Win32 path and store
908 the result in win32_path.
910 If win32_path != NULL, the relative path, if possible to keep, is
911 stored in win32_path. If the relative path isn't possible to keep,
912 the full path is stored.
914 If full_win32_path != NULL, the full path is stored there.
916 The result is zero for success, or an errno value.
918 {,full_}win32_path must have sufficient space (i.e. MAX_PATH bytes). */
921 mount_info::conv_to_win32_path (const char *src_path, char *win32_path,
922 char *full_win32_path, DWORD &devn, int &unit,
925 int src_path_len = strlen (src_path);
926 int trailing_slash_p = (src_path_len > 1
927 && SLASH_P (src_path[src_path_len - 1]));
930 unsigned dummy_flags;
936 flags = &dummy_flags;
939 debug_printf ("conv_to_win32_path (%s)", src_path);
941 if (src_path_len >= MAX_PATH)
943 debug_printf ("ENAMETOOLONG = conv_to_win32_path (%s)", src_path);
949 mount_item *mi = NULL; /* initialized to avoid compiler warning */
950 char pathbuf[MAX_PATH];
952 /* Determine where the destination should be placed. */
953 if (full_win32_path != NULL)
954 dst = full_win32_path;
955 else if (win32_path != NULL)
959 goto out; /* Sanity check. */
961 /* An MS-DOS spec has either a : or a \. If this is found, short
962 circuit most of the rest of this function. */
963 if (strpbrk (src_path, ":\\") != NULL)
965 debug_printf ("%s already win32", src_path);
966 rc = normalize_win32_path (src_path, dst);
969 debug_printf ("normalize_win32_path failed, rc %d", rc);
972 isrelpath = !isabspath (src_path);
973 *flags = set_flags_from_win32_path (dst);
974 if (myself->rootlen && dst[0] && dst[1] == ':')
976 char posix_path[MAX_PATH + 1];
978 rc = cygwin_shared->mount.conv_to_posix_path (dst, posix_path, 0);
981 debug_printf ("conv_to_posix_path failed, rc %d", rc);
984 if (!ischrootpath (posix_path))
986 debug_printf ("ischrootpath failed");
993 /* Normalize the path, taking out ../../ stuff, we need to do this
994 so that we can move from one mounted directory to another with relative
997 eg mounting c:/foo /foo
1003 should look in c:/foo, not d:/foo.
1005 We do this by first getting an absolute UNIX-style path and then
1006 converting it to a DOS-style path, looking up the appropriate drive
1007 in the mount table. */
1009 rc = normalize_posix_path (src_path, pathbuf);
1013 debug_printf ("%d = conv_to_win32_path (%s)", rc, src_path);
1018 isrelpath = !isslash (*src_path);
1020 /* See if this is a cygwin "device" */
1021 if (win32_device_name (pathbuf, dst, devn, unit))
1023 *flags = MOUNT_BINARY; /* FIXME: Is this a sensible default for devices? */
1027 /* Check if the cygdrive prefix was specified. If so, just strip
1028 off the prefix and transform it into an MS-DOS path. */
1030 if (iscygdrive_device (pathbuf))
1032 if (!cygdrive_win32_path (pathbuf, dst, trailing_slash_p))
1034 *flags = cygdrive_flags;
1038 /* Check the mount table for prefix matches. */
1039 for (i = 0; i < nmounts; i++)
1041 mi = mount + posix_sorted[i];
1042 if (path_prefix_p (mi->posix_path, pathbuf, mi->posix_pathlen))
1048 if (slash_drive_prefix_p (pathbuf))
1049 slash_drive_to_win32_path (pathbuf, dst, trailing_slash_p);
1051 backslashify (pathbuf, dst, trailing_slash_p); /* just convert */
1056 int n = mi->native_pathlen;
1057 memcpy (dst, mi->native_path, n + 1);
1058 char *p = pathbuf + mi->posix_pathlen;
1059 if (!trailing_slash_p && !*p)
1061 if (isdrive (dst) && !dst[2])
1067 /* Do not add trailing \ to UNC device names like \\.\a: */
1068 if (*p != '/' && /* FIXME: this test seems wrong. */
1069 (strncmp (mi->native_path, "\\\\.\\", 4) != 0 ||
1070 strncmp (mi->native_path + 4, "UNC\\", 4) == 0))
1072 strcpy (dst + n, p);
1074 backslashify (dst, dst, trailing_slash_p);
1079 /* Compute relative path if asked to and able to. */
1080 if (win32_path == NULL)
1081 /* nothing to do */;
1084 char cwd_win32[MAX_PATH];
1085 if (!cygcwd.get (cwd_win32, 0))
1086 return get_errno ();
1087 unsigned cwdlen = strlen (cwd_win32);
1088 if (!path_prefix_p (cwd_win32, dst, cwdlen))
1089 strcpy (win32_path, dst);
1092 size_t n = strlen (dst);
1094 strcpy (win32_path, dst);
1100 dst += isdirsep (cwd_win32[cwdlen - 1]) ? cwdlen : cwdlen + 1;
1102 memmove (win32_path, dst, strlen (dst) + 1);
1105 strcpy (win32_path, ".");
1106 if (trailing_slash_p)
1107 strcat (win32_path, "\\");
1112 else if (win32_path != dst)
1113 strcpy (win32_path, dst);
1117 debug_printf ("%s(rel), %s(abs) %p(flags) = conv_to_win32_path (%s)",
1118 win32_path, full_win32_path, *flags,
1123 /* Convert PATH (for which slash_drive_prefix_p returns 1) to WIN32 form. */
1126 mount_info::slash_drive_to_win32_path (const char *path, char *buf,
1127 int trailing_slash_p)
1132 strcpy (buf + 2, "\\");
1134 backslashify (path + 3, buf + 2, trailing_slash_p);
1137 /* cygdrive_posix_path: Build POSIX path used as the
1138 mount point for cygdrives created when there is no other way to
1139 obtain a POSIX path from a Win32 one. */
1142 mount_info::cygdrive_posix_path (const char *src, char *dst, int trailing_slash_p)
1144 int len = cygdrive_len;
1146 memcpy (dst, cygdrive, len + 1);
1148 /* Now finish the path off with the drive letter to be used.
1149 The cygdrive prefix always ends with a trailing slash so
1150 the drive letter is added after the path. */
1151 dst[len++] = tolower (src[0]);
1152 if (!src[2] || (SLASH_P (src[2]) && !src[3]))
1153 dst[len++] = '\000';
1158 if (SLASH_P (src[2]))
1162 strcpy (dst + len, src + n);
1164 slashify (dst, dst, trailing_slash_p);
1168 mount_info::cygdrive_win32_path (const char *src, char *dst, int trailing_slash_p)
1170 const char *p = src + cygdrive_len;
1171 if (!isalpha (*p) || (!isdirsep (p[1]) && p[1]))
1175 strcpy (dst + 2, p + 1);
1176 backslashify (dst, dst, trailing_slash_p || !dst[2]);
1177 debug_printf ("src '%s', dst '%s'", src, dst);
1181 /* conv_to_posix_path: Ensure src_path is a POSIX path.
1183 The result is zero for success, or an errno value.
1184 posix_path must have sufficient space (i.e. MAX_PATH bytes).
1185 If keep_rel_p is non-zero, relative paths stay that way. */
1188 mount_info::conv_to_posix_path (const char *src_path, char *posix_path,
1191 int src_path_len = strlen (src_path);
1192 int relative_path_p = !isabspath (src_path);
1193 int trailing_slash_p;
1195 if (src_path_len <= 1)
1196 trailing_slash_p = 0;
1199 const char *lastchar = src_path + src_path_len - 1;
1200 trailing_slash_p = SLASH_P (*lastchar) && lastchar[-1] != ':';
1203 debug_printf ("conv_to_posix_path (%s, %s, %s)", src_path,
1204 keep_rel_p ? "keep-rel" : "no-keep-rel",
1205 trailing_slash_p ? "add-slash" : "no-add-slash");
1208 if (src_path_len >= MAX_PATH)
1210 debug_printf ("ENAMETOOLONG");
1211 return ENAMETOOLONG;
1214 /* FIXME: For now, if the path is relative and it's supposed to stay
1215 that way, skip mount table processing. */
1217 if (keep_rel_p && relative_path_p)
1219 slashify (src_path, posix_path, 0);
1220 debug_printf ("%s = conv_to_posix_path (%s)", posix_path, src_path);
1224 char pathbuf[MAX_PATH];
1225 int rc = normalize_win32_path (src_path, pathbuf);
1228 debug_printf ("%d = conv_to_posix_path (%s)", rc, src_path);
1232 int pathbuflen = strlen (pathbuf);
1233 for (int i = 0; i < nmounts; ++i)
1235 mount_item &mi = mount[native_sorted[i]];
1236 if (! path_prefix_p (mi.native_path, pathbuf, mi.native_pathlen))
1239 /* SRC_PATH is in the mount table. */
1241 const char *p = pathbuf + mi.native_pathlen;
1245 else if (isdirsep (*p))
1250 int addslash = nextchar > 0 ? 1 : 0;
1251 if ((mi.posix_pathlen + (pathbuflen - mi.native_pathlen) + addslash) >= MAX_PATH)
1252 return ENAMETOOLONG;
1253 strcpy (posix_path, mi.posix_path);
1255 strcat (posix_path, "/");
1258 posix_path + addslash + (mi.posix_pathlen == 1 ? 0 : mi.posix_pathlen),
1263 /* Not in the database. This should [theoretically] only happen if either
1264 the path begins with //, or / isn't mounted, or the path has a drive
1265 letter not covered by the mount table. If it's a relative path then the
1266 caller must want an absolute path (otherwise we would have returned
1267 above). So we always return an absolute path at this point. */
1268 if (isdrive (pathbuf))
1269 cygdrive_posix_path (pathbuf, posix_path, trailing_slash_p);
1272 /* The use of src_path and not pathbuf here is intentional.
1273 We couldn't translate the path, so just ensure no \'s are present. */
1274 slashify (src_path, posix_path, trailing_slash_p);
1278 debug_printf ("%s = conv_to_posix_path (%s)", posix_path, src_path);
1283 /* Return flags associated with a mount point given the win32 path. */
1286 mount_info::set_flags_from_win32_path (const char *p)
1288 for (int i = 0; i < nmounts; i++)
1290 mount_item &mi = mount[native_sorted[i]];
1291 if (path_prefix_p (mi.native_path, p, mi.native_pathlen))
1297 /* read_mounts: Given a specific regkey, read mounts from under its
1301 mount_info::read_mounts (reg_key& r)
1303 char posix_path[MAX_PATH];
1304 HKEY key = r.get_key ();
1305 DWORD i, posix_path_size;
1308 /* Loop through subkeys */
1309 /* FIXME: we would like to not check MAX_MOUNTS but the heap in the
1310 shared area is currently statically allocated so we can't have an
1311 arbitrarily large number of mounts. */
1314 char native_path[MAX_PATH];
1317 posix_path_size = MAX_PATH;
1318 /* FIXME: if maximum posix_path_size is 256, we're going to
1319 run into problems if we ever try to store a mount point that's
1320 over 256 but is under MAX_PATH! */
1321 res = RegEnumKeyEx (key, i, posix_path, &posix_path_size, NULL,
1324 if (res == ERROR_NO_MORE_ITEMS)
1326 else if (res != ERROR_SUCCESS)
1328 debug_printf ("RegEnumKeyEx failed, error %d!\n", res);
1332 /* Get a reg_key based on i. */
1333 reg_key subkey = reg_key (key, KEY_READ, posix_path, NULL);
1335 /* Fetch info from the subkey. */
1336 subkey.get_string ("native", native_path, sizeof (native_path), "");
1337 mount_flags = subkey.get_int ("flags", 0);
1339 /* Add mount_item corresponding to registry mount point. */
1340 res = cygwin_shared->mount.add_item (native_path, posix_path, mount_flags, FALSE);
1341 if (res && get_errno () == EMFILE)
1342 break; /* The number of entries exceeds MAX_MOUNTS */
1346 /* from_registry: Build the entire mount table from the registry. Also,
1347 read in cygdrive-related information from its registry location. */
1350 mount_info::from_registry ()
1352 /* Use current mount areas if either user or system mount areas
1353 already exist. Otherwise, import old mounts. */
1357 /* Retrieve cygdrive-related information. */
1358 read_cygdrive_info_from_registry ();
1362 /* First read mounts from user's table. */
1365 /* Then read mounts from system-wide mount table. */
1366 reg_key r1 (HKEY_LOCAL_MACHINE, KEY_READ, "SOFTWARE",
1367 CYGWIN_INFO_CYGNUS_REGISTRY_NAME,
1368 CYGWIN_INFO_CYGWIN_REGISTRY_NAME,
1369 CYGWIN_INFO_CYGWIN_MOUNT_REGISTRY_NAME,
1373 /* If we had to create both user and system mount areas, import
1375 if (had_to_create_mount_areas == 2)
1376 import_v1_mounts ();
1379 /* add_reg_mount: Add mount item to registry. Return zero on success,
1380 non-zero on failure. */
1381 /* FIXME: Need a mutex to avoid collisions with other tasks. */
1384 mount_info::add_reg_mount (const char * native_path, const char * posix_path, unsigned mountflags)
1388 /* Add the mount to the right registry location, depending on
1389 whether MOUNT_SYSTEM is set in the mount flags. */
1390 if (!(mountflags & MOUNT_SYSTEM)) /* current_user mount */
1392 /* reg_key for user mounts in HKEY_CURRENT_USER. */
1395 /* Start by deleting existing mount if one exists. */
1396 res = reg_user.kill (posix_path);
1397 if (res != ERROR_SUCCESS && res != ERROR_FILE_NOT_FOUND)
1400 /* Create the new mount. */
1401 reg_key subkey = reg_key (reg_user.get_key (),
1404 res = subkey.set_string ("native", native_path);
1405 if (res != ERROR_SUCCESS)
1407 res = subkey.set_int ("flags", mountflags);
1409 else /* local_machine mount */
1411 /* reg_key for system mounts in HKEY_LOCAL_MACHINE. */
1412 reg_key reg_sys (HKEY_LOCAL_MACHINE, KEY_ALL_ACCESS, "SOFTWARE",
1413 CYGWIN_INFO_CYGNUS_REGISTRY_NAME,
1414 CYGWIN_INFO_CYGWIN_REGISTRY_NAME,
1415 CYGWIN_INFO_CYGWIN_MOUNT_REGISTRY_NAME,
1418 /* Start by deleting existing mount if one exists. */
1419 res = reg_sys.kill (posix_path);
1420 if (res != ERROR_SUCCESS && res != ERROR_FILE_NOT_FOUND)
1423 /* Create the new mount. */
1424 reg_key subkey = reg_key (reg_sys.get_key (),
1427 res = subkey.set_string ("native", native_path);
1428 if (res != ERROR_SUCCESS)
1430 res = subkey.set_int ("flags", mountflags);
1433 return 0; /* Success! */
1435 __seterrno_from_win_error (res);
1439 /* del_reg_mount: delete mount item from registry indicated in flags.
1440 Return zero on success, non-zero on failure.*/
1441 /* FIXME: Need a mutex to avoid collisions with other tasks. */
1444 mount_info::del_reg_mount (const char * posix_path, unsigned flags)
1448 if ((flags & MOUNT_SYSTEM) == 0) /* Delete from user registry */
1450 reg_key reg_user (KEY_ALL_ACCESS,
1451 CYGWIN_INFO_CYGWIN_MOUNT_REGISTRY_NAME, NULL);
1452 res = reg_user.kill (posix_path);
1454 else /* Delete from system registry */
1456 reg_key reg_sys (HKEY_LOCAL_MACHINE, KEY_ALL_ACCESS, "SOFTWARE",
1457 CYGWIN_INFO_CYGNUS_REGISTRY_NAME,
1458 CYGWIN_INFO_CYGWIN_REGISTRY_NAME,
1459 CYGWIN_INFO_CYGWIN_MOUNT_REGISTRY_NAME,
1461 res = reg_sys.kill (posix_path);
1464 if (res != ERROR_SUCCESS)
1466 __seterrno_from_win_error (res);
1470 return 0; /* Success! */
1473 /* read_cygdrive_info_from_registry: Read the default prefix and flags
1474 to use when creating cygdrives from the special user registry
1475 location used to store cygdrive information. */
1478 mount_info::read_cygdrive_info_from_registry ()
1480 /* reg_key for user path prefix in HKEY_CURRENT_USER. */
1483 if (r.get_string ("cygdrive prefix", cygdrive, sizeof (cygdrive), "") != 0)
1485 /* Didn't find the user path prefix so check the system path prefix. */
1487 /* reg_key for system path prefix in HKEY_LOCAL_MACHINE. */
1488 reg_key r2 (HKEY_LOCAL_MACHINE, KEY_ALL_ACCESS, "SOFTWARE",
1489 CYGWIN_INFO_CYGNUS_REGISTRY_NAME,
1490 CYGWIN_INFO_CYGWIN_REGISTRY_NAME,
1491 CYGWIN_INFO_CYGWIN_MOUNT_REGISTRY_NAME,
1494 if (r2.get_string ("cygdrive prefix", cygdrive, sizeof (cygdrive), "") != 0)
1496 /* Didn't find either so write the default to the registry and use it.
1497 NOTE: We are writing and using the user path prefix. */
1498 write_cygdrive_info_to_registry ("/cygdrive", MOUNT_AUTO);
1502 /* Fetch system cygdrive_flags from registry; returns MOUNT_AUTO on
1504 cygdrive_flags = r2.get_int ("cygdrive flags", MOUNT_AUTO);
1505 slashify (cygdrive, cygdrive, 1);
1506 cygdrive_len = strlen(cygdrive);
1511 /* Fetch user cygdrive_flags from registry; returns MOUNT_AUTO on
1513 cygdrive_flags = r.get_int ("cygdrive flags", MOUNT_AUTO);
1514 slashify (cygdrive, cygdrive, 1);
1515 cygdrive_len = strlen(cygdrive);
1519 /* write_cygdrive_info_to_registry: Write the default prefix and flags
1520 to use when creating cygdrives to the special user registry
1521 location used to store cygdrive information. */
1524 mount_info::write_cygdrive_info_to_registry (const char *cygdrive_prefix, unsigned flags)
1526 /* Determine whether to modify user or system cygdrive path prefix. */
1527 HKEY top = (flags & MOUNT_SYSTEM) ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
1529 /* reg_key for user path prefix in HKEY_CURRENT_USER or system path prefix in
1530 HKEY_LOCAL_MACHINE. */
1531 reg_key r (top, KEY_ALL_ACCESS, "SOFTWARE",
1532 CYGWIN_INFO_CYGNUS_REGISTRY_NAME,
1533 CYGWIN_INFO_CYGWIN_REGISTRY_NAME,
1534 CYGWIN_INFO_CYGWIN_MOUNT_REGISTRY_NAME,
1537 /* Verify cygdrive prefix starts with a forward slash and if there's
1538 another character, it's not a slash. */
1539 if ((cygdrive_prefix == NULL) || (*cygdrive_prefix == 0) ||
1540 (!isslash (cygdrive_prefix[0])) ||
1541 ((cygdrive_prefix[1] != '\0') && (isslash (cygdrive_prefix[1]))))
1547 char hold_cygdrive_prefix[strlen (cygdrive_prefix) + 1];
1548 /* Ensure that there is never a final slash */
1549 nofinalslash (cygdrive_prefix, hold_cygdrive_prefix);
1552 res = r.set_string ("cygdrive prefix", hold_cygdrive_prefix);
1553 if (res != ERROR_SUCCESS)
1555 __seterrno_from_win_error (res);
1558 r.set_int ("cygdrive flags", flags);
1560 /* This also needs to go in the in-memory copy of "cygdrive", but only if
1562 1. setting user path prefix, or
1563 2. overwriting (a previous) system path prefix */
1564 if ((flags & MOUNT_SYSTEM) == 0 ||
1565 (cygwin_shared->mount.cygdrive_flags & MOUNT_SYSTEM) != 0)
1567 slashify (cygdrive_prefix, cygwin_shared->mount.cygdrive, 1);
1568 cygwin_shared->mount.cygdrive_flags = flags;
1569 cygwin_shared->mount.cygdrive_len = strlen(cygwin_shared->mount.cygdrive);
1576 mount_info::remove_cygdrive_info_from_registry (const char *cygdrive_prefix, unsigned flags)
1578 /* Determine whether to modify user or system cygdrive path prefix. */
1579 HKEY top = (flags & MOUNT_SYSTEM) ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
1581 /* reg_key for user path prefix in HKEY_CURRENT_USER or system path prefix in
1582 HKEY_LOCAL_MACHINE. */
1583 reg_key r (top, KEY_ALL_ACCESS, "SOFTWARE",
1584 CYGWIN_INFO_CYGNUS_REGISTRY_NAME,
1585 CYGWIN_INFO_CYGWIN_REGISTRY_NAME,
1586 CYGWIN_INFO_CYGWIN_MOUNT_REGISTRY_NAME,
1589 /* Delete cygdrive prefix and flags. */
1590 int res = r.killvalue ("cygdrive prefix");
1591 int res2 = r.killvalue ("cygdrive flags");
1593 /* Reinitialize the cygdrive path prefix to reflect to removal from the
1595 read_cygdrive_info_from_registry ();
1597 return (res != ERROR_SUCCESS) ? res : res2;
1601 mount_info::get_cygdrive_prefixes (char *user, char *system)
1603 /* Get the user path prefix from HKEY_CURRENT_USER. */
1605 int res = r.get_string ("cygdrive prefix", user, MAX_PATH, "");
1607 /* Get the system path prefix from HKEY_LOCAL_MACHINE. */
1608 reg_key r2 (HKEY_LOCAL_MACHINE, KEY_ALL_ACCESS, "SOFTWARE",
1609 CYGWIN_INFO_CYGNUS_REGISTRY_NAME,
1610 CYGWIN_INFO_CYGWIN_REGISTRY_NAME,
1611 CYGWIN_INFO_CYGWIN_MOUNT_REGISTRY_NAME,
1613 int res2 = r2.get_string ("cygdrive prefix", system, MAX_PATH, "");
1615 return (res != ERROR_SUCCESS) ? res : res2;
1619 mount_info::getmntent (int x)
1621 if (x < 0 || x >= nmounts)
1624 return mount[native_sorted[x]].getmntent ();
1627 static mount_item *mounts_for_sort;
1629 /* sort_by_posix_name: qsort callback to sort the mount entries. Sort
1630 user mounts ahead of system mounts to the same POSIX path. */
1631 /* FIXME: should the user should be able to choose whether to
1632 prefer user or system mounts??? */
1634 sort_by_posix_name (const void *a, const void *b)
1636 mount_item *ap = mounts_for_sort + (*((int*) a));
1637 mount_item *bp = mounts_for_sort + (*((int*) b));
1639 /* Base weighting on longest posix path first so that the most
1640 obvious path will be chosen. */
1641 size_t alen = strlen (ap->posix_path);
1642 size_t blen = strlen (bp->posix_path);
1644 int res = blen - alen;
1647 return res; /* Path lengths differed */
1649 /* The two paths were the same length, so just determine normal
1650 lexical sorted order. */
1651 res = strcmp (ap->posix_path, bp->posix_path);
1655 /* need to select between user and system mount to same POSIX path */
1656 if ((bp->flags & MOUNT_SYSTEM) == 0) /* user mount */
1665 /* sort_by_native_name: qsort callback to sort the mount entries. Sort
1666 user mounts ahead of system mounts to the same POSIX path. */
1667 /* FIXME: should the user should be able to choose whether to
1668 prefer user or system mounts??? */
1670 sort_by_native_name (const void *a, const void *b)
1672 mount_item *ap = mounts_for_sort + (*((int*) a));
1673 mount_item *bp = mounts_for_sort + (*((int*) b));
1675 /* Base weighting on longest win32 path first so that the most
1676 obvious path will be chosen. */
1677 size_t alen = strlen (ap->native_path);
1678 size_t blen = strlen (bp->native_path);
1680 int res = blen - alen;
1683 return res; /* Path lengths differed */
1685 /* The two paths were the same length, so just determine normal
1686 lexical sorted order. */
1687 res = strcmp (ap->native_path, bp->native_path);
1691 /* need to select between user and system mount to same POSIX path */
1692 if ((bp->flags & MOUNT_SYSTEM) == 0) /* user mount */
1704 for (int i = 0; i < nmounts; i++)
1705 native_sorted[i] = posix_sorted[i] = i;
1706 /* Sort them into reverse length order, otherwise we won't
1707 be able to look for /foo in /. */
1708 mounts_for_sort = mount; /* ouch. */
1709 qsort (posix_sorted, nmounts, sizeof (posix_sorted[0]), sort_by_posix_name);
1710 qsort (native_sorted, nmounts, sizeof (native_sorted[0]), sort_by_native_name);
1713 /* Add an entry to the mount table.
1714 Returns 0 on success, -1 on failure and errno is set.
1716 This is where all argument validation is done. It may not make sense to
1717 do this when called internally, but it's cleaner to keep it all here. */
1720 mount_info::add_item (const char *native, const char *posix, unsigned mountflags, int reg_p)
1722 /* Something's wrong if either path is NULL or empty, or if it's
1723 not a UNC or absolute path. */
1725 if ((native == NULL) || (*native == 0) ||
1726 (posix == NULL) || (*posix == 0) ||
1727 !isabspath (native) || !isabspath (posix) ||
1728 slash_unc_prefix_p (posix) || isdrive (posix))
1734 /* Make sure both paths do not end in /. */
1735 char nativetmp[MAX_PATH];
1736 char posixtmp[MAX_PATH];
1738 if (slash_drive_prefix_p (native))
1739 slash_drive_to_win32_path (native, nativetmp, 0);
1741 backslashify (native, nativetmp, 0);
1742 nofinalslash (nativetmp, nativetmp);
1744 slashify (posix, posixtmp, 0);
1745 nofinalslash (posixtmp, posixtmp);
1747 debug_printf ("%s[%s], %s[%s], %p",
1748 native, nativetmp, posix, posixtmp, mountflags);
1750 /* Duplicate /'s in path are an error. */
1751 for (char *p = posixtmp + 1; *p; ++p)
1753 if (p[-1] == '/' && p[0] == '/')
1760 /* Write over an existing mount item with the same POSIX path if
1761 it exists and is from the same registry area. */
1763 for (i = 0; i < nmounts; i++)
1765 if (strcasematch (mount[i].posix_path, posixtmp) &&
1766 (mount[i].flags & MOUNT_SYSTEM) == (mountflags & MOUNT_SYSTEM))
1770 if (i == nmounts && nmounts == MAX_MOUNTS)
1776 if (reg_p && add_reg_mount (nativetmp, posixtmp, mountflags))
1781 mount[i].init (nativetmp, posixtmp, mountflags);
1787 /* Delete a mount table entry where path is either a Win32 or POSIX
1788 path. Since the mount table is really just a table of aliases,
1789 deleting / is ok (although running without a slash mount is
1790 strongly discouraged because some programs may run erratically
1791 without one). If MOUNT_SYSTEM is set in flags, remove from system
1792 registry, otherwise remove the user registry mount.
1796 mount_info::del_item (const char *path, unsigned flags, int reg_p)
1798 char pathtmp[MAX_PATH];
1799 int posix_path_p = FALSE;
1801 /* Something's wrong if path is NULL or empty. */
1802 if (path == NULL || *path == 0 || !isabspath (path))
1808 if (slash_drive_prefix_p (path))
1809 slash_drive_to_win32_path (path, pathtmp, 0);
1810 else if (slash_unc_prefix_p (path) || strpbrk (path, ":\\"))
1811 backslashify (path, pathtmp, 0);
1814 slashify (path, pathtmp, 0);
1815 posix_path_p = TRUE;
1817 nofinalslash (pathtmp, pathtmp);
1819 if (reg_p && posix_path_p &&
1820 del_reg_mount (pathtmp, flags) &&
1821 del_reg_mount (path, flags)) /* for old irregular entries */
1824 for (int i = 0; i < nmounts; i++)
1826 int ent = native_sorted[i]; /* in the same order as getmntent() */
1828 ? strcasematch (mount[ent].posix_path, pathtmp)
1829 : strcasematch (mount[ent].native_path, pathtmp)) &&
1830 (mount[ent].flags & MOUNT_SYSTEM) == (flags & MOUNT_SYSTEM))
1832 if (!posix_path_p &&
1833 reg_p && del_reg_mount (mount[ent].posix_path, flags))
1836 nmounts--; /* One less mount table entry */
1837 /* Fill in the hole if not at the end of the table */
1839 memmove (mount + ent, mount + ent + 1,
1840 sizeof (mount[ent]) * (nmounts - ent));
1841 sort (); /* Resort the table */
1849 /* read_v1_mounts: Given a reg_key to an old mount table registry area,
1850 read in the mounts. The "which" arg contains zero if we're reading
1851 the user area and MOUNT_SYSTEM if we're reading the system area.
1852 This way we can store the mounts read in the appropriate place when
1853 they are written back to the new registry layout. */
1856 mount_info::read_v1_mounts (reg_key r, unsigned which)
1858 unsigned mountflags = 0;
1860 /* MAX_MOUNTS was 30 when we stopped using the v1 layout */
1861 for (int i = 0; i < 30; i++)
1864 char win32path[MAX_PATH];
1865 char unixpath[MAX_PATH];
1867 __small_sprintf (key_name, "%02x", i);
1869 reg_key k (r.get_key (), KEY_ALL_ACCESS, key_name, NULL);
1871 /* The registry names are historical but useful so are left alone. */
1872 k.get_string ("native", win32path, sizeof (win32path), "");
1873 k.get_string ("unix", unixpath, sizeof (unixpath), "");
1875 /* Does this entry contain something? */
1876 if (*win32path != 0)
1880 if (k.get_int ("fbinary", 0))
1881 mountflags |= MOUNT_BINARY;
1883 /* Or in zero or MOUNT_SYSTEM depending on which table
1885 mountflags |= which;
1887 int res = cygwin_shared->mount.add_item (win32path, unixpath, mountflags, TRUE);
1888 if (res && get_errno () == EMFILE)
1889 break; /* The number of entries exceeds MAX_MOUNTS */
1894 /* import_v1_mounts: If v1 mounts are present, load them and write
1895 the new entries to the new registry area. */
1898 mount_info::import_v1_mounts ()
1900 reg_key r (HKEY_CURRENT_USER, KEY_ALL_ACCESS,
1910 /* First read mounts from user's table. */
1911 read_v1_mounts (r, 0);
1913 /* Then read mounts from system-wide mount table. */
1914 reg_key r1 (HKEY_LOCAL_MACHINE, KEY_ALL_ACCESS,
1921 read_v1_mounts (r1, MOUNT_SYSTEM);
1924 /************************* mount_item class ****************************/
1927 mount_item::getmntent ()
1930 struct mntent &ret=_reent_winsup()->_ret;
1932 static NO_COPY struct mntent ret;
1935 /* Pass back pointers to mount_info strings reserved for use by
1936 getmntent rather than pointers to strings in the internal mount
1937 table because the mount table might change, causing weird effects
1938 from the getmntent user's point of view. */
1940 strcpy (cygwin_shared->mount.mnt_fsname, native_path);
1941 ret.mnt_fsname = cygwin_shared->mount.mnt_fsname;
1942 strcpy (cygwin_shared->mount.mnt_dir, posix_path);
1943 ret.mnt_dir = cygwin_shared->mount.mnt_dir;
1945 if (!(flags & MOUNT_SYSTEM)) /* user mount */
1946 strcpy (cygwin_shared->mount.mnt_type, (char *) "user");
1947 else /* system mount */
1948 strcpy (cygwin_shared->mount.mnt_type, (char *) "system");
1950 if ((flags & MOUNT_AUTO)) /* cygdrive */
1951 strcat (cygwin_shared->mount.mnt_type, (char *) ",auto");
1953 ret.mnt_type = cygwin_shared->mount.mnt_type;
1955 /* mnt_opts is a string that details mount params such as
1956 binary or textmode, or exec. We don't print
1957 `silent' here; it's a magic internal thing. */
1959 if (! (flags & MOUNT_BINARY))
1960 strcpy (cygwin_shared->mount.mnt_opts, (char *) "textmode");
1962 strcpy (cygwin_shared->mount.mnt_opts, (char *) "binmode");
1964 if (flags & MOUNT_CYGWIN_EXEC)
1965 strcat (cygwin_shared->mount.mnt_opts, (char *) ",cygexec");
1966 else if (flags & MOUNT_EXEC)
1967 strcat (cygwin_shared->mount.mnt_opts, (char *) ",exec");
1970 ret.mnt_opts = cygwin_shared->mount.mnt_opts;
1977 /* Fill in the fields of a mount table entry. */
1980 mount_item::init (const char *native, const char *posix, unsigned mountflags)
1982 strcpy ((char *) native_path, native);
1983 strcpy ((char *) posix_path, posix);
1985 native_pathlen = strlen (native_path);
1986 posix_pathlen = strlen (posix_path);
1991 /********************** Mount System Calls **************************/
1993 /* Mount table system calls.
1994 Note that these are exported to the application. */
1996 /* mount: Add a mount to the mount table in memory and to the registry
1997 that will cause paths under win32_path to be translated to paths
1998 under posix_path. */
2002 mount (const char *win32_path, const char *posix_path, unsigned flags)
2006 if (flags & MOUNT_AUTO) /* normal mount */
2008 /* When flags include MOUNT_AUTO, take this to mean that
2009 we actually want to change the cygdrive prefix and flags
2010 without actually mounting anything. */
2011 res = cygwin_shared->mount.write_cygdrive_info_to_registry (posix_path, flags);
2015 res = cygwin_shared->mount.add_item (win32_path, posix_path, flags, TRUE);
2017 syscall_printf ("%d = mount (%s, %s, %p)", res, win32_path, posix_path, flags);
2021 /* umount: The standard umount call only has a path parameter. Since
2022 it is not possible for this call to specify whether to remove the
2023 mount from the user or global mount registry table, assume the user
2028 umount (const char *path)
2030 return cygwin_umount (path, 0);
2033 /* cygwin_umount: This is like umount but takes an additional flags
2034 parameter that specifies whether to umount from the user or system-wide
2039 cygwin_umount (const char *path, unsigned flags)
2043 if (flags & MOUNT_AUTO)
2045 /* When flags include MOUNT_AUTO, take this to mean that we actually want
2046 to remove the cygdrive prefix and flags without actually unmounting
2048 res = cygwin_shared->mount.remove_cygdrive_info_from_registry (path, flags);
2052 res = cygwin_shared->mount.del_item (path, flags, TRUE);
2055 syscall_printf ("%d = cygwin_umount (%s, %d)", res, path, flags);
2060 #define iteration _reent_winsup()->_iteration
2062 static int iteration;
2067 setmntent (const char *filep, const char *)
2070 return (FILE *) filep;
2077 return cygwin_shared->mount.getmntent (iteration++);
2087 /********************** Symbolic Link Support **************************/
2089 /* Create a symlink from FROMPATH to TOPATH. */
2093 symlink (const char *topath, const char *frompath)
2098 path_conv win32_path (frompath, PC_SYM_NOFOLLOW);
2099 if (win32_path.error)
2101 set_errno (win32_path.error);
2105 syscall_printf ("symlink (%s, %s)", topath, win32_path.get_win32 ());
2112 if (strlen (topath) >= MAX_PATH)
2114 set_errno (ENAMETOOLONG);
2118 if (win32_path.is_device () ||
2119 win32_path.file_attributes () != (DWORD) -1)
2125 h = CreateFileA(win32_path, GENERIC_WRITE, 0, &sec_none_nih,
2126 CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0);
2127 if (h == INVALID_HANDLE_VALUE)
2131 char buf[sizeof (SYMLINK_COOKIE) + MAX_PATH + 10];
2133 __small_sprintf (buf, "%s%s", SYMLINK_COOKIE, topath);
2134 DWORD len = strlen (buf) + 1;
2136 /* Note that the terminating nul is written. */
2138 if (!WriteFile (h, buf, len, &written, NULL) || written != len)
2142 DeleteFileA (win32_path.get_win32 ());
2147 set_file_attribute (win32_path.has_acls (),
2148 win32_path.get_win32 (),
2149 S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO);
2150 SetFileAttributesA (win32_path.get_win32 (), FILE_ATTRIBUTE_SYSTEM);
2156 syscall_printf ("%d = symlink (%s, %s)", res, topath, frompath);
2160 static __inline char *
2161 has_suffix (const char *path, const suffix_info *suffixes)
2164 char *ext = strrchr (path, '.');
2166 for (const suffix_info *ex = suffixes; ex->name != NULL; ex++)
2167 if (strcasematch (ext, ex->name))
2172 static __inline__ int
2173 next_suffix (char *ext_here, const suffix_info *&suffixes)
2178 while (suffixes && suffixes->name)
2179 if (!suffixes->addon)
2183 strcpy (ext_here, suffixes->name);
2190 /* Check if PATH is a symlink. PATH must be a valid Win32 path name.
2192 If PATH is a symlink, put the value of the symlink--the file to
2193 which it points--into BUF. The value stored in BUF is not
2194 necessarily null terminated. BUFLEN is the length of BUF; only up
2195 to BUFLEN characters will be stored in BUF. BUF may be NULL, in
2196 which case nothing will be stored.
2198 Set *SYML if PATH is a symlink.
2200 Set *EXEC if PATH appears to be executable. This is an efficiency
2201 hack because we sometimes have to open the file anyhow. *EXEC will
2202 not be set for every executable file.
2204 Return -1 on error, 0 if PATH is not a symlink, or the length
2205 stored into BUF if PATH is a symlink. */
2208 symlink_info::check (const char *in_path, const suffix_info *suffixes)
2212 char extbuf[MAX_PATH + 5];
2213 const char *path = in_path;
2217 else if ((known_suffix = has_suffix (in_path, suffixes)) != NULL)
2224 path = strcpy (extbuf, in_path);
2225 ext_here = strchr (path, '\0');
2233 if (!next_suffix (ext_here, suffixes))
2236 fileattr = GetFileAttributesA (path);
2237 if (fileattr == (DWORD) -1)
2239 /* The GetFileAttributesA call can fail for reasons that don't
2240 matter, so we just return 0. For example, getting the
2241 attributes of \\HOST will typically fail. */
2242 debug_printf ("GetFileAttributesA (%s) failed", path);
2243 error = geterrno_from_win_error (GetLastError (), EACCES);
2247 /* A symlink will have the `system' file attribute. */
2248 /* Only files can be symlinks (which can be symlinks to directories). */
2249 if (!(pflags & PATH_SYMLINK) && !SYMLINKATTR (fileattr))
2250 goto file_not_symlink;
2252 /* Open the file. */
2254 h = CreateFileA (path, GENERIC_READ, FILE_SHARE_READ, &sec_none_nih, OPEN_EXISTING,
2255 FILE_ATTRIBUTE_NORMAL, 0);
2257 if (h == INVALID_HANDLE_VALUE)
2258 goto file_not_symlink;
2261 char cookie_buf[sizeof (SYMLINK_COOKIE) - 1];
2264 if (! ReadFile (h, cookie_buf, sizeof (cookie_buf), &got, 0))
2266 else if (got == sizeof (cookie_buf)
2267 && memcmp (cookie_buf, SYMLINK_COOKIE,
2268 sizeof (cookie_buf)) == 0)
2270 /* It's a symlink. */
2271 pflags = PATH_SYMLINK;
2273 res = ReadFile (h, contents, MAX_PATH + 1, &got, 0);
2278 /* Versions prior to b16 stored several trailing
2279 NULs with the path (to fill the path out to 1024
2280 chars). Current versions only store one trailing
2281 NUL. The length returned is the path without
2282 *any* trailing NULs. We also have to handle (or
2283 at least not die from) corrupted paths. */
2284 if (memchr (contents, 0, got) != NULL)
2285 res = strlen (contents);
2290 else if (got == sizeof (cookie_buf)
2291 && memcmp (cookie_buf, SOCKET_COOKIE,
2292 sizeof (cookie_buf)) == 0)
2294 pflags |= PATH_SOCKET;
2295 goto close_and_return;
2299 /* Not a symlink, see if executable. */
2300 if (!(pflags & PATH_ALL_EXEC) && got >= 2 &&
2301 ((cookie_buf[0] == '#' && cookie_buf[1] == '!') ||
2302 (cookie_buf[0] == ':' && cookie_buf[1] == '\n') ||
2303 (cookie_buf[0] == 'M' && cookie_buf[1] == 'Z')))
2304 pflags |= PATH_EXEC;
2307 goto file_not_symlink;
2319 syscall_printf ("not a symlink");
2323 syscall_printf ("%d = symlink.check (%s, %p) (%p)",
2324 res, path, contents, pflags);
2329 /* readlink system call */
2333 readlink (const char *path, char *buf, int buflen)
2335 extern suffix_info stat_suffixes[];
2339 set_errno (ENAMETOOLONG);
2343 path_conv pathbuf (path, PC_SYM_CONTENTS, stat_suffixes);
2347 set_errno (pathbuf.error);
2348 syscall_printf ("-1 = readlink (%s, %p, %d)", path, buf, buflen);
2352 if (!pathbuf.issymlink ())
2354 if (pathbuf.fileattr != (DWORD) -1)
2359 int len = min (buflen, (int) strlen (pathbuf.get_win32 ()));
2360 memcpy (buf, pathbuf.get_win32 (), len);
2362 /* errno set by symlink.check if error */
2366 /* Some programs rely on st_dev/st_ino being unique for each file.
2367 Hash the path name and hope for the best. The hash arg is not
2368 always initialized to zero since readdir needs to compute the
2369 dirent ino_t based on a combination of the hash of the directory
2370 done during the opendir call and the hash or the filename within
2371 the directory. FIXME: Not bullet-proof. */
2372 /* Cygwin internal */
2374 unsigned long __stdcall
2375 hash_path_name (unsigned long hash, const char *name)
2380 /* Perform some initial permutations on the pathname if this is
2384 /* Simplistic handling of drives. If there is a drive specified,
2385 make sure that the initial letter is upper case. If there is
2386 no \ after the ':' assume access through the root directory
2388 FIXME: Should really honor MS-Windows convention of using
2389 the environment to track current directory on various drives. */
2392 char *nn, *newname = (char *) alloca (strlen (name) + 2);
2393 nn = strncpy (newname, name, 2);
2395 *newname = tolower (*nn);
2408 /* Fill out the hashed path name with the current working directory if
2409 this is not an absolute path and there is no pre-specified hash value.
2410 Otherwise the inodes same will differ depending on whether a file is
2411 referenced with an absolute value or relatively. */
2413 if (!hash && !isabspath (name))
2415 hash = cygcwd.get_hash ();
2416 if (name[0] == '.' && name[1] == '\0')
2418 hash += hash_path_name (hash, "\\");
2423 /* Build up hash. Ignore single trailing slash or \a\b\ != \a\b or
2424 \a\b\. but allow a single \ if that's all there is. */
2427 int ch = tolower(*name);
2428 hash += ch + (ch << 17);
2431 while (*++name != '\0' &&
2432 !(*name == '\\' && (!name[1] || (name[1] == '.' && !name[2]))));
2437 getcwd (char *buf, size_t ulen)
2439 return cygcwd.get (buf, 1, 1, ulen);
2442 /* getwd: standards? */
2447 return getcwd (buf, MAX_PATH);
2450 /* chdir: POSIX 5.2.1.1 */
2453 chdir (const char *dir)
2456 syscall_printf ("dir %s", dir);
2457 path_conv path (dir, PC_FULL | PC_SYM_FOLLOW);
2461 set_errno (path.error);
2462 syscall_printf ("-1 = chdir (%s)", dir);
2466 /* Look for trailing path component consisting entirely of dots. This
2467 is needed only in case of chdir since Windows simply ignores count
2468 of dots > 2 here instead of returning an error code. Counts of dots
2469 <= 2 are already eliminated by normalize_posix_path. */
2470 const char *p = strrchr (dir, '/');
2476 size_t len = strlen (p);
2477 if (len > 2 && strspn (p, ".") == len)
2483 char *native_dir = path.get_win32 ();
2485 /* Check to see if path translates to something like C:.
2486 If it does, append a \ to the native directory specification to
2487 defeat the Windows 95 (i.e. MS-DOS) tendency of returning to
2488 the last directory visited on the given drive. */
2489 if (isdrive (native_dir) && !native_dir[2])
2491 native_dir[2] = '\\';
2492 native_dir[3] = '\0';
2494 int res = SetCurrentDirectoryA (native_dir) ? 0 : -1;
2498 cygcwd.set (path, dir);
2500 /* Note that we're accessing cwd.posix without a lock here. I didn't think
2501 it was worth locking just for strace. */
2502 syscall_printf ("%d = chdir() cygcwd.posix '%s' native '%s'", res,
2503 cygcwd.posix, native_dir);
2508 /******************** Exported Path Routines *********************/
2510 /* Cover functions to the path conversion routines.
2511 These are exported to the world as cygwin_foo by cygwin.din. */
2515 cygwin_conv_to_win32_path (const char *path, char *win32_path)
2517 path_conv p (path, PC_SYM_FOLLOW);
2520 set_errno (p.error);
2524 strcpy (win32_path, p.get_win32 ());
2530 cygwin_conv_to_full_win32_path (const char *path, char *win32_path)
2532 path_conv p (path, PC_SYM_FOLLOW | PC_FULL);
2535 set_errno (p.error);
2539 strcpy (win32_path, p.get_win32 ());
2543 /* This is exported to the world as cygwin_foo by cygwin.din. */
2547 cygwin_conv_to_posix_path (const char *path, char *posix_path)
2549 if (check_null_empty_path_errno (path))
2551 cygwin_shared->mount.conv_to_posix_path (path, posix_path, 1);
2557 cygwin_conv_to_full_posix_path (const char *path, char *posix_path)
2559 if (check_null_empty_path_errno (path))
2561 cygwin_shared->mount.conv_to_posix_path (path, posix_path, 0);
2565 /* The realpath function is supported on some UNIX systems. */
2569 realpath (const char *path, char *resolved)
2573 path_conv real_path (path, PC_SYM_FOLLOW | PC_FULL);
2575 if (real_path.error)
2576 err = real_path.error;
2579 err = cygwin_shared->mount.conv_to_posix_path (real_path.get_win32 (), resolved, 0);
2584 /* FIXME: on error, we are supposed to put the name of the path
2585 component which could not be resolved into RESOLVED. */
2592 /* Return non-zero if path is a POSIX path list.
2593 This is exported to the world as cygwin_foo by cygwin.din.
2596 <sect1 id="add-func-cygwin-posix-path-list-p">
2597 <para>Rather than use a mode to say what the "proper" path list
2598 format is, we allow any, and give apps the tools they need to
2599 convert between the two. If a ';' is present in the path list it's
2600 a Win32 path list. Otherwise, if the first path begins with
2601 [letter]: (in which case it can be the only element since if it
2602 wasn't a ';' would be present) it's a Win32 path list. Otherwise,
2603 it's a POSIX path list.</para>
2610 cygwin_posix_path_list_p (const char *path)
2612 int posix_p = ! (strchr (path, ';') || isdrive (path));
2616 /* These are used for apps that need to convert env vars like PATH back and
2617 forth. The conversion is a two step process. First, an upper bound on the
2618 size of the buffer needed is computed. Then the conversion is done. This
2619 allows the caller to use alloca if it wants. */
2622 conv_path_list_buf_size (const char *path_list, int to_posix_p)
2624 int i, num_elms, max_mount_path_len, size;
2627 /* The theory is that an upper bound is
2628 current_size + (num_elms * max_mount_path_len) */
2630 char delim = to_posix_p ? ';' : ':';
2632 for (num_elms = 1; (p = strchr (p, delim)) != NULL; ++num_elms)
2635 /* 7: strlen ("//c") + slop, a conservative initial value */
2636 for (max_mount_path_len = 7, i = 0; i < cygwin_shared->mount.nmounts; ++i)
2638 int mount_len = (to_posix_p
2639 ? cygwin_shared->mount.mount[i].posix_pathlen
2640 : cygwin_shared->mount.mount[i].native_pathlen);
2641 if (max_mount_path_len < mount_len)
2642 max_mount_path_len = mount_len;
2646 size = strlen (path_list) + (num_elms * max_mount_path_len) + 100;
2652 cygwin_win32_to_posix_path_list_buf_size (const char *path_list)
2654 return conv_path_list_buf_size (path_list, 1);
2659 cygwin_posix_to_win32_path_list_buf_size (const char *path_list)
2661 return conv_path_list_buf_size (path_list, 0);
2666 cygwin_win32_to_posix_path_list (const char *win32, char *posix)
2668 conv_path_list (win32, posix, 1);
2674 cygwin_posix_to_win32_path_list (const char *posix, char *win32)
2676 conv_path_list (posix, win32, 0);
2680 /* cygwin_split_path: Split a path into directory and file name parts.
2681 Buffers DIR and FILE are assumed to be big enough.
2683 Examples (path -> `dir' / `file'):
2686 . -> `.' / `.' (FIXME: should this be `.' / `'?)
2687 .. -> `.' / `..' (FIXME: should this be `..' / `'?)
2689 foo/bar -> `foo' / `bar'
2690 foo/bar/ -> `foo' / `bar'
2692 /foo/bar -> `/foo' / `bar'
2695 c:foo -> `c:/' / `foo'
2696 c:/foo -> `c:/' / `foo'
2701 cygwin_split_path (const char *path, char *dir, char *file)
2703 int dir_started_p = 0;
2705 /* Deal with drives.
2706 Remember that c:foo <==> c:/foo. */
2718 if (SLASH_P (*path))
2723 /* Determine if there are trailing slashes and "delete" them if present.
2724 We pretend as if they don't exist. */
2725 const char *end = path + strlen (path);
2726 /* path + 1: keep leading slash. */
2727 while (end > path + 1 && SLASH_P (end[-1]))
2730 /* At this point, END points to one beyond the last character
2731 (with trailing slashes "deleted"). */
2733 /* Point LAST_SLASH at the last slash (duh...). */
2734 const char *last_slash;
2735 for (last_slash = end - 1; last_slash >= path; --last_slash)
2736 if (SLASH_P (*last_slash))
2739 if (last_slash == path)
2744 else if (last_slash > path)
2746 memcpy (dir, path, last_slash - path);
2747 dir[last_slash - path] = 0;
2752 ; /* nothing to do */
2758 memcpy (file, last_slash + 1, end - last_slash - 1);
2759 file[end - last_slash - 1] = 0;
2762 /********************** String Helper Functions ************************/
2764 #define CHXOR ('a' ^ 'A')
2765 #define ch_case_eq(ch1, ch2) \
2768 !((x = ((unsigned char)ch1 ^ (unsigned char)ch2)) && \
2769 (x != CHXOR || !isalpha (ch1))); \
2772 /* Return TRUE if two strings match up to length n */
2773 extern "C" int __stdcall
2774 strncasematch (const char *s1, const char *s2, size_t n)
2782 if (!ch_case_eq (*s1, *s2))
2786 return !n || *s2 == '\0';
2789 /* Return TRUE if two strings match */
2790 extern "C" int __stdcall
2791 strcasematch (const char *s1, const char *s2)
2798 if (!ch_case_eq (*s1, *s2))
2805 extern "C" char * __stdcall
2806 strcasestr (const char *searchee, const char *lookfor)
2812 return (char *) searchee;
2820 if (lookfor[i] == 0)
2821 return (char *) searchee;
2823 if (!ch_case_eq (lookfor[i], searchee[i]))
2834 check_null_empty_path (const char *name)
2836 MEMORY_BASIC_INFORMATION m;
2837 if (!name || !VirtualQuery (name, &m, sizeof (m)) || (m.State != MEM_COMMIT))
2846 /* Return the hash value for the current win32 value.
2847 This is used when constructing inodes. */
2849 cwdstuff::get_hash ()
2858 /* Initialize cygcwd 'muto' for serializing access to cwd info. */
2862 lock = new_muto (FALSE, "cwd");
2865 /* Called to fill in cwd values after an exec. */
2867 cwdstuff::fixup_after_exec (char *win32_cwd, char *posix_cwd, DWORD hash_cwd)
2874 /* Get initial cwd. Should only be called once in a
2877 cwdstuff::get_initial ()
2886 for (i = 0, dlen = MAX_PATH, len = 0; i < 3; dlen *= 2, i++)
2888 win32 = (char *) crealloc (win32, dlen + 2);
2889 if ((len = GetCurrentDirectoryA (dlen, win32)) < dlen)
2897 debug_printf ("get_initial_cwd failed, %E");
2902 return 1; /* Leaves cwd lock unreleased */
2905 /* Fill out the elements of a cwdstuff struct.
2906 It is assumed that the lock for the cwd is acquired if
2907 win32_cwd == NULL. */
2909 cwdstuff::set (const char *win32_cwd, const char *posix_cwd)
2911 char pathbuf[MAX_PATH];
2916 win32 = (char *) crealloc (win32, strlen (win32_cwd) + 1);
2917 strcpy (win32, win32_cwd);
2921 cygwin_shared->mount.conv_to_posix_path (win32, pathbuf, 0);
2923 (void) normalize_posix_path (posix_cwd, pathbuf);
2925 posix = (char *) crealloc (posix, strlen (pathbuf) + 1);
2926 strcpy (posix, pathbuf);
2928 hash = hash_path_name (0, win32);
2936 /* Copy the value for either the posix or the win32 cwd into a buffer. */
2938 cwdstuff::get (char *buf, int need_posix, int with_chroot, unsigned ulen)
2948 if (!get_initial ()) /* Get initial cwd and set cwd lock */
2955 tocopy = with_chroot && ischrootpath(posix) ?
2956 posix + myself->rootlen : posix;
2958 debug_printf("myself->root: %s, posix: %s", myself->root, posix);
2959 if (strlen (tocopy) >= ulen)
2967 buf = (char *) malloc (strlen (tocopy) + 1);
2968 strcpy (buf, tocopy);
2969 if (!buf[0]) /* Should only happen when chroot */
2976 syscall_printf ("(%s) = cwdstuff::get (%p, %d, %d, %d), errno %d",
2977 buf, buf, ulen, need_posix, with_chroot, errno);
2982 /* Get copies of all cwdstuff elements. Used by spawn_guts. */
2984 cwdstuff::copy (char * &posix_cwd, char * &win32_cwd, DWORD hash_cwd)
2987 get_initial (); /* FIXME: Check return someday */
2988 posix_cwd = cstrdup (posix);
2989 win32_cwd = cstrdup (win32);