import HEAD into svn+ssh://svn.samba.org/home/svn/samba/trunk
[metze/old/v3-2-winbind-ndr.git] / source / lib / replace.c
1 /* 
2    Unix SMB/CIFS implementation.
3    replacement routines for broken systems
4    Copyright (C) Andrew Tridgell 1992-1998
5    
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "includes.h"
22
23  void replace_dummy(void);
24  void replace_dummy(void) {}
25
26 #ifndef HAVE_FTRUNCATE
27  /*******************************************************************
28 ftruncate for operating systems that don't have it
29 ********************************************************************/
30  int ftruncate(int f,SMB_OFF_T l)
31 {
32       struct  flock   fl;
33
34       fl.l_whence = 0;
35       fl.l_len = 0;
36       fl.l_start = l;
37       fl.l_type = F_WRLCK;
38       return fcntl(f, F_FREESP, &fl);
39 }
40 #endif /* HAVE_FTRUNCATE */
41
42
43 #ifndef HAVE_STRLCPY
44 /* like strncpy but does not 0 fill the buffer and always null 
45    terminates. bufsize is the size of the destination buffer */
46  size_t strlcpy(char *d, const char *s, size_t bufsize)
47 {
48         size_t len = strlen(s);
49         size_t ret = len;
50         if (bufsize <= 0) return 0;
51         if (len >= bufsize) len = bufsize-1;
52         memcpy(d, s, len);
53         d[len] = 0;
54         return ret;
55 }
56 #endif
57
58 #ifndef HAVE_STRLCAT
59 /* like strncat but does not 0 fill the buffer and always null 
60    terminates. bufsize is the length of the buffer, which should
61    be one more than the maximum resulting string length */
62  size_t strlcat(char *d, const char *s, size_t bufsize)
63 {
64         size_t len1 = strlen(d);
65         size_t len2 = strlen(s);
66         size_t ret = len1 + len2;
67
68         if (len1 >= bufsize) {
69                 return 0;
70         }
71         if (len1+len2 >= bufsize) {
72                 len2 = bufsize - (len1+1);
73         }
74         if (len2 > 0) {
75                 memcpy(d+len1, s, len2);
76                 d[len1+len2] = 0;
77         }
78         return ret;
79 }
80 #endif
81
82 #ifndef HAVE_MKTIME
83 /*******************************************************************
84 a mktime() replacement for those who don't have it - contributed by 
85 C.A. Lademann <cal@zls.com>
86 Corrections by richard.kettlewell@kewill.com
87 ********************************************************************/
88
89 #define  MINUTE  60
90 #define  HOUR    60*MINUTE
91 #define  DAY             24*HOUR
92 #define  YEAR    365*DAY
93  time_t mktime(struct tm *t)
94 {
95   struct tm       *u;
96   time_t  epoch = 0;
97   int n;
98   int             mon [] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
99   y, m, i;
100
101   if(t->tm_year < 70)
102     return((time_t)-1);
103
104   n = t->tm_year + 1900 - 1;
105   epoch = (t->tm_year - 70) * YEAR + 
106     ((n / 4 - n / 100 + n / 400) - (1969 / 4 - 1969 / 100 + 1969 / 400)) * DAY;
107
108   y = t->tm_year + 1900;
109   m = 0;
110
111   for(i = 0; i < t->tm_mon; i++) {
112     epoch += mon [m] * DAY;
113     if(m == 1 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0))
114       epoch += DAY;
115     
116     if(++m > 11) {
117       m = 0;
118       y++;
119     }
120   }
121
122   epoch += (t->tm_mday - 1) * DAY;
123   epoch += t->tm_hour * HOUR + t->tm_min * MINUTE + t->tm_sec;
124   
125   if((u = localtime(&epoch)) != NULL) {
126     t->tm_sec = u->tm_sec;
127     t->tm_min = u->tm_min;
128     t->tm_hour = u->tm_hour;
129     t->tm_mday = u->tm_mday;
130     t->tm_mon = u->tm_mon;
131     t->tm_year = u->tm_year;
132     t->tm_wday = u->tm_wday;
133     t->tm_yday = u->tm_yday;
134     t->tm_isdst = u->tm_isdst;
135   }
136
137   return(epoch);
138 }
139 #endif /* !HAVE_MKTIME */
140
141
142
143 #ifndef HAVE_RENAME
144 /* Rename a file. (from libiberty in GNU binutils)  */
145  int rename(const char *zfrom, const char *zto)
146 {
147   if (link (zfrom, zto) < 0)
148     {
149       if (errno != EEXIST)
150         return -1;
151       if (unlink (zto) < 0
152           || link (zfrom, zto) < 0)
153         return -1;
154     }
155   return unlink (zfrom);
156 }
157 #endif /* HAVE_RENAME */
158
159
160 #ifndef HAVE_INNETGR
161 #if defined(HAVE_SETNETGRENT) && defined(HAVE_GETNETGRENT) && defined(HAVE_ENDNETGRENT)
162 /*
163  * Search for a match in a netgroup. This replaces it on broken systems.
164  */
165  int innetgr(const char *group,const char *host,const char *user,const char *dom)
166 {
167         char *hst, *usr, *dm;
168   
169         setnetgrent(group);
170         while (getnetgrent(&hst, &usr, &dm)) {
171                 if (((host == 0) || (hst == 0) || !strcmp(host, hst)) &&
172                     ((user == 0) || (usr == 0) || !strcmp(user, usr)) &&
173                     ((dom == 0) || (dm == 0) || !strcmp(dom, dm))) {
174                         endnetgrent();
175                         return (1);
176                 }
177         }
178         endnetgrent();
179         return (0);
180 }
181 #endif /* HAVE_SETNETGRENT HAVE_GETNETGRENT HAVE_ENDNETGRENT */
182 #endif /* HAVE_INNETGR */
183
184
185
186 #ifndef HAVE_INITGROUPS
187 /****************************************************************************
188  some systems don't have an initgroups call 
189 ****************************************************************************/
190  int initgroups(char *name,gid_t id)
191 {
192 #ifndef HAVE_SETGROUPS
193         static int done;
194         if (!done) {
195                 DEBUG(1,("WARNING: running without setgroups\n"));
196                 done=1;
197         }
198         /* yikes! no SETGROUPS or INITGROUPS? how can this work? */
199         return(0);
200 #else /* HAVE_SETGROUPS */
201         gid_t *grouplst = NULL;
202         int max_gr = groups_max();
203         int ret;
204         int    i,j;
205         struct group *g;
206         char   *gr;
207         
208         if((grouplst = (gid_t *)malloc(sizeof(gid_t) * max_gr)) == NULL) {
209                 DEBUG(0,("initgroups: malloc fail !\n"));
210                 return -1;
211         }
212
213         grouplst[0] = id;
214         i = 1;
215         while (i < max_gr && ((g = (struct group *)getgrent()) != (struct group *)NULL)) {
216                 if (g->gr_gid == id)
217                         continue;
218                 j = 0;
219                 gr = g->gr_mem[0];
220                 while (gr && (*gr != (char)NULL)) {
221                         if (strcmp(name,gr) == 0) {
222                                 grouplst[i] = g->gr_gid;
223                                 i++;
224                                 gr = (char *)NULL;
225                                 break;
226                         }
227                         gr = g->gr_mem[++j];
228                 }
229         }
230         endgrent();
231         ret = sys_setgroups(i,grouplst);
232         SAFE_FREE(grouplst);
233         return ret;
234 #endif /* HAVE_SETGROUPS */
235 }
236 #endif /* HAVE_INITGROUPS */
237
238
239 #if (defined(SecureWare) && defined(SCO))
240 /* This is needed due to needing the nap() function but we don't want
241    to include the Xenix libraries since that will break other things...
242    BTW: system call # 0x0c28 is the same as calling nap() */
243  long nap(long milliseconds) {
244          return syscall(0x0c28, milliseconds);
245  }
246 #endif
247
248
249 #ifndef HAVE_MEMMOVE
250 /*******************************************************************
251 safely copies memory, ensuring no overlap problems.
252 this is only used if the machine does not have it's own memmove().
253 this is not the fastest algorithm in town, but it will do for our
254 needs.
255 ********************************************************************/
256  void *memmove(void *dest,const void *src,int size)
257 {
258         unsigned long d,s;
259         int i;
260         if (dest==src || !size) return(dest);
261
262         d = (unsigned long)dest;
263         s = (unsigned long)src;
264
265         if ((d >= (s+size)) || (s >= (d+size))) {
266                 /* no overlap */
267                 memcpy(dest,src,size);
268                 return(dest);
269         }
270
271         if (d < s) {
272                 /* we can forward copy */
273                 if (s-d >= sizeof(int) && 
274                     !(s%sizeof(int)) && 
275                     !(d%sizeof(int)) && 
276                     !(size%sizeof(int))) {
277                         /* do it all as words */
278                         int *idest = (int *)dest;
279                         int *isrc = (int *)src;
280                         size /= sizeof(int);
281                         for (i=0;i<size;i++) idest[i] = isrc[i];
282                 } else {
283                         /* simplest */
284                         char *cdest = (char *)dest;
285                         char *csrc = (char *)src;
286                         for (i=0;i<size;i++) cdest[i] = csrc[i];
287                 }
288         } else {
289                 /* must backward copy */
290                 if (d-s >= sizeof(int) && 
291                     !(s%sizeof(int)) && 
292                     !(d%sizeof(int)) && 
293                     !(size%sizeof(int))) {
294                         /* do it all as words */
295                         int *idest = (int *)dest;
296                         int *isrc = (int *)src;
297                         size /= sizeof(int);
298                         for (i=size-1;i>=0;i--) idest[i] = isrc[i];
299                 } else {
300                         /* simplest */
301                         char *cdest = (char *)dest;
302                         char *csrc = (char *)src;
303                         for (i=size-1;i>=0;i--) cdest[i] = csrc[i];
304                 }      
305         }
306         return(dest);
307 }
308 #endif /* HAVE_MEMMOVE */
309
310 #ifndef HAVE_STRDUP
311 /****************************************************************************
312 duplicate a string
313 ****************************************************************************/
314  char *strdup(const char *s)
315 {
316         size_t len;
317         char *ret;
318
319         if (!s) return(NULL);
320
321         len = strlen(s)+1;
322         ret = (char *)malloc(len);
323         if (!ret) return(NULL);
324         memcpy(ret,s,len);
325         return(ret);
326 }
327 #endif /* HAVE_STRDUP */
328
329 #ifdef REPLACE_INET_NTOA
330 char *rep_inet_ntoa(struct in_addr ip)
331 {
332         unsigned char *p = (unsigned char *)&ip.s_addr;
333         static char buf[18];
334         slprintf(buf, 17, "%d.%d.%d.%d", 
335                  (int)p[0], (int)p[1], (int)p[2], (int)p[3]);
336         return buf;
337 }
338 #endif /* REPLACE_INET_NTOA */
339
340 #ifndef HAVE_STRTOUL
341 #ifndef ULONG_MAX
342 #define ULONG_MAX       ((unsigned long)(~0L))          /* 0xFFFFFFFF */
343 #endif
344
345 /*
346  * Convert a string to an unsigned long integer.
347  * Taken from libg++ - libiberty code.
348  *
349  * Ignores `locale' stuff.  Assumes that the upper and lower case
350  * alphabets and digits are each contiguous.
351  */
352  unsigned long strtoul(const char *nptr, char **endptr, int base)
353 {
354         const char *s = nptr;
355         unsigned long acc;
356         int c;
357         unsigned long cutoff;
358         int neg = 0, any, cutlim;
359
360         /*
361          * See strtol for comments as to the logic used.
362          */
363         do {
364                 c = *s++;
365         } while (isspace(c));
366         if (c == '-') {
367                 neg = 1;
368                 c = *s++;
369         } else if (c == '+')
370                 c = *s++;
371         if ((base == 0 || base == 16) &&
372             c == '0' && (*s == 'x' || *s == 'X')) {
373                 c = s[1];
374                 s += 2;
375                 base = 16;
376         }
377         if (base == 0)
378                 base = c == '0' ? 8 : 10;
379         cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
380         cutlim = (int)((unsigned long)ULONG_MAX % (unsigned long)base);
381         for (acc = 0, any = 0;; c = *s++) {
382                 if (isdigit(c))
383                         c -= '0';
384                 else if (isalpha(c))
385                         c -= isupper(c) ? 'A' - 10 : 'a' - 10;
386                 else
387                         break;
388                 if (c >= base)
389                         break;
390                 if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
391                         any = -1;
392                 else {
393                         any = 1;
394                         acc *= base;
395                         acc += c;
396                 }
397         }
398         if (any < 0) {
399                 acc = ULONG_MAX;
400                 errno = ERANGE;
401         } else if (neg)
402                 acc = -acc;
403         if (endptr != 0)
404                 *endptr = (char *) (any ? s - 1 : nptr);
405         return (acc);
406 }
407 #endif /* HAVE_STRTOUL */
408
409 #ifndef HAVE_SETLINEBUF
410  int setlinebuf(FILE *stream)
411 {
412         return setvbuf(stream, (char *)NULL, _IOLBF, 0);
413 }
414 #endif /* HAVE_SETLINEBUF */
415
416 #ifndef HAVE_VSYSLOG
417 #ifdef HAVE_SYSLOG
418  void vsyslog (int facility_priority, char *format, va_list arglist)
419 {
420         char *msg = NULL;
421         vasprintf(&msg, format, arglist);
422         if (!msg)
423                 return;
424         syslog(facility_priority, "%s", msg);
425         SAFE_FREE(msg);
426 }
427 #endif /* HAVE_SYSLOG */
428 #endif /* HAVE_VSYSLOG */
429
430
431 #ifndef HAVE_TIMEGM
432 /*
433   yes, I know this looks insane, but its really needed. The function in the 
434   Linux timegm() manpage does not work on solaris.
435 */
436  time_t timegm(struct tm *tm) 
437 {
438         struct tm tm2, tm3;
439         time_t t;
440
441         tm2 = *tm;
442
443         t = mktime(&tm2);
444         tm3 = *localtime(&t);
445         tm2 = *tm;
446         tm2.tm_isdst = tm3.tm_isdst;
447         t = mktime(&tm2);
448         t -= TimeDiff(t);
449
450         return t;
451 }
452 #endif