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 2 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 */
158 #if defined(HAVE_SETNETGRENT) && defined(HAVE_GETNETGRENT) && defined(HAVE_ENDNETGRENT)
160 * Search for a match in a netgroup. This replaces it on broken systems.
162 int rep_innetgr(const char *group, const char *host, const char *user,
165 char *hst, *usr, *dm;
168 while (getnetgrent(&hst, &usr, &dm)) {
169 if (((host == 0) || (hst == 0) || !strcmp(host, hst)) &&
170 ((user == 0) || (usr == 0) || !strcmp(user, usr)) &&
171 ((dom == 0) || (dm == 0) || !strcmp(dom, dm))) {
179 #endif /* HAVE_SETNETGRENT HAVE_GETNETGRENT HAVE_ENDNETGRENT */
180 #endif /* HAVE_INNETGR */
184 #ifndef HAVE_INITGROUPS
185 /****************************************************************************
186 some systems don't have an initgroups call
187 ****************************************************************************/
188 int rep_initgroups(char *name, gid_t id)
190 #ifndef HAVE_SETGROUPS
191 /* yikes! no SETGROUPS or INITGROUPS? how can this work? */
194 #else /* HAVE_SETGROUPS */
198 gid_t *grouplst = NULL;
205 if((grouplst = malloc(sizeof(gid_t) * max_gr)) == NULL) {
212 while (i < max_gr && ((g = (struct group *)getgrent()) != (struct group *)NULL)) {
217 while (gr && (*gr != (char)NULL)) {
218 if (strcmp(name,gr) == 0) {
219 grouplst[i] = g->gr_gid;
228 ret = setgroups(i, grouplst);
231 #endif /* HAVE_SETGROUPS */
233 #endif /* HAVE_INITGROUPS */
236 #if (defined(SecureWare) && defined(SCO))
237 /* This is needed due to needing the nap() function but we don't want
238 to include the Xenix libraries since that will break other things...
239 BTW: system call # 0x0c28 is the same as calling nap() */
240 long nap(long milliseconds) {
241 return syscall(0x0c28, milliseconds);
247 /*******************************************************************
248 safely copies memory, ensuring no overlap problems.
249 this is only used if the machine does not have it's own memmove().
250 this is not the fastest algorithm in town, but it will do for our
252 ********************************************************************/
253 void *rep_memmove(void *dest,const void *src,int size)
257 if (dest==src || !size) return(dest);
259 d = (unsigned long)dest;
260 s = (unsigned long)src;
262 if ((d >= (s+size)) || (s >= (d+size))) {
264 memcpy(dest,src,size);
269 /* we can forward copy */
270 if (s-d >= sizeof(int) &&
273 !(size%sizeof(int))) {
274 /* do it all as words */
275 int *idest = (int *)dest;
276 int *isrc = (int *)src;
278 for (i=0;i<size;i++) idest[i] = isrc[i];
281 char *cdest = (char *)dest;
282 char *csrc = (char *)src;
283 for (i=0;i<size;i++) cdest[i] = csrc[i];
286 /* must backward copy */
287 if (d-s >= sizeof(int) &&
290 !(size%sizeof(int))) {
291 /* do it all as words */
292 int *idest = (int *)dest;
293 int *isrc = (int *)src;
295 for (i=size-1;i>=0;i--) idest[i] = isrc[i];
298 char *cdest = (char *)dest;
299 char *csrc = (char *)src;
300 for (i=size-1;i>=0;i--) cdest[i] = csrc[i];
305 #endif /* HAVE_MEMMOVE */
308 /****************************************************************************
310 ****************************************************************************/
311 char *rep_strdup(const char *s)
316 if (!s) return(NULL);
319 ret = (char *)malloc(len);
320 if (!ret) return(NULL);
324 #endif /* HAVE_STRDUP */
326 #ifndef WITH_PTHREADS
327 /* REWRITE: not thread safe */
328 #ifdef REPLACE_INET_NTOA
329 char *rep_inet_ntoa(struct in_addr ip)
331 uint8_t *p = (uint8_t *)&ip.s_addr;
333 slprintf(buf, 17, "%d.%d.%d.%d",
334 (int)p[0], (int)p[1], (int)p[2], (int)p[3]);
337 #endif /* REPLACE_INET_NTOA */
340 #ifndef HAVE_SETLINEBUF
341 void rep_setlinebuf(FILE *stream)
343 setvbuf(stream, (char *)NULL, _IOLBF, 0);
345 #endif /* HAVE_SETLINEBUF */
349 void rep_vsyslog (int facility_priority, const char *format, va_list arglist)
352 vasprintf(&msg, format, arglist);
355 syslog(facility_priority, "%s", msg);
358 #endif /* HAVE_SYSLOG */
359 #endif /* HAVE_VSYSLOG */
363 Some platforms don't have strnlen
365 size_t rep_strnlen(const char *s, size_t max)
369 for (len = 0; len < max; len++) {
370 if (s[len] == '\0') {
380 Some platforms don't have strndup.
382 char *rep_strndup(const char *s, size_t n)
398 int rep_waitpid(pid_t pid,int *status,int options)
400 return wait4(pid, status, options, NULL);
405 int rep_seteuid(uid_t euid)
407 #ifdef HAVE_SETRESUID
408 return setresuid(-1, euid, -1);
410 # error "You need a seteuid function"
416 int rep_setegid(gid_t egid)
418 #ifdef HAVE_SETRESGID
419 return setresgid(-1, egid, -1);
421 # error "You need a setegid function"
426 /*******************************************************************
427 os/2 also doesn't have chroot
428 ********************************************************************/
430 int rep_chroot(const char *dname)
437 /*****************************************************************
438 Possibly replace mkstemp if it is broken.
439 *****************************************************************/
441 #ifndef HAVE_SECURE_MKSTEMP
442 int rep_mkstemp(char *template)
444 /* have a reasonable go at emulating it. Hope that
445 the system mktemp() isn't completly hopeless */
446 char *p = mktemp(template);
449 return open(p, O_CREAT|O_EXCL|O_RDWR, 0600);
454 char *rep_mkdtemp(char *template)
458 if ((dname = mktemp(template))) {
459 if (mkdir(dname, 0700) >= 0) {
469 ssize_t rep_pread(int __fd, void *__buf, size_t __nbytes, off_t __offset)
471 if (lseek(__fd, __offset, SEEK_SET) != __offset) {
474 return read(__fd, __buf, __nbytes);
479 ssize_t rep_pwrite(int __fd, const void *__buf, size_t __nbytes, off_t __offset)
481 if (lseek(__fd, __offset, SEEK_SET) != __offset) {
484 return write(__fd, __buf, __nbytes);
488 #ifndef HAVE_STRCASESTR
489 char *rep_strcasestr(const char *haystack, const char *needle)
492 size_t nlen = strlen(needle);
493 for (s=haystack;*s;s++) {
494 if (toupper(*needle) == toupper(*s) &&
495 strncasecmp(s, needle, nlen) == 0) {
496 return (char *)((intptr_t)s);
503 #ifndef HAVE_STRTOK_R
504 /* based on GLIBC version, copyright Free Software Foundation */
505 char *rep_strtok_r(char *s, const char *delim, char **save_ptr)
509 if (s == NULL) s = *save_ptr;
511 s += strspn(s, delim);
518 s = strpbrk(token, delim);
520 *save_ptr = token + strlen(token);
531 long long int rep_strtoll(const char *str, char **endptr, int base)
534 return strtoq(str, endptr, base);
535 #elif defined(HAVE___STRTOLL)
536 return __strtoll(str, endptr, base);
537 #elif SIZEOF_LONG == SIZEOF_LONG_LONG
538 return (long long int) strtol(str, endptr, base);
540 # error "You need a strtoll function"
546 #ifndef HAVE_STRTOULL
547 unsigned long long int rep_strtoull(const char *str, char **endptr, int base)
550 return strtouq(str, endptr, base);
551 #elif defined(HAVE___STRTOULL)
552 return __strtoull(str, endptr, base);
553 #elif SIZEOF_LONG == SIZEOF_LONG_LONG
554 return (unsigned long long int) strtoul(str, endptr, base);
556 # error "You need a strtoull function"
562 int rep_setenv(const char *name, const char *value, int overwrite)
568 if (!overwrite && getenv(name)) {
581 memcpy(p+l1+1, value, l2);