Unix SMB/CIFS implementation.
replacement routines for broken systems
Copyright (C) Andrew Tridgell 1992-1998
+
+ ** NOTE! The following LGPL license applies to the replace
+ ** library. This does NOT imply that all of Samba is released
+ ** under the LGPL
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 3 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
-#include "includes.h"
-#include "system/wait.h"
+#include "replace.h"
+
+#include "system/filesys.h"
#include "system/time.h"
+#include "system/passwd.h"
+#include "system/syslog.h"
#include "system/network.h"
+#include "system/locale.h"
+#include "system/wait.h"
- void replace_dummy(void);
- void replace_dummy(void) {}
+void replace_dummy(void);
+void replace_dummy(void) {}
#ifndef HAVE_FTRUNCATE
/*******************************************************************
ftruncate for operating systems that don't have it
********************************************************************/
- int ftruncate(int f,off_t l)
+int rep_ftruncate(int f, off_t l)
{
#ifdef HAVE_CHSIZE
return chsize(f,l);
-#else
+#elif defined(F_FREESP)
struct flock fl;
fl.l_whence = 0;
fl.l_start = l;
fl.l_type = F_WRLCK;
return fcntl(f, F_FREESP, &fl);
+#else
+#error "you must have a ftruncate function"
#endif
}
#endif /* HAVE_FTRUNCATE */
#ifndef HAVE_STRLCPY
/* like strncpy but does not 0 fill the buffer and always null
terminates. bufsize is the size of the destination buffer */
- size_t strlcpy(char *d, const char *s, size_t bufsize)
+size_t rep_strlcpy(char *d, const char *s, size_t bufsize)
{
size_t len = strlen(s);
size_t ret = len;
/* like strncat but does not 0 fill the buffer and always null
terminates. bufsize is the length of the buffer, which should
be one more than the maximum resulting string length */
- size_t strlcat(char *d, const char *s, size_t bufsize)
+size_t rep_strlcat(char *d, const char *s, size_t bufsize)
{
size_t len1 = strlen(d);
size_t len2 = strlen(s);
#define HOUR 60*MINUTE
#define DAY 24*HOUR
#define YEAR 365*DAY
- time_t mktime(struct tm *t)
+time_t rep_mktime(struct tm *t)
{
struct tm *u;
time_t epoch = 0;
#endif /* !HAVE_MKTIME */
-
-#ifndef HAVE_RENAME
-/* Rename a file. (from libiberty in GNU binutils) */
- int rename(const char *zfrom, const char *zto)
-{
- if (link (zfrom, zto) < 0)
- {
- if (errno != EEXIST)
- return -1;
- if (unlink (zto) < 0
- || link (zfrom, zto) < 0)
- return -1;
- }
- return unlink (zfrom);
-}
-#endif /* HAVE_RENAME */
-
-
-#ifndef HAVE_INNETGR
-#if defined(HAVE_SETNETGRENT) && defined(HAVE_GETNETGRENT) && defined(HAVE_ENDNETGRENT)
-/*
- * Search for a match in a netgroup. This replaces it on broken systems.
- */
- int innetgr(const char *group,const char *host,const char *user,const char *dom)
-{
- char *hst, *usr, *dm;
-
- setnetgrent(group);
- while (getnetgrent(&hst, &usr, &dm)) {
- if (((host == 0) || (hst == 0) || !strcmp(host, hst)) &&
- ((user == 0) || (usr == 0) || !strcmp(user, usr)) &&
- ((dom == 0) || (dm == 0) || !strcmp(dom, dm))) {
- endnetgrent();
- return (1);
- }
- }
- endnetgrent();
- return (0);
-}
-#endif /* HAVE_SETNETGRENT HAVE_GETNETGRENT HAVE_ENDNETGRENT */
-#endif /* HAVE_INNETGR */
-
-
-
#ifndef HAVE_INITGROUPS
/****************************************************************************
some systems don't have an initgroups call
****************************************************************************/
- int initgroups(char *name, gid_t id)
+int rep_initgroups(char *name, gid_t id)
{
#ifndef HAVE_SETGROUPS
/* yikes! no SETGROUPS or INITGROUPS? how can this work? */
errno = ENOSYS;
return -1;
#else /* HAVE_SETGROUPS */
+
+#include <grp.h>
+
gid_t *grouplst = NULL;
- int max_gr = groups_max();
+ int max_gr = 32;
int ret;
int i,j;
struct group *g;
/* This is needed due to needing the nap() function but we don't want
to include the Xenix libraries since that will break other things...
BTW: system call # 0x0c28 is the same as calling nap() */
- long nap(long milliseconds) {
+long nap(long milliseconds) {
return syscall(0x0c28, milliseconds);
}
#endif
#ifndef HAVE_MEMMOVE
/*******************************************************************
safely copies memory, ensuring no overlap problems.
-this is only used if the machine does not have it's own memmove().
+this is only used if the machine does not have its own memmove().
this is not the fastest algorithm in town, but it will do for our
needs.
********************************************************************/
- void *memmove(void *dest,const void *src,int size)
+void *rep_memmove(void *dest,const void *src,int size)
{
unsigned long d,s;
int i;
/****************************************************************************
duplicate a string
****************************************************************************/
- char *strdup(const char *s)
+char *rep_strdup(const char *s)
{
size_t len;
char *ret;
}
#endif /* HAVE_STRDUP */
-#ifndef WITH_PTHREADS
-/* REWRITE: not thread safe */
-#ifdef REPLACE_INET_NTOA
- char *rep_inet_ntoa(struct in_addr ip)
-{
- uint8_t *p = (uint8_t *)&ip.s_addr;
- static char buf[18];
- slprintf(buf, 17, "%d.%d.%d.%d",
- (int)p[0], (int)p[1], (int)p[2], (int)p[3]);
- return buf;
-}
-#endif /* REPLACE_INET_NTOA */
-#endif
-
#ifndef HAVE_SETLINEBUF
- int setlinebuf(FILE *stream)
+void rep_setlinebuf(FILE *stream)
{
- return setvbuf(stream, (char *)NULL, _IOLBF, 0);
+ setvbuf(stream, (char *)NULL, _IOLBF, 0);
}
#endif /* HAVE_SETLINEBUF */
#ifndef HAVE_VSYSLOG
#ifdef HAVE_SYSLOG
- void vsyslog (int facility_priority, char *format, va_list arglist)
+void rep_vsyslog (int facility_priority, const char *format, va_list arglist)
{
char *msg = NULL;
vasprintf(&msg, format, arglist);
#endif /* HAVE_SYSLOG */
#endif /* HAVE_VSYSLOG */
-/*******************************************************************
-yield the difference between *A and *B, in seconds, ignoring leap seconds
-********************************************************************/
-static int tm_diff(struct tm *a, struct tm *b)
+#ifndef HAVE_STRNLEN
+/**
+ Some platforms don't have strnlen
+**/
+ size_t rep_strnlen(const char *s, size_t max)
{
- int ay = a->tm_year + (1900 - 1);
- int by = b->tm_year + (1900 - 1);
- int intervening_leap_days =
- (ay/4 - by/4) - (ay/100 - by/100) + (ay/400 - by/400);
- int years = ay - by;
- int days = 365*years + intervening_leap_days + (a->tm_yday - b->tm_yday);
- int hours = 24*days + (a->tm_hour - b->tm_hour);
- int minutes = 60*hours + (a->tm_min - b->tm_min);
- int seconds = 60*minutes + (a->tm_sec - b->tm_sec);
-
- return seconds;
+ size_t len;
+
+ for (len = 0; len < max; len++) {
+ if (s[len] == '\0') {
+ break;
+ }
+ }
+ return len;
}
+#endif
+
+#ifndef HAVE_STRNDUP
+/**
+ Some platforms don't have strndup.
+**/
+char *rep_strndup(const char *s, size_t n)
+{
+ char *ret;
+
+ n = strnlen(s, n);
+ ret = malloc(n+1);
+ if (!ret)
+ return NULL;
+ memcpy(ret, s, n);
+ ret[n] = 0;
-/*******************************************************************
- return the UTC offset in seconds west of UTC, or 0 if it cannot be determined
- ******************************************************************/
-int get_time_zone(time_t t)
+ return ret;
+}
+#endif
+
+#ifndef HAVE_WAITPID
+int rep_waitpid(pid_t pid,int *status,int options)
{
- struct tm *tm = gmtime(&t);
- struct tm tm_utc;
- if (!tm)
- return 0;
- tm_utc = *tm;
- tm = localtime(&t);
- if (!tm)
- return 0;
- return tm_diff(&tm_utc,tm);
+ return wait4(pid, status, options, NULL);
}
+#endif
-#ifndef HAVE_TIMEGM
-/*
- yes, I know this looks insane, but its really needed. The function in the
- Linux timegm() manpage does not work on solaris.
-*/
- time_t timegm(struct tm *tm)
+#ifndef HAVE_SETEUID
+int rep_seteuid(uid_t euid)
{
- struct tm tm2, tm3;
- time_t t;
+#ifdef HAVE_SETRESUID
+ return setresuid(-1, euid, -1);
+#else
+# error "You need a seteuid function"
+#endif
+}
+#endif
- tm2 = *tm;
+#ifndef HAVE_SETEGID
+int rep_setegid(gid_t egid)
+{
+#ifdef HAVE_SETRESGID
+ return setresgid(-1, egid, -1);
+#else
+# error "You need a setegid function"
+#endif
+}
+#endif
- t = mktime(&tm2);
- tm3 = *localtime(&t);
- tm2 = *tm;
- tm2.tm_isdst = tm3.tm_isdst;
- t = mktime(&tm2);
- t -= get_time_zone(t);
+/*******************************************************************
+os/2 also doesn't have chroot
+********************************************************************/
+#ifndef HAVE_CHROOT
+int rep_chroot(const char *dname)
+{
+ errno = ENOSYS;
+ return -1;
+}
+#endif
- return t;
+/*****************************************************************
+ Possibly replace mkstemp if it is broken.
+*****************************************************************/
+
+#ifndef HAVE_SECURE_MKSTEMP
+int rep_mkstemp(char *template)
+{
+ /* have a reasonable go at emulating it. Hope that
+ the system mktemp() isn't completly hopeless */
+ char *p = mktemp(template);
+ if (!p)
+ return -1;
+ return open(p, O_CREAT|O_EXCL|O_RDWR, 0600);
}
#endif
-#ifndef HAVE_SETENV
- int setenv(const char *name, const char *value, int overwrite)
+#ifndef HAVE_MKDTEMP
+char *rep_mkdtemp(char *template)
{
- char *p = NULL;
- int ret = -1;
+ char *dname;
+
+ if ((dname = mktemp(template))) {
+ if (mkdir(dname, 0700) >= 0) {
+ return dname;
+ }
+ }
- asprintf(&p, "%s=%s", name, value);
+ return NULL;
+}
+#endif
- if (overwrite || getenv(name)) {
- if (p) ret = putenv(p);
- } else {
- ret = 0;
- }
+/*****************************************************************
+ Watch out: this is not thread safe.
+*****************************************************************/
- return ret;
+#ifndef HAVE_PREAD
+ssize_t rep_pread(int __fd, void *__buf, size_t __nbytes, off_t __offset)
+{
+ if (lseek(__fd, __offset, SEEK_SET) != __offset) {
+ return -1;
+ }
+ return read(__fd, __buf, __nbytes);
}
#endif
+/*****************************************************************
+ Watch out: this is not thread safe.
+*****************************************************************/
-#ifndef HAVE_STRTOULL
- unsigned long long int strtoull(const char *str, char **endptr, int base)
+#ifndef HAVE_PWRITE
+ssize_t rep_pwrite(int __fd, const void *__buf, size_t __nbytes, off_t __offset)
{
-#ifdef HAVE_STRTOUQ
- return strtouq(str, endptr, base);
-#elif defined(HAVE___STRTOULL)
- return __strtoull(str, endptr, base);
-#else
-# error "You need a strtoull function"
+ if (lseek(__fd, __offset, SEEK_SET) != __offset) {
+ return -1;
+ }
+ return write(__fd, __buf, __nbytes);
+}
+#endif
+
+#ifndef HAVE_STRCASESTR
+char *rep_strcasestr(const char *haystack, const char *needle)
+{
+ const char *s;
+ size_t nlen = strlen(needle);
+ for (s=haystack;*s;s++) {
+ if (toupper(*needle) == toupper(*s) &&
+ strncasecmp(s, needle, nlen) == 0) {
+ return (char *)((intptr_t)s);
+ }
+ }
+ return NULL;
+}
#endif
+
+#ifndef HAVE_STRTOK_R
+/* based on GLIBC version, copyright Free Software Foundation */
+char *rep_strtok_r(char *s, const char *delim, char **save_ptr)
+{
+ char *token;
+
+ if (s == NULL) s = *save_ptr;
+
+ s += strspn(s, delim);
+ if (*s == '\0') {
+ *save_ptr = s;
+ return NULL;
+ }
+
+ token = s;
+ s = strpbrk(token, delim);
+ if (s == NULL) {
+ *save_ptr = token + strlen(token);
+ } else {
+ *s = '\0';
+ *save_ptr = s + 1;
+ }
+
+ return token;
}
#endif
#ifndef HAVE_STRTOLL
- long long int strtoll(const char *str, char **endptr, int base)
+long long int rep_strtoll(const char *str, char **endptr, int base)
{
#ifdef HAVE_STRTOQ
return strtoq(str, endptr, base);
#elif defined(HAVE___STRTOLL)
return __strtoll(str, endptr, base);
+#elif SIZEOF_LONG == SIZEOF_LONG_LONG
+ return (long long int) strtol(str, endptr, base);
#else
# error "You need a strtoll function"
#endif
#endif
-#ifndef HAVE_STRNDUP
-/**
- Some platforms don't have strndup.
-**/
- char *strndup(const char *s, size_t n)
+#ifndef HAVE_STRTOULL
+unsigned long long int rep_strtoull(const char *str, char **endptr, int base)
{
- char *ret;
-
- n = strnlen(s, n);
- ret = malloc(n+1);
- if (!ret)
- return NULL;
- memcpy(ret, s, n);
- ret[n] = 0;
-
- return ret;
+#ifdef HAVE_STRTOUQ
+ return strtouq(str, endptr, base);
+#elif defined(HAVE___STRTOULL)
+ return __strtoull(str, endptr, base);
+#elif SIZEOF_LONG == SIZEOF_LONG_LONG
+ return (unsigned long long int) strtoul(str, endptr, base);
+#else
+# error "You need a strtoull function"
+#endif
}
#endif
-#ifndef HAVE_STRNLEN
-/**
- Some platforms don't have strnlen
-**/
- size_t strnlen(const char *s, size_t n)
+#ifndef HAVE_SETENV
+int rep_setenv(const char *name, const char *value, int overwrite)
{
- int i;
- for (i=0; s[i] && i<n; i++)
- /* noop */ ;
- return i;
+ char *p;
+ size_t l1, l2;
+ int ret;
+
+ if (!overwrite && getenv(name)) {
+ return 0;
+ }
+
+ l1 = strlen(name);
+ l2 = strlen(value);
+
+ p = malloc(l1+l2+2);
+ if (p == NULL) {
+ return -1;
+ }
+ memcpy(p, name, l1);
+ p[l1] = '=';
+ memcpy(p+l1+1, value, l2);
+ p[l1+l2+1] = 0;
+
+ ret = putenv(p);
+ if (ret != 0) {
+ free(p);
+ }
+
+ return ret;
}
#endif
-int sys_waitpid(pid_t pid,int *status,int options)
+#ifndef HAVE_UNSETENV
+int rep_unsetenv(const char *name)
{
-#ifdef HAVE_WAITPID
- return waitpid(pid,status,options);
-#else /* USE_WAITPID */
- return wait4(pid, status, options, NULL);
-#endif /* USE_WAITPID */
+ extern char **environ;
+ size_t len = strlen(name);
+ size_t i, count;
+
+ if (environ == NULL || getenv(name) == NULL) {
+ return 0;
+ }
+
+ for (i=0;environ[i];i++) /* noop */ ;
+
+ count=i;
+
+ for (i=0;i<count;) {
+ if (strncmp(environ[i], name, len) == 0 && environ[i][len] == '=') {
+ /* note: we do _not_ free the old variable here. It is unsafe to
+ do so, as the pointer may not have come from malloc */
+ memmove(&environ[i], &environ[i+1], (count-i)*sizeof(char *));
+ count--;
+ } else {
+ i++;
+ }
+ }
+
+ return 0;
}
+#endif
-#ifndef HAVE_SETEUID
- int seteuid(uid_t euid)
+#ifndef HAVE_SOCKETPAIR
+int rep_socketpair(int d, int type, int protocol, int sv[2])
{
-#ifdef HAVE_SETRESUID
- return setresuid(-1, euid, -1);
-#else
-# error "You need a seteuid function"
-#endif
+ if (d != AF_UNIX) {
+ errno = EAFNOSUPPORT;
+ return -1;
+ }
+
+ if (protocol != 0) {
+ errno = EPROTONOSUPPORT;
+ return -1;
+ }
+
+ if (type != SOCK_STREAM) {
+ errno = EOPNOTSUPP;
+ return -1;
+ }
+
+ return pipe(sv);
}
#endif