source: branches/samba-3.0/source/lib/replace/replace.c

Last change on this file was 140, checked in by Paul Smedley, 17 years ago

Update branch to 3.0.31 release

File size: 13.7 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3 replacement routines for broken systems
4 Copyright (C) Andrew Tridgell 1992-1998
5
6 ** NOTE! The following LGPL license applies to the replace
7 ** library. This does NOT imply that all of Samba is released
8 ** under the LGPL
9
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.
14
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.
19
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
23*/
24
25#include "replace.h"
26
27#include "system/filesys.h"
28#include "system/time.h"
29#include "system/passwd.h"
30#include "system/syslog.h"
31#include "system/network.h"
32#include "system/locale.h"
33#include "system/wait.h"
34
35void replace_dummy(void);
36void replace_dummy(void) {}
37
38#ifndef HAVE_FTRUNCATE
39 /*******************************************************************
40ftruncate for operating systems that don't have it
41********************************************************************/
42int rep_ftruncate(int f, off_t l)
43{
44#ifdef HAVE_CHSIZE
45 return chsize(f,l);
46#elif defined(F_FREESP)
47 struct flock fl;
48
49 fl.l_whence = 0;
50 fl.l_len = 0;
51 fl.l_start = l;
52 fl.l_type = F_WRLCK;
53 return fcntl(f, F_FREESP, &fl);
54#else
55#error "you must have a ftruncate function"
56#endif
57}
58#endif /* HAVE_FTRUNCATE */
59
60
61#ifndef HAVE_STRLCPY
62/* like strncpy but does not 0 fill the buffer and always null
63 terminates. bufsize is the size of the destination buffer */
64size_t rep_strlcpy(char *d, const char *s, size_t bufsize)
65{
66 size_t len = strlen(s);
67 size_t ret = len;
68 if (bufsize <= 0) return 0;
69 if (len >= bufsize) len = bufsize-1;
70 memcpy(d, s, len);
71 d[len] = 0;
72 return ret;
73}
74#endif
75
76#ifndef HAVE_STRLCAT
77/* like strncat but does not 0 fill the buffer and always null
78 terminates. bufsize is the length of the buffer, which should
79 be one more than the maximum resulting string length */
80size_t rep_strlcat(char *d, const char *s, size_t bufsize)
81{
82 size_t len1 = strlen(d);
83 size_t len2 = strlen(s);
84 size_t ret = len1 + len2;
85
86 if (len1+len2 >= bufsize) {
87 if (bufsize < (len1+1)) {
88 return ret;
89 }
90 len2 = bufsize - (len1+1);
91 }
92 if (len2 > 0) {
93 memcpy(d+len1, s, len2);
94 d[len1+len2] = 0;
95 }
96 return ret;
97}
98#endif
99
100#ifndef HAVE_MKTIME
101/*******************************************************************
102a mktime() replacement for those who don't have it - contributed by
103C.A. Lademann <cal@zls.com>
104Corrections by richard.kettlewell@kewill.com
105********************************************************************/
106
107#define MINUTE 60
108#define HOUR 60*MINUTE
109#define DAY 24*HOUR
110#define YEAR 365*DAY
111time_t rep_mktime(struct tm *t)
112{
113 struct tm *u;
114 time_t epoch = 0;
115 int n;
116 int mon [] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
117 y, m, i;
118
119 if(t->tm_year < 70)
120 return((time_t)-1);
121
122 n = t->tm_year + 1900 - 1;
123 epoch = (t->tm_year - 70) * YEAR +
124 ((n / 4 - n / 100 + n / 400) - (1969 / 4 - 1969 / 100 + 1969 / 400)) * DAY;
125
126 y = t->tm_year + 1900;
127 m = 0;
128
129 for(i = 0; i < t->tm_mon; i++) {
130 epoch += mon [m] * DAY;
131 if(m == 1 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0))
132 epoch += DAY;
133
134 if(++m > 11) {
135 m = 0;
136 y++;
137 }
138 }
139
140 epoch += (t->tm_mday - 1) * DAY;
141 epoch += t->tm_hour * HOUR + t->tm_min * MINUTE + t->tm_sec;
142
143 if((u = localtime(&epoch)) != NULL) {
144 t->tm_sec = u->tm_sec;
145 t->tm_min = u->tm_min;
146 t->tm_hour = u->tm_hour;
147 t->tm_mday = u->tm_mday;
148 t->tm_mon = u->tm_mon;
149 t->tm_year = u->tm_year;
150 t->tm_wday = u->tm_wday;
151 t->tm_yday = u->tm_yday;
152 t->tm_isdst = u->tm_isdst;
153 }
154
155 return(epoch);
156}
157#endif /* !HAVE_MKTIME */
158
159
160#ifndef HAVE_INITGROUPS
161/****************************************************************************
162 some systems don't have an initgroups call
163****************************************************************************/
164int rep_initgroups(char *name, gid_t id)
165{
166#ifndef HAVE_SETGROUPS
167 /* yikes! no SETGROUPS or INITGROUPS? how can this work? */
168 errno = ENOSYS;
169 return -1;
170#else /* HAVE_SETGROUPS */
171
172#include <grp.h>
173
174 gid_t *grouplst = NULL;
175 int max_gr = 32;
176 int ret;
177 int i,j;
178 struct group *g;
179 char *gr;
180
181 if((grouplst = malloc(sizeof(gid_t) * max_gr)) == NULL) {
182 errno = ENOMEM;
183 return -1;
184 }
185
186 grouplst[0] = id;
187 i = 1;
188 while (i < max_gr && ((g = (struct group *)getgrent()) != (struct group *)NULL)) {
189 if (g->gr_gid == id)
190 continue;
191 j = 0;
192 gr = g->gr_mem[0];
193 while (gr && (*gr != (char)NULL)) {
194 if (strcmp(name,gr) == 0) {
195 grouplst[i] = g->gr_gid;
196 i++;
197 gr = (char *)NULL;
198 break;
199 }
200 gr = g->gr_mem[++j];
201 }
202 }
203 endgrent();
204 ret = setgroups(i, grouplst);
205 free(grouplst);
206 return ret;
207#endif /* HAVE_SETGROUPS */
208}
209#endif /* HAVE_INITGROUPS */
210
211
212#if (defined(SecureWare) && defined(SCO))
213/* This is needed due to needing the nap() function but we don't want
214 to include the Xenix libraries since that will break other things...
215 BTW: system call # 0x0c28 is the same as calling nap() */
216long nap(long milliseconds) {
217 return syscall(0x0c28, milliseconds);
218 }
219#endif
220
221
222#ifndef HAVE_MEMMOVE
223/*******************************************************************
224safely copies memory, ensuring no overlap problems.
225this is only used if the machine does not have it's own memmove().
226this is not the fastest algorithm in town, but it will do for our
227needs.
228********************************************************************/
229void *rep_memmove(void *dest,const void *src,int size)
230{
231 unsigned long d,s;
232 int i;
233 if (dest==src || !size) return(dest);
234
235 d = (unsigned long)dest;
236 s = (unsigned long)src;
237
238 if ((d >= (s+size)) || (s >= (d+size))) {
239 /* no overlap */
240 memcpy(dest,src,size);
241 return(dest);
242 }
243
244 if (d < s) {
245 /* we can forward copy */
246 if (s-d >= sizeof(int) &&
247 !(s%sizeof(int)) &&
248 !(d%sizeof(int)) &&
249 !(size%sizeof(int))) {
250 /* do it all as words */
251 int *idest = (int *)dest;
252 int *isrc = (int *)src;
253 size /= sizeof(int);
254 for (i=0;i<size;i++) idest[i] = isrc[i];
255 } else {
256 /* simplest */
257 char *cdest = (char *)dest;
258 char *csrc = (char *)src;
259 for (i=0;i<size;i++) cdest[i] = csrc[i];
260 }
261 } else {
262 /* must backward copy */
263 if (d-s >= sizeof(int) &&
264 !(s%sizeof(int)) &&
265 !(d%sizeof(int)) &&
266 !(size%sizeof(int))) {
267 /* do it all as words */
268 int *idest = (int *)dest;
269 int *isrc = (int *)src;
270 size /= sizeof(int);
271 for (i=size-1;i>=0;i--) idest[i] = isrc[i];
272 } else {
273 /* simplest */
274 char *cdest = (char *)dest;
275 char *csrc = (char *)src;
276 for (i=size-1;i>=0;i--) cdest[i] = csrc[i];
277 }
278 }
279 return(dest);
280}
281#endif /* HAVE_MEMMOVE */
282
283#ifndef HAVE_STRDUP
284/****************************************************************************
285duplicate a string
286****************************************************************************/
287char *rep_strdup(const char *s)
288{
289 size_t len;
290 char *ret;
291
292 if (!s) return(NULL);
293
294 len = strlen(s)+1;
295 ret = (char *)malloc(len);
296 if (!ret) return(NULL);
297 memcpy(ret,s,len);
298 return(ret);
299}
300#endif /* HAVE_STRDUP */
301
302#ifndef WITH_PTHREADS
303/* REWRITE: not thread safe */
304#ifdef REPLACE_INET_NTOA
305char *rep_inet_ntoa(struct in_addr ip)
306{
307 uint8_t *p = (uint8_t *)&ip.s_addr;
308 static char buf[18];
309 slprintf(buf, 17, "%d.%d.%d.%d",
310 (int)p[0], (int)p[1], (int)p[2], (int)p[3]);
311 return buf;
312}
313#endif /* REPLACE_INET_NTOA */
314#endif
315
316#ifndef HAVE_SETLINEBUF
317void rep_setlinebuf(FILE *stream)
318{
319 setvbuf(stream, (char *)NULL, _IOLBF, 0);
320}
321#endif /* HAVE_SETLINEBUF */
322
323#ifndef HAVE_VSYSLOG
324#ifdef HAVE_SYSLOG
325void rep_vsyslog (int facility_priority, const char *format, va_list arglist)
326{
327 char *msg = NULL;
328 vasprintf(&msg, format, arglist);
329 if (!msg)
330 return;
331 syslog(facility_priority, "%s", msg);
332 free(msg);
333}
334#endif /* HAVE_SYSLOG */
335#endif /* HAVE_VSYSLOG */
336
337#ifndef HAVE_STRNLEN
338/**
339 Some platforms don't have strnlen
340**/
341 size_t rep_strnlen(const char *s, size_t max)
342{
343 size_t len;
344
345 for (len = 0; len < max; len++) {
346 if (s[len] == '\0') {
347 break;
348 }
349 }
350 return len;
351}
352#endif
353
354#ifndef HAVE_STRNDUP
355/**
356 Some platforms don't have strndup.
357**/
358char *rep_strndup(const char *s, size_t n)
359{
360 char *ret;
361
362 n = strnlen(s, n);
363 ret = malloc(n+1);
364 if (!ret)
365 return NULL;
366 memcpy(ret, s, n);
367 ret[n] = 0;
368
369 return ret;
370}
371#endif
372
373#ifndef HAVE_WAITPID
374int rep_waitpid(pid_t pid,int *status,int options)
375{
376 return wait4(pid, status, options, NULL);
377}
378#endif
379
380#ifndef HAVE_SETEUID
381int rep_seteuid(uid_t euid)
382{
383#ifdef HAVE_SETRESUID
384 return setresuid(-1, euid, -1);
385#else
386# error "You need a seteuid function"
387#endif
388}
389#endif
390
391#ifndef HAVE_SETEGID
392int rep_setegid(gid_t egid)
393{
394#ifdef HAVE_SETRESGID
395 return setresgid(-1, egid, -1);
396#else
397# error "You need a setegid function"
398#endif
399}
400#endif
401
402/*******************************************************************
403os/2 also doesn't have chroot
404********************************************************************/
405#ifndef HAVE_CHROOT
406int rep_chroot(const char *dname)
407{
408 errno = ENOSYS;
409 return -1;
410}
411#endif
412
413/*****************************************************************
414 Possibly replace mkstemp if it is broken.
415*****************************************************************/
416
417#ifndef HAVE_SECURE_MKSTEMP
418int rep_mkstemp(char *template)
419{
420 /* have a reasonable go at emulating it. Hope that
421 the system mktemp() isn't completly hopeless */
422 char *p = mktemp(template);
423 if (!p)
424 return -1;
425 return open(p, O_CREAT|O_EXCL|O_RDWR, 0600);
426}
427#endif
428
429#ifndef HAVE_MKDTEMP
430char *rep_mkdtemp(char *template)
431{
432 char *dname;
433
434 if ((dname = mktemp(template))) {
435 if (mkdir(dname, 0700) >= 0) {
436 return dname;
437 }
438 }
439
440 return NULL;
441}
442#endif
443
444#ifndef HAVE_PREAD
445ssize_t rep_pread(int __fd, void *__buf, size_t __nbytes, off_t __offset)
446{
447 if (lseek(__fd, __offset, SEEK_SET) != __offset) {
448 return -1;
449 }
450 return read(__fd, __buf, __nbytes);
451}
452#endif
453
454#ifndef HAVE_PWRITE
455ssize_t rep_pwrite(int __fd, const void *__buf, size_t __nbytes, off_t __offset)
456{
457 if (lseek(__fd, __offset, SEEK_SET) != __offset) {
458 return -1;
459 }
460 return write(__fd, __buf, __nbytes);
461}
462#endif
463
464#ifndef HAVE_STRCASESTR
465char *rep_strcasestr(const char *haystack, const char *needle)
466{
467 const char *s;
468 size_t nlen = strlen(needle);
469 for (s=haystack;*s;s++) {
470 if (toupper(*needle) == toupper(*s) &&
471 strncasecmp(s, needle, nlen) == 0) {
472 return (char *)((intptr_t)s);
473 }
474 }
475 return NULL;
476}
477#endif
478
479#ifndef HAVE_STRTOK_R
480/* based on GLIBC version, copyright Free Software Foundation */
481char *rep_strtok_r(char *s, const char *delim, char **save_ptr)
482{
483 char *token;
484
485 if (s == NULL) s = *save_ptr;
486
487 s += strspn(s, delim);
488 if (*s == '\0') {
489 *save_ptr = s;
490 return NULL;
491 }
492
493 token = s;
494 s = strpbrk(token, delim);
495 if (s == NULL) {
496 *save_ptr = token + strlen(token);
497 } else {
498 *s = '\0';
499 *save_ptr = s + 1;
500 }
501
502 return token;
503}
504#endif
505
506#ifndef HAVE_STRTOLL
507long long int rep_strtoll(const char *str, char **endptr, int base)
508{
509#ifdef HAVE_STRTOQ
510 return strtoq(str, endptr, base);
511#elif defined(HAVE___STRTOLL)
512 return __strtoll(str, endptr, base);
513#elif SIZEOF_LONG == SIZEOF_LONG_LONG
514 return (long long int) strtol(str, endptr, base);
515#else
516# error "You need a strtoll function"
517#endif
518}
519#endif
520
521
522#ifndef HAVE_STRTOULL
523unsigned long long int rep_strtoull(const char *str, char **endptr, int base)
524{
525#ifdef HAVE_STRTOUQ
526 return strtouq(str, endptr, base);
527#elif defined(HAVE___STRTOULL)
528 return __strtoull(str, endptr, base);
529#elif SIZEOF_LONG == SIZEOF_LONG_LONG
530 return (unsigned long long int) strtoul(str, endptr, base);
531#else
532# error "You need a strtoull function"
533#endif
534}
535#endif
536
537#ifndef HAVE_SETENV
538int rep_setenv(const char *name, const char *value, int overwrite)
539{
540 char *p;
541 size_t l1, l2;
542 int ret;
543
544 if (!overwrite && getenv(name)) {
545 return 0;
546 }
547
548 l1 = strlen(name);
549 l2 = strlen(value);
550
551 p = malloc(l1+l2+2);
552 if (p == NULL) {
553 return -1;
554 }
555 memcpy(p, name, l1);
556 p[l1] = '=';
557 memcpy(p+l1+1, value, l2);
558 p[l1+l2+1] = 0;
559
560 ret = putenv(p);
561 if (ret != 0) {
562 free(p);
563 }
564
565 return ret;
566}
567#endif
568
569#ifndef HAVE_UNSETENV
570int rep_unsetenv(const char *name)
571{
572 extern char **environ;
573 size_t len = strlen(name);
574 size_t i;
575 int found = 0;
576
577 for (i=0; (environ && environ[i]); i++) {
578 if (found) {
579 environ[i-1] = environ[i];
580 continue;
581 }
582
583 if (strncmp(environ[i], name, len) == 0 && environ[i][len] == '=') {
584 free(environ[i]);
585 environ[i] = NULL;
586 found = 1;
587 continue;
588 }
589 }
590
591 return 0;
592}
593#endif
594
595#ifndef HAVE_SOCKETPAIR
596int rep_socketpair(int d, int type, int protocol, int sv[2])
597{
598 if (d != AF_UNIX) {
599 errno = EAFNOSUPPORT;
600 return -1;
601 }
602
603 if (protocol != 0) {
604 errno = EPROTONOSUPPORT;
605 return -1;
606 }
607
608 if (type != SOCK_STREAM) {
609 errno = EOPNOTSUPP;
610 return -1;
611 }
612
613 return pipe(sv);
614}
615#endif
Note: See TracBrowser for help on using the repository browser.