From 548ec7045bc7c80eaf03e92f390d1da2c9e9cd86 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Thu, 28 Mar 2019 12:52:44 +0000 Subject: win32: interpret absolute paths as relative to %SYSTEMDRIVE% BusyBox contains hardcoded references to absolute paths which are unique in the *nix world but on Microsoft Windows are interpreted as being on the current drive. To make these unique again consider them to be relative to %SYSTEMDRIVE%. Support this by adding functions to: - determine the system drive (not using the environment variable); - change a process's current directory to the root of the system drive; - make relative paths absolute before changing directory (if needed). The following applications have been modified: - ash references /etc/profile from the system drive; - dpkg places its data store on and installs files to the system drive; - rpm installs files to the system drive; - man looks for configuration files and man pages on the system drive. See GitHub issue #158. --- win32/mingw.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) (limited to 'win32') diff --git a/win32/mingw.c b/win32/mingw.c index 3ee1a2496..1d5644f92 100644 --- a/win32/mingw.c +++ b/win32/mingw.c @@ -1644,3 +1644,59 @@ int root_len(const char *path) return 2; return unc_root_len(path); } + +char *get_system_drive(void) +{ + struct passwd *pwd; + char *drive = NULL; + int len; + + pwd = getpwuid(0); + if (pwd != NULL && (len=root_len(pwd->pw_dir))) { + drive = xstrdup(pwd->pw_dir); + drive[len] = '\0'; + } + + return drive; +} + +int chdir_system_drive(void) +{ + char *sd = get_system_drive(); + int ret = -1; + + if (sd) { + strcat(sd, "/"); + ret = chdir(sd); + } + free(sd); + return ret; +} + +/* + * This function is used to make relative paths absolute before a call + * to chdir_system_drive(). It's unlikely to be useful in other cases. + * + * If the argument is an absolute path or a relative path which resolves + * to a path on the system drive return 'path'. If it's a relative path + * which resolves to a path that isn't on the system drive return an + * allocated string containing the resolved path. Die on failure, + * which is most likely because the file doesn't exist. + */ +char *xabsolute_path(char *path) +{ + char *rpath, *sd; + + if (root_len(path) != 0) + return path; // absolute path + rpath = xmalloc_realpath(path); + if (rpath) { + sd = auto_string(get_system_drive()); + if (sd && is_prefixed_with_case(rpath, sd)) { + free(rpath); + return path; // resolved path is on system drive + } + return rpath; + } + bb_perror_msg_and_die("can't open '%s'", path); +} -- cgit v1.2.3-55-g6feb