1 /* $OpenBSD: util.c,v 1.16 2022/02/03 10:25:14 visa Exp $ */ 2 3 /* 4 * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/stat.h> 20 #include <err.h> 21 #include <errno.h> 22 #include <fcntl.h> 23 #include <stdarg.h> 24 #include <stdio.h> 25 #include <stdlib.h> 26 #include <string.h> 27 #include <unistd.h> 28 #include <limits.h> 29 #include <libgen.h> 30 31 #include "installboot.h" 32 33 #define MINIMUM(a, b) (((a) < (b)) ? (a) : (b)) 34 35 #define BUFSIZE 512 36 37 int 38 filecopy(const char *srcfile, const char *dstfile) 39 { 40 struct stat sb; 41 ssize_t sz, n; 42 int sfd, dfd; 43 char *buf; 44 45 sfd = open(srcfile, O_RDONLY); 46 if (sfd == -1) { 47 warn("open %s", srcfile); 48 return (-1); 49 } 50 if (fstat(sfd, &sb) == -1) { 51 warn("fstat"); 52 return (-1); 53 } 54 sz = sb.st_size; 55 56 dfd = open(dstfile, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); 57 if (dfd == -1) { 58 warn("open %s", dstfile); 59 return (-1); 60 } 61 if (fchown(dfd, 0, 0) == -1) 62 if (errno != EINVAL) { 63 warn("chown"); 64 return (-1); 65 } 66 if (fchmod(dfd, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) == -1) { 67 warn("chmod"); 68 return (-1); 69 } 70 71 if ((buf = malloc(BUFSIZE)) == NULL) { 72 warn("malloc"); 73 return (-1); 74 } 75 76 while (sz > 0) { 77 n = MINIMUM(sz, BUFSIZE); 78 if ((n = read(sfd, buf, n)) == -1) { 79 warn("read"); 80 free(buf); 81 return (-1); 82 } 83 sz -= n; 84 if (write(dfd, buf, n) != n) { 85 warn("write"); 86 free(buf); 87 return (-1); 88 } 89 } 90 91 ftruncate(dfd, sb.st_size); 92 93 close(dfd); 94 close(sfd); 95 free(buf); 96 97 return (0); 98 } 99 100 char * 101 fileprefix(const char *base, const char *path) 102 { 103 char *r = NULL, *d, *b, *s; 104 int n; 105 106 if ((s = malloc(PATH_MAX)) == NULL) { 107 warn("malloc"); 108 return (NULL); 109 } 110 n = snprintf(s, PATH_MAX, "%s/%s", base, path); 111 if (n < 0 || n >= PATH_MAX) { 112 warn("snprintf"); 113 goto err; 114 } 115 if ((d = dirname(s)) == NULL) { 116 warn("dirname"); 117 goto err; 118 } 119 if ((r = realpath(d, NULL)) == NULL) { 120 warn("realpath"); 121 goto err; 122 } 123 if ((b = basename(s)) == NULL) { 124 warn("basename"); 125 goto err; 126 } 127 n = snprintf(s, PATH_MAX, "%s/%s", r, b); 128 if (n < 0 || n >= PATH_MAX) { 129 warn("snprintf"); 130 goto err; 131 } 132 free(r); 133 return (s); 134 135 err: 136 free(s); 137 free(r); 138 return (NULL); 139 } 140 141 int 142 fileprintf(const char *filename, const char *fmt, ...) 143 { 144 va_list ap; 145 int fd, ret; 146 int rslt = -1; 147 148 fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 149 S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); 150 if (fd == -1) { 151 warn("open %s", filename); 152 return (-1); 153 } 154 if (fchown(fd, 0, 0) == -1) { 155 if (errno != EINVAL) { 156 warn("chown"); 157 goto err; 158 } 159 } 160 if (fchmod(fd, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) == -1) { 161 warn("chmod"); 162 goto err; 163 } 164 165 va_start(ap, fmt); 166 ret = vdprintf(fd, fmt, ap); 167 va_end(ap); 168 169 if (ret < 0) { 170 warn("vdprintf"); 171 goto err; 172 } 173 174 rslt = 0; 175 176 err: 177 close(fd); 178 return (rslt); 179 } 180 181 /* 182 * Adapted from Hacker's Delight crc32b(). 183 * 184 * To quote http://www.hackersdelight.org/permissions.htm : 185 * 186 * "You are free to use, copy, and distribute any of the code on 187 * this web site, whether modified by you or not. You need not give 188 * attribution. This includes the algorithms (some of which appear 189 * in Hacker's Delight), the Hacker's Assistant, and any code submitted 190 * by readers. Submitters implicitly agree to this." 191 */ 192 u_int32_t 193 crc32(const u_char *buf, const u_int32_t size) 194 { 195 int j; 196 u_int32_t i, byte, crc, mask; 197 198 crc = 0xFFFFFFFF; 199 200 for (i = 0; i < size; i++) { 201 byte = buf[i]; /* Get next byte. */ 202 crc = crc ^ byte; 203 for (j = 7; j >= 0; j--) { /* Do eight times. */ 204 mask = -(crc & 1); 205 crc = (crc >> 1) ^ (0xEDB88320 & mask); 206 } 207 } 208 209 return ~crc; 210 } 211