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
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/>.
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"
37 #define mkdir(d,m) _mkdir(d)
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
)
51 #elif defined(F_FREESP)
58 return fcntl(f
, F_FREESP
, &fl
);
60 #error "you must have a ftruncate function"
63 #endif /* HAVE_FTRUNCATE */
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
);
73 if (bufsize
<= 0) return 0;
74 if (len
>= bufsize
) len
= bufsize
-1;
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)) {
95 len2
= bufsize
- (len1
+1);
98 memcpy(d
+len1
, s
, len2
);
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 ********************************************************************/
113 #define HOUR 60*MINUTE
116 time_t rep_mktime(struct tm
*t
)
121 int mon
[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
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;
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))
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
;
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? */
175 #else /* HAVE_SETGROUPS */
179 gid_t
*grouplst
= NULL
;
180 int max_gr
= NGROUPS_MAX
;
186 if((grouplst
= malloc(sizeof(gid_t
) * max_gr
)) == NULL
) {
193 while (i
< max_gr
&& ((g
= (struct group
*)getgrent()) != (struct group
*)NULL
)) {
198 while (gr
&& (*gr
!= (char)NULL
)) {
199 if (strcmp(name
,gr
) == 0) {
200 grouplst
[i
] = g
->gr_gid
;
209 ret
= setgroups(i
, grouplst
);
212 #endif /* HAVE_SETGROUPS */
214 #endif /* HAVE_INITGROUPS */
218 /*******************************************************************
219 safely copies memory, ensuring no overlap problems.
220 this is only used if the machine does not have its own memmove().
221 this is not the fastest algorithm in town, but it will do for our
223 ********************************************************************/
224 void *rep_memmove(void *dest
,const void *src
,int size
)
228 if (dest
==src
|| !size
) return(dest
);
230 d
= (unsigned long)dest
;
231 s
= (unsigned long)src
;
233 if ((d
>= (s
+size
)) || (s
>= (d
+size
))) {
235 memcpy(dest
,src
,size
);
240 /* we can forward copy */
241 if (s
-d
>= sizeof(int) &&
244 !(size
%sizeof(int))) {
245 /* do it all as words */
246 int *idest
= (int *)dest
;
247 int *isrc
= (int *)src
;
249 for (i
=0;i
<size
;i
++) idest
[i
] = isrc
[i
];
252 char *cdest
= (char *)dest
;
253 char *csrc
= (char *)src
;
254 for (i
=0;i
<size
;i
++) cdest
[i
] = csrc
[i
];
257 /* must backward copy */
258 if (d
-s
>= sizeof(int) &&
261 !(size
%sizeof(int))) {
262 /* do it all as words */
263 int *idest
= (int *)dest
;
264 int *isrc
= (int *)src
;
266 for (i
=size
-1;i
>=0;i
--) idest
[i
] = isrc
[i
];
269 char *cdest
= (char *)dest
;
270 char *csrc
= (char *)src
;
271 for (i
=size
-1;i
>=0;i
--) cdest
[i
] = csrc
[i
];
276 #endif /* HAVE_MEMMOVE */
279 /****************************************************************************
281 ****************************************************************************/
282 char *rep_strdup(const char *s
)
287 if (!s
) return(NULL
);
290 ret
= (char *)malloc(len
);
291 if (!ret
) return(NULL
);
295 #endif /* HAVE_STRDUP */
297 #ifndef HAVE_SETLINEBUF
298 void rep_setlinebuf(FILE *stream
)
300 setvbuf(stream
, (char *)NULL
, _IOLBF
, 0);
302 #endif /* HAVE_SETLINEBUF */
306 void rep_vsyslog (int facility_priority
, const char *format
, va_list arglist
)
309 vasprintf(&msg
, format
, arglist
);
312 syslog(facility_priority
, "%s", msg
);
315 #endif /* HAVE_SYSLOG */
316 #endif /* HAVE_VSYSLOG */
320 Some platforms don't have strnlen
322 size_t rep_strnlen(const char *s
, size_t max
)
326 for (len
= 0; len
< max
; len
++) {
327 if (s
[len
] == '\0') {
337 Some platforms don't have strndup.
339 char *rep_strndup(const char *s
, size_t n
)
354 #if !defined(HAVE_WAITPID) && defined(HAVE_WAIT4)
355 int rep_waitpid(pid_t pid
,int *status
,int options
)
357 return wait4(pid
, status
, options
, NULL
);
362 int rep_seteuid(uid_t euid
)
364 #ifdef HAVE_SETRESUID
365 return setresuid(-1, euid
, -1);
374 int rep_setegid(gid_t egid
)
376 #ifdef HAVE_SETRESGID
377 return setresgid(-1, egid
, -1);
385 /*******************************************************************
386 os/2 also doesn't have chroot
387 ********************************************************************/
389 int rep_chroot(const char *dname
)
396 /*****************************************************************
397 Possibly replace mkstemp if it is broken.
398 *****************************************************************/
400 #ifndef HAVE_SECURE_MKSTEMP
401 int rep_mkstemp(char *template)
403 /* have a reasonable go at emulating it. Hope that
404 the system mktemp() isn't completely hopeless */
406 if (template[0] == 0)
408 return open(template, O_CREAT
|O_EXCL
|O_RDWR
, 0600);
413 char *rep_mkdtemp(char *template)
417 if ((dname
= mktemp(template))) {
418 if (mkdir(dname
, 0700) >= 0) {
427 /*****************************************************************
428 Watch out: this is not thread safe.
429 *****************************************************************/
432 ssize_t
rep_pread(int __fd
, void *__buf
, size_t __nbytes
, off_t __offset
)
434 if (lseek(__fd
, __offset
, SEEK_SET
) != __offset
) {
437 return read(__fd
, __buf
, __nbytes
);
441 /*****************************************************************
442 Watch out: this is not thread safe.
443 *****************************************************************/
446 ssize_t
rep_pwrite(int __fd
, const void *__buf
, size_t __nbytes
, off_t __offset
)
448 if (lseek(__fd
, __offset
, SEEK_SET
) != __offset
) {
451 return write(__fd
, __buf
, __nbytes
);
455 #ifndef HAVE_STRCASESTR
456 char *rep_strcasestr(const char *haystack
, const char *needle
)
459 size_t nlen
= strlen(needle
);
460 for (s
=haystack
;*s
;s
++) {
461 if (toupper(*needle
) == toupper(*s
) &&
462 strncasecmp(s
, needle
, nlen
) == 0) {
463 return (char *)((uintptr_t)s
);
471 char *rep_strsep(char **pps
, const char *delim
)
479 p
+= strcspn(p
, delim
);
490 #ifndef HAVE_STRTOK_R
491 /* based on GLIBC version, copyright Free Software Foundation */
492 char *rep_strtok_r(char *s
, const char *delim
, char **save_ptr
)
496 if (s
== NULL
) s
= *save_ptr
;
498 s
+= strspn(s
, delim
);
505 s
= strpbrk(token
, delim
);
507 *save_ptr
= token
+ strlen(token
);
519 long long int rep_strtoll(const char *str
, char **endptr
, int base
)
522 return strtoq(str
, endptr
, base
);
523 #elif defined(HAVE___STRTOLL)
524 return __strtoll(str
, endptr
, base
);
525 #elif SIZEOF_LONG == SIZEOF_LONG_LONG
526 return (long long int) strtol(str
, endptr
, base
);
528 # error "You need a strtoll function"
532 #ifdef HAVE_BSD_STRTOLL
534 long long int rep_strtoll(const char *str
, char **endptr
, int base
)
536 long long int nb
= strtoq(str
, endptr
, base
);
537 /* In linux EINVAL is only returned if base is not ok */
538 if (errno
== EINVAL
) {
539 if (base
== 0 || (base
>1 && base
<37)) {
540 /* Base was ok so it's because we were not
541 * able to make the convertion.
550 #error "You need the strtoq function"
551 #endif /* HAVE_STRTOQ */
552 #endif /* HAVE_BSD_STRTOLL */
553 #endif /* HAVE_STRTOLL */
556 #ifndef HAVE_STRTOULL
557 unsigned long long int rep_strtoull(const char *str
, char **endptr
, int base
)
560 return strtouq(str
, endptr
, base
);
561 #elif defined(HAVE___STRTOULL)
562 return __strtoull(str
, endptr
, base
);
563 #elif SIZEOF_LONG == SIZEOF_LONG_LONG
564 return (unsigned long long int) strtoul(str
, endptr
, base
);
566 # error "You need a strtoull function"
570 #ifdef HAVE_BSD_STRTOLL
572 unsigned long long int rep_strtoull(const char *str
, char **endptr
, int base
)
574 unsigned long long int nb
= strtouq(str
, endptr
, base
);
575 /* In linux EINVAL is only returned if base is not ok */
576 if (errno
== EINVAL
) {
577 if (base
== 0 || (base
>1 && base
<37)) {
578 /* Base was ok so it's because we were not
579 * able to make the convertion.
588 #error "You need the strtouq function"
589 #endif /* HAVE_STRTOUQ */
590 #endif /* HAVE_BSD_STRTOLL */
591 #endif /* HAVE_STRTOULL */
594 int rep_setenv(const char *name
, const char *value
, int overwrite
)
600 if (!overwrite
&& getenv(name
)) {
613 memcpy(p
+l1
+1, value
, l2
);
625 #ifndef HAVE_UNSETENV
626 int rep_unsetenv(const char *name
)
628 extern char **environ
;
629 size_t len
= strlen(name
);
632 if (environ
== NULL
|| getenv(name
) == NULL
) {
636 for (i
=0;environ
[i
];i
++) /* noop */ ;
641 if (strncmp(environ
[i
], name
, len
) == 0 && environ
[i
][len
] == '=') {
642 /* note: we do _not_ free the old variable here. It is unsafe to
643 do so, as the pointer may not have come from malloc */
644 memmove(&environ
[i
], &environ
[i
+1], (count
-i
)*sizeof(char *));
656 int rep_utime(const char *filename
, const struct utimbuf
*buf
)
664 int rep_utimes(const char *filename
, const struct timeval tv
[2])
668 u
.actime
= tv
[0].tv_sec
;
669 if (tv
[0].tv_usec
> 500000) {
673 u
.modtime
= tv
[1].tv_sec
;
674 if (tv
[1].tv_usec
> 500000) {
678 return utime(filename
, &u
);
683 int rep_dup2(int oldfd
, int newfd
)
692 chown isn't used much but OS/2 doesn't have it
694 int rep_chown(const char *fname
, uid_t uid
, gid_t gid
)
702 int rep_link(const char *oldpath
, const char *newpath
)
709 #ifndef HAVE_READLINK
710 int rep_readlink(const char *path
, char *buf
, size_t bufsiz
)
718 int rep_symlink(const char *oldpath
, const char *newpath
)
726 int rep_lchown(const char *fname
,uid_t uid
,gid_t gid
)
733 #ifndef HAVE_REALPATH
734 char *rep_realpath(const char *path
, char *resolved_path
)
736 /* As realpath is not a system call we can't return ENOSYS. */
744 void *rep_memmem(const void *haystack
, size_t haystacklen
,
745 const void *needle
, size_t needlelen
)
747 if (needlelen
== 0) {
748 return discard_const(haystack
);
750 while (haystacklen
>= needlelen
) {
751 char *p
= (char *)memchr(haystack
, *(const char *)needle
,
752 haystacklen
-(needlelen
-1));
754 if (memcmp(p
, needle
, needlelen
) == 0) {
758 haystacklen
-= (p
- (const char *)haystack
) + 1;
764 #if !defined(HAVE_VDPRINTF) || !defined(HAVE_C99_VSNPRINTF)
765 int rep_vdprintf(int fd
, const char *format
, va_list ap
)
770 vasprintf(&s
, format
, ap
);
775 ret
= write(fd
, s
, strlen(s
));
781 #if !defined(HAVE_DPRINTF) || !defined(HAVE_C99_VSNPRINTF)
782 int rep_dprintf(int fd
, const char *format
, ...)
787 va_start(ap
, format
);
788 ret
= vdprintf(fd
, format
, ap
);
795 #ifndef HAVE_GET_CURRENT_DIR_NAME
796 char *rep_get_current_dir_name(void)
798 char buf
[PATH_MAX
+1];
800 p
= getcwd(buf
, sizeof(buf
));
808 #ifndef HAVE_STRERROR_R
809 int rep_strerror_r(int errnum
, char *buf
, size_t buflen
)
811 char *s
= strerror(errnum
);
812 if (strlen(s
)+1 > buflen
) {
816 strncpy(buf
, s
, buflen
);
821 #ifndef HAVE_CLOCK_GETTIME
822 int rep_clock_gettime(clockid_t clk_id
, struct timespec
*tp
)
826 case 0: /* CLOCK_REALTIME :*/
827 #ifdef HAVE_GETTIMEOFDAY_TZ
828 gettimeofday(&tval
,NULL
);
832 tp
->tv_sec
= tval
.tv_sec
;
833 tp
->tv_nsec
= tval
.tv_usec
* 1000;
843 #ifndef HAVE_MEMALIGN
844 void *rep_memalign( size_t align
, size_t size
)
846 #if defined(HAVE_POSIX_MEMALIGN)
848 int ret
= posix_memalign( &p
, align
, size
);
854 /* On *BSD systems memaligns doesn't exist, but memory will
855 * be aligned on allocations of > pagesize. */
856 #if defined(SYSCONF_SC_PAGESIZE)
857 size_t pagesize
= (size_t)sysconf(_SC_PAGESIZE
);
858 #elif defined(HAVE_GETPAGESIZE)
859 size_t pagesize
= (size_t)getpagesize();
861 size_t pagesize
= (size_t)-1;
863 if (pagesize
== (size_t)-1) {
867 if (size
< pagesize
) {
875 #ifndef HAVE_GETPEEREID
876 int rep_getpeereid(int s
, uid_t
*uid
, gid_t
*gid
)
878 #if defined(HAVE_PEERCRED)
880 socklen_t cred_len
= sizeof(struct ucred
);
884 ret
= getsockopt(s
, SOL_SOCKET
, SO_PEERCRED
, (void *)&cred
, &cred_len
);
889 if (cred_len
!= sizeof(struct ucred
)) {
905 int rep_usleep(useconds_t sec
)
909 * Fake it with select...
912 tval
.tv_usec
= usecs
/1000;
913 select(0,NULL
,NULL
,NULL
,&tval
);
916 #endif /* HAVE_USLEEP */
918 #ifndef HAVE_SETPROCTITLE
919 void rep_setproctitle(const char *fmt
, ...)