s3:printing: Allow to run samba-bgqd as a standalone systemd service
[Samba.git] / lib / replace / replace.c
blob68829f2a3c9701914357c6ea4f7bde268b3d5c01
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
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
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.
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.
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/>.
26 #include "replace.h"
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"
36 #ifdef HAVE_SYS_SYSCALL_H
37 #include <sys/syscall.h>
38 #endif
40 #ifdef _WIN32
41 #define mkdir(d,m) _mkdir(d)
42 #endif
44 void replace_dummy(void);
45 void replace_dummy(void) {}
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)
53 #ifdef HAVE_CHSIZE
54 return chsize(f,l);
55 #elif defined(F_FREESP)
56 struct flock fl;
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
67 #endif /* HAVE_FTRUNCATE */
70 #ifndef HAVE_STRLCPY
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.
76 size_t rep_strlcpy(char *d, const char *s, size_t bufsize)
78 size_t len = strlen(s);
79 size_t ret = len;
81 if (bufsize <= 0) {
82 return 0;
84 if (len >= bufsize) {
85 len = bufsize - 1;
87 memcpy(d, s, len);
88 d[len] = 0;
89 return ret;
91 #endif
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)
99 size_t len1 = strnlen(d, bufsize);
100 size_t len2 = strlen(s);
101 size_t ret = len1 + len2;
103 if (len1+len2 >= bufsize) {
104 if (bufsize < (len1+1)) {
105 return ret;
107 len2 = bufsize - (len1+1);
109 if (len2 > 0) {
110 memcpy(d+len1, s, len2);
111 d[len1+len2] = 0;
113 return ret;
115 #endif
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 ********************************************************************/
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)
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;
136 if(t->tm_year < 70)
137 return((time_t)-1);
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;
143 y = t->tm_year + 1900;
144 m = 0;
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;
151 if(++m > 11) {
152 m = 0;
153 y++;
157 epoch += (t->tm_mday - 1) * DAY;
158 epoch += t->tm_hour * HOUR + t->tm_min * MINUTE + t->tm_sec;
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;
172 return(epoch);
174 #endif /* !HAVE_MKTIME */
177 #ifndef HAVE_INITGROUPS
178 /****************************************************************************
179 some systems don't have an initgroups call
180 ****************************************************************************/
181 int rep_initgroups(char *name, gid_t id)
183 #ifndef HAVE_SETGROUPS
184 /* yikes! no SETGROUPS or INITGROUPS? how can this work? */
185 errno = ENOSYS;
186 return -1;
187 #else /* HAVE_SETGROUPS */
189 #include <grp.h>
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;
198 if((grouplst = malloc(sizeof(gid_t) * max_gr)) == NULL) {
199 errno = ENOMEM;
200 return -1;
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;
217 gr = g->gr_mem[++j];
220 endgrent();
221 ret = setgroups(i, grouplst);
222 free(grouplst);
223 return ret;
224 #endif /* HAVE_SETGROUPS */
226 #endif /* HAVE_INITGROUPS */
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)
238 unsigned long d,s;
239 int i;
240 if (dest==src || !size) return(dest);
242 d = (unsigned long)dest;
243 s = (unsigned long)src;
245 if ((d >= (s+size)) || (s >= (d+size))) {
246 /* no overlap */
247 memcpy(dest,src,size);
248 return(dest);
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];
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];
286 return(dest);
288 #endif /* HAVE_MEMMOVE */
290 #ifndef HAVE_STRDUP
291 /****************************************************************************
292 duplicate a string
293 ****************************************************************************/
294 char *rep_strdup(const char *s)
296 size_t len;
297 char *ret;
299 if (!s) return(NULL);
301 len = strlen(s)+1;
302 ret = (char *)malloc(len);
303 if (!ret) return(NULL);
304 memcpy(ret,s,len);
305 return(ret);
307 #endif /* HAVE_STRDUP */
309 #ifndef HAVE_SETLINEBUF
310 void rep_setlinebuf(FILE *stream)
312 setvbuf(stream, (char *)NULL, _IOLBF, 0);
314 #endif /* HAVE_SETLINEBUF */
316 #ifndef HAVE_VSYSLOG
317 #ifdef HAVE_SYSLOG
318 void rep_vsyslog (int facility_priority, const char *format, va_list arglist)
320 char *msg = NULL;
321 vasprintf(&msg, format, arglist);
322 if (!msg)
323 return;
324 syslog(facility_priority, "%s", msg);
325 free(msg);
327 #endif /* HAVE_SYSLOG */
328 #endif /* HAVE_VSYSLOG */
330 #ifndef HAVE_STRNLEN
332 Some platforms don't have strnlen
334 size_t rep_strnlen(const char *s, size_t max)
336 size_t len;
338 for (len = 0; len < max; len++) {
339 if (s[len] == '\0') {
340 break;
343 return len;
345 #endif
347 #ifndef HAVE_STRNDUP
349 Some platforms don't have strndup.
351 char *rep_strndup(const char *s, size_t n)
353 char *ret;
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;
362 return ret;
364 #endif
366 #if !defined(HAVE_WAITPID) && defined(HAVE_WAIT4)
367 int rep_waitpid(pid_t pid,int *status,int options)
369 return wait4(pid, status, options, NULL);
371 #endif
373 #ifndef HAVE_SETEUID
374 int rep_seteuid(uid_t euid)
376 #ifdef HAVE_SETRESUID
377 return setresuid(-1, euid, -1);
378 #else
379 errno = ENOSYS;
380 return -1;
381 #endif
383 #endif
385 #ifndef HAVE_SETEGID
386 int rep_setegid(gid_t egid)
388 #ifdef HAVE_SETRESGID
389 return setresgid(-1, egid, -1);
390 #else
391 errno = ENOSYS;
392 return -1;
393 #endif
395 #endif
397 /*******************************************************************
398 os/2 also doesn't have chroot
399 ********************************************************************/
400 #ifndef HAVE_CHROOT
401 int rep_chroot(const char *dname)
403 errno = ENOSYS;
404 return -1;
406 #endif
408 /*****************************************************************
409 Possibly replace mkstemp if it is broken.
410 *****************************************************************/
412 #ifndef HAVE_SECURE_MKSTEMP
413 int rep_mkstemp(char *template)
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);
422 #endif
424 #ifndef HAVE_MKDTEMP
425 char *rep_mkdtemp(char *template)
427 char *dname;
429 if ((dname = mktemp(template))) {
430 if (mkdir(dname, 0700) >= 0) {
431 return dname;
435 return NULL;
437 #endif
439 /*****************************************************************
440 Watch out: this is not thread safe.
441 *****************************************************************/
443 #ifndef HAVE_PREAD
444 ssize_t rep_pread(int __fd, void *__buf, size_t __nbytes, off_t __offset)
446 if (lseek(__fd, __offset, SEEK_SET) != __offset) {
447 return -1;
449 return read(__fd, __buf, __nbytes);
451 #endif
453 /*****************************************************************
454 Watch out: this is not thread safe.
455 *****************************************************************/
457 #ifndef HAVE_PWRITE
458 ssize_t rep_pwrite(int __fd, const void *__buf, size_t __nbytes, off_t __offset)
460 if (lseek(__fd, __offset, SEEK_SET) != __offset) {
461 return -1;
463 return write(__fd, __buf, __nbytes);
465 #endif
467 #ifndef HAVE_STRCASESTR
468 char *rep_strcasestr(const char *haystack, const char *needle)
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);
478 return NULL;
480 #endif
482 #ifndef HAVE_STRSEP
483 char *rep_strsep(char **pps, const char *delim)
485 char *ret = *pps;
486 char *p = *pps;
488 if (p == NULL) {
489 return NULL;
491 p += strcspn(p, delim);
492 if (*p == '\0') {
493 *pps = NULL;
494 } else {
495 *p = '\0';
496 *pps = p + 1;
498 return ret;
500 #endif
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)
506 char *token;
508 if (s == NULL) s = *save_ptr;
510 s += strspn(s, delim);
511 if (*s == '\0') {
512 *save_ptr = s;
513 return NULL;
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;
525 return token;
527 #endif
530 #ifndef HAVE_STRTOLL
531 long long int rep_strtoll(const char *str, char **endptr, int base)
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
543 #else
544 #ifdef HAVE_BSD_STRTOLL
545 #undef strtoll
546 long long int rep_strtoll(const char *str, char **endptr, int base)
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.
557 errno = saved_errno;
560 return nb;
562 #endif /* HAVE_BSD_STRTOLL */
563 #endif /* HAVE_STRTOLL */
566 #ifndef HAVE_STRTOULL
567 unsigned long long int rep_strtoull(const char *str, char **endptr, int base)
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
579 #else
580 #ifdef HAVE_BSD_STRTOLL
581 #undef strtoull
582 unsigned long long int rep_strtoull(const char *str, char **endptr, int base)
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.
593 errno = saved_errno;
596 return nb;
598 #endif /* HAVE_BSD_STRTOLL */
599 #endif /* HAVE_STRTOULL */
601 #ifndef HAVE_SETENV
602 int rep_setenv(const char *name, const char *value, int overwrite)
604 char *p;
605 size_t l1, l2;
606 int ret;
608 if (!overwrite && getenv(name)) {
609 return 0;
612 l1 = strlen(name);
613 l2 = strlen(value);
615 p = malloc(l1+l2+2);
616 if (p == NULL) {
617 return -1;
619 memcpy(p, name, l1);
620 p[l1] = '=';
621 memcpy(p+l1+1, value, l2);
622 p[l1+l2+1] = 0;
624 ret = putenv(p);
625 if (ret != 0) {
626 free(p);
629 return ret;
631 #endif
633 #ifndef HAVE_UNSETENV
634 int rep_unsetenv(const char *name)
636 extern char **environ;
637 size_t len = strlen(name);
638 size_t i, count;
640 if (environ == NULL || getenv(name) == NULL) {
641 return 0;
644 for (i=0;environ[i];i++) /* noop */ ;
646 count=i;
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++;
659 return 0;
661 #endif
663 #ifndef HAVE_UTIME
664 int rep_utime(const char *filename, const struct utimbuf *buf)
666 errno = ENOSYS;
667 return -1;
669 #endif
671 #ifndef HAVE_UTIMES
672 int rep_utimes(const char *filename, const struct timeval tv[2])
674 struct utimbuf u;
676 u.actime = tv[0].tv_sec;
677 if (tv[0].tv_usec > 500000) {
678 u.actime += 1;
681 u.modtime = tv[1].tv_sec;
682 if (tv[1].tv_usec > 500000) {
683 u.modtime += 1;
686 return utime(filename, &u);
688 #endif
690 #ifndef HAVE_DUP2
691 int rep_dup2(int oldfd, int newfd)
693 errno = ENOSYS;
694 return -1;
696 #endif
698 #ifndef HAVE_CHOWN
700 chown isn't used much but OS/2 doesn't have it
702 int rep_chown(const char *fname, uid_t uid, gid_t gid)
704 errno = ENOSYS;
705 return -1;
707 #endif
709 #ifndef HAVE_LINK
710 int rep_link(const char *oldpath, const char *newpath)
712 errno = ENOSYS;
713 return -1;
715 #endif
717 #ifndef HAVE_READLINK
718 int rep_readlink(const char *path, char *buf, size_t bufsiz)
720 errno = ENOSYS;
721 return -1;
723 #endif
725 #ifndef HAVE_SYMLINK
726 int rep_symlink(const char *oldpath, const char *newpath)
728 errno = ENOSYS;
729 return -1;
731 #endif
733 #ifndef HAVE_LCHOWN
734 int rep_lchown(const char *fname,uid_t uid,gid_t gid)
736 errno = ENOSYS;
737 return -1;
739 #endif
741 #ifndef HAVE_REALPATH
742 char *rep_realpath(const char *path, char *resolved_path)
744 /* As realpath is not a system call we can't return ENOSYS. */
745 errno = EINVAL;
746 return NULL;
748 #endif
751 #ifndef HAVE_MEMMEM
752 void *rep_memmem(const void *haystack, size_t haystacklen,
753 const void *needle, size_t needlelen)
755 if (needlelen == 0) {
756 return discard_const(haystack);
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;
765 haystack = p+1;
766 haystacklen -= (p - (const char *)haystack) + 1;
768 return NULL;
770 #endif
772 #if !defined(HAVE_VDPRINTF) || !defined(HAVE_C99_VSNPRINTF)
773 int rep_vdprintf(int fd, const char *format, va_list ap)
775 char *s = NULL;
776 int ret;
778 vasprintf(&s, format, ap);
779 if (s == NULL) {
780 errno = ENOMEM;
781 return -1;
783 ret = write(fd, s, strlen(s));
784 free(s);
785 return ret;
787 #endif
789 #if !defined(HAVE_DPRINTF) || !defined(HAVE_C99_VSNPRINTF)
790 int rep_dprintf(int fd, const char *format, ...)
792 int ret;
793 va_list ap;
795 va_start(ap, format);
796 ret = vdprintf(fd, format, ap);
797 va_end(ap);
799 return ret;
801 #endif
803 #ifndef HAVE_GET_CURRENT_DIR_NAME
804 char *rep_get_current_dir_name(void)
806 char buf[PATH_MAX+1];
807 char *p;
808 p = getcwd(buf, sizeof(buf));
809 if (p == NULL) {
810 return NULL;
812 return strdup(p);
814 #endif
816 #ifndef HAVE_STRERROR_R
817 int rep_strerror_r(int errnum, char *buf, size_t buflen)
819 char *s = strerror(errnum);
820 if (strlen(s)+1 > buflen) {
821 errno = ERANGE;
822 return -1;
824 strncpy(buf, s, buflen);
825 return 0;
827 #elif (!defined(STRERROR_R_XSI_NOT_GNU))
828 #undef strerror_r
829 int rep_strerror_r(int errnum, char *buf, size_t buflen)
831 char *s = strerror_r(errnum, buf, buflen);
832 if (s == NULL) {
833 /* Shouldn't happen, should always get a string */
834 return EINVAL;
836 if (s != buf) {
837 strlcpy(buf, s, buflen);
838 if (strlen(s) > buflen - 1) {
839 return ERANGE;
842 return 0;
845 #endif
847 #ifndef HAVE_CLOCK_GETTIME
848 int rep_clock_gettime(clockid_t clk_id, struct timespec *tp)
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;
865 return 0;
867 #endif
869 #ifndef HAVE_MEMALIGN
870 void *rep_memalign( size_t align, size_t size )
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;
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;
893 if (size < pagesize) {
894 size = pagesize;
896 return malloc(size);
897 #endif
899 #endif
901 #ifndef HAVE_GETPEEREID
902 int rep_getpeereid(int s, uid_t *uid, gid_t *gid)
904 #if defined(HAVE_PEERCRED)
905 struct ucred cred;
906 socklen_t cred_len = sizeof(struct ucred);
907 int ret;
909 #undef getsockopt
910 ret = getsockopt(s, SOL_SOCKET, SO_PEERCRED, (void *)&cred, &cred_len);
911 if (ret != 0) {
912 return -1;
915 if (cred_len != sizeof(struct ucred)) {
916 errno = EINVAL;
917 return -1;
920 *uid = cred.uid;
921 *gid = cred.gid;
922 return 0;
923 #else
924 errno = ENOSYS;
925 return -1;
926 #endif
928 #endif
930 #ifndef HAVE_USLEEP
931 int rep_usleep(useconds_t sec)
933 struct timeval tval;
935 * Fake it with select...
937 tval.tv_sec = 0;
938 tval.tv_usec = usecs/1000;
939 select(0,NULL,NULL,NULL,&tval);
940 return 0;
942 #endif /* HAVE_USLEEP */
944 #ifndef HAVE_SETPROCTITLE
945 void rep_setproctitle(const char *fmt, ...)
948 #endif
949 #ifndef HAVE_SETPROCTITLE_INIT
950 void rep_setproctitle_init(int argc, char *argv[], char *envp[])
953 #endif
955 #ifndef HAVE_MEMSET_S
956 # ifndef RSIZE_MAX
957 # define RSIZE_MAX (SIZE_MAX >> 1)
958 # endif
960 int rep_memset_s(void *dest, size_t destsz, int ch, size_t count)
962 if (dest == NULL) {
963 return EINVAL;
966 if (destsz > RSIZE_MAX ||
967 count > RSIZE_MAX ||
968 count > destsz) {
969 return ERANGE;
972 #if defined(HAVE_MEMSET_EXPLICIT)
973 memset_explicit(dest, destsz, ch, count);
974 #else /* HAVE_MEMSET_EXPLICIT */
975 memset(dest, ch, count);
976 # if defined(HAVE_GCC_VOLATILE_MEMORY_PROTECTION)
977 /* See http://llvm.org/bugs/show_bug.cgi?id=15495 */
978 __asm__ volatile("" : : "g"(dest) : "memory");
979 # endif /* HAVE_GCC_VOLATILE_MEMORY_PROTECTION */
980 #endif /* HAVE_MEMSET_EXPLICIT */
982 return 0;
984 #endif /* HAVE_MEMSET_S */
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 */
992 const char *rep_getprogname(void)
994 #ifdef HAVE_PROGRAM_INVOCATION_SHORT_NAME
995 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;
1005 if (rep_progname[0] != '\0') {
1006 return rep_progname;
1009 len = snprintf(rep_progname, sizeof(rep_progname), "%s", "<unknown>");
1010 if (len <= 0) {
1011 return NULL;
1014 pid = getpid();
1015 if (pid <= 1 || pid == (pid_t)-1) {
1016 return NULL;
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;
1027 fp = fopen(cmdline, "r");
1028 if (fp == NULL) {
1029 return NULL;
1032 nread = fread(cmdline, 1, sizeof(cmdline) - 1, fp);
1034 rc = fclose(fp);
1035 if (rc != 0) {
1036 return NULL;
1039 if (nread == 0) {
1040 return NULL;
1043 cmdline[nread] = '\0';
1045 p = strrchr(cmdline, '/');
1046 if (p != NULL) {
1047 p++;
1048 } else {
1049 p = cmdline;
1052 len = strlen(p);
1053 if (len > PROGNAME_SIZE) {
1054 p[PROGNAME_SIZE - 1] = '\0';
1057 (void)snprintf(rep_progname, sizeof(rep_progname), "%s", p);
1059 return rep_progname;
1060 #endif /* HAVE_PROGRAM_INVOCATION_SHORT_NAME */
1062 #endif /* HAVE_GETPROGNAME */
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)
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;
1084 #endif /* HAVE_COPY_FILE_RANGE */
1086 #ifndef HAVE_OPENAT2
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 */
1107 #ifdef DISABLE_OPATH
1109 * systems without O_PATH also don't have openat2,
1110 * so make sure we at a realistic combination.
1112 #undef __NR_openat2
1113 #endif /* DISABLE_OPATH */
1115 long rep_openat2(int dirfd, const char *pathname,
1116 struct open_how *how, size_t size)
1118 #ifdef __NR_openat2
1119 #if _FILE_OFFSET_BITS == 64 && SIZE_MAX == 0xffffffffUL && defined(O_LARGEFILE)
1120 struct open_how __how;
1122 #if defined(O_PATH) && ! defined(DISABLE_OPATH)
1123 if ((how->flags & O_PATH) == 0)
1124 #endif
1126 if (sizeof(__how) == size) {
1127 __how = *how;
1129 __how.flags |= O_LARGEFILE;
1130 how = &__how;
1133 #endif
1135 return syscall(__NR_openat2,
1136 dirfd,
1137 pathname,
1138 how,
1139 size);
1140 #else
1141 errno = ENOSYS;
1142 return -1;
1143 #endif
1145 #endif /* !HAVE_OPENAT2 */