| 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/passwd.h"
 | 
|---|
| 31 | #include "system/syslog.h"
 | 
|---|
| 32 | #include "system/locale.h"
 | 
|---|
| 33 | #include "system/wait.h"
 | 
|---|
| 34 | 
 | 
|---|
| 35 | #ifdef _WIN32
 | 
|---|
| 36 | #define mkdir(d,m) _mkdir(d)
 | 
|---|
| 37 | #endif
 | 
|---|
| 38 | 
 | 
|---|
| 39 | void replace_dummy(void);
 | 
|---|
| 40 | void replace_dummy(void) {}
 | 
|---|
| 41 | 
 | 
|---|
| 42 | #ifndef HAVE_FTRUNCATE
 | 
|---|
| 43 |  /*******************************************************************
 | 
|---|
| 44 | ftruncate for operating systems that don't have it
 | 
|---|
| 45 | ********************************************************************/
 | 
|---|
| 46 | int rep_ftruncate(int f, off_t l)
 | 
|---|
| 47 | {
 | 
|---|
| 48 | #ifdef HAVE_CHSIZE
 | 
|---|
| 49 |       return chsize(f,l);
 | 
|---|
| 50 | #elif defined(F_FREESP)
 | 
|---|
| 51 |       struct  flock   fl;
 | 
|---|
| 52 | 
 | 
|---|
| 53 |       fl.l_whence = 0;
 | 
|---|
| 54 |       fl.l_len = 0;
 | 
|---|
| 55 |       fl.l_start = l;
 | 
|---|
| 56 |       fl.l_type = F_WRLCK;
 | 
|---|
| 57 |       return fcntl(f, F_FREESP, &fl);
 | 
|---|
| 58 | #else
 | 
|---|
| 59 | #error "you must have a ftruncate function"
 | 
|---|
| 60 | #endif
 | 
|---|
| 61 | }
 | 
|---|
| 62 | #endif /* HAVE_FTRUNCATE */
 | 
|---|
| 63 | 
 | 
|---|
| 64 | 
 | 
|---|
| 65 | #ifndef HAVE_STRLCPY
 | 
|---|
| 66 | /* like strncpy but does not 0 fill the buffer and always null 
 | 
|---|
| 67 |    terminates. bufsize is the size of the destination buffer */
 | 
|---|
| 68 | size_t rep_strlcpy(char *d, const char *s, size_t bufsize)
 | 
|---|
| 69 | {
 | 
|---|
| 70 |         size_t len = strlen(s);
 | 
|---|
| 71 |         size_t ret = len;
 | 
|---|
| 72 |         if (bufsize <= 0) return 0;
 | 
|---|
| 73 |         if (len >= bufsize) len = bufsize-1;
 | 
|---|
| 74 |         memcpy(d, s, len);
 | 
|---|
| 75 |         d[len] = 0;
 | 
|---|
| 76 |         return ret;
 | 
|---|
| 77 | }
 | 
|---|
| 78 | #endif
 | 
|---|
| 79 | 
 | 
|---|
| 80 | #ifndef HAVE_STRLCAT
 | 
|---|
| 81 | /* like strncat but does not 0 fill the buffer and always null 
 | 
|---|
| 82 |    terminates. bufsize is the length of the buffer, which should
 | 
|---|
| 83 |    be one more than the maximum resulting string length */
 | 
|---|
| 84 | size_t rep_strlcat(char *d, const char *s, size_t bufsize)
 | 
|---|
| 85 | {
 | 
|---|
| 86 |         size_t len1 = strlen(d);
 | 
|---|
| 87 |         size_t len2 = strlen(s);
 | 
|---|
| 88 |         size_t ret = len1 + len2;
 | 
|---|
| 89 | 
 | 
|---|
| 90 |         if (len1+len2 >= bufsize) {
 | 
|---|
| 91 |                 if (bufsize < (len1+1)) {
 | 
|---|
| 92 |                         return ret;
 | 
|---|
| 93 |                 }
 | 
|---|
| 94 |                 len2 = bufsize - (len1+1);
 | 
|---|
| 95 |         }
 | 
|---|
| 96 |         if (len2 > 0) {
 | 
|---|
| 97 |                 memcpy(d+len1, s, len2);
 | 
|---|
| 98 |                 d[len1+len2] = 0;
 | 
|---|
| 99 |         }
 | 
|---|
| 100 |         return ret;
 | 
|---|
| 101 | }
 | 
|---|
| 102 | #endif
 | 
|---|
| 103 | 
 | 
|---|
| 104 | #ifndef HAVE_MKTIME
 | 
|---|
| 105 | /*******************************************************************
 | 
|---|
| 106 | a mktime() replacement for those who don't have it - contributed by 
 | 
|---|
| 107 | C.A. Lademann <cal@zls.com>
 | 
|---|
| 108 | Corrections by richard.kettlewell@kewill.com
 | 
|---|
| 109 | ********************************************************************/
 | 
|---|
| 110 | 
 | 
|---|
| 111 | #define  MINUTE  60
 | 
|---|
| 112 | #define  HOUR    60*MINUTE
 | 
|---|
| 113 | #define  DAY             24*HOUR
 | 
|---|
| 114 | #define  YEAR    365*DAY
 | 
|---|
| 115 | time_t rep_mktime(struct tm *t)
 | 
