Spelling fixes for libreplace.
[ira/wip.git] / lib / replace / replace.c
1 /* 
2    Unix SMB/CIFS implementation.
3    replacement routines for broken systems
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Jelmer Vernooij 2005-2008
6
7      ** NOTE! The following LGPL license applies to the replace
8      ** library. This does NOT imply that all of Samba is released
9      ** under the LGPL
10    
11    This library is free software; you can redistribute it and/or
12    modify it under the terms of the GNU Lesser General Public
13    License as published by the Free Software Foundation; either
14    version 3 of the License, or (at your option) any later version.
15
16    This library is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19    Lesser General Public License for more details.
20
21    You should have received a copy of the GNU Lesser General Public
22    License along with this library; if not, see <http://www.gnu.org/licenses/>.
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/locale.h"
32 #include "system/wait.h"
33
34 #ifdef _WIN32
35 #define mkdir(d,m) _mkdir(d)
36 #endif
37
38 void replace_dummy(void);
39 void replace_dummy(void) {}
40
41 #ifndef HAVE_FTRUNCATE
42  /*******************************************************************
43 ftruncate for operating systems that don't have it
44 ********************************************************************/
45 int rep_ftruncate(int f, off_t l)
46 {
47 #ifdef HAVE_CHSIZE
48       return chsize(f,l);
49 #elif defined(F_FREESP)
50       struct  flock   fl;
51
52       fl.l_whence = 0;
53       fl.l_len = 0;
54       fl.l_start = l;
55       fl.l_type = F_WRLCK;
56       return fcntl(f, F_FREESP, &fl);
57 #else
58 #error "you must have a ftruncate function"
59 #endif
60 }
61 #endif /* HAVE_FTRUNCATE */
62
63
64 #ifndef HAVE_STRLCPY
65 /* like strncpy but does not 0 fill the buffer and always null 
66    terminates. bufsize is the size of the destination buffer */
67 size_t rep_strlcpy(char *d, const char *s, size_t bufsize)
68 {
69         size_t len = strlen(s);
70         size_t ret = len;
71         if (bufsize <= 0) return 0;
72         if (len >= bufsize) len = bufsize-1;
73         memcpy(d, s, len);
74         d[len] = 0;
75         return ret;
76 }
77 #endif
78
79 #ifndef HAVE_STRLCAT
80 /* like strncat but does not 0 fill the buffer and always null 
81    terminates. bufsize is the length of the buffer, which should
82    be one more than the maximum resulting string length */
83 size_t rep_strlcat(char *d, const char *s, size_t bufsize)
84 {
85         size_t len1 = strlen(d);
86         size_t len2 = strlen(s);
87         size_t ret = len1 + len2;
88
89         if (len1+len2 >= bufsize) {
90                 if (bufsize < (len1+1)) {
91                         return ret;
92                 }
93                 len2 = bufsize - (len1+1);
94         }
95         if (len2 > 0) {
96                 memcpy(d+len1, s, len2);
97                 d[len1+len2] = 0;
98         }
99         return ret;
100 }
101 #endif
102
103 #ifndef HAVE_MKTIME
104 /*******************************************************************
105 a mktime() replacement for those who don't have it - contributed by 
106 C.A. Lademann <cal@zls.com>
107 Corrections by richard.kettlewell@kewill.com
108 ********************************************************************/
109
110 #define  MINUTE  60
111 #define  HOUR    60*MINUTE
112 #define  DAY             24*HOUR
113 #define  YEAR    365*DAY
114 time_t rep_mktime(struct tm *t)
115 {
116   struct tm       *u;
117   time_t  epoch = 0;
118   int n;
119   int             mon [] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
120   y, m, i;
121
122   if(t->tm_year < 70)
123     return((time_t)-1);
124
125   n = t->tm_year + 1900 - 1;
126   epoch = (t->tm_year - 70) * YEAR + 
127     ((n / 4 - n / 100 + n / 400) - (1969 / 4 - 1969 / 100 + 1969 / 400)) * DAY;
128
129   y = t->tm_year + 1900;
130   m = 0;
131
132   for(i = 0; i < t->tm_mon; i++) {
133     epoch += mon [m] * DAY;
134     if(m == 1 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0))
135       epoch += DAY;
136     
137     if(++m > 11) {
138       m = 0;
139       y++;
140     }
141   }
142
143   epoch += (t->tm_mday - 1) * DAY;
144   epoch += t->tm_hour * HOUR + t->tm_min * MINUTE + t->tm_sec;
145   
146   if((u = localtime(&epoch)) != NULL) {
147     t->tm_sec = u->tm_sec;
148     t->tm_min = u->tm_min;
149     t->tm_hour = u->tm_hour;
150     t->tm_mday = u->tm_mday;
151     t->tm_mon = u->tm_mon;
152     t->tm_year = u->tm_year;
153     t->tm_wday = u->tm_wday;
154     t->tm_yday = u->tm_yday;
155     t->tm_isdst = u->tm_isdst;
156   }
157
158   return(epoch);
159 }
160 #endif /* !HAVE_MKTIME */
161
162
163 #ifndef HAVE_INITGROUPS
164 /****************************************************************************
165  some systems don't have an initgroups call 
166 ****************************************************************************/
167 int rep_initgroups(char *name, gid_t id)
168 {
169 #ifndef HAVE_SETGROUPS
170         /* yikes! no SETGROUPS or INITGROUPS? how can this work? */
171         errno = ENOSYS;
172         return -1;
173 #else /* HAVE_SETGROUPS */
174
175 #include <grp.h>
176
177         gid_t *grouplst = NULL;
178         int max_gr = NGROUPS_MAX;
179         int ret;
180         int    i,j;
181         struct group *g;
182         char   *gr;
183         
184         if((grouplst = malloc(sizeof(gid_t) * max_gr)) == NULL) {
185                 errno = ENOMEM;
186                 return -1;
187         }
188
189         grouplst[0] = id;
190         i = 1;
191         while (i < max_gr && ((g = (struct group *)getgrent()) != (struct group *)NULL)) {
192                 if (g->gr_gid == id)
193                         continue;
194                 j = 0;
195                 gr = g->gr_mem[0];
196                 while (gr && (*gr != (char)NULL)) {
197                         if (strcmp(name,gr) == 0) {
198                                 grouplst[i] = g->gr_gid;
199                                 i++;
200                                 gr = (char *)NULL;
201                                 break;
202                         }
203                         gr = g->gr_mem[++j];
204                 }
205         }
206         endgrent();
207         ret = setgroups(i, grouplst);
208         free(grouplst);
209         return ret;
210 #endif /* HAVE_SETGROUPS */
211 }
212 #endif /* HAVE_INITGROUPS */
213
214
215 #if (defined(SecureWare) && defined(SCO))
216 /* This is needed due to needing the nap() function but we don't want
217    to include the Xenix libraries since that will break other things...
218    BTW: system call # 0x0c28 is the same as calling nap() */
219 long nap(long milliseconds) {
220          return syscall(0x0c28, milliseconds);
221  }
222 #endif
223
224
225 #ifndef HAVE_MEMMOVE
226 /*******************************************************************
227 safely copies memory, ensuring no overlap problems.
228 this is only used if the machine does not have its own memmove().
229 this is not the fastest algorithm in town, but it will do for our
230 needs.
231 ********************************************************************/
232 void *rep_memmove(void *dest,const void *src,int size)
233 {
234         unsigned long d,s;
235         int i;
236         if (dest==src || !size) return(dest);
237
238         d = (unsigned long)dest;
239         s = (unsigned long)src;
240
241         if ((d >= (s+size)) || (s >= (d+size))) {
242                 /* no overlap */
243                 memcpy(dest,src,size);
244                 return(dest);
245         }
246
247         if (d < s) {
248                 /* we can forward copy */
249                 if (s-d >= sizeof(int) && 
250                     !(s%sizeof(int)) && 
251                     !(d%sizeof(int)) && 
252                     !(size%sizeof(int))) {
253                         /* do it all as words */
254                         int *idest = (int *)dest;
255                         int *isrc = (int *)src;
256                         size /= sizeof(int);
257                         for (i=0;i<size;i++) idest[i] = isrc[i];
258                 } else {
259                         /* simplest */
260                         char *cdest = (char *)dest;
261                         char *csrc = (char *)src;
262                         for (i=0;i<size;i++) cdest[i] = csrc[i];
263                 }
264         } else {
265                 /* must backward copy */
266                 if (d-s >= sizeof(int) && 
267                     !(s%sizeof(int)) && 
268                     !(d%sizeof(int)) && 
269                     !(size%sizeof(int))) {
270                         /* do it all as words */
271                         int *idest = (int *)dest;
272                         int *isrc = (int *)src;
273                         size /= sizeof(int);
274                         for (i=size-1;i>=0;i--) idest[i] = isrc[i];
275                 } else {
276                         /* simplest */
277                         char *cdest = (char *)dest;
278                         char *csrc = (char *)src;
279                         for (i=size-1;i>=0;i--) cdest[i] = csrc[i];
280                 }      
281         }
282         return(dest);
283 }
284 #endif /* HAVE_MEMMOVE */
285
286 #ifndef HAVE_STRDUP
287 /****************************************************************************
288 duplicate a string
289 ****************************************************************************/
290 char *rep_strdup(const char *s)
291 {
292         size_t len;
293         char *ret;
294
295         if (!s) return(NULL);
296
297         len = strlen(s)+1;
298         ret = (char *)malloc(len);
299         if (!ret) return(NULL);
300         memcpy(ret,s,len);
301         return(ret);
302 }
303 #endif /* HAVE_STRDUP */
304
305 #ifndef HAVE_SETLINEBUF
306 void rep_setlinebuf(FILE *stream)
307 {
308         setvbuf(stream, (char *)NULL, _IOLBF, 0);
309 }
310 #endif /* HAVE_SETLINEBUF */
311
312 #ifndef HAVE_VSYSLOG
313 #ifdef HAVE_SYSLOG
314 void rep_vsyslog (int facility_priority, const char *format, va_list arglist)
315 {
316         char *msg = NULL;
317         vasprintf(&msg, format, arglist);
318         if (!msg)
319                 return;
320         syslog(facility_priority, "%s", msg);
321         free(msg);
322 }
323 #endif /* HAVE_SYSLOG */
324 #endif /* HAVE_VSYSLOG */
325
326 #ifndef HAVE_STRNLEN
327 /**
328  Some platforms don't have strnlen
329 **/
330  size_t rep_strnlen(const char *s, size_t max)
331 {
332         size_t len;
333   
334         for (len = 0; len < max; len++) {
335                 if (s[len] == '\0') {
336                         break;
337                 }
338         }
339         return len;  
340 }
341 #endif
342   
343 #ifndef HAVE_STRNDUP
344 /**
345  Some platforms don't have strndup.
346 **/
347 char *rep_strndup(const char *s, size_t n)
348 {
349         char *ret;
350         
351         n = strnlen(s, n);
352         ret = malloc(n+1);
353         if (!ret)
354                 return NULL;
355         memcpy(ret, s, n);
356         ret[n] = 0;
357
358         return ret;
359 }
360 #endif
361
362 #if !defined(HAVE_WAITPID) && defined(HAVE_WAIT4)
363 int rep_waitpid(pid_t pid,int *status,int options)
364 {
365   return wait4(pid, status, options, NULL);
366 }
367 #endif
368
369 #ifndef HAVE_SETEUID
370 int rep_seteuid(uid_t euid)
371 {
372 #ifdef HAVE_SETRESUID
373         return setresuid(-1, euid, -1);
374 #else
375         errno = ENOSYS;
376         return -1;
377 #endif
378 }
379 #endif
380
381 #ifndef HAVE_SETEGID
382 int rep_setegid(gid_t egid)
383 {
384 #ifdef HAVE_SETRESGID
385         return setresgid(-1, egid, -1);
386 #else
387         errno = ENOSYS;
388         return -1;
389 #endif
390 }
391 #endif
392
393 /*******************************************************************
394 os/2 also doesn't have chroot
395 ********************************************************************/
396 #ifndef HAVE_CHROOT
397 int rep_chroot(const char *dname)
398 {
399         errno = ENOSYS;
400         return -1;
401 }
402 #endif
403
404 /*****************************************************************
405  Possibly replace mkstemp if it is broken.
406 *****************************************************************/  
407
408 #ifndef HAVE_SECURE_MKSTEMP
409 int rep_mkstemp(char *template)
410 {
411         /* have a reasonable go at emulating it. Hope that
412            the system mktemp() isn't completely hopeless */
413         char *p = mktemp(template);
414         if (!p)
415                 return -1;
416         return open(p, O_CREAT|O_EXCL|O_RDWR, 0600);
417 }
418 #endif
419
420 #ifndef HAVE_MKDTEMP
421 char *rep_mkdtemp(char *template)
422 {
423         char *dname;
424         
425         if ((dname = mktemp(template))) {
426                 if (mkdir(dname, 0700) >= 0) {
427                         return dname;
428                 }
429         }
430
431         return NULL;
432 }
433 #endif
434
435 /*****************************************************************
436  Watch out: this is not thread safe.
437 *****************************************************************/
438
439 #ifndef HAVE_PREAD
440 ssize_t rep_pread(int __fd, void *__buf, size_t __nbytes, off_t __offset)
441 {
442         if (lseek(__fd, __offset, SEEK_SET) != __offset) {
443                 return -1;
444         }
445         return read(__fd, __buf, __nbytes);
446 }
447 #endif
448
449 /*****************************************************************
450  Watch out: this is not thread safe.
451 *****************************************************************/
452
453 #ifndef HAVE_PWRITE
454 ssize_t rep_pwrite(int __fd, const void *__buf, size_t __nbytes, off_t __offset)
455 {
456         if (lseek(__fd, __offset, SEEK_SET) != __offset) {
457                 return -1;
458         }
459         return write(__fd, __buf, __nbytes);
460 }
461 #endif
462
463 #ifndef HAVE_STRCASESTR
464 char *rep_strcasestr(const char *haystack, const char *needle)
465 {
466         const char *s;
467         size_t nlen = strlen(needle);
468         for (s=haystack;*s;s++) {
469                 if (toupper(*needle) == toupper(*s) &&
470                     strncasecmp(s, needle, nlen) == 0) {
471                         return (char *)((uintptr_t)s);
472                 }
473         }
474         return NULL;
475 }
476 #endif
477
478 #ifndef HAVE_STRTOK_R
479 /* based on GLIBC version, copyright Free Software Foundation */
480 char *rep_strtok_r(char *s, const char *delim, char **save_ptr)
481 {
482         char *token;
483
484         if (s == NULL) s = *save_ptr;
485
486         s += strspn(s, delim);
487         if (*s == '\0') {
488                 *save_ptr = s;
489                 return NULL;
490         }
491
492         token = s;
493         s = strpbrk(token, delim);
494         if (s == NULL) {
495                 *save_ptr = token + strlen(token);
496         } else {
497                 *s = '\0';
498                 *save_ptr = s + 1;
499         }
500
501         return token;
502 }
503 #endif
504
505 #ifndef HAVE_STRTOLL
506 long long int rep_strtoll(const char *str, char **endptr, int base)
507 {
508 #ifdef HAVE_STRTOQ
509         return strtoq(str, endptr, base);
510 #elif defined(HAVE___STRTOLL) 
511         return __strtoll(str, endptr, base);
512 #elif SIZEOF_LONG == SIZEOF_LONG_LONG
513         return (long long int) strtol(str, endptr, base);
514 #else
515 # error "You need a strtoll function"
516 #endif
517 }
518 #endif
519
520
521 #ifndef HAVE_STRTOULL
522 unsigned long long int rep_strtoull(const char *str, char **endptr, int base)
523 {
524 #ifdef HAVE_STRTOUQ
525         return strtouq(str, endptr, base);
526 #elif defined(HAVE___STRTOULL) 
527         return __strtoull(str, endptr, base);
528 #elif SIZEOF_LONG == SIZEOF_LONG_LONG
529         return (unsigned long long int) strtoul(str, endptr, base);
530 #else
531 # error "You need a strtoull function"
532 #endif
533 }
534 #endif
535
536 #ifndef HAVE_SETENV
537 int rep_setenv(const char *name, const char *value, int overwrite) 
538 {
539         char *p;
540         size_t l1, l2;
541         int ret;
542
543         if (!overwrite && getenv(name)) {
544                 return 0;
545         }
546
547         l1 = strlen(name);
548         l2 = strlen(value);
549
550         p = malloc(l1+l2+2);
551         if (p == NULL) {
552                 return -1;
553         }
554         memcpy(p, name, l1);
555         p[l1] = '=';
556         memcpy(p+l1+1, value, l2);
557         p[l1+l2+1] = 0;
558
559         ret = putenv(p);
560         if (ret != 0) {
561                 free(p);
562         }
563
564         return ret;
565 }
566 #endif
567
568 #ifndef HAVE_UNSETENV
569 int rep_unsetenv(const char *name)
570 {
571         extern char **environ;
572         size_t len = strlen(name);
573         size_t i, count;
574
575         if (environ == NULL || getenv(name) == NULL) {
576                 return 0;
577         }
578
579         for (i=0;environ[i];i++) /* noop */ ;
580
581         count=i;
582         
583         for (i=0;i<count;) {
584                 if (strncmp(environ[i], name, len) == 0 && environ[i][len] == '=') {
585                         /* note: we do _not_ free the old variable here. It is unsafe to 
586                            do so, as the pointer may not have come from malloc */
587                         memmove(&environ[i], &environ[i+1], (count-i)*sizeof(char *));
588                         count--;
589                 } else {
590                         i++;
591                 }
592         }
593
594         return 0;
595 }
596 #endif
597
598 #ifndef HAVE_UTIME
599 int rep_utime(const char *filename, const struct utimbuf *buf)
600 {
601         errno = ENOSYS;
602         return -1;
603 }
604 #endif
605
606 #ifndef HAVE_UTIMES
607 int rep_utimes(const char *filename, const struct timeval tv[2])
608 {
609         struct utimbuf u;
610
611         u.actime = tv[0].tv_sec;
612         if (tv[0].tv_usec > 500000) {
613                 u.actime += 1;
614         }
615
616         u.modtime = tv[1].tv_sec;
617         if (tv[1].tv_usec > 500000) {
618                 u.modtime += 1;
619         }
620
621         return utime(filename, &u);
622 }
623 #endif
624
625 #ifndef HAVE_DUP2
626 int rep_dup2(int oldfd, int newfd) 
627 {
628         errno = ENOSYS;
629         return -1;
630 }
631 #endif
632
633 #ifndef HAVE_CHOWN
634 /**
635 chown isn't used much but OS/2 doesn't have it
636 **/
637 int rep_chown(const char *fname, uid_t uid, gid_t gid)
638 {
639         errno = ENOSYS;
640         return -1;
641 }
642 #endif
643
644 #ifndef HAVE_LINK
645 int rep_link(const char *oldpath, const char *newpath)
646 {
647         errno = ENOSYS;
648         return -1;
649 }
650 #endif
651
652 #ifndef HAVE_READLINK
653 int rep_readlink(const char *path, char *buf, size_t bufsiz)
654 {
655         errno = ENOSYS;
656         return -1;
657 }
658 #endif
659
660 #ifndef HAVE_SYMLINK
661 int rep_symlink(const char *oldpath, const char *newpath)
662 {
663         errno = ENOSYS;
664         return -1;
665 }
666 #endif
667
668 #ifndef HAVE_LCHOWN
669 int rep_lchown(const char *fname,uid_t uid,gid_t gid)
670 {
671         errno = ENOSYS;
672         return -1;
673 }
674 #endif
675
676 #ifndef HAVE_REALPATH
677 char *rep_realpath(const char *path, char *resolved_path)
678 {
679         /* As realpath is not a system call we can't return ENOSYS. */
680         errno = EINVAL;
681         return NULL;
682 }
683 #endif
684
685
686 #ifndef HAVE_MEMMEM
687 void *rep_memmem(const void *haystack, size_t haystacklen,
688                  const void *needle, size_t needlelen)
689 {
690         if (needlelen == 0) {
691                 return discard_const(haystack);
692         }
693         while (haystacklen >= needlelen) {
694                 char *p = (char *)memchr(haystack, *(const char *)needle,
695                                          haystacklen-(needlelen-1));
696                 if (!p) return NULL;
697                 if (memcmp(p, needle, needlelen) == 0) {
698                         return p;
699                 }
700                 haystack = p+1;
701                 haystacklen -= (p - (const char *)haystack) + 1;
702         }
703         return NULL;
704 }
705 #endif
706
707 #ifndef HAVE_VDPRINTF
708 int vdprintf(int fd, const char *format, va_list ap)
709 {
710         char *s = NULL;
711         int ret;
712
713         vasprintf(&s, format, ap);
714         if (s == NULL) {
715                 errno = ENOMEM;
716                 return -1;
717         }
718         ret = write(fd, s, strlen(s));
719         free(s);
720         return ret;
721 }
722 #endif
723
724 #ifndef HAVE_DPRINTF
725 int dprintf(int fd, const char *format, ...)
726 {
727         int ret;
728         va_list ap;
729
730         va_start(ap, format);
731         ret = vdprintf(fd, format, ap);
732         va_end(ap);
733
734         return ret;
735 }
736 #endif
737