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
32 void replace_dummy(void);
33 void replace_dummy(void) {}
35 #ifndef HAVE_FTRUNCATE
36 /*******************************************************************
37 ftruncate for operating systems that don't have it
38 ********************************************************************/
39 int rep_ftruncate(int f, off_t l)
50 return fcntl(f, F_FREESP, &fl);
53 #endif /* HAVE_FTRUNCATE */
57 /* like strncpy but does not 0 fill the buffer and always null
58 terminates. bufsize is the size of the destination buffer */
59 size_t rep_strlcpy(char *d, const char *s, size_t bufsize)
61 size_t len = strlen(s);
63 if (bufsize <= 0) return 0;
64 if (len >= bufsize) len = bufsize-1;
72 /* like strncat but does not 0 fill the buffer and always null
73 terminates. bufsize is the length of the buffer, which should
74 be one more than the maximum resulting string length */
75 size_t rep_strlcat(char *d, const char *s, size_t bufsize)
77 size_t len1 = strlen(d);
78 size_t len2 = strlen(s);
79 size_t ret = len1 + len2;
81 if (len1+len2 >= bufsize) {
82 len2 = bufsize - (len1+1);
85 memcpy(d+len1, s, len2);
93 /*******************************************************************
94 a mktime() replacement for those who don't have it - contributed by
95 C.A. Lademann <cal@zls.com>
96 Corrections by richard.kettlewell@kewill.com
97 ********************************************************************/
100 #define HOUR 60*MINUTE
103 time_t rep_mktime(struct tm *t)
108 int mon [] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
114 n = t->tm_year + 1900 - 1;
115 epoch = (t->tm_year - 70) * YEAR +
116 ((n / 4 - n / 100 + n / 400) - (1969 / 4 - 1969 / 100 + 1969 / 400)) * DAY;
118 y = t->tm_year + 1900;
121 for(i = 0; i < t->tm_mon; i++) {
122 epoch += mon [m] * DAY;
123 if(m == 1 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0))
132 epoch += (t->tm_mday - 1) * DAY;
133 epoch += t->tm_hour * HOUR + t->tm_min * MINUTE + t->tm_sec;
135 if((u = localtime(&epoch)) != NULL) {
136 t->tm_sec = u->tm_sec;
137 t->tm_min = u->tm_min;
138 t->tm_hour = u->tm_hour;
139 t->tm_mday = u->tm_mday;
140 t->tm_mon = u->tm_mon;
141 t->tm_year = u->tm_year;
142 t->tm_wday = u->tm_wday;
143 t->tm_yday = u->tm_yday;
144 t->tm_isdst = u->tm_isdst;
149 #endif /* !HAVE_MKTIME */
154 /* Rename a file. (from libiberty in GNU binutils) */
155 int rep_rename(const char *zfrom, const char *zto)
157 if (link (zfrom, zto) < 0)
162 || link (zfrom, zto) < 0)
165 return unlink (zfrom);
167 #endif /* HAVE_RENAME */
171 #if defined(HAVE_SETNETGRENT) && defined(HAVE_GETNETGRENT) && defined(HAVE_ENDNETGRENT)
173 * Search for a match in a netgroup. This replaces it on broken systems.
175 int rep_innetgr(const char *group, const char *host, const char *user,
178 char *hst, *usr, *dm;
181 while (getnetgrent(&hst, &usr, &dm)) {
182 if (((host == 0) || (hst == 0) || !strcmp(host, hst)) &&
183 ((user == 0) || (usr == 0) || !strcmp(user, usr)) &&
184 ((dom == 0) || (dm == 0) || !strcmp(dom, dm))) {
192 #endif /* HAVE_SETNETGRENT HAVE_GETNETGRENT HAVE_ENDNETGRENT */
193 #endif /* HAVE_INNETGR */
197 #ifndef HAVE_INITGROUPS
198 /****************************************************************************
199 some systems don't have an initgroups call
200 ****************************************************************************/
201 int rep_initgroups(char *name, gid_t id)
203 #ifndef HAVE_SETGROUPS
204 /* yikes! no SETGROUPS or INITGROUPS? how can this work? */
207 #else /* HAVE_SETGROUPS */
211 gid_t *grouplst = NULL;
212 int max_gr = groups_max();
218 if((grouplst = malloc(sizeof(gid_t) * max_gr)) == NULL) {
225 while (i < max_gr && ((g = (struct group *)getgrent()) != (struct group *)NULL)) {
230 while (gr && (*gr != (char)NULL)) {
231 if (strcmp(name,gr) == 0) {
232 grouplst[i] = g->gr_gid;
241 ret = setgroups(i, grouplst);
244 #endif /* HAVE_SETGROUPS */
246 #endif /* HAVE_INITGROUPS */
249 #if (defined(SecureWare) && defined(SCO))
250 /* This is needed due to needing the nap() function but we don't want
251 to include the Xenix libraries since that will break other things...
252 BTW: system call # 0x0c28 is the same as calling nap() */
253 long nap(long milliseconds) {
254 return syscall(0x0c28, milliseconds);
260 /*******************************************************************
261 safely copies memory, ensuring no overlap problems.
262 this is only used if the machine does not have it's own memmove().
263 this is not the fastest algorithm in town, but it will do for our
265 ********************************************************************/
266 void *rep_memmove(void *dest,const void *src,int size)
270 if (dest==src || !size) return(dest);
272 d = (unsigned long)dest;
273 s = (unsigned long)src;
275 if ((d >= (s+size)) || (s >= (d+size))) {
277 memcpy(dest,src,size);
282 /* we can forward copy */
283 if (s-d >= sizeof(int) &&
286 !(size%sizeof(int))) {
287 /* do it all as words */
288 int *idest = (int *)dest;
289 int *isrc = (int *)src;
291 for (i=0;i<size;i++) idest[i] = isrc[i];
294 char *cdest = (char *)dest;
295 char *csrc = (char *)src;
296 for (i=0;i<size;i++) cdest[i] = csrc[i];
299 /* must backward copy */
300 if (d-s >= sizeof(int) &&
303 !(size%sizeof(int))) {
304 /* do it all as words */
305 int *idest = (int *)dest;
306 int *isrc = (int *)src;
308 for (i=size-1;i>=0;i--) idest[i] = isrc[i];
311 char *cdest = (char *)dest;
312 char *csrc = (char *)src;
313 for (i=size-1;i>=0;i--) cdest[i] = csrc[i];
318 #endif /* HAVE_MEMMOVE */
321 /****************************************************************************
323 ****************************************************************************/
324 char *rep_strdup(const char *s)
329 if (!s) return(NULL);
332 ret = (char *)malloc(len);
333 if (!ret) return(NULL);
337 #endif /* HAVE_STRDUP */
339 #ifndef WITH_PTHREADS
340 /* REWRITE: not thread safe */
341 #ifdef REPLACE_INET_NTOA
342 char *rep_inet_ntoa(struct in_addr ip)
344 uint8_t *p = (uint8_t *)&ip.s_addr;
346 slprintf(buf, 17, "%d.%d.%d.%d",
347 (int)p[0], (int)p[1], (int)p[2], (int)p[3]);
350 #endif /* REPLACE_INET_NTOA */
353 #ifndef HAVE_SETLINEBUF
354 int rep_setlinebuf(FILE *stream)
356 return setvbuf(stream, (char *)NULL, _IOLBF, 0);
358 #endif /* HAVE_SETLINEBUF */
362 void rep_vsyslog (int facility_priority, char *format, va_list arglist)
365 vasprintf(&msg, format, arglist);
368 syslog(facility_priority, "%s", msg);
371 #endif /* HAVE_SYSLOG */
372 #endif /* HAVE_VSYSLOG */
376 Some platforms don't have strnlen
378 size_t strnlen(const char *s, size_t max)
382 for (len = 0; len < max; len++) {
383 if (s[len] == '\0') {
393 Some platforms don't have strndup.
395 char *rep_strndup(const char *s, size_t n)
411 int rep_waitpid(pid_t pid,int *status,int options)
413 return wait4(pid, status, options, NULL);
418 int rep_seteuid(uid_t euid)
420 #ifdef HAVE_SETRESUID
421 return setresuid(-1, euid, -1);
423 # error "You need a seteuid function"
429 int rep_setegid(gid_t egid)
431 #ifdef HAVE_SETRESGID
432 return setresgid(-1, egid, -1);
434 # error "You need a setegid function"
439 /*******************************************************************
440 os/2 also doesn't have chroot
441 ********************************************************************/
443 int rep_chroot(const char *dname)
450 /*****************************************************************
451 Possibly replace mkstemp if it is broken.
452 *****************************************************************/
454 #ifndef HAVE_SECURE_MKSTEMP
455 int rep_mkstemp(char *template)
457 /* have a reasonable go at emulating it. Hope that
458 the system mktemp() isn't completly hopeless */
459 char *p = mktemp(template);
462 return open(p, O_CREAT|O_EXCL|O_RDWR, 0600);
467 char *rep_mkdtemp(char *template)
471 if (dname = mktemp(template)) {
472 if (mkdir(dname, 0700) >= 0) {
482 static ssize_t rep_pread(int __fd, void *__buf, size_t __nbytes, off_t __offset)
484 if (lseek(__fd, __offset, SEEK_SET) != __offset) {
487 return read(__fd, __buf, __nbytes);
492 static ssize_t rep_pwrite(int __fd, const void *__buf, size_t __nbytes, off_t __offset)
494 if (lseek(__fd, __offset, SEEK_SET) != __offset) {
497 return write(__fd, __buf, __nbytes);
501 #ifndef HAVE_STRCASESTR
502 char *rep_strcasestr(const char *haystack, const char *needle)
505 size_t nlen = strlen(needle);
506 for (s=haystack;*s;s++) {
507 if (toupper(*needle) == toupper(*s) &&
508 strncasecmp(s, needle, nlen) == 0) {
509 return discard_const_p(char, s);
516 #ifndef HAVE_STRTOK_R
517 /* based on GLIBC version, copyright Free Software Foundation */
518 char *rep_strtok_r(char *s, const char *delim, char **save_ptr)
522 if (s == NULL) s = *save_ptr;
524 s += strspn(s, delim);
531 s = strpbrk(token, delim);
533 *save_ptr = token + strlen(token);
545 Some platforms don't have strnlen
547 size_t rep_strnlen(const char *s, size_t n)
550 for (i=0; s[i] && i<n; i++)
557 long long int rep_strtoll(const char *str, char **endptr, int base)
560 return strtoq(str, endptr, base);
561 #elif defined(HAVE___STRTOLL)
562 return __strtoll(str, endptr, base);
563 #elif SIZEOF_LONG == SIZEOF_LONG_LONG
564 return (long long int) strtol(str, endptr, base);
566 # error "You need a strtoll function"
572 #ifndef HAVE_STRTOULL
573 unsigned long long int rep_strtoull(const char *str, char **endptr, int base)
576 return strtouq(str, endptr, base);
577 #elif defined(HAVE___STRTOULL)
578 return __strtoull(str, endptr, base);
579 #elif SIZEOF_LONG == SIZEOF_LONG_LONG
580 return (unsigned long long int) strtoul(str, endptr, base);
582 # error "You need a strtoull function"
588 int rep_setenv(const char *name, const char *value, int overwrite)
594 if (!overwrite && getenv(name)) {
607 memcpy(p+l1+1, value, l2);
619 #if !defined(HAVE_TIMEGM)
621 static int is_leap(unsigned y)
624 return (y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0);
627 time_t timegm(struct tm *tm)
629 static const unsigned ndays[2][12] ={
630 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
631 {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}};
635 for (i = 70; i < tm->tm_year; ++i)
636 res += is_leap(i) ? 366 : 365;
638 for (i = 0; i < tm->tm_mon; ++i)
639 res += ndays[is_leap(tm->tm_year)][i];
640 res += tm->tm_mday - 1;