|---|
| 116 | {
 | 
|---|
| 117 |   struct tm       *u;
 | 
|---|
| 118 |   time_t  epoch = 0;
 | 
|---|
| 119 |   int n;
 | 
|---|
| 120 |   int             mon [] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
 | 
|---|
| 121 |   y, m, i;
 | 
|---|
| 122 | 
 | 
|---|
| 123 |   if(t->tm_year < 70)
 | 
|---|
| 124 |     return((time_t)-1);
 | 
|---|
| 125 | 
 | 
|---|
| 126 |   n = t->tm_year + 1900 - 1;
 | 
|---|
| 127 |   epoch = (t->tm_year - 70) * YEAR + 
 | 
|---|
| 128 |     ((n / 4 - n / 100 + n / 400) - (1969 / 4 - 1969 / 100 + 1969 / 400)) * DAY;
 | 
|---|
| 129 | 
 | 
|---|
| 130 |   y = t->tm_year + 1900;
 | 
|---|
| 131 |   m = 0;
 | 
|---|
| 132 | 
 | 
|---|
| 133 |   for(i = 0; i < t->tm_mon; i++) {
 | 
|---|
| 134 |     epoch += mon [m] * DAY;
 | 
|---|
| 135 |     if(m == 1 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0))
 | 
|---|
| 136 |       epoch += DAY;
 | 
|---|
| 137 |     
 | 
|---|
| 138 |     if(++m > 11) {
 | 
|---|
| 139 |       m = 0;
 | 
|---|
| 140 |       y++;
 | 
|---|
| 141 |     }
 | 
|---|
| 142 |   }
 | 
|---|
| 143 | 
 | 
|---|
| 144 |   epoch += (t->tm_mday - 1) * DAY;
 | 
|---|
| 145 |   epoch += t->tm_hour * HOUR + t->tm_min * MINUTE + t->tm_sec;
 | 
|---|
| 146 |   
 | 
|---|
| 147 |   if((u = localtime(&epoch)) != NULL) {
 | 
|---|
| 148 |     t->tm_sec = u->tm_sec;
 | 
|---|
| 149 |     t->tm_min = u->tm_min;
 | 
|---|
| 150 |     t->tm_hour = u->tm_hour;
 | 
|---|
| 151 |     t->tm_mday = u->tm_mday;
 | 
|---|
| 152 |     t->tm_mon = u->tm_mon;
 | 
|---|
| 153 |     t->tm_year = u->tm_year;
 | 
|---|
| 154 |     t->tm_wday = u->tm_wday;
 | 
|---|
| 155 |     t->tm_yday = u->tm_yday;
 | 
|---|
| 156 |     t->tm_isdst = u->tm_isdst;
 | 
|---|
| 157 |   }
 | 
|---|
| 158 | 
 | 
|---|
| 159 |   return(epoch);
 | 
|---|
| 160 | }
 | 
|---|
| 161 | #endif /* !HAVE_MKTIME */
 | 
|---|
| 162 | 
 | 
|---|
| 163 | 
 | 
|---|
| 164 | #ifndef HAVE_INITGROUPS
 | 
|---|
| 165 | /****************************************************************************
 | 
|---|
| 166 |  some systems don't have an initgroups call 
 | 
|---|
| 167 | ****************************************************************************/
 | 
|---|
| 168 | int rep_initgroups(char *name, gid_t id)
 | 
|---|
| 169 | {
 | 
|---|
| 170 | #ifndef HAVE_SETGROUPS
 | 
|---|
| 171 |         /* yikes! no SETGROUPS or INITGROUPS? how can this work? */
 | 
|---|
| 172 |         errno = ENOSYS;
 | 
|---|
| 173 |         return -1;
 | 
|---|
| 174 | #else /* HAVE_SETGROUPS */
 | 
|---|
| 175 | 
 | 
|---|
| 176 | #include <grp.h>
 | 
|---|
| 177 | 
 | 
|---|
| 178 |         gid_t *grouplst = NULL;
 | 
|---|
| 179 |         int max_gr = NGROUPS_MAX;
 | 
|---|
| 180 |         int ret;
 | 
|---|
| 181 |         int    i,j;
 | 
|---|
| 182 |         struct group *g;
 | 
|---|
| 183 |         char   *gr;
 | 
|---|
| 184 |         
 | 
|---|
| 185 |         if((grouplst = malloc(sizeof(gid_t) * max_gr)) == NULL) {
 | 
|---|
| 186 |                 errno = ENOMEM;
 | 
|---|
| 187 |                 return -1;
 | 
|---|
| 188 |         }
 | 
|---|
| 189 | 
 | 
|---|
| 190 |         grouplst[0] = id;
 | 
|---|
| 191 |         i = 1;
 | 
|---|
| 192 |         while (i < max_gr && ((g = (struct group *)getgrent()) != (struct group *)NULL)) {
 | 
|---|
| 193 |                 if (g->gr_gid == id)
 | 
|---|
| 194 |                         continue;
 | 
|---|
| 195 |                 j = 0;
 | 
|---|
| 196 |                 gr = g->gr_mem[0];
 | 
|---|
| 197 |                 while (gr && (*gr != (char)NULL)) {
 | 
|---|
| 198 |                         if (strcmp(name,gr) == 0) {
 | 
|---|
| 199 |                                 grouplst[i] = g->gr_gid;
 | 
|---|
| 200 |                                 i++;
 | 
|---|
| 201 |                                 gr = (char *)NULL;
 | 
|---|
| 202 |                                 break;
 | 
|---|
| 203 |                         }
 | 
|---|
| 204 |                         gr = g->gr_mem[++j];
 | 
|---|
| 205 |                 }
 | 
|---|
| 206 |         }
 | 
|---|
| 207 |         endgrent();
 | 
|---|
| 208 |         ret = setgroups(i, grouplst);
 | 
|---|
| 209 |         free(grouplst);
 | 
|---|
| 210 |         return ret;
 | 
|---|
| 211 | #endif /* HAVE_SETGROUPS */
 | 
|---|
| 212 | }
 | 
|---|
| 213 | #endif /* HAVE_INITGROUPS */
 | 
|---|
| 214 | 
 | 
|---|
| 215 | 
 | 
|---|
| 216 | #if (defined(SecureWare) && defined(SCO))
 | 
|---|
| 217 | /* This is needed due to needing the nap() function but we don't want
 | 
|---|
| 218 |    to include the Xenix libraries since that will break other things...
 | 
|---|
| 219 |    BTW: system call # 0x0c28 is the same as calling nap() */
 | 
|---|
| 220 | long nap(long milliseconds) {
 | 
|---|
| 221 |          return syscall(0x0c28, milliseconds);
 | 
|---|
| 222 |  }
 | 
