Fix sparse warning: Variable length array is used.
[metastore.git] / src / utils.c
blob4cba896f4b51ebb735908190ec68e8d169eca19e
1 /*
2 * Main functions of the program.
4 * Copyright (C) 2007 David Härdeman <david@hardeman.nu>
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; only version 2 of the License is applicable.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 #define _BSD_SOURCE
21 #define _DEFAULT_SOURCE
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <ctype.h>
25 #include <string.h>
26 #include <stdint.h>
27 #include <stdarg.h>
28 #include <unistd.h>
29 #include <errno.h>
30 #include <sys/types.h>
31 #include <grp.h>
32 #include <pwd.h>
34 #include "utils.h"
36 /* Controls the verbosity level for msg() */
37 static int verbosity = 0;
39 /* Adjusts the verbosity level for msg() */
40 void
41 adjust_verbosity(int adj)
43 verbosity += adj;
47 * Prints messages to console according to the current verbosity
48 * - see utils.h for level defines
50 int
51 msg(int level, const char *fmt, ...)
53 int ret;
54 va_list ap;
56 if (level > verbosity)
57 return 0;
59 va_start(ap, fmt);
61 if (level < MSG_QUIET)
62 ret = vfprintf(stderr, fmt, ap);
63 else
64 ret = vfprintf(stdout, fmt, ap);
66 va_end(ap);
67 return ret;
70 /* Malloc which either succeeds or exits */
71 void *
72 xmalloc(size_t size)
74 void *result = malloc(size);
75 if (!result) {
76 msg(MSG_CRITICAL, "Failed to malloc %zi bytes\n", size);
77 exit(EXIT_FAILURE);
79 return result;
82 /* Ditto for strdup */
83 char *
84 xstrdup(const char *s)
86 char *result = strdup(s);
87 if (!result) {
88 msg(MSG_CRITICAL, "Failed to strdup %zi bytes\n", strlen(s));
89 exit(EXIT_FAILURE);
91 return result;
94 /* Human-readable printout of binary data */
95 void
96 binary_print(const char *s, ssize_t len)
98 ssize_t i;
100 for (i = 0; i < len; i++) {
101 if (isprint(s[i]))
102 msg(MSG_DEBUG, "%c", s[i]);
103 else
104 msg(MSG_DEBUG, "0x%02X", (int)s[i]);
108 /* Writes data to a file or exits on failure */
109 void
110 xfwrite(const void *ptr, size_t size, FILE *stream)
112 if (size && fwrite(ptr, size, 1, stream) != 1) {
113 msg(MSG_CRITICAL, "Failed to write to file: %s\n",
114 strerror(errno));
115 exit(EXIT_FAILURE);
119 /* Writes an int to a file, using len bytes, in bigendian order */
120 void
121 write_int(uint64_t value, size_t len, FILE *to)
123 char buf[sizeof(value)];
124 size_t i;
126 for (i = 0; i < len; i++)
127 buf[i] = ((value >> (8 * i)) & 0xff);
128 xfwrite(buf, len, to);
131 /* Writes a binary string to a file */
132 void
133 write_binary_string(const char *string, size_t len, FILE *to)
135 xfwrite(string, len, to);
138 /* Writes a normal C string to a file */
139 void
140 write_string(const char *string, FILE *to)
142 xfwrite(string, strlen(string) + 1, to);
145 /* Reads an int from a file, using len bytes, in bigendian order */
146 uint64_t
147 read_int(char **from, size_t len, const char *max)
149 uint64_t result = 0;
150 size_t i;
152 if (*from + len > max) {
153 msg(MSG_CRITICAL,
154 "Attempt to read beyond end of file, corrupt file?\n");
155 exit(EXIT_FAILURE);
158 for (i = 0; i < len; i++)
159 result += (((*from)[i] & 0xff) << (8 * i));
160 *from += len;
161 return result;
164 /* Reads a binary string from a file */
165 char *
166 read_binary_string(char **from, size_t len, const char *max)
168 char *result;
170 if (*from + len > max) {
171 msg(MSG_CRITICAL,
172 "Attempt to read beyond end of file, corrupt file?\n");
173 exit(EXIT_FAILURE);
176 result = xmalloc(len);
177 memcpy(result, *from, len);
178 *from += len;
179 return result;
182 /* Reads a normal C string from a file */
183 char *
184 read_string(char **from, const char *max)
186 return read_binary_string(from, strlen(*from) + 1, max);
189 /* For group caching */
190 static struct group *gtable = NULL;
192 /* Initial setup of the gid table */
193 static void
194 create_group_table(void)
196 struct group *tmp;
197 int count, index;
199 for (count = 0; getgrent(); count++) /* Do nothing */;
201 gtable = xmalloc(sizeof(struct group) * (count + 1));
202 memset(gtable, 0, sizeof(struct group) * (count + 1));
203 setgrent();
205 for (index = 0; (tmp = getgrent()) && index < count; index++) {
206 gtable[index].gr_gid = tmp->gr_gid;
207 gtable[index].gr_name = xstrdup(tmp->gr_name);
210 endgrent();
213 /* Caching version of getgrnam */
214 struct group *
215 xgetgrnam(const char *name)
217 int i;
219 if (!gtable)
220 create_group_table();
222 for (i = 0; gtable[i].gr_name; i++) {
223 if (!strcmp(name, gtable[i].gr_name))
224 return &(gtable[i]);
227 return NULL;
230 /* Caching version of getgrgid */
231 struct group *
232 xgetgrgid(gid_t gid)
234 int i;
236 if (!gtable)
237 create_group_table();
239 for (i = 0; gtable[i].gr_name; i++) {
240 if (gtable[i].gr_gid == gid)
241 return &(gtable[i]);
244 return NULL;
247 /* For user caching */
248 static struct passwd *ptable = NULL;
250 /* Initial setup of the passwd table */
251 static void
252 create_passwd_table(void)
254 struct passwd *tmp;
255 int count, index;
257 for (count = 0; getpwent(); count++) /* Do nothing */;
259 ptable = xmalloc(sizeof(struct passwd) * (count + 1));
260 memset(ptable, 0, sizeof(struct passwd) * (count + 1));
261 setpwent();
263 for (index = 0; (tmp = getpwent()) && index < count; index++) {
264 ptable[index].pw_uid = tmp->pw_uid;
265 ptable[index].pw_name = xstrdup(tmp->pw_name);
268 endpwent();
271 /* Caching version of getpwnam */
272 struct passwd *
273 xgetpwnam(const char *name)
275 int i;
277 if (!ptable)
278 create_passwd_table();
280 for (i = 0; ptable[i].pw_name; i++) {
281 if (!strcmp(name, ptable[i].pw_name))
282 return &(ptable[i]);
285 return NULL;
288 /* Caching version of getpwuid */
289 struct passwd *
290 xgetpwuid(uid_t uid)
292 int i;
294 if (!ptable)
295 create_passwd_table();
297 for (i = 0; ptable[i].pw_name; i++) {
298 if (ptable[i].pw_uid == uid)
299 return &(ptable[i]);
302 return NULL;