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 */
|