diff options
Diffstat (limited to 'libbb')
41 files changed, 1542 insertions, 72 deletions
diff --git a/libbb/Config.src b/libbb/Config.src index b980f19a9..61b4601d6 100644 --- a/libbb/Config.src +++ b/libbb/Config.src | |||
@@ -188,6 +188,16 @@ config FEATURE_EDITING_HISTORY | |||
188 | help | 188 | help |
189 | Specify command history size (0 - disable). | 189 | Specify command history size (0 - disable). |
190 | 190 | ||
191 | config FEATURE_EDITING_HISTORY_DEFAULT | ||
192 | int "Default history size" | ||
193 | range 0 FEATURE_EDITING_HISTORY | ||
194 | default 255 | ||
195 | depends on PLATFORM_MINGW32 && FEATURE_EDITING && FEATURE_SH_HISTFILESIZE | ||
196 | help | ||
197 | Specify default command history size. This may be smaller than | ||
198 | FEATURE_EDITING_HISTORY, in which case the user may increase | ||
199 | the history size by setting HISTFILESIZE. | ||
200 | |||
191 | config FEATURE_EDITING_SAVEHISTORY | 201 | config FEATURE_EDITING_SAVEHISTORY |
192 | bool "History saving" | 202 | bool "History saving" |
193 | default y | 203 | default y |
diff --git a/libbb/Kbuild.src b/libbb/Kbuild.src index cb8d2c2ec..32fde90e6 100644 --- a/libbb/Kbuild.src +++ b/libbb/Kbuild.src | |||
@@ -10,17 +10,14 @@ lib-y:= | |||
10 | 10 | ||
11 | INSERT | 11 | INSERT |
12 | 12 | ||
13 | lib-y += alloc_affinity.o | ||
14 | lib-y += appletlib.o | 13 | lib-y += appletlib.o |
15 | lib-y += ask_confirmation.o | 14 | lib-y += ask_confirmation.o |
16 | lib-y += bb_askpass.o | ||
17 | lib-y += bb_bswap_64.o | 15 | lib-y += bb_bswap_64.o |
18 | lib-y += bb_do_delay.o | 16 | lib-y += bb_do_delay.o |
19 | lib-y += bb_pwd.o | 17 | lib-y += bb_pwd.o |
20 | lib-y += bb_qsort.o | 18 | lib-y += bb_qsort.o |
21 | #lib-y += bb_strtod.o | 19 | #lib-y += bb_strtod.o |
22 | lib-y += bb_strtonum.o | 20 | lib-y += bb_strtonum.o |
23 | lib-y += change_identity.o | ||
24 | lib-y += chomp.o | 21 | lib-y += chomp.o |
25 | lib-y += compare_string_array.o | 22 | lib-y += compare_string_array.o |
26 | lib-y += concat_path_file.o | 23 | lib-y += concat_path_file.o |
@@ -30,32 +27,23 @@ lib-y += copy_file.o | |||
30 | lib-y += copyfd.o | 27 | lib-y += copyfd.o |
31 | lib-y += crc32.o | 28 | lib-y += crc32.o |
32 | lib-y += default_error_retval.o | 29 | lib-y += default_error_retval.o |
33 | lib-y += device_open.o | ||
34 | lib-y += dump.o | 30 | lib-y += dump.o |
35 | lib-y += executable.o | 31 | lib-y += executable.o |
36 | lib-y += fclose_nonstdin.o | 32 | lib-y += fclose_nonstdin.o |
37 | lib-y += fflush_stdout_and_exit.o | 33 | lib-y += fflush_stdout_and_exit.o |
38 | lib-y += fgets_str.o | 34 | lib-y += fgets_str.o |
39 | lib-y += find_pid_by_name.o | 35 | lib-y += find_pid_by_name.o |
40 | lib-y += find_root_device.o | ||
41 | lib-y += full_write.o | 36 | lib-y += full_write.o |
42 | lib-y += get_console.o | ||
43 | lib-y += get_last_path_component.o | 37 | lib-y += get_last_path_component.o |
44 | lib-y += get_line_from_file.o | 38 | lib-y += get_line_from_file.o |
45 | lib-y += getpty.o | 39 | lib-y += getopt32.o |
46 | lib-y += get_volsize.o | ||
47 | lib-y += herror_msg.o | 40 | lib-y += herror_msg.o |
48 | lib-y += human_readable.o | 41 | lib-y += human_readable.o |
49 | lib-y += inet_common.o | ||
50 | lib-y += inode_hash.o | ||
51 | lib-y += isdirectory.o | 42 | lib-y += isdirectory.o |
52 | lib-y += kernel_version.o | ||
53 | lib-y += last_char_is.o | 43 | lib-y += last_char_is.o |
54 | lib-y += lineedit.o lineedit_ptr_hack.o | 44 | lib-y += lineedit.o lineedit_ptr_hack.o |
55 | lib-y += llist.o | 45 | lib-y += llist.o |
56 | lib-y += login.o | ||
57 | lib-y += make_directory.o | 46 | lib-y += make_directory.o |
58 | lib-y += makedev.o | ||
59 | lib-y += hash_md5_sha.o | 47 | lib-y += hash_md5_sha.o |
60 | lib-y += hash_sha1_x86-64.o | 48 | lib-y += hash_sha1_x86-64.o |
61 | lib-y += hash_sha1_hwaccel_x86-64.o | 49 | lib-y += hash_sha1_hwaccel_x86-64.o |
@@ -68,21 +56,18 @@ lib-y += messages.o | |||
68 | lib-y += mode_string.o | 56 | lib-y += mode_string.o |
69 | lib-y += parse_mode.o | 57 | lib-y += parse_mode.o |
70 | lib-y += perror_msg.o | 58 | lib-y += perror_msg.o |
71 | lib-y += perror_nomsg.o | ||
72 | lib-y += perror_nomsg_and_die.o | 59 | lib-y += perror_nomsg_and_die.o |
73 | lib-y += pidfile.o | ||
74 | lib-y += platform.o | 60 | lib-y += platform.o |
75 | lib-y += popcnt.o | 61 | lib-y += popcnt.o |
76 | lib-y += printable.o | 62 | lib-y += printable.o |
77 | lib-y += printable_string.o | 63 | lib-y += printable_string.o |
78 | lib-y += print_flags.o | ||
79 | lib-y += process_escape_sequence.o | 64 | lib-y += process_escape_sequence.o |
80 | lib-y += procps.o | 65 | lib-y += procps.o |
81 | lib-y += progress.o | 66 | lib-y += progress.o |
82 | lib-y += ptr_to_globals.o | 67 | lib-y += ptr_to_globals.o |
83 | lib-y += read.o | 68 | lib-y += read.o |
84 | lib-y += read_printf.o | ||
85 | lib-y += read_key.o | 69 | lib-y += read_key.o |
70 | lib-y += read_printf.o | ||
86 | lib-y += recursive_action.o | 71 | lib-y += recursive_action.o |
87 | lib-y += remove_file.o | 72 | lib-y += remove_file.o |
88 | lib-y += run_shell.o | 73 | lib-y += run_shell.o |
@@ -91,12 +76,9 @@ lib-y += safe_poll.o | |||
91 | lib-y += safe_strncpy.o | 76 | lib-y += safe_strncpy.o |
92 | lib-y += safe_write.o | 77 | lib-y += safe_write.o |
93 | lib-y += securetty.o | 78 | lib-y += securetty.o |
94 | lib-y += setup_environment.o | ||
95 | lib-y += signals.o | ||
96 | lib-y += simplify_path.o | 79 | lib-y += simplify_path.o |
97 | lib-y += single_argv.o | 80 | lib-y += single_argv.o |
98 | lib-y += skip_whitespace.o | 81 | lib-y += skip_whitespace.o |
99 | lib-y += speed_table.o | ||
100 | lib-y += str_tolower.o | 82 | lib-y += str_tolower.o |
101 | lib-y += strrstr.o | 83 | lib-y += strrstr.o |
102 | lib-y += sysconf.o | 84 | lib-y += sysconf.o |
@@ -109,17 +91,39 @@ lib-y += vfork_daemon_rexec.o | |||
109 | lib-y += warn_ignoring_args.o | 91 | lib-y += warn_ignoring_args.o |
110 | lib-y += wfopen.o | 92 | lib-y += wfopen.o |
111 | lib-y += wfopen_input.o | 93 | lib-y += wfopen_input.o |
112 | lib-y += write.o | ||
113 | lib-y += xatonum.o | 94 | lib-y += xatonum.o |
114 | lib-y += xconnect.o | 95 | lib-y += xconnect.o |
115 | lib-y += xfuncs.o | 96 | lib-y += xfuncs.o |
116 | lib-y += xfuncs_printf.o | 97 | lib-y += xfuncs_printf.o |
117 | lib-y += xfunc_die.o | 98 | lib-y += xfunc_die.o |
118 | lib-y += xgetcwd.o | 99 | lib-y += xgetcwd.o |
119 | lib-y += xgethostbyname.o | ||
120 | lib-y += xreadlink.o | 100 | lib-y += xreadlink.o |
121 | lib-y += xrealloc_vector.o | 101 | lib-y += xrealloc_vector.o |
122 | 102 | ||
103 | lib-$(CONFIG_PLATFORM_POSIX) += alloc_affinity.o | ||
104 | lib-$(CONFIG_PLATFORM_POSIX) += bb_askpass.o | ||
105 | lib-$(CONFIG_PLATFORM_POSIX) += change_identity.o | ||
106 | lib-$(CONFIG_PLATFORM_POSIX) += device_open.o | ||
107 | lib-$(CONFIG_PLATFORM_POSIX) += find_root_device.o | ||
108 | lib-$(CONFIG_PLATFORM_POSIX) += get_console.o | ||
109 | lib-$(CONFIG_PLATFORM_POSIX) += getpty.o | ||
110 | lib-$(CONFIG_PLATFORM_POSIX) += get_volsize.o | ||
111 | lib-$(CONFIG_PLATFORM_POSIX) += inet_common.o | ||
112 | lib-$(CONFIG_PLATFORM_POSIX) += inode_hash.o | ||
113 | lib-$(CONFIG_FEATURE_EXTRA_FILE_DATA) += inode_hash.o | ||
114 | lib-$(CONFIG_PLATFORM_POSIX) += kernel_version.o | ||
115 | lib-$(CONFIG_PLATFORM_POSIX) += login.o | ||
116 | lib-$(CONFIG_PLATFORM_POSIX) += makedev.o | ||
117 | lib-$(CONFIG_PLATFORM_POSIX) += perror_nomsg.o | ||
118 | lib-$(CONFIG_PLATFORM_POSIX) += pidfile.o | ||
119 | lib-$(CONFIG_PLATFORM_POSIX) += print_flags.o | ||
120 | lib-$(CONFIG_PLATFORM_POSIX) += setup_environment.o | ||
121 | lib-$(CONFIG_PLATFORM_POSIX) += signals.o | ||
122 | lib-$(CONFIG_PLATFORM_POSIX) += speed_table.o | ||
123 | lib-$(CONFIG_PLATFORM_POSIX) += udp_io.o | ||
124 | lib-$(CONFIG_PLATFORM_POSIX) += write.o | ||
125 | lib-$(CONFIG_PLATFORM_POSIX) += xgethostbyname.o | ||
126 | |||
123 | lib-$(CONFIG_MOUNT) += match_fstype.o | 127 | lib-$(CONFIG_MOUNT) += match_fstype.o |
124 | lib-$(CONFIG_UMOUNT) += match_fstype.o | 128 | lib-$(CONFIG_UMOUNT) += match_fstype.o |
125 | 129 | ||
@@ -132,7 +136,7 @@ lib-$(CONFIG_FEATURE_MTAB_SUPPORT) += mtab.o | |||
132 | lib-$(CONFIG_UNICODE_SUPPORT) += unicode.o | 136 | lib-$(CONFIG_UNICODE_SUPPORT) += unicode.o |
133 | lib-$(CONFIG_FEATURE_CHECK_NAMES) += die_if_bad_username.o | 137 | lib-$(CONFIG_FEATURE_CHECK_NAMES) += die_if_bad_username.o |
134 | 138 | ||
135 | lib-$(CONFIG_NC) += udp_io.o | 139 | lib-$(CONFIG_NC_110_COMPAT) += udp_io.o |
136 | lib-$(CONFIG_NETCAT) += udp_io.o | 140 | lib-$(CONFIG_NETCAT) += udp_io.o |
137 | lib-$(CONFIG_DNSD) += udp_io.o | 141 | lib-$(CONFIG_DNSD) += udp_io.o |
138 | lib-$(CONFIG_NTPD) += udp_io.o | 142 | lib-$(CONFIG_NTPD) += udp_io.o |
@@ -171,6 +175,7 @@ lib-$(CONFIG_MKE2FS) += find_mount_point.o | |||
171 | lib-$(CONFIG_MKFS_REISER) += find_mount_point.o | 175 | lib-$(CONFIG_MKFS_REISER) += find_mount_point.o |
172 | lib-$(CONFIG_FSCK_MINIX) += find_mount_point.o | 176 | lib-$(CONFIG_FSCK_MINIX) += find_mount_point.o |
173 | lib-$(CONFIG_MOUNT) += find_mount_point.o | 177 | lib-$(CONFIG_MOUNT) += find_mount_point.o |
178 | lib-$(CONFIG_STAT) += find_mount_point.o | ||
174 | 179 | ||
175 | lib-$(CONFIG_HWCLOCK) += rtc.o | 180 | lib-$(CONFIG_HWCLOCK) += rtc.o |
176 | lib-$(CONFIG_RTCWAKE) += rtc.o | 181 | lib-$(CONFIG_RTCWAKE) += rtc.o |
diff --git a/libbb/appletlib.c b/libbb/appletlib.c index d2e5900b5..d6e042775 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c | |||
@@ -53,6 +53,15 @@ static inline int *get_perrno(void) { return &errno; } | |||
53 | # define IF_FEATURE_INDIVIDUAL(...) __VA_ARGS__ | 53 | # define IF_FEATURE_INDIVIDUAL(...) __VA_ARGS__ |
54 | #endif | 54 | #endif |
55 | 55 | ||
56 | #if (ENABLE_FEATURE_INSTALLER && !ENABLE_PLATFORM_MINGW32) || \ | ||
57 | (ENABLE_PLATFORM_MINGW32 && (ENABLE_FEATURE_PREFER_APPLETS \ | ||
58 | || ENABLE_FEATURE_SH_STANDALONE \ | ||
59 | || ENABLE_FEATURE_SH_NOFORK)) | ||
60 | # define IF_FULL_LIST_OPTION(...) __VA_ARGS__ | ||
61 | #else | ||
62 | # define IF_FULL_LIST_OPTION(...) | ||
63 | #endif | ||
64 | |||
56 | #include "usage_compressed.h" | 65 | #include "usage_compressed.h" |
57 | 66 | ||
58 | #if ENABLE_FEATURE_SH_EMBEDDED_SCRIPTS | 67 | #if ENABLE_FEATURE_SH_EMBEDDED_SCRIPTS |
@@ -62,6 +71,7 @@ static inline int *get_perrno(void) { return &errno; } | |||
62 | # define NUM_SCRIPTS 0 | 71 | # define NUM_SCRIPTS 0 |
63 | #endif | 72 | #endif |
64 | #if NUM_SCRIPTS > 0 | 73 | #if NUM_SCRIPTS > 0 |
74 | # define BB_ARCHIVE_PUBLIC | ||
65 | # include "bb_archive.h" | 75 | # include "bb_archive.h" |
66 | static const char packed_scripts[] ALIGN1 = { PACKED_SCRIPTS }; | 76 | static const char packed_scripts[] ALIGN1 = { PACKED_SCRIPTS }; |
67 | #endif | 77 | #endif |
@@ -90,6 +100,12 @@ static const char packed_scripts[] ALIGN1 = { PACKED_SCRIPTS }; | |||
90 | # define ENABLE_FEATURE_COMPRESS_USAGE 0 | 100 | # define ENABLE_FEATURE_COMPRESS_USAGE 0 |
91 | #endif | 101 | #endif |
92 | 102 | ||
103 | #if ENABLE_PLATFORM_MINGW32 && NUM_APPLETS > 1 && \ | ||
104 | ENABLE_FEATURE_SH_STANDALONE | ||
105 | static int find_applet_by_name_internal(const char *name); | ||
106 | #else | ||
107 | # define find_applet_by_name_internal(n) find_applet_by_name(n) | ||
108 | #endif | ||
93 | 109 | ||
94 | unsigned FAST_FUNC string_array_len(char **argv) | 110 | unsigned FAST_FUNC string_array_len(char **argv) |
95 | { | 111 | { |
@@ -111,6 +127,7 @@ static const char usage_messages[] ALIGN1 = UNPACKED_USAGE; | |||
111 | #if ENABLE_FEATURE_COMPRESS_USAGE | 127 | #if ENABLE_FEATURE_COMPRESS_USAGE |
112 | 128 | ||
113 | static const char packed_usage[] ALIGN1 = { PACKED_USAGE }; | 129 | static const char packed_usage[] ALIGN1 = { PACKED_USAGE }; |
130 | # define BB_ARCHIVE_PUBLIC | ||
114 | # include "bb_archive.h" | 131 | # include "bb_archive.h" |
115 | # define unpack_usage_messages() \ | 132 | # define unpack_usage_messages() \ |
116 | unpack_bz2_data(packed_usage, sizeof(packed_usage), sizeof(UNPACKED_USAGE)) | 133 | unpack_bz2_data(packed_usage, sizeof(packed_usage), sizeof(UNPACKED_USAGE)) |
@@ -147,7 +164,7 @@ void FAST_FUNC bb_show_usage(void) | |||
147 | #else | 164 | #else |
148 | const char *p; | 165 | const char *p; |
149 | const char *usage_string = p = unpack_usage_messages(); | 166 | const char *usage_string = p = unpack_usage_messages(); |
150 | int ap = find_applet_by_name(applet_name); | 167 | int ap = find_applet_by_name_internal(applet_name); |
151 | 168 | ||
152 | if (ap < 0 || usage_string == NULL) | 169 | if (ap < 0 || usage_string == NULL) |
153 | xfunc_die(); | 170 | xfunc_die(); |
@@ -156,7 +173,11 @@ void FAST_FUNC bb_show_usage(void) | |||
156 | ap--; | 173 | ap--; |
157 | } | 174 | } |
158 | full_write_fn(bb_banner); | 175 | full_write_fn(bb_banner); |
176 | #if ENABLE_PLATFORM_MINGW32 | ||
177 | full_write_fn("\n"); | ||
178 | #else | ||
159 | full_write_fn(" multi-call binary.\n"); /* common string */ | 179 | full_write_fn(" multi-call binary.\n"); /* common string */ |
180 | #endif | ||
160 | if (*p == '\b') | 181 | if (*p == '\b') |
161 | full_write_fn("\nNo help available\n"); | 182 | full_write_fn("\nNo help available\n"); |
162 | else { | 183 | else { |
@@ -176,7 +197,12 @@ void FAST_FUNC bb_show_usage(void) | |||
176 | xfunc_die(); | 197 | xfunc_die(); |
177 | } | 198 | } |
178 | 199 | ||
200 | #if ENABLE_PLATFORM_MINGW32 && NUM_APPLETS > 1 && \ | ||
201 | ENABLE_FEATURE_SH_STANDALONE | ||
202 | static int find_applet_by_name_internal(const char *name) | ||
203 | #else | ||
179 | int FAST_FUNC find_applet_by_name(const char *name) | 204 | int FAST_FUNC find_applet_by_name(const char *name) |
205 | #endif | ||
180 | { | 206 | { |
181 | unsigned i; | 207 | unsigned i; |
182 | int j; | 208 | int j; |
@@ -241,6 +267,83 @@ int FAST_FUNC find_applet_by_name(const char *name) | |||
241 | return -1; | 267 | return -1; |
242 | } | 268 | } |
243 | 269 | ||
270 | #if ENABLE_PLATFORM_MINGW32 && NUM_APPLETS > 1 | ||
271 | # if ENABLE_FEATURE_SH_STANDALONE | ||
272 | int FAST_FUNC find_applet_by_name_for_sh(const char *name, const char *path) | ||
273 | { | ||
274 | int applet_no = find_applet_by_name_internal(name); | ||
275 | return applet_no >= 0 && prefer_applet(name, path) ? applet_no : -1; | ||
276 | } | ||
277 | |||
278 | int FAST_FUNC find_applet_by_name(const char *name) | ||
279 | { | ||
280 | return find_applet_by_name_for_sh(name, NULL); | ||
281 | } | ||
282 | # endif | ||
283 | |||
284 | # if ENABLE_FEATURE_SH_STANDALONE || ENABLE_FEATURE_PREFER_APPLETS | ||
285 | static int external_exists(const char *name, const char *path) | ||
286 | { | ||
287 | const char *path0, *path1, *ret; | ||
288 | |||
289 | path0 = path1 = xstrdup(path ?: getenv("PATH")); | ||
290 | ret = find_executable(name, &path1); | ||
291 | free((void *)ret); | ||
292 | free((void *)path0); | ||
293 | return ret != NULL; | ||
294 | } | ||
295 | |||
296 | static int prefer_applet_internal(const char *name, const char *path, | ||
297 | const char *override) | ||
298 | { | ||
299 | const char *s, *sep; | ||
300 | size_t len; | ||
301 | |||
302 | if (override && *override) { | ||
303 | /* '-' disables all applets */ | ||
304 | if (override[0] == '-' && override[1] == '\0') | ||
305 | return FALSE; | ||
306 | |||
307 | /* '+' each applet is overridden if an external command exists */ | ||
308 | if (override[0] == '+' && override[1] == '\0') | ||
309 | return !external_exists(name, path); | ||
310 | |||
311 | /* Handle applets from a list separated by spaces, commas or | ||
312 | * semicolons. Applets before the first semicolon are disabled. | ||
313 | * Applets after the first semicolon are overridden if a | ||
314 | * corresponding external command exists. */ | ||
315 | sep = strchr(override, ';'); | ||
316 | len = strlen(name); | ||
317 | s = override - 1; | ||
318 | while (1) { | ||
319 | s = strstr(s + 1, name); | ||
320 | if (!s) | ||
321 | break; | ||
322 | /* neither "name.." nor "xxx,name.."? */ | ||
323 | if (s != override && !strchr(" ,;", s[-1])) | ||
324 | continue; | ||
325 | /* neither "..name" nor "..name,xxx"? */ | ||
326 | if (s[len] != '\0' && !strchr(" ,;", s[len])) | ||
327 | continue; | ||
328 | return (sep == NULL || s < sep) ? | ||
329 | FALSE : !external_exists(name, path); | ||
330 | } | ||
331 | } | ||
332 | return TRUE; | ||
333 | } | ||
334 | |||
335 | int FAST_FUNC prefer_applet(const char *name, const char *path) | ||
336 | { | ||
337 | int ret; | ||
338 | |||
339 | ret = prefer_applet_internal(name, path, getenv(BB_OVERRIDE_APPLETS)); | ||
340 | if (sizeof(CONFIG_OVERRIDE_APPLETS) > 1 && ret) | ||
341 | ret = prefer_applet_internal(name, path, CONFIG_OVERRIDE_APPLETS); | ||
342 | return ret; | ||
343 | } | ||
344 | # endif | ||
345 | #endif | ||
346 | |||
244 | 347 | ||
245 | void lbb_prepare(const char *applet | 348 | void lbb_prepare(const char *applet |
246 | IF_FEATURE_INDIVIDUAL(, char **argv)) | 349 | IF_FEATURE_INDIVIDUAL(, char **argv)) |
@@ -291,6 +394,18 @@ const char *applet_name; | |||
291 | #if !BB_MMU | 394 | #if !BB_MMU |
292 | bool re_execed; | 395 | bool re_execed; |
293 | #endif | 396 | #endif |
397 | #if ENABLE_PLATFORM_MINGW32 | ||
398 | static int interp = 0; | ||
399 | char bb_comm[COMM_LEN]; | ||
400 | char bb_command_line[128]; | ||
401 | |||
402 | # if ENABLE_FEATURE_SH_STANDALONE | ||
403 | void FAST_FUNC set_interp(int i) | ||
404 | { | ||
405 | interp = i; | ||
406 | } | ||
407 | # endif | ||
408 | #endif | ||
294 | 409 | ||
295 | 410 | ||
296 | /* If not built as a single-applet executable... */ | 411 | /* If not built as a single-applet executable... */ |
@@ -676,15 +791,36 @@ static void install_links(const char *busybox, int use_symbolic_links, | |||
676 | const char *appname = applet_names; | 791 | const char *appname = applet_names; |
677 | unsigned i; | 792 | unsigned i; |
678 | int rc; | 793 | int rc; |
794 | # if ENABLE_PLATFORM_MINGW32 | ||
795 | const char *sd = ""; | ||
796 | |||
797 | if (custom_install_dir != NULL) { | ||
798 | bb_make_directory(custom_install_dir, 0755, FILEUTILS_RECUR); | ||
799 | } | ||
800 | else { | ||
801 | sd = get_system_drive(); | ||
802 | for (i=1; i<ARRAY_SIZE(install_dir); ++i) { | ||
803 | fpc = concat_path_file(sd, install_dir[i]); | ||
804 | bb_make_directory(fpc, 0755, FILEUTILS_RECUR); | ||
805 | free(fpc); | ||
806 | } | ||
807 | } | ||
808 | # endif | ||
679 | 809 | ||
680 | lf = link; | 810 | lf = link; |
681 | if (use_symbolic_links) | 811 | if (use_symbolic_links) |
682 | lf = symlink; | 812 | lf = symlink; |
683 | 813 | ||
684 | for (i = 0; i < ARRAY_SIZE(applet_main); i++) { | 814 | for (i = 0; i < ARRAY_SIZE(applet_main); i++) { |
815 | # if ENABLE_PLATFORM_MINGW32 | ||
816 | fpc = xasprintf("%s%s/%s.exe", sd, | ||
817 | custom_install_dir ?: install_dir[APPLET_INSTALL_LOC(i)], | ||
818 | appname); | ||
819 | # else | ||
685 | fpc = concat_path_file( | 820 | fpc = concat_path_file( |
686 | custom_install_dir ? custom_install_dir : install_dir[APPLET_INSTALL_LOC(i)], | 821 | custom_install_dir ? custom_install_dir : install_dir[APPLET_INSTALL_LOC(i)], |
687 | appname); | 822 | appname); |
823 | # endif | ||
688 | // debug: bb_error_msg("%slinking %s to busybox", | 824 | // debug: bb_error_msg("%slinking %s to busybox", |
689 | // use_symbolic_links ? "sym" : "", fpc); | 825 | // use_symbolic_links ? "sym" : "", fpc); |
690 | rc = lf(busybox, fpc); | 826 | rc = lf(busybox, fpc); |
@@ -781,20 +917,40 @@ int busybox_main(int argc UNUSED_PARAM, char **argv) | |||
781 | output_width = get_terminal_width(2); | 917 | output_width = get_terminal_width(2); |
782 | 918 | ||
783 | full_write1_str(bb_banner); /* reuse const string */ | 919 | full_write1_str(bb_banner); /* reuse const string */ |
920 | # if ENABLE_PLATFORM_MINGW32 | ||
921 | full_write1_str("\n("); | ||
922 | # if defined(MINGW_VER) | ||
923 | if (sizeof(MINGW_VER) > 5) { | ||
924 | full_write1_str(MINGW_VER "; "); | ||
925 | } | ||
926 | # endif | ||
927 | full_write1_str(ENABLE_GLOBBING ? "glob" : "noglob"); | ||
928 | # if ENABLE_FEATURE_UTF8_MANIFEST | ||
929 | full_write1_str("; Unicode"); | ||
930 | # endif | ||
931 | full_write1_str(")\n\n"); | ||
932 | # else | ||
784 | full_write1_str(" multi-call binary.\n"); /* reuse */ | 933 | full_write1_str(" multi-call binary.\n"); /* reuse */ |
934 | #endif | ||
785 | full_write1_str( | 935 | full_write1_str( |
786 | "BusyBox is copyrighted by many authors between 1998-2015.\n" | 936 | "BusyBox is copyrighted by many authors between 1998-2024.\n" |
787 | "Licensed under GPLv2. See source distribution for detailed\n" | 937 | "Licensed under GPLv2. See source distribution for detailed\n" |
788 | "copyright notices.\n" | 938 | "copyright notices.\n" |
789 | "\n" | 939 | "\n" |
790 | "Usage: busybox [function [arguments]...]\n" | 940 | "Usage: busybox [function [arguments]...]\n" |
791 | " or: busybox --list"IF_FEATURE_INSTALLER("[-full]")"\n" | 941 | " or: busybox --list"IF_FULL_LIST_OPTION("[-full]")"\n" |
792 | # if ENABLE_FEATURE_SHOW_SCRIPT && NUM_SCRIPTS > 0 | 942 | # if ENABLE_FEATURE_SHOW_SCRIPT && NUM_SCRIPTS > 0 |
793 | " or: busybox --show SCRIPT\n" | 943 | " or: busybox --show SCRIPT\n" |
794 | # endif | 944 | # endif |
795 | IF_FEATURE_INSTALLER( | 945 | IF_FEATURE_INSTALLER( |
946 | IF_NOT_PLATFORM_MINGW32( | ||
796 | " or: busybox --install [-s] [DIR]\n" | 947 | " or: busybox --install [-s] [DIR]\n" |
797 | ) | 948 | ) |
949 | IF_PLATFORM_MINGW32( | ||
950 | " or: busybox --install [-s] [-u|DIR]\n" | ||
951 | " or: busybox --uninstall [-n] file\n" | ||
952 | ) | ||
953 | ) | ||
798 | " or: function [arguments]...\n" | 954 | " or: function [arguments]...\n" |
799 | "\n" | 955 | "\n" |
800 | IF_NOT_FEATURE_SH_STANDALONE( | 956 | IF_NOT_FEATURE_SH_STANDALONE( |
@@ -854,9 +1010,28 @@ int busybox_main(int argc UNUSED_PARAM, char **argv) | |||
854 | unsigned i = 0; | 1010 | unsigned i = 0; |
855 | const char *a = applet_names; | 1011 | const char *a = applet_names; |
856 | while (*a) { | 1012 | while (*a) { |
857 | # if ENABLE_FEATURE_INSTALLER | 1013 | # if ENABLE_FEATURE_INSTALLER && !ENABLE_PLATFORM_MINGW32 |
858 | if (argv[1][6]) /* --list-full? */ | 1014 | if (argv[1][6]) /* --list-full? */ |
859 | full_write1_str(install_dir[APPLET_INSTALL_LOC(i)] + 1); | 1015 | full_write1_str(install_dir[APPLET_INSTALL_LOC(i)] + 1); |
1016 | # elif ENABLE_PLATFORM_MINGW32 && (ENABLE_FEATURE_PREFER_APPLETS \ | ||
1017 | || ENABLE_FEATURE_SH_STANDALONE \ | ||
1018 | || ENABLE_FEATURE_SH_NOFORK) | ||
1019 | if (argv[1][6]) { /* --list-full? */ | ||
1020 | const char *str; | ||
1021 | |||
1022 | if (APPLET_IS_NOFORK(i)) | ||
1023 | str = "NOFORK "; | ||
1024 | else if (APPLET_IS_NOEXEC(i)) | ||
1025 | str = "noexec "; | ||
1026 | # if NUM_SCRIPTS > 0 | ||
1027 | else if (applet_main[i] == scripted_main) | ||
1028 | str = "script "; | ||
1029 | # endif | ||
1030 | else | ||
1031 | str = " "; | ||
1032 | full_write1_str(str); | ||
1033 | full_write1_str(install_dir[APPLET_INSTALL_LOC(i)] + 1); | ||
1034 | } | ||
860 | # endif | 1035 | # endif |
861 | full_write1_str(a); | 1036 | full_write1_str(a); |
862 | full_write1_str("\n"); | 1037 | full_write1_str("\n"); |
@@ -869,6 +1044,7 @@ int busybox_main(int argc UNUSED_PARAM, char **argv) | |||
869 | 1044 | ||
870 | if (ENABLE_FEATURE_INSTALLER && strcmp(argv[1], "--install") == 0) { | 1045 | if (ENABLE_FEATURE_INSTALLER && strcmp(argv[1], "--install") == 0) { |
871 | int use_symbolic_links; | 1046 | int use_symbolic_links; |
1047 | #if !ENABLE_PLATFORM_MINGW32 | ||
872 | const char *busybox; | 1048 | const char *busybox; |
873 | 1049 | ||
874 | busybox = xmalloc_readlink(bb_busybox_exec_path); | 1050 | busybox = xmalloc_readlink(bb_busybox_exec_path); |
@@ -888,8 +1064,62 @@ int busybox_main(int argc UNUSED_PARAM, char **argv) | |||
888 | */ | 1064 | */ |
889 | use_symbolic_links = (argv[2] && strcmp(argv[2], "-s") == 0 && ++argv); | 1065 | use_symbolic_links = (argv[2] && strcmp(argv[2], "-s") == 0 && ++argv); |
890 | install_links(busybox, use_symbolic_links, argv[2]); | 1066 | install_links(busybox, use_symbolic_links, argv[2]); |
1067 | #else | ||
1068 | char *target; | ||
1069 | uint32_t opt; | ||
1070 | enum { OPT_s = (1 << 0), OPT_u = (1 << 1) }; | ||
1071 | |||
1072 | /* busybox --install [-s] [-u|DIR] | ||
1073 | * -s: make symlinks | ||
1074 | * -u: install to Unix-style directories in system drive | ||
1075 | * DIR: directory to install links to | ||
1076 | * If no argument is provided put the links in the same directory | ||
1077 | * as busybox. | ||
1078 | */ | ||
1079 | argv += 1; | ||
1080 | opt = getopt32(argv, "!su"); | ||
1081 | argv += optind; | ||
1082 | |||
1083 | if (opt == (uint32_t)-1 || | ||
1084 | (*argv != NULL && (opt & OPT_u || *(argv + 1) != NULL))) | ||
1085 | bb_simple_error_msg_and_die("busybox --install [-s] [-u|DIR]"); | ||
1086 | |||
1087 | if (opt & OPT_u) | ||
1088 | target = NULL; | ||
1089 | else if (*argv != NULL) | ||
1090 | target = *argv; | ||
1091 | else | ||
1092 | target = dirname(xstrdup(bb_busybox_exec_path)); | ||
1093 | |||
1094 | use_symbolic_links = opt & OPT_s; | ||
1095 | /* NULL target -> install to Unix-style dirs */ | ||
1096 | install_links(bb_busybox_exec_path, use_symbolic_links, target); | ||
1097 | #endif | ||
1098 | return 0; | ||
1099 | } | ||
1100 | |||
1101 | #if ENABLE_PLATFORM_MINGW32 && ENABLE_FEATURE_INSTALLER | ||
1102 | if (strcmp(argv[1], "--uninstall") == 0) { | ||
1103 | char name[PATH_MAX]; | ||
1104 | int dry_run = (argv[2] && strcmp(argv[2], "-n") == 0 && ++argv); | ||
1105 | const char *file = argv[2]; | ||
1106 | |||
1107 | if (!argv[2]) | ||
1108 | bb_error_msg_and_die(bb_msg_requires_arg, "--uninstall"); | ||
1109 | |||
1110 | while (enumerate_links(file, name)) { | ||
1111 | if (dry_run) { | ||
1112 | full_write1_str(name); | ||
1113 | full_write1_str("\n"); | ||
1114 | } | ||
1115 | else if (unlink(name) != 0) { | ||
1116 | bb_simple_perror_msg(name); | ||
1117 | } | ||
1118 | file = NULL; | ||
1119 | } | ||
891 | return 0; | 1120 | return 0; |
892 | } | 1121 | } |
1122 | #endif | ||
893 | 1123 | ||
894 | if (strcmp(argv[1], "--help") == 0) { | 1124 | if (strcmp(argv[1], "--help") == 0) { |
895 | /* "busybox --help [<applet>]" */ | 1125 | /* "busybox --help [<applet>]" */ |
@@ -902,7 +1132,7 @@ int busybox_main(int argc UNUSED_PARAM, char **argv) | |||
902 | /* convert to "<applet> --help" */ | 1132 | /* convert to "<applet> --help" */ |
903 | applet_name = argv[0] = argv[2]; | 1133 | applet_name = argv[0] = argv[2]; |
904 | argv[2] = NULL; | 1134 | argv[2] = NULL; |
905 | if (find_applet_by_name(applet_name) >= 0) { | 1135 | if (find_applet_by_name_internal(applet_name) >= 0) { |
906 | /* Make "--help foo" exit with 0: */ | 1136 | /* Make "--help foo" exit with 0: */ |
907 | xfunc_error_retval = 0; | 1137 | xfunc_error_retval = 0; |
908 | bb_show_usage(); | 1138 | bb_show_usage(); |
@@ -913,6 +1143,10 @@ int busybox_main(int argc UNUSED_PARAM, char **argv) | |||
913 | /* We support "busybox /a/path/to/applet args..." too. Allows for | 1143 | /* We support "busybox /a/path/to/applet args..." too. Allows for |
914 | * "#!/bin/busybox"-style wrappers | 1144 | * "#!/bin/busybox"-style wrappers |
915 | */ | 1145 | */ |
1146 | # if ENABLE_PLATFORM_MINGW32 | ||
1147 | if (interp) | ||
1148 | --interp; | ||
1149 | # endif | ||
916 | applet_name = bb_get_last_path_component_nostrip(argv[0]); | 1150 | applet_name = bb_get_last_path_component_nostrip(argv[0]); |
917 | } | 1151 | } |
918 | run_applet_and_exit(applet_name, argv); | 1152 | run_applet_and_exit(applet_name, argv); |
@@ -943,6 +1177,9 @@ void FAST_FUNC show_usage_if_dash_dash_help(int applet_no UNUSED_PARAM, char **a | |||
943 | # if ENABLE_TEST1 || ENABLE_TEST2 | 1177 | # if ENABLE_TEST1 || ENABLE_TEST2 |
944 | && argv[0][0] != '[' /* exclude [ --help ] and [[ --help ]] too */ | 1178 | && argv[0][0] != '[' /* exclude [ --help ] and [[ --help ]] too */ |
945 | # endif | 1179 | # endif |
1180 | # if ENABLE_PLATFORM_MINGW32 && defined APPLET_NO_busybox | ||
1181 | && applet_no != APPLET_NO_busybox | ||
1182 | # endif | ||
946 | ) { | 1183 | ) { |
947 | if (argv[1] && strcmp(argv[1], "--help") == 0) { | 1184 | if (argv[1] && strcmp(argv[1], "--help") == 0) { |
948 | /* Make "foo --help [...]" exit with 0: */ | 1185 | /* Make "foo --help [...]" exit with 0: */ |
@@ -954,7 +1191,14 @@ void FAST_FUNC show_usage_if_dash_dash_help(int applet_no UNUSED_PARAM, char **a | |||
954 | 1191 | ||
955 | void FAST_FUNC run_applet_no_and_exit(int applet_no, const char *name, char **argv) | 1192 | void FAST_FUNC run_applet_no_and_exit(int applet_no, const char *name, char **argv) |
956 | { | 1193 | { |
1194 | # if ENABLE_PLATFORM_MINGW32 | ||
1195 | int argc = string_array_len(argv); | ||
1196 | int i; | ||
1197 | const char *vmask; | ||
1198 | unsigned int mask; | ||
1199 | # else | ||
957 | int argc; | 1200 | int argc; |
1201 | # endif | ||
958 | 1202 | ||
959 | /* | 1203 | /* |
960 | * We do not use argv[0]: do not want to repeat massaging of | 1204 | * We do not use argv[0]: do not want to repeat massaging of |
@@ -967,7 +1211,23 @@ void FAST_FUNC run_applet_no_and_exit(int applet_no, const char *name, char **ar | |||
967 | if (ENABLE_FEATURE_SUID) | 1211 | if (ENABLE_FEATURE_SUID) |
968 | check_suid(applet_no); | 1212 | check_suid(applet_no); |
969 | 1213 | ||
1214 | # if ENABLE_PLATFORM_MINGW32 | ||
1215 | safe_strncpy(bb_comm, | ||
1216 | interp ? bb_basename(argv[interp]) : applet_name, | ||
1217 | sizeof(bb_comm)); | ||
1218 | |||
1219 | safe_strncpy(bb_command_line, applet_name, sizeof(bb_command_line)); | ||
1220 | for (i=1; i < argc && argv[i] && | ||
1221 | strlen(bb_command_line) + strlen(argv[i]) + 2 < 128; ++i) { | ||
1222 | strcat(strcat(bb_command_line, " "), argv[i]); | ||
1223 | } | ||
1224 | |||
1225 | vmask = getenv("BB_UMASK"); | ||
1226 | if (vmask && sscanf(vmask, "%o", &mask) == 1) | ||
1227 | umask((mode_t)mask); | ||
1228 | # else | ||
970 | argc = string_array_len(argv); | 1229 | argc = string_array_len(argv); |
1230 | # endif | ||
971 | xfunc_error_retval = applet_main[applet_no](argc, argv); | 1231 | xfunc_error_retval = applet_main[applet_no](argc, argv); |
972 | 1232 | ||
973 | /* Note: applet_main() may also not return (die on a xfunc or such) */ | 1233 | /* Note: applet_main() may also not return (die on a xfunc or such) */ |
@@ -985,7 +1245,7 @@ static NORETURN void run_applet_and_exit(const char *name, char **argv) | |||
985 | # if NUM_APPLETS > 0 | 1245 | # if NUM_APPLETS > 0 |
986 | /* find_applet_by_name() search is more expensive, so goes second */ | 1246 | /* find_applet_by_name() search is more expensive, so goes second */ |
987 | { | 1247 | { |
988 | int applet = find_applet_by_name(name); | 1248 | int applet = find_applet_by_name_internal(name); |
989 | if (applet >= 0) | 1249 | if (applet >= 0) |
990 | run_applet_no_and_exit(applet, name, argv); | 1250 | run_applet_no_and_exit(applet, name, argv); |
991 | } | 1251 | } |
@@ -1077,6 +1337,44 @@ int main(int argc UNUSED_PARAM, char **argv) | |||
1077 | argv[0][0] &= 0x7f; | 1337 | argv[0][0] &= 0x7f; |
1078 | } | 1338 | } |
1079 | #endif | 1339 | #endif |
1340 | #if ENABLE_PLATFORM_MINGW32 | ||
1341 | # if ENABLE_FEATURE_UTF8_MANIFEST | ||
1342 | if (GetACP() != CP_UTF8) { | ||
1343 | full_write2_str(bb_basename(argv[0])); | ||
1344 | full_write2_str(": UTF8 manifest not supported\n"); | ||
1345 | return 1; | ||
1346 | } | ||
1347 | # endif | ||
1348 | |||
1349 | /* detect if we're running an interpreted script */ | ||
1350 | if (argv[0][1] == ':' && argv[0][2] == '/') { | ||
1351 | switch (argv[0][0]) { | ||
1352 | case '2': | ||
1353 | ++interp; | ||
1354 | /* fall through */ | ||
1355 | case '1': | ||
1356 | ++interp; | ||
1357 | argv[0] += 3; | ||
1358 | break; | ||
1359 | } | ||
1360 | } | ||
1361 | |||
1362 | /* Have this process handle critical errors itself: the default | ||
1363 | * system-generated error dialogs may be inconvenient. */ | ||
1364 | change_critical_error_dialogs(getenv(BB_CRITICAL_ERROR_DIALOGS)); | ||
1365 | #endif | ||
1366 | |||
1367 | #if defined(__MINGW64_VERSION_MAJOR) | ||
1368 | if ( stdin ) { | ||
1369 | _setmode(fileno(stdin), _O_BINARY); | ||
1370 | } | ||
1371 | if ( stdout ) { | ||
1372 | _setmode(fileno(stdout), _O_BINARY); | ||
1373 | } | ||
1374 | if ( stderr ) { | ||
1375 | _setmode(fileno(stderr), _O_BINARY); | ||
1376 | } | ||
1377 | #endif | ||
1080 | 1378 | ||
1081 | #if defined(SINGLE_APPLET_MAIN) | 1379 | #if defined(SINGLE_APPLET_MAIN) |
1082 | 1380 | ||
@@ -1101,6 +1399,10 @@ int main(int argc UNUSED_PARAM, char **argv) | |||
1101 | 1399 | ||
1102 | #else | 1400 | #else |
1103 | 1401 | ||
1402 | # if ENABLE_PLATFORM_MINGW32 | ||
1403 | if (argv[1] && argv[2] && strcmp(argv[1], "--busybox") == 0) | ||
1404 | argv += 2; | ||
1405 | # endif | ||
1104 | lbb_prepare("busybox" IF_FEATURE_INDIVIDUAL(, argv)); | 1406 | lbb_prepare("busybox" IF_FEATURE_INDIVIDUAL(, argv)); |
1105 | # if !ENABLE_BUSYBOX | 1407 | # if !ENABLE_BUSYBOX |
1106 | if (argv[1] && is_prefixed_with(bb_basename(argv[0]), "busybox")) | 1408 | if (argv[1] && is_prefixed_with(bb_basename(argv[0]), "busybox")) |
@@ -1109,6 +1411,27 @@ int main(int argc UNUSED_PARAM, char **argv) | |||
1109 | applet_name = argv[0]; | 1411 | applet_name = argv[0]; |
1110 | if (applet_name[0] == '-') | 1412 | if (applet_name[0] == '-') |
1111 | applet_name++; | 1413 | applet_name++; |
1414 | # if ENABLE_PLATFORM_MINGW32 | ||
1415 | str_tolower(argv[0]); | ||
1416 | bs_to_slash(argv[0]); | ||
1417 | if (has_exe_suffix_or_dot(argv[0])) { | ||
1418 | char *s = strrchr(argv[0], '.'); | ||
1419 | if (s) | ||
1420 | *s = '\0'; | ||
1421 | } | ||
1422 | |||
1423 | if (windows_env()) { | ||
1424 | /* remove single trailing separator from PATH */ | ||
1425 | for (char **envp = environ; envp && *envp; envp++) { | ||
1426 | if (is_prefixed_with_case(*envp, "PATH=")) { | ||
1427 | char *end = last_char_is(*envp, ';'); | ||
1428 | if (end && end[-1] != ';') | ||
1429 | *end = '\0'; | ||
1430 | break; | ||
1431 | } | ||
1432 | } | ||
1433 | } | ||
1434 | # endif | ||
1112 | applet_name = bb_basename(applet_name); | 1435 | applet_name = bb_basename(applet_name); |
1113 | 1436 | ||
1114 | /* If we are a result of execv("/proc/self/exe"), fix ugly comm of "exe" */ | 1437 | /* If we are a result of execv("/proc/self/exe"), fix ugly comm of "exe" */ |
diff --git a/libbb/bb_getgroups.c b/libbb/bb_getgroups.c index 31cff2b41..757b80be8 100644 --- a/libbb/bb_getgroups.c +++ b/libbb/bb_getgroups.c | |||
@@ -10,6 +10,7 @@ | |||
10 | 10 | ||
11 | #include "libbb.h" | 11 | #include "libbb.h" |
12 | 12 | ||
13 | #if !ENABLE_PLATFORM_MINGW32 | ||
13 | gid_t* FAST_FUNC bb_getgroups(int *ngroups, gid_t *group_array) | 14 | gid_t* FAST_FUNC bb_getgroups(int *ngroups, gid_t *group_array) |
14 | { | 15 | { |
15 | int n = ngroups ? *ngroups : 0; | 16 | int n = ngroups ? *ngroups : 0; |
@@ -45,6 +46,7 @@ gid_t* FAST_FUNC bb_getgroups(int *ngroups, gid_t *group_array) | |||
45 | *ngroups = n; | 46 | *ngroups = n; |
46 | return group_array; | 47 | return group_array; |
47 | } | 48 | } |
49 | #endif | ||
48 | 50 | ||
49 | uid_t FAST_FUNC get_cached_euid(uid_t *euid) | 51 | uid_t FAST_FUNC get_cached_euid(uid_t *euid) |
50 | { | 52 | { |
@@ -60,6 +62,11 @@ gid_t FAST_FUNC get_cached_egid(gid_t *egid) | |||
60 | return *egid; | 62 | return *egid; |
61 | } | 63 | } |
62 | 64 | ||
65 | #if !ENABLE_PLATFORM_MINGW32 | ||
66 | // Both current callers of is_in_supplementary_groups() check the gid | ||
67 | // first. Our implementation of getgroups() provides no additional | ||
68 | // information so there's no reason to call it. | ||
69 | |||
63 | /* Return non-zero if GID is in our supplementary group list. */ | 70 | /* Return non-zero if GID is in our supplementary group list. */ |
64 | int FAST_FUNC is_in_supplementary_groups(struct cached_groupinfo *groupinfo, gid_t gid) | 71 | int FAST_FUNC is_in_supplementary_groups(struct cached_groupinfo *groupinfo, gid_t gid) |
65 | { | 72 | { |
@@ -79,3 +86,4 @@ int FAST_FUNC is_in_supplementary_groups(struct cached_groupinfo *groupinfo, gid | |||
79 | 86 | ||
80 | return 0; | 87 | return 0; |
81 | } | 88 | } |
89 | #endif | ||
diff --git a/libbb/compare_string_array.c b/libbb/compare_string_array.c index d8cd033a3..70a4c29cf 100644 --- a/libbb/compare_string_array.c +++ b/libbb/compare_string_array.c | |||
@@ -27,11 +27,25 @@ char* FAST_FUNC is_prefixed_with(const char *string, const char *key) | |||
27 | #endif | 27 | #endif |
28 | } | 28 | } |
29 | 29 | ||
30 | #if ENABLE_PLATFORM_MINGW32 | ||
31 | char* FAST_FUNC is_prefixed_with_case(const char *string, const char *key) | ||
32 | { | ||
33 | while (*key != '\0') { | ||
34 | if (tolower(*key) != tolower(*string)) | ||
35 | return NULL; | ||
36 | key++; | ||
37 | string++; | ||
38 | } | ||
39 | return (char*)string; | ||
40 | } | ||
41 | #endif | ||
42 | |||
30 | /* | 43 | /* |
31 | * Return NULL if string is not suffixed with key. Return pointer to the | 44 | * Return NULL if string is not suffixed with key. Return pointer to the |
32 | * beginning of prefix key in string. If key is an empty string return pointer | 45 | * beginning of prefix key in string. If key is an empty string return pointer |
33 | * to the end of string. | 46 | * to the end of string. |
34 | */ | 47 | */ |
48 | #if !ENABLE_PLATFORM_MINGW32 | ||
35 | char* FAST_FUNC is_suffixed_with(const char *string, const char *key) | 49 | char* FAST_FUNC is_suffixed_with(const char *string, const char *key) |
36 | { | 50 | { |
37 | size_t key_len = strlen(key); | 51 | size_t key_len = strlen(key); |
@@ -46,6 +60,33 @@ char* FAST_FUNC is_suffixed_with(const char *string, const char *key) | |||
46 | 60 | ||
47 | return NULL; | 61 | return NULL; |
48 | } | 62 | } |
63 | #else | ||
64 | static char* FAST_FUNC is_suffixed(const char *string, const char *key, | ||
65 | int (*fn)(const char *, const char*)) | ||
66 | { | ||
67 | size_t key_len = strlen(key); | ||
68 | ssize_t len_diff = strlen(string) - key_len; | ||
69 | |||
70 | if (len_diff >= 0) { | ||
71 | string += len_diff; | ||
72 | if (fn(string, key) == 0) { | ||
73 | return (char*)string; | ||
74 | } | ||
75 | } | ||
76 | |||
77 | return NULL; | ||
78 | } | ||
79 | |||
80 | char* FAST_FUNC is_suffixed_with(const char *string, const char *key) | ||
81 | { | ||
82 | return is_suffixed(string, key, strcmp); | ||
83 | } | ||
84 | |||
85 | char* FAST_FUNC is_suffixed_with_case(const char *string, const char *key) | ||
86 | { | ||
87 | return is_suffixed(string, key, strcasecmp); | ||
88 | } | ||
89 | #endif | ||
49 | 90 | ||
50 | /* returns the array index of the string */ | 91 | /* returns the array index of the string */ |
51 | /* (index of first match is returned, or -1) */ | 92 | /* (index of first match is returned, or -1) */ |
diff --git a/libbb/concat_path_file.c b/libbb/concat_path_file.c index 5b4b7f113..3afb0e3a4 100644 --- a/libbb/concat_path_file.c +++ b/libbb/concat_path_file.c | |||
@@ -21,8 +21,14 @@ char* FAST_FUNC concat_path_file(const char *path, const char *filename) | |||
21 | 21 | ||
22 | if (!path) | 22 | if (!path) |
23 | path = ""; | 23 | path = ""; |
24 | #if ENABLE_PLATFORM_MINGW32 | ||
25 | lc = last_char_is_dir_sep(path); | ||
26 | while (is_dir_sep(*filename)) | ||
27 | filename++; | ||
28 | #else | ||
24 | lc = last_char_is(path, '/'); | 29 | lc = last_char_is(path, '/'); |
25 | while (*filename == '/') | 30 | while (*filename == '/') |
26 | filename++; | 31 | filename++; |
32 | #endif | ||
27 | return xasprintf("%s%s%s", path, (lc==NULL ? "/" : ""), filename); | 33 | return xasprintf("%s%s%s", path, (lc==NULL ? "/" : ""), filename); |
28 | } | 34 | } |
diff --git a/libbb/const_hack.c b/libbb/const_hack.c index 9575e6d67..75163fede 100644 --- a/libbb/const_hack.c +++ b/libbb/const_hack.c | |||
@@ -13,4 +13,14 @@ void FAST_FUNC XZALLOC_CONST_PTR(const void *pptr, size_t size) | |||
13 | { | 13 | { |
14 | ASSIGN_CONST_PTR(pptr, xzalloc(size)); | 14 | ASSIGN_CONST_PTR(pptr, xzalloc(size)); |
15 | } | 15 | } |
16 | |||
17 | # if ENABLE_PLATFORM_MINGW32 | ||
18 | void FAST_FUNC ASSIGN_CONST_PTR(const void *pptr, const void *v) | ||
19 | { | ||
20 | do { | ||
21 | *(void**)not_const_pp(pptr) = (void*)(v); | ||
22 | barrier(); | ||
23 | } while (0); | ||
24 | } | ||
25 | # endif | ||
16 | #endif | 26 | #endif |
diff --git a/libbb/copy_file.c b/libbb/copy_file.c index 044bc3c20..c0928a5a8 100644 --- a/libbb/copy_file.c +++ b/libbb/copy_file.c | |||
@@ -105,12 +105,18 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags) | |||
105 | return -1; | 105 | return -1; |
106 | } | 106 | } |
107 | } else { | 107 | } else { |
108 | #if ENABLE_PLATFORM_POSIX || ENABLE_FEATURE_EXTRA_FILE_DATA | ||
108 | if (source_stat.st_dev == dest_stat.st_dev | 109 | if (source_stat.st_dev == dest_stat.st_dev |
109 | && source_stat.st_ino == dest_stat.st_ino | 110 | && source_stat.st_ino == dest_stat.st_ino |
111 | # if ENABLE_FEATURE_EXTRA_FILE_DATA | ||
112 | /* ignore invalid inode numbers */ | ||
113 | && source_stat.st_ino != 0 | ||
114 | # endif | ||
110 | ) { | 115 | ) { |
111 | bb_error_msg("'%s' and '%s' are the same file", source, dest); | 116 | bb_error_msg("'%s' and '%s' are the same file", source, dest); |
112 | return -1; | 117 | return -1; |
113 | } | 118 | } |
119 | #endif | ||
114 | if (flags & FILEUTILS_NO_OVERWRITE) /* cp -n */ | 120 | if (flags & FILEUTILS_NO_OVERWRITE) /* cp -n */ |
115 | return 0; | 121 | return 0; |
116 | dest_exists = 1; | 122 | dest_exists = 1; |
diff --git a/libbb/dump.c b/libbb/dump.c index 2ca9919da..aa57eca8c 100644 --- a/libbb/dump.c +++ b/libbb/dump.c | |||
@@ -36,6 +36,9 @@ typedef struct priv_dumper_t { | |||
36 | off_t eaddress; /* end address */ | 36 | off_t eaddress; /* end address */ |
37 | int blocksize; | 37 | int blocksize; |
38 | smallint exitval; /* final exit value */ | 38 | smallint exitval; /* final exit value */ |
39 | #if ENABLE_PLATFORM_MINGW32 | ||
40 | FILE *fd; | ||
41 | #endif | ||
39 | 42 | ||
40 | /* former statics */ | 43 | /* former statics */ |
41 | smallint next__done; | 44 | smallint next__done; |
@@ -59,6 +62,9 @@ dumper_t* FAST_FUNC alloc_dumper(void) | |||
59 | dumper->pub.dump_length = -1; | 62 | dumper->pub.dump_length = -1; |
60 | dumper->pub.dump_vflag = FIRST; | 63 | dumper->pub.dump_vflag = FIRST; |
61 | dumper->get__ateof = 1; | 64 | dumper->get__ateof = 1; |
65 | #if ENABLE_PLATFORM_MINGW32 | ||
66 | dumper->fd = stdin; | ||
67 | #endif | ||
62 | return &dumper->pub; | 68 | return &dumper->pub; |
63 | } | 69 | } |
64 | 70 | ||
@@ -335,7 +341,11 @@ static void do_skip(priv_dumper_t *dumper, const char *fname) | |||
335 | { | 341 | { |
336 | struct stat sbuf; | 342 | struct stat sbuf; |
337 | 343 | ||
344 | #if ENABLE_PLATFORM_MINGW32 | ||
345 | xfstat(fileno(dumper->fd), &sbuf, fname); | ||
346 | #else | ||
338 | xfstat(STDIN_FILENO, &sbuf, fname); | 347 | xfstat(STDIN_FILENO, &sbuf, fname); |
348 | #endif | ||
339 | if (S_ISREG(sbuf.st_mode) | 349 | if (S_ISREG(sbuf.st_mode) |
340 | && dumper->pub.dump_skip >= sbuf.st_size | 350 | && dumper->pub.dump_skip >= sbuf.st_size |
341 | ) { | 351 | ) { |
@@ -344,7 +354,11 @@ static void do_skip(priv_dumper_t *dumper, const char *fname) | |||
344 | dumper->pub.address += sbuf.st_size; | 354 | dumper->pub.address += sbuf.st_size; |
345 | return; | 355 | return; |
346 | } | 356 | } |
357 | #if ENABLE_PLATFORM_MINGW32 | ||
358 | if (fseeko(dumper->fd, dumper->pub.dump_skip, SEEK_SET)) { | ||
359 | #else | ||
347 | if (fseeko(stdin, dumper->pub.dump_skip, SEEK_SET)) { | 360 | if (fseeko(stdin, dumper->pub.dump_skip, SEEK_SET)) { |
361 | #endif | ||
348 | bb_simple_perror_msg_and_die(fname); | 362 | bb_simple_perror_msg_and_die(fname); |
349 | } | 363 | } |
350 | dumper->pub.address += dumper->pub.dump_skip; | 364 | dumper->pub.address += dumper->pub.dump_skip; |
@@ -360,13 +374,23 @@ static NOINLINE int next(priv_dumper_t *dumper) | |||
360 | if (fname) { | 374 | if (fname) { |
361 | dumper->argv++; | 375 | dumper->argv++; |
362 | if (NOT_LONE_DASH(fname)) { | 376 | if (NOT_LONE_DASH(fname)) { |
377 | #if ENABLE_PLATFORM_MINGW32 | ||
378 | dumper->fd = fopen(fname, "r"); | ||
379 | if (!dumper->fd) { | ||
380 | #else | ||
363 | if (!freopen(fname, "r", stdin)) { | 381 | if (!freopen(fname, "r", stdin)) { |
382 | #endif | ||
364 | bb_simple_perror_msg(fname); | 383 | bb_simple_perror_msg(fname); |
365 | dumper->exitval = 1; | 384 | dumper->exitval = 1; |
366 | dumper->next__done = 1; | 385 | dumper->next__done = 1; |
367 | continue; | 386 | continue; |
368 | } | 387 | } |
369 | } | 388 | } |
389 | #if ENABLE_PLATFORM_MINGW32 | ||
390 | else { | ||
391 | dumper->fd = stdin; | ||
392 | } | ||
393 | #endif | ||
370 | } else { | 394 | } else { |
371 | if (dumper->next__done) | 395 | if (dumper->next__done) |
372 | return 0; /* no next file */ | 396 | return 0; /* no next file */ |
@@ -421,13 +445,25 @@ static unsigned char *get(priv_dumper_t *dumper) | |||
421 | dumper->eaddress = dumper->pub.address + nread; | 445 | dumper->eaddress = dumper->pub.address + nread; |
422 | return dumper->get__curp; | 446 | return dumper->get__curp; |
423 | } | 447 | } |
448 | #if ENABLE_PLATFORM_MINGW32 | ||
449 | n = fread(dumper->get__curp + nread, sizeof(unsigned char), | ||
450 | dumper->pub.dump_length == -1 ? need : MIN(dumper->pub.dump_length, need), dumper->fd); | ||
451 | #else | ||
424 | n = fread(dumper->get__curp + nread, sizeof(unsigned char), | 452 | n = fread(dumper->get__curp + nread, sizeof(unsigned char), |
425 | dumper->pub.dump_length == -1 ? need : MIN(dumper->pub.dump_length, need), stdin); | 453 | dumper->pub.dump_length == -1 ? need : MIN(dumper->pub.dump_length, need), stdin); |
454 | #endif | ||
426 | if (n == 0) { | 455 | if (n == 0) { |
456 | #if ENABLE_PLATFORM_MINGW32 | ||
457 | if (ferror(dumper->fd)) { | ||
458 | #else | ||
427 | if (ferror(stdin)) { | 459 | if (ferror(stdin)) { |
460 | #endif | ||
428 | bb_simple_perror_msg(dumper->argv[-1]); | 461 | bb_simple_perror_msg(dumper->argv[-1]); |
429 | } | 462 | } |
430 | dumper->get__ateof = 1; | 463 | dumper->get__ateof = 1; |
464 | #if ENABLE_PLATFORM_MINGW32 | ||
465 | fclose(dumper->fd); | ||
466 | #endif | ||
431 | continue; | 467 | continue; |
432 | } | 468 | } |
433 | dumper->get__ateof = 0; | 469 | dumper->get__ateof = 0; |
diff --git a/libbb/executable.c b/libbb/executable.c index 09bed1eaf..263141912 100644 --- a/libbb/executable.c +++ b/libbb/executable.c | |||
@@ -15,7 +15,12 @@ | |||
15 | int FAST_FUNC file_is_executable(const char *name) | 15 | int FAST_FUNC file_is_executable(const char *name) |
16 | { | 16 | { |
17 | struct stat s; | 17 | struct stat s; |
18 | #if !ENABLE_PLATFORM_MINGW32 | ||
18 | return (!access(name, X_OK) && !stat(name, &s) && S_ISREG(s.st_mode)); | 19 | return (!access(name, X_OK) && !stat(name, &s) && S_ISREG(s.st_mode)); |
20 | #else | ||
21 | /* expand WIN32 implementation of access(2) */ | ||
22 | return (!stat(name, &s) && S_ISREG(s.st_mode) && (s.st_mode & S_IXUSR)); | ||
23 | #endif | ||
19 | } | 24 | } |
20 | 25 | ||
21 | /* search (*PATHp) for an executable file; | 26 | /* search (*PATHp) for an executable file; |
@@ -40,8 +45,9 @@ char* FAST_FUNC find_executable(const char *name, const char **PATHp) | |||
40 | if (!p) | 45 | if (!p) |
41 | return NULL; | 46 | return NULL; |
42 | while (1) { | 47 | while (1) { |
43 | const char *end = strchrnul(p, ':'); | 48 | const char *end = strchrnul(p, PATH_SEP); |
44 | int sz = end - p; | 49 | int sz = end - p; |
50 | int ex; | ||
45 | 51 | ||
46 | if (sz != 0) { | 52 | if (sz != 0) { |
47 | p = xasprintf("%.*s/%s", sz, p, name); | 53 | p = xasprintf("%.*s/%s", sz, p, name); |
@@ -55,7 +61,19 @@ char* FAST_FUNC find_executable(const char *name, const char **PATHp) | |||
55 | // With -a, both skip over all colons: xxx::::yyy is the same as xxx::yyy, | 61 | // With -a, both skip over all colons: xxx::::yyy is the same as xxx::yyy, |
56 | // current dir is not tried the second time. | 62 | // current dir is not tried the second time. |
57 | } | 63 | } |
58 | if (file_is_executable(p)) { | 64 | #if ENABLE_PLATFORM_MINGW32 |
65 | { | ||
66 | char *w = file_is_win32_exe(p); | ||
67 | ex = w != NULL; | ||
68 | if (ex) { | ||
69 | free(p); | ||
70 | p = w; | ||
71 | } | ||
72 | } | ||
73 | #else | ||
74 | ex = file_is_executable(p); | ||
75 | #endif | ||
76 | if (ex) { | ||
59 | *PATHp = (*end ? end+1 : NULL); | 77 | *PATHp = (*end ? end+1 : NULL); |
60 | return p; | 78 | return p; |
61 | } | 79 | } |
diff --git a/libbb/find_mount_point.c b/libbb/find_mount_point.c index 0e1be3820..cf06c6e18 100644 --- a/libbb/find_mount_point.c +++ b/libbb/find_mount_point.c | |||
@@ -6,6 +6,9 @@ | |||
6 | * | 6 | * |
7 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | 7 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
8 | */ | 8 | */ |
9 | #if ENABLE_PLATFORM_MINGW32 | ||
10 | # define MNTENT_PRIVATE | ||
11 | #endif | ||
9 | #include "libbb.h" | 12 | #include "libbb.h" |
10 | #include <mntent.h> | 13 | #include <mntent.h> |
11 | 14 | ||
@@ -19,14 +22,22 @@ | |||
19 | struct mntent* FAST_FUNC find_mount_point(const char *name, int subdir_too) | 22 | struct mntent* FAST_FUNC find_mount_point(const char *name, int subdir_too) |
20 | { | 23 | { |
21 | struct stat s; | 24 | struct stat s; |
25 | #if !ENABLE_PLATFORM_MINGW32 | ||
22 | FILE *mtab_fp; | 26 | FILE *mtab_fp; |
23 | struct mntent *mountEntry; | 27 | struct mntent *mountEntry; |
24 | dev_t devno_of_name; | 28 | dev_t devno_of_name; |
25 | bool block_dev; | 29 | bool block_dev; |
30 | #else | ||
31 | struct mntent *mountEntry; | ||
32 | static struct mntdata *data = NULL; | ||
33 | char *current; | ||
34 | const char *path; | ||
35 | #endif | ||
26 | 36 | ||
27 | if (stat(name, &s) != 0) | 37 | if (stat(name, &s) != 0) |
28 | return NULL; | 38 | return NULL; |
29 | 39 | ||
40 | #if !ENABLE_PLATFORM_MINGW32 | ||
30 | devno_of_name = s.st_dev; | 41 | devno_of_name = s.st_dev; |
31 | block_dev = 0; | 42 | block_dev = 0; |
32 | /* Why S_ISCHR? - UBI volumes use char devices, not block */ | 43 | /* Why S_ISCHR? - UBI volumes use char devices, not block */ |
@@ -74,6 +85,26 @@ struct mntent* FAST_FUNC find_mount_point(const char *name, int subdir_too) | |||
74 | } | 85 | } |
75 | } | 86 | } |
76 | endmntent(mtab_fp); | 87 | endmntent(mtab_fp); |
88 | #else | ||
89 | mountEntry = NULL; | ||
90 | path = NULL; | ||
91 | current = NULL; | ||
92 | |||
93 | if ( isalpha(name[0]) && name[1] == ':' ) { | ||
94 | path = name; | ||
95 | } else { | ||
96 | path = current = xrealloc_getcwd_or_warn(NULL); | ||
97 | } | ||
98 | |||
99 | if ( path && isalpha(path[0]) && path[1] == ':' ) { | ||
100 | if (data == NULL) | ||
101 | data = xmalloc(sizeof(*data)); | ||
102 | |||
103 | fill_mntdata(data, toupper(path[0]) - 'A'); | ||
104 | mountEntry = &data->me; | ||
105 | } | ||
106 | free(current); | ||
107 | #endif | ||
77 | 108 | ||
78 | return mountEntry; | 109 | return mountEntry; |
79 | } | 110 | } |
diff --git a/libbb/find_pid_by_name.c b/libbb/find_pid_by_name.c index fe13f7211..0b6d5a206 100644 --- a/libbb/find_pid_by_name.c +++ b/libbb/find_pid_by_name.c | |||
@@ -39,8 +39,10 @@ and therefore comm field contains "exe". | |||
39 | 39 | ||
40 | static int comm_match(procps_status_t *p, const char *procName) | 40 | static int comm_match(procps_status_t *p, const char *procName) |
41 | { | 41 | { |
42 | #if !ENABLE_PLATFORM_MINGW32 | ||
42 | int argv1idx; | 43 | int argv1idx; |
43 | const char *argv1; | 44 | const char *argv1; |
45 | #endif | ||
44 | 46 | ||
45 | if (strncmp(p->comm, procName, 15) != 0) | 47 | if (strncmp(p->comm, procName, 15) != 0) |
46 | return 0; /* comm does not match */ | 48 | return 0; /* comm does not match */ |
@@ -55,6 +57,7 @@ static int comm_match(procps_status_t *p, const char *procName) | |||
55 | * This can be crazily_long_script_name.sh! | 57 | * This can be crazily_long_script_name.sh! |
56 | * The telltale sign is basename(argv[1]) == procName */ | 58 | * The telltale sign is basename(argv[1]) == procName */ |
57 | 59 | ||
60 | #if !ENABLE_PLATFORM_MINGW32 | ||
58 | if (!p->argv0) | 61 | if (!p->argv0) |
59 | return 0; | 62 | return 0; |
60 | 63 | ||
@@ -65,6 +68,7 @@ static int comm_match(procps_status_t *p, const char *procName) | |||
65 | 68 | ||
66 | if (strcmp(bb_basename(argv1), procName) != 0) | 69 | if (strcmp(bb_basename(argv1), procName) != 0) |
67 | return 0; | 70 | return 0; |
71 | #endif | ||
68 | 72 | ||
69 | return 1; | 73 | return 1; |
70 | } | 74 | } |
@@ -87,6 +91,7 @@ pid_t* FAST_FUNC find_pid_by_name(const char *procName) | |||
87 | pidList = xzalloc(sizeof(*pidList)); | 91 | pidList = xzalloc(sizeof(*pidList)); |
88 | while ((p = procps_scan(p, PSSCAN_PID|PSSCAN_COMM|PSSCAN_ARGVN|PSSCAN_EXE))) { | 92 | while ((p = procps_scan(p, PSSCAN_PID|PSSCAN_COMM|PSSCAN_ARGVN|PSSCAN_EXE))) { |
89 | if (comm_match(p, procName) | 93 | if (comm_match(p, procName) |
94 | #if !ENABLE_PLATFORM_MINGW32 | ||
90 | /* or we require argv0 to match (essential for matching reexeced /proc/self/exe)*/ | 95 | /* or we require argv0 to match (essential for matching reexeced /proc/self/exe)*/ |
91 | || (p->argv0 && strcmp(bb_basename(p->argv0), procName) == 0) | 96 | || (p->argv0 && strcmp(bb_basename(p->argv0), procName) == 0) |
92 | /* or we require /proc/PID/exe link to match */ | 97 | /* or we require /proc/PID/exe link to match */ |
@@ -95,6 +100,7 @@ pid_t* FAST_FUNC find_pid_by_name(const char *procName) | |||
95 | : bb_basename(p->exe), | 100 | : bb_basename(p->exe), |
96 | procName | 101 | procName |
97 | ) == 0) | 102 | ) == 0) |
103 | #endif | ||
98 | ) { | 104 | ) { |
99 | pidList = xrealloc_vector(pidList, 2, i); | 105 | pidList = xrealloc_vector(pidList, 2, i); |
100 | pidList[i++] = p->pid; | 106 | pidList[i++] = p->pid; |
diff --git a/libbb/get_last_path_component.c b/libbb/get_last_path_component.c index 04fdf2a3e..46a87d7fc 100644 --- a/libbb/get_last_path_component.c +++ b/libbb/get_last_path_component.c | |||
@@ -10,12 +10,34 @@ | |||
10 | 10 | ||
11 | const char* FAST_FUNC bb_basename(const char *name) | 11 | const char* FAST_FUNC bb_basename(const char *name) |
12 | { | 12 | { |
13 | #if ENABLE_PLATFORM_MINGW32 | ||
14 | const char *cp; | ||
15 | for (cp = name; *cp; cp++) | ||
16 | if (*cp == '/' || *cp == '\\' || *cp == ':') | ||
17 | name = cp + 1; | ||
18 | #else | ||
13 | const char *cp = strrchr(name, '/'); | 19 | const char *cp = strrchr(name, '/'); |
14 | if (cp) | 20 | if (cp) |
15 | return cp + 1; | 21 | return cp + 1; |
22 | #endif | ||
16 | return name; | 23 | return name; |
17 | } | 24 | } |
18 | 25 | ||
26 | #if ENABLE_PLATFORM_MINGW32 | ||
27 | char * FAST_FUNC get_last_slash(const char *path) | ||
28 | { | ||
29 | const char *start = path + root_len(path); | ||
30 | char *slash = strrchr(start, '/'); | ||
31 | char *bslash = strrchr(start, '\\'); | ||
32 | |||
33 | if (slash && bslash) | ||
34 | slash = MAX(slash, bslash); | ||
35 | else if (!slash) | ||
36 | slash = bslash; | ||
37 | return slash; | ||
38 | } | ||
39 | #endif | ||
40 | |||
19 | /* | 41 | /* |
20 | * "/" -> "/" | 42 | * "/" -> "/" |
21 | * "abc" -> "abc" | 43 | * "abc" -> "abc" |
@@ -24,10 +46,20 @@ const char* FAST_FUNC bb_basename(const char *name) | |||
24 | */ | 46 | */ |
25 | char* FAST_FUNC bb_get_last_path_component_nostrip(const char *path) | 47 | char* FAST_FUNC bb_get_last_path_component_nostrip(const char *path) |
26 | { | 48 | { |
49 | #if ENABLE_PLATFORM_MINGW32 | ||
50 | const char *start = path + root_len(path); | ||
51 | char *slash = get_last_slash(path); | ||
52 | |||
53 | if (!slash && has_dos_drive_prefix(path) && path[2] != '\0') | ||
54 | return (char *)path + 2; | ||
55 | if (!slash || (slash == start && !slash[1])) | ||
56 | return (char*)path; | ||
57 | #else | ||
27 | char *slash = strrchr(path, '/'); | 58 | char *slash = strrchr(path, '/'); |
28 | 59 | ||
29 | if (!slash || (slash == path && !slash[1])) | 60 | if (!slash || (slash == path && !slash[1])) |
30 | return (char*)path; | 61 | return (char*)path; |
62 | #endif | ||
31 | 63 | ||
32 | return slash + 1; | 64 | return slash + 1; |
33 | } | 65 | } |
@@ -40,11 +72,20 @@ char* FAST_FUNC bb_get_last_path_component_nostrip(const char *path) | |||
40 | */ | 72 | */ |
41 | char* FAST_FUNC bb_get_last_path_component_strip(char *path) | 73 | char* FAST_FUNC bb_get_last_path_component_strip(char *path) |
42 | { | 74 | { |
75 | #if ENABLE_PLATFORM_MINGW32 | ||
76 | char *slash = last_char_is_dir_sep(path); | ||
77 | const char *start = has_dos_drive_prefix(path) ? path+2 : path; | ||
78 | |||
79 | if (slash) | ||
80 | while (is_dir_sep(*slash) && slash != start) | ||
81 | *slash-- = '\0'; | ||
82 | #else | ||
43 | char *slash = last_char_is(path, '/'); | 83 | char *slash = last_char_is(path, '/'); |
44 | 84 | ||
45 | if (slash) | 85 | if (slash) |
46 | while (*slash == '/' && slash != path) | 86 | while (*slash == '/' && slash != path) |
47 | *slash-- = '\0'; | 87 | *slash-- = '\0'; |
88 | #endif | ||
48 | 89 | ||
49 | return bb_get_last_path_component_nostrip(path); | 90 | return bb_get_last_path_component_nostrip(path); |
50 | } | 91 | } |
diff --git a/libbb/get_line_from_file.c b/libbb/get_line_from_file.c index 903ff1fb6..2142ec94c 100644 --- a/libbb/get_line_from_file.c +++ b/libbb/get_line_from_file.c | |||
@@ -16,7 +16,11 @@ char* FAST_FUNC bb_get_chunk_from_file(FILE *file, size_t *end) | |||
16 | size_t idx = 0; | 16 | size_t idx = 0; |
17 | char *linebuf = NULL; | 17 | char *linebuf = NULL; |
18 | 18 | ||
19 | #if ENABLE_PLATFORM_MINGW32 | ||
20 | while ((ch = _getc_nolock(file)) != EOF) { | ||
21 | #else | ||
19 | while ((ch = getc(file)) != EOF) { | 22 | while ((ch = getc(file)) != EOF) { |
23 | #endif | ||
20 | /* grow the line buffer as necessary */ | 24 | /* grow the line buffer as necessary */ |
21 | if (!(idx & 0xff)) { | 25 | if (!(idx & 0xff)) { |
22 | if (idx == ((size_t)-1) - 0xff) | 26 | if (idx == ((size_t)-1) - 0xff) |
@@ -41,6 +45,11 @@ char* FAST_FUNC bb_get_chunk_from_file(FILE *file, size_t *end) | |||
41 | linebuf = xrealloc(linebuf, idx + 1); | 45 | linebuf = xrealloc(linebuf, idx + 1); |
42 | linebuf[idx] = '\0'; | 46 | linebuf[idx] = '\0'; |
43 | } | 47 | } |
48 | #if ENABLE_PLATFORM_MINGW32 | ||
49 | if (idx && isatty(fileno(file)) && | ||
50 | GetStdHandle(STD_INPUT_HANDLE) != INVALID_HANDLE_VALUE) | ||
51 | conToCharBuffA(linebuf, idx); | ||
52 | #endif | ||
44 | return linebuf; | 53 | return linebuf; |
45 | } | 54 | } |
46 | 55 | ||
@@ -57,8 +66,17 @@ char* FAST_FUNC xmalloc_fgetline(FILE *file) | |||
57 | size_t i; | 66 | size_t i; |
58 | char *c = bb_get_chunk_from_file(file, &i); | 67 | char *c = bb_get_chunk_from_file(file, &i); |
59 | 68 | ||
69 | #if !ENABLE_PLATFORM_MINGW32 | ||
60 | if (i && c[--i] == '\n') | 70 | if (i && c[--i] == '\n') |
61 | c[i] = '\0'; | 71 | c[i] = '\0'; |
72 | #else | ||
73 | if (i && c[--i] == '\n') { | ||
74 | c[i] = '\0'; | ||
75 | if (i && c[--i] == '\r') { | ||
76 | c[i] = '\0'; | ||
77 | } | ||
78 | } | ||
79 | #endif | ||
62 | 80 | ||
63 | return c; | 81 | return c; |
64 | } | 82 | } |
diff --git a/libbb/getopt32.c b/libbb/getopt32.c index b5efa19ac..76d29d5eb 100644 --- a/libbb/getopt32.c +++ b/libbb/getopt32.c | |||
@@ -592,7 +592,7 @@ vgetopt32(char **argv, const char *applet_opts, const char *applet_long_options, | |||
592 | return (int32_t)-1; | 592 | return (int32_t)-1; |
593 | } | 593 | } |
594 | 594 | ||
595 | uint32_t FAST_FUNC | 595 | uint32_t |
596 | getopt32(char **argv, const char *applet_opts, ...) | 596 | getopt32(char **argv, const char *applet_opts, ...) |
597 | { | 597 | { |
598 | uint32_t opt; | 598 | uint32_t opt; |
@@ -605,7 +605,7 @@ getopt32(char **argv, const char *applet_opts, ...) | |||
605 | } | 605 | } |
606 | 606 | ||
607 | #if ENABLE_LONG_OPTS | 607 | #if ENABLE_LONG_OPTS |
608 | uint32_t FAST_FUNC | 608 | uint32_t |
609 | getopt32long(char **argv, const char *applet_opts, const char *longopts, ...) | 609 | getopt32long(char **argv, const char *applet_opts, const char *longopts, ...) |
610 | { | 610 | { |
611 | uint32_t opt; | 611 | uint32_t opt; |
diff --git a/libbb/herror_msg.c b/libbb/herror_msg.c index a7dd98679..09537ae92 100644 --- a/libbb/herror_msg.c +++ b/libbb/herror_msg.c | |||
@@ -8,7 +8,7 @@ | |||
8 | */ | 8 | */ |
9 | #include "libbb.h" | 9 | #include "libbb.h" |
10 | 10 | ||
11 | void FAST_FUNC bb_herror_msg(const char *s, ...) | 11 | void bb_herror_msg(const char *s, ...) |
12 | { | 12 | { |
13 | va_list p; | 13 | va_list p; |
14 | 14 | ||
@@ -17,7 +17,7 @@ void FAST_FUNC bb_herror_msg(const char *s, ...) | |||
17 | va_end(p); | 17 | va_end(p); |
18 | } | 18 | } |
19 | 19 | ||
20 | void FAST_FUNC bb_herror_msg_and_die(const char *s, ...) | 20 | void bb_herror_msg_and_die(const char *s, ...) |
21 | { | 21 | { |
22 | va_list p; | 22 | va_list p; |
23 | 23 | ||
diff --git a/libbb/human_readable.c b/libbb/human_readable.c index 09221a186..3199ede6e 100644 --- a/libbb/human_readable.c +++ b/libbb/human_readable.c | |||
@@ -38,7 +38,7 @@ const char* FAST_FUNC make_human_readable_str(unsigned long long val, | |||
38 | if (val == 0) | 38 | if (val == 0) |
39 | return "0"; | 39 | return "0"; |
40 | 40 | ||
41 | fmt = "%llu"; | 41 | fmt = "%"LL_FMT"u"; |
42 | if (block_size > 1) | 42 | if (block_size > 1) |
43 | val *= block_size; | 43 | val *= block_size; |
44 | frac = 0; | 44 | frac = 0; |
@@ -52,7 +52,7 @@ const char* FAST_FUNC make_human_readable_str(unsigned long long val, | |||
52 | while ((val >= 1024) | 52 | while ((val >= 1024) |
53 | /* && (u < unit_chars + sizeof(unit_chars) - 1) - always true */ | 53 | /* && (u < unit_chars + sizeof(unit_chars) - 1) - always true */ |
54 | ) { | 54 | ) { |
55 | fmt = "%llu.%u%c"; | 55 | fmt = "%"LL_FMT"u.%u%c"; |
56 | u++; | 56 | u++; |
57 | frac = (((unsigned)val % 1024) * 10 + 1024/2) / 1024; | 57 | frac = (((unsigned)val % 1024) * 10 + 1024/2) / 1024; |
58 | val /= 1024; | 58 | val /= 1024; |
@@ -67,7 +67,7 @@ const char* FAST_FUNC make_human_readable_str(unsigned long long val, | |||
67 | if (frac >= 5) { | 67 | if (frac >= 5) { |
68 | ++val; | 68 | ++val; |
69 | } | 69 | } |
70 | fmt = "%llu%*c"; | 70 | fmt = "%"LL_FMT"u%*c"; |
71 | frac = 1; | 71 | frac = 1; |
72 | } | 72 | } |
73 | #endif | 73 | #endif |
diff --git a/libbb/inode_hash.c b/libbb/inode_hash.c index a125244ca..f2cc417bc 100644 --- a/libbb/inode_hash.c +++ b/libbb/inode_hash.c | |||
@@ -61,6 +61,11 @@ void FAST_FUNC add_to_ino_dev_hashtable(const struct stat *statbuf, const char * | |||
61 | int i; | 61 | int i; |
62 | ino_dev_hashtable_bucket_t *bucket; | 62 | ino_dev_hashtable_bucket_t *bucket; |
63 | 63 | ||
64 | #if ENABLE_FEATURE_EXTRA_FILE_DATA | ||
65 | /* ignore invalid inode numbers */ | ||
66 | if (statbuf->st_ino == 0) | ||
67 | return; | ||
68 | #endif | ||
64 | if (!name) | 69 | if (!name) |
65 | name = ""; | 70 | name = ""; |
66 | bucket = xmalloc(sizeof(ino_dev_hashtable_bucket_t) + strlen(name)); | 71 | bucket = xmalloc(sizeof(ino_dev_hashtable_bucket_t) + strlen(name)); |
diff --git a/libbb/last_char_is.c b/libbb/last_char_is.c index fba05f974..c2cd92174 100644 --- a/libbb/last_char_is.c +++ b/libbb/last_char_is.c | |||
@@ -17,3 +17,14 @@ char* FAST_FUNC last_char_is(const char *s, int c) | |||
17 | s++; | 17 | s++; |
18 | return (*s == (char)c) ? (char *) s : NULL; | 18 | return (*s == (char)c) ? (char *) s : NULL; |
19 | } | 19 | } |
20 | |||
21 | #if ENABLE_PLATFORM_MINGW32 | ||
22 | char* FAST_FUNC last_char_is_dir_sep(const char *s) | ||
23 | { | ||
24 | if (!s[0]) | ||
25 | return NULL; | ||
26 | while (s[1]) | ||
27 | s++; | ||
28 | return is_dir_sep(*s)? (char *) s : NULL; | ||
29 | } | ||
30 | #endif | ||
diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 151208c1c..8e2b37853 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c | |||
@@ -258,8 +258,14 @@ static NOINLINE const char *get_homedir_or_NULL(void) | |||
258 | # else | 258 | # else |
259 | home = getenv("HOME"); | 259 | home = getenv("HOME"); |
260 | # endif | 260 | # endif |
261 | if (home != NULL && home[0] != '\0') | 261 | if (home != NULL && home[0] != '\0') { |
262 | # if ENABLE_PLATFORM_MINGW32 | ||
263 | char *t = auto_string(xstrdup(home)); | ||
264 | bs_to_slash(t); | ||
265 | home = t; | ||
266 | # endif | ||
262 | return home; | 267 | return home; |
268 | } | ||
263 | 269 | ||
264 | if (!got_user_strings) | 270 | if (!got_user_strings) |
265 | get_user_strings(); | 271 | get_user_strings(); |
@@ -413,7 +419,7 @@ int adjust_width_and_validate_wc(unsigned *width_adj, int wc); | |||
413 | /* Put 'command_ps[cursor]', cursor++. | 419 | /* Put 'command_ps[cursor]', cursor++. |
414 | * Advance cursor on screen. If we reached right margin, scroll text up | 420 | * Advance cursor on screen. If we reached right margin, scroll text up |
415 | * and remove terminal margin effect by printing 'next_char' */ | 421 | * and remove terminal margin effect by printing 'next_char' */ |
416 | #define HACK_FOR_WRONG_WIDTH 1 | 422 | #define HACK_FOR_WRONG_WIDTH 1 && !ENABLE_PLATFORM_MINGW32 |
417 | static void put_cur_glyph_and_inc_cursor(void) | 423 | static void put_cur_glyph_and_inc_cursor(void) |
418 | { | 424 | { |
419 | CHAR_T c = command_ps[cursor]; | 425 | CHAR_T c = command_ps[cursor]; |
@@ -476,6 +482,42 @@ static void put_cur_glyph_and_inc_cursor(void) | |||
476 | } | 482 | } |
477 | } | 483 | } |
478 | 484 | ||
485 | #if ENABLE_PLATFORM_MINGW32 | ||
486 | static void inc_cursor(void) | ||
487 | { | ||
488 | CHAR_T c = command_ps[cursor]; | ||
489 | unsigned width = 0; | ||
490 | int ofs_to_right; | ||
491 | |||
492 | /* advance cursor */ | ||
493 | cursor++; | ||
494 | if (unicode_status == UNICODE_ON) { | ||
495 | IF_UNICODE_WIDE_WCHARS(width = cmdedit_x;) | ||
496 | c = adjust_width_and_validate_wc(&cmdedit_x, c); | ||
497 | IF_UNICODE_WIDE_WCHARS(width = cmdedit_x - width;) | ||
498 | } else { | ||
499 | cmdedit_x++; | ||
500 | } | ||
501 | |||
502 | ofs_to_right = cmdedit_x - cmdedit_termw; | ||
503 | if (!ENABLE_UNICODE_WIDE_WCHARS || ofs_to_right <= 0) { | ||
504 | /* cursor remains on this line */ | ||
505 | printf(ESC"[1C"); | ||
506 | } | ||
507 | |||
508 | if (ofs_to_right >= 0) { | ||
509 | /* we go to the next line */ | ||
510 | printf(ESC"[1B"); | ||
511 | bb_putchar('\r'); | ||
512 | cmdedit_y++; | ||
513 | if (!ENABLE_UNICODE_WIDE_WCHARS || ofs_to_right == 0) { | ||
514 | width = 0; | ||
515 | } | ||
516 | cmdedit_x = width; | ||
517 | } | ||
518 | } | ||
519 | #endif | ||
520 | |||
479 | /* Move to end of line (by printing all chars till the end) */ | 521 | /* Move to end of line (by printing all chars till the end) */ |
480 | static void put_till_end_and_adv_cursor(void) | 522 | static void put_till_end_and_adv_cursor(void) |
481 | { | 523 | { |
@@ -538,6 +580,7 @@ static void input_backward(unsigned num) | |||
538 | 580 | ||
539 | if (cmdedit_x >= num) { | 581 | if (cmdedit_x >= num) { |
540 | cmdedit_x -= num; | 582 | cmdedit_x -= num; |
583 | #if !ENABLE_PLATFORM_MINGW32 | ||
541 | if (num <= 4) { | 584 | if (num <= 4) { |
542 | /* This is longer by 5 bytes on x86. | 585 | /* This is longer by 5 bytes on x86. |
543 | * Also gets miscompiled for ARM users | 586 | * Also gets miscompiled for ARM users |
@@ -550,6 +593,7 @@ static void input_backward(unsigned num) | |||
550 | } while (--num); | 593 | } while (--num); |
551 | return; | 594 | return; |
552 | } | 595 | } |
596 | #endif | ||
553 | fprintf(stderr, ESC"[%uD", num); | 597 | fprintf(stderr, ESC"[%uD", num); |
554 | return; | 598 | return; |
555 | } | 599 | } |
@@ -688,7 +732,23 @@ static void input_backspace(void) | |||
688 | static void input_forward(void) | 732 | static void input_forward(void) |
689 | { | 733 | { |
690 | if (cursor < command_len) | 734 | if (cursor < command_len) |
735 | #if !ENABLE_PLATFORM_MINGW32 | ||
691 | put_cur_glyph_and_inc_cursor(); | 736 | put_cur_glyph_and_inc_cursor(); |
737 | #else | ||
738 | /* | ||
739 | * inc_cursor improves forward cursor movement appearance on | ||
740 | * win 7/8 console, but it's broken with unicode wide-glyphs, | ||
741 | * e.g. paste and move forward over: echo 开开心心过每一天 | ||
742 | * so disable inc_cursor when unicode is active (which is only | ||
743 | * windows 10+, where inc_cursor is not needed anyway). | ||
744 | */ | ||
745 | { | ||
746 | if (unicode_status == UNICODE_ON) | ||
747 | put_cur_glyph_and_inc_cursor(); | ||
748 | else | ||
749 | inc_cursor(); | ||
750 | } | ||
751 | #endif | ||
692 | } | 752 | } |
693 | 753 | ||
694 | #if ENABLE_FEATURE_TAB_COMPLETION | 754 | #if ENABLE_FEATURE_TAB_COMPLETION |
@@ -709,25 +769,56 @@ static void free_tab_completion_data(void) | |||
709 | } | 769 | } |
710 | } | 770 | } |
711 | 771 | ||
712 | static void add_match(char *matched) | 772 | #if !ENABLE_PLATFORM_MINGW32 |
773 | # define add_match(m, s) add_match(m) | ||
774 | #endif | ||
775 | |||
776 | static void add_match(char *matched, int sensitive) | ||
713 | { | 777 | { |
778 | # if ENABLE_PLATFORM_MINGW32 | ||
779 | size_t len; | ||
780 | # endif | ||
714 | unsigned char *p = (unsigned char*)matched; | 781 | unsigned char *p = (unsigned char*)matched; |
715 | while (*p) { | 782 | while (*p) { |
716 | /* ESC attack fix: drop any string with control chars */ | 783 | /* ESC attack fix: drop any string with control chars */ |
717 | if (*p < ' ' | 784 | if (*p < ' ' |
785 | # if !ENABLE_PLATFORM_MINGW32 | ||
718 | || (!ENABLE_UNICODE_SUPPORT && *p >= 0x7f) | 786 | || (!ENABLE_UNICODE_SUPPORT && *p >= 0x7f) |
719 | || (ENABLE_UNICODE_SUPPORT && *p == 0x7f) | 787 | || (ENABLE_UNICODE_SUPPORT && *p == 0x7f) |
788 | # else | ||
789 | /* | ||
790 | * on Windows, *p > 0x7f is never control: | ||
791 | * without unicode active: these are normal codepage chars. | ||
792 | * with unicode active: these are UTF8 continuation bytes. | ||
793 | */ | ||
794 | || *p == 0x7f | ||
795 | # endif | ||
720 | ) { | 796 | ) { |
721 | free(matched); | 797 | free(matched); |
722 | return; | 798 | return; |
723 | } | 799 | } |
724 | p++; | 800 | p++; |
725 | } | 801 | } |
802 | # if ENABLE_PLATFORM_MINGW32 | ||
803 | /* The case-sensitivity flag is stored after NUL terminator */ | ||
804 | len = strlen(matched); | ||
805 | matched = xrealloc(matched, len + 2); | ||
806 | matched[len + 1] = sensitive; | ||
807 | # endif | ||
726 | matches = xrealloc_vector(matches, 4, num_matches); | 808 | matches = xrealloc_vector(matches, 4, num_matches); |
727 | matches[num_matches] = matched; | 809 | matches[num_matches] = matched; |
728 | num_matches++; | 810 | num_matches++; |
729 | } | 811 | } |
730 | 812 | ||
813 | # if ENABLE_PLATFORM_MINGW32 | ||
814 | static int is_case_sensitive(const char *p) | ||
815 | { | ||
816 | while (*p++) | ||
817 | ; | ||
818 | return *p; | ||
819 | } | ||
820 | # endif | ||
821 | |||
731 | # if ENABLE_FEATURE_USERNAME_COMPLETION | 822 | # if ENABLE_FEATURE_USERNAME_COMPLETION |
732 | /* Replace "~user/..." with "/homedir/...". | 823 | /* Replace "~user/..." with "/homedir/...". |
733 | * The parameter is malloced, free it or return it | 824 | * The parameter is malloced, free it or return it |
@@ -735,13 +826,16 @@ static void add_match(char *matched) | |||
735 | */ | 826 | */ |
736 | static char *username_path_completion(char *ud) | 827 | static char *username_path_completion(char *ud) |
737 | { | 828 | { |
829 | # if !ENABLE_PLATFORM_MINGW32 | ||
738 | struct passwd *entry; | 830 | struct passwd *entry; |
831 | #endif | ||
739 | char *tilde_name = ud; | 832 | char *tilde_name = ud; |
740 | const char *home = NULL; | 833 | const char *home = NULL; |
741 | 834 | ||
742 | ud++; /* skip ~ */ | 835 | ud++; /* skip ~ */ |
743 | if (*ud == '/') { /* "~/..." */ | 836 | if (*ud == '/') { /* "~/..." */ |
744 | home = get_homedir_or_NULL(); | 837 | home = get_homedir_or_NULL(); |
838 | # if !ENABLE_PLATFORM_MINGW32 | ||
745 | } else { | 839 | } else { |
746 | /* "~user/..." */ | 840 | /* "~user/..." */ |
747 | ud = strchr(ud, '/'); | 841 | ud = strchr(ud, '/'); |
@@ -750,6 +844,7 @@ static char *username_path_completion(char *ud) | |||
750 | *ud = '/'; /* restore "~user/..." */ | 844 | *ud = '/'; /* restore "~user/..." */ |
751 | if (entry) | 845 | if (entry) |
752 | home = entry->pw_dir; | 846 | home = entry->pw_dir; |
847 | # endif | ||
753 | } | 848 | } |
754 | if (home) { | 849 | if (home) { |
755 | ud = concat_path_file(home, ud); | 850 | ud = concat_path_file(home, ud); |
@@ -759,6 +854,7 @@ static char *username_path_completion(char *ud) | |||
759 | return tilde_name; | 854 | return tilde_name; |
760 | } | 855 | } |
761 | 856 | ||
857 | # if !ENABLE_PLATFORM_MINGW32 | ||
762 | /* ~use<tab> - find all users with this prefix. | 858 | /* ~use<tab> - find all users with this prefix. |
763 | * Return the length of the prefix used for matching. | 859 | * Return the length of the prefix used for matching. |
764 | */ | 860 | */ |
@@ -774,13 +870,14 @@ static NOINLINE unsigned complete_username(const char *ud) | |||
774 | while ((pw = getpwent()) != NULL) { | 870 | while ((pw = getpwent()) != NULL) { |
775 | /* Null usernames should result in all users as possible completions. */ | 871 | /* Null usernames should result in all users as possible completions. */ |
776 | if (/* !ud[0] || */ is_prefixed_with(pw->pw_name, ud)) { | 872 | if (/* !ud[0] || */ is_prefixed_with(pw->pw_name, ud)) { |
777 | add_match(xasprintf("~%s/", pw->pw_name)); | 873 | add_match(xasprintf("~%s/", pw->pw_name), TRUE); |
778 | } | 874 | } |
779 | } | 875 | } |
780 | endpwent(); /* don't keep password file open */ | 876 | endpwent(); /* don't keep password file open */ |
781 | 877 | ||
782 | return 1 + userlen; | 878 | return 1 + userlen; |
783 | } | 879 | } |
880 | # endif | ||
784 | # endif /* FEATURE_USERNAME_COMPLETION */ | 881 | # endif /* FEATURE_USERNAME_COMPLETION */ |
785 | 882 | ||
786 | enum { | 883 | enum { |
@@ -810,7 +907,7 @@ static unsigned path_parse(char ***p) | |||
810 | tmp = (char*)pth; | 907 | tmp = (char*)pth; |
811 | npth = 1; /* path component count */ | 908 | npth = 1; /* path component count */ |
812 | while (1) { | 909 | while (1) { |
813 | tmp = strchr(tmp, ':'); | 910 | tmp = strchr(tmp, PATH_SEP); |
814 | if (!tmp) | 911 | if (!tmp) |
815 | break; | 912 | break; |
816 | tmp++; | 913 | tmp++; |
@@ -821,7 +918,7 @@ static unsigned path_parse(char ***p) | |||
821 | res[0] = tmp = xstrdup(pth); | 918 | res[0] = tmp = xstrdup(pth); |
822 | npth = 1; | 919 | npth = 1; |
823 | while (1) { | 920 | while (1) { |
824 | tmp = strchr(tmp, ':'); | 921 | tmp = strchr(tmp, PATH_SEP); |
825 | if (!tmp) | 922 | if (!tmp) |
826 | break; | 923 | break; |
827 | *tmp++ = '\0'; /* ':' -> '\0' */ | 924 | *tmp++ = '\0'; /* ':' -> '\0' */ |
@@ -849,6 +946,17 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type) | |||
849 | path1[0] = (char*)"."; | 946 | path1[0] = (char*)"."; |
850 | 947 | ||
851 | basecmd = strrchr(command, '/'); | 948 | basecmd = strrchr(command, '/'); |
949 | #if ENABLE_PLATFORM_MINGW32 | ||
950 | if (!basecmd && has_dos_drive_prefix(command) && command[2] != '\0') { | ||
951 | char buffer[PATH_MAX]; | ||
952 | |||
953 | /* path is of form c:path with no '/' */ | ||
954 | if (get_drive_cwd(command, buffer, PATH_MAX)) { | ||
955 | basecmd = command + 2; | ||
956 | path1[0] = dirbuf = xstrdup(buffer); | ||
957 | } | ||
958 | } else | ||
959 | #endif | ||
852 | if (!basecmd) { | 960 | if (!basecmd) { |
853 | if (type == FIND_EXE_ONLY) | 961 | if (type == FIND_EXE_ONLY) |
854 | npaths = path_parse(&paths); | 962 | npaths = path_parse(&paths); |
@@ -869,9 +977,13 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type) | |||
869 | if (type == FIND_EXE_ONLY && !dirbuf) { | 977 | if (type == FIND_EXE_ONLY && !dirbuf) { |
870 | # if ENABLE_FEATURE_SH_STANDALONE && NUM_APPLETS != 1 | 978 | # if ENABLE_FEATURE_SH_STANDALONE && NUM_APPLETS != 1 |
871 | const char *p = applet_names; | 979 | const char *p = applet_names; |
980 | # if ENABLE_PLATFORM_MINGW32 | ||
981 | const char *shpath = state->flags & WITH_PATH_LOOKUP ? | ||
982 | state->path_lookup : NULL; | ||
983 | # endif | ||
872 | while (*p) { | 984 | while (*p) { |
873 | if (strncmp(basecmd, p, baselen) == 0) | 985 | if (strncmp(basecmd, p, baselen) == 0 && prefer_applet(p, shpath)) |
874 | add_match(xstrdup(p)); | 986 | add_match(xstrdup(p), TRUE); |
875 | while (*p++ != '\0') | 987 | while (*p++ != '\0') |
876 | continue; | 988 | continue; |
877 | } | 989 | } |
@@ -884,7 +996,7 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type) | |||
884 | if (!b) | 996 | if (!b) |
885 | break; | 997 | break; |
886 | if (strncmp(basecmd, b, baselen) == 0) | 998 | if (strncmp(basecmd, b, baselen) == 0) |
887 | add_match(xstrdup(b)); | 999 | add_match(xstrdup(b), TRUE); |
888 | } | 1000 | } |
889 | } | 1001 | } |
890 | # endif | 1002 | # endif |
@@ -918,7 +1030,11 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type) | |||
918 | if (!basecmd[0] && DOT_OR_DOTDOT(name_found)) | 1030 | if (!basecmd[0] && DOT_OR_DOTDOT(name_found)) |
919 | continue; | 1031 | continue; |
920 | /* match? */ | 1032 | /* match? */ |
1033 | # if ENABLE_PLATFORM_MINGW32 | ||
1034 | if (strncasecmp(basecmd, name_found, baselen) != 0) | ||
1035 | # else | ||
921 | if (strncmp(basecmd, name_found, baselen) != 0) | 1036 | if (strncmp(basecmd, name_found, baselen) != 0) |
1037 | # endif | ||
922 | continue; /* no */ | 1038 | continue; /* no */ |
923 | 1039 | ||
924 | found = concat_path_file(lpath, name_found); | 1040 | found = concat_path_file(lpath, name_found); |
@@ -928,6 +1044,16 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type) | |||
928 | if (stat(found, &st) && lstat(found, &st)) | 1044 | if (stat(found, &st) && lstat(found, &st)) |
929 | goto cont; /* hmm, remove in progress? */ | 1045 | goto cont; /* hmm, remove in progress? */ |
930 | 1046 | ||
1047 | # if ENABLE_PLATFORM_MINGW32 | ||
1048 | # if ENABLE_ASH_GLOB_OPTIONS | ||
1049 | if (state->sh_accept_glob && !state->sh_accept_glob(found)) | ||
1050 | goto cont; | ||
1051 | # endif | ||
1052 | if (type == FIND_EXE_ONLY && S_ISREG(st.st_mode) && | ||
1053 | !(st.st_mode & S_IXUSR)) | ||
1054 | goto cont; | ||
1055 | # endif | ||
1056 | |||
931 | /* Save only name */ | 1057 | /* Save only name */ |
932 | len = strlen(name_found); | 1058 | len = strlen(name_found); |
933 | found = xrealloc(found, len + 2); /* +2: for slash and NUL */ | 1059 | found = xrealloc(found, len + 2); /* +2: for slash and NUL */ |
@@ -946,7 +1072,7 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type) | |||
946 | goto cont; | 1072 | goto cont; |
947 | } | 1073 | } |
948 | /* add it to the list */ | 1074 | /* add it to the list */ |
949 | add_match(found); | 1075 | add_match(found, FALSE); |
950 | continue; | 1076 | continue; |
951 | cont: | 1077 | cont: |
952 | free(found); | 1078 | free(found); |
@@ -1011,7 +1137,13 @@ static NOINLINE int build_match_prefix(char *match_buf) | |||
1011 | 1137 | ||
1012 | /* Mark every \c as "quoted c" */ | 1138 | /* Mark every \c as "quoted c" */ |
1013 | for (i = 0; int_buf[i]; i++) { | 1139 | for (i = 0; int_buf[i]; i++) { |
1140 | #if ENABLE_PLATFORM_MINGW32 | ||
1141 | /* Trailing backslash is effectively removed which confuses | ||
1142 | * the code to display case-preserved filenames. */ | ||
1143 | if (int_buf[i] == '\\' && int_buf[i+1] != '\0') { | ||
1144 | #else | ||
1014 | if (int_buf[i] == '\\') { | 1145 | if (int_buf[i] == '\\') { |
1146 | #endif | ||
1015 | remove_chunk(int_buf, i, i + 1); | 1147 | remove_chunk(int_buf, i, i + 1); |
1016 | int_buf[i] |= QUOT; | 1148 | int_buf[i] |= QUOT; |
1017 | } | 1149 | } |
@@ -1212,6 +1344,25 @@ static NOINLINE void input_tab(smallint *lastWasTab) | |||
1212 | size_t len_found; | 1344 | size_t len_found; |
1213 | /* Length of string used for matching */ | 1345 | /* Length of string used for matching */ |
1214 | unsigned match_pfx_len = match_pfx_len; | 1346 | unsigned match_pfx_len = match_pfx_len; |
1347 | # if ENABLE_PLATFORM_MINGW32 | ||
1348 | int chosen_index = 0; | ||
1349 | int chosen_sens = FALSE; | ||
1350 | # if !ENABLE_UNICODE_SUPPORT | ||
1351 | /* | ||
1352 | * FIXME: the next three vars are unused with ENABLE_UNICODE_SUPPORT | ||
1353 | * because the mingw code which uses them to update a tab-completion | ||
1354 | * prefix to the correct case (e.g. ~/desk<tab> to ~/Desktop/) is | ||
1355 | * not compiled, and so e.g. ~/desk<tab> completes to ~/desktop/ . | ||
1356 | */ | ||
1357 | unsigned orig_pfx_len; | ||
1358 | char *target; | ||
1359 | const char *source; | ||
1360 | # endif | ||
1361 | # define first_match 0 | ||
1362 | # else | ||
1363 | # define chosen_index 0 | ||
1364 | # define first_match 1 | ||
1365 | # endif | ||
1215 | int find_type; | 1366 | int find_type; |
1216 | # if ENABLE_UNICODE_SUPPORT | 1367 | # if ENABLE_UNICODE_SUPPORT |
1217 | /* cursor pos in command converted to multibyte form */ | 1368 | /* cursor pos in command converted to multibyte form */ |
@@ -1259,7 +1410,7 @@ static NOINLINE void input_tab(smallint *lastWasTab) | |||
1259 | /* Free up any memory already allocated */ | 1410 | /* Free up any memory already allocated */ |
1260 | free_tab_completion_data(); | 1411 | free_tab_completion_data(); |
1261 | 1412 | ||
1262 | # if ENABLE_FEATURE_USERNAME_COMPLETION | 1413 | # if ENABLE_FEATURE_USERNAME_COMPLETION && !ENABLE_PLATFORM_MINGW32 |
1263 | /* If the word starts with ~ and there is no slash in the word, | 1414 | /* If the word starts with ~ and there is no slash in the word, |
1264 | * then try completing this word as a username. */ | 1415 | * then try completing this word as a username. */ |
1265 | if (state->flags & USERNAME_COMPLETION) | 1416 | if (state->flags & USERNAME_COMPLETION) |
@@ -1276,6 +1427,9 @@ static NOINLINE void input_tab(smallint *lastWasTab) | |||
1276 | { | 1427 | { |
1277 | const char *e = match_buf + strlen(match_buf); | 1428 | const char *e = match_buf + strlen(match_buf); |
1278 | const char *s = e - match_pfx_len; | 1429 | const char *s = e - match_pfx_len; |
1430 | # if ENABLE_PLATFORM_MINGW32 && !ENABLE_UNICODE_SUPPORT | ||
1431 | orig_pfx_len = match_pfx_len; | ||
1432 | # endif | ||
1279 | while (s < e) | 1433 | while (s < e) |
1280 | if (is_special_char(*s++)) | 1434 | if (is_special_char(*s++)) |
1281 | match_pfx_len++; | 1435 | match_pfx_len++; |
@@ -1306,10 +1460,29 @@ static NOINLINE void input_tab(smallint *lastWasTab) | |||
1306 | if (!matches) | 1460 | if (!matches) |
1307 | goto ret; /* no matches at all */ | 1461 | goto ret; /* no matches at all */ |
1308 | /* Find common prefix */ | 1462 | /* Find common prefix */ |
1309 | chosen_match = xstrdup(matches[0]); | 1463 | # if ENABLE_PLATFORM_MINGW32 |
1464 | /* Any comparison involving a filename must be case-insensitive. | ||
1465 | * The chosen match should be case-sensitive, if possible */ | ||
1466 | for (unsigned i = 0; i < num_matches; ++i) { | ||
1467 | if (is_case_sensitive(matches[i])) { | ||
1468 | chosen_index = i; | ||
1469 | chosen_sens = TRUE; | ||
1470 | break; | ||
1471 | } | ||
1472 | } | ||
1473 | # endif | ||
1474 | chosen_match = xstrdup(matches[chosen_index]); | ||
1310 | for (cp = chosen_match; *cp; cp++) { | 1475 | for (cp = chosen_match; *cp; cp++) { |
1311 | unsigned n; | 1476 | unsigned n; |
1312 | for (n = 1; n < num_matches; n++) { | 1477 | for (n = first_match; n < num_matches; n++) { |
1478 | # if ENABLE_PLATFORM_MINGW32 | ||
1479 | if (!is_case_sensitive(matches[n]) || !chosen_sens) { | ||
1480 | if (tolower(matches[n][cp - chosen_match]) != | ||
1481 | tolower(*cp)) { | ||
1482 | goto stop; | ||
1483 | } | ||
1484 | } else | ||
1485 | # endif | ||
1313 | if (matches[n][cp - chosen_match] != *cp) { | 1486 | if (matches[n][cp - chosen_match] != *cp) { |
1314 | goto stop; | 1487 | goto stop; |
1315 | } | 1488 | } |
@@ -1346,7 +1519,21 @@ static NOINLINE void input_tab(smallint *lastWasTab) | |||
1346 | /* save tail */ | 1519 | /* save tail */ |
1347 | strcpy(match_buf, &command_ps[cursor]); | 1520 | strcpy(match_buf, &command_ps[cursor]); |
1348 | /* add match and tail */ | 1521 | /* add match and tail */ |
1522 | # if ENABLE_PLATFORM_MINGW32 | ||
1523 | if (match_pfx_len == orig_pfx_len) { | ||
1524 | /* replace match prefix to allow for altered case */ | ||
1525 | target = &command_ps[cursor-match_pfx_len]; | ||
1526 | source = chosen_match; | ||
1527 | } | ||
1528 | else { | ||
1529 | /* only replace tail of match if special characters are quoted */ | ||
1530 | target = &command_ps[cursor]; | ||
1531 | source = chosen_match + match_pfx_len; | ||
1532 | } | ||
1533 | strcpy(stpcpy(target, source), match_buf); | ||
1534 | # else | ||
1349 | sprintf(&command_ps[cursor], "%s%s", chosen_match + match_pfx_len, match_buf); | 1535 | sprintf(&command_ps[cursor], "%s%s", chosen_match + match_pfx_len, match_buf); |
1536 | # endif | ||
1350 | command_len = strlen(command_ps); | 1537 | command_len = strlen(command_ps); |
1351 | /* new pos */ | 1538 | /* new pos */ |
1352 | pos = cursor + len_found - match_pfx_len; | 1539 | pos = cursor + len_found - match_pfx_len; |
@@ -1382,7 +1569,6 @@ static NOINLINE void input_tab(smallint *lastWasTab) | |||
1382 | free(chosen_match); | 1569 | free(chosen_match); |
1383 | free(match_buf); | 1570 | free(match_buf); |
1384 | } | 1571 | } |
1385 | |||
1386 | #endif /* FEATURE_TAB_COMPLETION */ | 1572 | #endif /* FEATURE_TAB_COMPLETION */ |
1387 | 1573 | ||
1388 | 1574 | ||
@@ -1402,7 +1588,11 @@ line_input_t* FAST_FUNC new_line_input_t(int flags) | |||
1402 | 1588 | ||
1403 | unsigned FAST_FUNC size_from_HISTFILESIZE(const char *hp) | 1589 | unsigned FAST_FUNC size_from_HISTFILESIZE(const char *hp) |
1404 | { | 1590 | { |
1591 | # if ENABLE_PLATFORM_MINGW32 && DEFAULT_HISTORY > 0 && DEFAULT_HISTORY <= MAX_HISTORY | ||
1592 | int size = DEFAULT_HISTORY; | ||
1593 | # else | ||
1405 | int size = MAX_HISTORY; | 1594 | int size = MAX_HISTORY; |
1595 | # endif | ||
1406 | if (hp) { | 1596 | if (hp) { |
1407 | size = atoi(hp); | 1597 | size = atoi(hp); |
1408 | if (size <= 0) | 1598 | if (size <= 0) |
@@ -2053,7 +2243,11 @@ static void parse_and_put_prompt(const char *prmt_ptr) | |||
2053 | char *after_home_user; | 2243 | char *after_home_user; |
2054 | 2244 | ||
2055 | /* /home/user[/something] -> ~[/something] */ | 2245 | /* /home/user[/something] -> ~[/something] */ |
2246 | #if !ENABLE_PLATFORM_MINGW32 | ||
2056 | after_home_user = is_prefixed_with(cwd_buf, home); | 2247 | after_home_user = is_prefixed_with(cwd_buf, home); |
2248 | #else | ||
2249 | after_home_user = is_prefixed_with_case(cwd_buf, home); | ||
2250 | #endif | ||
2057 | if (after_home_user | 2251 | if (after_home_user |
2058 | && (*after_home_user == '/' || *after_home_user == '\0') | 2252 | && (*after_home_user == '/' || *after_home_user == '\0') |
2059 | ) { | 2253 | ) { |
@@ -2484,7 +2678,11 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman | |||
2484 | n = get_termios_and_make_raw(STDIN_FILENO, &new_settings, &initial_settings, 0 | 2678 | n = get_termios_and_make_raw(STDIN_FILENO, &new_settings, &initial_settings, 0 |
2485 | | TERMIOS_CLEAR_ISIG /* turn off INTR (ctrl-C), QUIT, SUSP */ | 2679 | | TERMIOS_CLEAR_ISIG /* turn off INTR (ctrl-C), QUIT, SUSP */ |
2486 | ); | 2680 | ); |
2681 | #if !ENABLE_PLATFORM_MINGW32 | ||
2487 | if (n != 0 || (initial_settings.c_lflag & (ECHO|ICANON)) == ICANON) { | 2682 | if (n != 0 || (initial_settings.c_lflag & (ECHO|ICANON)) == ICANON) { |
2683 | #else | ||
2684 | if (n != 0 || !isatty(0)) { | ||
2685 | #endif | ||
2488 | /* Happens when e.g. stty -echo was run before. | 2686 | /* Happens when e.g. stty -echo was run before. |
2489 | * But if ICANON is not set, we don't come here. | 2687 | * But if ICANON is not set, we don't come here. |
2490 | * (example: interactive python ^Z-backgrounded, | 2688 | * (example: interactive python ^Z-backgrounded, |
@@ -2494,8 +2692,12 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman | |||
2494 | fflush_all(); | 2692 | fflush_all(); |
2495 | if (fgets(command, maxsize, stdin) == NULL) | 2693 | if (fgets(command, maxsize, stdin) == NULL) |
2496 | len = -1; /* EOF or error */ | 2694 | len = -1; /* EOF or error */ |
2497 | else | 2695 | else { |
2498 | len = strlen(command); | 2696 | len = strlen(command); |
2697 | #if ENABLE_PLATFORM_MINGW32 | ||
2698 | len = remove_cr(command, len); | ||
2699 | #endif | ||
2700 | } | ||
2499 | DEINIT_S(); | 2701 | DEINIT_S(); |
2500 | return len; | 2702 | return len; |
2501 | } | 2703 | } |
@@ -2577,6 +2779,11 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman | |||
2577 | } | 2779 | } |
2578 | #endif | 2780 | #endif |
2579 | ic = ic_raw = lineedit_read_key(read_key_buffer, timeout); | 2781 | ic = ic_raw = lineedit_read_key(read_key_buffer, timeout); |
2782 | #if ENABLE_PLATFORM_MINGW32 | ||
2783 | /* scroll to cursor position on any keypress */ | ||
2784 | if (isatty(fileno(stdin)) && isatty(fileno(stdout))) | ||
2785 | move_cursor_row(0); | ||
2786 | #endif | ||
2580 | 2787 | ||
2581 | #if ENABLE_FEATURE_REVERSE_SEARCH | 2788 | #if ENABLE_FEATURE_REVERSE_SEARCH |
2582 | again: | 2789 | again: |
@@ -2638,6 +2845,17 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman | |||
2638 | input_tab(&lastWasTab); | 2845 | input_tab(&lastWasTab); |
2639 | break; | 2846 | break; |
2640 | #endif | 2847 | #endif |
2848 | #if ENABLE_PLATFORM_MINGW32 | ||
2849 | case CTRL('Z'): | ||
2850 | command_ps[command_len] = '\0'; | ||
2851 | #if ENABLE_UNICODE_SUPPORT | ||
2852 | bs_to_slash_u(command_ps); | ||
2853 | #else | ||
2854 | bs_to_slash(command_ps); | ||
2855 | #endif | ||
2856 | redraw(cmdedit_y, 0); | ||
2857 | break; | ||
2858 | #endif | ||
2641 | case CTRL('K'): | 2859 | case CTRL('K'): |
2642 | /* Control-k -- clear to end of line */ | 2860 | /* Control-k -- clear to end of line */ |
2643 | command_ps[cursor] = BB_NUL; | 2861 | command_ps[cursor] = BB_NUL; |
@@ -2892,6 +3110,10 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman | |||
2892 | && ic_raw == initial_settings.c_cc[VINTR] | 3110 | && ic_raw == initial_settings.c_cc[VINTR] |
2893 | ) { | 3111 | ) { |
2894 | /* Ctrl-C (usually) - stop gathering input */ | 3112 | /* Ctrl-C (usually) - stop gathering input */ |
3113 | #if ENABLE_PLATFORM_MINGW32 | ||
3114 | if (state->flags & IGNORE_CTRL_C) | ||
3115 | break; | ||
3116 | #endif | ||
2895 | command_len = 0; | 3117 | command_len = 0; |
2896 | break_out = -1; /* "do not append '\n'" */ | 3118 | break_out = -1; /* "do not append '\n'" */ |
2897 | break; | 3119 | break; |
diff --git a/libbb/make_directory.c b/libbb/make_directory.c index 9b03bb8d0..e0fd486d8 100644 --- a/libbb/make_directory.c +++ b/libbb/make_directory.c | |||
@@ -49,11 +49,19 @@ int FAST_FUNC bb_make_directory(char *path, long mode, int flags) | |||
49 | } | 49 | } |
50 | 50 | ||
51 | org_mask = cur_mask = (mode_t)-1L; | 51 | org_mask = cur_mask = (mode_t)-1L; |
52 | #if ENABLE_PLATFORM_MINGW32 | ||
53 | /* normalise path separators, path is already assumed writable */ | ||
54 | bs_to_slash(path); | ||
55 | #endif | ||
52 | s = path; | 56 | s = path; |
53 | while (1) { | 57 | while (1) { |
54 | c = '\0'; | 58 | c = '\0'; |
55 | 59 | ||
56 | if (flags & FILEUTILS_RECUR) { /* Get the parent */ | 60 | if (flags & FILEUTILS_RECUR) { /* Get the parent */ |
61 | #if ENABLE_PLATFORM_MINGW32 | ||
62 | if (s == path) | ||
63 | s += root_len(path); | ||
64 | #endif | ||
57 | /* Bypass leading non-'/'s and then subsequent '/'s */ | 65 | /* Bypass leading non-'/'s and then subsequent '/'s */ |
58 | while (*s) { | 66 | while (*s) { |
59 | if (*s == '/') { | 67 | if (*s == '/') { |
diff --git a/libbb/messages.c b/libbb/messages.c index 6914d5701..311eda004 100644 --- a/libbb/messages.c +++ b/libbb/messages.c | |||
@@ -5,6 +5,9 @@ | |||
5 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | 5 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
6 | */ | 6 | */ |
7 | #include "libbb.h" | 7 | #include "libbb.h" |
8 | #if ENABLE_PLATFORM_MINGW32 | ||
9 | # include "BB_VER.h" | ||
10 | #endif | ||
8 | 11 | ||
9 | /* allow version to be extended, via CFLAGS */ | 12 | /* allow version to be extended, via CFLAGS */ |
10 | #ifndef BB_EXTRA_VERSION | 13 | #ifndef BB_EXTRA_VERSION |
@@ -27,7 +30,26 @@ const char bb_msg_standard_output[] ALIGN1 = "standard output"; | |||
27 | 30 | ||
28 | const char bb_hexdigits_upcase[] ALIGN1 = "0123456789ABCDEF"; | 31 | const char bb_hexdigits_upcase[] ALIGN1 = "0123456789ABCDEF"; |
29 | 32 | ||
33 | #if !ENABLE_PLATFORM_MINGW32 | ||
30 | const char bb_busybox_exec_path[] ALIGN1 = CONFIG_BUSYBOX_EXEC_PATH; | 34 | const char bb_busybox_exec_path[] ALIGN1 = CONFIG_BUSYBOX_EXEC_PATH; |
35 | #else | ||
36 | /* Some special shell variables are placed in the environment immediately | ||
37 | * when they're exported. | ||
38 | * | ||
39 | * BB_GLOBBING and BB_UMASK are excluded because users shouldn't be | ||
40 | * messing with them; BB_FIX_BACKSLASH is excluded because it only | ||
41 | * affects particular applets, not the shell itself. | ||
42 | * | ||
43 | * If you change any of these you should also update the definitions in | ||
44 | * include/libbb.h. | ||
45 | */ | ||
46 | const char bbvar[] ALIGN1 = | ||
47 | "BB_OVERRIDE_APPLETS\0" \ | ||
48 | "BB_SKIP_ANSI_EMULATION\0" \ | ||
49 | "BB_TERMINAL_MODE\0" \ | ||
50 | "BB_SYSTEMROOT\0" \ | ||
51 | "BB_CRITICAL_ERROR_DIALOGS\0"; | ||
52 | #endif | ||
31 | const char bb_default_login_shell[] ALIGN1 = LIBBB_DEFAULT_LOGIN_SHELL; | 53 | const char bb_default_login_shell[] ALIGN1 = LIBBB_DEFAULT_LOGIN_SHELL; |
32 | /* util-linux manpage says /sbin:/bin:/usr/sbin:/usr/bin, | 54 | /* util-linux manpage says /sbin:/bin:/usr/sbin:/usr/bin, |
33 | * but I want to save a few bytes here. Check libbb.h before changing! */ | 55 | * but I want to save a few bytes here. Check libbb.h before changing! */ |
diff --git a/libbb/mode_string.c b/libbb/mode_string.c index 52abe66f7..906c03964 100644 --- a/libbb/mode_string.c +++ b/libbb/mode_string.c | |||
@@ -19,7 +19,7 @@ | |||
19 | /* Generate ls-style "mode string" like "-rwsr-xr-x" or "drwxrwxrwt" */ | 19 | /* Generate ls-style "mode string" like "-rwsr-xr-x" or "drwxrwxrwt" */ |
20 | 20 | ||
21 | #if ( S_IFSOCK!= 0140000 ) || ( S_IFLNK != 0120000 ) \ | 21 | #if ( S_IFSOCK!= 0140000 ) || ( S_IFLNK != 0120000 ) \ |
22 | || ( S_IFREG != 0100000 ) || ( S_IFBLK != 0060000 ) \ | 22 | || ( S_IFREG != 0100000 ) || ( S_IFBLK != 0060000 && S_IFBLK != 0030000 ) \ |
23 | || ( S_IFDIR != 0040000 ) || ( S_IFCHR != 0020000 ) \ | 23 | || ( S_IFDIR != 0040000 ) || ( S_IFCHR != 0020000 ) \ |
24 | || ( S_IFIFO != 0010000 ) | 24 | || ( S_IFIFO != 0010000 ) |
25 | # warning mode type bitflag value assumption(s) violated! falling back to larger version | 25 | # warning mode type bitflag value assumption(s) violated! falling back to larger version |
diff --git a/libbb/parse_config.c b/libbb/parse_config.c index 8701b010c..bcd667c7c 100644 --- a/libbb/parse_config.c +++ b/libbb/parse_config.c | |||
@@ -113,8 +113,17 @@ static int get_line_with_continuation(parser_t *parser) | |||
113 | line = parser->line; | 113 | line = parser->line; |
114 | for (;;) { | 114 | for (;;) { |
115 | parser->lineno++; | 115 | parser->lineno++; |
116 | #if !ENABLE_PLATFORM_MINGW32 | ||
116 | if (line[len - 1] == '\n') | 117 | if (line[len - 1] == '\n') |
117 | len--; | 118 | len--; |
119 | #else | ||
120 | if (line[len - 1] == '\n') { | ||
121 | len--; | ||
122 | if (len != 0 && line[len - 1] == '\r') { | ||
123 | len--; | ||
124 | } | ||
125 | } | ||
126 | #endif | ||
118 | if (len == 0 || line[len - 1] != '\\') | 127 | if (len == 0 || line[len - 1] != '\\') |
119 | break; | 128 | break; |
120 | len--; | 129 | len--; |
diff --git a/libbb/perror_msg.c b/libbb/perror_msg.c index fa1f0d339..32adb8c38 100644 --- a/libbb/perror_msg.c +++ b/libbb/perror_msg.c | |||
@@ -8,7 +8,7 @@ | |||
8 | */ | 8 | */ |
9 | #include "libbb.h" | 9 | #include "libbb.h" |
10 | 10 | ||
11 | void FAST_FUNC bb_perror_msg(const char *s, ...) | 11 | void bb_perror_msg(const char *s, ...) |
12 | { | 12 | { |
13 | va_list p; | 13 | va_list p; |
14 | 14 | ||
@@ -18,7 +18,7 @@ void FAST_FUNC bb_perror_msg(const char *s, ...) | |||
18 | va_end(p); | 18 | va_end(p); |
19 | } | 19 | } |
20 | 20 | ||
21 | void FAST_FUNC bb_perror_msg_and_die(const char *s, ...) | 21 | void bb_perror_msg_and_die(const char *s, ...) |
22 | { | 22 | { |
23 | va_list p; | 23 | va_list p; |
24 | 24 | ||
diff --git a/libbb/printable_string.c b/libbb/printable_string.c index a814fd03c..2e8895a4f 100644 --- a/libbb/printable_string.c +++ b/libbb/printable_string.c | |||
@@ -42,7 +42,7 @@ const char* FAST_FUNC printable_string2(uni_stat_t *stats, const char *str) | |||
42 | unsigned char c = *d; | 42 | unsigned char c = *d; |
43 | if (c == '\0') | 43 | if (c == '\0') |
44 | break; | 44 | break; |
45 | if (c < ' ' || c >= 0x7f) | 45 | if (c < ' ' || (c >= 0x7f && !ENABLE_PLATFORM_MINGW32)) |
46 | *d = '?'; | 46 | *d = '?'; |
47 | d++; | 47 | d++; |
48 | } | 48 | } |
diff --git a/libbb/procps.c b/libbb/procps.c index f56b71b21..8c9cac125 100644 --- a/libbb/procps.c +++ b/libbb/procps.c | |||
@@ -63,6 +63,7 @@ const char* FAST_FUNC get_cached_groupname(gid_t gid) | |||
63 | return get_cached(1, gid, gid2group_utoa); | 63 | return get_cached(1, gid, gid2group_utoa); |
64 | } | 64 | } |
65 | 65 | ||
66 | #if !ENABLE_PLATFORM_MINGW32 | ||
66 | 67 | ||
67 | #define PROCPS_BUFSIZE 1024 | 68 | #define PROCPS_BUFSIZE 1024 |
68 | 69 | ||
@@ -618,6 +619,8 @@ void FAST_FUNC read_cmdline(char *buf, int col, unsigned pid, const char *comm) | |||
618 | } | 619 | } |
619 | } | 620 | } |
620 | 621 | ||
622 | #endif /* ENABLE_PLATFORM_MINGW32 */ | ||
623 | |||
621 | /* from kernel: | 624 | /* from kernel: |
622 | // pid comm S ppid pgid sid tty_nr tty_pgrp flg | 625 | // pid comm S ppid pgid sid tty_nr tty_pgrp flg |
623 | sprintf(buffer,"%d (%s) %c %d %d %d %d %d %lu %lu \ | 626 | sprintf(buffer,"%d (%s) %c %d %d %d %d %d %lu %lu \ |
diff --git a/libbb/read_key.c b/libbb/read_key.c index cf8ed411e..54886cc9c 100644 --- a/libbb/read_key.c +++ b/libbb/read_key.c | |||
@@ -112,6 +112,11 @@ int64_t FAST_FUNC read_key(int fd, char *buffer, int timeout) | |||
112 | 0 | 112 | 0 |
113 | }; | 113 | }; |
114 | 114 | ||
115 | #if ENABLE_PLATFORM_MINGW32 | ||
116 | if (!(terminal_mode(FALSE) & VT_INPUT)) | ||
117 | return windows_read_key(fd, buffer, timeout); | ||
118 | #endif | ||
119 | |||
115 | pfd.fd = fd; | 120 | pfd.fd = fd; |
116 | pfd.events = POLLIN; | 121 | pfd.events = POLLIN; |
117 | 122 | ||
diff --git a/libbb/read_printf.c b/libbb/read_printf.c index 0cd04ab7b..379dd2448 100644 --- a/libbb/read_printf.c +++ b/libbb/read_printf.c | |||
@@ -93,6 +93,11 @@ char* FAST_FUNC xmalloc_reads(int fd, size_t *maxsz_p) | |||
93 | break; | 93 | break; |
94 | p++; | 94 | p++; |
95 | } | 95 | } |
96 | #if ENABLE_PLATFORM_MINGW32 | ||
97 | if ( p != buf && *(p-1) == '\r' ) { | ||
98 | --p; | ||
99 | } | ||
100 | #endif | ||
96 | *p = '\0'; | 101 | *p = '\0'; |
97 | if (maxsz_p) | 102 | if (maxsz_p) |
98 | *maxsz_p = p - buf; | 103 | *maxsz_p = p - buf; |
diff --git a/libbb/signals.c b/libbb/signals.c index 0bebc847d..c09a562ed 100644 --- a/libbb/signals.c +++ b/libbb/signals.c | |||
@@ -18,6 +18,7 @@ void record_signo(int signo) | |||
18 | bb_got_signal = signo; | 18 | bb_got_signal = signo; |
19 | } | 19 | } |
20 | 20 | ||
21 | #if !ENABLE_PLATFORM_MINGW32 | ||
21 | /* Saves 2 bytes on x86! Oh my... */ | 22 | /* Saves 2 bytes on x86! Oh my... */ |
22 | int FAST_FUNC sigaction_set(int signum, const struct sigaction *act) | 23 | int FAST_FUNC sigaction_set(int signum, const struct sigaction *act) |
23 | { | 24 | { |
@@ -40,6 +41,7 @@ int FAST_FUNC sigprocmask2(int how, sigset_t *set) | |||
40 | oset = set; | 41 | oset = set; |
41 | return sigprocmask(how, set, oset); | 42 | return sigprocmask(how, set, oset); |
42 | } | 43 | } |
44 | #endif | ||
43 | 45 | ||
44 | void FAST_FUNC bb_signals(int sigs, void (*f)(int)) | 46 | void FAST_FUNC bb_signals(int sigs, void (*f)(int)) |
45 | { | 47 | { |
diff --git a/libbb/time.c b/libbb/time.c index f09ef5d52..e7c9fa65e 100644 --- a/libbb/time.c +++ b/libbb/time.c | |||
@@ -44,12 +44,21 @@ int FAST_FUNC parse_datestr(const char *date_str, struct tm *ptm) | |||
44 | save = *ptm; | 44 | save = *ptm; |
45 | fmt = fmt_str; | 45 | fmt = fmt_str; |
46 | while (*fmt) { | 46 | while (*fmt) { |
47 | #if ENABLE_PLATFORM_MINGW32 && ENABLE_FEATURE_TIMEZONE | ||
48 | long gmtoff; | ||
49 | endp = mingw_strptime(date_str, fmt, ptm, &gmtoff); | ||
50 | #else | ||
47 | endp = strptime(date_str, fmt, ptm); | 51 | endp = strptime(date_str, fmt, ptm); |
52 | #endif | ||
48 | if (endp && *endp == '\0') { | 53 | if (endp && *endp == '\0') { |
49 | # if ENABLE_FEATURE_TIMEZONE | 54 | # if ENABLE_FEATURE_TIMEZONE |
50 | if (strchr(fmt, 'z')) { | 55 | if (strchr(fmt, 'z')) { |
51 | /* we have timezone offset: obtain Unix time_t */ | 56 | /* we have timezone offset: obtain Unix time_t */ |
57 | #if ENABLE_PLATFORM_MINGW32 | ||
58 | ptm->tm_sec -= gmtoff; | ||
59 | #else | ||
52 | ptm->tm_sec -= ptm->tm_gmtoff; | 60 | ptm->tm_sec -= ptm->tm_gmtoff; |
61 | #endif | ||
53 | ptm->tm_isdst = 0; | 62 | ptm->tm_isdst = 0; |
54 | t = timegm(ptm); | 63 | t = timegm(ptm); |
55 | if (t == (time_t)-1) | 64 | if (t == (time_t)-1) |
diff --git a/libbb/u_signal_names.c b/libbb/u_signal_names.c index f7d598c7a..ef2b6f891 100644 --- a/libbb/u_signal_names.c +++ b/libbb/u_signal_names.c | |||
@@ -27,10 +27,23 @@ | |||
27 | 27 | ||
28 | #include "libbb.h" | 28 | #include "libbb.h" |
29 | 29 | ||
30 | #if ENABLE_PLATFORM_MINGW32 | ||
31 | # undef SIGPIPE | ||
32 | #endif | ||
33 | |||
34 | #if ENABLE_PLATFORM_POSIX || defined(SIGSTKFLT) || defined(SIGVTALRM) | ||
35 | # define SIGLEN 7 | ||
36 | #elif defined(SIGWINCH) || (ENABLE_FEATURE_RTMINMAX && \ | ||
37 | !ENABLE_FEATURE_RTMINMAX_USE_LIBC_DEFINITIONS && defined(__SIGRTMIN)) | ||
38 | # define SIGLEN 6 | ||
39 | #else | ||
40 | # define SIGLEN 5 | ||
41 | #endif | ||
42 | |||
30 | /* Believe it or not, but some arches have more than 32 SIGs! | 43 | /* Believe it or not, but some arches have more than 32 SIGs! |
31 | * HPPA: SIGSTKFLT == 36. */ | 44 | * HPPA: SIGSTKFLT == 36. */ |
32 | 45 | ||
33 | static const char signals[][7] ALIGN1 = { | 46 | static const char signals[][SIGLEN] ALIGN1 = { |
34 | // SUSv3 says kill must support these, and specifies the numerical values, | 47 | // SUSv3 says kill must support these, and specifies the numerical values, |
35 | // http://www.opengroup.org/onlinepubs/009695399/utilities/kill.html | 48 | // http://www.opengroup.org/onlinepubs/009695399/utilities/kill.html |
36 | // {0, "EXIT"}, {1, "HUP"}, {2, "INT"}, {3, "QUIT"}, | 49 | // {0, "EXIT"}, {1, "HUP"}, {2, "INT"}, {3, "QUIT"}, |
diff --git a/libbb/unicode.c b/libbb/unicode.c index e98cbbf35..acc7cd8df 100644 --- a/libbb/unicode.c +++ b/libbb/unicode.c | |||
@@ -69,8 +69,14 @@ void FAST_FUNC init_unicode(void) | |||
69 | void FAST_FUNC reinit_unicode(const char *LANG) | 69 | void FAST_FUNC reinit_unicode(const char *LANG) |
70 | { | 70 | { |
71 | unicode_status = UNICODE_OFF; | 71 | unicode_status = UNICODE_OFF; |
72 | #if ENABLE_PLATFORM_MINGW32 | ||
73 | /* enable unicode only when ACP is UTF8 and the env var is not 'C' */ | ||
74 | if (GetACP() != CP_UTF8 || (LANG && LANG[0] == 'C' && LANG[1] == 0)) | ||
75 | return; | ||
76 | #else | ||
72 | if (!LANG || !(strstr(LANG, ".utf") || strstr(LANG, ".UTF"))) | 77 | if (!LANG || !(strstr(LANG, ".utf") || strstr(LANG, ".UTF"))) |
73 | return; | 78 | return; |
79 | #endif | ||
74 | unicode_status = UNICODE_ON; | 80 | unicode_status = UNICODE_ON; |
75 | } | 81 | } |
76 | 82 | ||
@@ -270,7 +276,9 @@ int FAST_FUNC iswpunct(wint_t wc) | |||
270 | return (unsigned)wc <= 0x7f && ispunct(wc); | 276 | return (unsigned)wc <= 0x7f && ispunct(wc); |
271 | } | 277 | } |
272 | 278 | ||
279 | #define WCWIDTH_ALT (ENABLE_PLATFORM_MINGW32 && CONFIG_LAST_SUPPORTED_WCHAR >= 0x30000) | ||
273 | 280 | ||
281 | # if !WCWIDTH_ALT || ENABLE_UNICODE_BIDI_SUPPORT | ||
274 | # if CONFIG_LAST_SUPPORTED_WCHAR >= 0x300 | 282 | # if CONFIG_LAST_SUPPORTED_WCHAR >= 0x300 |
275 | struct interval { | 283 | struct interval { |
276 | uint16_t first; | 284 | uint16_t first; |
@@ -327,7 +335,9 @@ static int in_uint16_table(unsigned ucs, const uint16_t *table, unsigned max) | |||
327 | return 0; | 335 | return 0; |
328 | } | 336 | } |
329 | # endif | 337 | # endif |
338 | # endif /* !WCWIDTH_ALT || ENABLE_UNICODE_BIDI_SUPPORT */ | ||
330 | 339 | ||
340 | # if !WCWIDTH_ALT | ||
331 | 341 | ||
332 | /* | 342 | /* |
333 | * This is an implementation of wcwidth() and wcswidth() (defined in | 343 | * This is an implementation of wcwidth() and wcswidth() (defined in |
@@ -697,6 +707,9 @@ int FAST_FUNC wcwidth(unsigned ucs) | |||
697 | # endif /* >= 0x300 */ | 707 | # endif /* >= 0x300 */ |
698 | } | 708 | } |
699 | 709 | ||
710 | # else /* WCWIDTH_ALT */ | ||
711 | # include "wcwidth_alt.c" /* simpler and more up-to-date implementation */ | ||
712 | # endif | ||
700 | 713 | ||
701 | # if ENABLE_UNICODE_BIDI_SUPPORT | 714 | # if ENABLE_UNICODE_BIDI_SUPPORT |
702 | int FAST_FUNC unicode_bidi_isrtl(wint_t wc) | 715 | int FAST_FUNC unicode_bidi_isrtl(wint_t wc) |
diff --git a/libbb/verror_msg.c b/libbb/verror_msg.c index 74b608f4c..7c167d912 100644 --- a/libbb/verror_msg.c +++ b/libbb/verror_msg.c | |||
@@ -156,7 +156,7 @@ void FAST_FUNC bb_verror_msg(const char *s, va_list p, const char* strerr) | |||
156 | #endif | 156 | #endif |
157 | 157 | ||
158 | 158 | ||
159 | void FAST_FUNC bb_error_msg_and_die(const char *s, ...) | 159 | void bb_error_msg_and_die(const char *s, ...) |
160 | { | 160 | { |
161 | va_list p; | 161 | va_list p; |
162 | 162 | ||
@@ -166,7 +166,7 @@ void FAST_FUNC bb_error_msg_and_die(const char *s, ...) | |||
166 | xfunc_die(); | 166 | xfunc_die(); |
167 | } | 167 | } |
168 | 168 | ||
169 | void FAST_FUNC bb_error_msg(const char *s, ...) | 169 | void bb_error_msg(const char *s, ...) |
170 | { | 170 | { |
171 | va_list p; | 171 | va_list p; |
172 | 172 | ||
@@ -183,7 +183,7 @@ void FAST_FUNC bb_vinfo_msg(const char *s, va_list p) | |||
183 | syslog_level = LOG_ERR; | 183 | syslog_level = LOG_ERR; |
184 | } | 184 | } |
185 | 185 | ||
186 | void FAST_FUNC bb_info_msg(const char *s, ...) | 186 | void bb_info_msg(const char *s, ...) |
187 | { | 187 | { |
188 | va_list p; | 188 | va_list p; |
189 | 189 | ||
diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c index 2055c4b71..dad50ddb9 100644 --- a/libbb/vfork_daemon_rexec.c +++ b/libbb/vfork_daemon_rexec.c | |||
@@ -171,6 +171,7 @@ void FAST_FUNC run_noexec_applet_and_exit(int a, const char *name, char **argv) | |||
171 | * Higher-level code, hiding optional NOFORK/NOEXEC trickery. | 171 | * Higher-level code, hiding optional NOFORK/NOEXEC trickery. |
172 | */ | 172 | */ |
173 | 173 | ||
174 | #if !ENABLE_PLATFORM_MINGW32 | ||
174 | /* This does a fork/exec in one call, using vfork(). Returns PID of new child, | 175 | /* This does a fork/exec in one call, using vfork(). Returns PID of new child, |
175 | * -1 for failure. Runs argv[0], searching path if that has no / in it. */ | 176 | * -1 for failure. Runs argv[0], searching path if that has no / in it. */ |
176 | pid_t FAST_FUNC spawn(char **argv) | 177 | pid_t FAST_FUNC spawn(char **argv) |
@@ -212,6 +213,7 @@ pid_t FAST_FUNC spawn(char **argv) | |||
212 | } | 213 | } |
213 | return pid; | 214 | return pid; |
214 | } | 215 | } |
216 | #endif | ||
215 | 217 | ||
216 | /* Die with an error message if we can't spawn a child process. */ | 218 | /* Die with an error message if we can't spawn a child process. */ |
217 | pid_t FAST_FUNC xspawn(char **argv) | 219 | pid_t FAST_FUNC xspawn(char **argv) |
@@ -232,6 +234,7 @@ int FAST_FUNC spawn_and_wait(char **argv) | |||
232 | if (APPLET_IS_NOFORK(a)) | 234 | if (APPLET_IS_NOFORK(a)) |
233 | return run_nofork_applet(a, argv); | 235 | return run_nofork_applet(a, argv); |
234 | # if BB_MMU /* NOEXEC needs fork(), thus this is done only on MMU machines: */ | 236 | # if BB_MMU /* NOEXEC needs fork(), thus this is done only on MMU machines: */ |
237 | # if !ENABLE_PLATFORM_MINGW32 /* and then only if not on Microsoft Windows */ | ||
235 | if (APPLET_IS_NOEXEC(a)) { | 238 | if (APPLET_IS_NOEXEC(a)) { |
236 | fflush_all(); | 239 | fflush_all(); |
237 | rc = fork(); | 240 | rc = fork(); |
@@ -241,6 +244,7 @@ int FAST_FUNC spawn_and_wait(char **argv) | |||
241 | /* child */ | 244 | /* child */ |
242 | run_noexec_applet_and_exit(a, argv[0], argv); | 245 | run_noexec_applet_and_exit(a, argv[0], argv); |
243 | } | 246 | } |
247 | # endif | ||
244 | # endif | 248 | # endif |
245 | } | 249 | } |
246 | #endif | 250 | #endif |
@@ -248,6 +252,7 @@ int FAST_FUNC spawn_and_wait(char **argv) | |||
248 | return wait4pid(rc); | 252 | return wait4pid(rc); |
249 | } | 253 | } |
250 | 254 | ||
255 | #if !ENABLE_PLATFORM_MINGW32 | ||
251 | #if !BB_MMU | 256 | #if !BB_MMU |
252 | void FAST_FUNC re_exec(char **argv) | 257 | void FAST_FUNC re_exec(char **argv) |
253 | { | 258 | { |
@@ -340,3 +345,4 @@ void FAST_FUNC bb_sanitize_stdio(void) | |||
340 | { | 345 | { |
341 | bb_daemonize_or_rexec(DAEMON_ONLY_SANITIZE, NULL); | 346 | bb_daemonize_or_rexec(DAEMON_ONLY_SANITIZE, NULL); |
342 | } | 347 | } |
348 | #endif /* !MINGW32 */ | ||
diff --git a/libbb/wcwidth_alt.c b/libbb/wcwidth_alt.c new file mode 100644 index 000000000..9a45ab0e9 --- /dev/null +++ b/libbb/wcwidth_alt.c | |||
@@ -0,0 +1,506 @@ | |||
1 | /* wcwidth - Unicode 15.1.0, generated by scripts/mkwcwidth. | ||
2 | * Copyright (C) 2024 Avi Halachmi <avihpit at yahoo.com> | ||
3 | * License: MIT | ||
4 | * | ||
5 | * Data imported on 2024-03-29 from https://github.com/jquast/wcwidth | ||
6 | * commit 0.2.13-3-g056ee4b (2024-02-14 15:05:06 -0500) | ||
7 | */ | ||
8 | int FAST_FUNC wcwidth(uint32_t ucs) | ||
9 | { | ||
10 | /* sorted ranges, "first" is clipped to 16 bit, and its high bits | ||
11 | * (plane) are deduced from the "planes" array below. | ||
12 | * (imported from table_zero.py and table_wide.py) | ||
13 | */ | ||
14 | static const struct range { | ||
15 | uint16_t first; | ||
16 | uint16_t iswide: 1; /* bitfield order empirically faster */ | ||
17 | uint16_t difflast: 15; | ||
18 | } ranges[] = { | ||
19 | #define R(first, last, width) {first & 0xffff, width/2, last-first} | ||
20 | R(0x000000, 0x000000, 0), /* nil */ | ||
21 | R(0x0000ad, 0x0000ad, 0), /* Soft Hyphen */ | ||
22 | R(0x000300, 0x00036f, 0), /* Combining Grave Accent ..Combining Latin Small Le */ | ||
23 | R(0x000483, 0x000489, 0), /* Combining Cyrillic Titlo..Combining Cyrillic Milli */ | ||
24 | R(0x000591, 0x0005bd, 0), /* Hebrew Accent Etnahta ..Hebrew Point Meteg */ | ||
25 | R(0x0005bf, 0x0005bf, 0), /* Hebrew Point Rafe */ | ||
26 | R(0x0005c1, 0x0005c2, 0), /* Hebrew Point Shin Dot ..Hebrew Point Sin Dot */ | ||
27 | R(0x0005c4, 0x0005c5, 0), /* Hebrew Mark Upper Dot ..Hebrew Mark Lower Dot */ | ||
28 | R(0x0005c7, 0x0005c7, 0), /* Hebrew Point Qamats Qatan */ | ||
29 | R(0x000600, 0x000605, 0), /* Arabic Number Sign ..Arabic Number Mark Above */ | ||
30 | R(0x000610, 0x00061a, 0), /* Arabic Sign Sallallahou ..Arabic Small Kasra */ | ||
31 | R(0x00061c, 0x00061c, 0), /* Arabic Letter Mark */ | ||
32 | R(0x00064b, 0x00065f, 0), /* Arabic Fathatan ..Arabic Wavy Hamza Below */ | ||
33 | R(0x000670, 0x000670, 0), /* Arabic Letter Superscript Alef */ | ||
34 | R(0x0006d6, 0x0006dd, 0), /* Arabic Small High Ligatu..Arabic End Of Ayah */ | ||
35 | R(0x0006df, 0x0006e4, 0), /* Arabic Small High Rounde..Arabic Small High Madda */ | ||
36 | R(0x0006e7, 0x0006e8, 0), /* Arabic Small High Yeh ..Arabic Small High Noon */ | ||
37 | R(0x0006ea, 0x0006ed, 0), /* Arabic Empty Centre Low ..Arabic Small Low Meem */ | ||
38 | R(0x00070f, 0x00070f, 0), /* Syriac Abbreviation Mark */ | ||
39 | R(0x000711, 0x000711, 0), /* Syriac Letter Superscript Alaph */ | ||
40 | R(0x000730, 0x00074a, 0), /* Syriac Pthaha Above ..Syriac Barrekh */ | ||
41 | R(0x0007a6, 0x0007b0, 0), /* Thaana Abafili ..Thaana Sukun */ | ||
42 | R(0x0007eb, 0x0007f3, 0), /* Nko Combining Short High..Nko Combining Double Dot */ | ||
43 | R(0x0007fd, 0x0007fd, 0), /* Nko Dantayalan */ | ||
44 | R(0x000816, 0x000819, 0), /* Samaritan Mark In ..Samaritan Mark Dagesh */ | ||
45 | R(0x00081b, 0x000823, 0), /* Samaritan Mark Epentheti..Samaritan Vowel Sign A */ | ||
46 | R(0x000825, 0x000827, 0), /* Samaritan Vowel Sign Sho..Samaritan Vowel Sign U */ | ||
47 | R(0x000829, 0x00082d, 0), /* Samaritan Vowel Sign Lon..Samaritan Mark Nequdaa */ | ||
48 | R(0x000859, 0x00085b, 0), /* Mandaic Affrication Mark..Mandaic Gemination Mark */ | ||
49 | R(0x000890, 0x000891, 0), /* Arabic Pound Mark Above ..Arabic Piastre Mark Abov */ | ||
50 | R(0x000898, 0x00089f, 0), /* Arabic Small High Word A..Arabic Half Madda Over M */ | ||
51 | R(0x0008ca, 0x000903, 0), /* Arabic Small High Farsi ..Devanagari Sign Visarga */ | ||
52 | R(0x00093a, 0x00093c, 0), /* Devanagari Vowel Sign Oe..Devanagari Sign Nukta */ | ||
53 | R(0x00093e, 0x00094f, 0), /* Devanagari Vowel Sign Aa..Devanagari Vowel Sign Aw */ | ||
54 | R(0x000951, 0x000957, 0), /* Devanagari Stress Sign U..Devanagari Vowel Sign Uu */ | ||
55 | R(0x000962, 0x000963, 0), /* Devanagari Vowel Sign Vo..Devanagari Vowel Sign Vo */ | ||
56 | R(0x000981, 0x000983, 0), /* Bengali Sign Candrabindu..Bengali Sign Visarga */ | ||
57 | R(0x0009bc, 0x0009bc, 0), /* Bengali Sign Nukta */ | ||
58 | R(0x0009be, 0x0009c4, 0), /* Bengali Vowel Sign Aa ..Bengali Vowel Sign Vocal */ | ||
59 | R(0x0009c7, 0x0009c8, 0), /* Bengali Vowel Sign E ..Bengali Vowel Sign Ai */ | ||
60 | R(0x0009cb, 0x0009cd, 0), /* Bengali Vowel Sign O ..Bengali Sign Virama */ | ||
61 | R(0x0009d7, 0x0009d7, 0), /* Bengali Au Length Mark */ | ||
62 | R(0x0009e2, 0x0009e3, 0), /* Bengali Vowel Sign Vocal..Bengali Vowel Sign Vocal */ | ||
63 | R(0x0009fe, 0x0009fe, 0), /* Bengali Sandhi Mark */ | ||
64 | R(0x000a01, 0x000a03, 0), /* Gurmukhi Sign Adak Bindi..Gurmukhi Sign Visarga */ | ||
65 | R(0x000a3c, 0x000a3c, 0), /* Gurmukhi Sign Nukta */ | ||
66 | R(0x000a3e, 0x000a42, 0), /* Gurmukhi Vowel Sign Aa ..Gurmukhi Vowel Sign Uu */ | ||
67 | R(0x000a47, 0x000a48, 0), /* Gurmukhi Vowel Sign Ee ..Gurmukhi Vowel Sign Ai */ | ||
68 | R(0x000a4b, 0x000a4d, 0), /* Gurmukhi Vowel Sign Oo ..Gurmukhi Sign Virama */ | ||
69 | R(0x000a51, 0x000a51, 0), /* Gurmukhi Sign Udaat */ | ||
70 | R(0x000a70, 0x000a71, 0), /* Gurmukhi Tippi ..Gurmukhi Addak */ | ||
71 | R(0x000a75, 0x000a75, 0), /* Gurmukhi Sign Yakash */ | ||
72 | R(0x000a81, 0x000a83, 0), /* Gujarati Sign Candrabind..Gujarati Sign Visarga */ | ||
73 | R(0x000abc, 0x000abc, 0), /* Gujarati Sign Nukta */ | ||
74 | R(0x000abe, 0x000ac5, 0), /* Gujarati Vowel Sign Aa ..Gujarati Vowel Sign Cand */ | ||
75 | R(0x000ac7, 0x000ac9, 0), /* Gujarati Vowel Sign E ..Gujarati Vowel Sign Cand */ | ||
76 | R(0x000acb, 0x000acd, 0), /* Gujarati Vowel Sign O ..Gujarati Sign Virama */ | ||
77 | R(0x000ae2, 0x000ae3, 0), /* Gujarati Vowel Sign Voca..Gujarati Vowel Sign Voca */ | ||
78 | R(0x000afa, 0x000aff, 0), /* Gujarati Sign Sukun ..Gujarati Sign Two-circle */ | ||
79 | R(0x000b01, 0x000b03, 0), /* Oriya Sign Candrabindu ..Oriya Sign Visarga */ | ||
80 | R(0x000b3c, 0x000b3c, 0), /* Oriya Sign Nukta */ | ||
81 | R(0x000b3e, 0x000b44, 0), /* Oriya Vowel Sign Aa ..Oriya Vowel Sign Vocalic */ | ||
82 | R(0x000b47, 0x000b48, 0), /* Oriya Vowel Sign E ..Oriya Vowel Sign Ai */ | ||
83 | R(0x000b4b, 0x000b4d, 0), /* Oriya Vowel Sign O ..Oriya Sign Virama */ | ||
84 | R(0x000b55, 0x000b57, 0), /* Oriya Sign Overline ..Oriya Au Length Mark */ | ||
85 | R(0x000b62, 0x000b63, 0), /* Oriya Vowel Sign Vocalic..Oriya Vowel Sign Vocalic */ | ||
86 | R(0x000b82, 0x000b82, 0), /* Tamil Sign Anusvara */ | ||
87 | R(0x000bbe, 0x000bc2, 0), /* Tamil Vowel Sign Aa ..Tamil Vowel Sign Uu */ | ||
88 | R(0x000bc6, 0x000bc8, 0), /* Tamil Vowel Sign E ..Tamil Vowel Sign Ai */ | ||
89 | R(0x000bca, 0x000bcd, 0), /* Tamil Vowel Sign O ..Tamil Sign Virama */ | ||
90 | R(0x000bd7, 0x000bd7, 0), /* Tamil Au Length Mark */ | ||
91 | R(0x000c00, 0x000c04, 0), /* Telugu Sign Combining Ca..Telugu Sign Combining An */ | ||
92 | R(0x000c3c, 0x000c3c, 0), /* Telugu Sign Nukta */ | ||
93 | R(0x000c3e, 0x000c44, 0), /* Telugu Vowel Sign Aa ..Telugu Vowel Sign Vocali */ | ||
94 | R(0x000c46, 0x000c48, 0), /* Telugu Vowel Sign E ..Telugu Vowel Sign Ai */ | ||
95 | R(0x000c4a, 0x000c4d, 0), /* Telugu Vowel Sign O ..Telugu Sign Virama */ | ||
96 | R(0x000c55, 0x000c56, 0), /* Telugu Length Mark ..Telugu Ai Length Mark */ | ||
97 | R(0x000c62, 0x000c63, 0), /* Telugu Vowel Sign Vocali..Telugu Vowel Sign Vocali */ | ||
98 | R(0x000c81, 0x000c83, 0), /* Kannada Sign Candrabindu..Kannada Sign Visarga */ | ||
99 | R(0x000cbc, 0x000cbc, 0), /* Kannada Sign Nukta */ | ||
100 | R(0x000cbe, 0x000cc4, 0), /* Kannada Vowel Sign Aa ..Kannada Vowel Sign Vocal */ | ||
101 | R(0x000cc6, 0x000cc8, 0), /* Kannada Vowel Sign E ..Kannada Vowel Sign Ai */ | ||
102 | R(0x000cca, 0x000ccd, 0), /* Kannada Vowel Sign O ..Kannada Sign Virama */ | ||
103 | R(0x000cd5, 0x000cd6, 0), /* Kannada Length Mark ..Kannada Ai Length Mark */ | ||
104 | R(0x000ce2, 0x000ce3, 0), /* Kannada Vowel Sign Vocal..Kannada Vowel Sign Vocal */ | ||
105 | R(0x000cf3, 0x000cf3, 0), /* Kannada Sign Combining Anusvara Above Right */ | ||
106 | R(0x000d00, 0x000d03, 0), /* Malayalam Sign Combining..Malayalam Sign Visarga */ | ||
107 | R(0x000d3b, 0x000d3c, 0), /* Malayalam Sign Vertical ..Malayalam Sign Circular */ | ||
108 | R(0x000d3e, 0x000d44, 0), /* Malayalam Vowel Sign Aa ..Malayalam Vowel Sign Voc */ | ||
109 | R(0x000d46, 0x000d48, 0), /* Malayalam Vowel Sign E ..Malayalam Vowel Sign Ai */ | ||
110 | R(0x000d4a, 0x000d4d, 0), /* Malayalam Vowel Sign O ..Malayalam Sign Virama */ | ||
111 | R(0x000d57, 0x000d57, 0), /* Malayalam Au Length Mark */ | ||
112 | R(0x000d62, 0x000d63, 0), /* Malayalam Vowel Sign Voc..Malayalam Vowel Sign Voc */ | ||
113 | R(0x000d81, 0x000d83, 0), /* Sinhala Sign Candrabindu..Sinhala Sign Visargaya */ | ||
114 | R(0x000dca, 0x000dca, 0), /* Sinhala Sign Al-lakuna */ | ||
115 | R(0x000dcf, 0x000dd4, 0), /* Sinhala Vowel Sign Aela-..Sinhala Vowel Sign Ketti */ | ||
116 | R(0x000dd6, 0x000dd6, 0), /* Sinhala Vowel Sign Diga Paa-pilla */ | ||
117 | R(0x000dd8, 0x000ddf, 0), /* Sinhala Vowel Sign Gaett..Sinhala Vowel Sign Gayan */ | ||
118 | R(0x000df2, 0x000df3, 0), /* Sinhala Vowel Sign Diga ..Sinhala Vowel Sign Diga */ | ||
119 | R(0x000e31, 0x000e31, 0), /* Thai Character Mai Han-akat */ | ||
120 | R(0x000e34, 0x000e3a, 0), /* Thai Character Sara I ..Thai Character Phinthu */ | ||
121 | R(0x000e47, 0x000e4e, 0), /* Thai Character Maitaikhu..Thai Character Yamakkan */ | ||
122 | R(0x000eb1, 0x000eb1, 0), /* Lao Vowel Sign Mai Kan */ | ||
123 | R(0x000eb4, 0x000ebc, 0), /* Lao Vowel Sign I ..Lao Semivowel Sign Lo */ | ||
124 | R(0x000ec8, 0x000ece, 0), /* Lao Tone Mai Ek ..Lao Yamakkan */ | ||
125 | R(0x000f18, 0x000f19, 0), /* Tibetan Astrological Sig..Tibetan Astrological Sig */ | ||
126 | R(0x000f35, 0x000f35, 0), /* Tibetan Mark Ngas Bzung Nyi Zla */ | ||
127 | R(0x000f37, 0x000f37, 0), /* Tibetan Mark Ngas Bzung Sgor Rtags */ | ||
128 | R(0x000f39, 0x000f39, 0), /* Tibetan Mark Tsa -phru */ | ||
129 | R(0x000f3e, 0x000f3f, 0), /* Tibetan Sign Yar Tshes ..Tibetan Sign Mar Tshes */ | ||
130 | R(0x000f71, 0x000f84, 0), /* Tibetan Vowel Sign Aa ..Tibetan Mark Halanta */ | ||
131 | R(0x000f86, 0x000f87, 0), /* Tibetan Sign Lci Rtags ..Tibetan Sign Yang Rtags */ | ||
132 | R(0x000f8d, 0x000f97, 0), /* Tibetan Subjoined Sign L..Tibetan Subjoined Letter */ | ||
133 | R(0x000f99, 0x000fbc, 0), /* Tibetan Subjoined Letter..Tibetan Subjoined Letter */ | ||
134 | R(0x000fc6, 0x000fc6, 0), /* Tibetan Symbol Padma Gdan */ | ||
135 | R(0x00102b, 0x00103e, 0), /* Myanmar Vowel Sign Tall ..Myanmar Consonant Sign M */ | ||
136 | R(0x001056, 0x001059, 0), /* Myanmar Vowel Sign Vocal..Myanmar Vowel Sign Vocal */ | ||
137 | R(0x00105e, 0x001060, 0), /* Myanmar Consonant Sign M..Myanmar Consonant Sign M */ | ||
138 | R(0x001062, 0x001064, 0), /* Myanmar Vowel Sign Sgaw ..Myanmar Tone Mark Sgaw K */ | ||
139 | R(0x001067, 0x00106d, 0), /* Myanmar Vowel Sign Weste..Myanmar Sign Western Pwo */ | ||
140 | R(0x001071, 0x001074, 0), /* Myanmar Vowel Sign Geba ..Myanmar Vowel Sign Kayah */ | ||
141 | R(0x001082, 0x00108d, 0), /* Myanmar Consonant Sign S..Myanmar Sign Shan Counci */ | ||
142 | R(0x00108f, 0x00108f, 0), /* Myanmar Sign Rumai Palaung Tone-5 */ | ||
143 | R(0x00109a, 0x00109d, 0), /* Myanmar Sign Khamti Tone..Myanmar Vowel Sign Aiton */ | ||
144 | R(0x001100, 0x00115f, 2), /* Hangul Choseong Kiyeok ..Hangul Choseong Filler */ | ||
145 | R(0x001160, 0x0011ff, 0), /* Hangul Jungseong Filler ..Hangul Jongseong Ssangni */ | ||
146 | R(0x00135d, 0x00135f, 0), /* Ethiopic Combining Gemin..Ethiopic Combining Gemin */ | ||
147 | R(0x001712, 0x001715, 0), /* Tagalog Vowel Sign I ..Tagalog Sign Pamudpod */ | ||
148 | R(0x001732, 0x001734, 0), /* Hanunoo Vowel Sign I ..Hanunoo Sign Pamudpod */ | ||
149 | R(0x001752, 0x001753, 0), /* Buhid Vowel Sign I ..Buhid Vowel Sign U */ | ||
150 | R(0x001772, 0x001773, 0), /* Tagbanwa Vowel Sign I ..Tagbanwa Vowel Sign U */ | ||
151 | R(0x0017b4, 0x0017d3, 0), /* Khmer Vowel Inherent Aq ..Khmer Sign Bathamasat */ | ||
152 | R(0x0017dd, 0x0017dd, 0), /* Khmer Sign Atthacan */ | ||
153 | R(0x00180b, 0x00180f, 0), /* Mongolian Free Variation..Mongolian Free Variation */ | ||
154 | R(0x001885, 0x001886, 0), /* Mongolian Letter Ali Gal..Mongolian Letter Ali Gal */ | ||
155 | R(0x0018a9, 0x0018a9, 0), /* Mongolian Letter Ali Gali Dagalga */ | ||
156 | R(0x001920, 0x00192b, 0), /* Limbu Vowel Sign A ..Limbu Subjoined Letter W */ | ||
157 | R(0x001930, 0x00193b, 0), /* Limbu Small Letter Ka ..Limbu Sign Sa-i */ | ||
158 | R(0x001a17, 0x001a1b, 0), /* Buginese Vowel Sign I ..Buginese Vowel Sign Ae */ | ||
159 | R(0x001a55, 0x001a5e, 0), /* Tai Tham Consonant Sign ..Tai Tham Consonant Sign */ | ||
160 | R(0x001a60, 0x001a7c, 0), /* Tai Tham Sign Sakot ..Tai Tham Sign Khuen-lue */ | ||
161 | R(0x001a7f, 0x001a7f, 0), /* Tai Tham Combining Cryptogrammic Dot */ | ||
162 | R(0x001ab0, 0x001ace, 0), /* Combining Doubled Circum..Combining Latin Small Le */ | ||
163 | R(0x001b00, 0x001b04, 0), /* Balinese Sign Ulu Ricem ..Balinese Sign Bisah */ | ||
164 | R(0x001b34, 0x001b44, 0), /* Balinese Sign Rerekan ..Balinese Adeg Adeg */ | ||
165 | R(0x001b6b, 0x001b73, 0), /* Balinese Musical Symbol ..Balinese Musical Symbol */ | ||
166 | R(0x001b80, 0x001b82, 0), /* Sundanese Sign Panyecek ..Sundanese Sign Pangwisad */ | ||
167 | R(0x001ba1, 0x001bad, 0), /* Sundanese Consonant Sign..Sundanese Consonant Sign */ | ||
168 | R(0x001be6, 0x001bf3, 0), /* Batak Sign Tompi ..Batak Panongonan */ | ||
169 | R(0x001c24, 0x001c37, 0), /* Lepcha Subjoined Letter ..Lepcha Sign Nukta */ | ||
170 | R(0x001cd0, 0x001cd2, 0), /* Vedic Tone Karshana ..Vedic Tone Prenkha */ | ||
171 | R(0x001cd4, 0x001ce8, 0), /* Vedic Sign Yajurvedic Mi..Vedic Sign Visarga Anuda */ | ||
172 | R(0x001ced, 0x001ced, 0), /* Vedic Sign Tiryak */ | ||
173 | R(0x001cf4, 0x001cf4, 0), /* Vedic Tone Candra Above */ | ||
174 | R(0x001cf7, 0x001cf9, 0), /* Vedic Sign Atikrama ..Vedic Tone Double Ring A */ | ||
175 | R(0x001dc0, 0x001dff, 0), /* Combining Dotted Grave A..Combining Right Arrowhea */ | ||
176 | R(0x00200b, 0x00200f, 0), /* Zero Width Space ..Right-to-left Mark */ | ||
177 | R(0x002028, 0x00202e, 0), /* Line Separator ..Right-to-left Override */ | ||
178 | R(0x002060, 0x002064, 0), /* Word Joiner ..Invisible Plus */ | ||
179 | R(0x002066, 0x00206f, 0), /* Left-to-right Isolate ..Nominal Digit Shapes */ | ||
180 | R(0x0020d0, 0x0020f0, 0), /* Combining Left Harpoon A..Combining Asterisk Above */ | ||
181 | R(0x00231a, 0x00231b, 2), /* Watch ..Hourglass */ | ||
182 | R(0x002329, 0x00232a, 2), /* Left-pointing Angle Brac..Right-pointing Angle Bra */ | ||
183 | R(0x0023e9, 0x0023ec, 2), /* Black Right-pointing Dou..Black Down-pointing Doub */ | ||
184 | R(0x0023f0, 0x0023f0, 2), /* Alarm Clock */ | ||
185 | R(0x0023f3, 0x0023f3, 2), /* Hourglass With Flowing Sand */ | ||
186 | R(0x0025fd, 0x0025fe, 2), /* White Medium Small Squar..Black Medium Small Squar */ | ||
187 | R(0x002614, 0x002615, 2), /* Umbrella With Rain Drops..Hot Beverage */ | ||
188 | R(0x002648, 0x002653, 2), /* Aries ..Pisces */ | ||
189 | R(0x00267f, 0x00267f, 2), /* Wheelchair Symbol */ | ||
190 | R(0x002693, 0x002693, 2), /* Anchor */ | ||
191 | R(0x0026a1, 0x0026a1, 2), /* High Voltage Sign */ | ||
192 | R(0x0026aa, 0x0026ab, 2), /* Medium White Circle ..Medium Black Circle */ | ||
193 | R(0x0026bd, 0x0026be, 2), /* Soccer Ball ..Baseball */ | ||
194 | R(0x0026c4, 0x0026c5, 2), /* Snowman Without Snow ..Sun Behind Cloud */ | ||
195 | R(0x0026ce, 0x0026ce, 2), /* Ophiuchus */ | ||
196 | R(0x0026d4, 0x0026d4, 2), /* No Entry */ | ||
197 | R(0x0026ea, 0x0026ea, 2), /* Church */ | ||
198 | R(0x0026f2, 0x0026f3, 2), /* Fountain ..Flag In Hole */ | ||
199 | R(0x0026f5, 0x0026f5, 2), /* Sailboat */ | ||
200 | R(0x0026fa, 0x0026fa, 2), /* Tent */ | ||
201 | R(0x0026fd, 0x0026fd, 2), /* Fuel Pump */ | ||
202 | R(0x002705, 0x002705, 2), /* White Heavy Check Mark */ | ||
203 | R(0x00270a, 0x00270b, 2), /* Raised Fist ..Raised Hand */ | ||
204 | R(0x002728, 0x002728, 2), /* Sparkles */ | ||
205 | R(0x00274c, 0x00274c, 2), /* Cross Mark */ | ||
206 | R(0x00274e, 0x00274e, 2), /* Negative Squared Cross Mark */ | ||
207 | R(0x002753, 0x002755, 2), /* Black Question Mark Orna..White Exclamation Mark O */ | ||
208 | R(0x002757, 0x002757, 2), /* Heavy Exclamation Mark Symbol */ | ||
209 | R(0x002795, 0x002797, 2), /* Heavy Plus Sign ..Heavy Division Sign */ | ||
210 | R(0x0027b0, 0x0027b0, 2), /* Curly Loop */ | ||
211 | R(0x0027bf, 0x0027bf, 2), /* Double Curly Loop */ | ||
212 | R(0x002b1b, 0x002b1c, 2), /* Black Large Square ..White Large Square */ | ||
213 | R(0x002b50, 0x002b50, 2), /* White Medium Star */ | ||
214 | R(0x002b55, 0x002b55, 2), /* Heavy Large Circle */ | ||
215 | R(0x002cef, 0x002cf1, 0), /* Coptic Combining Ni Abov..Coptic Combining Spiritu */ | ||
216 | R(0x002d7f, 0x002d7f, 0), /* Tifinagh Consonant Joiner */ | ||
217 | R(0x002de0, 0x002dff, 0), /* Combining Cyrillic Lette..Combining Cyrillic Lette */ | ||
218 | R(0x002e80, 0x002e99, 2), /* Cjk Radical Repeat ..Cjk Radical Rap */ | ||
219 | R(0x002e9b, 0x002ef3, 2), /* Cjk Radical Choke ..Cjk Radical C-simplified */ | ||
220 | R(0x002f00, 0x002fd5, 2), /* Kangxi Radical One ..Kangxi Radical Flute */ | ||
221 | R(0x002ff0, 0x003029, 2), /* Ideographic Description ..Hangzhou Numeral Nine */ | ||
222 | R(0x00302a, 0x00302f, 0), /* Ideographic Level Tone M..Hangul Double Dot Tone M */ | ||
223 | R(0x003030, 0x00303e, 2), /* Wavy Dash ..Ideographic Variation In */ | ||
224 | R(0x003041, 0x003096, 2), /* Hiragana Letter Small A ..Hiragana Letter Small Ke */ | ||
225 | R(0x003099, 0x00309a, 0), /* Combining Katakana-hirag..Combining Katakana-hirag */ | ||
226 | R(0x00309b, 0x0030ff, 2), /* Katakana-hiragana Voiced..Katakana Digraph Koto */ | ||
227 | R(0x003105, 0x00312f, 2), /* Bopomofo Letter B ..Bopomofo Letter Nn */ | ||
228 | R(0x003131, 0x00318e, 2), /* Hangul Letter Kiyeok ..Hangul Letter Araeae */ | ||
229 | R(0x003190, 0x0031e3, 2), /* Ideographic Annotation L..Cjk Stroke Q */ | ||
230 | R(0x0031ef, 0x00321e, 2), /* nil ..Parenthesized Korean Cha */ | ||
231 | R(0x003220, 0x003247, 2), /* Parenthesized Ideograph ..Circled Ideograph Koto */ | ||
232 | R(0x003250, 0x004dbf, 2), /* Partnership Sign ..Cjk Unified Ideograph-4d */ | ||
233 | R(0x004e00, 0x00a48c, 2), /* Cjk Unified Ideograph-4e..Yi Syllable Yyr */ | ||
234 | R(0x00a490, 0x00a4c6, 2), /* Yi Radical Qot ..Yi Radical Ke */ | ||
235 | R(0x00a66f, 0x00a672, 0), /* Combining Cyrillic Vzmet..Combining Cyrillic Thous */ | ||
236 | R(0x00a674, 0x00a67d, 0), /* Combining Cyrillic Lette..Combining Cyrillic Payer */ | ||
237 | R(0x00a69e, 0x00a69f, 0), /* Combining Cyrillic Lette..Combining Cyrillic Lette */ | ||
238 | R(0x00a6f0, 0x00a6f1, 0), /* Bamum Combining Mark Koq..Bamum Combining Mark Tuk */ | ||
239 | R(0x00a802, 0x00a802, 0), /* Syloti Nagri Sign Dvisvara */ | ||
240 | R(0x00a806, 0x00a806, 0), /* Syloti Nagri Sign Hasanta */ | ||
241 | R(0x00a80b, 0x00a80b, 0), /* Syloti Nagri Sign Anusvara */ | ||
242 | R(0x00a823, 0x00a827, 0), /* Syloti Nagri Vowel Sign ..Syloti Nagri Vowel Sign */ | ||
243 | R(0x00a82c, 0x00a82c, 0), /* Syloti Nagri Sign Alternate Hasanta */ | ||
244 | R(0x00a880, 0x00a881, 0), /* Saurashtra Sign Anusvara..Saurashtra Sign Visarga */ | ||
245 | R(0x00a8b4, 0x00a8c5, 0), /* Saurashtra Consonant Sig..Saurashtra Sign Candrabi */ | ||
246 | R(0x00a8e0, 0x00a8f1, 0), /* Combining Devanagari Dig..Combining Devanagari Sig */ | ||
247 | R(0x00a8ff, 0x00a8ff, 0), /* Devanagari Vowel Sign Ay */ | ||
248 | R(0x00a926, 0x00a92d, 0), /* Kayah Li Vowel Ue ..Kayah Li Tone Calya Plop */ | ||
249 | R(0x00a947, 0x00a953, 0), /* Rejang Vowel Sign I ..Rejang Virama */ | ||
250 | R(0x00a960, 0x00a97c, 2), /* Hangul Choseong Tikeut-m..Hangul Choseong Ssangyeo */ | ||
251 | R(0x00a980, 0x00a983, 0), /* Javanese Sign Panyangga ..Javanese Sign Wignyan */ | ||
252 | R(0x00a9b3, 0x00a9c0, 0), /* Javanese Sign Cecak Telu..Javanese Pangkon */ | ||
253 | R(0x00a9e5, 0x00a9e5, 0), /* Myanmar Sign Shan Saw */ | ||
254 | R(0x00aa29, 0x00aa36, 0), /* Cham Vowel Sign Aa ..Cham Consonant Sign Wa */ | ||
255 | R(0x00aa43, 0x00aa43, 0), /* Cham Consonant Sign Final Ng */ | ||
256 | R(0x00aa4c, 0x00aa4d, 0), /* Cham Consonant Sign Fina..Cham Consonant Sign Fina */ | ||
257 | R(0x00aa7b, 0x00aa7d, 0), /* Myanmar Sign Pao Karen T..Myanmar Sign Tai Laing T */ | ||
258 | R(0x00aab0, 0x00aab0, 0), /* Tai Viet Mai Kang */ | ||
259 | R(0x00aab2, 0x00aab4, 0), /* Tai Viet Vowel I ..Tai Viet Vowel U */ | ||
260 | R(0x00aab7, 0x00aab8, 0), /* Tai Viet Mai Khit ..Tai Viet Vowel Ia */ | ||
261 | R(0x00aabe, 0x00aabf, 0), /* Tai Viet Vowel Am ..Tai Viet Tone Mai Ek */ | ||
262 | R(0x00aac1, 0x00aac1, 0), /* Tai Viet Tone Mai Tho */ | ||
263 | R(0x00aaeb, 0x00aaef, 0), /* Meetei Mayek Vowel Sign ..Meetei Mayek Vowel Sign */ | ||
264 | R(0x00aaf5, 0x00aaf6, 0), /* Meetei Mayek Vowel Sign ..Meetei Mayek Virama */ | ||
265 | R(0x00abe3, 0x00abea, 0), /* Meetei Mayek Vowel Sign ..Meetei Mayek Vowel Sign */ | ||
266 | R(0x00abec, 0x00abed, 0), /* Meetei Mayek Lum Iyek ..Meetei Mayek Apun Iyek */ | ||
267 | R(0x00ac00, 0x00d7a3, 2), /* Hangul Syllable Ga ..Hangul Syllable Hih */ | ||
268 | R(0x00d7b0, 0x00d7ff, 0), /* Hangul Jungseong O-yeo .. nil */ | ||
269 | R(0x00f900, 0x00faff, 2), /* Cjk Compatibility Ideogr.. nil */ | ||
270 | R(0x00fb1e, 0x00fb1e, 0), /* Hebrew Point Judeo-spanish Varika */ | ||
271 | R(0x00fe00, 0x00fe0f, 0), /* Variation Selector-1 ..Variation Selector-16 */ | ||
272 | R(0x00fe10, 0x00fe19, 2), /* Presentation Form For Ve..Presentation Form For Ve */ | ||
273 | R(0x00fe20, 0x00fe2f, 0), /* Combining Ligature Left ..Combining Cyrillic Titlo */ | ||
274 | R(0x00fe30, 0x00fe52, 2), /* Presentation Form For Ve..Small Full Stop */ | ||
275 | R(0x00fe54, 0x00fe66, 2), /* Small Semicolon ..Small Equals Sign */ | ||
276 | R(0x00fe68, 0x00fe6b, 2), /* Small Reverse Solidus ..Small Commercial At */ | ||
277 | R(0x00feff, 0x00feff, 0), /* Zero Width No-break Space */ | ||
278 | R(0x00ff01, 0x00ff60, 2), /* Fullwidth Exclamation Ma..Fullwidth Right White Pa */ | ||
279 | R(0x00ffe0, 0x00ffe6, 2), /* Fullwidth Cent Sign ..Fullwidth Won Sign */ | ||
280 | R(0x00fff9, 0x00fffb, 0), /* Interlinear Annotation A..Interlinear Annotation T */ | ||
281 | R(0x0101fd, 0x0101fd, 0), /* Phaistos Disc Sign Combining Oblique Stroke */ | ||
282 | R(0x0102e0, 0x0102e0, 0), /* Coptic Epact Thousands Mark */ | ||
283 | R(0x010376, 0x01037a, 0), /* Combining Old Permic Let..Combining Old Permic Let */ | ||
284 | R(0x010a01, 0x010a03, 0), /* Kharoshthi Vowel Sign I ..Kharoshthi Vowel Sign Vo */ | ||
285 | R(0x010a05, 0x010a06, 0), /* Kharoshthi Vowel Sign E ..Kharoshthi Vowel Sign O */ | ||
286 | R(0x010a0c, 0x010a0f, 0), /* Kharoshthi Vowel Length ..Kharoshthi Sign Visarga */ | ||
287 | R(0x010a38, 0x010a3a, 0), /* Kharoshthi Sign Bar Abov..Kharoshthi Sign Dot Belo */ | ||
288 | R(0x010a3f, 0x010a3f, 0), /* Kharoshthi Virama */ | ||
289 | R(0x010ae5, 0x010ae6, 0), /* Manichaean Abbreviation ..Manichaean Abbreviation */ | ||
290 | R(0x010d24, 0x010d27, 0), /* Hanifi Rohingya Sign Har..Hanifi Rohingya Sign Tas */ | ||
291 | R(0x010eab, 0x010eac, 0), /* Yezidi Combining Hamza M..Yezidi Combining Madda M */ | ||
292 | R(0x010efd, 0x010eff, 0), /* Arabic Small Low Word Sa..Arabic Small Low Word Ma */ | ||
293 | R(0x010f46, 0x010f50, 0), /* Sogdian Combining Dot Be..Sogdian Combining Stroke */ | ||
294 | R(0x010f82, 0x010f85, 0), /* Old Uyghur Combining Dot..Old Uyghur Combining Two */ | ||
295 | R(0x011000, 0x011002, 0), /* Brahmi Sign Candrabindu ..Brahmi Sign Visarga */ | ||
296 | R(0x011038, 0x011046, 0), /* Brahmi Vowel Sign Aa ..Brahmi Virama */ | ||
297 | R(0x011070, 0x011070, 0), /* Brahmi Sign Old Tamil Virama */ | ||
298 | R(0x011073, 0x011074, 0), /* Brahmi Vowel Sign Old Ta..Brahmi Vowel Sign Old Ta */ | ||
299 | R(0x01107f, 0x011082, 0), /* Brahmi Number Joiner ..Kaithi Sign Visarga */ | ||
300 | R(0x0110b0, 0x0110ba, 0), /* Kaithi Vowel Sign Aa ..Kaithi Sign Nukta */ | ||
301 | R(0x0110bd, 0x0110bd, 0), /* Kaithi Number Sign */ | ||
302 | R(0x0110c2, 0x0110c2, 0), /* Kaithi Vowel Sign Vocalic R */ | ||
303 | R(0x0110cd, 0x0110cd, 0), /* Kaithi Number Sign Above */ | ||
304 | R(0x011100, 0x011102, 0), /* Chakma Sign Candrabindu ..Chakma Sign Visarga */ | ||
305 | R(0x011127, 0x011134, 0), /* Chakma Vowel Sign A ..Chakma Maayyaa */ | ||
306 | R(0x011145, 0x011146, 0), /* Chakma Vowel Sign Aa ..Chakma Vowel Sign Ei */ | ||
307 | R(0x011173, 0x011173, 0), /* Mahajani Sign Nukta */ | ||
308 | R(0x011180, 0x011182, 0), /* Sharada Sign Candrabindu..Sharada Sign Visarga */ | ||
309 | R(0x0111b3, 0x0111c0, 0), /* Sharada Vowel Sign Aa ..Sharada Sign Virama */ | ||
310 | R(0x0111c9, 0x0111cc, 0), /* Sharada Sandhi Mark ..Sharada Extra Short Vowe */ | ||
311 | R(0x0111ce, 0x0111cf, 0), /* Sharada Vowel Sign Prish..Sharada Sign Inverted Ca */ | ||
312 | R(0x01122c, 0x011237, 0), /* Khojki Vowel Sign Aa ..Khojki Sign Shadda */ | ||
313 | R(0x01123e, 0x01123e, 0), /* Khojki Sign Sukun */ | ||
314 | R(0x011241, 0x011241, 0), /* Khojki Vowel Sign Vocalic R */ | ||
315 | R(0x0112df, 0x0112ea, 0), /* Khudawadi Sign Anusvara ..Khudawadi Sign Virama */ | ||
316 | R(0x011300, 0x011303, 0), /* Grantha Sign Combining A..Grantha Sign Visarga */ | ||
317 | R(0x01133b, 0x01133c, 0), /* Combining Bindu Below ..Grantha Sign Nukta */ | ||
318 | R(0x01133e, 0x011344, 0), /* Grantha Vowel Sign Aa ..Grantha Vowel Sign Vocal */ | ||
319 | R(0x011347, 0x011348, 0), /* Grantha Vowel Sign Ee ..Grantha Vowel Sign Ai */ | ||
320 | R(0x01134b, 0x01134d, 0), /* Grantha Vowel Sign Oo ..Grantha Sign Virama */ | ||
321 | R(0x011357, 0x011357, 0), /* Grantha Au Length Mark */ | ||
322 | R(0x011362, 0x011363, 0), /* Grantha Vowel Sign Vocal..Grantha Vowel Sign Vocal */ | ||
323 | R(0x011366, 0x01136c, 0), /* Combining Grantha Digit ..Combining Grantha Digit */ | ||
324 | R(0x011370, 0x011374, 0), /* Combining Grantha Letter..Combining Grantha Letter */ | ||
325 | R(0x011435, 0x011446, 0), /* Newa Vowel Sign Aa ..Newa Sign Nukta */ | ||
326 | R(0x01145e, 0x01145e, 0), /* Newa Sandhi Mark */ | ||
327 | R(0x0114b0, 0x0114c3, 0), /* Tirhuta Vowel Sign Aa ..Tirhuta Sign Nukta */ | ||
328 | R(0x0115af, 0x0115b5, 0), /* Siddham Vowel Sign Aa ..Siddham Vowel Sign Vocal */ | ||
329 | R(0x0115b8, 0x0115c0, 0), /* Siddham Vowel Sign E ..Siddham Sign Nukta */ | ||
330 | R(0x0115dc, 0x0115dd, 0), /* Siddham Vowel Sign Alter..Siddham Vowel Sign Alter */ | ||
331 | R(0x011630, 0x011640, 0), /* Modi Vowel Sign Aa ..Modi Sign Ardhacandra */ | ||
332 | R(0x0116ab, 0x0116b7, 0), /* Takri Sign Anusvara ..Takri Sign Nukta */ | ||
333 | R(0x01171d, 0x01172b, 0), /* Ahom Consonant Sign Medi..Ahom Sign Killer */ | ||
334 | R(0x01182c, 0x01183a, 0), /* Dogra Vowel Sign Aa ..Dogra Sign Nukta */ | ||
335 | R(0x011930, 0x011935, 0), /* Dives Akuru Vowel Sign A..Dives Akuru Vowel Sign E */ | ||
336 | R(0x011937, 0x011938, 0), /* Dives Akuru Vowel Sign A..Dives Akuru Vowel Sign O */ | ||
337 | R(0x01193b, 0x01193e, 0), /* Dives Akuru Sign Anusvar..Dives Akuru Virama */ | ||
338 | R(0x011940, 0x011940, 0), /* Dives Akuru Medial Ya */ | ||
339 | R(0x011942, 0x011943, 0), /* Dives Akuru Medial Ra ..Dives Akuru Sign Nukta */ | ||
340 | R(0x0119d1, 0x0119d7, 0), /* Nandinagari Vowel Sign A..Nandinagari Vowel Sign V */ | ||
341 | R(0x0119da, 0x0119e0, 0), /* Nandinagari Vowel Sign E..Nandinagari Sign Virama */ | ||
342 | R(0x0119e4, 0x0119e4, 0), /* Nandinagari Vowel Sign Prishthamatra E */ | ||
343 | R(0x011a01, 0x011a0a, 0), /* Zanabazar Square Vowel S..Zanabazar Square Vowel L */ | ||
344 | R(0x011a33, 0x011a39, 0), /* Zanabazar Square Final C..Zanabazar Square Sign Vi */ | ||
345 | R(0x011a3b, 0x011a3e, 0), /* Zanabazar Square Cluster..Zanabazar Square Cluster */ | ||
346 | R(0x011a47, 0x011a47, 0), /* Zanabazar Square Subjoiner */ | ||
347 | R(0x011a51, 0x011a5b, 0), /* Soyombo Vowel Sign I ..Soyombo Vowel Length Mar */ | ||
348 | R(0x011a8a, 0x011a99, 0), /* Soyombo Final Consonant ..Soyombo Subjoiner */ | ||
349 | R(0x011c2f, 0x011c36, 0), /* Bhaiksuki Vowel Sign Aa ..Bhaiksuki Vowel Sign Voc */ | ||
350 | R(0x011c38, 0x011c3f, 0), /* Bhaiksuki Vowel Sign E ..Bhaiksuki Sign Virama */ | ||
351 | R(0x011c92, 0x011ca7, 0), /* Marchen Subjoined Letter..Marchen Subjoined Letter */ | ||
352 | R(0x011ca9, 0x011cb6, 0), /* Marchen Subjoined Letter..Marchen Sign Candrabindu */ | ||
353 | R(0x011d31, 0x011d36, 0), /* Masaram Gondi Vowel Sign..Masaram Gondi Vowel Sign */ | ||
354 | R(0x011d3a, 0x011d3a, 0), /* Masaram Gondi Vowel Sign E */ | ||
355 | R(0x011d3c, 0x011d3d, 0), /* Masaram Gondi Vowel Sign..Masaram Gondi Vowel Sign */ | ||
356 | R(0x011d3f, 0x011d45, 0), /* Masaram Gondi Vowel Sign..Masaram Gondi Virama */ | ||
357 | R(0x011d47, 0x011d47, 0), /* Masaram Gondi Ra-kara */ | ||
358 | R(0x011d8a, 0x011d8e, 0), /* Gunjala Gondi Vowel Sign..Gunjala Gondi Vowel Sign */ | ||
359 | R(0x011d90, 0x011d91, 0), /* Gunjala Gondi Vowel Sign..Gunjala Gondi Vowel Sign */ | ||
360 | R(0x011d93, 0x011d97, 0), /* Gunjala Gondi Vowel Sign..Gunjala Gondi Virama */ | ||
361 | R(0x011ef3, 0x011ef6, 0), /* Makasar Vowel Sign I ..Makasar Vowel Sign O */ | ||
362 | R(0x011f00, 0x011f01, 0), /* Kawi Sign Candrabindu ..Kawi Sign Anusvara */ | ||
363 | R(0x011f03, 0x011f03, 0), /* Kawi Sign Visarga */ | ||
364 | R(0x011f34, 0x011f3a, 0), /* Kawi Vowel Sign Aa ..Kawi Vowel Sign Vocalic */ | ||
365 | R(0x011f3e, 0x011f42, 0), /* Kawi Vowel Sign E ..Kawi Conjoiner */ | ||
366 | R(0x013430, 0x013440, 0), /* Egyptian Hieroglyph Vert..Egyptian Hieroglyph Mirr */ | ||
367 | R(0x013447, 0x013455, 0), /* Egyptian Hieroglyph Modi..Egyptian Hieroglyph Modi */ | ||
368 | R(0x016af0, 0x016af4, 0), /* Bassa Vah Combining High..Bassa Vah Combining High */ | ||
369 | R(0x016b30, 0x016b36, 0), /* Pahawh Hmong Mark Cim Tu..Pahawh Hmong Mark Cim Ta */ | ||
370 | R(0x016f4f, 0x016f4f, 0), /* Miao Sign Consonant Modifier Bar */ | ||
371 | R(0x016f51, 0x016f87, 0), /* Miao Sign Aspiration ..Miao Vowel Sign Ui */ | ||
372 | R(0x016f8f, 0x016f92, 0), /* Miao Tone Right ..Miao Tone Below */ | ||
373 | R(0x016fe0, 0x016fe3, 2), /* Tangut Iteration Mark ..Old Chinese Iteration Ma */ | ||
374 | R(0x016fe4, 0x016fe4, 0), /* Khitan Small Script Filler */ | ||
375 | R(0x016ff0, 0x016ff1, 0), /* Vietnamese Alternate Rea..Vietnamese Alternate Rea */ | ||
376 | R(0x017000, 0x0187f7, 2), /* nil */ | ||
377 | R(0x018800, 0x018cd5, 2), /* Tangut Component-001 ..Khitan Small Script Char */ | ||
378 | R(0x018d00, 0x018d08, 2), /* nil */ | ||
379 | R(0x01aff0, 0x01aff3, 2), /* Katakana Letter Minnan T..Katakana Letter Minnan T */ | ||
380 | R(0x01aff5, 0x01affb, 2), /* Katakana Letter Minnan T..Katakana Letter Minnan N */ | ||
381 | R(0x01affd, 0x01affe, 2), /* Katakana Letter Minnan N..Katakana Letter Minnan N */ | ||
382 | R(0x01b000, 0x01b122, 2), /* Katakana Letter Archaic ..Katakana Letter Archaic */ | ||
383 | R(0x01b132, 0x01b132, 2), /* Hiragana Letter Small Ko */ | ||
384 | R(0x01b150, 0x01b152, 2), /* Hiragana Letter Small Wi..Hiragana Letter Small Wo */ | ||
385 | R(0x01b155, 0x01b155, 2), /* Katakana Letter Small Ko */ | ||
386 | R(0x01b164, 0x01b167, 2), /* Katakana Letter Small Wi..Katakana Letter Small N */ | ||
387 | R(0x01b170, 0x01b2fb, 2), /* Nushu Character-1b170 ..Nushu Character-1b2fb */ | ||
388 | R(0x01bc9d, 0x01bc9e, 0), /* Duployan Thick Letter Se..Duployan Double Mark */ | ||
389 | R(0x01bca0, 0x01bca3, 0), /* Shorthand Format Letter ..Shorthand Format Up Step */ | ||
390 | R(0x01cf00, 0x01cf2d, 0), /* Znamenny Combining Mark ..Znamenny Combining Mark */ | ||
391 | R(0x01cf30, 0x01cf46, 0), /* Znamenny Combining Tonal..Znamenny Priznak Modifie */ | ||
392 | R(0x01d165, 0x01d169, 0), /* Musical Symbol Combining..Musical Symbol Combining */ | ||
393 | R(0x01d16d, 0x01d182, 0), /* Musical Symbol Combining..Musical Symbol Combining */ | ||
394 | R(0x01d185, 0x01d18b, 0), /* Musical Symbol Combining..Musical Symbol Combining */ | ||
395 | R(0x01d1aa, 0x01d1ad, 0), /* Musical Symbol Combining..Musical Symbol Combining */ | ||
396 | R(0x01d242, 0x01d244, 0), /* Combining Greek Musical ..Combining Greek Musical */ | ||
397 | R(0x01da00, 0x01da36, 0), /* Signwriting Head Rim ..Signwriting Air Sucking */ | ||
398 | R(0x01da3b, 0x01da6c, 0), /* Signwriting Mouth Closed..Signwriting Excitement */ | ||
399 | R(0x01da75, 0x01da75, 0), /* Signwriting Upper Body Tilting From Hip Joints */ | ||
400 | R(0x01da84, 0x01da84, 0), /* Signwriting Location Head Neck */ | ||
401 | R(0x01da9b, 0x01da9f, 0), /* Signwriting Fill Modifie..Signwriting Fill Modifie */ | ||
402 | R(0x01daa1, 0x01daaf, 0), /* Signwriting Rotation Mod..Signwriting Rotation Mod */ | ||
403 | R(0x01e000, 0x01e006, 0), /* Combining Glagolitic Let..Combining Glagolitic Let */ | ||
404 | R(0x01e008, 0x01e018, 0), /* Combining Glagolitic Let..Combining Glagolitic Let */ | ||
405 | R(0x01e01b, 0x01e021, 0), /* Combining Glagolitic Let..Combining Glagolitic Let */ | ||
406 | R(0x01e023, 0x01e024, 0), /* Combining Glagolitic Let..Combining Glagolitic Let */ | ||
407 | R(0x01e026, 0x01e02a, 0), /* Combining Glagolitic Let..Combining Glagolitic Let */ | ||
408 | R(0x01e08f, 0x01e08f, 0), /* Combining Cyrillic Small Letter Byelorussian-ukr */ | ||
409 | R(0x01e130, 0x01e136, 0), /* Nyiakeng Puachue Hmong T..Nyiakeng Puachue Hmong T */ | ||
410 | R(0x01e2ae, 0x01e2ae, 0), /* Toto Sign Rising Tone */ | ||
411 | R(0x01e2ec, 0x01e2ef, 0), /* Wancho Tone Tup ..Wancho Tone Koini */ | ||
412 | R(0x01e4ec, 0x01e4ef, 0), /* Nag Mundari Sign Muhor ..Nag Mundari Sign Sutuh */ | ||
413 | R(0x01e8d0, 0x01e8d6, 0), /* Mende Kikakui Combining ..Mende Kikakui Combining */ | ||
414 | R(0x01e944, 0x01e94a, 0), /* Adlam Alif Lengthener ..Adlam Nukta */ | ||
415 | R(0x01f004, 0x01f004, 2), /* Mahjong Tile Red Dragon */ | ||
416 | R(0x01f0cf, 0x01f0cf, 2), /* Playing Card Black Joker */ | ||
417 | R(0x01f18e, 0x01f18e, 2), /* Negative Squared Ab */ | ||
418 | R(0x01f191, 0x01f19a, 2), /* Squared Cl ..Squared Vs */ | ||
419 | R(0x01f200, 0x01f202, 2), /* Square Hiragana Hoka ..Squared Katakana Sa */ | ||
420 | R(0x01f210, 0x01f23b, 2), /* Squared Cjk Unified Ideo..Squared Cjk Unified Ideo */ | ||
421 | R(0x01f240, 0x01f248, 2), /* Tortoise Shell Bracketed..Tortoise Shell Bracketed */ | ||
422 | R(0x01f250, 0x01f251, 2), /* Circled Ideograph Advant..Circled Ideograph Accept */ | ||
423 | R(0x01f260, 0x01f265, 2), /* Rounded Symbol For Fu ..Rounded Symbol For Cai */ | ||
424 | R(0x01f300, 0x01f320, 2), /* Cyclone ..Shooting Star */ | ||
425 | R(0x01f32d, 0x01f335, 2), /* Hot Dog ..Cactus */ | ||
426 | R(0x01f337, 0x01f37c, 2), /* Tulip ..Baby Bottle */ | ||
427 | R(0x01f37e, 0x01f393, 2), /* Bottle With Popping Cork..Graduation Cap */ | ||
428 | R(0x01f3a0, 0x01f3ca, 2), /* Carousel Horse ..Swimmer */ | ||
429 | R(0x01f3cf, 0x01f3d3, 2), /* Cricket Bat And Ball ..Table Tennis Paddle And */ | ||
430 | R(0x01f3e0, 0x01f3f0, 2), /* House Building ..European Castle */ | ||
431 | R(0x01f3f4, 0x01f3f4, 2), /* Waving Black Flag */ | ||
432 | R(0x01f3f8, 0x01f3fa, 2), /* Badminton Racquet And Sh..Amphora */ | ||
433 | R(0x01f3fb, 0x01f3ff, 0), /* Emoji Modifier Fitzpatri..Emoji Modifier Fitzpatri */ | ||
434 | R(0x01f400, 0x01f43e, 2), /* Rat ..Paw Prints */ | ||
435 | R(0x01f440, 0x01f440, 2), /* Eyes */ | ||
436 | R(0x01f442, 0x01f4fc, 2), /* Ear ..Videocassette */ | ||
437 | R(0x01f4ff, 0x01f53d, 2), /* Prayer Beads ..Down-pointing Small Red */ | ||
438 | R(0x01f54b, 0x01f54e, 2), /* Kaaba ..Menorah With Nine Branch */ | ||
439 | R(0x01f550, 0x01f567, 2), /* Clock Face One Oclock ..Clock Face Twelve-thirty */ | ||
440 | R(0x01f57a, 0x01f57a, 2), /* Man Dancing */ | ||
441 | R(0x01f595, 0x01f596, 2), /* Reversed Hand With Middl..Raised Hand With Part Be */ | ||
442 | R(0x01f5a4, 0x01f5a4, 2), /* Black Heart */ | ||
443 | R(0x01f5fb, 0x01f64f, 2), /* Mount Fuji ..Person With Folded Hands */ | ||
444 | R(0x01f680, 0x01f6c5, 2), /* Rocket ..Left Luggage */ | ||
445 | R(0x01f6cc, 0x01f6cc, 2), /* Sleeping Accommodation */ | ||
446 | R(0x01f6d0, 0x01f6d2, 2), /* Place Of Worship ..Shopping Trolley */ | ||
447 | R(0x01f6d5, 0x01f6d7, 2), /* Hindu Temple ..Elevator */ | ||
448 | R(0x01f6dc, 0x01f6df, 2), /* Wireless ..Ring Buoy */ | ||
449 | R(0x01f6eb, 0x01f6ec, 2), /* Airplane Departure ..Airplane Arriving */ | ||
450 | R(0x01f6f4, 0x01f6fc, 2), /* Scooter ..Roller Skate */ | ||
451 | R(0x01f7e0, 0x01f7eb, 2), /* Large Orange Circle ..Large Brown Square */ | ||
452 | R(0x01f7f0, 0x01f7f0, 2), /* Heavy Equals Sign */ | ||
453 | R(0x01f90c, 0x01f93a, 2), /* Pinched Fingers ..Fencer */ | ||
454 | R(0x01f93c, 0x01f945, 2), /* Wrestlers ..Goal Net */ | ||
455 | R(0x01f947, 0x01f9ff, 2), /* First Place Medal ..Nazar Amulet */ | ||
456 | R(0x01fa70, 0x01fa7c, 2), /* Ballet Shoes ..Crutch */ | ||
457 | R(0x01fa80, 0x01fa88, 2), /* Yo-yo ..Flute */ | ||
458 | R(0x01fa90, 0x01fabd, 2), /* Ringed Planet ..Wing */ | ||
459 | R(0x01fabf, 0x01fac5, 2), /* Goose ..Person With Crown */ | ||
460 | R(0x01face, 0x01fadb, 2), /* Moose ..Pea Pod */ | ||
461 | R(0x01fae0, 0x01fae8, 2), /* Melting Face ..Shaking Face */ | ||
462 | R(0x01faf0, 0x01faf8, 2), /* Hand With Index Finger A..Rightwards Pushing Hand */ | ||
463 | R(0x020000, 0x027fff, 2), /* Cjk Unified Ideograph-20.. nil */ | ||
464 | R(0x028000, 0x02fffd, 2), /* (continued...) */ | ||
465 | R(0x030000, 0x037fff, 2), /* Cjk Unified Ideograph-30.. nil */ | ||
466 | R(0x038000, 0x03fffd, 2), /* (continued...) */ | ||
467 | R(0x0e0001, 0x0e0001, 0), /* Language Tag */ | ||
468 | R(0x0e0020, 0x0e007f, 0), /* Tag Space ..Cancel Tag */ | ||
469 | R(0x0e0100, 0x0e01ef, 0), /* Variation Selector-17 ..Variation Selector-256 */ | ||
470 | #undef R | ||
471 | }; | ||
472 | |||
473 | /* planes[p], planes[p+1] are [from, to) at "ranges" for plane p */ | ||
474 | static const uint16_t planes[/* 18 */] = { | ||
475 | 0, 261, 443, 445, 447, 447, 447, 447, 447, 447, 447, 447, | ||
476 | 447, 447, 447, 450, 450, 450, | ||
477 | }; | ||
478 | |||
479 | /******* END OF STATIC DATA *******/ | ||
480 | |||
481 | uint32_t p, bot, top; | ||
482 | |||
483 | /* 0:0, 1..31:-1 (C0), 32..126:1 (isprint), 127..159:-1 (DEL, C1) */ | ||
484 | if (ucs < 160) | ||
485 | return ((ucs + 1) & 127) > 32 ? 1 : ucs ? -1 : 0; | ||
486 | |||
487 | /* out of range for "planes" (and non-unicode), non-characters. */ | ||
488 | /* (some also test surrogate halves, but not required by POSIX) */ | ||
489 | if (ucs > 0x10ffff || (ucs & 0xfffe) == 0xfffe) | ||
490 | return -1; | ||
491 | |||
492 | p = ucs >> 16; | ||
493 | ucs &= 0xffff; | ||
494 | |||
495 | for (bot = planes[p], top = planes[p+1]; bot < top; ) { | ||
496 | uint32_t mid = (bot + top) / 2; | ||
497 | if (ucs < ranges[mid].first) | ||
498 | top = mid; | ||
499 | else if (ucs > ranges[mid].first + ranges[mid].difflast) | ||
500 | bot = mid + 1; | ||
501 | else | ||
502 | return 2 * ranges[mid].iswide; | ||
503 | } | ||
504 | |||
505 | return 1; | ||
506 | } /* wcwidth - Unicode 15.1.0 */ | ||
diff --git a/libbb/xatonum_template.c b/libbb/xatonum_template.c index e0471983c..0d5d35b47 100644 --- a/libbb/xatonum_template.c +++ b/libbb/xatonum_template.c | |||
@@ -67,7 +67,7 @@ unsigned type FAST_FUNC xstrtou(_range_sfx)(const char *numstr, int base, | |||
67 | if (r >= lower && r <= upper) | 67 | if (r >= lower && r <= upper) |
68 | return r; | 68 | return r; |
69 | range: | 69 | range: |
70 | bb_error_msg_and_die("number %s is not in %llu..%llu range", | 70 | bb_error_msg_and_die("number %s is not in %"LL_FMT"u..%"LL_FMT"u range", |
71 | numstr, (unsigned long long)lower, | 71 | numstr, (unsigned long long)lower, |
72 | (unsigned long long)upper); | 72 | (unsigned long long)upper); |
73 | inval: | 73 | inval: |
@@ -144,7 +144,8 @@ type FAST_FUNC xstrto(_range_sfx)(const char *numstr, int base, | |||
144 | } | 144 | } |
145 | 145 | ||
146 | if (r < lower || r > upper) { | 146 | if (r < lower || r > upper) { |
147 | bb_error_msg_and_die("number %s is not in %lld..%lld range", | 147 | bb_error_msg_and_die("number %s is not in " |
148 | "%"LL_FMT"d..%"LL_FMT"d range", | ||
148 | numstr, (long long)lower, (long long)upper); | 149 | numstr, (long long)lower, (long long)upper); |
149 | } | 150 | } |
150 | 151 | ||
diff --git a/libbb/xconnect.c b/libbb/xconnect.c index 0e0b247b8..65b1cb8de 100644 --- a/libbb/xconnect.c +++ b/libbb/xconnect.c | |||
@@ -71,6 +71,7 @@ int FAST_FUNC setsockopt_bindtodevice(int fd UNUSED_PARAM, | |||
71 | } | 71 | } |
72 | #endif | 72 | #endif |
73 | 73 | ||
74 | #if !ENABLE_PLATFORM_MINGW32 | ||
74 | static len_and_sockaddr* get_lsa(int fd, int (*get_name)(int fd, struct sockaddr *addr, socklen_t *addrlen)) | 75 | static len_and_sockaddr* get_lsa(int fd, int (*get_name)(int fd, struct sockaddr *addr, socklen_t *addrlen)) |
75 | { | 76 | { |
76 | len_and_sockaddr lsa; | 77 | len_and_sockaddr lsa; |
@@ -99,16 +100,17 @@ len_and_sockaddr* FAST_FUNC get_peer_lsa(int fd) | |||
99 | { | 100 | { |
100 | return get_lsa(fd, getpeername); | 101 | return get_lsa(fd, getpeername); |
101 | } | 102 | } |
103 | #endif | ||
102 | 104 | ||
103 | void FAST_FUNC xconnect(int s, const struct sockaddr *s_addr, socklen_t addrlen) | 105 | void FAST_FUNC xconnect(int s, const struct sockaddr *saddr, socklen_t addrlen) |
104 | { | 106 | { |
105 | if (connect(s, s_addr, addrlen) < 0) { | 107 | if (connect(s, saddr, addrlen) < 0) { |
106 | if (ENABLE_FEATURE_CLEAN_UP) | 108 | if (ENABLE_FEATURE_CLEAN_UP) |
107 | close(s); | 109 | close(s); |
108 | if (s_addr->sa_family == AF_INET) | 110 | if (saddr->sa_family == AF_INET) |
109 | bb_perror_msg_and_die("%s (%s)", | 111 | bb_perror_msg_and_die("%s (%s)", |
110 | "can't connect to remote host", | 112 | "can't connect to remote host", |
111 | inet_ntoa(((struct sockaddr_in *)s_addr)->sin_addr)); | 113 | inet_ntoa(((struct sockaddr_in *)saddr)->sin_addr)); |
112 | bb_simple_perror_msg_and_die("can't connect to remote host"); | 114 | bb_simple_perror_msg_and_die("can't connect to remote host"); |
113 | } | 115 | } |
114 | } | 116 | } |
@@ -348,6 +350,10 @@ int FAST_FUNC xsocket_type(len_and_sockaddr **lsap, int family, int sock_type) | |||
348 | #if ENABLE_FEATURE_IPV6 | 350 | #if ENABLE_FEATURE_IPV6 |
349 | fd = socket(AF_INET6, sock_type, 0); | 351 | fd = socket(AF_INET6, sock_type, 0); |
350 | if (fd >= 0) { | 352 | if (fd >= 0) { |
353 | #if ENABLE_PLATFORM_MINGW32 | ||
354 | DWORD buffer = 0; | ||
355 | setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &buffer, sizeof(DWORD)); | ||
356 | #endif | ||
351 | family = AF_INET6; | 357 | family = AF_INET6; |
352 | goto done; | 358 | goto done; |
353 | } | 359 | } |
diff --git a/libbb/xfuncs.c b/libbb/xfuncs.c index b03af8542..7df1a4cd3 100644 --- a/libbb/xfuncs.c +++ b/libbb/xfuncs.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include "libbb.h" | 23 | #include "libbb.h" |
24 | 24 | ||
25 | /* Turn on nonblocking I/O on a fd */ | 25 | /* Turn on nonblocking I/O on a fd */ |
26 | #if !ENABLE_PLATFORM_MINGW32 | ||
26 | int FAST_FUNC ndelay_on(int fd) | 27 | int FAST_FUNC ndelay_on(int fd) |
27 | { | 28 | { |
28 | int flags = fcntl(fd, F_GETFL); | 29 | int flags = fcntl(fd, F_GETFL); |
@@ -45,6 +46,7 @@ void FAST_FUNC close_on_exec_on(int fd) | |||
45 | { | 46 | { |
46 | fcntl(fd, F_SETFD, FD_CLOEXEC); | 47 | fcntl(fd, F_SETFD, FD_CLOEXEC); |
47 | } | 48 | } |
49 | #endif | ||
48 | 50 | ||
49 | char* FAST_FUNC strncpy_IFNAMSIZ(char *dst, const char *src) | 51 | char* FAST_FUNC strncpy_IFNAMSIZ(char *dst, const char *src) |
50 | { | 52 | { |
@@ -219,7 +221,12 @@ off_t FAST_FUNC fdlength(int fd) | |||
219 | 221 | ||
220 | int FAST_FUNC bb_putchar_stderr(char ch) | 222 | int FAST_FUNC bb_putchar_stderr(char ch) |
221 | { | 223 | { |
224 | #if ENABLE_PLATFORM_MINGW32 && !defined(_UCRT) | ||
225 | // Workaround for problems with stderr in MSVCRT | ||
226 | return fputc(ch, stderr); | ||
227 | #else | ||
222 | return write(STDERR_FILENO, &ch, 1); | 228 | return write(STDERR_FILENO, &ch, 1); |
229 | #endif | ||
223 | } | 230 | } |
224 | 231 | ||
225 | ssize_t FAST_FUNC full_write1_str(const char *str) | 232 | ssize_t FAST_FUNC full_write1_str(const char *str) |
@@ -268,6 +275,7 @@ int FAST_FUNC get_terminal_width_height(int fd, unsigned *width, unsigned *heigh | |||
268 | int err; | 275 | int err; |
269 | int close_me = -1; | 276 | int close_me = -1; |
270 | 277 | ||
278 | #if !ENABLE_PLATFORM_MINGW32 | ||
271 | if (fd == -1) { | 279 | if (fd == -1) { |
272 | if (isatty(STDOUT_FILENO)) | 280 | if (isatty(STDOUT_FILENO)) |
273 | fd = STDOUT_FILENO; | 281 | fd = STDOUT_FILENO; |
@@ -280,6 +288,7 @@ int FAST_FUNC get_terminal_width_height(int fd, unsigned *width, unsigned *heigh | |||
280 | else | 288 | else |
281 | close_me = fd = open("/dev/tty", O_RDONLY); | 289 | close_me = fd = open("/dev/tty", O_RDONLY); |
282 | } | 290 | } |
291 | #endif | ||
283 | 292 | ||
284 | win.ws_row = 0; | 293 | win.ws_row = 0; |
285 | win.ws_col = 0; | 294 | win.ws_col = 0; |
@@ -314,7 +323,7 @@ int FAST_FUNC tcsetattr_stdin_TCSANOW(const struct termios *tp) | |||
314 | return tcsetattr(STDIN_FILENO, TCSANOW, tp); | 323 | return tcsetattr(STDIN_FILENO, TCSANOW, tp); |
315 | } | 324 | } |
316 | 325 | ||
317 | int FAST_FUNC get_termios_and_make_raw(int fd, struct termios *newterm, struct termios *oldterm, int flags) | 326 | int FAST_FUNC get_termios_and_make_raw(int fd, struct termios *newterm, struct termios *oldterm, int flags IF_PLATFORM_MINGW32(UNUSED_PARAM)) |
318 | { | 327 | { |
319 | //TODO: slattach, shell read might be adapted to use this too: grep for "tcsetattr", "[VTIME] = 0" | 328 | //TODO: slattach, shell read might be adapted to use this too: grep for "tcsetattr", "[VTIME] = 0" |
320 | int r; | 329 | int r; |
@@ -323,6 +332,10 @@ int FAST_FUNC get_termios_and_make_raw(int fd, struct termios *newterm, struct t | |||
323 | r = tcgetattr(fd, oldterm); | 332 | r = tcgetattr(fd, oldterm); |
324 | *newterm = *oldterm; | 333 | *newterm = *oldterm; |
325 | 334 | ||
335 | #if ENABLE_PLATFORM_MINGW32 | ||
336 | newterm->imode &= | ||
337 | ~(ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT); | ||
338 | #else | ||
326 | /* Turn off buffered input (ICANON) | 339 | /* Turn off buffered input (ICANON) |
327 | * Turn off echoing (ECHO) | 340 | * Turn off echoing (ECHO) |
328 | * and separate echoing of newline (ECHONL, normally off anyway) | 341 | * and separate echoing of newline (ECHONL, normally off anyway) |
@@ -379,6 +392,7 @@ int FAST_FUNC get_termios_and_make_raw(int fd, struct termios *newterm, struct t | |||
379 | */ | 392 | */ |
380 | newterm->c_iflag &= ~(IXOFF|IXON|IXANY|BRKINT|INLCR|ICRNL|IUCLC|IMAXBEL); | 393 | newterm->c_iflag &= ~(IXOFF|IXON|IXANY|BRKINT|INLCR|ICRNL|IUCLC|IMAXBEL); |
381 | } | 394 | } |
395 | #endif | ||
382 | return r; | 396 | return r; |
383 | } | 397 | } |
384 | 398 | ||
diff --git a/libbb/xfuncs_printf.c b/libbb/xfuncs_printf.c index 842d10cd2..0ead3b2eb 100644 --- a/libbb/xfuncs_printf.c +++ b/libbb/xfuncs_printf.c | |||
@@ -108,6 +108,7 @@ void* FAST_FUNC xmemdup(const void *s, size_t n) | |||
108 | return memcpy(xmalloc(n), s, n); | 108 | return memcpy(xmalloc(n), s, n); |
109 | } | 109 | } |
110 | 110 | ||
111 | #if !ENABLE_PLATFORM_MINGW32 | ||
111 | void* FAST_FUNC mmap_read(int fd, size_t size) | 112 | void* FAST_FUNC mmap_read(int fd, size_t size) |
112 | { | 113 | { |
113 | return mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); | 114 | return mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); |
@@ -128,6 +129,7 @@ void* FAST_FUNC xmmap_anon(size_t size) | |||
128 | bb_die_memory_exhausted(); | 129 | bb_die_memory_exhausted(); |
129 | return p; | 130 | return p; |
130 | } | 131 | } |
132 | #endif | ||
131 | 133 | ||
132 | // Die if we can't open a file and return a FILE* to it. | 134 | // Die if we can't open a file and return a FILE* to it. |
133 | // Notice we haven't got xfread(), This is for use with fscanf() and friends. | 135 | // Notice we haven't got xfread(), This is for use with fscanf() and friends. |
@@ -334,7 +336,7 @@ void FAST_FUNC xprint_and_close_file(FILE *file) | |||
334 | 336 | ||
335 | // Die with an error message if we can't malloc() enough space and do an | 337 | // Die with an error message if we can't malloc() enough space and do an |
336 | // sprintf() into that space. | 338 | // sprintf() into that space. |
337 | char* FAST_FUNC xasprintf(const char *format, ...) | 339 | char* xasprintf(const char *format, ...) |
338 | { | 340 | { |
339 | va_list p; | 341 | va_list p; |
340 | int r; | 342 | int r; |
@@ -501,6 +503,7 @@ void FAST_FUNC xlisten(int s, int backlog) | |||
501 | if (listen(s, backlog)) bb_simple_perror_msg_and_die("listen"); | 503 | if (listen(s, backlog)) bb_simple_perror_msg_and_die("listen"); |
502 | } | 504 | } |
503 | 505 | ||
506 | #if !ENABLE_PLATFORM_MINGW32 | ||
504 | /* Die with an error message if sendto failed. | 507 | /* Die with an error message if sendto failed. |
505 | * Return bytes sent otherwise */ | 508 | * Return bytes sent otherwise */ |
506 | ssize_t FAST_FUNC xsendto(int s, const void *buf, size_t len, const struct sockaddr *to, | 509 | ssize_t FAST_FUNC xsendto(int s, const void *buf, size_t len, const struct sockaddr *to, |
@@ -514,6 +517,7 @@ ssize_t FAST_FUNC xsendto(int s, const void *buf, size_t len, const struct socka | |||
514 | } | 517 | } |
515 | return ret; | 518 | return ret; |
516 | } | 519 | } |
520 | #endif | ||
517 | 521 | ||
518 | // xstat() - a stat() which dies on failure with meaningful error message | 522 | // xstat() - a stat() which dies on failure with meaningful error message |
519 | void FAST_FUNC xstat(const char *name, struct stat *stat_buf) | 523 | void FAST_FUNC xstat(const char *name, struct stat *stat_buf) |
@@ -547,7 +551,8 @@ void FAST_FUNC selinux_or_die(void) | |||
547 | /* not defined, other code must have no calls to it */ | 551 | /* not defined, other code must have no calls to it */ |
548 | #endif | 552 | #endif |
549 | 553 | ||
550 | int FAST_FUNC ioctl_or_perror_and_die(int fd, unsigned request, void *argp, const char *fmt,...) | 554 | #if !ENABLE_PLATFORM_MINGW32 |
555 | int ioctl_or_perror_and_die(int fd, unsigned request, void *argp, const char *fmt,...) | ||
551 | { | 556 | { |
552 | int ret; | 557 | int ret; |
553 | va_list p; | 558 | va_list p; |
@@ -563,7 +568,7 @@ int FAST_FUNC ioctl_or_perror_and_die(int fd, unsigned request, void *argp, cons | |||
563 | return ret; | 568 | return ret; |
564 | } | 569 | } |
565 | 570 | ||
566 | int FAST_FUNC ioctl_or_perror(int fd, unsigned request, void *argp, const char *fmt,...) | 571 | int ioctl_or_perror(int fd, unsigned request, void *argp, const char *fmt,...) |
567 | { | 572 | { |
568 | va_list p; | 573 | va_list p; |
569 | int ret = ioctl(fd, request, argp); | 574 | int ret = ioctl(fd, request, argp); |
@@ -711,6 +716,7 @@ void FAST_FUNC xvfork_parent_waits_and_exits(void) | |||
711 | } | 716 | } |
712 | /* Child continues */ | 717 | /* Child continues */ |
713 | } | 718 | } |
719 | #endif /* !ENABLE_PLATFORM_MINGW32 */ | ||
714 | 720 | ||
715 | // Useful when we do know that pid is valid, and we just want to wait | 721 | // Useful when we do know that pid is valid, and we just want to wait |
716 | // for it to exit. Not existing pid is fatal. waitpid() status is not returned. | 722 | // for it to exit. Not existing pid is fatal. waitpid() status is not returned. |
@@ -724,11 +730,13 @@ int FAST_FUNC wait_for_exitstatus(pid_t pid) | |||
724 | return exit_status; | 730 | return exit_status; |
725 | } | 731 | } |
726 | 732 | ||
733 | #if !ENABLE_PLATFORM_MINGW32 | ||
727 | void FAST_FUNC xsettimeofday(const struct timeval *tv) | 734 | void FAST_FUNC xsettimeofday(const struct timeval *tv) |
728 | { | 735 | { |
729 | if (settimeofday(tv, NULL)) | 736 | if (settimeofday(tv, NULL)) |
730 | bb_simple_perror_msg_and_die("settimeofday"); | 737 | bb_simple_perror_msg_and_die("settimeofday"); |
731 | } | 738 | } |
739 | #endif | ||
732 | 740 | ||
733 | void FAST_FUNC xgettimeofday(struct timeval *tv) | 741 | void FAST_FUNC xgettimeofday(struct timeval *tv) |
734 | { | 742 | { |
diff --git a/libbb/xreadlink.c b/libbb/xreadlink.c index 2682f6975..fc10a2939 100644 --- a/libbb/xreadlink.c +++ b/libbb/xreadlink.c | |||
@@ -17,6 +17,7 @@ | |||
17 | * NOTE: This function returns a malloced char* that you will have to free | 17 | * NOTE: This function returns a malloced char* that you will have to free |
18 | * yourself. | 18 | * yourself. |
19 | */ | 19 | */ |
20 | #if !ENABLE_PLATFORM_MINGW32 | ||
20 | char* FAST_FUNC xmalloc_readlink(const char *path) | 21 | char* FAST_FUNC xmalloc_readlink(const char *path) |
21 | { | 22 | { |
22 | enum { GROWBY = 80 }; /* how large we will grow strings by */ | 23 | enum { GROWBY = 80 }; /* how large we will grow strings by */ |
@@ -38,6 +39,7 @@ char* FAST_FUNC xmalloc_readlink(const char *path) | |||
38 | 39 | ||
39 | return buf; | 40 | return buf; |
40 | } | 41 | } |
42 | #endif | ||
41 | 43 | ||
42 | /* | 44 | /* |
43 | * This routine is not the same as realpath(), which | 45 | * This routine is not the same as realpath(), which |
@@ -64,19 +66,26 @@ char* FAST_FUNC xmalloc_follow_symlinks(const char *path) | |||
64 | linkpath = xmalloc_readlink(buf); | 66 | linkpath = xmalloc_readlink(buf); |
65 | if (!linkpath) { | 67 | if (!linkpath) { |
66 | /* not a symlink, or doesn't exist */ | 68 | /* not a symlink, or doesn't exist */ |
67 | if (errno == EINVAL || errno == ENOENT) | 69 | if (errno == EINVAL || errno == ENOENT || (ENABLE_PLATFORM_MINGW32 && errno == ENOSYS)) |
68 | return buf; | 70 | return buf; |
69 | goto free_buf_ret_null; | 71 | goto free_buf_ret_null; |
70 | } | 72 | } |
71 | 73 | ||
72 | if (!--looping) { | 74 | if (!--looping) { |
75 | #if ENABLE_PLATFORM_MINGW32 | ||
76 | errno = ELOOP; | ||
77 | #endif | ||
73 | free(linkpath); | 78 | free(linkpath); |
74 | free_buf_ret_null: | 79 | free_buf_ret_null: |
75 | free(buf); | 80 | free(buf); |
76 | return NULL; | 81 | return NULL; |
77 | } | 82 | } |
78 | 83 | ||
84 | #if ENABLE_PLATFORM_MINGW32 | ||
85 | if (is_relative_path(linkpath)) { | ||
86 | #else | ||
79 | if (*linkpath != '/') { | 87 | if (*linkpath != '/') { |
88 | #endif | ||
80 | bufsize += strlen(linkpath); | 89 | bufsize += strlen(linkpath); |
81 | buf = xrealloc(buf, bufsize); | 90 | buf = xrealloc(buf, bufsize); |
82 | lpc = bb_get_last_path_component_strip(buf); | 91 | lpc = bb_get_last_path_component_strip(buf); |
@@ -149,7 +158,11 @@ char* FAST_FUNC xmalloc_realpath_coreutils(char *path) | |||
149 | * $ realpath symlink | 158 | * $ realpath symlink |
150 | * /usr/bin/qwe | 159 | * /usr/bin/qwe |
151 | */ | 160 | */ |
161 | #if ENABLE_PLATFORM_MINGW32 | ||
162 | if (is_relative_path(target)) { | ||
163 | #else | ||
152 | if (target[0] != '/') { | 164 | if (target[0] != '/') { |
165 | #endif | ||
153 | /* | 166 | /* |
154 | * $ ln -s target_does_not_exist symlink | 167 | * $ ln -s target_does_not_exist symlink |
155 | * $ readlink -f symlink | 168 | * $ readlink -f symlink |
@@ -168,6 +181,35 @@ char* FAST_FUNC xmalloc_realpath_coreutils(char *path) | |||
168 | return buf; | 181 | return buf; |
169 | } | 182 | } |
170 | 183 | ||
184 | #if ENABLE_PLATFORM_MINGW32 | ||
185 | /* ignore leading and trailing slashes */ | ||
186 | /* but keep leading slashes of UNC path */ | ||
187 | if (!is_unc_path(path)) { | ||
188 | while (is_dir_sep(path[0]) && is_dir_sep(path[1])) | ||
189 | ++path; | ||
190 | } | ||
191 | i = strlen(path) - 1; | ||
192 | while (i > 0 && is_dir_sep(path[i])) | ||
193 | i--; | ||
194 | c = path[i + 1]; | ||
195 | path[i + 1] = '\0'; | ||
196 | |||
197 | last_slash = get_last_slash(path); | ||
198 | if (last_slash == path + root_len(path)) | ||
199 | buf = xstrdup(path); | ||
200 | else if (last_slash) { | ||
201 | char c2 = *last_slash; | ||
202 | *last_slash = '\0'; | ||
203 | buf = xmalloc_realpath(path); | ||
204 | *last_slash++ = c2; | ||
205 | if (buf) { | ||
206 | unsigned len = strlen(buf); | ||
207 | buf = xrealloc(buf, len + strlen(last_slash) + 2); | ||
208 | buf[len++] = c2; | ||
209 | strcpy(buf + len, last_slash); | ||
210 | } | ||
211 | } | ||
212 | #else | ||
171 | /* ignore leading and trailing slashes */ | 213 | /* ignore leading and trailing slashes */ |
172 | while (path[0] == '/' && path[1] == '/') | 214 | while (path[0] == '/' && path[1] == '/') |
173 | ++path; | 215 | ++path; |
@@ -191,6 +233,7 @@ char* FAST_FUNC xmalloc_realpath_coreutils(char *path) | |||
191 | strcpy(buf + len, last_slash); | 233 | strcpy(buf + len, last_slash); |
192 | } | 234 | } |
193 | } | 235 | } |
236 | #endif | ||
194 | path[i + 1] = c; | 237 | path[i + 1] = c; |
195 | } | 238 | } |
196 | 239 | ||