source: branches/samba-3.2.x/source/lib/replace/replace.c

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

Update trunk to v3.2.2

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