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.
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
)
41 return fcntl(f
, F_FREESP
, &fl
);
44 #endif /* HAVE_FTRUNCATE */
47 /* like strncpy but does not 0 fill the buffer and always null
48 terminates. bufsize is the size of the destination buffer */
49 size_t strlcpy(char *d
, const char *s
, size_t bufsize
)
51 size_t len
= strlen(s
);
53 if (bufsize
<= 0) return 0;
54 if (len
>= bufsize
) len
= bufsize
-1;
62 /* like strncat but does not 0 fill the buffer and always null
63 terminates. bufsize is the length of the buffer, which should
64 be one more than the maximum resulting string length */
65 size_t strlcat(char *d
, const char *s
, size_t bufsize
)
67 size_t len1
= strlen(d
);
68 size_t len2
= strlen(s
);
69 size_t ret
= len1
+ len2
;
71 if (len1
>= bufsize
) {
74 if (len1
+len2
>= bufsize
) {
75 len2
= bufsize
- (len1
+1);
78 memcpy(d
+len1
, s
, len2
);
86 /*******************************************************************
87 a mktime() replacement for those who don't have it - contributed by
88 C.A. Lademann <cal@zls.com>
89 Corrections by richard.kettlewell@kewill.com
90 ********************************************************************/
93 #define HOUR 60*MINUTE
96 time_t mktime(struct tm
*t
)
101 int mon
[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
107 n
= t
->tm_year
+ 1900 - 1;
108 epoch
= (t
->tm_year
- 70) * YEAR
+
109 ((n
/ 4 - n
/ 100 + n
/ 400) - (1969 / 4 - 1969 / 100 + 1969 / 400)) * DAY
;
111 y
= t
->tm_year
+ 1900;
114 for(i
= 0; i
< t
->tm_mon
; i
++) {
115 epoch
+= mon
[m
] * DAY
;
116 if(m
== 1 && y
% 4 == 0 && (y
% 100 != 0 || y
% 400 == 0))
125 epoch
+= (t
->tm_mday
- 1) * DAY
;
126 epoch
+= t
->tm_hour
* HOUR
+ t
->tm_min
* MINUTE
+ t
->tm_sec
;
128 if((u
= localtime(&epoch
)) != NULL
) {
129 t
->tm_sec
= u
->tm_sec
;
130 t
->tm_min
= u
->tm_min
;
131 t
->tm_hour
= u
->tm_hour
;
132 t
->tm_mday
= u
->tm_mday
;
133 t
->tm_mon
= u
->tm_mon
;
134 t
->tm_year
= u
->tm_year
;
135 t
->tm_wday
= u
->tm_wday
;
136 t
->tm_yday
= u
->tm_yday
;
137 t
->tm_isdst
= u
->tm_isdst
;
142 #endif /* !HAVE_MKTIME */
147 /* Rename a file. (from libiberty in GNU binutils) */
148 int rename(const char *zfrom
, const char *zto
)
150 if (link (zfrom
, zto
) < 0)
155 || link (zfrom
, zto
) < 0)
158 return unlink (zfrom
);
160 #endif /* HAVE_RENAME */
164 #if defined(HAVE_SETNETGRENT) && defined(HAVE_GETNETGRENT) && defined(HAVE_ENDNETGRENT)
166 * Search for a match in a netgroup. This replaces it on broken systems.
168 int innetgr(const char *group
,const char *host
,const char *user
,const char *dom
)
170 char *hst
, *usr
, *dm
;
173 while (getnetgrent(&hst
, &usr
, &dm
)) {
174 if (((host
== 0) || (hst
== 0) || !strcmp(host
, hst
)) &&
175 ((user
== 0) || (usr
== 0) || !strcmp(user
, usr
)) &&
176 ((dom
== 0) || (dm
== 0) || !strcmp(dom
, dm
))) {
184 #endif /* HAVE_SETNETGRENT HAVE_GETNETGRENT HAVE_ENDNETGRENT */
185 #endif /* HAVE_INNETGR */
189 #ifndef HAVE_INITGROUPS
190 /****************************************************************************
191 some systems don't have an initgroups call
192 ****************************************************************************/
193 int initgroups(char *name
,gid_t id
)
195 #ifndef HAVE_SETGROUPS
198 DEBUG(1,("WARNING: running without setgroups\n"));
201 /* yikes! no SETGROUPS or INITGROUPS? how can this work? */
203 #else /* HAVE_SETGROUPS */
204 gid_t
*grouplst
= NULL
;
205 int max_gr
= groups_max();
211 if((grouplst
= SMB_MALLOC_ARRAY(gid_t
, max_gr
)) == NULL
) {
212 DEBUG(0,("initgroups: malloc fail !\n"));
218 while (i
< max_gr
&& ((g
= (struct group
*)getgrent()) != (struct group
*)NULL
)) {
223 while (gr
&& (*gr
!= (char)NULL
)) {
224 if (strcmp(name
,gr
) == 0) {
225 grouplst
[i
] = g
->gr_gid
;
234 ret
= sys_setgroups(i
,grouplst
);
237 #endif /* HAVE_SETGROUPS */
239 #endif /* HAVE_INITGROUPS */
242 #if (defined(SecureWare) && defined(SCO))
243 /* This is needed due to needing the nap() function but we don't want
244 to include the Xenix libraries since that will break other things...
245 BTW: system call # 0x0c28 is the same as calling nap() */
246 long nap(long milliseconds
) {
247 return syscall(0x0c28, milliseconds
);
253 /*******************************************************************
254 safely copies memory, ensuring no overlap problems.
255 this is only used if the machine does not have it's own memmove().
256 this is not the fastest algorithm in town, but it will do for our
258 ********************************************************************/
259 void *memmove(void *dest
,const void *src
,int size
)
263 if (dest
==src
|| !size
) return(dest
);
265 d
= (unsigned long)dest
;
266 s
= (unsigned long)src
;
268 if ((d
>= (s
+size
)) || (s
>= (d
+size
))) {
270 memcpy(dest
,src
,size
);
275 /* we can forward copy */
276 if (s
-d
>= sizeof(int) &&
279 !(size
%sizeof(int))) {
280 /* do it all as words */
281 int *idest
= (int *)dest
;
282 int *isrc
= (int *)src
;
284 for (i
=0;i
<size
;i
++) idest
[i
] = isrc
[i
];
287 char *cdest
= (char *)dest
;
288 char *csrc
= (char *)src
;
289 for (i
=0;i
<size
;i
++) cdest
[i
] = csrc
[i
];
292 /* must backward copy */
293 if (d
-s
>= sizeof(int) &&
296 !(size
%sizeof(int))) {
297 /* do it all as words */
298 int *idest
= (int *)dest
;
299 int *isrc
= (int *)src
;
301 for (i
=size
-1;i
>=0;i
--) idest
[i
] = isrc
[i
];
304 char *cdest
= (char *)dest
;
305 char *csrc
= (char *)src
;
306 for (i
=size
-1;i
>=0;i
--) cdest
[i
] = csrc
[i
];
311 #endif /* HAVE_MEMMOVE */
314 /****************************************************************************
316 ****************************************************************************/
322 char *strdup(const char *s
)
327 if (!s
) return(NULL
);
330 ret
= (char *)SMB_MALLOC(len
);
331 if (!ret
) return(NULL
);
335 #endif /* HAVE_STRDUP */
337 #ifdef REPLACE_INET_NTOA
338 char *rep_inet_ntoa(struct in_addr ip
)
340 unsigned char *p
= (unsigned char *)&ip
.s_addr
;
342 slprintf(buf
, 17, "%d.%d.%d.%d",
343 (int)p
[0], (int)p
[1], (int)p
[2], (int)p
[3]);
346 #endif /* REPLACE_INET_NTOA */
350 #define ULONG_MAX ((unsigned long)(~0L)) /* 0xFFFFFFFF */
354 * Convert a string to an unsigned long integer.
355 * Taken from libg++ - libiberty code.
357 * Ignores `locale' stuff. Assumes that the upper and lower case
358 * alphabets and digits are each contiguous.
360 unsigned long strtoul(const char *nptr
, char **endptr
, int base
)
362 const char *s
= nptr
;
365 unsigned long cutoff
;
366 int neg
= 0, any
, cutlim
;
369 * See strtol for comments as to the logic used.
373 } while (isspace(c
));
379 if ((base
== 0 || base
== 16) &&
380 c
== '0' && (*s
== 'x' || *s
== 'X')) {
386 base
= c
== '0' ? 8 : 10;
387 cutoff
= (unsigned long)ULONG_MAX
/ (unsigned long)base
;
388 cutlim
= (int)((unsigned long)ULONG_MAX
% (unsigned long)base
);
389 for (acc
= 0, any
= 0;; c
= *s
++) {
393 c
-= isupper_ascii(c
) ? 'A' - 10 : 'a' - 10;
398 if (any
< 0 || acc
> cutoff
|| acc
== cutoff
&& c
> cutlim
)
412 *endptr
= (char *) (any
? s
- 1 : nptr
);
415 #endif /* HAVE_STRTOUL */
417 #ifndef HAVE_SETLINEBUF
418 int setlinebuf(FILE *stream
)
420 return setvbuf(stream
, (char *)NULL
, _IOLBF
, 0);
422 #endif /* HAVE_SETLINEBUF */
426 void vsyslog (int facility_priority
, const char *format
, va_list arglist
)
429 vasprintf(&msg
, format
, arglist
);
432 syslog(facility_priority
, "%s", msg
);
435 #endif /* HAVE_SYSLOG */
436 #endif /* HAVE_VSYSLOG */
441 yes, I know this looks insane, but its really needed. The function in the
442 Linux timegm() manpage does not work on solaris.
444 time_t timegm(struct tm
*tm
)
452 tm3
= *localtime(&t
);
454 tm2
.tm_isdst
= tm3
.tm_isdst
;
456 t
-= get_time_zone(t
);