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
7 ** NOTE! The following LGPL license applies to the replace
8 ** library. This does NOT imply that all of Samba is released
11 This library is free software; you can redistribute it and/or
12 modify it under the terms of the GNU Lesser General Public
13 License as published by the Free Software Foundation; either
14 version 3 of the License, or (at your option) any later version.
16 This library is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 Lesser General Public License for more details.
21 You should have received a copy of the GNU Lesser General Public
22 License along with this library; if not, see <http://www.gnu.org/licenses/>.
27 #include "system/filesys.h"
28 #include "system/time.h"
29 #include "system/passwd.h"
30 #include "system/syslog.h"
31 #include "system/locale.h"
32 #include "system/wait.h"
34 void replace_dummy(void);
35 void replace_dummy(void) {}
37 #ifndef HAVE_FTRUNCATE
38 /*******************************************************************
39 ftruncate for operating systems that don't have it
40 ********************************************************************/
41 int rep_ftruncate(int f
, off_t l
)
45 #elif defined(F_FREESP)
52 return fcntl(f
, F_FREESP
, &fl
);
54 #error "you must have a ftruncate function"
57 #endif /* HAVE_FTRUNCATE */
61 /* like strncpy but does not 0 fill the buffer and always null
62 terminates. bufsize is the size of the destination buffer */
63 size_t rep_strlcpy(char *d
, const char *s
, size_t bufsize
)
65 size_t len
= strlen(s
);
67 if (bufsize
<= 0) return 0;
68 if (len
>= bufsize
) len
= bufsize
-1;
76 /* like strncat but does not 0 fill the buffer and always null
77 terminates. bufsize is the length of the buffer, which should
78 be one more than the maximum resulting string length */
79 size_t rep_strlcat(char *d
, const char *s
, size_t bufsize
)
81 size_t len1
= strlen(d
);
82 size_t len2
= strlen(s
);
83 size_t ret
= len1
+ len2
;
85 if (len1
+len2
>= bufsize
) {
86 if (bufsize
< (len1
+1)) {
89 len2
= bufsize
- (len1
+1);
92 memcpy(d
+len1
, s
, len2
);
100 /*******************************************************************
101 a mktime() replacement for those who don't have it - contributed by
102 C.A. Lademann <cal@zls.com>
103 Corrections by richard.kettlewell@kewill.com
104 ********************************************************************/
107 #define HOUR 60*MINUTE
110 time_t rep_mktime(struct tm
*t
)
115 int mon
[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
121 n
= t
->tm_year
+ 1900 - 1;
122 epoch
= (t
->tm_year
- 70) * YEAR
+
123 ((n
/ 4 - n
/ 100 + n
/ 400) - (1969 / 4 - 1969 / 100 + 1969 / 400)) * DAY
;
125 y
= t
->tm_year
+ 1900;
128 for(i
= 0; i
< t
->tm_mon
; i
++) {
129 epoch
+= mon
[m
] * DAY
;
130 if(m
== 1 && y
% 4 == 0 && (y
% 100 != 0 || y
% 400 == 0))
139 epoch
+= (t
->tm_mday
- 1) * DAY
;
140 epoch
+= t
->tm_hour
* HOUR
+ t
->tm_min
* MINUTE
+ t
->tm_sec
;
142 if((u
= localtime(&epoch
)) != NULL
) {
143 t
->tm_sec
= u
->tm_sec
;
144 t
->tm_min
= u
->tm_min
;
145 t
->tm_hour
= u
->tm_hour
;
146 t
->tm_mday
= u
->tm_mday
;
147 t
->tm_mon
= u
->tm_mon
;
148 t
->tm_year
= u
->tm_year
;
149 t
->tm_wday
= u
->tm_wday
;
150 t
->tm_yday
= u
->tm_yday
;
151 t
->tm_isdst
= u
->tm_isdst
;
156 #endif /* !HAVE_MKTIME */
159 #ifndef HAVE_INITGROUPS
160 /****************************************************************************
161 some systems don't have an initgroups call
162 ****************************************************************************/
163 int rep_initgroups(char *name
, gid_t id
)
165 #ifndef HAVE_SETGROUPS
166 /* yikes! no SETGROUPS or INITGROUPS? how can this work? */
169 #else /* HAVE_SETGROUPS */
173 gid_t
*grouplst
= NULL
;
174 int max_gr
= NGROUPS_MAX
;
180 if((grouplst
= malloc(sizeof(gid_t
) * max_gr
)) == NULL
) {
187 while (i
< max_gr
&& ((g
= (struct group
*)getgrent()) != (struct group
*)NULL
)) {
192 while (gr
&& (*gr
!= (char)NULL
)) {
193 if (strcmp(name
,gr
) == 0) {
194 grouplst
[i
] = g
->gr_gid
;
203 ret
= setgroups(i
, grouplst
);
206 #endif /* HAVE_SETGROUPS */
208 #endif /* HAVE_INITGROUPS */
211 #if (defined(SecureWare) && defined(SCO))
212 /* This is needed due to needing the nap() function but we don't want
213 to include the Xenix libraries since that will break other things...
214 BTW: system call # 0x0c28 is the same as calling nap() */
215 long nap(long milliseconds
) {
216 return syscall(0x0c28, milliseconds
);
222 /*******************************************************************
223 safely copies memory, ensuring no overlap problems.
224 this is only used if the machine does not have its own memmove().
225 this is not the fastest algorithm in town, but it will do for our
227 ********************************************************************/
228 void *rep_memmove(void *dest
,const void *src
,int size
)
232 if (dest
==src
|| !size
) return(dest
);
234 d
= (unsigned long)dest
;
235 s
= (unsigned long)src
;
237 if ((d
>= (s
+size
)) || (s
>= (d
+size
))) {
239 memcpy(dest
,src
,size
);
244 /* we can forward copy */
245 if (s
-d
>= sizeof(int) &&
248 !(size
%sizeof(int))) {
249 /* do it all as words */
250 int *idest
= (int *)dest
;
251 int *isrc
= (int *)src
;
253 for (i
=0;i
<size
;i
++) idest
[i
] = isrc
[i
];
256 char *cdest
= (char *)dest
;
257 char *csrc
= (char *)src
;
258 for (i
=0;i
<size
;i
++) cdest
[i
] = csrc
[i
];
261 /* must backward copy */
262 if (d
-s
>= sizeof(int) &&
265 !(size
%sizeof(int))) {
266 /* do it all as words */
267 int *idest
= (int *)dest
;
268 int *isrc
= (int *)src
;
270 for (i
=size
-1;i
>=0;i
--) idest
[i
] = isrc
[i
];
273 char *cdest
= (char *)dest
;
274 char *csrc
= (char *)src
;
275 for (i
=size
-1;i
>=0;i
--) cdest
[i
] = csrc
[i
];
280 #endif /* HAVE_MEMMOVE */
283 /****************************************************************************
285 ****************************************************************************/
286 char *rep_strdup(const char *s
)
291 if (!s
) return(NULL
);
294 ret
= (char *)malloc(len
);
295 if (!ret
) return(NULL
);
299 #endif /* HAVE_STRDUP */
301 #ifndef HAVE_SETLINEBUF
302 void rep_setlinebuf(FILE *stream
)
304 setvbuf(stream
, (char *)NULL
, _IOLBF
, 0);
306 #endif /* HAVE_SETLINEBUF */
310 void rep_vsyslog (int facility_priority
, const char *format
, va_list arglist
)
313 vasprintf(&msg
, format
, arglist
);
316 syslog(facility_priority
, "%s", msg
);
319 #endif /* HAVE_SYSLOG */
320 #endif /* HAVE_VSYSLOG */
324 Some platforms don't have strnlen
326 size_t rep_strnlen(const char *s
, size_t max
)
330 for (len
= 0; len
< max
; len
++) {
331 if (s
[len
] == '\0') {
341 Some platforms don't have strndup.
343 char *rep_strndup(const char *s
, size_t n
)
359 int rep_waitpid(pid_t pid
,int *status
,int options
)
361 return wait4(pid
, status
, options
, NULL
);
366 int rep_seteuid(uid_t euid
)
368 #ifdef HAVE_SETRESUID
369 return setresuid(-1, euid
, -1);
371 # error "You need a seteuid function"
377 int rep_setegid(gid_t egid
)
379 #ifdef HAVE_SETRESGID
380 return setresgid(-1, egid
, -1);
382 # error "You need a setegid function"
387 /*******************************************************************
388 os/2 also doesn't have chroot
389 ********************************************************************/
391 int rep_chroot(const char *dname
)
398 /*****************************************************************
399 Possibly replace mkstemp if it is broken.
400 *****************************************************************/
402 #ifndef HAVE_SECURE_MKSTEMP
403 int rep_mkstemp(char *template)
405 /* have a reasonable go at emulating it. Hope that
406 the system mktemp() isn't completly hopeless */
407 char *p
= mktemp(template);
410 return open(p
, O_CREAT
|O_EXCL
|O_RDWR
, 0600);
415 char *rep_mkdtemp(char *template)
419 if ((dname
= mktemp(template))) {
420 if (mkdir(dname
, 0700) >= 0) {
429 /*****************************************************************
430 Watch out: this is not thread safe.
431 *****************************************************************/
434 ssize_t
rep_pread(int __fd
, void *__buf
, size_t __nbytes
, off_t __offset
)
436 if (lseek(__fd
, __offset
, SEEK_SET
) != __offset
) {
439 return read(__fd
, __buf
, __nbytes
);
443 /*****************************************************************
444 Watch out: this is not thread safe.
445 *****************************************************************/
448 ssize_t
rep_pwrite(int __fd
, const void *__buf
, size_t __nbytes
, off_t __offset
)
450 if (lseek(__fd
, __offset
, SEEK_SET
) != __offset
) {
453 return write(__fd
, __buf
, __nbytes
);
457 #ifndef HAVE_STRCASESTR
458 char *rep_strcasestr(const char *haystack
, const char *needle
)
461 size_t nlen
= strlen(needle
);
462 for (s
=haystack
;*s
;s
++) {
463 if (toupper(*needle
) == toupper(*s
) &&
464 strncasecmp(s
, needle
, nlen
) == 0) {
465 return (char *)((uintptr_t)s
);
472 #ifndef HAVE_STRTOK_R
473 /* based on GLIBC version, copyright Free Software Foundation */
474 char *rep_strtok_r(char *s
, const char *delim
, char **save_ptr
)
478 if (s
== NULL
) s
= *save_ptr
;
480 s
+= strspn(s
, delim
);
487 s
= strpbrk(token
, delim
);
489 *save_ptr
= token
+ strlen(token
);
500 long long int rep_strtoll(const char *str
, char **endptr
, int base
)
503 return strtoq(str
, endptr
, base
);
504 #elif defined(HAVE___STRTOLL)
505 return __strtoll(str
, endptr
, base
);
506 #elif SIZEOF_LONG == SIZEOF_LONG_LONG
507 return (long long int) strtol(str
, endptr
, base
);
509 # error "You need a strtoll function"
515 #ifndef HAVE_STRTOULL
516 unsigned long long int rep_strtoull(const char *str
, char **endptr
, int base
)
519 return strtouq(str
, endptr
, base
);
520 #elif defined(HAVE___STRTOULL)
521 return __strtoull(str
, endptr
, base
);
522 #elif SIZEOF_LONG == SIZEOF_LONG_LONG
523 return (unsigned long long int) strtoul(str
, endptr
, base
);
525 # error "You need a strtoull function"
531 int rep_setenv(const char *name
, const char *value
, int overwrite
)
537 if (!overwrite
&& getenv(name
)) {
550 memcpy(p
+l1
+1, value
, l2
);
562 #ifndef HAVE_UNSETENV
563 int rep_unsetenv(const char *name
)
565 extern char **environ
;
566 size_t len
= strlen(name
);
569 if (environ
== NULL
|| getenv(name
) == NULL
) {
573 for (i
=0;environ
[i
];i
++) /* noop */ ;
578 if (strncmp(environ
[i
], name
, len
) == 0 && environ
[i
][len
] == '=') {
579 /* note: we do _not_ free the old variable here. It is unsafe to
580 do so, as the pointer may not have come from malloc */
581 memmove(&environ
[i
], &environ
[i
+1], (count
-i
)*sizeof(char *));
593 int rep_utime(const char *filename
, const struct utimbuf
*buf
)
601 int rep_utimes(const char *filename
, const struct timeval tv
[2])
605 u
.actime
= tv
[0].tv_sec
;
606 if (tv
[0].tv_usec
> 500000) {
610 u
.modtime
= tv
[1].tv_sec
;
611 if (tv
[1].tv_usec
> 500000) {
615 return utime(filename
, &u
);
620 int rep_dup2(int oldfd
, int newfd
)
629 chown isn't used much but OS/2 doesn't have it
631 int rep_chown(const char *fname
, uid_t uid
, gid_t gid
)
639 int rep_link(const char *oldpath
, const char *newpath
)
646 #ifndef HAVE_READLINK
647 int rep_readlink(const char *path
, char *buf
, size_t bufsiz
)
655 int rep_symlink(const char *oldpath
, const char *newpath
)
663 int rep_lchown(const char *fname
,uid_t uid
,gid_t gid
)
670 #ifndef HAVE_REALPATH
671 char *rep_realpath(const char *path
, char *resolved_path
)
673 /* As realpath is not a system call we can't return ENOSYS. */