aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2021-02-12 14:11:01 +0000
committerRon Yorston <rmy@pobox.com>2021-02-12 14:11:01 +0000
commit7587b56c10a4d11fe434e3eaa51212113f09ec10 (patch)
tree219264f8c4079d13ab8c29d9d90f04b22e6470bc
parent1b61a02b5139a47e2e3ac8be5afca325d7b3cea7 (diff)
downloadbusybox-w32-7587b56c10a4d11fe434e3eaa51212113f09ec10.tar.gz
busybox-w32-7587b56c10a4d11fe434e3eaa51212113f09ec10.tar.bz2
busybox-w32-7587b56c10a4d11fe434e3eaa51212113f09ec10.zip
win32: implement symlink(2)
Provide an implementation of symlink(2). Calls to symlink(2) will fail in default Windows installations unless running with elevated privileges. Failure to create a symlink when extracting files from an archive is therefore treated as a non-fatal error. There are two ways to permit the creation of symlinks: - Edit security policy to give users the 'Create symbolic links' privilege. Unfortunately this doesn't work for users who are an Administrator. - Enable developer mode, which is available in later versions of Windows 10. The ability to create symlinks is not available in Windows XP or ReactOS.
-rw-r--r--archival/libarchive/unsafe_symlink_target.c30
-rw-r--r--include/mingw.h2
-rw-r--r--win32/mingw.c35
3 files changed, 55 insertions, 12 deletions
diff --git a/archival/libarchive/unsafe_symlink_target.c b/archival/libarchive/unsafe_symlink_target.c
index b5f5a2670..8e4cd4380 100644
--- a/archival/libarchive/unsafe_symlink_target.c
+++ b/archival/libarchive/unsafe_symlink_target.c
@@ -5,12 +5,17 @@
5#include "libbb.h" 5#include "libbb.h"
6#include "bb_archive.h" 6#include "bb_archive.h"
7 7
8/* symlink may not be available for WIN32, just issue a warning */
9#if ENABLE_PLATFORM_MINGW32
10# undef bb_perror_msg_and_die
11# define bb_perror_msg_and_die(...) bb_perror_msg(__VA_ARGS__)
12#endif
13
8void FAST_FUNC create_or_remember_link(llist_t **link_placeholders, 14void FAST_FUNC create_or_remember_link(llist_t **link_placeholders,
9 const char *target, 15 const char *target,
10 const char *linkname, 16 const char *linkname,
11 int hard_link) 17 int hard_link)
12{ 18{
13#if !ENABLE_PLATFORM_MINGW32
14 if (hard_link || target[0] == '/' || strstr(target, "..")) { 19 if (hard_link || target[0] == '/' || strstr(target, "..")) {
15 llist_add_to_end(link_placeholders, 20 llist_add_to_end(link_placeholders,
16 xasprintf("%c%s%c%s", hard_link, linkname, '\0', target) 21 xasprintf("%c%s%c%s", hard_link, linkname, '\0', target)
@@ -23,16 +28,6 @@ void FAST_FUNC create_or_remember_link(llist_t **link_placeholders,
23 "sym", linkname, target 28 "sym", linkname, target
24 ); 29 );
25 } 30 }
26#else
27 if (hard_link) {
28 llist_add_to_end(link_placeholders,
29 xasprintf("%c%s%c%s", hard_link, linkname, '\0', target)
30 );
31 return;
32 }
33 /* symlink isn't implemented for WIN32, just issue a warning */
34 bb_perror_msg("can't create symlink '%s' to '%s'", linkname, target);
35#endif
36} 31}
37 32
38void FAST_FUNC create_links_from_list(llist_t *list) 33void FAST_FUNC create_links_from_list(llist_t *list)
@@ -42,11 +37,24 @@ void FAST_FUNC create_links_from_list(llist_t *list)
42 37
43 target = list->data + 1 + strlen(list->data + 1) + 1; 38 target = list->data + 1 + strlen(list->data + 1) + 1;
44 if ((*list->data ? link : symlink) (target, list->data + 1)) { 39 if ((*list->data ? link : symlink) (target, list->data + 1)) {
40#if !ENABLE_PLATFORM_MINGW32
45 /* shared message */ 41 /* shared message */
46 bb_error_msg_and_die("can't create %slink '%s' to '%s'", 42 bb_error_msg_and_die("can't create %slink '%s' to '%s'",
47 *list->data ? "hard" : "sym", 43 *list->data ? "hard" : "sym",
48 list->data + 1, target 44 list->data + 1, target
49 ); 45 );
46#else
47 if (!*list->data)
48 bb_error_msg("can't create %slink '%s' to '%s'",
49 "sym",
50 list->data + 1, target
51 );
52 else
53 bb_error_msg_and_die("can't create %slink '%s' to '%s'",
54 "hard",
55 list->data + 1, target
56 );
57#endif
50 } 58 }
51 list = list->link; 59 list = list->link;
52 } 60 }
diff --git a/include/mingw.h b/include/mingw.h
index 713205ef9..e2c02babf 100644
--- a/include/mingw.h
+++ b/include/mingw.h
@@ -440,7 +440,7 @@ NOIMPL(setsid,void);
440NOIMPL(setuid,uid_t gid UNUSED_PARAM); 440NOIMPL(setuid,uid_t gid UNUSED_PARAM);
441NOIMPL(seteuid,uid_t gid UNUSED_PARAM); 441NOIMPL(seteuid,uid_t gid UNUSED_PARAM);
442unsigned int sleep(unsigned int seconds); 442unsigned int sleep(unsigned int seconds);
443NOIMPL(symlink,const char *oldpath UNUSED_PARAM, const char *newpath UNUSED_PARAM); 443int symlink(const char *target, const char *linkpath);
444static inline void sync(void) {} 444static inline void sync(void) {}
445long sysconf(int name); 445long sysconf(int name);
446IMPL(getpagesize,int,4096,void); 446IMPL(getpagesize,int,4096,void);
diff --git a/win32/mingw.c b/win32/mingw.c
index 41dba9857..a6362333d 100644
--- a/win32/mingw.c
+++ b/win32/mingw.c
@@ -1063,6 +1063,41 @@ int link(const char *oldpath, const char *newpath)
1063 return 0; 1063 return 0;
1064} 1064}
1065 1065
1066#ifndef SYMBOLIC_LINK_FLAG_DIRECTORY
1067# define SYMBOLIC_LINK_FLAG_DIRECTORY (0x1)
1068#endif
1069#ifndef SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE
1070# define SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE (0x2)
1071#endif
1072
1073int symlink(const char *target, const char *linkpath)
1074{
1075 DWORD flag = SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
1076 struct stat st;
1077 DECLARE_PROC_ADDR(BOOL, CreateSymbolicLinkA, LPCSTR, LPCSTR, DWORD);
1078
1079 if (!INIT_PROC_ADDR(kernel32.dll, CreateSymbolicLinkA)) {
1080 return -1;
1081 }
1082
1083 if (stat(target, &st) != -1 && S_ISDIR(st.st_mode))
1084 flag |= SYMBOLIC_LINK_FLAG_DIRECTORY;
1085
1086 retry:
1087 if (!CreateSymbolicLinkA(linkpath, target, flag)) {
1088 /* Old Windows versions see 'UNPRIVILEGED_CREATE' as an invalid
1089 * parameter. Retry without it. */
1090 if ((flag & SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE) &&
1091 GetLastError() == ERROR_INVALID_PARAMETER) {
1092 flag &= ~SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
1093 goto retry;
1094 }
1095 errno = err_win_to_posix();
1096 return -1;
1097 }
1098 return 0;
1099}
1100
1066static char *normalize_ntpathA(char *buf) 1101static char *normalize_ntpathA(char *buf)
1067{ 1102{
1068 /* fix absolute path prefixes */ 1103 /* fix absolute path prefixes */