Rename util/ to libutil/

This commit is contained in:
sin
2014-11-17 16:48:01 +00:00
parent ee1e90ebdc
commit 027052f5e5
26 changed files with 26 additions and 26 deletions

18
libutil/agetcwd.c Normal file
View File

@@ -0,0 +1,18 @@
/* See LICENSE file for copyright and license details. */
#include <unistd.h>
#include "../util.h"
char *
agetcwd(void)
{
char *buf;
long size;
apathmax(&buf, &size);
if (!getcwd(buf, size))
eprintf("getcwd:");
return buf;
}

13
libutil/agetline.c Normal file
View File

@@ -0,0 +1,13 @@
/* See LICENSE file for copyright and license details. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../text.h"
#include "../util.h"
ssize_t
agetline(char **p, size_t *size, FILE *fp)
{
return getline(p, size, fp);
}

22
libutil/apathmax.c Normal file
View File

@@ -0,0 +1,22 @@
/* See LICENSE file for copyright and license details. */
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "../util.h"
void
apathmax(char **p, long *size)
{
errno = 0;
if ((*size = pathconf("/", _PC_PATH_MAX)) == -1) {
if (errno == 0) {
*size = BUFSIZ;
} else {
eprintf("pathconf:");
}
}
*p = emalloc(*size);
}

20
libutil/concat.c Normal file
View File

@@ -0,0 +1,20 @@
/* See LICENSE file for copyright and license details. */
#include <stdio.h>
#include <unistd.h>
#include "../text.h"
#include "../util.h"
void
concat(FILE *fp1, const char *s1, FILE *fp2, const char *s2)
{
char buf[BUFSIZ];
ssize_t n;
while ((n = read(fileno(fp1), buf, sizeof buf)) > 0) {
if (write(fileno(fp2), buf, n) != n)
eprintf("%s: write error:", s2);
}
if (n < 0)
eprintf("%s: read error:", s1);
}

151
libutil/cp.c Normal file
View File

@@ -0,0 +1,151 @@
/* 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 "../text.h"
#include "../util.h"
int cp_aflag = 0;
int cp_dflag = 0;
int cp_fflag = 0;
int cp_pflag = 0;
int cp_rflag = 0;
int cp_vflag = 0;
int cp_status = 0;
int
cp(const char *s1, const char *s2)
{
FILE *f1, *f2;
char *ns1, *ns2;
long size1, size2;
struct dirent *d;
struct stat st;
struct utimbuf ut;
char buf[PATH_MAX];
DIR *dp;
int r;
if (cp_vflag)
printf("'%s' -> '%s'\n", s1, s2);
if (cp_dflag)
r = lstat(s1, &st);
else
r = stat(s1, &st);
if (r == 0) {
if (cp_dflag && S_ISLNK(st.st_mode)) {
if (readlink(s1, buf, sizeof(buf) - 1) >= 0) {
if (cp_fflag)
unlink(s2);
if (symlink(buf, s2) != 0) {
weprintf("%s: can't create '%s'\n", argv0, s2);
cp_status = 1;
return 0;
}
}
goto preserve;
}
if (S_ISDIR(st.st_mode)) {
if (!cp_rflag)
eprintf("%s: is a directory\n", s1);
if (!(dp = opendir(s1)))
eprintf("opendir %s:", s1);
if (mkdir(s2, st.st_mode) == -1 && errno != EEXIST)
eprintf("mkdir %s:", s2);
apathmax(&ns1, &size1);
apathmax(&ns2, &size2);
while ((d = readdir(dp))) {
if (strcmp(d->d_name, ".") && strcmp(d->d_name, "..")) {
r = snprintf(ns1, size1, "%s/%s", s1, d->d_name);
if (r >= size1 || r < 0) {
eprintf("%s/%s: filename too long\n",
s1, d->d_name);
}
r = snprintf(ns2, size2, "%s/%s", s2, d->d_name);
if (r >= size2 || r < 0) {
eprintf("%s/%s: filename too long\n",
s2, d->d_name);
}
fnck(ns1, ns2, cp);
}
}
closedir(dp);
free(ns1);
free(ns2);
goto preserve;
}
}
if (cp_aflag) {
if (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode) ||
S_ISSOCK(st.st_mode) || S_ISFIFO(st.st_mode)) {
unlink(s2);
if (mknod(s2, st.st_mode, st.st_rdev) < 0) {
weprintf("%s: can't create '%s':", argv0, s2);
cp_status = 1;
return 0;
}
goto preserve;
}
}
if (!(f1 = fopen(s1, "r"))) {
weprintf("fopen %s:", s1);
cp_status = 1;
return 0;
}
if (!(f2 = fopen(s2, "w"))) {
if (cp_fflag) {
unlink(s2);
if (!(f2 = fopen(s2, "w"))) {
weprintf("fopen %s:", s2);
cp_status = 1;
return 0;
}
} else {
weprintf("fopen %s:", s2);
cp_status = 1;
return 0;
}
}
concat(f1, s1, f2, s2);
fchmod(fileno(f2), st.st_mode);
fclose(f2);
fclose(f1);
preserve:
if (cp_aflag || cp_pflag) {
if (!(S_ISLNK(st.st_mode))) {
/* timestamp */
ut.actime = st.st_atime;
ut.modtime = st.st_mtime;
utime(s2, &ut);
}
/* preserve owner ? */
if (S_ISLNK(st.st_mode))
r = lchown(s2, st.st_uid, st.st_gid);
else
r = chown(s2, st.st_uid, st.st_gid);
if (r == -1) {
weprintf("cp: can't preserve ownership of '%s':", s2);
cp_status = 1;
}
}
return 0;
}

