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
31 #include <sys/types.h>
34 void replace_dummy(void);
35 void replace_dummy(void) {}
37 #ifndef HAVE_FTRUNCATE
38 /*******************************************************************
39 ftruncate for operating systems that don't have it
40 ********************************************************************/
41 int rep_ftruncate(int f, off_t l)
52 return fcntl(f, F_FREESP, &fl);
55 #endif /* HAVE_FTRUNCATE */
59 /* like strncpy but does not 0 fill the buffer and always null
60 terminates. bufsize is the size of the destination buffer */
61 size_t rep_strlcpy(char *d, const char *s, size_t bufsize)
63 size_t len = strlen(s);
65 if (bufsize <= 0) return 0;
66 if (len >= bufsize) len = bufsize-1;
74 /* like strncat but does not 0 fill the buffer and always null
75 terminates. bufsize is the length of the buffer, which should
76 be one more than the maximum resulting string length */
77 size_t rep_strlcat(char *d, const char *s, size_t bufsize)
79 size_t len1 = strlen(d);
80 size_t len2 = strlen(s);
81 size_t ret = len1 + len2;
83 if (len1+len2 >= bufsize) {
84 len2 = bufsize - (len1+1);
87 memcpy(d+len1, s, len2);
95 /*******************************************************************
96 a mktime() replacement for those who don't have it - contributed by
97 C.A. Lademann <cal@zls.com>
98 Corrections by richard.kettlewell@kewill.com
99 ********************************************************************/
102 #define HOUR 60*MINUTE
105 time_t rep_mktime(struct tm *t)
110 int mon [] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
116 n = t->tm_year + 1900 - 1;
117 epoch = (t->tm_year - 70) * YEAR +
118 ((n / 4 - n / 100 + n / 400) - (1969 / 4 - 1969 / 100 + 1969 / 400)) * DAY;
120 y = t->tm_year + 1900;
123 for(i = 0; i < t->tm_mon; i++) {
124 epoch += mon [m] * DAY;
125 if(m == 1 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0))
134 epoch += (t->tm_mday - 1) * DAY;
135 epoch += t->tm_hour * HOUR + t->tm_min * MINUTE + t->tm_sec;
137 if((u = localtime(&epoch)) != NULL) {
138 t->tm_sec = u->tm_sec;
139 t->tm_min = u->tm_min;
140 t->tm_hour = u->tm_hour;
141 t->tm_mday = u->tm_mday;
142 t->tm_mon = u->tm_mon;
143 t->tm_year = u->tm_year;
144 t->tm_wday = u->tm_wday;
145 t->tm_yday = u->tm_yday;
146 t->tm_isdst = u->tm_isdst;
151 #endif /* !HAVE_MKTIME */
156 /* Rename a file. (from libiberty in GNU binutils) */
157 int rep_rename(const char *zfrom, const char *zto)
159 if (link (zfrom, zto) < 0)
164 || link (zfrom, zto) < 0)
167 return unlink (zfrom);
169 #endif /* HAVE_RENAME */
173 #if defined(HAVE_SETNETGRENT) && defined(HAVE_GETNETGRENT) && defined(HAVE_ENDNETGRENT)
175 * Search for a match in a netgroup. This replaces it on broken systems.
177 int rep_innetgr(const char *group, const char *host, const char *user,
180 char *hst, *usr, *dm;
183 while (getnetgrent(&hst, &usr, &dm)) {
184 if (((host == 0) || (hst == 0) || !strcmp(host, hst)) &&
185 ((user == 0) || (usr == 0) || !strcmp(user, usr)) &&
186 ((dom == 0) || (dm == 0) || !strcmp(dom, dm))) {
194 #endif /* HAVE_SETNETGRENT HAVE_GETNETGRENT HAVE_ENDNETGRENT */
195 #endif /* HAVE_INNETGR */
199 #ifndef HAVE_INITGROUPS
200 /****************************************************************************
201 some systems don't have an initgroups call
202 ****************************************************************************/
203 int rep_initgroups(char *name, gid_t id)
205 #ifndef HAVE_SETGROUPS
206 /* yikes! no SETGROUPS or INITGROUPS? how can this work? */
209 #else /* HAVE_SETGROUPS */
213 gid_t *grouplst = NULL;
214 int max_gr = groups_max();
220 if((grouplst = malloc(sizeof(gid_t) * max_gr)) == NULL) {
227 while (i < max_gr && ((g = (struct group *)getgrent()) != (struct group *)NULL)) {
232 while (gr && (*gr != (char)NULL)) {
233 if (strcmp(name,gr) == 0) {
234 grouplst[i] = g->gr_gid;
243 ret = setgroups(i, grouplst);
246 #endif /* HAVE_SETGROUPS */
248 #endif /* HAVE_INITGROUPS */
251 #if (defined(SecureWare) && defined(SCO))
252 /* This is needed due to needing the nap() function but we don't want
253 to include the Xenix libraries since that will break other things...
254 BTW: system call # 0x0c28 is the same as calling nap() */
255 long nap(long milliseconds) {
256 return syscall(0x0c28, milliseconds);
262 /*******************************************************************
263 safely copies memory, ensuring no overlap problems.
264 this is only used if the machine does not have it's own memmove().
265 this is not the fastest algorithm in town, but it will do for our
267 ********************************************************************/
268 void *rep_memmove(void *dest,const void *src,int size)
272 if (dest==src || !size) return(dest);
274 d = (unsigned long)dest;
275 s = (unsigned long)src;
277 if ((d >= (s+size)) || (s >= (d+size))) {
279 memcpy(dest,src,size);
284 /* we can forward copy */
285 if (s-d >= sizeof(int) &&
288 !(size%sizeof(int))) {
289 /* do it all as words */
290 int *idest = (int *)dest;
291 int *isrc = (int *)src;
293 for (i=0;i<size;i++) idest[i] = isrc[i];
296 char *cdest = (char *)dest;
297 char *csrc = (char *)src;
298 for (i=0;i<size;i++) cdest[i] = csrc[i];
301 /* must backward copy */
302 if (d-s >= sizeof(int) &&
305 !(size%sizeof(int))) {
306 /* do it all as words */
307 int *idest = (int *)dest;
308 int *isrc = (int *)src;
310 for (i=size-1;i>=0;i--) idest[i] = isrc[i];
313 char *cdest = (char *)dest;
314 char *csrc = (char *)src;
315 for (i=size-1;i>=0;i--) cdest[i] = csrc[i];
320 #endif /* HAVE_MEMMOVE */
323 /****************************************************************************
325 ****************************************************************************/
326 char *rep_strdup(const char *s)
331 if (!s) return(NULL);
334 ret = (char *)malloc(len);
335 if (!ret) return(NULL);
339 #endif /* HAVE_STRDUP */
341 #ifndef WITH_PTHREADS
342 /* REWRITE: not thread safe */
343 #ifdef REPLACE_INET_NTOA
344 char *rep_inet_ntoa(struct in_addr ip)
346 uint8_t *p = (uint8_t *)&ip.s_addr;
348 slprintf(buf, 17, "%d.%d.%d.%d",
349 (int)p[0], (int)p[1], (int)p[2], (int)p[3]);
352 #endif /* REPLACE_INET_NTOA */
355 #ifndef HAVE_SETLINEBUF
356 int rep_setlinebuf(FILE *stream)
358 return setvbuf(stream, (char *)NULL, _IOLBF, 0);
360 #endif /* HAVE_SETLINEBUF */
364 void rep_vsyslog (int facility_priority, char *format, va_list arglist)
367 vasprintf(&msg, format, arglist);
370 syslog(facility_priority, "%s", msg);
373 #endif /* HAVE_SYSLOG */
374 #endif /* HAVE_VSYSLOG */
378 Some platforms don't have strnlen
380 size_t rep_strnlen(const char *s, size_t max)
384 for (len = 0; len < max; len++) {
385 if (s[len] == '\0') {
395 Some platforms don't have strndup.
397 char *rep_strndup(const char *s, size_t n)
413 int rep_waitpid(pid_t pid,int *status,int options)
415 return wait4(pid, status, options, NULL);
420 int rep_seteuid(uid_t euid)
422 #ifdef HAVE_SETRESUID
423 return setresuid(-1, euid, -1);
425 # error "You need a seteuid function"
431 int rep_setegid(gid_t egid)
433 #ifdef HAVE_SETRESGID
434 return setresgid(-1, egid, -1);
436 # error "You need a setegid function"
441 /*******************************************************************
442 os/2 also doesn't have chroot
443 ********************************************************************/
445 int rep_chroot(const char *dname)
452 /*****************************************************************
453 Possibly replace mkstemp if it is broken.
454 *****************************************************************/
456 #ifndef HAVE_SECURE_MKSTEMP
457 int rep_mkstemp(char *template)
459 /* have a reasonable go at emulating it. Hope that
460 the system mktemp() isn't completly hopeless */
461 char *p = mktemp(template);
464 return open(p, O_CREAT|O_EXCL|O_RDWR, 0600);
469 char *rep_mkdtemp(char *template)
473 if ((dname = mktemp(template))) {
474 if (mkdir(dname, 0700) >= 0) {
484 static ssize_t rep_pread(int __fd, void *__buf, size_t __nbytes, off_t __offset)
486 if (lseek(__fd, __offset, SEEK_SET) != __offset) {
489 return read(__fd, __buf, __nbytes);
494 static ssize_t rep_pwrite(int __fd, const void *__buf, size_t __nbytes, off_t __offset)
496 if (lseek(__fd, __offset, SEEK_SET) != __offset) {
499 return write(__fd, __buf, __nbytes);
503 #ifndef HAVE_STRCASESTR
504 char *rep_strcasestr(const char *haystack, const char *needle)
507 size_t nlen = strlen(needle);
508 for (s=haystack;*s;s++) {
509 if (toupper(*needle) == toupper(*s) &&
510 strncasecmp(s, needle, nlen) == 0) {
511 return (char *)((intptr_t)s);
518 #ifndef HAVE_STRTOK_R
519 /* based on GLIBC version, copyright Free Software Foundation */
520 char *rep_strtok_r(char *s, const char *delim, char **save_ptr)
524 if (s == NULL) s = *save_ptr;
526 s += strspn(s, delim);
533 s = strpbrk(token, delim);
535 *save_ptr = token + strlen(token);
546 long long int rep_strtoll(const char *str, char **endptr, int base)
549 return strtoq(str, endptr, base);
550 #elif defined(HAVE___STRTOLL)
551 return __strtoll(str, endptr, base);
552 #elif SIZEOF_LONG == SIZEOF_LONG_LONG
553 return (long long int) strtol(str, endptr, base);
555 # error "You need a strtoll function"
561 #ifndef HAVE_STRTOULL
562 unsigned long long int rep_strtoull(const char *str, char **endptr, int base)
565 return strtouq(str, endptr, base);
566 #elif defined(HAVE___STRTOULL)
567 return __strtoull(str, endptr, base);
568 #elif SIZEOF_LONG == SIZEOF_LONG_LONG
569 return (unsigned long long int) strtoul(str, endptr, base);
571 # error "You need a strtoull function"
577 int rep_setenv(const char *name, const char *value, int overwrite)
583 if (!overwrite && getenv(name)) {
596 memcpy(p+l1+1, value, l2);