lib:util: Don't print lstat warning on ERROR debug level
[Samba.git] / lib / util / util.c
blob56056a3403ce7c442833748a0de2e3769ad9e0bf
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 "replace.h"
26 #include <talloc.h>
27 #include "system/network.h"
28 #include "system/filesys.h"
29 #include "system/locale.h"
30 #include "system/shmem.h"
31 #include "system/passwd.h"
32 #include "system/time.h"
33 #include "system/wait.h"
34 #include "debug.h"
35 #include "samba_util.h"
37 #undef malloc
38 #undef strcasecmp
39 #undef strncasecmp
40 #undef strdup
41 #undef realloc
42 #undef calloc
44 /**
45 * @file
46 * @brief Misc utility functions
49 /**
50 Find a suitable temporary directory. The result should be copied immediately
51 as it may be overwritten by a subsequent call.
52 **/
53 _PUBLIC_ const char *tmpdir(void)
55 char *p;
56 if ((p = getenv("TMPDIR")))
57 return p;
58 return "/tmp";
62 /**
63 Create a tmp file, open it and immediately unlink it.
64 If dir is NULL uses tmpdir()
65 Returns the file descriptor or -1 on error.
66 **/
67 int create_unlink_tmp(const char *dir)
69 size_t len = strlen(dir ? dir : (dir = tmpdir()));
70 char fname[len+25];
71 int fd;
72 mode_t mask;
74 len = snprintf(fname, sizeof(fname), "%s/listenerlock_XXXXXX", dir);
75 if (len >= sizeof(fname)) {
76 errno = ENOMEM;
77 return -1;
79 mask = umask(S_IRWXO | S_IRWXG);
80 fd = mkstemp(fname);
81 umask(mask);
82 if (fd == -1) {
83 return -1;
85 if (unlink(fname) == -1) {
86 int sys_errno = errno;
87 close(fd);
88 errno = sys_errno;
89 return -1;
91 return fd;
95 /**
96 Check if a file exists - call vfs_file_exist for samba files.
97 **/
98 _PUBLIC_ bool file_exist(const char *fname)
100 struct stat st;
102 if (stat(fname, &st) != 0) {
103 return false;
106 return ((S_ISREG(st.st_mode)) || (S_ISFIFO(st.st_mode)));
110 Check a files mod time.
113 _PUBLIC_ time_t file_modtime(const char *fname)
115 struct stat st;
117 if (stat(fname,&st) != 0)
118 return(0);
120 return(st.st_mtime);
124 Check file permissions.
127 _PUBLIC_ bool file_check_permissions(const char *fname,
128 uid_t uid,
129 mode_t file_perms,
130 struct stat *pst)
132 int ret;
133 struct stat st;
135 if (pst == NULL) {
136 pst = &st;
139 ZERO_STRUCTP(pst);
141 ret = stat(fname, pst);
142 if (ret != 0) {
143 DEBUG(0, ("stat failed on file '%s': %s\n",
144 fname, strerror(errno)));
145 return false;
148 if (pst->st_uid != uid && !uid_wrapper_enabled()) {
149 DEBUG(0, ("invalid ownership of file '%s': "
150 "owned by uid %u, should be %u\n",
151 fname, (unsigned int)pst->st_uid,
152 (unsigned int)uid));
153 return false;
156 if ((pst->st_mode & 0777) != file_perms) {
157 DEBUG(0, ("invalid permissions on file "
158 "'%s': has 0%o should be 0%o\n", fname,
159 (unsigned int)(pst->st_mode & 0777),
160 (unsigned int)file_perms));
161 return false;
164 return true;
168 Check if a directory exists.
171 _PUBLIC_ bool directory_exist(const char *dname)
173 struct stat st;
174 bool ret;
176 if (stat(dname,&st) != 0) {
177 return false;
180 ret = S_ISDIR(st.st_mode);
181 if(!ret)
182 errno = ENOTDIR;
183 return ret;
187 * Try to create the specified directory if it didn't exist.
189 * @retval true if the directory already existed
190 * or was successfully created.
192 _PUBLIC_ bool directory_create_or_exist(const char *dname,
193 mode_t dir_perms)
195 int ret;
196 struct stat st;
197 mode_t old_umask;
199 ret = lstat(dname, &st);
200 if (ret == 0) {
201 return true;
204 if (errno != ENOENT) {
205 DBG_WARNING("lstat failed on directory %s: %s\n",
206 dname, strerror(errno));
207 return false;
210 /* Create directory */
211 old_umask = umask(0);
212 ret = mkdir(dname, dir_perms);
213 if (ret == -1 && errno != EEXIST) {
214 DEBUG(0, ("mkdir failed on directory "
215 "%s: %s\n", dname,
216 strerror(errno)));
217 umask(old_umask);
218 return false;
220 umask(old_umask);
222 ret = lstat(dname, &st);
223 if (ret == -1) {
224 DEBUG(0, ("lstat failed on created directory %s: %s\n",
225 dname, strerror(errno)));
226 return false;
229 return true;
233 * @brief Try to create a specified directory if it doesn't exist.
235 * The function creates a directory with the given uid and permissions if it
236 * doesn't exist. If it exists it makes sure the uid and permissions are
237 * correct and it will fail if they are different.
239 * @param[in] dname The directory to create.
241 * @param[in] uid The uid the directory needs to belong too.
243 * @param[in] dir_perms The expected permissions of the directory.
245 * @return True on success, false on error.
247 _PUBLIC_ bool directory_create_or_exist_strict(const char *dname,
248 uid_t uid,
249 mode_t dir_perms)
251 struct stat st;
252 bool ok;
253 int rc;
255 ok = directory_create_or_exist(dname, dir_perms);
256 if (!ok) {
257 return false;
260 rc = lstat(dname, &st);
261 if (rc == -1) {
262 DEBUG(0, ("lstat failed on created directory %s: %s\n",
263 dname, strerror(errno)));
264 return false;
267 /* Check ownership and permission on existing directory */
268 if (!S_ISDIR(st.st_mode)) {
269 DEBUG(0, ("directory %s isn't a directory\n",
270 dname));
271 return false;
273 if (st.st_uid != uid && !uid_wrapper_enabled()) {
274 DBG_NOTICE("invalid ownership on directory "
275 "%s\n", dname);
276 return false;
278 if ((st.st_mode & 0777) != dir_perms) {
279 DEBUG(0, ("invalid permissions on directory "
280 "'%s': has 0%o should be 0%o\n", dname,
281 (unsigned int)(st.st_mode & 0777), (unsigned int)dir_perms));
282 return false;
285 return true;
290 Sleep for a specified number of milliseconds.
293 _PUBLIC_ void smb_msleep(unsigned int t)
295 #if defined(HAVE_NANOSLEEP)
296 struct timespec ts;
297 int ret;
299 ts.tv_sec = t/1000;
300 ts.tv_nsec = 1000000*(t%1000);
302 do {
303 errno = 0;
304 ret = nanosleep(&ts, &ts);
305 } while (ret < 0 && errno == EINTR && (ts.tv_sec > 0 || ts.tv_nsec > 0));
306 #else
307 unsigned int tdiff=0;
308 struct timeval tval,t1,t2;
309 fd_set fds;
311 GetTimeOfDay(&t1);
312 t2 = t1;
314 while (tdiff < t) {
315 tval.tv_sec = (t-tdiff)/1000;
316 tval.tv_usec = 1000*((t-tdiff)%1000);
318 /* Never wait for more than 1 sec. */
319 if (tval.tv_sec > 1) {
320 tval.tv_sec = 1;
321 tval.tv_usec = 0;
324 FD_ZERO(&fds);
325 errno = 0;
326 select(0,&fds,NULL,NULL,&tval);
328 GetTimeOfDay(&t2);
329 if (t2.tv_sec < t1.tv_sec) {
330 /* Someone adjusted time... */
331 t1 = t2;
334 tdiff = usec_time_diff(&t2,&t1)/1000;
336 #endif
340 Get my own name, return in talloc'ed storage.
343 _PUBLIC_ char *get_myname(TALLOC_CTX *ctx)
345 char *p;
346 char hostname[HOST_NAME_MAX];
348 /* get my host name */
349 if (gethostname(hostname, sizeof(hostname)) == -1) {
350 DEBUG(0,("gethostname failed\n"));
351 return NULL;
354 /* Ensure null termination. */
355 hostname[sizeof(hostname)-1] = '\0';
357 /* split off any parts after an initial . */
358 p = strchr_m(hostname, '.');
359 if (p) {
360 *p = 0;
363 return talloc_strdup(ctx, hostname);
367 Check if a process exists. Does this work on all unixes?
370 _PUBLIC_ bool process_exists_by_pid(pid_t pid)
372 /* Doing kill with a non-positive pid causes messages to be
373 * sent to places we don't want. */
374 if (pid <= 0) {
375 return false;
377 return(kill(pid,0) == 0 || errno != ESRCH);
381 Simple routine to do POSIX file locking. Cruft in NFS and 64->32 bit mapping
382 is dealt with in posix.c
385 _PUBLIC_ bool fcntl_lock(int fd, int op, off_t offset, off_t count, int type)
387 struct flock lock;
388 int ret;
390 DEBUG(8,("fcntl_lock %d %d %.0f %.0f %d\n",fd,op,(double)offset,(double)count,type));
392 lock.l_type = type;
393 lock.l_whence = SEEK_SET;
394 lock.l_start = offset;
395 lock.l_len = count;
396 lock.l_pid = 0;
398 ret = fcntl(fd,op,&lock);
400 if (ret == -1 && errno != 0)
401 DEBUG(3,("fcntl_lock: fcntl lock gave errno %d (%s)\n",errno,strerror(errno)));
403 /* a lock query */
404 if (op == F_GETLK) {
405 if ((ret != -1) &&
406 (lock.l_type != F_UNLCK) &&
407 (lock.l_pid != 0) &&
408 (lock.l_pid != getpid())) {
409 DEBUG(3,("fcntl_lock: fd %d is locked by pid %d\n",fd,(int)lock.l_pid));
410 return true;
413 /* it must be not locked or locked by me */
414 return false;
417 /* a lock set or unset */
418 if (ret == -1) {
419 DEBUG(3,("fcntl_lock: lock failed at offset %.0f count %.0f op %d type %d (%s)\n",
420 (double)offset,(double)count,op,type,strerror(errno)));
421 return false;
424 /* everything went OK */
425 DEBUG(8,("fcntl_lock: Lock call successful\n"));
427 return true;
430 struct debug_channel_level {
431 int channel;
432 int level;
435 static void debugadd_channel_cb(const char *buf, void *private_data)
437 struct debug_channel_level *dcl =
438 (struct debug_channel_level *)private_data;
440 DEBUGADDC(dcl->channel, dcl->level,("%s", buf));
443 static void debugadd_cb(const char *buf, void *private_data)
445 int *plevel = (int *)private_data;
446 DEBUGADD(*plevel, ("%s", buf));
449 void print_asc_cb(const uint8_t *buf, int len,
450 void (*cb)(const char *buf, void *private_data),
451 void *private_data)
453 int i;
454 char s[2];
455 s[1] = 0;
457 for (i=0; i<len; i++) {
458 s[0] = isprint(buf[i]) ? buf[i] : '.';
459 cb(s, private_data);
463 void print_asc(int level, const uint8_t *buf,int len)
465 print_asc_cb(buf, len, debugadd_cb, &level);
469 * Write dump of binary data to a callback
471 void dump_data_cb(const uint8_t *buf, int len,
472 bool omit_zero_bytes,
473 void (*cb)(const char *buf, void *private_data),
474 void *private_data)
476 int i=0;
477 static const uint8_t empty[16] = { 0, };
478 bool skipped = false;
479 char tmp[16];
481 if (len<=0) return;
483 for (i=0;i<len;) {
485 if (i%16 == 0) {
486 if ((omit_zero_bytes == true) &&
487 (i > 0) &&
488 (len > i+16) &&
489 (memcmp(&buf[i], &empty, 16) == 0))
491 i +=16;
492 continue;
495 if (i<len) {
496 snprintf(tmp, sizeof(tmp), "[%04X] ", i);
497 cb(tmp, private_data);
501 snprintf(tmp, sizeof(tmp), "%02X ", (int)buf[i]);
502 cb(tmp, private_data);
503 i++;
504 if (i%8 == 0) {
505 cb(" ", private_data);
507 if (i%16 == 0) {
509 print_asc_cb(&buf[i-16], 8, cb, private_data);
510 cb(" ", private_data);
511 print_asc_cb(&buf[i-8], 8, cb, private_data);
512 cb("\n", private_data);
514 if ((omit_zero_bytes == true) &&
515 (len > i+16) &&
516 (memcmp(&buf[i], &empty, 16) == 0)) {
517 if (!skipped) {
518 cb("skipping zero buffer bytes\n",
519 private_data);
520 skipped = true;
526 if (i%16) {
527 int n;
528 n = 16 - (i%16);
529 cb(" ", private_data);
530 if (n>8) {
531 cb(" ", private_data);
533 while (n--) {
534 cb(" ", private_data);
536 n = MIN(8,i%16);
537 print_asc_cb(&buf[i-(i%16)], n, cb, private_data);
538 cb(" ", private_data);
539 n = (i%16) - n;
540 if (n>0) {
541 print_asc_cb(&buf[i-n], n, cb, private_data);
543 cb("\n", private_data);
549 * Write dump of binary data to the log file.
551 * The data is only written if the log level is at least level.
553 _PUBLIC_ void dump_data(int level, const uint8_t *buf, int len)
555 if (!DEBUGLVL(level)) {
556 return;
558 dump_data_cb(buf, len, false, debugadd_cb, &level);
562 * Write dump of binary data to the log file.
564 * The data is only written if the log level is at least level for
565 * debug class dbgc_class.
567 _PUBLIC_ void dump_data_dbgc(int dbgc_class, int level, const uint8_t *buf, int len)
569 struct debug_channel_level dcl = { dbgc_class, level };
571 if (!DEBUGLVLC(dbgc_class, level)) {
572 return;
574 dump_data_cb(buf, len, false, debugadd_channel_cb, &dcl);
578 * Write dump of binary data to the log file.
580 * The data is only written if the log level is at least level.
581 * 16 zero bytes in a row are omitted
583 _PUBLIC_ void dump_data_skip_zeros(int level, const uint8_t *buf, int len)
585 if (!DEBUGLVL(level)) {
586 return;
588 dump_data_cb(buf, len, true, debugadd_cb, &level);
591 static void fprintf_cb(const char *buf, void *private_data)
593 FILE *f = (FILE *)private_data;
594 fprintf(f, "%s", buf);
597 void dump_data_file(const uint8_t *buf, int len, bool omit_zero_bytes,
598 FILE *f)
600 dump_data_cb(buf, len, omit_zero_bytes, fprintf_cb, f);
604 malloc that aborts with smb_panic on fail or zero size.
607 _PUBLIC_ void *smb_xmalloc(size_t size)
609 void *p;
610 if (size == 0)
611 smb_panic("smb_xmalloc: called with zero size.\n");
612 if ((p = malloc(size)) == NULL)
613 smb_panic("smb_xmalloc: malloc fail.\n");
614 return p;
618 Memdup with smb_panic on fail.
621 _PUBLIC_ void *smb_xmemdup(const void *p, size_t size)
623 void *p2;
624 p2 = smb_xmalloc(size);
625 memcpy(p2, p, size);
626 return p2;
630 strdup that aborts on malloc fail.
633 char *smb_xstrdup(const char *s)
635 #if defined(PARANOID_MALLOC_CHECKER)
636 #ifdef strdup
637 #undef strdup
638 #endif
639 #endif
641 #ifndef HAVE_STRDUP
642 #define strdup rep_strdup
643 #endif
645 char *s1 = strdup(s);
646 #if defined(PARANOID_MALLOC_CHECKER)
647 #ifdef strdup
648 #undef strdup
649 #endif
650 #define strdup(s) __ERROR_DONT_USE_STRDUP_DIRECTLY
651 #endif
652 if (!s1) {
653 smb_panic("smb_xstrdup: malloc failed");
655 return s1;
660 strndup that aborts on malloc fail.
663 char *smb_xstrndup(const char *s, size_t n)
665 #if defined(PARANOID_MALLOC_CHECKER)
666 #ifdef strndup
667 #undef strndup
668 #endif
669 #endif
671 #if (defined(BROKEN_STRNDUP) || !defined(HAVE_STRNDUP))
672 #undef HAVE_STRNDUP
673 #define strndup rep_strndup
674 #endif
676 char *s1 = strndup(s, n);
677 #if defined(PARANOID_MALLOC_CHECKER)
678 #ifdef strndup
679 #undef strndup
680 #endif
681 #define strndup(s,n) __ERROR_DONT_USE_STRNDUP_DIRECTLY
682 #endif
683 if (!s1) {
684 smb_panic("smb_xstrndup: malloc failed");
686 return s1;
692 Like strdup but for memory.
695 _PUBLIC_ void *smb_memdup(const void *p, size_t size)
697 void *p2;
698 if (size == 0)
699 return NULL;
700 p2 = malloc(size);
701 if (!p2)
702 return NULL;
703 memcpy(p2, p, size);
704 return p2;
708 * Write a password to the log file.
710 * @note Only actually does something if DEBUG_PASSWORD was defined during
711 * compile-time.
713 _PUBLIC_ void dump_data_pw(const char *msg, const uint8_t * data, size_t len)
715 #ifdef DEBUG_PASSWORD
716 DEBUG(11, ("%s", msg));
717 if (data != NULL && len > 0)
719 dump_data(11, data, len);
721 #endif
726 * see if a range of memory is all zero. A NULL pointer is considered
727 * to be all zero
729 _PUBLIC_ bool all_zero(const uint8_t *ptr, size_t size)
731 size_t i;
732 if (!ptr) return true;
733 for (i=0;i<size;i++) {
734 if (ptr[i]) return false;
736 return true;
740 realloc an array, checking for integer overflow in the array size
742 _PUBLIC_ void *realloc_array(void *ptr, size_t el_size, unsigned count, bool free_on_fail)
744 #define MAX_MALLOC_SIZE 0x7fffffff
745 if (count == 0 ||
746 count >= MAX_MALLOC_SIZE/el_size) {
747 if (free_on_fail)
748 SAFE_FREE(ptr);
749 return NULL;
751 if (!ptr) {
752 return malloc(el_size * count);
754 return realloc(ptr, el_size * count);
757 /****************************************************************************
758 Type-safe malloc.
759 ****************************************************************************/
761 void *malloc_array(size_t el_size, unsigned int count)
763 return realloc_array(NULL, el_size, count, false);
766 /****************************************************************************
767 Type-safe memalign
768 ****************************************************************************/
770 void *memalign_array(size_t el_size, size_t align, unsigned int count)
772 if (el_size == 0 || count >= MAX_MALLOC_SIZE/el_size) {
773 return NULL;
776 return memalign(align, el_size*count);
779 /****************************************************************************
780 Type-safe calloc.
781 ****************************************************************************/
783 void *calloc_array(size_t size, size_t nmemb)
785 if (nmemb >= MAX_MALLOC_SIZE/size) {
786 return NULL;
788 if (size == 0 || nmemb == 0) {
789 return NULL;
791 return calloc(nmemb, size);
795 Trim the specified elements off the front and back of a string.
797 _PUBLIC_ bool trim_string(char *s, const char *front, const char *back)
799 bool ret = false;
800 size_t front_len;
801 size_t back_len;
802 size_t len;
804 /* Ignore null or empty strings. */
805 if (!s || (s[0] == '\0')) {
806 return false;
808 len = strlen(s);
810 front_len = front? strlen(front) : 0;
811 back_len = back? strlen(back) : 0;
813 if (front_len) {
814 size_t front_trim = 0;
816 while (strncmp(s+front_trim, front, front_len)==0) {
817 front_trim += front_len;
819 if (front_trim > 0) {
820 /* Must use memmove here as src & dest can
821 * easily overlap. Found by valgrind. JRA. */
822 memmove(s, s+front_trim, (len-front_trim)+1);
823 len -= front_trim;
824 ret=true;
828 if (back_len) {
829 while ((len >= back_len) && strncmp(s+len-back_len,back,back_len)==0) {
830 s[len-back_len]='\0';
831 len -= back_len;
832 ret=true;
835 return ret;
839 Find the number of 'c' chars in a string
841 _PUBLIC_ _PURE_ size_t count_chars(const char *s, char c)
843 size_t count = 0;
845 while (*s) {
846 if (*s == c) count++;
847 s ++;
850 return count;
854 * Routine to get hex characters and turn them into a byte array.
855 * the array can be variable length.
856 * - "0xnn" or "0Xnn" is specially catered for.
857 * - The first non-hex-digit character (apart from possibly leading "0x"
858 * finishes the conversion and skips the rest of the input.
859 * - A single hex-digit character at the end of the string is skipped.
861 * valid examples: "0A5D15"; "0x123456"
863 _PUBLIC_ size_t strhex_to_str(char *p, size_t p_len, const char *strhex, size_t strhex_len)
865 size_t i = 0;
866 size_t num_chars = 0;
867 uint8_t lonybble, hinybble;
868 const char *hexchars = "0123456789ABCDEF";
869 char *p1 = NULL, *p2 = NULL;
871 /* skip leading 0x prefix */
872 if (strncasecmp(strhex, "0x", 2) == 0) {
873 i += 2; /* skip two chars */
876 for (; i+1 < strhex_len && strhex[i] != 0 && strhex[i+1] != 0; i++) {
877 p1 = strchr(hexchars, toupper((unsigned char)strhex[i]));
878 if (p1 == NULL) {
879 break;
882 i++; /* next hex digit */
884 p2 = strchr(hexchars, toupper((unsigned char)strhex[i]));
885 if (p2 == NULL) {
886 break;
889 /* get the two nybbles */
890 hinybble = PTR_DIFF(p1, hexchars);
891 lonybble = PTR_DIFF(p2, hexchars);
893 if (num_chars >= p_len) {
894 break;
897 p[num_chars] = (hinybble << 4) | lonybble;
898 num_chars++;
900 p1 = NULL;
901 p2 = NULL;
903 return num_chars;
906 /**
907 * Parse a hex string and return a data blob.
909 _PUBLIC_ _PURE_ DATA_BLOB strhex_to_data_blob(TALLOC_CTX *mem_ctx, const char *strhex)
911 DATA_BLOB ret_blob = data_blob_talloc(mem_ctx, NULL, strlen(strhex)/2+1);
913 ret_blob.length = strhex_to_str((char *)ret_blob.data, ret_blob.length,
914 strhex,
915 strlen(strhex));
917 return ret_blob;
921 * Print a buf in hex. Assumes dst is at least (srclen*2)+1 large.
923 _PUBLIC_ void hex_encode_buf(char *dst, const uint8_t *src, size_t srclen)
925 size_t i;
926 for (i=0; i<srclen; i++) {
927 snprintf(dst + i*2, 3, "%02X", src[i]);
930 * Ensure 0-termination for 0-length buffers
932 dst[srclen*2] = '\0';
936 * talloc version of hex_encode_buf()
938 _PUBLIC_ char *hex_encode_talloc(TALLOC_CTX *mem_ctx, const unsigned char *buff_in, size_t len)
940 char *hex_buffer;
942 hex_buffer = talloc_array(mem_ctx, char, (len*2)+1);
943 if (!hex_buffer) {
944 return NULL;
946 hex_encode_buf(hex_buffer, buff_in, len);
947 talloc_set_name_const(hex_buffer, hex_buffer);
948 return hex_buffer;
952 varient of strcmp() that handles NULL ptrs
954 _PUBLIC_ int strcmp_safe(const char *s1, const char *s2)
956 if (s1 == s2) {
957 return 0;
959 if (s1 == NULL || s2 == NULL) {
960 return s1?-1:1;
962 return strcmp(s1, s2);
967 return the number of bytes occupied by a buffer in ASCII format
968 the result includes the null termination
969 limited by 'n' bytes
971 _PUBLIC_ size_t ascii_len_n(const char *src, size_t n)
973 size_t len;
975 len = strnlen(src, n);
976 if (len+1 <= n) {
977 len += 1;
980 return len;
983 struct anonymous_shared_header {
984 union {
985 size_t length;
986 uint8_t pad[16];
987 } u;
990 /* Map a shared memory buffer of at least nelem counters. */
991 void *anonymous_shared_allocate(size_t orig_bufsz)
993 void *ptr;
994 void *buf;
995 size_t pagesz = getpagesize();
996 size_t pagecnt;
997 size_t bufsz = orig_bufsz;
998 struct anonymous_shared_header *hdr;
1000 bufsz += sizeof(*hdr);
1002 /* round up to full pages */
1003 pagecnt = bufsz / pagesz;
1004 if (bufsz % pagesz) {
1005 pagecnt += 1;
1007 bufsz = pagesz * pagecnt;
1009 if (orig_bufsz >= bufsz) {
1010 /* integer wrap */
1011 errno = ENOMEM;
1012 return NULL;
1015 #ifdef MAP_ANON
1016 /* BSD */
1017 buf = mmap(NULL, bufsz, PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED,
1018 -1 /* fd */, 0 /* offset */);
1019 #else
1021 int saved_errno;
1022 int fd;
1024 fd = open("/dev/zero", O_RDWR);
1025 if (fd == -1) {
1026 return NULL;
1029 buf = mmap(NULL, bufsz, PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED,
1030 fd, 0 /* offset */);
1031 saved_errno = errno;
1032 close(fd);
1033 errno = saved_errno;
1035 #endif
1037 if (buf == MAP_FAILED) {
1038 return NULL;
1041 hdr = (struct anonymous_shared_header *)buf;
1042 hdr->u.length = bufsz;
1044 ptr = (void *)(&hdr[1]);
1046 return ptr;
1049 void *anonymous_shared_resize(void *ptr, size_t new_size, bool maymove)
1051 #ifdef HAVE_MREMAP
1052 void *buf;
1053 size_t pagesz = getpagesize();
1054 size_t pagecnt;
1055 size_t bufsz;
1056 struct anonymous_shared_header *hdr;
1057 int flags = 0;
1059 if (ptr == NULL) {
1060 errno = EINVAL;
1061 return NULL;
1064 hdr = (struct anonymous_shared_header *)ptr;
1065 hdr--;
1066 if (hdr->u.length > (new_size + sizeof(*hdr))) {
1067 errno = EINVAL;
1068 return NULL;
1071 bufsz = new_size + sizeof(*hdr);
1073 /* round up to full pages */
1074 pagecnt = bufsz / pagesz;
1075 if (bufsz % pagesz) {
1076 pagecnt += 1;
1078 bufsz = pagesz * pagecnt;
1080 if (new_size >= bufsz) {
1081 /* integer wrap */
1082 errno = ENOSPC;
1083 return NULL;
1086 if (bufsz <= hdr->u.length) {
1087 return ptr;
1090 if (maymove) {
1091 flags = MREMAP_MAYMOVE;
1094 buf = mremap(hdr, hdr->u.length, bufsz, flags);
1096 if (buf == MAP_FAILED) {
1097 errno = ENOSPC;
1098 return NULL;
1101 hdr = (struct anonymous_shared_header *)buf;
1102 hdr->u.length = bufsz;
1104 ptr = (void *)(&hdr[1]);
1106 return ptr;
1107 #else
1108 errno = ENOSPC;
1109 return NULL;
1110 #endif
1113 void anonymous_shared_free(void *ptr)
1115 struct anonymous_shared_header *hdr;
1117 if (ptr == NULL) {
1118 return;
1121 hdr = (struct anonymous_shared_header *)ptr;
1123 hdr--;
1125 munmap(hdr, hdr->u.length);
1128 #ifdef DEVELOPER
1129 /* used when you want a debugger started at a particular point in the
1130 code. Mostly useful in code that runs as a child process, where
1131 normal gdb attach is harder to organise.
1133 void samba_start_debugger(void)
1135 char *cmd = NULL;
1136 if (asprintf(&cmd, "xterm -e \"gdb --pid %u\"&", getpid()) == -1) {
1137 return;
1139 if (system(cmd) == -1) {
1140 free(cmd);
1141 return;
1143 free(cmd);
1144 sleep(2);
1146 #endif