aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2026-09-04 09:27:17 +0100
committerRon Yorston <rmy@pobox.com>2026-09-04 09:27:17 +0100
commita7cfac2b372e21950cf8b9e9defff742b92043d8 (patch)
treea0b292c4c473412c6c1070d46e9b39384cb4a644
parentdc703c7272ef1c71c0d43a056e21299d1bb5fea0 (diff)
parent74ac096e895acd6b02976bb010e9b3511234e899 (diff)
downloadbusybox-w32-merge.tar.gz
busybox-w32-merge.tar.bz2
busybox-w32-merge.zip
Merge branch 'busybox' into mergemerge
Signed-off-by: Ron Yorston <rmy@pobox.com>
Diffstat (limited to '')
-rw-r--r--archival/ar.c3
-rw-r--r--archival/libarchive/get_header_ar.c2
-rw-r--r--archival/libarchive/get_header_cpio.c2
-rw-r--r--archival/libarchive/get_header_tar.c2
-rw-r--r--archival/libarchive/header_list.c9
-rw-r--r--archival/libarchive/header_skip.c2
-rw-r--r--archival/libarchive/header_verbose_list.c15
-rw-r--r--archival/rpm.c4
-rw-r--r--archival/tar.c2
-rw-r--r--coreutils/cp.c28
-rw-r--r--coreutils/id.c2
-rw-r--r--coreutils/install.c4
-rw-r--r--coreutils/libcoreutils/getopt_mk_fifo_nod.c2
-rw-r--r--coreutils/ls.c2
-rw-r--r--coreutils/mkdir.c2
-rw-r--r--coreutils/sort.c19
-rw-r--r--coreutils/stat.c156
-rw-r--r--editors/awk.c103
-rw-r--r--editors/patch.c23
-rw-r--r--editors/vi.c12
-rw-r--r--findutils/find.c4
-rw-r--r--findutils/grep.c77
-rw-r--r--include/bb_archive.h8
-rw-r--r--include/libbb.h15
-rw-r--r--include/platform.h15
-rw-r--r--libbb/copy_file.c6
-rw-r--r--libbb/run_shell.c4
-rw-r--r--libbb/selinux_common.c6
-rw-r--r--libbb/update_passwd.c2
-rw-r--r--loginutils/login.c6
-rw-r--r--miscutils/devfsd.c4
-rw-r--r--miscutils/hdparm.c2
-rw-r--r--miscutils/less.c11
-rw-r--r--networking/inetd.c2
-rw-r--r--networking/tftp.c2
-rw-r--r--selinux/chcon.c4
-rw-r--r--selinux/matchpathcon.c2
-rw-r--r--selinux/runcon.c4
-rw-r--r--selinux/sestatus.c2
-rw-r--r--shell/ash_test/ash-read/read_n.right2
-rwxr-xr-xshell/ash_test/ash-read/read_n.tests2
-rw-r--r--shell/hush.c20
-rw-r--r--shell/hush_test/hush-read/read_n.right2
-rwxr-xr-xshell/hush_test/hush-read/read_n.tests2
-rw-r--r--shell/shell_common.c5
-rwxr-xr-xtestsuite/awk.tests27
-rwxr-xr-xtestsuite/hdparm.tests51
-rwxr-xr-xtestsuite/sort.tests10
-rwxr-xr-xtestsuite/tar.tests24
-rw-r--r--util-linux/mkswap.c4
50 files changed, 511 insertions, 208 deletions
diff --git a/archival/ar.c b/archival/ar.c
index 16bb33227..0780548d6 100644
--- a/archival/ar.c
+++ b/archival/ar.c
@@ -211,8 +211,9 @@ static int write_ar_archive(archive_handle_t *handle)
211} 211}
212#endif /* FEATURE_AR_CREATE */ 212#endif /* FEATURE_AR_CREATE */
213 213
214static void FAST_FUNC header_verbose_list_ar(const file_header_t *file_header) 214static void FAST_FUNC header_verbose_list_ar(archive_handle_t *archive_handle)
215{ 215{
216 const file_header_t *file_header = archive_handle->file_header;
216 char mode[12]; 217 char mode[12];
217 char *mtime; 218 char *mtime;
218 219
diff --git a/archival/libarchive/get_header_ar.c b/archival/libarchive/get_header_ar.c
index 6bd897392..8106ccb4d 100644
--- a/archival/libarchive/get_header_ar.c
+++ b/archival/libarchive/get_header_ar.c
@@ -124,7 +124,7 @@ char FAST_FUNC get_header_ar(archive_handle_t *archive_handle)
124 typed->name[strcspn(typed->name, " /")] = '\0'; 124 typed->name[strcspn(typed->name, " /")] = '\0';
125 125
126 if (archive_handle->filter(archive_handle) == EXIT_SUCCESS) { 126 if (archive_handle->filter(archive_handle) == EXIT_SUCCESS) {
127 archive_handle->action_header(typed); 127 archive_handle->action_header(archive_handle);
128#if ENABLE_DPKG || ENABLE_DPKG_DEB 128#if ENABLE_DPKG || ENABLE_DPKG_DEB
129 if (archive_handle->dpkg__sub_archive) { 129 if (archive_handle->dpkg__sub_archive) {
130 struct archive_handle_t *sa = archive_handle->dpkg__sub_archive; 130 struct archive_handle_t *sa = archive_handle->dpkg__sub_archive;
diff --git a/archival/libarchive/get_header_cpio.c b/archival/libarchive/get_header_cpio.c
index 9ad0557c2..63a0b6d8a 100644
--- a/archival/libarchive/get_header_cpio.c
+++ b/archival/libarchive/get_header_cpio.c
@@ -125,7 +125,7 @@ char FAST_FUNC get_header_cpio(archive_handle_t *archive_handle)
125//cpio: etc/hosts not created: newer or same age file exists 125//cpio: etc/hosts not created: newer or same age file exists
126//etc/hosts <-- should NOT show it 126//etc/hosts <-- should NOT show it
127//2 blocks <-- should say "0 blocks" 127//2 blocks <-- should say "0 blocks"
128 archive_handle->action_header(file_header); 128 archive_handle->action_header(archive_handle);
129 } else { 129 } else {
130 data_skip(archive_handle); 130 data_skip(archive_handle);
131 } 131 }
diff --git a/archival/libarchive/get_header_tar.c b/archival/libarchive/get_header_tar.c
index b83523fb2..56a81d093 100644
--- a/archival/libarchive/get_header_tar.c
+++ b/archival/libarchive/get_header_tar.c
@@ -474,7 +474,7 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle)
474 cp = last_char_is(file_header->name, '/'); 474 cp = last_char_is(file_header->name, '/');
475 475
476 if (archive_handle->filter(archive_handle) == EXIT_SUCCESS) { 476 if (archive_handle->filter(archive_handle) == EXIT_SUCCESS) {
477 archive_handle->action_header(/*archive_handle->*/ file_header); 477 archive_handle->action_header(archive_handle);
478 /* Note that we kill the '/' only after action_header() */ 478 /* Note that we kill the '/' only after action_header() */
479 /* (like GNU tar 1.15.1: verbose mode outputs "dir/dir/") */ 479 /* (like GNU tar 1.15.1: verbose mode outputs "dir/dir/") */
480 if (cp) 480 if (cp)
diff --git a/archival/libarchive/header_list.c b/archival/libarchive/header_list.c
index 9490b3635..28ac831d5 100644
--- a/archival/libarchive/header_list.c
+++ b/archival/libarchive/header_list.c
@@ -5,8 +5,13 @@
5#include "libbb.h" 5#include "libbb.h"
6#include "bb_archive.h" 6#include "bb_archive.h"
7 7
8void FAST_FUNC header_list(const file_header_t *file_header) 8void FAST_FUNC header_list(archive_handle_t *archive_handle)
9{ 9{
10//TODO: cpio -vp DIR should output "DIR/NAME", not just "NAME" */ 10//TODO: cpio -vp DIR should output "DIR/NAME", not just "NAME" */
11 puts(printable_string(file_header->name)); 11
12 const file_header_t *file_header = archive_handle->file_header;
13 /* "tar xvOf TARFILE >OUTFILE" should use stderr for file list output: */
14 FILE *fp = (archive_handle->action_data == data_extract_to_stdout) ? stderr : stdout;
15
16 fprintf(fp, "%s\n", printable_string(file_header->name));
12} 17}
diff --git a/archival/libarchive/header_skip.c b/archival/libarchive/header_skip.c
index f5987bfe2..e7691534e 100644
--- a/archival/libarchive/header_skip.c
+++ b/archival/libarchive/header_skip.c
@@ -5,6 +5,6 @@
5#include "libbb.h" 5#include "libbb.h"
6#include "bb_archive.h" 6#include "bb_archive.h"
7 7
8void FAST_FUNC header_skip(const file_header_t *file_header UNUSED_PARAM) 8void FAST_FUNC header_skip(archive_handle_t *archive_handle UNUSED_PARAM)
9{ 9{
10} 10}
diff --git a/archival/libarchive/header_verbose_list.c b/archival/libarchive/header_verbose_list.c
index e7a09430d..0cd477de7 100644
--- a/archival/libarchive/header_verbose_list.c
+++ b/archival/libarchive/header_verbose_list.c
@@ -5,11 +5,14 @@
5#include "libbb.h" 5#include "libbb.h"
6#include "bb_archive.h" 6#include "bb_archive.h"
7 7
8void FAST_FUNC header_verbose_list(const file_header_t *file_header) 8void FAST_FUNC header_verbose_list(archive_handle_t *archive_handle)
9{ 9{
10 const file_header_t *file_header = archive_handle->file_header;
10 struct tm tm_time; 11 struct tm tm_time;
11 struct tm *ptm = &tm_time; //localtime(&file_header->mtime); 12 struct tm *ptm = &tm_time; //localtime(&file_header->mtime);
12 char modestr[12]; 13 char modestr[12];
14 /* "tar xvvOf TARFILE >OUTFILE" should use stderr for file list output: */
15 FILE *fp = (archive_handle->action_data == data_extract_to_stdout) ? stderr : stdout;
13 16
14#if ENABLE_FEATURE_TAR_UNAME_GNAME 17#if ENABLE_FEATURE_TAR_UNAME_GNAME
15 char uid[sizeof(int)*3 + 2]; 18 char uid[sizeof(int)*3 + 2];
@@ -29,7 +32,7 @@ void FAST_FUNC header_verbose_list(const file_header_t *file_header)
29 /*sprintf(gid, "%u", (unsigned)file_header->gid);*/ 32 /*sprintf(gid, "%u", (unsigned)file_header->gid);*/
30 group = utoa(file_header->gid); 33 group = utoa(file_header->gid);
31 } 34 }
32 printf("%s %s/%s %9"OFF_FMT"u %4u-%02u-%02u %02u:%02u:%02u %s", 35 fprintf(fp, "%s %s/%s %9"OFF_FMT"u %4u-%02u-%02u %02u:%02u:%02u %s",
33 bb_mode_string(modestr, file_header->mode), 36 bb_mode_string(modestr, file_header->mode),
34 user, 37 user,
35 group, 38 group,
@@ -40,13 +43,13 @@ void FAST_FUNC header_verbose_list(const file_header_t *file_header)
40 ptm->tm_hour, 43 ptm->tm_hour,
41 ptm->tm_min, 44 ptm->tm_min,
42 ptm->tm_sec, 45 ptm->tm_sec,
43 file_header->name); 46 printable_string(file_header->name));
44 47
45#else /* !FEATURE_TAR_UNAME_GNAME */ 48#else /* !FEATURE_TAR_UNAME_GNAME */
46 49
47 localtime_r(&file_header->mtime, ptm); 50 localtime_r(&file_header->mtime, ptm);
48 51
49 printf("%s %u/%u %9"OFF_FMT"u %4u-%02u-%02u %02u:%02u:%02u %s", 52 fprintf(fp, "%s %u/%u %9"OFF_FMT"u %4u-%02u-%02u %02u:%02u:%02u %s",
50 bb_mode_string(modestr, file_header->mode), 53 bb_mode_string(modestr, file_header->mode),
51 (unsigned)file_header->uid, 54 (unsigned)file_header->uid,
52 (unsigned)file_header->gid, 55 (unsigned)file_header->gid,
@@ -63,7 +66,7 @@ void FAST_FUNC header_verbose_list(const file_header_t *file_header)
63 66
64 /* NB: GNU tar shows "->" for symlinks and "link to" for hardlinks */ 67 /* NB: GNU tar shows "->" for symlinks and "link to" for hardlinks */
65 if (file_header->link_target) { 68 if (file_header->link_target) {
66 printf(" -> %s", printable_string(file_header->link_target)); 69 fprintf(fp, " -> %s", printable_string(file_header->link_target));
67 } 70 }
68 bb_putchar('\n'); 71 putc('\n', fp);
69} 72}
diff --git a/archival/rpm.c b/archival/rpm.c
index 81b3248d1..5c287378a 100644
--- a/archival/rpm.c
+++ b/archival/rpm.c
@@ -550,9 +550,9 @@ int rpm2cpio_main(int argc UNUSED_PARAM, char **argv)
550 // /* We need to know whether child (gzip/bzip/etc) exits abnormally */ 550 // /* We need to know whether child (gzip/bzip/etc) exits abnormally */
551 // signal(SIGCHLD, check_errors_in_children); 551 // signal(SIGCHLD, check_errors_in_children);
552 552
553 str = NULL; 553 str = rpm_getstr0(TAG_PAYLOADCOMPRESSOR);
554 if (ENABLE_FEATURE_SEAMLESS_LZMA 554 if (ENABLE_FEATURE_SEAMLESS_LZMA
555 && (str = rpm_getstr0(TAG_PAYLOADCOMPRESSOR)) != NULL 555 && str != NULL
556 && strcmp(str, "lzma") == 0 556 && strcmp(str, "lzma") == 0
557 ) { 557 ) {
558 // lzma compression can't be detected 558 // lzma compression can't be detected
diff --git a/archival/tar.c b/archival/tar.c
index 382c7733c..2b8b368ad 100644
--- a/archival/tar.c
+++ b/archival/tar.c
@@ -433,7 +433,7 @@ static int writeTarHeader(struct TarBallInfo *tbInfo,
433 /* GNU "tar cvvf" prints "extended" listing a-la "ls -l" */ 433 /* GNU "tar cvvf" prints "extended" listing a-la "ls -l" */
434 /* We don't have such excesses here: for us "v" == "vv" */ 434 /* We don't have such excesses here: for us "v" == "vv" */
435 /* '/' is probably a GNUism */ 435 /* '/' is probably a GNUism */
436 fprintf(vbFd, "%s%s\n", header_name, 436 fprintf(vbFd, "%s%s\n", printable_string(header_name),
437 S_ISDIR(statbuf->st_mode) ? "/" : ""); 437 S_ISDIR(statbuf->st_mode) ? "/" : "");
438 } 438 }
439 439
diff --git a/coreutils/cp.c b/coreutils/cp.c
index 961de5b42..85af104e6 100644
--- a/coreutils/cp.c
+++ b/coreutils/cp.c
@@ -29,6 +29,11 @@
29//config: bool "Enable --reflink[=auto]" 29//config: bool "Enable --reflink[=auto]"
30//config: default y 30//config: default y
31//config: depends on FEATURE_CP_LONG_OPTIONS 31//config: depends on FEATURE_CP_LONG_OPTIONS
32//config:
33//config:config FEATURE_CP_SPARSE
34//config: bool "Enable --sparse=WHEN"
35//config: default y
36//config: depends on FEATURE_CP_LONG_OPTIONS
32 37
33//applet:IF_CP(APPLET_NOEXEC(cp, cp, BB_DIR_BIN, BB_SUID_DROP, cp)) 38//applet:IF_CP(APPLET_NOEXEC(cp, cp, BB_DIR_BIN, BB_SUID_DROP, cp))
34/* NOEXEC despite cases when it can be a "runner" (cp -r LARGE_DIR NEW_DIR) */ 39/* NOEXEC despite cases when it can be a "runner" (cp -r LARGE_DIR NEW_DIR) */
@@ -108,6 +113,8 @@
108#include "libbb.h" 113#include "libbb.h"
109#include "libcoreutils/coreutils.h" 114#include "libcoreutils/coreutils.h"
110 115
116#define DBG_OPTION_PARSING 0
117
111/* This is a NOEXEC applet. Be very careful! */ 118/* This is a NOEXEC applet. Be very careful! */
112 119
113int cp_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 120int cp_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
@@ -130,6 +137,9 @@ int cp_main(int argc, char **argv)
130# if ENABLE_FEATURE_CP_REFLINK 137# if ENABLE_FEATURE_CP_REFLINK
131 char *reflink = NULL; 138 char *reflink = NULL;
132# endif 139# endif
140# if ENABLE_FEATURE_CP_SPARSE
141 char *sparse = NULL;
142# endif
133 flags = getopt32long(argv, "^" 143 flags = getopt32long(argv, "^"
134 FILEUTILS_CP_OPTSTR 144 FILEUTILS_CP_OPTSTR
135 "\0" 145 "\0"
@@ -159,11 +169,19 @@ int cp_main(int argc, char **argv)
159# if ENABLE_FEATURE_CP_REFLINK 169# if ENABLE_FEATURE_CP_REFLINK
160 "reflink\0" Optional_argument "\xfd" 170 "reflink\0" Optional_argument "\xfd"
161# endif 171# endif
172# if ENABLE_FEATURE_CP_SPARSE
173 "sparse\0" Required_argument "\xfc"
174# endif
162 , &last 175 , &last
163# if ENABLE_FEATURE_CP_REFLINK 176# if ENABLE_FEATURE_CP_REFLINK
164 , &reflink 177 , &reflink
165# endif 178# endif
179# if ENABLE_FEATURE_CP_SPARSE
180 // NOP for now
181 , &sparse
182# endif
166 ); 183 );
184
167# if ENABLE_FEATURE_CP_REFLINK 185# if ENABLE_FEATURE_CP_REFLINK
168 BUILD_BUG_ON((int)OPT_reflink != (int)FILEUTILS_REFLINK); 186 BUILD_BUG_ON((int)OPT_reflink != (int)FILEUTILS_REFLINK);
169 if (flags & FILEUTILS_REFLINK) { 187 if (flags & FILEUTILS_REFLINK) {
@@ -175,6 +193,16 @@ int cp_main(int argc, char **argv)
175 bb_show_usage(); 193 bb_show_usage();
176 } 194 }
177# endif 195# endif
196# if DBG_OPTION_PARSING
197 bb_error_msg("flags: 0x%08x", flags);
198# define showopt(o) bb_error_msg("flags & %s(%x):\t%x", #o, o, flags & o);
199 showopt(FILEUTILS_RMDEST );
200 showopt(OPT_parents );
201 showopt(OPT_reflink );
202 showopt(FILEUTILS_REFLINK_ALWAYS);
203 return 0;
204# undef showopt
205# endif
178#else 206#else
179 flags = getopt32(argv, "^" 207 flags = getopt32(argv, "^"
180 FILEUTILS_CP_OPTSTR 208 FILEUTILS_CP_OPTSTR
diff --git a/coreutils/id.c b/coreutils/id.c
index 0e1286294..050487ecc 100644
--- a/coreutils/id.c
+++ b/coreutils/id.c
@@ -158,7 +158,7 @@ int id_main(int argc UNUSED_PARAM, char **argv)
158 const char *prefix; 158 const char *prefix;
159 const char *username; 159 const char *username;
160#if ENABLE_SELINUX 160#if ENABLE_SELINUX
161 security_context_t scontext = NULL; 161 char *scontext = NULL;
162#endif 162#endif
163 163
164 if (ENABLE_GROUPS && (!ENABLE_ID || applet_name[0] == 'g')) { 164 if (ENABLE_GROUPS && (!ENABLE_ID || applet_name[0] == 'g')) {
diff --git a/coreutils/install.c b/coreutils/install.c
index 00f8be87e..728ea7126 100644
--- a/coreutils/install.c
+++ b/coreutils/install.c
@@ -73,7 +73,7 @@ static const char install_longopts[] ALIGN1 =
73static void setdefaultfilecon(const char *path) 73static void setdefaultfilecon(const char *path)
74{ 74{
75 struct stat s; 75 struct stat s;
76 security_context_t scontext = NULL; 76 char *scontext = NULL;
77 77
78 if (!is_selinux_enabled()) { 78 if (!is_selinux_enabled()) {
79 return; 79 return;
@@ -119,7 +119,7 @@ int install_main(int argc, char **argv)
119 int ret = EXIT_SUCCESS; 119 int ret = EXIT_SUCCESS;
120 int isdir; 120 int isdir;
121#if ENABLE_SELINUX 121#if ENABLE_SELINUX
122 security_context_t scontext; 122 char *scontext;
123 bool use_default_selinux_context = 1; 123 bool use_default_selinux_context = 1;
124#endif 124#endif
125 enum { 125 enum {
diff --git a/coreutils/libcoreutils/getopt_mk_fifo_nod.c b/coreutils/libcoreutils/getopt_mk_fifo_nod.c
index dafe70edf..938adef18 100644
--- a/coreutils/libcoreutils/getopt_mk_fifo_nod.c
+++ b/coreutils/libcoreutils/getopt_mk_fifo_nod.c
@@ -26,7 +26,7 @@ mode_t FAST_FUNC getopt_mk_fifo_nod(char **argv)
26 mode_t mode = 0666; 26 mode_t mode = 0666;
27 char *smode = NULL; 27 char *smode = NULL;
28#if ENABLE_SELINUX 28#if ENABLE_SELINUX
29 security_context_t scontext; 29 char *scontext;
30#endif 30#endif
31 int opt; 31 int opt;
32 opt = getopt32(argv, "m:" IF_SELINUX("Z:"), &smode IF_SELINUX(,&scontext)); 32 opt = getopt32(argv, "m:" IF_SELINUX("Z:"), &smode IF_SELINUX(,&scontext));
diff --git a/coreutils/ls.c b/coreutils/ls.c
index 2fed317c6..20385bd32 100644
--- a/coreutils/ls.c
+++ b/coreutils/ls.c
@@ -319,7 +319,7 @@ struct dnode {
319 const char *name; /* usually basename, but think "ls -l dir/file" */ 319 const char *name; /* usually basename, but think "ls -l dir/file" */
320 const char *fullname; /* full name (usable for stat etc) */ 320 const char *fullname; /* full name (usable for stat etc) */
321 struct dnode *dn_next; /* for linked list */ 321 struct dnode *dn_next; /* for linked list */
322 IF_SELINUX(security_context_t sid;) 322 IF_SELINUX(char *sid;)
323 smallint fname_allocated; 323 smallint fname_allocated;
324 324
325 /* Used to avoid re-doing [l]stat at printout stage 325 /* Used to avoid re-doing [l]stat at printout stage
diff --git a/coreutils/mkdir.c b/coreutils/mkdir.c
index e074c3561..6ba4141d3 100644
--- a/coreutils/mkdir.c
+++ b/coreutils/mkdir.c
@@ -57,7 +57,7 @@ int mkdir_main(int argc UNUSED_PARAM, char **argv)
57 unsigned opt; 57 unsigned opt;
58 char *smode; 58 char *smode;
59#if ENABLE_SELINUX 59#if ENABLE_SELINUX
60 security_context_t scontext; 60 char *scontext;
61#endif 61#endif
62 62
63 opt = getopt32long(argv, "m:pv" IF_SELINUX("Z:"), 63 opt = getopt32long(argv, "m:pv" IF_SELINUX("Z:"),
diff --git a/coreutils/sort.c b/coreutils/sort.c
index 949948203..0ed62770b 100644
--- a/coreutils/sort.c
+++ b/coreutils/sort.c
@@ -168,13 +168,18 @@ static char *get_key(char *str, struct sort_key *key, int flags)
168 /* Loop through fields */ 168 /* Loop through fields */
169 else { 169 else {
170 unsigned char ch = 0; 170 unsigned char ch = 0;
171 /* -kSTART,N.ENDCHAR: stop at the start of field N instead
172 * of its end, ENDCHAR below is an offset from there */
173 unsigned fields = key->range[2*j] + j;
174 if (j && key->range[3])
175 fields--;
171 176
172 end = 0; 177 end = 0;
173 for (i = 1; i < key->range[2*j] + j; i++) { 178 for (i = 1; i < fields; i++) {
174 if (key_separator) { 179 if (key_separator) {
175 /* Skip body of key and separator */ 180 /* Skip body of key and separator */
176 while ((ch = str[end]) != '\0') { 181 while ((ch = str[end]) != '\0') {
177 end++; 182 end++;
178 if (ch == key_separator) 183 if (ch == key_separator)
179 break; 184 break;
180 } 185 }
@@ -191,9 +196,9 @@ static char *get_key(char *str, struct sort_key *key, int flags)
191 } 196 }
192 } 197 }
193 /* Remove last delim: "abc:def:" => "abc:def" */ 198 /* Remove last delim: "abc:def:" => "abc:def" */
194 if (j && ch) { 199 if (j && ch && !key->range[3]) {
195 //if (str[end-1] != key_separator) 200 //if (str[end-1] != key_separator)
196 // bb_error_msg(_and_die("BUG! " 201 // bb_error_msg_and_die("BUG! "
197 // "str[start:%d,end:%d]:'%.*s'", 202 // "str[start:%d,end:%d]:'%.*s'",
198 // start, end, (int)(end-start), &str[start]); 203 // start, end, (int)(end-start), &str[start]);
199 end--; 204 end--;
@@ -208,9 +213,11 @@ static char *get_key(char *str, struct sort_key *key, int flags)
208 /* Strip trailing whitespace if necessary */ 213 /* Strip trailing whitespace if necessary */
209 if (flags & FLAG_bb) 214 if (flags & FLAG_bb)
210 while (end > start && isspace(str[end-1])) end--; 215 while (end > start && isspace(str[end-1])) end--;
211 /* -kSTART,N.ENDCHAR: honor ENDCHAR (1-based) */ 216 /* -kSTART,N.ENDCHAR: honor ENDCHAR (1-based), counted from the
217 * start of field N, which the loop above stopped at
218 */
212 if (key->range[3]) { 219 if (key->range[3]) {
213 end = key->range[3]; 220 end += key->range[3];
214 if (end > len) end = len; 221 if (end > len) end = len;
215 } 222 }
216 /* -kN.STARTCHAR[,...]: honor STARTCHAR (1-based) */ 223 /* -kN.STARTCHAR[,...]: honor STARTCHAR (1-based) */
diff --git a/coreutils/stat.c b/coreutils/stat.c
index fc9597ddb..c2f5b1ca1 100644
--- a/coreutils/stat.c
+++ b/coreutils/stat.c
@@ -249,53 +249,84 @@ static void strcatc(char *str, char c)
249 str[len] = '\0'; 249 str[len] = '\0';
250} 250}
251 251
252static void printfs(char *pformat, const char *msg) 252/* printf is a vararg function, on some arches varargs
253 * require more code, increasing code size win
254 * from factoring out common uses of printf into
255 * non-vararg functions.
256 */
257static void printf_s(char *pformat, const char *msg)
253{ 258{
254 strcatc(pformat, 's'); 259 strcatc(pformat, 's');
255 printf(pformat, msg); 260 printf(pformat, msg);
256} 261}
257 262
263static void printf_lu(char *pformat, unsigned long v)
264{
265 strcat(pformat, "lu");
266 printf(pformat, v);
267}
268
269static void printf_llu(char *pformat, unsigned long long v)
270{
271 strcat(pformat, "llu");
272 printf(pformat, v);
273}
274
275static void printf_lx(char *pformat, unsigned long v)
276{
277 strcat(pformat, "lx");
278 printf(pformat, v);
279}
280
281static void printf_llx(char *pformat, unsigned long long v)
282{
283 strcat(pformat, "llx");
284 printf(pformat, v);
285}
286
287static void printf_time_t(char *pformat, time_t val)
288{
289#define TYPE_SIGNED(t) ((t) -1 < (t) 0)
290 if (TYPE_SIGNED(time_t)) {
291 strcat(pformat, "lld");
292 printf(pformat, (long long) val);
293 } else {
294 printf_llu(pformat, val);
295 }
296}
297
258#if ENABLE_FEATURE_STAT_FILESYSTEM 298#if ENABLE_FEATURE_STAT_FILESYSTEM
259/* print statfs info */ 299/* print statfs info */
260static void FAST_FUNC print_statfs(char *pformat, const char m, 300static void FAST_FUNC print_statfs(char *pformat, const char m,
261 const char *const filename, const void *data 301 const char *const filename, const void *data
262 IF_SELINUX(, security_context_t scontext)) 302 IF_SELINUX(, char *scontext))
263{ 303{
264 const struct statfs *statfsbuf = data; 304 const struct statfs *statfsbuf = data;
265 if (m == 'n') { 305 if (m == 'n') {
266 printfs(pformat, filename); 306 printf_s(pformat, filename);
267 } else if (m == 'i') { 307 } else if (m == 'i') {
268 strcat(pformat, "llx"); 308 printf_llx(pformat, get_f_fsid(statfsbuf));
269 printf(pformat, get_f_fsid(statfsbuf));
270 } else if (m == 'l') { 309 } else if (m == 'l') {
271 strcat(pformat, "lu"); 310 printf_lu(pformat, statfsbuf->f_namelen);
272 printf(pformat, (unsigned long) statfsbuf->f_namelen);
273 } else if (m == 't') { 311 } else if (m == 't') {
274 strcat(pformat, "lx"); 312 printf_lx(pformat, statfsbuf->f_type); /* no equiv */
275 printf(pformat, (unsigned long) statfsbuf->f_type); /* no equiv */
276 } else if (m == 'T') { 313 } else if (m == 'T') {
277 printfs(pformat, human_fstype(statfsbuf->f_type)); 314 printf_s(pformat, human_fstype(statfsbuf->f_type));
278 } else if (m == 'b') { 315 } else if (m == 'b') {
279 strcat(pformat, "llu"); 316 printf_llu(pformat, statfsbuf->f_blocks);
280 printf(pformat, (unsigned long long) statfsbuf->f_blocks);
281 } else if (m == 'f') { 317 } else if (m == 'f') {
282 strcat(pformat, "llu"); 318 printf_llu(pformat, statfsbuf->f_bfree);
283 printf(pformat, (unsigned long long) statfsbuf->f_bfree);
284 } else if (m == 'a') { 319 } else if (m == 'a') {
285 strcat(pformat, "llu"); 320 printf_llu(pformat, statfsbuf->f_bavail);
286 printf(pformat, (unsigned long long) statfsbuf->f_bavail);
287 } else if (m == 's' || m == 'S') { 321 } else if (m == 's' || m == 'S') {
288 strcat(pformat, "lu"); 322 printf_lu(pformat, statfsbuf->f_bsize);
289 printf(pformat, (unsigned long) statfsbuf->f_bsize);
290 } else if (m == 'c') { 323 } else if (m == 'c') {
291 strcat(pformat, "llu"); 324 printf_llu(pformat, statfsbuf->f_files);
292 printf(pformat, (unsigned long long) statfsbuf->f_files);
293 } else if (m == 'd') { 325 } else if (m == 'd') {
294 strcat(pformat, "llu"); 326 printf_llu(pformat, statfsbuf->f_ffree);
295 printf(pformat, (unsigned long long) statfsbuf->f_ffree);
296# if ENABLE_SELINUX 327# if ENABLE_SELINUX
297 } else if (m == 'C' && (option_mask32 & OPT_SELINUX)) { 328 } else if (m == 'C' && (option_mask32 & OPT_SELINUX)) {
298 printfs(pformat, scontext); 329 printf_s(pformat, scontext);
299# endif 330# endif
300 } else { 331 } else {
301 strcatc(pformat, 'c'); 332 strcatc(pformat, 'c');
@@ -307,15 +338,14 @@ static void FAST_FUNC print_statfs(char *pformat, const char m,
307/* print stat info */ 338/* print stat info */
308static void FAST_FUNC print_stat(char *pformat, const char m, 339static void FAST_FUNC print_stat(char *pformat, const char m,
309 const char *const filename, const void *data 340 const char *const filename, const void *data
310 IF_SELINUX(, security_context_t scontext)) 341 IF_SELINUX(, char *scontext))
311{ 342{
312#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
313 struct stat *statbuf = (struct stat *) data; 343 struct stat *statbuf = (struct stat *) data;
314 struct passwd *pw_ent; 344 struct passwd *pw_ent;
315 struct group *gw_ent; 345 struct group *gw_ent;
316 346
317 if (m == 'n') { 347 if (m == 'n') {
318 printfs(pformat, filename); 348 printf_s(pformat, filename);
319 } else if (m == 'N') { 349 } else if (m == 'N') {
320 strcatc(pformat, 's'); 350 strcatc(pformat, 's');
321 if (S_ISLNK(statbuf->st_mode)) { 351 if (S_ISLNK(statbuf->st_mode)) {
@@ -328,78 +358,60 @@ static void FAST_FUNC print_stat(char *pformat, const char m,
328 printf(pformat, filename); 358 printf(pformat, filename);
329 } 359 }
330 } else if (m == 'd') { 360 } else if (m == 'd') {
331 strcat(pformat, "llu"); 361 printf_llu(pformat, statbuf->st_dev);
332 printf(pformat, (unsigned long long) statbuf->st_dev);
333 } else if (m == 'D') { 362 } else if (m == 'D') {
334 strcat(pformat, "llx"); 363 printf_llx(pformat, statbuf->st_dev);
335 printf(pformat, (unsigned long long) statbuf->st_dev);
336 } else if (m == 'i') { 364 } else if (m == 'i') {
337 strcat(pformat, "llu"); 365 printf_llu(pformat, statbuf->st_ino);
338 printf(pformat, (unsigned long long) statbuf->st_ino);
339 } else if (m == 'a') { 366 } else if (m == 'a') {
340 strcat(pformat, "lo"); 367 strcat(pformat, "lo");
341 printf(pformat, (unsigned long) (statbuf->st_mode & (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO))); 368 printf(pformat, (unsigned long) (statbuf->st_mode & (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO)));
342 } else if (m == 'A') { 369 } else if (m == 'A') {
343 char modestr[12]; 370 char modestr[12];
344 printfs(pformat, bb_mode_string(modestr, statbuf->st_mode)); 371 printf_s(pformat, bb_mode_string(modestr, statbuf->st_mode));
345 } else if (m == 'f') { 372 } else if (m == 'f') {
346 strcat(pformat, "lx"); 373 printf_lx(pformat, statbuf->st_mode);
347 printf(pformat, (unsigned long) statbuf->st_mode);
348 } else if (m == 'F') { 374 } else if (m == 'F') {
349 printfs(pformat, file_type(statbuf)); 375 printf_s(pformat, file_type(statbuf));
350 } else if (m == 'h') { 376 } else if (m == 'h') {
351 strcat(pformat, "lu"); 377 printf_lu(pformat, statbuf->st_nlink);
352 printf(pformat, (unsigned long) statbuf->st_nlink);
353 } else if (m == 'u') { 378 } else if (m == 'u') {
354 strcat(pformat, "lu"); 379 printf_lu(pformat, statbuf->st_uid);
355 printf(pformat, (unsigned long) statbuf->st_uid);
356 } else if (m == 'U') { 380 } else if (m == 'U') {
357 pw_ent = getpwuid(statbuf->st_uid); 381 pw_ent = getpwuid(statbuf->st_uid);
358 printfs(pformat, (pw_ent != NULL) ? pw_ent->pw_name : "UNKNOWN"); 382 printf_s(pformat, (pw_ent != NULL) ? pw_ent->pw_name : "UNKNOWN");
359 } else if (m == 'g') { 383 } else if (m == 'g') {
360 strcat(pformat, "lu"); 384 printf_lu(pformat, statbuf->st_gid);
361 printf(pformat, (unsigned long) statbuf->st_gid);
362 } else if (m == 'G') { 385 } else if (m == 'G') {
363 gw_ent = getgrgid(statbuf->st_gid); 386 gw_ent = getgrgid(statbuf->st_gid);
364 printfs(pformat, (gw_ent != NULL) ? gw_ent->gr_name : "UNKNOWN"); 387 printf_s(pformat, (gw_ent != NULL) ? gw_ent->gr_name : "UNKNOWN");
365 } else if (m == 't') { 388 } else if (m == 't') {
366 strcat(pformat, "lx"); 389 printf_lx(pformat, major(statbuf->st_rdev));
367 printf(pformat, (unsigned long) major(statbuf->st_rdev));
368 } else if (m == 'T') { 390 } else if (m == 'T') {
369 strcat(pformat, "lx"); 391 printf_lx(pformat, minor(statbuf->st_rdev));
370 printf(pformat, (unsigned long) minor(statbuf->st_rdev));
371 } else if (m == 's') { 392 } else if (m == 's') {
372 strcat(pformat, "llu"); 393 printf_llu(pformat, statbuf->st_size);
373 printf(pformat, (unsigned long long) statbuf->st_size);
374 } else if (m == 'B') { 394 } else if (m == 'B') {
375 strcat(pformat, "lu"); 395 printf_lu(pformat, 512); //ST_NBLOCKSIZE
376 printf(pformat, (unsigned long) 512); //ST_NBLOCKSIZE
377 } else if (m == 'b') { 396 } else if (m == 'b') {
378 strcat(pformat, "llu"); 397 printf_llu(pformat, statbuf->st_blocks);
379 printf(pformat, (unsigned long long) statbuf->st_blocks);
380 } else if (m == 'o') { 398 } else if (m == 'o') {
381 strcat(pformat, "lu"); 399 printf_lu(pformat, statbuf->st_blksize);
382 printf(pformat, (unsigned long) statbuf->st_blksize);
383 } else if (m == 'x') { 400 } else if (m == 'x') {
384 printfs(pformat, human_time(&statbuf->st_atim)); 401 printf_s(pformat, human_time(&statbuf->st_atim));
385 } else if (m == 'X') { 402 } else if (m == 'X') {
386 strcat(pformat, TYPE_SIGNED(time_t) ? "ld" : "lu"); 403 printf_time_t(pformat, statbuf->st_atime);
387 /* note: (unsigned long) would be wrong:
388 * imagine (unsigned long64)int32 */
389 printf(pformat, (long) statbuf->st_atime);
390 } else if (m == 'y') { 404 } else if (m == 'y') {
391 printfs(pformat, human_time(&statbuf->st_mtim)); 405 printf_s(pformat, human_time(&statbuf->st_mtim));
392 } else if (m == 'Y') { 406 } else if (m == 'Y') {
393 strcat(pformat, TYPE_SIGNED(time_t) ? "ld" : "lu"); 407 printf_time_t(pformat, statbuf->st_mtime);
394 printf(pformat, (long) statbuf->st_mtime);
395 } else if (m == 'z') { 408 } else if (m == 'z') {
396 printfs(pformat, human_time(&statbuf->st_ctim)); 409 printf_s(pformat, human_time(&statbuf->st_ctim));
397 } else if (m == 'Z') { 410 } else if (m == 'Z') {
398 strcat(pformat, TYPE_SIGNED(time_t) ? "ld" : "lu"); 411 printf_time_t(pformat, statbuf->st_ctime);
399 printf(pformat, (long) statbuf->st_ctime);
400# if ENABLE_SELINUX 412# if ENABLE_SELINUX
401 } else if (m == 'C' && (option_mask32 & OPT_SELINUX)) { 413 } else if (m == 'C' && (option_mask32 & OPT_SELINUX)) {
402 printfs(pformat, scontext); 414 printf_s(pformat, scontext);
403# endif 415# endif
404 } else { 416 } else {
405 strcatc(pformat, 'c'); 417 strcatc(pformat, 'c');
@@ -409,9 +421,9 @@ static void FAST_FUNC print_stat(char *pformat, const char m,
409 421
410static void print_it(const char *masterformat, 422static void print_it(const char *masterformat,
411 const char *filename, 423 const char *filename,
412 void FAST_FUNC (*print_func)(char*, char, const char*, const void* IF_SELINUX(, security_context_t scontext)), 424 void FAST_FUNC (*print_func)(char*, char, const char*, const void* IF_SELINUX(, char *scontext)),
413 const void *data 425 const void *data
414 IF_SELINUX(, security_context_t scontext)) 426 IF_SELINUX(, char *scontext))
415{ 427{
416 /* Create a working copy of the format string */ 428 /* Create a working copy of the format string */
417 char *format = xstrdup(masterformat); 429 char *format = xstrdup(masterformat);
@@ -476,7 +488,7 @@ static bool do_statfs(const char *filename, const char *format)
476 const char *format; 488 const char *format;
477#endif 489#endif
478#if ENABLE_SELINUX 490#if ENABLE_SELINUX
479 security_context_t scontext = NULL; 491 char *scontext = NULL;
480 492
481 if (option_mask32 & OPT_SELINUX) { 493 if (option_mask32 & OPT_SELINUX) {
482 if ((option_mask32 & OPT_DEREFERENCE 494 if ((option_mask32 & OPT_DEREFERENCE
@@ -591,7 +603,7 @@ static bool do_stat(const char *filename, const char *format)
591{ 603{
592 struct stat statbuf; 604 struct stat statbuf;
593#if ENABLE_SELINUX 605#if ENABLE_SELINUX
594 security_context_t scontext = NULL; 606 char *scontext = NULL;
595 607
596 if (option_mask32 & OPT_SELINUX) { 608 if (option_mask32 & OPT_SELINUX) {
597 if ((option_mask32 & OPT_DEREFERENCE 609 if ((option_mask32 & OPT_DEREFERENCE
diff --git a/editors/awk.c b/editors/awk.c
index 8ad7f9745..89a46488f 100644
--- a/editors/awk.c
+++ b/editors/awk.c
@@ -890,24 +890,30 @@ static char *nextword(char **s)
890 return p; 890 return p;
891} 891}
892 892
893/* Note: will NOT stop at NUL (either on <NUL> or \<newline><NUL>):
894 * *s will be advanced past NUL!
895 * Make sure you always check NUL return before continuing.
896 */
893static char nextchar(char **s) 897static char nextchar(char **s)
894{ 898{
895 char c, *pps; 899 char c;
896 again: 900 again:
897 c = *(*s)++; 901 c = *(*s)++;
898 pps = *s; 902
899 if (c == '\\') 903 if (c == '\\') {
904 char *pps = *s;
900 c = bb_process_escape_sequence((const char**)s); 905 c = bb_process_escape_sequence((const char**)s);
901 /* Example awk statement: 906 /* Example awk statement:
902 * s = "abc\"def" 907 * s = "abc\"def"
903 * we must treat \" as " 908 * we must treat \" as "
904 */ 909 */
905 if (c == '\\' && *s == pps) { /* unrecognized \z? */ 910 if (c == '\\' && *s == pps) { /* unrecognized \z? */
906 c = *(*s); /* yes, fetch z */ 911 c = *(*s); /* yes, fetch z */
907 if (c) { /* advance unless z = NUL */ 912 if (c) { /* advance unless z = NUL */
908 (*s)++; 913 (*s)++;
909 if (c == '\n') /* \<newline>? eat it */ 914 if (c == '\n') /* \<newline>? eat it */
910 goto again; 915 goto again;
916 }
911 } 917 }
912 } 918 }
913 return c; 919 return c;
@@ -961,20 +967,64 @@ static double my_strtod_or_hexoct(char **pp)
961 967
962/* -------- working with variables (set/get/copy/etc) -------- */ 968/* -------- working with variables (set/get/copy/etc) -------- */
963 969
970/* Perform OFMT or CONVFMT float-to-string conversion.
971 * According to POSIX, awk's behavior is undefined if OFMT
972 * contains anything but a floating-point conversion specification.
973 * However, GNU awk 5.3.0 allows prefix and suffix: "N:%.1f!"
974 * integer formats (%d et al), %s formats.
975 * It even allows %c, but we don't implement this.
976 * GNU awk also supports %ld, %lx, we don't (yet). GNU awk doesn't support %lld.
977 */
964static const char *fmt_num(const char *format, double n) 978static const char *fmt_num(const char *format, double n)
965{ 979{
966 if (n == (long long)n) { 980 if (n == trunc(n)) {
967 snprintf(g_buf, MAXVARFMT, "%"LL_FMT"d", (long long)n); 981 /* No fractionals? Try: awk -v OFMT='R:%d!' 'BEGIN { print 2**128 }' */
982 snprintf(g_buf, MAXVARFMT, "%.0f", n);
968 } else { 983 } else {
969 const char *s = format; 984 const char *s = format;
970 char c; 985 char c;
971 986
972 do { c = *s; } while (c && *++s); 987 /* Find %SPEC in format string */
988 for (;;) {
989 s = strchr(s, '%');
990 if (!s)
991 goto print_verbatim;
992 if (s[1] != '%')
993 break;
994 s += 2; /* skip "%%" */
995 }
996 if (strchr(s + 1, '%') != NULL)
997//TODO: allow "%%"s in the suffix too?
998 goto INV_FMT; /* more than one %SPEC */
999
1000//TODO: factor out awk_printf machinery to make %d print large numbers too. Example:
1001// awk -v OFMT='R:%d!' 'BEGIN { print 184467440737095.1 }'
1002// R:184467440737095!
1003 /* Find the format letter */
1004 for (;;) {
1005 c = *++s;
1006 if (!c) /* unterminated "....%SPEC" */
1007 goto print_verbatim;
1008 if (c == '*')
1009 goto INV_FMT; /* CONVFMT/OFMT='%*f' is not allowed */
1010 if (isalpha(c))
1011 break;
1012 }
1013
973 if (strchr("diouxX", c)) { 1014 if (strchr("diouxX", c)) {
974 snprintf(g_buf, MAXVARFMT, format, (int)n); 1015 snprintf(g_buf, MAXVARFMT, format, (int)n);
975 } else if (strchr("eEfFgGaA", c)) { 1016 } else if (strchr("eEfFgGaA", c)) {
1017 print_verbatim:
976 snprintf(g_buf, MAXVARFMT, format, n); 1018 snprintf(g_buf, MAXVARFMT, format, n);
1019 } else if (c == 's') {
1020 /* GNU awk OFMT="%..s" formats number through "%.6g",
1021 * then prints string through %s:
1022 */
1023 char nbuf[sizeof(n)*3 + 12]; /* +5 should do? +12 is paranoia */
1024 sprintf(nbuf, "%.6g", n);
1025 snprintf(g_buf, MAXVARFMT, format, nbuf);
977 } else { 1026 } else {
1027 INV_FMT:
978 syntax_error(EMSG_INV_FMT); 1028 syntax_error(EMSG_INV_FMT);
979 } 1029 }
980 } 1030 }
@@ -1205,11 +1255,22 @@ static uint32_t next_token(uint32_t expected)
1205 /* it's a string */ 1255 /* it's a string */
1206 char *s = t_string = ++p; 1256 char *s = t_string = ++p;
1207 while (*p != '"') { 1257 while (*p != '"') {
1208 char *pp; 1258 char c, *pp;
1209 if (*p == '\0' || *p == '\n') 1259
1260 /* Since we need to handle \<newline><NUL>
1261 * below, we can handle ordinary NUL there as well,
1262 * instead of here. Thus commented out.
1263 */
1264 if (/* *p == '\0' || */ *p == '\n')
1210 syntax_error(EMSG_UNEXP_EOS); 1265 syntax_error(EMSG_UNEXP_EOS);
1211 pp = p; 1266 pp = p;
1212 *s++ = nextchar(&pp); 1267 c = *s++ = nextchar(&pp);
1268 /* awk 'BEGIN { print "unterminated\
1269 * '
1270 * results in NUL here after nextchar() eats \<newline>
1271 */
1272 if (c == '\0')
1273 syntax_error(EMSG_UNEXP_EOS);
1213 p = pp; 1274 p = pp;
1214 } 1275 }
1215 p++; 1276 p++;
@@ -2490,6 +2551,7 @@ static char *awk_printf(node *n, size_t *len)
2490 } 2551 }
2491 goto tail; /* append remaining string, exit loop */ 2552 goto tail; /* append remaining string, exit loop */
2492 } 2553 }
2554//TODO: GNU awk 5.3.0 also supports %ld, %lx, we don't (yet). It does not support %lld.
2493 if (isalpha(c)) 2555 if (isalpha(c))
2494 break; 2556 break;
2495 starred |= (c == '*'); 2557 starred |= (c == '*');
@@ -3313,8 +3375,7 @@ static var *evaluate(node *op, var *res)
3313 for (;;) { 3375 for (;;) {
3314 var *v = evaluate(nextarg(&op1), TMPVAR0); 3376 var *v = evaluate(nextarg(&op1), TMPVAR0);
3315 if (v->type & VF_NUMBER) { 3377 if (v->type & VF_NUMBER) {
3316 fputs(fmt_num(getvar_s(intvar[OFMT]), getvar_i(v)), 3378 fputs(fmt_num(getvar_s(intvar[OFMT]), getvar_i(v)), F);
3317 F);
3318 } else { 3379 } else {
3319 fputs(getvar_s(v), F); 3380 fputs(getvar_s(v), F);
3320 } 3381 }
diff --git a/editors/patch.c b/editors/patch.c
index 8837d1751..ee0ccd384 100644
--- a/editors/patch.c
+++ b/editors/patch.c
@@ -57,9 +57,7 @@ struct double_list {
57 struct double_list *next; 57 struct double_list *next;
58 struct double_list *prev; 58 struct double_list *prev;
59 char *data; 59 char *data;
60#if ENABLE_PLATFORM_MINGW32
61 int no_newline; 60 int no_newline;
62#endif
63}; 61};
64 62
65// Free all the elements of a linked list 63// Free all the elements of a linked list
@@ -79,11 +77,7 @@ static void dlist_free(struct double_list *list, void (*freeit)(void *data))
79static struct double_list *dlist_add(struct double_list **list, char *data) 77static struct double_list *dlist_add(struct double_list **list, char *data)
80{ 78{
81 struct double_list *llist; 79 struct double_list *llist;
82#if ENABLE_PLATFORM_MINGW32
83 struct double_list *line = xzalloc(sizeof(*line)); 80 struct double_list *line = xzalloc(sizeof(*line));
84#else
85 struct double_list *line = xmalloc(sizeof(*line));
86#endif
87 81
88 line->data = data; 82 line->data = data;
89 llist = *list; 83 llist = *list;
@@ -147,10 +141,8 @@ static void do_line(void *data)
147 141
148 if (TT.state > 1 && *dlist->data != TT.state) 142 if (TT.state > 1 && *dlist->data != TT.state)
149 fdprintf(TT.state == 2 ? 2 : TT.fileout, 143 fdprintf(TT.state == 2 ? 2 : TT.fileout,
150#if ENABLE_PLATFORM_MINGW32 144 dlist->no_newline && TT.state != 2 ? "%s" : "%s\n",
151 dlist->no_newline && TT.state != 2 ? "%s" : 145 dlist->data + (TT.state > 3 ? 1 : 0));
152#endif
153 "%s\n", dlist->data + (TT.state > 3 ? 1 : 0));
154 146
155 if (PATCH_DEBUG) fdprintf(2, "DO %d: %s\n", TT.state, dlist->data); 147 if (PATCH_DEBUG) fdprintf(2, "DO %d: %s\n", TT.state, dlist->data);
156 148
@@ -443,7 +435,6 @@ int patch_main(int argc UNUSED_PARAM, char **argv)
443 435
444 // Are we assembling a hunk? 436 // Are we assembling a hunk?
445 if (state >= 2) { 437 if (state >= 2) {
446#if ENABLE_PLATFORM_MINGW32
447 switch (*patchline) { 438 switch (*patchline) {
448 case '\\': 439 case '\\':
449 // '\ No newline at end of file' detected, mark 440 // '\ No newline at end of file' detected, mark
@@ -455,9 +446,6 @@ int patch_main(int argc UNUSED_PARAM, char **argv)
455 case ' ': 446 case ' ':
456 case '+': 447 case '+':
457 case '-': 448 case '-':
458#else
459 if (*patchline == ' ' || *patchline == '+' || *patchline == '-') {
460#endif
461 dlist_add(&TT.current_hunk, patchline); 449 dlist_add(&TT.current_hunk, patchline);
462 450
463 if (*patchline != '+') oldlen--; 451 if (*patchline != '+') oldlen--;
@@ -469,9 +457,9 @@ int patch_main(int argc UNUSED_PARAM, char **argv)
469 457
470 // If we've consumed all expected hunk lines, apply the hunk. 458 // If we've consumed all expected hunk lines, apply the hunk.
471 459
472#if ENABLE_PLATFORM_MINGW32
473 if (!oldlen && !newlen) { 460 if (!oldlen && !newlen) {
474 // Peek ahead for '\ No newline at end of file' 461 // Peek ahead for '\ No newline at end of file', mark
462 // previous line, if it exists.
475 int c = getchar(); 463 int c = getchar();
476 ungetc(c, stdin); 464 ungetc(c, stdin);
477 if (c == '\\') { 465 if (c == '\\') {
@@ -483,9 +471,6 @@ int patch_main(int argc UNUSED_PARAM, char **argv)
483 } 471 }
484 state = apply_one_hunk(); 472 state = apply_one_hunk();
485 } 473 }
486#else
487 if (!oldlen && !newlen) state = apply_one_hunk();
488#endif
489 continue; 474 continue;
490 } 475 }
491 fail_hunk(); 476 fail_hunk();
diff --git a/editors/vi.c b/editors/vi.c
index e3ad120f6..5c0c5c30b 100644
--- a/editors/vi.c
+++ b/editors/vi.c
@@ -2842,21 +2842,25 @@ static void setops(char *args, int flg_no)
2842static char *expand_args(char *args) 2842static char *expand_args(char *args)
2843{ 2843{
2844 char *s; 2844 char *s;
2845 const char *replace;
2846 2845
2847 args = xstrdup(args); 2846 args = xstrdup(args);
2848 for (s = args; *s; s++) { 2847 for (s = args; *s; s++) {
2848 const char *replace;
2849 unsigned n; 2849 unsigned n;
2850 2850
2851//NB: vim 9.2 replaces "\%" with "%" _over entire string_,
2852//then replaces "\c" with "c". Result:
2853// "\%" is "%" (ok),
2854// "\\" is "\" (ok),
2855// "\\%" is "\%" (!!!), not "\CURFILE" as you would think.
2856//We don't do that. Should we?
2851 if (*s == '%') { 2857 if (*s == '%') {
2852 replace = current_filename; 2858 replace = current_filename;
2853 } else if (*s == '#') { 2859 } else if (*s == '#') {
2854 replace = alt_filename; 2860 replace = alt_filename;
2855 } else { 2861 } else {
2856 if (*s == '\\' && s[1] != '\0') { 2862 if (*s == '\\' && s[1] != '\0') {
2857 char *t; 2863 overlapping_strcpy(s, s + 1);
2858 for (t = s; *t; t++)
2859 *t = t[1];
2860 s++; 2864 s++;
2861 } 2865 }
2862 continue; 2866 continue;
diff --git a/findutils/find.c b/findutils/find.c
index 0a8a82e6c..b29ca234d 100644
--- a/findutils/find.c
+++ b/findutils/find.c
@@ -467,7 +467,7 @@ IF_FEATURE_FIND_INUM( ACTS(inum, ino_t inode_num;))
467IF_FEATURE_FIND_SAMEFILE(ACTS(samefile, ino_t inode_num; dev_t device;)) 467IF_FEATURE_FIND_SAMEFILE(ACTS(samefile, ino_t inode_num; dev_t device;))
468IF_FEATURE_FIND_USER( ACTS(user, uid_t uid;)) 468IF_FEATURE_FIND_USER( ACTS(user, uid_t uid;))
469IF_FEATURE_FIND_SIZE( ACTS(size, char size_char; off_t size;)) 469IF_FEATURE_FIND_SIZE( ACTS(size, char size_char; off_t size;))
470IF_FEATURE_FIND_CONTEXT(ACTS(context, security_context_t context;)) 470IF_FEATURE_FIND_CONTEXT(ACTS(context, char *context;))
471IF_FEATURE_FIND_PAREN( ACTS(paren, action ***subexpr;)) 471IF_FEATURE_FIND_PAREN( ACTS(paren, action ***subexpr;))
472IF_FEATURE_FIND_PRUNE( ACTS(prune)) 472IF_FEATURE_FIND_PRUNE( ACTS(prune))
473IF_FEATURE_FIND_QUIT( ACTS(quit)) 473IF_FEATURE_FIND_QUIT( ACTS(quit))
@@ -983,7 +983,7 @@ ACTF(empty)
983#if ENABLE_FEATURE_FIND_CONTEXT 983#if ENABLE_FEATURE_FIND_CONTEXT
984ACTF(context) 984ACTF(context)
985{ 985{
986 security_context_t con; 986 char *con;
987 int rc; 987 int rc;
988 988
989 if (G.recurse_flags & ACTION_FOLLOWLINKS) { 989 if (G.recurse_flags & ACTION_FOLLOWLINKS) {
diff --git a/findutils/grep.c b/findutils/grep.c
index f6d0a73f4..99220f603 100644
--- a/findutils/grep.c
+++ b/findutils/grep.c
@@ -73,10 +73,10 @@
73//usage: "\n -c Show only count of matching lines" 73//usage: "\n -c Show only count of matching lines"
74//usage: "\n -o Show only the matching part of line" 74//usage: "\n -o Show only the matching part of line"
75//usage: "\n -q Quiet. Return 0 if PATTERN is found, 1 otherwise" 75//usage: "\n -q Quiet. Return 0 if PATTERN is found, 1 otherwise"
76//usage: "\n -v Select non-matching lines"
77//usage: "\n -s Suppress open and read errors" 76//usage: "\n -s Suppress open and read errors"
78//usage: "\n -r Recurse" 77//usage: "\n -r Recurse"
79//usage: "\n -R Recurse and dereference symlinks" 78//usage: "\n -R Recurse and dereference symlinks"
79//usage: "\n -v Select non-matching lines"
80//usage: "\n -i Ignore case" 80//usage: "\n -i Ignore case"
81//usage: "\n -w Match whole words only" 81//usage: "\n -w Match whole words only"
82//usage: "\n -x Match whole lines only" 82//usage: "\n -x Match whole lines only"
@@ -105,6 +105,58 @@
105//usage:#define fgrep_trivial_usage NOUSAGE_STR 105//usage:#define fgrep_trivial_usage NOUSAGE_STR
106//usage:#define fgrep_full_usage "" 106//usage:#define fgrep_full_usage ""
107 107
108// GNU grep 3.7 options:
109// s:short option supported by our code
110// S:short option "supported" by ignoring it
111// l:long option supported
112// .:not supported
113// s. | -E, --extended-regexp
114// s. | -F, --fixed-strings
115// .. | -G, --basic-regexp: Interpret PATTERNS as basic regular expressions (this is the default)
116// .. | -P, --perl-regexp
117// s. | -e PATTERNS, --regexp=PATTERNS
118// s. | -f FILE, --file=FILE
119// s. | -i, --ignore-case (-y is an obsolete synonym)
120// . | --no-ignore-case
121// s. | -v, --invert-match
122// s. | -w, --word-regexp
123// s. | -x, --line-regexp
124// s. | -c, --count
125// l. | --color[=WHEN], --colour[=WHEN]
126// s. | -L, --files-without-match
127// s. | -l, --files-with-matches
128// s. | -m NUM, --max-count=NUM
129// s. | -o, --only-matching
130// sl.| -q, --quiet, --silent
131// s. | -s, --no-messages
132// .. | -b, --byte-offset
133// s. | -H, --with-filename
134// s. | -h, --no-filename
135// . | --label=LABEL: Display input coming from standard input as input coming from file LABEL
136// s. | -n, --line-number
137// .. | -T, --initial-tab
138// .. | -Z, --null: Output zero byte (the ASCII NUL character) instead of the character that normally follows filename
139// s. | -A NUM, --after-context=NUM
140// s. | -B NUM, --before-context=NUM
141// s. | -C NUM, --context=NUM
142// . | -NUM: same as -C NUM
143// . | --group-separator=SEP: When -A, -B, or -C are in use, print SEP instead of -- between groups of lines
144// . | --no-group-separator: When -A, -B, or -C are in use, do not print a separator between groups of lines
145// s. | -a, --text
146// . | --binary-files=TYPE
147// S | -I: Process binary files as if they did not contain matching data (equivalent to --binary-files=without-match)
148// .. | -D ACTION, --devices=ACTION
149// .. | -d ACTION, --directories=ACTION
150// . | --exclude=GLOB: Skip any file with a name suffix that matches the pattern GLOB
151// . | --exclude-from=FILE: Skip files whose base name matches any of the file-name globs read from FILE
152// . | --exclude-dir=GLOB: Skip any directory with a name suffix that matches the pattern GLOB
153// . | --include=GLOB: Search only files whose base name matches GLOB
154// s. | -r, --recursive
155// s. | -R, --dereference-recursive
156// . | --line-buffered
157// .. | -U, --binary
158// s. | -z, --null-data
159
108/* -e,-f are lists; -m,-A,-B,-C have numeric param */ 160/* -e,-f are lists; -m,-A,-B,-C have numeric param */
109#define OPTSTR_GREP \ 161#define OPTSTR_GREP \
110 "lnqvscFiHhe:*f:*LorRm:+wx" \ 162 "lnqvscFiHhe:*f:*LorRm:+wx" \
@@ -713,22 +765,30 @@ int grep_main(int argc UNUSED_PARAM, char **argv)
713#if ENABLE_FEATURE_GREP_CONTEXT 765#if ENABLE_FEATURE_GREP_CONTEXT
714 int Copt, opts; 766 int Copt, opts;
715#endif 767#endif
768#if ENABLE_LONG_OPTS
769 static const char grep_longopts[] ALIGN1 =
770 "quiet\0" No_argument "q"
771 "color\0" Optional_argument "\xff"
772 ;
773# define GETOPT32 getopt32long
774#else
775# define GETOPT32 getopt32
776#endif
716 INIT_G(); 777 INIT_G();
717 778
718 /* For grep, exitcode of 1 is "not found". Other errors are 2: */ 779 /* For grep, exitcode of 1 is "not found". Other errors are 2: */
719 xfunc_error_retval = 2; 780 xfunc_error_retval = 2;
720 781
721 /* do normal option parsing */
722#if ENABLE_FEATURE_GREP_CONTEXT 782#if ENABLE_FEATURE_GREP_CONTEXT
723 /* -H unsets -h; -C unsets -A,-B */ 783 /* -H unsets -h; -C unsets -A,-B */
724 opts = getopt32long(argv, "^" 784 opts = GETOPT32(argv, "^"
725 OPTSTR_GREP 785 OPTSTR_GREP
726 "\0" 786 "\0"
727 "H-h:C-AB", 787 "H-h:C-AB",
728 "color\0" Optional_argument "\xff", 788 IF_LONG_OPTS(grep_longopts,)
729 &pattern_head, &fopt, &max_matches, 789 &pattern_head, &fopt, &max_matches,
730 &lines_after, &lines_before, &Copt 790 &lines_after, &lines_before, &Copt
731 , NULL 791 IF_LONG_OPTS(, NULL)
732 ); 792 );
733 793
734 if (opts & OPT_C) { 794 if (opts & OPT_C) {
@@ -753,8 +813,11 @@ int grep_main(int argc UNUSED_PARAM, char **argv)
753 } 813 }
754#else 814#else
755 /* with auto sanity checks */ 815 /* with auto sanity checks */
756 getopt32(argv, "^" OPTSTR_GREP "\0" "H-h:c-n:q-n:l-n:", // why trailing ":"? 816 GETOPT32(argv, "^" OPTSTR_GREP "\0" "H-h:c-n:q-n:l-n",
757 &pattern_head, &fopt, &max_matches); 817 IF_LONG_OPTS(grep_longopts,)
818 &pattern_head, &fopt, &max_matches
819 IF_LONG_OPTS(, NULL)
820 );
758#endif 821#endif
759 invert_search = ((option_mask32 & OPT_v) != 0); /* 0 | 1 */ 822 invert_search = ((option_mask32 & OPT_v) != 0); /* 0 | 1 */
760 823
diff --git a/include/bb_archive.h b/include/bb_archive.h
index 54e3eb6c3..c34faaf79 100644
--- a/include/bb_archive.h
+++ b/include/bb_archive.h
@@ -78,7 +78,7 @@ typedef struct archive_handle_t {
78 llist_t *link_placeholders; 78 llist_t *link_placeholders;
79 79
80 /* Process the header component, e.g. tar -t */ 80 /* Process the header component, e.g. tar -t */
81 void FAST_FUNC (*action_header)(const file_header_t *); 81 void FAST_FUNC (*action_header)(struct archive_handle_t *);
82 82
83 /* Process the data component, e.g. extract to filesystem */ 83 /* Process the data component, e.g. extract to filesystem */
84 void FAST_FUNC (*action_data)(struct archive_handle_t *); 84 void FAST_FUNC (*action_data)(struct archive_handle_t *);
@@ -197,9 +197,9 @@ void data_extract_all(archive_handle_t *archive_handle) FAST_FUNC;
197void data_extract_to_stdout(archive_handle_t *archive_handle) FAST_FUNC; 197void data_extract_to_stdout(archive_handle_t *archive_handle) FAST_FUNC;
198void data_extract_to_command(archive_handle_t *archive_handle) FAST_FUNC; 198void data_extract_to_command(archive_handle_t *archive_handle) FAST_FUNC;
199 199
200void header_skip(const file_header_t *file_header) FAST_FUNC; 200void header_skip(archive_handle_t *archive_handle) FAST_FUNC;
201void header_list(const file_header_t *file_header) FAST_FUNC; 201void header_list(archive_handle_t *archive_handle) FAST_FUNC;
202void header_verbose_list(const file_header_t *file_header) FAST_FUNC; 202void header_verbose_list(archive_handle_t *archive_handle) FAST_FUNC;
203 203
204char get_header_ar(archive_handle_t *archive_handle) FAST_FUNC; 204char get_header_ar(archive_handle_t *archive_handle) FAST_FUNC;
205char get_header_cpio(archive_handle_t *archive_handle) FAST_FUNC; 205char get_header_cpio(archive_handle_t *archive_handle) FAST_FUNC;
diff --git a/include/libbb.h b/include/libbb.h
index 044a7c81d..8ba71946f 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -554,16 +554,17 @@ enum { /* cp.c, mv.c, install.c depend on these values. CAREFUL when changing th
554#endif 554#endif
555#define FILEUTILS_CP_OPTSTR "pdRfinlsLHarPvuTt:" IF_SELINUX("c") 555#define FILEUTILS_CP_OPTSTR "pdRfinlsLHarPvuTt:" IF_SELINUX("c")
556/* How many bits in FILEUTILS_CP_OPTSTR? */ 556/* How many bits in FILEUTILS_CP_OPTSTR? */
557 FILEUTILS_CP_OPTBITS = 18 - !ENABLE_SELINUX, 557 FILEUTILS_CP_OPTBITS = (18 - !ENABLE_SELINUX),
558 558
559 FILEUTILS_RMDEST = 1 << (19 - !ENABLE_SELINUX), /* cp --remove-destination */ 559 FILEUTILS_RMDEST = 1 << (18 - !ENABLE_SELINUX), /* cp --remove-destination */
560 /* bit 18 skipped for "cp --parents" */ 560 /* bit 19 is used in cp for "cp --parents" */
561 FILEUTILS_REFLINK = 1 << (20 - !ENABLE_SELINUX), /* cp --reflink=auto */ 561 FILEUTILS_REFLINK = 1 << (20 - !ENABLE_SELINUX), /* cp --reflink=auto */
562 FILEUTILS_REFLINK_ALWAYS = 1 << (21 - !ENABLE_SELINUX), /* cp --reflink[=always] */ 562 /* bit 21 is used in cp for "cp --sparse=... */
563 /* 563 /*
564 * Hole. cp may have some bits set here, 564 * Hole. cp may have some bits set here,
565 * they should not affect remove_file()/copy_file() 565 * they should not affect remove_file()/copy_file()
566 */ 566 */
567 FILEUTILS_REFLINK_ALWAYS = 1 << 29, /* cp --reflink, --reflink=always */
567#if ENABLE_SELINUX 568#if ENABLE_SELINUX
568 FILEUTILS_SET_SECURITY_CONTEXT = 1 << 30, 569 FILEUTILS_SET_SECURITY_CONTEXT = 1 << 30,
569#endif 570#endif
@@ -2011,10 +2012,10 @@ void getcaps(void *caps) FAST_FUNC;
2011 2012
2012#if ENABLE_SELINUX 2013#if ENABLE_SELINUX
2013extern void renew_current_security_context(void) FAST_FUNC; 2014extern void renew_current_security_context(void) FAST_FUNC;
2014extern void set_current_security_context(security_context_t sid) FAST_FUNC; 2015extern void set_current_security_context(char *sid) FAST_FUNC;
2015extern context_t set_security_context_component(security_context_t cur_context, 2016extern context_t set_security_context_component(char *cur_context,
2016 char *user, char *role, char *type, char *range) FAST_FUNC; 2017 char *user, char *role, char *type, char *range) FAST_FUNC;
2017extern void setfscreatecon_or_die(security_context_t scontext) FAST_FUNC; 2018extern void setfscreatecon_or_die(char *scontext) FAST_FUNC;
2018extern void selinux_preserve_fcontext(int fdesc) FAST_FUNC; 2019extern void selinux_preserve_fcontext(int fdesc) FAST_FUNC;
2019#else 2020#else
2020#define selinux_preserve_fcontext(fdesc) ((void)0) 2021#define selinux_preserve_fcontext(fdesc) ((void)0)
diff --git a/include/platform.h b/include/platform.h
index f46569f0f..7f516dd77 100644
--- a/include/platform.h
+++ b/include/platform.h
@@ -165,6 +165,21 @@
165# endif 165# endif
166#endif 166#endif
167 167
168/* Somewhere after gcc-9, it stopped recognizing "int var = var;" initializer
169 * as the "this variable is intentionally not initialized, don't warn" idiom.
170 */
171#if !__GNUC_PREREQ(10,0)
172# define UNINITIALIZED_VAR(var,zero) var = var
173#else
174# define UNINITIALIZED_VAR(var,zero) var = zero
175/* NB: in case newer gcc is able to see that the variable
176 * is never used before initialization on all possible code paths,
177 * you can use int UNINITIALIZED_VAR(var,var);
178 * instead of int UNINITIALIZED_VAR(var,0);
179 * and avoid having extra zeroing instruction.
180 */
181#endif
182
168 183
169/* ---- Endian Detection ------------------------------------ */ 184/* ---- Endian Detection ------------------------------------ */
170 185
diff --git a/libbb/copy_file.c b/libbb/copy_file.c
index c0928a5a8..e764deb60 100644
--- a/libbb/copy_file.c
+++ b/libbb/copy_file.c
@@ -124,10 +124,10 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags)
124 124
125#if ENABLE_SELINUX 125#if ENABLE_SELINUX
126 if ((flags & FILEUTILS_PRESERVE_SECURITY_CONTEXT) && is_selinux_enabled() > 0) { 126 if ((flags & FILEUTILS_PRESERVE_SECURITY_CONTEXT) && is_selinux_enabled() > 0) {
127 security_context_t con; 127 char *con;
128 if (lgetfilecon(source, &con) >= 0) { 128 if (lgetfilecon(source, &con) >= 0) {
129 if (setfscreatecon(con) < 0) { 129 if (setfscreatecon(con) < 0) {
130 bb_perror_msg("can't set setfscreatecon %s", con); 130 bb_perror_msg("can't setfscreatecon %s", con);
131 freecon(con); 131 freecon(con);
132 return -1; 132 return -1;
133 } 133 }
@@ -333,7 +333,7 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags)
333 if ((flags & (FILEUTILS_PRESERVE_SECURITY_CONTEXT|FILEUTILS_SET_SECURITY_CONTEXT)) 333 if ((flags & (FILEUTILS_PRESERVE_SECURITY_CONTEXT|FILEUTILS_SET_SECURITY_CONTEXT))
334 && is_selinux_enabled() > 0 334 && is_selinux_enabled() > 0
335 ) { 335 ) {
336 security_context_t con; 336 char *con;
337 if (getfscreatecon(&con) == -1) { 337 if (getfscreatecon(&con) == -1) {
338 bb_simple_perror_msg("getfscreatecon"); 338 bb_simple_perror_msg("getfscreatecon");
339 return -1; 339 return -1;
diff --git a/libbb/run_shell.c b/libbb/run_shell.c
index c22bba87b..1c366d069 100644
--- a/libbb/run_shell.c
+++ b/libbb/run_shell.c
@@ -33,14 +33,14 @@
33#endif 33#endif
34 34
35#if ENABLE_SELINUX 35#if ENABLE_SELINUX
36static security_context_t current_sid; 36static char *current_sid;
37 37
38void FAST_FUNC renew_current_security_context(void) 38void FAST_FUNC renew_current_security_context(void)
39{ 39{
40 freecon(current_sid); /* Release old context */ 40 freecon(current_sid); /* Release old context */
41 getcon(&current_sid); /* update */ 41 getcon(&current_sid); /* update */
42} 42}
43void FAST_FUNC set_current_security_context(security_context_t sid) 43void FAST_FUNC set_current_security_context(char *sid)
44{ 44{
45 freecon(current_sid); /* Release old context */ 45 freecon(current_sid); /* Release old context */
46 current_sid = sid; 46 current_sid = sid;
diff --git a/libbb/selinux_common.c b/libbb/selinux_common.c
index f917a1c6a..8f00f2db5 100644
--- a/libbb/selinux_common.c
+++ b/libbb/selinux_common.c
@@ -9,7 +9,7 @@
9#include "libbb.h" 9#include "libbb.h"
10#include <selinux/context.h> 10#include <selinux/context.h>
11 11
12context_t FAST_FUNC set_security_context_component(security_context_t cur_context, 12context_t FAST_FUNC set_security_context_component(char *cur_context,
13 char *user, char *role, char *type, char *range) 13 char *user, char *role, char *type, char *range)
14{ 14{
15 context_t con = context_new(cur_context); 15 context_t con = context_new(cur_context);
@@ -31,7 +31,7 @@ error:
31 return NULL; 31 return NULL;
32} 32}
33 33
34void FAST_FUNC setfscreatecon_or_die(security_context_t scontext) 34void FAST_FUNC setfscreatecon_or_die(char *scontext)
35{ 35{
36 if (setfscreatecon(scontext) < 0) { 36 if (setfscreatecon(scontext) < 0) {
37 /* Can be NULL. All known printf implementations 37 /* Can be NULL. All known printf implementations
@@ -43,7 +43,7 @@ void FAST_FUNC setfscreatecon_or_die(security_context_t scontext)
43 43
44void FAST_FUNC selinux_preserve_fcontext(int fdesc) 44void FAST_FUNC selinux_preserve_fcontext(int fdesc)
45{ 45{
46 security_context_t context; 46 char *context;
47 47
48 if (fgetfilecon(fdesc, &context) < 0) { 48 if (fgetfilecon(fdesc, &context) < 0) {
49 if (errno == ENODATA || errno == ENOTSUP) 49 if (errno == ENODATA || errno == ENOTSUP)
diff --git a/libbb/update_passwd.c b/libbb/update_passwd.c
index a228075cc..b8a47dc5a 100644
--- a/libbb/update_passwd.c
+++ b/libbb/update_passwd.c
@@ -18,7 +18,7 @@
18#if ENABLE_SELINUX 18#if ENABLE_SELINUX
19static void check_selinux_update_passwd(const char *username) 19static void check_selinux_update_passwd(const char *username)
20{ 20{
21 security_context_t seuser; 21 char *seuser;
22 char *p; 22 char *p;
23 23
24 if (getuid() != (uid_t)0 || is_selinux_enabled() == 0) 24 if (getuid() != (uid_t)0 || is_selinux_enabled() == 0)
diff --git a/loginutils/login.c b/loginutils/login.c
index 301be4a34..16e009496 100644
--- a/loginutils/login.c
+++ b/loginutils/login.c
@@ -181,9 +181,9 @@ static void die_if_nologin(void)
181 181
182#if ENABLE_SELINUX 182#if ENABLE_SELINUX
183static void initselinux(char *username, char *full_tty, 183static void initselinux(char *username, char *full_tty,
184 security_context_t *user_sid) 184 char **user_sid)
185{ 185{
186 security_context_t old_tty_sid, new_tty_sid; 186 char *old_tty_sid, *new_tty_sid;
187 187
188 if (!is_selinux_enabled()) 188 if (!is_selinux_enabled())
189 return; 189 return;
@@ -333,7 +333,7 @@ int login_main(int argc UNUSED_PARAM, char **argv)
333 char *opt_user = opt_user; /* for compiler */ 333 char *opt_user = opt_user; /* for compiler */
334 char *full_tty; 334 char *full_tty;
335 char *short_tty; 335 char *short_tty;
336 IF_SELINUX(security_context_t user_sid = NULL;) 336 IF_SELINUX(char *user_sid = NULL;)
337#if ENABLE_PAM 337#if ENABLE_PAM
338 int pamret; 338 int pamret;
339 pam_handle_t *pamh; 339 pam_handle_t *pamh;
diff --git a/miscutils/devfsd.c b/miscutils/devfsd.c
index d57691414..e6f01eb6a 100644
--- a/miscutils/devfsd.c
+++ b/miscutils/devfsd.c
@@ -1016,9 +1016,9 @@ static void restore(char *spath, struct stat source_stat, int rootlen)
1016 dest_stat.st_mode = 0; 1016 dest_stat.st_mode = 0;
1017 dpath = concat_path_file(mount_point, spath + rootlen); 1017 dpath = concat_path_file(mount_point, spath + rootlen);
1018 lstat(dpath, &dest_stat); 1018 lstat(dpath, &dest_stat);
1019 free(dpath);
1020 if (S_ISLNK(source_stat.st_mode) || (source_stat.st_mode & S_ISVTX)) 1019 if (S_ISLNK(source_stat.st_mode) || (source_stat.st_mode & S_ISVTX))
1021 copy_inode(dpath, &dest_stat, (source_stat.st_mode & ~S_ISVTX), spath, &source_stat); 1020 copy_inode(dpath, &dest_stat, (source_stat.st_mode & ~S_ISVTX), spath, &source_stat);
1021 free(dpath);
1022 1022
1023 if (S_ISDIR(source_stat.st_mode)) 1023 if (S_ISDIR(source_stat.st_mode))
1024 dir_operation(RESTORE, spath, rootlen, NULL); 1024 dir_operation(RESTORE, spath, rootlen, NULL);
@@ -1271,7 +1271,7 @@ static void dir_operation(int type, const char * dir_name, int var, unsigned lon
1271 1271
1272 while ((de = readdir(dp)) != NULL) { 1272 while ((de = readdir(dp)) != NULL) {
1273 1273
1274 if (de->d_name && DOT_OR_DOTDOT(de->d_name)) 1274 if (DOT_OR_DOTDOT(de->d_name))
1275 continue; 1275 continue;
1276 path = concat_path_file(dir_name, de->d_name); 1276 path = concat_path_file(dir_name, de->d_name);
1277 if (lstat(path, &statbuf) == 0) { 1277 if (lstat(path, &statbuf) == 0) {
diff --git a/miscutils/hdparm.c b/miscutils/hdparm.c
index 8b844717f..e07ee6398 100644
--- a/miscutils/hdparm.c
+++ b/miscutils/hdparm.c
@@ -552,7 +552,7 @@ static void print_ascii(const char *p, int length)
552 552
553 length *= 2; 553 length *= 2;
554 /* find first non-space & print it */ 554 /* find first non-space & print it */
555 while (length && p[ofs] != ' ') { 555 while (length && p[ofs] == ' ') {
556 p++; 556 p++;
557 LE_ONLY(ofs = -ofs;) 557 LE_ONLY(ofs = -ofs;)
558 length--; 558 length--;
diff --git a/miscutils/less.c b/miscutils/less.c
index e81130988..521792f2e 100644
--- a/miscutils/less.c
+++ b/miscutils/less.c
@@ -477,7 +477,8 @@ static int at_end(void)
477 */ 477 */
478static void read_lines(void) 478static void read_lines(void)
479{ 479{
480 int ndelay_set, eagain, fdflags; 480 int ndelay_set, eagain;
481 int UNINITIALIZED_VAR(fdflags, fdflags);
481 char *current_line, *p; 482 char *current_line, *p;
482 int w = width; 483 int w = width;
483 char last_terminated = terminated; 484 char last_terminated = terminated;
@@ -509,16 +510,16 @@ static void read_lines(void)
509 // Consider these cases: 510 // Consider these cases:
510 // "less FILE": can set O_NONBLOCK on open. 511 // "less FILE": can set O_NONBLOCK on open.
511 // "true | less": can't. 512 // "true | less": can't.
512 // " { less; cat; } <FILE": can't. And must not confuse cat. 513 // "{ less; cat; } <FILE": can't. And must not confuse cat.
513 ndelay_set = -1; // "don't know whether stdin is nonblocking" 514 ndelay_set = -1; // "don't know whether stdin is nonblocking"
514 eagain = 0; 515 eagain = 0;
515 516
516 while (1) { /* read lines until we reach cur_fline or wanted_match */ 517 while (1) { // read lines until we reach cur_fline or wanted_match
517 *p = '\0'; 518 *p = '\0';
518 terminated = 0; 519 terminated = 0;
519 while (1) { /* read chars until we have a line */ 520 while (1) { // read chars until we have a line
520 char c; 521 char c;
521 /* if no unprocessed chars left, eat more */ 522 // if no unprocessed chars left, eat more
522 if (readpos >= read_size) { 523 if (readpos >= read_size) {
523 // Read stdin, temporarily make it nonblocking (if it's not already) 524 // Read stdin, temporarily make it nonblocking (if it's not already)
524 if (ndelay_set < 0) { 525 if (ndelay_set < 0) {
diff --git a/networking/inetd.c b/networking/inetd.c
index 6220a08e3..75b1b2ea5 100644
--- a/networking/inetd.c
+++ b/networking/inetd.c
@@ -1043,7 +1043,7 @@ static void reread_config_file(int sig UNUSED_PARAM)
1043 portno = bb_strtou(sep->se_service, NULL, 10); 1043 portno = bb_strtou(sep->se_service, NULL, 10);
1044#if ENABLE_FEATURE_INETD_RPC 1044#if ENABLE_FEATURE_INETD_RPC
1045 if (is_rpc_service(sep)) { 1045 if (is_rpc_service(sep)) {
1046 sep->se_rpcprog = n; 1046 sep->se_rpcprog = portno;
1047 if (errno) { /* se_service is not numeric */ 1047 if (errno) { /* se_service is not numeric */
1048 struct rpcent *rp = getrpcbyname(sep->se_service); 1048 struct rpcent *rp = getrpcbyname(sep->se_service);
1049 if (rp == NULL) { 1049 if (rp == NULL) {
diff --git a/networking/tftp.c b/networking/tftp.c
index b698a9288..e13223d1d 100644
--- a/networking/tftp.c
+++ b/networking/tftp.c
@@ -883,7 +883,7 @@ int tftpd_main(int argc UNUSED_PARAM, char **argv)
883 len_and_sockaddr *our_lsa; 883 len_and_sockaddr *our_lsa;
884 len_and_sockaddr *peer_lsa; 884 len_and_sockaddr *peer_lsa;
885 char *mode, *user_opt; 885 char *mode, *user_opt;
886 char *local_file = local_file; 886 char *UNINITIALIZED_VAR(local_file, NULL);
887 const char *error_msg; 887 const char *error_msg;
888 int opt, result, opcode; 888 int opt, result, opcode;
889 IF_FEATURE_TFTP_BLOCKSIZE(int blksize = TFTP_BLKSIZE_DEFAULT;) 889 IF_FEATURE_TFTP_BLOCKSIZE(int blksize = TFTP_BLKSIZE_DEFAULT;)
diff --git a/selinux/chcon.c b/selinux/chcon.c
index e1778a36a..9543de120 100644
--- a/selinux/chcon.c
+++ b/selinux/chcon.c
@@ -67,8 +67,8 @@ static int FAST_FUNC change_filedir_context(struct recursive_state *state UNUSED
67 struct stat *stbuf UNUSED_PARAM) 67 struct stat *stbuf UNUSED_PARAM)
68{ 68{
69 context_t context = NULL; 69 context_t context = NULL;
70 security_context_t file_context = NULL; 70 char *file_context = NULL;
71 security_context_t context_string; 71 const char *context_string;
72 int rc = FALSE; 72 int rc = FALSE;
73 int status = 0; 73 int status = 0;
74 74
diff --git a/selinux/matchpathcon.c b/selinux/matchpathcon.c
index 6945a0295..456209bbd 100644
--- a/selinux/matchpathcon.c
+++ b/selinux/matchpathcon.c
@@ -80,7 +80,7 @@ int matchpathcon_main(int argc UNUSED_PARAM, char **argv)
80 } 80 }
81 81
82 while ((path = *argv++) != NULL) { 82 while ((path = *argv++) != NULL) {
83 security_context_t con; 83 char *con;
84 int rc; 84 int rc;
85 85
86 if (!(opts & OPT_VERIFY)) { 86 if (!(opts & OPT_VERIFY)) {
diff --git a/selinux/runcon.c b/selinux/runcon.c
index bc4fa23e0..343b6563d 100644
--- a/selinux/runcon.c
+++ b/selinux/runcon.c
@@ -62,13 +62,13 @@ static context_t runcon_compute_new_context(char *user, char *role, char *type,
62 char *command, int compute_trans) 62 char *command, int compute_trans)
63{ 63{
64 context_t con; 64 context_t con;
65 security_context_t cur_context; 65 char *cur_context;
66 66
67 if (getcon(&cur_context)) 67 if (getcon(&cur_context))
68 bb_simple_error_msg_and_die("can't get current context"); 68 bb_simple_error_msg_and_die("can't get current context");
69 69
70 if (compute_trans) { 70 if (compute_trans) {
71 security_context_t file_context, new_context; 71 char *file_context, *new_context;
72 72
73 if (getfilecon(command, &file_context) < 0) 73 if (getfilecon(command, &file_context) < 0)
74 bb_error_msg_and_die("can't retrieve attributes of '%s'", 74 bb_error_msg_and_die("can't retrieve attributes of '%s'",
diff --git a/selinux/sestatus.c b/selinux/sestatus.c
index cf664cc18..4a82338fb 100644
--- a/selinux/sestatus.c
+++ b/selinux/sestatus.c
@@ -92,7 +92,7 @@ static void read_config(char **pc, int npc, char **fc, int nfc)
92 92
93static void display_verbose(void) 93static void display_verbose(void)
94{ 94{
95 security_context_t con, _con; 95 char *con, *_con;
96 char *fc[50], *pc[50], *cterm; 96 char *fc[50], *pc[50], *cterm;
97 pid_t *pidList; 97 pid_t *pidList;
98 int i; 98 int i;
diff --git a/shell/ash_test/ash-read/read_n.right b/shell/ash_test/ash-read/read_n.right
index 1f81af0bc..bd29f8ca3 100644
--- a/shell/ash_test/ash-read/read_n.right
+++ b/shell/ash_test/ash-read/read_n.right
@@ -1,3 +1,5 @@
1test 1test
2tes 2tes
3tes 3tes
412
5\1
diff --git a/shell/ash_test/ash-read/read_n.tests b/shell/ash_test/ash-read/read_n.tests
index 12423ba6e..fde3d8954 100755
--- a/shell/ash_test/ash-read/read_n.tests
+++ b/shell/ash_test/ash-read/read_n.tests
@@ -1,3 +1,5 @@
1echo 'test' | (read reply; echo "$reply") 1echo 'test' | (read reply; echo "$reply")
2echo 'test' | (read -n 3 reply; echo "$reply") 2echo 'test' | (read -n 3 reply; echo "$reply")
3echo 'test' | (read -n3 reply; echo "$reply") 3echo 'test' | (read -n3 reply; echo "$reply")
4echo '\1\2' | (read -n 2 reply; echo "$reply")
5echo '\1\2' | (read -r -n 2 reply; echo "$reply")
diff --git a/shell/hush.c b/shell/hush.c
index d1e954485..bc8d1e7f7 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -3295,7 +3295,7 @@ static void o_addqchr(o_string *o, int ch)
3295 /* '-' is included because of this case: 3295 /* '-' is included because of this case:
3296 * >filename0 >filename1 >filename9; v='-'; echo filename[0"$v"9] 3296 * >filename0 >filename1 >filename9; v='-'; echo filename[0"$v"9]
3297 */ 3297 */
3298 char *found = strchr("*?[-\\" MAYBE_BRACES, ch); 3298 const char *found = strchr("*?[-\\" MAYBE_BRACES, ch);
3299 if (found) 3299 if (found)
3300 sz++; 3300 sz++;
3301 o_grow_by(o, sz); 3301 o_grow_by(o, sz);
@@ -7183,9 +7183,9 @@ static NOINLINE int expand_one_var(o_string *output, int n, char *arg, char **pp
7183 char *p; 7183 char *p;
7184 char *var; 7184 char *var;
7185 char exp_op; 7185 char exp_op;
7186 char exp_save = exp_save; /* for compiler */ 7186 char UNINITIALIZED_VAR(exp_savech, exp_savech); /* for compiler */
7187 char *exp_saveptr; /* points to expansion operator */ 7187 char *exp_saveptr; /* points to expansion operator */
7188 char *exp_word = exp_word; /* for compiler */ 7188 char *UNINITIALIZED_VAR(exp_word, NULL); /* for compiler */
7189 char arg0; 7189 char arg0;
7190 7190
7191 val = NULL; 7191 val = NULL;
@@ -7193,13 +7193,13 @@ static NOINLINE int expand_one_var(o_string *output, int n, char *arg, char **pp
7193 p = *pp; 7193 p = *pp;
7194 *p = '\0'; /* replace trailing SPECIAL_VAR_SYMBOL */ 7194 *p = '\0'; /* replace trailing SPECIAL_VAR_SYMBOL */
7195 var = arg; 7195 var = arg;
7196 exp_saveptr = arg[1] ? strchr(VAR_ENCODED_SUBST_OPS, arg[1]) : NULL; 7196 exp_saveptr = arg[1] ? (char*)strchr(VAR_ENCODED_SUBST_OPS, arg[1]) : NULL;
7197 arg0 = arg[0]; 7197 arg0 = arg[0];
7198 arg[0] = (arg0 & 0x7f); 7198 arg[0] = (arg0 & 0x7f);
7199 exp_op = 0; 7199 exp_op = 0;
7200 7200
7201 if (arg[0] == '#' && arg[1] /* ${#...} but not ${#} */ 7201 if (arg[0] == '#' && arg[1] /* ${#...} but not ${#} */
7202 && (!exp_saveptr /* and ( not(${#<op_char>...}) */ 7202 && (!exp_saveptr /* and ( not ${#<op_char>...} */
7203 || (arg[2] == '\0' && strchr(SPECIAL_VARS_STR, arg[1])) /* or ${#C} "len of $C" ) */ 7203 || (arg[2] == '\0' && strchr(SPECIAL_VARS_STR, arg[1])) /* or ${#C} "len of $C" ) */
7204 ) /* NB: skipping ^^^specvar check mishandles ${#::2} */ 7204 ) /* NB: skipping ^^^specvar check mishandles ${#::2} */
7205 ) { 7205 ) {
@@ -7217,7 +7217,7 @@ static NOINLINE int expand_one_var(o_string *output, int n, char *arg, char **pp
7217 /* ${?}, ${var}, ${var:0}, ${var[:]%0} etc */ 7217 /* ${?}, ${var}, ${var:0}, ${var[:]%0} etc */
7218 exp_saveptr = var+1 + strcspn(var+1, VAR_ENCODED_SUBST_OPS); 7218 exp_saveptr = var+1 + strcspn(var+1, VAR_ENCODED_SUBST_OPS);
7219 } 7219 }
7220 exp_op = exp_save = *exp_saveptr; 7220 exp_op = exp_savech = *exp_saveptr;
7221 if (exp_op) { 7221 if (exp_op) {
7222 exp_word = exp_saveptr + 1; 7222 exp_word = exp_saveptr + 1;
7223 if (exp_op == ':') { 7223 if (exp_op == ':') {
@@ -7514,11 +7514,11 @@ static NOINLINE int expand_one_var(o_string *output, int n, char *arg, char **pp
7514 * $ x=; f "${x:-'x y' z}" 7514 * $ x=; f "${x:-'x y' z}"
7515 * |'x y' z| 7515 * |'x y' z|
7516 */ 7516 */
7517 int use_word = (!val || ((exp_save == ':') && !val[0])); 7517 int use_word = (!val || ((exp_savech == ':') && !val[0]));
7518 if (exp_op == '+') 7518 if (exp_op == '+')
7519 use_word = !use_word; 7519 use_word = !use_word;
7520 debug_printf_expand("expand: op:%c (null:%s) test:%i\n", exp_op, 7520 debug_printf_expand("expand: op:%c (null:%s) test:%i\n", exp_op,
7521 (exp_save == ':') ? "true" : "false", use_word); 7521 (exp_savech == ':') ? "true" : "false", use_word);
7522 if (use_word) { 7522 if (use_word) {
7523 if (exp_op == '+' || exp_op == '-') { 7523 if (exp_op == '+' || exp_op == '-') {
7524 /* ${var+word} - use alternative value */ 7524 /* ${var+word} - use alternative value */
@@ -7545,7 +7545,7 @@ static NOINLINE int expand_one_var(o_string *output, int n, char *arg, char **pp
7545 ? exp_word 7545 ? exp_word
7546 : "parameter null or not set" 7546 : "parameter null or not set"
7547 /* ash has more specific messages, a-la: */ 7547 /* ash has more specific messages, a-la: */
7548 /*: (exp_save == ':' ? "parameter null or not set" : "parameter not set")*/ 7548 /*: (exp_savech == ':' ? "parameter null or not set" : "parameter not set")*/
7549 ); 7549 );
7550//TODO: how interactive bash aborts expansion mid-command? 7550//TODO: how interactive bash aborts expansion mid-command?
7551//It aborts the entire line, returns to prompt: 7551//It aborts the entire line, returns to prompt:
@@ -7571,7 +7571,7 @@ static NOINLINE int expand_one_var(o_string *output, int n, char *arg, char **pp
7571 } 7571 }
7572 } /* one of "-=+?" */ 7572 } /* one of "-=+?" */
7573 7573
7574 *exp_saveptr = exp_save; 7574 *exp_saveptr = exp_savech;
7575 } /* if (exp_op) */ 7575 } /* if (exp_op) */
7576 7576
7577 arg[0] = arg0; 7577 arg[0] = arg0;
diff --git a/shell/hush_test/hush-read/read_n.right b/shell/hush_test/hush-read/read_n.right
index 1f81af0bc..bd29f8ca3 100644
--- a/shell/hush_test/hush-read/read_n.right
+++ b/shell/hush_test/hush-read/read_n.right
@@ -1,3 +1,5 @@
1test 1test
2tes 2tes
3tes 3tes
412
5\1
diff --git a/shell/hush_test/hush-read/read_n.tests b/shell/hush_test/hush-read/read_n.tests
index 12423ba6e..fde3d8954 100755
--- a/shell/hush_test/hush-read/read_n.tests
+++ b/shell/hush_test/hush-read/read_n.tests
@@ -1,3 +1,5 @@
1echo 'test' | (read reply; echo "$reply") 1echo 'test' | (read reply; echo "$reply")
2echo 'test' | (read -n 3 reply; echo "$reply") 2echo 'test' | (read -n 3 reply; echo "$reply")
3echo 'test' | (read -n3 reply; echo "$reply") 3echo 'test' | (read -n3 reply; echo "$reply")
4echo '\1\2' | (read -n 2 reply; echo "$reply")
5echo '\1\2' | (read -r -n 2 reply; echo "$reply")
diff --git a/shell/shell_common.c b/shell/shell_common.c
index 031182ff4..87290783d 100644
--- a/shell/shell_common.c
+++ b/shell/shell_common.c
@@ -280,7 +280,7 @@ shell_builtin_read(struct builtin_read_params *params)
280 break; 280 break;
281 } 281 }
282 retval = (const char *)(uintptr_t)1; 282 retval = (const char *)(uintptr_t)1;
283 goto ret; 283 break;
284 } 284 }
285 if (read(fd, &buffer[bufpos], 1) != 1) { 285 if (read(fd, &buffer[bufpos], 1) != 1) {
286 err = errno; 286 err = errno;
@@ -363,7 +363,7 @@ shell_builtin_read(struct builtin_read_params *params)
363 } 363 }
364 put: 364 put:
365 bufpos++; 365 bufpos++;
366 } while (IF_PLATFORM_MINGW32(backslash ||) --nchars); 366 } while (backslash || --nchars);
367 367
368 if (argv[0]) { 368 if (argv[0]) {
369 /* Remove trailing space $IFS chars */ 369 /* Remove trailing space $IFS chars */
@@ -416,7 +416,6 @@ shell_builtin_read(struct builtin_read_params *params)
416 params->setvar("REPLY", buffer); 416 params->setvar("REPLY", buffer);
417 } 417 }
418 418
419 ret:
420 free(buffer); 419 free(buffer);
421#if !ENABLE_PLATFORM_MINGW32 420#if !ENABLE_PLATFORM_MINGW32
422 if (read_flags & BUILTIN_READ_SILENT) 421 if (read_flags & BUILTIN_READ_SILENT)
diff --git a/testsuite/awk.tests b/testsuite/awk.tests
index ef7c4497f..1238ba6c4 100755
--- a/testsuite/awk.tests
+++ b/testsuite/awk.tests
@@ -75,7 +75,7 @@ testing "awk %.3d 99999999999999000.1234" \
75testing "awk %.*d 3 99999999999999000.1234" \ 75testing "awk %.*d 3 99999999999999000.1234" \
76"awk 'BEGIN { printf \"%.*d\n\", 3, 99999999999999000.1234; }'" "99999999999999008\n" "" "" 76"awk 'BEGIN { printf \"%.*d\n\", 3, 99999999999999000.1234; }'" "99999999999999008\n" "" ""
77 77
78# fractioals are rounded towards 0 78# fractionals are rounded towards 0
79testing "awk %d -1.9" \ 79testing "awk %d -1.9" \
80"awk 'BEGIN { printf \"%d\n\", -1.9; }'" "-1\n" "" "" 80"awk 'BEGIN { printf \"%d\n\", -1.9; }'" "-1\n" "" ""
81testing "awk %u -1.9" \ 81testing "awk %u -1.9" \
@@ -85,6 +85,31 @@ testing "awk %x -1.9" \
85testing "awk %o -1.9" \ 85testing "awk %o -1.9" \
86"awk 'BEGIN { printf \"%o\n\", -1.9; }'" "1777777777777777777777\n" "" "" 86"awk 'BEGIN { printf \"%o\n\", -1.9; }'" "1777777777777777777777\n" "" ""
87 87
88# OFMT can contain literals before and after %SPEC:
89testing "awk OFMT='R%%:%f!' -1.9" \
90"awk -v OFMT='R%%:%f!' 'BEGIN { print -1.9; }'" "R%:-1.900000!\n" "" ""
91
92# OFMT is ignored if the value has no fractionals (even if it does not fit into uint64)
93testing "awk OFMT='R%%:%f!' 2**128" \
94"awk -v OFMT='R%%:%f!' 'BEGIN { print 2**128; }'" "340282366920938463463374607431768211456\n" "" ""
95testing "awk OFMT='R%%:%f!' 2**128" \
96"awk -v OFMT='R%%:%f!' 'BEGIN { print -2**129; }'" "-680564733841876926926749214863536422912\n" "" ""
97
98# OFMT can contain no %SPEC (be a literal):
99testing "awk OFMT='No formats, %% allowed!'" \
100"awk -v OFMT='No formats, %% allowed!' 'BEGIN { print -1.9; }'" "No formats, % allowed!\n" "" ""
101
102# OFMT can't have more than one %SPEC:
103testing "awk OFMT='%f%s' is not allowed" \
104"awk -v OFMT='R%%:%f!%s!' 'BEGIN { print -1.9; }' 2>&1" \
105"awk: cmd. line:1: Invalid format specifier\n" "" ""
106
107# OFMT %s:
108testing "awk OFMT='%-22s' -1.9" \
109"awk -v OFMT='R:%-22s!' 'BEGIN { print -1.9; }'" \
110"R:-1.9 !\n" "" ""
111
112
88# 4294967295 = 0xffffffff 113# 4294967295 = 0xffffffff
89testing "awk bitwise op" "awk '{ print or(4294967295,1) }'" "4294967295\n" "" "\n" 114testing "awk bitwise op" "awk '{ print or(4294967295,1) }'" "4294967295\n" "" "\n"
90 115
diff --git a/testsuite/hdparm.tests b/testsuite/hdparm.tests
new file mode 100755
index 000000000..e029d3d42
--- /dev/null
+++ b/testsuite/hdparm.tests
@@ -0,0 +1,51 @@
1#!/bin/sh
2# Copyright 2026 by Romain Guyard <foss@romainguyard.com>
3# Licensed under GPLv2, see file LICENSE in this source tree.
4
5. ./testing.sh
6
7# testing "test name" "commands" "expected result" "file input" "stdin"
8
9# With no device argument and a non-tty stdin, hdparm parses a hex IDENTIFY
10# DEVICE block from stdin (identify_from_stdin) and prints it the way
11# "hdparm -I" does. That makes the ASCII field decoding testable without
12# a disk.
13#
14# The block below carries:
15# words 10-19 serial number "SN0123456789ABCDEF" (no embedded space)
16# words 23-26 firmware rev "FW1234"
17# words 27-46 model number "EXAMPLE SSD 256GB" (has one)
18# words 176-195 media serial " MEDIASN00001" (leading spaces)
19#
20# ATA strings are left-justified and space-padded. print_ascii() must skip
21# leading *spaces* only. It used to skip the leading run of *non-space*
22# characters instead, which emptied every field with no embedded space
23# (serial number, firmware revision) and truncated the model number at its
24# first space.
25
26testing "hdparm -I decodes ASCII fields" \
27 "hdparm | grep -E 'Number:|Revision:|Serial Num:' | sed 's/[[:space:]]*\$//'" \
28"\
29\tModel Number: EXAMPLE SSD 256GB
30\tSerial Number: SN0123456789ABCDEF
31\tFirmware Revision: FW1234
32\tMedia Serial Num: MEDIASN00001
33" \
34 "" \
35"\
360040000000000000000000000000000000000000534e3031323334353637383941424344454620200000000000004657\
373132333420204558414d504c452053534420323536474220202020202020202020202020202020202020202020200000\
38000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\
39000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\
40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\
41000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\
42000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\
43000000000000000000000000000000002020204d45444941534e30303030312020202020202020202020202020202020\
44202020202020202000000000000000000000000000000000000000000000000000000000000000000000000000000000\
45000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\
4600000000000000000000000000000000000000000000000000000000000000a500000000000000000000000000000000\
47000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\
48000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\
4900000000000000000000000000000000"
50
51exit $FAILCOUNT
diff --git a/testsuite/sort.tests b/testsuite/sort.tests
index 8dbadbdae..6d12eb6f4 100755
--- a/testsuite/sort.tests
+++ b/testsuite/sort.tests
@@ -114,6 +114,16 @@ aa.2
114ab.1 114ab.1
115" "" 115" ""
116 116
117testing "sort with ENDCHAR on a later field" "sort -t: -k2.1,2.1 input" "\
118a:aa
119b:aa
120a:ba
121" "\
122b:aa
123a:ba
124a:aa
125" ""
126
117testing "glibc build sort" "sort -t. -k 1,1 -k 2n,2n -k 3 input" "\ 127testing "glibc build sort" "sort -t. -k 1,1 -k 2n,2n -k 3 input" "\
118GLIBC_2.1 128GLIBC_2.1
119GLIBC_2.1.1 129GLIBC_2.1.1
diff --git a/testsuite/tar.tests b/testsuite/tar.tests
index 1f8c9cff3..83c8c2edf 100755
--- a/testsuite/tar.tests
+++ b/testsuite/tar.tests
@@ -206,6 +206,30 @@ SKIP=
206cd .. || exit 1; rm -rf tar.tempdir 2>/dev/null 206cd .. || exit 1; rm -rf tar.tempdir 2>/dev/null
207 207
208mkdir tar.tempdir && cd tar.tempdir || exit 1 208mkdir tar.tempdir && cd tar.tempdir || exit 1
209optional FEATURE_TAR_CREATE
210testing "tar xvO sends file list to stderr" '\
211echo "data1" >file1.txt
212echo "data2" >file2.txt
213echo "data3" >file3.txt
214tar cf test.tar file1.txt file2.txt file3.txt
215tar xvOf test.tar >out 2>err
216echo OUT:; cat out
217echo ERR:; cat err
218' "\
219OUT:
220data1
221data2
222data3
223ERR:
224file1.txt
225file2.txt
226file3.txt
227" \
228"" ""
229SKIP=
230cd .. || exit 1; rm -rf tar.tempdir 2>/dev/null
231
232mkdir tar.tempdir && cd tar.tempdir || exit 1
209# Had a bug where on extract autodetect first "switched off" -z 233# Had a bug where on extract autodetect first "switched off" -z
210# and then failed to recognize .tgz extension 234# and then failed to recognize .tgz extension
211optional FEATURE_TAR_CREATE FEATURE_SEAMLESS_GZ GUNZIP 235optional FEATURE_TAR_CREATE FEATURE_SEAMLESS_GZ GUNZIP
diff --git a/util-linux/mkswap.c b/util-linux/mkswap.c
index bca3de199..0c2e12951 100644
--- a/util-linux/mkswap.c
+++ b/util-linux/mkswap.c
@@ -49,8 +49,8 @@ static void mkswap_selinux_setcontext(int fd, const char *path)
49 49
50 xfstat(fd, &stbuf, path); 50 xfstat(fd, &stbuf, path);
51 if (S_ISREG(stbuf.st_mode)) { 51 if (S_ISREG(stbuf.st_mode)) {
52 security_context_t newcon; 52 const char *newcon;
53 security_context_t oldcon = NULL; 53 char *oldcon = NULL;
54 context_t context; 54 context_t context;
55 55
56 if (fgetfilecon(fd, &oldcon) < 0) { 56 if (fgetfilecon(fd, &oldcon) < 0) {