|---|
| 223 | #endif
 | 
|---|
| 224 | 
 | 
|---|
| 225 | 
 | 
|---|
| 226 | #ifndef HAVE_MEMMOVE
 | 
|---|
| 227 | /*******************************************************************
 | 
|---|
| 228 | safely copies memory, ensuring no overlap problems.
 | 
|---|
| 229 | this is only used if the machine does not have its own memmove().
 | 
|---|
| 230 | this is not the fastest algorithm in town, but it will do for our
 | 
|---|
| 231 | needs.
 | 
|---|
| 232 | ********************************************************************/
 | 
|---|
| 233 | void *rep_memmove(void *dest,const void *src,int size)
 | 
|---|
| 234 | {
 | 
|---|
| 235 |         unsigned long d,s;
 | 
|---|
| 236 |         int i;
 | 
|---|
| 237 |         if (dest==src || !size) return(dest);
 | 
|---|
| 238 | 
 | 
|---|
| 239 |         d = (unsigned long)dest;
 | 
|---|
| 240 |         s = (unsigned long)src;
 | 
|---|
| 241 | 
 | 
|---|
| 242 |         if ((d >= (s+size)) || (s >= (d+size))) {
 | 
|---|
| 243 |                 /* no overlap */
 | 
|---|
| 244 |                 memcpy(dest,src,size);
 | 
|---|
| 245 |                 return(dest);
 | 
|---|
| 246 |         }
 | 
|---|
| 247 | 
 | 
|---|
| 248 |         if (d < s) {
 | 
|---|
| 249 |                 /* we can forward copy */
 | 
|---|
| 250 |                 if (s-d >= sizeof(int) && 
 | 
|---|
| 251 |                     !(s%sizeof(int)) && 
 | 
|---|
| 252 |                     !(d%sizeof(int)) && 
 | 
|---|
| 253 |                     !(size%sizeof(int))) {
 | 
|---|
| 254 |                         /* do it all as words */
 | 
|---|
| 255 |                         int *idest = (int *)dest;
 | 
|---|
| 256 |                         int *isrc = (int *)src;
 | 
|---|
| 257 |                         size /= sizeof(int);
 | 
|---|
| 258 |                         for (i=0;i<size;i++) idest[i] = isrc[i];
 | 
|---|
| 259 |                 } else {
 | 
|---|
| 260 |                         /* simplest */
 | 
|---|
| 261 |                         char *cdest = (char *)dest;
 | 
|---|
| 262 |                         char *csrc = (char *)src;
 | 
|---|
| 263 |                         for (i=0;i<size;i++) cdest[i] = csrc[i];
 | 
|---|
| 264 |                 }
 | 
|---|
| 265 |         } else {
 | 
|---|
| 266 |                 /* must backward copy */
 | 
|---|
| 267 |                 if (d-s >= sizeof(int) && 
 | 
|---|
| 268 |                     !(s%sizeof(int)) && 
 | 
|---|
| 269 |                     !(d%sizeof(int)) && 
 | 
|---|
| 270 |                     !(size%sizeof(int))) {
 | 
|---|
| 271 |                         /* do it all as words */
 | 
|---|
| 272 |                         int *idest = (int *)dest;
 | 
|---|
| 273 |                         int *isrc = (int *)src;
 | 
|---|
| 274 |                         size /= sizeof(int);
 | 
|---|
| 275 |                         for (i=size-1;i>=0;i--) idest[i] = isrc[i];
 | 
|---|
| 276 |                 } else {
 | 
|---|
| 277 |                         /* simplest */
 | 
|---|
| 278 |                         char *cdest = (char *)dest;
 | 
|---|
| 279 |                         char *csrc = (char *)src;
 | 
|---|
| 280 |                         for (i=size-1;i>=0;i--) cdest[i] = csrc[i];
 | 
|---|
| 281 |                 }      
 | 
|---|
| 282 |         }
 | 
|---|
| 283 |         return(dest);
 | 
|---|
| 284 | }
 | 
|---|
| 285 | #endif /* HAVE_MEMMOVE */
 | 
|---|
| 286 | 
 | 
|---|
| 287 | #ifndef HAVE_STRDUP
 | 
|---|
| 288 | /****************************************************************************
 | 
|---|
| 289 | duplicate a string
 | 
|---|
| 290 | ****************************************************************************/
 | 
|---|
| 291 | char *rep_strdup(const char *s)
 | 
|---|
| 292 | {
 | 
|---|
| 293 |         size_t len;
 | 
|---|
| 294 |         char *ret;
 | 
|---|
| 295 | 
 | 
|---|
| 296 |         if (!s) return(NULL);
 | 
|---|
| 297 | 
 | 
|---|
| 298 |         len = strlen(s)+1;
 | 
|---|
| 299 |         ret = (char *)malloc(len);
 | 
|---|
| 300 |         if (!ret) return(NULL);
 | 
|---|
| 301 |         memcpy(ret,s,len);
 | 
|---|
| 302 |         return(ret);
 | 
|---|
| 303 | }
 | 
|---|
| 304 | #endif /* HAVE_STRDUP */
 | 
|---|
| 305 | 
 | 
|---|
| 306 | #ifndef HAVE_SETLINEBUF
 | 
|---|
| 307 | void rep_setlinebuf(FILE *stream)
 | 
|---|
| 308 | {
 | 
|---|
| 309 |         setvbuf(stream, (char *)NULL, _IOLBF, 0);
 | 
|---|
| 310 | }
 | 
|---|
| 311 | #endif /* HAVE_SETLINEBUF */
 | 
|---|
| 312 | 
 | 
|---|
| 313 | #ifndef HAVE_VSYSLOG
 | 
|---|
| 314 | #ifdef HAVE_SYSLOG
 | 
|---|
| 315 | void rep_vsyslog (int facility_priority, const char *format, va_list arglist)
 | 
