Fix from richard.kettlewell@kewill.com for leapyear bugs.
[ira/wip.git] / source3 / 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
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;
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
123
124
125 #ifndef HAVE_INNETGR
126 /*
127  * Search for a match in a netgroup. This replaces it on broken systems.
128  */
129  int innetgr(char *group,char *host,char *user,char *dom)
130 {
131         char *hst, *usr, *dm;
132   
133         setnetgrent(group);
134         while (getnetgrent(&hst, &usr, &dm)) {
135                 if (((host == 0) || (hst == 0) || !strcmp(host, hst)) &&
136                     ((user == 0) || (usr == 0) || !strcmp(user, usr)) &&
137                     ((dom == 0) || (dm == 0) || !strcmp(dom, dm))) {
138                         endnetgrent();
139                         return (1);
140                 }
141         }
142         endnetgrent();
143         return (0);
144 }
145 #endif
146
147
148
149 #ifndef HAVE_INITGROUPS
150 /****************************************************************************
151  some systems don't have an initgroups call 
152 ****************************************************************************/
153  int initgroups(char *name,gid_t id)
154 {
155 #ifndef HAVE_SETGROUPS
156         static int done;
157         if (!done) {
158                 DEBUG(1,("WARNING: running without setgroups\n"));
159                 done=1;
160         }
161         /* yikes! no SETGROUPS or INITGROUPS? how can this work? */
162         return(0);
163 #else
164         gid_t  grouplst[NGROUPS_MAX];
165         int    i,j;
166         struct group *g;
167         char   *gr;
168         
169         grouplst[0] = id;
170         i = 1;
171         while (i < NGROUPS_MAX && 
172                ((g = (struct group *)getgrent()) != (struct group *)NULL)) {
173                 if (g->gr_gid == id)
174                         continue;
175                 j = 0;
176                 gr = g->gr_mem[0];
177                 while (gr && (*gr != (char)NULL)) {
178                         if (strcmp(name,gr) == 0) {
179                                 grouplst[i] = g->gr_gid;
180                                 i++;
181                                 gr = (char *)NULL;
182                                 break;
183                         }
184                         gr = g->gr_mem[++j];
185                 }
186         }
187         endgrent();
188         return(setgroups(i,grouplst));
189 #endif
190 }
191 #endif
192
193
194 #if (defined(SecureWare) && defined(SCO))
195 /* This is needed due to needing the nap() function but we don't want
196    to include the Xenix libraries since that will break other things...
197    BTW: system call # 0x0c28 is the same as calling nap() */
198  long nap(long milliseconds) {
199          return syscall(0x0c28, milliseconds);
200  }
201 #endif
202
203
204 #ifndef HAVE_MEMMOVE
205 /*******************************************************************
206 safely copies memory, ensuring no overlap problems.
207 this is only used if the machine does not have it's own memmove().
208 this is not the fastest algorithm in town, but it will do for our
209 needs.
210 ********************************************************************/
211  void *memmove(void *dest,const void *src,int size)
212 {
213         unsigned long d,s;
214         int i;
215         if (dest==src || !size) return(dest);
216
217         d = (unsigned long)dest;
218         s = (unsigned long)src;
219
220         if ((d >= (s+size)) || (s >= (d+size))) {
221                 /* no overlap */
222                 memcpy(dest,src,size);
223                 return(dest);
224         }
225
226         if (d < s) {
227                 /* we can forward copy */
228                 if (s-d >= sizeof(int) && 
229                     !(s%sizeof(int)) && 
230                     !(d%sizeof(int)) && 
231                     !(size%sizeof(int))) {
232                         /* do it all as words */
233                         int *idest = (int *)dest;
234                         int *isrc = (int *)src;
235                         size /= sizeof(int);
236                         for (i=0;i<size;i++) idest[i] = isrc[i];
237                 } else {
238                         /* simplest */
239                         char *cdest = (char *)dest;
240                         char *csrc = (char *)src;
241                         for (i=0;i<size;i++) cdest[i] = csrc[i];
242                 }
243         } else {
244                 /* must backward copy */
245                 if (d-s >= sizeof(int) && 
246                     !(s%sizeof(int)) && 
247                     !(d%sizeof(int)) && 
248                     !(size%sizeof(int))) {
249                         /* do it all as words */
250                         int *idest = (int *)dest;
251                         int *isrc = (int *)src;
252                         size /= sizeof(int);
253                         for (i=size-1;i>=0;i--) idest[i] = isrc[i];
254                 } else {
255                         /* simplest */
256                         char *cdest = (char *)dest;
257                         char *csrc = (char *)src;
258                         for (i=size-1;i>=0;i--) cdest[i] = csrc[i];
259                 }      
260         }
261         return(dest);
262 }
263 #endif
264
265 #ifndef HAVE_STRDUP
266 /****************************************************************************
267 duplicate a string
268 ****************************************************************************/
269  char *strdup(const char *s)
270 {
271         int len;
272         char *ret;
273
274         if (!s) return(NULL);
275
276         len = strlen(s)+1;
277         ret = (char *)malloc(len);
278         if (!ret) return(NULL);
279         memcpy(ret,s,len);
280         return(ret);
281 }
282 #endif
283
284 #ifdef REPLACE_INET_NTOA
285 char *rep_inet_ntoa(struct in_addr ip)
286 {
287         unsigned char *p = (unsigned char *)&ip.s_addr;
288         static char buf[18];
289 #if WORDS_BIGENDIAN
290         slprintf(buf, 17, "%d.%d.%d.%d", 
291                  (int)p[0], (int)p[1], (int)p[2], (int)p[3]);
292 #else
293         slprintf(buf, 17, "%d.%d.%d.%d", 
294                  (int)p[3], (int)p[2], (int)p[1], (int)p[0]);
295 #endif
296         return buf;
297 }
298 #endif
299