diff options
Diffstat (limited to 'util/sbase/libutil')
38 files changed, 2466 insertions, 0 deletions
| diff --git a/util/sbase/libutil/concat.c b/util/sbase/libutil/concat.c new file mode 100644 index 00000000..2e9aa521 --- /dev/null +++ b/util/sbase/libutil/concat.c @@ -0,0 +1,23 @@ +/* See LICENSE file for copyright and license details. */ +#include <unistd.h> + +#include "../util.h" + +int +concat(int f1, const char *s1, int f2, const char *s2) +{ +	char buf[BUFSIZ]; +	ssize_t n; + +	while ((n = read(f1, buf, sizeof(buf))) > 0) { +		if (writeall(f2, buf, n) < 0) { +			weprintf("write %s:", s2); +			return -2; +		} +	} +	if (n < 0) { +		weprintf("read %s:", s1); +		return -1; +	} +	return 0; +} diff --git a/util/sbase/libutil/confirm.c b/util/sbase/libutil/confirm.c new file mode 100644 index 00000000..44396af9 --- /dev/null +++ b/util/sbase/libutil/confirm.c @@ -0,0 +1,22 @@ +/* See LICENSE file for copyright and license details. */ +#include <stdarg.h> +#include <ctype.h> + +#include "../util.h" + +int +confirm(const char *fmt, ...) +{ +	int c, ans; +	va_list ap; + +	va_start(ap, fmt); +	xvprintf(fmt, ap); +	va_end(ap); + +	c = getchar(); +	ans = (c == 'y' || c == 'Y'); +	while (c != '\n' && c != EOF) +		c = getchar(); +	return ans; +} diff --git a/util/sbase/libutil/cp.c b/util/sbase/libutil/cp.c new file mode 100644 index 00000000..2ab32a03 --- /dev/null +++ b/util/sbase/libutil/cp.c @@ -0,0 +1,176 @@ +/* See LICENSE file for copyright and license details. */ +#include <dirent.h> +#include <errno.h> +#include <fcntl.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> +#include <utime.h> + +#include "../fs.h" +#include "../util.h" + +int cp_aflag  = 0; +int cp_fflag  = 0; +int cp_iflag  = 0; +int cp_pflag  = 0; +int cp_rflag  = 0; +int cp_vflag  = 0; +int cp_status = 0; +int cp_follow; + +int +cp(const char *s1, const char *s2, int depth) +{ +	DIR *dp; +	int f1, f2, flags = 0; +	struct dirent *d; +	struct stat st; +	struct timespec times[2]; +	ssize_t r; +	char target[PATH_MAX], ns1[PATH_MAX], ns2[PATH_MAX]; + +	if (cp_follow == 'P' || (cp_follow == 'H' && depth)) +		flags |= AT_SYMLINK_NOFOLLOW; + +	if (fstatat(AT_FDCWD, s1, &st, flags) < 0) { +		weprintf("stat %s:", s1); +		cp_status = 1; +		return 0; +	} + +	if (cp_iflag && access(s2, F_OK) == 0) { +		if (!confirm("overwrite '%s'? ", s2)) +			return 0; +	} + +	if (cp_vflag) +		printf("%s -> %s\n", s1, s2); + +	if (S_ISLNK(st.st_mode)) { +		if ((r = readlink(s1, target, sizeof(target) - 1)) >= 0) { +			target[r] = '\0'; +			if (cp_fflag && unlink(s2) < 0 && errno != ENOENT) { +				weprintf("unlink %s:", s2); +				cp_status = 1; +				return 0; +			} else if (symlink(target, s2) < 0) { +				weprintf("symlink %s -> %s:", s2, target); +				cp_status = 1; +				return 0; +			} +		} +	} else if (S_ISDIR(st.st_mode)) { +		if (!cp_rflag) { +			weprintf("%s is a directory\n", s1); +			cp_status = 1; +			return 0; +		} +		if (!(dp = opendir(s1))) { +			weprintf("opendir %s:", s1); +			cp_status = 1; +			return 0; +		} +		if (mkdir(s2, st.st_mode) < 0 && errno != EEXIST) { +			weprintf("mkdir %s:", s2); +			cp_status = 1; +			closedir(dp); +			return 0; +		} + +		while ((d = readdir(dp))) { +			if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) +				continue; + +			estrlcpy(ns1, s1, sizeof(ns1)); +			if (s1[strlen(s1) - 1] != '/') +				estrlcat(ns1, "/", sizeof(ns1)); +			estrlcat(ns1, d->d_name, sizeof(ns1)); + +			estrlcpy(ns2, s2, sizeof(ns2)); +			if (s2[strlen(s2) - 1] != '/') +				estrlcat(ns2, "/", sizeof(ns2)); +			estrlcat(ns2, d->d_name, sizeof(ns2)); + +			fnck(ns1, ns2, cp, depth + 1); +		} + +		closedir(dp); +	} else if (cp_aflag && (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode) || +	           S_ISSOCK(st.st_mode) || S_ISFIFO(st.st_mode))) { +		if (cp_fflag && unlink(s2) < 0 && errno != ENOENT) { +			weprintf("unlink %s:", s2); +			cp_status = 1; +			return 0; +		} else if (mknod(s2, st.st_mode, st.st_rdev) < 0) { +			weprintf("mknod %s:", s2); +			cp_status = 1; +			return 0; +		} +	} else { +		if ((f1 = open(s1, O_RDONLY)) < 0) { +			weprintf("open %s:", s1); +			cp_status = 1; +			return 0; +		} +		if ((f2 = creat(s2, st.st_mode)) < 0 && cp_fflag) { +			if (unlink(s2) < 0 && errno != ENOENT) { +				weprintf("unlink %s:", s2); +				cp_status = 1; +				close(f1); +				return 0; +			} +			f2 = creat(s2, st.st_mode); +		} +		if (f2 < 0) { +			weprintf("creat %s:", s2); +			cp_status = 1; +			close(f1); +			return 0; +		} +		if (concat(f1, s1, f2, s2) < 0) { +			cp_status = 1; +			close(f1); +			close(f2); +			return 0; +		} + +		close(f1); +		close(f2); +	} + +	if (cp_aflag || cp_pflag) { +		/* atime and mtime */ +		times[0] = st.st_atim; +		times[1] = st.st_mtim; +		if (utimensat(AT_FDCWD, s2, times, AT_SYMLINK_NOFOLLOW) < 0) { +			weprintf("utimensat %s:", s2); +			cp_status = 1; +		} + +		/* owner and mode */ +		if (!S_ISLNK(st.st_mode)) { +			if (chown(s2, st.st_uid, st.st_gid) < 0) { +				weprintf("chown %s:", s2); +				cp_status = 1; +				st.st_mode &= ~(S_ISUID | S_ISGID); +			} +			if (chmod(s2, st.st_mode) < 0) { +				weprintf("chmod %s:", s2); +				cp_status = 1; +			} +		} else { +			if (lchown(s2, st.st_uid, st.st_gid) < 0) { +				weprintf("lchown %s:", s2); +				cp_status = 1; +				return 0; +			} +		} +	} + +	return 0; +} diff --git a/util/sbase/libutil/crypt.c b/util/sbase/libutil/crypt.c new file mode 100644 index 00000000..e285614b --- /dev/null +++ b/util/sbase/libutil/crypt.c @@ -0,0 +1,184 @@ +/* See LICENSE file for copyright and license details. */ +#include <fcntl.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "../crypt.h" +#include "../text.h" +#include "../util.h" + +static int +hexdec(int c) +{ +	if (c >= '0' && c <= '9') +		return c - '0'; +	else if (c >= 'A' && c <= 'F') +		return c - 'A' + 10; +	else if (c >= 'a' && c <= 'f') +		return c - 'a' + 10; +	return -1; /* unknown character */ +} + +static int +mdcheckline(const char *s, uint8_t *md, size_t sz) +{ +	size_t i; +	int b1, b2; + +	for (i = 0; i < sz; i++) { +		if (!*s || (b1 = hexdec(*s++)) < 0) +			return -1; /* invalid format */ +		if (!*s || (b2 = hexdec(*s++)) < 0) +			return -1; /* invalid format */ +		if ((uint8_t)((b1 << 4) | b2) != md[i]) +			return 0; /* value mismatch */ +	} +	return (i == sz) ? 1 : 0; +} + +static void +mdchecklist(FILE *listfp, struct crypt_ops *ops, uint8_t *md, size_t sz, +            int *formatsucks, int *noread, int *nonmatch) +{ +	int fd; +	size_t bufsiz = 0; +	int r; +	char *line = NULL, *file, *p; + +	while (getline(&line, &bufsiz, listfp) > 0) { +		if (!(file = strstr(line, "  "))) { +			(*formatsucks)++; +			continue; +		} +		if ((file - line) / 2 != sz) { +			(*formatsucks)++; /* checksum length mismatch */ +			continue; +		} +		*file = '\0'; +		file += 2; +		for (p = file; *p && *p != '\n' && *p != '\r'; p++); /* strip newline */ +		*p = '\0'; +		if ((fd = open(file, O_RDONLY)) < 0) { +			weprintf("open %s:", file); +			(*noread)++; +			continue; +		} +		if (cryptsum(ops, fd, file, md)) { +			(*noread)++; +			continue; +		} +		r = mdcheckline(line, md, sz); +		if (r == 1) { +			printf("%s: OK\n", file); +		} else if (r == 0) { +			printf("%s: FAILED\n", file); +			(*nonmatch)++; +		} else { +			(*formatsucks)++; +		} +		close(fd); +	} +	free(line); +} + +int +cryptcheck(int argc, char *argv[], struct crypt_ops *ops, uint8_t *md, size_t sz) +{ +	FILE *fp; +	int formatsucks = 0, noread = 0, nonmatch = 0, ret = 0; + +	if (argc == 0) { +		mdchecklist(stdin, ops, md, sz, &formatsucks, &noread, &nonmatch); +	} else { +		for (; *argv; argc--, argv++) { +			if ((*argv)[0] == '-' && !(*argv)[1]) { +				fp = stdin; +			} else if (!(fp = fopen(*argv, "r"))) { +				weprintf("fopen %s:", *argv); +				ret = 1; +				continue; +			} +			mdchecklist(fp, ops, md, sz, &formatsucks, &noread, &nonmatch); +			if (fp != stdin) +				fclose(fp); +		} +	} + +	if (formatsucks) { +		weprintf("%d lines are improperly formatted\n", formatsucks); +		ret = 1; +	} +	if (noread) { +		weprintf("%d listed file could not be read\n", noread); +		ret = 1; +	} +	if (nonmatch) { +		weprintf("%d computed checksums did NOT match\n", nonmatch); +		ret = 1; +	} + +	return ret; +} + +int +cryptmain(int argc, char *argv[], struct crypt_ops *ops, uint8_t *md, size_t sz) +{ +	int fd; +	int ret = 0; + +	if (argc == 0) { +		if (cryptsum(ops, 0, "<stdin>", md)) +			ret = 1; +		else +			mdprint(md, "<stdin>", sz); +	} else { +		for (; *argv; argc--, argv++) { +			if ((*argv)[0] == '-' && !(*argv)[1]) { +				*argv = "<stdin>"; +				fd = 0; +			} else if ((fd = open(*argv, O_RDONLY)) < 0) { +				weprintf("open %s:", *argv); +				ret = 1; +				continue; +			} +			if (cryptsum(ops, fd, *argv, md)) +				ret = 1; +			else +				mdprint(md, *argv, sz); +			if (fd != 0) +				close(fd); +		} +	} + +	return ret; +} + +int +cryptsum(struct crypt_ops *ops, int fd, const char *f, uint8_t *md) +{ +	uint8_t buf[BUFSIZ]; +	ssize_t n; + +	ops->init(ops->s); +	while ((n = read(fd, buf, sizeof(buf))) > 0) +		ops->update(ops->s, buf, n); +	if (n < 0) { +		weprintf("%s: read error:", f); +		return 1; +	} +	ops->sum(ops->s, md); +	return 0; +} + +void +mdprint(const uint8_t *md, const char *f, size_t len) +{ +	size_t i; + +	for (i = 0; i < len; i++) +		printf("%02x", md[i]); +	printf("  %s\n", f); +} diff --git a/util/sbase/libutil/ealloc.c b/util/sbase/libutil/ealloc.c new file mode 100644 index 00000000..320865da --- /dev/null +++ b/util/sbase/libutil/ealloc.c @@ -0,0 +1,88 @@ +/* See LICENSE file for copyright and license details. */ +#include <stdlib.h> +#include <string.h> + +#include "../util.h" + +void * +ecalloc(size_t nmemb, size_t size) +{ +	return encalloc(1, nmemb, size); +} + +void * +emalloc(size_t size) +{ +	return enmalloc(1, size); +} + +void * +erealloc(void *p, size_t size) +{ +	return enrealloc(1, p, size); +} + +char * +estrdup(const char *s) +{ +	return enstrdup(1, s); +} + +char * +estrndup(const char *s, size_t n) +{ +	return enstrndup(1, s, n); +} + +void * +encalloc(int status, size_t nmemb, size_t size) +{ +	void *p; + +	p = calloc(nmemb, size); +	if (!p) +		enprintf(status, "calloc: out of memory\n"); +	return p; +} + +void * +enmalloc(int status, size_t size) +{ +	void *p; + +	p = malloc(size); +	if (!p) +		enprintf(status, "malloc: out of memory\n"); +	return p; +} + +void * +enrealloc(int status, void *p, size_t size) +{ +	p = realloc(p, size); +	if (!p) +		enprintf(status, "realloc: out of memory\n"); +	return p; +} + +char * +enstrdup(int status, const char *s) +{ +	char *p; + +	p = strdup(s); +	if (!p) +		enprintf(status, "strdup: out of memory\n"); +	return p; +} + +char * +enstrndup(int status, const char *s, size_t n) +{ +	char *p; + +	p = strndup(s, n); +	if (!p) +		enprintf(status, "strndup: out of memory\n"); +	return p; +} diff --git a/util/sbase/libutil/enmasse.c b/util/sbase/libutil/enmasse.c new file mode 100644 index 00000000..a2e225ab --- /dev/null +++ b/util/sbase/libutil/enmasse.c @@ -0,0 +1,38 @@ +/* See LICENSE file for copyright and license details. */ +#include <libgen.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> +#include <unistd.h> + +#include "../util.h" + +void +enmasse(int argc, char *argv[], int (*fn)(const char *, const char *, int)) +{ +	struct stat st; +	char buf[PATH_MAX], *dir; +	int i, len; +	size_t dlen; + +	if (argc == 2 && !(stat(argv[1], &st) == 0 && S_ISDIR(st.st_mode))) { +		fnck(argv[0], argv[1], fn, 0); +		return; +	} else { +		dir = (argc == 1) ? "." : argv[--argc]; +	} + +	for (i = 0; i < argc; i++) { +		dlen = strlen(dir); +		if (dlen > 0 && dir[dlen - 1] == '/') +			len = snprintf(buf, sizeof(buf), "%s%s", dir, basename(argv[i])); +		else +			len = snprintf(buf, sizeof(buf), "%s/%s", dir, basename(argv[i])); +		if (len < 0 || len >= sizeof(buf)) { +			eprintf("%s/%s: filename too long\n", dir, +			        basename(argv[i])); +		} +		fnck(argv[i], buf, fn, 0); +	} +} diff --git a/util/sbase/libutil/eprintf.c b/util/sbase/libutil/eprintf.c new file mode 100644 index 00000000..7197fbb9 --- /dev/null +++ b/util/sbase/libutil/eprintf.c @@ -0,0 +1,57 @@ +/* See LICENSE file for copyright and license details. */ +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "../util.h" + +char *argv0; + +void +eprintf(const char *fmt, ...) +{ +	va_list ap; + +	va_start(ap, fmt); +	xvprintf(fmt, ap); +	va_end(ap); + +	exit(1); +} + +void +enprintf(int status, const char *fmt, ...) +{ +	va_list ap; + +	va_start(ap, fmt); +	xvprintf(fmt, ap); +	va_end(ap); + +	exit(status); +} + +void +weprintf(const char *fmt, ...) +{ +	va_list ap; + +	va_start(ap, fmt); +	xvprintf(fmt, ap); +	va_end(ap); +} + +void +xvprintf(const char *fmt, va_list ap) +{ +	if (argv0 && strncmp(fmt, "usage", strlen("usage"))) +		fprintf(stderr, "%s: ", argv0); + +	vfprintf(stderr, fmt, ap); + +	if (fmt[0] && fmt[strlen(fmt)-1] == ':') { +		fputc(' ', stderr); +		perror(NULL); +	} +} diff --git a/util/sbase/libutil/eregcomp.c b/util/sbase/libutil/eregcomp.c new file mode 100644 index 00000000..02c8698c --- /dev/null +++ b/util/sbase/libutil/eregcomp.c @@ -0,0 +1,27 @@ +#include <sys/types.h> + +#include <regex.h> +#include <stdio.h> + +#include "../util.h" + +int +enregcomp(int status, regex_t *preg, const char *regex, int cflags) +{ +	char errbuf[BUFSIZ] = ""; +	int r; + +	if ((r = regcomp(preg, regex, cflags)) == 0) +		return r; + +	regerror(r, preg, errbuf, sizeof(errbuf)); +	enprintf(status, "invalid regex: %s\n", errbuf); + +	return r; +} + +int +eregcomp(regex_t *preg, const char *regex, int cflags) +{ +	return enregcomp(1, preg, regex, cflags); +} diff --git a/util/sbase/libutil/estrtod.c b/util/sbase/libutil/estrtod.c new file mode 100644 index 00000000..24e4fdce --- /dev/null +++ b/util/sbase/libutil/estrtod.c @@ -0,0 +1,18 @@ +/* See LICENSE file for copyright and license details. */ +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> + +#include "../util.h" + +double +estrtod(const char *s) +{ +	char *end; +	double d; + +	d = strtod(s, &end); +	if (end == s || *end != '\0') +		eprintf("%s: not a real number\n", s); +	return d; +} diff --git a/util/sbase/libutil/fnck.c b/util/sbase/libutil/fnck.c new file mode 100644 index 00000000..4f8875ba --- /dev/null +++ b/util/sbase/libutil/fnck.c @@ -0,0 +1,22 @@ +/* See LICENSE file for copyright and license details. */ +#include <sys/stat.h> + +#include "../util.h" + +void +fnck(const char *a, const char *b, +     int (*fn)(const char *, const char *, int), int depth) +{ +	struct stat sta, stb; + +	if (!stat(a, &sta) +	    && !stat(b, &stb) +	    && sta.st_dev == stb.st_dev +	    && sta.st_ino == stb.st_ino) { +		weprintf("%s -> %s: same file\n", a, b); +		return; +	} + +	if (fn(a, b, depth) < 0) +		eprintf("%s -> %s:", a, b); +} diff --git a/util/sbase/libutil/fshut.c b/util/sbase/libutil/fshut.c new file mode 100644 index 00000000..e596f074 --- /dev/null +++ b/util/sbase/libutil/fshut.c @@ -0,0 +1,43 @@ +/* See LICENSE file for copyright and license details. */ +#include <stdio.h> +#include <stdlib.h> + +#include "../util.h" + +int +fshut(FILE *fp, const char *fname) +{ +	int ret = 0; + +	/* fflush() is undefined for input streams by ISO C, +	 * but not POSIX 2008 if you ignore ISO C overrides. +	 * Leave it unchecked and rely on the following +	 * functions to detect errors. +	 */ +	fflush(fp); + +	if (ferror(fp) && !ret) { +		weprintf("ferror %s:", fname); +		ret = 1; +	} + +	if (fclose(fp) && !ret) { +		weprintf("fclose %s:", fname); +		ret = 1; +	} + +	return ret; +} + +void +enfshut(int status, FILE *fp, const char *fname) +{ +	if (fshut(fp, fname)) +		exit(status); +} + +void +efshut(FILE *fp, const char *fname) +{ +	enfshut(1, fp, fname); +} diff --git a/util/sbase/libutil/getlines.c b/util/sbase/libutil/getlines.c new file mode 100644 index 00000000..cef9a612 --- /dev/null +++ b/util/sbase/libutil/getlines.c @@ -0,0 +1,32 @@ +/* See LICENSE file for copyright and license details. */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "../text.h" +#include "../util.h" + +void +getlines(FILE *fp, struct linebuf *b) +{ +	char *line = NULL; +	size_t size = 0, linelen = 0; +	ssize_t len; + +	while ((len = getline(&line, &size, fp)) > 0) { +		if (++b->nlines > b->capacity) { +			b->capacity += 512; +			b->lines = ereallocarray(b->lines, b->capacity, sizeof(*b->lines)); +		} +		linelen = len; +		b->lines[b->nlines - 1].data = memcpy(emalloc(linelen + 1), line, linelen + 1); +		b->lines[b->nlines - 1].len = linelen; +	} +	free(line); +	if (b->lines && b->nlines && linelen && b->lines[b->nlines - 1].data[linelen - 1] != '\n') { +		b->lines[b->nlines - 1].data = erealloc(b->lines[b->nlines - 1].data, linelen + 2); +		b->lines[b->nlines - 1].data[linelen] = '\n'; +		b->lines[b->nlines - 1].data[linelen + 1] = '\0'; +		b->lines[b->nlines - 1].len++; +	} +} diff --git a/util/sbase/libutil/human.c b/util/sbase/libutil/human.c new file mode 100644 index 00000000..7e39ba5f --- /dev/null +++ b/util/sbase/libutil/human.c @@ -0,0 +1,25 @@ +/* See LICENSE file for copyright and license details. */ +#include <stdio.h> +#include <string.h> +#include <stdint.h> + +#include "../util.h" + +char * +humansize(off_t n) +{ +	static char buf[16]; +	const char postfixes[] = "BKMGTPE"; +	double size; +	int i; + +	for (size = n, i = 0; size >= 1024 && i < strlen(postfixes); i++) +		size /= 1024; + +	if (!i) +		snprintf(buf, sizeof(buf), "%ju", (uintmax_t)n); +	else +		snprintf(buf, sizeof(buf), "%.1f%c", size, postfixes[i]); + +	return buf; +} diff --git a/util/sbase/libutil/linecmp.c b/util/sbase/libutil/linecmp.c new file mode 100644 index 00000000..08fc0e3a --- /dev/null +++ b/util/sbase/libutil/linecmp.c @@ -0,0 +1,17 @@ +/* See LICENSE file for copyright and license details. */ +#include <stdio.h> +#include <string.h> + +#include "../text.h" +#include "../util.h" + +int +linecmp(struct line *a, struct line *b) +{ +	int res = 0; + +	if (!(res = memcmp(a->data, b->data, MIN(a->len, b->len)))) +		res = a->len - b->len; + +	return res; +} diff --git a/util/sbase/libutil/md5.c b/util/sbase/libutil/md5.c new file mode 100644 index 00000000..c7483ac6 --- /dev/null +++ b/util/sbase/libutil/md5.c @@ -0,0 +1,148 @@ +/* public domain md5 implementation based on rfc1321 and libtomcrypt */ +#include <stdint.h> +#include <string.h> + +#include "../md5.h" + +static uint32_t rol(uint32_t n, int k) { return (n << k) | (n >> (32-k)); } +#define F(x,y,z) (z ^ (x & (y ^ z))) +#define G(x,y,z) (y ^ (z & (y ^ x))) +#define H(x,y,z) (x ^ y ^ z) +#define I(x,y,z) (y ^ (x | ~z)) +#define FF(a,b,c,d,w,s,t) a += F(b,c,d) + w + t; a = rol(a,s) + b +#define GG(a,b,c,d,w,s,t) a += G(b,c,d) + w + t; a = rol(a,s) + b +#define HH(a,b,c,d,w,s,t) a += H(b,c,d) + w + t; a = rol(a,s) + b +#define II(a,b,c,d,w,s,t) a += I(b,c,d) + w + t; a = rol(a,s) + b + +static const uint32_t tab[64] = { +	0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, +	0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, +	0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, +	0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, +	0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, +	0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, +	0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, +	0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 +}; + +static void +processblock(struct md5 *s, const uint8_t *buf) +{ +	uint32_t i, W[16], a, b, c, d; + +	for (i = 0; i < 16; i++) { +		W[i] = buf[4*i]; +		W[i] |= (uint32_t)buf[4*i+1]<<8; +		W[i] |= (uint32_t)buf[4*i+2]<<16; +		W[i] |= (uint32_t)buf[4*i+3]<<24; +	} + +	a = s->h[0]; +	b = s->h[1]; +	c = s->h[2]; +	d = s->h[3]; + +	i = 0; +	while (i < 16) { +		FF(a,b,c,d, W[i],  7, tab[i]); i++; +		FF(d,a,b,c, W[i], 12, tab[i]); i++; +		FF(c,d,a,b, W[i], 17, tab[i]); i++; +		FF(b,c,d,a, W[i], 22, tab[i]); i++; +	} +	while (i < 32) { +		GG(a,b,c,d, W[(5*i+1)%16],  5, tab[i]); i++; +		GG(d,a,b,c, W[(5*i+1)%16],  9, tab[i]); i++; +		GG(c,d,a,b, W[(5*i+1)%16], 14, tab[i]); i++; +		GG(b,c,d,a, W[(5*i+1)%16], 20, tab[i]); i++; +	} +	while (i < 48) { +		HH(a,b,c,d, W[(3*i+5)%16],  4, tab[i]); i++; +		HH(d,a,b,c, W[(3*i+5)%16], 11, tab[i]); i++; +		HH(c,d,a,b, W[(3*i+5)%16], 16, tab[i]); i++; +		HH(b,c,d,a, W[(3*i+5)%16], 23, tab[i]); i++; +	} +	while (i < 64) { +		II(a,b,c,d, W[7*i%16],  6, tab[i]); i++; +		II(d,a,b,c, W[7*i%16], 10, tab[i]); i++; +		II(c,d,a,b, W[7*i%16], 15, tab[i]); i++; +		II(b,c,d,a, W[7*i%16], 21, tab[i]); i++; +	} + +	s->h[0] += a; +	s->h[1] += b; +	s->h[2] += c; +	s->h[3] += d; +} + +static void +pad(struct md5 *s) +{ +	unsigned r = s->len % 64; + +	s->buf[r++] = 0x80; +	if (r > 56) { +		memset(s->buf + r, 0, 64 - r); +		r = 0; +		processblock(s, s->buf); +	} +	memset(s->buf + r, 0, 56 - r); +	s->len *= 8; +	s->buf[56] = s->len; +	s->buf[57] = s->len >> 8; +	s->buf[58] = s->len >> 16; +	s->buf[59] = s->len >> 24; +	s->buf[60] = s->len >> 32; +	s->buf[61] = s->len >> 40; +	s->buf[62] = s->len >> 48; +	s->buf[63] = s->len >> 56; +	processblock(s, s->buf); +} + +void +md5_init(void *ctx) +{ +	struct md5 *s = ctx; +	s->len = 0; +	s->h[0] = 0x67452301; +	s->h[1] = 0xefcdab89; +	s->h[2] = 0x98badcfe; +	s->h[3] = 0x10325476; +} + +void +md5_sum(void *ctx, uint8_t md[MD5_DIGEST_LENGTH]) +{ +	struct md5 *s = ctx; +	int i; + +	pad(s); +	for (i = 0; i < 4; i++) { +		md[4*i] = s->h[i]; +		md[4*i+1] = s->h[i] >> 8; +		md[4*i+2] = s->h[i] >> 16; +		md[4*i+3] = s->h[i] >> 24; +	} +} + +void +md5_update(void *ctx, const void *m, unsigned long len) +{ +	struct md5 *s = ctx; +	const uint8_t *p = m; +	unsigned r = s->len % 64; + +	s->len += len; +	if (r) { +		if (len < 64 - r) { +			memcpy(s->buf + r, p, len); +			return; +		} +		memcpy(s->buf + r, p, 64 - r); +		len -= 64 - r; +		p += 64 - r; +		processblock(s, s->buf); +	} +	for (; len >= 64; len -= 64, p += 64) +		processblock(s, p); +	memcpy(s->buf, p, len); +} diff --git a/util/sbase/libutil/memmem.c b/util/sbase/libutil/memmem.c new file mode 100644 index 00000000..7dfef34b --- /dev/null +++ b/util/sbase/libutil/memmem.c @@ -0,0 +1,66 @@ +/*	$OpenBSD: memmem.c,v 1.4 2015/08/31 02:53:57 guenther Exp $ */ + +/* + * Copyright (c) 2005 Pascal Gloor <pascal.gloor@spale.com> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in the + *    documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + *    products derived from this software without specific prior written + *    permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <string.h> + +#include "../util.h" + +/* + * Find the first occurrence of the byte string s in byte string l. + */ + +void * +memmem(const void *l, size_t l_len, const void *s, size_t s_len) +{ +	const char *cur, *last; +	const char *cl = l; +	const char *cs = s; + +	/* a zero length needle should just return the haystack */ +	if (s_len == 0) +		return (void *)cl; + +	/* "s" must be smaller or equal to "l" */ +	if (l_len < s_len) +		return NULL; + +	/* special case where s_len == 1 */ +	if (s_len == 1) +		return memchr(l, *cs, l_len); + +	/* the last position where its possible to find "s" in "l" */ +	last = cl + l_len - s_len; + +	for (cur = cl; cur <= last; cur++) +		if (cur[0] == cs[0] && memcmp(cur, cs, s_len) == 0) +			return (void *)cur; + +	return NULL; +} diff --git a/util/sbase/libutil/mkdirp.c b/util/sbase/libutil/mkdirp.c new file mode 100644 index 00000000..c3c678c0 --- /dev/null +++ b/util/sbase/libutil/mkdirp.c @@ -0,0 +1,39 @@ +/* See LICENSE file for copyright and license details. */ +#include <sys/stat.h> + +#include <errno.h> +#include <limits.h> + +#include "../util.h" + +int +mkdirp(const char *path, mode_t mode, mode_t pmode) +{ +	char tmp[PATH_MAX], *p; +	struct stat st; + +	if (stat(path, &st) == 0) { +		if (S_ISDIR(st.st_mode)) +			return 0; +		errno = ENOTDIR; +		weprintf("%s:", path); +		return -1; +	} + +	estrlcpy(tmp, path, sizeof(tmp)); +	for (p = tmp + (tmp[0] == '/'); *p; p++) { +		if (*p != '/') +			continue; +		*p = '\0'; +		if (mkdir(tmp, pmode) < 0 && errno != EEXIST) { +			weprintf("mkdir %s:", tmp); +			return -1; +		} +		*p = '/'; +	} +	if (mkdir(tmp, mode) < 0 && errno != EEXIST) { +		weprintf("mkdir %s:", tmp); +		return -1; +	} +	return 0; +} diff --git a/util/sbase/libutil/mode.c b/util/sbase/libutil/mode.c new file mode 100644 index 00000000..2754be79 --- /dev/null +++ b/util/sbase/libutil/mode.c @@ -0,0 +1,152 @@ +/* See LICENSE file for copyright and license details. */ +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> +#include <unistd.h> + +#include "../util.h" + +mode_t +getumask(void) +{ +	mode_t mask = umask(0); +	umask(mask); +	return mask; +} + +mode_t +parsemode(const char *str, mode_t mode, mode_t mask) +{ +	char *end; +	const char *p = str; +	int octal, op; +	mode_t who, perm, clear; + +	octal = strtol(str, &end, 8); +	if (*end == '\0') { +		if (octal < 0 || octal > 07777) +			eprintf("%s: invalid mode\n", str); +		return octal; +	} +next: +	/* first, determine which bits we will be modifying */ +	for (who = 0; *p; p++) { +		switch (*p) { +		/* masks */ +		case 'u': +			who |= S_IRWXU|S_ISUID; +			continue; +		case 'g': +			who |= S_IRWXG|S_ISGID; +			continue; +		case 'o': +			who |= S_IRWXO|S_ISVTX; +			continue; +		case 'a': +			who |= S_IRWXU|S_ISUID|S_IRWXG|S_ISGID|S_IRWXO|S_ISVTX; +			continue; +		} +		break; +	} +	if (who) { +		clear = who; +	} else { +		clear = S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO; +		who = ~mask; +	} +	while (*p) { +		switch (*p) { +		/* opers */ +		case '=': +		case '+': +		case '-': +			op = (int)*p; +			break; +		default: +			eprintf("%s: invalid mode\n", str); +		} + +		perm = 0; +		switch (*++p) { +		/* copy */ +		case 'u': +			if (mode & S_IRUSR) +				perm |= S_IRUSR|S_IRGRP|S_IROTH; +			if (mode & S_IWUSR) +				perm |= S_IWUSR|S_IWGRP|S_IWOTH; +			if (mode & S_IXUSR) +				perm |= S_IXUSR|S_IXGRP|S_IXOTH; +			if (mode & S_ISUID) +				perm |= S_ISUID|S_ISGID; +			p++; +			break; +		case 'g': +			if (mode & S_IRGRP) +				perm |= S_IRUSR|S_IRGRP|S_IROTH; +			if (mode & S_IWGRP) +				perm |= S_IWUSR|S_IWGRP|S_IWOTH; +			if (mode & S_IXGRP) +				perm |= S_IXUSR|S_IXGRP|S_IXOTH; +			if (mode & S_ISGID) +				perm |= S_ISUID|S_ISGID; +			p++; +			break; +		case 'o': +			if (mode & S_IROTH) +				perm |= S_IRUSR|S_IRGRP|S_IROTH; +			if (mode & S_IWOTH) +				perm |= S_IWUSR|S_IWGRP|S_IWOTH; +			if (mode & S_IXOTH) +				perm |= S_IXUSR|S_IXGRP|S_IXOTH; +			p++; +			break; +		default: +			for (; *p; p++) { +				switch (*p) { +				/* modes */ +				case 'r': +					perm |= S_IRUSR|S_IRGRP|S_IROTH; +					break; +				case 'w': +					perm |= S_IWUSR|S_IWGRP|S_IWOTH; +					break; +				case 'x': +					perm |= S_IXUSR|S_IXGRP|S_IXOTH; +					break; +				case 'X': +					if (S_ISDIR(mode) || mode & (S_IXUSR|S_IXGRP|S_IXOTH)) +						perm |= S_IXUSR|S_IXGRP|S_IXOTH; +					break; +				case 's': +					perm |= S_ISUID|S_ISGID; +					break; +				case 't': +					perm |= S_ISVTX; +					break; +				default: +					goto apply; +				} +			} +		} + +apply: +		/* apply */ +		switch (op) { +		case '=': +			mode &= ~clear; +			/* fallthrough */ +		case '+': +			mode |= perm & who; +			break; +		case '-': +			mode &= ~(perm & who); +			break; +		} +		/* if we hit a comma, move on to the next clause */ +		if (*p == ',') { +			p++; +			goto next; +		} +	} +	return mode & ~S_IFMT; +} diff --git a/util/sbase/libutil/parseoffset.c b/util/sbase/libutil/parseoffset.c new file mode 100644 index 00000000..362a7829 --- /dev/null +++ b/util/sbase/libutil/parseoffset.c @@ -0,0 +1,61 @@ +/* See LICENSE file for copyright and license details. */ +#include <ctype.h> +#include <errno.h> +#include <inttypes.h> +#include <stdlib.h> +#include <string.h> + +#include "../util.h" + +off_t +parseoffset(const char *str) +{ +	off_t res, scale = 1; +	char *end; + +	/* strictly check what strtol() usually would let pass */ +	if (!str || !*str || isspace(*str) || *str == '+' || *str == '-') { +		weprintf("parseoffset %s: invalid value\n", str); +		return -1; +	} + +	errno = 0; +	res = strtol(str, &end, 0); +	if (errno) { +		weprintf("parseoffset %s: invalid value\n", str); +		return -1; +	} +	if (res < 0) { +		weprintf("parseoffset %s: negative value\n", str); +		return -1; +	} + +	/* suffix */ +	if (*end) { +		switch (toupper((int)*end)) { +		case 'B': +			scale = 512L; +			break; +		case 'K': +			scale = 1024L; +			break; +		case 'M': +			scale = 1024L * 1024L; +			break; +		case 'G': +			scale = 1024L * 1024L * 1024L; +			break; +		default: +			weprintf("parseoffset %s: invalid suffix '%s'\n", str, end); +			return -1; +		} +	} + +	/* prevent overflow */ +	if (res > (SSIZE_MAX / scale)) { +		weprintf("parseoffset %s: out of range\n", str); +		return -1; +	} + +	return res * scale; +} diff --git a/util/sbase/libutil/putword.c b/util/sbase/libutil/putword.c new file mode 100644 index 00000000..80a9860a --- /dev/null +++ b/util/sbase/libutil/putword.c @@ -0,0 +1,16 @@ +/* See LICENSE file for copyright and license details. */ +#include <stdio.h> + +#include "../util.h" + +void +putword(FILE *fp, const char *s) +{ +	static int first = 1; + +	if (!first) +		fputc(' ', fp); + +	fputs(s, fp); +	first = 0; +} diff --git a/util/sbase/libutil/reallocarray.c b/util/sbase/libutil/reallocarray.c new file mode 100644 index 00000000..31ff6c31 --- /dev/null +++ b/util/sbase/libutil/reallocarray.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2008 Otto Moerbeek <otto@drijf.net> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/types.h> +#include <errno.h> +#include <stdint.h> +#include <stdlib.h> + +#include "../util.h" + +/* + * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX + * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW + */ +#define MUL_NO_OVERFLOW	(1UL << (sizeof(size_t) * 4)) + +void * +reallocarray(void *optr, size_t nmemb, size_t size) +{ +	if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && +	    nmemb > 0 && SIZE_MAX / nmemb < size) { +		errno = ENOMEM; +		return NULL; +	} +	return realloc(optr, size * nmemb); +} + +void * +ereallocarray(void *optr, size_t nmemb, size_t size) +{ +	return enreallocarray(1, optr, nmemb, size); +} + +void * +enreallocarray(int status, void *optr, size_t nmemb, size_t size) +{ +	void *p; + +	if (!(p = reallocarray(optr, nmemb, size))) +		enprintf(status, "reallocarray: out of memory\n"); + +	return p; +} diff --git a/util/sbase/libutil/recurse.c b/util/sbase/libutil/recurse.c new file mode 100644 index 00000000..e66efaf5 --- /dev/null +++ b/util/sbase/libutil/recurse.c @@ -0,0 +1,108 @@ +/* See LICENSE file for copyright and license details. */ +#include <dirent.h> +#include <errno.h> +#include <fcntl.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> + +#include "../fs.h" +#include "../util.h" + +int recurse_status = 0; + +void +recurse(int dirfd, const char *name, void *data, struct recursor *r) +{ +	struct dirent *d; +	struct history *new, *h; +	struct stat st, dst; +	DIR *dp; +	int flags = 0, fd; +	size_t pathlen = r->pathlen; + +	if (dirfd == AT_FDCWD) +		pathlen = estrlcpy(r->path, name, sizeof(r->path)); + +	if (r->follow == 'P' || (r->follow == 'H' && r->depth)) +		flags |= AT_SYMLINK_NOFOLLOW; + +	if (fstatat(dirfd, name, &st, flags) < 0) { +		if (!(r->flags & SILENT)) { +			weprintf("stat %s:", r->path); +			recurse_status = 1; +		} +		return; +	} +	if (!S_ISDIR(st.st_mode)) { +		r->fn(dirfd, name, &st, data, r); +		return; +	} + +	new = emalloc(sizeof(struct history)); +	new->prev  = r->hist; +	r->hist    = new; +	new->dev   = st.st_dev; +	new->ino   = st.st_ino; + +	for (h = new->prev; h; h = h->prev) +		if (h->ino == st.st_ino && h->dev == st.st_dev) +			return; + +	if (!r->depth && (r->flags & DIRFIRST)) +		r->fn(dirfd, name, &st, data, r); + +	if (!r->maxdepth || r->depth + 1 < r->maxdepth) { +		fd = openat(dirfd, name, O_RDONLY | O_CLOEXEC | O_DIRECTORY); +		if (fd < 0) { +			weprintf("open %s:", r->path); +			recurse_status = 1; +		} +		if (!(dp = fdopendir(fd))) { +			if (!(r->flags & SILENT)) { +				weprintf("fdopendir:"); +				recurse_status = 1; +			} +			return; +		} +		if (r->path[pathlen - 1] != '/') +			r->path[pathlen++] = '/'; +		if (r->follow == 'H') +			flags |= AT_SYMLINK_NOFOLLOW; +		while ((d = readdir(dp))) { +			if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) +				continue; +			r->pathlen = pathlen + estrlcpy(r->path + pathlen, d->d_name, sizeof(r->path) - pathlen); +			if (fstatat(fd, d->d_name, &dst, flags) < 0) { +				if (!(r->flags & SILENT)) { +					weprintf("stat %s:", r->path); +					recurse_status = 1; +				} +			} else if ((r->flags & SAMEDEV) && dst.st_dev != st.st_dev) { +				continue; +			} else { +				r->depth++; +				r->fn(fd, d->d_name, &dst, data, r); +				r->depth--; +			} +		} +		r->path[pathlen - 1] = '\0'; +		r->pathlen = pathlen - 1; +		closedir(dp); +	} + +	if (!r->depth) { +		if (!(r->flags & DIRFIRST)) +			r->fn(dirfd, name, &st, data, r); + +		while (r->hist) { +			h = r->hist; +			r->hist = r->hist->prev; +			free(h); +		} +	} +} diff --git a/util/sbase/libutil/rm.c b/util/sbase/libutil/rm.c new file mode 100644 index 00000000..fb99840d --- /dev/null +++ b/util/sbase/libutil/rm.c @@ -0,0 +1,49 @@ +/* See LICENSE file for copyright and license details. */ +#include <sys/stat.h> + +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <unistd.h> + +#include "../fs.h" +#include "../util.h" + +int rm_status = 0; + +void +rm(int dirfd, const char *name, struct stat *st, void *data, struct recursor *r) +{ +	int quiet, ask, write, flags, ignore; + +	ignore = r->flags & IGNORE; +	quiet = r->flags & SILENT; +	ask = r->flags & CONFIRM; +	write = faccessat(dirfd, name, W_OK, 0) == 0; +	flags = 0; + +	if (S_ISDIR(st->st_mode) && r->maxdepth) { +		errno = EISDIR; +		goto err; +	} + +	if (!quiet && (!write && isatty(0) || ask)) { +		if (!confirm("remove file '%s'", r->path)); +			return; +	} + +	if (S_ISDIR(st->st_mode)) { +		flags = AT_REMOVEDIR; +		recurse(dirfd, name, NULL, r); +	} + +	if (unlinkat(dirfd, name, flags) < 0) +		goto err; +	return; + +err: +	if (!ignore) { +		weprintf("cannot remove '%s':", r->path); +		rm_status = 1; +	} +} diff --git a/util/sbase/libutil/sha1.c b/util/sbase/libutil/sha1.c new file mode 100644 index 00000000..3d76a1be --- /dev/null +++ b/util/sbase/libutil/sha1.c @@ -0,0 +1,144 @@ +/* public domain sha1 implementation based on rfc3174 and libtomcrypt */ +#include <stdint.h> +#include <string.h> + +#include "../sha1.h" + +static uint32_t rol(uint32_t n, int k) { return (n << k) | (n >> (32-k)); } +#define F0(b,c,d) (d ^ (b & (c ^ d))) +#define F1(b,c,d) (b ^ c ^ d) +#define F2(b,c,d) ((b & c) | (d & (b | c))) +#define F3(b,c,d) (b ^ c ^ d) +#define G0(a,b,c,d,e,i) e += rol(a,5)+F0(b,c,d)+W[i]+0x5A827999; b = rol(b,30) +#define G1(a,b,c,d,e,i) e += rol(a,5)+F1(b,c,d)+W[i]+0x6ED9EBA1; b = rol(b,30) +#define G2(a,b,c,d,e,i) e += rol(a,5)+F2(b,c,d)+W[i]+0x8F1BBCDC; b = rol(b,30) +#define G3(a,b,c,d,e,i) e += rol(a,5)+F3(b,c,d)+W[i]+0xCA62C1D6; b = rol(b,30) + +static void +processblock(struct sha1 *s, const uint8_t *buf) +{ +	uint32_t W[80], a, b, c, d, e; +	int i; + +	for (i = 0; i < 16; i++) { +		W[i] = (uint32_t)buf[4*i]<<24; +		W[i] |= (uint32_t)buf[4*i+1]<<16; +		W[i] |= (uint32_t)buf[4*i+2]<<8; +		W[i] |= buf[4*i+3]; +	} +	for (; i < 80; i++) +		W[i] = rol(W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16], 1); +	a = s->h[0]; +	b = s->h[1]; +	c = s->h[2]; +	d = s->h[3]; +	e = s->h[4]; +	for (i = 0; i < 20; ) { +		G0(a,b,c,d,e,i++); +		G0(e,a,b,c,d,i++); +		G0(d,e,a,b,c,i++); +		G0(c,d,e,a,b,i++); +		G0(b,c,d,e,a,i++); +	} +	while (i < 40) { +		G1(a,b,c,d,e,i++); +		G1(e,a,b,c,d,i++); +		G1(d,e,a,b,c,i++); +		G1(c,d,e,a,b,i++); +		G1(b,c,d,e,a,i++); +	} +	while (i < 60) { +		G2(a,b,c,d,e,i++); +		G2(e,a,b,c,d,i++); +		G2(d,e,a,b,c,i++); +		G2(c,d,e,a,b,i++); +		G2(b,c,d,e,a,i++); +	} +	while (i < 80) { +		G3(a,b,c,d,e,i++); +		G3(e,a,b,c,d,i++); +		G3(d,e,a,b,c,i++); +		G3(c,d,e,a,b,i++); +		G3(b,c,d,e,a,i++); +	} +	s->h[0] += a; +	s->h[1] += b; +	s->h[2] += c; +	s->h[3] += d; +	s->h[4] += e; +} + +static void +pad(struct sha1 *s) +{ +	unsigned r = s->len % 64; + +	s->buf[r++] = 0x80; +	if (r > 56) { +		memset(s->buf + r, 0, 64 - r); +		r = 0; +		processblock(s, s->buf); +	} +	memset(s->buf + r, 0, 56 - r); +	s->len *= 8; +	s->buf[56] = s->len >> 56; +	s->buf[57] = s->len >> 48; +	s->buf[58] = s->len >> 40; +	s->buf[59] = s->len >> 32; +	s->buf[60] = s->len >> 24; +	s->buf[61] = s->len >> 16; +	s->buf[62] = s->len >> 8; +	s->buf[63] = s->len; +	processblock(s, s->buf); +} + +void +sha1_init(void *ctx) +{ +	struct sha1 *s = ctx; + +	s->len = 0; +	s->h[0] = 0x67452301; +	s->h[1] = 0xEFCDAB89; +	s->h[2] = 0x98BADCFE; +	s->h[3] = 0x10325476; +	s->h[4] = 0xC3D2E1F0; +} + +void +sha1_sum(void *ctx, uint8_t md[SHA1_DIGEST_LENGTH]) +{ +	struct sha1 *s = ctx; +	int i; + +	pad(s); +	for (i = 0; i < 5; i++) { +		md[4*i] = s->h[i] >> 24; +		md[4*i+1] = s->h[i] >> 16; +		md[4*i+2] = s->h[i] >> 8; +		md[4*i+3] = s->h[i]; +	} +} + +void +sha1_update(void *ctx, const void *m, unsigned long len) +{ +	struct sha1 *s = ctx; +	const uint8_t *p = m; +	unsigned r = s->len % 64; + +	s->len += len; +	if (r) { +		if (len < 64 - r) { +			memcpy(s->buf + r, p, len); +			return; +		} +		memcpy(s->buf + r, p, 64 - r); +		len -= 64 - r; +		p += 64 - r; +		processblock(s, s->buf); +	} +	for (; len >= 64; len -= 64, p += 64) +		processblock(s, p); +	memcpy(s->buf, p, len); +} diff --git a/util/sbase/libutil/sha224.c b/util/sbase/libutil/sha224.c new file mode 100644 index 00000000..fce520f5 --- /dev/null +++ b/util/sbase/libutil/sha224.c @@ -0,0 +1,26 @@ +/* public domain sha224 implementation based on fips180-3 */ +#include <stdint.h> +#include "../sha224.h" + +extern void sha256_sum_n(void *, uint8_t *, int n); + +void +sha224_init(void *ctx) +{ +	struct sha224 *s = ctx; +	s->len = 0; +	s->h[0] = 0xc1059ed8; +	s->h[1] = 0x367cd507; +	s->h[2] = 0x3070dd17; +	s->h[3] = 0xf70e5939; +	s->h[4] = 0xffc00b31; +	s->h[5] = 0x68581511; +	s->h[6] = 0x64f98fa7; +	s->h[7] = 0xbefa4fa4; +} + +void +sha224_sum(void *ctx, uint8_t md[SHA224_DIGEST_LENGTH]) +{ +	sha256_sum_n(ctx, md, 8); +} diff --git a/util/sbase/libutil/sha256.c b/util/sbase/libutil/sha256.c new file mode 100644 index 00000000..266cfecb --- /dev/null +++ b/util/sbase/libutil/sha256.c @@ -0,0 +1,154 @@ +/* public domain sha256 implementation based on fips180-3 */ +#include <ctype.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "../sha256.h" + +static uint32_t ror(uint32_t n, int k) { return (n >> k) | (n << (32-k)); } +#define Ch(x,y,z)  (z ^ (x & (y ^ z))) +#define Maj(x,y,z) ((x & y) | (z & (x | y))) +#define S0(x)      (ror(x,2) ^ ror(x,13) ^ ror(x,22)) +#define S1(x)      (ror(x,6) ^ ror(x,11) ^ ror(x,25)) +#define R0(x)      (ror(x,7) ^ ror(x,18) ^ (x>>3)) +#define R1(x)      (ror(x,17) ^ ror(x,19) ^ (x>>10)) + +static const uint32_t K[64] = { +0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, +0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, +0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, +0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, +0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, +0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, +0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, +0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +}; + +static void +processblock(struct sha256 *s, const uint8_t *buf) +{ +	uint32_t W[64], t1, t2, a, b, c, d, e, f, g, h; +	int i; + +	for (i = 0; i < 16; i++) { +		W[i] = (uint32_t)buf[4*i]<<24; +		W[i] |= (uint32_t)buf[4*i+1]<<16; +		W[i] |= (uint32_t)buf[4*i+2]<<8; +		W[i] |= buf[4*i+3]; +	} +	for (; i < 64; i++) +		W[i] = R1(W[i-2]) + W[i-7] + R0(W[i-15]) + W[i-16]; +	a = s->h[0]; +	b = s->h[1]; +	c = s->h[2]; +	d = s->h[3]; +	e = s->h[4]; +	f = s->h[5]; +	g = s->h[6]; +	h = s->h[7]; +	for (i = 0; i < 64; i++) { +		t1 = h + S1(e) + Ch(e,f,g) + K[i] + W[i]; +		t2 = S0(a) + Maj(a,b,c); +		h = g; +		g = f; +		f = e; +		e = d + t1; +		d = c; +		c = b; +		b = a; +		a = t1 + t2; +	} +	s->h[0] += a; +	s->h[1] += b; +	s->h[2] += c; +	s->h[3] += d; +	s->h[4] += e; +	s->h[5] += f; +	s->h[6] += g; +	s->h[7] += h; +} + +static void +pad(struct sha256 *s) +{ +	unsigned r = s->len % 64; + +	s->buf[r++] = 0x80; +	if (r > 56) { +		memset(s->buf + r, 0, 64 - r); +		r = 0; +		processblock(s, s->buf); +	} +	memset(s->buf + r, 0, 56 - r); +	s->len *= 8; +	s->buf[56] = s->len >> 56; +	s->buf[57] = s->len >> 48; +	s->buf[58] = s->len >> 40; +	s->buf[59] = s->len >> 32; +	s->buf[60] = s->len >> 24; +	s->buf[61] = s->len >> 16; +	s->buf[62] = s->len >> 8; +	s->buf[63] = s->len; +	processblock(s, s->buf); +} + +void +sha256_init(void *ctx) +{ +	struct sha256 *s = ctx; +	s->len = 0; +	s->h[0] = 0x6a09e667; +	s->h[1] = 0xbb67ae85; +	s->h[2] = 0x3c6ef372; +	s->h[3] = 0xa54ff53a; +	s->h[4] = 0x510e527f; +	s->h[5] = 0x9b05688c; +	s->h[6] = 0x1f83d9ab; +	s->h[7] = 0x5be0cd19; +} + +void +sha256_sum_n(void *ctx, uint8_t *md, int n) +{ +	struct sha256 *s = ctx; +	int i; + +	pad(s); +	for (i = 0; i < n; i++) { +		md[4*i] = s->h[i] >> 24; +		md[4*i+1] = s->h[i] >> 16; +		md[4*i+2] = s->h[i] >> 8; +		md[4*i+3] = s->h[i]; +	} +} + +void +sha256_sum(void *ctx, uint8_t md[SHA256_DIGEST_LENGTH]) +{ +	sha256_sum_n(ctx, md, 8); +} + +void +sha256_update(void *ctx, const void *m, unsigned long len) +{ +	struct sha256 *s = ctx; +	const uint8_t *p = m; +	unsigned r = s->len % 64; + +	s->len += len; +	if (r) { +		if (len < 64 - r) { +			memcpy(s->buf + r, p, len); +			return; +		} +		memcpy(s->buf + r, p, 64 - r); +		len -= 64 - r; +		p += 64 - r; +		processblock(s, s->buf); +	} +	for (; len >= 64; len -= 64, p += 64) +		processblock(s, p); +	memcpy(s->buf, p, len); +} diff --git a/util/sbase/libutil/sha384.c b/util/sbase/libutil/sha384.c new file mode 100644 index 00000000..0a0e7777 --- /dev/null +++ b/util/sbase/libutil/sha384.c @@ -0,0 +1,26 @@ +/* public domain sha384 implementation based on fips180-3 */ +#include <stdint.h> +#include "../sha384.h" + +extern void sha512_sum_n(void *, uint8_t *, int n); + +void +sha384_init(void *ctx) +{ +	struct sha384 *s = ctx; +	s->len = 0; +	s->h[0] = 0xcbbb9d5dc1059ed8ULL; +	s->h[1] = 0x629a292a367cd507ULL; +	s->h[2] = 0x9159015a3070dd17ULL; +	s->h[3] = 0x152fecd8f70e5939ULL; +	s->h[4] = 0x67332667ffc00b31ULL; +	s->h[5] = 0x8eb44a8768581511ULL; +	s->h[6] = 0xdb0c2e0d64f98fa7ULL; +	s->h[7] = 0x47b5481dbefa4fa4ULL; +} + +void +sha384_sum(void *ctx, uint8_t md[SHA384_DIGEST_LENGTH]) +{ +	sha512_sum_n(ctx, md, 6); +} diff --git a/util/sbase/libutil/sha512-224.c b/util/sbase/libutil/sha512-224.c new file mode 100644 index 00000000..a5636c13 --- /dev/null +++ b/util/sbase/libutil/sha512-224.c @@ -0,0 +1,26 @@ +/* public domain sha512/224 implementation based on fips180-3 */ +#include <stdint.h> +#include "../sha512-224.h" + +extern void sha512_sum_n(void *, uint8_t *, int n); + +void +sha512_224_init(void *ctx) +{ +	struct sha512_224 *s = ctx; +	s->len = 0; +	s->h[0] = 0x8c3d37c819544da2ULL; +	s->h[1] = 0x73e1996689dcd4d6ULL; +	s->h[2] = 0x1dfab7ae32ff9c82ULL; +	s->h[3] = 0x679dd514582f9fcfULL; +	s->h[4] = 0x0f6d2b697bd44da8ULL; +	s->h[5] = 0x77e36f7304c48942ULL; +	s->h[6] = 0x3f9d85a86a1d36c8ULL; +	s->h[7] = 0x1112e6ad91d692a1ULL; +} + +void +sha512_224_sum(void *ctx, uint8_t md[SHA512_224_DIGEST_LENGTH]) +{ +	sha512_sum_n(ctx, md, 4); +} diff --git a/util/sbase/libutil/sha512-256.c b/util/sbase/libutil/sha512-256.c new file mode 100644 index 00000000..d4b84495 --- /dev/null +++ b/util/sbase/libutil/sha512-256.c @@ -0,0 +1,26 @@ +/* public domain sha512/256 implementation based on fips180-3 */ +#include <stdint.h> +#include "../sha512-256.h" + +extern void sha512_sum_n(void *, uint8_t *, int n); + +void +sha512_256_init(void *ctx) +{ +	struct sha512_256 *s = ctx; +	s->len = 0; +	s->h[0] = 0x22312194fc2bf72cULL; +	s->h[1] = 0x9f555fa3c84c64c2ULL; +	s->h[2] = 0x2393b86b6f53b151ULL; +	s->h[3] = 0x963877195940eabdULL; +	s->h[4] = 0x96283ee2a88effe3ULL; +	s->h[5] = 0xbe5e1e2553863992ULL; +	s->h[6] = 0x2b0199fc2c85b8aaULL; +	s->h[7] = 0x0eb72ddc81c52ca2ULL; +} + +void +sha512_256_sum(void *ctx, uint8_t md[SHA512_256_DIGEST_LENGTH]) +{ +	sha512_sum_n(ctx, md, 4); +} diff --git a/util/sbase/libutil/sha512.c b/util/sbase/libutil/sha512.c new file mode 100644 index 00000000..25264c78 --- /dev/null +++ b/util/sbase/libutil/sha512.c @@ -0,0 +1,175 @@ +/* public domain sha256 implementation based on fips180-3 */ + +#include <ctype.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "../sha512.h" + +static uint64_t ror(uint64_t n, int k) { return (n >> k) | (n << (64-k)); } +#define Ch(x,y,z)  (z ^ (x & (y ^ z))) +#define Maj(x,y,z) ((x & y) | (z & (x | y))) +#define S0(x)      (ror(x,28) ^ ror(x,34) ^ ror(x,39)) +#define S1(x)      (ror(x,14) ^ ror(x,18) ^ ror(x,41)) +#define R0(x)      (ror(x,1) ^ ror(x,8) ^ (x>>7)) +#define R1(x)      (ror(x,19) ^ ror(x,61) ^ (x>>6)) + +static const uint64_t K[80] = { +0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, +0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, +0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, +0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL, +0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, +0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, +0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, +0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, +0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, +0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL, +0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, +0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, +0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, +0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, +0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, +0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, +0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, +0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, +0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL, +0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL +}; + +static void +processblock(struct sha512 *s, const uint8_t *buf) +{ +	uint64_t W[80], t1, t2, a, b, c, d, e, f, g, h; +	int i; + +	for (i = 0; i < 16; i++) { +		W[i] = (uint64_t)buf[8*i]<<56; +		W[i] |= (uint64_t)buf[8*i+1]<<48; +		W[i] |= (uint64_t)buf[8*i+2]<<40; +		W[i] |= (uint64_t)buf[8*i+3]<<32; +		W[i] |= (uint64_t)buf[8*i+4]<<24; +		W[i] |= (uint64_t)buf[8*i+5]<<16; +		W[i] |= (uint64_t)buf[8*i+6]<<8; +		W[i] |= buf[8*i+7]; +	} +	for (; i < 80; i++) +		W[i] = R1(W[i-2]) + W[i-7] + R0(W[i-15]) + W[i-16]; +	a = s->h[0]; +	b = s->h[1]; +	c = s->h[2]; +	d = s->h[3]; +	e = s->h[4]; +	f = s->h[5]; +	g = s->h[6]; +	h = s->h[7]; +	for (i = 0; i < 80; i++) { +		t1 = h + S1(e) + Ch(e,f,g) + K[i] + W[i]; +		t2 = S0(a) + Maj(a,b,c); +		h = g; +		g = f; +		f = e; +		e = d + t1; +		d = c; +		c = b; +		b = a; +		a = t1 + t2; +	} +	s->h[0] += a; +	s->h[1] += b; +	s->h[2] += c; +	s->h[3] += d; +	s->h[4] += e; +	s->h[5] += f; +	s->h[6] += g; +	s->h[7] += h; +} + +static void +pad(struct sha512 *s) +{ +	unsigned r = s->len % 128; + +	s->buf[r++] = 0x80; +	if (r > 112) { +		memset(s->buf + r, 0, 128 - r); +		r = 0; +		processblock(s, s->buf); +	} +	memset(s->buf + r, 0, 120 - r); +	s->len *= 8; +	s->buf[120] = s->len >> 56; +	s->buf[121] = s->len >> 48; +	s->buf[122] = s->len >> 40; +	s->buf[123] = s->len >> 32; +	s->buf[124] = s->len >> 24; +	s->buf[125] = s->len >> 16; +	s->buf[126] = s->len >> 8; +	s->buf[127] = s->len; +	processblock(s, s->buf); +} + +void +sha512_init(void *ctx) +{ +	struct sha512 *s = ctx; +	s->len = 0; +	s->h[0] = 0x6a09e667f3bcc908ULL; +	s->h[1] = 0xbb67ae8584caa73bULL; +	s->h[2] = 0x3c6ef372fe94f82bULL; +	s->h[3] = 0xa54ff53a5f1d36f1ULL; +	s->h[4] = 0x510e527fade682d1ULL; +	s->h[5] = 0x9b05688c2b3e6c1fULL; +	s->h[6] = 0x1f83d9abfb41bd6bULL; +	s->h[7] = 0x5be0cd19137e2179ULL; +} + +void +sha512_sum_n(void *ctx, uint8_t *md, int n) +{ +	struct sha512 *s = ctx; +	int i; + +	pad(s); +	for (i = 0; i < n; i++) { +		md[8*i] = s->h[i] >> 56; +		md[8*i+1] = s->h[i] >> 48; +		md[8*i+2] = s->h[i] >> 40; +		md[8*i+3] = s->h[i] >> 32; +		md[8*i+4] = s->h[i] >> 24; +		md[8*i+5] = s->h[i] >> 16; +		md[8*i+6] = s->h[i] >> 8; +		md[8*i+7] = s->h[i]; +	} +} + +void +sha512_sum(void *ctx, uint8_t md[SHA512_DIGEST_LENGTH]) +{ +	sha512_sum_n(ctx, md, 8); +} + +void +sha512_update(void *ctx, const void *m, unsigned long len) +{ +	struct sha512 *s = ctx; +	const uint8_t *p = m; +	unsigned r = s->len % 128; + +	s->len += len; +	if (r) { +		if (len < 128 - r) { +			memcpy(s->buf + r, p, len); +			return; +		} +		memcpy(s->buf + r, p, 128 - r); +		len -= 128 - r; +		p += 128 - r; +		processblock(s, s->buf); +	} +	for (; len >= 128; len -= 128, p += 128) +		processblock(s, p); +	memcpy(s->buf, p, len); +} diff --git a/util/sbase/libutil/strcasestr.c b/util/sbase/libutil/strcasestr.c new file mode 100644 index 00000000..26eb6bbd --- /dev/null +++ b/util/sbase/libutil/strcasestr.c @@ -0,0 +1,38 @@ +/* + * Copyright 2005-2014 Rich Felker, et al. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +#include <string.h> +#include <strings.h> + +#include "../util.h" + +char * +strcasestr(const char *h, const char *n) +{ +	size_t l = strlen(n); + +	for (; *h; h++) +		if (!strncasecmp(h, n, l)) +			return (char *)h; + +	return 0; +} diff --git a/util/sbase/libutil/strlcat.c b/util/sbase/libutil/strlcat.c new file mode 100644 index 00000000..bf263b87 --- /dev/null +++ b/util/sbase/libutil/strlcat.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <string.h> +#include <sys/types.h> + +#include "../util.h" + +/* + * Appends src to string dst of size siz (unlike strncat, siz is the + * full size of dst, not space left). At most siz-1 characters + * will be copied. Always NUL terminates (unless siz <= strlen(dst)). + * Returns strlen(src) + MIN(siz, strlen(initial dst)). + * If retval >= siz, truncation occurred. + */ +size_t +strlcat(char *dst, const char *src, size_t siz) +{ +	char *d = dst; +	const char *s = src; +	size_t n = siz; +	size_t dlen; +	/* Find the end of dst and adjust bytes left but don't go past end */ +	while (n-- != 0 && *d != '\0') +		d++; +	dlen = d - dst; +	n = siz - dlen; +	if (n == 0) +		return(dlen + strlen(s)); +	while (*s != '\0') { +		if (n != 1) { +			*d++ = *s; +			n--; +		} +		s++; +	} +	*d = '\0'; +	return(dlen + (s - src)); /* count does not include NUL */ +} + +size_t +estrlcat(char *dst, const char *src, size_t siz) +{ +	size_t ret; + +	if ((ret = strlcat(dst, src, siz)) >= siz) +		eprintf("strlcat: input string too long\n"); + +	return ret; +} diff --git a/util/sbase/libutil/strlcpy.c b/util/sbase/libutil/strlcpy.c new file mode 100644 index 00000000..44b618a0 --- /dev/null +++ b/util/sbase/libutil/strlcpy.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <string.h> +#include <sys/types.h> + +#include "../util.h" + +/* + * Copy src to string dst of size siz. At most siz-1 characters + * will be copied. Always NUL terminates (unless siz == 0). + * Returns strlen(src); if retval >= siz, truncation occurred. + */ +size_t +strlcpy(char *dst, const char *src, size_t siz) +{ +	char *d = dst; +	const char *s = src; +	size_t n = siz; +	/* Copy as many bytes as will fit */ +	if (n != 0) { +		while (--n != 0) { +			if ((*d++ = *s++) == '\0') +				break; +		} +	} +	/* Not enough room in dst, add NUL and traverse rest of src */ +	if (n == 0) { +		if (siz != 0) +			*d = '\0'; /* NUL-terminate dst */ +		while (*s++) +			; +	} +	return(s - src - 1); /* count does not include NUL */ +} + +size_t +estrlcpy(char *dst, const char *src, size_t siz) +{ +	size_t ret; + +	if ((ret = strlcpy(dst, src, siz)) >= siz) +		eprintf("strlcpy: input string too long\n"); + +	return ret; +} diff --git a/util/sbase/libutil/strnsubst.c b/util/sbase/libutil/strnsubst.c new file mode 100644 index 00000000..2da54aba --- /dev/null +++ b/util/sbase/libutil/strnsubst.c @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2002 J. Mallett.  All rights reserved. + * You may do whatever you want with this file as long as + * the above copyright and this notice remain intact, along + * with the following statement: + * 	For the man who taught me vi, and who got too old, too young. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "../util.h" + +/* + * Replaces str with a string consisting of str with match replaced with + * replstr as many times as can be done before the constructed string is + * maxsize bytes large.  It does not free the string pointed to by str, it + * is up to the calling program to be sure that the original contents of + * str as well as the new contents are handled in an appropriate manner. + * If replstr is NULL, then that internally is changed to a nil-string, so + * that we can still pretend to do somewhat meaningful substitution. + * No value is returned. + */ +void +strnsubst(char **str, const char *match, const char *replstr, size_t maxsize) +{ +	char *s1, *s2, *this; +	size_t matchlen, s2len; +	int n; + +	if ((s1 = *str) == NULL) +		return; +	s2 = emalloc(maxsize); + +	if (replstr == NULL) +		replstr = ""; + +	if (match == NULL || *match == '\0' || strlen(s1) >= maxsize) { +		strlcpy(s2, s1, maxsize); +		goto done; +	} + +	*s2 = '\0'; +	s2len = 0; +	matchlen = strlen(match); +	for (;;) { +		if ((this = strstr(s1, match)) == NULL) +			break; +		n = snprintf(s2 + s2len, maxsize - s2len, "%.*s%s", +		    (int)(this - s1), s1, replstr); +		if (n == -1 || n + s2len + strlen(this + matchlen) >= maxsize) +			break;			/* out of room */ +		s2len += n; +		s1 = this + matchlen; +	} +	strlcpy(s2 + s2len, s1, maxsize - s2len); +done: +	*str = s2; +	return; +} diff --git a/util/sbase/libutil/strsep.c b/util/sbase/libutil/strsep.c new file mode 100644 index 00000000..d9f06444 --- /dev/null +++ b/util/sbase/libutil/strsep.c @@ -0,0 +1,37 @@ +/* + * Copyright 2005-2014 Rich Felker, et al. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +#include <string.h> + +#include "../util.h" + +char * +strsep(char **str, const char *sep) +{ +	char *s = *str, *end; +	if (!s) return NULL; +	end = s + strcspn(s, sep); +	if (*end) *end++ = 0; +	else end = 0; +	*str = end; +	return s; +} diff --git a/util/sbase/libutil/strtonum.c b/util/sbase/libutil/strtonum.c new file mode 100644 index 00000000..c0ac401f --- /dev/null +++ b/util/sbase/libutil/strtonum.c @@ -0,0 +1,85 @@ +/*	$OpenBSD: strtonum.c,v 1.7 2013/04/17 18:40:58 tedu Exp $	*/ + +/* + * Copyright (c) 2004 Ted Unangst and Todd Miller + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <errno.h> +#include <limits.h> +#include <stdlib.h> + +#include "../util.h" + +#define	INVALID		1 +#define	TOOSMALL	2 +#define	TOOLARGE	3 + +long long +strtonum(const char *numstr, long long minval, long long maxval, +         const char **errstrp) +{ +	long long ll = 0; +	int error = 0; +	char *ep; +	struct errval { +		const char *errstr; +		int err; +	} ev[4] = { +		{ NULL,		0 }, +		{ "invalid",	EINVAL }, +		{ "too small",	ERANGE }, +		{ "too large",	ERANGE }, +	}; + +	ev[0].err = errno; +	errno = 0; +	if (minval > maxval) { +		error = INVALID; +	} else { +		ll = strtoll(numstr, &ep, 10); +		if (numstr == ep || *ep != '\0') +			error = INVALID; +		else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval) +			error = TOOSMALL; +		else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval) +			error = TOOLARGE; +	} +	if (errstrp != NULL) +		*errstrp = ev[error].errstr; +	errno = ev[error].err; +	if (error) +		ll = 0; + +	return (ll); +} + +long long +enstrtonum(int status, const char *numstr, long long minval, long long maxval) +{ +	const char *errstr; +	long long ll; + +	ll = strtonum(numstr, minval, maxval, &errstr); +	if (errstr) +		enprintf(status, "strtonum %s: %s\n", numstr, errstr); +	return ll; +} + +long long +estrtonum(const char *numstr, long long minval, long long maxval) +{ +	return enstrtonum(1, numstr, minval, maxval); +} diff --git a/util/sbase/libutil/unescape.c b/util/sbase/libutil/unescape.c new file mode 100644 index 00000000..b8f75ca9 --- /dev/null +++ b/util/sbase/libutil/unescape.c @@ -0,0 +1,58 @@ +/* See LICENSE file for copyright and license details. */ +#include <ctype.h> +#include <string.h> + +#include "../util.h" + +#define is_odigit(c)  ('0' <= c && c <= '7') + +size_t +unescape(char *s) +{ +	static const char escapes[256] = { +		['"'] = '"', +		['\''] = '\'', +		['\\'] = '\\', +		['a'] = '\a', +		['b'] = '\b', +		['E'] = 033, +		['e'] = 033, +		['f'] = '\f', +		['n'] = '\n', +		['r'] = '\r', +		['t'] = '\t', +		['v'] = '\v' +	}; +	size_t m, q; +	char *r, *w; + +	for (r = w = s; *r;) { +		if (*r != '\\') { +			*w++ = *r++; +			continue; +		} +		r++; +		if (!*r) { +			eprintf("null escape sequence\n"); +		} else if (escapes[(unsigned char)*r]) { +			*w++ = escapes[(unsigned char)*r++]; +		} else if (is_odigit(*r)) { +			for (q = 0, m = 3; m && is_odigit(*r); m--, r++) +				q = q * 8 + (*r - '0'); +			*w++ = MIN(q, 255); +		} else if (*r == 'x' && isxdigit(r[1])) { +			r++; +			for (q = 0, m = 2; m && isxdigit(*r); m--, r++) +				if (isdigit(*r)) +					q = q * 16 + (*r - '0'); +				else +					q = q * 16 + (tolower(*r) - 'a' + 10); +			*w++ = q; +		} else { +			eprintf("invalid escape sequence '\\%c'\n", *r); +		} +	} +	*w = '\0'; + +	return w - s; +} diff --git a/util/sbase/libutil/writeall.c b/util/sbase/libutil/writeall.c new file mode 100644 index 00000000..4725ced8 --- /dev/null +++ b/util/sbase/libutil/writeall.c @@ -0,0 +1,21 @@ +/* See LICENSE file for copyright and license details. */ +#include <unistd.h> + +#include "../util.h" + +ssize_t +writeall(int fd, const void *buf, size_t len) +{ +	const char *p = buf; +	ssize_t n; + +	while (len) { +		n = write(fd, p, len); +		if (n <= 0) +			return n; +		p += n; +		len -= n; +	} + +	return p - (const char *)buf; +} | 
