• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Utility functions for the 'fsverity' program
4  *
5  * Copyright (C) 2018 Google LLC
6  *
7  * Written by Eric Biggers.
8  */
9 
10 #include <errno.h>
11 #include <fcntl.h>
12 #include <limits.h>
13 #include <stdarg.h>
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <sys/stat.h>
18 #include <unistd.h>
19 
20 #include "util.h"
21 
22 /* ========== Memory allocation ========== */
23 
xmalloc(size_t size)24 void *xmalloc(size_t size)
25 {
26 	void *p = malloc(size);
27 
28 	if (!p)
29 		fatal_error("out of memory");
30 	return p;
31 }
32 
xzalloc(size_t size)33 void *xzalloc(size_t size)
34 {
35 	return memset(xmalloc(size), 0, size);
36 }
37 
xmemdup(const void * mem,size_t size)38 void *xmemdup(const void *mem, size_t size)
39 {
40 	return memcpy(xmalloc(size), mem, size);
41 }
42 
xstrdup(const char * s)43 char *xstrdup(const char *s)
44 {
45 	return xmemdup(s, strlen(s) + 1);
46 }
47 
48 /* ========== Error messages and assertions ========== */
49 
do_error_msg(const char * format,va_list va,int err)50 void do_error_msg(const char *format, va_list va, int err)
51 {
52 	fputs("ERROR: ", stderr);
53 	vfprintf(stderr, format, va);
54 	if (err)
55 		fprintf(stderr, ": %s", strerror(err));
56 	putc('\n', stderr);
57 }
58 
error_msg(const char * format,...)59 void error_msg(const char *format, ...)
60 {
61 	va_list va;
62 
63 	va_start(va, format);
64 	do_error_msg(format, va, 0);
65 	va_end(va);
66 }
67 
error_msg_errno(const char * format,...)68 void error_msg_errno(const char *format, ...)
69 {
70 	va_list va;
71 
72 	va_start(va, format);
73 	do_error_msg(format, va, errno);
74 	va_end(va);
75 }
76 
fatal_error(const char * format,...)77 __noreturn void fatal_error(const char *format, ...)
78 {
79 	va_list va;
80 
81 	va_start(va, format);
82 	do_error_msg(format, va, 0);
83 	va_end(va);
84 	abort();
85 }
86 
assertion_failed(const char * expr,const char * file,int line)87 __noreturn void assertion_failed(const char *expr, const char *file, int line)
88 {
89 	fatal_error("Assertion failed: %s at %s:%d", expr, file, line);
90 }
91 
92 /* ========== File utilities ========== */
93 
open_file(struct filedes * file,const char * filename,int flags,int mode)94 bool open_file(struct filedes *file, const char *filename, int flags, int mode)
95 {
96 	file->fd = open(filename, flags, mode);
97 	if (file->fd < 0) {
98 		error_msg_errno("can't open '%s' for %s", filename,
99 				(flags & O_ACCMODE) == O_RDONLY ? "reading" :
100 				(flags & O_ACCMODE) == O_WRONLY ? "writing" :
101 				"reading and writing");
102 		return false;
103 	}
104 	file->name = xstrdup(filename);
105 	return true;
106 }
107 
get_file_size(struct filedes * file,u64 * size_ret)108 bool get_file_size(struct filedes *file, u64 *size_ret)
109 {
110 	struct stat stbuf;
111 
112 	if (fstat(file->fd, &stbuf) != 0) {
113 		error_msg_errno("can't stat file '%s'", file->name);
114 		return false;
115 	}
116 	*size_ret = stbuf.st_size;
117 	return true;
118 }
119 
full_read(struct filedes * file,void * buf,size_t count)120 bool full_read(struct filedes *file, void *buf, size_t count)
121 {
122 	while (count) {
123 		int n = read(file->fd, buf, min(count, INT_MAX));
124 
125 		if (n < 0) {
126 			error_msg_errno("reading from '%s'", file->name);
127 			return false;
128 		}
129 		if (n == 0) {
130 			error_msg("unexpected end-of-file on '%s'", file->name);
131 			return false;
132 		}
133 		buf += n;
134 		count -= n;
135 	}
136 	return true;
137 }
138 
full_write(struct filedes * file,const void * buf,size_t count)139 bool full_write(struct filedes *file, const void *buf, size_t count)
140 {
141 	while (count) {
142 		int n = write(file->fd, buf, min(count, INT_MAX));
143 
144 		if (n < 0) {
145 			error_msg_errno("writing to '%s'", file->name);
146 			return false;
147 		}
148 		buf += n;
149 		count -= n;
150 	}
151 	return true;
152 }
153 
filedes_close(struct filedes * file)154 bool filedes_close(struct filedes *file)
155 {
156 	int res;
157 
158 	if (file->fd < 0)
159 		return true;
160 	res = close(file->fd);
161 	if (res != 0)
162 		error_msg_errno("closing '%s'", file->name);
163 	file->fd = -1;
164 	free(file->name);
165 	file->name = NULL;
166 	return res == 0;
167 }
168 
169 /* ========== String utilities ========== */
170 
hex2bin_char(char c)171 static int hex2bin_char(char c)
172 {
173 	if (c >= '0' && c <= '9')
174 		return c - '0';
175 	if (c >= 'a' && c <= 'f')
176 		return 10 + (c - 'a');
177 	if (c >= 'A' && c <= 'F')
178 		return 10 + (c - 'A');
179 	return -1;
180 }
181 
hex2bin(const char * hex,u8 * bin,size_t bin_len)182 bool hex2bin(const char *hex, u8 *bin, size_t bin_len)
183 {
184 	if (strlen(hex) != 2 * bin_len)
185 		return false;
186 
187 	while (bin_len--) {
188 		int hi = hex2bin_char(*hex++);
189 		int lo = hex2bin_char(*hex++);
190 
191 		if (hi < 0 || lo < 0)
192 			return false;
193 		*bin++ = (hi << 4) | lo;
194 	}
195 	return true;
196 }
197 
bin2hex_char(u8 nibble)198 static char bin2hex_char(u8 nibble)
199 {
200 	ASSERT(nibble <= 0xf);
201 
202 	if (nibble < 10)
203 		return '0' + nibble;
204 	return 'a' + (nibble - 10);
205 }
206 
bin2hex(const u8 * bin,size_t bin_len,char * hex)207 void bin2hex(const u8 *bin, size_t bin_len, char *hex)
208 {
209 	while (bin_len--) {
210 		*hex++ = bin2hex_char(*bin >> 4);
211 		*hex++ = bin2hex_char(*bin & 0xf);
212 		bin++;
213 	}
214 	*hex = '\0';
215 }
216