VirtualBox

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

Last change on this file since 3387 was 3299, checked in by bird, 5 years ago

kmkbuiltin/cmp_util.c: FreeBSD build fix

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

© 2023 Oracle
ContactPrivacy policyTerms of Use