19b50d902SRodney W. Grimes /* 2*8a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 3*8a16b7a1SPedro F. Giffuni * 49b50d902SRodney W. Grimes * Copyright (c) 1987, 1990, 1993, 1994 59b50d902SRodney W. Grimes * The Regents of the University of California. All rights reserved. 69b50d902SRodney W. Grimes * 79b50d902SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 89b50d902SRodney W. Grimes * modification, are permitted provided that the following conditions 99b50d902SRodney W. Grimes * are met: 109b50d902SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 119b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 129b50d902SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 139b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 149b50d902SRodney W. Grimes * documentation and/or other materials provided with the distribution. 15fbbd9655SWarner Losh * 3. Neither the name of the University nor the names of its contributors 169b50d902SRodney W. Grimes * may be used to endorse or promote products derived from this software 179b50d902SRodney W. Grimes * without specific prior written permission. 189b50d902SRodney W. Grimes * 199b50d902SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 209b50d902SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 219b50d902SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 229b50d902SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 239b50d902SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 249b50d902SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 259b50d902SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 269b50d902SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 279b50d902SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 289b50d902SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 299b50d902SRodney W. Grimes * SUCH DAMAGE. 309b50d902SRodney W. Grimes */ 319b50d902SRodney W. Grimes 329b50d902SRodney W. Grimes #ifndef lint 33fa146c53SArchie Cobbs static const char copyright[] = 349b50d902SRodney W. Grimes "@(#) Copyright (c) 1987, 1990, 1993, 1994\n\ 359b50d902SRodney W. Grimes The Regents of the University of California. All rights reserved.\n"; 366af414cbSMark Murray #endif 379b50d902SRodney W. Grimes 389f5b04e9SDavid Malone #if 0 399b50d902SRodney W. Grimes #ifndef lint 409f5b04e9SDavid Malone static char sccsid[] = "@(#)cmp.c 8.3 (Berkeley) 4/2/94"; 416af414cbSMark Murray #endif 429f5b04e9SDavid Malone #endif 439f5b04e9SDavid Malone 449f5b04e9SDavid Malone #include <sys/cdefs.h> 459f5b04e9SDavid Malone __FBSDID("$FreeBSD$"); 469b50d902SRodney W. Grimes 479b50d902SRodney W. Grimes #include <sys/types.h> 48d36899d1SConrad Meyer #include <sys/capsicum.h> 499b50d902SRodney W. Grimes #include <sys/stat.h> 509b50d902SRodney W. Grimes 51a4e3fc54SMariusz Zaborski #include <capsicum_helpers.h> 529b50d902SRodney W. Grimes #include <err.h> 53e1bfde1bSBrian Somers #include <errno.h> 549b50d902SRodney W. Grimes #include <fcntl.h> 55e75a7302SConrad Meyer #include <nl_types.h> 569b50d902SRodney W. Grimes #include <stdio.h> 579b50d902SRodney W. Grimes #include <stdlib.h> 589b50d902SRodney W. Grimes #include <string.h> 599b50d902SRodney W. Grimes #include <unistd.h> 609b50d902SRodney W. Grimes 619b50d902SRodney W. Grimes #include "extern.h" 629b50d902SRodney W. Grimes 633e6902efSBrian Somers int lflag, sflag, xflag, zflag; 649b50d902SRodney W. Grimes 65f1bb2cd2SWarner Losh static void usage(void); 669b50d902SRodney W. Grimes 679b50d902SRodney W. Grimes int 68f2e8e0daSDavid Malone main(int argc, char *argv[]) 699b50d902SRodney W. Grimes { 709b50d902SRodney W. Grimes struct stat sb1, sb2; 719b50d902SRodney W. Grimes off_t skip1, skip2; 72e1bfde1bSBrian Somers int ch, fd1, fd2, oflag, special; 73c5250ed1SDavid Malone const char *file1, *file2; 74e75a7302SConrad Meyer cap_rights_t rights; 75e75a7302SConrad Meyer uint32_t fcntls; 769b50d902SRodney W. Grimes 77e1bfde1bSBrian Somers oflag = O_RDONLY; 78e1bfde1bSBrian Somers while ((ch = getopt(argc, argv, "hlsxz")) != -1) 799b50d902SRodney W. Grimes switch (ch) { 80e1bfde1bSBrian Somers case 'h': /* Don't follow symlinks */ 81e1bfde1bSBrian Somers oflag |= O_NOFOLLOW; 82e1bfde1bSBrian Somers break; 839b50d902SRodney W. Grimes case 'l': /* print all differences */ 849b50d902SRodney W. Grimes lflag = 1; 859b50d902SRodney W. Grimes break; 869b50d902SRodney W. Grimes case 's': /* silent run */ 879b50d902SRodney W. Grimes sflag = 1; 883e6902efSBrian Somers zflag = 1; 899b50d902SRodney W. Grimes break; 90e03983a3SPoul-Henning Kamp case 'x': /* hex output */ 91e03983a3SPoul-Henning Kamp lflag = 1; 92e03983a3SPoul-Henning Kamp xflag = 1; 93e03983a3SPoul-Henning Kamp break; 943e6902efSBrian Somers case 'z': /* compare size first */ 953e6902efSBrian Somers zflag = 1; 963e6902efSBrian Somers break; 979b50d902SRodney W. Grimes case '?': 989b50d902SRodney W. Grimes default: 999b50d902SRodney W. Grimes usage(); 1009b50d902SRodney W. Grimes } 1019b50d902SRodney W. Grimes argv += optind; 1029b50d902SRodney W. Grimes argc -= optind; 1039b50d902SRodney W. Grimes 1049b50d902SRodney W. Grimes if (lflag && sflag) 1053e6902efSBrian Somers errx(ERR_EXIT, "specifying -s with -l or -x is not permitted"); 1069b50d902SRodney W. Grimes 1079b50d902SRodney W. Grimes if (argc < 2 || argc > 4) 1089b50d902SRodney W. Grimes usage(); 1099b50d902SRodney W. Grimes 1109b50d902SRodney W. Grimes /* Backward compatibility -- handle "-" meaning stdin. */ 1119b50d902SRodney W. Grimes special = 0; 1129b50d902SRodney W. Grimes if (strcmp(file1 = argv[0], "-") == 0) { 1139b50d902SRodney W. Grimes special = 1; 1149b50d902SRodney W. Grimes fd1 = 0; 1159b50d902SRodney W. Grimes file1 = "stdin"; 1169b50d902SRodney W. Grimes } 117e1bfde1bSBrian Somers else if ((fd1 = open(file1, oflag, 0)) < 0 && errno != EMLINK) { 118e5266259SJordan K. Hubbard if (!sflag) 1199b50d902SRodney W. Grimes err(ERR_EXIT, "%s", file1); 120e5266259SJordan K. Hubbard else 121c8718058STim J. Robbins exit(ERR_EXIT); 122e5266259SJordan K. Hubbard } 1239b50d902SRodney W. Grimes if (strcmp(file2 = argv[1], "-") == 0) { 1249b50d902SRodney W. Grimes if (special) 1259b50d902SRodney W. Grimes errx(ERR_EXIT, 1269b50d902SRodney W. Grimes "standard input may only be specified once"); 1279b50d902SRodney W. Grimes special = 1; 1289b50d902SRodney W. Grimes fd2 = 0; 1299b50d902SRodney W. Grimes file2 = "stdin"; 1309b50d902SRodney W. Grimes } 131e1bfde1bSBrian Somers else if ((fd2 = open(file2, oflag, 0)) < 0 && errno != EMLINK) { 132e5266259SJordan K. Hubbard if (!sflag) 1339b50d902SRodney W. Grimes err(ERR_EXIT, "%s", file2); 134e5266259SJordan K. Hubbard else 135c8718058STim J. Robbins exit(ERR_EXIT); 136e5266259SJordan K. Hubbard } 1379b50d902SRodney W. Grimes 1381e17b945SJonathan Lemon skip1 = argc > 2 ? strtol(argv[2], NULL, 0) : 0; 1391e17b945SJonathan Lemon skip2 = argc == 4 ? strtol(argv[3], NULL, 0) : 0; 1409b50d902SRodney W. Grimes 141e1bfde1bSBrian Somers if (fd1 == -1) { 142e1bfde1bSBrian Somers if (fd2 == -1) { 143e1bfde1bSBrian Somers c_link(file1, skip1, file2, skip2); 144e1bfde1bSBrian Somers exit(0); 145e1bfde1bSBrian Somers } else if (!sflag) 146e1bfde1bSBrian Somers errx(ERR_EXIT, "%s: Not a symbolic link", file2); 147e1bfde1bSBrian Somers else 148e1bfde1bSBrian Somers exit(ERR_EXIT); 149e1bfde1bSBrian Somers } else if (fd2 == -1) { 150e1bfde1bSBrian Somers if (!sflag) 151e1bfde1bSBrian Somers errx(ERR_EXIT, "%s: Not a symbolic link", file1); 152e1bfde1bSBrian Somers else 153e1bfde1bSBrian Somers exit(ERR_EXIT); 154e1bfde1bSBrian Somers } 155e1bfde1bSBrian Somers 156e75a7302SConrad Meyer cap_rights_init(&rights, CAP_FCNTL, CAP_FSTAT, CAP_MMAP_R); 157e75a7302SConrad Meyer if (cap_rights_limit(fd1, &rights) < 0 && errno != ENOSYS) 158e75a7302SConrad Meyer err(ERR_EXIT, "unable to limit rights for %s", file1); 159e75a7302SConrad Meyer if (cap_rights_limit(fd2, &rights) < 0 && errno != ENOSYS) 160e75a7302SConrad Meyer err(ERR_EXIT, "unable to limit rights for %s", file2); 161e75a7302SConrad Meyer 162e75a7302SConrad Meyer /* Required for fdopen(3). */ 163e75a7302SConrad Meyer fcntls = CAP_FCNTL_GETFL; 164e75a7302SConrad Meyer if (cap_fcntls_limit(fd1, fcntls) < 0 && errno != ENOSYS) 165e75a7302SConrad Meyer err(ERR_EXIT, "unable to limit fcntls for %s", file1); 166e75a7302SConrad Meyer if (cap_fcntls_limit(fd2, fcntls) < 0 && errno != ENOSYS) 167e75a7302SConrad Meyer err(ERR_EXIT, "unable to limit fcntls for %s", file2); 168e75a7302SConrad Meyer 169abdfa0b1SMariusz Zaborski if (!special) { 170abdfa0b1SMariusz Zaborski cap_rights_init(&rights); 171abdfa0b1SMariusz Zaborski if (cap_rights_limit(STDIN_FILENO, &rights) < 0 && 172abdfa0b1SMariusz Zaborski errno != ENOSYS) { 173abdfa0b1SMariusz Zaborski err(ERR_EXIT, "unable to limit stdio"); 174abdfa0b1SMariusz Zaborski } 175abdfa0b1SMariusz Zaborski } 176abdfa0b1SMariusz Zaborski 177a4e3fc54SMariusz Zaborski if (caph_limit_stdout() == -1 || caph_limit_stderr() == -1) 178a4e3fc54SMariusz Zaborski err(ERR_EXIT, "unable to limit stdio"); 179e75a7302SConrad Meyer 180a4e3fc54SMariusz Zaborski caph_cache_catpages(); 181e75a7302SConrad Meyer 182e75a7302SConrad Meyer if (cap_enter() < 0 && errno != ENOSYS) 183e75a7302SConrad Meyer err(ERR_EXIT, "unable to enter capability mode"); 184e75a7302SConrad Meyer 1859b50d902SRodney W. Grimes if (!special) { 186e5266259SJordan K. Hubbard if (fstat(fd1, &sb1)) { 187e5266259SJordan K. Hubbard if (!sflag) 1889b50d902SRodney W. Grimes err(ERR_EXIT, "%s", file1); 189e5266259SJordan K. Hubbard else 190c8718058STim J. Robbins exit(ERR_EXIT); 191e5266259SJordan K. Hubbard } 1929b50d902SRodney W. Grimes if (!S_ISREG(sb1.st_mode)) 1939b50d902SRodney W. Grimes special = 1; 1949b50d902SRodney W. Grimes else { 195e5266259SJordan K. Hubbard if (fstat(fd2, &sb2)) { 196e5266259SJordan K. Hubbard if (!sflag) 1979b50d902SRodney W. Grimes err(ERR_EXIT, "%s", file2); 198e5266259SJordan K. Hubbard else 199c8718058STim J. Robbins exit(ERR_EXIT); 200e5266259SJordan K. Hubbard } 2019b50d902SRodney W. Grimes if (!S_ISREG(sb2.st_mode)) 2029b50d902SRodney W. Grimes special = 1; 2039b50d902SRodney W. Grimes } 2049b50d902SRodney W. Grimes } 2059b50d902SRodney W. Grimes 2069b50d902SRodney W. Grimes if (special) 2079b50d902SRodney W. Grimes c_special(fd1, file1, skip1, fd2, file2, skip2); 2081727cb4cSSheldon Hearn else { 2093e6902efSBrian Somers if (zflag && sb1.st_size != sb2.st_size) { 2103e6902efSBrian Somers if (!sflag) 2113e6902efSBrian Somers (void) printf("%s %s differ: size\n", 2123e6902efSBrian Somers file1, file2); 2133e6902efSBrian Somers exit(DIFF_EXIT); 2143e6902efSBrian Somers } 2159b50d902SRodney W. Grimes c_regular(fd1, file1, skip1, sb1.st_size, 2169b50d902SRodney W. Grimes fd2, file2, skip2, sb2.st_size); 2171727cb4cSSheldon Hearn } 2189b50d902SRodney W. Grimes exit(0); 2199b50d902SRodney W. Grimes } 2209b50d902SRodney W. Grimes 2219b50d902SRodney W. Grimes static void 222f2e8e0daSDavid Malone usage(void) 2239b50d902SRodney W. Grimes { 2249b50d902SRodney W. Grimes 2259b50d902SRodney W. Grimes (void)fprintf(stderr, 226e1bfde1bSBrian Somers "usage: cmp [-l | -s | -x] [-hz] file1 file2 [skip1 [skip2]]\n"); 2279b50d902SRodney W. Grimes exit(ERR_EXIT); 2289b50d902SRodney W. Grimes } 229