s3:smbd: s/EVENT_FD/TEVENT_FD
[Samba.git] / lib / util / util.c
blobf63720c3ee0acc5a29c342e219980549d8589f32
1 /*
2 Unix SMB/CIFS implementation.
3 Samba utility functions
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Jeremy Allison 2001-2002
6 Copyright (C) Simo Sorce 2001-2011
7 Copyright (C) Jim McDonough (jmcd@us.ibm.com) 2003.
8 Copyright (C) James J Myers 2003
9 Copyright (C) Volker Lendecke 2010
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 3 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "includes.h"
26 #include "system/network.h"
27 #include "system/filesys.h"
28 #include "system/locale.h"
29 #include "system/shmem.h"
30 #include "system/passwd.h"
32 #undef malloc
33 #undef strcasecmp
34 #undef strncasecmp
35 #undef strdup
36 #undef realloc
37 #undef calloc
39 /**
40 * @file
41 * @brief Misc utility functions
44 /**
45 Find a suitable temporary directory. The result should be copied immediately
46 as it may be overwritten by a subsequent call.
47 **/
48 _PUBLIC_ const char *tmpdir(void)
50 char *p;
51 if ((p = getenv("TMPDIR")))
52 return p;
53 return "/tmp";
57 /**
58 Create a tmp file, open it and immediately unlink it.
59 If dir is NULL uses tmpdir()
60 Returns the file descriptor or -1 on error.
61 **/
62 int create_unlink_tmp(const char *dir)
64 char *fname;
65 int fd;
67 if (!dir) {
68 dir = tmpdir();
71 fname = talloc_asprintf(talloc_tos(), "%s/listenerlock_XXXXXX", dir);
72 if (fname == NULL) {
73 errno = ENOMEM;
74 return -1;
76 fd = mkstemp(fname);
77 if (fd == -1) {
78 TALLOC_FREE(fname);
79 return -1;
81 if (unlink(fname) == -1) {
82 int sys_errno = errno;
83 close(fd);
84 TALLOC_FREE(fname);
85 errno = sys_errno;
86 return -1;
88 TALLOC_FREE(fname);
89 return fd;
93 /**
94 Check if a file exists - call vfs_file_exist for samba files.
95 **/
96 _PUBLIC_ bool file_exist(const char *fname)
98 struct stat st;
100 if (stat(fname, &st) != 0) {
101 return false;
104 return ((S_ISREG(st.st_mode)) || (S_ISFIFO(st.st_mode)));
108 Check a files mod time.
111 _PUBLIC_ time_t file_modtime(const char *fname)
113 struct stat st;
115 if (stat(fname,&st) != 0)
116 return(0);
118 return(st.st_mtime);
122 Check file permissions.
125 _PUBLIC_ bool file_check_permissions(const char *fname,
126 uid_t uid,
127 mode_t file_perms,
128 struct stat *pst)
130 int ret;
131 struct stat st;
133 if (pst == NULL) {
134 pst = &st;
137 ZERO_STRUCTP(pst);
139 ret = stat(fname, pst);
140 if (ret != 0) {
141 DEBUG(0, ("stat failed on file '%s': %s\n",
142 fname, strerror(errno)));
143 return false;
146 if (pst->st_uid != uid && !uwrap_enabled()) {
147 DEBUG(0, ("invalid ownership of file '%s': "
148 "owned by uid %u, should be %u\n",
149 fname, (unsigned int)pst->st_uid,
150 (unsigned int)uid));
151 return false;
154 if ((pst->st_mode & 0777) != file_perms) {
155 DEBUG(0, ("invalid permissions on file "
156 "'%s': has 0%o should be 0%o\n", fname,
157 (unsigned int)(pst->st_mode & 0777),
158 (unsigned int)file_perms));
159 return false;
162 return true;
166 Check if a directory exists.
169 _PUBLIC_ bool directory_exist(const char *dname)
171 struct stat st;
172 bool ret;
174 if (stat(dname,&st) != 0) {
175 return false;
178 ret = S_ISDIR(st.st_mode);
179 if(!ret)
180 errno = ENOTDIR;
181 return ret;
185 * Try to create the specified directory if it didn't exist.
187 * @retval true if the directory already existed and has the right permissions
188 * or was successfully created.
190 _PUBLIC_ bool directory_create_or_exist(const char *dname, uid_t uid,
191 mode_t dir_perms)
193 int ret;
194 struct stat st;
196 ret = lstat(dname, &st);
197 if (ret == -1) {
198 mode_t old_umask;
200 if (errno != ENOENT) {
201 DEBUG(0, ("lstat failed on directory %s: %s\n",
202 dname, strerror(errno)));
203 return false;
206 /* Create directory */
207 old_umask = umask(0);
208 ret = mkdir(dname, dir_perms);
209 if (ret == -1 && errno != EEXIST) {
210 DEBUG(0, ("mkdir failed on directory "
211 "%s: %s\n", dname,
212 strerror(errno)));
213 umask(old_umask);
214 return false;
216 umask(old_umask);
218 ret = lstat(dname, &st);
219 if (ret == -1) {
220 DEBUG(0, ("lstat failed on created directory %s: %s\n",
221 dname, strerror(errno)));
222 return false;
226 /* Check ownership and permission on existing directory */
227 if (!S_ISDIR(st.st_mode)) {
228 DEBUG(0, ("directory %s isn't a directory\n",
229 dname));
230 return false;
232 if (st.st_uid != uid && !uwrap_enabled()) {
233 DEBUG(0, ("invalid ownership on directory "
234 "%s\n", dname));
235 return false;
237 if ((st.st_mode & 0777) != dir_perms) {
238 DEBUG(0, ("invalid permissions on directory "
239 "'%s': has 0%o should be 0%o\n", dname,
240 (st.st_mode & 0777), dir_perms));
241 return false;
244 return true;
249 Sleep for a specified number of milliseconds.
252 _PUBLIC_ void smb_msleep(unsigned int t)
254 #if defined(HAVE_NANOSLEEP)
255 struct timespec ts;
256 int ret;
258 ts.tv_sec = t/1000;
259 ts.tv_nsec = 1000000*(t%1000);
261 do {
262 errno = 0;
263 ret = nanosleep(&ts, &ts);
264 } while (ret < 0 && errno == EINTR && (ts.tv_sec > 0 || ts.tv_nsec > 0));
265 #else
266 unsigned int tdiff=0;
267 struct timeval tval,t1,t2;
268 fd_set fds;
270 GetTimeOfDay(&t1);
271 t2 = t1;
273 while (tdiff < t) {
274 tval.tv_sec = (t-tdiff)/1000;
275 tval.tv_usec = 1000*((t-tdiff)%1000);
277 /* Never wait for more than 1 sec. */
278 if (tval.tv_sec > 1) {
279 tval.tv_sec = 1;
280 tval.tv_usec = 0;
283 FD_ZERO(&fds);
284 errno = 0;
285 select(0,&fds,NULL,NULL,&tval);
287 GetTimeOfDay(&t2);
288 if (t2.tv_sec < t1.tv_sec) {
289 /* Someone adjusted time... */
290 t1 = t2;
293 tdiff = usec_time_diff(&t2,&t1)/1000;
295 #endif
299 Get my own name, return in talloc'ed storage.
302 _PUBLIC_ char *get_myname(TALLOC_CTX *ctx)
304 char *p;
305 char hostname[HOST_NAME_MAX];
307 /* get my host name */
308 if (gethostname(hostname, sizeof(hostname)) == -1) {
309 DEBUG(0,("gethostname failed\n"));
310 return NULL;
313 /* Ensure null termination. */
314 hostname[sizeof(hostname)-1] = '\0';
316 /* split off any parts after an initial . */
317 p = strchr_m(hostname, '.');
318 if (p) {
319 *p = 0;
322 return talloc_strdup(ctx, hostname);
326 Check if a process exists. Does this work on all unixes?
329 _PUBLIC_ bool process_exists_by_pid(pid_t pid)
331 /* Doing kill with a non-positive pid causes messages to be
332 * sent to places we don't want. */
333 if (pid <= 0) {
334 return false;
336 return(kill(pid,0) == 0 || errno != ESRCH);
340 Simple routine to do POSIX file locking. Cruft in NFS and 64->32 bit mapping
341 is dealt with in posix.c
344 _PUBLIC_ bool fcntl_lock(int fd, int op, off_t offset, off_t count, int type)
346 struct flock lock;
347 int ret;
349 DEBUG(8,("fcntl_lock %d %d %.0f %.0f %d\n",fd,op,(double)offset,(double)count,type));
351 lock.l_type = type;
352 lock.l_whence = SEEK_SET;
353 lock.l_start = offset;
354 lock.l_len = count;
355 lock.l_pid = 0;
357 ret = fcntl(fd,op,&lock);
359 if (ret == -1 && errno != 0)
360 DEBUG(3,("fcntl_lock: fcntl lock gave errno %d (%s)\n",errno,strerror(errno)));
362 /* a lock query */
363 if (op == F_GETLK) {
364 if ((ret != -1) &&
365 (lock.l_type != F_UNLCK) &&
366 (lock.l_pid != 0) &&
367 (lock.l_pid != getpid())) {
368 DEBUG(3,("fcntl_lock: fd %d is locked by pid %d\n",fd,(int)lock.l_pid));
369 return true;
372 /* it must be not locked or locked by me */
373 return false;
376 /* a lock set or unset */
377 if (ret == -1) {
378 DEBUG(3,("fcntl_lock: lock failed at offset %.0f count %.0f op %d type %d (%s)\n",
379 (double)offset,(double)count,op,type,strerror(errno)));
380 return false;
383 /* everything went OK */
384 DEBUG(8,("fcntl_lock: Lock call successful\n"));
386 return true;
389 static void debugadd_cb(const char *buf, void *private_data)
391 int *plevel = (int *)private_data;
392 DEBUGADD(*plevel, ("%s", buf));
395 void print_asc_cb(const uint8_t *buf, int len,
396 void (*cb)(const char *buf, void *private_data),
397 void *private_data)
399 int i;
400 char s[2];
401 s[1] = 0;
403 for (i=0; i<len; i++) {
404 s[0] = isprint(buf[i]) ? buf[i] : '.';
405 cb(s, private_data);
409 void print_asc(int level, const uint8_t *buf,int len)
411 print_asc_cb(buf, len, debugadd_cb, &level);
415 * Write dump of binary data to a callback
417 void dump_data_cb(const uint8_t *buf, int len,
418 bool omit_zero_bytes,
419 void (*cb)(const char *buf, void *private_data),
420 void *private_data)
422 int i=0;
423 static const uint8_t empty[16] = { 0, };
424 bool skipped = false;
425 char tmp[16];
427 if (len<=0) return;
429 for (i=0;i<len;) {
431 if (i%16 == 0) {
432 if ((omit_zero_bytes == true) &&
433 (i > 0) &&
434 (len > i+16) &&
435 (memcmp(&buf[i], &empty, 16) == 0))
437 i +=16;
438 continue;
441 if (i<len) {
442 snprintf(tmp, sizeof(tmp), "[%04X] ", i);
443 cb(tmp, private_data);
447 snprintf(tmp, sizeof(tmp), "%02X ", (int)buf[i]);
448 cb(tmp, private_data);
449 i++;
450 if (i%8 == 0) {
451 cb(" ", private_data);
453 if (i%16 == 0) {
455 print_asc_cb(&buf[i-16], 8, cb, private_data);
456 cb(" ", private_data);
457 print_asc_cb(&buf[i-8], 8, cb, private_data);
458 cb("\n", private_data);
460 if ((omit_zero_bytes == true) &&
461 (len > i+16) &&
462 (memcmp(&buf[i], &empty, 16) == 0)) {
463 if (!skipped) {
464 cb("skipping zero buffer bytes\n",
465 private_data);
466 skipped = true;
472 if (i%16) {
473 int n;
474 n = 16 - (i%16);
475 cb(" ", private_data);
476 if (n>8) {
477 cb(" ", private_data);
479 while (n--) {
480 cb(" ", private_data);
482 n = MIN(8,i%16);
483 print_asc_cb(&buf[i-(i%16)], n, cb, private_data);
484 cb(" ", private_data);
485 n = (i%16) - n;
486 if (n>0) {
487 print_asc_cb(&buf[i-n], n, cb, private_data);
489 cb("\n", private_data);
495 * Write dump of binary data to the log file.
497 * The data is only written if the log level is at least level.
499 _PUBLIC_ void dump_data(int level, const uint8_t *buf, int len)
501 if (!DEBUGLVL(level)) {
502 return;
504 dump_data_cb(buf, len, false, debugadd_cb, &level);
508 * Write dump of binary data to the log file.
510 * The data is only written if the log level is at least level.
511 * 16 zero bytes in a row are omitted
513 _PUBLIC_ void dump_data_skip_zeros(int level, const uint8_t *buf, int len)
515 if (!DEBUGLVL(level)) {
516 return;
518 dump_data_cb(buf, len, true, debugadd_cb, &level);
521 static void fprintf_cb(const char *buf, void *private_data)
523 FILE *f = (FILE *)private_data;
524 fprintf(f, "%s", buf);
527 void dump_data_file(const uint8_t *buf, int len, bool omit_zero_bytes,
528 FILE *f)
530 dump_data_cb(buf, len, omit_zero_bytes, fprintf_cb, f);
534 malloc that aborts with smb_panic on fail or zero size.
537 _PUBLIC_ void *smb_xmalloc(size_t size)
539 void *p;
540 if (size == 0)
541 smb_panic("smb_xmalloc: called with zero size.\n");
542 if ((p = malloc(size)) == NULL)
543 smb_panic("smb_xmalloc: malloc fail.\n");
544 return p;
548 Memdup with smb_panic on fail.
551 _PUBLIC_ void *smb_xmemdup(const void *p, size_t size)
553 void *p2;
554 p2 = smb_xmalloc(size);
555 memcpy(p2, p, size);
556 return p2;
560 strdup that aborts on malloc fail.
563 char *smb_xstrdup(const char *s)
565 #if defined(PARANOID_MALLOC_CHECKER)
566 #ifdef strdup
567 #undef strdup
568 #endif
569 #endif
571 #ifndef HAVE_STRDUP
572 #define strdup rep_strdup
573 #endif
575 char *s1 = strdup(s);
576 #if defined(PARANOID_MALLOC_CHECKER)
577 #ifdef strdup
578 #undef strdup
579 #endif
580 #define strdup(s) __ERROR_DONT_USE_STRDUP_DIRECTLY
581 #endif
582 if (!s1) {
583 smb_panic("smb_xstrdup: malloc failed");
585 return s1;
590 strndup that aborts on malloc fail.
593 char *smb_xstrndup(const char *s, size_t n)
595 #if defined(PARANOID_MALLOC_CHECKER)
596 #ifdef strndup
597 #undef strndup
598 #endif
599 #endif
601 #if (defined(BROKEN_STRNDUP) || !defined(HAVE_STRNDUP))
602 #undef HAVE_STRNDUP
603 #define strndup rep_strndup
604 #endif
606 char *s1 = strndup(s, n);
607 #if defined(PARANOID_MALLOC_CHECKER)
608 #ifdef strndup
609 #undef strndup
610 #endif
611 #define strndup(s,n) __ERROR_DONT_USE_STRNDUP_DIRECTLY
612 #endif
613 if (!s1) {
614 smb_panic("smb_xstrndup: malloc failed");
616 return s1;
622 Like strdup but for memory.
625 _PUBLIC_ void *memdup(const void *p, size_t size)
627 void *p2;
628 if (size == 0)
629 return NULL;
630 p2 = malloc(size);
631 if (!p2)
632 return NULL;
633 memcpy(p2, p, size);
634 return p2;
638 * Write a password to the log file.
640 * @note Only actually does something if DEBUG_PASSWORD was defined during
641 * compile-time.
643 _PUBLIC_ void dump_data_pw(const char *msg, const uint8_t * data, size_t len)
645 #ifdef DEBUG_PASSWORD
646 DEBUG(11, ("%s", msg));
647 if (data != NULL && len > 0)
649 dump_data(11, data, len);
651 #endif
656 * see if a range of memory is all zero. A NULL pointer is considered
657 * to be all zero
659 _PUBLIC_ bool all_zero(const uint8_t *ptr, size_t size)
661 int i;
662 if (!ptr) return true;
663 for (i=0;i<size;i++) {
664 if (ptr[i]) return false;
666 return true;
670 realloc an array, checking for integer overflow in the array size
672 _PUBLIC_ void *realloc_array(void *ptr, size_t el_size, unsigned count, bool free_on_fail)
674 #define MAX_MALLOC_SIZE 0x7fffffff
675 if (count == 0 ||
676 count >= MAX_MALLOC_SIZE/el_size) {
677 if (free_on_fail)
678 SAFE_FREE(ptr);
679 return NULL;
681 if (!ptr) {
682 return malloc(el_size * count);
684 return realloc(ptr, el_size * count);
687 /****************************************************************************
688 Type-safe malloc.
689 ****************************************************************************/
691 void *malloc_array(size_t el_size, unsigned int count)
693 return realloc_array(NULL, el_size, count, false);
696 /****************************************************************************
697 Type-safe memalign
698 ****************************************************************************/
700 void *memalign_array(size_t el_size, size_t align, unsigned int count)
702 if (count*el_size >= MAX_MALLOC_SIZE) {
703 return NULL;
706 return memalign(align, el_size*count);
709 /****************************************************************************
710 Type-safe calloc.
711 ****************************************************************************/
713 void *calloc_array(size_t size, size_t nmemb)
715 if (nmemb >= MAX_MALLOC_SIZE/size) {
716 return NULL;
718 if (size == 0 || nmemb == 0) {
719 return NULL;
721 return calloc(nmemb, size);
725 Trim the specified elements off the front and back of a string.
727 _PUBLIC_ bool trim_string(char *s, const char *front, const char *back)
729 bool ret = false;
730 size_t front_len;
731 size_t back_len;
732 size_t len;
734 /* Ignore null or empty strings. */
735 if (!s || (s[0] == '\0'))
736 return false;
738 front_len = front? strlen(front) : 0;
739 back_len = back? strlen(back) : 0;
741 len = strlen(s);
743 if (front_len) {
744 while (len && strncmp(s, front, front_len)==0) {
745 /* Must use memmove here as src & dest can
746 * easily overlap. Found by valgrind. JRA. */
747 memmove(s, s+front_len, (len-front_len)+1);
748 len -= front_len;
749 ret=true;
753 if (back_len) {
754 while ((len >= back_len) && strncmp(s+len-back_len,back,back_len)==0) {
755 s[len-back_len]='\0';
756 len -= back_len;
757 ret=true;
760 return ret;
764 Find the number of 'c' chars in a string
766 _PUBLIC_ _PURE_ size_t count_chars(const char *s, char c)
768 size_t count = 0;
770 while (*s) {
771 if (*s == c) count++;
772 s ++;
775 return count;
779 * Routine to get hex characters and turn them into a byte array.
780 * the array can be variable length.
781 * - "0xnn" or "0Xnn" is specially catered for.
782 * - The first non-hex-digit character (apart from possibly leading "0x"
783 * finishes the conversion and skips the rest of the input.
784 * - A single hex-digit character at the end of the string is skipped.
786 * valid examples: "0A5D15"; "0x123456"
788 _PUBLIC_ size_t strhex_to_str(char *p, size_t p_len, const char *strhex, size_t strhex_len)
790 size_t i = 0;
791 size_t num_chars = 0;
792 uint8_t lonybble, hinybble;
793 const char *hexchars = "0123456789ABCDEF";
794 char *p1 = NULL, *p2 = NULL;
796 /* skip leading 0x prefix */
797 if (strncasecmp(strhex, "0x", 2) == 0) {
798 i += 2; /* skip two chars */
801 for (; i+1 < strhex_len && strhex[i] != 0 && strhex[i+1] != 0; i++) {
802 p1 = strchr(hexchars, toupper((unsigned char)strhex[i]));
803 if (p1 == NULL) {
804 break;
807 i++; /* next hex digit */
809 p2 = strchr(hexchars, toupper((unsigned char)strhex[i]));
810 if (p2 == NULL) {
811 break;
814 /* get the two nybbles */
815 hinybble = PTR_DIFF(p1, hexchars);
816 lonybble = PTR_DIFF(p2, hexchars);
818 if (num_chars >= p_len) {
819 break;
822 p[num_chars] = (hinybble << 4) | lonybble;
823 num_chars++;
825 p1 = NULL;
826 p2 = NULL;
828 return num_chars;
831 /**
832 * Parse a hex string and return a data blob.
834 _PUBLIC_ _PURE_ DATA_BLOB strhex_to_data_blob(TALLOC_CTX *mem_ctx, const char *strhex)
836 DATA_BLOB ret_blob = data_blob_talloc(mem_ctx, NULL, strlen(strhex)/2+1);
838 ret_blob.length = strhex_to_str((char *)ret_blob.data, ret_blob.length,
839 strhex,
840 strlen(strhex));
842 return ret_blob;
846 * Print a buf in hex. Assumes dst is at least (srclen*2)+1 large.
848 _PUBLIC_ void hex_encode_buf(char *dst, const uint8_t *src, size_t srclen)
850 size_t i;
851 for (i=0; i<srclen; i++) {
852 snprintf(dst + i*2, 3, "%02X", src[i]);
855 * Ensure 0-termination for 0-length buffers
857 dst[srclen*2] = '\0';
861 * Routine to print a buffer as HEX digits, into an allocated string.
863 _PUBLIC_ void hex_encode(const unsigned char *buff_in, size_t len, char **out_hex_buffer)
865 char *hex_buffer;
867 *out_hex_buffer = malloc_array_p(char, (len*2)+1);
868 hex_buffer = *out_hex_buffer;
869 hex_encode_buf(hex_buffer, buff_in, len);
873 * talloc version of hex_encode()
875 _PUBLIC_ char *hex_encode_talloc(TALLOC_CTX *mem_ctx, const unsigned char *buff_in, size_t len)
877 char *hex_buffer;
879 hex_buffer = talloc_array(mem_ctx, char, (len*2)+1);
880 if (!hex_buffer) {
881 return NULL;
883 hex_encode_buf(hex_buffer, buff_in, len);
884 talloc_set_name_const(hex_buffer, hex_buffer);
885 return hex_buffer;
889 varient of strcmp() that handles NULL ptrs
891 _PUBLIC_ int strcmp_safe(const char *s1, const char *s2)
893 if (s1 == s2) {
894 return 0;
896 if (s1 == NULL || s2 == NULL) {
897 return s1?-1:1;
899 return strcmp(s1, s2);
904 return the number of bytes occupied by a buffer in ASCII format
905 the result includes the null termination
906 limited by 'n' bytes
908 _PUBLIC_ size_t ascii_len_n(const char *src, size_t n)
910 size_t len;
912 len = strnlen(src, n);
913 if (len+1 <= n) {
914 len += 1;
917 return len;
921 Set a boolean variable from the text value stored in the passed string.
922 Returns true in success, false if the passed string does not correctly
923 represent a boolean.
926 _PUBLIC_ bool set_boolean(const char *boolean_string, bool *boolean)
928 if (strwicmp(boolean_string, "yes") == 0 ||
929 strwicmp(boolean_string, "true") == 0 ||
930 strwicmp(boolean_string, "on") == 0 ||
931 strwicmp(boolean_string, "1") == 0) {
932 *boolean = true;
933 return true;
934 } else if (strwicmp(boolean_string, "no") == 0 ||
935 strwicmp(boolean_string, "false") == 0 ||
936 strwicmp(boolean_string, "off") == 0 ||
937 strwicmp(boolean_string, "0") == 0) {
938 *boolean = false;
939 return true;
941 return false;
945 return the number of bytes occupied by a buffer in CH_UTF16 format
946 the result includes the null termination
948 _PUBLIC_ size_t utf16_len(const void *buf)
950 size_t len;
952 for (len = 0; SVAL(buf,len); len += 2) ;
954 return len + 2;
958 return the number of bytes occupied by a buffer in CH_UTF16 format
959 the result includes the null termination
960 limited by 'n' bytes
962 _PUBLIC_ size_t utf16_len_n(const void *src, size_t n)
964 size_t len;
966 for (len = 0; (len+2 < n) && SVAL(src, len); len += 2) ;
968 if (len+2 <= n) {
969 len += 2;
972 return len;
976 * @file
977 * @brief String utilities.
980 static bool next_token_internal_talloc(TALLOC_CTX *ctx,
981 const char **ptr,
982 char **pp_buff,
983 const char *sep,
984 bool ltrim)
986 const char *s;
987 const char *saved_s;
988 char *pbuf;
989 bool quoted;
990 size_t len=1;
992 *pp_buff = NULL;
993 if (!ptr) {
994 return(false);
997 s = *ptr;
999 /* default to simple separators */
1000 if (!sep) {
1001 sep = " \t\n\r";
1004 /* find the first non sep char, if left-trimming is requested */
1005 if (ltrim) {
1006 while (*s && strchr_m(sep,*s)) {
1007 s++;
1011 /* nothing left? */
1012 if (!*s) {
1013 return false;
1016 /* When restarting we need to go from here. */
1017 saved_s = s;
1019 /* Work out the length needed. */
1020 for (quoted = false; *s &&
1021 (quoted || !strchr_m(sep,*s)); s++) {
1022 if (*s == '\"') {
1023 quoted = !quoted;
1024 } else {
1025 len++;
1029 /* We started with len = 1 so we have space for the nul. */
1030 *pp_buff = talloc_array(ctx, char, len);
1031 if (!*pp_buff) {
1032 return false;
1035 /* copy over the token */
1036 pbuf = *pp_buff;
1037 s = saved_s;
1038 for (quoted = false; *s &&
1039 (quoted || !strchr_m(sep,*s)); s++) {
1040 if ( *s == '\"' ) {
1041 quoted = !quoted;
1042 } else {
1043 *pbuf++ = *s;
1047 *ptr = (*s) ? s+1 : s;
1048 *pbuf = 0;
1050 return true;
1053 bool next_token_talloc(TALLOC_CTX *ctx,
1054 const char **ptr,
1055 char **pp_buff,
1056 const char *sep)
1058 return next_token_internal_talloc(ctx, ptr, pp_buff, sep, true);
1062 * Get the next token from a string, return false if none found. Handles
1063 * double-quotes. This version does not trim leading separator characters
1064 * before looking for a token.
1067 bool next_token_no_ltrim_talloc(TALLOC_CTX *ctx,
1068 const char **ptr,
1069 char **pp_buff,
1070 const char *sep)
1072 return next_token_internal_talloc(ctx, ptr, pp_buff, sep, false);
1076 * Get the next token from a string, return False if none found.
1077 * Handles double-quotes.
1079 * Based on a routine by GJC@VILLAGE.COM.
1080 * Extensively modified by Andrew.Tridgell@anu.edu.au
1082 _PUBLIC_ bool next_token(const char **ptr,char *buff, const char *sep, size_t bufsize)
1084 const char *s;
1085 bool quoted;
1086 size_t len=1;
1088 if (!ptr)
1089 return false;
1091 s = *ptr;
1093 /* default to simple separators */
1094 if (!sep)
1095 sep = " \t\n\r";
1097 /* find the first non sep char */
1098 while (*s && strchr_m(sep,*s))
1099 s++;
1101 /* nothing left? */
1102 if (!*s)
1103 return false;
1105 /* copy over the token */
1106 for (quoted = false; len < bufsize && *s && (quoted || !strchr_m(sep,*s)); s++) {
1107 if (*s == '\"') {
1108 quoted = !quoted;
1109 } else {
1110 len++;
1111 *buff++ = *s;
1115 *ptr = (*s) ? s+1 : s;
1116 *buff = 0;
1118 return true;
1121 struct anonymous_shared_header {
1122 union {
1123 size_t length;
1124 uint8_t pad[16];
1125 } u;
1128 /* Map a shared memory buffer of at least nelem counters. */
1129 void *anonymous_shared_allocate(size_t orig_bufsz)
1131 void *ptr;
1132 void *buf;
1133 size_t pagesz = getpagesize();
1134 size_t pagecnt;
1135 size_t bufsz = orig_bufsz;
1136 struct anonymous_shared_header *hdr;
1138 bufsz += sizeof(*hdr);
1140 /* round up to full pages */
1141 pagecnt = bufsz / pagesz;
1142 if (bufsz % pagesz) {
1143 pagecnt += 1;
1145 bufsz = pagesz * pagecnt;
1147 if (orig_bufsz >= bufsz) {
1148 /* integer wrap */
1149 errno = ENOMEM;
1150 return NULL;
1153 #ifdef MAP_ANON
1154 /* BSD */
1155 buf = mmap(NULL, bufsz, PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED,
1156 -1 /* fd */, 0 /* offset */);
1157 #else
1159 int saved_errno;
1160 int fd;
1162 fd = open("/dev/zero", O_RDWR);
1163 if (fd == -1) {
1164 return NULL;
1167 buf = mmap(NULL, bufsz, PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED,
1168 fd, 0 /* offset */);
1169 saved_errno = errno;
1170 close(fd);
1171 errno = saved_errno;
1173 #endif
1175 if (buf == MAP_FAILED) {
1176 return NULL;
1179 hdr = (struct anonymous_shared_header *)buf;
1180 hdr->u.length = bufsz;
1182 ptr = (void *)(&hdr[1]);
1184 return ptr;
1187 void *anonymous_shared_resize(void *ptr, size_t new_size, bool maymove)
1189 #ifdef HAVE_MREMAP
1190 void *buf;
1191 size_t pagesz = getpagesize();
1192 size_t pagecnt;
1193 size_t bufsz;
1194 struct anonymous_shared_header *hdr;
1195 int flags = 0;
1197 if (ptr == NULL) {
1198 errno = EINVAL;
1199 return NULL;
1202 hdr = (struct anonymous_shared_header *)ptr;
1203 hdr--;
1204 if (hdr->u.length > (new_size + sizeof(*hdr))) {
1205 errno = EINVAL;
1206 return NULL;
1209 bufsz = new_size + sizeof(*hdr);
1211 /* round up to full pages */
1212 pagecnt = bufsz / pagesz;
1213 if (bufsz % pagesz) {
1214 pagecnt += 1;
1216 bufsz = pagesz * pagecnt;
1218 if (new_size >= bufsz) {
1219 /* integer wrap */
1220 errno = ENOSPC;
1221 return NULL;
1224 if (bufsz <= hdr->u.length) {
1225 return ptr;
1228 if (maymove) {
1229 flags = MREMAP_MAYMOVE;
1232 buf = mremap(hdr, hdr->u.length, bufsz, flags);
1234 if (buf == MAP_FAILED) {
1235 errno = ENOSPC;
1236 return NULL;
1239 hdr = (struct anonymous_shared_header *)buf;
1240 hdr->u.length = bufsz;
1242 ptr = (void *)(&hdr[1]);
1244 return ptr;
1245 #else
1246 errno = ENOSPC;
1247 return NULL;
1248 #endif
1251 void anonymous_shared_free(void *ptr)
1253 struct anonymous_shared_header *hdr;
1255 if (ptr == NULL) {
1256 return;
1259 hdr = (struct anonymous_shared_header *)ptr;
1261 hdr--;
1263 munmap(hdr, hdr->u.length);
1266 #ifdef DEVELOPER
1267 /* used when you want a debugger started at a particular point in the
1268 code. Mostly useful in code that runs as a child process, where
1269 normal gdb attach is harder to organise.
1271 void samba_start_debugger(void)
1273 char *cmd = NULL;
1274 if (asprintf(&cmd, "xterm -e \"gdb --pid %u\"&", getpid()) == -1) {
1275 return;
1277 if (system(cmd) == -1) {
1278 free(cmd);
1279 return;
1281 free(cmd);
1282 sleep(2);
1284 #endif