source: MondoRescue/branches/3.3/mindi-busybox/editors/cmp.c@ 3723

Last change on this file since 3723 was 3621, checked in by Bruno Cornec, 10 years ago

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

  • Property svn:eol-style set to native
File size: 3.9 KB
Line 
1/* vi: set sw=4 ts=4: */
2/*
3 * Mini cmp implementation for busybox
4 *
5 * Copyright (C) 2000,2001 by Matt Kraai <kraai@alumni.carnegiemellon.edu>
6 *
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */
9
10/* BB_AUDIT SUSv3 (virtually) compliant -- uses nicer GNU format for -l. */
11/* http://www.opengroup.org/onlinepubs/007904975/utilities/cmp.html */
12
13//config:config CMP
14//config: bool "cmp"
15//config: default y
16//config: help
17//config: cmp is used to compare two files and returns the result
18//config: to standard output.
19
20//kbuild:lib-$(CONFIG_CMP) += cmp.o
21
22//applet:IF_CMP(APPLET(cmp, BB_DIR_USR_BIN, BB_SUID_DROP))
23
24//usage:#define cmp_trivial_usage
25//usage: "[-l] [-s] FILE1 [FILE2" IF_DESKTOP(" [SKIP1 [SKIP2]]") "]"
26//usage:#define cmp_full_usage "\n\n"
27//usage: "Compare FILE1 with FILE2 (or stdin)\n"
28//usage: "\n -l Write the byte numbers (decimal) and values (octal)"
29//usage: "\n for all differing bytes"
30//usage: "\n -s Quiet"
31
32#include "libbb.h"
33
34static const char fmt_eof[] ALIGN1 = "cmp: EOF on %s\n";
35static const char fmt_differ[] ALIGN1 = "%s %s differ: char %"OFF_FMT"u, line %u\n";
36// This fmt_l_opt uses gnu-isms. SUSv3 would be "%.0s%.0s%"OFF_FMT"u %o %o\n"
37static const char fmt_l_opt[] ALIGN1 = "%.0s%.0s%"OFF_FMT"u %3o %3o\n";
38
39static const char opt_chars[] ALIGN1 = "sl";
40#define CMP_OPT_s (1<<0)
41#define CMP_OPT_l (1<<1)
42
43int cmp_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
44int cmp_main(int argc UNUSED_PARAM, char **argv)
45{
46 FILE *fp1, *fp2, *outfile = stdout;
47 const char *filename1, *filename2 = "-";
48 off_t skip1 = 0, skip2 = 0, char_pos = 0;
49 int line_pos = 1; /* Hopefully won't overflow... */
50 const char *fmt;
51 int c1, c2;
52 unsigned opt;
53 int retval = 0;
54
55 opt_complementary = "-1"
56 IF_DESKTOP(":?4")
57 IF_NOT_DESKTOP(":?2")
58 ":l--s:s--l";
59 opt = getopt32(argv, opt_chars);
60 argv += optind;
61
62 filename1 = *argv;
63 if (*++argv) {
64 filename2 = *argv;
65 if (ENABLE_DESKTOP && *++argv) {
66 skip1 = XATOOFF(*argv);
67 if (*++argv) {
68 skip2 = XATOOFF(*argv);
69 }
70 }
71 }
72
73 xfunc_error_retval = 2; /* missing file results in exitcode 2 */
74 if (opt & CMP_OPT_s)
75 logmode = 0; /* -s suppresses open error messages */
76 fp1 = xfopen_stdin(filename1);
77 fp2 = xfopen_stdin(filename2);
78 if (fp1 == fp2) { /* Paranoia check... stdin == stdin? */
79 /* Note that we don't bother reading stdin. Neither does gnu wc.
80 * But perhaps we should, so that other apps down the chain don't
81 * get the input. Consider 'echo hello | (cmp - - && cat -)'.
82 */
83 return 0;
84 }
85 logmode = LOGMODE_STDIO;
86
87 if (opt & CMP_OPT_l)
88 fmt = fmt_l_opt;
89 else
90 fmt = fmt_differ;
91
92 if (ENABLE_DESKTOP) {
93 while (skip1) { getc(fp1); skip1--; }
94 while (skip2) { getc(fp2); skip2--; }
95 }
96 do {
97 c1 = getc(fp1);
98 c2 = getc(fp2);
99 ++char_pos;
100 if (c1 != c2) { /* Remember: a read error may have occurred. */
101 retval = 1; /* But assume the files are different for now. */
102 if (c2 == EOF) {
103 /* We know that fp1 isn't at EOF or in an error state. But to
104 * save space below, things are setup to expect an EOF in fp1
105 * if an EOF occurred. So, swap things around.
106 */
107 fp1 = fp2;
108 filename1 = filename2;
109 c1 = c2;
110 }
111 if (c1 == EOF) {
112 die_if_ferror(fp1, filename1);
113 fmt = fmt_eof; /* Well, no error, so it must really be EOF. */
114 outfile = stderr;
115 /* There may have been output to stdout (option -l), so
116 * make sure we fflush before writing to stderr. */
117 fflush_all();
118 }
119 if (!(opt & CMP_OPT_s)) {
120 if (opt & CMP_OPT_l) {
121 line_pos = c1; /* line_pos is unused in the -l case. */
122 }
123 fprintf(outfile, fmt, filename1, filename2, char_pos, line_pos, c2);
124 if (opt) { /* This must be -l since not -s. */
125 /* If we encountered an EOF,
126 * the while check will catch it. */
127 continue;
128 }
129 }
130 break;
131 }
132 if (c1 == '\n') {
133 ++line_pos;
134 }
135 } while (c1 != EOF);
136
137 die_if_ferror(fp1, filename1);
138 die_if_ferror(fp2, filename2);
139
140 fflush_stdout_and_exit(retval);
141}
Note: See TracBrowser for help on using the repository browser.