fix documentation of --compare
[metastore.git] / utils.c
blobaa6df96c6aa6284b9fb8300f254ee3a0258e9e86
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 version 2 of the License.
9 *
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.
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <ctype.h>
24 #include <string.h>
25 #include <stdint.h>
26 #include <stdarg.h>
27 #include <unistd.h>
28 #include <errno.h>
29 #include <sys/types.h>
30 #include <grp.h>
31 #include <pwd.h>
33 #include "utils.h"
35 /* Controls the verbosity level for msg() */
36 static int verbosity = 0;
38 /* Adjusts the verbosity level for msg() */
39 void
40 adjust_verbosity(int adj)
42 verbosity += adj;
46 * Prints messages to console according to the current verbosity
47 * - see utils.h for level defines
49 int
50 msg(int level, const char *fmt, ...)
52 int ret;
53 va_list ap;
55 if (level > verbosity)
56 return 0;
58 va_start(ap, fmt);
60 if (level < MSG_QUIET)
61 ret = vfprintf(stderr, fmt, ap);
62 else
63 ret = vfprintf(stdout, fmt, ap);
65 va_end(ap);
66 return ret;
69 /* Malloc which either succeeds or exits */
70 void *
71 xmalloc(size_t size)
73 void *result = malloc(size);
74 if (!result) {
75 msg(MSG_CRITICAL, "Failed to malloc %zi bytes\n", size);
76 exit(EXIT_FAILURE);
78 return result;
81 /* Ditto for strdup */
82 char *
83 xstrdup(const char *s)
85 char *result = strdup(s);
86 if (!result) {
87 msg(MSG_CRITICAL, "Failed to strdup %zi bytes\n", strlen(s));
88 exit(EXIT_FAILURE);
90 return result;
93 /* Human-readable printout of binary data */
94 void
95 binary_print(const char *s, ssize_t len)
97 ssize_t i;
99 for (i = 0; i < len; i++) {
100 if (isprint(s[i]))
101 msg(MSG_DEBUG, "%c", s[i]);
102 else
103 msg(MSG_DEBUG, "0x%02X", (int)s[i]);
107 /* Writes data to a file or exits on failure */
108 void
109 xfwrite(const void *ptr, size_t size, FILE *stream)
111 if (fwrite(ptr, size, 1, stream) != 1) {
112 msg(MSG_CRITICAL, "Failed to write to file: %s\n",
113 strerror(errno));
114 exit(EXIT_FAILURE);
118 /* Writes an int to a file, using len bytes, in bigendian order */
119 void
120 write_int(uint64_t value, size_t len, FILE *to)
122 char buf[len];
123 int i;
125 for (i = 0; i < len; i++)
126 buf[i] = ((value >> (8 * i)) & 0xff);
127 xfwrite(buf, len, to);
130 /* Writes a binary string to a file */
131 void
132 write_binary_string(const char *string, size_t len, FILE *to)
134 xfwrite(string, len, to);
137 /* Writes a normal C string to a file */
138 void
139 write_string(const char *string, FILE *to)
141 xfwrite(string, strlen(string) + 1, to);
144 /* Reads an int from a file, using len bytes, in bigendian order */
145 uint64_t
146 read_int(char **from, size_t len, const char *max)
148 uint64_t result = 0;
149 int i;
151 if (*from + len > max) {
152 msg(MSG_CRITICAL,
153 "Attempt to read beyond end of file, corrupt file?\n");
154 exit(EXIT_FAILURE);
157 for (i = 0; i < len; i++)
158 result += (((*from)[i] & 0xff) << (8 * i));
159 *from += len;
160 return result;
163 /* Reads a binary string from a file */
164 char *
165 read_binary_string(char **from, size_t len, const char *max)
167 char *result;
169 if (*from + len > max) {
170 msg(MSG_CRITICAL,
171 "Attempt to read beyond end of file, corrupt file?\n");
172 exit(EXIT_FAILURE);
175 result = xmalloc(len);
176 strncpy(result, *from, len);
177 *from += len;
178 return result;
181 /* Reads a normal C string from a file */
182 char *
183 read_string(char **from, const char *max)
185 return read_binary_string(from, strlen(*from) + 1, max);
188 /* For group caching */
189 static struct group *gtable = NULL;
191 /* Initial setup of the gid table */
192 static void
193 create_group_table()
195 struct group *tmp;
196 int count, index;
198 for (count = 0; getgrent(); count++) /* Do nothing */;
200 gtable = xmalloc(sizeof(struct group) * (count + 1));
201 memset(gtable, 0, sizeof(struct group) * (count + 1));
202 setgrent();
204 for (index = 0; (tmp = getgrent()) && index < count; index++) {
205 gtable[index].gr_gid = tmp->gr_gid;
206 gtable[index].gr_name = xstrdup(tmp->gr_name);
209 endgrent();
212 /* Caching version of getgrnam */
213 struct group *
214 xgetgrnam(const char *name)
216 int i;
218 if (!gtable)
219 create_group_table();
221 for (i = 0; gtable[i].gr_name; i++) {
222 if (!strcmp(name, gtable[i].gr_name))
223 return &(gtable[i]);
226 return NULL;
229 /* Caching version of getgrgid */
230 struct group *
231 xgetgrgid(gid_t gid)
233 int i;
235 if (!gtable)
236 create_group_table();
238 for (i = 0; gtable[i].gr_name; i++) {
239 if (gtable[i].gr_gid == gid)
240 return &(gtable[i]);
243 return NULL;
246 /* For user caching */
247 static struct passwd *ptable = NULL;
249 /* Initial setup of the passwd table */
250 static void
251 create_passwd_table()
253 struct passwd *tmp;
254 int count, index;
256 for (count = 0; getpwent(); count++) /* Do nothing */;
258 ptable = xmalloc(sizeof(struct passwd) * (count + 1));
259 memset(ptable, 0, sizeof(struct passwd) * (count + 1));
260 setpwent();
262 for (index = 0; (tmp = getpwent()) && index < count; index++) {
263 ptable[index].pw_uid = tmp->pw_uid;
264 ptable[index].pw_name = xstrdup(tmp->pw_name);
267 endpwent();
270 /* Caching version of getpwnam */
271 struct passwd *
272 xgetpwnam(const char *name)
274 int i;
276 if (!ptable)
277 create_passwd_table();
279 for (i = 0; ptable[i].pw_name; i++) {
280 if (!strcmp(name, ptable[i].pw_name))
281 return &(ptable[i]);
284 return NULL;
287 /* Caching version of getpwuid */
288 struct passwd *
289 xgetpwuid(uid_t uid)
291 int i;
293 if (!ptable)
294 create_passwd_table();
296 for (i = 0; ptable[i].pw_name; i++) {
297 if (ptable[i].pw_uid == uid)
298 return &(ptable[i]);
301 return NULL;