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/network.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 len2 = bufsize - (len1+1);
89 memcpy(d+len1, s, len2);
97 /*******************************************************************
98 a mktime() replacement for those who don't have it - contributed by
99 C.A. Lademann <cal@zls.com>
100 Corrections by richard.kettlewell@kewill.com
101 ********************************************************************/
104 #define HOUR 60*MINUTE
107 time_t rep_mktime(struct tm *t)
112 int mon [] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
118 n = t->tm_year + 1900 - 1;
119 epoch = (t->tm_year - 70) * YEAR +
120 ((n / 4 - n / 100 + n / 400) - (1969 / 4 - 1969 / 100 + 1969 / 400)) * DAY;
122 y = t->tm_year + 1900;
125 for(i = 0; i < t->tm_mon; i++) {
126 epoch += mon [m] * DAY;
127 if(m == 1 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0))
136 epoch += (t->tm_mday - 1) * DAY;
137 epoch += t->tm_hour * HOUR + t->tm_min * MINUTE + t->tm_sec;
139 if((u = localtime(&epoch)) != NULL) {
140 t->tm_sec = u->tm_sec;
141 t->tm_min = u->tm_min;
142 t->tm_hour = u->tm_hour;
143 t->tm_mday = u->tm_mday;
144 t->tm_mon = u->tm_mon;
145 t->tm_year = u->tm_year;
146 t->tm_wday = u->tm_wday;
147 t->tm_yday = u->tm_yday;
148 t->tm_isdst = u->tm_isdst;
153 #endif /* !HAVE_MKTIME */
156 #ifndef HAVE_INITGROUPS
157 /****************************************************************************
158 some systems don't have an initgroups call
159 ****************************************************************************/
160 int rep_initgroups(char *name, gid_t id)
162 #ifndef HAVE_SETGROUPS
163 /* yikes! no SETGROUPS or INITGROUPS? how can this work? */
166 #else /* HAVE_SETGROUPS */
170 gid_t *grouplst = NULL;
177 if((grouplst = malloc(sizeof(gid_t) * max_gr)) == NULL) {
184 while (i < max_gr && ((g = (struct group *)getgrent()) != (struct group *)NULL)) {
189 while (gr && (*gr != (char)NULL)) {
190 if (strcmp(name,gr) == 0) {
191 grouplst[i] = g->gr_gid;
200 ret = setgroups(i, grouplst);
203 #endif /* HAVE_SETGROUPS */
205 #endif /* HAVE_INITGROUPS */
208 #if (defined(SecureWare) && defined(SCO))
209 /* This is needed due to needing the nap() function but we don't want
210 to include the Xenix libraries since that will break other things...
211 BTW: system call # 0x0c28 is the same as calling nap() */
212 long nap(long milliseconds) {
213 return syscall(0x0c28, milliseconds);
219 /*******************************************************************
220 safely copies memory, ensuring no overlap problems.
221 this is only used if the machine does not have its own memmove().
222 this is not the fastest algorithm in town, but it will do for our
224 ********************************************************************/
225 void *rep_memmove(void *dest,const void *src,int size)
229 if (dest==src || !size) return(dest);
231 d = (unsigned long)dest;
232 s = (unsigned long)src;
234 if ((d >= (s+size)) || (s >= (d+size))) {
236 memcpy(dest,src,size);
241 /* we can forward copy */
242 if (s-d >= sizeof(int) &&
245 !(size%sizeof(int))) {
246 /* do it all as words */
247 int *idest = (int *)dest;
248 int *isrc = (int *)src;
250 for (i=0;i<size;i++) idest[i] = isrc[i];
253 char *cdest = (char *)dest;
254 char *csrc = (char *)src;
255 for (i=0;i<size;i++) cdest[i] = csrc[i];
258 /* must backward copy */
259 if (d-s >= sizeof(int) &&
262 !(size%sizeof(int))) {
263 /* do it all as words */
264 int *idest = (int *)dest;
265 int *isrc = (int *)src;
267 for (i=size-1;i>=0;i--) idest[i] = isrc[i];
270 char *cdest = (char *)dest;
271 char *csrc = (char *)src;
272 for (i=size-1;i>=0;i--) cdest[i] = csrc[i];
277 #endif /* HAVE_MEMMOVE */
280 /****************************************************************************
282 ****************************************************************************/
283 char *rep_strdup(const char *s)
288 if (!s) return(NULL);
291 ret = (char *)malloc(len);
292 if (!ret) return(NULL);
296 #endif /* HAVE_STRDUP */
298 #ifndef HAVE_SETLINEBUF
299 void rep_setlinebuf(FILE *stream)
301 setvbuf(stream, (char *)NULL, _IOLBF, 0);
303 #endif /* HAVE_SETLINEBUF */
307 void rep_vsyslog (int facility_priority, const char *format, va_list arglist)
310 vasprintf(&msg, format, arglist);
313 syslog(facility_priority, "%s", msg);
316 #endif /* HAVE_SYSLOG */
317 #endif /* HAVE_VSYSLOG */
321 Some platforms don't have strnlen
323 size_t rep_strnlen(const char *s, size_t max)
327 for (len = 0; len < max; len++) {
328 if (s[len] == '\0') {
338 Some platforms don't have strndup.
340 char *rep_strndup(const char *s, size_t n)
356 int rep_waitpid(pid_t pid,int *status,int options)
358 return wait4(pid, status, options, NULL);
363 int rep_seteuid(uid_t euid)
365 #ifdef HAVE_SETRESUID
366 return setresuid(-1, euid, -1);
368 # error "You need a seteuid function"
374 int rep_setegid(gid_t egid)
376 #ifdef HAVE_SETRESGID
377 return setresgid(-1, egid, -1);
379 # error "You need a setegid function"
384 /*******************************************************************
385 os/2 also doesn't have chroot
386 ********************************************************************/
388 int rep_chroot(const char *dname)
395 /*****************************************************************
396 Possibly replace mkstemp if it is broken.
397 *****************************************************************/
399 #ifndef HAVE_SECURE_MKSTEMP
400 int rep_mkstemp(char *template)
402 /* have a reasonable go at emulating it. Hope that
403 the system mktemp() isn't completly hopeless */
404 char *p = mktemp(template);
407 return open(p, O_CREAT|O_EXCL|O_RDWR, 0600);
412 char *rep_mkdtemp(char *template)
416 if ((dname = mktemp(template))) {
417 if (mkdir(dname, 0700) >= 0) {
426 /*****************************************************************
427 Watch out: this is not thread safe.
428 *****************************************************************/
431 ssize_t rep_pread(int __fd, void *__buf, size_t __nbytes, off_t __offset)
433 if (lseek(__fd, __offset, SEEK_SET) != __offset) {
436 return read(__fd, __buf, __nbytes);
440 /*****************************************************************
441 Watch out: this is not thread safe.
442 *****************************************************************/
445 ssize_t rep_pwrite(int __fd, const void *__buf, size_t __nbytes, off_t __offset)
447 if (lseek(__fd, __offset, SEEK_SET) != __offset) {
450 return write(__fd, __buf, __nbytes);
454 #ifndef HAVE_STRCASESTR
455 char *rep_strcasestr(const char *haystack, const char *needle)
458 size_t nlen = strlen(needle);
459 for (s=haystack;*s;s++) {
460 if (toupper(*needle) == toupper(*s) &&
461 strncasecmp(s, needle, nlen) == 0) {
462 return (char *)((intptr_t)s);
469 #ifndef HAVE_STRTOK_R
470 /* based on GLIBC version, copyright Free Software Foundation */
471 char *rep_strtok_r(char *s, const char *delim, char **save_ptr)
475 if (s == NULL) s = *save_ptr;
477 s += strspn(s, delim);
484 s = strpbrk(token, delim);
486 *save_ptr = token + strlen(token);
497 long long int rep_strtoll(const char *str, char **endptr, int base)
500 return strtoq(str, endptr, base);
501 #elif defined(HAVE___STRTOLL)
502 return __strtoll(str, endptr, base);
503 #elif SIZEOF_LONG == SIZEOF_LONG_LONG
504 return (long long int) strtol(str, endptr, base);
506 # error "You need a strtoll function"
512 #ifndef HAVE_STRTOULL
513 unsigned long long int rep_strtoull(const char *str, char **endptr, int base)
516 return strtouq(str, endptr, base);
517 #elif defined(HAVE___STRTOULL)
518 return __strtoull(str, endptr, base);
519 #elif SIZEOF_LONG == SIZEOF_LONG_LONG
520 return (unsigned long long int) strtoul(str, endptr, base);
522 # error "You need a strtoull function"
528 int rep_setenv(const char *name, const char *value, int overwrite)
534 if (!overwrite && getenv(name)) {
547 memcpy(p+l1+1, value, l2);
559 #ifndef HAVE_UNSETENV
560 int rep_unsetenv(const char *name)
562 extern char **environ;
563 size_t len = strlen(name);
566 if (environ == NULL || getenv(name) == NULL) {
570 for (i=0;environ[i];i++) /* noop */ ;
575 if (strncmp(environ[i], name, len) == 0 && environ[i][len] == '=') {
576 /* note: we do _not_ free the old variable here. It is unsafe to
577 do so, as the pointer may not have come from malloc */
578 memmove(&environ[i], &environ[i+1], (count-i)*sizeof(char *));