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