|---|
| 316 | {
 | 
|---|
| 317 |         char *msg = NULL;
 | 
|---|
| 318 |         vasprintf(&msg, format, arglist);
 | 
|---|
| 319 |         if (!msg)
 | 
|---|
| 320 |                 return;
 | 
|---|
| 321 |         syslog(facility_priority, "%s", msg);
 | 
|---|
| 322 |         free(msg);
 | 
|---|
| 323 | }
 | 
|---|
| 324 | #endif /* HAVE_SYSLOG */
 | 
|---|
| 325 | #endif /* HAVE_VSYSLOG */
 | 
|---|
| 326 | 
 | 
|---|
| 327 | #ifndef HAVE_STRNLEN
 | 
|---|
| 328 | /**
 | 
|---|
| 329 |  Some platforms don't have strnlen
 | 
|---|
| 330 | **/
 | 
|---|
| 331 |  size_t rep_strnlen(const char *s, size_t max)
 | 
|---|
| 332 | {
 | 
|---|
| 333 |         size_t len;
 | 
|---|
| 334 |   
 | 
|---|
| 335 |         for (len = 0; len < max; len++) {
 | 
|---|
| 336 |                 if (s[len] == '\0') {
 | 
|---|
| 337 |                         break;
 | 
|---|
| 338 |                 }
 | 
|---|
| 339 |         }
 | 
|---|
| 340 |         return len;  
 | 
|---|
| 341 | }
 | 
|---|
| 342 | #endif
 | 
|---|
| 343 |   
 | 
|---|
| 344 | #ifndef HAVE_STRNDUP
 | 
|---|
| 345 | /**
 | 
|---|
| 346 |  Some platforms don't have strndup.
 | 
|---|
| 347 | **/
 | 
|---|
| 348 | char *rep_strndup(const char *s, size_t n)
 | 
|---|
| 349 | {
 | 
|---|
| 350 |         char *ret;
 | 
|---|
| 351 |         
 | 
|---|
| 352 |         n = strnlen(s, n);
 | 
|---|
| 353 |         ret = malloc(n+1);
 | 
|---|
| 354 |         if (!ret)
 | 
|---|
| 355 |                 return NULL;
 | 
|---|
| 356 |         memcpy(ret, s, n);
 | 
|---|
| 357 |         ret[n] = 0;
 | 
|---|
| 358 | 
 | 
|---|
| 359 |         return ret;
 | 
|---|
| 360 | }
 | 
|---|
| 361 | #endif
 | 
|---|
| 362 | 
 | 
|---|
| 363 | #if !defined(HAVE_WAITPID) && defined(HAVE_WAIT4)
 | 
|---|
| 364 | int rep_waitpid(pid_t pid,int *status,int options)
 | 
|---|
| 365 | {
 | 
|---|
| 366 |   return wait4(pid, status, options, NULL);
 | 
|---|
| 367 | }
 | 
|---|
| 368 | #endif
 | 
|---|
| 369 | 
 | 
|---|
| 370 | #ifndef HAVE_SETEUID
 | 
|---|
| 371 | int rep_seteuid(uid_t euid)
 | 
|---|
| 372 | {
 | 
|---|
| 373 | #ifdef HAVE_SETRESUID
 | 
|---|
| 374 |         return setresuid(-1, euid, -1);
 | 
|---|
| 375 | #else
 | 
|---|
| 376 |         errno = ENOSYS;
 | 
|---|
| 377 |         return -1;
 | 
|---|
| 378 | #endif
 | 
|---|
| 379 | }
 | 
|---|
| 380 | #endif
 | 
|---|
| 381 | 
 | 
|---|
| 382 | #ifndef HAVE_SETEGID
 | 
|---|
| 383 | int rep_setegid(gid_t egid)
 | 
|---|
| 384 | {
 | 
|---|
| 385 | #ifdef HAVE_SETRESGID
 | 
|---|
| 386 |         return setresgid(-1, egid, -1);
 | 
|---|
| 387 | #else
 | 
|---|
| 388 |         errno = ENOSYS;
 | 
|---|
| 389 |         return -1;
 | 
|---|
| 390 | #endif
 | 
|---|
| 391 | }
 | 
|---|
| 392 | #endif
 | 
|---|
| 393 | 
 | 
|---|
| 394 | /*******************************************************************
 | 
|---|
| 395 | os/2 also doesn't have chroot
 | 
|---|
| 396 | ********************************************************************/
 | 
|---|
| 397 | #ifndef HAVE_CHROOT
 | 
|---|
| 398 | int rep_chroot(const char *dname)
 | 
|---|
| 399 | {
 | 
|---|
| 400 |         errno = ENOSYS;
 | 
|---|
| 401 |         return -1;
 | 
|---|
| 402 | }
 | 
|---|
| 403 | #endif
 | 
|---|
| 404 | 
 | 
|---|
| 405 | /*****************************************************************
 | 
|---|
| 406 |  Possibly replace mkstemp if it is broken.
 | 
|---|
| 407 | *****************************************************************/  
 | 
|---|
| 408 | 
 | 
|---|
| 409 | #ifndef HAVE_SECURE_MKSTEMP
 | 
|---|
| 410 | int rep_mkstemp(char *template)
 | 
|---|
| 411 | {
 | 
|---|
| 412 |         /* have a reasonable go at emulating it. Hope that
 | 
|---|
| 413 |            the system mktemp() isn't completely hopeless */
 | 
|---|
| 414 |         char *p = mktemp(template);
 | 
|---|
| 415 |         if (!p)
 | 
|---|
| 416 |                 return -1;
 | 
|---|
| 417 |         return open(p, O_CREAT|O_EXCL|O_RDWR, 0600);
 | 
|---|
| 418 | }
 | 
|---|
| 419 | #endif
 | 
|---|
| 420 | 
 | 
|---|
| 421 | #ifndef HAVE_MKDTEMP
 | 
|---|
| 422 | char *rep_mkdtemp(char *template)
 | 
