diff options
author | Ron Yorston <rmy@pobox.com> | 2019-03-28 12:52:44 +0000 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2019-03-28 13:09:50 +0000 |
commit | 548ec7045bc7c80eaf03e92f390d1da2c9e9cd86 (patch) | |
tree | b4c0102539c8889eeeec9eef8afa863510c7592b | |
parent | 215e01e70f13f28d1a4dbe297f095b25de04ee21 (diff) | |
download | busybox-w32-548ec7045bc7c80eaf03e92f390d1da2c9e9cd86.tar.gz busybox-w32-548ec7045bc7c80eaf03e92f390d1da2c9e9cd86.tar.bz2 busybox-w32-548ec7045bc7c80eaf03e92f390d1da2c9e9cd86.zip |
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.
-rw-r--r-- | archival/dpkg.c | 24 | ||||
-rw-r--r-- | archival/rpm.c | 3 | ||||
-rw-r--r-- | include/mingw.h | 3 | ||||
-rw-r--r-- | miscutils/man.c | 14 | ||||
-rw-r--r-- | shell/ash.c | 13 | ||||
-rw-r--r-- | win32/mingw.c | 56 |
6 files changed, 112 insertions, 1 deletions
diff --git a/archival/dpkg.c b/archival/dpkg.c index 8b25cfd47..08f15ad44 100644 --- a/archival/dpkg.c +++ b/archival/dpkg.c | |||
@@ -1752,6 +1752,10 @@ int dpkg_main(int argc UNUSED_PARAM, char **argv) | |||
1752 | int state_status; | 1752 | int state_status; |
1753 | int status_num; | 1753 | int status_num; |
1754 | int i; | 1754 | int i; |
1755 | #if ENABLE_PLATFORM_MINGW32 | ||
1756 | char **ptr, *path; | ||
1757 | int fd; | ||
1758 | #endif | ||
1755 | #if ENABLE_LONG_OPTS | 1759 | #if ENABLE_LONG_OPTS |
1756 | static const char dpkg_longopts[] ALIGN1 = | 1760 | static const char dpkg_longopts[] ALIGN1 = |
1757 | // FIXME: we use -C non-compatibly, should be: | 1761 | // FIXME: we use -C non-compatibly, should be: |
@@ -1796,6 +1800,26 @@ int dpkg_main(int argc UNUSED_PARAM, char **argv) | |||
1796 | bb_show_usage(); | 1800 | bb_show_usage(); |
1797 | } | 1801 | } |
1798 | 1802 | ||
1803 | #if ENABLE_PLATFORM_MINGW32 | ||
1804 | if (opt & OPT_install) { | ||
1805 | /* add system drive prefix to filenames, if necessary */ | ||
1806 | for (ptr = argv; *ptr; ++ptr) { | ||
1807 | *ptr = xabsolute_path(*ptr); | ||
1808 | } | ||
1809 | } | ||
1810 | |||
1811 | chdir_system_drive(); | ||
1812 | |||
1813 | /* initialise data store */ | ||
1814 | path = xstrdup("/var/lib/dpkg/info"); | ||
1815 | bb_make_directory(path, -1, FILEUTILS_RECUR); | ||
1816 | free(path); | ||
1817 | |||
1818 | fd = open("/var/lib/dpkg/status", O_RDWR|O_CREAT, 0666); | ||
1819 | if (fd >= 0) | ||
1820 | xclose(fd); | ||
1821 | #endif | ||
1822 | |||
1799 | /* puts("(Reading database ... xxxxx files and directories installed.)"); */ | 1823 | /* puts("(Reading database ... xxxxx files and directories installed.)"); */ |
1800 | index_status_file("/var/lib/dpkg/status"); | 1824 | index_status_file("/var/lib/dpkg/status"); |
1801 | 1825 | ||
diff --git a/archival/rpm.c b/archival/rpm.c index 3dd4d4777..c9e8785e2 100644 --- a/archival/rpm.c +++ b/archival/rpm.c | |||
@@ -303,6 +303,9 @@ static void extract_cpio(int fd, const char *source_rpm) | |||
303 | 303 | ||
304 | if (source_rpm != NULL) { | 304 | if (source_rpm != NULL) { |
305 | /* Binary rpm (it was built from some SRPM), install to root */ | 305 | /* Binary rpm (it was built from some SRPM), install to root */ |
306 | #if ENABLE_PLATFORM_MINGW32 | ||
307 | if (chdir_system_drive()) | ||
308 | #endif | ||
306 | xchdir("/"); | 309 | xchdir("/"); |
307 | } /* else: SRPM, install to current dir */ | 310 | } /* else: SRPM, install to current dir */ |
308 | 311 | ||
diff --git a/include/mingw.h b/include/mingw.h index 7c9423cad..d77a9beb9 100644 --- a/include/mingw.h +++ b/include/mingw.h | |||
@@ -525,3 +525,6 @@ void hide_console(void); | |||
525 | 525 | ||
526 | int unc_root_len(const char *dir); | 526 | int unc_root_len(const char *dir); |
527 | int root_len(const char *path); | 527 | int root_len(const char *path); |
528 | char *get_system_drive(void); | ||
529 | int chdir_system_drive(void); | ||
530 | char *xabsolute_path(char *path); | ||
diff --git a/miscutils/man.c b/miscutils/man.c index 3c1a79085..0bc11e623 100644 --- a/miscutils/man.c +++ b/miscutils/man.c | |||
@@ -253,11 +253,22 @@ int man_main(int argc UNUSED_PARAM, char **argv) | |||
253 | int cur_mp; | 253 | int cur_mp; |
254 | int opt, not_found; | 254 | int opt, not_found; |
255 | char *token[2]; | 255 | char *token[2]; |
256 | #if ENABLE_PLATFORM_MINGW32 | ||
257 | char **ptr; | ||
258 | #endif | ||
256 | 259 | ||
257 | INIT_G(); | 260 | INIT_G(); |
258 | 261 | ||
259 | opt = getopt32(argv, "^+" "aw" "\0" "-1"/*at least one arg*/); | 262 | opt = getopt32(argv, "^+" "aw" "\0" "-1"/*at least one arg*/); |
260 | argv += optind; | 263 | argv += optind; |
264 | #if ENABLE_PLATFORM_MINGW32 | ||
265 | /* add system drive prefix to filenames, if necessary */ | ||
266 | for (ptr = argv; *ptr; ++ptr) { | ||
267 | if (strchr(*ptr, '/') || strchr(*ptr, '\\')) | ||
268 | *ptr = xabsolute_path(*ptr); | ||
269 | } | ||
270 | chdir_system_drive(); | ||
271 | #endif | ||
261 | 272 | ||
262 | sec_list = xstrdup("0p:1:1p:2:3:3p:4:5:6:7:8:9"); | 273 | sec_list = xstrdup("0p:1:1p:2:3:3p:4:5:6:7:8:9"); |
263 | 274 | ||
@@ -311,7 +322,8 @@ int man_main(int argc UNUSED_PARAM, char **argv) | |||
311 | char *relpath = concat_path_file(dirname(exepath), "man"); | 322 | char *relpath = concat_path_file(dirname(exepath), "man"); |
312 | if (count_mp == 0) { | 323 | if (count_mp == 0) { |
313 | /* default must match path set above */ | 324 | /* default must match path set above */ |
314 | man_path_list = add_MANPATH(man_path_list, &count_mp, "/usr/man"); | 325 | man_path_list = add_MANPATH(man_path_list, &count_mp, |
326 | (char *)"/usr/man"); | ||
315 | } | 327 | } |
316 | man_path_list = add_MANPATH(man_path_list, &count_mp, relpath); | 328 | man_path_list = add_MANPATH(man_path_list, &count_mp, relpath); |
317 | free(relpath); | 329 | free(relpath); |
diff --git a/shell/ash.c b/shell/ash.c index 34ddc14f1..40965bafa 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -14906,6 +14906,9 @@ int ash_main(int argc UNUSED_PARAM, char **argv) | |||
14906 | struct jmploc jmploc; | 14906 | struct jmploc jmploc; |
14907 | struct stackmark smark; | 14907 | struct stackmark smark; |
14908 | int login_sh; | 14908 | int login_sh; |
14909 | #if ENABLE_PLATFORM_MINGW32 | ||
14910 | char *sd; | ||
14911 | #endif | ||
14909 | 14912 | ||
14910 | /* Initialize global data */ | 14913 | /* Initialize global data */ |
14911 | INIT_G_misc(); | 14914 | INIT_G_misc(); |
@@ -15014,6 +15017,16 @@ int ash_main(int argc UNUSED_PARAM, char **argv) | |||
15014 | #endif | 15017 | #endif |
15015 | 15018 | ||
15016 | state = 1; | 15019 | state = 1; |
15020 | #if ENABLE_PLATFORM_MINGW32 | ||
15021 | sd = get_system_drive(); | ||
15022 | if (sd) { | ||
15023 | char *path = xasprintf("%s/etc/profile", sd); | ||
15024 | read_profile(path); | ||
15025 | free(sd); | ||
15026 | free(path); | ||
15027 | } | ||
15028 | else | ||
15029 | #endif | ||
15017 | read_profile("/etc/profile"); | 15030 | read_profile("/etc/profile"); |
15018 | state1: | 15031 | state1: |
15019 | state = 2; | 15032 | state = 2; |
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) | |||
1644 | return 2; | 1644 | return 2; |
1645 | return unc_root_len(path); | 1645 | return unc_root_len(path); |
1646 | } | 1646 | } |
1647 | |||
1648 | char *get_system_drive(void) | ||
1649 | { | ||
1650 | struct passwd *pwd; | ||
1651 | char *drive = NULL; | ||
1652 | int len; | ||
1653 | |||
1654 | pwd = getpwuid(0); | ||
1655 | if (pwd != NULL && (len=root_len(pwd->pw_dir))) { | ||
1656 | drive = xstrdup(pwd->pw_dir); | ||
1657 | drive[len] = '\0'; | ||
1658 | } | ||
1659 | |||
1660 | return drive; | ||
1661 | } | ||
1662 | |||
1663 | int chdir_system_drive(void) | ||
1664 | { | ||
1665 | char *sd = get_system_drive(); | ||
1666 | int ret = -1; | ||
1667 | |||
1668 | if (sd) { | ||
1669 | strcat(sd, "/"); | ||
1670 | ret = chdir(sd); | ||
1671 | } | ||
1672 | free(sd); | ||
1673 | return ret; | ||
1674 | } | ||
1675 | |||
1676 | /* | ||
1677 | * This function is used to make relative paths absolute before a call | ||
1678 | * to chdir_system_drive(). It's unlikely to be useful in other cases. | ||
1679 | * | ||
1680 | * If the argument is an absolute path or a relative path which resolves | ||
1681 | * to a path on the system drive return 'path'. If it's a relative path | ||
1682 | * which resolves to a path that isn't on the system drive return an | ||
1683 | * allocated string containing the resolved path. Die on failure, | ||
1684 | * which is most likely because the file doesn't exist. | ||
1685 | */ | ||
1686 | char *xabsolute_path(char *path) | ||
1687 | { | ||
1688 | char *rpath, *sd; | ||
1689 | |||
1690 | if (root_len(path) != 0) | ||
1691 | return path; // absolute path | ||
1692 | rpath = xmalloc_realpath(path); | ||
1693 | if (rpath) { | ||
1694 | sd = auto_string(get_system_drive()); | ||
1695 | if (sd && is_prefixed_with_case(rpath, sd)) { | ||
1696 | free(rpath); | ||
1697 | return path; // resolved path is on system drive | ||
1698 | } | ||
1699 | return rpath; | ||
1700 | } | ||
1701 | bb_perror_msg_and_die("can't open '%s'", path); | ||
1702 | } | ||