📄 path.cc
字号:
} else { /* Fetch user cygdrive_flags from registry; returns MOUNT_CYGDRIVE on error. */ cygdrive_flags = r.get_int (CYGWIN_INFO_CYGDRIVE_FLAGS, MOUNT_CYGDRIVE); slashify (cygdrive, cygdrive, 1); cygdrive_len = strlen (cygdrive); }}/* write_cygdrive_info_to_registry: Write the default prefix and flags to use when creating cygdrives to the special user registry location used to store cygdrive information. */intmount_info::write_cygdrive_info_to_registry (const char *cygdrive_prefix, unsigned flags){ /* Determine whether to modify user or system cygdrive path prefix. */ HKEY top = (flags & MOUNT_SYSTEM) ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; if (flags & MOUNT_SYSTEM) { sys_mount_table_counter++; cygwin_shared->sys_mount_table_counter++; } /* reg_key for user path prefix in HKEY_CURRENT_USER or system path prefix in HKEY_LOCAL_MACHINE. */ reg_key r (top, KEY_ALL_ACCESS, "SOFTWARE", CYGWIN_INFO_CYGNUS_REGISTRY_NAME, CYGWIN_REGNAME, CYGWIN_INFO_CYGWIN_MOUNT_REGISTRY_NAME, NULL); /* Verify cygdrive prefix starts with a forward slash and if there's another character, it's not a slash. */ if ((cygdrive_prefix == NULL) || (*cygdrive_prefix == 0) || (!isslash (cygdrive_prefix[0])) || ((cygdrive_prefix[1] != '\0') && (isslash (cygdrive_prefix[1])))) { set_errno (EINVAL); return -1; } char hold_cygdrive_prefix[strlen (cygdrive_prefix) + 1]; /* Ensure that there is never a final slash */ nofinalslash (cygdrive_prefix, hold_cygdrive_prefix); int res; res = r.set_string (CYGWIN_INFO_CYGDRIVE_PREFIX, hold_cygdrive_prefix); if (res != ERROR_SUCCESS) { __seterrno_from_win_error (res); return -1; } r.set_int (CYGWIN_INFO_CYGDRIVE_FLAGS, flags); /* This also needs to go in the in-memory copy of "cygdrive", but only if appropriate: 1. setting user path prefix, or 2. overwriting (a previous) system path prefix */ if (!(flags & MOUNT_SYSTEM) || (mount_table->cygdrive_flags & MOUNT_SYSTEM)) { slashify (cygdrive_prefix, mount_table->cygdrive, 1); mount_table->cygdrive_flags = flags; mount_table->cygdrive_len = strlen (mount_table->cygdrive); } return 0;}intmount_info::remove_cygdrive_info_from_registry (const char *cygdrive_prefix, unsigned flags){ /* Determine whether to modify user or system cygdrive path prefix. */ HKEY top = (flags & MOUNT_SYSTEM) ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; if (flags & MOUNT_SYSTEM) { sys_mount_table_counter++; cygwin_shared->sys_mount_table_counter++; } /* reg_key for user path prefix in HKEY_CURRENT_USER or system path prefix in HKEY_LOCAL_MACHINE. */ reg_key r (top, KEY_ALL_ACCESS, "SOFTWARE", CYGWIN_INFO_CYGNUS_REGISTRY_NAME, CYGWIN_REGNAME, CYGWIN_INFO_CYGWIN_MOUNT_REGISTRY_NAME, NULL); /* Delete cygdrive prefix and flags. */ int res = r.killvalue (CYGWIN_INFO_CYGDRIVE_PREFIX); int res2 = r.killvalue (CYGWIN_INFO_CYGDRIVE_FLAGS); /* Reinitialize the cygdrive path prefix to reflect to removal from the registry. */ read_cygdrive_info_from_registry (); return (res != ERROR_SUCCESS) ? res : res2;}intmount_info::get_cygdrive_info (char *user, char *system, char* user_flags, char* system_flags){ /* Get the user path prefix from HKEY_CURRENT_USER. */ reg_key r; int res = r.get_string (CYGWIN_INFO_CYGDRIVE_PREFIX, user, MAX_PATH, ""); /* Get the user flags, if appropriate */ if (res == ERROR_SUCCESS) { int flags = r.get_int (CYGWIN_INFO_CYGDRIVE_FLAGS, MOUNT_CYGDRIVE); strcpy (user_flags, (flags & MOUNT_BINARY) ? "binmode" : "textmode"); } /* Get the system path prefix from 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); int res2 = r2.get_string (CYGWIN_INFO_CYGDRIVE_PREFIX, system, MAX_PATH, ""); /* Get the system flags, if appropriate */ if (res2 == ERROR_SUCCESS) { int flags = r2.get_int (CYGWIN_INFO_CYGDRIVE_FLAGS, MOUNT_CYGDRIVE); strcpy (system_flags, (flags & MOUNT_BINARY) ? "binmode" : "textmode"); } return (res != ERROR_SUCCESS) ? res : res2;}static mount_item *mounts_for_sort;/* sort_by_posix_name: qsort callback to sort the mount entries. Sort user mounts ahead of system mounts to the same POSIX path. *//* FIXME: should the user should be able to choose whether to prefer user or system mounts??? */static intsort_by_posix_name (const void *a, const void *b){ mount_item *ap = mounts_for_sort + (*((int*) a)); mount_item *bp = mounts_for_sort + (*((int*) b)); /* Base weighting on longest posix path first so that the most obvious path will be chosen. */ size_t alen = strlen (ap->posix_path); size_t blen = strlen (bp->posix_path); int res = blen - alen; if (res) return res; /* Path lengths differed */ /* The two paths were the same length, so just determine normal lexical sorted order. */ res = strcmp (ap->posix_path, bp->posix_path); if (res == 0) { /* need to select between user and system mount to same POSIX path */ if (!(bp->flags & MOUNT_SYSTEM)) /* user mount */ return 1; else return -1; } return res;}/* sort_by_native_name: qsort callback to sort the mount entries. Sort user mounts ahead of system mounts to the same POSIX path. *//* FIXME: should the user should be able to choose whether to prefer user or system mounts??? */static intsort_by_native_name (const void *a, const void *b){ mount_item *ap = mounts_for_sort + (*((int*) a)); mount_item *bp = mounts_for_sort + (*((int*) b)); /* Base weighting on longest win32 path first so that the most obvious path will be chosen. */ size_t alen = strlen (ap->native_path); size_t blen = strlen (bp->native_path); int res = blen - alen; if (res) return res; /* Path lengths differed */ /* The two paths were the same length, so just determine normal lexical sorted order. */ res = strcmp (ap->native_path, bp->native_path); if (res == 0) { /* need to select between user and system mount to same POSIX path */ if (!(bp->flags & MOUNT_SYSTEM)) /* user mount */ return 1; else return -1; } return res;}voidmount_info::sort (){ for (int i = 0; i < nmounts; i++) native_sorted[i] = posix_sorted[i] = i; /* Sort them into reverse length order, otherwise we won't be able to look for /foo in /. */ mounts_for_sort = mount; /* ouch. */ qsort (posix_sorted, nmounts, sizeof (posix_sorted[0]), sort_by_posix_name); qsort (native_sorted, nmounts, sizeof (native_sorted[0]), sort_by_native_name);}/* Add an entry to the mount table. Returns 0 on success, -1 on failure and errno is set. This is where all argument validation is done. It may not make sense to do this when called internally, but it's cleaner to keep it all here. */intmount_info::add_item (const char *native, const char *posix, unsigned mountflags, int reg_p){ /* Something's wrong if either path is NULL or empty, or if it's not a UNC or absolute path. */ if ((native == NULL) || (*native == 0) || (posix == NULL) || (*posix == 0) || !isabspath (native) || !isabspath (posix) || slash_unc_prefix_p (posix) || isdrive (posix)) { set_errno (EINVAL); return -1; } /* Make sure both paths do not end in /. */ char nativetmp[MAX_PATH]; char posixtmp[MAX_PATH]; backslashify (native, nativetmp, 0); nofinalslash (nativetmp, nativetmp); slashify (posix, posixtmp, 0); nofinalslash (posixtmp, posixtmp); debug_printf ("%s[%s], %s[%s], %p", native, nativetmp, posix, posixtmp, mountflags); /* Duplicate /'s in path are an error. */ for (char *p = posixtmp + 1; *p; ++p) { if (p[-1] == '/' && p[0] == '/') { set_errno (EINVAL); return -1; } } /* Write over an existing mount item with the same POSIX path if it exists and is from the same registry area. */ int i; for (i = 0; i < nmounts; i++) { if (strcasematch (mount[i].posix_path, posixtmp) && (mount[i].flags & MOUNT_SYSTEM) == (mountflags & MOUNT_SYSTEM)) break; } if (i == nmounts && nmounts == MAX_MOUNTS) { set_errno (EMFILE); return -1; } if (reg_p && add_reg_mount (nativetmp, posixtmp, mountflags)) return -1; if (i == nmounts) nmounts++; mount[i].init (nativetmp, posixtmp, mountflags); sort (); return 0;}/* Delete a mount table entry where path is either a Win32 or POSIX path. Since the mount table is really just a table of aliases, deleting / is ok (although running without a slash mount is strongly discouraged because some programs may run erratically without one). If MOUNT_SYSTEM is set in flags, remove from system registry, otherwise remove the user registry mount.*/intmount_info::del_item (const char *path, unsigned flags, int reg_p){ char pathtmp[MAX_PATH]; int posix_path_p = false; /* Something's wrong if path is NULL or empty. */ if (path == NULL || *path == 0 || !isabspath (path)) { set_errno (EINVAL); return -1; } if (slash_unc_prefix_p (path) || strpbrk (path, ":\\")) backslashify (path, pathtmp, 0); else { slashify (path, pathtmp, 0); posix_path_p = TRUE; } nofinalslash (pathtmp, pathtmp); if (reg_p && posix_path_p && del_reg_mount (pathtmp, flags) && del_reg_mount (path, flags)) /* for old irregular entries */ return -1; for (int i = 0; i < nmounts; i++) { int ent = native_sorted[i]; /* in the same order as getmntent() */ if (((posix_path_p) ? strcasematch (mount[ent].posix_path, pathtmp) : strcasematch (mount[ent].native_path, pathtmp)) && (mount[ent].flags & MOUNT_SYSTEM) == (flags & MOUNT_SYSTEM)) { if (!posix_path_p && reg_p && del_reg_mount (mount[ent].posix_path, flags)) return -1; nmounts--; /* One less mount table entry */ /* Fill in the hole if not at the end of the table */ if (ent < nmounts) memmove (mount + ent, mount + ent + 1, sizeof (mount[ent]) * (nmounts - ent)); sort (); /* Resort the table */ return 0; } } set_errno (EINVAL); return -1;}/************************* mount_item class ****************************/static mntent *fillout_mntent (const char *native_path, const char *posix_path, unsigned flags){#ifdef _MT_SAFE struct mntent &ret=_reent_winsup ()->mntbuf;#else static NO_COPY struct mntent ret;#endif /* Remove drivenum from list if we see a x: style path */ if (strlen (native_path) == 2 && native_path[1] == ':') { int drivenum = cyg_tolower (native_path[0]) - 'a'; if (drivenum >= 0 && drivenum <= 31) available_drives &= ~(1 << drivenum); } /* Pass back pointers to mount_table strings reserved for use by getmntent rather than pointers to strings in the internal mount table because the mount table might change, causing weird effects from the getmntent user's point of view. */ strcpy (_reent_winsup ()->mnt_fsname, native_path); ret.mnt_fsname = _reent_winsup ()->mnt_fsname; strcpy (_reent_winsup ()->mnt_dir, posix_path); ret.mnt_dir = _reent_winsup ()->mnt_dir; if (!(flags & MOUNT_SYSTEM)) /* user mount */ strcpy (_reent_winsup ()->mnt_type, (char *) "user"); else /* system mount */ strcpy (_reent_winsup ()->mnt_type, (char *) "system"); ret.mnt_type = _reent_winsup ()->mnt_type; /* mnt_opts is a string that details mount params such as binary or textmode, or exec. We don't print `silent' here; it's a magic internal thing. */ if (!(flags & MOUNT_BINARY)) strcpy (_reent_winsup ()->mnt_opts, (char *) "textmode"); else strcpy (_reent_winsup ()->mnt_opts, (char *) "binmode"); if (flags & MOUNT_CYGWIN_EXEC) strcat (_reent_winsup ()->mnt_opts, (char *) ",cygexec"); else if (flags & MOUNT_EXEC) strcat (_reent_winsup ()->mnt_opts, (char *) ",exec"); else if (flags & MOUNT_NOTEXEC) strcat (_reent_winsup ()->mnt_opts, (char *) ",noexec"); if ((flags & MOUNT_CYGDRIVE)) /* cygdrive */ strcat (_reent_winsup ()->mnt_opts, (char *) ",noumount"); ret.mnt_opts = _reent_winsup ()->mnt_opts; ret.mnt_freq = 1; ret.mnt_passno = 1; return &ret;}struct mntent *mount_item::getmntent (){ return fillout_mntent (native_path, posix_path, flags);}static struct mntent *cygdrive_getmntent (){ char native_path[4]; char posix_path[MAX_PATH]; DWORD mask = 1, drive = 'a'; struct mntent *ret = NULL; while (available_drives) { for (/* nothing */; drive <= 'z'; mask <<= 1, drive++) if (available_drives & mask) break; __small_sprintf (native_path, "%c:\\", drive); if (GetDriveType (native_path) == DRIVE_REMOVABLE || GetFileAttributes (native_path) == INVALID_FILE_ATTRIBUTES) { available_drives &= ~mask; continue; } native_path[2] = '\0'; __small_sprintf (posix_path, "%s%c", mount_table->cygdrive, drive); ret = fillout_mntent (native_path, posix_path, mount_table->cygdrive_flags); break; } return ret;}struct mntent *mount_info::getmntent (int x){ if (x < 0 || x >= nmounts) return cygdrive_getmntent (); return mount[native_sorted[x]].getmntent ();}/* Fill in the fields of a mount table entry. */voidmount_item::init (const char *native, const char *posix, unsigned mountflags){ strcpy ((char *) native_path, native); strcpy ((char *) posix_path, posix); native_pathlen = strlen (native_path); posix_pathlen = strlen (posix_path); flags = mountflags;}/********************** Mount System Calls **************************//* Mount table system calls. Note that these are exported to the application. *//* mount: Add a mount to the mount table in memory and to the registry that will cause paths under win32_path to be translated to paths under posix_path. */extern "C" intmount (const char *win32_path, const char *posix_path, unsigned flags){ int res = -1; if (flags & MOUNT_CYGDRIVE) /* normal mount */ { /* When flags include MOUNT_CYGDRIVE, take this to mean that we actually want to change the cygdrive prefix and flags without actually mounting anything. */ res = mount_table->write_cygdrive_info_to_
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -