Unix SMB/CIFS implementation.
replacement routines for broken systems
Copyright (C) Andrew Tridgell 1992-1998
+ Copyright (C) Jelmer Vernooij 2005-2008
+ Copyright (C) Matthieu Patou 2010
** NOTE! The following LGPL license applies to the replace
** library. This does NOT imply that all of Samba is released
#include "system/filesys.h"
#include "system/time.h"
+#include "system/network.h"
#include "system/passwd.h"
#include "system/syslog.h"
#include "system/locale.h"
#include "system/wait.h"
+#ifdef _WIN32
+#define mkdir(d,m) _mkdir(d)
+#endif
+
void replace_dummy(void);
void replace_dummy(void) {}
}
#endif
-#ifndef HAVE_WAITPID
+#if !defined(HAVE_WAITPID) && defined(HAVE_WAIT4)
int rep_waitpid(pid_t pid,int *status,int options)
{
return wait4(pid, status, options, NULL);
#ifdef HAVE_SETRESUID
return setresuid(-1, euid, -1);
#else
-# error "You need a seteuid function"
+ errno = ENOSYS;
+ return -1;
#endif
}
#endif
#ifdef HAVE_SETRESGID
return setresgid(-1, egid, -1);
#else
-# error "You need a setegid function"
+ errno = ENOSYS;
+ return -1;
#endif
}
#endif
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)
+ the system mktemp() isn't completely hopeless */
+ mktemp(template);
+ if (template[0] == 0)
return -1;
return open(p, O_CREAT|O_EXCL|O_RDWR, 0600);
}
}
#endif
+
#ifndef HAVE_STRTOLL
long long int rep_strtoll(const char *str, char **endptr, int base)
{
# error "You need a strtoll function"
#endif
}
-#endif
+#else
+#ifdef HAVE_BSD_STRTOLL
+#ifdef HAVE_STRTOQ
+long long int rep_strtoll(const char *str, char **endptr, int base)
+{
+ long long int nb = strtoq(str, endptr, base);
+ /* In linux EINVAL is only returned if base is not ok */
+ if (errno == EINVAL) {
+ if (base == 0 || (base >1 && base <37)) {
+ /* Base was ok so it's because we were not
+ * able to make the convertion.
+ * Let's reset errno.
+ */
+ errno = 0;
+ }
+ }
+ return nb;
+}
+#else
+#error "You need the strtoq function"
+#endif /* HAVE_STRTOQ */
+#endif /* HAVE_BSD_STRTOLL */
+#endif /* HAVE_STRTOLL */
#ifndef HAVE_STRTOULL
# error "You need a strtoull function"
#endif
}
-#endif
+#else
+#ifdef HAVE_BSD_STRTOLL
+#ifdef HAVE_STRTOUQ
+unsigned long long int rep_strtoull(const char *str, char **endptr, int base)
+{
+ unsigned long long int nb = strtouq(str, endptr, base);
+ /* In linux EINVAL is only returned if base is not ok */
+ if (errno == EINVAL) {
+ if (base == 0 || (base >1 && base <37)) {
+ /* Base was ok so it's because we were not
+ * able to make the convertion.
+ * Let's reset errno.
+ */
+ errno = 0;
+ }
+ }
+ return nb;
+}
+#else
+#error "You need the strtouq function"
+#endif /* HAVE_STRTOUQ */
+#endif /* HAVE_BSD_STRTOLL */
+#endif /* HAVE_STRTOULL */
#ifndef HAVE_SETENV
int rep_setenv(const char *name, const char *value, int overwrite)
return utime(filename, &u);
}
#endif
+
+#ifndef HAVE_DUP2
+int rep_dup2(int oldfd, int newfd)
+{
+ errno = ENOSYS;
+ return -1;
+}
+#endif
+
+#ifndef HAVE_CHOWN
+/**
+chown isn't used much but OS/2 doesn't have it
+**/
+int rep_chown(const char *fname, uid_t uid, gid_t gid)
+{
+ errno = ENOSYS;
+ return -1;
+}
+#endif
+
+#ifndef HAVE_LINK
+int rep_link(const char *oldpath, const char *newpath)
+{
+ errno = ENOSYS;
+ return -1;
+}
+#endif
+
+#ifndef HAVE_READLINK
+int rep_readlink(const char *path, char *buf, size_t bufsiz)
+{
+ errno = ENOSYS;
+ return -1;
+}
+#endif
+
+#ifndef HAVE_SYMLINK
+int rep_symlink(const char *oldpath, const char *newpath)
+{
+ errno = ENOSYS;
+ return -1;
+}
+#endif
+
+#ifndef HAVE_LCHOWN
+int rep_lchown(const char *fname,uid_t uid,gid_t gid)
+{
+ errno = ENOSYS;
+ return -1;
+}
+#endif
+
+#ifndef HAVE_REALPATH
+char *rep_realpath(const char *path, char *resolved_path)
+{
+ /* As realpath is not a system call we can't return ENOSYS. */
+ errno = EINVAL;
+ return NULL;
+}
+#endif
+
+
+#ifndef HAVE_MEMMEM
+void *rep_memmem(const void *haystack, size_t haystacklen,
+ const void *needle, size_t needlelen)
+{
+ if (needlelen == 0) {
+ return discard_const(haystack);
+ }
+ while (haystacklen >= needlelen) {
+ char *p = (char *)memchr(haystack, *(const char *)needle,
+ haystacklen-(needlelen-1));
+ if (!p) return NULL;
+ if (memcmp(p, needle, needlelen) == 0) {
+ return p;
+ }
+ haystack = p+1;
+ haystacklen -= (p - (const char *)haystack) + 1;
+ }
+ return NULL;
+}
+#endif
+
+#ifndef HAVE_VDPRINTF
+int rep_vdprintf(int fd, const char *format, va_list ap)
+{
+ char *s = NULL;
+ int ret;
+
+ vasprintf(&s, format, ap);
+ if (s == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+ ret = write(fd, s, strlen(s));
+ free(s);
+ return ret;
+}
+#endif
+
+#ifndef HAVE_DPRINTF
+int rep_dprintf(int fd, const char *format, ...)
+{
+ int ret;
+ va_list ap;
+
+ va_start(ap, format);
+ ret = vdprintf(fd, format, ap);
+ va_end(ap);
+
+ return ret;
+}
+#endif
+
+#ifndef HAVE_GET_CURRENT_DIR_NAME
+char *rep_get_current_dir_name(void)
+{
+ char buf[PATH_MAX+1];
+ char *p;
+ p = getcwd(buf, sizeof(buf));
+ if (p == NULL) {
+ return NULL;
+ }
+ return strdup(p);
+}
+#endif
+
+#if !defined(HAVE_STRERROR_R) || !defined(STRERROR_R_PROTO_COMPATIBLE)
+int rep_strerror_r(int errnum, char *buf, size_t buflen)
+{
+ char *s = strerror(errnum);
+ if (strlen(s)+1 > buflen) {
+ errno = ERANGE;
+ return -1;
+ }
+ strncpy(buf, s, buflen);
+ return 0;
+}
+#endif
+
+#ifndef HAVE_CLOCK_GETTIME
+int rep_clock_gettime(clockid_t clk_id, struct timespec *tp)
+{
+ struct timeval tval;
+ switch (clk_id) {
+ case 0: /* CLOCK_REALTIME :*/
+#ifdef HAVE_GETTIMEOFDAY_TZ
+ gettimeofday(&tval,NULL);
+#else
+ gettimeofday(&tval);
+#endif
+ tp->tv_sec = tval.tv_sec;
+ tp->tv_nsec = tval.tv_usec * 1000;
+ break;
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+ return 0;
+}
+#endif
+
+#ifndef HAVE_MEMALIGN
+void *rep_memalign( size_t align, size_t size )
+{
+#if defined(HAVE_POSIX_MEMALIGN)
+ void *p = NULL;
+ int ret = posix_memalign( &p, align, size );
+ if ( ret == 0 )
+ return p;
+
+ return NULL;
+#else
+ /* On *BSD systems memaligns doesn't exist, but memory will
+ * be aligned on allocations of > pagesize. */
+#if defined(SYSCONF_SC_PAGESIZE)
+ size_t pagesize = (size_t)sysconf(_SC_PAGESIZE);
+#elif defined(HAVE_GETPAGESIZE)
+ size_t pagesize = (size_t)getpagesize();
+#else
+ size_t pagesize = (size_t)-1;
+#endif
+ if (pagesize == (size_t)-1) {
+ errno = ENOSYS;
+ return NULL;
+ }
+ if (size < pagesize) {
+ size = pagesize;
+ }
+ return malloc(size);
+#endif
+}
+#endif
+
+#ifndef HAVE_GETPEEREID
+int rep_getpeereid(int s, uid_t *uid, gid_t *gid)
+{
+#if defined(HAVE_PEERCRED)
+ struct ucred cred;
+ socklen_t cred_len = sizeof(struct ucred);
+ int ret;
+
+#undef getsockopt
+ ret = getsockopt(s, SOL_SOCKET, SO_PEERCRED, (void *)&cred, &cred_len);
+ if (ret != 0) {
+ return -1;
+ }
+
+ if (cred_len != sizeof(struct ucred)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ *uid = cred.uid;
+ *gid = cred.gid;
+ return 0;
+#else
+ errno = ENOSYS;
+ return -1;
+#endif
+}
+#endif
+
+#ifndef HAVE_USLEEP
+int rep_usleep(useconds_t sec)
+{
+ struct timeval tval;
+ /*
+ * Fake it with select...
+ */
+ tval.tv_sec = 0;
+ tval.tv_usec = usecs/1000;
+ select(0,NULL,NULL,NULL,&tval);
+ return 0;
+}
+#endif /* HAVE_USLEEP */