samba-tool: make 'samba-tool fsmo *' aware of all 7 fsmo roles
[Samba.git] / lib / replace / replace.c
blob9fae44aa5cf4aa22a0fcbca4edc75cc9190adb7c
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 _WIN32
37 #define mkdir(d,m) _mkdir(d)
38 #endif
40 void replace_dummy(void);
41 void replace_dummy(void) {}
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)
49 #ifdef HAVE_CHSIZE
50 return chsize(f,l);
51 #elif defined(F_FREESP)
52 struct flock fl;
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
63 #endif /* HAVE_FTRUNCATE */
66 #ifndef HAVE_STRLCPY
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.
72 size_t rep_strlcpy(char *d, const char *s, size_t bufsize)
74 size_t len = strlen(s);
75 size_t ret = len;
77 if (bufsize <= 0) {
78 return 0;
80 if (len >= bufsize) {
81 len = bufsize - 1;
83 memcpy(d, s, len);
84 d[len] = 0;
85 return ret;
87 #endif
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)
95 size_t len1 = strnlen(d, bufsize);
96 size_t len2 = strlen(s);
97 size_t ret = len1 + len2;
99 if (len1+len2 >= bufsize) {
100 if (bufsize < (len1+1)) {
101 return ret;
103 len2 = bufsize - (len1+1);
105 if (len2 > 0) {
106 memcpy(d+len1, s, len2);
107 d[len1+len2] = 0;
109 return ret;
111 #endif
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 ********************************************************************/
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)
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;
132 if(t->tm_year < 70)
133 return((time_t)-1);
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;
139 y = t->tm_year + 1900;
140 m = 0;
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;
147 if(++m > 11) {
148 m = 0;
149 y++;
153 epoch += (t->tm_mday - 1) * DAY;
154 epoch += t->tm_hour * HOUR + t->tm_min * MINUTE + t->tm_sec;
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;
168 return(epoch);
170 #endif /* !HAVE_MKTIME */
173 #ifndef HAVE_INITGROUPS
174 /****************************************************************************
175 some systems don't have an initgroups call
176 ****************************************************************************/
177 int rep_initgroups(char *name, gid_t id)
179 #ifndef HAVE_SETGROUPS
180 /* yikes! no SETGROUPS or INITGROUPS? how can this work? */
181 errno = ENOSYS;
182 return -1;
183 #else /* HAVE_SETGROUPS */
185 #include <grp.h>
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;
194 if((grouplst = malloc(sizeof(gid_t) * max_gr)) == NULL) {
195 errno = ENOMEM;
196 return -1;
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;
213 gr = g->gr_mem[++j];
216 endgrent();
217 ret = setgroups(i, grouplst);
218 free(grouplst);
219 return ret;
220 #endif /* HAVE_SETGROUPS */
222 #endif /* HAVE_INITGROUPS */
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)
234 unsigned long d,s;
235 int i;
236 if (dest==src || !size) return(dest);
238 d = (unsigned long)dest;
239 s = (unsigned long)src;
241 if ((d >= (s+size)) || (s >= (d+size))) {
242 /* no overlap */
243 memcpy(dest,src,size);
244 return(dest);
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];
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];
282 return(dest);
284 #endif /* HAVE_MEMMOVE */
286 #ifndef HAVE_STRDUP
287 /****************************************************************************
288 duplicate a string
289 ****************************************************************************/
290 char *rep_strdup(const char *s)
292 size_t len;
293 char *ret;
295 if (!s) return(NULL);
297 len = strlen(s)+1;
298 ret = (char *)malloc(len);
299 if (!ret) return(NULL);
300 memcpy(ret,s,len);
301 return(ret);
303 #endif /* HAVE_STRDUP */
305 #ifndef HAVE_SETLINEBUF
306 void rep_setlinebuf(FILE *stream)
308 setvbuf(stream, (char *)NULL, _IOLBF, 0);
310 #endif /* HAVE_SETLINEBUF */
312 #ifndef HAVE_VSYSLOG
313 #ifdef HAVE_SYSLOG
314 void rep_vsyslog (int facility_priority, const char *format, va_list arglist)
316 char *msg = NULL;
317 vasprintf(&msg, format, arglist);
318 if (!msg)
319 return;
320 syslog(facility_priority, "%s", msg);
321 free(msg);
323 #endif /* HAVE_SYSLOG */
324 #endif /* HAVE_VSYSLOG */
326 #ifndef HAVE_STRNLEN
328 Some platforms don't have strnlen
330 size_t rep_strnlen(const char *s, size_t max)
332 size_t len;
334 for (len = 0; len < max; len++) {
335 if (s[len] == '\0') {
336 break;
339 return len;
341 #endif
343 #ifndef HAVE_STRNDUP
345 Some platforms don't have strndup.
347 char *rep_strndup(const char *s, size_t n)
349 char *ret;
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;
358 return ret;
360 #endif
362 #if !defined(HAVE_WAITPID) && defined(HAVE_WAIT4)
363 int rep_waitpid(pid_t pid,int *status,int options)
365 return wait4(pid, status, options, NULL);
367 #endif
369 #ifndef HAVE_SETEUID
370 int rep_seteuid(uid_t euid)
372 #ifdef HAVE_SETRESUID
373 return setresuid(-1, euid, -1);
374 #else
375 errno = ENOSYS;
376 return -1;
377 #endif
379 #endif
381 #ifndef HAVE_SETEGID
382 int rep_setegid(gid_t egid)
384 #ifdef HAVE_SETRESGID
385 return setresgid(-1, egid, -1);
386 #else
387 errno = ENOSYS;
388 return -1;
389 #endif
391 #endif
393 /*******************************************************************
394 os/2 also doesn't have chroot
395 ********************************************************************/
396 #ifndef HAVE_CHROOT
397 int rep_chroot(const char *dname)
399 errno = ENOSYS;
400 return -1;
402 #endif
404 /*****************************************************************
405 Possibly replace mkstemp if it is broken.
406 *****************************************************************/
408 #ifndef HAVE_SECURE_MKSTEMP
409 int rep_mkstemp(char *template)
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);
418 #endif
420 #ifndef HAVE_MKDTEMP
421 char *rep_mkdtemp(char *template)
423 char *dname;
425 if ((dname = mktemp(template))) {
426 if (mkdir(dname, 0700) >= 0) {
427 return dname;
431 return NULL;
433 #endif
435 /*****************************************************************
436 Watch out: this is not thread safe.
437 *****************************************************************/
439 #ifndef HAVE_PREAD
440 ssize_t rep_pread(int __fd, void *__buf, size_t __nbytes, off_t __offset)
442 if (lseek(__fd, __offset, SEEK_SET) != __offset) {
443 return -1;
445 return read(__fd, __buf, __nbytes);
447 #endif
449 /*****************************************************************
450 Watch out: this is not thread safe.
451 *****************************************************************/
453 #ifndef HAVE_PWRITE
454 ssize_t rep_pwrite(int __fd, const void *__buf, size_t __nbytes, off_t __offset)
456 if (lseek(__fd, __offset, SEEK_SET) != __offset) {
457 return -1;
459 return write(__fd, __buf, __nbytes);
461 #endif
463 #ifndef HAVE_STRCASESTR
464 char *rep_strcasestr(const char *haystack, const char *needle)
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);
474 return NULL;
476 #endif
478 #ifndef HAVE_STRTOK_R
479 /* based on GLIBC version, copyright Free Software Foundation */
480 char *rep_strtok_r(char *s, const char *delim, char **save_ptr)
482 char *token;
484 if (s == NULL) s = *save_ptr;
486 s += strspn(s, delim);
487 if (*s == '\0') {
488 *save_ptr = s;
489 return NULL;
492 token = s;
493 s = strpbrk(token, delim);
494 if (s == NULL) {
495 *save_ptr = token + strlen(token);
496 } else {
497 *s = '\0';
498 *save_ptr = s + 1;
501 return token;
503 #endif
506 #ifndef HAVE_STRTOLL
507 long long int rep_strtoll(const char *str, char **endptr, int base)
509 #ifdef HAVE_STRTOQ
510 return strtoq(str, endptr, base);
511 #elif defined(HAVE___STRTOLL)
512 return __strtoll(str, endptr, base);
513 #elif SIZEOF_LONG == SIZEOF_LONG_LONG
514 return (long long int) strtol(str, endptr, base);
515 #else
516 # error "You need a strtoll function"
517 #endif
519 #else
520 #ifdef HAVE_BSD_STRTOLL
521 #ifdef HAVE_STRTOQ
522 long long int rep_strtoll(const char *str, char **endptr, int base)
524 long long int nb = strtoq(str, endptr, base);
525 /* In linux EINVAL is only returned if base is not ok */
526 if (errno == EINVAL) {
527 if (base == 0 || (base >1 && base <37)) {
528 /* Base was ok so it's because we were not
529 * able to make the convertion.
530 * Let's reset errno.
532 errno = 0;
535 return nb;
537 #else
538 #error "You need the strtoq function"
539 #endif /* HAVE_STRTOQ */
540 #endif /* HAVE_BSD_STRTOLL */
541 #endif /* HAVE_STRTOLL */
544 #ifndef HAVE_STRTOULL
545 unsigned long long int rep_strtoull(const char *str, char **endptr, int base)
547 #ifdef HAVE_STRTOUQ
548 return strtouq(str, endptr, base);
549 #elif defined(HAVE___STRTOULL)
550 return __strtoull(str, endptr, base);
551 #elif SIZEOF_LONG == SIZEOF_LONG_LONG
552 return (unsigned long long int) strtoul(str, endptr, base);
553 #else
554 # error "You need a strtoull function"
555 #endif
557 #else
558 #ifdef HAVE_BSD_STRTOLL
559 #ifdef HAVE_STRTOUQ
560 unsigned long long int rep_strtoull(const char *str, char **endptr, int base)
562 unsigned long long int nb = strtouq(str, endptr, base);
563 /* In linux EINVAL is only returned if base is not ok */
564 if (errno == EINVAL) {
565 if (base == 0 || (base >1 && base <37)) {
566 /* Base was ok so it's because we were not
567 * able to make the convertion.
568 * Let's reset errno.
570 errno = 0;
573 return nb;
575 #else
576 #error "You need the strtouq function"
577 #endif /* HAVE_STRTOUQ */
578 #endif /* HAVE_BSD_STRTOLL */
579 #endif /* HAVE_STRTOULL */
581 #ifndef HAVE_SETENV
582 int rep_setenv(const char *name, const char *value, int overwrite)
584 char *p;
585 size_t l1, l2;
586 int ret;
588 if (!overwrite && getenv(name)) {
589 return 0;
592 l1 = strlen(name);
593 l2 = strlen(value);
595 p = malloc(l1+l2+2);
596 if (p == NULL) {
597 return -1;
599 memcpy(p, name, l1);
600 p[l1] = '=';
601 memcpy(p+l1+1, value, l2);
602 p[l1+l2+1] = 0;
604 ret = putenv(p);
605 if (ret != 0) {
606 free(p);
609 return ret;
611 #endif
613 #ifndef HAVE_UNSETENV
614 int rep_unsetenv(const char *name)
616 extern char **environ;
617 size_t len = strlen(name);
618 size_t i, count;
620 if (environ == NULL || getenv(name) == NULL) {
621 return 0;
624 for (i=0;environ[i];i++) /* noop */ ;
626 count=i;
628 for (i=0;i<count;) {
629 if (strncmp(environ[i], name, len) == 0 && environ[i][len] == '=') {
630 /* note: we do _not_ free the old variable here. It is unsafe to
631 do so, as the pointer may not have come from malloc */
632 memmove(&environ[i], &environ[i+1], (count-i)*sizeof(char *));
633 count--;
634 } else {
635 i++;
639 return 0;
641 #endif
643 #ifndef HAVE_UTIME
644 int rep_utime(const char *filename, const struct utimbuf *buf)
646 errno = ENOSYS;
647 return -1;
649 #endif
651 #ifndef HAVE_UTIMES
652 int rep_utimes(const char *filename, const struct timeval tv[2])
654 struct utimbuf u;
656 u.actime = tv[0].tv_sec;
657 if (tv[0].tv_usec > 500000) {
658 u.actime += 1;
661 u.modtime = tv[1].tv_sec;
662 if (tv[1].tv_usec > 500000) {
663 u.modtime += 1;
666 return utime(filename, &u);
668 #endif
670 #ifndef HAVE_DUP2
671 int rep_dup2(int oldfd, int newfd)
673 errno = ENOSYS;
674 return -1;
676 #endif
678 #ifndef HAVE_CHOWN
680 chown isn't used much but OS/2 doesn't have it
682 int rep_chown(const char *fname, uid_t uid, gid_t gid)
684 errno = ENOSYS;
685 return -1;
687 #endif
689 #ifndef HAVE_LINK
690 int rep_link(const char *oldpath, const char *newpath)
692 errno = ENOSYS;
693 return -1;
695 #endif
697 #ifndef HAVE_READLINK
698 int rep_readlink(const char *path, char *buf, size_t bufsiz)
700 errno = ENOSYS;
701 return -1;
703 #endif
705 #ifndef HAVE_SYMLINK
706 int rep_symlink(const char *oldpath, const char *newpath)
708 errno = ENOSYS;
709 return -1;
711 #endif
713 #ifndef HAVE_LCHOWN
714 int rep_lchown(const char *fname,uid_t uid,gid_t gid)
716 errno = ENOSYS;
717 return -1;
719 #endif
721 #ifndef HAVE_REALPATH
722 char *rep_realpath(const char *path, char *resolved_path)
724 /* As realpath is not a system call we can't return ENOSYS. */
725 errno = EINVAL;
726 return NULL;
728 #endif
731 #ifndef HAVE_MEMMEM
732 void *rep_memmem(const void *haystack, size_t haystacklen,
733 const void *needle, size_t needlelen)
735 if (needlelen == 0) {
736 return discard_const(haystack);
738 while (haystacklen >= needlelen) {
739 char *p = (char *)memchr(haystack, *(const char *)needle,
740 haystacklen-(needlelen-1));
741 if (!p) return NULL;
742 if (memcmp(p, needle, needlelen) == 0) {
743 return p;
745 haystack = p+1;
746 haystacklen -= (p - (const char *)haystack) + 1;
748 return NULL;
750 #endif
752 #if !defined(HAVE_VDPRINTF) || !defined(HAVE_C99_VSNPRINTF)
753 int rep_vdprintf(int fd, const char *format, va_list ap)
755 char *s = NULL;
756 int ret;
758 vasprintf(&s, format, ap);
759 if (s == NULL) {
760 errno = ENOMEM;
761 return -1;
763 ret = write(fd, s, strlen(s));
764 free(s);
765 return ret;
767 #endif
769 #if !defined(HAVE_DPRINTF) || !defined(HAVE_C99_VSNPRINTF)
770 int rep_dprintf(int fd, const char *format, ...)
772 int ret;
773 va_list ap;
775 va_start(ap, format);
776 ret = vdprintf(fd, format, ap);
777 va_end(ap);
779 return ret;
781 #endif
783 #ifndef HAVE_GET_CURRENT_DIR_NAME
784 char *rep_get_current_dir_name(void)
786 char buf[PATH_MAX+1];
787 char *p;
788 p = getcwd(buf, sizeof(buf));
789 if (p == NULL) {
790 return NULL;
792 return strdup(p);
794 #endif
796 #ifndef HAVE_STRERROR_R
797 int rep_strerror_r(int errnum, char *buf, size_t buflen)
799 char *s = strerror(errnum);
800 if (strlen(s)+1 > buflen) {
801 errno = ERANGE;
802 return -1;
804 strncpy(buf, s, buflen);
805 return 0;
807 #endif
809 #ifndef HAVE_CLOCK_GETTIME
810 int rep_clock_gettime(clockid_t clk_id, struct timespec *tp)
812 struct timeval tval;
813 switch (clk_id) {
814 case 0: /* CLOCK_REALTIME :*/
815 #ifdef HAVE_GETTIMEOFDAY_TZ
816 gettimeofday(&tval,NULL);
817 #else
818 gettimeofday(&tval);
819 #endif
820 tp->tv_sec = tval.tv_sec;
821 tp->tv_nsec = tval.tv_usec * 1000;
822 break;
823 default:
824 errno = EINVAL;
825 return -1;
827 return 0;
829 #endif
831 #ifndef HAVE_MEMALIGN
832 void *rep_memalign( size_t align, size_t size )
834 #if defined(HAVE_POSIX_MEMALIGN)
835 void *p = NULL;
836 int ret = posix_memalign( &p, align, size );
837 if ( ret == 0 )
838 return p;
840 return NULL;
841 #else
842 /* On *BSD systems memaligns doesn't exist, but memory will
843 * be aligned on allocations of > pagesize. */
844 #if defined(SYSCONF_SC_PAGESIZE)
845 size_t pagesize = (size_t)sysconf(_SC_PAGESIZE);
846 #elif defined(HAVE_GETPAGESIZE)
847 size_t pagesize = (size_t)getpagesize();
848 #else
849 size_t pagesize = (size_t)-1;
850 #endif
851 if (pagesize == (size_t)-1) {
852 errno = ENOSYS;
853 return NULL;
855 if (size < pagesize) {
856 size = pagesize;
858 return malloc(size);
859 #endif
861 #endif
863 #ifndef HAVE_GETPEEREID
864 int rep_getpeereid(int s, uid_t *uid, gid_t *gid)
866 #if defined(HAVE_PEERCRED)
867 struct ucred cred;
868 socklen_t cred_len = sizeof(struct ucred);
869 int ret;
871 #undef getsockopt
872 ret = getsockopt(s, SOL_SOCKET, SO_PEERCRED, (void *)&cred, &cred_len);
873 if (ret != 0) {
874 return -1;
877 if (cred_len != sizeof(struct ucred)) {
878 errno = EINVAL;
879 return -1;
882 *uid = cred.uid;
883 *gid = cred.gid;
884 return 0;
885 #else
886 errno = ENOSYS;
887 return -1;
888 #endif
890 #endif
892 #ifndef HAVE_USLEEP
893 int rep_usleep(useconds_t sec)
895 struct timeval tval;
897 * Fake it with select...
899 tval.tv_sec = 0;
900 tval.tv_usec = usecs/1000;
901 select(0,NULL,NULL,NULL,&tval);
902 return 0;
904 #endif /* HAVE_USLEEP */
906 #ifndef HAVE_SETPROCTITLE
907 void rep_setproctitle(const char *fmt, ...)
910 #endif