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 if (bufsize < (len1+1)) {
88 len2 = bufsize - (len1+1);
91 memcpy(d+len1, s, len2);
99 /*******************************************************************
100 a mktime() replacement for those who don't have it - contributed by
101 C.A. Lademann <cal@zls.com>
102 Corrections by richard.kettlewell@kewill.com
103 ********************************************************************/
106 #define HOUR 60*MINUTE
109 time_t rep_mktime(struct tm *t)
114 int mon [] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
120 n = t->tm_year + 1900 - 1;
121 epoch = (t->tm_year - 70) * YEAR +
122 ((n / 4 - n / 100 + n / 400) - (1969 / 4 - 1969 / 100 + 1969 / 400)) * DAY;
124 y = t->tm_year + 1900;
127 for(i = 0; i < t->tm_mon; i++) {
128 epoch += mon [m] * DAY;
129 if(m == 1 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0))
138 epoch += (t->tm_mday - 1) * DAY;
139 epoch += t->tm_hour * HOUR + t->tm_min * MINUTE + t->tm_sec;
141 if((u = localtime(&epoch)) != NULL) {
142 t->tm_sec = u->tm_sec;
143 t->tm_min = u->tm_min;
144 t->tm_hour = u->tm_hour;
145 t->tm_mday = u->tm_mday;
146 t->tm_mon = u->tm_mon;
147 t->tm_year = u->tm_year;
148 t->tm_wday = u->tm_wday;
149 t->tm_yday = u->tm_yday;
150 t->tm_isdst = u->tm_isdst;
155 #endif /* !HAVE_MKTIME */
158 #ifndef HAVE_INITGROUPS
159 /****************************************************************************
160 some systems don't have an initgroups call
161 ****************************************************************************/
162 int rep_initgroups(char *name, gid_t id)
164 #ifndef HAVE_SETGROUPS
165 /* yikes! no SETGROUPS or INITGROUPS? how can this work? */
168 #else /* HAVE_SETGROUPS */
172 gid_t *grouplst = NULL;
173 int max_gr = NGROUPS_MAX;
179 if((grouplst = malloc(sizeof(gid_t) * max_gr)) == NULL) {
186 while (i < max_gr && ((g = (struct group *)getgrent()) != (struct group *)NULL)) {
191 while (gr && (*gr != (char)NULL)) {
192 if (strcmp(name,gr) == 0) {
193 grouplst[i] = g->gr_gid;
202 ret = setgroups(i, grouplst);
205 #endif /* HAVE_SETGROUPS */
207 #endif /* HAVE_INITGROUPS */
210 #if (defined(SecureWare) && defined(SCO))
211 /* This is needed due to needing the nap() function but we don't want
212 to include the Xenix libraries since that will break other things...
213 BTW: system call # 0x0c28 is the same as calling nap() */
214 long nap(long milliseconds) {
215 return syscall(0x0c28, milliseconds);
221 /*******************************************************************
222 safely copies memory, ensuring no overlap problems.
223 this is only used if the machine does not have its own memmove().
224 this is not the fastest algorithm in town, but it will do for our
226 ********************************************************************/
227 void *rep_memmove(void *dest,const void *src,int size)
231 if (dest==src || !size) return(dest);
233 d = (unsigned long)dest;
234 s = (unsigned long)src;
236 if ((d >= (s+size)) || (s >= (d+size))) {
238 memcpy(dest,src,size);
243 /* we can forward copy */
244 if (s-d >= sizeof(int) &&
247 !(size%sizeof(int))) {
248 /* do it all as words */
249 int *idest = (int *)dest;
250 int *isrc = (int *)src;
252 for (i=0;i<size;i++) idest[i] = isrc[i];
255 char *cdest = (char *)dest;
256 char *csrc = (char *)src;
257 for (i=0;i<size;i++) cdest[i] = csrc[i];
260 /* must backward copy */
261 if (d-s >= sizeof(int) &&
264 !(size%sizeof(int))) {
265 /* do it all as words */
266 int *idest = (int *)dest;
267 int *isrc = (int *)src;
269 for (i=size-1;i>=0;i--) idest[i] = isrc[i];
272 char *cdest = (char *)dest;
273 char *csrc = (char *)src;
274 for (i=size-1;i>=0;i--) cdest[i] = csrc[i];
279 #endif /* HAVE_MEMMOVE */
282 /****************************************************************************
284 ****************************************************************************/
285 char *rep_strdup(const char *s)
290 if (!s) return(NULL);
293 ret = (char *)malloc(len);
294 if (!ret) return(NULL);
298 #endif /* HAVE_STRDUP */
300 #ifndef HAVE_SETLINEBUF
301 void rep_setlinebuf(FILE *stream)
303 setvbuf(stream, (char *)NULL, _IOLBF, 0);
305 #endif /* HAVE_SETLINEBUF */
309 void rep_vsyslog (int facility_priority, const char *format, va_list arglist)
312 vasprintf(&msg, format, arglist);
315 syslog(facility_priority, "%s", msg);
318 #endif /* HAVE_SYSLOG */
319 #endif /* HAVE_VSYSLOG */
323 Some platforms don't have strnlen
325 size_t rep_strnlen(const char *s, size_t max)
329 for (len = 0; len < max; len++) {
330 if (s[len] == '\0') {
340 Some platforms don't have strndup.
342 char *rep_strndup(const char *s, size_t n)
358 int rep_waitpid(pid_t pid,int *status,int options)
360 return wait4(pid, status, options, NULL);
365 int rep_seteuid(uid_t euid)
367 #ifdef HAVE_SETRESUID
368 return setresuid(-1, euid, -1);
370 # error "You need a seteuid function"
376 int rep_setegid(gid_t egid)
378 #ifdef HAVE_SETRESGID
379 return setresgid(-1, egid, -1);
381 # error "You need a setegid function"
386 /*******************************************************************
387 os/2 also doesn't have chroot
388 ********************************************************************/
390 int rep_chroot(const char *dname)
397 /*****************************************************************
398 Possibly replace mkstemp if it is broken.
399 *****************************************************************/
401 #ifndef HAVE_SECURE_MKSTEMP
402 int rep_mkstemp(char *template)
404 /* have a reasonable go at emulating it. Hope that
405 the system mktemp() isn't completly hopeless */
406 char *p = mktemp(template);
409 return open(p, O_CREAT|O_EXCL|O_RDWR, 0600);
414 char *rep_mkdtemp(char *template)
418 if ((dname = mktemp(template))) {
419 if (mkdir(dname, 0700) >= 0) {
428 /*****************************************************************
429 Watch out: this is not thread safe.
430 *****************************************************************/
433 ssize_t rep_pread(int __fd, void *__buf, size_t __nbytes, off_t __offset)
435 if (lseek(__fd, __offset, SEEK_SET) != __offset) {
438 return read(__fd, __buf, __nbytes);
442 /*****************************************************************
443 Watch out: this is not thread safe.
444 *****************************************************************/
447 ssize_t rep_pwrite(int __fd, const void *__buf, size_t __nbytes, off_t __offset)
449 if (lseek(__fd, __offset, SEEK_SET) != __offset) {
452 return write(__fd, __buf, __nbytes);
456 #ifndef HAVE_STRCASESTR
457 char *rep_strcasestr(const char *haystack, const char *needle)
460 size_t nlen = strlen(needle);
461 for (s=haystack;*s;s++) {
462 if (toupper(*needle) == toupper(*s) &&
463 strncasecmp(s, needle, nlen) == 0) {
464 return (char *)((uintptr_t)s);
471 #ifndef HAVE_STRTOK_R
472 /* based on GLIBC version, copyright Free Software Foundation */
473 char *rep_strtok_r(char *s, const char *delim, char **save_ptr)
477 if (s == NULL) s = *save_ptr;
479 s += strspn(s, delim);
486 s = strpbrk(token, delim);
488 *save_ptr = token + strlen(token);
499 long long int rep_strtoll(const char *str, char **endptr, int base)
502 return strtoq(str, endptr, base);
503 #elif defined(HAVE___STRTOLL)
504 return __strtoll(str, endptr, base);
505 #elif SIZEOF_LONG == SIZEOF_LONG_LONG
506 return (long long int) strtol(str, endptr, base);
508 # error "You need a strtoll function"
514 #ifndef HAVE_STRTOULL
515 unsigned long long int rep_strtoull(const char *str, char **endptr, int base)
518 return strtouq(str, endptr, base);
519 #elif defined(HAVE___STRTOULL)
520 return __strtoull(str, endptr, base);
521 #elif SIZEOF_LONG == SIZEOF_LONG_LONG
522 return (unsigned long long int) strtoul(str, endptr, base);
524 # error "You need a strtoull function"
530 int rep_setenv(const char *name, const char *value, int overwrite)
536 if (!overwrite && getenv(name)) {
549 memcpy(p+l1+1, value, l2);
561 #ifndef HAVE_UNSETENV
562 int rep_unsetenv(const char *name)
564 extern char **environ;
565 size_t len = strlen(name);
568 if (environ == NULL || getenv(name) == NULL) {
572 for (i=0;environ[i];i++) /* noop */ ;
577 if (strncmp(environ[i], name, len) == 0 && environ[i][len] == '=') {
578 /* note: we do _not_ free the old variable here. It is unsafe to
579 do so, as the pointer may not have come from malloc */
580 memmove(&environ[i], &environ[i+1], (count-i)*sizeof(char *));
592 int rep_utime(const char *filename, const struct utimbuf *buf)
600 int rep_utimes(const char *filename, const struct timeval tv[2])
604 u.actime = tv[0].tv_sec;
605 if (tv[0].tv_usec > 500000) {
609 u.modtime = tv[1].tv_sec;
610 if (tv[1].tv_usec > 500000) {
614 return utime(filename, &u);