LCOV - code coverage report
Current view: top level - lib/util - util.c (source / functions) Hit Total Coverage
Test: coverage report for recycleplus df22b230 Lines: 259 500 51.8 %
Date: 2024-02-14 10:14:15 Functions: 37 52 71.2 %

          Line data    Source code
       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
      10             :    Copyright (C) Swen Schillig 2019
      11             : 
      12             :    This program is free software; you can redistribute it and/or modify
      13             :    it under the terms of the GNU General Public License as published by
      14             :    the Free Software Foundation; either version 3 of the License, or
      15             :    (at your option) any later version.
      16             :    
      17             :    This program is distributed in the hope that it will be useful,
      18             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      19             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      20             :    GNU General Public License for more details.
      21             :    
      22             :    You should have received a copy of the GNU General Public License
      23             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      24             : */
      25             : 
      26             : #include "replace.h"
      27             : #include <talloc.h>
      28             : #include <tevent.h>
      29             : #include "system/network.h"
      30             : #include "system/filesys.h"
      31             : #include "system/locale.h"
      32             : #include "system/shmem.h"
      33             : #include "system/passwd.h"
      34             : #include "system/time.h"
      35             : #include "system/wait.h"
      36             : #include "debug.h"
      37             : #include "samba_util.h"
      38             : #include "lib/util/select.h"
      39             : #include <libgen.h>
      40             : #include <gnutls/gnutls.h>
      41             : 
      42             : #ifdef HAVE_SYS_PRCTL_H
      43             : #include <sys/prctl.h>
      44             : #endif
      45             : 
      46             : #undef malloc
      47             : #undef strcasecmp
      48             : #undef strncasecmp
      49             : #undef strdup
      50             : #undef realloc
      51             : #undef calloc
      52             : 
      53             : /**
      54             :  * @file
      55             :  * @brief Misc utility functions
      56             :  */
      57             : 
      58             : /**
      59             :  Find a suitable temporary directory. The result should be copied immediately
      60             :  as it may be overwritten by a subsequent call.
      61             : **/
      62        1692 : _PUBLIC_ const char *tmpdir(void)
      63             : {
      64             :         char *p;
      65        1692 :         if ((p = getenv("TMPDIR")))
      66        1692 :                 return p;
      67           0 :         return "/tmp";
      68             : }
      69             : 
      70             : 
      71             : /**
      72             :  Create a tmp file, open it and immediately unlink it.
      73             :  If dir is NULL uses tmpdir()
      74             :  Returns the file descriptor or -1 on error.
      75             : **/
      76           0 : int create_unlink_tmp(const char *dir)
      77           0 : {
      78           0 :         size_t len = strlen(dir ? dir : (dir = tmpdir()));
      79           0 :         char fname[len+25];
      80             :         int fd;
      81             :         mode_t mask;
      82             : 
      83           0 :         len = snprintf(fname, sizeof(fname), "%s/listenerlock_XXXXXX", dir);
      84           0 :         if (len >= sizeof(fname)) {
      85           0 :                 errno = ENOMEM;
      86           0 :                 return -1;
      87             :         }
      88           0 :         mask = umask(S_IRWXO | S_IRWXG);
      89           0 :         fd = mkstemp(fname);
      90           0 :         umask(mask);
      91           0 :         if (fd == -1) {
      92           0 :                 return -1;
      93             :         }
      94           0 :         if (unlink(fname) == -1) {
      95           0 :                 int sys_errno = errno;
      96           0 :                 close(fd);
      97           0 :                 errno = sys_errno;
      98           0 :                 return -1;
      99             :         }
     100           0 :         return fd;
     101             : }
     102             : 
     103             : 
     104             : /**
     105             :  Check if a file exists - call vfs_file_exist for samba files.
     106             : **/
     107       42181 : _PUBLIC_ bool file_exist(const char *fname)
     108             : {
     109             :         struct stat st;
     110             : 
     111       42181 :         if (stat(fname, &st) != 0) {
     112       28552 :                 return false;
     113             :         }
     114             : 
     115       13629 :         return ((S_ISREG(st.st_mode)) || (S_ISFIFO(st.st_mode)));
     116             : }
     117             : 
     118             : /**
     119             :  * @brief Return a files modification time.
     120             :  *
     121             :  * @param fname  The name of the file.
     122             :  *
     123             :  * @param mt     A pointer to store the modification time.
     124             :  *
     125             :  * @return 0 on success, errno otherwise.
     126             :  */
     127       42377 : _PUBLIC_ int file_modtime(const char *fname, struct timespec *mt)
     128             : {
     129       42377 :         struct stat st = {0};
     130             : 
     131       42377 :         if (stat(fname, &st) != 0) {
     132        1925 :                 return errno;
     133             :         }
     134             : 
     135       40452 :         *mt = get_mtimespec(&st);
     136       40452 :         return 0;
     137             : }
     138             : 
     139             : /**
     140             :  Check file permissions.
     141             : **/
     142             : 
     143          50 : _PUBLIC_ bool file_check_permissions(const char *fname,
     144             :                                      uid_t uid,
     145             :                                      mode_t file_perms,
     146             :                                      struct stat *pst)
     147             : {
     148             :         int ret;
     149             :         struct stat st;
     150             : 
     151          50 :         if (pst == NULL) {
     152           0 :                 pst = &st;
     153             :         }
     154             : 
     155          50 :         ZERO_STRUCTP(pst);
     156             : 
     157          50 :         ret = stat(fname, pst);
     158          50 :         if (ret != 0) {
     159           0 :                 DEBUG(0, ("stat failed on file '%s': %s\n",
     160             :                          fname, strerror(errno)));
     161           0 :                 return false;
     162             :         }
     163             : 
     164          50 :         if (pst->st_uid != uid && !uid_wrapper_enabled()) {
     165           0 :                 DEBUG(0, ("invalid ownership of file '%s': "
     166             :                          "owned by uid %u, should be %u\n",
     167             :                          fname, (unsigned int)pst->st_uid,
     168             :                          (unsigned int)uid));
     169           0 :                 return false;
     170             :         }
     171             : 
     172          50 :         if ((pst->st_mode & 0777) != file_perms) {
     173           0 :                 DEBUG(0, ("invalid permissions on file "
     174             :                          "'%s': has 0%o should be 0%o\n", fname,
     175             :                          (unsigned int)(pst->st_mode & 0777),
     176             :                          (unsigned int)file_perms));
     177           0 :                 return false;
     178             :         }
     179             : 
     180          50 :         return true;
     181             : }
     182             : 
     183             : /**
     184             :  Check if a directory exists.
     185             : **/
     186             : 
     187         166 : _PUBLIC_ bool directory_exist(const char *dname)
     188             : {
     189             :         struct stat st;
     190             :         bool ret;
     191             : 
     192         166 :         if (stat(dname,&st) != 0) {
     193          55 :                 return false;
     194             :         }
     195             : 
     196         111 :         ret = S_ISDIR(st.st_mode);
     197         111 :         if(!ret)
     198           0 :                 errno = ENOTDIR;
     199         111 :         return ret;
     200             : }
     201             : 
     202             : /**
     203             :  * Try to create the specified directory if it didn't exist.
     204             :  * A symlink to a directory is also accepted as a valid existing directory.
     205             :  *
     206             :  * @retval true if the directory already existed
     207             :  * or was successfully created.
     208             :  */
     209      778133 : _PUBLIC_ bool directory_create_or_exist(const char *dname,
     210             :                                         mode_t dir_perms)
     211             : {
     212             :         int ret;
     213             :         mode_t old_umask;
     214             : 
     215             :         /* Create directory */
     216      778133 :         old_umask = umask(0);
     217      778133 :         ret = mkdir(dname, dir_perms);
     218      778133 :         if (ret == -1 && errno != EEXIST) {
     219          14 :                 int dbg_level = geteuid() == 0 ? DBGLVL_ERR : DBGLVL_NOTICE;
     220             : 
     221          14 :                 DBG_PREFIX(dbg_level,
     222             :                            ("mkdir failed on directory %s: %s\n",
     223             :                             dname,
     224             :                             strerror(errno)));
     225          14 :                 umask(old_umask);
     226          14 :                 return false;
     227             :         }
     228      778119 :         umask(old_umask);
     229             : 
     230      778119 :         if (ret != 0 && errno == EEXIST) {
     231             :                 struct stat sbuf;
     232             : 
     233      777211 :                 ret = lstat(dname, &sbuf);
     234      777211 :                 if (ret != 0) {
     235           0 :                         return false;
     236             :                 }
     237             : 
     238      777211 :                 if (S_ISDIR(sbuf.st_mode)) {
     239      777211 :                         return true;
     240             :                 }
     241             : 
     242           0 :                 if (S_ISLNK(sbuf.st_mode)) {
     243           0 :                         ret = stat(dname, &sbuf);
     244           0 :                         if (ret != 0) {
     245           0 :                                 return false;
     246             :                         }
     247             : 
     248           0 :                         if (S_ISDIR(sbuf.st_mode)) {
     249           0 :                                 return true;
     250             :                         }
     251             :                 }
     252             : 
     253           0 :                 return false;
     254             :         }
     255             : 
     256         908 :         return true;
     257             : }
     258             : 
     259           0 : _PUBLIC_ bool directory_create_or_exists_recursive(
     260             :                 const char *dname,
     261             :                 mode_t dir_perms)
     262             : {
     263             :         bool ok;
     264             : 
     265           0 :         ok = directory_create_or_exist(dname, dir_perms);
     266           0 :         if (!ok) {
     267           0 :                 if (!directory_exist(dname)) {
     268           0 :                         char tmp[PATH_MAX] = {0};
     269           0 :                         char *parent = NULL;
     270             :                         size_t n;
     271             : 
     272             :                         /* Use the null context */
     273           0 :                         n = strlcpy(tmp, dname, sizeof(tmp));
     274           0 :                         if (n < strlen(dname)) {
     275           0 :                                 DBG_ERR("Path too long!\n");
     276           0 :                                 return false;
     277             :                         }
     278             : 
     279           0 :                         parent = dirname(tmp);
     280           0 :                         if (parent == NULL) {
     281           0 :                                 DBG_ERR("Failed to create dirname!\n");
     282           0 :                                 return false;
     283             :                         }
     284             : 
     285           0 :                         ok = directory_create_or_exists_recursive(parent,
     286             :                                                                   dir_perms);
     287           0 :                         if (!ok) {
     288           0 :                                 return false;
     289             :                         }
     290             : 
     291           0 :                         ok = directory_create_or_exist(dname, dir_perms);
     292             :                 }
     293             :         }
     294             : 
     295           0 :         return ok;
     296             : }
     297             : 
     298             : /**
     299             :  * @brief Try to create a specified directory if it doesn't exist.
     300             :  *
     301             :  * The function creates a directory with the given uid and permissions if it
     302             :  * doesn't exist. If it exists it makes sure the uid and permissions are
     303             :  * correct and it will fail if they are different.
     304             :  *
     305             :  * @param[in]  dname  The directory to create.
     306             :  *
     307             :  * @param[in]  uid    The uid the directory needs to belong too.
     308             :  *
     309             :  * @param[in]  dir_perms  The expected permissions of the directory.
     310             :  *
     311             :  * @return True on success, false on error.
     312             :  */
     313      453586 : _PUBLIC_ bool directory_create_or_exist_strict(const char *dname,
     314             :                                                uid_t uid,
     315             :                                                mode_t dir_perms)
     316             : {
     317             :         struct stat st;
     318             :         bool ok;
     319             :         int rc;
     320             : 
     321      453586 :         ok = directory_create_or_exist(dname, dir_perms);
     322      453586 :         if (!ok) {
     323          14 :                 return false;
     324             :         }
     325             : 
     326      453572 :         rc = lstat(dname, &st);
     327      453572 :         if (rc == -1) {
     328           0 :                 DEBUG(0, ("lstat failed on created directory %s: %s\n",
     329             :                           dname, strerror(errno)));
     330           0 :                 return false;
     331             :         }
     332             : 
     333             :         /* Check ownership and permission on existing directory */
     334      453572 :         if (!S_ISDIR(st.st_mode)) {
     335           0 :                 DEBUG(0, ("directory %s isn't a directory\n",
     336             :                         dname));
     337           0 :                 return false;
     338             :         }
     339      453572 :         if (st.st_uid != uid && !uid_wrapper_enabled()) {
     340           0 :                 DBG_NOTICE("invalid ownership on directory "
     341             :                           "%s\n", dname);
     342           0 :                 return false;
     343             :         }
     344      453572 :         if ((st.st_mode & 0777) != dir_perms) {
     345           0 :                 DEBUG(0, ("invalid permissions on directory "
     346             :                           "'%s': has 0%o should be 0%o\n", dname,
     347             :                           (unsigned int)(st.st_mode & 0777), (unsigned int)dir_perms));
     348           0 :                 return false;
     349             :         }
     350             : 
     351      453572 :         return true;
     352             : }
     353             : 
     354             : 
     355             : /**
     356             :  Sleep for a specified number of milliseconds.
     357             : **/
     358             : 
     359         719 : _PUBLIC_ void smb_msleep(unsigned int t)
     360             : {
     361         719 :         sys_poll_intr(NULL, 0, t);
     362         719 : }
     363             : 
     364             : /**
     365             :  Get my own name, return in talloc'ed storage.
     366             : **/
     367             : 
     368       17651 : _PUBLIC_ char *get_myname(TALLOC_CTX *ctx)
     369             : {
     370             :         char *p;
     371             :         char hostname[HOST_NAME_MAX];
     372             : 
     373             :         /* get my host name */
     374       17651 :         if (gethostname(hostname, sizeof(hostname)) == -1) {
     375           0 :                 DEBUG(0,("gethostname failed\n"));
     376           0 :                 return NULL;
     377             :         }
     378             : 
     379             :         /* Ensure null termination. */
     380       17651 :         hostname[sizeof(hostname)-1] = '\0';
     381             : 
     382             :         /* split off any parts after an initial . */
     383       17651 :         p = strchr_m(hostname, '.');
     384       17651 :         if (p) {
     385       10667 :                 *p = 0;
     386             :         }
     387             : 
     388       17651 :         return talloc_strdup(ctx, hostname);
     389             : }
     390             : 
     391             : /**
     392             :  Check if a process exists. Does this work on all unixes?
     393             : **/
     394             : 
     395         388 : _PUBLIC_ bool process_exists_by_pid(pid_t pid)
     396             : {
     397             :         /* Doing kill with a non-positive pid causes messages to be
     398             :          * sent to places we don't want. */
     399         388 :         if (pid <= 0) {
     400           0 :                 return false;
     401             :         }
     402         388 :         return(kill(pid,0) == 0 || errno != ESRCH);
     403             : }
     404             : 
     405             : /**
     406             :  Simple routine to do POSIX file locking. Cruft in NFS and 64->32 bit mapping
     407             :  is dealt with in posix.c
     408             : **/
     409             : 
     410          29 : _PUBLIC_ bool fcntl_lock(int fd, int op, off_t offset, off_t count, int type)
     411             : {
     412             :         struct flock lock;
     413             :         int ret;
     414             : 
     415          29 :         DEBUG(8,("fcntl_lock %d %d %.0f %.0f %d\n",fd,op,(double)offset,(double)count,type));
     416             : 
     417          29 :         lock.l_type = type;
     418          29 :         lock.l_whence = SEEK_SET;
     419          29 :         lock.l_start = offset;
     420          29 :         lock.l_len = count;
     421          29 :         lock.l_pid = 0;
     422             : 
     423          29 :         ret = fcntl(fd,op,&lock);
     424             : 
     425          29 :         if (ret == -1 && errno != 0)
     426          19 :                 DEBUG(3,("fcntl_lock: fcntl lock gave errno %d (%s)\n",errno,strerror(errno)));
     427             : 
     428             :         /* a lock query */
     429          29 :         if (op == F_GETLK) {
     430           0 :                 if ((ret != -1) &&
     431           0 :                                 (lock.l_type != F_UNLCK) && 
     432           0 :                                 (lock.l_pid != 0) && 
     433           0 :                                 (lock.l_pid != tevent_cached_getpid())) {
     434           0 :                         DEBUG(3,("fcntl_lock: fd %d is locked by pid %d\n",fd,(int)lock.l_pid));
     435           0 :                         return true;
     436             :                 }
     437             : 
     438             :                 /* it must be not locked or locked by me */
     439           0 :                 return false;
     440             :         }
     441             : 
     442             :         /* a lock set or unset */
     443          29 :         if (ret == -1) {
     444          19 :                 DEBUG(3,("fcntl_lock: lock failed at offset %.0f count %.0f op %d type %d (%s)\n",
     445             :                         (double)offset,(double)count,op,type,strerror(errno)));
     446          19 :                 return false;
     447             :         }
     448             : 
     449             :         /* everything went OK */
     450          10 :         DEBUG(8,("fcntl_lock: Lock call successful\n"));
     451             : 
     452          10 :         return true;
     453             : }
     454             : 
     455             : struct debug_channel_level {
     456             :         int channel;
     457             :         int level;
     458             : };
     459             : 
     460           0 : static void debugadd_channel_cb(const char *buf, void *private_data)
     461             : {
     462           0 :         struct debug_channel_level *dcl =
     463             :                 (struct debug_channel_level *)private_data;
     464             : 
     465           0 :         DEBUGADDC(dcl->channel, dcl->level,("%s", buf));
     466           0 : }
     467             : 
     468      101666 : static void debugadd_cb(const char *buf, void *private_data)
     469             : {
     470      101666 :         int *plevel = (int *)private_data;
     471      101666 :         DEBUGADD(*plevel, ("%s", buf));
     472      101666 : }
     473             : 
     474    13041350 : void print_asc_cb(const uint8_t *buf, int len,
     475             :                   void (*cb)(const char *buf, void *private_data),
     476             :                   void *private_data)
     477             : {
     478             :         int i;
     479             :         char s[2];
     480    13041350 :         s[1] = 0;
     481             : 
     482    26082700 :         for (i=0; i<len; i++) {
     483    13041350 :                 s[0] = isprint(buf[i]) ? buf[i] : '.';
     484    13041350 :                 cb(s, private_data);
     485             :         }
     486    13041350 : }
     487             : 
     488           0 : void print_asc(int level, const uint8_t *buf,int len)
     489             : {
     490           0 :         print_asc_cb(buf, len, debugadd_cb, &level);
     491           0 : }
     492             : 
     493      905488 : static void dump_data_block16(const char *prefix, size_t idx,
     494             :                               const uint8_t *buf, size_t len,
     495             :                               void (*cb)(const char *buf, void *private_data),
     496             :                               void *private_data)
     497             : {
     498             :         char tmp[16];
     499             :         size_t i;
     500             : 
     501      905488 :         SMB_ASSERT(len >= 0 && len <= 16);
     502             : 
     503      905488 :         snprintf(tmp, sizeof(tmp), "%s[%04zX]", prefix, idx);
     504      905488 :         cb(tmp, private_data);
     505             : 
     506    15393296 :         for (i=0; i<16; i++) {
     507    14487808 :                 if (i == 8) {
     508      905488 :                         cb("  ", private_data);
     509             :                 }
     510    14487808 :                 if (i < len) {
     511    13041350 :                         snprintf(tmp, sizeof(tmp), " %02X", (int)buf[i]);
     512             :                 } else {
     513     1446458 :                         snprintf(tmp, sizeof(tmp), "   ");
     514             :                 }
     515    14487808 :                 cb(tmp, private_data);
     516             :         }
     517             : 
     518      905488 :         cb("   ", private_data);
     519             : 
     520      905488 :         if (len == 0) {
     521           0 :                 cb("EMPTY   BLOCK\n", private_data);
     522           0 :                 return;
     523             :         }
     524             : 
     525    13946838 :         for (i=0; i<len; i++) {
     526    13041350 :                 if (i == 8) {
     527      787070 :                         cb(" ", private_data);
     528             :                 }
     529    13041350 :                 print_asc_cb(&buf[i], 1, cb, private_data);
     530             :         }
     531             : 
     532      905488 :         cb("\n", private_data);
     533             : }
     534             : 
     535             : /**
     536             :  * Write dump of binary data to a callback
     537             :  */
     538      202958 : void dump_data_cb(const uint8_t *buf, int len,
     539             :                   bool omit_zero_bytes,
     540             :                   void (*cb)(const char *buf, void *private_data),
     541             :                   void *private_data)
     542             : {
     543      202958 :         int i=0;
     544      202958 :         bool skipped = false;
     545             : 
     546      202958 :         if (len<=0) return;
     547             : 
     548     1128725 :         for (i=0;i<len;i+=16) {
     549      925767 :                 size_t remaining_len = len - i;
     550      925767 :                 size_t this_len = MIN(remaining_len, 16);
     551      925767 :                 const uint8_t *this_buf = &buf[i];
     552             : 
     553      925767 :                 if ((omit_zero_bytes == true) &&
     554      722809 :                     (i > 0) && (remaining_len > 16) &&
     555      622949 :                     (this_len == 16) && all_zero(this_buf, 16))
     556             :                 {
     557       20279 :                         if (!skipped) {
     558       16022 :                                 cb("skipping zero buffer bytes\n",
     559             :                                    private_data);
     560       16022 :                                 skipped = true;
     561             :                         }
     562       20279 :                         continue;
     563             :                 }
     564             : 
     565      905488 :                 skipped = false;
     566      905488 :                 dump_data_block16("", i, this_buf, this_len,
     567             :                                   cb, private_data);
     568             :         }
     569             : }
     570             : 
     571             : /**
     572             :  * Write dump of binary data to the log file.
     573             :  *
     574             :  * The data is only written if the log level is at least level.
     575             :  */
     576     5774518 : _PUBLIC_ void dump_data(int level, const uint8_t *buf, int len)
     577             : {
     578     5774518 :         if (!DEBUGLVL(level)) {
     579     5771402 :                 return;
     580             :         }
     581        3116 :         dump_data_cb(buf, len, false, debugadd_cb, &level);
     582             : }
     583             : 
     584             : /**
     585             :  * Write dump of binary data to the log file.
     586             :  *
     587             :  * The data is only written if the log level is at least level for
     588             :  * debug class dbgc_class.
     589             :  */
     590        2541 : _PUBLIC_ void dump_data_dbgc(int dbgc_class, int level, const uint8_t *buf, int len)
     591             : {
     592        2541 :         struct debug_channel_level dcl = { dbgc_class, level };
     593             : 
     594        2541 :         if (!DEBUGLVLC(dbgc_class, level)) {
     595        2541 :                 return;
     596             :         }
     597           0 :         dump_data_cb(buf, len, false, debugadd_channel_cb, &dcl);
     598             : }
     599             : 
     600             : /**
     601             :  * Write dump of binary data to the log file.
     602             :  *
     603             :  * The data is only written if the log level is at least level.
     604             :  * 16 zero bytes in a row are omitted
     605             :  */
     606           0 : _PUBLIC_ void dump_data_skip_zeros(int level, const uint8_t *buf, int len)
     607             : {
     608           0 :         if (!DEBUGLVL(level)) {
     609           0 :                 return;
     610             :         }
     611           0 :         dump_data_cb(buf, len, true, debugadd_cb, &level);
     612             : }
     613             : 
     614           0 : static void fprintf_cb(const char *buf, void *private_data)
     615             : {
     616           0 :         FILE *f = (FILE *)private_data;
     617           0 :         fprintf(f, "%s", buf);
     618           0 : }
     619             : 
     620           0 : void dump_data_file(const uint8_t *buf, int len, bool omit_zero_bytes,
     621             :                     FILE *f)
     622             : {
     623           0 :         dump_data_cb(buf, len, omit_zero_bytes, fprintf_cb, f);
     624           0 : }
     625             : 
     626             : /**
     627             :  * Write dump of compared binary data to a callback
     628             :  */
     629           0 : void dump_data_diff_cb(const uint8_t *buf1, size_t len1,
     630             :                        const uint8_t *buf2, size_t len2,
     631             :                        bool omit_zero_bytes,
     632             :                        void (*cb)(const char *buf, void *private_data),
     633             :                        void *private_data)
     634             : {
     635           0 :         size_t len = MAX(len1, len2);
     636             :         size_t i;
     637           0 :         bool skipped = false;
     638             : 
     639           0 :         for (i=0; i<len; i+=16) {
     640           0 :                 size_t remaining_len = len - i;
     641           0 :                 size_t remaining_len1 = 0;
     642           0 :                 size_t this_len1 = 0;
     643           0 :                 const uint8_t *this_buf1 = NULL;
     644           0 :                 size_t remaining_len2 = 0;
     645           0 :                 size_t this_len2 = 0;
     646           0 :                 const uint8_t *this_buf2 = NULL;
     647             : 
     648           0 :                 if (i < len1) {
     649           0 :                         remaining_len1 = len1 - i;
     650           0 :                         this_len1 = MIN(remaining_len1, 16);
     651           0 :                         this_buf1 = &buf1[i];
     652             :                 }
     653           0 :                 if (i < len2) {
     654           0 :                         remaining_len2 = len2 - i;
     655           0 :                         this_len2 = MIN(remaining_len2, 16);
     656           0 :                         this_buf2 = &buf2[i];
     657             :                 }
     658             : 
     659           0 :                 if ((omit_zero_bytes == true) &&
     660           0 :                     (i > 0) && (remaining_len > 16) &&
     661           0 :                     (this_len1 == 16) && all_zero(this_buf1, 16) &&
     662           0 :                     (this_len2 == 16) && all_zero(this_buf2, 16))
     663             :                 {
     664           0 :                         if (!skipped) {
     665           0 :                                 cb("skipping zero buffer bytes\n",
     666             :                                    private_data);
     667           0 :                                 skipped = true;
     668             :                         }
     669           0 :                         continue;
     670             :                 }
     671             : 
     672           0 :                 skipped = false;
     673             : 
     674           0 :                 if ((this_len1 == this_len2) &&
     675           0 :                     (memcmp(this_buf1, this_buf2, this_len1) == 0))
     676             :                 {
     677           0 :                         dump_data_block16(" ", i, this_buf1, this_len1,
     678             :                                           cb, private_data);
     679           0 :                         continue;
     680             :                 }
     681             : 
     682           0 :                 dump_data_block16("-", i, this_buf1, this_len1,
     683             :                                   cb, private_data);
     684           0 :                 dump_data_block16("+", i, this_buf2, this_len2,
     685             :                                   cb, private_data);
     686             :         }
     687           0 : }
     688             : 
     689           0 : _PUBLIC_ void dump_data_diff(int dbgc_class, int level,
     690             :                              bool omit_zero_bytes,
     691             :                              const uint8_t *buf1, size_t len1,
     692             :                              const uint8_t *buf2, size_t len2)
     693             : {
     694           0 :         struct debug_channel_level dcl = { dbgc_class, level };
     695             : 
     696           0 :         if (!DEBUGLVLC(dbgc_class, level)) {
     697           0 :                 return;
     698             :         }
     699           0 :         dump_data_diff_cb(buf1, len1, buf2, len2, true, debugadd_channel_cb, &dcl);
     700             : }
     701             : 
     702           0 : _PUBLIC_ void dump_data_file_diff(FILE *f,
     703             :                                   bool omit_zero_bytes,
     704             :                                   const uint8_t *buf1, size_t len1,
     705             :                                   const uint8_t *buf2, size_t len2)
     706             : {
     707           0 :         dump_data_diff_cb(buf1, len1, buf2, len2, omit_zero_bytes, fprintf_cb, f);
     708           0 : }
     709             : 
     710             : /**
     711             :  malloc that aborts with smb_panic on fail or zero size.
     712             : **/
     713             : 
     714       23593 : _PUBLIC_ void *smb_xmalloc(size_t size)
     715             : {
     716             :         void *p;
     717       23593 :         if (size == 0)
     718           0 :                 smb_panic("smb_xmalloc: called with zero size.\n");
     719       23593 :         if ((p = malloc(size)) == NULL)
     720           0 :                 smb_panic("smb_xmalloc: malloc fail.\n");
     721       23593 :         return p;
     722             : }
     723             : 
     724             : /**
     725             :  Memdup with smb_panic on fail.
     726             : **/
     727             : 
     728       23593 : _PUBLIC_ void *smb_xmemdup(const void *p, size_t size)
     729             : {
     730             :         void *p2;
     731       23593 :         p2 = smb_xmalloc(size);
     732       23593 :         memcpy(p2, p, size);
     733       23593 :         return p2;
     734             : }
     735             : 
     736             : /**
     737             :  strdup that aborts on malloc fail.
     738             : **/
     739             : 
     740      562519 : char *smb_xstrdup(const char *s)
     741             : {
     742             : #if defined(PARANOID_MALLOC_CHECKER)
     743             : #ifdef strdup
     744             : #undef strdup
     745             : #endif
     746             : #endif
     747             : 
     748             : #ifndef HAVE_STRDUP
     749             : #define strdup rep_strdup
     750             : #endif
     751             : 
     752      562519 :         char *s1 = strdup(s);
     753             : #if defined(PARANOID_MALLOC_CHECKER)
     754             : #ifdef strdup
     755             : #undef strdup
     756             : #endif
     757             : #define strdup(s) __ERROR_DONT_USE_STRDUP_DIRECTLY
     758             : #endif
     759      562519 :         if (!s1) {
     760           0 :                 smb_panic("smb_xstrdup: malloc failed");
     761             :         }
     762      562519 :         return s1;
     763             : 
     764             : }
     765             : 
     766             : /**
     767             :  strndup that aborts on malloc fail.
     768             : **/
     769             : 
     770        2550 : char *smb_xstrndup(const char *s, size_t n)
     771             : {
     772             : #if defined(PARANOID_MALLOC_CHECKER)
     773             : #ifdef strndup
     774             : #undef strndup
     775             : #endif
     776             : #endif
     777             : 
     778             : #if (defined(BROKEN_STRNDUP) || !defined(HAVE_STRNDUP))
     779             : #undef HAVE_STRNDUP
     780             : #define strndup rep_strndup
     781             : #endif
     782             : 
     783        2550 :         char *s1 = strndup(s, n);
     784             : #if defined(PARANOID_MALLOC_CHECKER)
     785             : #ifdef strndup
     786             : #undef strndup
     787             : #endif
     788             : #define strndup(s,n) __ERROR_DONT_USE_STRNDUP_DIRECTLY
     789             : #endif
     790        2550 :         if (!s1) {
     791           0 :                 smb_panic("smb_xstrndup: malloc failed");
     792             :         }
     793        2550 :         return s1;
     794             : }
     795             : 
     796             : 
     797             : 
     798             : /**
     799             :  Like strdup but for memory.
     800             : **/
     801             : 
     802       22023 : _PUBLIC_ void *smb_memdup(const void *p, size_t size)
     803             : {
     804             :         void *p2;
     805       22023 :         if (size == 0)
     806           4 :                 return NULL;
     807       22019 :         p2 = malloc(size);
     808       22019 :         if (!p2)
     809           0 :                 return NULL;
     810       22019 :         memcpy(p2, p, size);
     811       22019 :         return p2;
     812             : }
     813             : 
     814             : /**
     815             :  * Write a password to the log file.
     816             :  *
     817             :  * @note Only actually does something if DEBUG_PASSWORD was defined during 
     818             :  * compile-time.
     819             :  */
     820     3177490 : _PUBLIC_ void dump_data_pw(const char *msg, const uint8_t * data, size_t len)
     821             : {
     822             : #ifdef DEBUG_PASSWORD
     823     3177490 :         DEBUG(11, ("%s", msg));
     824     3177490 :         if (data != NULL && len > 0)
     825             :         {
     826     3177135 :                 dump_data(11, data, len);
     827             :         }
     828             : #endif
     829     3177490 : }
     830             : 
     831             : 
     832             : /**
     833             :  * see if a range of memory is all zero. A NULL pointer is considered
     834             :  * to be all zero 
     835             :  */
     836    12060542 : _PUBLIC_ bool all_zero(const uint8_t *ptr, size_t size)
     837             : {
     838             :         size_t i;
     839    12060542 :         if (!ptr) return true;
     840   226227615 :         for (i=0;i<size;i++) {
     841   215072027 :                 if (ptr[i]) return false;
     842             :         }
     843    11155588 :         return true;
     844             : }
     845             : 
     846             : /**
     847             :   realloc an array, checking for integer overflow in the array size
     848             : */
     849       23000 : _PUBLIC_ void *realloc_array(void *ptr, size_t el_size, unsigned count, bool free_on_fail)
     850             : {
     851             : #define MAX_MALLOC_SIZE 0x7fffffff
     852       23000 :         if (count == 0 ||
     853       23000 :             count >= MAX_MALLOC_SIZE/el_size) {
     854           0 :                 if (free_on_fail)
     855           0 :                         SAFE_FREE(ptr);
     856           0 :                 return NULL;
     857             :         }
     858       23000 :         if (!ptr) {
     859       21528 :                 return malloc(el_size * count);
     860             :         }
     861        1472 :         return realloc(ptr, el_size * count);
     862             : }
     863             : 
     864             : /****************************************************************************
     865             :  Type-safe malloc.
     866             : ****************************************************************************/
     867             : 
     868       20240 : void *malloc_array(size_t el_size, unsigned int count)
     869             : {
     870       20240 :         return realloc_array(NULL, el_size, count, false);
     871             : }
     872             : 
     873             : /****************************************************************************
     874             :  Type-safe memalign
     875             : ****************************************************************************/
     876             : 
     877           0 : void *memalign_array(size_t el_size, size_t align, unsigned int count)
     878             : {
     879           0 :         if (el_size == 0 || count >= MAX_MALLOC_SIZE/el_size) {
     880           0 :                 return NULL;
     881             :         }
     882             : 
     883           0 :         return memalign(align, el_size*count);
     884             : }
     885             : 
     886             : /****************************************************************************
     887             :  Type-safe calloc.
     888             : ****************************************************************************/
     889             : 
     890           0 : void *calloc_array(size_t size, size_t nmemb)
     891             : {
     892           0 :         if (nmemb >= MAX_MALLOC_SIZE/size) {
     893           0 :                 return NULL;
     894             :         }
     895           0 :         if (size == 0 || nmemb == 0) {
     896           0 :                 return NULL;
     897             :         }
     898           0 :         return calloc(nmemb, size);
     899             : }
     900             : 
     901             : /**
     902             :  Trim the specified elements off the front and back of a string.
     903             : **/
     904      250552 : _PUBLIC_ bool trim_string(char *s, const char *front, const char *back)
     905             : {
     906      250552 :         bool ret = false;
     907             :         size_t front_len;
     908             :         size_t back_len;
     909             :         size_t len;
     910             : 
     911             :         /* Ignore null or empty strings. */
     912      250552 :         if (!s || (s[0] == '\0')) {
     913           0 :                 return false;
     914             :         }
     915      250552 :         len = strlen(s);
     916             : 
     917      250552 :         front_len       = front? strlen(front) : 0;
     918      250552 :         back_len        = back? strlen(back) : 0;
     919             : 
     920      250552 :         if (front_len) {
     921           2 :                 size_t front_trim = 0;
     922             : 
     923           4 :                 while (strncmp(s+front_trim, front, front_len)==0) {
     924           2 :                         front_trim += front_len;
     925             :                 }
     926           2 :                 if (front_trim > 0) {
     927             :                         /* Must use memmove here as src & dest can
     928             :                          * easily overlap. Found by valgrind. JRA. */
     929           2 :                         memmove(s, s+front_trim, (len-front_trim)+1);
     930           2 :                         len -= front_trim;
     931           2 :                         ret=true;
     932             :                 }
     933             :         }
     934             : 
     935      250552 :         if (back_len) {
     936      255245 :                 while ((len >= back_len) && strncmp(s+len-back_len,back,back_len)==0) {
     937        4693 :                         s[len-back_len]='\0';
     938        4693 :                         len -= back_len;
     939        4693 :                         ret=true;
     940             :                 }
     941             :         }
     942      250552 :         return ret;
     943             : }
     944             : 
     945             : /**
     946             :  Find the number of 'c' chars in a string
     947             : **/
     948        3380 : _PUBLIC_ _PURE_ size_t count_chars(const char *s, char c)
     949             : {
     950        3380 :         size_t count = 0;
     951             : 
     952      123977 :         while (*s) {
     953      120597 :                 if (*s == c) count++;
     954      120597 :                 s ++;
     955             :         }
     956             : 
     957        3380 :         return count;
     958             : }
     959             : 
     960             : /**
     961             :  * Routine to get hex characters and turn them into a byte array.
     962             :  * the array can be variable length.
     963             :  * -  "0xnn" or "0Xnn" is specially catered for.
     964             :  * - The first non-hex-digit character (apart from possibly leading "0x"
     965             :  *   finishes the conversion and skips the rest of the input.
     966             :  * - A single hex-digit character at the end of the string is skipped.
     967             :  *
     968             :  * valid examples: "0A5D15"; "0x123456"
     969             :  */
     970     4030873 : _PUBLIC_ size_t strhex_to_str(char *p, size_t p_len, const char *strhex, size_t strhex_len)
     971             : {
     972     4030873 :         size_t i = 0;
     973     4030873 :         size_t num_chars = 0;
     974             : 
     975             :         /* skip leading 0x prefix */
     976     4030873 :         if (strncasecmp(strhex, "0x", 2) == 0) {
     977           0 :                 i += 2; /* skip two chars */
     978             :         }
     979             : 
     980   135291109 :         while ((i < strhex_len) && (num_chars < p_len)) {
     981   131260236 :                 bool ok = hex_byte(&strhex[i], (uint8_t *)&p[num_chars]);
     982   131260236 :                 if (!ok) {
     983           0 :                         break;
     984             :                 }
     985   131260236 :                 i += 2;
     986   131260236 :                 num_chars += 1;
     987             :         }
     988             : 
     989     4030873 :         return num_chars;
     990             : }
     991             : 
     992             : /**
     993             :  * Parse a hex string and return a data blob.
     994             :  */
     995      192221 : _PUBLIC_ DATA_BLOB strhex_to_data_blob(TALLOC_CTX *mem_ctx, const char *strhex)
     996             : {
     997      192221 :         DATA_BLOB ret_blob = data_blob_talloc(mem_ctx, NULL, strlen(strhex)/2+1);
     998             : 
     999      192221 :         ret_blob.length = strhex_to_str((char *)ret_blob.data, ret_blob.length,
    1000             :                                         strhex,
    1001             :                                         strlen(strhex));
    1002             : 
    1003      192221 :         return ret_blob;
    1004             : }
    1005             : 
    1006             : /**
    1007             :  * Parse a hex dump and return a data blob. Hex dump is structured as 
    1008             :  * is generated from dump_data_cb() elsewhere in this file
    1009             :  * 
    1010             :  */
    1011           0 : _PUBLIC_ DATA_BLOB hexdump_to_data_blob(TALLOC_CTX *mem_ctx, const char *hexdump, size_t hexdump_len)
    1012             : {
    1013           0 :         DATA_BLOB ret_blob = { 0 };
    1014           0 :         size_t i = 0;
    1015           0 :         size_t char_count = 0;
    1016             :         /* hexdump line length is 77 chars long. We then use the ASCII representation of the bytes
    1017             :          * at the end of the final line to calculate how many are in that line, minus the extra space
    1018             :          * and newline. */
    1019           0 :         size_t hexdump_byte_count = (16 * (hexdump_len / 77));
    1020           0 :         if (hexdump_len % 77) {
    1021           0 :                 hexdump_byte_count += ((hexdump_len % 77) - 59 - 2);
    1022             :         }
    1023             :         
    1024           0 :         ret_blob = data_blob_talloc(mem_ctx, NULL, hexdump_byte_count+1);
    1025           0 :         for (; i+1 < hexdump_len && hexdump[i] != 0 && hexdump[i+1] != 0; i++) {
    1026           0 :                 if ((i%77) == 0) 
    1027           0 :                         i += 7; /* Skip the offset at the start of the line */
    1028           0 :                 if ((i%77) < 56) { /* position 56 is after both hex chunks */
    1029           0 :                         if (hexdump[i] != ' ') {
    1030           0 :                                 char_count += strhex_to_str((char *)&ret_blob.data[char_count],
    1031             :                                                             hexdump_byte_count - char_count,
    1032             :                                                             &hexdump[i], 2);
    1033           0 :                                 i += 2;
    1034             :                         } else {
    1035           0 :                                 i++;
    1036             :                         }
    1037             :                 } else {
    1038           0 :                         i++;
    1039             :                 }
    1040             :         }
    1041           0 :         ret_blob.length = char_count;
    1042             :         
    1043           0 :         return ret_blob;
    1044             : }
    1045             : 
    1046             : /**
    1047             :  * Print a buf in hex. Assumes dst is at least (srclen*2)+1 large.
    1048             :  */
    1049        6026 : _PUBLIC_ void hex_encode_buf(char *dst, const uint8_t *src, size_t srclen)
    1050             : {
    1051             :         size_t i;
    1052      156925 :         for (i=0; i<srclen; i++) {
    1053      150899 :                 snprintf(dst + i*2, 3, "%02X", src[i]);
    1054             :         }
    1055             :         /*
    1056             :          * Ensure 0-termination for 0-length buffers
    1057             :          */
    1058        6026 :         dst[srclen*2] = '\0';
    1059        6026 : }
    1060             : 
    1061             : /**
    1062             :  * talloc version of hex_encode_buf()
    1063             :  */
    1064        6022 : _PUBLIC_ char *hex_encode_talloc(TALLOC_CTX *mem_ctx, const unsigned char *buff_in, size_t len)
    1065             : {
    1066             :         char *hex_buffer;
    1067             : 
    1068        6022 :         hex_buffer = talloc_array(mem_ctx, char, (len*2)+1);
    1069        6022 :         if (!hex_buffer) {
    1070           0 :                 return NULL;
    1071             :         }
    1072        6022 :         hex_encode_buf(hex_buffer, buff_in, len);
    1073        6022 :         talloc_set_name_const(hex_buffer, hex_buffer);
    1074        6022 :         return hex_buffer;
    1075             : }
    1076             : 
    1077             : /**
    1078             :   varient of strcmp() that handles NULL ptrs
    1079             : **/
    1080      158233 : _PUBLIC_ int strcmp_safe(const char *s1, const char *s2)
    1081             : {
    1082      158233 :         if (s1 == s2) {
    1083         613 :                 return 0;
    1084             :         }
    1085      157620 :         if (s1 == NULL || s2 == NULL) {
    1086           0 :                 return s1?-1:1;
    1087             :         }
    1088      157620 :         return strcmp(s1, s2);
    1089             : }
    1090             : 
    1091             : 
    1092             : /**
    1093             : return the number of bytes occupied by a buffer in ASCII format
    1094             : the result includes the null termination
    1095             : limited by 'n' bytes
    1096             : **/
    1097     1114658 : _PUBLIC_ size_t ascii_len_n(const char *src, size_t n)
    1098             : {
    1099             :         size_t len;
    1100             : 
    1101     1114658 :         len = strnlen(src, n);
    1102     1114658 :         if (len+1 <= n) {
    1103     1114658 :                 len += 1;
    1104             :         }
    1105             : 
    1106     1114658 :         return len;
    1107             : }
    1108             : 
    1109     2178777 : _PUBLIC_ bool mem_equal_const_time(const void *s1, const void *s2, size_t n)
    1110             : {
    1111             :         /* Ensure we won't overflow the unsigned index used by gnutls. */
    1112     2178777 :         SMB_ASSERT(n <= UINT_MAX);
    1113             : 
    1114     2178777 :         return gnutls_memcmp(s1, s2, n) == 0;
    1115             : }
    1116             : 
    1117             : struct anonymous_shared_header {
    1118             :         union {
    1119             :                 size_t length;
    1120             :                 uint8_t pad[16];
    1121             :         } u;
    1122             : };
    1123             : 
    1124             : /* Map a shared memory buffer of at least nelem counters. */
    1125        1026 : void *anonymous_shared_allocate(size_t orig_bufsz)
    1126             : {
    1127             :         void *ptr;
    1128             :         void *buf;
    1129        1026 :         size_t pagesz = getpagesize();
    1130             :         size_t pagecnt;
    1131        1026 :         size_t bufsz = orig_bufsz;
    1132             :         struct anonymous_shared_header *hdr;
    1133             : 
    1134        1026 :         bufsz += sizeof(*hdr);
    1135             : 
    1136             :         /* round up to full pages */
    1137        1026 :         pagecnt = bufsz / pagesz;
    1138        1026 :         if (bufsz % pagesz) {
    1139        1026 :                 pagecnt += 1;
    1140             :         }
    1141        1026 :         bufsz = pagesz * pagecnt;
    1142             : 
    1143        1026 :         if (orig_bufsz >= bufsz) {
    1144             :                 /* integer wrap */
    1145           0 :                 errno = ENOMEM;
    1146           0 :                 return NULL;
    1147             :         }
    1148             : 
    1149             : #ifdef MAP_ANON
    1150             :         /* BSD */
    1151        1026 :         buf = mmap(NULL, bufsz, PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED,
    1152             :                         -1 /* fd */, 0 /* offset */);
    1153             : #else
    1154             : {
    1155             :         int saved_errno;
    1156             :         int fd;
    1157             : 
    1158             :         fd = open("/dev/zero", O_RDWR);
    1159             :         if (fd == -1) {
    1160             :                 return NULL;
    1161             :         }
    1162             : 
    1163             :         buf = mmap(NULL, bufsz, PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED,
    1164             :                    fd, 0 /* offset */);
    1165             :         saved_errno = errno;
    1166             :         close(fd);
    1167             :         errno = saved_errno;
    1168             : }
    1169             : #endif
    1170             : 
    1171        1026 :         if (buf == MAP_FAILED) {
    1172           0 :                 return NULL;
    1173             :         }
    1174             : 
    1175        1026 :         hdr = (struct anonymous_shared_header *)buf;
    1176        1026 :         hdr->u.length = bufsz;
    1177             : 
    1178        1026 :         ptr = (void *)(&hdr[1]);
    1179             : 
    1180        1026 :         return ptr;
    1181             : }
    1182             : 
    1183           0 : void *anonymous_shared_resize(void *ptr, size_t new_size, bool maymove)
    1184             : {
    1185             : #ifdef HAVE_MREMAP
    1186             :         void *buf;
    1187           0 :         size_t pagesz = getpagesize();
    1188             :         size_t pagecnt;
    1189             :         size_t bufsz;
    1190             :         struct anonymous_shared_header *hdr;
    1191           0 :         int flags = 0;
    1192             : 
    1193           0 :         if (ptr == NULL) {
    1194           0 :                 errno = EINVAL;
    1195           0 :                 return NULL;
    1196             :         }
    1197             : 
    1198           0 :         hdr = (struct anonymous_shared_header *)ptr;
    1199           0 :         hdr--;
    1200           0 :         if (hdr->u.length > (new_size + sizeof(*hdr))) {
    1201           0 :                 errno = EINVAL;
    1202           0 :                 return NULL;
    1203             :         }
    1204             : 
    1205           0 :         bufsz = new_size + sizeof(*hdr);
    1206             : 
    1207             :         /* round up to full pages */
    1208           0 :         pagecnt = bufsz / pagesz;
    1209           0 :         if (bufsz % pagesz) {
    1210           0 :                 pagecnt += 1;
    1211             :         }
    1212           0 :         bufsz = pagesz * pagecnt;
    1213             : 
    1214           0 :         if (new_size >= bufsz) {
    1215             :                 /* integer wrap */
    1216           0 :                 errno = ENOSPC;
    1217           0 :                 return NULL;
    1218             :         }
    1219             : 
    1220           0 :         if (bufsz <= hdr->u.length) {
    1221           0 :                 return ptr;
    1222             :         }
    1223             : 
    1224           0 :         if (maymove) {
    1225           0 :                 flags = MREMAP_MAYMOVE;
    1226             :         }
    1227             : 
    1228           0 :         buf = mremap(hdr, hdr->u.length, bufsz, flags);
    1229             : 
    1230           0 :         if (buf == MAP_FAILED) {
    1231           0 :                 errno = ENOSPC;
    1232           0 :                 return NULL;
    1233             :         }
    1234             : 
    1235           0 :         hdr = (struct anonymous_shared_header *)buf;
    1236           0 :         hdr->u.length = bufsz;
    1237             : 
    1238           0 :         ptr = (void *)(&hdr[1]);
    1239             : 
    1240           0 :         return ptr;
    1241             : #else
    1242             :         errno = ENOSPC;
    1243             :         return NULL;
    1244             : #endif
    1245             : }
    1246             : 
    1247        1020 : void anonymous_shared_free(void *ptr)
    1248             : {
    1249             :         struct anonymous_shared_header *hdr;
    1250             : 
    1251        1020 :         if (ptr == NULL) {
    1252           0 :                 return;
    1253             :         }
    1254             : 
    1255        1020 :         hdr = (struct anonymous_shared_header *)ptr;
    1256             : 
    1257        1020 :         hdr--;
    1258             : 
    1259        1020 :         munmap(hdr, hdr->u.length);
    1260             : }
    1261             : 
    1262             : #ifdef DEVELOPER
    1263             : /* used when you want a debugger started at a particular point in the
    1264             :    code. Mostly useful in code that runs as a child process, where
    1265             :    normal gdb attach is harder to organise.
    1266             : */
    1267           0 : void samba_start_debugger(void)
    1268             : {
    1269             :         int ready_pipe[2];
    1270             :         char c;
    1271             :         int ret;
    1272             :         pid_t pid;
    1273             : 
    1274           0 :         ret = pipe(ready_pipe);
    1275           0 :         SMB_ASSERT(ret == 0);
    1276             : 
    1277           0 :         pid = fork();
    1278           0 :         SMB_ASSERT(pid >= 0);
    1279             : 
    1280           0 :         if (pid) {
    1281           0 :                 c = 0;
    1282             : 
    1283           0 :                 ret = close(ready_pipe[0]);
    1284           0 :                 SMB_ASSERT(ret == 0);
    1285             : #if defined(HAVE_PRCTL) && defined(PR_SET_PTRACER)
    1286             :                 /*
    1287             :                  * Make sure the child process can attach a debugger.
    1288             :                  *
    1289             :                  * We don't check the error code as the debugger
    1290             :                  * will tell us if it can't attach.
    1291             :                  */
    1292           0 :                 (void)prctl(PR_SET_PTRACER, pid, 0, 0, 0);
    1293             : #endif
    1294           0 :                 ret = write(ready_pipe[1], &c, 1);
    1295           0 :                 SMB_ASSERT(ret == 1);
    1296             : 
    1297           0 :                 ret = close(ready_pipe[1]);
    1298           0 :                 SMB_ASSERT(ret == 0);
    1299             : 
    1300             :                 /* Wait for gdb to attach. */
    1301           0 :                 sleep(2);
    1302             :         } else {
    1303           0 :                 char *cmd = NULL;
    1304             : 
    1305           0 :                 ret = close(ready_pipe[1]);
    1306           0 :                 SMB_ASSERT(ret == 0);
    1307             : 
    1308           0 :                 ret = read(ready_pipe[0], &c, 1);
    1309           0 :                 SMB_ASSERT(ret == 1);
    1310             : 
    1311           0 :                 ret = close(ready_pipe[0]);
    1312           0 :                 SMB_ASSERT(ret == 0);
    1313             : 
    1314           0 :                 ret = asprintf(&cmd, "gdb --pid %u", getppid());
    1315           0 :                 SMB_ASSERT(ret != -1);
    1316             : 
    1317           0 :                 execlp("xterm", "xterm", "-e", cmd, (char *) NULL);
    1318           0 :                 smb_panic("execlp() failed");
    1319             :         }
    1320           0 : }
    1321             : #endif

Generated by: LCOV version 1.14