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

Generated by: LCOV version 1.14