diff options
| author | Ron Yorston <rmy@pobox.com> | 2025-11-13 07:50:50 +0000 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2026-03-05 21:46:04 +0100 |
| commit | ea01f254b4e0dc2f59db4cba9dd4fa98e9f5b2e5 (patch) | |
| tree | cce0009e2d1ade4f28a32c9e23709dc20ede2d80 | |
| parent | b59b00323181d5d450a92959b9bbfe3585c6786b (diff) | |
| download | busybox-w32-ea01f254b4e0dc2f59db4cba9dd4fa98e9f5b2e5.tar.gz busybox-w32-ea01f254b4e0dc2f59db4cba9dd4fa98e9f5b2e5.tar.bz2 busybox-w32-ea01f254b4e0dc2f59db4cba9dd4fa98e9f5b2e5.zip | |
paste: fix output when file lengths differ
If the files being pasted had different numbers of lines the
output was incorrect.
Rewrite the loop over all lines to allow for this. Add tests for
such conditions.
function old new delta
paste_main 458 526 +68
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
| -rw-r--r-- | coreutils/paste.c | 36 | ||||
| -rw-r--r-- | testsuite/paste/paste-long-short | 19 | ||||
| -rw-r--r-- | testsuite/paste/paste-short-long | 19 |
3 files changed, 62 insertions, 12 deletions
diff --git a/coreutils/paste.c b/coreutils/paste.c index 3e5f20158..363340e3d 100644 --- a/coreutils/paste.c +++ b/coreutils/paste.c | |||
| @@ -34,27 +34,38 @@ | |||
| 34 | 34 | ||
| 35 | static void paste_files(FILE** files, int file_cnt, char* delims, int del_cnt) | 35 | static void paste_files(FILE** files, int file_cnt, char* delims, int del_cnt) |
| 36 | { | 36 | { |
| 37 | char *line; | 37 | char **line = xmalloc(file_cnt * sizeof(char *)); |
| 38 | char delim; | 38 | char delim; |
| 39 | int active_files = file_cnt; | 39 | int active_files = file_cnt; |
| 40 | int i; | 40 | int i; |
| 41 | 41 | ||
| 42 | while (active_files > 0) { | 42 | while (active_files > 0) { |
| 43 | int del_idx = 0; | 43 | int del_idx = 0; |
| 44 | int got_line = FALSE; | ||
| 44 | 45 | ||
| 45 | for (i = 0; i < file_cnt; ++i) { | 46 | for (i = 0; i < file_cnt; ++i) { |
| 46 | if (files[i] == NULL) | 47 | if (files[i]) { |
| 47 | continue; | 48 | line[i] = xmalloc_fgetline(files[i]); |
| 48 | 49 | if (!line[i]) { | |
| 49 | line = xmalloc_fgetline(files[i]); | 50 | fclose_if_not_stdin(files[i]); |
| 50 | if (!line) { | 51 | files[i] = NULL; |
| 51 | fclose_if_not_stdin(files[i]); | 52 | --active_files; |
| 52 | files[i] = NULL; | 53 | } else { |
| 53 | --active_files; | 54 | got_line = TRUE; |
| 54 | continue; | 55 | } |
| 56 | } else { | ||
| 57 | line[i] = NULL; | ||
| 58 | } | ||
| 59 | } | ||
| 60 | |||
| 61 | if (!got_line) | ||
| 62 | break; | ||
| 63 | |||
| 64 | for (i = 0; i < file_cnt; ++i) { | ||
| 65 | if (line[i]) { | ||
| 66 | fputs_stdout(line[i]); | ||
| 67 | free(line[i]); | ||
| 55 | } | 68 | } |
| 56 | fputs_stdout(line); | ||
| 57 | free(line); | ||
| 58 | delim = '\n'; | 69 | delim = '\n'; |
| 59 | if (i != file_cnt - 1) { | 70 | if (i != file_cnt - 1) { |
| 60 | delim = delims[del_idx++]; | 71 | delim = delims[del_idx++]; |
| @@ -65,6 +76,7 @@ static void paste_files(FILE** files, int file_cnt, char* delims, int del_cnt) | |||
| 65 | fputc(delim, stdout); | 76 | fputc(delim, stdout); |
| 66 | } | 77 | } |
| 67 | } | 78 | } |
| 79 | free(line); | ||
| 68 | } | 80 | } |
| 69 | 81 | ||
| 70 | static void paste_files_separate(FILE** files, char* delims, int del_cnt) | 82 | static void paste_files_separate(FILE** files, char* delims, int del_cnt) |
diff --git a/testsuite/paste/paste-long-short b/testsuite/paste/paste-long-short new file mode 100644 index 000000000..e626d730e --- /dev/null +++ b/testsuite/paste/paste-long-short | |||
| @@ -0,0 +1,19 @@ | |||
| 1 | cat > foo <<EOF | ||
| 2 | foo1 | ||
| 3 | foo2 | ||
| 4 | foo3 | ||
| 5 | EOF | ||
| 6 | |||
| 7 | cat > bar <<EOF | ||
| 8 | bar1 | ||
| 9 | bar2 | ||
| 10 | EOF | ||
| 11 | |||
| 12 | cat > baz <<EOF | ||
| 13 | foo1 bar1 | ||
| 14 | foo2 bar2 | ||
| 15 | foo3 | ||
| 16 | EOF | ||
| 17 | |||
| 18 | busybox paste foo bar > qux | ||
| 19 | diff -u baz qux | ||
diff --git a/testsuite/paste/paste-short-long b/testsuite/paste/paste-short-long new file mode 100644 index 000000000..785da60a7 --- /dev/null +++ b/testsuite/paste/paste-short-long | |||
| @@ -0,0 +1,19 @@ | |||
| 1 | cat > foo <<EOF | ||
| 2 | foo1 | ||
| 3 | foo2 | ||
| 4 | EOF | ||
| 5 | |||
| 6 | cat > bar <<EOF | ||
| 7 | bar1 | ||
| 8 | bar2 | ||
| 9 | bar3 | ||
| 10 | EOF | ||
| 11 | |||
| 12 | cat > baz <<EOF | ||
| 13 | foo1 bar1 | ||
| 14 | foo2 bar2 | ||
| 15 | bar3 | ||
| 16 | EOF | ||
| 17 | |||
| 18 | busybox paste foo bar > qux | ||
| 19 | diff -u baz qux | ||
