1 /* util.h -- general utility functions
2  *
3  * Copyright (c) 1994-2008 Carnegie Mellon University.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in
14  *    the documentation and/or other materials provided with the
15  *    distribution.
16  *
17  * 3. The name "Carnegie Mellon University" must not be used to
18  *    endorse or promote products derived from this software without
19  *    prior written permission. For permission or any legal
20  *    details, please contact
21  *      Carnegie Mellon University
22  *      Center for Technology Transfer and Enterprise Creation
23  *      4615 Forbes Avenue
24  *      Suite 302
25  *      Pittsburgh, PA  15213
26  *      (412) 268-7393, fax: (412) 268-7395
27  *      innovation@andrew.cmu.edu
28  *
29  * 4. Redistributions of any form whatsoever must retain the following
30  *    acknowledgment:
31  *    "This product includes software developed by Computing Services
32  *     at Carnegie Mellon University (http://www.cmu.edu/computing/)."
33  *
34  * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
35  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
36  * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
37  * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
38  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
39  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
40  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
41  *
42  * Author: Chris Newman
43  * Start Date: 4/6/93
44  */
45 
46 #ifndef INCLUDED_UTIL_H
47 #define INCLUDED_UTIL_H
48 
49 #include <config.h>
50 #include <ctype.h>
51 #include <sys/types.h>
52 #include <limits.h>
53 #include <stdarg.h>
54 #include <stdint.h>
55 #include <stdio.h>
56 
57 #ifdef HAVE_UNISTD_H
58 #include <unistd.h>
59 #endif
60 
61 #ifndef STDIN_FILENO
62 /* Standard file descriptors.  */
63 #define	STDIN_FILENO	0	/* Standard input.  */
64 #define	STDOUT_FILENO	1	/* Standard output.  */
65 #define	STDERR_FILENO	2	/* Standard error output.  */
66 #endif
67 
68 #include "xmalloc.h"
69 
70 /* version string printable in gdb tracking */
71 extern const char CYRUS_VERSION[];
72 
73 #ifdef ENABLE_REGEX
74 # ifdef HAVE_PCREPOSIX_H
75 #  include <pcre.h>
76 #  include <pcreposix.h>
77 # else /* !HAVE_PCREPOSIX_H */
78 #  ifdef HAVE_RXPOSIX_H
79 #   include <rxposix.h>
80 #  else /* !HAVE_RXPOSIX_H */
81 #   include <regex.h>
82 #  endif /* HAVE_RXPOSIX_H */
83 # endif /* HAVE_PCREPOSIX_H */
84 #endif /* ENABLE_REGEX */
85 
86 #ifdef HAVE_LIBUUID
87 #include <uuid/uuid.h>
88 #endif
89 #ifndef UUID_STR_LEN
90 #define UUID_STR_LEN  37
91 #endif
92 
93 #define BIT32_MAX 4294967295U
94 
95 #if UINT_MAX == BIT32_MAX
96 typedef unsigned int bit32;
97 #elif ULONG_MAX == BIT32_MAX
98 typedef unsigned long bit32;
99 #elif USHRT_MAX == BIT32_MAX
100 typedef unsigned short bit32;
101 #else
102 #error dont know what to use for bit32
103 #endif
104 
105 typedef unsigned long long int bit64;
106 typedef unsigned long long int modseq_t;
107 #define MODSEQ_FMT "%llu"
108 #define atomodseq_t(s) strtoull(s, NULL, 10)
109 
110 #if SIZEOF_LONG >= 8
111 #define INT64_FMT "%ld"
112 #else
113 #define INT64_FMT "%lld"
114 #endif
115 
116 #define Uisalnum(c) isalnum((int)((unsigned char)(c)))
117 #define Uisalpha(c) isalpha((int)((unsigned char)(c)))
118 #define Uisascii(c) isascii((int)((unsigned char)(c)))
119 #define Uiscntrl(c) iscntrl((int)((unsigned char)(c)))
120 #define Uisdigit(c) isdigit((int)((unsigned char)(c)))
121 #define Uislower(c) islower((int)((unsigned char)(c)))
122 #define Uisspace(c) isspace((int)((unsigned char)(c)))
123 #define Uisupper(c) isupper((int)((unsigned char)(c)))
124 #define Uisxdigit(c) isxdigit((int)((unsigned char)(c)))
125 
126 extern const unsigned char convert_to_lowercase[256];
127 extern const unsigned char convert_to_uppercase[256];
128 
129 #ifndef TOUPPER
130 #define TOUPPER(c) (convert_to_uppercase[(unsigned char)(c)])
131 #endif
132 #ifndef TOLOWER
133 #define TOLOWER(c) (convert_to_lowercase[(unsigned char)(c)])
134 #endif
135 
136 #ifndef MAX
137 #define MAX(x, y) ((x) > (y) ? (x) : (y))
138 #endif
139 #ifndef MIN
140 #define MIN(x, y) ((x) < (y) ? (x) : (y))
141 #endif
142 
143 /* Some BSDs don't print "NULL" for a NULL pointer string. */
144 #ifndef IS_NULL
145 #define IS_NULL(s)      ((s) == NULL ? "(NULL)" : (s))
146 #endif
147 
148 /* Calculate the number of entries in a vector */
149 #define VECTOR_SIZE(vector) (sizeof(vector)/sizeof(vector[0]))
150 
151 #ifndef TIMESPEC_TO_TIMEVAL
152 #define TIMESPEC_TO_TIMEVAL(tv, ts) { \
153         (tv)->tv_sec = (ts)->tv_sec; \
154         (tv)->tv_usec = (ts)->tv_nsec / 1000; \
155 }
156 #endif
157 
158 typedef struct keyvalue {
159     char *key, *value;
160 } keyvalue;
161 
162 /* convert string to all lower case
163  */
164 extern char *lcase (char *str);
165 
166 /* convert string to all upper case
167  */
168 extern char *ucase (char *str);
169 
170 /* clean up control characters in a string while copying it
171  *  returns pointer to a static buffer containing the cleaned-up version
172  */
173 extern char *beautify_string (const char *src);
174 
175 /* Same semantics as strcmp() but gracefully handles
176  * either or both it's arguments being NULL */
177 int strcmpsafe(const char *a, const char *b);
178 /* Same semantics as strcasecmp() but gracefully handles
179  * either or both it's arguments being NULL */
180 int strcasecmpsafe(const char *a, const char *b);
181 /* ditto strncmp */
182 int strncmpsafe(const char *a, const char *b, size_t n);
183 
184 /* NULL isn't "" */
185 int strcmpnull(const char *a, const char *b);
186 
187 /* do a binary search in a keyvalue array
188  *  nelem is the number of keyvalue elements in the kv array
189  *  cmpf is the comparison function (strcmp, stricmp, etc).
190  *  returns NULL if not found, or key/value pair if found.
191  */
192 extern keyvalue *kv_bsearch (const char *key, keyvalue *kv, int nelem,
193                                int (*cmpf)(const char *s1, const char *s2));
194 
195 /* Examine the name of a file, and return a single character
196  *  (as an int) that can be used as the name of a hash
197  *  directory.  Caller is responsible for skipping any prefix
198  *  of the name.
199  */
200 extern int dir_hash_c(const char *name, int full);
201 /*
202  * Like dir_hash_c() but builds the result as a single-byte
203  * C string in the provided buffer, and returns the buffer,
204  * which is sometimes more convenient.
205  */
206 extern char *dir_hash_b(const char *name, int full, char buf[2]);
207 
208 /*
209  * create an [unlinked] temporary file and return the file descriptor.
210  */
211 extern int create_tempfile(const char *path);
212 
213 /* Close a network filedescriptor the "safe" way */
214 extern int cyrus_close_sock(int fd);
215 
216 /* Reset stdin/stdout/stderr */
217 extern void cyrus_reset_stdio(void);
218 
219 /* Create all parent directories for the given path,
220  * up to but not including the basename.
221  */
222 extern int cyrus_mkdir(const char *path, mode_t mode);
223 
224 enum {
225     COPYFILE_NOLINK = (1<<0),
226     COPYFILE_MKDIR  = (1<<1),
227     COPYFILE_RENAME = (1<<2),
228     COPYFILE_KEEPTIME = (1<<3)
229 };
230 
231 extern int cyrus_copyfile(const char *from, const char *to, int flags);
232 
233 enum {
234     BEFORE_SETUID,
235     AFTER_SETUID,
236     BEFORE_BIND,
237     AFTER_BIND,
238     AFTER_FORK
239 };
240 
241 extern int set_caps(int stage, int is_master);
242 extern int become_cyrus(int is_master);
243 extern const char *cyrus_user(void);
244 extern const char *cyrus_group(void);
245 
246 /* Some systems have very inefficient implementations of isdigit,
247  * and we use it in a lot of inner loops
248  */
249 
250 #define cyrus_isdigit(x) ((x) >= '0' && (x) <= '9')
251 int parseint32(const char *p, const char **ptr, int32_t *res);
252 int parseuint32(const char *p, const char **ptr, uint32_t *res);
253 int parsenum(const char *p, const char **ptr, int maxlen, bit64 *res);
254 int parsehex(const char *p, const char **ptr, int maxlen, bit64 *res);
255 uint64_t str2uint64(const char *p);
256 
257 /* Timing related funcs/vars */
258 extern void cmdtime_settimer(int enable);
259 extern void cmdtime_starttimer(void);
260 extern void cmdtime_endtimer(double * cmdtime, double * nettime);
261 extern void cmdtime_netstart(void);
262 extern void cmdtime_netend(void);
263 extern int cmdtime_checksearch(void);
264 extern double timeval_get_double(const struct timeval *tv);
265 extern void timeval_set_double(struct timeval *tv, double d);
266 extern void timeval_add_double(struct timeval *tv, double delta);
267 extern double timesub(const struct timeval *start, const struct timeval *end);
268 extern int64_t now_ms(void);
269 
270 extern clock_t sclock(void);
271 
272 #define BUF_MMAP    (1<<1)
273 
274 struct buf {
275     char *s;
276     size_t len;
277     size_t alloc;
278     unsigned flags;
279 };
280 #define BUF_INITIALIZER { NULL, 0, 0, 0 }
281 
282 #define buf_new() ((struct buf *) xzmalloc(sizeof(struct buf)))
283 #define buf_destroy(b) do { buf_free((b)); free((b)); } while (0)
284 #define buf_ensure(b, n) do { if ((b)->alloc < (b)->len + (n)) _buf_ensure((b), (n)); } while (0)
285 #define buf_putc(b, c) do { buf_ensure((b), 1); (b)->s[(b)->len++] = (c); } while (0)
286 
287 void _buf_ensure(struct buf *buf, size_t len);
288 const char *buf_cstring(const struct buf *buf);
289 const char *buf_cstringnull(const struct buf *buf);
290 const char *buf_cstringnull_ifempty(const struct buf *buf);
291 char *buf_release(struct buf *buf);
292 char *buf_newcstring(struct buf *buf);
293 char *buf_releasenull(struct buf *buf);
294 void buf_getmap(struct buf *buf, const char **base, size_t *len);
295 int buf_getline(struct buf *buf, FILE *fp);
296 size_t buf_len(const struct buf *buf);
297 const char *buf_base(const struct buf *buf);
298 void buf_reset(struct buf *buf);
299 void buf_truncate(struct buf *buf, ssize_t len);
300 void buf_setcstr(struct buf *buf, const char *str);
301 void buf_setmap(struct buf *buf, const char *base, size_t len);
302 void buf_copy(struct buf *dst, const struct buf *src);
303 void buf_append(struct buf *dst, const struct buf *src);
304 void buf_appendcstr(struct buf *buf, const char *str);
305 void buf_appendoverlap(struct buf *buf, const char *str);
306 void buf_appendbit32(struct buf *buf, bit32 num);
307 void buf_appendbit64(struct buf *buf, bit64 num);
308 void buf_appendmap(struct buf *buf, const char *base, size_t len);
309 void buf_cowappendmap(struct buf *buf, const char *base, unsigned int len);
310 void buf_cowappendfree(struct buf *buf, char *base, unsigned int len);
311 void buf_insert(struct buf *dst, unsigned int off, const struct buf *src);
312 void buf_insertcstr(struct buf *buf, unsigned int off, const char *str);
313 void buf_insertmap(struct buf *buf, unsigned int off, const char *base, int len);
314 void buf_vprintf(struct buf *buf, const char *fmt, va_list args)
315                 __attribute__((format(printf, 2, 0)));
316 void buf_printf(struct buf *buf, const char *fmt, ...)
317                 __attribute__((format(printf, 2, 3)));
318 int buf_replace_all(struct buf *buf, const char *match,
319                     const char *replace);
320 int buf_replace_char(struct buf *buf, char match, char replace);
321 #ifdef ENABLE_REGEX
322 int buf_replace_all_re(struct buf *buf, const regex_t *,
323                        const char *replace);
324 int buf_replace_one_re(struct buf *buf, const regex_t *,
325                        const char *replace);
326 #endif
327 void buf_remove(struct buf *buf, unsigned int off, unsigned int len);
328 int buf_cmp(const struct buf *, const struct buf *);
329 int buf_findchar(const struct buf *, unsigned int off, int c);
330 int buf_findline(const struct buf *buf, const char *line);
331 void buf_init_ro(struct buf *buf, const char *base, size_t len);
332 void buf_initm(struct buf *buf, char *base, int len);
333 void buf_init_ro_cstr(struct buf *buf, const char *str);
334 void buf_refresh_mmap(struct buf *buf, int onceonly, int fd,
335                    const char *fname, size_t size, const char *mboxname);
336 void buf_free(struct buf *buf);
337 void buf_move(struct buf *dst, struct buf *src);
338 const char *buf_lcase(struct buf *buf);
339 const char *buf_ucase(struct buf *buf);
340 const char *buf_tocrlf(struct buf *buf);
341 void buf_trim(struct buf *buf);
342 
343 /*
344  * Given a list of strings, terminated by (char *)NULL,
345  * return a newly allocated string containing the
346  * concatenation of all the argument strings.  The
347  * caller must free the returned string using free().
348  *
349  * This API idea based on glib's g_strconcat() which
350  * is really quite amazingly convenient.
351  */
352 char *strconcat(const char *s1, ...);
353 
354 #define BH_LOWER            (0)
355 #define BH_UPPER            (1<<8)
356 #define _BH_SEP             (1<<9)
357 #define BH_SEPARATOR(c)     (_BH_SEP|((c)&0x7f))
358 #define _BH_GETSEP(flags)   (flags & _BH_SEP ? (char)(flags & 0x7f) : '\0')
359 int bin_to_hex(const void *bin, size_t binlen, char *hex, int flags);
360 int bin_to_lchex(const void *bin, size_t binlen, char *hex);
361 int hex_to_bin(const char *hex, size_t hexlen, void *bin);
362 
363 /* use getpassphrase on machines which support it */
364 #ifdef HAVE_GETPASSPHRASE
365 #define cyrus_getpass getpassphrase
366 #else
367 #define cyrus_getpass getpass
368 #endif
369 
370 #ifdef HAVE_ZLIB
371 enum {
372     DEFLATE_RAW,
373     DEFLATE_GZIP,
374     DEFLATE_ZLIB
375 };
376 
377 int buf_inflate(struct buf *buf, int scheme);
378 int buf_deflate(struct buf *buf, int compLevel, int scheme);
379 #endif
380 
381 /* A wrapper for close() which handles the fd=-1 case cleanly.
382  * The argument may have side effects and must be an lvalue */
383 #define xclose(fd) \
384     do { \
385         int *_fdp = &(fd); \
386         if (*_fdp >= 0) { \
387             close(*_fdp); \
388             *_fdp = -1; \
389         } \
390     } while(0)
391 
392 /* A wrapper for strncpy() which ensures that the destination
393  * string is always NUL-terminated.  Yes, I know we have an
394  * implementation of the BSD strlcpy() which has this semantic,
395  * but that isn't a highly optimised libc or compiler provided
396  * function like strncpy(), and we can trivially and efficiently
397  * add the NUL termination semantic on top of strncpy(). */
398 #define xstrncpy(d, s, n) \
399     do { \
400         char *_d = (d); \
401         size_t _n = (n); \
402         strncpy(_d, (s), _n-1); \
403         _d[_n-1] = '\0'; \
404     } while(0)
405 
406 /* simple function to request a file gets pre-loaded by the OS */
407 int warmup_file(const char *filename, off_t offset, off_t length);
408 
409 const char *makeuuid();
410 
411 void tcp_enable_keepalive(int fd);
412 void tcp_disable_nagle(int fd);
413 
414 /*
415  * GCC_VERSION macro usage:
416  * #if GCC_VERSION > 60909    //GCC version 7 and above
417  *   do_something();
418  * #endif
419  */
420 #define GCC_VERSION (__GNUC__ * 10000           \
421                      + __GNUC_MINOR__ * 100     \
422                      + __GNUC_PATCHLEVEL__)
423 
424 #endif /* INCLUDED_UTIL_H */
425