156
libutil/crypt.c Normal file
View File

@@ -0,0 +1,156 @@
/* See LICENSE file for copyright and license details. */
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.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;
}
int
cryptcheck(char *sumfile, int argc, char *argv[],
struct crypt_ops *ops, uint8_t *md, size_t sz)
{
FILE *cfp, *fp;
char *line = NULL, *file, *p;
int r, nonmatch = 0, formatsucks = 0, noread = 0, ret = 0;
size_t bufsiz = 0;
if (!sumfile)
cfp = stdin;
else if (!(cfp = fopen(sumfile, "r")))
eprintf("fopen %s:", sumfile);
while (agetline(&line, &bufsiz, cfp) != -1) {
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 (!(fp = fopen(file, "r"))) {
weprintf("fopen %s:", file);
noread++;
continue;
}
cryptsum(ops, fp, file, md);
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++;
}
fclose(fp);
}
if (sumfile)
fclose(cfp);
free(line);
if (formatsucks > 0) {
weprintf("%d lines are improperly formatted\n", formatsucks);
ret = 1;
}
if (noread > 0) {
weprintf("%d listed file could not be read\n", noread);
ret = 1;
}
if (nonmatch > 0) {
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)
{
FILE *fp;
int ret = 0;
if (argc == 0) {
cryptsum(ops, stdin, "<stdin>", md);
mdprint(md, "<stdin>", sz);
} else {
for (; argc > 0; argc--) {
if (!(fp = fopen(*argv, "r"))) {
weprintf("fopen %s:", *argv);
ret = 1;
continue;
}
if (cryptsum(ops, fp, *argv, md) == 1)
ret = 1;
else
mdprint(md, *argv, sz);
fclose(fp);
argv++;
}
}
return ret;
}
int
cryptsum(struct crypt_ops *ops, FILE *fp, const char *f,
uint8_t *md)
{
uint8_t buf[BUFSIZ];
size_t n;
ops->init(ops->s);
while ((n = fread(buf, 1, sizeof(buf), fp)) > 0)
ops->update(ops->s, buf, n);
if (ferror(fp)) {
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);
}

47
libutil/ealloc.c Normal file
View File

