VirtualBox

source: kBuild/trunk/src/kmk/kmkbuiltin/cmp_util.c@ 1455

Last change on this file since 1455 was 1309, checked in by bird, 17 years ago

combined the bulk of the cmp stuff into cmp_util.c. implemented cp --changed.

  • Property svn:eol-style set to native
File size: 14.8 KB
Line 
1/* $NetBSD: cmp.c,v 1.15 2006/01/19 20:44:57 garbled Exp $ */
2/* $NetBSD: misc.c,v 1.11 2007/08/22 16:59:19 christos Exp $ */
3/* $NetBSD: regular.c,v 1.20 2006/06/03 21:47:55 christos Exp $ */
4/* $NetBSD: special.c,v 1.12 2007/08/21 14:09:54 christos Exp $ */
5
6/*
7 * Copyright (c) 1987, 1990, 1993, 1994
8 * The Regents of the University of California. All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35/*__COPYRIGHT("@(#) Copyright (c) 1987, 1990, 1993, 1994\n\
36 The Regents of the University of California. All rights reserved.\n");*/
37
38#include <sys/types.h>
39#include <sys/stat.h>
40#if defined(__FreeBSD__) || defined(__NetBSD__) /** @todo more mmap capable OSes. */
41# define CMP_USE_MMAP
42# include <sys/param.h>
43# include <sys/mman.h>
44#endif
45#include <errno.h>
46#include <fcntl.h>
47#include <stdio.h>
48#include <stdlib.h>
49#include <string.h>
50#ifndef _MSC_VER
51# include <unistd.h>
52# ifndef O_BINARY
53# define O_BINARY 0
54# endif
55#else
56# define MSC_DO_64_BIT_IO
57# include "mscfakes.h"
58#endif
59#include "err.h"
60
61#include "cmp_extern.h"
62
63
64static int
65errmsg(const char *file, off_t byte, off_t line, int lflag)
66{
67 if (lflag)
68#ifdef _MSC_VER
69 return err(ERR_EXIT, "%s: char %I64d, line %lld", file, (__int64)byte, (long long)line);
70#else
71 return err(ERR_EXIT, "%s: char %lld, line %lld", file, (long long)byte, (long long)line);
72#endif
73 return err(ERR_EXIT, "%s", file);
74}
75
76
77static int
78eofmsg(const char *file, off_t byte, off_t line, int sflag, int lflag)
79{
80 if (!sflag)
81 {
82 if (!lflag)
83 warnx("EOF on %s", file);
84 else
85 {
86#ifdef _MSC_VER
87 if (line > 0)
88 warnx("EOF on %s: char %I64d, line %I64d", file, (__int64)byte, (__int64)line);
89 else
90 warnx("EOF on %s: char %I64d", file, (__int64)byte);
91#else
92 if (line > 0)
93 warnx("EOF on %s: char %lld, line %lld", file, (long long)byte, (long long)line);
94 else
95 warnx("EOF on %s: char %lld", file, (long long)byte);
96#endif
97 }
98 }
99 return DIFF_EXIT;
100}
101
102
103static int
104diffmsg(const char *file1, const char *file2, off_t byte, off_t line, int sflag)
105{
106 if (!sflag)
107#ifdef _MSC_VER
108 printf("%s %s differ: char %I64d, line %I64d\n",
109 file1, file2, (__int64)byte, (__int64)line);
110#else
111 printf("%s %s differ: char %lld, line %lld\n",
112 file1, file2, (long long)byte, (long long)line);
113#endif
114 return DIFF_EXIT;
115}
116
117
118/**
119 * Compares two files, where one or both are non-regular ones.
120 */
121static int
122c_special(int fd1, const char *file1, off_t skip1,
123 int fd2, const char *file2, off_t skip2,
124 int lflag, int sflag)
125{
126 int fd1dup, fd2dup;
127 FILE *fp1;
128 int rc;
129
130 /* duplicate because fdopen+fclose will otherwise close the handle. */
131 fd1dup = dup(fd1);
132 if (fd1 < 0)
133 return err(ERR_EXIT, "%s", file1);
134 fp1 = fdopen(fd1dup, "rb");
135 if (!fp1)
136 fp1 = fdopen(fd1dup, "r");
137 if (!fp1)
138 {
139 err(ERR_EXIT, "%s", file1);
140 close(fd1dup);
141 return ERR_EXIT;
142 }
143
144 fd2dup = dup(fd2);
145 if (fd2dup >= 0)
146 {
147 FILE *fp2 = fdopen(fd2dup, "rb");
148 if (!fp2)
149 fp2 = fdopen(fd2dup, "r");
150 if (fp2)
151 {
152 off_t byte;
153 off_t line;
154 int ch1 = 0;
155 int ch2 = 0;
156
157 /* skipping ahead */
158 rc = OK_EXIT;
159 for (byte = line = 1; skip1--; byte++)
160 {
161 ch1 = getc(fp1);
162 if (ch1 == EOF)
163 break;
164 if (ch1 == '\n')
165 line++;
166 }
167 for (byte = line = 1; skip2--; byte++)
168 {
169 ch2 = getc(fp2);
170 if (ch2 == EOF)
171 break;
172 if (ch2 == '\n')
173 line++;
174 }
175 if (ch2 != EOF && ch1 != EOF)
176 {
177 /* compare byte by byte */
178 for (byte = line = 1;; ++byte)
179 {
180 ch1 = getc(fp1);
181 ch2 = getc(fp2);
182 if (ch1 == EOF || ch2 == EOF)
183 break;
184 if (ch1 != ch2)
185 {
186 if (!lflag)
187 {
188 rc = diffmsg(file1, file2, byte, line, sflag);
189 break;
190 }
191 rc = DIFF_EXIT;
192#ifdef _MSC_VER
193 printf("%6i64d %3o %3o\n", (__int64)byte, ch1, ch2);
194#else
195 printf("%6lld %3o %3o\n", (long long)byte, ch1, ch2);
196#endif
197 }
198 if (ch1 == '\n')
199 ++line;
200 }
201 }
202
203 /* Check for errors and length differences (EOF). */
204 if (ferror(fp1) && rc != ERR_EXIT)
205 rc = errmsg(file1, byte, line, lflag);
206 if (ferror(fp2) && rc != ERR_EXIT)
207 rc = errmsg(file2, byte, line, lflag);
208 if (rc == OK_EXIT)
209 {
210 if (feof(fp1))
211 {
212 if (!feof(fp2))
213 rc = eofmsg(file1, byte, line, sflag, lflag);
214 }
215 else if (feof(fp2))
216 rc = eofmsg(file2, byte, line, sflag, lflag);
217 }
218
219 fclose(fp2);
220 }
221 else
222 {
223 rc = err(ERR_EXIT, "%s", file2);
224 close(fd2dup);
225 }
226 }
227 else
228 rc = err(ERR_EXIT, "%s", file2);
229
230 fclose(fp1);
231 return rc;
232}
233
234
235#ifdef CMP_USE_MMAP
236/**
237 * Compare two files using mmap.
238 */
239static int
240c_regular(int fd1, const char *file1, off_t skip1, off_t len1,
241 int fd2, const char *file2, off_t skip2, off_t len2, int sflag, int lflag)
242{
243 unsigned char ch, *p1, *p2, *b1, *b2;
244 off_t byte, length, line;
245 int dfound;
246 size_t blk_sz, blk_cnt;
247
248 if (sflag && len1 != len2)
249 return DIFF_EXIT;
250
251 if (skip1 > len1)
252 return eofmsg(file1, len1 + 1, 0, sflag, lflag);
253 len1 -= skip1;
254 if (skip2 > len2)
255 return eofmsg(file2, len2 + 1, 0, sflag, lflag);
256 len2 -= skip2;
257
258 byte = line = 1;
259 dfound = 0;
260 length = len1 <= len2 ? len1 : len2;
261 for (blk_sz = 1024 * 1024; length != 0; length -= blk_sz)
262 {
263 if (blk_sz > length)
264 blk_sz = length;
265 b1 = p1 = mmap(NULL, blk_sz, PROT_READ, MAP_FILE | MAP_SHARED, fd1, skip1);
266 if (p1 == MAP_FAILED)
267 goto l_mmap_failed;
268
269 b2 = p2 = mmap(NULL, blk_sz, PROT_READ, MAP_FILE | MAP_SHARED, fd2, skip2);
270 if (p2 == MAP_FAILED)
271 {
272 munmap(p1, blk_sz);
273 goto l_mmap_failed;
274 }
275
276 blk_cnt = blk_sz;
277 for (; blk_cnt--; ++p1, ++p2, ++byte)
278 {
279 if ((ch = *p1) != *p2)
280 {
281 if (!lflag)
282 {
283 munmap(b1, blk_sz);
284 munmap(b2, blk_sz);
285 return diffmsg(file1, file2, byte, line, sflag);
286 }
287 dfound = 1;
288#ifdef _MSC_VER
289 printf("%6I64d %3o %3o\n", (__int64)byte, ch, *p2);
290#else
291 printf("%6lld %3o %3o\n", (long long)byte, ch, *p2);
292#endif
293 }
294 if (ch == '\n')
295 ++line;
296 }
297 munmap(p1 - blk_sz, blk_sz);
298 munmap(p2 - blk_sz, blk_sz);
299 skip1 += blk_sz;
300 skip2 += blk_sz;
301 }
302
303 if (len1 != len2)
304 return eofmsg(len1 > len2 ? file2 : file1, byte, line, sflag, lflag);
305 if (dfound)
306 return DIFF_EXIT;
307 return OK_EXIT;
308
309l_mmap_failed:
310 return c_special(fd1, file1, skip1, fd2, file2, skip2, lflag, sflag);
311}
312
313#else /* non-mmap c_regular: */
314
315/**
316 * Compare two files without mmaping them.
317 */
318static int
319c_regular(int fd1, const char *file1, off_t skip1, off_t len1,
320 int fd2, const char *file2, off_t skip2, off_t len2, int sflag, int lflag)
321{
322 unsigned char ch, *p1, *p2, *b1 = 0, *b2 = 0;
323 off_t byte, length, line, bytes_read;
324 int dfound;
325 size_t blk_sz, blk_cnt;
326
327 if (sflag && len1 != len2)
328 return DIFF_EXIT;
329
330 if (skip1 > len1)
331 return eofmsg(file1, len1 + 1, 0, sflag, lflag);
332 len1 -= skip1;
333 if (skip2 > len2)
334 return eofmsg(file2, len2 + 1, 0, sflag, lflag);
335 len2 -= skip2;
336
337 if (skip1 && lseek(fd1, skip1, SEEK_SET) < 0)
338 goto l_special;
339 if (skip2 && lseek(fd2, skip2, SEEK_SET) < 0)
340 {
341 if (skip1 && lseek(fd1, 0, SEEK_SET) < 0)
342 return err(1, "seek failed");
343 goto l_special;
344 }
345
346#define CMP_BUF_SIZE (128*1024)
347
348 b1 = malloc(CMP_BUF_SIZE);
349 b2 = malloc(CMP_BUF_SIZE);
350 if (!b1 || !b2)
351 goto l_malloc_failed;
352
353 byte = line = 1;
354 dfound = 0;
355 length = len1;
356 if (length > len2)
357 length = len2;
358 for (blk_sz = CMP_BUF_SIZE; length != 0; length -= blk_sz)
359 {
360 if ((off_t)blk_sz > length)
361 blk_sz = length;
362
363 bytes_read = read(fd1, b1, blk_sz);
364 if (bytes_read != blk_sz)
365 goto l_read_error;
366
367 bytes_read = read(fd2, b2, blk_sz);
368 if (bytes_read != blk_sz)
369 goto l_read_error;
370
371 blk_cnt = blk_sz;
372 p1 = b1;
373 p2 = b2;
374 for (; blk_cnt--; ++p1, ++p2, ++byte)
375 {
376 if ((ch = *p1) != *p2)
377 {
378 if (!lflag)
379 {
380 free(b1);
381 free(b2);
382 return diffmsg(file1, file2, byte, line, sflag);
383 }
384 dfound = 1;
385#ifdef _MSC_VER
386 printf("%6I64d %3o %3o\n", (__int64)byte, ch, *p2);
387#else
388 printf("%6lld %3o %3o\n", (long long)byte, ch, *p2);
389#endif
390 }
391 if (ch == '\n')
392 ++line;
393 }
394 skip1 += blk_sz;
395 skip2 += blk_sz;
396 }
397
398 if (len1 != len2)
399 return eofmsg(len1 > len2 ? file2 : file1, byte, line, sflag, lflag);
400 if (dfound)
401 return DIFF_EXIT;
402 return OK_EXIT;
403
404l_read_error:
405 if ( lseek(fd1, 0, SEEK_SET) < 0
406 || lseek(fd2, 0, SEEK_SET) < 0)
407 {
408 err(1, "seek failed");
409 free(b1);
410 free(b2);
411 return 1;
412 }
413l_malloc_failed:
414 free(b1);
415 free(b2);
416l_special:
417 return c_special(fd1, file1, skip1, fd2, file2, skip2, lflag, sflag);
418}
419#endif /* non-mmap c_regular */
420
421
422/**
423 * Compares two open files.
424 */
425int
426cmp_fd_and_fd_ex(int fd1, const char *file1, off_t skip1,
427 int fd2, const char *file2, off_t skip2,
428 int sflag, int lflag, int special)
429{
430 struct stat st1, st2;
431 int rc;
432
433 if (fstat(fd1, &st1))
434 return err(ERR_EXIT, "%s", file1);
435 if (fstat(fd2, &st2))
436 return err(ERR_EXIT, "%s", file2);
437
438 if ( !S_ISREG(st1.st_mode)
439 || !S_ISREG(st2.st_mode)
440 || special)
441 rc = c_special(fd1, file1, skip1,
442 fd2, file2, skip2, sflag, lflag);
443 else
444 rc = c_regular(fd1, file1, skip1, st1.st_size,
445 fd2, file2, skip2, st2.st_size, sflag, lflag);
446 return rc;
447}
448
449
450/**
451 * Compares two open files.
452 */
453int
454cmp_fd_and_fd(int fd1, const char *file1,
455 int fd2, const char *file2,
456 int sflag, int lflag, int special)
457{
458 return cmp_fd_and_fd_ex(fd1, file1, 0, fd2, file2, 0, sflag, lflag, special);
459}
460
461
462/**
463 * Compares an open file with another that isn't open yet.
464 */
465int
466cmp_fd_and_file_ex(int fd1, const char *file1, off_t skip1,
467 const char *file2, off_t skip2,
468 int sflag, int lflag, int special)
469{
470 int rc;
471 int fd2;
472
473 if (!strcmp(file2, "-"))
474 {
475 fd2 = 0 /* stdin */;
476 special = 1;
477 file2 = "stdin";
478 }
479 else
480 fd2 = open(file2, O_RDONLY | O_BINARY, 0);
481 if (fd2 >= 0)
482 {
483 rc = cmp_fd_and_fd_ex(fd1, file1, skip1,
484 fd2, file2, skip2, sflag, lflag, special);
485 close(fd2);
486 }
487 else
488 {
489 if (!sflag)
490 warn("%s", file2);
491 rc = ERR_EXIT;
492 }
493 return rc;
494}
495
496
497/**
498 * Compares an open file with another that isn't open yet.
499 */
500int
501cmp_fd_and_file(int fd1, const char *file1,
502 const char *file2,
503 int sflag, int lflag, int special)
504{
505 return cmp_fd_and_file_ex(fd1, file1, 0,
506 file2, 0, sflag, lflag, special);
507}
508
509
510/**
511 * Opens and compare two files.
512 */
513int
514cmp_file_and_file_ex(const char *file1, off_t skip1,
515 const char *file2, off_t skip2,
516 int sflag, int lflag, int special)
517{
518 int fd1;
519 int rc;
520
521 if (lflag && sflag)
522 return errx(ERR_EXIT, "only one of -l and -s may be specified");
523
524 if (!strcmp(file1, "-"))
525 {
526 if (!strcmp(file2, "-"))
527 return errx(ERR_EXIT, "standard input may only be specified once");
528 file1 = "stdin";
529 fd1 = 1;
530 special = 1;
531 }
532 else
533 fd1 = open(file1, O_RDONLY | O_BINARY, 0);
534 if (fd1 >= 0)
535 {
536 rc = cmp_fd_and_file_ex(fd1, file1, skip1,
537 file2, skip2, sflag, lflag, special);
538 close(fd1);
539 }
540 else
541 {
542 if (!sflag)
543 warn("%s", file1);
544 rc = ERR_EXIT;
545 }
546
547 return rc;
548}
549
550
551/**
552 * Opens and compare two files.
553 */
554int
555cmp_file_and_file(const char *file1, const char *file2, int sflag, int lflag, int special)
556{
557 return cmp_file_and_file_ex(file1, 0, file2, 0, sflag, lflag, special);
558}
559
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette