LCOV - code coverage report
Current view: top level - lib/replace - replace.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 16 21 76.2 %
Date: 2021-09-23 10:06:22 Functions: 3 4 75.0 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             :    replacement routines for broken systems
       4             :    Copyright (C) Andrew Tridgell 1992-1998
       5             :    Copyright (C) Jelmer Vernooij 2005-2008
       6             :    Copyright (C) Matthieu Patou  2010
       7             : 
       8             :      ** NOTE! The following LGPL license applies to the replace
       9             :      ** library. This does NOT imply that all of Samba is released
      10             :      ** under the LGPL
      11             :    
      12             :    This library is free software; you can redistribute it and/or
      13             :    modify it under the terms of the GNU Lesser General Public
      14             :    License as published by the Free Software Foundation; either
      15             :    version 3 of the License, or (at your option) any later version.
      16             : 
      17             :    This library 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 GNU
      20             :    Lesser General Public License for more details.
      21             : 
      22             :    You should have received a copy of the GNU Lesser General Public
      23             :    License along with this library; if not, see <http://www.gnu.org/licenses/>.
      24             : */
      25             : 
      26             : #include "replace.h"
      27             : 
      28             : #include "system/filesys.h"
      29             : #include "system/time.h"
      30             : #include "system/network.h"
      31             : #include "system/passwd.h"
      32             : #include "system/syslog.h"
      33             : #include "system/locale.h"
      34             : #include "system/wait.h"
      35             : 
      36             : #ifdef _WIN32
      37             : #define mkdir(d,m) _mkdir(d)
      38             : #endif
      39             : 
      40             : void replace_dummy(void);
      41           0 : void replace_dummy(void) {}
      42             : 
      43             : #ifndef HAVE_FTRUNCATE
      44             :  /*******************************************************************
      45             : ftruncate for operating systems that don't have it
      46             : ********************************************************************/
      47             : int rep_ftruncate(int f, off_t l)
      48             : {
      49             : #ifdef HAVE_CHSIZE
      50             :       return chsize(f,l);
      51             : #elif defined(F_FREESP)
      52             :       struct  flock   fl;
      53             : 
      54             :       fl.l_whence = 0;
      55             :       fl.l_len = 0;
      56             :       fl.l_start = l;
      57             :       fl.l_type = F_WRLCK;
      58             :       return fcntl(f, F_FREESP, &fl);
      59             : #else
      60             : #error "you must have a ftruncate function"
      61             : #endif
      62             : }
      63             : #endif /* HAVE_FTRUNCATE */
      64             : 
      65             : 
      66             : #ifndef HAVE_STRLCPY
      67             : /*
      68             :  * Like strncpy but does not 0 fill the buffer and always null
      69             :  * terminates. bufsize is the size of the destination buffer.
      70             :  * Returns the length of s.
      71             :  */
      72             : size_t rep_strlcpy(char *d, const char *s, size_t bufsize)
      73             : {
      74             :         size_t len = strlen(s);
      75             :         size_t ret = len;
      76             : 
      77             :         if (bufsize <= 0) {
      78             :                 return 0;
      79             :         }
      80             :         if (len >= bufsize) {
      81             :                 len = bufsize - 1;
      82             :         }
      83             :         memcpy(d, s, len);
      84             :         d[len] = 0;
      85             :         return ret;
      86             : }
      87             : #endif
      88             : 
      89             : #ifndef HAVE_STRLCAT
      90             : /* like strncat but does not 0 fill the buffer and always null 
      91             :    terminates. bufsize is the length of the buffer, which should
      92             :    be one more than the maximum resulting string length */
      93             : size_t rep_strlcat(char *d, const char *s, size_t bufsize)
      94             : {
      95             :         size_t len1 = strnlen(d, bufsize);
      96             :         size_t len2 = strlen(s);
      97             :         size_t ret = len1 + len2;
      98             : 
      99             :         if (len1+len2 >= bufsize) {
     100             :                 if (bufsize < (len1+1)) {
     101             :                         return ret;
     102             :                 }
     103             :                 len2 = bufsize - (len1+1);
     104             :         }
     105             :         if (len2 > 0) {
     106             :                 memcpy(d+len1, s, len2);
     107             :                 d[len1+len2] = 0;
     108             :         }
     109             :         return ret;
     110             : }
     111             : #endif
     112             : 
     113             : #ifndef HAVE_MKTIME
     114             : /*******************************************************************
     115             : a mktime() replacement for those who don't have it - contributed by 
     116             : C.A. Lademann <cal@zls.com>
     117             : Corrections by richard.kettlewell@kewill.com
     118             : ********************************************************************/
     119             : 
     120             : #define  MINUTE  60
     121             : #define  HOUR    60*MINUTE
     122             : #define  DAY             24*HOUR
     123             : #define  YEAR    365*DAY
     124             : time_t rep_mktime(struct tm *t)
     125             : {
     126             :   struct tm       *u;
     127             :   time_t  epoch = 0;
     128             :   int n;
     129             :   int             mon [] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
     130             :   y, m, i;
     131             : 
     132             :   if(t->tm_year < 70)
     133             :     return((time_t)-1);
     134             : 
     135             :   n = t->tm_year + 1900 - 1;
     136             :   epoch = (t->tm_year - 70) * YEAR + 
     137             :     ((n / 4 - n / 100 + n / 400) - (1969 / 4 - 1969 / 100 + 1969 / 400)) * DAY;
     138             : 
     139             :   y = t->tm_year + 1900;
     140             :   m = 0;
     141             : 
     142             :   for(i = 0; i < t->tm_mon; i++) {
     143             :     epoch += mon [m] * DAY;
     144             :     if(m == 1 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0))
     145             :       epoch += DAY;
     146             :     
     147             :     if(++m > 11) {
     148             :       m = 0;
     149             :       y++;
     150             :     }
     151             :   }
     152             : 
     153             :   epoch += (t->tm_mday - 1) * DAY;
     154             :   epoch += t->tm_hour * HOUR + t->tm_min * MINUTE + t->tm_sec;
     155             :   
     156             :   if((u = localtime(&epoch)) != NULL) {
     157             :     t->tm_sec = u->tm_sec;
     158             :     t->tm_min = u->tm_min;
     159             :     t->tm_hour = u->tm_hour;
     160             :     t->tm_mday = u->tm_mday;
     161             :     t->tm_mon = u->tm_mon;
     162             :     t->tm_year = u->tm_year;
     163             :     t->tm_wday = u->tm_wday;
     164             :     t->tm_yday = u->tm_yday;
     165             :     t->tm_isdst = u->tm_isdst;
     166             :   }
     167             : 
     168             :   return(epoch);
     169             : }
     170             : #endif /* !HAVE_MKTIME */
     171             : 
     172             : 
     173             : #ifndef HAVE_INITGROUPS
     174             : /****************************************************************************
     175             :  some systems don't have an initgroups call 
     176             : ****************************************************************************/
     177             : int rep_initgroups(char *name, gid_t id)
     178             : {
     179             : #ifndef HAVE_SETGROUPS
     180             :         /* yikes! no SETGROUPS or INITGROUPS? how can this work? */
     181             :         errno = ENOSYS;
     182             :         return -1;
     183             : #else /* HAVE_SETGROUPS */
     184             : 
     185             : #include <grp.h>
     186             : 
     187             :         gid_t *grouplst = NULL;
     188             :         int max_gr = NGROUPS_MAX;
     189             :         int ret;
     190             :         int    i,j;
     191             :         struct group *g;
     192             :         char   *gr;
     193             :         
     194             :         if((grouplst = malloc(sizeof(gid_t) * max_gr)) == NULL) {
     195             :                 errno = ENOMEM;
     196             :                 return -1;
     197             :         }
     198             : 
     199             :         grouplst[0] = id;
     200             :         i = 1;
     201             :         while (i < max_gr && ((g = (struct group *)getgrent()) != (struct group *)NULL)) {
     202             :                 if (g->gr_gid == id)
     203             :                         continue;
     204             :                 j = 0;
     205             :                 gr = g->gr_mem[0];
     206             :                 while (gr && (*gr != (char)NULL)) {
     207             :                         if (strcmp(name,gr) == 0) {
     208             :                                 grouplst[i] = g->gr_gid;
     209             :                                 i++;
     210             :                                 gr = (char *)NULL;
     211             :                                 break;
     212             :                         }
     213             :                         gr = g->gr_mem[++j];
     214             :                 }
     215             :         }
     216             :         endgrent();
     217             :         ret = setgroups(i, grouplst);
     218             :         free(grouplst);
     219             :         return ret;
     220             : #endif /* HAVE_SETGROUPS */
     221             : }
     222             : #endif /* HAVE_INITGROUPS */
     223             : 
     224             : 
     225             : #ifndef HAVE_MEMMOVE
     226             : /*******************************************************************
     227             : safely copies memory, ensuring no overlap problems.
     228             : this is only used if the machine does not have its own memmove().
     229             : this is not the fastest algorithm in town, but it will do for our
     230             : needs.
     231             : ********************************************************************/
     232             : void *rep_memmove(void *dest,const void *src,int size)
     233             : {
     234             :         unsigned long d,s;
     235             :         int i;
     236             :         if (dest==src || !size) return(dest);
     237             : 
     238             :         d = (unsigned long)dest;
     239             :         s = (unsigned long)src;
     240             : 
     241             :         if ((d >= (s+size)) || (s >= (d+size))) {
     242             :                 /* no overlap */
     243             :                 memcpy(dest,src,size);
     244             :                 return(dest);
     245             :         }
     246             : 
     247             :         if (d < s) {
     248             :                 /* we can forward copy */
     249             :                 if (s-d >= sizeof(int) && 
     250             :                     !(s%sizeof(int)) && 
     251             :                     !(d%sizeof(int)) && 
     252             :                     !(size%sizeof(int))) {
     253             :                         /* do it all as words */
     254             :                         int *idest = (int *)dest;
     255             :                         int *isrc = (int *)src;
     256             :                         size /= sizeof(int);
     257             :                         for (i=0;i<size;i++) idest[i] = isrc[i];
     258             :                 } else {
     259             :                         /* simplest */
     260             :                         char *cdest = (char *)dest;
     261             :                         char *csrc = (char *)src;
     262             :                         for (i=0;i<size;i++) cdest[i] = csrc[i];
     263             :                 }
     264             :         } else {
     265             :                 /* must backward copy */
     266             :                 if (d-s >= sizeof(int) && 
     267             :                     !(s%sizeof(int)) && 
     268             :                     !(d%sizeof(int)) && 
     269             :                     !(size%sizeof(int))) {
     270             :                         /* do it all as words */
     271             :                         int *idest = (int *)dest;
     272             :                         int *isrc = (int *)src;
     273             :                         size /= sizeof(int);
     274             :                         for (i=size-1;i>=0;i--) idest[i] = isrc[i];
     275             :                 } else {
     276             :                         /* simplest */
     277             :                         char *cdest = (char *)dest;
     278             :                         char *csrc = (char *)src;
     279             :                         for (i=size-1;i>=0;i--) cdest[i] = csrc[i];
     280             :                 }      
     281             :         }
     282             :         return(dest);
     283             : }
     284             : #endif /* HAVE_MEMMOVE */
     285             : 
     286             : #ifndef HAVE_STRDUP
     287             : /****************************************************************************
     288             : duplicate a string
     289             : ****************************************************************************/
     290             : char *rep_strdup(const char *s)
     291             : {
     292             :         size_t len;
     293             :         char *ret;
     294             : 
     295             :         if (!s) return(NULL);
     296             : 
     297             :         len = strlen(s)+1;
     298             :         ret = (char *)malloc(len);
     299             :         if (!ret) return(NULL);
     300             :         memcpy(ret,s,len);
     301             :         return(ret);
     302             : }
     303             : #endif /* HAVE_STRDUP */
     304             : 
     305             : #ifndef HAVE_SETLINEBUF
     306             : void rep_setlinebuf(FILE *stream)
     307             : {
     308             :         setvbuf(stream, (char *)NULL, _IOLBF, 0);
     309             : }
     310             : #endif /* HAVE_SETLINEBUF */
     311             : 
     312             : #ifndef HAVE_VSYSLOG
     313             : #ifdef HAVE_SYSLOG
     314             : void rep_vsyslog (int facility_priority, const char *format, va_list arglist)
     315             : {
     316             :         char *msg = NULL;
     317             :         vasprintf(&msg, format, arglist);
     318             :         if (!msg)
     319             :                 return;
     320             :         syslog(facility_priority, "%s", msg);
     321             :         free(msg);
     322             : }
     323             : #endif /* HAVE_SYSLOG */
     324             : #endif /* HAVE_VSYSLOG */
     325             : 
     326             : #ifndef HAVE_STRNLEN
     327             : /**
     328             :  Some platforms don't have strnlen
     329             : **/
     330             :  size_t rep_strnlen(const char *s, size_t max)
     331             : {
     332             :         size_t len;
     333             :   
     334             :         for (len = 0; len < max; len++) {
     335             :                 if (s[len] == '\0') {
     336             :                         break;
     337             :                 }
     338             :         }
     339             :         return len;  
     340             : }
     341             : #endif
     342             :   
     343             : #ifndef HAVE_STRNDUP
     344             : /**
     345             :  Some platforms don't have strndup.
     346             : **/
     347             : char *rep_strndup(const char *s, size_t n)
     348             : {
     349             :         char *ret;
     350             :         
     351             :         n = strnlen(s, n);
     352             :         ret = malloc(n+1);
     353             :         if (!ret)
     354             :                 return NULL;
     355             :         memcpy(ret, s, n);
     356             :         ret[n] = 0;
     357             : 
     358             :         return ret;
     359             : }
     360             : #endif
     361             : 
     362             : #if !defined(HAVE_WAITPID) && defined(HAVE_WAIT4)
     363             : int rep_waitpid(pid_t pid,int *status,int options)
     364             : {
     365             :   return wait4(pid, status, options, NULL);
     366             : }
     367             : #endif
     368             : 
     369             : #ifndef HAVE_SETEUID
     370             : int rep_seteuid(uid_t euid)
     371             : {
     372             : #ifdef HAVE_SETRESUID
     373             :         return setresuid(-1, euid, -1);
     374             : #else
     375             :         errno = ENOSYS;
     376             :         return -1;
     377             : #endif
     378             : }
     379             : #endif
     380             : 
     381             : #ifndef HAVE_SETEGID
     382             : int rep_setegid(gid_t egid)
     383             : {
     384             : #ifdef HAVE_SETRESGID
     385             :         return setresgid(-1, egid, -1);
     386             : #else
     387             :         errno = ENOSYS;
     388             :         return -1;
     389             : #endif
     390             : }
     391             : #endif
     392             : 
     393             : /*******************************************************************
     394             : os/2 also doesn't have chroot
     395             : ********************************************************************/
     396             : #ifndef HAVE_CHROOT
     397             : int rep_chroot(const char *dname)
     398             : {
     399             :         errno = ENOSYS;
     400             :         return -1;
     401             : }
     402             : #endif
     403             : 
     404             : /*****************************************************************
     405             :  Possibly replace mkstemp if it is broken.
     406             : *****************************************************************/  
     407             : 
     408             : #ifndef HAVE_SECURE_MKSTEMP
     409             : int rep_mkstemp(char *template)
     410             : {
     411             :         /* have a reasonable go at emulating it. Hope that
     412             :            the system mktemp() isn't completely hopeless */
     413             :         mktemp(template);
     414             :         if (template[0] == 0)
     415             :                 return -1;
     416             :         return open(template, O_CREAT|O_EXCL|O_RDWR, 0600);
     417             : }
     418             : #endif
     419             : 
     420             : #ifndef HAVE_MKDTEMP
     421             : char *rep_mkdtemp(char *template)
     422             : {
     423             :         char *dname;
     424             :         
     425             :         if ((dname = mktemp(template))) {
     426             :                 if (mkdir(dname, 0700) >= 0) {
     427             :                         return dname;
     428             :                 }
     429             :         }
     430             : 
     431             :         return NULL;
     432             : }
     433             : #endif
     434             : 
     435             : /*****************************************************************
     436             :  Watch out: this is not thread safe.
     437             : *****************************************************************/
     438             : 
     439             : #ifndef HAVE_PREAD
     440             : ssize_t rep_pread(int __fd, void *__buf, size_t __nbytes, off_t __offset)
     441             : {
     442             :         if (lseek(__fd, __offset, SEEK_SET) != __offset) {
     443             :                 return -1;
     444             :         }
     445             :         return read(__fd, __buf, __nbytes);
     446             : }
     447             : #endif
     448             : 
     449             : /*****************************************************************
     450             :  Watch out: this is not thread safe.
     451             : *****************************************************************/
     452             : 
     453             : #ifndef HAVE_PWRITE
     454             : ssize_t rep_pwrite(int __fd, const void *__buf, size_t __nbytes, off_t __offset)
     455             : {
     456             :         if (lseek(__fd, __offset, SEEK_SET) != __offset) {
     457             :                 return -1;
     458             :         }
     459             :         return write(__fd, __buf, __nbytes);
     460             : }
     461             : #endif
     462             : 
     463             : #ifndef HAVE_STRCASESTR
     464             : char *rep_strcasestr(const char *haystack, const char *needle)
     465             : {
     466             :         const char *s;
     467             :         size_t nlen = strlen(needle);
     468             :         for (s=haystack;*s;s++) {
     469             :                 if (toupper(*needle) == toupper(*s) &&
     470             :                     strncasecmp(s, needle, nlen) == 0) {
     471             :                         return (char *)((uintptr_t)s);
     472             :                 }
     473             :         }
     474             :         return NULL;
     475             : }
     476             : #endif
     477             : 
     478             : #ifndef HAVE_STRSEP
     479             : char *rep_strsep(char **pps, const char *delim)
     480             : {
     481             :         char *ret = *pps;
     482             :         char *p = *pps;
     483             : 
     484             :         if (p == NULL) {
     485             :                 return NULL;
     486             :         }
     487             :         p += strcspn(p, delim);
     488             :         if (*p == '\0') {
     489             :                 *pps = NULL;
     490             :         } else {
     491             :                 *p = '\0';
     492             :                 *pps = p + 1;
     493             :         }
     494             :         return ret;
     495             : }
     496             : #endif
     497             : 
     498             : #ifndef HAVE_STRTOK_R
     499             : /* based on GLIBC version, copyright Free Software Foundation */
     500             : char *rep_strtok_r(char *s, const char *delim, char **save_ptr)
     501             : {
     502             :         char *token;
     503             : 
     504             :         if (s == NULL) s = *save_ptr;
     505             : 
     506             :         s += strspn(s, delim);
     507             :         if (*s == '\0') {
     508             :                 *save_ptr = s;
     509             :                 return NULL;
     510             :         }
     511             : 
     512             :         token = s;
     513             :         s = strpbrk(token, delim);
     514             :         if (s == NULL) {
     515             :                 *save_ptr = token + strlen(token);
     516             :         } else {
     517             :                 *s = '\0';
     518             :                 *save_ptr = s + 1;
     519             :         }
     520             : 
     521             :         return token;
     522             : }
     523             : #endif
     524             : 
     525             : 
     526             : #ifndef HAVE_STRTOLL
     527             : long long int rep_strtoll(const char *str, char **endptr, int base)
     528             : {
     529             : #ifdef HAVE_STRTOQ
     530             :         return strtoq(str, endptr, base);
     531             : #elif defined(HAVE___STRTOLL) 
     532             :         return __strtoll(str, endptr, base);
     533             : #elif SIZEOF_LONG == SIZEOF_LONG_LONG
     534             :         return (long long int) strtol(str, endptr, base);
     535             : #else
     536             : # error "You need a strtoll function"
     537             : #endif
     538             : }
     539             : #else
     540             : #ifdef HAVE_BSD_STRTOLL
     541             : #undef strtoll
     542             : long long int rep_strtoll(const char *str, char **endptr, int base)
     543             : {
     544             :         int saved_errno = errno;
     545             :         long long int nb = strtoll(str, endptr, base);
     546             :         /* With glibc EINVAL is only returned if base is not ok */
     547             :         if (errno == EINVAL) {
     548             :                 if (base == 0 || (base >1 && base <37)) {
     549             :                         /* Base was ok so it's because we were not
     550             :                          * able to make the conversion.
     551             :                          * Let's reset errno.
     552             :                          */
     553             :                         errno = saved_errno;
     554             :                 }
     555             :         }
     556             :         return nb;
     557             : }
     558             : #endif /* HAVE_BSD_STRTOLL */
     559             : #endif /* HAVE_STRTOLL */
     560             : 
     561             : 
     562             : #ifndef HAVE_STRTOULL
     563             : unsigned long long int rep_strtoull(const char *str, char **endptr, int base)
     564             : {
     565             : #ifdef HAVE_STRTOUQ
     566             :         return strtouq(str, endptr, base);
     567             : #elif defined(HAVE___STRTOULL) 
     568             :         return __strtoull(str, endptr, base);
     569             : #elif SIZEOF_LONG == SIZEOF_LONG_LONG
     570             :         return (unsigned long long int) strtoul(str, endptr, base);
     571             : #else
     572             : # error "You need a strtoull function"
     573             : #endif
     574             : }
     575             : #else
     576             : #ifdef HAVE_BSD_STRTOLL
     577             : #undef strtoull
     578             : unsigned long long int rep_strtoull(const char *str, char **endptr, int base)
     579             : {
     580             :         int saved_errno = errno;
     581             :         unsigned long long int nb = strtoull(str, endptr, base);
     582             :         /* With glibc EINVAL is only returned if base is not ok */
     583             :         if (errno == EINVAL) {
     584             :                 if (base == 0 || (base >1 && base <37)) {
     585             :                         /* Base was ok so it's because we were not
     586             :                          * able to make the conversion.
     587             :                          * Let's reset errno.
     588             :                          */
     589             :                         errno = saved_errno;
     590             :                 }
     591             :         }
     592             :         return nb;
     593             : }
     594             : #endif /* HAVE_BSD_STRTOLL */
     595             : #endif /* HAVE_STRTOULL */
     596             : 
     597             : #ifndef HAVE_SETENV
     598             : int rep_setenv(const char *name, const char *value, int overwrite) 
     599             : {
     600             :         char *p;
     601             :         size_t l1, l2;
     602             :         int ret;
     603             : 
     604             :         if (!overwrite && getenv(name)) {
     605             :                 return 0;
     606             :         }
     607             : 
     608             :         l1 = strlen(name);
     609             :         l2 = strlen(value);
     610             : 
     611             :         p = malloc(l1+l2+2);
     612             :         if (p == NULL) {
     613             :                 return -1;
     614             :         }
     615             :         memcpy(p, name, l1);
     616             :         p[l1] = '=';
     617             :         memcpy(p+l1+1, value, l2);
     618             :         p[l1+l2+1] = 0;
     619             : 
     620             :         ret = putenv(p);
     621             :         if (ret != 0) {
     622             :                 free(p);
     623             :         }
     624             : 
     625             :         return ret;
     626             : }
     627             : #endif
     628             : 
     629             : #ifndef HAVE_UNSETENV
     630             : int rep_unsetenv(const char *name)
     631             : {
     632             :         extern char **environ;
     633             :         size_t len = strlen(name);
     634             :         size_t i, count;
     635             : 
     636             :         if (environ == NULL || getenv(name) == NULL) {
     637             :                 return 0;
     638             :         }
     639             : 
     640             :         for (i=0;environ[i];i++) /* noop */ ;
     641             : 
     642             :         count=i;
     643             :         
     644             :         for (i=0;i<count;) {
     645             :                 if (strncmp(environ[i], name, len) == 0 && environ[i][len] == '=') {
     646             :                         /* note: we do _not_ free the old variable here. It is unsafe to 
     647             :                            do so, as the pointer may not have come from malloc */
     648             :                         memmove(&environ[i], &environ[i+1], (count-i)*sizeof(char *));
     649             :                         count--;
     650             :                 } else {
     651             :                         i++;
     652             :                 }
     653             :         }
     654             : 
     655             :         return 0;
     656             : }
     657             : #endif
     658             : 
     659             : #ifndef HAVE_UTIME
     660             : int rep_utime(const char *filename, const struct utimbuf *buf)
     661             : {
     662             :         errno = ENOSYS;
     663             :         return -1;
     664             : }
     665             : #endif
     666             : 
     667             : #ifndef HAVE_UTIMES
     668             : int rep_utimes(const char *filename, const struct timeval tv[2])
     669             : {
     670             :         struct utimbuf u;
     671             : 
     672             :         u.actime = tv[0].tv_sec;
     673             :         if (tv[0].tv_usec > 500000) {
     674             :                 u.actime += 1;
     675             :         }
     676             : 
     677             :         u.modtime = tv[1].tv_sec;
     678             :         if (tv[1].tv_usec > 500000) {
     679             :                 u.modtime += 1;
     680             :         }
     681             : 
     682             :         return utime(filename, &u);
     683             : }
     684             : #endif
     685             : 
     686             : #ifndef HAVE_DUP2
     687             : int rep_dup2(int oldfd, int newfd) 
     688             : {
     689             :         errno = ENOSYS;
     690             :         return -1;
     691             : }
     692             : #endif
     693             : 
     694             : #ifndef HAVE_CHOWN
     695             : /**
     696             : chown isn't used much but OS/2 doesn't have it
     697             : **/
     698             : int rep_chown(const char *fname, uid_t uid, gid_t gid)
     699             : {
     700             :         errno = ENOSYS;
     701             :         return -1;
     702             : }
     703             : #endif
     704             : 
     705             : #ifndef HAVE_LINK
     706             : int rep_link(const char *oldpath, const char *newpath)
     707             : {
     708             :         errno = ENOSYS;
     709             :         return -1;
     710             : }
     711             : #endif
     712             : 
     713             : #ifndef HAVE_READLINK
     714             : int rep_readlink(const char *path, char *buf, size_t bufsiz)
     715             : {
     716             :         errno = ENOSYS;
     717             :         return -1;
     718             : }
     719             : #endif
     720             : 
     721             : #ifndef HAVE_SYMLINK
     722             : int rep_symlink(const char *oldpath, const char *newpath)
     723             : {
     724             :         errno = ENOSYS;
     725             :         return -1;
     726             : }
     727             : #endif
     728             : 
     729             : #ifndef HAVE_LCHOWN
     730             : int rep_lchown(const char *fname,uid_t uid,gid_t gid)
     731             : {
     732             :         errno = ENOSYS;
     733             :         return -1;
     734             : }
     735             : #endif
     736             : 
     737             : #ifndef HAVE_REALPATH
     738             : char *rep_realpath(const char *path, char *resolved_path)
     739             : {
     740             :         /* As realpath is not a system call we can't return ENOSYS. */
     741             :         errno = EINVAL;
     742             :         return NULL;
     743             : }
     744             : #endif
     745             : 
     746             : 
     747             : #ifndef HAVE_MEMMEM
     748             : void *rep_memmem(const void *haystack, size_t haystacklen,
     749             :                  const void *needle, size_t needlelen)
     750             : {
     751             :         if (needlelen == 0) {
     752             :                 return discard_const(haystack);
     753             :         }
     754             :         while (haystacklen >= needlelen) {
     755             :                 char *p = (char *)memchr(haystack, *(const char *)needle,
     756             :                                          haystacklen-(needlelen-1));
     757             :                 if (!p) return NULL;
     758             :                 if (memcmp(p, needle, needlelen) == 0) {
     759             :                         return p;
     760             :                 }
     761             :                 haystack = p+1;
     762             :                 haystacklen -= (p - (const char *)haystack) + 1;
     763             :         }
     764             :         return NULL;
     765             : }
     766             : #endif
     767             : 
     768             : #if !defined(HAVE_VDPRINTF) || !defined(HAVE_C99_VSNPRINTF)
     769             : int rep_vdprintf(int fd, const char *format, va_list ap)
     770             : {
     771             :         char *s = NULL;
     772             :         int ret;
     773             : 
     774             :         vasprintf(&s, format, ap);
     775             :         if (s == NULL) {
     776             :                 errno = ENOMEM;
     777             :                 return -1;
     778             :         }
     779             :         ret = write(fd, s, strlen(s));
     780             :         free(s);
     781             :         return ret;
     782             : }
     783             : #endif
     784             : 
     785             : #if !defined(HAVE_DPRINTF) || !defined(HAVE_C99_VSNPRINTF)
     786             : int rep_dprintf(int fd, const char *format, ...)
     787             : {
     788             :         int ret;
     789             :         va_list ap;
     790             : 
     791             :         va_start(ap, format);
     792             :         ret = vdprintf(fd, format, ap);
     793             :         va_end(ap);
     794             : 
     795             :         return ret;
     796             : }
     797             : #endif
     798             : 
     799             : #ifndef HAVE_GET_CURRENT_DIR_NAME
     800             : char *rep_get_current_dir_name(void)
     801             : {
     802             :         char buf[PATH_MAX+1];
     803             :         char *p;
     804             :         p = getcwd(buf, sizeof(buf));
     805             :         if (p == NULL) {
     806             :                 return NULL;
     807             :         }
     808             :         return strdup(p);
     809             : }
     810             : #endif
     811             : 
     812             : #ifndef HAVE_STRERROR_R
     813             : int rep_strerror_r(int errnum, char *buf, size_t buflen)
     814             : {
     815             :         char *s = strerror(errnum);
     816             :         if (strlen(s)+1 > buflen) {
     817             :                 errno = ERANGE;
     818             :                 return -1;
     819             :         }
     820             :         strncpy(buf, s, buflen);
     821             :         return 0;
     822             : }
     823             : #elif (!defined(STRERROR_R_XSI_NOT_GNU))
     824             : #undef strerror_r
     825       33856 : int rep_strerror_r(int errnum, char *buf, size_t buflen)
     826             : {
     827       33856 :         char *s = strerror_r(errnum, buf, buflen);
     828       33856 :         if (s == NULL) {
     829             :                 /* Shouldn't happen, should always get a string */
     830           0 :                 return EINVAL;
     831             :         }
     832       33856 :         if (s != buf) {
     833       33856 :                 strlcpy(buf, s, buflen);
     834       33856 :                 if (strlen(s) > buflen - 1) {
     835           0 :                         return ERANGE;
     836             :                 }
     837             :         }
     838       32993 :         return 0;
     839             : 
     840             : }
     841             : #endif
     842             : 
     843             : #ifndef HAVE_CLOCK_GETTIME
     844             : int rep_clock_gettime(clockid_t clk_id, struct timespec *tp)
     845             : {
     846             :         struct timeval tval;
     847             :         switch (clk_id) {
     848             :                 case 0: /* CLOCK_REALTIME :*/
     849             : #if defined(HAVE_GETTIMEOFDAY_TZ) || defined(HAVE_GETTIMEOFDAY_TZ_VOID)
     850             :                         gettimeofday(&tval,NULL);
     851             : #else
     852             :                         gettimeofday(&tval);
     853             : #endif
     854             :                         tp->tv_sec = tval.tv_sec;
     855             :                         tp->tv_nsec = tval.tv_usec * 1000;
     856             :                         break;
     857             :                 default:
     858             :                         errno = EINVAL;
     859             :                         return -1;
     860             :         }
     861             :         return 0;
     862             : }
     863             : #endif
     864             : 
     865             : #ifndef HAVE_MEMALIGN
     866             : void *rep_memalign( size_t align, size_t size )
     867             : {
     868             : #if defined(HAVE_POSIX_MEMALIGN)
     869             :         void *p = NULL;
     870             :         int ret = posix_memalign( &p, align, size );
     871             :         if ( ret == 0 )
     872             :                 return p;
     873             : 
     874             :         return NULL;
     875             : #else
     876             :         /* On *BSD systems memaligns doesn't exist, but memory will
     877             :          * be aligned on allocations of > pagesize. */
     878             : #if defined(SYSCONF_SC_PAGESIZE)
     879             :         size_t pagesize = (size_t)sysconf(_SC_PAGESIZE);
     880             : #elif defined(HAVE_GETPAGESIZE)
     881             :         size_t pagesize = (size_t)getpagesize();
     882             : #else
     883             :         size_t pagesize = (size_t)-1;
     884             : #endif
     885             :         if (pagesize == (size_t)-1) {
     886             :                 errno = ENOSYS;
     887             :                 return NULL;
     888             :         }
     889             :         if (size < pagesize) {
     890             :                 size = pagesize;
     891             :         }
     892             :         return malloc(size);
     893             : #endif
     894             : }
     895             : #endif
     896             : 
     897             : #ifndef HAVE_GETPEEREID
     898             : int rep_getpeereid(int s, uid_t *uid, gid_t *gid)
     899             : {
     900             : #if defined(HAVE_PEERCRED)
     901             :         struct ucred cred;
     902             :         socklen_t cred_len = sizeof(struct ucred);
     903             :         int ret;
     904             : 
     905             : #undef getsockopt
     906             :         ret = getsockopt(s, SOL_SOCKET, SO_PEERCRED, (void *)&cred, &cred_len);
     907             :         if (ret != 0) {
     908             :                 return -1;
     909             :         }
     910             : 
     911             :         if (cred_len != sizeof(struct ucred)) {
     912             :                 errno = EINVAL;
     913             :                 return -1;
     914             :         }
     915             : 
     916             :         *uid = cred.uid;
     917             :         *gid = cred.gid;
     918             :         return 0;
     919             : #else
     920             :         errno = ENOSYS;
     921             :         return -1;
     922             : #endif
     923             : }
     924             : #endif
     925             : 
     926             : #ifndef HAVE_USLEEP
     927             : int rep_usleep(useconds_t sec)
     928             : {
     929             :         struct timeval tval;
     930             :         /*
     931             :          * Fake it with select...
     932             :          */
     933             :         tval.tv_sec = 0;
     934             :         tval.tv_usec = usecs/1000;
     935             :         select(0,NULL,NULL,NULL,&tval);
     936             :         return 0;
     937             : }
     938             : #endif /* HAVE_USLEEP */
     939             : 
     940             : #ifndef HAVE_SETPROCTITLE
     941             : void rep_setproctitle(const char *fmt, ...)
     942             : {
     943             : }
     944             : #endif
     945             : #ifndef HAVE_SETPROCTITLE_INIT
     946             : void rep_setproctitle_init(int argc, char *argv[], char *envp[])
     947             : {
     948             : }
     949             : #endif
     950             : 
     951             : #ifndef HAVE_MEMSET_S
     952             : # ifndef RSIZE_MAX
     953             : #  define RSIZE_MAX (SIZE_MAX >> 1)
     954             : # endif
     955             : 
     956   875852079 : int rep_memset_s(void *dest, size_t destsz, int ch, size_t count)
     957             : {
     958   875852079 :         if (dest == NULL) {
     959           0 :                 return EINVAL;
     960             :         }
     961             : 
     962  1608325625 :         if (destsz > RSIZE_MAX ||
     963  1608325625 :             count > RSIZE_MAX ||
     964             :             count > destsz) {
     965           0 :                 return ERANGE;
     966             :         }
     967             : 
     968             : #if defined(HAVE_MEMSET_EXPLICIT)
     969             :         memset_explicit(dest, destsz, ch, count);
     970             : #else /* HAVE_MEMSET_EXPLICIT */
     971   875852079 :         memset(dest, ch, count);
     972             : # if defined(HAVE_GCC_VOLATILE_MEMORY_PROTECTION)
     973             :         /* See http://llvm.org/bugs/show_bug.cgi?id=15495 */
     974   875852079 :         __asm__ volatile("" : : "g"(dest) : "memory");
     975             : # endif /* HAVE_GCC_VOLATILE_MEMORY_PROTECTION */
     976             : #endif /* HAVE_MEMSET_EXPLICIT */
     977             : 
     978   875852080 :         return 0;
     979             : }
     980             : #endif /* HAVE_MEMSET_S */
     981             : 
     982             : #ifndef HAVE_GETPROGNAME
     983             : # ifndef HAVE_PROGRAM_INVOCATION_SHORT_NAME
     984             : # define PROGNAME_SIZE 32
     985             : static char rep_progname[PROGNAME_SIZE];
     986             : # endif /* HAVE_PROGRAM_INVOCATION_SHORT_NAME */
     987             : 
     988      170181 : const char *rep_getprogname(void)
     989             : {
     990             : #ifdef HAVE_PROGRAM_INVOCATION_SHORT_NAME
     991      170181 :         return program_invocation_short_name;
     992             : #else /* HAVE_PROGRAM_INVOCATION_SHORT_NAME */
     993             :         FILE *fp = NULL;
     994             :         char cmdline[4096] = {0};
     995             :         char *p = NULL;
     996             :         pid_t pid;
     997             :         size_t nread;
     998             :         int len;
     999             :         int rc;
    1000             : 
    1001             :         if (rep_progname[0] != '\0') {
    1002             :                 return rep_progname;
    1003             :         }
    1004             : 
    1005             :         len = snprintf(rep_progname, sizeof(rep_progname), "%s", "<unknown>");
    1006             :         if (len <= 0) {
    1007             :                 return NULL;
    1008             :         }
    1009             : 
    1010             :         pid = getpid();
    1011             :         if (pid <= 1 || pid == (pid_t)-1) {
    1012             :                 return NULL;
    1013             :         }
    1014             : 
    1015             :         len = snprintf(cmdline,
    1016             :                        sizeof(cmdline),
    1017             :                        "/proc/%u/cmdline",
    1018             :                        (unsigned int)pid);
    1019             :         if (len <= 0 || len == sizeof(cmdline)) {
    1020             :                 return NULL;
    1021             :         }
    1022             : 
    1023             :         fp = fopen(cmdline, "r");
    1024             :         if (fp == NULL) {
    1025             :                 return NULL;
    1026             :         }
    1027             : 
    1028             :         nread = fread(cmdline, 1, sizeof(cmdline) - 1, fp);
    1029             : 
    1030             :         rc = fclose(fp);
    1031             :         if (rc != 0) {
    1032             :                 return NULL;
    1033             :         }
    1034             : 
    1035             :         if (nread == 0) {
    1036             :                 return NULL;
    1037             :         }
    1038             : 
    1039             :         cmdline[nread] = '\0';
    1040             : 
    1041             :         p = strrchr(cmdline, '/');
    1042             :         if (p != NULL) {
    1043             :                 p++;
    1044             :         } else {
    1045             :                 p = cmdline;
    1046             :         }
    1047             : 
    1048             :         len = strlen(p);
    1049             :         if (len > PROGNAME_SIZE) {
    1050             :                 p[PROGNAME_SIZE - 1] = '\0';
    1051             :         }
    1052             : 
    1053             :         (void)snprintf(rep_progname, sizeof(rep_progname), "%s", p);
    1054             : 
    1055             :         return rep_progname;
    1056             : #endif /* HAVE_PROGRAM_INVOCATION_SHORT_NAME */
    1057             : }
    1058             : #endif /* HAVE_GETPROGNAME */
    1059             : 
    1060             : #ifndef HAVE_COPY_FILE_RANGE
    1061             : # ifdef HAVE_SYSCALL_COPY_FILE_RANGE
    1062             : # include <sys/syscall.h>
    1063             : # endif
    1064             : ssize_t rep_copy_file_range(int fd_in,
    1065             :                             loff_t *off_in,
    1066             :                             int fd_out,
    1067             :                             loff_t *off_out,
    1068             :                             size_t len,
    1069             :                             unsigned int flags)
    1070             : {
    1071             : # ifdef HAVE_SYSCALL_COPY_FILE_RANGE
    1072             :         return syscall(__NR_copy_file_range,
    1073             :                        fd_in,
    1074             :                        off_in,
    1075             :                        fd_out,
    1076             :                        off_out,
    1077             :                        len,
    1078             :                        flags);
    1079             : # endif /* HAVE_SYSCALL_COPY_FILE_RANGE */
    1080             :         errno = ENOSYS;
    1081             :         return -1;
    1082             : }
    1083             : #endif /* HAVE_COPY_FILE_RANGE */

Generated by: LCOV version 1.13