@@ -0,0 +1,47 @@
/* 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)
{
void *p;
p = calloc(nmemb, size);
if (!p)
eprintf("calloc: out of memory\n");
return p;
}
void *
emalloc(size_t size)
{
void *p;
p = malloc(size);
if (!p)
eprintf("malloc: out of memory\n");
return p;
}
void *
erealloc(void *p, size_t size)
{
p = realloc(p, size);
if (!p)
eprintf("realloc: out of memory\n");
return p;
}
char *
estrdup(const char *s)
{
char *p;
p = strdup(s);
if (!p)
eprintf("strdup: out of memory\n");
return p;
}

41
libutil/enmasse.c Normal file
View File

@@ -0,0 +1,41 @@
/* 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 *))
{
char *buf, *dir;
int i, len;
long size;
struct stat st;
size_t dlen;
if (argc == 2 && !(stat(argv[1], &st) == 0 && S_ISDIR(st.st_mode))) {
fnck(argv[0], argv[1], fn);
return;
} else {
dir = (argc == 1) ? "." : argv[--argc];
}
apathmax(&buf, &size);
for (i = 0; i < argc; i++) {
dlen = strlen(dir);
if (dlen > 0 && dir[dlen - 1] == '/')
len = snprintf(buf, size, "%s%s", dir, basename(argv[i]));
else
len = snprintf(buf, size, "%s/%s", dir, basename(argv[i]));
if (len < 0 || len >= size) {
eprintf("%s/%s: filename too long\n", dir,
basename(argv[i]));
}
fnck(argv[i], buf, fn);
}
free(buf);
}

67
libutil/eprintf.c Normal file
View File

@@ -0,0 +1,67 @@
/* 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;
static void venprintf(int, const char *, va_list);
void
eprintf(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
venprintf(1, fmt, ap);
va_end(ap);
}
void
enprintf(int status, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
venprintf(status, fmt, ap);
va_end(ap);
}
void
venprintf(int status, const char *fmt, va_list ap)
{
#ifdef DEBUG
fprintf(stderr, "%s: ", argv0);
#endif
vfprintf(stderr, fmt, ap);
if (fmt[0] && fmt[strlen(fmt)-1] == ':') {
fputc(' ', stderr);
perror(NULL);
}
exit(status);
}
void
weprintf(const char *fmt, ...)
{
va_list ap;
#ifdef DEBUG
fprintf(stderr, "%s: ", argv0);
#endif
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
if (fmt[0] && fmt[strlen(fmt)-1] == ':') {
fputc(' ', stderr);
perror(NULL);
}
}

25
libutil/eregcomp.c Normal file
View File

@@ -0,0 +1,25 @@
#include <regex.h>
#include <stdio.h>
#include <sys/types.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);
}

18
libutil/estrtod.c Normal file
View File

@@ -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;
}

27
libutil/estrtol.c Normal file
View File

@@ -0,0 +1,27 @@
/* See LICENSE file for copyright and license details. */
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include "../util.h"
long
estrtol(const char *s, int base)
{
char *end;
long n;
errno = 0;
n = strtol(s, &end, base);
if (*end != '\0') {
if (base == 0)
eprintf("%s: not an integer\n", s);
else
eprintf("%s: not a base %d integer\n", s, base);
}
if (errno != 0)
eprintf("%s:", s);
return n;
}

20
libutil/fnck.c Normal file
View File

@@ -0,0 +1,20 @@
/* 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 *))
{
struct stat sta, stb;
if (stat(a, &sta) == 0
&& stat(b, &stb) == 0
&& sta.st_dev == stb.st_dev
&& sta.st_ino == stb.st_ino) {
eprintf("%s -> %s: same file\n", a, b);
}
if (fn(a, b) == -1)
eprintf("%s -> %s:", a, b);
}

27
libutil/getlines.c Normal file
View File

@@ -0,0 +1,27 @@
/* 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, **nline;
size_t size = 0, linelen;
ssize_t len;
while ((len = agetline(&line, &size, fp)) != -1) {
if (++b->nlines > b->capacity) {
b->capacity += 512;
nline = erealloc(b->lines, b->capacity * sizeof(*b->lines));
b->lines = nline;
}
linelen = len + 1;
b->lines[b->nlines-1] = emalloc(linelen);
memcpy(b->lines[b->nlines-1], line, linelen);
}
free(line);
}

22
libutil/human.c Normal file
View File

@@ -0,0 +1,22 @@
/* See LICENSE file for copyright and license details. */
#include <stdio.h>
#include <string.h>
#include "../util.h"
char *
humansize(double n)
{
static char buf[16];
const char postfixes[] = "BKMGTPE";
size_t i;
for (i = 0; n >= 1024 && i < strlen(postfixes); i++)
n /= 1024;
if (!i)
snprintf(buf, sizeof(buf), "%lu", (unsigned long)n);
else
snprintf(buf, sizeof(buf), "%.1f%c", n, postfixes[i]);
return buf;
}

