backport from head
[Samba.git] / source3 / lib / replace.c
blobfe1cfc04eb11c2edd4487782277de60b117fd15a
1 /*
2 Unix SMB/CIFS implementation.
3 replacement routines for broken systems
4 Copyright (C) Andrew Tridgell 1992-1998
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.
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.
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.
21 #include "includes.h"
23 void replace_dummy(void);
24 void replace_dummy(void) {}
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)
32 struct flock fl;
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);
40 #endif /* HAVE_FTRUNCATE */
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)
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;
56 #endif
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)
64 size_t len1 = strlen(d);
65 size_t len2 = strlen(s);
66 size_t ret = len1 + len2;
68 if (len1 >= bufsize) {
69 return 0;
71 if (len1+len2 >= bufsize) {
72 len2 = bufsize - (len1+1);
74 if (len2 > 0) {
75 memcpy(d+len1, s, len2);
76 d[len1+len2] = 0;
78 return ret;
80 #endif
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 ********************************************************************/
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)
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;
101 if(t->tm_year < 70)
102 return((time_t)-1);
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;
108 y = t->tm_year + 1900;
109 m = 0;
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;
116 if(++m > 11) {
117 m = 0;
118 y++;
122 epoch += (t->tm_mday - 1) * DAY;
123 epoch += t->tm_hour * HOUR + t->tm_min * MINUTE + t->tm_sec;
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;
137 return(epoch);
139 #endif /* !HAVE_MKTIME */
143 #ifndef HAVE_RENAME
144 /* Rename a file. (from libiberty in GNU binutils) */
145 int rename(const char *zfrom, const char *zto)
147 if (link (zfrom, zto) < 0)
149 if (errno != EEXIST)
150 return -1;
151 if (unlink (zto) < 0
152 || link (zfrom, zto) < 0)
153 return -1;
155 return unlink (zfrom);
157 #endif /* HAVE_RENAME */
160 #ifndef HAVE_INNETGR
161 #if defined(HAVE_SETNETGRENT) && defined(HAVE_GETNETGRENT) && defined(HAVE_ENDNETGRENT)
163 * Search for a match in a netgroup. This replaces it on broken systems.
165 int innetgr(const char *group,const char *host,const char *user,const char *dom)
167 char *hst, *usr, *dm;
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);
178 endnetgrent();
179 return (0);
181 #endif /* HAVE_SETNETGRENT HAVE_GETNETGRENT HAVE_ENDNETGRENT */
182 #endif /* HAVE_INNETGR */
186 #ifndef HAVE_INITGROUPS
187 /****************************************************************************
188 some systems don't have an initgroups call
189 ****************************************************************************/
190 int initgroups(char *name,gid_t id)
192 #ifndef HAVE_SETGROUPS
193 static int done;
194 if (!done) {
195 DEBUG(1,("WARNING: running without setgroups\n"));
196 done=1;
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;
208 if((grouplst = (gid_t *)malloc(sizeof(gid_t) * max_gr)) == NULL) {
209 DEBUG(0,("initgroups: malloc fail !\n"));
210 return -1;
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;
227 gr = g->gr_mem[++j];
230 endgrent();
231 ret = sys_setgroups(i,grouplst);
232 SAFE_FREE(grouplst);
233 return ret;
234 #endif /* HAVE_SETGROUPS */
236 #endif /* HAVE_INITGROUPS */
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);
246 #endif
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)
258 unsigned long d,s;
259 int i;
260 if (dest==src || !size) return(dest);
262 d = (unsigned long)dest;
263 s = (unsigned long)src;
265 if ((d >= (s+size)) || (s >= (d+size))) {
266 /* no overlap */
267 memcpy(dest,src,size);
268 return(dest);
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];
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];
306 return(dest);
308 #endif /* HAVE_MEMMOVE */
310 #ifndef HAVE_STRDUP
311 /****************************************************************************
312 duplicate a string
313 ****************************************************************************/
314 char *strdup(const char *s)
316 size_t len;
317 char *ret;
319 if (!s) return(NULL);
321 len = strlen(s)+1;
322 ret = (char *)malloc(len);
323 if (!ret) return(NULL);
324 memcpy(ret,s,len);
325 return(ret);
327 #endif /* HAVE_STRDUP */
329 #ifdef REPLACE_INET_NTOA
330 char *rep_inet_ntoa(struct in_addr ip)
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;
338 #endif /* REPLACE_INET_NTOA */
340 #ifndef HAVE_STRTOUL
341 #ifndef ULONG_MAX
342 #define ULONG_MAX ((unsigned long)(~0L)) /* 0xFFFFFFFF */
343 #endif
346 * Convert a string to an unsigned long integer.
347 * Taken from libg++ - libiberty code.
349 * Ignores `locale' stuff. Assumes that the upper and lower case
350 * alphabets and digits are each contiguous.
352 unsigned long strtoul(const char *nptr, char **endptr, int base)
354 const char *s = nptr;
355 unsigned long acc;
356 int c;
357 unsigned long cutoff;
358 int neg = 0, any, cutlim;
361 * See strtol for comments as to the logic used.
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;
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;
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);
407 #endif /* HAVE_STRTOUL */
409 #ifndef HAVE_SETLINEBUF
410 int setlinebuf(FILE *stream)
412 return setvbuf(stream, (char *)NULL, _IOLBF, 0);
414 #endif /* HAVE_SETLINEBUF */
416 #ifndef HAVE_VSYSLOG
417 #ifdef HAVE_SYSLOG
418 void vsyslog (int facility_priority, char *format, va_list arglist)
420 char *msg = NULL;
421 vasprintf(&msg, format, arglist);
422 if (!msg)
423 return;
424 syslog(facility_priority, "%s", msg);
425 SAFE_FREE(msg);
427 #endif /* HAVE_SYSLOG */
428 #endif /* HAVE_VSYSLOG */
431 #ifndef HAVE_TIMEGM
433 yes, I know this looks insane, but its really needed. The function in the
434 Linux timegm() manpage does not work on solaris.
436 time_t timegm(struct tm *tm)
438 struct tm tm2, tm3;
439 time_t t;
441 tm2 = *tm;
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);
450 return t;
452 #endif