fc4661cf54056be5a5272350f91b3c96c1fa853c
[oweals/busybox.git] / busybox / patches / cmp_n.diff
1 Index: coreutils/Config.in
2 ===================================================================
3 RCS file: /var/cvs/busybox/coreutils/Config.in,v
4 retrieving revision 1.24
5 diff -u -r1.24 Config.in
6 --- a/coreutils/Config.in       15 Mar 2004 08:28:19 -0000      1.24
7 +++ b/coreutils/Config.in       31 Mar 2004 11:51:17 -0000
8 @@ -59,6 +59,21 @@
9           cmp is used to compare two files and returns the result
10           to standard output.
11  
12 +config CONFIG_FEATURE_CMP_SKIP
13 +       bool "  Enable optional arguments SKIP1 and SKIP2"
14 +       default n
15 +       depends on CONFIG_CMP
16 +       help
17 +         SKIP1 and SKIP2 specify how many bytes to ignore
18 +         at the start of each file.
19 +
20 +config CONFIG_FEATURE_CMP_LIMIT
21 +       bool "  Enable limit of inputs"
22 +       default n
23 +       depends on CONFIG_CMP
24 +       help
25 +         Enable cmp option (-n).
26 +
27  config CONFIG_CP
28         bool "cp"
29         default n
30 Index: coreutils/cmp.c
31 ===================================================================
32 RCS file: /var/cvs/busybox/coreutils/cmp.c,v
33 retrieving revision 1.9
34 diff -u -r1.9 cmp.c
35 --- a/coreutils/cmp.c   19 Mar 2003 09:11:32 -0000      1.9
36 +++ b/coreutils/cmp.c   31 Mar 2004 11:51:17 -0000
37 @@ -39,6 +39,12 @@
38  #include <unistd.h>
39  #include "busybox.h"
40  
41 +#ifdef CONFIG_FEATURE_CMP_SKIP
42 +#define MAX_OPTIONAL_ARGS      3
43 +#else
44 +#define MAX_OPTIONAL_ARGS      1
45 +#endif
46 +
47  static FILE *cmp_xfopen_input(const char *filename)
48  {
49         FILE *fp;
50 @@ -58,12 +64,57 @@
51  static const char fmt_l_opt[] = "%.0s%.0s%d %3o %3o\n";        /* nicer gnu format */
52  #endif
53  
54 -static const char opt_chars[] = "sl";
55 +#ifdef CONFIG_FEATURE_CMP_LIMIT
56 +#define OPTCHR_LIMIT   "n:"
57 +#define OPTARG_LIMIT   ,&limit_str
58 +#else
59 +#define OPTCHR_LIMIT
60 +#define OPTARG_LIMIT
61 +#endif
62 +
63 +static const char opt_chars[] = "sl" OPTCHR_LIMIT;
64  
65  enum {
66         OPT_s = 1,
67 -       OPT_l = 2
68 +       OPT_l = 2,
69 +       OPT_n = 4
70 +};
71 +
72 +#ifdef CONFIG_LFS
73 +#define SUFFIX_STRUCT          suffix_mult64
74 +#define PARSE_FUNC             bb_xgetllarg10_sfx
75 +#else
76 +#define SUFFIX_STRUCT          suffix_mult
77 +#define PARSE_FUNC             bb_xgetlarg10_sfx
78 +#endif
79 +
80 +#if defined(CONFIG_FEATURE_CMP_SKIP) || defined(CONFIG_FEATURE_CMP_LIMIT)
81 +static const struct SUFFIX_STRUCT suffixes[] = {
82 +       { "k", 1UL << 10 },
83 +       { "M", 1UL << 20 },
84 +       { "G", 1UL << 30 },
85 +#ifdef CONFIG_LFS
86 +       { "T", 1ULL << 40 },
87 +       { "P", 1ULL << 50 },
88 +       { "E", 1ULL << 60 },
89 +#endif
90 +       { NULL, 0 }
91  };
92 +#endif
93 +
94 +#ifdef CONFIG_FEATURE_CMP_SKIP
95 +static void skip_input(FILE *fp, off_t skip, const char *filename)
96 +{
97 +       if (skip > 0 && fseeko(fp, skip, SEEK_CUR) != 0) {
98 +               while (skip-- > 0) {
99 +                       if (getc(fp) == EOF) {
100 +                               bb_xferror(fp, filename);
101 +                               break;
102 +                       }
103 +               }
104 +       }
105 +}
106 +#endif
107  
108  int cmp_main(int argc, char **argv)
109  {
110 @@ -73,12 +124,26 @@
111         int c1, c2, char_pos, line_pos;
112         int opt_flags;
113         int exit_val = 0;
114 +#ifdef CONFIG_FEATURE_CMP_SKIP
115 +       off_t skip1 = 0, skip2 = 0;
116 +#endif
117 +#ifdef CONFIG_FEATURE_CMP_LIMIT
118 +       off_t limit = -1;
119 +       char *limit_str;
120 +#endif
121  
122         bb_default_error_retval = 2;    /* 1 is returned if files are different. */
123  
124 -       opt_flags = bb_getopt_ulflags(argc, argv, opt_chars);
125 +       opt_flags = bb_getopt_ulflags(argc, argv, opt_chars OPTARG_LIMIT);
126  
127 -       if ((opt_flags == 3) || (((unsigned int)(--argc - optind)) > 1)) {
128 +#ifdef CONFIG_FEATURE_CMP_LIMIT
129 +       if (opt_flags & OPT_n) {
130 +               limit = PARSE_FUNC(limit_str, suffixes);
131 +               opt_flags &= 3;
132 +       }
133 +#endif
134 +
135 +       if ((opt_flags == 3) || (((unsigned int)(--argc - optind)) > MAX_OPTIONAL_ARGS)) {
136                 bb_show_usage();
137         }
138  
139 @@ -87,6 +152,13 @@
140         filename2 = "-";
141         if (*++argv) {
142                 filename2 = *argv;
143 +#ifdef CONFIG_FEATURE_CMP_SKIP
144 +               if (*++argv) {
145 +                       skip1 = PARSE_FUNC(*argv, suffixes);
146 +                       if (*++argv)
147 +                               skip2 = PARSE_FUNC(*argv, suffixes);
148 +               }
149 +#endif
150         }
151         fp2 = cmp_xfopen_input(filename2);
152  
153 @@ -98,6 +170,11 @@
154                 return 0;
155         }
156  
157 +#ifdef CONFIG_FEATURE_CMP_SKIP
158 +       skip_input(fp1, skip1, filename1);
159 +       skip_input(fp2, skip2, filename2);
160 +#endif
161 +
162         fmt = fmt_differ;
163         if (opt_flags == OPT_l) {
164                 fmt = fmt_l_opt;
165 @@ -106,6 +183,10 @@
166         char_pos = 0;
167         line_pos = 1;
168         do {
169 +#ifdef CONFIG_FEATURE_CMP_LIMIT
170 +               if (limit-- == 0)
171 +                       break;
172 +#endif
173                 c1 = getc(fp1);
174                 c2 = getc(fp2);
175                 ++char_pos;
176 Index: include/usage.h
177 ===================================================================
178 RCS file: /var/cvs/busybox/include/usage.h,v
179 retrieving revision 1.198
180 diff -u -r1.198 usage.h
181 --- a/include/usage.h   29 Mar 2004 08:20:08 -0000      1.198
182 +++ b/include/usage.h   31 Mar 2004 11:51:17 -0000
183 @@ -186,14 +186,29 @@
184  #define clear_full_usage \
185         "Clear screen."
186  
187 +#ifdef CONFIG_FEATURE_CMP_SKIP
188 +#define USAGE_CMP_SKIP(a) a
189 +#else
190 +#define USAGE_CMP_SKIP(a)
191 +#endif
192 +
193 +#ifdef CONFIG_FEATURE_CMP_LIMIT
194 +#define USAGE_CMP_LIMIT(a) a
195 +#else
196 +#define USAGE_CMP_LIMIT(a)
197 +#endif
198 +
199  #define cmp_trivial_usage \
200 -       "[OPTION]... FILE1 [FILE2]"
201 +       "[OPTION]... FILE1 [FILE2" USAGE_CMP_SKIP(" [SKIP1 [SKIP2]]") "]"
202  #define cmp_full_usage \
203 -       "Compare files.\n\n" \
204 +       "Compare files.\n" \
205 +       USAGE_CMP_SKIP("SKIP1 and SKIP2 are the number of bytes to skip in each file.\n") \
206 +       "\n" \
207         "Options:\n" \
208 -       "\t-l\tWrite the byte numbers (decimal) and values (octal)\n" \
209 -       "\t\t  for all differing bytes.\n" \
210 -       "\t-s\tquiet mode - do not print"
211 +       "\t-l\t\tWrite the byte numbers (decimal) and values (octal)\n" \
212 +       "\t\t\t  for all differing bytes.\n" \
213 +       USAGE_CMP_LIMIT("\t-n LIMIT\tCompare at most LIMIT bytes.\n") \
214 +       "\t-s\t\tquiet mode - do not print"
215  
216  #define cp_trivial_usage \
217         "[OPTION]... SOURCE DEST"
218 Index: include/libbb.h
219 ===================================================================
220 RCS file: /var/cvs/busybox/include/libbb.h,v
221 retrieving revision 1.129
222 diff -u -r1.129 libbb.h
223 --- a/include/libbb.h   15 Mar 2004 08:28:38 -0000      1.129
224 +++ b/include/libbb.h   31 Mar 2004 11:51:17 -0000
225 @@ -217,6 +217,21 @@
226                                                                 const struct suffix_mult *suffixes);
227  extern long bb_xgetlarg10_sfx(const char *arg, const struct suffix_mult *suffixes);
228  
229 +struct suffix_mult64 {
230 +       const char *suffix;
231 +       unsigned long long mult;
232 +};
233 +
234 +extern unsigned long long bb_xgetullarg_bnd_sfx(const char *arg, int base,
235 +                                                                                 unsigned long long lower,
236 +                                                                                 unsigned long long upper,
237 +                                                                                 const struct suffix_mult64 *suffixes);
238 +
239 +extern long long bb_xgetllarg_bnd_sfx(const char *arg, int base,
240 +                                                               long long lower,
241 +                                                               long long upper,
242 +                                                               const struct suffix_mult64 *suffixes);
243 +extern long long bb_xgetllarg10_sfx(const char *arg, const struct suffix_mult64 *suffixes);
244  
245  //#warning pitchable now?
246  extern unsigned long bb_xparse_number(const char *numstr,
247 Index: libbb/Makefile.in
248 ===================================================================
249 RCS file: /var/cvs/busybox/libbb/Makefile.in,v
250 retrieving revision 1.34
251 diff -u -r1.34 Makefile.in
252 --- a/libbb/Makefile.in 6 Mar 2004 22:11:45 -0000       1.34
253 +++ b/libbb/Makefile.in 31 Mar 2004 11:51:17 -0000
254 @@ -70,7 +70,8 @@
255  
256  LIBBB_MSRC3:=$(LIBBB_DIR)xgetularg.c
257  LIBBB_MOBJ3:=xgetularg_bnd_sfx.o xgetlarg_bnd_sfx.o getlarg10_sfx.o \
258 -       xgetularg_bnd.o xgetularg10_bnd.o xgetularg10.o
259 +       xgetularg_bnd.o xgetularg10_bnd.o xgetularg10.o \
260 +       xgetullarg_bnd_sfx.o xgetllarg_bnd_sfx.o xgetllarg10_sfx.o
261  
262  LIBBB_MSRC4:=$(LIBBB_DIR)/safe_strtol.c
263  LIBBB_MOBJ4:=safe_strtoi.o safe_strtod.o safe_strtol.o safe_strtoul.o
264 Index: libbb/xgetularg.c
265 ===================================================================
266 RCS file: /var/cvs/busybox/libbb/xgetularg.c,v
267 retrieving revision 1.2
268 diff -u -r1.2 xgetularg.c
269 --- a/libbb/xgetularg.c 15 Mar 2004 08:28:44 -0000      1.2
270 +++ b/libbb/xgetularg.c 31 Mar 2004 11:51:17 -0000
271 @@ -158,3 +158,106 @@
272         return bb_xgetularg10_bnd(arg, 0, ULONG_MAX);
273  }
274  #endif
275 +
276 +#ifdef L_xgetullarg_bnd_sfx
277 +extern
278 +unsigned long long bb_xgetullarg_bnd_sfx(const char *arg, int base,
279 +                                                                  unsigned long long lower,
280 +                                                                  unsigned long long upper,
281 +                                                                  const struct suffix_mult64 *suffixes)
282 +{
283 +       unsigned long long r;
284 +       int old_errno;
285 +       char *e;
286 +
287 +       assert(arg);
288 +
289 +       /* Disallow '-' and any leading whitespace.  Speed isn't critical here
290 +        * since we're parsing commandline args.  So make sure we get the
291 +        * actual isspace function rather than a larger macro implementaion. */
292 +       if ((*arg == '-') || (isspace)(*arg)) {
293 +               bb_show_usage();
294 +       }
295 +
296 +       /* Since this is a lib function, we're not allowed to reset errno to 0.
297 +        * Doing so could break an app that is deferring checking of errno.
298 +        * So, save the old value so that we can restore it if successful. */
299 +       old_errno = errno;
300 +       errno = 0;
301 +       r = strtoull(arg, &e, base);
302 +       /* Do the initial validity check.  Note: The standards do not
303 +        * guarantee that errno is set if no digits were found.  So we
304 +        * must test for this explicitly. */
305 +       if (errno || (arg == e)) {      /* error or no digits */
306 +               bb_show_usage();
307 +       }
308 +       errno = old_errno;      /* Ok.  So restore errno. */
309 +
310 +       /* Do optional suffix parsing.  Allow 'empty' suffix tables.
311 +        * Note that we also all nul suffixes with associated multipliers,
312 +        * to allow for scaling of the arg by some default multiplier. */
313 +
314 +       if (suffixes) {
315 +               while (suffixes->suffix) {
316 +                       if (strcmp(suffixes->suffix, e) == 0) {
317 +                               if (ULONG_LONG_MAX / suffixes->mult < r) {      /* Overflow! */
318 +                                       bb_show_usage();
319 +                               }
320 +                               ++e;
321 +                               r *= suffixes->mult;
322 +                               break;
323 +                       }
324 +                       ++suffixes;
325 +               }
326 +       }
327 +
328 +       /* Finally, check for illegal trailing chars and range limits. */
329 +       /* Note: although we allow leading space (via stroul), trailing space
330 +        * is an error.  It would be easy enough to allow though if desired. */
331 +       if (*e || (r < lower) || (r > upper)) {
332 +               bb_show_usage();
333 +       }
334 +
335 +       return r;
336 +}
337 +#endif
338 +
339 +#ifdef L_xgetllarg_bnd_sfx
340 +extern
341 +long long bb_xgetllarg_bnd_sfx(const char *arg, int base,
342 +                                                long long lower,
343 +                                                long long upper,
344 +                                                const struct suffix_mult64 *suffixes)
345 +{
346 +       unsigned long long u = LONG_LONG_MAX;
347 +       long long r;
348 +       const char *p = arg;
349 +
350 +       if ((*p == '-') && (p[1] != '+')) {
351 +               ++p;
352 +#if LONG_LONG_MAX == (-(LONG_LONG_MIN + 1))
353 +               ++u;    /* two's complement */
354 +#endif
355 +       }
356 +
357 +       r = bb_xgetullarg_bnd_sfx(p, base, 0, u, suffixes);
358 +
359 +       if (*arg == '-') {
360 +               r = -r;
361 +       }
362 +
363 +       if ((r < lower) || (r > upper)) {
364 +               bb_show_usage();
365 +       }
366 +
367 +       return r;
368 +}
369 +#endif
370 +
371 +#ifdef L_xgetllarg10_sfx
372 +extern
373 +long long bb_xgetllarg10_sfx(const char *arg, const struct suffix_mult64 *suffixes)
374 +{
375 +       return bb_xgetllarg_bnd_sfx(arg, 10, LONG_LONG_MIN, LONG_LONG_MAX, suffixes);
376 +}
377 +#endif