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>
70 #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];
172 char *rel_path, *full_path;
174 if (!(opt & PC_NULLEMPTY))
176 else if ((error = check_null_empty_path (src)))
180 rel_path = path_buf, full_path = this->path;
182 rel_path = this->path, full_path = path_buf;
184 /* This loop handles symlink expansion. */
188 fileattr = (DWORD) -1;
192 /* Must look up path in mount table, etc. */
193 error = cygwin_shared->mount.conv_to_win32_path (src, rel_path,
195 devn, unit, &path_flags);
205 /* Eat trailing slashes */
206 char *tail = strchr (full_path, '\0');
207 /* If path is only a drivename, Windows interprets it as
208 the current working directory on this drive instead of
209 the root dir which is what we want. So we need
210 the trailing backslash in this case. */
211 while (tail > full_path + 3 && (*--tail == '\\'))
213 if (full_path[0] && full_path[1] == ':' && full_path[2] == '\0')
214 strcat (full_path, "\\");
216 if (opt & PC_SYM_IGNORE)
218 fileattr = GetFileAttributesA (path);
222 /* Make a copy of the path that we can munge up */
223 strcpy (path_copy, full_path);
225 tail = path_copy + 1 + (tail - full_path); // Point to end of copy
227 /* Scan path_copy from right to left looking either for a symlink
228 or an actual existing file. If an existing file is found, just
229 return. If a symlink is found exit the for loop.
230 Also: be careful to preserve the errno returned from
231 symlink.check as the caller may need it. */
232 /* FIXME: Do we have to worry about multiple \'s here? */
233 int component = 0; // Number of translated components
234 sym.contents[0] = '\0';
238 const suffix_info *suff;
240 /* Don't allow symlink.check to set anything in the path_conv
241 class if we're working on an inner component of the path */
250 sym.pflags = path_flags;
253 int len = sym.check (path_copy, suff);
256 path_flags = sym.pflags;
258 /* If symlink.check found an existing non-symlink file, then
259 it sets the appropriate flag. It also sets any suffix found
261 if (!sym.is_symlink && sym.fileattr != (DWORD) -1)
266 fileattr = sym.fileattr;
269 goto out; // file found
271 /* Found a symlink if len > 0. If component == 0, then the
272 src path itself was a symlink. If !follow_mode then
273 we're done. Otherwise we have to insert the path found
274 into the full path that we are building and perform all of
275 these operations again on the newly derived path. */
278 if (component == 0 && !(opt & PC_SYM_FOLLOW))
280 set_symlink (); // last component of path is a symlink.
281 fileattr = sym.fileattr;
282 if (opt & PC_SYM_CONTENTS)
283 strcpy (path, sym.contents);
289 /* No existing file found. */
291 if (!(tail = strrchr (path_copy, '\\')) ||
292 (tail > path_copy && tail[-1] == ':'))
293 goto out; // all done
295 /* Haven't found a valid pathname component yet.
296 Pinch off the tail and try again. */
301 /* Arrive here if above loop detected a symlink. */
302 if (++loop > MAX_LINK_DEPTH)
304 error = ELOOP; // Eep.
309 tail = full_path + (tail - path_copy);
310 int taillen = strlen (tail);
311 int buflen = strlen (sym.contents);
312 if (buflen + taillen > MAX_PATH)
314 error = ENAMETOOLONG;
315 strcpy (path, "::ENAMETOOLONG::");
319 /* Copy tail of full_path to discovered symlink. */
321 for (p = sym.contents + buflen; *tail; tail++)
322 *p++ = *tail == '\\' ? '/' : *tail;
325 /* If symlink referred to an absolute path, then we
326 just use sym.contents and loop. Otherwise tack the head of
327 path_copy before sym.contents and translate it back from a
328 Win32-style path to a POSIX-style one. */
329 if (isabspath (sym.contents))
331 else if (!(tail = strrchr (path_copy, '\\')))
332 system_printf ("problem parsing %s - '%s'", src, full_path);
335 int headlen = 1 + tail - path_copy;
336 p = sym.contents - headlen;
337 memcpy (p, path_copy, headlen);
339 error = cygwin_shared->mount.conv_to_posix_path (p, tmp_buf, 1);
348 if (sym.known_suffix)
349 known_suffix = this->path + (sym.known_suffix - path_copy);
350 else if (sym.ext_here && !(opt & PC_SYM_CONTENTS))
352 known_suffix = strchr (this->path, '\0');
353 strcpy (known_suffix, sym.ext_here);
357 DWORD serial, volflags;
359 strcpy (tmp_buf, full_path);
360 if (!rootdir (tmp_buf) ||
361 !GetVolumeInformation (tmp_buf, NULL, 0, &serial, NULL, &volflags, NULL, 0))
363 debug_printf ("GetVolumeInformation(%s) = ERR, full_path(%s), set_has_acls(FALSE)",
364 tmp_buf, full_path, GetLastError ());
365 set_has_acls (FALSE);
369 debug_printf ("GetVolumeInformation(%s) = OK, full_path(%s), set_has_acls(%d)",
370 tmp_buf, full_path, volflags & FS_PERSISTENT_ACLS);
371 set_has_acls (volflags & FS_PERSISTENT_ACLS);
375 #define deveq(s) (strcasematch (name, (s)))
376 #define deveqn(s, n) (strncasematch (name, (s), (n)))
379 digits (const char *name)
382 int n = strtol(name, &p, 10);
384 return p > name && !*p ? n : -1;
387 const char *windows_device_names[] =
414 get_raw_device_number (const char *uxname, const char *w32path, int &unit)
418 if (strncasematch (w32path, "\\\\.\\tape", 8))
421 unit = digits (w32path + 8);
422 // norewind tape devices have leading n in name
423 if (strncasematch (uxname, "/dev/n", 6))
426 else if (isdrive (w32path + 4))
429 unit = tolower (w32path[4]) - 'a';
431 else if (strncasematch (w32path, "\\\\.\\physicaldrive", 17))
434 unit = digits (w32path + 17) + 128;
440 get_device_number (const char *name, int &unit, BOOL from_conv)
445 if ((*name == '/' && deveqn ("/dev/", 5)) ||
446 (*name == '\\' && deveqn ("\\dev\\", 5)))
451 if (tty_attached (myself))
456 else if (myself->ctty > 0)
459 else if (deveqn ("tty", 3) && (unit = digits (name + 3)) >= 0)
461 else if (deveq ("ttym"))
463 else if (deveq ("ptmx"))
465 else if (deveq ("windows"))
467 else if (deveq ("conin"))
469 else if (deveq ("conout"))
471 else if (deveq ("null"))
473 else if (deveq ("zero"))
475 else if (deveq ("random") || deveq ("urandom"))
478 unit = 8 + (deveqn ("u", 1) ? 1 : 0); /* Keep unit Linux conformant */
480 else if (deveqn ("com", 3) && (unit = digits (name + 3)) >= 0)
482 else if (deveq ("pipe") || deveq ("piper") || deveq ("pipew"))
484 else if (deveq ("tcp") || deveq ("udp") || deveq ("streamsocket")
485 || deveq ("dgsocket"))
487 else if (! from_conv)
488 devn = get_raw_device_number (name - 5,
490 PC_SYM_IGNORE).get_win32 (),
493 else if (deveqn ("com", 3) && (unit = digits (name + 3)) >= 0)
499 /* Return TRUE if src_path is a Win32 device name, filling out the device
500 name in win32_path */
503 win32_device_name (const char *src_path, char *win32_path,
504 DWORD &devn, int &unit)
508 devn = get_device_number (src_path, unit, TRUE);
513 if ((devfmt = windows_device_names[FHDEVN (devn)]) == NULL)
515 if (devn == FH_RANDOM)
516 __small_sprintf (win32_path, devfmt, unit == 8 ? "" : "u");
518 __small_sprintf (win32_path, devfmt, unit);
522 /* Normalize a POSIX path.
523 \'s are converted to /'s in the process.
524 All duplicate /'s, except for 2 leading /'s, are deleted.
525 The result is 0 for success, or an errno error value. */
527 #define isslash(c) ((c) == '/')
530 normalize_posix_path (const char *src, char *dst)
532 const char *src_start = src;
533 char *dst_start = dst;
535 syscall_printf ("src %s", src);
536 if (isdrive (src) || strpbrk (src, "\\:"))
538 cygwin_conv_to_full_posix_path (src, dst);
541 if (!isslash (src[0]))
544 if (!cygcwd.get (cwd))
546 if (strlen (cwd) + 1 + strlen (src) >= MAX_PATH)
548 debug_printf ("ENAMETOOLONG = normalize_posix_path (%s)", src);
552 dst = strchr (dst, '\0');
555 if (dst > dst_start && !isslash (dst[-1]))
558 /* Two leading /'s? If so, preserve them. */
559 else if (isslash (src[1]))
563 debug_printf ("ENOENT = normalize_posix_path (%s)", src);
570 { /* Starts with three or more slashes - reset. */
576 /* Exactly one leading slash. Absolute path. Check for chroot. */
577 else if (myself->rootlen)
579 strcpy (dst, myself->root);
580 dst += myself->rootlen;
585 /* Strip runs of /'s. */
603 if (dst == dst_start)
607 if (!isslash (src[1]))
610 else if (src[2] && !isslash (src[2]))
614 if (!ischrootpath (dst_start) ||
615 dst - dst_start != (int) myself->rootlen)
616 while (dst > dst_start && !isslash (*--dst))
628 if (--dst > dst_start && isslash (*dst))
631 debug_printf ("%s = normalize_posix_path (%s)", dst_start, src_start);
635 /* Normalize a Win32 path.
636 /'s are converted to \'s in the process.
637 All duplicate \'s, except for 2 leading \'s, are deleted.
639 The result is 0 for success, or an errno error value.
640 FIXME: A lot of this should be mergeable with the POSIX critter. */
642 normalize_win32_path (const char *src, char *dst)
644 const char *src_start = src;
645 char *dst_start = dst;
646 char *dst_root_start = dst;
648 if (!SLASH_P (src[0]) && strchr (src, ':') == NULL)
651 if (!cygcwd.get (cwd, 0))
653 if (strlen (cwd) + 1 + strlen (src) >= MAX_PATH)
655 debug_printf ("ENAMETOOLONG = normalize_win32_path (%s)", src);
660 if (!*cwd || !SLASH_P (dst[-1]))
663 /* Two leading \'s? If so, preserve them. */
664 else if (SLASH_P (src[0]) && SLASH_P (src[1]))
668 debug_printf ("ENOENT = normalize_win32_path (%s)", src);
674 /* If absolute path, care for chroot. */
675 else if (SLASH_P (src[0]) && !SLASH_P (src[1]) && myself->rootlen)
677 strcpy (dst, myself->root);
679 while ((c = strchr (dst, '/')) != NULL)
681 dst += myself->rootlen;
682 dst_root_start = dst;
688 /* Strip duplicate /'s. */
689 if (SLASH_P (src[0]) && SLASH_P (src[1]))
692 else if (src[0] == '.' && SLASH_P (src[1])
693 && (src == src_start || SLASH_P (src[-1])))
698 /* Backup if "..". */
699 else if (src[0] == '.' && src[1] == '.'
700 /* dst must be greater than dst_start */
702 && (SLASH_P (src[2]) || src[2] == 0))
704 /* Back up over /, but not if it's the first one. */
705 if (dst > dst_root_start + 1)
707 /* Now back up to the next /. */
708 while (dst > dst_root_start + 1 && dst[-1] != '\\' && dst[-2] != ':')
714 /* Otherwise, add char to result. */
725 debug_printf ("%s = normalize_win32_path (%s)", dst_start, src_start);
730 /* Various utilities. */
732 /* slashify: Convert all back slashes in src path to forward slashes
733 in dst path. Add a trailing slash to dst when trailing_slash_p arg
737 slashify (const char *src, char *dst, int trailing_slash_p)
739 const char *start = src;
751 && !isdirsep (src[-1]))
756 /* backslashify: Convert all forward slashes in src path to back slashes
757 in dst path. Add a trailing slash to dst when trailing_slash_p arg
761 backslashify (const char *src, char *dst, int trailing_slash_p)
763 const char *start = src;
775 && !isdirsep (src[-1]))
780 /* nofinalslash: Remove trailing / and \ from SRC (except for the
781 first one). It is ok for src == dst. */
784 nofinalslash (const char *src, char *dst)
786 int len = strlen (src);
788 memcpy (dst, src, len + 1);
789 while (len > 1 && SLASH_P (dst[--len]))
793 /* slash_drive_prefix_p: Return non-zero if PATH begins with
797 slash_drive_prefix_p (const char *path)
799 return (isdirsep(path[0])
802 && (path[3] == 0 || path[3] == '/'));
805 /* slash_unc_prefix_p: Return non-zero if PATH begins with //UNC/SHARE */
808 slash_unc_prefix_p (const char *path)
811 int ret = (isdirsep (path[0])
812 && isdirsep (path[1])
815 && !isdirsep (path[3])
816 && ((p = strchr(&path[3], '/')) != NULL));
817 if (!ret || p == NULL)
819 return ret && isalnum (p[1]);
822 /* conv_path_list: Convert a list of path names to/from Win32/POSIX.
824 SRC is not a const char * because we temporarily modify it to ease
827 I believe Win32 always has '.' in $PATH. POSIX obviously doesn't.
828 We certainly don't want to handle that here, but it is something for
829 the caller to think about. */
832 conv_path_list (const char *src, char *dst, int to_posix_p)
836 char src_delim = to_posix_p ? ';' : ':';
837 char dst_delim = to_posix_p ? ':' : ';';
838 int (*conv_fn) (const char *, char *) = (to_posix_p
839 ? cygwin_conv_to_posix_path
840 : cygwin_conv_to_win32_path);
844 s = strchr (src, src_delim);
848 (*conv_fn) (src[0] != 0 ? src : ".", d);
857 (*conv_fn) (src[0] != 0 ? src : ".", d);
863 /************************* mount_info class ****************************/
865 /* init: Initialize the mount table. */
871 had_to_create_mount_areas = 0;
873 /* Fetch the mount table and cygdrive-related information from
878 /* conv_to_win32_path: Ensure src_path is a pure Win32 path and store
879 the result in win32_path.
881 If win32_path != NULL, the relative path, if possible to keep, is
882 stored in win32_path. If the relative path isn't possible to keep,
883 the full path is stored.
885 If full_win32_path != NULL, the full path is stored there.
887 The result is zero for success, or an errno value.
889 {,full_}win32_path must have sufficient space (i.e. MAX_PATH bytes). */
892 mount_info::conv_to_win32_path (const char *src_path, char *win32_path,
893 char *full_win32_path, DWORD &devn, int &unit,
896 int src_path_len = strlen (src_path);
897 int trailing_slash_p = (src_path_len > 1
898 && SLASH_P (src_path[src_path_len - 1]));
901 unsigned dummy_flags;
907 flags = &dummy_flags;
910 debug_printf ("conv_to_win32_path (%s)", src_path);
912 if (src_path_len >= MAX_PATH)
914 debug_printf ("ENAMETOOLONG = conv_to_win32_path (%s)", src_path);
920 mount_item *mi = NULL; /* initialized to avoid compiler warning */
921 char pathbuf[MAX_PATH];
923 /* Determine where the destination should be placed. */
924 if (full_win32_path != NULL)
925 dst = full_win32_path;
926 else if (win32_path != NULL)
930 goto out; /* Sanity check. */
932 /* An MS-DOS spec has either a : or a \. If this is found, short
933 circuit most of the rest of this function. */
934 if (strpbrk (src_path, ":\\") != NULL)
936 debug_printf ("%s already win32", src_path);
937 rc = normalize_win32_path (src_path, dst);
940 debug_printf ("normalize_win32_path failed, rc %d", rc);
943 isrelpath = !isabspath (src_path);
944 *flags = set_flags_from_win32_path (dst);
945 if (myself->rootlen && dst[0] && dst[1] == ':')
947 char posix_path[MAX_PATH + 1];
949 rc = cygwin_shared->mount.conv_to_posix_path (dst, posix_path, 0);
952 debug_printf ("conv_to_posix_path failed, rc %d", rc);
955 if (!ischrootpath (posix_path))
957 debug_printf ("ischrootpath failed");
964 /* Normalize the path, taking out ../../ stuff, we need to do this
965 so that we can move from one mounted directory to another with relative
968 eg mounting c:/foo /foo
974 should look in c:/foo, not d:/foo.
976 We do this by first getting an absolute UNIX-style path and then
977 converting it to a DOS-style path, looking up the appropriate drive
978 in the mount table. */
980 rc = normalize_posix_path (src_path, pathbuf);
984 debug_printf ("%d = conv_to_win32_path (%s)", rc, src_path);
989 isrelpath = !isslash (*src_path);
991 /* See if this is a cygwin "device" */
992 if (win32_device_name (pathbuf, dst, devn, unit))
994 *flags = MOUNT_BINARY; /* FIXME: Is this a sensible default for devices? */
998 /* Check if the cygdrive prefix was specified. If so, just strip
999 off the prefix and transform it into an MS-DOS path. */
1001 if (iscygdrive_device (pathbuf))
1003 if (!cygdrive_win32_path (pathbuf, dst, trailing_slash_p))
1005 *flags = cygdrive_flags;
1009 /* Check the mount table for prefix matches. */
1010 for (i = 0; i < nmounts; i++)
1012 mi = mount + posix_sorted[i];
1013 if (path_prefix_p (mi->posix_path, pathbuf, mi->posix_pathlen))
1019 if (slash_drive_prefix_p (pathbuf))
1020 slash_drive_to_win32_path (pathbuf, dst, trailing_slash_p);
1022 backslashify (pathbuf, dst, trailing_slash_p); /* just convert */
1027 int n = mi->native_pathlen;
1028 memcpy (dst, mi->native_path, n + 1);
1029 char *p = pathbuf + mi->posix_pathlen;
1030 if (!trailing_slash_p && !*p)
1032 if (isdrive (dst) && !dst[2])
1038 /* Do not add trailing \ to UNC device names like \\.\a: */
1039 if (*p != '/' && /* FIXME: this test seems wrong. */
1040 (strncmp (mi->native_path, "\\\\.\\", 4) != 0 ||
1041 strncmp (mi->native_path + 4, "UNC\\", 4) == 0))
1043 strcpy (dst + n, p);
1045 backslashify (dst, dst, trailing_slash_p);
1050 /* Compute relative path if asked to and able to. */
1051 if (win32_path == NULL)
1052 /* nothing to do */;
1055 char cwd_win32[MAX_PATH];
1056 if (!cygcwd.get (cwd_win32, 0))
1057 return get_errno ();
1058 unsigned cwdlen = strlen (cwd_win32);
1059 if (!path_prefix_p (cwd_win32, dst, cwdlen))
1060 strcpy (win32_path, dst);
1063 size_t n = strlen (dst);
1065 strcpy (win32_path, dst);
1071 dst += isdirsep (cwd_win32[cwdlen - 1]) ? cwdlen : cwdlen + 1;
1073 memmove (win32_path, dst, strlen (dst) + 1);
1076 strcpy (win32_path, ".");
1077 if (trailing_slash_p)
1078 strcat (win32_path, "\\");
1083 else if (win32_path != dst)
1084 strcpy (win32_path, dst);
1088 debug_printf ("%s(rel), %s(abs) %p(flags) = conv_to_win32_path (%s)",
1089 win32_path, full_win32_path, *flags,
1094 /* Convert PATH (for which slash_drive_prefix_p returns 1) to WIN32 form. */
1097 mount_info::slash_drive_to_win32_path (const char *path, char *buf,
1098 int trailing_slash_p)
1103 strcpy (buf + 2, "\\");
1105 backslashify (path + 3, buf + 2, trailing_slash_p);
1108 /* cygdrive_posix_path: Build POSIX path used as the
1109 mount point for cygdrives created when there is no other way to
1110 obtain a POSIX path from a Win32 one. */
1113 mount_info::cygdrive_posix_path (const char *src, char *dst, int trailing_slash_p)
1115 int len = cygdrive_len;
1117 memcpy (dst, cygdrive, len + 1);
1119 /* Now finish the path off with the drive letter to be used.
1120 The cygdrive prefix always ends with a trailing slash so
1121 the drive letter is added after the path. */
1122 dst[len++] = tolower (src[0]);
1123 if (!src[2] || (SLASH_P (src[2]) && !src[3]))
1124 dst[len++] = '\000';
1128 strcpy (dst + len, src + 3);
1130 slashify (dst, dst, trailing_slash_p);
1134 mount_info::cygdrive_win32_path (const char *src, char *dst, int trailing_slash_p)
1136 const char *p = src + cygdrive_len;
1137 if (!isalpha (*p) || (!isdirsep (p[1]) && p[1]))
1141 strcpy (dst + 2, p + 1);
1142 backslashify (dst, dst, trailing_slash_p || !dst[2]);
1143 debug_printf ("src '%s', dst '%s'", src, dst);
1147 /* conv_to_posix_path: Ensure src_path is a POSIX path.
1149 The result is zero for success, or an errno value.
1150 posix_path must have sufficient space (i.e. MAX_PATH bytes).
1151 If keep_rel_p is non-zero, relative paths stay that way. */
1154 mount_info::conv_to_posix_path (const char *src_path, char *posix_path,
1157 int src_path_len = strlen (src_path);
1158 int relative_path_p = !isabspath (src_path);
1159 int trailing_slash_p;
1161 if (src_path_len <= 1)
1162 trailing_slash_p = 0;
1165 const char *lastchar = src_path + src_path_len - 1;
1166 trailing_slash_p = SLASH_P (*lastchar) && lastchar[-1] != ':';
1169 debug_printf ("conv_to_posix_path (%s, %s, %s)", src_path,
1170 keep_rel_p ? "keep-rel" : "no-keep-rel",
1171 trailing_slash_p ? "add-slash" : "no-add-slash");
1174 if (src_path_len >= MAX_PATH)
1176 debug_printf ("ENAMETOOLONG");
1177 return ENAMETOOLONG;
1180 /* FIXME: For now, if the path is relative and it's supposed to stay
1181 that way, skip mount table processing. */
1183 if (keep_rel_p && relative_path_p)
1185 slashify (src_path, posix_path, 0);
1186 debug_printf ("%s = conv_to_posix_path (%s)", posix_path, src_path);
1190 char pathbuf[MAX_PATH];
1191 int rc = normalize_win32_path (src_path, pathbuf);
1194 debug_printf ("%d = conv_to_posix_path (%s)", rc, src_path);
1198 int pathbuflen = strlen (pathbuf);
1199 for (int i = 0; i < nmounts; ++i)
1201 mount_item &mi = mount[native_sorted[i]];
1202 if (! path_prefix_p (mi.native_path, pathbuf, mi.native_pathlen))
1205 /* SRC_PATH is in the mount table. */
1207 const char *p = pathbuf + mi.native_pathlen;
1211 else if (isdirsep (*p))
1216 int addslash = nextchar > 0 ? 1 : 0;
1217 if ((mi.posix_pathlen + (pathbuflen - mi.native_pathlen) + addslash) >= MAX_PATH)
1218 return ENAMETOOLONG;
1219 strcpy (posix_path, mi.posix_path);
1221 strcat (posix_path, "/");
1224 posix_path + addslash + (mi.posix_pathlen == 1 ? 0 : mi.posix_pathlen),
1229 /* Not in the database. This should [theoretically] only happen if either
1230 the path begins with //, or / isn't mounted, or the path has a drive
1231 letter not covered by the mount table. If it's a relative path then the
1232 caller must want an absolute path (otherwise we would have returned
1233 above). So we always return an absolute path at this point. */
1234 if (isdrive (pathbuf))
1235 cygdrive_posix_path (pathbuf, posix_path, trailing_slash_p);
1238 /* The use of src_path and not pathbuf here is intentional.
1239 We couldn't translate the path, so just ensure no \'s are present. */
1240 slashify (src_path, posix_path, trailing_slash_p);
1244 debug_printf ("%s = conv_to_posix_path (%s)", posix_path, src_path);
1249 /* Return flags associated with a mount point given the win32 path. */
1252 mount_info::set_flags_from_win32_path (const char *p)
1254 for (int i = 0; i < nmounts; i++)
1256 mount_item &mi = mount[native_sorted[i]];
1257 if (path_prefix_p (mi.native_path, p, mi.native_pathlen))
1263 /* read_mounts: Given a specific regkey, read mounts from under its
1267 mount_info::read_mounts (reg_key& r)
1269 char posix_path[MAX_PATH];
1270 HKEY key = r.get_key ();
1271 DWORD i, posix_path_size;
1272 int found_cygdrive = FALSE;
1274 /* Loop through subkeys */
1275 /* FIXME: we would like to not check MAX_MOUNTS but the heap in the
1276 shared area is currently statically allocated so we can't have an
1277 arbitrarily large number of mounts. */
1278 for (DWORD i = 0; ; i++)
1280 char native_path[MAX_PATH];
1283 posix_path_size = MAX_PATH;
1284 /* FIXME: if maximum posix_path_size is 256, we're going to
1285 run into problems if we ever try to store a mount point that's
1286 over 256 but is under MAX_PATH! */
1287 LONG err = RegEnumKeyEx (key, i, posix_path, &posix_path_size, NULL,
1290 if (err == ERROR_NO_MORE_ITEMS)
1292 else if (err != ERROR_SUCCESS)
1294 debug_printf ("RegEnumKeyEx failed, error %d!\n", err);
1298 if (iscygdrive (posix_path))
1300 found_cygdrive = TRUE;
1304 /* Get a reg_key based on i. */
1305 reg_key subkey = reg_key (key, KEY_READ, posix_path, NULL);
1307 /* Fetch info from the subkey. */
1308 subkey.get_string ("native", native_path, sizeof (native_path), "");
1309 mount_flags = subkey.get_int ("flags", 0);
1311 /* Add mount_item corresponding to registry mount point. */
1312 int res = cygwin_shared->mount.add_item (native_path, posix_path, mount_flags, FALSE);
1313 if (res && get_errno () == EMFILE)
1314 break; /* The number of entries exceeds MAX_MOUNTS */
1317 if (!found_cygdrive)
1323 posix_path_size = MAX_PATH;
1324 LONG err = RegEnumKeyEx (key, i, posix_path, &posix_path_size, NULL,
1327 if (err != ERROR_SUCCESS)
1330 if (iscygdrive (posix_path))
1332 /* This shouldn't be in the mount table. */
1333 (void) r.kill (posix_path);
1339 /* from_registry: Build the entire mount table from the registry. Also,
1340 read in cygdrive-related information from its registry location. */
1343 mount_info::from_registry ()
1345 /* Use current mount areas if either user or system mount areas
1346 already exist. Otherwise, import old mounts. */
1350 /* Retrieve cygdrive-related information. */
1351 read_cygdrive_info_from_registry ();
1355 /* First read mounts from user's table. */
1358 /* Then read mounts from system-wide mount table. */
1359 reg_key r1 (HKEY_LOCAL_MACHINE, KEY_READ, "SOFTWARE",
1360 CYGWIN_INFO_CYGNUS_REGISTRY_NAME,
1361 CYGWIN_INFO_CYGWIN_REGISTRY_NAME,
1362 CYGWIN_INFO_CYGWIN_MOUNT_REGISTRY_NAME,
1366 /* If we had to create both user and system mount areas, import
1368 if (had_to_create_mount_areas == 2)
1369 import_v1_mounts ();
1372 /* add_reg_mount: Add mount item to registry. Return zero on success,
1373 non-zero on failure. */
1374 /* FIXME: Need a mutex to avoid collisions with other tasks. */
1377 mount_info::add_reg_mount (const char * native_path, const char * posix_path, unsigned mountflags)
1379 /* Add the mount to the right registry location, depending on
1380 whether MOUNT_SYSTEM is set in the mount flags. */
1381 if (!(mountflags & MOUNT_SYSTEM)) /* current_user mount */
1383 /* reg_key for user mounts in HKEY_CURRENT_USER. */
1386 /* Start by deleting existing mount if one exists. */
1387 reg_user.kill (posix_path);
1389 /* Create the new mount. */
1390 reg_key subkey = reg_key (reg_user.get_key (),
1393 subkey.set_string ("native", native_path);
1394 subkey.set_int ("flags", mountflags);
1396 else /* local_machine mount */
1398 /* reg_key for system mounts in HKEY_LOCAL_MACHINE. */
1399 reg_key reg_sys (HKEY_LOCAL_MACHINE, KEY_ALL_ACCESS, "SOFTWARE",
1400 CYGWIN_INFO_CYGNUS_REGISTRY_NAME,
1401 CYGWIN_INFO_CYGWIN_REGISTRY_NAME,
1402 CYGWIN_INFO_CYGWIN_MOUNT_REGISTRY_NAME,
1405 if (reg_sys.get_key () == INVALID_HANDLE_VALUE)
1411 /* Start by deleting existing mount if one exists. */
1412 reg_sys.kill (posix_path);
1414 /* Create the new mount. */
1415 reg_key subkey = reg_key (reg_sys.get_key (),
1418 subkey.set_string ("native", native_path);
1419 subkey.set_int ("flags", mountflags);
1422 return 0; /* Success! */
1425 /* del_reg_mount: delete mount item from registry indicated in flags.
1426 Return zero on success, non-zero on failure.*/
1427 /* FIXME: Need a mutex to avoid collisions with other tasks. */
1430 mount_info::del_reg_mount (const char * posix_path, unsigned flags)
1434 if ((flags & MOUNT_SYSTEM) == 0) /* Delete from user registry */
1436 reg_key reg_user (KEY_ALL_ACCESS,
1437 CYGWIN_INFO_CYGWIN_MOUNT_REGISTRY_NAME, NULL);
1438 killres = reg_user.kill (posix_path);
1440 else /* Delete from system registry */
1442 reg_key reg_sys (HKEY_LOCAL_MACHINE, KEY_ALL_ACCESS, "SOFTWARE",
1443 CYGWIN_INFO_CYGNUS_REGISTRY_NAME,
1444 CYGWIN_INFO_CYGWIN_REGISTRY_NAME,
1445 CYGWIN_INFO_CYGWIN_MOUNT_REGISTRY_NAME,
1448 if (reg_sys.get_key () == INVALID_HANDLE_VALUE)
1454 killres = reg_sys.kill (posix_path);
1457 if (killres != ERROR_SUCCESS)
1459 __seterrno_from_win_error (killres);
1463 return 0; /* Success! */
1466 /* read_cygdrive_info_from_registry: Read the default prefix and flags
1467 to use when creating cygdrives from the special user registry
1468 location used to store cygdrive information. */
1471 mount_info::read_cygdrive_info_from_registry ()
1473 /* reg_key for user path prefix in HKEY_CURRENT_USER. */
1476 if (r.get_string ("cygdrive prefix", cygdrive, sizeof (cygdrive), "") != 0)
1478 /* Didn't find the user path prefix so check the system path prefix. */
1480 /* reg_key for system path prefix in HKEY_LOCAL_MACHINE. */
1481 reg_key r2 (HKEY_LOCAL_MACHINE, KEY_ALL_ACCESS, "SOFTWARE",
1482 CYGWIN_INFO_CYGNUS_REGISTRY_NAME,
1483 CYGWIN_INFO_CYGWIN_REGISTRY_NAME,
1484 CYGWIN_INFO_CYGWIN_MOUNT_REGISTRY_NAME,
1487 if (r2.get_string ("cygdrive prefix", cygdrive, sizeof (cygdrive), "") != 0)
1489 /* Didn't find either so write the default to the registry and use it.
1490 NOTE: We are writing and using the user path prefix. */
1491 write_cygdrive_info_to_registry ("/cygdrive", MOUNT_AUTO);
1495 /* Fetch system cygdrive_flags from registry; returns MOUNT_AUTO on
1497 cygdrive_flags = r2.get_int ("cygdrive flags", MOUNT_AUTO);
1498 slashify (cygdrive, cygdrive, 1);
1499 cygdrive_len = strlen(cygdrive);
1504 /* Fetch user cygdrive_flags from registry; returns MOUNT_AUTO on
1506 cygdrive_flags = r.get_int ("cygdrive flags", MOUNT_AUTO);
1507 slashify (cygdrive, cygdrive, 1);
1508 cygdrive_len = strlen(cygdrive);
1512 /* write_cygdrive_info_to_registry: Write the default prefix and flags
1513 to use when creating cygdrives to the special user registry
1514 location used to store cygdrive information. */
1517 mount_info::write_cygdrive_info_to_registry (const char *cygdrive_prefix, unsigned flags)
1519 /* Determine whether to modify user or system cygdrive path prefix. */
1520 HKEY top = (flags & MOUNT_SYSTEM) ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
1522 /* reg_key for user path prefix in HKEY_CURRENT_USER or system path prefix in
1523 HKEY_LOCAL_MACHINE. */
1524 reg_key r (top, KEY_ALL_ACCESS, "SOFTWARE",
1525 CYGWIN_INFO_CYGNUS_REGISTRY_NAME,
1526 CYGWIN_INFO_CYGWIN_REGISTRY_NAME,
1527 CYGWIN_INFO_CYGWIN_MOUNT_REGISTRY_NAME,
1530 /* Verify cygdrive prefix starts with a forward slash and if there's
1531 another character, it's not a slash. */
1532 if ((cygdrive_prefix == NULL) || (*cygdrive_prefix == 0) ||
1533 (!isslash (cygdrive_prefix[0])) ||
1534 ((cygdrive_prefix[1] != '\0') && (isslash (cygdrive_prefix[1]))))
1540 char hold_cygdrive_prefix[strlen (cygdrive_prefix) + 1];
1541 /* Ensure that there is never a final slash */
1542 nofinalslash (cygdrive_prefix, hold_cygdrive_prefix);
1544 r.set_string ("cygdrive prefix", hold_cygdrive_prefix);
1545 r.set_int ("cygdrive flags", flags);
1547 /* This also needs to go in the in-memory copy of "cygdrive", but only if
1549 1. setting user path prefix, or
1550 2. overwriting (a previous) system path prefix */
1551 if ((flags & MOUNT_SYSTEM) == 0 ||
1552 (cygwin_shared->mount.cygdrive_flags & MOUNT_SYSTEM) != 0)
1554 slashify (cygdrive_prefix, cygwin_shared->mount.cygdrive, 1);
1555 cygwin_shared->mount.cygdrive_flags = flags;
1556 cygwin_shared->mount.cygdrive_len = strlen(cygwin_shared->mount.cygdrive);
1563 mount_info::remove_cygdrive_info_from_registry (const char *cygdrive_prefix, unsigned flags)
1565 /* Determine whether to modify user or system cygdrive path prefix. */
1566 HKEY top = (flags & MOUNT_SYSTEM) ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
1568 /* reg_key for user path prefix in HKEY_CURRENT_USER or system path prefix in
1569 HKEY_LOCAL_MACHINE. */
1570 reg_key r (top, KEY_ALL_ACCESS, "SOFTWARE",
1571 CYGWIN_INFO_CYGNUS_REGISTRY_NAME,
1572 CYGWIN_INFO_CYGWIN_REGISTRY_NAME,
1573 CYGWIN_INFO_CYGWIN_MOUNT_REGISTRY_NAME,
1576 /* Delete cygdrive prefix and flags. */
1577 int res = r.killvalue ("cygdrive prefix");
1578 int res2 = r.killvalue ("cygdrive flags");
1580 /* Reinitialize the cygdrive path prefix to reflect to removal from the
1582 read_cygdrive_info_from_registry ();
1584 return (res != ERROR_SUCCESS) ? res : res2;
1588 mount_info::get_cygdrive_prefixes (char *user, char *system)
1590 /* Get the user path prefix from HKEY_CURRENT_USER. */
1592 int res = r.get_string ("cygdrive prefix", user, MAX_PATH, "");
1594 /* Get the system path prefix from HKEY_LOCAL_MACHINE. */
1595 reg_key r2 (HKEY_LOCAL_MACHINE, KEY_ALL_ACCESS, "SOFTWARE",
1596 CYGWIN_INFO_CYGNUS_REGISTRY_NAME,
1597 CYGWIN_INFO_CYGWIN_REGISTRY_NAME,
1598 CYGWIN_INFO_CYGWIN_MOUNT_REGISTRY_NAME,
1600 int res2 = r2.get_string ("cygdrive prefix", system, MAX_PATH, "");
1602 return (res != ERROR_SUCCESS) ? res : res2;
1606 mount_info::getmntent (int x)
1608 if (x < 0 || x >= nmounts)
1611 return mount[native_sorted[x]].getmntent ();
1614 static mount_item *mounts_for_sort;
1616 /* sort_by_posix_name: qsort callback to sort the mount entries. Sort
1617 user mounts ahead of system mounts to the same POSIX path. */
1618 /* FIXME: should the user should be able to choose whether to
1619 prefer user or system mounts??? */
1621 sort_by_posix_name (const void *a, const void *b)
1623 mount_item *ap = mounts_for_sort + (*((int*) a));
1624 mount_item *bp = mounts_for_sort + (*((int*) b));
1626 /* Base weighting on longest posix path first so that the most
1627 obvious path will be chosen. */
1628 size_t alen = strlen (ap->posix_path);
1629 size_t blen = strlen (bp->posix_path);
1631 int res = blen - alen;
1634 return res; /* Path lengths differed */
1636 /* The two paths were the same length, so just determine normal
1637 lexical sorted order. */
1638 res = strcmp (ap->posix_path, bp->posix_path);
1642 /* need to select between user and system mount to same POSIX path */
1643 if ((bp->flags & MOUNT_SYSTEM) == 0) /* user mount */
1652 /* sort_by_native_name: qsort callback to sort the mount entries. Sort
1653 user mounts ahead of system mounts to the same POSIX path. */
1654 /* FIXME: should the user should be able to choose whether to
1655 prefer user or system mounts??? */
1657 sort_by_native_name (const void *a, const void *b)
1659 mount_item *ap = mounts_for_sort + (*((int*) a));
1660 mount_item *bp = mounts_for_sort + (*((int*) b));
1662 /* Base weighting on longest win32 path first so that the most
1663 obvious path will be chosen. */
1664 size_t alen = strlen (ap->native_path);
1665 size_t blen = strlen (bp->native_path);
1667 int res = blen - alen;
1670 return res; /* Path lengths differed */
1672 /* The two paths were the same length, so just determine normal
1673 lexical sorted order. */
1674 res = strcmp (ap->native_path, bp->native_path);
1678 /* need to select between user and system mount to same POSIX path */
1679 if ((bp->flags & MOUNT_SYSTEM) == 0) /* user mount */
1691 for (int i = 0; i < nmounts; i++)
1692 native_sorted[i] = posix_sorted[i] = i;
1693 /* Sort them into reverse length order, otherwise we won't
1694 be able to look for /foo in /. */
1695 mounts_for_sort = mount; /* ouch. */
1696 qsort (posix_sorted, nmounts, sizeof (posix_sorted[0]), sort_by_posix_name);
1697 qsort (native_sorted, nmounts, sizeof (native_sorted[0]), sort_by_native_name);
1700 /* Add an entry to the mount table.
1701 Returns 0 on success, -1 on failure and errno is set.
1703 This is where all argument validation is done. It may not make sense to
1704 do this when called internally, but it's cleaner to keep it all here. */
1707 mount_info::add_item (const char *native, const char *posix, unsigned mountflags, int reg_p)
1709 /* Something's wrong if either path is NULL or empty, or if it's
1710 not a UNC or absolute path. */
1712 if ((native == NULL) || (*native == 0) ||
1713 (posix == NULL) || (*posix == 0) ||
1714 (!slash_unc_prefix_p (native) && !isabspath (native)))
1720 /* Make sure both paths do not end in /. */
1721 char nativetmp[MAX_PATH];
1722 char posixtmp[MAX_PATH];
1724 if (slash_drive_prefix_p (native))
1725 slash_drive_to_win32_path (native, nativetmp, 0);
1727 backslashify (native, nativetmp, 0);
1728 nofinalslash (nativetmp, nativetmp);
1730 slashify (posix, posixtmp, 0);
1731 nofinalslash (posixtmp, posixtmp);
1733 debug_printf ("%s[%s], %s[%s], %p",
1734 native, nativetmp, posix, posixtmp, mountflags);
1736 /* Duplicate /'s in path are an error. */
1737 for (char *p = posixtmp + 1; *p; ++p)
1739 if (p[-1] == '/' && p[0] == '/')
1746 /* Write over an existing mount item with the same POSIX path if
1747 it exists and is from the same registry area. */
1749 for (i = 0; i < nmounts; i++)
1751 if (strcasematch (mount[i].posix_path, posixtmp) &&
1752 (mount[i].flags & MOUNT_SYSTEM) == (mountflags & MOUNT_SYSTEM))
1758 if (nmounts < MAX_MOUNTS)
1767 if (reg_p && add_reg_mount (nativetmp, posixtmp, mountflags))
1770 mount[i].init (nativetmp, posixtmp, mountflags);
1776 /* Delete a mount table entry where path is either a Win32 or POSIX
1777 path. Since the mount table is really just a table of aliases,
1778 deleting / is ok (although running without a slash mount is
1779 strongly discouraged because some programs may run erratically
1780 without one). If MOUNT_SYSTEM is set in flags, remove from system
1781 registry, otherwise remove the user registry mount.
1785 mount_info::del_item (const char *path, unsigned flags, int reg_p)
1787 char pathtmp[MAX_PATH];
1788 int posix_path_p = FALSE;
1790 /* Something's wrong if path is NULL or empty. */
1791 if (path == NULL || *path == 0 || !isabspath (path))
1797 if (slash_drive_prefix_p (path))
1798 slash_drive_to_win32_path (path, pathtmp, 0);
1799 else if (slash_unc_prefix_p (path) || strpbrk (path, ":\\"))
1800 backslashify (path, pathtmp, 0);
1803 slashify (path, pathtmp, 0);
1804 posix_path_p = TRUE;
1806 nofinalslash (pathtmp, pathtmp);
1808 if (reg_p && posix_path_p &&
1809 del_reg_mount (pathtmp, flags) &&
1810 del_reg_mount (path, flags)) /* for old irregular entries */
1813 for (int i = 0; i < nmounts; i++)
1815 int ent = native_sorted[i]; /* in the same order as getmntent() */
1817 ? strcasematch (mount[ent].posix_path, pathtmp)
1818 : strcasematch (mount[ent].native_path, pathtmp)) &&
1819 (mount[ent].flags & MOUNT_SYSTEM) == (flags & MOUNT_SYSTEM))
1821 if (!posix_path_p &&
1822 reg_p && del_reg_mount (mount[ent].posix_path, flags))
1825 nmounts--; /* One less mount table entry */
1826 /* Fill in the hole if not at the end of the table */
1828 memmove (mount + ent, mount + ent + 1,
1829 sizeof (mount[ent]) * (nmounts - ent));
1830 sort (); /* Resort the table */
1838 /* read_v1_mounts: Given a reg_key to an old mount table registry area,
1839 read in the mounts. The "which" arg contains zero if we're reading
1840 the user area and MOUNT_SYSTEM if we're reading the system area.
1841 This way we can store the mounts read in the appropriate place when
1842 they are written back to the new registry layout. */
1845 mount_info::read_v1_mounts (reg_key r, unsigned which)
1847 unsigned mountflags = 0;
1849 /* MAX_MOUNTS was 30 when we stopped using the v1 layout */
1850 for (int i = 0; i < 30; i++)
1853 char win32path[MAX_PATH];
1854 char unixpath[MAX_PATH];
1856 __small_sprintf (key_name, "%02x", i);
1858 reg_key k (r.get_key (), KEY_ALL_ACCESS, key_name, NULL);
1860 /* The registry names are historical but useful so are left alone. */
1861 k.get_string ("native", win32path, sizeof (win32path), "");
1862 k.get_string ("unix", unixpath, sizeof (unixpath), "");
1864 /* Does this entry contain something? */
1865 if (*win32path != 0)
1869 if (k.get_int ("fbinary", 0))
1870 mountflags |= MOUNT_BINARY;
1872 /* Or in zero or MOUNT_SYSTEM depending on which table
1874 mountflags |= which;
1876 int res = cygwin_shared->mount.add_item (win32path, unixpath, mountflags, TRUE);
1877 if (res && get_errno () == EMFILE)
1878 break; /* The number of entries exceeds MAX_MOUNTS */
1883 /* import_v1_mounts: If v1 mounts are present, load them and write
1884 the new entries to the new registry area. */
1887 mount_info::import_v1_mounts ()
1889 reg_key r (HKEY_CURRENT_USER, KEY_ALL_ACCESS,
1899 /* First read mounts from user's table. */
1900 read_v1_mounts (r, 0);
1902 /* Then read mounts from system-wide mount table. */
1903 reg_key r1 (HKEY_LOCAL_MACHINE, KEY_ALL_ACCESS,
1910 read_v1_mounts (r1, MOUNT_SYSTEM);
1913 /************************* mount_item class ****************************/
1916 mount_item::getmntent ()
1919 struct mntent &ret=_reent_winsup()->_ret;
1921 static NO_COPY struct mntent ret;
1924 /* Pass back pointers to mount_info strings reserved for use by
1925 getmntent rather than pointers to strings in the internal mount
1926 table because the mount table might change, causing weird effects
1927 from the getmntent user's point of view. */
1929 strcpy (cygwin_shared->mount.mnt_fsname, native_path);
1930 ret.mnt_fsname = cygwin_shared->mount.mnt_fsname;
1931 strcpy (cygwin_shared->mount.mnt_dir, posix_path);
1932 ret.mnt_dir = cygwin_shared->mount.mnt_dir;
1934 if (!(flags & MOUNT_SYSTEM)) /* user mount */
1935 strcpy (cygwin_shared->mount.mnt_type, (char *) "user");
1936 else /* system mount */
1937 strcpy (cygwin_shared->mount.mnt_type, (char *) "system");
1939 if ((flags & MOUNT_AUTO)) /* cygdrive */
1940 strcat (cygwin_shared->mount.mnt_type, (char *) ",auto");
1942 ret.mnt_type = cygwin_shared->mount.mnt_type;
1944 /* mnt_opts is a string that details mount params such as
1945 binary or textmode, or exec. We don't print
1946 `silent' here; it's a magic internal thing. */
1948 if (! (flags & MOUNT_BINARY))
1949 strcpy (cygwin_shared->mount.mnt_opts, (char *) "textmode");
1951 strcpy (cygwin_shared->mount.mnt_opts, (char *) "binmode");
1953 if (flags & MOUNT_CYGWIN_EXEC)
1954 strcat (cygwin_shared->mount.mnt_opts, (char *) ",cygexec");
1955 else if (flags & MOUNT_EXEC)
1956 strcat (cygwin_shared->mount.mnt_opts, (char *) ",exec");
1959 ret.mnt_opts = cygwin_shared->mount.mnt_opts;
1966 /* Fill in the fields of a mount table entry. */
1969 mount_item::init (const char *native, const char *posix, unsigned mountflags)
1971 strcpy ((char *) native_path, native);
1972 strcpy ((char *) posix_path, posix);
1974 native_pathlen = strlen (native_path);
1975 posix_pathlen = strlen (posix_path);
1980 /********************** Mount System Calls **************************/
1982 /* Mount table system calls.
1983 Note that these are exported to the application. */
1985 /* mount: Add a mount to the mount table in memory and to the registry
1986 that will cause paths under win32_path to be translated to paths
1987 under posix_path. */
1991 mount (const char *win32_path, const char *posix_path, unsigned flags)
1995 if (flags & MOUNT_AUTO) /* normal mount */
1997 /* When flags include MOUNT_AUTO, take this to mean that
1998 we actually want to change the cygdrive prefix and flags
1999 without actually mounting anything. */
2000 res = cygwin_shared->mount.write_cygdrive_info_to_registry (posix_path, flags);
2005 if (iscygdrive (posix_path))
2008 return res; /* Don't try to add cygdrive prefix. */
2011 res = cygwin_shared->mount.add_item (win32_path, posix_path, flags, TRUE);
2014 syscall_printf ("%d = mount (%s, %s, %p)", res, win32_path, posix_path, flags);
2018 /* umount: The standard umount call only has a path parameter. Since
2019 it is not possible for this call to specify whether to remove the
2020 mount from the user or global mount registry table, assume the user
2025 umount (const char *path)
2027 return cygwin_umount (path, 0);
2030 /* cygwin_umount: This is like umount but takes an additional flags
2031 parameter that specifies whether to umount from the user or system-wide
2036 cygwin_umount (const char *path, unsigned flags)
2040 if (flags & MOUNT_AUTO)
2042 /* When flags include MOUNT_AUTO, take this to mean that we actually want
2043 to remove the cygdrive prefix and flags without actually unmounting
2045 res = cygwin_shared->mount.remove_cygdrive_info_from_registry (path, flags);
2049 res = cygwin_shared->mount.del_item (path, flags, TRUE);
2052 syscall_printf ("%d = cygwin_umount (%s, %d)", res, path, flags);
2057 #define iteration _reent_winsup()->_iteration
2059 static int iteration;
2064 setmntent (const char *filep, const char *)
2067 return (FILE *) filep;
2074 return cygwin_shared->mount.getmntent (iteration++);
2084 /********************** Symbolic Link Support **************************/
2086 /* Create a symlink from FROMPATH to TOPATH. */
2090 symlink (const char *topath, const char *frompath)
2095 path_conv win32_path (frompath, PC_SYM_NOFOLLOW);
2096 if (win32_path.error)
2098 set_errno (win32_path.error);
2102 syscall_printf ("symlink (%s, %s)", topath, win32_path.get_win32 ());
2109 if (strlen (topath) >= MAX_PATH)
2111 set_errno (ENAMETOOLONG);
2115 if (win32_path.is_device () ||
2116 win32_path.file_attributes () != (DWORD) -1)
2122 h = CreateFileA(win32_path.get_win32 (), GENERIC_WRITE, 0, &sec_none_nih,
2123 CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0);
2124 if (h == INVALID_HANDLE_VALUE)
2128 char buf[sizeof (SYMLINK_COOKIE) + MAX_PATH + 10];
2130 __small_sprintf (buf, "%s%s", SYMLINK_COOKIE, topath);
2131 DWORD len = strlen (buf) + 1;
2133 /* Note that the terminating nul is written. */
2135 if (!WriteFile (h, buf, len, &written, NULL) || written != len)
2139 DeleteFileA (win32_path.get_win32 ());
2144 set_file_attribute (win32_path.has_acls (),
2145 win32_path.get_win32 (),
2146 S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO);
2147 SetFileAttributesA (win32_path.get_win32 (), FILE_ATTRIBUTE_SYSTEM);
2153 syscall_printf ("%d = symlink (%s, %s)", res, topath, frompath);
2157 static __inline char *
2158 has_suffix (const char *path, const suffix_info *suffixes)
2160 char *ext = strrchr (path, '.');
2162 for (const suffix_info *ex = suffixes; ex->name != NULL; ex++)
2163 if (strcasematch (ext, ex->name))
2168 static __inline__ int
2169 next_suffix (char *ext_here, const suffix_info *&suffixes)
2174 while (suffixes && suffixes->name)
2175 if (!suffixes->addon)
2179 strcpy (ext_here, suffixes->name);
2186 /* Check if PATH is a symlink. PATH must be a valid Win32 path name.
2188 If PATH is a symlink, put the value of the symlink--the file to
2189 which it points--into BUF. The value stored in BUF is not
2190 necessarily null terminated. BUFLEN is the length of BUF; only up
2191 to BUFLEN characters will be stored in BUF. BUF may be NULL, in
2192 which case nothing will be stored.
2194 Set *SYML if PATH is a symlink.
2196 Set *EXEC if PATH appears to be executable. This is an efficiency
2197 hack because we sometimes have to open the file anyhow. *EXEC will
2198 not be set for every executable file.
2200 Return -1 on error, 0 if PATH is not a symlink, or the length
2201 stored into BUF if PATH is a symlink. */
2204 symlink_info::check (const char *in_path, const suffix_info *suffixes)
2208 char extbuf[MAX_PATH + 5];
2209 const char *path = in_path;
2213 else if ((known_suffix = has_suffix (in_path, suffixes)) != NULL)
2220 path = strcpy (extbuf, in_path);
2221 ext_here = strchr (path, '\0');
2229 if (!next_suffix (ext_here, suffixes))
2232 fileattr = GetFileAttributesA (path);
2233 if (fileattr == (DWORD) -1)
2235 /* The GetFileAttributesA call can fail for reasons that don't
2236 matter, so we just return 0. For example, getting the
2237 attributes of \\HOST will typically fail. */
2238 debug_printf ("GetFileAttributesA (%s) failed", path);
2239 error = geterrno_from_win_error (GetLastError (), EACCES);
2243 /* Windows allows path\. even when `path' isn't a directory.
2244 Detect this scenario and disallow it, since it is non-UNIX like.
2245 FIXME: This code actually checks for things like foo/ and foo/..
2246 even though those usages have already been (erroneously?) eaten
2247 by cygwin_shared->mount.conv_to_win32_path in path_conv::check. */
2249 char *p = strrchr (path, '\\');
2250 if (p && !(fileattr & FILE_ATTRIBUTE_DIRECTORY) &&
2251 (*++p == '\0' || (*p == '.' && (*++p == '\0' || (*p == '.' && p[1] == '\0')))))
2253 debug_printf ("%s is a non-directory", path);
2255 goto file_not_symlink;
2258 /* A symlink will have the `system' file attribute. */
2259 /* Only files can be symlinks (which can be symlinks to directories). */
2260 if (!(pflags & PATH_SYMLINK) && !SYMLINKATTR (fileattr))
2261 goto file_not_symlink;
2263 /* Open the file. */
2265 h = CreateFileA (path, GENERIC_READ, FILE_SHARE_READ, &sec_none_nih, OPEN_EXISTING,
2266 FILE_ATTRIBUTE_NORMAL, 0);
2268 if (h == INVALID_HANDLE_VALUE)
2269 goto file_not_symlink;
2272 char cookie_buf[sizeof (SYMLINK_COOKIE) - 1];
2275 if (! ReadFile (h, cookie_buf, sizeof (cookie_buf), &got, 0))
2277 else if (got == sizeof (cookie_buf)
2278 && memcmp (cookie_buf, SYMLINK_COOKIE,
2279 sizeof (cookie_buf)) == 0)
2281 /* It's a symlink. */
2282 pflags = PATH_SYMLINK;
2284 res = ReadFile (h, contents, MAX_PATH + 1, &got, 0);
2289 /* Versions prior to b16 stored several trailing
2290 NULs with the path (to fill the path out to 1024
2291 chars). Current versions only store one trailing
2292 NUL. The length returned is the path without
2293 *any* trailing NULs. We also have to handle (or
2294 at least not die from) corrupted paths. */
2295 if (memchr (contents, 0, got) != NULL)
2296 res = strlen (contents);
2301 else if (got == sizeof (cookie_buf)
2302 && memcmp (cookie_buf, SOCKET_COOKIE,
2303 sizeof (cookie_buf)) == 0)
2305 pflags |= PATH_SOCKET;
2306 goto close_and_return;
2310 /* Not a symlink, see if executable. */
2311 if (!(pflags & (PATH_EXEC | PATH_CYGWIN_EXEC)) && got >= 2 &&
2312 ((cookie_buf[0] == '#' && cookie_buf[1] == '!') ||
2313 (cookie_buf[0] == ':' && cookie_buf[1] == '\n')))
2314 pflags |= PATH_EXEC;
2317 goto file_not_symlink;
2329 syscall_printf ("not a symlink");
2333 syscall_printf ("%d = symlink.check (%s, %p) (%p)",
2334 res, path, contents, pflags);
2339 /* readlink system call */
2343 readlink (const char *path, char *buf, int buflen)
2345 extern suffix_info stat_suffixes[];
2349 set_errno (ENAMETOOLONG);
2353 path_conv pathbuf (path, PC_SYM_CONTENTS, stat_suffixes);
2357 set_errno (pathbuf.error);
2358 syscall_printf ("-1 = readlink (%s, %p, %d)", path, buf, buflen);
2362 if (!pathbuf.issymlink ())
2364 if (pathbuf.fileattr != (DWORD) -1)
2369 int len = min (buflen, (int) strlen (pathbuf.get_win32 ()));
2370 memcpy (buf, pathbuf.get_win32 (), len);
2372 /* errno set by symlink.check if error */
2376 /* Some programs rely on st_dev/st_ino being unique for each file.
2377 Hash the path name and hope for the best. The hash arg is not
2378 always initialized to zero since readdir needs to compute the
2379 dirent ino_t based on a combination of the hash of the directory
2380 done during the opendir call and the hash or the filename within
2381 the directory. FIXME: Not bullet-proof. */
2382 /* Cygwin internal */
2384 unsigned long __stdcall
2385 hash_path_name (unsigned long hash, const char *name)
2390 /* Perform some initial permutations on the pathname if this is
2394 /* Simplistic handling of drives. If there is a drive specified,
2395 make sure that the initial letter is upper case. If there is
2396 no \ after the ':' assume access through the root directory
2398 FIXME: Should really honor MS-Windows convention of using
2399 the environment to track current directory on various drives. */
2402 char *nn, *newname = (char *) alloca (strlen (name) + 2);
2403 nn = strncpy (newname, name, 2);
2405 *newname = toupper (*nn);
2418 /* Fill out the hashed path name with the current working directory if
2419 this is not an absolute path and there is no pre-specified hash value.
2420 Otherwise the inodes same will differ depending on whether a file is
2421 referenced with an absolute value or relatively. */
2425 hash = cygcwd.get_hash ();
2426 if (name[0] == '.' && name[1] == '\0')
2428 hash = hash_path_name (hash, "\\");
2433 /* Build up hash. Ignore single trailing slash or \a\b\ != \a\b or
2434 \a\b\. but allow a single \ if that's all there is. */
2437 hash += *name + (*name << 17);
2440 while (*++name != '\0' &&
2441 !(*name == '\\' && (!name[1] || (name[1] == '.' && !name[2]))));
2446 getcwd (char *buf, size_t ulen)
2449 char *usebuf, uselen;
2463 ulen = MAX_PATH + 1;
2466 usebuf = (char *) malloc (ulen);
2467 usebuf [ulen - 1] = '\0';
2470 res = cygcwd.get (usebuf, 1, 1, ulen);
2473 usebuf = (char *) realloc (usebuf, strlen (usebuf) + 1);
2474 else if (!res && buf == NULL)
2480 /* getwd: standards? */
2485 return getcwd (buf, MAX_PATH);
2488 /* chdir: POSIX 5.2.1.1 */
2491 chdir (const char *dir)
2493 syscall_printf ("dir %s", dir);
2494 path_conv path (dir, PC_FULL | PC_SYM_FOLLOW);
2498 set_errno (path.error);
2499 syscall_printf ("-1 = chdir (%s)", dir);
2503 /* Look for trailing path component consisting entirely of dots. This
2504 is needed only in case of chdir since Windows simply ignores count
2505 of dots > 2 here instead of returning an error code. Counts of dots
2506 <= 2 are already eliminated by normalize_posix_path. */
2507 const char *p = strrchr (dir, '/');
2513 size_t len = strlen (p);
2514 if (len > 2 && strspn (p, ".") == len)
2520 char *native_dir = path.get_win32 ();
2522 /* Check to see if path translates to something like C:.
2523 If it does, append a \ to the native directory specification to
2524 defeat the Windows 95 (i.e. MS-DOS) tendency of returning to
2525 the last directory visited on the given drive. */
2526 if (isdrive (native_dir) && !native_dir[2])
2528 native_dir[2] = '\\';
2529 native_dir[3] = '\0';
2531 int res = SetCurrentDirectoryA (native_dir) ? 0 : -1;
2535 cygcwd.set (path, dir);
2537 /* Note that we're accessing cwd.posix without a lock here. I didn't think
2538 it was worth locking just for strace. */
2539 syscall_printf ("%d = chdir() cygcwd.posix '%s' native '%s'", res,
2540 cygcwd.posix, native_dir);
2544 /******************** Exported Path Routines *********************/
2546 /* Cover functions to the path conversion routines.
2547 These are exported to the world as cygwin_foo by cygwin.din. */
2551 cygwin_conv_to_win32_path (const char *path, char *win32_path)
2553 path_conv p (path, PC_SYM_FOLLOW);
2556 set_errno (p.error);
2560 strcpy (win32_path, p.get_win32 ());
2566 cygwin_conv_to_full_win32_path (const char *path, char *win32_path)
2568 path_conv p (path, PC_SYM_FOLLOW | PC_FULL);
2571 set_errno (p.error);
2575 strcpy (win32_path, p.get_win32 ());
2579 /* This is exported to the world as cygwin_foo by cygwin.din. */
2583 cygwin_conv_to_posix_path (const char *path, char *posix_path)
2585 if (check_null_empty_path_errno (path))
2587 cygwin_shared->mount.conv_to_posix_path (path, posix_path, 1);
2593 cygwin_conv_to_full_posix_path (const char *path, char *posix_path)
2595 if (check_null_empty_path_errno (path))
2597 cygwin_shared->mount.conv_to_posix_path (path, posix_path, 0);
2601 /* The realpath function is supported on some UNIX systems. */
2605 realpath (const char *path, char *resolved)
2609 path_conv real_path (path, PC_SYM_FOLLOW | PC_FULL);
2611 if (real_path.error)
2612 err = real_path.error;
2615 err = cygwin_shared->mount.conv_to_posix_path (real_path.get_win32 (), resolved, 0);
2620 /* FIXME: on error, we are supposed to put the name of the path
2621 component which could not be resolved into RESOLVED. */
2628 /* Return non-zero if path is a POSIX path list.
2629 This is exported to the world as cygwin_foo by cygwin.din.
2632 <sect1 id="add-func-cygwin-posix-path-list-p">
2633 <para>Rather than use a mode to say what the "proper" path list
2634 format is, we allow any, and give apps the tools they need to
2635 convert between the two. If a ';' is present in the path list it's
2636 a Win32 path list. Otherwise, if the first path begins with
2637 [letter]: (in which case it can be the only element since if it
2638 wasn't a ';' would be present) it's a Win32 path list. Otherwise,
2639 it's a POSIX path list.</para>
2646 cygwin_posix_path_list_p (const char *path)
2648 int posix_p = ! (strchr (path, ';') || isdrive (path));
2652 /* These are used for apps that need to convert env vars like PATH back and
2653 forth. The conversion is a two step process. First, an upper bound on the
2654 size of the buffer needed is computed. Then the conversion is done. This
2655 allows the caller to use alloca if it wants. */
2658 conv_path_list_buf_size (const char *path_list, int to_posix_p)
2660 int i, num_elms, max_mount_path_len, size;
2663 /* The theory is that an upper bound is
2664 current_size + (num_elms * max_mount_path_len) */
2666 char delim = to_posix_p ? ';' : ':';
2668 for (num_elms = 1; (p = strchr (p, delim)) != NULL; ++num_elms)
2671 /* 7: strlen ("//c") + slop, a conservative initial value */
2672 for (max_mount_path_len = 7, i = 0; i < cygwin_shared->mount.nmounts; ++i)
2674 int mount_len = (to_posix_p
2675 ? cygwin_shared->mount.mount[i].posix_pathlen
2676 : cygwin_shared->mount.mount[i].native_pathlen);
2677 if (max_mount_path_len < mount_len)
2678 max_mount_path_len = mount_len;
2682 size = strlen (path_list) + (num_elms * max_mount_path_len) + 100;
2688 cygwin_win32_to_posix_path_list_buf_size (const char *path_list)
2690 return conv_path_list_buf_size (path_list, 1);
2695 cygwin_posix_to_win32_path_list_buf_size (const char *path_list)
2697 return conv_path_list_buf_size (path_list, 0);
2702 cygwin_win32_to_posix_path_list (const char *win32, char *posix)
2704 conv_path_list (win32, posix, 1);
2710 cygwin_posix_to_win32_path_list (const char *posix, char *win32)
2712 conv_path_list (posix, win32, 0);
2716 /* cygwin_split_path: Split a path into directory and file name parts.
2717 Buffers DIR and FILE are assumed to be big enough.
2719 Examples (path -> `dir' / `file'):
2722 . -> `.' / `.' (FIXME: should this be `.' / `'?)
2723 .. -> `.' / `..' (FIXME: should this be `..' / `'?)
2725 foo/bar -> `foo' / `bar'
2726 foo/bar/ -> `foo' / `bar'
2728 /foo/bar -> `/foo' / `bar'
2731 c:foo -> `c:/' / `foo'
2732 c:/foo -> `c:/' / `foo'
2737 cygwin_split_path (const char *path, char *dir, char *file)
2739 int dir_started_p = 0;
2741 /* Deal with drives.
2742 Remember that c:foo <==> c:/foo. */
2754 if (SLASH_P (*path))
2759 /* Determine if there are trailing slashes and "delete" them if present.
2760 We pretend as if they don't exist. */
2761 const char *end = path + strlen (path);
2762 /* path + 1: keep leading slash. */
2763 while (end > path + 1 && SLASH_P (end[-1]))
2766 /* At this point, END points to one beyond the last character
2767 (with trailing slashes "deleted"). */
2769 /* Point LAST_SLASH at the last slash (duh...). */
2770 const char *last_slash;
2771 for (last_slash = end - 1; last_slash >= path; --last_slash)
2772 if (SLASH_P (*last_slash))
2775 if (last_slash == path)
2780 else if (last_slash > path)
2782 memcpy (dir, path, last_slash - path);
2783 dir[last_slash - path] = 0;
2788 ; /* nothing to do */
2794 memcpy (file, last_slash + 1, end - last_slash - 1);
2795 file[end - last_slash - 1] = 0;
2798 /********************** String Helper Functions ************************/
2800 #define CHXOR ('a' ^ 'A')
2801 #define ch_case_eq(ch1, ch2) \
2804 !((x = ((unsigned char)ch1 ^ (unsigned char)ch2)) && \
2805 (x != CHXOR || !isalpha (ch1))); \
2808 /* Return TRUE if two strings match up to length n */
2810 strncasematch (const char *s1, const char *s2, size_t n)
2818 if (!ch_case_eq (*s1, *s2))
2822 return !n || *s2 == '\0';
2825 /* Return TRUE if two strings match */
2827 strcasematch (const char *s1, const char *s2)
2834 if (!ch_case_eq (*s1, *s2))
2842 strcasestr (const char *searchee, const char *lookfor)
2848 return (char *) searchee;
2856 if (lookfor[i] == 0)
2857 return (char *) searchee;
2859 if (!ch_case_eq (lookfor[i], searchee[i]))
2870 check_null_empty_path (const char *name)
2872 MEMORY_BASIC_INFORMATION m;
2873 if (!name || !VirtualQuery (name, &m, sizeof (m)) || (m.State != MEM_COMMIT))
2882 /* Return the hash value for the current win32 value.
2883 This is used when constructing inodes. */
2885 cwdstuff::get_hash ()
2894 /* Initialize cygcwd 'muto' for serializing access to cwd info. */
2898 lock = new_muto (FALSE, "cwd");
2901 /* Called to fill in cwd values after an exec. */
2903 cwdstuff::fixup_after_exec (char *win32_cwd, char *posix_cwd, DWORD hash_cwd)
2910 /* Get initial cwd. Should only be called once in a
2913 cwdstuff::get_initial ()
2921 for (i = 0, dlen = MAX_PATH, len = 0; i < 3; dlen *= 2, i++)
2923 win32 = (char *) crealloc (win32, dlen + 2);
2924 if ((len = GetCurrentDirectoryA (dlen, win32)) < dlen)
2932 debug_printf ("get_initial_cwd failed, %E");
2936 return 1; /* Leaves cwd lock unreleased */
2939 /* Fill out the elements of a cwdstuff struct.
2940 It is assumed that the lock for the cwd is acquired if
2941 win32_cwd == NULL. */
2943 cwdstuff::set (const char *win32_cwd, const char *posix_cwd)
2945 char pathbuf[MAX_PATH];
2950 win32 = (char *) crealloc (win32, strlen (win32_cwd) + 1);
2951 strcpy (win32, win32_cwd);
2955 cygwin_shared->mount.conv_to_posix_path (win32, pathbuf, 0);
2957 (void) normalize_posix_path (posix_cwd, pathbuf);
2959 posix = (char *) crealloc (posix, strlen (pathbuf) + 1);
2960 strcpy (posix, pathbuf);
2962 hash = hash_path_name (0, win32);
2970 /* Copy the value for either the posix or the win32 cwd into a buffer. */
2972 cwdstuff::get (char *buf, int need_posix, int with_chroot, unsigned ulen)
2976 if (!get_initial ()) /* Get initial cwd and set cwd lock */
2983 tocopy = with_chroot && ischrootpath(posix) ?
2984 posix + myself->rootlen : posix;
2986 debug_printf("myself->root: %s, posix: %s", myself->root, posix);
2987 if (strlen (tocopy) >= ulen)
2994 strcpy (buf, tocopy);
2995 if (!buf[0]) /* Should only happen when chroot */
3000 syscall_printf ("(%s) = cwdstuff::get (%p, %d, %d, %d)",
3001 buf, buf, len, need_posix, with_chroot);
3005 /* Get copies of all cwdstuff elements. Used by spawn_guts. */
3007 cwdstuff::copy (char * &posix_cwd, char * &win32_cwd, DWORD hash_cwd)
3010 get_initial (); /* FIXME: Check return someday */
3011 posix_cwd = cstrdup (posix);
3012 win32_cwd = cstrdup (win32);