cmp.c revision 87628
1169689Skan/*
2169689Skan * Copyright (c) 1987, 1990, 1993, 1994
3169689Skan *	The Regents of the University of California.  All rights reserved.
4169689Skan *
5169689Skan * Redistribution and use in source and binary forms, with or without
6169689Skan * modification, are permitted provided that the following conditions
7169689Skan * are met:
8169689Skan * 1. Redistributions of source code must retain the above copyright
9169689Skan *    notice, this list of conditions and the following disclaimer.
10169689Skan * 2. Redistributions in binary form must reproduce the above copyright
11169689Skan *    notice, this list of conditions and the following disclaimer in the
12169689Skan *    documentation and/or other materials provided with the distribution.
13169689Skan * 3. All advertising materials mentioning features or use of this software
14169689Skan *    must display the following acknowledgement:
15169689Skan *	This product includes software developed by the University of
16169689Skan *	California, Berkeley and its contributors.
17169689Skan * 4. Neither the name of the University nor the names of its contributors
18169689Skan *    may be used to endorse or promote products derived from this software
19169689Skan *    without specific prior written permission.
20169689Skan *
21169689Skan * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22169689Skan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23169689Skan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24169689Skan * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25169689Skan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26169689Skan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27169689Skan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28169689Skan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29169689Skan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30169689Skan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31169689Skan * SUCH DAMAGE.
32169689Skan */
33169689Skan
34169689Skan#ifndef lint
35169689Skanstatic const char copyright[] =
36169689Skan"@(#) Copyright (c) 1987, 1990, 1993, 1994\n\
37169689Skan	The Regents of the University of California.  All rights reserved.\n";
38169689Skan#endif
39169689Skan
40169689Skan#if 0
41169689Skan#ifndef lint
42169689Skanstatic char sccsid[] = "@(#)cmp.c	8.3 (Berkeley) 4/2/94";
43169689Skan#endif
44169689Skan#endif
45169689Skan
46169689Skan#include <sys/cdefs.h>
47169689Skan__FBSDID("$FreeBSD: head/usr.bin/cmp/cmp.c 87628 2001-12-10 21:13:08Z dwmalone $");
48169689Skan
49169689Skan#include <sys/types.h>
50169689Skan#include <sys/stat.h>
51169689Skan
52169689Skan#include <err.h>
53169689Skan#include <fcntl.h>
54169689Skan#include <stdio.h>
55169689Skan#include <stdlib.h>
56169689Skan#include <string.h>
57169689Skan#include <unistd.h>
58169689Skan
59169689Skan#include "extern.h"
60169689Skan
61169689Skanint	lflag, sflag, xflag, zflag;
62169689Skan
63169689Skanstatic void usage __P((void));
64169689Skan
65169689Skanint
66169689Skanmain(argc, argv)
67169689Skan	int argc;
68169689Skan	char *argv[];
69169689Skan{
70169689Skan	struct stat sb1, sb2;
71169689Skan	off_t skip1, skip2;
72169689Skan	int ch, fd1, fd2, special;
73169689Skan	const char *file1, *file2;
74169689Skan
75169689Skan	while ((ch = getopt(argc, argv, "-lsxz")) != -1)
76169689Skan		switch (ch) {
77169689Skan		case 'l':		/* print all differences */
78169689Skan			lflag = 1;
79169689Skan			break;
80169689Skan		case 's':		/* silent run */
81169689Skan			sflag = 1;
82169689Skan			zflag = 1;
83169689Skan			break;
84169689Skan		case 'x':		/* hex output */
85169689Skan			lflag = 1;
86169689Skan			xflag = 1;
87169689Skan			break;
88169689Skan		case 'z':		/* compare size first */
89169689Skan			zflag = 1;
90169689Skan			break;
91169689Skan		case '-':		/* stdin (must be after options) */
92169689Skan			--optind;
93169689Skan			goto endargs;
94169689Skan		case '?':
95169689Skan		default:
96169689Skan			usage();
97169689Skan		}
98169689Skanendargs:
99169689Skan	argv += optind;
100169689Skan	argc -= optind;
101169689Skan
102169689Skan	if (lflag && sflag)
103169689Skan		errx(ERR_EXIT, "specifying -s with -l or -x is not permitted");
104169689Skan
105169689Skan	if (argc < 2 || argc > 4)
106169689Skan		usage();
107169689Skan
108169689Skan	/* Backward compatibility -- handle "-" meaning stdin. */
109169689Skan	special = 0;
110169689Skan	if (strcmp(file1 = argv[0], "-") == 0) {
111169689Skan		special = 1;
112169689Skan		fd1 = 0;
113169689Skan		file1 = "stdin";
114169689Skan	}
115169689Skan	else if ((fd1 = open(file1, O_RDONLY, 0)) < 0) {
116169689Skan		if (!sflag)
117169689Skan			err(ERR_EXIT, "%s", file1);
118169689Skan		else
119169689Skan			exit(1);
120169689Skan	}
121169689Skan	if (strcmp(file2 = argv[1], "-") == 0) {
122169689Skan		if (special)
123169689Skan			errx(ERR_EXIT,
124169689Skan				"standard input may only be specified once");
125169689Skan		special = 1;
126169689Skan		fd2 = 0;
127169689Skan		file2 = "stdin";
128169689Skan	}
129169689Skan	else if ((fd2 = open(file2, O_RDONLY, 0)) < 0) {
130169689Skan		if (!sflag)
131169689Skan			err(ERR_EXIT, "%s", file2);
132169689Skan		else
133169689Skan			exit(1);
134169689Skan	}
135169689Skan
136169689Skan	skip1 = argc > 2 ? strtol(argv[2], NULL, 0) : 0;
137169689Skan	skip2 = argc == 4 ? strtol(argv[3], NULL, 0) : 0;
138169689Skan
139169689Skan	if (!special) {
140169689Skan		if (fstat(fd1, &sb1)) {
141169689Skan			if (!sflag)
142169689Skan				err(ERR_EXIT, "%s", file1);
143169689Skan			else
144169689Skan				exit(1);
145169689Skan		}
146169689Skan		if (!S_ISREG(sb1.st_mode))
147169689Skan			special = 1;
148169689Skan		else {
149169689Skan			if (fstat(fd2, &sb2)) {
150169689Skan				if (!sflag)
151169689Skan					err(ERR_EXIT, "%s", file2);
152169689Skan				else
153169689Skan					exit(1);
154169689Skan			}
155169689Skan			if (!S_ISREG(sb2.st_mode))
156169689Skan				special = 1;
157169689Skan		}
158169689Skan	}
159169689Skan
160169689Skan	if (special)
161169689Skan		c_special(fd1, file1, skip1, fd2, file2, skip2);
162169689Skan	else {
163169689Skan		if (zflag && sb1.st_size != sb2.st_size) {
164169689Skan			if (!sflag)
165169689Skan				(void) printf("%s %s differ: size\n",
166169689Skan				    file1, file2);
167169689Skan			exit(DIFF_EXIT);
168169689Skan		}
169169689Skan		c_regular(fd1, file1, skip1, sb1.st_size,
170169689Skan		    fd2, file2, skip2, sb2.st_size);
171169689Skan	}
172169689Skan	exit(0);
173169689Skan}
174169689Skan
175169689Skanstatic void
176169689Skanusage()
177169689Skan{
178169689Skan
179169689Skan	(void)fprintf(stderr,
180169689Skan	    "usage: cmp [-l | -s | -x] [-z] file1 file2 [skip1 [skip2]]\n");
181169689Skan	exit(ERR_EXIT);
182169689Skan}
183169689Skan