diff options
Diffstat (limited to 'usr/src/lib/libcmd/common/cksum.c')
-rw-r--r-- | usr/src/lib/libcmd/common/cksum.c | 632 |
1 files changed, 0 insertions, 632 deletions
diff --git a/usr/src/lib/libcmd/common/cksum.c b/usr/src/lib/libcmd/common/cksum.c deleted file mode 100644 index c42e865b09..0000000000 --- a/usr/src/lib/libcmd/common/cksum.c +++ /dev/null @@ -1,632 +0,0 @@ -/*********************************************************************** -* * -* This software is part of the ast package * -* Copyright (c) 1992-2010 AT&T Intellectual Property * -* and is licensed under the * -* Common Public License, Version 1.0 * -* by AT&T Intellectual Property * -* * -* A copy of the License is available at * -* http://www.opensource.org/licenses/cpl1.0.txt * -* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * -* * -* Information and Software Systems Research * -* AT&T Research * -* Florham Park NJ * -* * -* Glenn Fowler <gsf@research.att.com> * -* David Korn <dgk@research.att.com> * -* * -***********************************************************************/ -#pragma prototyped -/* - * Glenn Fowler - * AT&T Research - * - * sum -- list file checksum and size - */ - -static const char usage[] = -"[-?\n@(#)$Id: sum (AT&T Research) 2009-11-28 $\n]" -USAGE_LICENSE -"[+NAME?cksum,md5sum,sum - print file checksum and block count]" -"[+DESCRIPTION?\bsum\b lists the checksum, and for most methods the block" -" count, for each file argument. The standard input is read if there are" -" no \afile\a arguments. \bgetconf UNIVERSE\b determines the default" -" \bsum\b method: \batt\b for the \batt\b universe, \bbsd\b otherwise." -" The default for the other commands is the command name itself. The" -" \batt\b method is a true sum, all others are order dependent.]" -"[+?Method names consist of a leading identifier and 0 or more options" -" separated by -.]" -"[+?\bgetconf PATH_RESOLVE\b determines how symbolic links are handled. This" -" can be explicitly overridden by the \b--logical\b, \b--metaphysical\b," -" and \b--physical\b options below. \bPATH_RESOLVE\b can be one of:]{" -" [+logical?Follow all symbolic links.]" -" [+metaphysical?Follow command argument symbolic links," -" otherwise don't follow.]" -" [+physical?Don't follow symbolic links.]" -"}" - -"[a:all?List the checksum for all files. Use with \b--total\b to list both" -" individual and total checksums and block counts.]" -"[b:binary?Read files in binary mode. This is the default.]" -"[B:scale?Block count scale (bytes per block) override for methods that" -" include size in the output. The default is method specific.]#[scale]" -"[c:check?Each \afile\a is interpreted as the output from a previous \bsum\b." -" If \b--header\b or \b--permissions\b was specified in the previous" -" \bsum\b then the checksum method is automatically determined," -" otherwise \b--method\b must be specified. The listed checksum is" -" compared with the current value and a warning is issued for each file" -" that does not match. If \afile\a was generated by \b--permissions\b" -" then the file mode, user and group are also checked. Empty lines," -" lines starting with \b#<space>\b, or the line \b#\b are ignored. Lines" -" containing no blanks are interpreted as [no]]\aname\a[=\avalue\a]]" -" options:]{" -" [+method=name?Checksum method to apply to subsequent lines.]" -" [+permissions?Subsequent lines were generated with" -" \b--permissions\b.]" -"}" -"[h:header?Print the checksum method as the first output line. Used with" -" \b--check\b and \b--permissions\b.]" -"[l:list?Each \afile\a is interpreted as a list of files, one per line," -" that is checksummed.]" -"[p:permissions?If \b--check\b is not specified then list the file" -" mode, user and group between the checksum and path. User and group" -" matching the caller are output as \b-\b. If \b--check\b is" -" specified then the mode, user and group for each path in \afile\a" -" are updated if necessary to match those in \afile\a. A warning is" -" printed on the standard error for each changed file.]" -"[R:recursive?Recursively checksum the contents of directories.]" -"[S:silent|status?No output for \b--check\b; 0 exit status means all sums" -" matched, non-0 means at least one sum failed to match. Ignored for" -" \b--permissions\b.]" -"[t:total?List only the total checksum and block count of all files." -" \b--all\b \b--total\b lists each checksum and the total. The" -" total checksum and block count may be different from the checksum" -" and block count of the catenation of all files due to partial" -" blocks that may occur when the files are treated separately.]" -"[T:text?Read files in text mode (i.e., treat \b\\r\\n\b as \b\\n\b).]" -"[w!:warn?Warn about invalid \b--check\b lines.]" -"[x:method|algorithm?Specifies the checksum \amethod\a to" -" apply. Parenthesized method options are readonly implementation" -" details.]:[method]{\fmethods\f}" -"[L:logical|follow?Follow symbolic links when traversing directories. The" -" default is determined by \bgetconf PATH_RESOLVE\b.]" -"[H:metaphysical?Follow command argument symbolic links, otherwise don't" -" follow symbolic links when traversing directories. The default is" -" determined by \bgetconf PATH_RESOLVE\b.]" -"[P:physical?Don't follow symbolic links when traversing directories. The" -" default is determined by \bgetconf PATH_RESOLVE\b.]" -"[r:bsd?Equivalent to \b--method=bsd --scale=512\b for compatibility with" -" other \bsum\b(1) implementations.]" -"[s:sysv?Equivalent to \b--method=sys5\b for compatibility with other" -" \bsum\b(1) implementations.]" - -"\n" -"\n[ file ... ]\n" -"\n" - -"[+SEE ALSO?\bgetconf\b(1), \btw\b(1), \buuencode\b(1)]" -; - -#include <cmd.h> -#include <sum.h> -#include <ls.h> -#include <modex.h> -#include <fts_fix.h> -#include <error.h> - -typedef struct State_s /* program state */ -{ - int all; /* list all items */ - Sfio_t* check; /* check previous output */ - int flags; /* sumprint() SUM_* flags */ - gid_t gid; /* caller gid */ - int header; /* list method on output */ - int list; /* list file name too */ - Sum_t* oldsum; /* previous sum method */ - int permissions; /* include mode,uer,group */ - int haveperm; /* permissions in the input */ - int recursive; /* recursively descend dirs */ - size_t scale; /* scale override */ - unsigned long size; /* combined size of all files */ - int silent; /* silent check, 0 exit if ok */ - int (*sort)(FTSENT* const*, FTSENT* const*); - Sum_t* sum; /* sum method */ - int text; /* \r\n == \n */ - int total; /* list totals only */ - uid_t uid; /* caller uid */ - int warn; /* invalid check line warnings */ -} State_t; - -static void verify(State_t*, char*, char*, Sfio_t*); - -/* - * open path for read mode - */ - -static Sfio_t* -openfile(const char* path, const char* mode) -{ - Sfio_t* sp; - - if (!path || streq(path, "-") || streq(path, "/dev/stdin") || streq(path, "/dev/fd/0")) - { - sp = sfstdin; - sfopen(sp, NiL, mode); - } - else if (!(sp = sfopen(NiL, path, mode))) - error(ERROR_SYSTEM|2, "%s: cannot read", path); - return sp; -} - -/* - * close an openfile() stream - */ - -static int -closefile(Sfio_t* sp) -{ - return sp == sfstdin ? 0 : sfclose(sp); -} - -/* - * compute and print sum on an open file - */ - -static void -pr(State_t* state, Sfio_t* op, Sfio_t* ip, char* file, int perm, struct stat* st, Sfio_t* check) -{ - register char* p; - register char* r; - register char* e; - register int peek; - struct stat ss; - - if (check) - { - state->oldsum = state->sum; - while (p = sfgetr(ip, '\n', 1)) - verify(state, p, file, check); - state->sum = state->oldsum; - if (state->warn && !sfeof(ip)) - error(2, "%s: last line incomplete", file); - return; - } - suminit(state->sum); - if (state->text) - { - peek = 0; - while (p = sfreserve(ip, SF_UNBOUND, 0)) - { - e = p + sfvalue(ip); - if (peek) - { - peek = 0; - if (*p != '\n') - sumblock(state->sum, "\r", 1); - } - while (r = memchr(p, '\r', e - p)) - { - if (++r >= e) - { - e--; - peek = 1; - break; - } - sumblock(state->sum, p, r - p - (*r == '\n')); - p = r; - } - sumblock(state->sum, p, e - p); - } - if (peek) - sumblock(state->sum, "\r", 1); - } - else - while (p = sfreserve(ip, SF_UNBOUND, 0)) - sumblock(state->sum, p, sfvalue(ip)); - if (sfvalue(ip)) - error(ERROR_SYSTEM|2, "%s: read error", file); - sumdone(state->sum); - if (!state->total || state->all) - { - sumprint(state->sum, op, state->flags|SUM_SCALE, state->scale); - if (perm >= 0) - { - if (perm) - { - if (!st && fstat(sffileno(ip), st = &ss)) - error(ERROR_SYSTEM|2, "%s: cannot stat", file); - else - sfprintf(sfstdout, " %04o %s %s", - modex(st->st_mode & S_IPERM), - (st->st_uid != state->uid && ((st->st_mode & S_ISUID) || (st->st_mode & S_IRUSR) && !(st->st_mode & (S_IRGRP|S_IROTH)) || (st->st_mode & S_IXUSR) && !(st->st_mode & (S_IXGRP|S_IXOTH)))) ? fmtuid(st->st_uid) : "-", - (st->st_gid != state->gid && ((st->st_mode & S_ISGID) || (st->st_mode & S_IRGRP) && !(st->st_mode & S_IROTH) || (st->st_mode & S_IXGRP) && !(st->st_mode & S_IXOTH))) ? fmtgid(st->st_gid) : "-"); - } - if (ip != sfstdin) - sfprintf(op, " %s", file); - sfputc(op, '\n'); - } - } -} - -/* - * verify previous sum output - */ - -static void -verify(State_t* state, register char* s, char* check, Sfio_t* rp) -{ - register char* t; - char* e; - char* file; - int attr; - int mode; - int uid; - int gid; - Sfio_t* sp; - struct stat st; - - if (!*s || *s == '#' && (!*(s + 1) || *(s + 1) == ' ' || *(s + 1) == '\t')) - return; - if (t = strchr(s, ' ')) - { - if ((t - s) > 10 || !(file = strchr(t + 1, ' '))) - file = t; - *file++ = 0; - attr = 0; - if ((mode = strtol(file, &e, 8)) && *e == ' ' && (e - file) == 4) - { - mode = modei(mode); - if (t = strchr(++e, ' ')) - { - if (*e == '-' && (t - e) == 1) - uid = -1; - else - { - *t = 0; - uid = struid(e); - *t = ' '; - } - if (e = strchr(++t, ' ')) - { - if (*t == '-' && (e - t) == 1) - gid = -1; - else - { - *e = 0; - gid = struid(t); - *e = ' '; - } - file = e + 1; - attr = 1; - } - } - } - if (sp = openfile(file, "rb")) - { - pr(state, rp, sp, file, -1, NiL, NiL); - if (!(t = sfstruse(rp))) - error(ERROR_SYSTEM|3, "out of space"); - if (!streq(s, t)) - { - if (state->silent) - error_info.errors++; - else - error(2, "%s: checksum changed", file); - } - else if (attr) - { - if (fstat(sffileno(sp), &st)) - { - if (state->silent) - error_info.errors++; - else - error(ERROR_SYSTEM|2, "%s: cannot stat", file); - } - else - { - if (uid < 0 || uid == st.st_uid) - uid = -1; - else if (!state->permissions) - { - if (state->silent) - error_info.errors++; - else - error(2, "%s: uid should be %s", file, fmtuid(uid)); - } - if (gid < 0 || gid == st.st_gid) - gid = -1; - else if (!state->permissions) - { - if (state->silent) - error_info.errors++; - else - error(2, "%s: gid should be %s", file, fmtgid(gid)); - } - if (state->permissions && (uid >= 0 || gid >= 0)) - { - if (chown(file, uid, gid) < 0) - { - if (uid < 0) - error(ERROR_SYSTEM|2, "%s: cannot change group to %s", file, fmtgid(gid)); - else if (gid < 0) - error(ERROR_SYSTEM|2, "%s: cannot change user to %s", file, fmtuid(uid)); - else - error(ERROR_SYSTEM|2, "%s: cannot change user to %s and group to %s", file, fmtuid(uid), fmtgid(gid)); - } - else - { - if (uid < 0) - error(1, "%s: changed group to %s", file, fmtgid(gid)); - else if (gid < 0) - error(1, "%s: changed user to %s", file, fmtuid(uid)); - else - error(1, "%s: changed user to %s and group to %s", file, fmtuid(uid), fmtgid(gid)); - } - } - if ((st.st_mode & S_IPERM) ^ mode) - { - if (state->permissions) - { - if (chmod(file, mode) < 0) - error(ERROR_SYSTEM|2, "%s: cannot change mode to %s", file, fmtmode(mode, 0)); - else - error(ERROR_SYSTEM|1, "%s: changed mode to %s", file, fmtmode(mode, 0)); - } - else if (state->silent) - error_info.errors++; - else - error(2, "%s: mode should be %s", file, fmtmode(mode, 0)); - } - } - } - closefile(sp); - } - } - else if (strneq(s, "method=", 7)) - { - s += 7; - if (state->sum != state->oldsum) - sumclose(state->sum); - if (!(state->sum = sumopen(s))) - error(3, "%s: %s: unknown checksum method", check, s); - } - else if (streq(s, "permissions")) - state->haveperm = 1; - else - error(1, "%s: %s: unknown option", check, s); -} - -/* - * sum the list of files in lp - */ - -static void -list(State_t* state, register Sfio_t* lp) -{ - register char* file; - register Sfio_t* sp; - - while (file = sfgetr(lp, '\n', 1)) - if (sp = openfile(file, state->check ? "rt" : "rb")) - { - pr(state, sfstdout, sp, file, state->permissions, NiL, state->check); - closefile(sp); - } -} - -/* - * order child entries - */ - -static int -order(FTSENT* const* f1, FTSENT* const* f2) -{ - return strcoll((*f1)->fts_name, (*f2)->fts_name); -} - -/* - * optget() info discipline function - */ - -static int -optinfo(Opt_t* op, Sfio_t* sp, const char* s, Optdisc_t* dp) -{ - if (streq(s, "methods")) - return sumusage(sp); - return 0; -} - -int -b_cksum(int argc, register char** argv, void* context) -{ - register int flags; - char* file; - char* method; - Sfio_t* sp; - FTS* fts; - FTSENT* ent; - int logical; - Optdisc_t optdisc; - State_t state; - - cmdinit(argc, argv, context, ERROR_CATALOG, ERROR_NOTIFY); - memset(&state, 0, sizeof(state)); - flags = fts_flags() | FTS_TOP | FTS_NOPOSTORDER; - state.flags = SUM_SIZE; - state.warn = 1; - logical = 1; - method = 0; - optinit(&optdisc, optinfo); - for (;;) - { - switch (optget(argv, usage)) - { - case 'a': - state.all = 1; - continue; - case 'b': - state.text = 0; - continue; - case 'B': - state.scale = opt_info.num; - continue; - case 'c': - if (!(state.check = sfstropen())) - error(3, "out of space [check]"); - continue; - case 'h': - state.header = 1; - continue; - case 'l': - state.list = 1; - continue; - case 'p': - state.permissions = 1; - continue; - case 'r': - method = "bsd"; - state.scale = 512; - state.flags |= SUM_LEGACY; - continue; - case 'R': - flags &= ~FTS_TOP; - state.recursive = 1; - state.sort = order; - logical = 0; - continue; - case 's': - method = "sys5"; - continue; - case 'S': - state.silent = opt_info.num; - continue; - case 't': - state.total = 1; - continue; - case 'w': - state.warn = opt_info.num; - continue; - case 'x': - method = opt_info.arg; - continue; - case 'H': - flags |= FTS_META|FTS_PHYSICAL; - logical = 0; - continue; - case 'L': - flags &= ~(FTS_META|FTS_PHYSICAL); - logical = 0; - continue; - case 'P': - flags &= ~FTS_META; - flags |= FTS_PHYSICAL; - logical = 0; - continue; - case 'T': - state.text = 1; - continue; - case '?': - error(ERROR_USAGE|4, "%s", opt_info.arg); - break; - case ':': - error(2, "%s", opt_info.arg); - break; - } - break; - } - argv += opt_info.index; - if (error_info.errors) - error(ERROR_USAGE|4, "%s", optusage(NiL)); - - /* - * check the method - */ - - if (method && !(state.sum = sumopen(method))) - error(3, "%s: unknown checksum method", method); - if (!state.sum && !(state.sum = sumopen(error_info.id)) && !(state.sum = sumopen(astconf("UNIVERSE", NiL, NiL)))) - state.sum = sumopen(NiL); - - /* - * do it - */ - - if (logical) - { - flags &= ~(FTS_META|FTS_PHYSICAL); - flags |= FTS_SEEDOTDIR; - } - if (state.permissions) - { - state.uid = geteuid(); - state.gid = getegid(); - state.silent = 0; - } - if (!state.check && (state.header || state.permissions)) - { - sfprintf(sfstdout, "method=%s\n", state.sum->name); - if (state.permissions) - sfprintf(sfstdout, "permissions\n"); - } - if (state.list) - { - if (*argv) - { - while (file = *argv++) - if (sp = openfile(file, "rt")) - { - list(&state, sp); - closefile(sp); - } - } - else if (sp = openfile(NiL, "rt")) - { - list(&state, sp); - closefile(sp); - } - } - else if (!*argv && !state.recursive) - pr(&state, sfstdout, sfstdin, "/dev/stdin", state.permissions, NiL, state.check); - else if (!(fts = fts_open(argv, flags, state.sort))) - error(ERROR_system(1), "%s: not found", *argv); - else - { - while (!sh_checksig(context) && (ent = fts_read(fts))) - switch (ent->fts_info) - { - case FTS_SL: - if (!(flags & FTS_PHYSICAL) || (flags & FTS_META) && ent->fts_level == 1) - fts_set(NiL, ent, FTS_FOLLOW); - break; - case FTS_F: - if (sp = openfile(ent->fts_accpath, "rb")) - { - pr(&state, sfstdout, sp, ent->fts_path, state.permissions, ent->fts_statp, state.check); - closefile(sp); - } - break; - case FTS_DC: - error(ERROR_warn(0), "%s: directory causes cycle", ent->fts_accpath); - break; - case FTS_DNR: - error(ERROR_system(0), "%s: cannot read directory", ent->fts_accpath); - break; - case FTS_DNX: - error(ERROR_system(0), "%s: cannot search directory", ent->fts_accpath); - break; - case FTS_NS: - error(ERROR_system(0), "%s: not found", ent->fts_accpath); - break; - } - fts_close(fts); - } - if (state.total) - { - sumprint(state.sum, sfstdout, state.flags|SUM_TOTAL|SUM_SCALE, state.scale); - sfputc(sfstdout, '\n'); - } - sumclose(state.sum); - return error_info.errors != 0; -} |