• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/router/samba-3.0.25b/source/lib/
1/*
2   Unix SMB/CIFS implementation.
3   Samba system utilities
4   Copyright (C) Andrew Tridgell 1992-1998
5   Copyright (C) Jeremy Allison  1998-2005
6   Copyright (C) Timur Bakeyev        2005
7
8   This program is free software; you can redistribute it and/or modify
9   it under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 2 of the License, or
11   (at your option) any later version.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program; if not, write to the Free Software
20   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21*/
22
23#include "includes.h"
24
25#ifdef HAVE_SYS_PRCTL_H
26#include <sys/prctl.h>
27#endif
28
29/*
30   The idea is that this file will eventually have wrappers around all
31   important system calls in samba. The aims are:
32
33   - to enable easier porting by putting OS dependent stuff in here
34
35   - to allow for hooks into other "pseudo-filesystems"
36
37   - to allow easier integration of things like the japanese extensions
38
39   - to support the philosophy of Samba to expose the features of
40     the OS within the SMB model. In general whatever file/printer/variable
41     expansions/etc make sense to the OS should be acceptable to Samba.
42*/
43
44
45
46/*******************************************************************
47 A wrapper for memalign
48********************************************************************/
49
50void *sys_memalign( size_t align, size_t size )
51{
52#if defined(HAVE_POSIX_MEMALIGN)
53	void *p = NULL;
54	int ret = posix_memalign( &p, align, size );
55	if ( ret == 0 )
56		return p;
57
58	return NULL;
59#elif defined(HAVE_MEMALIGN)
60	return memalign( align, size );
61#else
62	/* On *BSD systems memaligns doesn't exist, but memory will
63	 * be aligned on allocations of > pagesize. */
64#if defined(SYSCONF_SC_PAGESIZE)
65	size_t pagesize = (size_t)sysconf(_SC_PAGESIZE);
66#elif defined(HAVE_GETPAGESIZE)
67	size_t pagesize = (size_t)getpagesize();
68#else
69	size_t pagesize = (size_t)-1;
70#endif
71	if (pagesize == (size_t)-1) {
72		DEBUG(0,("memalign functionalaity not available on this platform!\n"));
73		return NULL;
74	}
75	if (size < pagesize) {
76		size = pagesize;
77	}
78	return SMB_MALLOC(size);
79#endif
80}
81
82/*******************************************************************
83 A wrapper for usleep in case we don't have one.
84********************************************************************/
85
86int sys_usleep(long usecs)
87{
88#ifndef HAVE_USLEEP
89	struct timeval tval;
90#endif
91
92	/*
93	 * We need this braindamage as the glibc usleep
94	 * is not SPEC1170 complient... grumble... JRA.
95	 */
96
97	if(usecs < 0 || usecs > 1000000) {
98		errno = EINVAL;
99		return -1;
100	}
101
102#if HAVE_USLEEP
103	usleep(usecs);
104	return 0;
105#else /* HAVE_USLEEP */
106	/*
107	 * Fake it with select...
108	 */
109	tval.tv_sec = 0;
110	tval.tv_usec = usecs/1000;
111	select(0,NULL,NULL,NULL,&tval);
112	return 0;
113#endif /* HAVE_USLEEP */
114}
115
116/*******************************************************************
117A read wrapper that will deal with EINTR.
118********************************************************************/
119
120ssize_t sys_read(int fd, void *buf, size_t count)
121{
122	ssize_t ret;
123
124	do {
125		ret = read(fd, buf, count);
126	} while (ret == -1 && errno == EINTR);
127	return ret;
128}
129
130/*******************************************************************
131A write wrapper that will deal with EINTR.
132********************************************************************/
133
134ssize_t sys_write(int fd, const void *buf, size_t count)
135{
136	ssize_t ret;
137
138	do {
139		ret = write(fd, buf, count);
140	} while (ret == -1 && errno == EINTR);
141	return ret;
142}
143
144/*******************************************************************
145A pread wrapper that will deal with EINTR and 64-bit file offsets.
146********************************************************************/
147
148#if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
149ssize_t sys_pread(int fd, void *buf, size_t count, SMB_OFF_T off)
150{
151	ssize_t ret;
152
153	do {
154#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_PREAD64)
155		ret = pread64(fd, buf, count, off);
156#else
157		ret = pread(fd, buf, count, off);
158#endif
159	} while (ret == -1 && errno == EINTR);
160	return ret;
161}
162#endif
163
164/*******************************************************************
165A write wrapper that will deal with EINTR and 64-bit file offsets.
166********************************************************************/
167
168#if defined(HAVE_PWRITE) || defined(HAVE_PWRITE64)
169ssize_t sys_pwrite(int fd, const void *buf, size_t count, SMB_OFF_T off)
170{
171	ssize_t ret;
172
173	do {
174#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_PWRITE64)
175		ret = pwrite64(fd, buf, count, off);
176#else
177		ret = pwrite(fd, buf, count, off);
178#endif
179	} while (ret == -1 && errno == EINTR);
180	return ret;
181}
182#endif
183
184/*******************************************************************
185A send wrapper that will deal with EINTR.
186********************************************************************/
187
188ssize_t sys_send(int s, const void *msg, size_t len, int flags)
189{
190	ssize_t ret;
191
192	do {
193		ret = send(s, msg, len, flags);
194	} while (ret == -1 && errno == EINTR);
195	return ret;
196}
197
198/*******************************************************************
199A sendto wrapper that will deal with EINTR.
200********************************************************************/
201
202ssize_t sys_sendto(int s,  const void *msg, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
203{
204	ssize_t ret;
205
206	do {
207		ret = sendto(s, msg, len, flags, to, tolen);
208	} while (ret == -1 && errno == EINTR);
209	return ret;
210}
211
212/*******************************************************************
213A recv wrapper that will deal with EINTR.
214********************************************************************/
215
216ssize_t sys_recv(int fd, void *buf, size_t count, int flags)
217{
218	ssize_t ret;
219
220	do {
221		ret = recv(fd, buf, count, flags);
222	} while (ret == -1 && errno == EINTR);
223	return ret;
224}
225
226/*******************************************************************
227A recvfrom wrapper that will deal with EINTR.
228********************************************************************/
229
230ssize_t sys_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
231{
232	ssize_t ret;
233
234	do {
235		ret = recvfrom(s, buf, len, flags, from, fromlen);
236	} while (ret == -1 && errno == EINTR);
237	return ret;
238}
239
240/*******************************************************************
241A fcntl wrapper that will deal with EINTR.
242********************************************************************/
243
244int sys_fcntl_ptr(int fd, int cmd, void *arg)
245{
246	int ret;
247
248	do {
249		ret = fcntl(fd, cmd, arg);
250	} while (ret == -1 && errno == EINTR);
251	return ret;
252}
253
254/*******************************************************************
255A fcntl wrapper that will deal with EINTR.
256********************************************************************/
257
258int sys_fcntl_long(int fd, int cmd, long arg)
259{
260	int ret;
261
262	do {
263		ret = fcntl(fd, cmd, arg);
264	} while (ret == -1 && errno == EINTR);
265	return ret;
266}
267
268/*******************************************************************
269A stat() wrapper that will deal with 64 bit filesizes.
270********************************************************************/
271
272int sys_stat(const char *fname,SMB_STRUCT_STAT *sbuf)
273{
274	int ret;
275#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
276	ret = stat64(fname, sbuf);
277#else
278	ret = stat(fname, sbuf);
279#endif
280	/* we always want directories to appear zero size */
281	if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
282	return ret;
283}
284
285/*******************************************************************
286 An fstat() wrapper that will deal with 64 bit filesizes.
287********************************************************************/
288
289int sys_fstat(int fd,SMB_STRUCT_STAT *sbuf)
290{
291	int ret;
292#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FSTAT64)
293	ret = fstat64(fd, sbuf);
294#else
295	ret = fstat(fd, sbuf);
296#endif
297	/* we always want directories to appear zero size */
298	if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
299	return ret;
300}
301
302/*******************************************************************
303 An lstat() wrapper that will deal with 64 bit filesizes.
304********************************************************************/
305
306int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf)
307{
308	int ret;
309#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSTAT64)
310	ret = lstat64(fname, sbuf);
311#else
312	ret = lstat(fname, sbuf);
313#endif
314	/* we always want directories to appear zero size */
315	if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
316	return ret;
317}
318
319/*******************************************************************
320 An ftruncate() wrapper that will deal with 64 bit filesizes.
321********************************************************************/
322
323int sys_ftruncate(int fd, SMB_OFF_T offset)
324{
325#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FTRUNCATE64)
326	return ftruncate64(fd, offset);
327#else
328	return ftruncate(fd, offset);
329#endif
330}
331
332/*******************************************************************
333 An lseek() wrapper that will deal with 64 bit filesizes.
334********************************************************************/
335
336SMB_OFF_T sys_lseek(int fd, SMB_OFF_T offset, int whence)
337{
338#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSEEK64)
339	return lseek64(fd, offset, whence);
340#else
341	return lseek(fd, offset, whence);
342#endif
343}
344
345/*******************************************************************
346 An fseek() wrapper that will deal with 64 bit filesizes.
347********************************************************************/
348
349int sys_fseek(FILE *fp, SMB_OFF_T offset, int whence)
350{
351#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEK64)
352	return fseek64(fp, offset, whence);
353#elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEKO64)
354	return fseeko64(fp, offset, whence);
355#else
356	return fseek(fp, offset, whence);
357#endif
358}
359
360/*******************************************************************
361 An ftell() wrapper that will deal with 64 bit filesizes.
362********************************************************************/
363
364SMB_OFF_T sys_ftell(FILE *fp)
365{
366#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELL64)
367	return (SMB_OFF_T)ftell64(fp);
368#elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELLO64)
369	return (SMB_OFF_T)ftello64(fp);
370#else
371	return (SMB_OFF_T)ftell(fp);
372#endif
373}
374
375/*******************************************************************
376 A creat() wrapper that will deal with 64 bit filesizes.
377********************************************************************/
378
379int sys_creat(const char *path, mode_t mode)
380{
381#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CREAT64)
382	return creat64(path, mode);
383#else
384	/*
385	 * If creat64 isn't defined then ensure we call a potential open64.
386	 * JRA.
387	 */
388	return sys_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
389#endif
390}
391
392/*******************************************************************
393 An open() wrapper that will deal with 64 bit filesizes.
394********************************************************************/
395
396int sys_open(const char *path, int oflag, mode_t mode)
397{
398#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPEN64)
399	return open64(path, oflag, mode);
400#else
401	return open(path, oflag, mode);
402#endif
403}
404
405/*******************************************************************
406 An fopen() wrapper that will deal with 64 bit filesizes.
407********************************************************************/
408
409FILE *sys_fopen(const char *path, const char *type)
410{
411#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FOPEN64)
412	return fopen64(path, type);
413#else
414	return fopen(path, type);
415#endif
416}
417
418
419/*******************************************************************
420 A flock() wrapper that will perform the kernel flock.
421********************************************************************/
422
423void kernel_flock(int fd, uint32 share_mode)
424{
425#if HAVE_KERNEL_SHARE_MODES
426	int kernel_mode = 0;
427	if (share_mode == FILE_SHARE_WRITE) {
428		kernel_mode = LOCK_MAND|LOCK_WRITE;
429	} else if (share_mode == FILE_SHARE_READ) {
430		kernel_mode = LOCK_MAND|LOCK_READ;
431	} else if (share_mode == FILE_SHARE_NONE) {
432		kernel_mode = LOCK_MAND;
433	}
434	if (kernel_mode) {
435		flock(fd, kernel_mode);
436	}
437#endif
438	;
439}
440
441
442
443/*******************************************************************
444 An opendir wrapper that will deal with 64 bit filesizes.
445********************************************************************/
446
447SMB_STRUCT_DIR *sys_opendir(const char *name)
448{
449#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPENDIR64)
450	return opendir64(name);
451#else
452	return opendir(name);
453#endif
454}
455
456/*******************************************************************
457 A readdir wrapper that will deal with 64 bit filesizes.
458********************************************************************/
459
460SMB_STRUCT_DIRENT *sys_readdir(SMB_STRUCT_DIR *dirp)
461{
462#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_READDIR64)
463	return readdir64(dirp);
464#else
465	return readdir(dirp);
466#endif
467}
468
469/*******************************************************************
470 A seekdir wrapper that will deal with 64 bit filesizes.
471********************************************************************/
472
473void sys_seekdir(SMB_STRUCT_DIR *dirp, long offset)
474{
475#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_SEEKDIR64)
476	seekdir64(dirp, offset);
477#else
478	seekdir(dirp, offset);
479#endif
480}
481
482/*******************************************************************
483 A telldir wrapper that will deal with 64 bit filesizes.
484********************************************************************/
485
486long sys_telldir(SMB_STRUCT_DIR *dirp)
487{
488#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_TELLDIR64)
489	return (long)telldir64(dirp);
490#else
491	return (long)telldir(dirp);
492#endif
493}
494
495/*******************************************************************
496 A rewinddir wrapper that will deal with 64 bit filesizes.
497********************************************************************/
498
499void sys_rewinddir(SMB_STRUCT_DIR *dirp)
500{
501#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_REWINDDIR64)
502	rewinddir64(dirp);
503#else
504	rewinddir(dirp);
505#endif
506}
507
508/*******************************************************************
509 A close wrapper that will deal with 64 bit filesizes.
510********************************************************************/
511
512int sys_closedir(SMB_STRUCT_DIR *dirp)
513{
514#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CLOSEDIR64)
515	return closedir64(dirp);
516#else
517	return closedir(dirp);
518#endif
519}
520
521/*******************************************************************
522 An mknod() wrapper that will deal with 64 bit filesizes.
523********************************************************************/
524
525int sys_mknod(const char *path, mode_t mode, SMB_DEV_T dev)
526{
527#if defined(HAVE_MKNOD) || defined(HAVE_MKNOD64)
528#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_MKNOD64) && defined(HAVE_DEV64_T)
529	return mknod64(path, mode, dev);
530#else
531	return mknod(path, mode, dev);
532#endif
533#else
534	/* No mknod system call. */
535	errno = ENOSYS;
536	return -1;
537#endif
538}
539
540/*******************************************************************
541 Wrapper for realpath.
542********************************************************************/
543
544char *sys_realpath(const char *path, char *resolved_path)
545{
546#if defined(HAVE_REALPATH)
547	return realpath(path, resolved_path);
548#else
549	/* As realpath is not a system call we can't return ENOSYS. */
550	errno = EINVAL;
551	return NULL;
552#endif
553}
554
555/*******************************************************************
556The wait() calls vary between systems
557********************************************************************/
558
559int sys_waitpid(pid_t pid,int *status,int options)
560{
561#ifdef HAVE_WAITPID
562	return waitpid(pid,status,options);
563#else /* HAVE_WAITPID */
564	return wait4(pid, status, options, NULL);
565#endif /* HAVE_WAITPID */
566}
567
568/*******************************************************************
569 System wrapper for getwd
570********************************************************************/
571
572char *sys_getwd(char *s)
573{
574	char *wd;
575#ifdef HAVE_GETCWD
576	wd = (char *)getcwd(s, sizeof (pstring));
577#else
578	wd = (char *)getwd(s);
579#endif
580	return wd;
581}
582
583/*******************************************************************
584system wrapper for symlink
585********************************************************************/
586
587int sys_symlink(const char *oldpath, const char *newpath)
588{
589#ifndef HAVE_SYMLINK
590	errno = ENOSYS;
591	return -1;
592#else
593	return symlink(oldpath, newpath);
594#endif
595}
596
597/*******************************************************************
598system wrapper for readlink
599********************************************************************/
600
601int sys_readlink(const char *path, char *buf, size_t bufsiz)
602{
603#ifndef HAVE_READLINK
604	errno = ENOSYS;
605	return -1;
606#else
607	return readlink(path, buf, bufsiz);
608#endif
609}
610
611/*******************************************************************
612system wrapper for link
613********************************************************************/
614
615int sys_link(const char *oldpath, const char *newpath)
616{
617#ifndef HAVE_LINK
618	errno = ENOSYS;
619	return -1;
620#else
621	return link(oldpath, newpath);
622#endif
623}
624
625/*******************************************************************
626chown isn't used much but OS/2 doesn't have it
627********************************************************************/
628
629int sys_chown(const char *fname,uid_t uid,gid_t gid)
630{
631#ifndef HAVE_CHOWN
632	static int done;
633	if (!done) {
634		DEBUG(1,("WARNING: no chown!\n"));
635		done=1;
636	}
637	errno = ENOSYS;
638	return -1;
639#else
640	return(chown(fname,uid,gid));
641#endif
642}
643
644/*******************************************************************
645os/2 also doesn't have chroot
646********************************************************************/
647int sys_chroot(const char *dname)
648{
649#ifndef HAVE_CHROOT
650	static int done;
651	if (!done) {
652		DEBUG(1,("WARNING: no chroot!\n"));
653		done=1;
654	}
655	errno = ENOSYS;
656	return -1;
657#else
658	return(chroot(dname));
659#endif
660}
661
662/**************************************************************************
663A wrapper for gethostbyname() that tries avoids looking up hostnames
664in the root domain, which can cause dial-on-demand links to come up for no
665apparent reason.
666****************************************************************************/
667
668struct hostent *sys_gethostbyname(const char *name)
669{
670#ifdef REDUCE_ROOT_DNS_LOOKUPS
671	char query[256], hostname[256];
672	char *domain;
673
674	/* Does this name have any dots in it? If so, make no change */
675
676	if (strchr_m(name, '.'))
677		return(gethostbyname(name));
678
679	/* Get my hostname, which should have domain name
680		attached. If not, just do the gethostname on the
681		original string.
682	*/
683
684	gethostname(hostname, sizeof(hostname) - 1);
685	hostname[sizeof(hostname) - 1] = 0;
686	if ((domain = strchr_m(hostname, '.')) == NULL)
687		return(gethostbyname(name));
688
689	/* Attach domain name to query and do modified query.
690		If names too large, just do gethostname on the
691		original string.
692	*/
693
694	if((strlen(name) + strlen(domain)) >= sizeof(query))
695		return(gethostbyname(name));
696
697	slprintf(query, sizeof(query)-1, "%s%s", name, domain);
698	return(gethostbyname(query));
699#else /* REDUCE_ROOT_DNS_LOOKUPS */
700	return(gethostbyname(name));
701#endif /* REDUCE_ROOT_DNS_LOOKUPS */
702}
703
704
705#if defined(HAVE_POSIX_CAPABILITIES)
706
707#ifdef HAVE_SYS_CAPABILITY_H
708
709#if defined(BROKEN_REDHAT_7_SYSTEM_HEADERS) && !defined(_I386_STATFS_H) && !defined(_PPC_STATFS_H)
710#define _I386_STATFS_H
711#define _PPC_STATFS_H
712#define BROKEN_REDHAT_7_STATFS_WORKAROUND
713#endif
714
715#include <sys/capability.h>
716
717#ifdef BROKEN_REDHAT_7_STATFS_WORKAROUND
718#undef _I386_STATFS_H
719#undef _PPC_STATFS_H
720#undef BROKEN_REDHAT_7_STATFS_WORKAROUND
721#endif
722
723#endif /* HAVE_SYS_CAPABILITY_H */
724
725/**************************************************************************
726 Try and abstract process capabilities (for systems that have them).
727****************************************************************************/
728
729/* Set the POSIX capabilities needed for the given purpose into the effective
730 * capability set of the current process. Make sure they are always removed
731 * from the inheritable set, because there is no circumstance in which our
732 * children should inherit our elevated privileges.
733 */
734static BOOL set_process_capability(enum smbd_capability capability,
735				   BOOL	enable)
736{
737	cap_value_t cap_vals[2] = {0};
738	int num_cap_vals = 0;
739
740	cap_t cap;
741
742#if defined(HAVE_PRCTL) && defined(PR_GET_KEEPCAPS) && defined(PR_SET_KEEPCAPS)
743	/* On Linux, make sure that any capabilities we grab are sticky
744	 * across UID changes. We expect that this would allow us to keep both
745	 * the effective and permitted capability sets, but as of circa 2.6.16,
746	 * only the permitted set is kept. It is a bug (which we work around)
747	 * that the effective set is lost, but we still require the effective
748	 * set to be kept.
749	 */
750	if (!prctl(PR_GET_KEEPCAPS)) {
751		prctl(PR_SET_KEEPCAPS, 1);
752	}
753#endif
754
755	cap = cap_get_proc();
756	if (cap == NULL) {
757		DEBUG(0,("set_process_capability: cap_get_proc failed: %s\n",
758			strerror(errno)));
759		return False;
760	}
761
762	switch (capability) {
763		case KERNEL_OPLOCK_CAPABILITY:
764#ifdef CAP_NETWORK_MGT
765			/* IRIX has CAP_NETWORK_MGT for oplocks. */
766			cap_vals[num_cap_vals++] = CAP_NETWORK_MGT;
767#endif
768			break;
769		case DMAPI_ACCESS_CAPABILITY:
770#ifdef CAP_DEVICE_MGT
771			/* IRIX has CAP_DEVICE_MGT for DMAPI access. */
772			cap_vals[num_cap_vals++] = CAP_DEVICE_MGT;
773#elif CAP_MKNOD
774			/* Linux has CAP_MKNOD for DMAPI access. */
775			cap_vals[num_cap_vals++] = CAP_MKNOD;
776#endif
777			break;
778	}
779
780	SMB_ASSERT(num_cap_vals <= ARRAY_SIZE(cap_vals));
781
782	if (num_cap_vals == 0) {
783		cap_free(cap);
784		return True;
785	}
786
787	cap_set_flag(cap, CAP_EFFECTIVE, num_cap_vals, cap_vals,
788		enable ? CAP_SET : CAP_CLEAR);
789
790	/* We never want to pass capabilities down to our children, so make
791	 * sure they are not inherited.
792	 */
793	cap_set_flag(cap, CAP_INHERITABLE, num_cap_vals, cap_vals, CAP_CLEAR);
794
795	if (cap_set_proc(cap) == -1) {
796		DEBUG(0, ("set_process_capability: cap_set_proc failed: %s\n",
797			strerror(errno)));
798		cap_free(cap);
799		return False;
800	}
801
802	cap_free(cap);
803	return True;
804}
805
806#endif /* HAVE_POSIX_CAPABILITIES */
807
808/****************************************************************************
809 Gain the oplock capability from the kernel if possible.
810****************************************************************************/
811
812void set_effective_capability(enum smbd_capability capability)
813{
814#if defined(HAVE_POSIX_CAPABILITIES)
815	set_process_capability(capability, True);
816#endif /* HAVE_POSIX_CAPABILITIES */
817}
818
819void drop_effective_capability(enum smbd_capability capability)
820{
821#if defined(HAVE_POSIX_CAPABILITIES)
822	set_process_capability(capability, False);
823#endif /* HAVE_POSIX_CAPABILITIES */
824}
825
826/**************************************************************************
827 Wrapper for random().
828****************************************************************************/
829
830long sys_random(void)
831{
832#if defined(HAVE_RANDOM)
833	return (long)random();
834#elif defined(HAVE_RAND)
835	return (long)rand();
836#else
837	DEBUG(0,("Error - no random function available !\n"));
838	exit(1);
839#endif
840}
841
842/**************************************************************************
843 Wrapper for srandom().
844****************************************************************************/
845
846void sys_srandom(unsigned int seed)
847{
848#if defined(HAVE_SRANDOM)
849	srandom(seed);
850#elif defined(HAVE_SRAND)
851	srand(seed);
852#else
853	DEBUG(0,("Error - no srandom function available !\n"));
854	exit(1);
855#endif
856}
857
858/**************************************************************************
859 Returns equivalent to NGROUPS_MAX - using sysconf if needed.
860****************************************************************************/
861
862int groups_max(void)
863{
864#if defined(SYSCONF_SC_NGROUPS_MAX)
865	int ret = sysconf(_SC_NGROUPS_MAX);
866	return (ret == -1) ? NGROUPS_MAX : ret;
867#else
868	return NGROUPS_MAX;
869#endif
870}
871
872/**************************************************************************
873 Wrapper for getgroups. Deals with broken (int) case.
874****************************************************************************/
875
876int sys_getgroups(int setlen, gid_t *gidset)
877{
878#if !defined(HAVE_BROKEN_GETGROUPS)
879	return getgroups(setlen, gidset);
880#else
881
882	GID_T gid;
883	GID_T *group_list;
884	int i, ngroups;
885
886	if(setlen == 0) {
887		return getgroups(setlen, &gid);
888	}
889
890	/*
891	 * Broken case. We need to allocate a
892	 * GID_T array of size setlen.
893	 */
894
895	if(setlen < 0) {
896		errno = EINVAL;
897		return -1;
898	}
899
900	if (setlen == 0)
901		setlen = groups_max();
902
903	if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
904		DEBUG(0,("sys_getgroups: Malloc fail.\n"));
905		return -1;
906	}
907
908	if((ngroups = getgroups(setlen, group_list)) < 0) {
909		int saved_errno = errno;
910		SAFE_FREE(group_list);
911		errno = saved_errno;
912		return -1;
913	}
914
915	for(i = 0; i < ngroups; i++)
916		gidset[i] = (gid_t)group_list[i];
917
918	SAFE_FREE(group_list);
919	return ngroups;
920#endif /* HAVE_BROKEN_GETGROUPS */
921}
922
923
924/**************************************************************************
925 Wrapper for setgroups. Deals with broken (int) case. Automatically used
926 if we have broken getgroups.
927****************************************************************************/
928
929int sys_setgroups(int setlen, gid_t *gidset)
930{
931#if !defined(HAVE_SETGROUPS)
932	errno = ENOSYS;
933	return -1;
934#endif /* HAVE_SETGROUPS */
935
936#if !defined(HAVE_BROKEN_GETGROUPS)
937	return setgroups(setlen, gidset);
938#else
939
940	GID_T *group_list;
941	int i ;
942
943	if (setlen == 0)
944		return 0 ;
945
946	if (setlen < 0 || setlen > groups_max()) {
947		errno = EINVAL;
948		return -1;
949	}
950
951	/*
952	 * Broken case. We need to allocate a
953	 * GID_T array of size setlen.
954	 */
955
956	if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
957		DEBUG(0,("sys_setgroups: Malloc fail.\n"));
958		return -1;
959	}
960
961	for(i = 0; i < setlen; i++)
962		group_list[i] = (GID_T) gidset[i];
963
964	if(setgroups(setlen, group_list) != 0) {
965		int saved_errno = errno;
966		SAFE_FREE(group_list);
967		errno = saved_errno;
968		return -1;
969	}
970
971	SAFE_FREE(group_list);
972	return 0 ;
973#endif /* HAVE_BROKEN_GETGROUPS */
974}
975
976/**************************************************************************
977 Wrappers for setpwent(), getpwent() and endpwent()
978****************************************************************************/
979
980void sys_setpwent(void)
981{
982	setpwent();
983}
984
985struct passwd *sys_getpwent(void)
986{
987	return getpwent();
988}
989
990void sys_endpwent(void)
991{
992	endpwent();
993}
994
995/**************************************************************************
996 Wrappers for getpwnam(), getpwuid(), getgrnam(), getgrgid()
997****************************************************************************/
998
999#ifdef ENABLE_BUILD_FARM_HACKS
1000
1001/*
1002 * In the build farm we want to be able to join machines to the domain. As we
1003 * don't have root access, we need to bypass direct access to /etc/passwd
1004 * after a user has been created via samr. Fake those users.
1005 */
1006
1007static struct passwd *fake_pwd;
1008static int num_fake_pwd;
1009
1010struct passwd *sys_getpwnam(const char *name)
1011{
1012	int i;
1013
1014	for (i=0; i<num_fake_pwd; i++) {
1015		if (strcmp(fake_pwd[i].pw_name, name) == 0) {
1016			DEBUG(10, ("Returning fake user %s\n", name));
1017			return &fake_pwd[i];
1018		}
1019	}
1020
1021	return getpwnam(name);
1022}
1023
1024struct passwd *sys_getpwuid(uid_t uid)
1025{
1026	int i;
1027
1028	for (i=0; i<num_fake_pwd; i++) {
1029		if (fake_pwd[i].pw_uid == uid) {
1030			DEBUG(10, ("Returning fake user %s\n",
1031				   fake_pwd[i].pw_name));
1032			return &fake_pwd[i];
1033		}
1034	}
1035
1036	return getpwuid(uid);
1037}
1038
1039void faked_create_user(const char *name)
1040{
1041	int i;
1042	uid_t uid;
1043	struct passwd new_pwd;
1044
1045	for (i=0; i<10; i++) {
1046		generate_random_buffer((unsigned char *)&uid,
1047				       sizeof(uid));
1048		if (getpwuid(uid) == NULL) {
1049			break;
1050		}
1051	}
1052
1053	if (i==10) {
1054		/* Weird. No free uid found... */
1055		return;
1056	}
1057
1058	new_pwd.pw_name = SMB_STRDUP(name);
1059	new_pwd.pw_passwd = SMB_STRDUP("x");
1060	new_pwd.pw_uid = uid;
1061	new_pwd.pw_gid = 100;
1062	new_pwd.pw_gecos = SMB_STRDUP("faked user");
1063	new_pwd.pw_dir = SMB_STRDUP("/nodir");
1064	new_pwd.pw_shell = SMB_STRDUP("/bin/false");
1065
1066	ADD_TO_ARRAY(NULL, struct passwd, new_pwd, &fake_pwd,
1067		     &num_fake_pwd);
1068
1069	DEBUG(10, ("Added fake user %s, have %d fake users\n",
1070		   name, num_fake_pwd));
1071}
1072
1073#else
1074
1075struct passwd *sys_getpwnam(const char *name)
1076{
1077	return getpwnam(name);
1078}
1079
1080struct passwd *sys_getpwuid(uid_t uid)
1081{
1082	return getpwuid(uid);
1083}
1084
1085#endif
1086
1087struct group *sys_getgrnam(const char *name)
1088{
1089	return getgrnam(name);
1090}
1091
1092struct group *sys_getgrgid(gid_t gid)
1093{
1094	return getgrgid(gid);
1095}
1096
1097#if 0 /* NOT CURRENTLY USED - JRA */
1098/**************************************************************************
1099 The following are the UNICODE versions of *all* system interface functions
1100 called within Samba. Ok, ok, the exceptions are the gethostbyXX calls,
1101 which currently are left as ascii as they are not used other than in name
1102 resolution.
1103****************************************************************************/
1104
1105/**************************************************************************
1106 Wide stat. Just narrow and call sys_xxx.
1107****************************************************************************/
1108
1109int wsys_stat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
1110{
1111	pstring fname;
1112	return sys_stat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
1113}
1114
1115/**************************************************************************
1116 Wide lstat. Just narrow and call sys_xxx.
1117****************************************************************************/
1118
1119int wsys_lstat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
1120{
1121	pstring fname;
1122	return sys_lstat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
1123}
1124
1125/**************************************************************************
1126 Wide creat. Just narrow and call sys_xxx.
1127****************************************************************************/
1128
1129int wsys_creat(const smb_ucs2_t *wfname, mode_t mode)
1130{
1131	pstring fname;
1132	return sys_creat(unicode_to_unix(fname,wfname,sizeof(fname)), mode);
1133}
1134
1135/**************************************************************************
1136 Wide open. Just narrow and call sys_xxx.
1137****************************************************************************/
1138
1139int wsys_open(const smb_ucs2_t *wfname, int oflag, mode_t mode)
1140{
1141	pstring fname;
1142	return sys_open(unicode_to_unix(fname,wfname,sizeof(fname)), oflag, mode);
1143}
1144
1145/**************************************************************************
1146 Wide fopen. Just narrow and call sys_xxx.
1147****************************************************************************/
1148
1149FILE *wsys_fopen(const smb_ucs2_t *wfname, const char *type)
1150{
1151	pstring fname;
1152	return sys_fopen(unicode_to_unix(fname,wfname,sizeof(fname)), type);
1153}
1154
1155/**************************************************************************
1156 Wide opendir. Just narrow and call sys_xxx.
1157****************************************************************************/
1158
1159SMB_STRUCT_DIR *wsys_opendir(const smb_ucs2_t *wfname)
1160{
1161	pstring fname;
1162	return opendir(unicode_to_unix(fname,wfname,sizeof(fname)));
1163}
1164
1165/**************************************************************************
1166 Wide readdir. Return a structure pointer containing a wide filename.
1167****************************************************************************/
1168
1169SMB_STRUCT_WDIRENT *wsys_readdir(SMB_STRUCT_DIR *dirp)
1170{
1171	static SMB_STRUCT_WDIRENT retval;
1172	SMB_STRUCT_DIRENT *dirval = sys_readdir(dirp);
1173
1174	if(!dirval)
1175		return NULL;
1176
1177	/*
1178	 * The only POSIX defined member of this struct is d_name.
1179	 */
1180
1181	unix_to_unicode(retval.d_name,dirval->d_name,sizeof(retval.d_name));
1182
1183	return &retval;
1184}
1185
1186/**************************************************************************
1187 Wide getwd. Call sys_xxx and widen. Assumes s points to a wpstring.
1188****************************************************************************/
1189
1190smb_ucs2_t *wsys_getwd(smb_ucs2_t *s)
1191{
1192	pstring fname;
1193	char *p = sys_getwd(fname);
1194
1195	if(!p)
1196		return NULL;
1197
1198	return unix_to_unicode(s, p, sizeof(wpstring));
1199}
1200
1201/**************************************************************************
1202 Wide chown. Just narrow and call sys_xxx.
1203****************************************************************************/
1204
1205int wsys_chown(const smb_ucs2_t *wfname, uid_t uid, gid_t gid)
1206{
1207	pstring fname;
1208	return chown(unicode_to_unix(fname,wfname,sizeof(fname)), uid, gid);
1209}
1210
1211/**************************************************************************
1212 Wide chroot. Just narrow and call sys_xxx.
1213****************************************************************************/
1214
1215int wsys_chroot(const smb_ucs2_t *wfname)
1216{
1217	pstring fname;
1218	return chroot(unicode_to_unix(fname,wfname,sizeof(fname)));
1219}
1220
1221/**************************************************************************
1222 Wide getpwnam. Return a structure pointer containing wide names.
1223****************************************************************************/
1224
1225SMB_STRUCT_WPASSWD *wsys_getpwnam(const smb_ucs2_t *wname)
1226{
1227	static SMB_STRUCT_WPASSWD retval;
1228	fstring name;
1229	struct passwd *pwret = sys_getpwnam(unicode_to_unix(name,wname,sizeof(name)));
1230
1231	if(!pwret)
1232		return NULL;
1233
1234	unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
1235	retval.pw_passwd = pwret->pw_passwd;
1236	retval.pw_uid = pwret->pw_uid;
1237	retval.pw_gid = pwret->pw_gid;
1238	unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
1239	unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
1240	unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
1241
1242	return &retval;
1243}
1244
1245/**************************************************************************
1246 Wide getpwuid. Return a structure pointer containing wide names.
1247****************************************************************************/
1248
1249SMB_STRUCT_WPASSWD *wsys_getpwuid(uid_t uid)
1250{
1251	static SMB_STRUCT_WPASSWD retval;
1252	struct passwd *pwret = sys_getpwuid(uid);
1253
1254	if(!pwret)
1255		return NULL;
1256
1257	unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
1258	retval.pw_passwd = pwret->pw_passwd;
1259	retval.pw_uid = pwret->pw_uid;
1260	retval.pw_gid = pwret->pw_gid;
1261	unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
1262	unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
1263	unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
1264
1265	return &retval;
1266}
1267#endif /* NOT CURRENTLY USED - JRA */
1268
1269/**************************************************************************
1270 Extract a command into an arg list. Uses a static pstring for storage.
1271 Caller frees returned arg list (which contains pointers into the static pstring).
1272****************************************************************************/
1273
1274static char **extract_args(const char *command)
1275{
1276	static pstring trunc_cmd;
1277	char *ptr;
1278	int argcl;
1279	char **argl = NULL;
1280	int i;
1281
1282	pstrcpy(trunc_cmd, command);
1283
1284	if(!(ptr = strtok(trunc_cmd, " \t"))) {
1285		errno = EINVAL;
1286		return NULL;
1287	}
1288
1289	/*
1290	 * Count the args.
1291	 */
1292
1293	for( argcl = 1; ptr; ptr = strtok(NULL, " \t"))
1294		argcl++;
1295
1296	if((argl = (char **)SMB_MALLOC((argcl + 1) * sizeof(char *))) == NULL)
1297		return NULL;
1298
1299	/*
1300	 * Now do the extraction.
1301	 */
1302
1303	pstrcpy(trunc_cmd, command);
1304
1305	ptr = strtok(trunc_cmd, " \t");
1306	i = 0;
1307	argl[i++] = ptr;
1308
1309	while((ptr = strtok(NULL, " \t")) != NULL)
1310		argl[i++] = ptr;
1311
1312	argl[i++] = NULL;
1313	return argl;
1314}
1315
1316/**************************************************************************
1317 Wrapper for fork. Ensures that mypid is reset. Used so we can write
1318 a sys_getpid() that only does a system call *once*.
1319****************************************************************************/
1320
1321static pid_t mypid = (pid_t)-1;
1322
1323pid_t sys_fork(void)
1324{
1325	pid_t forkret = fork();
1326
1327	if (forkret == (pid_t)0) /* Child - reset mypid so sys_getpid does a system call. */
1328		mypid = (pid_t) -1;
1329
1330	return forkret;
1331}
1332
1333/**************************************************************************
1334 Wrapper for getpid. Ensures we only do a system call *once*.
1335****************************************************************************/
1336
1337pid_t sys_getpid(void)
1338{
1339	if (mypid == (pid_t)-1)
1340		mypid = getpid();
1341
1342	return mypid;
1343}
1344
1345/**************************************************************************
1346 Wrapper for popen. Safer as it doesn't search a path.
1347 Modified from the glibc sources.
1348 modified by tridge to return a file descriptor. We must kick our FILE* habit
1349****************************************************************************/
1350
1351typedef struct _popen_list
1352{
1353	int fd;
1354	pid_t child_pid;
1355	struct _popen_list *next;
1356} popen_list;
1357
1358static popen_list *popen_chain;
1359
1360int sys_popen(const char *command)
1361{
1362	int parent_end, child_end;
1363	int pipe_fds[2];
1364	popen_list *entry = NULL;
1365	char **argl = NULL;
1366
1367	if (pipe(pipe_fds) < 0)
1368		return -1;
1369
1370	parent_end = pipe_fds[0];
1371	child_end = pipe_fds[1];
1372
1373	if (!*command) {
1374		errno = EINVAL;
1375		goto err_exit;
1376	}
1377
1378	if((entry = SMB_MALLOC_P(popen_list)) == NULL)
1379		goto err_exit;
1380
1381	ZERO_STRUCTP(entry);
1382
1383	/*
1384	 * Extract the command and args into a NULL terminated array.
1385	 */
1386
1387	if(!(argl = extract_args(command)))
1388		goto err_exit;
1389
1390	entry->child_pid = sys_fork();
1391
1392	if (entry->child_pid == -1) {
1393		goto err_exit;
1394	}
1395
1396	if (entry->child_pid == 0) {
1397
1398		/*
1399		 * Child !
1400		 */
1401
1402		int child_std_end = STDOUT_FILENO;
1403		popen_list *p;
1404
1405		close(parent_end);
1406		if (child_end != child_std_end) {
1407			dup2 (child_end, child_std_end);
1408			close (child_end);
1409		}
1410
1411		/*
1412		 * POSIX.2:  "popen() shall ensure that any streams from previous
1413		 * popen() calls that remain open in the parent process are closed
1414		 * in the new child process."
1415		 */
1416
1417		for (p = popen_chain; p; p = p->next)
1418			close(p->fd);
1419
1420		execv(argl[0], argl);
1421		_exit (127);
1422	}
1423
1424	/*
1425	 * Parent.
1426	 */
1427
1428	close (child_end);
1429	SAFE_FREE(argl);
1430
1431	/* Link into popen_chain. */
1432	entry->next = popen_chain;
1433	popen_chain = entry;
1434	entry->fd = parent_end;
1435
1436	return entry->fd;
1437
1438err_exit:
1439
1440	SAFE_FREE(entry);
1441	SAFE_FREE(argl);
1442	close(pipe_fds[0]);
1443	close(pipe_fds[1]);
1444	return -1;
1445}
1446
1447/**************************************************************************
1448 Wrapper for pclose. Modified from the glibc sources.
1449****************************************************************************/
1450
1451int sys_pclose(int fd)
1452{
1453	int wstatus;
1454	popen_list **ptr = &popen_chain;
1455	popen_list *entry = NULL;
1456	pid_t wait_pid;
1457	int status = -1;
1458
1459	/* Unlink from popen_chain. */
1460	for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
1461		if ((*ptr)->fd == fd) {
1462			entry = *ptr;
1463			*ptr = (*ptr)->next;
1464			status = 0;
1465			break;
1466		}
1467	}
1468
1469	if (status < 0 || close(entry->fd) < 0)
1470		return -1;
1471
1472	/*
1473	 * As Samba is catching and eating child process
1474	 * exits we don't really care about the child exit
1475	 * code, a -1 with errno = ECHILD will do fine for us.
1476	 */
1477
1478	do {
1479		wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
1480	} while (wait_pid == -1 && errno == EINTR);
1481
1482	SAFE_FREE(entry);
1483
1484	if (wait_pid == -1)
1485		return -1;
1486	return wstatus;
1487}
1488
1489/**************************************************************************
1490 Wrappers for dlopen, dlsym, dlclose.
1491****************************************************************************/
1492
1493void *sys_dlopen(const char *name, int flags)
1494{
1495#if defined(HAVE_DLOPEN)
1496	return dlopen(name, flags);
1497#else
1498	return NULL;
1499#endif
1500}
1501
1502void *sys_dlsym(void *handle, const char *symbol)
1503{
1504#if defined(HAVE_DLSYM)
1505    return dlsym(handle, symbol);
1506#else
1507    return NULL;
1508#endif
1509}
1510
1511int sys_dlclose (void *handle)
1512{
1513#if defined(HAVE_DLCLOSE)
1514	return dlclose(handle);
1515#else
1516	return 0;
1517#endif
1518}
1519
1520const char *sys_dlerror(void)
1521{
1522#if defined(HAVE_DLERROR)
1523	return dlerror();
1524#else
1525	return NULL;
1526#endif
1527}
1528
1529int sys_dup2(int oldfd, int newfd)
1530{
1531#if defined(HAVE_DUP2)
1532	return dup2(oldfd, newfd);
1533#else
1534	errno = ENOSYS;
1535	return -1;
1536#endif
1537}
1538
1539/**************************************************************************
1540 Wrapper for Admin Logs.
1541****************************************************************************/
1542
1543 void sys_adminlog(int priority, const char *format_str, ...)
1544{
1545	va_list ap;
1546	int ret;
1547	char *msgbuf = NULL;
1548
1549	va_start( ap, format_str );
1550	ret = vasprintf( &msgbuf, format_str, ap );
1551	va_end( ap );
1552
1553	if (ret == -1)
1554		return;
1555
1556#if defined(HAVE_SYSLOG)
1557	syslog( priority, "%s", msgbuf );
1558#else
1559	DEBUG(0,("%s", msgbuf ));
1560#endif
1561	SAFE_FREE(msgbuf);
1562}
1563
1564/**************************************************************************
1565 Wrappers for extented attribute calls. Based on the Linux package with
1566 support for IRIX and (Net|Free)BSD also. Expand as other systems have them.
1567****************************************************************************/
1568
1569ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t size)
1570{
1571#if defined(HAVE_GETXATTR)
1572#ifndef XATTR_ADD_OPT
1573	return getxattr(path, name, value, size);
1574#else
1575	int options = 0;
1576	return getxattr(path, name, value, size, 0, options);
1577#endif
1578#elif defined(HAVE_GETEA)
1579	return getea(path, name, value, size);
1580#elif defined(HAVE_EXTATTR_GET_FILE)
1581	char *s;
1582	ssize_t retval;
1583	int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1584		EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1585	const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1586	/*
1587	 * The BSD implementation has a nasty habit of silently truncating
1588	 * the returned value to the size of the buffer, so we have to check
1589	 * that the buffer is large enough to fit the returned value.
1590	 */
1591	if((retval=extattr_get_file(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1592		if(retval > size) {
1593			errno = ERANGE;
1594			return -1;
1595		}
1596		if((retval=extattr_get_file(path, attrnamespace, attrname, value, size)) >= 0)
1597			return retval;
1598	}
1599
1600	DEBUG(10,("sys_getxattr: extattr_get_file() failed with: %s\n", strerror(errno)));
1601	return -1;
1602#elif defined(HAVE_ATTR_GET)
1603	int retval, flags = 0;
1604	int valuelength = (int)size;
1605	char *attrname = strchr(name,'.') + 1;
1606
1607	if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1608
1609	retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1610
1611	return retval ? retval : valuelength;
1612#else
1613	errno = ENOSYS;
1614	return -1;
1615#endif
1616}
1617
1618ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t size)
1619{
1620#if defined(HAVE_LGETXATTR)
1621	return lgetxattr(path, name, value, size);
1622#elif defined(HAVE_GETXATTR) && defined(XATTR_ADD_OPT)
1623	int options = XATTR_NOFOLLOW;
1624	return getxattr(path, name, value, size, 0, options);
1625#elif defined(HAVE_LGETEA)
1626	return lgetea(path, name, value, size);
1627#elif defined(HAVE_EXTATTR_GET_LINK)
1628	char *s;
1629	ssize_t retval;
1630	int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1631		EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1632	const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1633
1634	if((retval=extattr_get_link(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1635		if(retval > size) {
1636			errno = ERANGE;
1637			return -1;
1638		}
1639		if((retval=extattr_get_link(path, attrnamespace, attrname, value, size)) >= 0)
1640			return retval;
1641	}
1642
1643	DEBUG(10,("sys_lgetxattr: extattr_get_link() failed with: %s\n", strerror(errno)));
1644	return -1;
1645#elif defined(HAVE_ATTR_GET)
1646	int retval, flags = ATTR_DONTFOLLOW;
1647	int valuelength = (int)size;
1648	char *attrname = strchr(name,'.') + 1;
1649
1650	if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1651
1652	retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1653
1654	return retval ? retval : valuelength;
1655#else
1656	errno = ENOSYS;
1657	return -1;
1658#endif
1659}
1660
1661ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size)
1662{
1663#if defined(HAVE_FGETXATTR)
1664#ifndef XATTR_ADD_OPT
1665	return fgetxattr(filedes, name, value, size);
1666#else
1667	int options = 0;
1668	return fgetxattr(filedes, name, value, size, 0, options);
1669#endif
1670#elif defined(HAVE_FGETEA)
1671	return fgetea(filedes, name, value, size);
1672#elif defined(HAVE_EXTATTR_GET_FD)
1673	char *s;
1674	ssize_t retval;
1675	int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1676		EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1677	const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1678
1679	if((retval=extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0)) >= 0) {
1680		if(retval > size) {
1681			errno = ERANGE;
1682			return -1;
1683		}
1684		if((retval=extattr_get_fd(filedes, attrnamespace, attrname, value, size)) >= 0)
1685			return retval;
1686	}
1687
1688	DEBUG(10,("sys_fgetxattr: extattr_get_fd() failed with: %s\n", strerror(errno)));
1689	return -1;
1690#elif defined(HAVE_ATTR_GETF)
1691	int retval, flags = 0;
1692	int valuelength = (int)size;
1693	char *attrname = strchr(name,'.') + 1;
1694
1695	if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1696
1697	retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags);
1698
1699	return retval ? retval : valuelength;
1700#else
1701	errno = ENOSYS;
1702	return -1;
1703#endif
1704}
1705
1706#if defined(HAVE_EXTATTR_LIST_FILE)
1707
1708#define EXTATTR_PREFIX(s)	(s), (sizeof((s))-1)
1709
1710static struct {
1711        int space;
1712	const char *name;
1713	size_t len;
1714}
1715extattr[] = {
1716	{ EXTATTR_NAMESPACE_SYSTEM, EXTATTR_PREFIX("system.") },
1717        { EXTATTR_NAMESPACE_USER, EXTATTR_PREFIX("user.") },
1718};
1719
1720typedef union {
1721	const char *path;
1722	int filedes;
1723} extattr_arg;
1724
1725static ssize_t bsd_attr_list (int type, extattr_arg arg, char *list, size_t size)
1726{
1727	ssize_t list_size, total_size = 0;
1728	int i, t, len;
1729	char *buf;
1730	/* Iterate through extattr(2) namespaces */
1731	for(t = 0; t < (sizeof(extattr)/sizeof(extattr[0])); t++) {
1732		switch(type) {
1733#if defined(HAVE_EXTATTR_LIST_FILE)
1734			case 0:
1735				list_size = extattr_list_file(arg.path, extattr[t].space, list, size);
1736				break;
1737#endif
1738#if defined(HAVE_EXTATTR_LIST_LINK)
1739			case 1:
1740				list_size = extattr_list_link(arg.path, extattr[t].space, list, size);
1741				break;
1742#endif
1743#if defined(HAVE_EXTATTR_LIST_FD)
1744			case 2:
1745				list_size = extattr_list_fd(arg.filedes, extattr[t].space, list, size);
1746				break;
1747#endif
1748			default:
1749				errno = ENOSYS;
1750				return -1;
1751		}
1752		/* Some error happend. Errno should be set by the previous call */
1753		if(list_size < 0)
1754			return -1;
1755		/* No attributes */
1756		if(list_size == 0)
1757			continue;
1758		/* XXX: Call with an empty buffer may be used to calculate
1759		   necessary buffer size. Unfortunately, we can't say, how
1760		   many attributes were returned, so here is the potential
1761		   problem with the emulation.
1762		*/
1763		if(list == NULL) {
1764			/* Take the worse case of one char attribute names -
1765			   two bytes per name plus one more for sanity.
1766			*/
1767			total_size += list_size + (list_size/2 + 1)*extattr[t].len;
1768			continue;
1769		}
1770		/* Count necessary offset to fit namespace prefixes */
1771		len = 0;
1772		for(i = 0; i < list_size; i += list[i] + 1)
1773			len += extattr[t].len;
1774
1775		total_size += list_size + len;
1776		/* Buffer is too small to fit the results */
1777		if(total_size > size) {
1778			errno = ERANGE;
1779			return -1;
1780		}
1781		/* Shift results back, so we can prepend prefixes */
1782		buf = memmove(list + len, list, list_size);
1783
1784		for(i = 0; i < list_size; i += len + 1) {
1785			len = buf[i];
1786			strncpy(list, extattr[t].name, extattr[t].len + 1);
1787			list += extattr[t].len;
1788			strncpy(list, buf + i + 1, len);
1789			list[len] = '\0';
1790			list += len + 1;
1791		}
1792		size -= total_size;
1793	}
1794	return total_size;
1795}
1796
1797#endif
1798
1799#if defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1800static char attr_buffer[ATTR_MAX_VALUELEN];
1801
1802static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags)
1803{
1804	int retval = 0, index;
1805	attrlist_cursor_t *cursor = 0;
1806	int total_size = 0;
1807	attrlist_t * al = (attrlist_t *)attr_buffer;
1808	attrlist_ent_t *ae;
1809	size_t ent_size, left = size;
1810	char *bp = list;
1811
1812	while (True) {
1813	    if (filedes)
1814		retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1815	    else
1816		retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1817	    if (retval) break;
1818	    for (index = 0; index < al->al_count; index++) {
1819		ae = ATTR_ENTRY(attr_buffer, index);
1820		ent_size = strlen(ae->a_name) + sizeof("user.");
1821		if (left >= ent_size) {
1822		    strncpy(bp, "user.", sizeof("user."));
1823		    strncat(bp, ae->a_name, ent_size - sizeof("user."));
1824		    bp += ent_size;
1825		    left -= ent_size;
1826		} else if (size) {
1827		    errno = ERANGE;
1828		    retval = -1;
1829		    break;
1830		}
1831		total_size += ent_size;
1832	    }
1833	    if (al->al_more == 0) break;
1834	}
1835	if (retval == 0) {
1836	    flags |= ATTR_ROOT;
1837	    cursor = 0;
1838	    while (True) {
1839		if (filedes)
1840		    retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1841		else
1842		    retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1843		if (retval) break;
1844		for (index = 0; index < al->al_count; index++) {
1845		    ae = ATTR_ENTRY(attr_buffer, index);
1846		    ent_size = strlen(ae->a_name) + sizeof("system.");
1847		    if (left >= ent_size) {
1848			strncpy(bp, "system.", sizeof("system."));
1849			strncat(bp, ae->a_name, ent_size - sizeof("system."));
1850			bp += ent_size;
1851			left -= ent_size;
1852		    } else if (size) {
1853			errno = ERANGE;
1854			retval = -1;
1855			break;
1856		    }
1857		    total_size += ent_size;
1858		}
1859		if (al->al_more == 0) break;
1860	    }
1861	}
1862	return (ssize_t)(retval ? retval : total_size);
1863}
1864
1865#endif
1866
1867ssize_t sys_listxattr (const char *path, char *list, size_t size)
1868{
1869#if defined(HAVE_LISTXATTR)
1870#ifndef XATTR_ADD_OPT
1871	return listxattr(path, list, size);
1872#else
1873	int options = 0;
1874	return listxattr(path, list, size, options);
1875#endif
1876#elif defined(HAVE_LISTEA)
1877	return listea(path, list, size);
1878#elif defined(HAVE_EXTATTR_LIST_FILE)
1879	extattr_arg arg;
1880	arg.path = path;
1881	return bsd_attr_list(0, arg, list, size);
1882#elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1883	return irix_attr_list(path, 0, list, size, 0);
1884#else
1885	errno = ENOSYS;
1886	return -1;
1887#endif
1888}
1889
1890ssize_t sys_llistxattr (const char *path, char *list, size_t size)
1891{
1892#if defined(HAVE_LLISTXATTR)
1893	return llistxattr(path, list, size);
1894#elif defined(HAVE_LISTXATTR) && defined(XATTR_ADD_OPT)
1895	int options = XATTR_NOFOLLOW;
1896	return listxattr(path, list, size, options);
1897#elif defined(HAVE_LLISTEA)
1898	return llistea(path, list, size);
1899#elif defined(HAVE_EXTATTR_LIST_LINK)
1900	extattr_arg arg;
1901	arg.path = path;
1902	return bsd_attr_list(1, arg, list, size);
1903#elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1904	return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW);
1905#else
1906	errno = ENOSYS;
1907	return -1;
1908#endif
1909}
1910
1911ssize_t sys_flistxattr (int filedes, char *list, size_t size)
1912{
1913#if defined(HAVE_FLISTXATTR)
1914#ifndef XATTR_ADD_OPT
1915	return flistxattr(filedes, list, size);
1916#else
1917	int options = 0;
1918	return flistxattr(filedes, list, size, options);
1919#endif
1920#elif defined(HAVE_FLISTEA)
1921	return flistea(filedes, list, size);
1922#elif defined(HAVE_EXTATTR_LIST_FD)
1923	extattr_arg arg;
1924	arg.filedes = filedes;
1925	return bsd_attr_list(2, arg, list, size);
1926#elif defined(HAVE_ATTR_LISTF)
1927	return irix_attr_list(NULL, filedes, list, size, 0);
1928#else
1929	errno = ENOSYS;
1930	return -1;
1931#endif
1932}
1933
1934int sys_removexattr (const char *path, const char *name)
1935{
1936#if defined(HAVE_REMOVEXATTR)
1937#ifndef XATTR_ADD_OPT
1938	return removexattr(path, name);
1939#else
1940	int options = 0;
1941	return removexattr(path, name, options);
1942#endif
1943#elif defined(HAVE_REMOVEEA)
1944	return removeea(path, name);
1945#elif defined(HAVE_EXTATTR_DELETE_FILE)
1946	char *s;
1947	int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1948		EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1949	const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1950
1951	return extattr_delete_file(path, attrnamespace, attrname);
1952#elif defined(HAVE_ATTR_REMOVE)
1953	int flags = 0;
1954	char *attrname = strchr(name,'.') + 1;
1955
1956	if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1957
1958	return attr_remove(path, attrname, flags);
1959#else
1960	errno = ENOSYS;
1961	return -1;
1962#endif
1963}
1964
1965int sys_lremovexattr (const char *path, const char *name)
1966{
1967#if defined(HAVE_LREMOVEXATTR)
1968	return lremovexattr(path, name);
1969#elif defined(HAVE_REMOVEXATTR) && defined(XATTR_ADD_OPT)
1970	int options = XATTR_NOFOLLOW;
1971	return removexattr(path, name, options);
1972#elif defined(HAVE_LREMOVEEA)
1973	return lremoveea(path, name);
1974#elif defined(HAVE_EXTATTR_DELETE_LINK)
1975	char *s;
1976	int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1977		EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1978	const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1979
1980	return extattr_delete_link(path, attrnamespace, attrname);
1981#elif defined(HAVE_ATTR_REMOVE)
1982	int flags = ATTR_DONTFOLLOW;
1983	char *attrname = strchr(name,'.') + 1;
1984
1985	if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1986
1987	return attr_remove(path, attrname, flags);
1988#else
1989	errno = ENOSYS;
1990	return -1;
1991#endif
1992}
1993
1994int sys_fremovexattr (int filedes, const char *name)
1995{
1996#if defined(HAVE_FREMOVEXATTR)
1997#ifndef XATTR_ADD_OPT
1998	return fremovexattr(filedes, name);
1999#else
2000	int options = 0;
2001	return fremovexattr(filedes, name, options);
2002#endif
2003#elif defined(HAVE_FREMOVEEA)
2004	return fremoveea(filedes, name);
2005#elif defined(HAVE_EXTATTR_DELETE_FD)
2006	char *s;
2007	int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2008		EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2009	const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2010
2011	return extattr_delete_fd(filedes, attrnamespace, attrname);
2012#elif defined(HAVE_ATTR_REMOVEF)
2013	int flags = 0;
2014	char *attrname = strchr(name,'.') + 1;
2015
2016	if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
2017
2018	return attr_removef(filedes, attrname, flags);
2019#else
2020	errno = ENOSYS;
2021	return -1;
2022#endif
2023}
2024
2025#if !defined(HAVE_SETXATTR)
2026#define XATTR_CREATE  0x1       /* set value, fail if attr already exists */
2027#define XATTR_REPLACE 0x2       /* set value, fail if attr does not exist */
2028#endif
2029
2030int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags)
2031{
2032#if defined(HAVE_SETXATTR)
2033#ifndef XATTR_ADD_OPT
2034	return setxattr(path, name, value, size, flags);
2035#else
2036	int options = 0;
2037	return setxattr(path, name, value, size, 0, options);
2038#endif
2039#elif defined(HAVE_SETEA)
2040	return setea(path, name, value, size, flags);
2041#elif defined(HAVE_EXTATTR_SET_FILE)
2042	char *s;
2043	int retval = 0;
2044	int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2045		EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2046	const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2047	if (flags) {
2048		/* Check attribute existence */
2049		retval = extattr_get_file(path, attrnamespace, attrname, NULL, 0);
2050		if (retval < 0) {
2051			/* REPLACE attribute, that doesn't exist */
2052			if (flags & XATTR_REPLACE && errno == ENOATTR) {
2053				errno = ENOATTR;
2054				return -1;
2055			}
2056			/* Ignore other errors */
2057		}
2058		else {
2059			/* CREATE attribute, that already exists */
2060			if (flags & XATTR_CREATE) {
2061				errno = EEXIST;
2062				return -1;
2063			}
2064		}
2065	}
2066	retval = extattr_set_file(path, attrnamespace, attrname, value, size);
2067	return (retval < 0) ? -1 : 0;
2068#elif defined(HAVE_ATTR_SET)
2069	int myflags = 0;
2070	char *attrname = strchr(name,'.') + 1;
2071
2072	if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2073	if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2074	if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2075
2076	return attr_set(path, attrname, (const char *)value, size, myflags);
2077#else
2078	errno = ENOSYS;
2079	return -1;
2080#endif
2081}
2082
2083int sys_lsetxattr (const char *path, const char *name, const void *value, size_t size, int flags)
2084{
2085#if defined(HAVE_LSETXATTR)
2086	return lsetxattr(path, name, value, size, flags);
2087#elif defined(HAVE_SETXATTR) && defined(XATTR_ADD_OPT)
2088	int options = XATTR_NOFOLLOW;
2089	return setxattr(path, name, value, size, 0, options);
2090#elif defined(LSETEA)
2091	return lsetea(path, name, value, size, flags);
2092#elif defined(HAVE_EXTATTR_SET_LINK)
2093	char *s;
2094	int retval = 0;
2095	int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2096		EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2097	const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2098	if (flags) {
2099		/* Check attribute existence */
2100		retval = extattr_get_link(path, attrnamespace, attrname, NULL, 0);
2101		if (retval < 0) {
2102			/* REPLACE attribute, that doesn't exist */
2103			if (flags & XATTR_REPLACE && errno == ENOATTR) {
2104				errno = ENOATTR;
2105				return -1;
2106			}
2107			/* Ignore other errors */
2108		}
2109		else {
2110			/* CREATE attribute, that already exists */
2111			if (flags & XATTR_CREATE) {
2112				errno = EEXIST;
2113				return -1;
2114			}
2115		}
2116	}
2117
2118	retval = extattr_set_link(path, attrnamespace, attrname, value, size);
2119	return (retval < 0) ? -1 : 0;
2120#elif defined(HAVE_ATTR_SET)
2121	int myflags = ATTR_DONTFOLLOW;
2122	char *attrname = strchr(name,'.') + 1;
2123
2124	if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2125	if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2126	if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2127
2128	return attr_set(path, attrname, (const char *)value, size, myflags);
2129#else
2130	errno = ENOSYS;
2131	return -1;
2132#endif
2133}
2134
2135int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags)
2136{
2137#if defined(HAVE_FSETXATTR)
2138#ifndef XATTR_ADD_OPT
2139	return fsetxattr(filedes, name, value, size, flags);
2140#else
2141	int options = 0;
2142	return fsetxattr(filedes, name, value, size, 0, options);
2143#endif
2144#elif defined(HAVE_FSETEA)
2145	return fsetea(filedes, name, value, size, flags);
2146#elif defined(HAVE_EXTATTR_SET_FD)
2147	char *s;
2148	int retval = 0;
2149	int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2150		EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2151	const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2152	if (flags) {
2153		/* Check attribute existence */
2154		retval = extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0);
2155		if (retval < 0) {
2156			/* REPLACE attribute, that doesn't exist */
2157			if (flags & XATTR_REPLACE && errno == ENOATTR) {
2158				errno = ENOATTR;
2159				return -1;
2160			}
2161			/* Ignore other errors */
2162		}
2163		else {
2164			/* CREATE attribute, that already exists */
2165			if (flags & XATTR_CREATE) {
2166				errno = EEXIST;
2167				return -1;
2168			}
2169		}
2170	}
2171	retval = extattr_set_fd(filedes, attrnamespace, attrname, value, size);
2172	return (retval < 0) ? -1 : 0;
2173#elif defined(HAVE_ATTR_SETF)
2174	int myflags = 0;
2175	char *attrname = strchr(name,'.') + 1;
2176
2177	if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2178	if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2179	if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2180
2181	return attr_setf(filedes, attrname, (const char *)value, size, myflags);
2182#else
2183	errno = ENOSYS;
2184	return -1;
2185#endif
2186}
2187
2188/****************************************************************************
2189 Return the major devicenumber for UNIX extensions.
2190****************************************************************************/
2191
2192uint32 unix_dev_major(SMB_DEV_T dev)
2193{
2194#if defined(HAVE_DEVICE_MAJOR_FN)
2195        return (uint32)major(dev);
2196#else
2197        return (uint32)(dev >> 8);
2198#endif
2199}
2200
2201/****************************************************************************
2202 Return the minor devicenumber for UNIX extensions.
2203****************************************************************************/
2204
2205uint32 unix_dev_minor(SMB_DEV_T dev)
2206{
2207#if defined(HAVE_DEVICE_MINOR_FN)
2208        return (uint32)minor(dev);
2209#else
2210        return (uint32)(dev & 0xff);
2211#endif
2212}
2213
2214#if defined(WITH_AIO)
2215
2216/*******************************************************************
2217 An aio_read wrapper that will deal with 64-bit sizes.
2218********************************************************************/
2219
2220int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2221{
2222#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_READ64)
2223        return aio_read64(aiocb);
2224#elif defined(HAVE_AIO_READ)
2225        return aio_read(aiocb);
2226#else
2227	errno = ENOSYS;
2228	return -1;
2229#endif
2230}
2231
2232/*******************************************************************
2233 An aio_write wrapper that will deal with 64-bit sizes.
2234********************************************************************/
2235
2236int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2237{
2238#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_WRITE64)
2239        return aio_write64(aiocb);
2240#elif defined(HAVE_AIO_WRITE)
2241        return aio_write(aiocb);
2242#else
2243	errno = ENOSYS;
2244	return -1;
2245#endif
2246}
2247
2248/*******************************************************************
2249 An aio_return wrapper that will deal with 64-bit sizes.
2250********************************************************************/
2251
2252ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2253{
2254#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_RETURN64)
2255        return aio_return64(aiocb);
2256#elif defined(HAVE_AIO_RETURN)
2257        return aio_return(aiocb);
2258#else
2259	errno = ENOSYS;
2260	return -1;
2261#endif
2262}
2263
2264/*******************************************************************
2265 An aio_cancel wrapper that will deal with 64-bit sizes.
2266********************************************************************/
2267
2268int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2269{
2270#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_CANCEL64)
2271        return aio_cancel64(fd, aiocb);
2272#elif defined(HAVE_AIO_CANCEL)
2273        return aio_cancel(fd, aiocb);
2274#else
2275	errno = ENOSYS;
2276	return -1;
2277#endif
2278}
2279
2280/*******************************************************************
2281 An aio_error wrapper that will deal with 64-bit sizes.
2282********************************************************************/
2283
2284int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2285{
2286#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_ERROR64)
2287        return aio_error64(aiocb);
2288#elif defined(HAVE_AIO_ERROR)
2289        return aio_error(aiocb);
2290#else
2291	errno = ENOSYS;
2292	return -1;
2293#endif
2294}
2295
2296/*******************************************************************
2297 An aio_fsync wrapper that will deal with 64-bit sizes.
2298********************************************************************/
2299
2300int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2301{
2302#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_FSYNC64)
2303        return aio_fsync64(op, aiocb);
2304#elif defined(HAVE_AIO_FSYNC)
2305        return aio_fsync(op, aiocb);
2306#else
2307	errno = ENOSYS;
2308	return -1;
2309#endif
2310}
2311
2312/*******************************************************************
2313 An aio_fsync wrapper that will deal with 64-bit sizes.
2314********************************************************************/
2315
2316int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2317{
2318#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_SUSPEND64)
2319        return aio_suspend64(cblist, n, timeout);
2320#elif defined(HAVE_AIO_FSYNC)
2321        return aio_suspend(cblist, n, timeout);
2322#else
2323	errno = ENOSYS;
2324	return -1;
2325#endif
2326}
2327#else /* !WITH_AIO */
2328
2329int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2330{
2331	errno = ENOSYS;
2332	return -1;
2333}
2334
2335int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2336{
2337	errno = ENOSYS;
2338	return -1;
2339}
2340
2341ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2342{
2343	errno = ENOSYS;
2344	return -1;
2345}
2346
2347int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2348{
2349	errno = ENOSYS;
2350	return -1;
2351}
2352
2353int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2354{
2355	errno = ENOSYS;
2356	return -1;
2357}
2358
2359int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2360{
2361	errno = ENOSYS;
2362	return -1;
2363}
2364
2365int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2366{
2367	errno = ENOSYS;
2368	return -1;
2369}
2370#endif /* WITH_AIO */
2371
2372int sys_getpeereid( int s, uid_t *uid)
2373{
2374#if defined(HAVE_PEERCRED)
2375	struct ucred cred;
2376	socklen_t cred_len = sizeof(struct ucred);
2377	int ret;
2378
2379	ret = getsockopt(s, SOL_SOCKET, SO_PEERCRED, (void *)&cred, &cred_len);
2380	if (ret != 0) {
2381		return -1;
2382	}
2383
2384	if (cred_len != sizeof(struct ucred)) {
2385		errno = EINVAL;
2386		return -1;
2387	}
2388
2389	*uid = cred.uid;
2390	return 0;
2391#else
2392	errno = ENOSYS;
2393	return -1;
2394#endif
2395}
2396