#include <sys/stat.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
#include <libgen.h>
#include "installboot.h"
#define MINIMUM(a, b) (((a) < (b)) ? (a) : (b))
#define BUFSIZE 512
int
filecopy(const char *srcfile, const char *dstfile)
{
struct stat sb;
ssize_t sz, n;
int sfd, dfd;
char *buf;
sfd = open(srcfile, O_RDONLY);
if (sfd == -1) {
warn("open %s", srcfile);
return (-1);
}
if (fstat(sfd, &sb) == -1) {
warn("fstat");
return (-1);
}
sz = sb.st_size;
dfd = open(dstfile, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
if (dfd == -1) {
warn("open %s", dstfile);
return (-1);
}
if (fchown(dfd, 0, 0) == -1)
if (errno != EINVAL) {
warn("chown");
return (-1);
}
if (fchmod(dfd, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) == -1) {
warn("chmod");
return (-1);
}
if ((buf = malloc(BUFSIZE)) == NULL) {
warn("malloc");
return (-1);
}
while (sz > 0) {
n = MINIMUM(sz, BUFSIZE);
if ((n = read(sfd, buf, n)) == -1) {
warn("read");
free(buf);
return (-1);
}
sz -= n;
if (write(dfd, buf, n) != n) {
warn("write");
free(buf);
return (-1);
}
}
ftruncate(dfd, sb.st_size);
close(dfd);
close(sfd);
free(buf);
return (0);
}
char *
fileprefix(const char *base, const char *path)
{
char *r = NULL, *d, *b, *s;
int n;
if ((s = malloc(PATH_MAX)) == NULL) {
warn("malloc");
return (NULL);
}
n = snprintf(s, PATH_MAX, "%s/%s", base, path);
if (n < 0 || n >= PATH_MAX) {
warn("snprintf");
goto err;
}
if ((d = dirname(s)) == NULL) {
warn("dirname");
goto err;
}
if ((r = realpath(d, NULL)) == NULL) {
warn("realpath");
goto err;
}
if ((b = basename(s)) == NULL) {
warn("basename");
goto err;
}
n = snprintf(s, PATH_MAX, "%s/%s", r, b);
if (n < 0 || n >= PATH_MAX) {
warn("snprintf");
goto err;
}
free(r);
return (s);
err:
free(s);
free(r);
return (NULL);
}
int
fileprintf(const char *filename, const char *fmt, ...)
{
va_list ap;
int fd, ret;
int rslt = -1;
fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC,
S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
if (fd == -1) {
warn("open %s", filename);
return (-1);
}
if (fchown(fd, 0, 0) == -1) {
if (errno != EINVAL) {
warn("chown");
goto err;
}
}
if (fchmod(fd, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) == -1) {
warn("chmod");
goto err;
}
va_start(ap, fmt);
ret = vdprintf(fd, fmt, ap);
va_end(ap);
if (ret < 0) {
warn("vdprintf");
goto err;
}
rslt = 0;
err:
close(fd);
return (rslt);
}
u_int32_t
crc32(const u_char *buf, const u_int32_t size)
{
int j;
u_int32_t i, byte, crc, mask;
crc = 0xFFFFFFFF;
for (i = 0; i < size; i++) {
byte = buf[i];
crc = crc ^ byte;
for (j = 7; j >= 0; j--) {
mask = -(crc & 1);
crc = (crc >> 1) ^ (0xEDB88320 & mask);
}
}
return ~crc;
}