xref: /aosp_15_r20/external/fsverity-utils/programs/utils.c (revision b13c0e4024008a1f948ee8189745cb3371f4ac04)
1*b13c0e40SEric Biggers // SPDX-License-Identifier: MIT
2*b13c0e40SEric Biggers /*
3*b13c0e40SEric Biggers  * Utility functions for the 'fsverity' program
4*b13c0e40SEric Biggers  *
5*b13c0e40SEric Biggers  * Copyright 2018 Google LLC
6*b13c0e40SEric Biggers  *
7*b13c0e40SEric Biggers  * Use of this source code is governed by an MIT-style
8*b13c0e40SEric Biggers  * license that can be found in the LICENSE file or at
9*b13c0e40SEric Biggers  * https://opensource.org/licenses/MIT.
10*b13c0e40SEric Biggers  */
11*b13c0e40SEric Biggers 
12*b13c0e40SEric Biggers #include "utils.h"
13*b13c0e40SEric Biggers 
14*b13c0e40SEric Biggers #include <errno.h>
15*b13c0e40SEric Biggers #include <fcntl.h>
16*b13c0e40SEric Biggers #include <inttypes.h>
17*b13c0e40SEric Biggers #include <limits.h>
18*b13c0e40SEric Biggers #include <stdarg.h>
19*b13c0e40SEric Biggers #include <sys/stat.h>
20*b13c0e40SEric Biggers #include <unistd.h>
21*b13c0e40SEric Biggers #ifdef _WIN32
22*b13c0e40SEric Biggers #  include <windows.h>
23*b13c0e40SEric Biggers #endif
24*b13c0e40SEric Biggers 
25*b13c0e40SEric Biggers /* ========== Memory allocation ========== */
26*b13c0e40SEric Biggers 
xmalloc(size_t size)27*b13c0e40SEric Biggers void *xmalloc(size_t size)
28*b13c0e40SEric Biggers {
29*b13c0e40SEric Biggers 	void *p = malloc(size);
30*b13c0e40SEric Biggers 
31*b13c0e40SEric Biggers 	if (!p)
32*b13c0e40SEric Biggers 		fatal_error("out of memory");
33*b13c0e40SEric Biggers 	return p;
34*b13c0e40SEric Biggers }
35*b13c0e40SEric Biggers 
xzalloc(size_t size)36*b13c0e40SEric Biggers void *xzalloc(size_t size)
37*b13c0e40SEric Biggers {
38*b13c0e40SEric Biggers 	return memset(xmalloc(size), 0, size);
39*b13c0e40SEric Biggers }
40*b13c0e40SEric Biggers 
xmemdup(const void * mem,size_t size)41*b13c0e40SEric Biggers void *xmemdup(const void *mem, size_t size)
42*b13c0e40SEric Biggers {
43*b13c0e40SEric Biggers 	return memcpy(xmalloc(size), mem, size);
44*b13c0e40SEric Biggers }
45*b13c0e40SEric Biggers 
xstrdup(const char * s)46*b13c0e40SEric Biggers char *xstrdup(const char *s)
47*b13c0e40SEric Biggers {
48*b13c0e40SEric Biggers 	return xmemdup(s, strlen(s) + 1);
49*b13c0e40SEric Biggers }
50*b13c0e40SEric Biggers 
51*b13c0e40SEric Biggers /* ========== Error messages and assertions ========== */
52*b13c0e40SEric Biggers 
do_error_msg(const char * format,va_list va,int err)53*b13c0e40SEric Biggers static void do_error_msg(const char *format, va_list va, int err)
54*b13c0e40SEric Biggers {
55*b13c0e40SEric Biggers 	fputs("ERROR: ", stderr);
56*b13c0e40SEric Biggers 	vfprintf(stderr, format, va);
57*b13c0e40SEric Biggers 	if (err)
58*b13c0e40SEric Biggers 		fprintf(stderr, ": %s", strerror(err));
59*b13c0e40SEric Biggers 	putc('\n', stderr);
60*b13c0e40SEric Biggers }
61*b13c0e40SEric Biggers 
error_msg(const char * format,...)62*b13c0e40SEric Biggers void error_msg(const char *format, ...)
63*b13c0e40SEric Biggers {
64*b13c0e40SEric Biggers 	va_list va;
65*b13c0e40SEric Biggers 
66*b13c0e40SEric Biggers 	va_start(va, format);
67*b13c0e40SEric Biggers 	do_error_msg(format, va, 0);
68*b13c0e40SEric Biggers 	va_end(va);
69*b13c0e40SEric Biggers }
70*b13c0e40SEric Biggers 
error_msg_errno(const char * format,...)71*b13c0e40SEric Biggers void error_msg_errno(const char *format, ...)
72*b13c0e40SEric Biggers {
73*b13c0e40SEric Biggers 	va_list va;
74*b13c0e40SEric Biggers 
75*b13c0e40SEric Biggers 	va_start(va, format);
76*b13c0e40SEric Biggers 	do_error_msg(format, va, errno);
77*b13c0e40SEric Biggers 	va_end(va);
78*b13c0e40SEric Biggers }
79*b13c0e40SEric Biggers 
fatal_error(const char * format,...)80*b13c0e40SEric Biggers __noreturn void fatal_error(const char *format, ...)
81*b13c0e40SEric Biggers {
82*b13c0e40SEric Biggers 	va_list va;
83*b13c0e40SEric Biggers 
84*b13c0e40SEric Biggers 	va_start(va, format);
85*b13c0e40SEric Biggers 	do_error_msg(format, va, 0);
86*b13c0e40SEric Biggers 	va_end(va);
87*b13c0e40SEric Biggers 	abort();
88*b13c0e40SEric Biggers }
89*b13c0e40SEric Biggers 
assertion_failed(const char * expr,const char * file,int line)90*b13c0e40SEric Biggers __noreturn void assertion_failed(const char *expr, const char *file, int line)
91*b13c0e40SEric Biggers {
92*b13c0e40SEric Biggers 	fatal_error("Assertion failed: %s at %s:%d", expr, file, line);
93*b13c0e40SEric Biggers }
94*b13c0e40SEric Biggers 
print_libfsverity_error(const char * msg)95*b13c0e40SEric Biggers static void print_libfsverity_error(const char *msg)
96*b13c0e40SEric Biggers {
97*b13c0e40SEric Biggers 	error_msg("%s", msg);
98*b13c0e40SEric Biggers }
99*b13c0e40SEric Biggers 
install_libfsverity_error_handler(void)100*b13c0e40SEric Biggers void install_libfsverity_error_handler(void)
101*b13c0e40SEric Biggers {
102*b13c0e40SEric Biggers 	libfsverity_set_error_callback(print_libfsverity_error);
103*b13c0e40SEric Biggers }
104*b13c0e40SEric Biggers 
105*b13c0e40SEric Biggers /* ========== File utilities ========== */
106*b13c0e40SEric Biggers 
open_file(struct filedes * file,const char * filename,int flags,int mode)107*b13c0e40SEric Biggers bool open_file(struct filedes *file, const char *filename, int flags, int mode)
108*b13c0e40SEric Biggers {
109*b13c0e40SEric Biggers 	file->fd = open(filename, flags | O_BINARY, mode);
110*b13c0e40SEric Biggers 	if (file->fd < 0) {
111*b13c0e40SEric Biggers 		error_msg_errno("can't open '%s' for %s", filename,
112*b13c0e40SEric Biggers 				(flags & O_ACCMODE) == O_RDONLY ? "reading" :
113*b13c0e40SEric Biggers 				(flags & O_ACCMODE) == O_WRONLY ? "writing" :
114*b13c0e40SEric Biggers 				"reading and writing");
115*b13c0e40SEric Biggers 		return false;
116*b13c0e40SEric Biggers 	}
117*b13c0e40SEric Biggers 	file->name = xstrdup(filename);
118*b13c0e40SEric Biggers 	return true;
119*b13c0e40SEric Biggers }
120*b13c0e40SEric Biggers 
get_file_size(struct filedes * file,u64 * size_ret)121*b13c0e40SEric Biggers bool get_file_size(struct filedes *file, u64 *size_ret)
122*b13c0e40SEric Biggers {
123*b13c0e40SEric Biggers 	struct stat stbuf;
124*b13c0e40SEric Biggers 
125*b13c0e40SEric Biggers 	if (fstat(file->fd, &stbuf) != 0) {
126*b13c0e40SEric Biggers 		error_msg_errno("can't stat file '%s'", file->name);
127*b13c0e40SEric Biggers 		return false;
128*b13c0e40SEric Biggers 	}
129*b13c0e40SEric Biggers 	*size_ret = stbuf.st_size;
130*b13c0e40SEric Biggers 	return true;
131*b13c0e40SEric Biggers }
132*b13c0e40SEric Biggers 
preallocate_file(struct filedes * file,u64 size)133*b13c0e40SEric Biggers bool preallocate_file(struct filedes *file, u64 size)
134*b13c0e40SEric Biggers {
135*b13c0e40SEric Biggers 	int res;
136*b13c0e40SEric Biggers 
137*b13c0e40SEric Biggers 	if (size == 0)
138*b13c0e40SEric Biggers 		return true;
139*b13c0e40SEric Biggers #ifdef _WIN32
140*b13c0e40SEric Biggers 	/* Not exactly the same as posix_fallocate(), but good enough... */
141*b13c0e40SEric Biggers 	res = _chsize_s(file->fd, size);
142*b13c0e40SEric Biggers #else
143*b13c0e40SEric Biggers 	res = posix_fallocate(file->fd, 0, size);
144*b13c0e40SEric Biggers #endif
145*b13c0e40SEric Biggers 	if (res != 0) {
146*b13c0e40SEric Biggers 		error_msg_errno("preallocating %" PRIu64 "-byte file '%s'",
147*b13c0e40SEric Biggers 				size, file->name);
148*b13c0e40SEric Biggers 		return false;
149*b13c0e40SEric Biggers 	}
150*b13c0e40SEric Biggers 	return true;
151*b13c0e40SEric Biggers }
152*b13c0e40SEric Biggers 
full_read(struct filedes * file,void * buf,size_t count)153*b13c0e40SEric Biggers bool full_read(struct filedes *file, void *buf, size_t count)
154*b13c0e40SEric Biggers {
155*b13c0e40SEric Biggers 	while (count) {
156*b13c0e40SEric Biggers 		int n = read(file->fd, buf, min(count, INT_MAX));
157*b13c0e40SEric Biggers 
158*b13c0e40SEric Biggers 		if (n < 0) {
159*b13c0e40SEric Biggers 			error_msg_errno("reading from '%s'", file->name);
160*b13c0e40SEric Biggers 			return false;
161*b13c0e40SEric Biggers 		}
162*b13c0e40SEric Biggers 		if (n == 0) {
163*b13c0e40SEric Biggers 			error_msg("unexpected end-of-file on '%s'", file->name);
164*b13c0e40SEric Biggers 			return false;
165*b13c0e40SEric Biggers 		}
166*b13c0e40SEric Biggers 		buf += n;
167*b13c0e40SEric Biggers 		count -= n;
168*b13c0e40SEric Biggers 	}
169*b13c0e40SEric Biggers 	return true;
170*b13c0e40SEric Biggers }
171*b13c0e40SEric Biggers 
full_write(struct filedes * file,const void * buf,size_t count)172*b13c0e40SEric Biggers bool full_write(struct filedes *file, const void *buf, size_t count)
173*b13c0e40SEric Biggers {
174*b13c0e40SEric Biggers 	while (count) {
175*b13c0e40SEric Biggers 		int n = write(file->fd, buf, min(count, INT_MAX));
176*b13c0e40SEric Biggers 
177*b13c0e40SEric Biggers 		if (n < 0) {
178*b13c0e40SEric Biggers 			error_msg_errno("writing to '%s'", file->name);
179*b13c0e40SEric Biggers 			return false;
180*b13c0e40SEric Biggers 		}
181*b13c0e40SEric Biggers 		buf += n;
182*b13c0e40SEric Biggers 		count -= n;
183*b13c0e40SEric Biggers 	}
184*b13c0e40SEric Biggers 	return true;
185*b13c0e40SEric Biggers }
186*b13c0e40SEric Biggers 
raw_pwrite(int fd,const void * buf,int count,u64 offset)187*b13c0e40SEric Biggers static int raw_pwrite(int fd, const void *buf, int count, u64 offset)
188*b13c0e40SEric Biggers {
189*b13c0e40SEric Biggers #ifdef _WIN32
190*b13c0e40SEric Biggers 	HANDLE h = (HANDLE)_get_osfhandle(fd);
191*b13c0e40SEric Biggers 	OVERLAPPED pos = { .Offset = offset, .OffsetHigh = offset >> 32 };
192*b13c0e40SEric Biggers 	DWORD written = 0;
193*b13c0e40SEric Biggers 
194*b13c0e40SEric Biggers 	/* Not exactly the same as pwrite(), but good enough... */
195*b13c0e40SEric Biggers 	if (!WriteFile(h, buf, count, &written, &pos)) {
196*b13c0e40SEric Biggers 		errno = EIO;
197*b13c0e40SEric Biggers 		return -1;
198*b13c0e40SEric Biggers 	}
199*b13c0e40SEric Biggers 	return written;
200*b13c0e40SEric Biggers #else
201*b13c0e40SEric Biggers 	return pwrite(fd, buf, count, offset);
202*b13c0e40SEric Biggers #endif
203*b13c0e40SEric Biggers }
204*b13c0e40SEric Biggers 
full_pwrite(struct filedes * file,const void * buf,size_t count,u64 offset)205*b13c0e40SEric Biggers bool full_pwrite(struct filedes *file, const void *buf, size_t count,
206*b13c0e40SEric Biggers 		 u64 offset)
207*b13c0e40SEric Biggers {
208*b13c0e40SEric Biggers 	while (count) {
209*b13c0e40SEric Biggers 		int n = raw_pwrite(file->fd, buf, min(count, INT_MAX), offset);
210*b13c0e40SEric Biggers 
211*b13c0e40SEric Biggers 		if (n < 0) {
212*b13c0e40SEric Biggers 			error_msg_errno("writing to '%s'", file->name);
213*b13c0e40SEric Biggers 			return false;
214*b13c0e40SEric Biggers 		}
215*b13c0e40SEric Biggers 		buf += n;
216*b13c0e40SEric Biggers 		count -= n;
217*b13c0e40SEric Biggers 		offset += n;
218*b13c0e40SEric Biggers 	}
219*b13c0e40SEric Biggers 	return true;
220*b13c0e40SEric Biggers }
221*b13c0e40SEric Biggers 
filedes_close(struct filedes * file)222*b13c0e40SEric Biggers bool filedes_close(struct filedes *file)
223*b13c0e40SEric Biggers {
224*b13c0e40SEric Biggers 	int res;
225*b13c0e40SEric Biggers 
226*b13c0e40SEric Biggers 	if (file->fd < 0)
227*b13c0e40SEric Biggers 		return true;
228*b13c0e40SEric Biggers 	res = close(file->fd);
229*b13c0e40SEric Biggers 	if (res != 0)
230*b13c0e40SEric Biggers 		error_msg_errno("closing '%s'", file->name);
231*b13c0e40SEric Biggers 	file->fd = -1;
232*b13c0e40SEric Biggers 	free(file->name);
233*b13c0e40SEric Biggers 	file->name = NULL;
234*b13c0e40SEric Biggers 	return res == 0;
235*b13c0e40SEric Biggers }
236*b13c0e40SEric Biggers 
read_callback(void * file,void * buf,size_t count)237*b13c0e40SEric Biggers int read_callback(void *file, void *buf, size_t count)
238*b13c0e40SEric Biggers {
239*b13c0e40SEric Biggers 	errno = 0;
240*b13c0e40SEric Biggers 	if (!full_read(file, buf, count))
241*b13c0e40SEric Biggers 		return errno ? -errno : -EIO;
242*b13c0e40SEric Biggers 	return 0;
243*b13c0e40SEric Biggers }
244*b13c0e40SEric Biggers 
245*b13c0e40SEric Biggers /* ========== String utilities ========== */
246*b13c0e40SEric Biggers 
hex2bin_char(char c)247*b13c0e40SEric Biggers static int hex2bin_char(char c)
248*b13c0e40SEric Biggers {
249*b13c0e40SEric Biggers 	if (c >= '0' && c <= '9')
250*b13c0e40SEric Biggers 		return c - '0';
251*b13c0e40SEric Biggers 	if (c >= 'a' && c <= 'f')
252*b13c0e40SEric Biggers 		return 10 + (c - 'a');
253*b13c0e40SEric Biggers 	if (c >= 'A' && c <= 'F')
254*b13c0e40SEric Biggers 		return 10 + (c - 'A');
255*b13c0e40SEric Biggers 	return -1;
256*b13c0e40SEric Biggers }
257*b13c0e40SEric Biggers 
hex2bin(const char * hex,u8 * bin,size_t bin_len)258*b13c0e40SEric Biggers bool hex2bin(const char *hex, u8 *bin, size_t bin_len)
259*b13c0e40SEric Biggers {
260*b13c0e40SEric Biggers 	size_t i;
261*b13c0e40SEric Biggers 
262*b13c0e40SEric Biggers 	if (strlen(hex) != 2 * bin_len)
263*b13c0e40SEric Biggers 		return false;
264*b13c0e40SEric Biggers 
265*b13c0e40SEric Biggers 	for (i = 0; i < bin_len; i++) {
266*b13c0e40SEric Biggers 		int hi = hex2bin_char(*hex++);
267*b13c0e40SEric Biggers 		int lo = hex2bin_char(*hex++);
268*b13c0e40SEric Biggers 
269*b13c0e40SEric Biggers 		if (hi < 0 || lo < 0)
270*b13c0e40SEric Biggers 			return false;
271*b13c0e40SEric Biggers 		bin[i] = (hi << 4) | lo;
272*b13c0e40SEric Biggers 	}
273*b13c0e40SEric Biggers 	return true;
274*b13c0e40SEric Biggers }
275*b13c0e40SEric Biggers 
bin2hex_char(u8 nibble)276*b13c0e40SEric Biggers static char bin2hex_char(u8 nibble)
277*b13c0e40SEric Biggers {
278*b13c0e40SEric Biggers 	ASSERT(nibble <= 0xf);
279*b13c0e40SEric Biggers 
280*b13c0e40SEric Biggers 	if (nibble < 10)
281*b13c0e40SEric Biggers 		return '0' + nibble;
282*b13c0e40SEric Biggers 	return 'a' + (nibble - 10);
283*b13c0e40SEric Biggers }
284*b13c0e40SEric Biggers 
bin2hex(const u8 * bin,size_t bin_len,char * hex)285*b13c0e40SEric Biggers void bin2hex(const u8 *bin, size_t bin_len, char *hex)
286*b13c0e40SEric Biggers {
287*b13c0e40SEric Biggers 	size_t i;
288*b13c0e40SEric Biggers 
289*b13c0e40SEric Biggers 	for (i = 0; i < bin_len; i++) {
290*b13c0e40SEric Biggers 		*hex++ = bin2hex_char(bin[i] >> 4);
291*b13c0e40SEric Biggers 		*hex++ = bin2hex_char(bin[i] & 0xf);
292*b13c0e40SEric Biggers 	}
293*b13c0e40SEric Biggers 	*hex = '\0';
294*b13c0e40SEric Biggers }
295