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