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