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, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #include "system/filesys.h"
28 #include "system/time.h"
29 #include "system/passwd.h"
30 #include "system/syslog.h"
31 #include "system/network.h"
32 #include "system/locale.h"
33 #include "system/wait.h"
35 void replace_dummy(void);
36 void replace_dummy(void) {}
38 #ifndef HAVE_FTRUNCATE
39 /*******************************************************************
40 ftruncate for operating systems that don't have it
41 ********************************************************************/
42 int rep_ftruncate(int f, off_t l)
46 #elif defined(F_FREESP)
53 return fcntl(f, F_FREESP, &fl);
55 #error "you must have a ftruncate function"
58 #endif /* HAVE_FTRUNCATE */
62 /* like strncpy but does not 0 fill the buffer and always null
63 terminates. bufsize is the size of the destination buffer */
64 size_t rep_strlcpy(char *d, const char *s, size_t bufsize)
66 size_t len = strlen(s);
68 if (bufsize <= 0) return 0;
69 if (len >= bufsize) len = bufsize-1;
77 /* like strncat but does not 0 fill the buffer and always null
78 terminates. bufsize is the length of the buffer, which should
79 be one more than the maximum resulting string length */
80 size_t rep_strlcat(char *d, const char *s, size_t bufsize)
82 size_t len1 = strlen(d);
83 size_t len2 = strlen(s);
84 size_t ret = len1 + len2;
86 if (len1+len2 >= bufsize) {
87 len2 = bufsize - (len1+1);
90 memcpy(d+len1, s, len2);
98 /*******************************************************************
99 a mktime() replacement for those who don't have it - contributed by
100 C.A. Lademann <cal@zls.com>
101 Corrections by richard.kettlewell@kewill.com
102 ********************************************************************/
105 #define HOUR 60*MINUTE
108 time_t rep_mktime(struct tm *t)
113 int mon [] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
119 n = t->tm_year + 1900 - 1;
120 epoch = (t->tm_year - 70) * YEAR +
121 ((n / 4 - n / 100 + n / 400) - (1969 / 4 - 1969 / 100 + 1969 / 400)) * DAY;
123 y = t->tm_year + 1900;
126 for(i = 0; i < t->tm_mon; i++) {
127 epoch += mon [m] * DAY;
128 if(m == 1 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0))
137 epoch += (t->tm_mday - 1) * DAY;
138 epoch += t->tm_hour * HOUR + t->tm_min * MINUTE + t->tm_sec;
140 if((u = localtime(&epoch)) != NULL) {
141 t->tm_sec = u->tm_sec;
142 t->tm_min = u->tm_min;
143 t->tm_hour = u->tm_hour;
144 t->tm_mday = u->tm_mday;
145 t->tm_mon = u->tm_mon;
146 t->tm_year = u->tm_year;
147 t->tm_wday = u->tm_wday;
148 t->tm_yday = u->tm_yday;
149 t->tm_isdst = u->tm_isdst;
154 #endif /* !HAVE_MKTIME */
157 #ifndef HAVE_INITGROUPS
158 /****************************************************************************
159 some systems don't have an initgroups call
160 ****************************************************************************/
161 int rep_initgroups(char *name, gid_t id)
163 #ifndef HAVE_SETGROUPS
164 /* yikes! no SETGROUPS or INITGROUPS? how can this work? */
167 #else /* HAVE_SETGROUPS */
171 gid_t *grouplst = NULL;
178 if((grouplst = malloc(sizeof(gid_t) * max_gr)) == NULL) {
185 while (i < max_gr && ((g = (struct group *)getgrent()) != (struct group *)NULL)) {
190 while (gr && (*gr != (char)NULL)) {
191 if (strcmp(name,gr) == 0) {
192 grouplst[i] = g->gr_gid;
201 ret = setgroups(i, grouplst);
204 #endif /* HAVE_SETGROUPS */
206 #endif /* HAVE_INITGROUPS */
209 #if (defined(SecureWare) && defined(SCO))
210 /* This is needed due to needing the nap() function but we don't want
211 to include the Xenix libraries since that will break other things...
212 BTW: system call # 0x0c28 is the same as calling nap() */
213 long nap(long milliseconds) {
214 return syscall(0x0c28, milliseconds);
220 /*******************************************************************
221 safely copies memory, ensuring no overlap problems.
222 this is only used if the machine does not have it's own memmove().
223 this is not the fastest algorithm in town, but it will do for our
225 ********************************************************************/
226 void *rep_memmove(void *dest,const void *src,int size)
230 if (dest==src || !size) return(dest);
232 d = (unsigned long)dest;
233 s = (unsigned long)src;
235 if ((d >= (s+size)) || (s >= (d+size))) {
237 memcpy(dest,src,size);
242 /* we can forward copy */
243 if (s-d >= sizeof(int) &&
246 !(size%sizeof(int))) {
247 /* do it all as words */
248 int *idest = (int *)dest;
249 int *isrc = (int *)src;
251 for (i=0;i<size;i++) idest[i] = isrc[i];
254 char *cdest = (char *)dest;
255 char *csrc = (char *)src;
256 for (i=0;i<size;i++) cdest[i] = csrc[i];
259 /* must backward copy */
260 if (d-s >= sizeof(int) &&
263 !(size%sizeof(int))) {
264 /* do it all as words */
265 int *idest = (int *)dest;
266 int *isrc = (int *)src;
268 for (i=size-1;i>=0;i--) idest[i] = isrc[i];
271 char *cdest = (char *)dest;
272 char *csrc = (char *)src;
273 for (i=size-1;i>=0;i--) cdest[i] = csrc[i];
278 #endif /* HAVE_MEMMOVE */
281 /****************************************************************************
283 ****************************************************************************/
284 char *rep_strdup(const char *s)
289 if (!s) return(NULL);
292 ret = (char *)malloc(len);
293 if (!ret) return(NULL);
297 #endif /* HAVE_STRDUP */
299 #ifndef WITH_PTHREADS
300 /* REWRITE: not thread safe */
301 #ifdef REPLACE_INET_NTOA
302 char *rep_inet_ntoa(struct in_addr ip)
304 uint8_t *p = (uint8_t *)&ip.s_addr;
306 slprintf(buf, 17, "%d.%d.%d.%d",
307 (int)p[0], (int)p[1], (int)p[2], (int)p[3]);
310 #endif /* REPLACE_INET_NTOA */
313 #ifndef HAVE_SETLINEBUF
314 void rep_setlinebuf(FILE *stream)
316 setvbuf(stream, (char *)NULL, _IOLBF, 0);
318 #endif /* HAVE_SETLINEBUF */
322 void rep_vsyslog (int facility_priority, const char *format, va_list arglist)
325 vasprintf(&msg, format, arglist);
328 syslog(facility_priority, "%s", msg);
331 #endif /* HAVE_SYSLOG */
332 #endif /* HAVE_VSYSLOG */
336 Some platforms don't have strnlen
338 size_t rep_strnlen(const char *s, size_t max)
342 for (len = 0; len < max; len++) {
343 if (s[len] == '\0') {
353 Some platforms don't have strndup.
355 char *rep_strndup(const char *s, size_t n)
371 int rep_waitpid(pid_t pid,int *status,int options)
373 return wait4(pid, status, options, NULL);
378 int rep_seteuid(uid_t euid)
380 #ifdef HAVE_SETRESUID
381 return setresuid(-1, euid, -1);
383 # error "You need a seteuid function"
389 int rep_setegid(gid_t egid)
391 #ifdef HAVE_SETRESGID
392 return setresgid(-1, egid, -1);
394 # error "You need a setegid function"
399 /*******************************************************************
400 os/2 also doesn't have chroot
401 ********************************************************************/
403 int rep_chroot(const char *dname)
410 /*****************************************************************
411 Possibly replace mkstemp if it is broken.
412 *****************************************************************/
414 #ifndef HAVE_SECURE_MKSTEMP
415 int rep_mkstemp(char *template)
417 /* have a reasonable go at emulating it. Hope that
418 the system mktemp() isn't completly hopeless */
419 char *p = mktemp(template);
422 return open(p, O_CREAT|O_EXCL|O_RDWR, 0600);
427 char *rep_mkdtemp(char *template)
431 if ((dname = mktemp(template))) {
432 if (mkdir(dname, 0700) >= 0) {
441 /*****************************************************************
442 Watch out: this is not thread safe.
443 *****************************************************************/
446 ssize_t rep_pread(int __fd, void *__buf, size_t __nbytes, off_t __offset)
448 if (lseek(__fd, __offset, SEEK_SET) != __offset) {
451 return read(__fd, __buf, __nbytes);
455 /*****************************************************************
456 Watch out: this is not thread safe.
457 *****************************************************************/
460 ssize_t rep_pwrite(int __fd, const void *__buf, size_t __nbytes, off_t __offset)
462 if (lseek(__fd, __offset, SEEK_SET) != __offset) {
465 return write(__fd, __buf, __nbytes);
469 #ifndef HAVE_STRCASESTR
470 char *rep_strcasestr(const char *haystack, const char *needle)
473 size_t nlen = strlen(needle);
474 for (s=haystack;*s;s++) {
475 if (toupper(*needle) == toupper(*s) &&
476 strncasecmp(s, needle, nlen) == 0) {
477 return (char *)((intptr_t)s);
484 #ifndef HAVE_STRTOK_R
485 /* based on GLIBC version, copyright Free Software Foundation */
486 char *rep_strtok_r(char *s, const char *delim, char **save_ptr)
490 if (s == NULL) s = *save_ptr;
492 s += strspn(s, delim);
499 s = strpbrk(token, delim);
501 *save_ptr = token + strlen(token);
512 long long int rep_strtoll(const char *str, char **endptr, int base)
515 return strtoq(str, endptr, base);
516 #elif defined(HAVE___STRTOLL)
517 return __strtoll(str, endptr, base);
518 #elif SIZEOF_LONG == SIZEOF_LONG_LONG
519 return (long long int) strtol(str, endptr, base);
521 # error "You need a strtoll function"
527 #ifndef HAVE_STRTOULL
528 unsigned long long int rep_strtoull(const char *str, char **endptr, int base)
531 return strtouq(str, endptr, base);
532 #elif defined(HAVE___STRTOULL)
533 return __strtoull(str, endptr, base);
534 #elif SIZEOF_LONG == SIZEOF_LONG_LONG
535 return (unsigned long long int) strtoul(str, endptr, base);
537 # error "You need a strtoull function"
543 int rep_setenv(const char *name, const char *value, int overwrite)
549 if (!overwrite && getenv(name)) {
562 memcpy(p+l1+1, value, l2);
574 #ifndef HAVE_UNSETENV
575 int rep_unsetenv(const char *name)
577 extern char **environ;
578 size_t len = strlen(name);
581 if (environ == NULL || getenv(name) == NULL) {
585 for (i=0;environ[i];i++) /* noop */ ;
590 if (strncmp(environ[i], name, len) == 0 && environ[i][len] == '=') {
591 /* note: we do _not_ free the old variable here. It is unsafe to
592 do so, as the pointer may not have come from malloc */
593 memmove(&environ[i], &environ[i+1], (count-i)*sizeof(char *));
604 #ifndef HAVE_SOCKETPAIR
605 int rep_socketpair(int d, int type, int protocol, int sv[2])
608 errno = EAFNOSUPPORT;
613 errno = EPROTONOSUPPORT;
617 if (type != SOCK_STREAM) {