11de7b4b8SPedro F. Giffuni /*- 21de7b4b8SPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 31de7b4b8SPedro F. Giffuni * 4dcf118f1SJordan K. Hubbard * Copyright (c) 1997 Robert Nordier 5dcf118f1SJordan K. Hubbard * All rights reserved. 6dcf118f1SJordan K. Hubbard * 7dcf118f1SJordan K. Hubbard * Redistribution and use in source and binary forms, with or without 8dcf118f1SJordan K. Hubbard * modification, are permitted provided that the following conditions 9dcf118f1SJordan K. Hubbard * are met: 10dcf118f1SJordan K. Hubbard * 1. Redistributions of source code must retain the above copyright 11dcf118f1SJordan K. Hubbard * notice, this list of conditions and the following disclaimer. 12dcf118f1SJordan K. Hubbard * 2. Redistributions in binary form must reproduce the above copyright 13dcf118f1SJordan K. Hubbard * notice, this list of conditions and the following disclaimer in 14dcf118f1SJordan K. Hubbard * the documentation and/or other materials provided with the 15dcf118f1SJordan K. Hubbard * distribution. 16dcf118f1SJordan K. Hubbard * 17dcf118f1SJordan K. Hubbard * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS 18dcf118f1SJordan K. Hubbard * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19dcf118f1SJordan K. Hubbard * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20dcf118f1SJordan K. Hubbard * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY 21dcf118f1SJordan K. Hubbard * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22dcf118f1SJordan K. Hubbard * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 23dcf118f1SJordan K. Hubbard * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24dcf118f1SJordan K. Hubbard * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25dcf118f1SJordan K. Hubbard * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 26dcf118f1SJordan K. Hubbard * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27dcf118f1SJordan K. Hubbard * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28dcf118f1SJordan K. Hubbard */ 29dcf118f1SJordan K. Hubbard 3055c5024eSPhilippe Charnier #ifndef lint 3155c5024eSPhilippe Charnier static const char rcsid[] = 3297d92980SPeter Wemm "$FreeBSD$"; 3355c5024eSPhilippe Charnier #endif /* not lint */ 3455c5024eSPhilippe Charnier 35dcf118f1SJordan K. Hubbard #include <sys/types.h> 36dcf118f1SJordan K. Hubbard #include <sys/stat.h> 37fadcf8aeSRobert Drehmel 38dcf118f1SJordan K. Hubbard #include <err.h> 39dcf118f1SJordan K. Hubbard #include <errno.h> 4055c5024eSPhilippe Charnier #include <fcntl.h> 4155c5024eSPhilippe Charnier #include <fts.h> 4255c5024eSPhilippe Charnier #include <md5.h> 4355c5024eSPhilippe Charnier #include <stdio.h> 44fadcf8aeSRobert Drehmel #include <stdint.h> 45dcf118f1SJordan K. Hubbard #include <stdlib.h> 46dcf118f1SJordan K. Hubbard #include <string.h> 4755c5024eSPhilippe Charnier #include <unistd.h> 48dcf118f1SJordan K. Hubbard 49fadcf8aeSRobert Drehmel extern int crc(int fd, uint32_t *cval, off_t *clen); 50dcf118f1SJordan K. Hubbard 51dcf118f1SJordan K. Hubbard #define DISTMD5 1 /* MD5 format */ 52dcf118f1SJordan K. Hubbard #define DISTINF 2 /* .inf format */ 53dcf118f1SJordan K. Hubbard #define DISTTYPES 2 /* types supported */ 54dcf118f1SJordan K. Hubbard 55dcf118f1SJordan K. Hubbard #define E_UNKNOWN 1 /* Unknown format */ 56dcf118f1SJordan K. Hubbard #define E_BADMD5 2 /* Invalid MD5 format */ 57dcf118f1SJordan K. Hubbard #define E_BADINF 3 /* Invalid .inf format */ 58dcf118f1SJordan K. Hubbard #define E_NAME 4 /* Can't derive component name */ 59dcf118f1SJordan K. Hubbard #define E_LENGTH 5 /* Length mismatch */ 60dcf118f1SJordan K. Hubbard #define E_CHKSUM 6 /* Checksum mismatch */ 61dcf118f1SJordan K. Hubbard #define E_ERRNO 7 /* sys_errlist[errno] */ 62dcf118f1SJordan K. Hubbard 63dcf118f1SJordan K. Hubbard #define isfatal(err) ((err) && (err) <= E_NAME) 64dcf118f1SJordan K. Hubbard 65dcf118f1SJordan K. Hubbard #define NAMESIZE 256 /* filename buffer size */ 66dcf118f1SJordan K. Hubbard #define MDSUMLEN 32 /* length of MD5 message digest */ 67dcf118f1SJordan K. Hubbard 68dcf118f1SJordan K. Hubbard #define isstdin(path) ((path)[0] == '-' && !(path)[1]) 69dcf118f1SJordan K. Hubbard 70dcf118f1SJordan K. Hubbard static const char *opt_dir; /* where to look for components */ 71dcf118f1SJordan K. Hubbard static const char *opt_name; /* name for accessing components */ 72dcf118f1SJordan K. Hubbard static int opt_all; /* report on all components */ 73dcf118f1SJordan K. Hubbard static int opt_ignore; /* ignore missing components */ 74dcf118f1SJordan K. Hubbard static int opt_recurse; /* search directories recursively */ 75dcf118f1SJordan K. Hubbard static int opt_silent; /* silent about inaccessible files */ 76dcf118f1SJordan K. Hubbard static int opt_type; /* dist type: md5 or inf */ 77dcf118f1SJordan K. Hubbard static int opt_exist; /* just verify existence */ 78dcf118f1SJordan K. Hubbard 79dcf118f1SJordan K. Hubbard static int ckdist(const char *path, int type); 80dcf118f1SJordan K. Hubbard static int chkmd5(FILE * fp, const char *path); 81dcf118f1SJordan K. Hubbard static int chkinf(FILE * fp, const char *path); 82dcf118f1SJordan K. Hubbard static int report(const char *path, const char *name, int error); 83dcf118f1SJordan K. Hubbard static const char *distname(const char *path, const char *name, 84dcf118f1SJordan K. Hubbard const char *ext); 859d21c94eSXin LI static const char *stripath(const char *path); 86dcf118f1SJordan K. Hubbard static int distfile(const char *path); 87dcf118f1SJordan K. Hubbard static int disttype(const char *name); 88dcf118f1SJordan K. Hubbard static int fail(const char *path, const char *msg); 89dcf118f1SJordan K. Hubbard static void usage(void); 90dcf118f1SJordan K. Hubbard 91dcf118f1SJordan K. Hubbard int 92dcf118f1SJordan K. Hubbard main(int argc, char *argv[]) 93dcf118f1SJordan K. Hubbard { 94dcf118f1SJordan K. Hubbard static char *arg[2]; 95dcf118f1SJordan K. Hubbard struct stat sb; 96dcf118f1SJordan K. Hubbard FTS *ftsp; 97dcf118f1SJordan K. Hubbard FTSENT *f; 98dcf118f1SJordan K. Hubbard int rval, c, type; 99dcf118f1SJordan K. Hubbard 100dcf118f1SJordan K. Hubbard while ((c = getopt(argc, argv, "ad:in:rst:x")) != -1) 101dcf118f1SJordan K. Hubbard switch (c) { 102dcf118f1SJordan K. Hubbard case 'a': 103dcf118f1SJordan K. Hubbard opt_all = 1; 104dcf118f1SJordan K. Hubbard break; 105dcf118f1SJordan K. Hubbard case 'd': 106dcf118f1SJordan K. Hubbard opt_dir = optarg; 107dcf118f1SJordan K. Hubbard break; 108dcf118f1SJordan K. Hubbard case 'i': 109dcf118f1SJordan K. Hubbard opt_ignore = 1; 110dcf118f1SJordan K. Hubbard break; 111dcf118f1SJordan K. Hubbard case 'n': 112dcf118f1SJordan K. Hubbard opt_name = optarg; 113dcf118f1SJordan K. Hubbard break; 114dcf118f1SJordan K. Hubbard case 'r': 115dcf118f1SJordan K. Hubbard opt_recurse = 1; 116dcf118f1SJordan K. Hubbard break; 117dcf118f1SJordan K. Hubbard case 's': 118dcf118f1SJordan K. Hubbard opt_silent = 1; 119dcf118f1SJordan K. Hubbard break; 120dcf118f1SJordan K. Hubbard case 't': 121dcf118f1SJordan K. Hubbard if ((opt_type = disttype(optarg)) == 0) { 122dcf118f1SJordan K. Hubbard warnx("illegal argument to -t option"); 123dcf118f1SJordan K. Hubbard usage(); 124dcf118f1SJordan K. Hubbard } 125dcf118f1SJordan K. Hubbard break; 126dcf118f1SJordan K. Hubbard case 'x': 127dcf118f1SJordan K. Hubbard opt_exist = 1; 128dcf118f1SJordan K. Hubbard break; 129dcf118f1SJordan K. Hubbard default: 130dcf118f1SJordan K. Hubbard usage(); 131dcf118f1SJordan K. Hubbard } 132dcf118f1SJordan K. Hubbard argc -= optind; 133dcf118f1SJordan K. Hubbard argv += optind; 134dcf118f1SJordan K. Hubbard if (argc < 1) 135dcf118f1SJordan K. Hubbard usage(); 136dcf118f1SJordan K. Hubbard if (opt_dir) { 137dcf118f1SJordan K. Hubbard if (stat(opt_dir, &sb)) 1387f69f4fdSPhilippe Charnier err(2, "%s", opt_dir); 139dcf118f1SJordan K. Hubbard if (!S_ISDIR(sb.st_mode)) 14055c5024eSPhilippe Charnier errx(2, "%s: not a directory", opt_dir); 141dcf118f1SJordan K. Hubbard } 142dcf118f1SJordan K. Hubbard rval = 0; 143dcf118f1SJordan K. Hubbard do { 144dcf118f1SJordan K. Hubbard if (isstdin(*argv)) 145dcf118f1SJordan K. Hubbard rval |= ckdist(*argv, opt_type); 146dcf118f1SJordan K. Hubbard else if (stat(*argv, &sb)) 147dcf118f1SJordan K. Hubbard rval |= fail(*argv, NULL); 148dcf118f1SJordan K. Hubbard else if (S_ISREG(sb.st_mode)) 149dcf118f1SJordan K. Hubbard rval |= ckdist(*argv, opt_type); 150dcf118f1SJordan K. Hubbard else { 151dcf118f1SJordan K. Hubbard arg[0] = *argv; 152dcf118f1SJordan K. Hubbard if ((ftsp = fts_open(arg, FTS_LOGICAL, NULL)) == NULL) 153dcf118f1SJordan K. Hubbard err(2, "fts_open"); 154*2dfa4b66SBryan Drewery while (errno = 0, (f = fts_read(ftsp)) != NULL) 155dcf118f1SJordan K. Hubbard switch (f->fts_info) { 156dcf118f1SJordan K. Hubbard case FTS_DC: 157dcf118f1SJordan K. Hubbard rval = fail(f->fts_path, "Directory causes a cycle"); 158dcf118f1SJordan K. Hubbard break; 159dcf118f1SJordan K. Hubbard case FTS_DNR: 160dcf118f1SJordan K. Hubbard case FTS_ERR: 161dcf118f1SJordan K. Hubbard case FTS_NS: 162dcf118f1SJordan K. Hubbard rval = fail(f->fts_path, sys_errlist[f->fts_errno]); 163dcf118f1SJordan K. Hubbard break; 164dcf118f1SJordan K. Hubbard case FTS_D: 165dcf118f1SJordan K. Hubbard if (!opt_recurse && f->fts_level > FTS_ROOTLEVEL && 166dcf118f1SJordan K. Hubbard fts_set(ftsp, f, FTS_SKIP)) 167dcf118f1SJordan K. Hubbard err(2, "fts_set"); 168dcf118f1SJordan K. Hubbard break; 169dcf118f1SJordan K. Hubbard case FTS_F: 170dcf118f1SJordan K. Hubbard if ((type = distfile(f->fts_name)) != 0 && 171dcf118f1SJordan K. Hubbard (!opt_type || type == opt_type)) 172dcf118f1SJordan K. Hubbard rval |= ckdist(f->fts_path, type); 173dcf118f1SJordan K. Hubbard break; 174dcf118f1SJordan K. Hubbard default: ; 175dcf118f1SJordan K. Hubbard } 176dcf118f1SJordan K. Hubbard if (errno) 177dcf118f1SJordan K. Hubbard err(2, "fts_read"); 178dcf118f1SJordan K. Hubbard if (fts_close(ftsp)) 179dcf118f1SJordan K. Hubbard err(2, "fts_close"); 180dcf118f1SJordan K. Hubbard } 181dcf118f1SJordan K. Hubbard } while (*++argv); 182dcf118f1SJordan K. Hubbard return rval; 183dcf118f1SJordan K. Hubbard } 184dcf118f1SJordan K. Hubbard 185dcf118f1SJordan K. Hubbard static int 186dcf118f1SJordan K. Hubbard ckdist(const char *path, int type) 187dcf118f1SJordan K. Hubbard { 188dcf118f1SJordan K. Hubbard FILE *fp; 189dcf118f1SJordan K. Hubbard int rval, c; 190dcf118f1SJordan K. Hubbard 191dcf118f1SJordan K. Hubbard if (isstdin(path)) { 192dcf118f1SJordan K. Hubbard path = "(stdin)"; 193dcf118f1SJordan K. Hubbard fp = stdin; 194dcf118f1SJordan K. Hubbard } else if ((fp = fopen(path, "r")) == NULL) 195dcf118f1SJordan K. Hubbard return fail(path, NULL); 196dcf118f1SJordan K. Hubbard if (!type) { 197dcf118f1SJordan K. Hubbard if (fp != stdin) 198dcf118f1SJordan K. Hubbard type = distfile(path); 199dcf118f1SJordan K. Hubbard if (!type) 200dcf118f1SJordan K. Hubbard if ((c = fgetc(fp)) != EOF) { 201dcf118f1SJordan K. Hubbard type = c == 'M' ? DISTMD5 : c == 'P' ? DISTINF : 0; 202dcf118f1SJordan K. Hubbard (void)ungetc(c, fp); 203dcf118f1SJordan K. Hubbard } 204dcf118f1SJordan K. Hubbard } 205dcf118f1SJordan K. Hubbard switch (type) { 206dcf118f1SJordan K. Hubbard case DISTMD5: 207dcf118f1SJordan K. Hubbard rval = chkmd5(fp, path); 208dcf118f1SJordan K. Hubbard break; 209dcf118f1SJordan K. Hubbard case DISTINF: 210dcf118f1SJordan K. Hubbard rval = chkinf(fp, path); 211dcf118f1SJordan K. Hubbard break; 212dcf118f1SJordan K. Hubbard default: 213dcf118f1SJordan K. Hubbard rval = report(path, NULL, E_UNKNOWN); 214dcf118f1SJordan K. Hubbard } 215dcf118f1SJordan K. Hubbard if (ferror(fp)) 2167f69f4fdSPhilippe Charnier warn("%s", path); 217dcf118f1SJordan K. Hubbard if (fp != stdin && fclose(fp)) 2187f69f4fdSPhilippe Charnier err(2, "%s", path); 219dcf118f1SJordan K. Hubbard return rval; 220dcf118f1SJordan K. Hubbard } 221dcf118f1SJordan K. Hubbard 222dcf118f1SJordan K. Hubbard static int 223dcf118f1SJordan K. Hubbard chkmd5(FILE * fp, const char *path) 224dcf118f1SJordan K. Hubbard { 225dcf118f1SJordan K. Hubbard char buf[298]; /* "MD5 (NAMESIZE = MDSUMLEN" */ 226dcf118f1SJordan K. Hubbard char name[NAMESIZE + 1]; 227dcf118f1SJordan K. Hubbard char sum[MDSUMLEN + 1], chk[MDSUMLEN + 1]; 228dcf118f1SJordan K. Hubbard const char *dname; 229dcf118f1SJordan K. Hubbard char *s; 230dcf118f1SJordan K. Hubbard int rval, error, c, fd; 231dcf118f1SJordan K. Hubbard char ch; 232dcf118f1SJordan K. Hubbard 233dcf118f1SJordan K. Hubbard rval = 0; 234dcf118f1SJordan K. Hubbard while (fgets(buf, sizeof(buf), fp)) { 235dcf118f1SJordan K. Hubbard dname = NULL; 236dcf118f1SJordan K. Hubbard error = 0; 237dcf118f1SJordan K. Hubbard if (((c = sscanf(buf, "MD5 (%256s = %32s%c", name, sum, 238dcf118f1SJordan K. Hubbard &ch)) != 3 && (!feof(fp) || c != 2)) || 239dcf118f1SJordan K. Hubbard (c == 3 && ch != '\n') || 240dcf118f1SJordan K. Hubbard (s = strrchr(name, ')')) == NULL || 241dcf118f1SJordan K. Hubbard strlen(sum) != MDSUMLEN) 242dcf118f1SJordan K. Hubbard error = E_BADMD5; 243dcf118f1SJordan K. Hubbard else { 244dcf118f1SJordan K. Hubbard *s = 0; 245dcf118f1SJordan K. Hubbard if ((dname = distname(path, name, NULL)) == NULL) 246dcf118f1SJordan K. Hubbard error = E_NAME; 247dcf118f1SJordan K. Hubbard else if (opt_exist) { 248dcf118f1SJordan K. Hubbard if ((fd = open(dname, O_RDONLY)) == -1) 249dcf118f1SJordan K. Hubbard error = E_ERRNO; 250dcf118f1SJordan K. Hubbard else if (close(fd)) 2517f69f4fdSPhilippe Charnier err(2, "%s", dname); 2529d21c94eSXin LI } else if (!MD5File(dname, chk)) 253dcf118f1SJordan K. Hubbard error = E_ERRNO; 254dcf118f1SJordan K. Hubbard else if (strcmp(chk, sum)) 255dcf118f1SJordan K. Hubbard error = E_CHKSUM; 256dcf118f1SJordan K. Hubbard } 257dcf118f1SJordan K. Hubbard if (opt_ignore && error == E_ERRNO && errno == ENOENT) 258dcf118f1SJordan K. Hubbard continue; 259dcf118f1SJordan K. Hubbard if (error || opt_all) 260dcf118f1SJordan K. Hubbard rval |= report(path, dname, error); 261dcf118f1SJordan K. Hubbard if (isfatal(error)) 262dcf118f1SJordan K. Hubbard break; 263dcf118f1SJordan K. Hubbard } 264dcf118f1SJordan K. Hubbard return rval; 265dcf118f1SJordan K. Hubbard } 266dcf118f1SJordan K. Hubbard 267dcf118f1SJordan K. Hubbard static int 268dcf118f1SJordan K. Hubbard chkinf(FILE * fp, const char *path) 269dcf118f1SJordan K. Hubbard { 270dcf118f1SJordan K. Hubbard char buf[30]; /* "cksum.2 = 10 6" */ 271dcf118f1SJordan K. Hubbard char ext[3]; 272dcf118f1SJordan K. Hubbard struct stat sb; 273dcf118f1SJordan K. Hubbard const char *dname; 274fadcf8aeSRobert Drehmel off_t len; 275fadcf8aeSRobert Drehmel u_long sum; 276fadcf8aeSRobert Drehmel intmax_t sumlen; 277fadcf8aeSRobert Drehmel uint32_t chk; 278dcf118f1SJordan K. Hubbard int rval, error, c, pieces, cnt, fd; 279dcf118f1SJordan K. Hubbard char ch; 280dcf118f1SJordan K. Hubbard 281dcf118f1SJordan K. Hubbard rval = 0; 282dcf118f1SJordan K. Hubbard for (cnt = -1; fgets(buf, sizeof(buf), fp); cnt++) { 283dcf118f1SJordan K. Hubbard fd = -1; 284dcf118f1SJordan K. Hubbard dname = NULL; 285dcf118f1SJordan K. Hubbard error = 0; 286dcf118f1SJordan K. Hubbard if (cnt == -1) { 287dcf118f1SJordan K. Hubbard if ((c = sscanf(buf, "Pieces = %d%c", &pieces, &ch)) != 2 || 288dcf118f1SJordan K. Hubbard ch != '\n' || pieces < 1) 289dcf118f1SJordan K. Hubbard error = E_BADINF; 290fadcf8aeSRobert Drehmel } else if (((c = sscanf(buf, "cksum.%2s = %lu %jd%c", ext, &sum, 291fadcf8aeSRobert Drehmel &sumlen, &ch)) != 4 && 292dcf118f1SJordan K. Hubbard (!feof(fp) || c != 3)) || (c == 4 && ch != '\n') || 293dcf118f1SJordan K. Hubbard ext[0] != 'a' + cnt / 26 || ext[1] != 'a' + cnt % 26) 294dcf118f1SJordan K. Hubbard error = E_BADINF; 295dcf118f1SJordan K. Hubbard else if ((dname = distname(fp == stdin ? NULL : path, NULL, 296dcf118f1SJordan K. Hubbard ext)) == NULL) 297dcf118f1SJordan K. Hubbard error = E_NAME; 298dcf118f1SJordan K. Hubbard else if ((fd = open(dname, O_RDONLY)) == -1) 299dcf118f1SJordan K. Hubbard error = E_ERRNO; 300dcf118f1SJordan K. Hubbard else if (fstat(fd, &sb)) 301dcf118f1SJordan K. Hubbard error = E_ERRNO; 302fadcf8aeSRobert Drehmel else if (sb.st_size != (off_t)sumlen) 303dcf118f1SJordan K. Hubbard error = E_LENGTH; 304dcf118f1SJordan K. Hubbard else if (!opt_exist) { 305dcf118f1SJordan K. Hubbard if (crc(fd, &chk, &len)) 306dcf118f1SJordan K. Hubbard error = E_ERRNO; 307dcf118f1SJordan K. Hubbard else if (chk != sum) 308dcf118f1SJordan K. Hubbard error = E_CHKSUM; 309dcf118f1SJordan K. Hubbard } 310dcf118f1SJordan K. Hubbard if (fd != -1 && close(fd)) 3117f69f4fdSPhilippe Charnier err(2, "%s", dname); 312dcf118f1SJordan K. Hubbard if (opt_ignore && error == E_ERRNO && errno == ENOENT) 313dcf118f1SJordan K. Hubbard continue; 314dcf118f1SJordan K. Hubbard if (error || (opt_all && cnt >= 0)) 315dcf118f1SJordan K. Hubbard rval |= report(path, dname, error); 316dcf118f1SJordan K. Hubbard if (isfatal(error)) 317dcf118f1SJordan K. Hubbard break; 318dcf118f1SJordan K. Hubbard } 319dcf118f1SJordan K. Hubbard return rval; 320dcf118f1SJordan K. Hubbard } 321dcf118f1SJordan K. Hubbard 322dcf118f1SJordan K. Hubbard static int 323dcf118f1SJordan K. Hubbard report(const char *path, const char *name, int error) 324dcf118f1SJordan K. Hubbard { 325dcf118f1SJordan K. Hubbard if (name) 326dcf118f1SJordan K. Hubbard name = stripath(name); 327dcf118f1SJordan K. Hubbard switch (error) { 328dcf118f1SJordan K. Hubbard case E_UNKNOWN: 329dcf118f1SJordan K. Hubbard printf("%s: Unknown format\n", path); 330dcf118f1SJordan K. Hubbard break; 331dcf118f1SJordan K. Hubbard case E_BADMD5: 332dcf118f1SJordan K. Hubbard printf("%s: Invalid MD5 format\n", path); 333dcf118f1SJordan K. Hubbard break; 334dcf118f1SJordan K. Hubbard case E_BADINF: 335dcf118f1SJordan K. Hubbard printf("%s: Invalid .inf format\n", path); 336dcf118f1SJordan K. Hubbard break; 337dcf118f1SJordan K. Hubbard case E_NAME: 338dcf118f1SJordan K. Hubbard printf("%s: Can't derive component name\n", path); 339dcf118f1SJordan K. Hubbard break; 340dcf118f1SJordan K. Hubbard case E_LENGTH: 341dcf118f1SJordan K. Hubbard printf("%s: %s: Size mismatch\n", path, name); 342dcf118f1SJordan K. Hubbard break; 343dcf118f1SJordan K. Hubbard case E_CHKSUM: 344dcf118f1SJordan K. Hubbard printf("%s: %s: Checksum mismatch\n", path, name); 345dcf118f1SJordan K. Hubbard break; 346dcf118f1SJordan K. Hubbard case E_ERRNO: 347dcf118f1SJordan K. Hubbard printf("%s: %s: %s\n", path, name, sys_errlist[errno]); 348dcf118f1SJordan K. Hubbard break; 349dcf118f1SJordan K. Hubbard default: 350dcf118f1SJordan K. Hubbard printf("%s: %s: OK\n", path, name); 351dcf118f1SJordan K. Hubbard } 352dcf118f1SJordan K. Hubbard return error != 0; 353dcf118f1SJordan K. Hubbard } 354dcf118f1SJordan K. Hubbard 355dcf118f1SJordan K. Hubbard static const char * 356dcf118f1SJordan K. Hubbard distname(const char *path, const char *name, const char *ext) 357dcf118f1SJordan K. Hubbard { 358dcf118f1SJordan K. Hubbard static char buf[NAMESIZE]; 359dcf118f1SJordan K. Hubbard size_t plen, nlen; 360dcf118f1SJordan K. Hubbard char *s; 361dcf118f1SJordan K. Hubbard 362dcf118f1SJordan K. Hubbard if (opt_name) 363dcf118f1SJordan K. Hubbard name = opt_name; 364dcf118f1SJordan K. Hubbard else if (!name) { 365dcf118f1SJordan K. Hubbard if (!path) 366dcf118f1SJordan K. Hubbard return NULL; 367dcf118f1SJordan K. Hubbard name = stripath(path); 368dcf118f1SJordan K. Hubbard } 369dcf118f1SJordan K. Hubbard nlen = strlen(name); 370dcf118f1SJordan K. Hubbard if (ext && nlen > 4 && name[nlen - 4] == '.' && 371dcf118f1SJordan K. Hubbard disttype(name + nlen - 3) == DISTINF) 372dcf118f1SJordan K. Hubbard nlen -= 4; 373dcf118f1SJordan K. Hubbard if (opt_dir) { 374dcf118f1SJordan K. Hubbard path = opt_dir; 375dcf118f1SJordan K. Hubbard plen = strlen(path); 376dcf118f1SJordan K. Hubbard } else 377dcf118f1SJordan K. Hubbard plen = path && (s = strrchr(path, '/')) != NULL ? 378dcf118f1SJordan K. Hubbard (size_t)(s - path) : 0; 379dcf118f1SJordan K. Hubbard if (plen + (plen > 0) + nlen + (ext ? 3 : 0) >= sizeof(buf)) 380dcf118f1SJordan K. Hubbard return NULL; 381dcf118f1SJordan K. Hubbard s = buf; 382dcf118f1SJordan K. Hubbard if (plen) { 383dcf118f1SJordan K. Hubbard memcpy(s, path, plen); 384dcf118f1SJordan K. Hubbard s += plen; 385dcf118f1SJordan K. Hubbard *s++ = '/'; 386dcf118f1SJordan K. Hubbard } 387dcf118f1SJordan K. Hubbard memcpy(s, name, nlen); 388dcf118f1SJordan K. Hubbard s += nlen; 389dcf118f1SJordan K. Hubbard if (ext) { 390dcf118f1SJordan K. Hubbard *s++ = '.'; 391dcf118f1SJordan K. Hubbard memcpy(s, ext, 2); 392dcf118f1SJordan K. Hubbard s += 2; 393dcf118f1SJordan K. Hubbard } 394dcf118f1SJordan K. Hubbard *s = 0; 395dcf118f1SJordan K. Hubbard return buf; 396dcf118f1SJordan K. Hubbard } 397dcf118f1SJordan K. Hubbard 3989d21c94eSXin LI static const char * 399dcf118f1SJordan K. Hubbard stripath(const char *path) 400dcf118f1SJordan K. Hubbard { 401dcf118f1SJordan K. Hubbard const char *s; 402dcf118f1SJordan K. Hubbard 4039d21c94eSXin LI return ((s = strrchr(path, '/')) != NULL && s[1] ? 404dcf118f1SJordan K. Hubbard s + 1 : path); 405dcf118f1SJordan K. Hubbard } 406dcf118f1SJordan K. Hubbard 407dcf118f1SJordan K. Hubbard static int 408dcf118f1SJordan K. Hubbard distfile(const char *path) 409dcf118f1SJordan K. Hubbard { 410dcf118f1SJordan K. Hubbard const char *s; 411dcf118f1SJordan K. Hubbard int type; 412dcf118f1SJordan K. Hubbard 413dcf118f1SJordan K. Hubbard if ((type = disttype(path)) == DISTMD5 || 414dcf118f1SJordan K. Hubbard ((s = strrchr(path, '.')) != NULL && s > path && 415dcf118f1SJordan K. Hubbard (type = disttype(s + 1)) != 0)) 416dcf118f1SJordan K. Hubbard return type; 417dcf118f1SJordan K. Hubbard return 0; 418dcf118f1SJordan K. Hubbard } 419dcf118f1SJordan K. Hubbard 420dcf118f1SJordan K. Hubbard static int 421dcf118f1SJordan K. Hubbard disttype(const char *name) 422dcf118f1SJordan K. Hubbard { 423dcf118f1SJordan K. Hubbard static const char dname[DISTTYPES][4] = {"md5", "inf"}; 424dcf118f1SJordan K. Hubbard int i; 425dcf118f1SJordan K. Hubbard 426dcf118f1SJordan K. Hubbard for (i = 0; i < DISTTYPES; i++) 427dcf118f1SJordan K. Hubbard if (!strcmp(dname[i], name)) 428dcf118f1SJordan K. Hubbard return 1 + i; 429dcf118f1SJordan K. Hubbard return 0; 430dcf118f1SJordan K. Hubbard } 431dcf118f1SJordan K. Hubbard 432dcf118f1SJordan K. Hubbard static int 433dcf118f1SJordan K. Hubbard fail(const char *path, const char *msg) 434dcf118f1SJordan K. Hubbard { 435dcf118f1SJordan K. Hubbard if (opt_silent) 436dcf118f1SJordan K. Hubbard return 0; 437dcf118f1SJordan K. Hubbard warnx("%s: %s", path, msg ? msg : sys_errlist[errno]); 438dcf118f1SJordan K. Hubbard return 2; 439dcf118f1SJordan K. Hubbard } 440dcf118f1SJordan K. Hubbard 441dcf118f1SJordan K. Hubbard static void 442dcf118f1SJordan K. Hubbard usage(void) 443dcf118f1SJordan K. Hubbard { 444dcf118f1SJordan K. Hubbard fprintf(stderr, 44555c5024eSPhilippe Charnier "usage: ckdist [-airsx] [-d dir] [-n name] [-t type] file ...\n"); 446dcf118f1SJordan K. Hubbard exit(2); 447dcf118f1SJordan K. Hubbard } 448