aboutsummaryrefslogtreecommitdiff
path: root/libbb
diff options
context:
space:
mode:
Diffstat (limited to 'libbb')
-rw-r--r--libbb/c_escape.c20
-rw-r--r--libbb/concat_path_file.c75
-rw-r--r--libbb/dump.c55
-rw-r--r--libbb/getopt32.c13
-rw-r--r--libbb/hash_md5_sha.c58
-rw-r--r--libbb/lineedit.c2
-rw-r--r--libbb/procps.c174
-rw-r--r--libbb/replace.c14
-rw-r--r--libbb/yescrypt/alg-sha256.c13
9 files changed, 293 insertions, 131 deletions
diff --git a/libbb/c_escape.c b/libbb/c_escape.c
new file mode 100644
index 000000000..6c109f2e0
--- /dev/null
+++ b/libbb/c_escape.c
@@ -0,0 +1,20 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Copyright (C) 2025 by Denys Vlasenko <vda.linux@googlemail.com>
4 *
5 * Licensed under GPLv2, see file LICENSE in this source tree.
6 */
7//kbuild:lib-y += c_escape.o
8
9#include "libbb.h"
10
11const char c_escape_conv_str00[] ALIGN1 =
12 "\\""0""\0" // [0]:00
13 "\\""a""\0" // [1]:07
14 "\\""b""\0" // [2]:08
15 "\\""t""\0" // [3]:09
16 "\\""n""\0" // [4]:0a
17 "\\""v""\0" // [5]:0b
18 "\\""f""\0" // [6]:0c
19 "\\""r" // [7]:0d
20 ;
diff --git a/libbb/concat_path_file.c b/libbb/concat_path_file.c
index 5b4b7f113..aefb84f45 100644
--- a/libbb/concat_path_file.c
+++ b/libbb/concat_path_file.c
@@ -17,6 +17,7 @@
17 17
18char* FAST_FUNC concat_path_file(const char *path, const char *filename) 18char* FAST_FUNC concat_path_file(const char *path, const char *filename)
19{ 19{
20#if 0
20 char *lc; 21 char *lc;
21 22
22 if (!path) 23 if (!path)
@@ -25,4 +26,78 @@ char* FAST_FUNC concat_path_file(const char *path, const char *filename)
25 while (*filename == '/') 26 while (*filename == '/')
26 filename++; 27 filename++;
27 return xasprintf("%s%s%s", path, (lc==NULL ? "/" : ""), filename); 28 return xasprintf("%s%s%s", path, (lc==NULL ? "/" : ""), filename);
29#else
30/* ^^^^^^^^^^^ timing of xasprintf-based code above:
31 * real 7.074s
32 * user 0.156s <<<
33 * sys 6.394s
34 * "rm -rf" of a Linux kernel tree from tmpfs (run time still dominated by in-kernel work, though)
35 * real 6.989s
36 * user 0.055s <<< 3 times less CPU used
37 * sys 6.450s
38 * vvvvvvvvvvv timing of open-coded malloc+memcpy code below (+59 bytes):
39 */
40 char *buf, *p;
41 size_t n1, n2, n3;
42
43 while (*filename == '/')
44 filename++;
45
46 if (!path || !path[0])
47 return xstrdup(filename);
48
49 n1 = strlen(path);
50 n2 = (path[n1 - 1] != '/'); /* 1: "path has no trailing slash" */
51 n3 = strlen(filename) + 1;
52
53 buf = xmalloc(n1 + n2 + n3);
54 p = mempcpy(buf, path, n1);
55 if (n2)
56 *p++ = '/';
57 memcpy(p, filename, n3);
58 return buf;
59#endif
60}
61
62/* If second component comes from struct dirent,
63 * it's possible to eliminate one strlen() by using name length
64 * provided by kernel in struct dirent. See below.
65 * However, the win seems to be insignificant.
66 */
67
68#if 0
69
70/* Extract d_namlen from struct dirent */
71static size_t get_d_namlen(const struct dirent *de)
72{
73#if defined(_DIRENT_HAVE_D_NAMLEN)
74 return de->d_namlen;
75#elif defined(_DIRENT_HAVE_D_RECLEN)
76 const size_t prefix_sz = offsetof(struct dirent, d_name);
77 return de->d_reclen - prefix_sz;
78#else
79 return strlen(de->d_name);
80#endif
81}
82
83char* FAST_FUNC concat_path_dirent(const char *path, const struct dirent *de)
84{
85 char *buf, *p;
86 size_t n1, n2, n3;
87
88 if (!path || !path[0])
89 return xstrdup(de->d_name);
90
91 n1 = strlen(path);
92 n2 = (path[n1 - 1] != '/');
93 n3 = get_d_namlen(de) + 1;
94
95 buf = xmalloc(n1 + n2 + n3);
96 p = mempcpy(buf, path, n1);
97 if (n2)
98 *p++ = '/';
99 memcpy(p, de->d_name, n3);
100 return buf;
28} 101}
102
103#endif
diff --git a/libbb/dump.c b/libbb/dump.c
index ac5d47d9e..d34094576 100644
--- a/libbb/dump.c
+++ b/libbb/dump.c
@@ -478,37 +478,52 @@ static void bpad(PR *pr)
478 continue; 478 continue;
479} 479}
480 480
481static const char conv_str[] ALIGN1 =
482 "\0" "\\""0""\0"
483 "\007""\\""a""\0"
484 "\b" "\\""b""\0"
485 "\f" "\\""f""\0"
486 "\n" "\\""n""\0"
487 "\r" "\\""r""\0"
488 "\t" "\\""t""\0"
489 "\v" "\\""v""\0"
490 ;
491
492static void conv_c(PR *pr, unsigned char *p) 481static void conv_c(PR *pr, unsigned char *p)
493{ 482{
494 const char *str = conv_str; 483 const char *str;
495 484 unsigned char ch;
496 do { 485
497 if (*p == *str) { 486 ch = *p;
498 ++str; 487 if (ch == 0 || (ch -= 6, (signed char)ch > 0 && ch <= 7)) {
499 goto strpr; /* map e.g. '\n' to "\\n" */ 488 /* map chars 0,7..13 to "\0","\{a,b,t,n,v,f,r}" */
500 } 489 str = c_escape_conv_str00 + 3 * ch;
501 str += 4; 490 goto strpr;
502 } while (*str); 491 }
503 492
504 if (isprint_asciionly(*p)) { 493 if (isprint_asciionly(*p)) {
505 *pr->cchar = 'c'; 494 *pr->cchar = 'c';
506 printf(pr->fmt, *p); 495 printf(pr->fmt, *p);
507 } else { 496 } else {
497#if defined(__i386__) || defined(__x86_64__)
498 /* Abuse partial register operations */
499 uint32_t buf;
500 unsigned n = *p;
501 asm ( //00000000 00000000 00000000 aabbbccc
502"\n shll $10,%%eax" //00000000 000000aa bbbccc00 00000000
503"\n shrw $5,%%ax" //00000000 000000aa 00000bbb ccc00000
504"\n shrb $5,%%al" //00000000 000000aa 00000bbb 00000ccc
505"\n shll $8,%%eax" //000000aa 00000bbb 00000ccc 00000000
506"\n bswapl %%eax" //00000000 00000ccc 00000bbb 000000aa
507"\n addl $0x303030,%%eax"
508"\n" : "=a" (n)
509 : "0" (n)
510 );
511 buf = n;
512 str = (void*)&buf;
513#elif 1
508 char buf[4]; 514 char buf[4];
509 /* gcc-8.0.1 needs lots of casts to shut up */ 515 /* gcc-8.0.1 needs lots of casts to shut up */
510 sprintf(buf, "%03o", (unsigned)(uint8_t)*p); 516 sprintf(buf, "%03o", (unsigned)(uint8_t)*p);
511 str = buf; 517 str = buf;
518#else // use faster version? +20 bytes of code relative to sprintf() method
519 char buf[4];
520 buf[3] = '\0';
521 ch = *p;
522 buf[2] = '0' + (ch & 7); ch >>= 3;
523 buf[1] = '0' + (ch & 7); ch >>= 3;
524 buf[0] = '0' + ch;
525 str = buf;
526#endif
512 strpr: 527 strpr:
513 *pr->cchar = 's'; 528 *pr->cchar = 's';
514 printf(pr->fmt, str); 529 printf(pr->fmt, str);
diff --git a/libbb/getopt32.c b/libbb/getopt32.c
index b5efa19ac..4c05dcb97 100644
--- a/libbb/getopt32.c
+++ b/libbb/getopt32.c
@@ -530,6 +530,7 @@ vgetopt32(char **argv, const char *applet_opts, const char *applet_long_options,
530 * "fake" short options, like this one: 530 * "fake" short options, like this one:
531 * wget $'-\203' "Test: test" http://kernel.org/ 531 * wget $'-\203' "Test: test" http://kernel.org/
532 * (supposed to act as --header, but doesn't) */ 532 * (supposed to act as --header, but doesn't) */
533 next_opt:
533#if ENABLE_LONG_OPTS 534#if ENABLE_LONG_OPTS
534 while ((c = getopt_long(argc, argv, applet_opts, 535 while ((c = getopt_long(argc, argv, applet_opts,
535 long_options, NULL)) != -1) { 536 long_options, NULL)) != -1) {
@@ -544,8 +545,16 @@ vgetopt32(char **argv, const char *applet_opts, const char *applet_long_options,
544 * but we construct long opts so that flag 545 * but we construct long opts so that flag
545 * is always NULL (see above) */ 546 * is always NULL (see above) */
546 if (on_off->opt_char == '\0' /* && c != '\0' */) { 547 if (on_off->opt_char == '\0' /* && c != '\0' */) {
547 /* c is probably '?' - "bad option" */ 548 /* We reached the end of complementary[] and did not find -c */
548 goto error; 549 if (c == '?') /* getopt says: "bad option, or option has no required argument" */
550 goto error;
551 /* if there were options beyond 32 bits (example: ls),
552 * they got no complementary[] slot, and no result bit.
553 * IOW: they must be "accept but ignore" options.
554 * For them, we end up here.
555 */
556 //bb_error_msg("ignored option '%c', skipping", c);
557 goto next_opt;
549 } 558 }
550 } 559 }
551 if (flags & on_off->incongruously) 560 if (flags & on_off->incongruously)
diff --git a/libbb/hash_md5_sha.c b/libbb/hash_md5_sha.c
index 75a61c32c..9ebda232a 100644
--- a/libbb/hash_md5_sha.c
+++ b/libbb/hash_md5_sha.c
@@ -11,7 +11,7 @@
11#define STR1(s) #s 11#define STR1(s) #s
12#define STR(s) STR1(s) 12#define STR(s) STR1(s)
13 13
14#define NEED_SHA512 (ENABLE_SHA512SUM || ENABLE_USE_BB_CRYPT_SHA) 14#define NEED_SHA512 (ENABLE_SHA512SUM || ENABLE_SHA384SUM || ENABLE_USE_BB_CRYPT_SHA)
15 15
16#if ENABLE_SHA1_HWACCEL || ENABLE_SHA256_HWACCEL 16#if ENABLE_SHA1_HWACCEL || ENABLE_SHA256_HWACCEL
17# if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) 17# if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
@@ -1032,7 +1032,7 @@ static const sha_K_int sha_K[] ALIGN8 = {
1032 K(0x84c87814a1f0ab72ULL), K(0x8cc702081a6439ecULL), 1032 K(0x84c87814a1f0ab72ULL), K(0x8cc702081a6439ecULL),
1033 K(0x90befffa23631e28ULL), K(0xa4506cebde82bde9ULL), 1033 K(0x90befffa23631e28ULL), K(0xa4506cebde82bde9ULL),
1034 K(0xbef9a3f7b2c67915ULL), K(0xc67178f2e372532bULL), 1034 K(0xbef9a3f7b2c67915ULL), K(0xc67178f2e372532bULL),
1035#if NEED_SHA512 /* [64]+ are used for sha512 only */ 1035#if NEED_SHA512 /* [64]+ are used for sha384 and sha512 only */
1036 K(0xca273eceea26619cULL), K(0xd186b8c721c0c207ULL), 1036 K(0xca273eceea26619cULL), K(0xd186b8c721c0c207ULL),
1037 K(0xeada7dd6cde0eb1eULL), K(0xf57d4f7fee6ed178ULL), 1037 K(0xeada7dd6cde0eb1eULL), K(0xf57d4f7fee6ed178ULL),
1038 K(0x06f067aa72176fbaULL), K(0x0a637dc5a2c898a6ULL), 1038 K(0x06f067aa72176fbaULL), K(0x0a637dc5a2c898a6ULL),
@@ -1229,11 +1229,20 @@ static const uint32_t init512_lo[] ALIGN4 = {
1229 0x137e2179, 1229 0x137e2179,
1230}; 1230};
1231#endif /* NEED_SHA512 */ 1231#endif /* NEED_SHA512 */
1232 1232#if ENABLE_SHA384SUM
1233// Note: SHA-384 is identical to SHA-512, except that initial hash values are 1233static const uint64_t init384[] ALIGN8 = {
1234// 0xcbbb9d5dc1059ed8, 0x629a292a367cd507, 0x9159015a3070dd17, 0x152fecd8f70e5939, 1234 0,
1235// 0x67332667ffc00b31, 0x8eb44a8768581511, 0xdb0c2e0d64f98fa7, 0x47b5481dbefa4fa4, 1235 0,
1236// and the output is constructed by omitting last two 64-bit words of it. 1236 0xcbbb9d5dc1059ed8,
1237 0x629a292a367cd507,
1238 0x9159015a3070dd17,
1239 0x152fecd8f70e5939,
1240 0x67332667ffc00b31,
1241 0x8eb44a8768581511,
1242 0xdb0c2e0d64f98fa7,
1243 0x47b5481dbefa4fa4,
1244};
1245#endif
1237 1246
1238/* Initialize structure containing state of computation. 1247/* Initialize structure containing state of computation.
1239 (FIPS 180-2:5.3.2) */ 1248 (FIPS 180-2:5.3.2) */
@@ -1255,9 +1264,19 @@ void FAST_FUNC sha256_begin(sha256_ctx_t *ctx)
1255#endif 1264#endif
1256} 1265}
1257 1266
1258#if NEED_SHA512 1267#if ENABLE_SHA384SUM
1259/* Initialize structure containing state of computation. 1268/* Initialize structure containing state of computation.
1260 (FIPS 180-2:5.3.3) */ 1269 (FIPS 180-2:5.3.3) */
1270void FAST_FUNC sha384_begin(sha512_ctx_t *ctx)
1271{
1272 memcpy(&ctx->total64, init384, sizeof(init384));
1273 /*ctx->total64[0] = ctx->total64[1] = 0; - already done */
1274}
1275#endif
1276
1277#if NEED_SHA512
1278/* Initialize structure containing state of computation.
1279 (FIPS 180-2:5.3.4) */
1261void FAST_FUNC sha512_begin(sha512_ctx_t *ctx) 1280void FAST_FUNC sha512_begin(sha512_ctx_t *ctx)
1262{ 1281{
1263 int i; 1282 int i;
@@ -1332,7 +1351,7 @@ unsigned FAST_FUNC sha1_end(sha1_ctx_t *ctx, void *resbuf)
1332} 1351}
1333 1352
1334#if NEED_SHA512 1353#if NEED_SHA512
1335unsigned FAST_FUNC sha512_end(sha512_ctx_t *ctx, void *resbuf) 1354static unsigned FAST_FUNC sha512384_end(sha512_ctx_t *ctx, void *resbuf, unsigned outsize)
1336{ 1355{
1337 unsigned bufpos = ctx->total64[0] & 127; 1356 unsigned bufpos = ctx->total64[0] & 127;
1338 1357
@@ -1363,11 +1382,21 @@ unsigned FAST_FUNC sha512_end(sha512_ctx_t *ctx, void *resbuf)
1363 for (i = 0; i < ARRAY_SIZE(ctx->hash); ++i) 1382 for (i = 0; i < ARRAY_SIZE(ctx->hash); ++i)
1364 ctx->hash[i] = SWAP_BE64(ctx->hash[i]); 1383 ctx->hash[i] = SWAP_BE64(ctx->hash[i]);
1365 } 1384 }
1366 memcpy(resbuf, ctx->hash, sizeof(ctx->hash)); 1385 memcpy(resbuf, ctx->hash, outsize);
1367 return sizeof(ctx->hash); 1386 return outsize;
1387}
1388unsigned FAST_FUNC sha512_end(sha384_ctx_t *ctx, void *resbuf)
1389{
1390 return sha512384_end(ctx, resbuf, SHA512_OUTSIZE);
1368} 1391}
1369#endif /* NEED_SHA512 */ 1392#endif /* NEED_SHA512 */
1370 1393
1394#if ENABLE_SHA384SUM
1395unsigned FAST_FUNC sha384_end(sha384_ctx_t *ctx, void *resbuf)
1396{
1397 return sha512384_end(ctx, resbuf, SHA384_OUTSIZE);
1398}
1399#endif
1371 1400
1372/* 1401/*
1373 * The Keccak sponge function, designed by Guido Bertoni, Joan Daemen, 1402 * The Keccak sponge function, designed by Guido Bertoni, Joan Daemen,
@@ -1904,6 +1933,8 @@ void FAST_FUNC sha3_hash(sha3_ctx_t *ctx, const void *buffer, size_t len)
1904 1933
1905unsigned FAST_FUNC sha3_end(sha3_ctx_t *ctx, void *resbuf) 1934unsigned FAST_FUNC sha3_end(sha3_ctx_t *ctx, void *resbuf)
1906{ 1935{
1936 unsigned hash_len;
1937
1907 /* Padding */ 1938 /* Padding */
1908 uint8_t *buf = (uint8_t*)ctx->state; 1939 uint8_t *buf = (uint8_t*)ctx->state;
1909 /* 1940 /*
@@ -1926,6 +1957,7 @@ unsigned FAST_FUNC sha3_end(sha3_ctx_t *ctx, void *resbuf)
1926 sha3_process_block72(ctx->state); 1957 sha3_process_block72(ctx->state);
1927 1958
1928 /* Output */ 1959 /* Output */
1929 memcpy(resbuf, ctx->state, 64); 1960 hash_len = (1600/8 - ctx->input_block_bytes) / 2;
1930 return 64; 1961 memcpy(resbuf, ctx->state, hash_len);
1962 return hash_len;
1931} 1963}
diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index 43d1da35c..10cc0433b 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -1564,7 +1564,7 @@ void FAST_FUNC save_history(line_input_t *st)
1564 FILE *fp; 1564 FILE *fp;
1565 1565
1566 /* bash compat: HISTFILE="" disables history saving */ 1566 /* bash compat: HISTFILE="" disables history saving */
1567 if (!st || !st->hist_file || !state->hist_file[0]) 1567 if (!st || !st->hist_file || !st->hist_file[0])
1568 return; 1568 return;
1569 if (st->cnt_history <= st->cnt_history_in_file) 1569 if (st->cnt_history <= st->cnt_history_in_file)
1570 return; /* no new entries were added */ 1570 return; /* no new entries were added */
diff --git a/libbb/procps.c b/libbb/procps.c
index f56b71b21..fc31c075d 100644
--- a/libbb/procps.c
+++ b/libbb/procps.c
@@ -109,7 +109,7 @@ void FAST_FUNC free_procps_scan(procps_status_t* sp)
109} 109}
110 110
111#if ENABLE_FEATURE_TOPMEM || ENABLE_PMAP 111#if ENABLE_FEATURE_TOPMEM || ENABLE_PMAP
112static unsigned long long fast_strtoull_16(char **endptr) 112unsigned long long FAST_FUNC fast_strtoull_16(char **endptr)
113{ 113{
114 unsigned char c; 114 unsigned char c;
115 char *str = *endptr; 115 char *str = *endptr;
@@ -130,7 +130,7 @@ static unsigned long long fast_strtoull_16(char **endptr)
130 130
131#if ENABLE_FEATURE_FAST_TOP || ENABLE_FEATURE_TOPMEM || ENABLE_PMAP 131#if ENABLE_FEATURE_FAST_TOP || ENABLE_FEATURE_TOPMEM || ENABLE_PMAP
132/* We cut a lot of corners here for speed */ 132/* We cut a lot of corners here for speed */
133static unsigned long fast_strtoul_10(char **endptr) 133unsigned long FAST_FUNC fast_strtoul_10(char **endptr)
134{ 134{
135 unsigned char c; 135 unsigned char c;
136 char *str = *endptr; 136 char *str = *endptr;
@@ -143,6 +143,24 @@ static unsigned long fast_strtoul_10(char **endptr)
143 *endptr = str + 1; /* We skip trailing space! */ 143 *endptr = str + 1; /* We skip trailing space! */
144 return n; 144 return n;
145} 145}
146# if LONG_MAX < LLONG_MAX
147/* For VSZ, which can be very large */
148static unsigned long long fast_strtoull_10(char **endptr)
149{
150 unsigned char c;
151 char *str = *endptr;
152 unsigned long long n = *str - '0';
153
154 /* Need to stop on both ' ' and '\n' */
155 while ((c = *++str) > ' ')
156 n = n*10 + (c - '0');
157
158 *endptr = str + 1; /* We skip trailing space! */
159 return n;
160}
161# else
162# define fast_strtoull_10(endptr) fast_strtoul_10(endptr)
163# endif
146 164
147# if ENABLE_FEATURE_FAST_TOP 165# if ENABLE_FEATURE_FAST_TOP
148static long fast_strtol_10(char **endptr) 166static long fast_strtol_10(char **endptr)
@@ -155,7 +173,7 @@ static long fast_strtol_10(char **endptr)
155} 173}
156# endif 174# endif
157 175
158static char *skip_fields(char *str, int count) 176char* FAST_FUNC skip_fields(char *str, int count)
159{ 177{
160 do { 178 do {
161 while (*str++ != ' ') 179 while (*str++ != ' ')
@@ -166,35 +184,25 @@ static char *skip_fields(char *str, int count)
166} 184}
167#endif 185#endif
168 186
169#if ENABLE_FEATURE_TOPMEM || ENABLE_PMAP 187#if ENABLE_FEATURE_TOPMEM
170static char* skip_whitespace_if_prefixed_with(char *buf, const char *prefix) 188static NOINLINE void procps_read_smaps(pid_t pid, procps_status_t *sp)
171{ 189{
172 char *tp = is_prefixed_with(buf, prefix); 190 // There is A LOT of /proc/PID/smaps data on a big system.
173 if (tp) { 191 // Optimize this for speed, makes "top -m" faster.
174 tp = skip_whitespace(tp); 192//TODO large speedup:
175 } 193//read /proc/PID/smaps_rollup (cumulative stats of all mappings, much faster)
176 return tp; 194//and /proc/PID/maps to get mapped_ro and mapped_rw (IOW: VSZ,VSZRW)
177}
178 195
179int FAST_FUNC procps_read_smaps(pid_t pid, struct smaprec *total,
180 void (*cb)(struct smaprec *, void *), void *data)
181{
182 FILE *file; 196 FILE *file;
183 struct smaprec currec;
184 char filename[sizeof("/proc/%u/smaps") + sizeof(int)*3]; 197 char filename[sizeof("/proc/%u/smaps") + sizeof(int)*3];
185 char buf[PROCPS_BUFSIZE]; 198 char buf[PROCPS_BUFSIZE];
186#if !ENABLE_PMAP
187 void (*cb)(struct smaprec *, void *) = NULL;
188 void *data = NULL;
189#endif
190 199
191 sprintf(filename, "/proc/%u/smaps", (int)pid); 200 sprintf(filename, "/proc/%u/smaps", (int)pid);
192 201
193 file = fopen_for_read(filename); 202 file = fopen_for_read(filename);
194 if (!file) 203 if (!file)
195 return 1; 204 return;
196 205
197 memset(&currec, 0, sizeof(currec));
198 while (fgets(buf, PROCPS_BUFSIZE, file)) { 206 while (fgets(buf, PROCPS_BUFSIZE, file)) {
199 // Each mapping datum has this form: 207 // Each mapping datum has this form:
200 // f7d29000-f7d39000 rw-s FILEOFS M:m INODE FILENAME 208 // f7d29000-f7d39000 rw-s FILEOFS M:m INODE FILENAME
@@ -202,80 +210,53 @@ int FAST_FUNC procps_read_smaps(pid_t pid, struct smaprec *total,
202 // Rss: nnn kB 210 // Rss: nnn kB
203 // ..... 211 // .....
204 212
205 char *tp, *p; 213 char *tp;
206 214
215 if (buf[0] == 'S' || buf[0] == 'P') {
207#define SCAN(S, X) \ 216#define SCAN(S, X) \
208 if ((tp = skip_whitespace_if_prefixed_with(buf, S)) != NULL) { \ 217 if (memcmp(buf, S, sizeof(S)-1) == 0) { \
209 total->X += currec.X = fast_strtoul_10(&tp); \ 218 tp = skip_whitespace(buf + sizeof(S)-1); \
210 continue; \ 219 sp->X += fast_strtoul_10(&tp); \
211 } 220 continue; \
212 if (cb) { 221 }
213 SCAN("Pss:" , smap_pss ); 222 SCAN("Private_Dirty:", private_dirty)
214 SCAN("Swap:" , smap_swap ); 223 SCAN("Private_Clean:", private_clean)
215 } 224 SCAN("Shared_Dirty:" , shared_dirty )
216 SCAN("Private_Dirty:", private_dirty); 225 SCAN("Shared_Clean:" , shared_clean )
217 SCAN("Private_Clean:", private_clean);
218 SCAN("Shared_Dirty:" , shared_dirty );
219 SCAN("Shared_Clean:" , shared_clean );
220#undef SCAN 226#undef SCAN
227 }
221 tp = strchr(buf, '-'); 228 tp = strchr(buf, '-');
222 if (tp) { 229 if (tp) {
223 // We reached next mapping - the line of this form: 230 // We reached next mapping - the line of this form:
224 // f7d29000-f7d39000 rw-s FILEOFS M:m INODE FILENAME 231 // f7d29000-f7d39000 rw-s FILEOFS M:m INODE FILENAME
225 232
226 if (cb) { 233 char *rwx;
227 /* If we have a previous record, there's nothing more 234 unsigned long sz;
228 * for it, call the callback and clear currec
229 */
230 if (currec.smap_size)
231 cb(&currec, data);
232 free(currec.smap_name);
233 }
234 memset(&currec, 0, sizeof(currec));
235 235
236 *tp = ' '; 236 *tp = ' ';
237 tp = buf; 237 tp = buf;
238 currec.smap_start = fast_strtoull_16(&tp); 238 sz = fast_strtoull_16(&tp); // start
239 currec.smap_size = (fast_strtoull_16(&tp) - currec.smap_start) >> 10; 239 sz = (fast_strtoull_16(&tp) - sz) >> 10; // end - start
240 240 // tp -> "rw-s" string
241 strncpy(currec.smap_mode, tp, sizeof(currec.smap_mode)-1); 241 rwx = tp;
242
243 // skipping "rw-s FILEOFS M:m INODE " 242 // skipping "rw-s FILEOFS M:m INODE "
244 tp = skip_whitespace(skip_fields(tp, 4)); 243 tp = skip_whitespace(skip_fields(tp, 4));
245 // filter out /dev/something (something != zero) 244 // if not a device memory mapped...
246 if (!is_prefixed_with(tp, "/dev/") || strcmp(tp, "/dev/zero\n") == 0) { 245 if (memcmp(tp, "/dev/", 5) != 0 // not "/dev/something"
247 if (currec.smap_mode[1] == 'w') { 246 || strcmp(tp + 5, "zero\n") == 0 // or is "/dev/zero" (which isn't a device)
248 currec.mapped_rw = currec.smap_size; 247 ) {
249 total->mapped_rw += currec.smap_size; 248 if (rwx[1] == 'w')
250 } else if (currec.smap_mode[1] == '-') { 249 sp->mapped_rw += sz;
251 currec.mapped_ro = currec.smap_size; 250 else if (rwx[0] == 'r' || rwx[2] == 'x')
252 total->mapped_ro += currec.smap_size; 251 sp->mapped_ro += sz;
253 } 252 // else: seen "---p" mappings (mmap guard gaps?),
253 // do NOT account these as VSZ, they aren't really
254 } 254 }
255
256 if (strcmp(tp, "[stack]\n") == 0) 255 if (strcmp(tp, "[stack]\n") == 0)
257 total->stack += currec.smap_size; 256 sp->stack += sz;
258 if (cb) {
259 p = skip_non_whitespace(tp);
260 if (p == tp) {
261 currec.smap_name = xstrdup(" [ anon ]");
262 } else {
263 *p = '\0';
264 currec.smap_name = xstrdup(tp);
265 }
266 }
267 total->smap_size += currec.smap_size;
268 } 257 }
269 } 258 }
270 fclose(file); 259 fclose(file);
271
272 if (cb) {
273 if (currec.smap_size)
274 cb(&currec, data);
275 free(currec.smap_name);
276 }
277
278 return 0;
279} 260}
280#endif 261#endif
281 262
@@ -370,7 +351,8 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags)
370 char *cp, *comm1; 351 char *cp, *comm1;
371 int tty; 352 int tty;
372#if !ENABLE_FEATURE_FAST_TOP 353#if !ENABLE_FEATURE_FAST_TOP
373 unsigned long vsz, rss; 354 unsigned long long vsz;
355 unsigned long rss;
374#endif 356#endif
375 /* see proc(5) for some details on this */ 357 /* see proc(5) for some details on this */
376 strcpy(filename_tail, "stat"); 358 strcpy(filename_tail, "stat");
@@ -396,7 +378,7 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags)
396 "%ld " /* nice */ 378 "%ld " /* nice */
397 "%*s %*s " /* timeout, it_real_value */ 379 "%*s %*s " /* timeout, it_real_value */
398 "%lu " /* start_time */ 380 "%lu " /* start_time */
399 "%lu " /* vsize */ 381 "%llu " /* vsize - can be very large */
400 "%lu " /* rss */ 382 "%lu " /* rss */
401# if ENABLE_FEATURE_TOP_SMP_PROCESS 383# if ENABLE_FEATURE_TOP_SMP_PROCESS
402 "%*s %*s %*s %*s %*s %*s " /*rss_rlim, start_code, end_code, start_stack, kstk_esp, kstk_eip */ 384 "%*s %*s %*s %*s %*s %*s " /*rss_rlim, start_code, end_code, start_stack, kstk_esp, kstk_eip */
@@ -449,7 +431,7 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags)
449 cp = skip_fields(cp, 2); /* timeout, it_real_value */ 431 cp = skip_fields(cp, 2); /* timeout, it_real_value */
450 sp->start_time = fast_strtoul_10(&cp); 432 sp->start_time = fast_strtoul_10(&cp);
451 /* vsz is in bytes and we want kb */ 433 /* vsz is in bytes and we want kb */
452 sp->vsz = fast_strtoul_10(&cp) >> 10; 434 sp->vsz = fast_strtoull_10(&cp) >> 10;
453 /* vsz is in bytes but rss is in *PAGES*! Can you believe that? */ 435 /* vsz is in bytes but rss is in *PAGES*! Can you believe that? */
454 sp->rss = fast_strtoul_10(&cp) << sp->shift_pages_to_kb; 436 sp->rss = fast_strtoul_10(&cp) << sp->shift_pages_to_kb;
455# if ENABLE_FEATURE_TOP_SMP_PROCESS 437# if ENABLE_FEATURE_TOP_SMP_PROCESS
@@ -483,7 +465,7 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags)
483 465
484#if ENABLE_FEATURE_TOPMEM 466#if ENABLE_FEATURE_TOPMEM
485 if (flags & PSSCAN_SMAPS) 467 if (flags & PSSCAN_SMAPS)
486 procps_read_smaps(pid, &sp->smaps, NULL, NULL); 468 procps_read_smaps(pid, sp);
487#endif /* TOPMEM */ 469#endif /* TOPMEM */
488#if ENABLE_FEATURE_PS_ADDITIONAL_COLUMNS 470#if ENABLE_FEATURE_PS_ADDITIONAL_COLUMNS
489 if (flags & PSSCAN_RUIDGID) { 471 if (flags & PSSCAN_RUIDGID) {
@@ -566,36 +548,45 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags)
566 return sp; 548 return sp;
567} 549}
568 550
569void FAST_FUNC read_cmdline(char *buf, int col, unsigned pid, const char *comm) 551int FAST_FUNC read_cmdline(char *buf, int col, unsigned pid, const char *comm)
570{ 552{
571 int sz; 553 int sz;
572 char filename[sizeof("/proc/%u/cmdline") + sizeof(int)*3]; 554 char filename[sizeof("/proc/%u/cmdline") + sizeof(int)*3];
573 555
574 sprintf(filename, "/proc/%u/cmdline", pid); 556 sprintf(filename, "/proc/%u/cmdline", pid);
575 sz = open_read_close(filename, buf, col - 1); 557 sz = open_read_close(filename, buf, col - 1);
558 if (sz < 0)
559 return sz;
576 if (sz > 0) { 560 if (sz > 0) {
577 const char *base; 561 const char *program_basename;
578 int comm_len; 562 int comm_len;
579 563
580 buf[sz] = '\0'; 564 buf[sz] = '\0';
581 while (--sz >= 0 && buf[sz] == '\0') 565 while (--sz >= 0 && buf[sz] == '\0')
582 continue; 566 continue;
583 /* Prevent basename("process foo/bar") = "bar" */ 567
584 strchrnul(buf, ' ')[0] = '\0'; 568 /* Find "program" in "[-][/PATH/TO/]program" */
585 base = bb_basename(buf); /* before we replace argv0's NUL with space */ 569 strchrnul(buf, ' ')[0] = '\0'; /* prevent basename("program foo/bar") = "bar" */
570 program_basename = bb_basename(buf[0] == '-' ? buf + 1 : buf);
571 /* ^^^ note: must do it *before* replacing argv0's NUL with space */
572
573 /* Prevent stuff like this:
574 * echo 'sleep 999; exit' >`printf '\ec'`; sh ?c
575 * messing up top and ps output (or worse).
576 * This also replaces NULs with spaces, converting
577 * list of NUL-strings into one string.
578 */
586 while (sz >= 0) { 579 while (sz >= 0) {
587 if ((unsigned char)(buf[sz]) < ' ') 580 if ((unsigned char)(buf[sz]) < ' ')
588 buf[sz] = ' '; 581 buf[sz] = ' ';
589 sz--; 582 sz--;
590 } 583 }
591 if (base[0] == '-') /* "-sh" (login shell)? */
592 base++;
593 584
594 /* If comm differs from argv0, prepend "{comm} ". 585 /* If comm differs from argv0, prepend "{comm} ".
595 * It allows to see thread names set by prctl(PR_SET_NAME). 586 * It allows to see thread names set by prctl(PR_SET_NAME).
596 */ 587 */
597 if (!comm) 588 if (!comm)
598 return; 589 return 0;
599 comm_len = strlen(comm); 590 comm_len = strlen(comm);
600 /* Why compare up to comm_len, not COMM_LEN-1? 591 /* Why compare up to comm_len, not COMM_LEN-1?
601 * Well, some processes rewrite argv, and use _spaces_ there 592 * Well, some processes rewrite argv, and use _spaces_ there
@@ -603,19 +594,20 @@ void FAST_FUNC read_cmdline(char *buf, int col, unsigned pid, const char *comm)
603 * I prefer to still treat argv0 "process foo bar" 594 * I prefer to still treat argv0 "process foo bar"
604 * as 'equal' to comm "process". 595 * as 'equal' to comm "process".
605 */ 596 */
606 if (strncmp(base, comm, comm_len) != 0) { 597 if (strncmp(program_basename, comm, comm_len) != 0) {
607 comm_len += 3; 598 comm_len += 3;
608 if (col > comm_len) 599 if (col > comm_len)
609 memmove(buf + comm_len, buf, col - comm_len); 600 memmove(buf + comm_len, buf, col - comm_len);
610 snprintf(buf, col, "{%s}", comm); 601 snprintf(buf, col, "{%s}", comm);
611 if (col <= comm_len) 602 if (col <= comm_len)
612 return; 603 return 0;
613 buf[comm_len - 1] = ' '; 604 buf[comm_len - 1] = ' ';
614 buf[col - 1] = '\0'; 605 buf[col - 1] = '\0';
615 } 606 }
616 } else { 607 } else {
617 snprintf(buf, col, "[%s]", comm ? comm : "?"); 608 snprintf(buf, col, "[%s]", comm ? comm : "?");
618 } 609 }
610 return 0;
619} 611}
620 612
621/* from kernel: 613/* from kernel:
diff --git a/libbb/replace.c b/libbb/replace.c
index 6183d3e6f..bc26b04cc 100644
--- a/libbb/replace.c
+++ b/libbb/replace.c
@@ -46,3 +46,17 @@ char* FAST_FUNC xmalloc_substitute_string(const char *src, int count, const char
46 //dbg_msg("subst9:'%s'", buf); 46 //dbg_msg("subst9:'%s'", buf);
47 return buf; 47 return buf;
48} 48}
49
50#if 0 /* inlined in libbb.h */
51/* Returns strlen as a bonus */
52size_t FAST_FUNC replace_char(char *str, char from, char to)
53{
54 char *p = str;
55 while (*p) {
56 if (*p == from)
57 *p = to;
58 p++;
59 }
60 return p - str;
61}
62#endif
diff --git a/libbb/yescrypt/alg-sha256.c b/libbb/yescrypt/alg-sha256.c
index 20e8d1ee4..dc748c968 100644
--- a/libbb/yescrypt/alg-sha256.c
+++ b/libbb/yescrypt/alg-sha256.c
@@ -47,9 +47,12 @@ PBKDF2_SHA256(const uint8_t *passwd, size_t passwdlen,
47 47
48 /* Iterate through the blocks. */ 48 /* Iterate through the blocks. */
49 for (i = 0; dkLen != 0; ) { 49 for (i = 0; dkLen != 0; ) {
50 uint64_t U[32 / 8]; 50 long U[32 / sizeof(long)];
51 uint64_t T[32 / 8]; 51 long T[32 / sizeof(long)];
52 uint64_t j; 52// Do not make these ^^ uint64_t[]. Keep them long[].
53// Even though the XORing loop below is optimized out,
54// gcc is not smart enough to realize that 64-bit alignment of the stack
55// is no longer useful, and generates ~50 more bytes of code on i386...
53 uint32_t ivec; 56 uint32_t ivec;
54 size_t clen; 57 size_t clen;
55 int k; 58 int k;
@@ -64,13 +67,15 @@ PBKDF2_SHA256(const uint8_t *passwd, size_t passwdlen,
64//does libbb need a non-vararg version with just one (buf,len)? 67//does libbb need a non-vararg version with just one (buf,len)?
65 68
66 if (c > 1) { 69 if (c > 1) {
70//in yescrypt, c is always 1, so this if() branch is optimized out
71 uint64_t j;
67 /* T_i = U_1 ... */ 72 /* T_i = U_1 ... */
68 memcpy(U, T, 32); 73 memcpy(U, T, 32);
69 for (j = 2; j <= c; j++) { 74 for (j = 2; j <= c; j++) {
70 /* Compute U_j. */ 75 /* Compute U_j. */
71 hmac_peek_hash(&Phctx, (void*)U, U, 32, NULL); 76 hmac_peek_hash(&Phctx, (void*)U, U, 32, NULL);
72 /* ... xor U_j ... */ 77 /* ... xor U_j ... */
73 for (k = 0; k < 32 / 8; k++) 78 for (k = 0; k < 32 / sizeof(long); k++)
74 T[k] ^= U[k]; 79 T[k] ^= U[k];
75 //TODO: xorbuf32_aligned_long(T, U); 80 //TODO: xorbuf32_aligned_long(T, U);
76 } 81 }