|---|
| 423 | {
 | 
|---|
| 424 |         char *dname;
 | 
|---|
| 425 |         
 | 
|---|
| 426 |         if ((dname = mktemp(template))) {
 | 
|---|
| 427 |                 if (mkdir(dname, 0700) >= 0) {
 | 
|---|
| 428 |                         return dname;
 | 
|---|
| 429 |                 }
 | 
|---|
| 430 |         }
 | 
|---|
| 431 | 
 | 
|---|
| 432 |         return NULL;
 | 
|---|
| 433 | }
 | 
|---|
| 434 | #endif
 | 
|---|
| 435 | 
 | 
|---|
| 436 | /*****************************************************************
 | 
|---|
| 437 |  Watch out: this is not thread safe.
 | 
|---|
| 438 | *****************************************************************/
 | 
|---|
| 439 | 
 | 
|---|
| 440 | #ifndef HAVE_PREAD
 | 
|---|
| 441 | ssize_t rep_pread(int __fd, void *__buf, size_t __nbytes, off_t __offset)
 | 
|---|
| 442 | {
 | 
|---|
| 443 |         if (lseek(__fd, __offset, SEEK_SET) != __offset) {
 | 
|---|
| 444 |                 return -1;
 | 
|---|
| 445 |         }
 | 
|---|
| 446 |         return read(__fd, __buf, __nbytes);
 | 
|---|
| 447 | }
 | 
|---|
| 448 | #endif
 | 
|---|
| 449 | 
 | 
|---|
| 450 | /*****************************************************************
 | 
|---|
| 451 |  Watch out: this is not thread safe.
 | 
|---|
| 452 | *****************************************************************/
 | 
|---|
| 453 | 
 | 
|---|
| 454 | #ifndef HAVE_PWRITE
 | 
|---|
| 455 | ssize_t rep_pwrite(int __fd, const void *__buf, size_t __nbytes, off_t __offset)
 | 
|---|
| 456 | {
 | 
|---|
| 457 |         if (lseek(__fd, __offset, SEEK_SET) != __offset) {
 | 
|---|
| 458 |                 return -1;
 | 
|---|
| 459 |         }
 | 
|---|
| 460 |         return write(__fd, __buf, __nbytes);
 | 
|---|
| 461 | }
 | 
|---|
| 462 | #endif
 | 
|---|
| 463 | 
 | 
|---|
| 464 | #ifndef HAVE_STRCASESTR
 | 
|---|
| 465 | char *rep_strcasestr(const char *haystack, const char *needle)
 | 
|---|
| 466 | {
 | 
|---|
| 467 |         const char *s;
 | 
|---|
| 468 |         size_t nlen = strlen(needle);
 | 
|---|
| 469 |         for (s=haystack;*s;s++) {
 | 
|---|
| 470 |                 if (toupper(*needle) == toupper(*s) &&
 | 
|---|
| 471 |                     strncasecmp(s, needle, nlen) == 0) {
 | 
|---|
| 472 |                         return (char *)((uintptr_t)s);
 | 
|---|
| 473 |                 }
 | 
|---|
| 474 |         }
 | 
|---|
| 475 |         return NULL;
 | 
|---|
| 476 | }
 | 
|---|
| 477 | #endif
 | 
|---|
| 478 | 
 | 
|---|
| 479 | #ifndef HAVE_STRTOK_R
 | 
|---|
| 480 | /* based on GLIBC version, copyright Free Software Foundation */
 | 
|---|
| 481 | char *rep_strtok_r(char *s, const char *delim, char **save_ptr)
 | 
|---|
| 482 | {
 | 
|---|
| 483 |         char *token;
 | 
|---|
| 484 | 
 | 
|---|
| 485 |         if (s == NULL) s = *save_ptr;
 | 
|---|
| 486 | 
 | 
|---|
| 487 |         s += strspn(s, delim);
 | 
|---|
| 488 |         if (*s == '\0') {
 | 
|---|
| 489 |                 *save_ptr = s;
 | 
|---|
| 490 |                 return NULL;
 | 
|---|
| 491 |         }
 | 
|---|
| 492 | 
 | 
|---|
| 493 |         token = s;
 | 
|---|
| 494 |         s = strpbrk(token, delim);
 | 
|---|
| 495 |         if (s == NULL) {
 | 
|---|
| 496 |                 *save_ptr = token + strlen(token);
 | 
|---|
| 497 |         } else {
 | 
|---|
| 498 |                 *s = '\0';
 | 
|---|
| 499 |                 *save_ptr = s + 1;
 | 
|---|
| 500 |         }
 | 
|---|
| 501 | 
 | 
|---|
| 502 |         return token;
 | 
|---|
| 503 | }
 | 
|---|
| 504 | #endif
 | 
|---|
| 505 | 
 | 
|---|
| 506 | 
 | 
|---|
| 507 | #ifndef HAVE_STRTOLL
 | 
|---|
| 508 | long long int rep_strtoll(const char *str, char **endptr, int base)
 | 
|---|
| 509 | {
 | 
|---|
| 510 | #ifdef HAVE_STRTOQ
 | 
|---|
| 511 |         return strtoq(str, endptr, base);
 | 
|---|
| 512 | #elif defined(HAVE___STRTOLL) 
 | 
|---|
| 513 |         return __strtoll(str, endptr, base);
 | 
|---|
| 514 | #elif SIZEOF_LONG == SIZEOF_LONG_LONG
 | 
|---|
| 515 |         return (long long int) strtol(str, endptr, base);
 | 
|---|
| 516 | #else
 | 
|---|
| 517 | # error "You need a strtoll function"
 | 
|---|
| 518 | #endif
 | 
|---|
| 519 | }
 | 
|---|
| 520 | #else
 | 
|---|
| 521 | #ifdef HAVE_BSD_STRTOLL
 | 
|---|
| 522 | #ifdef HAVE_STRTOQ
 | 
|---|
| 523 | long long int rep_strtoll(const char *str, char **endptr, int base)
 | 
