1 /* $OpenBSD: util.c,v 1.14 2019/07/03 03:24:03 deraadt 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 <stdio.h> 24 #include <stdlib.h> 25 #include <string.h> 26 #include <unistd.h> 27 #include <limits.h> 28 #include <libgen.h> 29 30 #include "installboot.h" 31 32 #define MINIMUM(a, b) (((a) < (b)) ? (a) : (b)) 33 34 #define BUFSIZE 512 35 36 int 37 filecopy(const char *srcfile, const char *dstfile) 38 { 39 struct stat sb; 40 ssize_t sz, n; 41 int sfd, dfd; 42 char *buf; 43 44 sfd = open(srcfile, O_RDONLY); 45 if (sfd == -1) { 46 warn("open %s", srcfile); 47 return (-1); 48 } 49 if (fstat(sfd, &sb) == -1) { 50 warn("fstat"); 51 return (-1); 52 } 53 sz = sb.st_size; 54 55 dfd = open(dstfile, O_WRONLY|O_CREAT); 56 if (dfd == -1) { 57 warn("open %s", dstfile); 58 return (-1); 59 } 60 if (fchown(dfd, 0, 0) == -1) 61 if (errno != EINVAL) { 62 warn("chown"); 63 return (-1); 64 } 65 if (fchmod(dfd, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) == -1) { 66 warn("chmod"); 67 return (-1); 68 } 69 70 if ((buf = malloc(BUFSIZE)) == NULL) { 71 warn("malloc"); 72 return (-1); 73 } 74 75 while (sz > 0) { 76 n = MINIMUM(sz, BUFSIZE); 77 if ((n = read(sfd, buf, n)) == -1) { 78 warn("read"); 79 free(buf); 80 return (-1); 81 } 82 sz -= n; 83 if (write(dfd, buf, n) != n) { 84 warn("write"); 85 free(buf); 86 return (-1); 87 } 88 } 89 90 ftruncate(dfd, sb.st_size); 91 92 close(dfd); 93 close(sfd); 94 free(buf); 95 96 return (0); 97 } 98 99 char * 100 fileprefix(const char *base, const char *path) 101 { 102 char *r = NULL, *d, *b, *s; 103 int n; 104 105 if ((s = malloc(PATH_MAX)) == NULL) { 106 warn("malloc"); 107 return (NULL); 108 } 109 n = snprintf(s, PATH_MAX, "%s/%s", base, path); 110 if (n < 0 || n >= PATH_MAX) { 111 warn("snprintf"); 112 goto err; 113 } 114 if ((d = dirname(s)) == NULL) { 115 warn("dirname"); 116 goto err; 117 } 118 if ((r = realpath(d, NULL)) == NULL) { 119 warn("realpath"); 120 goto err; 121 } 122 if ((b = basename(s)) == NULL) { 123 warn("basename"); 124 goto err; 125 } 126 n = snprintf(s, PATH_MAX, "%s/%s", r, b); 127 if (n < 0 || n >= PATH_MAX) { 128 warn("snprintf"); 129 goto err; 130 } 131 free(r); 132 return (s); 133 134 err: 135 free(s); 136 free(r); 137 return (NULL); 138 } 139 140 /* 141 * Adapted from Hacker's Delight crc32b(). 142 * 143 * To quote http://www.hackersdelight.org/permissions.htm : 144 * 145 * "You are free to use, copy, and distribute any of the code on 146 * this web site, whether modified by you or not. You need not give 147 * attribution. This includes the algorithms (some of which appear 148 * in Hacker's Delight), the Hacker's Assistant, and any code submitted 149 * by readers. Submitters implicitly agree to this." 150 */ 151 u_int32_t 152 crc32(const u_char *buf, const u_int32_t size) 153 { 154 int j; 155 u_int32_t i, byte, crc, mask; 156 157 crc = 0xFFFFFFFF; 158 159 for (i = 0; i < size; i++) { 160 byte = buf[i]; /* Get next byte. */ 161 crc = crc ^ byte; 162 for (j = 7; j >= 0; j--) { /* Do eight times. */ 163 mask = -(crc & 1); 164 crc = (crc >> 1) ^ (0xEDB88320 & mask); 165 } 166 } 167 168 return ~crc; 169 } 170