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/passwd.h"
31 #include "system/syslog.h"
32 #include "system/locale.h"
33 #include "system/wait.h"
36 #define mkdir(d,m) _mkdir(d)
39 void replace_dummy(void);
40 void replace_dummy(void) {}
42 #ifndef HAVE_FTRUNCATE
43 /*******************************************************************
44 ftruncate for operating systems that don't have it
45 ********************************************************************/
46 int rep_ftruncate(int f
, off_t l
)
50 #elif defined(F_FREESP)
57 return fcntl(f
, F_FREESP
, &fl
);
59 #error "you must have a ftruncate function"
62 #endif /* HAVE_FTRUNCATE */
66 /* like strncpy but does not 0 fill the buffer and always null
67 terminates. bufsize is the size of the destination buffer */
68 size_t rep_strlcpy(char *d
, const char *s
, size_t bufsize
)
70 size_t len
= strlen(s
);
72 if (bufsize
<= 0) return 0;
73 if (len
>= bufsize
) len
= bufsize
-1;
81 /* like strncat but does not 0 fill the buffer and always null
82 terminates. bufsize is the length of the buffer, which should
83 be one more than the maximum resulting string length */
84 size_t rep_strlcat(char *d
, const char *s
, size_t bufsize
)
86 size_t len1
= strlen(d
);
87 size_t len2
= strlen(s
);
88 size_t ret
= len1
+ len2
;
90 if (len1
+len2
>= bufsize
) {
91 if (bufsize
< (len1
+1)) {
94 len2
= bufsize
- (len1
+1);
97 memcpy(d
+len1
, s
, len2
);
105 /*******************************************************************
106 a mktime() replacement for those who don't have it - contributed by
107 C.A. Lademann <cal@zls.com>
108 Corrections by richard.kettlewell@kewill.com
109 ********************************************************************/
112 #define HOUR 60*MINUTE
115 time_t rep_mktime(struct tm
*t
)
120 int mon
[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
126 n
= t
->tm_year
+ 1900 - 1;
127 epoch
= (t
->tm_year
- 70) * YEAR
+
128 ((n
/ 4 - n
/ 100 + n
/ 400) - (1969 / 4 - 1969 / 100 + 1969 / 400)) * DAY
;
130 y
= t
->tm_year
+ 1900;
133 for(i
= 0; i
< t
->tm_mon
; i
++) {
134 epoch
+= mon
[m
] * DAY
;
135 if(m
== 1 && y
% 4 == 0 && (y
% 100 != 0 || y
% 400 == 0))
144 epoch
+= (t
->tm_mday
- 1) * DAY
;
145 epoch
+= t
->tm_hour
* HOUR
+ t
->tm_min
* MINUTE
+ t
->tm_sec
;
147 if((u
= localtime(&epoch
)) != NULL
) {
148 t
->tm_sec
= u
->tm_sec
;
149 t
->tm_min
= u
->tm_min
;
150 t
->tm_hour
= u
->tm_hour
;
151 t
->tm_mday
= u
->tm_mday
;
152 t
->tm_mon
= u
->tm_mon
;
153 t
->tm_year
= u
->tm_year
;
154 t
->tm_wday
= u
->tm_wday
;
155 t
->tm_yday
= u
->tm_yday
;
156 t
->tm_isdst
= u
->tm_isdst
;
161 #endif /* !HAVE_MKTIME */
164 #ifndef HAVE_INITGROUPS
165 /****************************************************************************
166 some systems don't have an initgroups call
167 ****************************************************************************/
168 int rep_initgroups(char *name
, gid_t id
)
170 #ifndef HAVE_SETGROUPS
171 /* yikes! no SETGROUPS or INITGROUPS? how can this work? */
174 #else /* HAVE_SETGROUPS */
178 gid_t
*grouplst
= NULL
;
179 int max_gr
= NGROUPS_MAX
;
185 if((grouplst
= malloc(sizeof(gid_t
) * max_gr
)) == NULL
) {
192 while (i
< max_gr
&& ((g
= (struct group
*)getgrent()) != (struct group
*)NULL
)) {
197 while (gr
&& (*gr
!= (char)NULL
)) {
198 if (strcmp(name
,gr
) == 0) {
199 grouplst
[i
] = g
->gr_gid
;
208 ret
= setgroups(i
, grouplst
);
211 #endif /* HAVE_SETGROUPS */
213 #endif /* HAVE_INITGROUPS */
216 #if (defined(SecureWare) && defined(SCO))
217 /* This is needed due to needing the nap() function but we don't want
218 to include the Xenix libraries since that will break other things...
219 BTW: system call # 0x0c28 is the same as calling nap() */
220 long nap(long milliseconds
) {
221 return syscall(0x0c28, milliseconds
);
227 /*******************************************************************
228 safely copies memory, ensuring no overlap problems.
229 this is only used if the machine does not have its own memmove().
230 this is not the fastest algorithm in town, but it will do for our
232 ********************************************************************/
233 void *rep_memmove(void *dest
,const void *src
,int size
)
237 if (dest
==src
|| !size
) return(dest
);
239 d
= (unsigned long)dest
;
240 s
= (unsigned long)src
;
242 if ((d
>= (s
+size
)) || (s
>= (d
+size
))) {
244 memcpy(dest
,src
,size
);
249 /* we can forward copy */
250 if (s
-d
>= sizeof(int) &&
253 !(size
%sizeof(int))) {
254 /* do it all as words */
255 int *idest
= (int *)dest
;
256 int *isrc
= (int *)src
;
258 for (i
=0;i
<size
;i
++) idest
[i
] = isrc
[i
];
261 char *cdest
= (char *)dest
;
262 char *csrc
= (char *)src
;
263 for (i
=0;i
<size
;i
++) cdest
[i
] = csrc
[i
];
266 /* must backward copy */
267 if (d
-s
>= sizeof(int) &&
270 !(size
%sizeof(int))) {
271 /* do it all as words */
272 int *idest
= (int *)dest
;
273 int *isrc
= (int *)src
;
275 for (i
=size
-1;i
>=0;i
--) idest
[i
] = isrc
[i
];
278 char *cdest
= (char *)dest
;
279 char *csrc
= (char *)src
;
280 for (i
=size
-1;i
>=0;i
--) cdest
[i
] = csrc
[i
];
285 #endif /* HAVE_MEMMOVE */
288 /****************************************************************************
290 ****************************************************************************/
291 char *rep_strdup(const char *s
)
296 if (!s
) return(NULL
);
299 ret
= (char *)malloc(len
);
300 if (!ret
) return(NULL
);
304 #endif /* HAVE_STRDUP */
306 #ifndef HAVE_SETLINEBUF
307 void rep_setlinebuf(FILE *stream
)
309 setvbuf(stream
, (char *)NULL
, _IOLBF
, 0);
311 #endif /* HAVE_SETLINEBUF */
315 void rep_vsyslog (int facility_priority
, const char *format
, va_list arglist
)
318 vasprintf(&msg
, format
, arglist
);
321 syslog(facility_priority
, "%s", msg
);
324 #endif /* HAVE_SYSLOG */
325 #endif /* HAVE_VSYSLOG */
329 Some platforms don't have strnlen
331 size_t rep_strnlen(const char *s
, size_t max
)
335 for (len
= 0; len
< max
; len
++) {
336 if (s
[len
] == '\0') {
346 Some platforms don't have strndup.
348 char *rep_strndup(const char *s
, size_t n
)
363 #if !defined(HAVE_WAITPID) && defined(HAVE_WAIT4)
364 int rep_waitpid(pid_t pid
,int *status
,int options
)
366 return wait4(pid
, status
, options
, NULL
);
371 int rep_seteuid(uid_t euid
)
373 #ifdef HAVE_SETRESUID
374 return setresuid(-1, euid
, -1);
383 int rep_setegid(gid_t egid
)
385 #ifdef HAVE_SETRESGID
386 return setresgid(-1, egid
, -1);
394 /*******************************************************************
395 os/2 also doesn't have chroot
396 ********************************************************************/
398 int rep_chroot(const char *dname
)
405 /*****************************************************************
406 Possibly replace mkstemp if it is broken.
407 *****************************************************************/
409 #ifndef HAVE_SECURE_MKSTEMP
410 int rep_mkstemp(char *template)
412 /* have a reasonable go at emulating it. Hope that
413 the system mktemp() isn't completely hopeless */
414 char *p
= mktemp(template);
417 return open(p
, O_CREAT
|O_EXCL
|O_RDWR
, 0600);
422 char *rep_mkdtemp(char *template)
426 if ((dname
= mktemp(template))) {
427 if (mkdir(dname
, 0700) >= 0) {
436 /*****************************************************************
437 Watch out: this is not thread safe.
438 *****************************************************************/
441 ssize_t
rep_pread(int __fd
, void *__buf
, size_t __nbytes
, off_t __offset
)
443 if (lseek(__fd
, __offset
, SEEK_SET
) != __offset
) {
446 return read(__fd
, __buf
, __nbytes
);
450 /*****************************************************************
451 Watch out: this is not thread safe.
452 *****************************************************************/
455 ssize_t
rep_pwrite(int __fd
, const void *__buf
, size_t __nbytes
, off_t __offset
)
457 if (lseek(__fd
, __offset
, SEEK_SET
) != __offset
) {
460 return write(__fd
, __buf
, __nbytes
);
464 #ifndef HAVE_STRCASESTR
465 char *rep_strcasestr(const char *haystack
, const char *needle
)
468 size_t nlen
= strlen(needle
);
469 for (s
=haystack
;*s
;s
++) {
470 if (toupper(*needle
) == toupper(*s
) &&
471 strncasecmp(s
, needle
, nlen
) == 0) {
472 return (char *)((uintptr_t)s
);
479 #ifndef HAVE_STRTOK_R
480 /* based on GLIBC version, copyright Free Software Foundation */
481 char *rep_strtok_r(char *s
, const char *delim
, char **save_ptr
)
485 if (s
== NULL
) s
= *save_ptr
;
487 s
+= strspn(s
, delim
);
494 s
= strpbrk(token
, delim
);
496 *save_ptr
= token
+ strlen(token
);
508 long long int rep_strtoll(const char *str
, char **endptr
, int base
)
511 return strtoq(str
, endptr
, base
);
512 #elif defined(HAVE___STRTOLL)
513 return __strtoll(str
, endptr
, base
);
514 #elif SIZEOF_LONG == SIZEOF_LONG_LONG
515 return (long long int) strtol(str
, endptr
, base
);
517 # error "You need a strtoll function"
521 #ifdef HAVE_BSD_STRTOLL
523 long long int rep_strtoll(const char *str
, char **endptr
, int base
)
525 long long int nb
= strtoq(str
, endptr
, base
);
526 /* In linux EINVAL is only returned if base is not ok */
527 if (errno
== EINVAL
) {
528 if (base
== 0 || (base
>1 && base
<37)) {
529 /* Base was ok so it's because we were not
530 * able to make the convertion.
539 #error "You need the strtoq function"
540 #endif /* HAVE_STRTOQ */
541 #endif /* HAVE_BSD_STRTOLL */
542 #endif /* HAVE_STRTOLL */
545 #ifndef HAVE_STRTOULL
546 unsigned long long int rep_strtoull(const char *str
, char **endptr
, int base
)
549 return strtouq(str
, endptr
, base
);
550 #elif defined(HAVE___STRTOULL)
551 return __strtoull(str
, endptr
, base
);
552 #elif SIZEOF_LONG == SIZEOF_LONG_LONG
553 return (unsigned long long int) strtoul(str
, endptr
, base
);
555 # error "You need a strtoull function"
559 #ifdef HAVE_BSD_STRTOLL
561 unsigned long long int rep_strtoull(const char *str
, char **endptr
, int base
)
563 unsigned long long int nb
= strtouq(str
, endptr
, base
);
564 /* In linux EINVAL is only returned if base is not ok */
565 if (errno
== EINVAL
) {
566 if (base
== 0 || (base
>1 && base
<37)) {
567 /* Base was ok so it's because we were not
568 * able to make the convertion.
577 #error "You need the strtouq function"
578 #endif /* HAVE_STRTOUQ */
579 #endif /* HAVE_BSD_STRTOLL */
580 #endif /* HAVE_STRTOULL */
583 int rep_setenv(const char *name
, const char *value
, int overwrite
)
589 if (!overwrite
&& getenv(name
)) {
602 memcpy(p
+l1
+1, value
, l2
);
614 #ifndef HAVE_UNSETENV
615 int rep_unsetenv(const char *name
)
617 extern char **environ
;
618 size_t len
= strlen(name
);
621 if (environ
== NULL
|| getenv(name
) == NULL
) {
625 for (i
=0;environ
[i
];i
++) /* noop */ ;
630 if (strncmp(environ
[i
], name
, len
) == 0 && environ
[i
][len
] == '=') {
631 /* note: we do _not_ free the old variable here. It is unsafe to
632 do so, as the pointer may not have come from malloc */
633 memmove(&environ
[i
], &environ
[i
+1], (count
-i
)*sizeof(char *));
645 int rep_utime(const char *filename
, const struct utimbuf
*buf
)
653 int rep_utimes(const char *filename
, const struct timeval tv
[2])
657 u
.actime
= tv
[0].tv_sec
;
658 if (tv
[0].tv_usec
> 500000) {
662 u
.modtime
= tv
[1].tv_sec
;
663 if (tv
[1].tv_usec
> 500000) {
667 return utime(filename
, &u
);
672 int rep_dup2(int oldfd
, int newfd
)
681 chown isn't used much but OS/2 doesn't have it
683 int rep_chown(const char *fname
, uid_t uid
, gid_t gid
)
691 int rep_link(const char *oldpath
, const char *newpath
)
698 #ifndef HAVE_READLINK
699 int rep_readlink(const char *path
, char *buf
, size_t bufsiz
)
707 int rep_symlink(const char *oldpath
, const char *newpath
)
715 int rep_lchown(const char *fname
,uid_t uid
,gid_t gid
)
722 #ifndef HAVE_REALPATH
723 char *rep_realpath(const char *path
, char *resolved_path
)
725 /* As realpath is not a system call we can't return ENOSYS. */
733 void *rep_memmem(const void *haystack
, size_t haystacklen
,
734 const void *needle
, size_t needlelen
)
736 if (needlelen
== 0) {
737 return discard_const(haystack
);
739 while (haystacklen
>= needlelen
) {
740 char *p
= (char *)memchr(haystack
, *(const char *)needle
,
741 haystacklen
-(needlelen
-1));
743 if (memcmp(p
, needle
, needlelen
) == 0) {
747 haystacklen
-= (p
- (const char *)haystack
) + 1;
753 #ifndef HAVE_VDPRINTF
754 int rep_vdprintf(int fd
, const char *format
, va_list ap
)
759 vasprintf(&s
, format
, ap
);
764 ret
= write(fd
, s
, strlen(s
));
771 int rep_dprintf(int fd
, const char *format
, ...)
776 va_start(ap
, format
);
777 ret
= vdprintf(fd
, format
, ap
);
784 #ifndef HAVE_GET_CURRENT_DIR_NAME
785 char *rep_get_current_dir_name(void)
787 char buf
[PATH_MAX
+1];
789 p
= getcwd(buf
, sizeof(buf
));
797 #if !defined(HAVE_STRERROR_R) || !defined(STRERROR_R_PROTO_COMPATIBLE)
798 int rep_strerror_r(int errnum
, char *buf
, size_t buflen
)
800 char *s
= strerror(errnum
);
801 if (strlen(s
)+1 > buflen
) {
805 strncpy(buf
, s
, buflen
);
810 #ifndef HAVE_CLOCK_GETTIME
811 int rep_clock_gettime(clockid_t clk_id
, struct timespec
*tp
)
815 case 0: /* CLOCK_REALTIME :*/
816 #ifdef HAVE_GETTIMEOFDAY_TZ
817 gettimeofday(&tval
,NULL
);
821 tp
->tv_sec
= tval
.tv_sec
;
822 tp
->tv_nsec
= tval
.tv_usec
* 1000;