|---|
| 524 | {
 | 
|---|
| 525 |         long long int nb = strtoq(str, endptr, base);
 | 
|---|
| 526 |         /* In linux EINVAL is only returned if base is not ok */
 | 
|---|
| 527 |         if (errno == EINVAL) {
 | 
|---|
| 528 |                 if (base == 0 || (base >1 && base <37)) {
 | 
|---|
| 529 |                         /* Base was ok so it's because we were not
 | 
|---|
| 530 |                          * able to make the convertion.
 | 
|---|
| 531 |                          * Let's reset errno.
 | 
|---|
| 532 |                          */
 | 
|---|
| 533 |                         errno = 0;
 | 
|---|
| 534 |                 }
 | 
|---|
| 535 |         }
 | 
|---|
| 536 |         return nb;
 | 
|---|
| 537 | }
 | 
|---|
| 538 | #else
 | 
|---|
| 539 | #error "You need the strtoq function"
 | 
|---|
| 540 | #endif /* HAVE_STRTOQ */
 | 
|---|
| 541 | #endif /* HAVE_BSD_STRTOLL */
 | 
|---|
| 542 | #endif /* HAVE_STRTOLL */
 | 
|---|
| 543 | 
 | 
|---|
| 544 | 
 | 
|---|
| 545 | #ifndef HAVE_STRTOULL
 | 
|---|
| 546 | unsigned long long int rep_strtoull(const char *str, char **endptr, int base)
 | 
|---|
| 547 | {
 | 
|---|
| 548 | #ifdef HAVE_STRTOUQ
 | 
|---|
| 549 |         return strtouq(str, endptr, base);
 | 
|---|
| 550 | #elif defined(HAVE___STRTOULL) 
 | 
|---|
| 551 |         return __strtoull(str, endptr, base);
 | 
|---|
| 552 | #elif SIZEOF_LONG == SIZEOF_LONG_LONG
 | 
|---|
| 553 |         return (unsigned long long int) strtoul(str, endptr, base);
 | 
|---|
| 554 | #else
 | 
|---|
| 555 | # error "You need a strtoull function"
 | 
|---|
| 556 | #endif
 | 
|---|
| 557 | }
 | 
|---|
| 558 | #else
 | 
|---|
| 559 | #ifdef HAVE_BSD_STRTOLL
 | 
|---|
| 560 | #ifdef HAVE_STRTOUQ
 | 
|---|
| 561 | unsigned long long int rep_strtoull(const char *str, char **endptr, int base)
 | 
|---|
| 562 | {
 | 
|---|
| 563 |         unsigned long long int nb = strtouq(str, endptr, base);
 | 
|---|
| 564 |         /* In linux EINVAL is only returned if base is not ok */
 | 
|---|
| 565 |         if (errno == EINVAL) {
 | 
|---|
| 566 |                 if (base == 0 || (base >1 && base <37)) {
 | 
|---|
| 567 |                         /* Base was ok so it's because we were not
 | 
|---|
| 568 |                          * able to make the convertion.
 | 
|---|
| 569 |                          * Let's reset errno.
 | 
|---|
| 570 |                          */
 | 
|---|
| 571 |                         errno = 0;
 | 
|---|
| 572 |                 }
 | 
|---|
| 573 |         }
 | 
|---|
| 574 |         return nb;
 | 
|---|
| 575 | }
 | 
|---|
| 576 | #else
 | 
|---|
| 577 | #error "You need the strtouq function"
 | 
|---|
| 578 | #endif /* HAVE_STRTOUQ */
 | 
|---|
| 579 | #endif /* HAVE_BSD_STRTOLL */
 | 
|---|
| 580 | #endif /* HAVE_STRTOULL */
 | 
|---|
| 581 | 
 | 
|---|
| 582 | #ifndef HAVE_SETENV
 | 
|---|
| 583 | int rep_setenv(const char *name, const char *value, int overwrite) 
 | 
|---|
| 584 | {
 | 
|---|
| 585 |         char *p;
 | 
|---|
| 586 |         size_t l1, l2;
 | 
|---|
| 587 |         int ret;
 | 
|---|
| 588 | 
 | 
|---|
| 589 |         if (!overwrite && getenv(name)) {
 | 
|---|
| 590 |                 return 0;
 | 
|---|
| 591 |         }
 | 
|---|
| 592 | 
 | 
|---|
| 593 |         l1 = strlen(name);
 | 
|---|
| 594 |         l2 = strlen(value);
 | 
|---|
| 595 | 
 | 
|---|
| 596 |         p = malloc(l1+l2+2);
 | 
|---|
| 597 |         if (p == NULL) {
 | 
|---|
| 598 |                 return -1;
 | 
|---|
| 599 |         }
 | 
|---|
| 600 |         memcpy(p, name, l1);
 | 
|---|
| 601 |         p[l1] = '=';
 | 
|---|
| 602 |         memcpy(p+l1+1, value, l2);
 | 
|---|
| 603 |         p[l1+l2+1] = 0;
 | 
|---|
| 604 | 
 | 
|---|
| 605 |         ret = putenv(p);
 | 
|---|
| 606 |         if (ret != 0) {
 | 
|---|
| 607 |                 free(p);
 | 
|---|
| 608 |         }
 | 
|---|
| 609 | 
 | 
|---|
| 610 |         return ret;
 | 
|---|
| 611 | }
 | 
|---|
| 612 | #endif
 | 
|---|
| 613 | 
 | 
|---|
| 614 | #ifndef HAVE_UNSETENV
 | 
|---|
| 615 | int rep_unsetenv(const char *name)
 | 
