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