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