VirtualBox

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

Last change on this file since 2134 was 2113, checked in by bird, 16 years ago

kmkbuiltin: include config.h

  • 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 "config.h"
39#include <sys/types.h>
40#include <sys/stat.h>
41#if defined(__FreeBSD__) || defined(__NetBSD__) /** @todo more mmap capable OSes. */
42# define CMP_USE_MMAP
43# include <sys/param.h>
44# include <sys/mman.h>
45#endif
46#include <errno.h>
47#include <fcntl.h>
48#include <stdio.h>
49#include <stdlib.h>
50#include <string.h>
51#ifndef _MSC_VER
52# include <unistd.h>
53# ifndef O_BINARY
54# define O_BINARY 0
55# endif
56#else
57# define MSC_DO_64_BIT_IO
58# include "mscfakes.h"
59#endif
60#include "err.h"
61
62#include "cmp_extern.h"
63
64
65static int
66errmsg(const char *file, off_t byte, off_t line, int lflag)
67{
68 if (lflag)
69#ifdef _MSC_VER
70 return err(ERR_EXIT, "%s: char %I64d, line %lld", file, (__int64)byte, (long long)line);
71#else
72 return err(ERR_EXIT, "%s: char %lld, line %lld", file, (long long)byte, (long long)line);
73#endif
74 return err(ERR_EXIT, "%s", file);
75}
76
77
78static int
79eofmsg(const char *file, off_t byte, off_t line, int sflag, int lflag)
80{
81 if (!sflag)
82 {
83 if (!lflag)
84 warnx("EOF on %s", file);
85 else
86 {
87#ifdef _MSC_VER
88 if (line > 0)
89 warnx("EOF on %s: char %I64d, line %I64d", file, (__int64)byte, (__int64)line);
90 else
91 warnx("EOF on %s: char %I64d", file, (__int64)byte);
92#else
93 if (line > 0)
94 warnx("EOF on %s: char %lld, line %lld", file, (long long)byte, (long long)line);
95 else
96 warnx("EOF on %s: char %lld", file, (long long)byte);
97#endif
98 }
99 }
100 return DIFF_EXIT;
101}
102
103
104static int
105diffmsg(const char *file1, const char *file2, off_t byte, off_t line, int sflag)
106{
107 if (!sflag)
108#ifdef _MSC_VER
109 printf("%s %s differ: char %I64d, line %I64d\n",
110 file1, file2, (__int64)byte, (__int64)line);
111#else
112 printf("%s %s differ: char %lld, line %lld\n",
113 file1, file2, (long long)byte, (long long)line);
114#endif
115 return DIFF_EXIT;
116}
117
118
119/**
120 * Compares two files, where one or both are non-regular ones.
121 */
122static int
123c_special(int fd1, const char *file1, off_t skip1,
124 int fd2, const char *file2, off_t skip2,
125 int lflag, int sflag)
126{
127 int fd1dup, fd2dup;
128 FILE *fp1;
129 int rc;
130
131 /* duplicate because fdopen+fclose will otherwise close the handle. */
132 fd1dup = dup(fd1);
133 if (fd1 < 0)
134 return err(ERR_EXIT, "%s", file1);
135 fp1 = fdopen(fd1dup, "rb");
136 if (!fp1)
137 fp1 = fdopen(fd1dup, "r");
138 if (!fp1)
139 {
140 err(ERR_EXIT, "%s", file1);
141 close(fd1dup);
142 return ERR_EXIT;
143 }
144
145 fd2dup = dup(fd2);
146 if (fd2dup >= 0)
147 {
148 FILE *fp2 = fdopen(fd2dup, "rb");
149 if (!fp2)
150 fp2 = fdopen(fd2dup, "r");
151 if (fp2)
152 {
153 off_t byte;
154 off_t line;
155 int ch1 = 0;
156 int ch2 = 0;
157
158 /* skipping ahead */
159 rc = OK_EXIT;
160 for (byte = line = 1; skip1--; byte++)
161 {
162 ch1 = getc(fp1);
163 if (ch1 == EOF)
164 break;
165 if (ch1 == '\n')
166 line++;
167 }
168 for (byte = line = 1; skip2--; byte++)
169 {
170 ch2 = getc(fp2);
171 if (ch2 == EOF)
172 break;
173 if (ch2 == '\n')
174 line++;
175 }
176 if (ch2 != EOF && ch1 != EOF)
177 {
178 /* compare byte by byte */
179 for (byte = line = 1;; ++byte)
180 {
181 ch1 = getc(fp1);
182 ch2 = getc(fp2);
183 if (ch1 == EOF || ch2 == EOF)
184 break;
185 if (ch1 != ch2)
186 {
187 if (!lflag)
188 {
189 rc = diffmsg(file1, file2, byte, line, sflag);
190 break;
191 }
192 rc = DIFF_EXIT;
193#ifdef _MSC_VER
194 printf("%6i64d %3o %3o\n", (__int64)byte, ch1, ch2);
195#else
196 printf("%6lld %3o %3o\n", (long long)byte, ch1, ch2);
197#endif
198 }
199 if (ch1 == '\n')
200 ++line;
201 }
202 }
203
204 /* Check for errors and length differences (EOF). */
205 if (ferror(fp1) && rc != ERR_EXIT)
206 rc = errmsg(file1, byte, line, lflag);
207 if (ferror(fp2) && rc != ERR_EXIT)
208 rc = errmsg(file2, byte, line, lflag);
209 if (rc == OK_EXIT)
210 {
211 if (feof(fp1))
212 {
213 if (!feof(fp2))
214 rc = eofmsg(file1, byte, line, sflag, lflag);
215 }
216 else if (feof(fp2))
217 rc = eofmsg(file2, byte, line, sflag, lflag);
218 }
219
220 fclose(fp2);
221 }
222 else
223 {
224 rc = err(ERR_EXIT, "%s", file2);
225 close(fd2dup);
226 }
227 }
228 else
229 rc = err(ERR_EXIT, "%s", file2);
230
231 fclose(fp1);
232 return rc;
233}
234
235
236#ifdef CMP_USE_MMAP
237/**
238 * Compare two files using mmap.
239 */
240static int
241c_regular(int fd1, const char *file1, off_t skip1, off_t len1,
242 int fd2, const char *file2, off_t skip2, off_t len2, int sflag, int lflag)
243{
244 unsigned char ch, *p1, *p2, *b1, *b2;
245 off_t byte, length, line;
246 int dfound;
247 size_t blk_sz, blk_cnt;
248
249 if (sflag && len1 != len2)
250 return DIFF_EXIT;
251
252 if (skip1 > len1)
253 return eofmsg(file1, len1 + 1, 0, sflag, lflag);
254 len1 -= skip1;
255 if (skip2 > len2)
256 return eofmsg(file2, len2 + 1, 0, sflag, lflag);
257 len2 -= skip2;
258
259 byte = line = 1;
260 dfound = 0;
261 length = len1 <= len2 ? len1 : len2;
262 for (blk_sz = 1024 * 1024; length != 0; length -= blk_sz)
263 {
264 if (blk_sz > length)
265 blk_sz = length;
266 b1 = p1 = mmap(NULL, blk_sz, PROT_READ, MAP_FILE | MAP_SHARED, fd1, skip1);
267 if (p1 == MAP_FAILED)
268 goto l_mmap_failed;
269
270 b2 = p2 = mmap(NULL, blk_sz, PROT_READ, MAP_FILE | MAP_SHARED, fd2, skip2);
271 if (p2 == MAP_FAILED)
272 {
273 munmap(p1, blk_sz);
274 goto l_mmap_failed;
275 }
276
277 blk_cnt = blk_sz;
278 for (; blk_cnt--; ++p1, ++p2, ++byte)
279 {
280 if ((ch = *p1) != *p2)
281 {
282 if (!lflag)
283 {
284 munmap(b1, blk_sz);
285 munmap(b2, blk_sz);
286 return diffmsg(file1, file2, byte, line, sflag);
287 }
288 dfound = 1;
289#ifdef _MSC_VER
290 printf("%6I64d %3o %3o\n", (__int64)byte, ch, *p2);
291#else
292 printf("%6lld %3o %3o\n", (long long)byte, ch, *p2);
293#endif
294 }
295 if (ch == '\n')
296 ++line;
297 }
298 munmap(p1 - blk_sz, blk_sz);
299 munmap(p2 - blk_sz, blk_sz);
300 skip1 += blk_sz;
301 skip2 += blk_sz;
302 }
303
304 if (len1 != len2)
305 return eofmsg(len1 > len2 ? file2 : file1, byte, line, sflag, lflag);
306 if (dfound)
307 return DIFF_EXIT;
308 return OK_EXIT;
309
310l_mmap_failed:
311 return c_special(fd1, file1, skip1, fd2, file2, skip2, lflag, sflag);
312}
313
314#else /* non-mmap c_regular: */
315
316/**
317 * Compare two files without mmaping them.
318 */
319static int
320c_regular(int fd1, const char *file1, off_t skip1, off_t len1,
321 int fd2, const char *file2, off_t skip2, off_t len2, int sflag, int lflag)
322{
323 unsigned char ch, *p1, *p2, *b1 = 0, *b2 = 0;
324 off_t byte, length, line, bytes_read;
325 int dfound;
326 size_t blk_sz, blk_cnt;
327
328 if (sflag && len1 != len2)
329 return DIFF_EXIT;
330
331 if (skip1 > len1)
332 return eofmsg(file1, len1 + 1, 0, sflag, lflag);
333 len1 -= skip1;
334 if (skip2 > len2)
335 return eofmsg(file2, len2 + 1, 0, sflag, lflag);
336 len2 -= skip2;
337
338 if (skip1 && lseek(fd1, skip1, SEEK_SET) < 0)
339 goto l_special;
340 if (skip2 && lseek(fd2, skip2, SEEK_SET) < 0)
341 {
342 if (skip1 && lseek(fd1, 0, SEEK_SET) < 0)
343 return err(1, "seek failed");
344 goto l_special;
345 }
346
347#define CMP_BUF_SIZE (128*1024)
348
349 b1 = malloc(CMP_BUF_SIZE);
350 b2 = malloc(CMP_BUF_SIZE);
351 if (!b1 || !b2)
352 goto l_malloc_failed;
353
354 byte = line = 1;
355 dfound = 0;
356 length = len1;
357 if (length > len2)
358 length = len2;
359 for (blk_sz = CMP_BUF_SIZE; length != 0; length -= blk_sz)
360 {
361 if ((off_t)blk_sz > length)
362 blk_sz = length;
363
364 bytes_read = read(fd1, b1, blk_sz);
365 if (bytes_read != blk_sz)
366 goto l_read_error;
367
368 bytes_read = read(fd2, b2, blk_sz);
369 if (bytes_read != blk_sz)
370 goto l_read_error;
371
372 blk_cnt = blk_sz;
373 p1 = b1;
374 p2 = b2;
375 for (; blk_cnt--; ++p1, ++p2, ++byte)
376 {
377 if ((ch = *p1) != *p2)
378 {
379 if (!lflag)
380 {
381 free(b1);
382 free(b2);
383 return diffmsg(file1, file2, byte, line, sflag);
384 }
385 dfound = 1;
386#ifdef _MSC_VER
387 printf("%6I64d %3o %3o\n", (__int64)byte, ch, *p2);
388#else
389 printf("%6lld %3o %3o\n", (long long)byte, ch, *p2);
390#endif
391 }
392 if (ch == '\n')
393 ++line;
394 }
395 skip1 += blk_sz;
396 skip2 += blk_sz;
397 }
398
399 if (len1 != len2)
400 return eofmsg(len1 > len2 ? file2 : file1, byte, line, sflag, lflag);
401 if (dfound)
402 return DIFF_EXIT;
403 return OK_EXIT;
404
405l_read_error:
406 if ( lseek(fd1, 0, SEEK_SET) < 0
407 || lseek(fd2, 0, SEEK_SET) < 0)
408 {
409 err(1, "seek failed");
410 free(b1);
411 free(b2);
412 return 1;
413 }
414l_malloc_failed:
415 free(b1);
416 free(b2);
417l_special:
418 return c_special(fd1, file1, skip1, fd2, file2, skip2, lflag, sflag);
419}
420#endif /* non-mmap c_regular */
421
422
423/**
424 * Compares two open files.
425 */
426int
427cmp_fd_and_fd_ex(int fd1, const char *file1, off_t skip1,
428 int fd2, const char *file2, off_t skip2,
429 int sflag, int lflag, int special)
430{
431 struct stat st1, st2;
432 int rc;
433
434 if (fstat(fd1, &st1))
435 return err(ERR_EXIT, "%s", file1);
436 if (fstat(fd2, &st2))
437 return err(ERR_EXIT, "%s", file2);
438
439 if ( !S_ISREG(st1.st_mode)
440 || !S_ISREG(st2.st_mode)
441 || special)
442 rc = c_special(fd1, file1, skip1,
443 fd2, file2, skip2, sflag, lflag);
444 else
445 rc = c_regular(fd1, file1, skip1, st1.st_size,
446 fd2, file2, skip2, st2.st_size, sflag, lflag);
447 return rc;
448}
449
450
451/**
452 * Compares two open files.
453 */
454int
455cmp_fd_and_fd(int fd1, const char *file1,
456 int fd2, const char *file2,
457 int sflag, int lflag, int special)
458{
459 return cmp_fd_and_fd_ex(fd1, file1, 0, fd2, file2, 0, sflag, lflag, special);
460}
461
462
463/**
464 * Compares an open file with another that isn't open yet.
465 */
466int
467cmp_fd_and_file_ex(int fd1, const char *file1, off_t skip1,
468 const char *file2, off_t skip2,
469 int sflag, int lflag, int special)
470{
471 int rc;
472 int fd2;
473
474 if (!strcmp(file2, "-"))
475 {
476 fd2 = 0 /* stdin */;
477 special = 1;
478 file2 = "stdin";
479 }
480 else
481 fd2 = open(file2, O_RDONLY | O_BINARY, 0);
482 if (fd2 >= 0)
483 {
484 rc = cmp_fd_and_fd_ex(fd1, file1, skip1,
485 fd2, file2, skip2, sflag, lflag, special);
486 close(fd2);
487 }
488 else
489 {
490 if (!sflag)
491 warn("%s", file2);
492 rc = ERR_EXIT;
493 }
494 return rc;
495}
496
497
498/**
499 * Compares an open file with another that isn't open yet.
500 */
501int
502cmp_fd_and_file(int fd1, const char *file1,
503 const char *file2,
504 int sflag, int lflag, int special)
505{
506 return cmp_fd_and_file_ex(fd1, file1, 0,
507 file2, 0, sflag, lflag, special);
508}
509
510
511/**
512 * Opens and compare two files.
513 */
514int
515cmp_file_and_file_ex(const char *file1, off_t skip1,
516 const char *file2, off_t skip2,
517 int sflag, int lflag, int special)
518{
519 int fd1;
520 int rc;
521
522 if (lflag && sflag)
523 return errx(ERR_EXIT, "only one of -l and -s may be specified");
524
525 if (!strcmp(file1, "-"))
526 {
527 if (!strcmp(file2, "-"))
528 return errx(ERR_EXIT, "standard input may only be specified once");
529 file1 = "stdin";
530 fd1 = 1;
531 special = 1;
532 }
533 else
534 fd1 = open(file1, O_RDONLY | O_BINARY, 0);
535 if (fd1 >= 0)
536 {
537 rc = cmp_fd_and_file_ex(fd1, file1, skip1,
538 file2, skip2, sflag, lflag, special);
539 close(fd1);
540 }
541 else
542 {
543 if (!sflag)
544 warn("%s", file1);
545 rc = ERR_EXIT;
546 }
547
548 return rc;
549}
550
551
552/**
553 * Opens and compare two files.
554 */
555int
556cmp_file_and_file(const char *file1, const char *file2, int sflag, int lflag, int special)
557{
558 return cmp_file_and_file_ex(file1, 0, file2, 0, sflag, lflag, special);
559}
560
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