|---|
| 616 | {
 | 
|---|
| 617 |         extern char **environ;
 | 
|---|
| 618 |         size_t len = strlen(name);
 | 
|---|
| 619 |         size_t i, count;
 | 
|---|
| 620 | 
 | 
|---|
| 621 |         if (environ == NULL || getenv(name) == NULL) {
 | 
|---|
| 622 |                 return 0;
 | 
|---|
| 623 |         }
 | 
|---|
| 624 | 
 | 
|---|
| 625 |         for (i=0;environ[i];i++) /* noop */ ;
 | 
|---|
| 626 | 
 | 
|---|
| 627 |         count=i;
 | 
|---|
| 628 |         
 | 
|---|
| 629 |         for (i=0;i<count;) {
 | 
|---|
| 630 |                 if (strncmp(environ[i], name, len) == 0 && environ[i][len] == '=') {
 | 
|---|
| 631 |                         /* note: we do _not_ free the old variable here. It is unsafe to 
 | 
|---|
| 632 |                            do so, as the pointer may not have come from malloc */
 | 
|---|
| 633 |                         memmove(&environ[i], &environ[i+1], (count-i)*sizeof(char *));
 | 
|---|
| 634 |                         count--;
 | 
|---|
| 635 |                 } else {
 | 
|---|
| 636 |                         i++;
 | 
|---|
| 637 |                 }
 | 
|---|
| 638 |         }
 | 
|---|
| 639 | 
 | 
|---|
| 640 |         return 0;
 | 
|---|
| 641 | }
 | 
|---|
| 642 | #endif
 | 
|---|
| 643 | 
 | 
|---|
| 644 | #ifndef HAVE_UTIME
 | 
|---|
| 645 | int rep_utime(const char *filename, const struct utimbuf *buf)
 | 
|---|
| 646 | {
 | 
|---|
| 647 |         errno = ENOSYS;
 | 
|---|
| 648 |         return -1;
 | 
|---|
| 649 | }
 | 
|---|
| 650 | #endif
 | 
|---|
| 651 | 
 | 
|---|
| 652 | #ifndef HAVE_UTIMES
 | 
|---|
| 653 | int rep_utimes(const char *filename, const struct timeval tv[2])
 | 
|---|
| 654 | {
 | 
|---|
| 655 |         struct utimbuf u;
 | 
|---|
| 656 | 
 | 
|---|
| 657 |         u.actime = tv[0].tv_sec;
 | 
|---|
| 658 |         if (tv[0].tv_usec > 500000) {
 | 
|---|
| 659 |                 u.actime += 1;
 | 
|---|
| 660 |         }
 | 
|---|
| 661 | 
 | 
|---|
| 662 |         u.modtime = tv[1].tv_sec;
 | 
|---|
| 663 |         if (tv[1].tv_usec > 500000) {
 | 
|---|
| 664 |                 u.modtime += 1;
 | 
|---|
| 665 |         }
 | 
|---|
| 666 | 
 | 
|---|
| 667 |         return utime(filename, &u);
 | 
|---|
| 668 | }
 | 
|---|
| 669 | #endif
 | 
|---|
| 670 | 
 | 
|---|
| 671 | #ifndef HAVE_DUP2
 | 
|---|
| 672 | int rep_dup2(int oldfd, int newfd) 
 | 
|---|
| 673 | {
 | 
|---|
| 674 |         errno = ENOSYS;
 | 
|---|
| 675 |         return -1;
 | 
|---|
| 676 | }
 | 
|---|
| 677 | #endif
 | 
|---|
| 678 | 
 | 
|---|
| 679 | #ifndef HAVE_CHOWN
 | 
|---|
| 680 | /**
 | 
|---|
| 681 | chown isn't used much but OS/2 doesn't have it
 | 
|---|
| 682 | **/
 | 
|---|
| 683 | int rep_chown(const char *fname, uid_t uid, gid_t gid)
 | 
|---|
| 684 | {
 | 
|---|
| 685 |         errno = ENOSYS;
 | 
|---|
| 686 |         return -1;
 | 
|---|
| 687 | }
 | 
|---|
| 688 | #endif
 | 
|---|
| 689 | 
 | 
|---|
| 690 | #ifndef HAVE_LINK
 | 
|---|
| 691 | int rep_link(const char *oldpath, const char *newpath)
 | 
|---|
| 692 | {
 | 
|---|
| 693 |         errno = ENOSYS;
 | 
|---|
| 694 |         return -1;
 | 
|---|
| 695 | }
 | 
|---|
| 696 | #endif
 | 
|---|
| 697 | 
 | 
|---|
| 698 | #ifndef HAVE_READLINK
 | 
|---|
| 699 | int rep_readlink(const char *path, char *buf, size_t bufsiz)
 | 
|---|
| 700 | {
 | 
|---|
| 701 |         errno = ENOSYS;
 | 
|---|
| 702 |         return -1;
 | 
|---|
| 703 | }
 | 
|---|
| 704 | #endif
 | 
|---|
| 705 | 
 | 
|---|
| 706 | #ifndef HAVE_SYMLINK
 | 
|---|
| 707 | int rep_symlink(const char *oldpath, const char *newpath)
 | 
|---|
| 708 | {
 | 
|---|
| 709 |         errno = ENOSYS;
 | 
|---|
| 710 |         return -1;
 | 
|---|
| 711 | }
 | 
|---|
| 712 | #endif
 | 
|---|
| 713 | 
 | 
|---|
| 714 | #ifndef HAVE_LCHOWN
 | 
|---|
| 715 | int rep_lchown(const char *fname,uid_t uid,gid_t gid)
 | 
|---|
| 716 | {
 | 
|---|
| 717 |         errno = ENOSYS;
 | 
|---|
| 718 |         return -1;
 | 
|---|
| 719 | }
 | 
|---|
| 720 | #endif
 | 
|---|
| 721 | 
 | 
|---|
| 722 | #ifndef HAVE_REALPATH
 | 
|---|
| 723 | char *rep_realpath(const char *path, char *resolved_path)
 | 
|---|
| 724 | {
 | 
|---|
| 725 |         /* As realpath is not a system call we can't return ENOSYS. */
 | 
|---|
| 726 |         errno = EINVAL;
 | 
|---|
| 727 |         return NULL;
 | 
|---|
| 728 | }
 | 
|---|
| 729 | #endif
 | 
|---|
| 730 | 
 | 
|---|
| 731 | 
 | 
