Revert "pthreadpool: add pthreadpool_tevent_[current_job_]per_thread_cwd()"
[samba.git] / lib / replace / replace.c
index 17fd46bcc89828b5bd85ce7573c68fafe106c04c..a14322b8e578a94f693b53478829a1d55cd5d043 100644 (file)
@@ -3,6 +3,7 @@
    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
@@ -26,6 +27,7 @@
 
 #include "system/filesys.h"
 #include "system/time.h"
+#include "system/network.h"
 #include "system/passwd.h"
 #include "system/syslog.h"
 #include "system/locale.h"
@@ -62,14 +64,22 @@ int rep_ftruncate(int f, off_t l)
 
 
 #ifndef HAVE_STRLCPY
-/* like strncpy but does not 0 fill the buffer and always null 
-   terminates. bufsize is the size of the destination buffer */
+/*
+ * Like strncpy but does not 0 fill the buffer and always null
+ * terminates. bufsize is the size of the destination buffer.
+ * Returns the length of s.
+ */
 size_t rep_strlcpy(char *d, const char *s, size_t bufsize)
 {
        size_t len = strlen(s);
        size_t ret = len;
-       if (bufsize <= 0) return 0;
-       if (len >= bufsize) len = bufsize-1;
+
+       if (bufsize <= 0) {
+               return 0;
+       }
+       if (len >= bufsize) {
+               len = bufsize - 1;
+       }
        memcpy(d, s, len);
        d[len] = 0;
        return ret;
@@ -82,7 +92,7 @@ size_t rep_strlcpy(char *d, const char *s, size_t bufsize)
    be one more than the maximum resulting string length */
 size_t rep_strlcat(char *d, const char *s, size_t bufsize)
 {
-       size_t len1 = strlen(d);
+       size_t len1 = strnlen(d, bufsize);
        size_t len2 = strlen(s);
        size_t ret = len1 + len2;
 
@@ -212,16 +222,6 @@ int rep_initgroups(char *name, gid_t id)
 #endif /* HAVE_INITGROUPS */
 
 
-#if (defined(SecureWare) && defined(SCO))
-/* 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) {
-        return syscall(0x0c28, milliseconds);
- }
-#endif
-
-
 #ifndef HAVE_MEMMOVE
 /*******************************************************************
 safely copies memory, ensuring no overlap problems.
@@ -409,11 +409,11 @@ int rep_chroot(const char *dname)
 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);
+       return open(template, O_CREAT|O_EXCL|O_RDWR, 0600);
 }
 #endif
 
@@ -475,6 +475,26 @@ char *rep_strcasestr(const char *haystack, const char *needle)
 }
 #endif
 
+#ifndef HAVE_STRSEP
+char *rep_strsep(char **pps, const char *delim)
+{
+       char *ret = *pps;
+       char *p = *pps;
+
+       if (p == NULL) {
+               return NULL;
+       }
+       p += strcspn(p, delim);
+       if (*p == '\0') {
+               *pps = NULL;
+       } else {
+               *p = '\0';
+               *pps = p + 1;
+       }
+       return ret;
+}
+#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)
@@ -502,6 +522,7 @@ char *rep_strtok_r(char *s, const char *delim, char **save_ptr)
 }
 #endif
 
+
 #ifndef HAVE_STRTOLL
 long long int rep_strtoll(const char *str, char **endptr, int base)
 {
@@ -515,7 +536,27 @@ 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
+#undef strtoll
+long long int rep_strtoll(const char *str, char **endptr, int base)
+{
+       int saved_errno = errno;
+       long long int nb = strtoll(str, endptr, base);
+       /* With glibc 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 = saved_errno;
+               }
+       }
+       return nb;
+}
+#endif /* HAVE_BSD_STRTOLL */
+#endif /* HAVE_STRTOLL */
 
 
 #ifndef HAVE_STRTOULL
@@ -531,7 +572,27 @@ unsigned long long int rep_strtoull(const char *str, char **endptr, int base)
 # error "You need a strtoull function"
 #endif
 }
-#endif
+#else
+#ifdef HAVE_BSD_STRTOLL
+#undef strtoull
+unsigned long long int rep_strtoull(const char *str, char **endptr, int base)
+{
+       int saved_errno = errno;
+       unsigned long long int nb = strtoull(str, endptr, base);
+       /* With glibc 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 = saved_errno;
+               }
+       }
+       return nb;
+}
+#endif /* HAVE_BSD_STRTOLL */
+#endif /* HAVE_STRTOULL */
 
 #ifndef HAVE_SETENV
 int rep_setenv(const char *name, const char *value, int overwrite) 
@@ -691,8 +752,8 @@ void *rep_memmem(const void *haystack, size_t haystacklen,
                return discard_const(haystack);
        }
        while (haystacklen >= needlelen) {
-               char *p = memchr(haystack, *(const char *)needle,
-                                haystacklen-(needlelen-1));
+               char *p = (char *)memchr(haystack, *(const char *)needle,
+                                        haystacklen-(needlelen-1));
                if (!p) return NULL;
                if (memcmp(p, needle, needlelen) == 0) {
                        return p;
@@ -704,3 +765,294 @@ void *rep_memmem(const void *haystack, size_t haystacklen,
 }
 #endif
 
+#if !defined(HAVE_VDPRINTF) || !defined(HAVE_C99_VSNPRINTF)
+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
+
+#if !defined(HAVE_DPRINTF) || !defined(HAVE_C99_VSNPRINTF)
+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
+
+#ifndef HAVE_STRERROR_R
+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;
+}
+#elif (!defined(STRERROR_R_XSI_NOT_GNU))
+#undef strerror_r
+int rep_strerror_r(int errnum, char *buf, size_t buflen)
+{
+       char *s = strerror_r(errnum, buf, buflen);
+       if (s == NULL) {
+               /* Shouldn't happen, should always get a string */
+               return EINVAL;
+       }
+       if (s != buf) {
+               strlcpy(buf, s, buflen);
+               if (strlen(s) > buflen - 1) {
+                       return ERANGE;
+               }
+       }
+       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 :*/
+#if defined(HAVE_GETTIMEOFDAY_TZ) || defined(HAVE_GETTIMEOFDAY_TZ_VOID)
+                       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 */
+
+#ifndef HAVE_SETPROCTITLE
+void rep_setproctitle(const char *fmt, ...)
+{
+}
+#endif
+#ifndef HAVE_SETPROCTITLE_INIT
+void rep_setproctitle_init(int argc, char *argv[], char *envp[])
+{
+}
+#endif
+
+#ifndef HAVE_MEMSET_S
+# ifndef RSIZE_MAX
+#  define RSIZE_MAX (SIZE_MAX >> 1)
+# endif
+
+int rep_memset_s(void *dest, size_t destsz, int ch, size_t count)
+{
+       if (dest == NULL) {
+               return EINVAL;
+       }
+
+       if (destsz > RSIZE_MAX ||
+           count > RSIZE_MAX ||
+           count > destsz) {
+               return ERANGE;
+       }
+
+#if defined(HAVE_MEMSET_EXPLICIT)
+       memset_explicit(dest, destsz, ch, count);
+#else /* HAVE_MEMSET_EXPLICIT */
+       memset(dest, ch, count);
+# if defined(HAVE_GCC_VOLATILE_MEMORY_PROTECTION)
+       /* See http://llvm.org/bugs/show_bug.cgi?id=15495 */
+       __asm__ volatile("" : : "g"(dest) : "memory");
+# endif /* HAVE_GCC_VOLATILE_MEMORY_PROTECTION */
+#endif /* HAVE_MEMSET_EXPLICIT */
+
+       return 0;
+}
+#endif /* HAVE_MEMSET_S */
+
+#ifndef HAVE_GETPROGNAME
+# ifndef HAVE_PROGRAM_INVOCATION_SHORT_NAME
+# define PROGNAME_SIZE 32
+static char rep_progname[PROGNAME_SIZE];
+# endif /* HAVE_PROGRAM_INVOCATION_SHORT_NAME */
+
+const char *rep_getprogname(void)
+{
+#ifdef HAVE_PROGRAM_INVOCATION_SHORT_NAME
+       return program_invocation_short_name;
+#else /* HAVE_PROGRAM_INVOCATION_SHORT_NAME */
+       FILE *fp = NULL;
+       char cmdline[4096] = {0};
+       char *p = NULL;
+       pid_t pid;
+       size_t nread;
+       int len;
+       int rc;
+
+       if (rep_progname[0] != '\0') {
+               return rep_progname;
+       }
+
+       len = snprintf(rep_progname, sizeof(rep_progname), "%s", "<unknown>");
+       if (len <= 0) {
+               return NULL;
+       }
+
+       pid = getpid();
+       if (pid <= 1 || pid == (pid_t)-1) {
+               return NULL;
+       }
+
+       len = snprintf(cmdline,
+                      sizeof(cmdline),
+                      "/proc/%u/cmdline",
+                      (unsigned int)pid);
+       if (len <= 0 || len == sizeof(cmdline)) {
+               return NULL;
+       }
+
+       fp = fopen(cmdline, "r");
+       if (fp == NULL) {
+               return NULL;
+       }
+
+       nread = fread(cmdline, 1, sizeof(cmdline) - 1, fp);
+
+       rc = fclose(fp);
+       if (rc != 0) {
+               return NULL;
+       }
+
+       if (nread == 0) {
+               return NULL;
+       }
+
+       cmdline[nread] = '\0';
+
+       p = strrchr(cmdline, '/');
+       if (p != NULL) {
+               p++;
+       } else {
+               p = cmdline;
+       }
+
+       len = strlen(p);
+       if (len > PROGNAME_SIZE) {
+               p[PROGNAME_SIZE - 1] = '\0';
+       }
+
+       (void)snprintf(rep_progname, sizeof(rep_progname), "%s", p);
+
+       return rep_progname;
+#endif /* HAVE_PROGRAM_INVOCATION_SHORT_NAME */
+}
+#endif /* HAVE_GETPROGNAME */