/uClinux-dist/user/samba/source/lib/replace/replace.c
C | 612 lines | 460 code | 77 blank | 75 comment | 96 complexity | fd66cc876c36f4e3acf8932e2e8ad883 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause, LGPL-2.1, MPL-2.0-no-copyleft-exception, ISC, AGPL-1.0, LGPL-2.0, GPL-3.0, LGPL-3.0, 0BSD
- /*
- 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 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 2 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
- 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, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
- #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) {}
- #ifndef HAVE_FTRUNCATE
- /*******************************************************************
- ftruncate for operating systems that don't have it
- ********************************************************************/
- int rep_ftruncate(int f, off_t l)
- {
- #ifdef HAVE_CHSIZE
- return chsize(f,l);
- #elif defined(F_FREESP)
- struct flock fl;
- fl.l_whence = 0;
- fl.l_len = 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 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;
- memcpy(d, s, len);
- d[len] = 0;
- return ret;
- }
- #endif
- #ifndef HAVE_STRLCAT
- /* 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 rep_strlcat(char *d, const char *s, size_t bufsize)
- {
- size_t len1 = strlen(d);
- size_t len2 = strlen(s);
- size_t ret = len1 + len2;
- if (len1+len2 >= bufsize) {
- len2 = bufsize - (len1+1);
- }
- if (len2 > 0) {
- memcpy(d+len1, s, len2);
- d[len1+len2] = 0;
- }
- return ret;
- }
- #endif
- #ifndef HAVE_MKTIME
- /*******************************************************************
- a mktime() replacement for those who don't have it - contributed by
- C.A. Lademann <cal@zls.com>
- Corrections by richard.kettlewell@kewill.com
- ********************************************************************/
- #define MINUTE 60
- #define HOUR 60*MINUTE
- #define DAY 24*HOUR
- #define YEAR 365*DAY
- time_t rep_mktime(struct tm *t)
- {
- struct tm *u;
- time_t epoch = 0;
- int n;
- int mon [] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
- y, m, i;
- if(t->tm_year < 70)
- return((time_t)-1);
- n = t->tm_year + 1900 - 1;
- epoch = (t->tm_year - 70) * YEAR +
- ((n / 4 - n / 100 + n / 400) - (1969 / 4 - 1969 / 100 + 1969 / 400)) * DAY;
- y = t->tm_year + 1900;
- m = 0;
- for(i = 0; i < t->tm_mon; i++) {
- epoch += mon [m] * DAY;
- if(m == 1 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0))
- epoch += DAY;
-
- if(++m > 11) {
- m = 0;
- y++;
- }
- }
- epoch += (t->tm_mday - 1) * DAY;
- epoch += t->tm_hour * HOUR + t->tm_min * MINUTE + t->tm_sec;
-
- if((u = localtime(&epoch)) != NULL) {
- t->tm_sec = u->tm_sec;
- t->tm_min = u->tm_min;
- t->tm_hour = u->tm_hour;
- t->tm_mday = u->tm_mday;
- t->tm_mon = u->tm_mon;
- t->tm_year = u->tm_year;
- t->tm_wday = u->tm_wday;
- t->tm_yday = u->tm_yday;
- t->tm_isdst = u->tm_isdst;
- }
- return(epoch);
- }
- #endif /* !HAVE_MKTIME */
- #ifndef HAVE_INITGROUPS
- /****************************************************************************
- some systems don't have an initgroups call
- ****************************************************************************/
- 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 = 32;
- int ret;
- int i,j;
- struct group *g;
- char *gr;
-
- if((grouplst = malloc(sizeof(gid_t) * max_gr)) == NULL) {
- errno = ENOMEM;
- return -1;
- }
- grouplst[0] = id;
- i = 1;
- while (i < max_gr && ((g = (struct group *)getgrent()) != (struct group *)NULL)) {
- if (g->gr_gid == id)
- continue;
- j = 0;
- gr = g->gr_mem[0];
- while (gr && (*gr != (char)NULL)) {
- if (strcmp(name,gr) == 0) {
- grouplst[i] = g->gr_gid;
- i++;
- gr = (char *)NULL;
- break;
- }
- gr = g->gr_mem[++j];
- }
- }
- endgrent();
- ret = setgroups(i, grouplst);
- free(grouplst);
- return ret;
- #endif /* HAVE_SETGROUPS */
- }
- #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.
- this is only used if the machine does not have it's own memmove().
- this is not the fastest algorithm in town, but it will do for our
- needs.
- ********************************************************************/
- void *rep_memmove(void *dest,const void *src,int size)
- {
- unsigned long d,s;
- int i;
- if (dest==src || !size) return(dest);
- d = (unsigned long)dest;
- s = (unsigned long)src;
- if ((d >= (s+size)) || (s >= (d+size))) {
- /* no overlap */
- memcpy(dest,src,size);
- return(dest);
- }
- if (d < s) {
- /* we can forward copy */
- if (s-d >= sizeof(int) &&
- !(s%sizeof(int)) &&
- !(d%sizeof(int)) &&
- !(size%sizeof(int))) {
- /* do it all as words */
- int *idest = (int *)dest;
- int *isrc = (int *)src;
- size /= sizeof(int);
- for (i=0;i<size;i++) idest[i] = isrc[i];
- } else {
- /* simplest */
- char *cdest = (char *)dest;
- char *csrc = (char *)src;
- for (i=0;i<size;i++) cdest[i] = csrc[i];
- }
- } else {
- /* must backward copy */
- if (d-s >= sizeof(int) &&
- !(s%sizeof(int)) &&
- !(d%sizeof(int)) &&
- !(size%sizeof(int))) {
- /* do it all as words */
- int *idest = (int *)dest;
- int *isrc = (int *)src;
- size /= sizeof(int);
- for (i=size-1;i>=0;i--) idest[i] = isrc[i];
- } else {
- /* simplest */
- char *cdest = (char *)dest;
- char *csrc = (char *)src;
- for (i=size-1;i>=0;i--) cdest[i] = csrc[i];
- }
- }
- return(dest);
- }
- #endif /* HAVE_MEMMOVE */
- #ifndef HAVE_STRDUP
- /****************************************************************************
- duplicate a string
- ****************************************************************************/
- char *rep_strdup(const char *s)
- {
- size_t len;
- char *ret;
- if (!s) return(NULL);
- len = strlen(s)+1;
- ret = (char *)malloc(len);
- if (!ret) return(NULL);
- memcpy(ret,s,len);
- return(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
- void rep_setlinebuf(FILE *stream)
- {
- setvbuf(stream, (char *)NULL, _IOLBF, 0);
- }
- #endif /* HAVE_SETLINEBUF */
- #ifndef HAVE_VSYSLOG
- #ifdef HAVE_SYSLOG
- void rep_vsyslog (int facility_priority, const char *format, va_list arglist)
- {
- char *msg = NULL;
- vasprintf(&msg, format, arglist);
- if (!msg)
- return;
- syslog(facility_priority, "%s", msg);
- free(msg);
- }
- #endif /* HAVE_SYSLOG */
- #endif /* HAVE_VSYSLOG */
- #ifndef HAVE_STRNLEN
- /**
- Some platforms don't have strnlen
- **/
- size_t rep_strnlen(const char *s, size_t max)
- {
- 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 ret;
- }
- #endif
- #ifndef HAVE_WAITPID
- int rep_waitpid(pid_t pid,int *status,int options)
- {
- return wait4(pid, status, options, NULL);
- }
- #endif
- #ifndef HAVE_SETEUID
- int rep_seteuid(uid_t euid)
- {
- #ifdef HAVE_SETRESUID
- return setresuid(-1, euid, -1);
- #else
- # error "You need a seteuid function"
- #endif
- }
- #endif
- #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
- /*******************************************************************
- os/2 also doesn't have chroot
- ********************************************************************/
- #ifndef HAVE_CHROOT
- int rep_chroot(const char *dname)
- {
- errno = ENOSYS;
- return -1;
- }
- #endif
- /*****************************************************************
- 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_MKDTEMP
- char *rep_mkdtemp(char *template)
- {
- char *dname;
-
- if ((dname = mktemp(template))) {
- if (mkdir(dname, 0700) >= 0) {
- return dname;
- }
- }
- return NULL;
- }
- #endif
- #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
- #ifndef HAVE_PWRITE
- ssize_t rep_pwrite(int __fd, const void *__buf, size_t __nbytes, off_t __offset)
- {
- 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 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_STRTOULL
- unsigned long long int rep_strtoull(const char *str, char **endptr, int base)
- {
- #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_SETENV
- int rep_setenv(const char *name, const char *value, int overwrite)
- {
- 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
- #ifndef HAVE_UNSETENV
- int rep_unsetenv(const char *name)
- {
- extern char **environ;
- size_t len = strlen(name);
- size_t i;
- int found = 0;
- for (i=0; (environ && environ[i]); i++) {
- if (found) {
- environ[i-1] = environ[i];
- continue;
- }
- if (strncmp(environ[i], name, len) == 0 && environ[i][len] == '=') {
- free(environ[i]);
- environ[i] = NULL;
- found = 1;
- continue;
- }
- }
- return 0;
- }
- #endif
- #ifndef HAVE_SOCKETPAIR
- int rep_socketpair(int d, int type, int protocol, int sv[2])
- {
- 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