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
filecopy(const char * srcfile,const char * dstfile)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 *
fileprefix(const char * base,const char * path)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
fileprintf(const char * filename,const char * fmt,...)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
crc32(const u_char * buf,const u_int32_t size)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