aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2021-08-22 09:17:10 +0100
committerRon Yorston <rmy@pobox.com>2021-08-22 09:17:10 +0100
commit46c5767e7e39d1e173e382bda86ab88b4cad354d (patch)
treed22c7f2376527aebd556eec36e115f037f8a467e
parentf13defb1c8f892ecf3e8dd5dbe486cc2b53e6f03 (diff)
parent74c4f356aee9c64978a881e5760055d0e3510a6a (diff)
downloadbusybox-w32-46c5767e7e39d1e173e382bda86ab88b4cad354d.tar.gz
busybox-w32-46c5767e7e39d1e173e382bda86ab88b4cad354d.tar.bz2
busybox-w32-46c5767e7e39d1e173e382bda86ab88b4cad354d.zip
Merge branch 'busybox' into merge
-rw-r--r--Makefile2
-rw-r--r--archival/chksum_and_xwrite_tar_header.c35
-rw-r--r--archival/tar.c31
-rw-r--r--editors/vi.c192
-rw-r--r--include/bb_archive.h1
-rw-r--r--networking/udhcp/common.h12
-rw-r--r--procps/smemcap.c16
-rwxr-xr-xtestsuite/rev.tests46
-rw-r--r--util-linux/rev.c1
9 files changed, 194 insertions, 142 deletions
diff --git a/Makefile b/Makefile
index 5fe327519..65a548f6f 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
1VERSION = 1 1VERSION = 1
2PATCHLEVEL = 34 2PATCHLEVEL = 35
3SUBLEVEL = 0 3SUBLEVEL = 0
4EXTRAVERSION = .git 4EXTRAVERSION = .git
5NAME = Unnamed 5NAME = Unnamed
diff --git a/archival/chksum_and_xwrite_tar_header.c b/archival/chksum_and_xwrite_tar_header.c
new file mode 100644
index 000000000..25934f898
--- /dev/null
+++ b/archival/chksum_and_xwrite_tar_header.c
@@ -0,0 +1,35 @@
1/*
2 * Copyright (C) 2021 Denys Vlasenko <vda.linux@googlemail.com>
3 *
4 * Licensed under GPLv2, see file LICENSE in this source tree.
5 */
6//kbuild:lib-$(CONFIG_FEATURE_TAR_CREATE) += chksum_and_xwrite_tar_header.o
7//kbuild:lib-$(CONFIG_SMEMCAP) += chksum_and_xwrite_tar_header.o
8
9#include "libbb.h"
10#include "bb_archive.h"
11
12void FAST_FUNC chksum_and_xwrite_tar_header(int fd, struct tar_header_t *hp)
13{
14 /* POSIX says that checksum is done on unsigned bytes
15 * (Sun and HP-UX gets it wrong... more details in
16 * GNU tar source) */
17 const unsigned char *cp;
18 int chksum, size;
19
20 strcpy(hp->magic, "ustar ");
21
22 /* Calculate and store the checksum (the sum of all of the bytes of
23 * the header). The checksum field must be filled with blanks for the
24 * calculation. The checksum field is formatted differently from the
25 * other fields: it has 6 digits, a NUL, then a space -- rather than
26 * digits, followed by a NUL like the other fields... */
27 memset(hp->chksum, ' ', sizeof(hp->chksum));
28 cp = (const unsigned char *) hp;
29 chksum = 0;
30 size = sizeof(*hp);
31 do { chksum += *cp++; } while (--size);
32 sprintf(hp->chksum, "%06o", chksum);
33
34 xwrite(fd, hp, sizeof(*hp));
35}
diff --git a/archival/tar.c b/archival/tar.c
index 67c90e6fd..054640c01 100644
--- a/archival/tar.c
+++ b/archival/tar.c
@@ -256,32 +256,6 @@ static void putOctal(char *cp, int len, off_t value)
256} 256}
257#define PUT_OCTAL(a, b) putOctal((a), sizeof(a), (b)) 257#define PUT_OCTAL(a, b) putOctal((a), sizeof(a), (b))
258 258
259static void chksum_and_xwrite(int fd, struct tar_header_t* hp)
260{
261 /* POSIX says that checksum is done on unsigned bytes
262 * (Sun and HP-UX gets it wrong... more details in
263 * GNU tar source) */
264 const unsigned char *cp;
265 int chksum, size;
266
267 strcpy(hp->magic, "ustar ");
268
269 /* Calculate and store the checksum (i.e., the sum of all of the bytes of
270 * the header). The checksum field must be filled with blanks for the
271 * calculation. The checksum field is formatted differently from the
272 * other fields: it has 6 digits, a null, then a space -- rather than
273 * digits, followed by a null like the other fields... */
274 memset(hp->chksum, ' ', sizeof(hp->chksum));
275 cp = (const unsigned char *) hp;
276 chksum = 0;
277 size = sizeof(*hp);
278 do { chksum += *cp++; } while (--size);
279 putOctal(hp->chksum, sizeof(hp->chksum)-1, chksum);
280
281 /* Now write the header out to disk */
282 xwrite(fd, hp, sizeof(*hp));
283}
284
285# if ENABLE_FEATURE_TAR_GNU_EXTENSIONS 259# if ENABLE_FEATURE_TAR_GNU_EXTENSIONS
286static void writeLongname(int fd, int type, const char *name, int dir) 260static void writeLongname(int fd, int type, const char *name, int dir)
287{ 261{
@@ -312,7 +286,7 @@ static void writeLongname(int fd, int type, const char *name, int dir)
312 /* + dir: account for possible '/' */ 286 /* + dir: account for possible '/' */
313 287
314 PUT_OCTAL(header.size, size); 288 PUT_OCTAL(header.size, size);
315 chksum_and_xwrite(fd, &header); 289 chksum_and_xwrite_tar_header(fd, &header);
316 290
317 /* Write filename[/] and pad the block. */ 291 /* Write filename[/] and pad the block. */
318 /* dir=0: writes 'name<NUL>', pads */ 292 /* dir=0: writes 'name<NUL>', pads */
@@ -443,8 +417,7 @@ static int writeTarHeader(struct TarBallInfo *tbInfo,
443 header_name, S_ISDIR(statbuf->st_mode)); 417 header_name, S_ISDIR(statbuf->st_mode));
444# endif 418# endif
445 419
446 /* Now write the header out to disk */ 420 chksum_and_xwrite_tar_header(tbInfo->tarFd, &header);
447 chksum_and_xwrite(tbInfo->tarFd, &header);
448 421
449 /* Now do the verbose thing (or not) */ 422 /* Now do the verbose thing (or not) */
450 if (tbInfo->verboseFlag) { 423 if (tbInfo->verboseFlag) {
diff --git a/editors/vi.c b/editors/vi.c
index c5dff3fee..c791a32e1 100644
--- a/editors/vi.c
+++ b/editors/vi.c
@@ -7,7 +7,7 @@
7 */ 7 */
8// 8//
9//Things To Do: 9//Things To Do:
10// $HOME/.exrc and ./.exrc 10// ./.exrc
11// add magic to search /foo.*bar 11// add magic to search /foo.*bar
12// add :help command 12// add :help command
13// :map macros 13// :map macros
@@ -185,7 +185,7 @@
185//usage:#define vi_full_usage "\n\n" 185//usage:#define vi_full_usage "\n\n"
186//usage: "Edit FILE\n" 186//usage: "Edit FILE\n"
187//usage: IF_FEATURE_VI_COLON( 187//usage: IF_FEATURE_VI_COLON(
188//usage: "\n -c CMD Initial command to run ($EXINIT also available)" 188//usage: "\n -c CMD Initial command to run ($EXINIT and ~/.exrc also available)"
189//usage: ) 189//usage: )
190//usage: IF_FEATURE_VI_READONLY( 190//usage: IF_FEATURE_VI_READONLY(
191//usage: "\n -R Read-only" 191//usage: "\n -R Read-only"
@@ -201,6 +201,7 @@
201 201
202// the CRASHME code is unmaintained, and doesn't currently build 202// the CRASHME code is unmaintained, and doesn't currently build
203#define ENABLE_FEATURE_VI_CRASHME 0 203#define ENABLE_FEATURE_VI_CRASHME 0
204#define IF_FEATURE_VI_CRASHME(...)
204 205
205 206
206#if ENABLE_LOCALE_SUPPORT 207#if ENABLE_LOCALE_SUPPORT
@@ -405,7 +406,7 @@ struct globals {
405 int cindex; // saved character index for up/down motion 406 int cindex; // saved character index for up/down motion
406 smallint keep_index; // retain saved character index 407 smallint keep_index; // retain saved character index
407#if ENABLE_FEATURE_VI_COLON 408#if ENABLE_FEATURE_VI_COLON
408 char *initial_cmds[3]; // currently 2 entries, NULL terminated 409 llist_t *initial_cmds;
409#endif 410#endif
410 // Should be just enough to hold a key sequence, 411 // Should be just enough to hold a key sequence,
411 // but CRASHME mode uses it as generated command buffer too 412 // but CRASHME mode uses it as generated command buffer too
@@ -1405,21 +1406,14 @@ static void print_literal(char *buf, const char *s)
1405 char *d; 1406 char *d;
1406 unsigned char c; 1407 unsigned char c;
1407 1408
1408 buf[0] = '\0';
1409 if (!s[0]) 1409 if (!s[0])
1410 s = "(NULL)"; 1410 s = "(NULL)";
1411 1411
1412 d = buf; 1412 d = buf;
1413 for (; *s; s++) { 1413 for (; *s; s++) {
1414 int c_is_no_print;
1415
1416 c = *s; 1414 c = *s;
1417 c_is_no_print = (c & 0x80) && !Isprint(c); 1415 if ((c & 0x80) && !Isprint(c))
1418 if (c_is_no_print) { 1416 c = '?';
1419 strcpy(d, ESC_NORM_TEXT);
1420 d += sizeof(ESC_NORM_TEXT)-1;
1421 c = '.';
1422 }
1423 if (c < ' ' || c == 0x7f) { 1417 if (c < ' ' || c == 0x7f) {
1424 *d++ = '^'; 1418 *d++ = '^';
1425 c |= '@'; // 0x40 1419 c |= '@'; // 0x40
@@ -1428,14 +1422,6 @@ static void print_literal(char *buf, const char *s)
1428 } 1422 }
1429 *d++ = c; 1423 *d++ = c;
1430 *d = '\0'; 1424 *d = '\0';
1431 if (c_is_no_print) {
1432 strcpy(d, ESC_BOLD_TEXT);
1433 d += sizeof(ESC_BOLD_TEXT)-1;
1434 }
1435 if (*s == '\n') {
1436 *d++ = '$';
1437 *d = '\0';
1438 }
1439 if (d - buf > MAX_INPUT_LEN - 10) // paranoia 1425 if (d - buf > MAX_INPUT_LEN - 10) // paranoia
1440 break; 1426 break;
1441 } 1427 }
@@ -2592,8 +2578,13 @@ static char *get_one_address(char *p, int *result) // get colon addr, if present
2592 dir = ((unsigned)BACK << 1) | FULL; 2578 dir = ((unsigned)BACK << 1) | FULL;
2593 } 2579 }
2594 q = char_search(q, last_search_pattern + 1, dir); 2580 q = char_search(q, last_search_pattern + 1, dir);
2595 if (q == NULL) 2581 if (q == NULL) {
2596 return NULL; 2582 // no match, continue from other end of file
2583 q = char_search(dir > 0 ? text : end - 1,
2584 last_search_pattern + 1, dir);
2585 if (q == NULL)
2586 return NULL;
2587 }
2597 new_addr = count_lines(text, q); 2588 new_addr = count_lines(text, q);
2598 } 2589 }
2599# endif 2590# endif
@@ -2894,10 +2885,12 @@ static void colon(char *buf)
2894 // :!<cmd> // run <cmd> then return 2885 // :!<cmd> // run <cmd> then return
2895 // 2886 //
2896 2887
2897 if (!buf[0]) 2888 while (*buf == ':')
2898 goto ret; 2889 buf++; // move past leading colons
2899 if (*buf == ':') 2890 while (isblank(*buf))
2900 buf++; // move past the ':' 2891 buf++; // move past leading blanks
2892 if (!buf[0] || buf[0] == '"')
2893 goto ret; // ignore empty lines or those starting with '"'
2901 2894
2902 li = i = 0; 2895 li = i = 0;
2903 b = e = -1; 2896 b = e = -1;
@@ -4155,8 +4148,8 @@ static void do_cmd(int c)
4155#endif 4148#endif
4156 } 4149 }
4157 } 4150 }
4158 } else /* if (c == '>') */ { 4151 } else if (/* c == '>' && */ p != end_line(p)) {
4159 // shift right -- add tab or tabstop spaces 4152 // shift right -- add tab or tabstop spaces on non-empty lines
4160 char_insert(p, '\t', allow_undo); 4153 char_insert(p, '\t', allow_undo);
4161 } 4154 }
4162#if ENABLE_FEATURE_VI_UNDO 4155#if ENABLE_FEATURE_VI_UNDO
@@ -4774,6 +4767,21 @@ static void crash_test()
4774} 4767}
4775#endif 4768#endif
4776 4769
4770#if ENABLE_FEATURE_VI_COLON
4771static void run_cmds(char *p)
4772{
4773 while (p) {
4774 char *q = p;
4775 p = strchr(q, '\n');
4776 if (p)
4777 while (*p == '\n')
4778 *p++ = '\0';
4779 if (strlen(q) < MAX_INPUT_LEN)
4780 colon(q);
4781 }
4782}
4783#endif
4784
4777static void edit_file(char *fn) 4785static void edit_file(char *fn)
4778{ 4786{
4779#if ENABLE_FEATURE_VI_YANKMARK 4787#if ENABLE_FEATURE_VI_YANKMARK
@@ -4844,25 +4852,8 @@ static void edit_file(char *fn)
4844#endif 4852#endif
4845 4853
4846#if ENABLE_FEATURE_VI_COLON 4854#if ENABLE_FEATURE_VI_COLON
4847 { 4855 while (initial_cmds)
4848 char *p, *q; 4856 run_cmds((char *)llist_pop(&initial_cmds));
4849 int n = 0;
4850
4851 while ((p = initial_cmds[n]) != NULL) {
4852 do {
4853 q = p;
4854 p = strchr(q, '\n');
4855 if (p)
4856 while (*p == '\n')
4857 *p++ = '\0';
4858 if (*q)
4859 colon(q);
4860 } while (p);
4861 free(initial_cmds[n]);
4862 initial_cmds[n] = NULL;
4863 n++;
4864 }
4865 }
4866#endif 4857#endif
4867 redraw(FALSE); // dont force every col re-draw 4858 redraw(FALSE); // dont force every col re-draw
4868 //------This is the main Vi cmd handling loop ----------------------- 4859 //------This is the main Vi cmd handling loop -----------------------
@@ -4925,10 +4916,29 @@ static void edit_file(char *fn)
4925#undef cur_line 4916#undef cur_line
4926} 4917}
4927 4918
4919#define VI_OPTSTR \
4920 IF_FEATURE_VI_CRASHME("C") \
4921 IF_FEATURE_VI_COLON("c:*") \
4922 "Hh" \
4923 IF_FEATURE_VI_READONLY("R")
4924
4925enum {
4926 IF_FEATURE_VI_CRASHME(OPTBIT_C,)
4927 IF_FEATURE_VI_COLON(OPTBIT_c,)
4928 OPTBIT_H,
4929 OPTBIT_h,
4930 IF_FEATURE_VI_READONLY(OPTBIT_R,)
4931 OPT_C = IF_FEATURE_VI_CRASHME( (1 << OPTBIT_C)) + 0,
4932 OPT_c = IF_FEATURE_VI_COLON( (1 << OPTBIT_c)) + 0,
4933 OPT_H = 1 << OPTBIT_H,
4934 OPT_h = 1 << OPTBIT_h,
4935 OPT_R = IF_FEATURE_VI_READONLY( (1 << OPTBIT_R)) + 0,
4936};
4937
4928int vi_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 4938int vi_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
4929int vi_main(int argc, char **argv) 4939int vi_main(int argc, char **argv)
4930{ 4940{
4931 int c; 4941 int opts;
4932 4942
4933 INIT_G(); 4943 INIT_G();
4934 4944
@@ -4952,50 +4962,62 @@ int vi_main(int argc, char **argv)
4952 4962
4953 // 0: all of our options are disabled by default in vim 4963 // 0: all of our options are disabled by default in vim
4954 //vi_setops = 0; 4964 //vi_setops = 0;
4955 // 1- process EXINIT variable from environment 4965 opts = getopt32(argv, VI_OPTSTR IF_FEATURE_VI_COLON(, &initial_cmds));
4956 // 2- if EXINIT is unset process $HOME/.exrc file (not inplemented yet) 4966
4957 // 3- process command line args
4958#if ENABLE_FEATURE_VI_COLON
4959 {
4960 char *p = getenv("EXINIT");
4961 if (p && *p)
4962 initial_cmds[0] = xstrndup(p, MAX_INPUT_LEN);
4963 }
4964#endif
4965 while ((c = getopt(argc, argv,
4966#if ENABLE_FEATURE_VI_CRASHME
4967 "C"
4968#endif
4969 "RHh" IF_FEATURE_VI_COLON("c:"))) != -1) {
4970 switch (c) {
4971#if ENABLE_FEATURE_VI_CRASHME 4967#if ENABLE_FEATURE_VI_CRASHME
4972 case 'C': 4968 if (opts & OPT_C)
4973 crashme = 1; 4969 crashme = 1;
4974 break;
4975#endif
4976#if ENABLE_FEATURE_VI_READONLY
4977 case 'R': // Read-only flag
4978 SET_READONLY_MODE(readonly_mode);
4979 break;
4980#endif
4981#if ENABLE_FEATURE_VI_COLON
4982 case 'c': // cmd line vi command
4983 if (*optarg)
4984 initial_cmds[initial_cmds[0] != NULL] = xstrndup(optarg, MAX_INPUT_LEN);
4985 break;
4986#endif 4970#endif
4987 case 'H': 4971 if (opts & OPT_R)
4988 show_help(); 4972 SET_READONLY_MODE(readonly_mode);
4989 // fall through 4973 if (opts & OPT_H)
4990 default: 4974 show_help();
4991 bb_show_usage(); 4975 if (opts & (OPT_H | OPT_h)) {
4992 return 1; 4976 bb_show_usage();
4993 } 4977 return 1;
4994 } 4978 }
4995 4979
4996 argv += optind; 4980 argv += optind;
4997 cmdline_filecnt = argc - optind; 4981 cmdline_filecnt = argc - optind;
4998 4982
4983 // 1- process EXINIT variable from environment
4984 // 2- if EXINIT is unset process $HOME/.exrc file
4985 // 3- process command line args
4986#if ENABLE_FEATURE_VI_COLON
4987 {
4988 const char *exinit = getenv("EXINIT");
4989 char *cmds = NULL;
4990
4991 if (exinit) {
4992 cmds = xstrdup(exinit);
4993 } else {
4994 const char *home = getenv("HOME");
4995
4996 if (home && *home) {
4997 char *exrc = concat_path_file(home, ".exrc");
4998 struct stat st;
4999
5000 // .exrc must belong to and only be writable by user
5001 if (stat(exrc, &st) == 0) {
5002 if ((st.st_mode & (S_IWGRP|S_IWOTH)) == 0
5003 && st.st_uid == getuid()
5004 ) {
5005 cmds = xmalloc_open_read_close(exrc, NULL);
5006 } else {
5007 status_line_bold(".exrc: permission denied");
5008 }
5009 }
5010 free(exrc);
5011 }
5012 }
5013
5014 if (cmds) {
5015 init_text_buffer(NULL);
5016 run_cmds(cmds);
5017 free(cmds);
5018 }
5019 }
5020#endif
4999 // "Save cursor, use alternate screen buffer, clear screen" 5021 // "Save cursor, use alternate screen buffer, clear screen"
5000 write1(ESC"[?1049h"); 5022 write1(ESC"[?1049h");
5001 // This is the main file handling loop 5023 // This is the main file handling loop
diff --git a/include/bb_archive.h b/include/bb_archive.h
index 892c8a472..3bbe8af41 100644
--- a/include/bb_archive.h
+++ b/include/bb_archive.h
@@ -177,6 +177,7 @@ typedef struct tar_header_t { /* byte offset */
177struct BUG_tar_header { 177struct BUG_tar_header {
178 char c[sizeof(tar_header_t) == TAR_BLOCK_SIZE ? 1 : -1]; 178 char c[sizeof(tar_header_t) == TAR_BLOCK_SIZE ? 1 : -1];
179}; 179};
180void chksum_and_xwrite_tar_header(int fd, struct tar_header_t *hp) FAST_FUNC;
180 181
181 182
182extern const char cpio_TRAILER[]; 183extern const char cpio_TRAILER[];
diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h
index 8c678dd32..ca778dab8 100644
--- a/networking/udhcp/common.h
+++ b/networking/udhcp/common.h
@@ -304,18 +304,6 @@ void udhcp_dump_packet(struct dhcp_packet *packet) FAST_FUNC;
304# define log3s(msg) ((void)0) 304# define log3s(msg) ((void)0)
305#endif 305#endif
306 306
307#if defined(__mips__)
308/*
309 * The 'simple' message functions have a negative impact on the size of the
310 * DHCP code when compiled for MIPS, so don't use them in this case.
311 */
312#define bb_simple_info_msg bb_info_msg
313#define bb_simple_error_msg bb_error_msg
314#define bb_simple_perror_msg_and_die bb_perror_msg_and_die
315#undef log1s
316#define log1s log1
317#endif
318
319/*** Other shared functions ***/ 307/*** Other shared functions ***/
320 308
321/* 2nd param is "uint32_t*" */ 309/* 2nd param is "uint32_t*" */
diff --git a/procps/smemcap.c b/procps/smemcap.c
index 01acbf74e..429cc8a3e 100644
--- a/procps/smemcap.c
+++ b/procps/smemcap.c
@@ -30,7 +30,6 @@ struct fileblock {
30static void writeheader(const char *path, struct stat *sb, int type) 30static void writeheader(const char *path, struct stat *sb, int type)
31{ 31{
32 struct tar_header_t header; 32 struct tar_header_t header;
33 int i, sum;
34 33
35 memset(&header, 0, TAR_BLOCK_SIZE); 34 memset(&header, 0, TAR_BLOCK_SIZE);
36 strcpy(header.name, path); 35 strcpy(header.name, path);
@@ -41,20 +40,7 @@ static void writeheader(const char *path, struct stat *sb, int type)
41 sprintf(header.size, "%o", (unsigned)sb->st_size); 40 sprintf(header.size, "%o", (unsigned)sb->st_size);
42 sprintf(header.mtime, "%llo", sb->st_mtime & 077777777777LL); 41 sprintf(header.mtime, "%llo", sb->st_mtime & 077777777777LL);
43 header.typeflag = type; 42 header.typeflag = type;
44 strcpy(header.magic, "ustar "); /* like GNU tar */ 43 chksum_and_xwrite_tar_header(STDOUT_FILENO, &header);
45
46 /* Calculate and store the checksum (the sum of all of the bytes of
47 * the header). The checksum field must be filled with blanks for the
48 * calculation. The checksum field is formatted differently from the
49 * other fields: it has 6 digits, a NUL, then a space -- rather than
50 * digits, followed by a NUL like the other fields... */
51 header.chksum[7] = ' ';
52 sum = ' ' * 7;
53 for (i = 0; i < TAR_BLOCK_SIZE; i++)
54 sum += ((unsigned char*)&header)[i];
55 sprintf(header.chksum, "%06o", sum);
56
57 xwrite(STDOUT_FILENO, &header, TAR_BLOCK_SIZE);
58} 44}
59 45
60static void archivefile(const char *path) 46static void archivefile(const char *path)
diff --git a/testsuite/rev.tests b/testsuite/rev.tests
new file mode 100755
index 000000000..dd65dcd3b
--- /dev/null
+++ b/testsuite/rev.tests
@@ -0,0 +1,46 @@
1#!/bin/sh
2# Copyright 2021 by Ron Yorston
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
9testing "rev works" \
10 "rev input" \
11"\
121 enil
13
143 enil
15" \
16 "line 1\n\nline 3\n" \
17 ""
18
19testing "rev file with missing newline" \
20 "rev input" \
21"\
221 enil
23
243 enil" \
25 "line 1\n\nline 3" \
26 ""
27
28testing "rev file with NUL character" \
29 "rev input" \
30"\
31nil
323 enil
33" \
34 "lin\000e 1\n\nline 3\n" \
35 ""
36
37testing "rev file with long line" \
38 "rev input" \
39"\
40+--------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------
41cba
42" \
43 "---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+--------------+\nabc\n" \
44 ""
45
46exit $FAILCOUNT
diff --git a/util-linux/rev.c b/util-linux/rev.c
index cfcd12392..5f8e60cac 100644
--- a/util-linux/rev.c
+++ b/util-linux/rev.c
@@ -113,6 +113,7 @@ int rev_main(int argc UNUSED_PARAM, char **argv)
113 strrev(buf, strlen(buf)); 113 strrev(buf, strlen(buf));
114#endif 114#endif
115 fputs_stdout(buf); 115 fputs_stdout(buf);
116 pos = 0;
116 } 117 }
117 fclose(fp); 118 fclose(fp);
118 } while (*argv); 119 } while (*argv);