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