148
libutil/md5.c Normal file
View File

@@ -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);
}

163
libutil/mode.c Normal file
View File

@@ -0,0 +1,163 @@
#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 -1;
}
mode = 0;
if (octal & 04000) mode |= S_ISUID;
if (octal & 02000) mode |= S_ISGID;
if (octal & 01000) mode |= S_ISVTX;
if (octal & 00400) mode |= S_IRUSR;
if (octal & 00200) mode |= S_IWUSR;
if (octal & 00100) mode |= S_IXUSR;
if (octal & 00040) mode |= S_IRGRP;
if (octal & 00020) mode |= S_IWGRP;
if (octal & 00010) mode |= S_IXGRP;
if (octal & 00004) mode |= S_IROTH;
if (octal & 00002) mode |= S_IWOTH;
if (octal & 00001) mode |= S_IXOTH;
return mode;
}
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;
continue;
case 'a':
who |= S_IRWXU|S_ISUID|S_IRWXG|S_ISGID|S_IRWXO;
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);
return -1;
}
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 '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;
}

16
libutil/putword.c Normal file
View File

@@ -0,0 +1,16 @@
/* See LICENSE file for copyright and license details. */
#include <stdio.h>
#include "../util.h"
void
putword(const char *s)
{
static int first = 1;
if (!first)
putchar(' ');
fputs(s, stdout);
first = 0;
}

42
libutil/recurse.c Normal file
View File

@@ -0,0 +1,42 @@
/* See LICENSE file for copyright and license details. */
#include <dirent.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 "../util.h"
void
recurse(const char *path, void (*fn)(const char *))
{
char buf[PATH_MAX];
struct dirent *d;
struct stat st;
DIR *dp;
if (lstat(path, &st) == -1 || S_ISDIR(st.st_mode) == 0)
return;
if (!(dp = opendir(path)))
eprintf("opendir %s:", path);
while ((d = readdir(dp))) {
if (strcmp(d->d_name, ".") == 0 ||
strcmp(d->d_name, "..") == 0)
continue;
if (strlcpy(buf, path, sizeof(buf)) >= sizeof(buf))
eprintf("path too long\n");
if (buf[strlen(buf) - 1] != '/')
if (strlcat(buf, "/", sizeof(buf)) >= sizeof(buf))
eprintf("path too long\n");
if (strlcat(buf, d->d_name, sizeof(buf)) >= sizeof(buf))
eprintf("path too long\n");
fn(buf);
}
closedir(dp);
}

17
libutil/rm.c Normal file
View File

@@ -0,0 +1,17 @@
/* See LICENSE file for copyright and license details. */
#include <stdio.h>
#include "../fs.h"
#include "../util.h"
int rm_fflag = 0;
int rm_rflag = 0;
void
rm(const char *path)
{
if (rm_rflag)
recurse(path, rm);
if (remove(path) == -1 && !rm_fflag)
eprintf("remove %s:", path);
}

144
libutil/sha1.c Normal file
View File

@@ -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);
}

148
libutil/sha256.c Normal file
View File

@@ -0,0 +1,148 @@
/* 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(void *ctx, uint8_t md[SHA256_DIGEST_LENGTH])
{
struct sha256 *s = ctx;
int i;
pad(s);
for (i = 0; i < 8; 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_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);
}

169
libutil/sha512.c Normal file
View File

@@ -0,0 +1,169 @@
/* 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(void *ctx, uint8_t md[SHA512_DIGEST_LENGTH])
{
struct sha512 *s = ctx;
int i;
pad(s);
for (i = 0; i < 8; 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_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);
}

52
libutil/strlcat.c Normal file
View File

@@ -0,0 +1,52 @@
/*
* 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 */
}

48
libutil/strlcpy.c Normal file
View File

@@ -0,0 +1,48 @@
/*
* 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 */
}