LCOV - code coverage report
Current view: top level - lib/util - util.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 396 557 71.1 %
Date: 2024-04-21 15:09:00 Functions: 45 54 83.3 %

          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       25389 : _PUBLIC_ const char *tmpdir(void)
      63             : {
      64           1 :         char *p;
      65       25389 :         if ((p = getenv("TMPDIR")))
      66       25389 :                 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           0 :         int fd;
      81           0 :         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      326802 : _PUBLIC_ bool file_exist(const char *fname)
     108             : {
     109        3865 :         struct stat st;
     110             : 
     111      326802 :         if (stat(fname, &st) != 0) {
     112      174097 :                 return false;
     113             :         }
     114             : 
     115      148878 :         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      251394 : _PUBLIC_ int file_modtime(const char *fname, struct timespec *mt)
     128             : {
     129      251394 :         struct stat st = {0};
     130             : 
     131      251394 :         if (stat(fname, &st) != 0) {
     132       24317 :                 return errno;
     133             :         }
     134             : 
     135      227077 :         *mt = get_mtimespec(&st);
     136      227077 :         return 0;
     137             : }
     138             : 
     139             : /**
     140             :  Check file permissions.
     141             : **/
     142             : 
     143          63 : _PUBLIC_ bool file_check_permissions(const char *fname,
     144             :                                      uid_t uid,
     145             :                                      mode_t file_perms,
     146             :                                      struct stat *pst)
     147             : {
     148           3 :         int ret;
     149           3 :         struct stat st;
     150             : 
     151          63 :         if (pst == NULL) {
     152           1 :                 pst = &st;
     153             :         }
     154             : 
     155          63 :         ZERO_STRUCTP(pst);
     156             : 
     157          63 :         ret = stat(fname, pst);
     158          63 :         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          65 :         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          63 :         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          60 :         return true;
     181             : }
     182             : 
     183             : /**
     184             :  Check if a directory exists.
     185             : **/
     186             : 
     187         262 : _PUBLIC_ bool directory_exist(const char *dname)
     188             : {
     189          12 :         struct stat st;
     190          12 :         bool ret;
     191             : 
     192         262 :         if (stat(dname,&st) != 0) {
     193         123 :                 return false;
     194             :         }
     195             : 
     196         135 :         ret = S_ISDIR(st.st_mode);
     197         135 :         if(!ret)
     198           0 :                 errno = ENOTDIR;
     199         127 :         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     1527373 : _PUBLIC_ bool directory_create_or_exist(const char *dname,
     210             :                                         mode_t dir_perms)
     211             : {
     212       58692 :         int ret;
     213       58692 :         mode_t old_umask;
     214             : 
     215             :         /* Create directory */
     216     1527373 :         old_umask = umask(0);
     217     1527373 :         ret = mkdir(dname, dir_perms);
     218     1527373 :         if (ret == -1 && errno != EEXIST) {
     219          15 :                 int dbg_level = geteuid() == 0 ? DBGLVL_ERR : DBGLVL_NOTICE;
     220             : 
     221          15 :                 DBG_PREFIX(dbg_level,
     222             :                            ("mkdir failed on directory %s: %s\n",
     223             :                             dname,
     224             :                             strerror(errno)));
     225          15 :                 umask(old_umask);
     226          15 :                 return false;
     227             :         }
     228     1527358 :         umask(old_umask);
     229             : 
     230     1527358 :         if (ret != 0 && errno == EEXIST) {
     231       58568 :                 struct stat sbuf;
     232             : 
     233     1525636 :                 ret = lstat(dname, &sbuf);
     234     1525636 :                 if (ret != 0) {
     235           0 :                         return false;
     236             :                 }
     237             : 
     238     1525636 :                 if (S_ISDIR(sbuf.st_mode)) {
     239     1467068 :                         return true;
     240             :                 }
     241             : 
     242           5 :                 if (S_ISLNK(sbuf.st_mode)) {
     243           3 :                         ret = stat(dname, &sbuf);
     244           3 :                         if (ret != 0) {
     245           0 :                                 return false;
     246             :                         }
     247             : 
     248           2 :                         if (S_ISDIR(sbuf.st_mode)) {
     249           0 :                                 return true;
     250             :                         }
     251             :                 }
     252             : 
     253           3 :                 return false;
     254             :         }
     255             : 
     256        1599 :         return true;
     257             : }
     258             : 
     259           2 : _PUBLIC_ bool directory_create_or_exists_recursive(
     260             :                 const char *dname,
     261             :                 mode_t dir_perms)
     262             : {
     263           2 :         bool ok;
     264             : 
     265           2 :         ok = directory_create_or_exist(dname, dir_perms);
     266           2 :         if (!ok) {
     267           1 :                 if (!directory_exist(dname)) {
     268           1 :                         char tmp[PATH_MAX] = {0};
     269           1 :                         char *parent = NULL;
     270           1 :                         size_t n;
     271             : 
     272             :                         /* Use the null context */
     273           1 :                         n = strlcpy(tmp, dname, sizeof(tmp));
     274           1 :                         if (n < strlen(dname)) {
     275           0 :                                 DBG_ERR("Path too long!\n");
     276           0 :                                 return false;
     277             :                         }
     278             : 
     279           1 :                         parent = dirname(tmp);
     280           1 :                         if (parent == NULL) {
     281           0 :                                 DBG_ERR("Failed to create dirname!\n");
     282           0 :                                 return false;
     283             :                         }
     284             : 
     285           1 :                         ok = directory_create_or_exists_recursive(parent,
     286             :                                                                   dir_perms);
     287           1 :                         if (!ok) {
     288           0 :                                 return false;
     289             :                         }
     290             : 
     291           1 :                         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      842762 : _PUBLIC_ bool directory_create_or_exist_strict(const char *dname,
     314             :                                                uid_t uid,
     315             :                                                mode_t dir_perms)
     316             : {
     317       34464 :         struct stat st;
     318       34464 :         bool ok;
     319       34464 :         int rc;
     320             : 
     321      842762 :         ok = directory_create_or_exist(dname, dir_perms);
     322      842762 :         if (!ok) {
     323          14 :                 return false;
     324             :         }
     325             : 
     326      842748 :         rc = lstat(dname, &st);
     327      842748 :         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      842748 :         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      876334 :         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      842748 :         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      808284 :         return true;
     352             : }
     353             : 
     354             : 
     355             : /**
     356             :  Sleep for a specified number of milliseconds.
     357             : **/
     358             : 
     359       29403 : _PUBLIC_ void smb_msleep(unsigned int t)
     360             : {
     361       29403 :         sys_poll_intr(NULL, 0, t);
     362       29403 : }
     363             : 
     364             : /**
     365             :  Get my own name, return in talloc'ed storage.
     366             : **/
     367             : 
     368      131053 : _PUBLIC_ char *get_myname(TALLOC_CTX *ctx)
     369             : {
     370        1419 :         char *p;
     371        1419 :         char hostname[HOST_NAME_MAX];
     372             : 
     373             :         /* get my host name */
     374      131053 :         if (gethostname(hostname, sizeof(hostname)) == -1) {
     375           0 :                 DEBUG(0,("gethostname failed\n"));
     376           0 :                 return NULL;
     377             :         }
     378             : 
     379             :         /* Ensure null termination. */
     380      131053 :         hostname[sizeof(hostname)-1] = '\0';
     381             : 
     382             :         /* split off any parts after an initial . */
     383      131053 :         p = strchr_m(hostname, '.');
     384      131053 :         if (p) {
     385      122246 :                 *p = 0;
     386             :         }
     387             : 
     388      131053 :         return talloc_strdup(ctx, hostname);
     389             : }
     390             : 
     391             : /**
     392             :  Check if a process exists. Does this work on all unixes?
     393             : **/
     394             : 
     395       54869 : _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       54869 :         if (pid <= 0) {
     400          22 :                 return false;
     401             :         }
     402       54856 :         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        7062 : _PUBLIC_ bool fcntl_lock(int fd, int op, off_t offset, off_t count, int type)
     411             : {
     412          34 :         struct flock lock;
     413          34 :         int ret;
     414             : 
     415        7062 :         DEBUG(8,("fcntl_lock %d %d %.0f %.0f %d\n",fd,op,(double)offset,(double)count,type));
     416             : 
     417        7062 :         lock.l_type = type;
     418        7062 :         lock.l_whence = SEEK_SET;
     419        7062 :         lock.l_start = offset;
     420        7062 :         lock.l_len = count;
     421        7062 :         lock.l_pid = 0;
     422             : 
     423        7062 :         ret = fcntl(fd,op,&lock);
     424             : 
     425        7062 :         if (ret == -1 && errno != 0)
     426        1492 :                 DEBUG(3,("fcntl_lock: fcntl lock gave errno %d (%s)\n",errno,strerror(errno)));
     427             : 
     428             :         /* a lock query */
     429        7062 :         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        7062 :         if (ret == -1) {
     444        1492 :                 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        1492 :                 return false;
     447             :         }
     448             : 
     449             :         /* everything went OK */
     450        5570 :         DEBUG(8,("fcntl_lock: Lock call successful\n"));
     451             : 
     452        5536 :         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      276088 : static void debugadd_cb(const char *buf, void *private_data)
     469             : {
     470      276088 :         int *plevel = (int *)private_data;
     471      276088 :         DEBUGADD(*plevel, ("%s", buf));
     472      276088 : }
     473             : 
     474    13650948 : 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      621552 :         int i;
     479      621552 :         char s[2];
     480    13650948 :         s[1] = 0;
     481             : 
     482    27301941 :         for (i=0; i<len; i++) {
     483    13650993 :                 s[0] = isprint(buf[i]) ? buf[i] : '.';
     484    13650993 :                 cb(s, private_data);
     485             :         }
     486    13650948 : }
     487             : 
     488          23 : void print_asc(int level, const uint8_t *buf,int len)
     489             : {
     490          23 :         print_asc_cb(buf, len, debugadd_cb, &level);
     491          23 : }
     492             : 
     493      939803 : 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       39708 :         char tmp[16];
     499       39708 :         size_t i;
     500             : 
     501      939803 :         SMB_ASSERT(len <= 16);
     502             : 
     503      939803 :         snprintf(tmp, sizeof(tmp), "%s[%04zX]", prefix, idx);
     504      939803 :         cb(tmp, private_data);
     505             : 
     506    16016359 :         for (i=0; i<16; i++) {
     507    15036848 :                 if (i == 8) {
     508      939803 :                         cb("  ", private_data);
     509             :                 }
     510    15036848 :                 if (i < len) {
     511    13650925 :                         snprintf(tmp, sizeof(tmp), " %02X", (int)buf[i]);
     512             :                 } else {
     513     1385923 :                         snprintf(tmp, sizeof(tmp), "   ");
     514             :                 }
     515    15036848 :                 cb(tmp, private_data);
     516             :         }
     517             : 
     518      939803 :         cb("   ", private_data);
     519             : 
     520      939803 :         if (len == 0) {
     521          31 :                 cb("EMPTY   BLOCK\n", private_data);
     522          31 :                 return;
     523             :         }
     524             : 
     525    14590697 :         for (i=0; i<len; i++) {
     526    13650925 :                 if (i == 8) {
     527      825380 :                         cb(" ", private_data);
     528             :                 }
     529    13650925 :                 print_asc_cb(&buf[i], 1, cb, private_data);
     530             :         }
     531             : 
     532      939772 :         cb("\n", private_data);
     533             : }
     534             : 
     535             : /**
     536             :  * Write dump of binary data to a callback
     537             :  */
     538      199631 : 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      199631 :         int i=0;
     544      199631 :         bool skipped = false;
     545             : 
     546      199631 :         if (len<=0) return;
     547             : 
     548     1163564 :         for (i=0;i<len;i+=16) {
     549      963942 :                 size_t remaining_len = len - i;
     550      963942 :                 size_t this_len = MIN(remaining_len, 16);
     551      963942 :                 const uint8_t *this_buf = &buf[i];
     552             : 
     553      963942 :                 if ((omit_zero_bytes == true) &&
     554      766864 :                     (i > 0) && (remaining_len > 16) &&
     555      665517 :                     (this_len == 16) && all_zero(this_buf, 16))
     556             :                 {
     557       24603 :                         if (!skipped) {
     558       15502 :                                 cb("skipping zero buffer bytes\n",
     559             :                                    private_data);
     560       15502 :                                 skipped = true;
     561             :                         }
     562       24603 :                         continue;
     563             :                 }
     564             : 
     565      939339 :                 skipped = false;
     566      939339 :                 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    12047051 : _PUBLIC_ void dump_data(int level, const uint8_t *buf, int len)
     577             : {
     578    12047051 :         if (!DEBUGLVL(level)) {
     579    12038673 :                 return;
     580             :         }
     581        8378 :         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        4031 : _PUBLIC_ void dump_data_dbgc(int dbgc_class, int level, const uint8_t *buf, int len)
     591             : {
     592        4031 :         struct debug_channel_level dcl = { dbgc_class, level };
     593             : 
     594        4031 :         if (!DEBUGLVLC(dbgc_class, level)) {
     595        4031 :                 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       17722 : static void fprintf_cb(const char *buf, void *private_data)
     615             : {
     616       17722 :         FILE *f = (FILE *)private_data;
     617       17722 :         fprintf(f, "%s", buf);
     618       17722 : }
     619             : 
     620          14 : void dump_data_file(const uint8_t *buf, int len, bool omit_zero_bytes,
     621             :                     FILE *f)
     622             : {
     623          14 :         dump_data_cb(buf, len, omit_zero_bytes, fprintf_cb, f);
     624          14 : }
     625             : 
     626             : /**
     627             :  * Write dump of compared binary data to a callback
     628             :  */
     629           8 : 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           8 :         size_t len = MAX(len1, len2);
     636           8 :         size_t i;
     637           8 :         bool skipped = false;
     638             : 
     639         311 :         for (i=0; i<len; i+=16) {
     640         303 :                 size_t remaining_len = len - i;
     641         303 :                 size_t remaining_len1 = 0;
     642         303 :                 size_t this_len1 = 0;
     643         303 :                 const uint8_t *this_buf1 = NULL;
     644         303 :                 size_t remaining_len2 = 0;
     645         303 :                 size_t this_len2 = 0;
     646         303 :                 const uint8_t *this_buf2 = NULL;
     647             : 
     648         303 :                 if (i < len1) {
     649         303 :                         remaining_len1 = len1 - i;
     650         303 :                         this_len1 = MIN(remaining_len1, 16);
     651         303 :                         this_buf1 = &buf1[i];
     652             :                 }
     653         303 :                 if (i < len2) {
     654         272 :                         remaining_len2 = len2 - i;
     655         272 :                         this_len2 = MIN(remaining_len2, 16);
     656         272 :                         this_buf2 = &buf2[i];
     657             :                 }
     658             : 
     659         303 :                 if ((omit_zero_bytes == true) &&
     660         303 :                     (i > 0) && (remaining_len > 16) &&
     661         295 :                     (this_len1 == 16) && all_zero(this_buf1, 16) &&
     662          28 :                     (this_len2 == 16) && all_zero(this_buf2, 16))
     663             :                 {
     664          27 :                         if (!skipped) {
     665          16 :                                 cb("skipping zero buffer bytes\n",
     666             :                                    private_data);
     667          16 :                                 skipped = true;
     668             :                         }
     669          27 :                         continue;
     670             :                 }
     671             : 
     672         276 :                 skipped = false;
     673             : 
     674         276 :                 if ((this_len1 == this_len2) &&
     675         240 :                     (memcmp(this_buf1, this_buf2, this_len1) == 0))
     676             :                 {
     677          88 :                         dump_data_block16(" ", i, this_buf1, this_len1,
     678             :                                           cb, private_data);
     679          88 :                         continue;
     680             :                 }
     681             : 
     682         188 :                 dump_data_block16("-", i, this_buf1, this_len1,
     683             :                                   cb, private_data);
     684         188 :                 dump_data_block16("+", i, this_buf2, this_len2,
     685             :                                   cb, private_data);
     686             :         }
     687           8 : }
     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           8 : _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           8 :         dump_data_diff_cb(buf1, len1, buf2, len2, omit_zero_bytes, fprintf_cb, f);
     708           8 : }
     709             : 
     710             : /**
     711             :  malloc that aborts with smb_panic on fail or zero size.
     712             : **/
     713             : 
     714      727657 : _PUBLIC_ void *smb_xmalloc(size_t size)
     715             : {
     716        1792 :         void *p;
     717      727657 :         if (size == 0)
     718           0 :                 smb_panic("smb_xmalloc: called with zero size.\n");
     719      727657 :         if ((p = malloc(size)) == NULL)
     720           0 :                 smb_panic("smb_xmalloc: malloc fail.\n");
     721      727657 :         return p;
     722             : }
     723             : 
     724             : /**
     725             :  Memdup with smb_panic on fail.
     726             : **/
     727             : 
     728      727657 : _PUBLIC_ void *smb_xmemdup(const void *p, size_t size)
     729             : {
     730        1792 :         void *p2;
     731      727657 :         p2 = smb_xmalloc(size);
     732      727657 :         memcpy(p2, p, size);
     733      727657 :         return p2;
     734             : }
     735             : 
     736             : /**
     737             :  strdup that aborts on malloc fail.
     738             : **/
     739             : 
     740     8147332 : 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     8147332 :         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     8147332 :         if (!s1) {
     760           0 :                 smb_panic("smb_xstrdup: malloc failed");
     761             :         }
     762     8147332 :         return s1;
     763             : 
     764             : }
     765             : 
     766             : /**
     767             :  strndup that aborts on malloc fail.
     768             : **/
     769             : 
     770       50631 : 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       50631 :         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       50631 :         if (!s1) {
     791           0 :                 smb_panic("smb_xstrndup: malloc failed");
     792             :         }
     793       50631 :         return s1;
     794             : }
     795             : 
     796             : 
     797             : 
     798             : /**
     799             :  Like strdup but for memory.
     800             : **/
     801             : 
     802       70558 : _PUBLIC_ void *smb_memdup(const void *p, size_t size)
     803             : {
     804        1809 :         void *p2;
     805       70558 :         if (size == 0)
     806          14 :                 return NULL;
     807       70544 :         p2 = malloc(size);
     808       70544 :         if (!p2)
     809           0 :                 return NULL;
     810       70544 :         memcpy(p2, p, size);
     811       70544 :         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     7867724 : _PUBLIC_ void dump_data_pw(const char *msg, const uint8_t * data, size_t len)
     821             : {
     822             : #ifdef DEBUG_PASSWORD
     823     7867724 :         DEBUG(11, ("%s", msg));
     824     7867724 :         if (data != NULL && len > 0)
     825             :         {
     826     7867322 :                 dump_data(11, data, len);
     827             :         }
     828             : #endif
     829     7867724 : }
     830             : 
     831           0 : static void dump_data_addbuf_cb(const char *buf, void *private_data)
     832             : {
     833           0 :         char **str = private_data;
     834           0 :         talloc_asprintf_addbuf(str, "%s", buf);
     835           0 : }
     836             : 
     837           0 : _PUBLIC_ void dump_data_addbuf(const uint8_t *buf, size_t buflen, char **str)
     838             : {
     839           0 :         dump_data_cb(buf, buflen, false, dump_data_addbuf_cb, str);
     840           0 : }
     841             : 
     842             : 
     843             : /**
     844             :  * see if a range of memory is all zero. A NULL pointer is considered
     845             :  * to be all zero 
     846             :  */
     847    19620694 : _PUBLIC_ bool all_zero(const uint8_t *ptr, size_t size)
     848             : {
     849      910609 :         size_t i;
     850    19620694 :         if (!ptr) return true;
     851   305312711 :         for (i=0;i<size;i++) {
     852   286694643 :                 if (ptr[i]) return false;
     853             :         }
     854    17746147 :         return true;
     855             : }
     856             : 
     857             : /**
     858             :   realloc an array, checking for integer overflow in the array size
     859             : */
     860     3133777 : _PUBLIC_ void *realloc_array(void *ptr, size_t el_size, unsigned count, bool free_on_fail)
     861             : {
     862             : #define MAX_MALLOC_SIZE 0x7fffffff
     863     3133777 :         if (count == 0 ||
     864     3133777 :             count >= MAX_MALLOC_SIZE/el_size) {
     865           0 :                 if (free_on_fail)
     866           0 :                         SAFE_FREE(ptr);
     867           0 :                 return NULL;
     868             :         }
     869     3133777 :         if (!ptr) {
     870     3130926 :                 return malloc(el_size * count);
     871             :         }
     872        2851 :         return realloc(ptr, el_size * count);
     873             : }
     874             : 
     875             : /****************************************************************************
     876             :  Type-safe malloc.
     877             : ****************************************************************************/
     878             : 
     879     3127717 : void *malloc_array(size_t el_size, unsigned int count)
     880             : {
     881     3127717 :         return realloc_array(NULL, el_size, count, false);
     882             : }
     883             : 
     884             : /****************************************************************************
     885             :  Type-safe memalign
     886             : ****************************************************************************/
     887             : 
     888           0 : void *memalign_array(size_t el_size, size_t align, unsigned int count)
     889             : {
     890           0 :         if (el_size == 0 || count >= MAX_MALLOC_SIZE/el_size) {
     891           0 :                 return NULL;
     892             :         }
     893             : 
     894           0 :         return memalign(align, el_size*count);
     895             : }
     896             : 
     897             : /****************************************************************************
     898             :  Type-safe calloc.
     899             : ****************************************************************************/
     900             : 
     901          98 : void *calloc_array(size_t size, size_t nmemb)
     902             : {
     903          98 :         if (nmemb >= MAX_MALLOC_SIZE/size) {
     904           0 :                 return NULL;
     905             :         }
     906          98 :         if (size == 0 || nmemb == 0) {
     907           0 :                 return NULL;
     908             :         }
     909          98 :         return calloc(nmemb, size);
     910             : }
     911             : 
     912             : /**
     913             :  Trim the specified elements off the front and back of a string.
     914             : **/
     915      614491 : _PUBLIC_ bool trim_string(char *s, const char *front, const char *back)
     916             : {
     917      614491 :         bool ret = false;
     918       19083 :         size_t front_len;
     919       19083 :         size_t back_len;
     920       19083 :         size_t len;
     921             : 
     922             :         /* Ignore null or empty strings. */
     923      614491 :         if (!s || (s[0] == '\0')) {
     924         464 :                 return false;
     925             :         }
     926      614025 :         len = strlen(s);
     927             : 
     928      614025 :         front_len       = front? strlen(front) : 0;
     929      614025 :         back_len        = back? strlen(back) : 0;
     930             : 
     931      614025 :         if (front_len) {
     932        2314 :                 size_t front_trim = 0;
     933             : 
     934        4467 :                 while (strncmp(s+front_trim, front, front_len)==0) {
     935        2131 :                         front_trim += front_len;
     936             :                 }
     937        2336 :                 if (front_trim > 0) {
     938             :                         /* Must use memmove here as src & dest can
     939             :                          * easily overlap. Found by valgrind. JRA. */
     940        2119 :                         memmove(s, s+front_trim, (len-front_trim)+1);
     941        2119 :                         len -= front_trim;
     942        2119 :                         ret=true;
     943             :                 }
     944             :         }
     945             : 
     946      614025 :         if (back_len) {
     947      619066 :                 while ((len >= back_len) && strncmp(s+len-back_len,back,back_len)==0) {
     948        5054 :                         s[len-back_len]='\0';
     949        5054 :                         len -= back_len;
     950        5054 :                         ret=true;
     951             :                 }
     952             :         }
     953      594944 :         return ret;
     954             : }
     955             : 
     956             : /**
     957             :  Find the number of 'c' chars in a string
     958             : **/
     959       20613 : _PUBLIC_ _PURE_ size_t count_chars(const char *s, char c)
     960             : {
     961       20613 :         size_t count = 0;
     962             : 
     963      615682 :         while (*s) {
     964      595069 :                 if (*s == c) count++;
     965      595069 :                 s ++;
     966             :         }
     967             : 
     968       20613 :         return count;
     969             : }
     970             : 
     971             : /**
     972             :  * Routine to get hex characters and turn them into a byte array.
     973             :  * the array can be variable length.
     974             :  * -  "0xnn" or "0Xnn" is specially catered for.
     975             :  * - The first non-hex-digit character (apart from possibly leading "0x"
     976             :  *   finishes the conversion and skips the rest of the input.
     977             :  * - A single hex-digit character at the end of the string is skipped.
     978             :  *
     979             :  * valid examples: "0A5D15"; "0x123456"
     980             :  */
     981    10996506 : _PUBLIC_ size_t strhex_to_str(char *p, size_t p_len, const char *strhex, size_t strhex_len)
     982             : {
     983    10996506 :         size_t i = 0;
     984    10996506 :         size_t num_chars = 0;
     985             : 
     986             :         /* skip leading 0x prefix */
     987    10996506 :         if (strncasecmp(strhex, "0x", 2) == 0) {
     988          73 :                 i += 2; /* skip two chars */
     989             :         }
     990             : 
     991   437188848 :         while ((i < strhex_len) && (num_chars < p_len)) {
     992   426192729 :                 bool ok = hex_byte(&strhex[i], (uint8_t *)&p[num_chars]);
     993   426192729 :                 if (!ok) {
     994         384 :                         break;
     995             :                 }
     996   426192342 :                 i += 2;
     997   426192342 :                 num_chars += 1;
     998             :         }
     999             : 
    1000    10996506 :         return num_chars;
    1001             : }
    1002             : 
    1003             : /**
    1004             :  * Parse a hex string and return a data blob.
    1005             :  */
    1006      291326 : _PUBLIC_ DATA_BLOB strhex_to_data_blob(TALLOC_CTX *mem_ctx, const char *strhex)
    1007             : {
    1008      291326 :         DATA_BLOB ret_blob = data_blob_talloc(mem_ctx, NULL, strlen(strhex)/2+1);
    1009      291326 :         if (ret_blob.data == NULL) {
    1010             :                 /* ret_blob.length is already 0 */
    1011           0 :                 return ret_blob;
    1012             :         }
    1013      291326 :         ret_blob.length = strhex_to_str((char *)ret_blob.data, ret_blob.length,
    1014             :                                         strhex,
    1015             :                                         strlen(strhex));
    1016             : 
    1017      291326 :         return ret_blob;
    1018             : }
    1019             : 
    1020             : /**
    1021             :  * Parse a hex dump and return a data blob. Hex dump is structured as 
    1022             :  * is generated from dump_data_cb() elsewhere in this file
    1023             :  * 
    1024             :  */
    1025           4 : _PUBLIC_ DATA_BLOB hexdump_to_data_blob(TALLOC_CTX *mem_ctx, const char *hexdump, size_t hexdump_len)
    1026             : {
    1027           4 :         DATA_BLOB ret_blob = { 0 };
    1028           4 :         size_t i = 0;
    1029           4 :         size_t char_count = 0;
    1030             :         /* hexdump line length is 77 chars long. We then use the ASCII representation of the bytes
    1031             :          * at the end of the final line to calculate how many are in that line, minus the extra space
    1032             :          * and newline. */
    1033           4 :         size_t hexdump_byte_count = (16 * (hexdump_len / 77));
    1034           4 :         if (hexdump_len % 77) {
    1035           3 :                 hexdump_byte_count += ((hexdump_len % 77) - 59 - 2);
    1036             :         }
    1037             :         
    1038           4 :         ret_blob = data_blob_talloc(mem_ctx, NULL, hexdump_byte_count+1);
    1039        1462 :         for (; i+1 < hexdump_len && hexdump[i] != 0 && hexdump[i+1] != 0; i++) {
    1040        1458 :                 if ((i%77) == 0) 
    1041          54 :                         i += 7; /* Skip the offset at the start of the line */
    1042        1458 :                 if ((i%77) < 56) { /* position 56 is after both hex chunks */
    1043         932 :                         if (hexdump[i] != ' ') {
    1044         836 :                                 char_count += strhex_to_str((char *)&ret_blob.data[char_count],
    1045             :                                                             hexdump_byte_count - char_count,
    1046             :                                                             &hexdump[i], 2);
    1047         836 :                                 i += 2;
    1048             :                         } else {
    1049          96 :                                 i++;
    1050             :                         }
    1051             :                 } else {
    1052         526 :                         i++;
    1053             :                 }
    1054             :         }
    1055           4 :         ret_blob.length = char_count;
    1056             :         
    1057           4 :         return ret_blob;
    1058             : }
    1059             : 
    1060             : /**
    1061             :  * Print a buf in hex. Assumes dst is at least (srclen*2)+1 large.
    1062             :  */
    1063      478694 : _PUBLIC_ void hex_encode_buf(char *dst, const uint8_t *src, size_t srclen)
    1064             : {
    1065        1226 :         size_t i;
    1066     8619496 :         for (i=0; i<srclen; i++) {
    1067     8140802 :                 snprintf(dst + i*2, 3, "%02X", src[i]);
    1068             :         }
    1069             :         /*
    1070             :          * Ensure 0-termination for 0-length buffers
    1071             :          */
    1072      478694 :         dst[srclen*2] = '\0';
    1073      478694 : }
    1074             : 
    1075             : /**
    1076             :  * talloc version of hex_encode_buf()
    1077             :  */
    1078      478674 : _PUBLIC_ char *hex_encode_talloc(TALLOC_CTX *mem_ctx, const unsigned char *buff_in, size_t len)
    1079             : {
    1080        1224 :         char *hex_buffer;
    1081             : 
    1082      478674 :         hex_buffer = talloc_array(mem_ctx, char, (len*2)+1);
    1083      478674 :         if (!hex_buffer) {
    1084           0 :                 return NULL;
    1085             :         }
    1086      478674 :         hex_encode_buf(hex_buffer, buff_in, len);
    1087      478674 :         talloc_set_name_const(hex_buffer, hex_buffer);
    1088      478674 :         return hex_buffer;
    1089             : }
    1090             : 
    1091             : /**
    1092             :   variant of strcmp() that handles NULL ptrs
    1093             : **/
    1094     5119302 : _PUBLIC_ int strcmp_safe(const char *s1, const char *s2)
    1095             : {
    1096     5119302 :         if (s1 == s2) {
    1097         657 :                 return 0;
    1098             :         }
    1099     5118601 :         if (s1 == NULL || s2 == NULL) {
    1100           0 :                 return s1?-1:1;
    1101             :         }
    1102     5118601 :         return strcmp(s1, s2);
    1103             : }
    1104             : 
    1105             : 
    1106             : /**
    1107             : return the number of bytes occupied by a buffer in ASCII format
    1108             : the result includes the null termination
    1109             : limited by 'n' bytes
    1110             : **/
    1111   103010853 : _PUBLIC_ size_t ascii_len_n(const char *src, size_t n)
    1112             : {
    1113      869847 :         size_t len;
    1114             : 
    1115   103010853 :         len = strnlen(src, n);
    1116   103010853 :         if (len+1 <= n) {
    1117   103010836 :                 len += 1;
    1118             :         }
    1119             : 
    1120   103010853 :         return len;
    1121             : }
    1122             : 
    1123     4005727 : _PUBLIC_ bool mem_equal_const_time(const void *s1, const void *s2, size_t n)
    1124             : {
    1125             :         /* Ensure we won't overflow the unsigned index used by gnutls. */
    1126     4005727 :         SMB_ASSERT(n <= UINT_MAX);
    1127             : 
    1128     4005727 :         return gnutls_memcmp(s1, s2, n) == 0;
    1129             : }
    1130             : 
    1131             : struct anonymous_shared_header {
    1132             :         union {
    1133             :                 size_t length;
    1134             :                 uint8_t pad[16];
    1135             :         } u;
    1136             : };
    1137             : 
    1138             : /* Map a shared memory buffer of at least nelem counters. */
    1139        1546 : void *anonymous_shared_allocate(size_t orig_bufsz)
    1140             : {
    1141         149 :         void *ptr;
    1142         149 :         void *buf;
    1143        1546 :         size_t pagesz = getpagesize();
    1144         149 :         size_t pagecnt;
    1145        1546 :         size_t bufsz = orig_bufsz;
    1146         149 :         struct anonymous_shared_header *hdr;
    1147             : 
    1148        1546 :         bufsz += sizeof(*hdr);
    1149             : 
    1150             :         /* round up to full pages */
    1151        1546 :         pagecnt = bufsz / pagesz;
    1152        1546 :         if (bufsz % pagesz) {
    1153        1546 :                 pagecnt += 1;
    1154             :         }
    1155        1546 :         bufsz = pagesz * pagecnt;
    1156             : 
    1157        1546 :         if (orig_bufsz >= bufsz) {
    1158             :                 /* integer wrap */
    1159           1 :                 errno = ENOMEM;
    1160           1 :                 return NULL;
    1161             :         }
    1162             : 
    1163             : #ifdef MAP_ANON
    1164             :         /* BSD */
    1165        1545 :         buf = mmap(NULL, bufsz, PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED,
    1166             :                         -1 /* fd */, 0 /* offset */);
    1167             : #else
    1168             : {
    1169             :         int saved_errno;
    1170             :         int fd;
    1171             : 
    1172             :         fd = open("/dev/zero", O_RDWR);
    1173             :         if (fd == -1) {
    1174             :                 return NULL;
    1175             :         }
    1176             : 
    1177             :         buf = mmap(NULL, bufsz, PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED,
    1178             :                    fd, 0 /* offset */);
    1179             :         saved_errno = errno;
    1180             :         close(fd);
    1181             :         errno = saved_errno;
    1182             : }
    1183             : #endif
    1184             : 
    1185        1545 :         if (buf == MAP_FAILED) {
    1186           0 :                 return NULL;
    1187             :         }
    1188             : 
    1189        1545 :         hdr = (struct anonymous_shared_header *)buf;
    1190        1545 :         hdr->u.length = bufsz;
    1191             : 
    1192        1545 :         ptr = (void *)(&hdr[1]);
    1193             : 
    1194        1545 :         return ptr;
    1195             : }
    1196             : 
    1197           0 : void *anonymous_shared_resize(void *ptr, size_t new_size, bool maymove)
    1198             : {
    1199             : #ifdef HAVE_MREMAP
    1200           0 :         void *buf;
    1201           0 :         size_t pagesz = getpagesize();
    1202           0 :         size_t pagecnt;
    1203           0 :         size_t bufsz;
    1204           0 :         struct anonymous_shared_header *hdr;
    1205           0 :         int flags = 0;
    1206             : 
    1207           0 :         if (ptr == NULL) {
    1208           0 :                 errno = EINVAL;
    1209           0 :                 return NULL;
    1210             :         }
    1211             : 
    1212           0 :         hdr = (struct anonymous_shared_header *)ptr;
    1213           0 :         hdr--;
    1214           0 :         if (hdr->u.length > (new_size + sizeof(*hdr))) {
    1215           0 :                 errno = EINVAL;
    1216           0 :                 return NULL;
    1217             :         }
    1218             : 
    1219           0 :         bufsz = new_size + sizeof(*hdr);
    1220             : 
    1221             :         /* round up to full pages */
    1222           0 :         pagecnt = bufsz / pagesz;
    1223           0 :         if (bufsz % pagesz) {
    1224           0 :                 pagecnt += 1;
    1225             :         }
    1226           0 :         bufsz = pagesz * pagecnt;
    1227             : 
    1228           0 :         if (new_size >= bufsz) {
    1229             :                 /* integer wrap */
    1230           0 :                 errno = ENOSPC;
    1231           0 :                 return NULL;
    1232             :         }
    1233             : 
    1234           0 :         if (bufsz <= hdr->u.length) {
    1235           0 :                 return ptr;
    1236             :         }
    1237             : 
    1238           0 :         if (maymove) {
    1239           0 :                 flags = MREMAP_MAYMOVE;
    1240             :         }
    1241             : 
    1242           0 :         buf = mremap(hdr, hdr->u.length, bufsz, flags);
    1243             : 
    1244           0 :         if (buf == MAP_FAILED) {
    1245           0 :                 errno = ENOSPC;
    1246           0 :                 return NULL;
    1247             :         }
    1248             : 
    1249           0 :         hdr = (struct anonymous_shared_header *)buf;
    1250           0 :         hdr->u.length = bufsz;
    1251             : 
    1252           0 :         ptr = (void *)(&hdr[1]);
    1253             : 
    1254           0 :         return ptr;
    1255             : #else
    1256             :         errno = ENOSPC;
    1257             :         return NULL;
    1258             : #endif
    1259             : }
    1260             : 
    1261        1500 : void anonymous_shared_free(void *ptr)
    1262             : {
    1263         149 :         struct anonymous_shared_header *hdr;
    1264             : 
    1265        1500 :         if (ptr == NULL) {
    1266           0 :                 return;
    1267             :         }
    1268             : 
    1269        1499 :         hdr = (struct anonymous_shared_header *)ptr;
    1270             : 
    1271        1499 :         hdr--;
    1272             : 
    1273        1499 :         munmap(hdr, hdr->u.length);
    1274             : }
    1275             : 
    1276             : #ifdef DEVELOPER
    1277             : /* used when you want a debugger started at a particular point in the
    1278             :    code. Mostly useful in code that runs as a child process, where
    1279             :    normal gdb attach is harder to organise.
    1280             : */
    1281           0 : void samba_start_debugger(void)
    1282             : {
    1283           0 :         int ready_pipe[2];
    1284           0 :         char c;
    1285           0 :         int ret;
    1286           0 :         pid_t pid;
    1287             : 
    1288           0 :         ret = pipe(ready_pipe);
    1289           0 :         SMB_ASSERT(ret == 0);
    1290             : 
    1291           0 :         pid = fork();
    1292           0 :         SMB_ASSERT(pid >= 0);
    1293             : 
    1294           0 :         if (pid) {
    1295           0 :                 c = 0;
    1296             : 
    1297           0 :                 ret = close(ready_pipe[0]);
    1298           0 :                 SMB_ASSERT(ret == 0);
    1299             : #if defined(HAVE_PRCTL) && defined(PR_SET_PTRACER)
    1300             :                 /*
    1301             :                  * Make sure the child process can attach a debugger.
    1302             :                  *
    1303             :                  * We don't check the error code as the debugger
    1304             :                  * will tell us if it can't attach.
    1305             :                  */
    1306           0 :                 (void)prctl(PR_SET_PTRACER, pid, 0, 0, 0);
    1307             : #endif
    1308           0 :                 ret = write(ready_pipe[1], &c, 1);
    1309           0 :                 SMB_ASSERT(ret == 1);
    1310             : 
    1311           0 :                 ret = close(ready_pipe[1]);
    1312           0 :                 SMB_ASSERT(ret == 0);
    1313             : 
    1314             :                 /* Wait for gdb to attach. */
    1315           0 :                 sleep(2);
    1316             :         } else {
    1317           0 :                 char *cmd = NULL;
    1318             : 
    1319           0 :                 ret = close(ready_pipe[1]);
    1320           0 :                 SMB_ASSERT(ret == 0);
    1321             : 
    1322           0 :                 ret = read(ready_pipe[0], &c, 1);
    1323           0 :                 SMB_ASSERT(ret == 1);
    1324             : 
    1325           0 :                 ret = close(ready_pipe[0]);
    1326           0 :                 SMB_ASSERT(ret == 0);
    1327             : 
    1328           0 :                 ret = asprintf(&cmd, "gdb --pid %u", getppid());
    1329           0 :                 SMB_ASSERT(ret != -1);
    1330             : 
    1331           0 :                 execlp("xterm", "xterm", "-e", cmd, (char *) NULL);
    1332           0 :                 smb_panic("execlp() failed");
    1333             :         }
    1334           0 : }
    1335             : #endif

Generated by: LCOV version 1.14