|---|
| 732 | #ifndef HAVE_MEMMEM
 | 
|---|
| 733 | void *rep_memmem(const void *haystack, size_t haystacklen,
 | 
|---|
| 734 |                  const void *needle, size_t needlelen)
 | 
|---|
| 735 | {
 | 
|---|
| 736 |         if (needlelen == 0) {
 | 
|---|
| 737 |                 return discard_const(haystack);
 | 
|---|
| 738 |         }
 | 
|---|
| 739 |         while (haystacklen >= needlelen) {
 | 
|---|
| 740 |                 char *p = (char *)memchr(haystack, *(const char *)needle,
 | 
|---|
| 741 |                                          haystacklen-(needlelen-1));
 | 
|---|
| 742 |                 if (!p) return NULL;
 | 
|---|
| 743 |                 if (memcmp(p, needle, needlelen) == 0) {
 | 
|---|
| 744 |                         return p;
 | 
|---|
| 745 |                 }
 | 
|---|
| 746 |                 haystack = p+1;
 | 
|---|
| 747 |                 haystacklen -= (p - (const char *)haystack) + 1;
 | 
|---|
| 748 |         }
 | 
|---|
| 749 |         return NULL;
 | 
|---|
| 750 | }
 | 
|---|
| 751 | #endif
 | 
|---|
| 752 | 
 | 
|---|
| 753 | #if !defined(HAVE_VDPRINTF) || !defined(HAVE_C99_VSNPRINTF)
 | 
|---|
| 754 | int rep_vdprintf(int fd, const char *format, va_list ap)
 | 
|---|
| 755 | {
 | 
|---|
| 756 |         char *s = NULL;
 | 
|---|
| 757 |         int ret;
 | 
|---|
| 758 | 
 | 
|---|
| 759 |         vasprintf(&s, format, ap);
 | 
|---|
| 760 |         if (s == NULL) {
 | 
|---|
| 761 |                 errno = ENOMEM;
 | 
|---|
| 762 |                 return -1;
 | 
|---|
| 763 |         }
 | 
|---|
| 764 |         ret = write(fd, s, strlen(s));
 | 
|---|
| 765 |         free(s);
 | 
|---|
| 766 |         return ret;
 | 
|---|
| 767 | }
 | 
|---|
| 768 | #endif
 | 
|---|
| 769 | 
 | 
|---|
| 770 | #if !defined(HAVE_DPRINTF) || !defined(HAVE_C99_VSNPRINTF)
 | 
|---|
| 771 | int rep_dprintf(int fd, const char *format, ...)
 | 
|---|
| 772 | {
 | 
|---|
| 773 |         int ret;
 | 
|---|
| 774 |         va_list ap;
 | 
|---|
| 775 | 
 | 
|---|
| 776 |         va_start(ap, format);
 | 
|---|
| 777 |         ret = vdprintf(fd, format, ap);
 | 
|---|
| 778 |         va_end(ap);
 | 
|---|
| 779 | 
 | 
|---|
| 780 |         return ret;
 | 
|---|
| 781 | }
 | 
|---|
| 782 | #endif
 | 
|---|
| 783 | 
 | 
|---|
| 784 | #ifndef HAVE_GET_CURRENT_DIR_NAME
 | 
|---|
| 785 | char *rep_get_current_dir_name(void)
 | 
|---|
| 786 | {
 | 
|---|
| 787 |         char buf[PATH_MAX+1];
 | 
|---|
| 788 |         char *p;
 | 
|---|
| 789 |         p = getcwd(buf, sizeof(buf));
 | 
|---|
| 790 |         if (p == NULL) {
 | 
|---|
| 791 |                 return NULL;
 | 
|---|
| 792 |         }
 | 
|---|
| 793 |         return strdup(p);
 | 
|---|
| 794 | }
 | 
|---|
| 795 | #endif
 | 
|---|
| 796 | 
 | 
|---|
| 797 | #if !defined(HAVE_STRERROR_R) || !defined(STRERROR_R_PROTO_COMPATIBLE)
 | 
|---|
| 798 | int rep_strerror_r(int errnum, char *buf, size_t buflen)
 | 
|---|
| 799 | {
 | 
|---|
| 800 |         char *s = strerror(errnum);
 | 
|---|
| 801 |         if (strlen(s)+1 > buflen) {
 | 
|---|
| 802 |                 errno = ERANGE;
 | 
|---|
| 803 |                 return -1;
 | 
|---|
| 804 |         }
 | 
|---|
| 805 |         strncpy(buf, s, buflen);
 | 
|---|
| 806 |         return 0;
 | 
|---|
| 807 | }
 | 
|---|
| 808 | #endif
 | 
|---|
| 809 | 
 | 
|---|
| 810 | #ifndef HAVE_CLOCK_GETTIME
 | 
|---|
| 811 | int rep_clock_gettime(clockid_t clk_id, struct timespec *tp)
 | 
|---|
| 812 | {
 | 
|---|
| 813 |         struct timeval tval;
 | 
|---|
| 814 |         switch (clk_id) {
 | 
|---|
| 815 |                 case 0: /* CLOCK_REALTIME :*/
 | 
|---|
| 816 | #ifdef HAVE_GETTIMEOFDAY_TZ
 | 
|---|
| 817 |                         gettimeofday(&tval,NULL);
 | 
|---|
| 818 | #else
 | 
|---|
| 819 |                         gettimeofday(&tval);
 | 
|---|
| 820 | #endif
 | 
|---|
| 821 |                         tp->tv_sec = tval.tv_sec;
 | 
|---|
| 822 |                         tp->tv_nsec = tval.tv_usec * 1000;
 | 
|---|
| 823 |                         break;
 | 
|---|
| 824 |                 default:
 | 
|---|
| 825 |                         errno = EINVAL;
 | 
|---|
| 826 |                         return -1;
 | 
|---|
| 827 |         }
 | 
|---|
| 828 |         return 0;
 | 
|---|
| 829 | }
 | 
|---|
| 830 | #endif
 | 
|---|