2 Unix SMB/CIFS implementation.
3 replacement routines for broken systems
4 Copyright (C) Andrew Tridgell 1992-1998
6 ** NOTE! The following LGPL license applies to the replace
7 ** library. This does NOT imply that all of Samba is released
10 This library is free software; you can redistribute it and/or
11 modify it under the terms of the GNU Lesser General Public
12 License as published by the Free Software Foundation; either
13 version 3 of the License, or (at your option) any later version.
15 This library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Lesser General Public License for more details.
20 You should have received a copy of the GNU Lesser General Public
21 License along with this library; if not, see <http://www.gnu.org/licenses/>.
26 #include "system/filesys.h"
27 #include "system/time.h"
28 #include "system/passwd.h"
29 #include "system/syslog.h"
30 #include "system/locale.h"
31 #include "system/wait.h"
33 void replace_dummy(void);
34 void replace_dummy(void) {}
36 #ifndef HAVE_FTRUNCATE
37 /*******************************************************************
38 ftruncate for operating systems that don't have it
39 ********************************************************************/
40 int rep_ftruncate(int f, off_t l)
44 #elif defined(F_FREESP)
51 return fcntl(f, F_FREESP, &fl);
53 #error "you must have a ftruncate function"
56 #endif /* HAVE_FTRUNCATE */
60 /* like strncpy but does not 0 fill the buffer and always null
61 terminates. bufsize is the size of the destination buffer */
62 size_t rep_strlcpy(char *d, const char *s, size_t bufsize)
64 size_t len = strlen(s);
66 if (bufsize <= 0) return 0;
67 if (len >= bufsize) len = bufsize-1;
75 /* like strncat but does not 0 fill the buffer and always null
76 terminates. bufsize is the length of the buffer, which should
77 be one more than the maximum resulting string length */
78 size_t rep_strlcat(char *d, const char *s, size_t bufsize)
80 size_t len1 = strlen(d);
81 size_t len2 = strlen(s);
82 size_t ret = len1 + len2;
84 if (len1+len2 >= bufsize) {
85 len2 = bufsize - (len1+1);
88 memcpy(d+len1, s, len2);
96 /*******************************************************************
97 a mktime() replacement for those who don't have it - contributed by
98 C.A. Lademann <cal@zls.com>
99 Corrections by richard.kettlewell@kewill.com
100 ********************************************************************/
103 #define HOUR 60*MINUTE
106 time_t rep_mktime(struct tm *t)
111 int mon [] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
117 n = t->tm_year + 1900 - 1;
118 epoch = (t->tm_year - 70) * YEAR +
119 ((n / 4 - n / 100 + n / 400) - (1969 / 4 - 1969 / 100 + 1969 / 400)) * DAY;
121 y = t->tm_year + 1900;
124 for(i = 0; i < t->tm_mon; i++) {
125 epoch += mon [m] * DAY;
126 if(m == 1 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0))
135 epoch += (t->tm_mday - 1) * DAY;
136 epoch += t->tm_hour * HOUR + t->tm_min * MINUTE + t->tm_sec;
138 if((u = localtime(&epoch)) != NULL) {
139 t->tm_sec = u->tm_sec;
140 t->tm_min = u->tm_min;
141 t->tm_hour = u->tm_hour;
142 t->tm_mday = u->tm_mday;
143 t->tm_mon = u->tm_mon;
144 t->tm_year = u->tm_year;
145 t->tm_wday = u->tm_wday;
146 t->tm_yday = u->tm_yday;
147 t->tm_isdst = u->tm_isdst;
152 #endif /* !HAVE_MKTIME */
155 #ifndef HAVE_INITGROUPS
156 /****************************************************************************
157 some systems don't have an initgroups call
158 ****************************************************************************/
159 int rep_initgroups(char *name, gid_t id)
161 #ifndef HAVE_SETGROUPS
162 /* yikes! no SETGROUPS or INITGROUPS? how can this work? */
165 #else /* HAVE_SETGROUPS */
169 gid_t *grouplst = NULL;
176 if((grouplst = malloc(sizeof(gid_t) * max_gr)) == NULL) {
183 while (i < max_gr && ((g = (struct group *)getgrent()) != (struct group *)NULL)) {
188 while (gr && (*gr != (char)NULL)) {
189 if (strcmp(name,gr) == 0) {
190 grouplst[i] = g->gr_gid;
199 ret = setgroups(i, grouplst);
202 #endif /* HAVE_SETGROUPS */
204 #endif /* HAVE_INITGROUPS */
207 #if (defined(SecureWare) && defined(SCO))
208 /* This is needed due to needing the nap() function but we don't want
209 to include the Xenix libraries since that will break other things...
210 BTW: system call # 0x0c28 is the same as calling nap() */
211 long nap(long milliseconds) {
212 return syscall(0x0c28, milliseconds);
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)
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);
367 # error "You need a seteuid function"
373 int rep_setegid(gid_t egid)
375 #ifdef HAVE_SETRESGID
376 return setresgid(-1, egid, -1);
378 # error "You need a setegid function"
383 /*******************************************************************
384 os/2 also doesn't have chroot
385 ********************************************************************/
387 int rep_chroot(const char *dname)
394 /*****************************************************************
395 Possibly replace mkstemp if it is broken.
396 *****************************************************************/
398 #ifndef HAVE_SECURE_MKSTEMP
399 int rep_mkstemp(char *template)
401 /* have a reasonable go at emulating it. Hope that
402 the system mktemp() isn't completly hopeless */
403 char *p = mktemp(template);
406 return open(p, O_CREAT|O_EXCL|O_RDWR, 0600);
411 char *rep_mkdtemp(char *template)
415 if ((dname = mktemp(template))) {
416 if (mkdir(dname, 0700) >= 0) {
425 /*****************************************************************
426 Watch out: this is not thread safe.
427 *****************************************************************/
430 ssize_t rep_pread(int __fd, void *__buf, size_t __nbytes, off_t __offset)
432 if (lseek(__fd, __offset, SEEK_SET) != __offset) {
435 return read(__fd, __buf, __nbytes);
439 /*****************************************************************
440 Watch out: this is not thread safe.
441 *****************************************************************/
444 ssize_t rep_pwrite(int __fd, const void *__buf, size_t __nbytes, off_t __offset)
446 if (lseek(__fd, __offset, SEEK_SET) != __offset) {
449 return write(__fd, __buf, __nbytes);
453 #ifndef HAVE_STRCASESTR
454 char *rep_strcasestr(const char *haystack, const char *needle)
457 size_t nlen = strlen(needle);
458 for (s=haystack;*s;s++) {
459 if (toupper(*needle) == toupper(*s) &&
460 strncasecmp(s, needle, nlen) == 0) {
461 return (char *)((uintptr_t)s);
468 #ifndef HAVE_STRTOK_R
469 /* based on GLIBC version, copyright Free Software Foundation */
470 char *rep_strtok_r(char *s, const char *delim, char **save_ptr)
474 if (s == NULL) s = *save_ptr;
476 s += strspn(s, delim);
483 s = strpbrk(token, delim);
485 *save_ptr = token + strlen(token);
496 long long int rep_strtoll(const char *str, char **endptr, int base)
499 return strtoq(str, endptr, base);
500 #elif defined(HAVE___STRTOLL)
501 return __strtoll(str, endptr, base);
502 #elif SIZEOF_LONG == SIZEOF_LONG_LONG
503 return (long long int) strtol(str, endptr, base);
505 # error "You need a strtoll function"
511 #ifndef HAVE_STRTOULL
512 unsigned long long int rep_strtoull(const char *str, char **endptr, int base)
515 return strtouq(str, endptr, base);
516 #elif defined(HAVE___STRTOULL)
517 return __strtoull(str, endptr, base);
518 #elif SIZEOF_LONG == SIZEOF_LONG_LONG
519 return (unsigned long long int) strtoul(str, endptr, base);
521 # error "You need a strtoull function"
527 int rep_setenv(const char *name, const char *value, int overwrite)
533 if (!overwrite && getenv(name)) {
546 memcpy(p+l1+1, value, l2);
558 #ifndef HAVE_UNSETENV
559 int rep_unsetenv(const char *name)
561 extern char **environ;
562 size_t len = strlen(name);
565 if (environ == NULL || getenv(name) == NULL) {
569 for (i=0;environ[i];i++) /* noop */ ;
574 if (strncmp(environ[i], name, len) == 0 && environ[i][len] == '=') {
575 /* note: we do _not_ free the old variable here. It is unsafe to
576 do so, as the pointer may not have come from malloc */
577 memmove(&environ[i], &environ[i+1], (count-i)*sizeof(char *));
589 int rep_utime(const char *filename, const struct utimbuf *buf)
597 int rep_utimes(const char *filename, const struct timeval tv[2])
601 u.actime = tv[0].tv_sec;
602 if (tv[0].tv_usec > 500000) {
606 u.modtime = tv[1].tv_sec;
607 if (tv[1].tv_usec > 500000) {
611 return utime(filename, &u);