📄 path.cc
字号:
(pathbuf[n] == '/' && pathbuf[n + 1] == '.' && !pathbuf[n + 2])) { unit = 0; dst[0] = '\0'; if (mount_table->cygdrive_len > 1) devn = FH_CYGDRIVE; } else if (cygdrive_win32_path (pathbuf, dst, unit)) { set_flags (flags, (unsigned) cygdrive_flags); goto out; } else if (mount_table->cygdrive_len > 1) return ENOENT; } int chrooted_path_len; chrooted_path_len = 0; /* Check the mount table for prefix matches. */ for (i = 0; i < nmounts; i++) { const char *path; int len; mi = mount + posix_sorted[i]; if (!cygheap->root.exists () || (mi->posix_pathlen == 1 && mi->posix_path[0] == '/')) { path = mi->posix_path; len = mi->posix_pathlen; } else if (cygheap->root.posix_ok (mi->posix_path)) { path = cygheap->root.unchroot (mi->posix_path); chrooted_path_len = len = strlen (path); } else { chrooted_path_len = 0; continue; } if (path_prefix_p (path, pathbuf, len)) break; } if (i >= nmounts) { backslashify (pathbuf, dst, 0); /* just convert */ set_flags (flags, PATH_BINARY); } else { int n; const char *native_path; int posix_pathlen; if (chroot_ok || chrooted_path_len || mi->posix_pathlen != 1 || mi->posix_path[0] != '/') { n = mi->native_pathlen; native_path = mi->native_path; posix_pathlen = chrooted_path_len ?: mi->posix_pathlen; chroot_ok = 1; } else { n = cygheap->root.native_length (); native_path = cygheap->root.native_path (); posix_pathlen = mi->posix_pathlen; chroot_ok = 1; } memcpy (dst, native_path, n + 1); const char *p = pathbuf + posix_pathlen; if (*p == '/') /* nothing */; else if ((isdrive (dst) && !dst[2]) || *p) dst[n++] = '\\'; strcpy (dst + n, p); backslashify (dst, dst, 0); set_flags (flags, (unsigned) mi->flags); } if (!isvirtual_dev (devn)) win32_device_name (src_path, dst, devn, unit); out: MALLOC_CHECK; if (chroot_ok || cygheap->root.ischroot_native (dst)) rc = 0; else { debug_printf ("attempt to access outside of chroot '%s = %s'", cygheap->root.posix_path (), cygheap->root.native_path ()); rc = ENOENT; } out_no_chroot_check: debug_printf ("src_path %s, dst %s, flags %p, rc %d", src_path, dst, *flags, rc); return rc;}/* cygdrive_posix_path: Build POSIX path used as the mount point for cygdrives created when there is no other way to obtain a POSIX path from a Win32 one. */voidmount_info::cygdrive_posix_path (const char *src, char *dst, int trailing_slash_p){ int len = cygdrive_len; memcpy (dst, cygdrive, len + 1); /* Now finish the path off with the drive letter to be used. The cygdrive prefix always ends with a trailing slash so the drive letter is added after the path. */ dst[len++] = cyg_tolower (src[0]); if (!src[2] || (SLASH_P (src[2]) && !src[3])) dst[len++] = '\000'; else { int n; dst[len++] = '/'; if (SLASH_P (src[2])) n = 3; else n = 2; strcpy (dst + len, src + n); } slashify (dst, dst, trailing_slash_p);}intmount_info::cygdrive_win32_path (const char *src, char *dst, int& unit){ int res; const char *p = src + cygdrive_len; if (!isalpha (*p) || (!isdirsep (p[1]) && p[1])) { unit = -1; dst[0] = '\0'; res = 0; } else { dst[0] = cyg_tolower (*p); dst[1] = ':'; strcpy (dst + 2, p + 1); backslashify (dst, dst, !dst[2]); unit = dst[0]; res = 1; } debug_printf ("src '%s', dst '%s'", src, dst); return res;}/* conv_to_posix_path: Ensure src_path is a POSIX path. The result is zero for success, or an errno value. posix_path must have sufficient space (i.e. MAX_PATH bytes). If keep_rel_p is non-zero, relative paths stay that way. */intmount_info::conv_to_posix_path (const char *src_path, char *posix_path, int keep_rel_p){ int src_path_len = strlen (src_path); int relative_path_p = !isabspath (src_path); int trailing_slash_p; if (src_path_len <= 1) trailing_slash_p = 0; else { const char *lastchar = src_path + src_path_len - 1; trailing_slash_p = SLASH_P (*lastchar) && lastchar[-1] != ':'; } debug_printf ("conv_to_posix_path (%s, %s, %s)", src_path, keep_rel_p ? "keep-rel" : "no-keep-rel", trailing_slash_p ? "add-slash" : "no-add-slash"); MALLOC_CHECK; if (src_path_len >= MAX_PATH) { debug_printf ("ENAMETOOLONG"); return ENAMETOOLONG; } /* FIXME: For now, if the path is relative and it's supposed to stay that way, skip mount table processing. */ if (keep_rel_p && relative_path_p) { slashify (src_path, posix_path, 0); debug_printf ("%s = conv_to_posix_path (%s)", posix_path, src_path); return 0; } char pathbuf[MAX_PATH]; int rc = normalize_win32_path (src_path, pathbuf); if (rc != 0) { debug_printf ("%d = conv_to_posix_path (%s)", rc, src_path); return rc; } int pathbuflen = strlen (pathbuf); for (int i = 0; i < nmounts; ++i) { mount_item &mi = mount[native_sorted[i]]; if (!path_prefix_p (mi.native_path, pathbuf, mi.native_pathlen)) continue; if (cygheap->root.exists () && !cygheap->root.posix_ok (mi.posix_path)) continue; /* SRC_PATH is in the mount table. */ int nextchar; const char *p = pathbuf + mi.native_pathlen; if (!*p || !p[1]) nextchar = 0; else if (isdirsep (*p)) nextchar = -1; else nextchar = 1; int addslash = nextchar > 0 ? 1 : 0; if ((mi.posix_pathlen + (pathbuflen - mi.native_pathlen) + addslash) >= MAX_PATH) return ENAMETOOLONG; strcpy (posix_path, mi.posix_path); if (addslash) strcat (posix_path, "/"); if (nextchar) slashify (p, posix_path + addslash + (mi.posix_pathlen == 1 ? 0 : mi.posix_pathlen), trailing_slash_p); if (cygheap->root.exists ()) { const char *p = cygheap->root.unchroot (posix_path); memmove (posix_path, p, strlen (p) + 1); } goto out; } if (!cygheap->root.exists ()) /* nothing */; else if (cygheap->root.ischroot_native (pathbuf)) { const char *p = pathbuf + cygheap->root.native_length (); if (*p) slashify (p, posix_path, trailing_slash_p); else { posix_path[0] = '/'; posix_path[1] = '\0'; } } else return ENOENT; /* Not in the database. This should [theoretically] only happen if either the path begins with //, or / isn't mounted, or the path has a drive letter not covered by the mount table. If it's a relative path then the caller must want an absolute path (otherwise we would have returned above). So we always return an absolute path at this point. */ if (isdrive (pathbuf)) cygdrive_posix_path (pathbuf, posix_path, trailing_slash_p); else { /* The use of src_path and not pathbuf here is intentional. We couldn't translate the path, so just ensure no \'s are present. */ slashify (src_path, posix_path, trailing_slash_p); }out: debug_printf ("%s = conv_to_posix_path (%s)", posix_path, src_path); MALLOC_CHECK; return 0;}/* Return flags associated with a mount point given the win32 path. */unsignedmount_info::set_flags_from_win32_path (const char *p){ for (int i = 0; i < nmounts; i++) { mount_item &mi = mount[native_sorted[i]]; if (path_prefix_p (mi.native_path, p, mi.native_pathlen)) return mi.flags; } return PATH_BINARY;}/* read_mounts: Given a specific regkey, read mounts from under its key. */voidmount_info::read_mounts (reg_key& r){ char posix_path[MAX_PATH]; HKEY key = r.get_key (); DWORD i, posix_path_size; int res; /* Loop through subkeys */ /* FIXME: we would like to not check MAX_MOUNTS but the heap in the shared area is currently statically allocated so we can't have an arbitrarily large number of mounts. */ for (i = 0; ; i++) { char native_path[MAX_PATH]; int mount_flags; posix_path_size = MAX_PATH; /* FIXME: if maximum posix_path_size is 256, we're going to run into problems if we ever try to store a mount point that's over 256 but is under MAX_PATH. */ res = RegEnumKeyEx (key, i, posix_path, &posix_path_size, NULL, NULL, NULL, NULL); if (res == ERROR_NO_MORE_ITEMS) break; else if (res != ERROR_SUCCESS) { debug_printf ("RegEnumKeyEx failed, error %d!", res); break; } /* Get a reg_key based on i. */ reg_key subkey = reg_key (key, KEY_READ, posix_path, NULL); /* Fetch info from the subkey. */ subkey.get_string ("native", native_path, sizeof (native_path), ""); mount_flags = subkey.get_int ("flags", 0); /* Add mount_item corresponding to registry mount point. */ res = mount_table->add_item (native_path, posix_path, mount_flags, false); if (res && get_errno () == EMFILE) break; /* The number of entries exceeds MAX_MOUNTS */ }}/* from_registry: Build the entire mount table from the registry. Also, read in cygdrive-related information from its registry location. */voidmount_info::from_registry (){ /* Use current mount areas if either user or system mount areas already exist. Otherwise, import old mounts. */ reg_key r; /* Retrieve cygdrive-related information. */ read_cygdrive_info_from_registry (); nmounts = 0; /* First read mounts from user's table. */ read_mounts (r); /* Then read mounts from system-wide mount table. */ reg_key r1 (HKEY_LOCAL_MACHINE, KEY_READ, "SOFTWARE", CYGWIN_INFO_CYGNUS_REGISTRY_NAME, CYGWIN_REGNAME, CYGWIN_INFO_CYGWIN_MOUNT_REGISTRY_NAME, NULL); read_mounts (r1);}/* add_reg_mount: Add mount item to registry. Return zero on success, non-zero on failure. *//* FIXME: Need a mutex to avoid collisions with other tasks. */intmount_info::add_reg_mount (const char * native_path, const char * posix_path, unsigned mountflags){ int res = 0; /* Add the mount to the right registry location, depending on whether MOUNT_SYSTEM is set in the mount flags. */ if (!(mountflags & MOUNT_SYSTEM)) /* current_user mount */ { /* reg_key for user mounts in HKEY_CURRENT_USER. */ reg_key reg_user; /* Start by deleting existing mount if one exists. */ res = reg_user.kill (posix_path); if (res != ERROR_SUCCESS && res != ERROR_FILE_NOT_FOUND) goto err; /* Create the new mount. */ reg_key subkey = reg_key (reg_user.get_key (), KEY_ALL_ACCESS, posix_path, NULL); res = subkey.set_string ("native", native_path); if (res != ERROR_SUCCESS) goto err; res = subkey.set_int ("flags", mountflags); } else /* local_machine mount */ { /* reg_key for system mounts in HKEY_LOCAL_MACHINE. */ reg_key reg_sys (HKEY_LOCAL_MACHINE, KEY_ALL_ACCESS, "SOFTWARE", CYGWIN_INFO_CYGNUS_REGISTRY_NAME, CYGWIN_REGNAME, CYGWIN_INFO_CYGWIN_MOUNT_REGISTRY_NAME, NULL); /* Start by deleting existing mount if one exists. */ res = reg_sys.kill (posix_path); if (res != ERROR_SUCCESS && res != ERROR_FILE_NOT_FOUND) goto err; /* Create the new mount. */ reg_key subkey = reg_key (reg_sys.get_key (), KEY_ALL_ACCESS, posix_path, NULL); res = subkey.set_string ("native", native_path); if (res != ERROR_SUCCESS) goto err; res = subkey.set_int ("flags", mountflags); sys_mount_table_counter++; cygwin_shared->sys_mount_table_counter++; } return 0; /* Success */ err: __seterrno_from_win_error (res); return -1;}/* del_reg_mount: delete mount item from registry indicated in flags. Return zero on success, non-zero on failure.*//* FIXME: Need a mutex to avoid collisions with other tasks. */intmount_info::del_reg_mount (const char * posix_path, unsigned flags){ int res; if (!(flags & MOUNT_SYSTEM)) /* Delete from user registry */ { reg_key reg_user (KEY_ALL_ACCESS, CYGWIN_INFO_CYGWIN_MOUNT_REGISTRY_NAME, NULL); res = reg_user.kill (posix_path); } else /* Delete from system registry */ { sys_mount_table_counter++; cygwin_shared->sys_mount_table_counter++; reg_key reg_sys (HKEY_LOCAL_MACHINE, KEY_ALL_ACCESS, "SOFTWARE", CYGWIN_INFO_CYGNUS_REGISTRY_NAME, CYGWIN_REGNAME, CYGWIN_INFO_CYGWIN_MOUNT_REGISTRY_NAME, NULL); res = reg_sys.kill (posix_path); } if (res != ERROR_SUCCESS) { __seterrno_from_win_error (res); return -1; } return 0; /* Success */}/* read_cygdrive_info_from_registry: Read the default prefix and flags to use when creating cygdrives from the special user registry location used to store cygdrive information. */voidmount_info::read_cygdrive_info_from_registry (){ /* reg_key for user path prefix in HKEY_CURRENT_USER. */ reg_key r; if (r.get_string (CYGWIN_INFO_CYGDRIVE_PREFIX, cygdrive, sizeof (cygdrive), "") != 0) { /* Didn't find the user path prefix so check the system path prefix. */ /* reg_key for system path prefix in HKEY_LOCAL_MACHINE. */ reg_key r2 (HKEY_LOCAL_MACHINE, KEY_READ, "SOFTWARE", CYGWIN_INFO_CYGNUS_REGISTRY_NAME, CYGWIN_REGNAME, CYGWIN_INFO_CYGWIN_MOUNT_REGISTRY_NAME, NULL); if (r2.get_string (CYGWIN_INFO_CYGDRIVE_PREFIX, cygdrive, sizeof (cygdrive), "")) strcpy (cygdrive, CYGWIN_INFO_CYGDRIVE_DEFAULT_PREFIX); cygdrive_flags = r2.get_int (CYGWIN_INFO_CYGDRIVE_FLAGS, MOUNT_CYGDRIVE); slashify (cygdrive, cygdrive, 1); cygdrive_len = strlen (cygdrive);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -