📄 path.cc
字号:
... FH_FLOPPY 250 from mount tab \\.\Z:*/static intget_raw_device_number (const char *name, const char *w32_path, int &unit){ DWORD devn = FH_BAD; if (!w32_path) /* New approach using fixed device names. */ { if (deveqn ("st", 2)) { unit = digits (name + 2); if (unit >= 0 && unit < 128) devn = FH_TAPE; } else if (deveqn ("nst", 3)) { unit = digits (name + 3) + 128; if (unit >= 128 && unit < 256) devn = FH_TAPE; } else if (deveqn ("fd", 2)) { unit = digits (name + 2); if (unit >= 0 && unit < 16) devn = FH_FLOPPY; } else if (deveqn ("scd", 3)) { unit = digits (name + 3) + 16; if (unit >= 16 && unit < 32) devn = FH_FLOPPY; } else if (deveqn ("sd", 2) && isalpha (name[2])) { unit = (cyg_tolower (name[2]) - 'a') * 16 + 32; if (unit >= 32 && unit < 224) if (!name[3]) devn = FH_FLOPPY; else { int d = digits (name + 3); if (d >= 1 && d < 16) { unit += d; devn = FH_FLOPPY; } } } } else /* Backward compatible checking of mount table device mapping. */ { if (wdeveqn ("tape", 4)) { unit = digits (w32_path + 4); /* Norewind tape devices have leading n in name. */ if (deveqn ("n", 1)) unit += 128; devn = FH_TAPE; } else if (wdeveqn ("physicaldrive", 13)) { unit = digits (w32_path + 13) * 16 + 32; devn = FH_FLOPPY; } else if (isdrive (w32_path)) { unit = cyg_tolower (w32_path[0]) - 'a' + 224; devn = FH_FLOPPY; } } return devn;}static int __stdcall get_device_number (const char *unix_path, const char *w32_path, int &unit) __attribute__ ((regparm(3)));static int __stdcallget_device_number (const char *unix_path, const char *w32_path, int &unit){ DWORD devn = FH_BAD; unit = 0; if (*unix_path == '/' && udeveqn ("/dev/", 5)) { devn = get_devn (unix_path, unit); if (devn == FH_BAD && *w32_path == '\\' && wdeveqn ("\\dev\\", 5)) devn = get_devn (w32_path, unit); if (devn == FH_BAD && wdeveqn ("\\\\.\\", 4)) devn = get_raw_device_number (unix_path + 5, w32_path + 4, unit); if (devn == FH_BAD) devn = get_raw_device_number (unix_path + 5, NULL, unit); } else { char *p = strrchr (unix_path, '/'); if (p) unix_path = p + 1; if (udeveqn ("com", 3) && (unit = digits (unix_path + 3)) >= 0 && unit < 100) devn = FH_SERIAL; } return devn;}/* Return TRUE if src_path is a Win32 device name, filling out the device name in win32_path */static BOOLwin32_device_name (const char *src_path, char *win32_path, DWORD &devn, int &unit){ const char *devfmt; devn = get_device_number (src_path, win32_path, unit); if (devn == FH_BAD) return false; if ((devfmt = windows_device_names[FHDEVN (devn)]) == NULL) return false; switch (devn) { case FH_RANDOM: __small_sprintf (win32_path, devfmt, unit == 8 ? "" : "u"); break; case FH_TAPE: __small_sprintf (win32_path, "\\Device\\Tape%d", unit % 128); break; case FH_FLOPPY: if (unit < 16) __small_sprintf (win32_path, "\\Device\\Floppy%d", unit); else if (unit < 32) __small_sprintf (win32_path, "\\Device\\CdRom%d", unit - 16); else if (unit < 224) __small_sprintf (win32_path, "\\Device\\Harddisk%d\\Partition%d", (unit - 32) / 16, unit % 16); else __small_sprintf (win32_path, "\\DosDevices\\%c:", unit - 224 + 'A'); break; default: __small_sprintf (win32_path, devfmt, unit); break; } return TRUE;}/* Normalize a Win32 path. /'s are converted to \'s in the process. All duplicate \'s, except for 2 leading \'s, are deleted. The result is 0 for success, or an errno error value. FIXME: A lot of this should be mergeable with the POSIX critter. */static intnormalize_win32_path (const char *src, char *dst){ const char *src_start = src; char *dst_start = dst; char *dst_root_start = dst; bool beg_src_slash = isdirsep (src[0]); if (beg_src_slash && isdirsep (src[1])) { *dst++ = '\\'; src++; if (src[1] == '.' && isdirsep (src[2])) { *dst++ = '\\'; *dst++ = '.'; src += 2; } } else if (strchr (src, ':') == NULL && *src != '/') { if (!cygheap->cwd.get (dst, 0)) return get_errno (); if (beg_src_slash) { if (dst[1] == ':') dst[2] = '\0'; else if (slash_unc_prefix_p (dst)) { char *p = strpbrk (dst + 2, "\\/"); if (p && (p = strpbrk (p + 1, "\\/"))) *p = '\0'; } } if (strlen (dst) + 1 + strlen (src) >= MAX_PATH) { debug_printf ("ENAMETOOLONG = normalize_win32_path (%s)", src); return ENAMETOOLONG; } dst += strlen (dst); if (!beg_src_slash) *dst++ = '\\'; } while (*src) { /* Strip duplicate /'s. */ if (SLASH_P (src[0]) && SLASH_P (src[1])) src++; /* Ignore "./". */ else if (src[0] == '.' && SLASH_P (src[1]) && (src == src_start || SLASH_P (src[-1]))) src += 2; /* Backup if "..". */ else if (src[0] == '.' && src[1] == '.' /* dst must be greater than dst_start */ && dst[-1] == '\\' && (SLASH_P (src[2]) || src[2] == 0)) { /* Back up over /, but not if it's the first one. */ if (dst > dst_root_start + 1) dst--; /* Now back up to the next /. */ while (dst > dst_root_start + 1 && dst[-1] != '\\' && dst[-2] != ':') dst--; src += 2; if (SLASH_P (*src)) src++; } /* Otherwise, add char to result. */ else { if (*src == '/') *dst++ = '\\'; else *dst++ = *src; ++src; } if ((dst - dst_start) >= MAX_PATH) return ENAMETOOLONG; } *dst = 0; debug_printf ("%s = normalize_win32_path (%s)", dst_start, src_start); return 0;}/* Various utilities. *//* slashify: Convert all back slashes in src path to forward slashes in dst path. Add a trailing slash to dst when trailing_slash_p arg is set to 1. */static voidslashify (const char *src, char *dst, int trailing_slash_p){ const char *start = src; while (*src) { if (*src == '\\') *dst++ = '/'; else *dst++ = *src; ++src; } if (trailing_slash_p && src > start && !isdirsep (src[-1])) *dst++ = '/'; *dst++ = 0;}/* backslashify: Convert all forward slashes in src path to back slashes in dst path. Add a trailing slash to dst when trailing_slash_p arg is set to 1. */static voidbackslashify (const char *src, char *dst, int trailing_slash_p){ const char *start = src; while (*src) { if (*src == '/') *dst++ = '\\'; else *dst++ = *src; ++src; } if (trailing_slash_p && src > start && !isdirsep (src[-1])) *dst++ = '\\'; *dst++ = 0;}/* nofinalslash: Remove trailing / and \ from SRC (except for the first one). It is ok for src == dst. */void __stdcallnofinalslash (const char *src, char *dst){ int len = strlen (src); if (src != dst) memcpy (dst, src, len + 1); while (len > 1 && SLASH_P (dst[--len])) dst[len] = '\0';}/* slash_unc_prefix_p: Return non-zero if PATH begins with //UNC/SHARE */int __stdcallslash_unc_prefix_p (const char *path){ char *p = NULL; int ret = (isdirsep (path[0]) && isdirsep (path[1]) && isalpha (path[2]) && path[3] != 0 && !isdirsep (path[3]) && ((p = strpbrk (path + 3, "\\/")) != NULL)); if (!ret || p == NULL) return ret; return ret && isalnum (p[1]);}/* conv_path_list: Convert a list of path names to/from Win32/POSIX. */static voidconv_path_list (const char *src, char *dst, int to_posix_p){ char *s; char *d = dst; char src_delim = to_posix_p ? ';' : ':'; char dst_delim = to_posix_p ? ':' : ';'; int (*conv_fn) (const char *, char *) = (to_posix_p ? cygwin_conv_to_posix_path : cygwin_conv_to_win32_path); char *srcbuf = (char *) alloca (strlen (src) + 1); for (;;) { s = strccpy (srcbuf, &src, src_delim); int len = s - srcbuf; if (len >= MAX_PATH) srcbuf[MAX_PATH - 1] = '\0'; (*conv_fn) (len ? srcbuf : ".", d); if (!*src++) break; d = strchr (d, '\0'); *d++ = dst_delim; }}/* init: Initialize the mount table. */voidmount_info::init (){ nmounts = 0; /* Fetch the mount table and cygdrive-related information from the registry. */ from_registry ();}static voidset_flags (unsigned *flags, unsigned val){ *flags = val; if (!(*flags & PATH_BINARY)) { *flags |= PATH_TEXT; debug_printf ("flags: text (%p)", *flags & (PATH_TEXT | PATH_BINARY)); } else { *flags |= PATH_BINARY; debug_printf ("flags: binary (%p)", *flags & (PATH_TEXT | PATH_BINARY)); }}/* conv_to_win32_path: Ensure src_path is a pure Win32 path and store the result in win32_path. If win32_path != NULL, the relative path, if possible to keep, is stored in win32_path. If the relative path isn't possible to keep, the full path is stored. If full_win32_path != NULL, the full path is stored there. The result is zero for success, or an errno value. {,full_}win32_path must have sufficient space (i.e. MAX_PATH bytes). */intmount_info::conv_to_win32_path (const char *src_path, char *dst, DWORD &devn, int &unit, unsigned *flags, bool no_normalize){ while (sys_mount_table_counter < cygwin_shared->sys_mount_table_counter) { init (); sys_mount_table_counter++; } int src_path_len = strlen (src_path); MALLOC_CHECK; unsigned dummy_flags; int chroot_ok = !cygheap->root.exists (); devn = FH_BAD; unit = 0; if (!flags) flags = &dummy_flags; *flags = 0; debug_printf ("conv_to_win32_path (%s)", src_path); if (src_path_len >= MAX_PATH) { debug_printf ("ENAMETOOLONG = conv_to_win32_path (%s)", src_path); return ENAMETOOLONG; } int i, rc; mount_item *mi = NULL; /* initialized to avoid compiler warning */ char pathbuf[MAX_PATH]; if (dst == NULL) goto out; /* Sanity check. */ /* An MS-DOS spec has either a : or a \. If this is found, short circuit most of the rest of this function. */ if (strpbrk (src_path, ":\\") != NULL || slash_unc_prefix_p (src_path)) { debug_printf ("%s already win32", src_path); rc = normalize_win32_path (src_path, dst); if (rc) { debug_printf ("normalize_win32_path failed, rc %d", rc); return rc; } set_flags (flags, (unsigned) set_flags_from_win32_path (dst)); goto out; } /* Normalize the path, taking out ../../ stuff, we need to do this so that we can move from one mounted directory to another with relative stuff. eg mounting c:/foo /foo d:/bar /bar cd /bar ls ../foo should look in c:/foo, not d:/foo. We do this by first getting an absolute UNIX-style path and then converting it to a DOS-style path, looking up the appropriate drive in the mount table. */ if (no_normalize) strcpy (pathbuf, src_path); else { rc = normalize_posix_path (src_path, pathbuf); if (rc) { debug_printf ("%d = conv_to_win32_path (%s)", rc, src_path); return rc; } } /* See if this is a cygwin "device" */ if (win32_device_name (pathbuf, dst, devn, unit)) { *flags = MOUNT_BINARY; /* FIXME: Is this a sensible default for devices? */ rc = 0; goto out_no_chroot_check; } /* Check if the cygdrive prefix was specified. If so, just strip off the prefix and transform it into an MS-DOS path. */ MALLOC_CHECK; if (isproc (pathbuf)) { devn = fhandler_proc::get_proc_fhandler (pathbuf); if (devn == FH_BAD) return ENOENT; } else if (iscygdrive (pathbuf)) { int n = mount_table->cygdrive_len - 1; if (!pathbuf[n] ||
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -