s3: Fix malformed require_membership_of_sid.
[Samba/gbeck.git] / source3 / lib / system.c
blob6349af50725e285f486eb363ce6ff6d2d9d22f9e
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 Copyright (C) Bjoern Jacke 2006-2007
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "includes.h"
25 #ifdef HAVE_SYS_PRCTL_H
26 #include <sys/prctl.h>
27 #endif
30 The idea is that this file will eventually have wrappers around all
31 important system calls in samba. The aims are:
33 - to enable easier porting by putting OS dependent stuff in here
35 - to allow for hooks into other "pseudo-filesystems"
37 - to allow easier integration of things like the japanese extensions
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.
46 /*******************************************************************
47 A wrapper for memalign
48 ********************************************************************/
50 void *sys_memalign( size_t align, size_t size )
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;
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;
75 if (size < pagesize) {
76 size = pagesize;
78 return SMB_MALLOC(size);
79 #endif
82 /*******************************************************************
83 A wrapper for usleep in case we don't have one.
84 ********************************************************************/
86 int sys_usleep(long usecs)
88 #ifndef HAVE_USLEEP
89 struct timeval tval;
90 #endif
93 * We need this braindamage as the glibc usleep
94 * is not SPEC1170 complient... grumble... JRA.
97 if(usecs < 0 || usecs > 999999) {
98 errno = EINVAL;
99 return -1;
102 #if HAVE_USLEEP
103 usleep(usecs);
104 return 0;
105 #else /* HAVE_USLEEP */
107 * Fake it with select...
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 */
116 /*******************************************************************
117 A read wrapper that will deal with EINTR.
118 ********************************************************************/
120 ssize_t sys_read(int fd, void *buf, size_t count)
122 ssize_t ret;
124 do {
125 ret = read(fd, buf, count);
126 } while (ret == -1 && errno == EINTR);
127 return ret;
130 /*******************************************************************
131 A write wrapper that will deal with EINTR.
132 ********************************************************************/
134 ssize_t sys_write(int fd, const void *buf, size_t count)
136 ssize_t ret;
138 do {
139 ret = write(fd, buf, count);
140 } while (ret == -1 && errno == EINTR);
141 return ret;
144 /*******************************************************************
145 A writev wrapper that will deal with EINTR.
146 ********************************************************************/
148 ssize_t sys_writev(int fd, const struct iovec *iov, int iovcnt)
150 ssize_t ret;
152 #if 0
153 /* Try to confuse write_data_iov a bit */
154 if ((random() % 5) == 0) {
155 return sys_write(fd, iov[0].iov_base, iov[0].iov_len);
157 if (iov[0].iov_len > 1) {
158 return sys_write(fd, iov[0].iov_base,
159 (random() % (iov[0].iov_len-1)) + 1);
161 #endif
163 do {
164 ret = writev(fd, iov, iovcnt);
165 } while (ret == -1 && errno == EINTR);
166 return ret;
169 /*******************************************************************
170 A pread wrapper that will deal with EINTR and 64-bit file offsets.
171 ********************************************************************/
173 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
174 ssize_t sys_pread(int fd, void *buf, size_t count, SMB_OFF_T off)
176 ssize_t ret;
178 do {
179 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_PREAD64)
180 ret = pread64(fd, buf, count, off);
181 #else
182 ret = pread(fd, buf, count, off);
183 #endif
184 } while (ret == -1 && errno == EINTR);
185 return ret;
187 #endif
189 /*******************************************************************
190 A write wrapper that will deal with EINTR and 64-bit file offsets.
191 ********************************************************************/
193 #if defined(HAVE_PWRITE) || defined(HAVE_PWRITE64)
194 ssize_t sys_pwrite(int fd, const void *buf, size_t count, SMB_OFF_T off)
196 ssize_t ret;
198 do {
199 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_PWRITE64)
200 ret = pwrite64(fd, buf, count, off);
201 #else
202 ret = pwrite(fd, buf, count, off);
203 #endif
204 } while (ret == -1 && errno == EINTR);
205 return ret;
207 #endif
209 /*******************************************************************
210 A send wrapper that will deal with EINTR.
211 ********************************************************************/
213 ssize_t sys_send(int s, const void *msg, size_t len, int flags)
215 ssize_t ret;
217 do {
218 ret = send(s, msg, len, flags);
219 } while (ret == -1 && errno == EINTR);
220 return ret;
223 /*******************************************************************
224 A sendto wrapper that will deal with EINTR.
225 ********************************************************************/
227 ssize_t sys_sendto(int s, const void *msg, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
229 ssize_t ret;
231 do {
232 ret = sendto(s, msg, len, flags, to, tolen);
233 } while (ret == -1 && errno == EINTR);
234 return ret;
237 /*******************************************************************
238 A recv wrapper that will deal with EINTR.
239 ********************************************************************/
241 ssize_t sys_recv(int fd, void *buf, size_t count, int flags)
243 ssize_t ret;
245 do {
246 ret = recv(fd, buf, count, flags);
247 } while (ret == -1 && errno == EINTR);
248 return ret;
251 /*******************************************************************
252 A recvfrom wrapper that will deal with EINTR.
253 ********************************************************************/
255 ssize_t sys_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
257 ssize_t ret;
259 do {
260 ret = recvfrom(s, buf, len, flags, from, fromlen);
261 } while (ret == -1 && errno == EINTR);
262 return ret;
265 /*******************************************************************
266 A fcntl wrapper that will deal with EINTR.
267 ********************************************************************/
269 int sys_fcntl_ptr(int fd, int cmd, void *arg)
271 int ret;
273 do {
274 ret = fcntl(fd, cmd, arg);
275 } while (ret == -1 && errno == EINTR);
276 return ret;
279 /*******************************************************************
280 A fcntl wrapper that will deal with EINTR.
281 ********************************************************************/
283 int sys_fcntl_long(int fd, int cmd, long arg)
285 int ret;
287 do {
288 ret = fcntl(fd, cmd, arg);
289 } while (ret == -1 && errno == EINTR);
290 return ret;
293 /*******************************************************************
294 A stat() wrapper that will deal with 64 bit filesizes.
295 ********************************************************************/
297 int sys_stat(const char *fname,SMB_STRUCT_STAT *sbuf)
299 int ret;
300 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
301 ret = stat64(fname, sbuf);
302 #else
303 ret = stat(fname, sbuf);
304 #endif
305 /* we always want directories to appear zero size */
306 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
307 return ret;
310 /*******************************************************************
311 An fstat() wrapper that will deal with 64 bit filesizes.
312 ********************************************************************/
314 int sys_fstat(int fd,SMB_STRUCT_STAT *sbuf)
316 int ret;
317 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FSTAT64)
318 ret = fstat64(fd, sbuf);
319 #else
320 ret = fstat(fd, sbuf);
321 #endif
322 /* we always want directories to appear zero size */
323 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
324 return ret;
327 /*******************************************************************
328 An lstat() wrapper that will deal with 64 bit filesizes.
329 ********************************************************************/
331 int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf)
333 int ret;
334 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSTAT64)
335 ret = lstat64(fname, sbuf);
336 #else
337 ret = lstat(fname, sbuf);
338 #endif
339 /* we always want directories to appear zero size */
340 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
341 return ret;
344 /*******************************************************************
345 An ftruncate() wrapper that will deal with 64 bit filesizes.
346 ********************************************************************/
348 int sys_ftruncate(int fd, SMB_OFF_T offset)
350 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FTRUNCATE64)
351 return ftruncate64(fd, offset);
352 #else
353 return ftruncate(fd, offset);
354 #endif
357 /*******************************************************************
358 An lseek() wrapper that will deal with 64 bit filesizes.
359 ********************************************************************/
361 SMB_OFF_T sys_lseek(int fd, SMB_OFF_T offset, int whence)
363 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSEEK64)
364 return lseek64(fd, offset, whence);
365 #else
366 return lseek(fd, offset, whence);
367 #endif
370 /*******************************************************************
371 An fseek() wrapper that will deal with 64 bit filesizes.
372 ********************************************************************/
374 int sys_fseek(FILE *fp, SMB_OFF_T offset, int whence)
376 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEK64)
377 return fseek64(fp, offset, whence);
378 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEKO64)
379 return fseeko64(fp, offset, whence);
380 #else
381 return fseek(fp, offset, whence);
382 #endif
385 /*******************************************************************
386 An ftell() wrapper that will deal with 64 bit filesizes.
387 ********************************************************************/
389 SMB_OFF_T sys_ftell(FILE *fp)
391 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELL64)
392 return (SMB_OFF_T)ftell64(fp);
393 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELLO64)
394 return (SMB_OFF_T)ftello64(fp);
395 #else
396 return (SMB_OFF_T)ftell(fp);
397 #endif
400 /*******************************************************************
401 A creat() wrapper that will deal with 64 bit filesizes.
402 ********************************************************************/
404 int sys_creat(const char *path, mode_t mode)
406 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CREAT64)
407 return creat64(path, mode);
408 #else
410 * If creat64 isn't defined then ensure we call a potential open64.
411 * JRA.
413 return sys_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
414 #endif
417 /*******************************************************************
418 An open() wrapper that will deal with 64 bit filesizes.
419 ********************************************************************/
421 int sys_open(const char *path, int oflag, mode_t mode)
423 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPEN64)
424 return open64(path, oflag, mode);
425 #else
426 return open(path, oflag, mode);
427 #endif
430 /*******************************************************************
431 An fopen() wrapper that will deal with 64 bit filesizes.
432 ********************************************************************/
434 FILE *sys_fopen(const char *path, const char *type)
436 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FOPEN64)
437 return fopen64(path, type);
438 #else
439 return fopen(path, type);
440 #endif
444 /*******************************************************************
445 A flock() wrapper that will perform the kernel flock.
446 ********************************************************************/
448 void kernel_flock(int fd, uint32 share_mode)
450 #if HAVE_KERNEL_SHARE_MODES
451 int kernel_mode = 0;
452 if (share_mode == FILE_SHARE_WRITE) {
453 kernel_mode = LOCK_MAND|LOCK_WRITE;
454 } else if (share_mode == FILE_SHARE_READ) {
455 kernel_mode = LOCK_MAND|LOCK_READ;
456 } else if (share_mode == FILE_SHARE_NONE) {
457 kernel_mode = LOCK_MAND;
459 if (kernel_mode) {
460 flock(fd, kernel_mode);
462 #endif
468 /*******************************************************************
469 An opendir wrapper that will deal with 64 bit filesizes.
470 ********************************************************************/
472 SMB_STRUCT_DIR *sys_opendir(const char *name)
474 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPENDIR64)
475 return opendir64(name);
476 #else
477 return opendir(name);
478 #endif
481 /*******************************************************************
482 A readdir wrapper that will deal with 64 bit filesizes.
483 ********************************************************************/
485 SMB_STRUCT_DIRENT *sys_readdir(SMB_STRUCT_DIR *dirp)
487 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_READDIR64)
488 return readdir64(dirp);
489 #else
490 return readdir(dirp);
491 #endif
494 /*******************************************************************
495 A seekdir wrapper that will deal with 64 bit filesizes.
496 ********************************************************************/
498 void sys_seekdir(SMB_STRUCT_DIR *dirp, long offset)
500 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_SEEKDIR64)
501 seekdir64(dirp, offset);
502 #else
503 seekdir(dirp, offset);
504 #endif
507 /*******************************************************************
508 A telldir wrapper that will deal with 64 bit filesizes.
509 ********************************************************************/
511 long sys_telldir(SMB_STRUCT_DIR *dirp)
513 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_TELLDIR64)
514 return (long)telldir64(dirp);
515 #else
516 return (long)telldir(dirp);
517 #endif
520 /*******************************************************************
521 A rewinddir wrapper that will deal with 64 bit filesizes.
522 ********************************************************************/
524 void sys_rewinddir(SMB_STRUCT_DIR *dirp)
526 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_REWINDDIR64)
527 rewinddir64(dirp);
528 #else
529 rewinddir(dirp);
530 #endif
533 /*******************************************************************
534 A close wrapper that will deal with 64 bit filesizes.
535 ********************************************************************/
537 int sys_closedir(SMB_STRUCT_DIR *dirp)
539 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CLOSEDIR64)
540 return closedir64(dirp);
541 #else
542 return closedir(dirp);
543 #endif
546 /*******************************************************************
547 An mknod() wrapper that will deal with 64 bit filesizes.
548 ********************************************************************/
550 int sys_mknod(const char *path, mode_t mode, SMB_DEV_T dev)
552 #if defined(HAVE_MKNOD) || defined(HAVE_MKNOD64)
553 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_MKNOD64) && defined(HAVE_DEV64_T)
554 return mknod64(path, mode, dev);
555 #else
556 return mknod(path, mode, dev);
557 #endif
558 #else
559 /* No mknod system call. */
560 errno = ENOSYS;
561 return -1;
562 #endif
565 /*******************************************************************
566 The wait() calls vary between systems
567 ********************************************************************/
569 int sys_waitpid(pid_t pid,int *status,int options)
571 #ifdef HAVE_WAITPID
572 return waitpid(pid,status,options);
573 #else /* HAVE_WAITPID */
574 return wait4(pid, status, options, NULL);
575 #endif /* HAVE_WAITPID */
578 /*******************************************************************
579 System wrapper for getwd
580 ********************************************************************/
582 char *sys_getwd(char *s)
584 char *wd;
585 #ifdef HAVE_GETCWD
586 wd = (char *)getcwd(s, PATH_MAX);
587 #else
588 wd = (char *)getwd(s);
589 #endif
590 return wd;
593 #if defined(HAVE_POSIX_CAPABILITIES)
595 /* This define hasn't made it into the glibc capabilities header yet. */
596 #ifndef SECURE_NO_SETUID_FIXUP
597 #define SECURE_NO_SETUID_FIXUP 2
598 #endif
600 /**************************************************************************
601 Try and abstract process capabilities (for systems that have them).
602 ****************************************************************************/
604 /* Set the POSIX capabilities needed for the given purpose into the effective
605 * capability set of the current process. Make sure they are always removed
606 * from the inheritable set, because there is no circumstance in which our
607 * children should inherit our elevated privileges.
609 static bool set_process_capability(enum smbd_capability capability,
610 bool enable)
612 cap_value_t cap_vals[2] = {0};
613 int num_cap_vals = 0;
615 cap_t cap;
617 #if defined(HAVE_PRCTL) && defined(PR_GET_KEEPCAPS) && defined(PR_SET_KEEPCAPS)
618 /* On Linux, make sure that any capabilities we grab are sticky
619 * across UID changes. We expect that this would allow us to keep both
620 * the effective and permitted capability sets, but as of circa 2.6.16,
621 * only the permitted set is kept. It is a bug (which we work around)
622 * that the effective set is lost, but we still require the effective
623 * set to be kept.
625 if (!prctl(PR_GET_KEEPCAPS)) {
626 prctl(PR_SET_KEEPCAPS, 1);
628 #endif
630 #if defined(HAVE_PRCTL) && defined(PR_SET_SECUREBITS) && defined(SECURE_NO_SETUID_FIXUP)
631 /* New way of setting capabilities as "sticky". */
634 * Use PR_SET_SECUREBITS to prevent setresuid()
635 * atomically dropping effective capabilities on
636 * uid change. Only available in Linux kernels
637 * 2.6.26 and above.
639 * See here:
640 * http://www.kernel.org/doc/man-pages/online/pages/man7/capabilities.7.html
641 * for details.
643 * Specifically the CAP_KILL capability we need
644 * to allow Linux threads under different euids
645 * to send signals to each other.
648 if (prctl(PR_SET_SECUREBITS, 1 << SECURE_NO_SETUID_FIXUP)) {
649 DEBUG(0,("set_process_capability: "
650 "prctl PR_SET_SECUREBITS failed with error %s\n",
651 strerror(errno) ));
652 return false;
654 #endif
656 cap = cap_get_proc();
657 if (cap == NULL) {
658 DEBUG(0,("set_process_capability: cap_get_proc failed: %s\n",
659 strerror(errno)));
660 return False;
663 switch (capability) {
664 case KERNEL_OPLOCK_CAPABILITY:
665 #ifdef CAP_NETWORK_MGT
666 /* IRIX has CAP_NETWORK_MGT for oplocks. */
667 cap_vals[num_cap_vals++] = CAP_NETWORK_MGT;
668 #endif
669 break;
670 case DMAPI_ACCESS_CAPABILITY:
671 #ifdef CAP_DEVICE_MGT
672 /* IRIX has CAP_DEVICE_MGT for DMAPI access. */
673 cap_vals[num_cap_vals++] = CAP_DEVICE_MGT;
674 #elif CAP_MKNOD
675 /* Linux has CAP_MKNOD for DMAPI access. */
676 cap_vals[num_cap_vals++] = CAP_MKNOD;
677 #endif
678 break;
679 case LEASE_CAPABILITY:
680 #ifdef CAP_LEASE
681 cap_vals[num_cap_vals++] = CAP_LEASE;
682 #endif
683 break;
684 case KILL_CAPABILITY:
685 #ifdef CAP_KILL
686 cap_vals[num_cap_vals++] = CAP_KILL;
687 #endif
688 break;
691 SMB_ASSERT(num_cap_vals <= ARRAY_SIZE(cap_vals));
693 if (num_cap_vals == 0) {
694 cap_free(cap);
695 return True;
699 * Ensure the capability is effective. We assume that as a root
700 * process it's always permitted.
703 if (cap_set_flag(cap, CAP_EFFECTIVE, num_cap_vals, cap_vals,
704 enable ? CAP_SET : CAP_CLEAR) == -1) {
705 DEBUG(0, ("set_process_capability: cap_set_flag effective "
706 "failed (%d): %s\n",
707 (int)capability,
708 strerror(errno)));
709 cap_free(cap);
710 return false;
713 /* We never want to pass capabilities down to our children, so make
714 * sure they are not inherited.
716 if (cap_set_flag(cap, CAP_INHERITABLE, num_cap_vals,
717 cap_vals, CAP_CLEAR) == -1) {
718 DEBUG(0, ("set_process_capability: cap_set_flag inheritable "
719 "failed (%d): %s\n",
720 (int)capability,
721 strerror(errno)));
722 cap_free(cap);
723 return false;
726 if (cap_set_proc(cap) == -1) {
727 DEBUG(0, ("set_process_capability: cap_set_flag (%d) failed: %s\n",
728 (int)capability,
729 strerror(errno)));
730 cap_free(cap);
731 return False;
734 cap_free(cap);
735 return True;
738 #endif /* HAVE_POSIX_CAPABILITIES */
740 /****************************************************************************
741 Gain the oplock capability from the kernel if possible.
742 ****************************************************************************/
744 void set_effective_capability(enum smbd_capability capability)
746 #if defined(HAVE_POSIX_CAPABILITIES)
747 set_process_capability(capability, True);
748 #endif /* HAVE_POSIX_CAPABILITIES */
751 void drop_effective_capability(enum smbd_capability capability)
753 #if defined(HAVE_POSIX_CAPABILITIES)
754 set_process_capability(capability, False);
755 #endif /* HAVE_POSIX_CAPABILITIES */
758 /**************************************************************************
759 Wrapper for random().
760 ****************************************************************************/
762 long sys_random(void)
764 #if defined(HAVE_RANDOM)
765 return (long)random();
766 #elif defined(HAVE_RAND)
767 return (long)rand();
768 #else
769 DEBUG(0,("Error - no random function available !\n"));
770 exit(1);
771 #endif
774 /**************************************************************************
775 Wrapper for srandom().
776 ****************************************************************************/
778 void sys_srandom(unsigned int seed)
780 #if defined(HAVE_SRANDOM)
781 srandom(seed);
782 #elif defined(HAVE_SRAND)
783 srand(seed);
784 #else
785 DEBUG(0,("Error - no srandom function available !\n"));
786 exit(1);
787 #endif
790 /**************************************************************************
791 Returns equivalent to NGROUPS_MAX - using sysconf if needed.
792 ****************************************************************************/
794 int groups_max(void)
796 #if defined(SYSCONF_SC_NGROUPS_MAX)
797 int ret = sysconf(_SC_NGROUPS_MAX);
798 return (ret == -1) ? NGROUPS_MAX : ret;
799 #else
800 return NGROUPS_MAX;
801 #endif
804 /**************************************************************************
805 Wrap setgroups and getgroups for systems that declare getgroups() as
806 returning an array of gid_t, but actuall return an array of int.
807 ****************************************************************************/
809 #if defined(HAVE_BROKEN_GETGROUPS)
810 static int sys_broken_getgroups(int setlen, gid_t *gidset)
812 GID_T gid;
813 GID_T *group_list;
814 int i, ngroups;
816 if(setlen == 0) {
817 return getgroups(setlen, &gid);
821 * Broken case. We need to allocate a
822 * GID_T array of size setlen.
825 if(setlen < 0) {
826 errno = EINVAL;
827 return -1;
830 if (setlen == 0)
831 setlen = groups_max();
833 if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
834 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
835 return -1;
838 if((ngroups = getgroups(setlen, group_list)) < 0) {
839 int saved_errno = errno;
840 SAFE_FREE(group_list);
841 errno = saved_errno;
842 return -1;
845 for(i = 0; i < ngroups; i++)
846 gidset[i] = (gid_t)group_list[i];
848 SAFE_FREE(group_list);
849 return ngroups;
852 static int sys_broken_setgroups(int setlen, gid_t *gidset)
854 GID_T *group_list;
855 int i ;
857 if (setlen == 0)
858 return 0 ;
860 if (setlen < 0 || setlen > groups_max()) {
861 errno = EINVAL;
862 return -1;
866 * Broken case. We need to allocate a
867 * GID_T array of size setlen.
870 if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
871 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
872 return -1;
875 for(i = 0; i < setlen; i++)
876 group_list[i] = (GID_T) gidset[i];
878 if(setgroups(setlen, group_list) != 0) {
879 int saved_errno = errno;
880 SAFE_FREE(group_list);
881 errno = saved_errno;
882 return -1;
885 SAFE_FREE(group_list);
886 return 0 ;
889 #endif /* HAVE_BROKEN_GETGROUPS */
891 /* This is a list of systems that require the first GID passed to setgroups(2)
892 * to be the effective GID. If your system is one of these, add it here.
894 #if defined (FREEBSD) || defined (DARWINOS)
895 #define USE_BSD_SETGROUPS
896 #endif
898 #if defined(USE_BSD_SETGROUPS)
899 /* Depending on the particular BSD implementation, the first GID that is
900 * passed to setgroups(2) will either be ignored or will set the credential's
901 * effective GID. In either case, the right thing to do is to guarantee that
902 * gidset[0] is the effective GID.
904 static int sys_bsd_setgroups(gid_t primary_gid, int setlen, const gid_t *gidset)
906 gid_t *new_gidset = NULL;
907 int max;
908 int ret;
910 /* setgroups(2) will fail with EINVAL if we pass too many groups. */
911 max = groups_max();
913 /* No group list, just make sure we are setting the efective GID. */
914 if (setlen == 0) {
915 return setgroups(1, &primary_gid);
918 /* If the primary gid is not the first array element, grow the array
919 * and insert it at the front.
921 if (gidset[0] != primary_gid) {
922 new_gidset = SMB_MALLOC_ARRAY(gid_t, setlen + 1);
923 if (new_gidset == NULL) {
924 return -1;
927 memcpy(new_gidset + 1, gidset, (setlen * sizeof(gid_t)));
928 new_gidset[0] = primary_gid;
929 setlen++;
932 if (setlen > max) {
933 DEBUG(3, ("forced to truncate group list from %d to %d\n",
934 setlen, max));
935 setlen = max;
938 #if defined(HAVE_BROKEN_GETGROUPS)
939 ret = sys_broken_setgroups(setlen, new_gidset ? new_gidset : gidset);
940 #else
941 ret = setgroups(setlen, new_gidset ? new_gidset : gidset);
942 #endif
944 if (new_gidset) {
945 int errsav = errno;
946 SAFE_FREE(new_gidset);
947 errno = errsav;
950 return ret;
953 #endif /* USE_BSD_SETGROUPS */
955 /**************************************************************************
956 Wrapper for getgroups. Deals with broken (int) case.
957 ****************************************************************************/
959 int sys_getgroups(int setlen, gid_t *gidset)
961 #if defined(HAVE_BROKEN_GETGROUPS)
962 return sys_broken_getgroups(setlen, gidset);
963 #else
964 return getgroups(setlen, gidset);
965 #endif
968 /**************************************************************************
969 Wrapper for setgroups. Deals with broken (int) case and BSD case.
970 ****************************************************************************/
972 int sys_setgroups(gid_t UNUSED(primary_gid), int setlen, gid_t *gidset)
974 #if !defined(HAVE_SETGROUPS)
975 errno = ENOSYS;
976 return -1;
977 #endif /* HAVE_SETGROUPS */
979 #if defined(USE_BSD_SETGROUPS)
980 return sys_bsd_setgroups(primary_gid, setlen, gidset);
981 #elif defined(HAVE_BROKEN_GETGROUPS)
982 return sys_broken_setgroups(setlen, gidset);
983 #else
984 return setgroups(setlen, gidset);
985 #endif
988 /**************************************************************************
989 Wrappers for setpwent(), getpwent() and endpwent()
990 ****************************************************************************/
992 void sys_setpwent(void)
994 setpwent();
997 struct passwd *sys_getpwent(void)
999 return getpwent();
1002 void sys_endpwent(void)
1004 endpwent();
1007 /**************************************************************************
1008 Wrappers for getpwnam(), getpwuid(), getgrnam(), getgrgid()
1009 ****************************************************************************/
1012 struct passwd *sys_getpwnam(const char *name)
1014 return getpwnam(name);
1017 struct passwd *sys_getpwuid(uid_t uid)
1019 return getpwuid(uid);
1022 struct group *sys_getgrnam(const char *name)
1024 return getgrnam(name);
1027 struct group *sys_getgrgid(gid_t gid)
1029 return getgrgid(gid);
1032 /**************************************************************************
1033 Extract a command into an arg list.
1034 ****************************************************************************/
1036 static char **extract_args(TALLOC_CTX *mem_ctx, const char *command)
1038 char *trunc_cmd;
1039 char *saveptr;
1040 char *ptr;
1041 int argcl;
1042 char **argl = NULL;
1043 int i;
1045 if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1046 DEBUG(0, ("talloc failed\n"));
1047 goto nomem;
1050 if(!(ptr = strtok_r(trunc_cmd, " \t", &saveptr))) {
1051 TALLOC_FREE(trunc_cmd);
1052 errno = EINVAL;
1053 return NULL;
1057 * Count the args.
1060 for( argcl = 1; ptr; ptr = strtok_r(NULL, " \t", &saveptr))
1061 argcl++;
1063 TALLOC_FREE(trunc_cmd);
1065 if (!(argl = TALLOC_ARRAY(mem_ctx, char *, argcl + 1))) {
1066 goto nomem;
1070 * Now do the extraction.
1073 if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1074 goto nomem;
1077 ptr = strtok_r(trunc_cmd, " \t", &saveptr);
1078 i = 0;
1080 if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1081 goto nomem;
1084 while((ptr = strtok_r(NULL, " \t", &saveptr)) != NULL) {
1086 if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1087 goto nomem;
1091 argl[i++] = NULL;
1092 return argl;
1094 nomem:
1095 DEBUG(0, ("talloc failed\n"));
1096 TALLOC_FREE(trunc_cmd);
1097 TALLOC_FREE(argl);
1098 errno = ENOMEM;
1099 return NULL;
1102 /**************************************************************************
1103 Wrapper for popen. Safer as it doesn't search a path.
1104 Modified from the glibc sources.
1105 modified by tridge to return a file descriptor. We must kick our FILE* habit
1106 ****************************************************************************/
1108 typedef struct _popen_list
1110 int fd;
1111 pid_t child_pid;
1112 struct _popen_list *next;
1113 } popen_list;
1115 static popen_list *popen_chain;
1117 int sys_popen(const char *command)
1119 int parent_end, child_end;
1120 int pipe_fds[2];
1121 popen_list *entry = NULL;
1122 char **argl = NULL;
1124 if (pipe(pipe_fds) < 0)
1125 return -1;
1127 parent_end = pipe_fds[0];
1128 child_end = pipe_fds[1];
1130 if (!*command) {
1131 errno = EINVAL;
1132 goto err_exit;
1135 if((entry = SMB_MALLOC_P(popen_list)) == NULL)
1136 goto err_exit;
1138 ZERO_STRUCTP(entry);
1141 * Extract the command and args into a NULL terminated array.
1144 if(!(argl = extract_args(NULL, command)))
1145 goto err_exit;
1147 entry->child_pid = sys_fork();
1149 if (entry->child_pid == -1) {
1150 goto err_exit;
1153 if (entry->child_pid == 0) {
1156 * Child !
1159 int child_std_end = STDOUT_FILENO;
1160 popen_list *p;
1162 close(parent_end);
1163 if (child_end != child_std_end) {
1164 dup2 (child_end, child_std_end);
1165 close (child_end);
1169 * POSIX.2: "popen() shall ensure that any streams from previous
1170 * popen() calls that remain open in the parent process are closed
1171 * in the new child process."
1174 for (p = popen_chain; p; p = p->next)
1175 close(p->fd);
1177 execv(argl[0], argl);
1178 _exit (127);
1182 * Parent.
1185 close (child_end);
1186 TALLOC_FREE(argl);
1188 /* Link into popen_chain. */
1189 entry->next = popen_chain;
1190 popen_chain = entry;
1191 entry->fd = parent_end;
1193 return entry->fd;
1195 err_exit:
1197 SAFE_FREE(entry);
1198 SAFE_FREE(argl);
1199 close(pipe_fds[0]);
1200 close(pipe_fds[1]);
1201 return -1;
1204 /**************************************************************************
1205 Wrapper for pclose. Modified from the glibc sources.
1206 ****************************************************************************/
1208 int sys_pclose(int fd)
1210 int wstatus;
1211 popen_list **ptr = &popen_chain;
1212 popen_list *entry = NULL;
1213 pid_t wait_pid;
1214 int status = -1;
1216 /* Unlink from popen_chain. */
1217 for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
1218 if ((*ptr)->fd == fd) {
1219 entry = *ptr;
1220 *ptr = (*ptr)->next;
1221 status = 0;
1222 break;
1226 if (status < 0 || close(entry->fd) < 0)
1227 return -1;
1230 * As Samba is catching and eating child process
1231 * exits we don't really care about the child exit
1232 * code, a -1 with errno = ECHILD will do fine for us.
1235 do {
1236 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
1237 } while (wait_pid == -1 && errno == EINTR);
1239 SAFE_FREE(entry);
1241 if (wait_pid == -1)
1242 return -1;
1243 return wstatus;
1246 /**************************************************************************
1247 Wrapper for Admin Logs.
1248 ****************************************************************************/
1250 void sys_adminlog(int priority, const char *format_str, ...)
1252 va_list ap;
1253 int ret;
1254 char *msgbuf = NULL;
1256 va_start( ap, format_str );
1257 ret = vasprintf( &msgbuf, format_str, ap );
1258 va_end( ap );
1260 if (ret == -1)
1261 return;
1263 #if defined(HAVE_SYSLOG)
1264 syslog( priority, "%s", msgbuf );
1265 #else
1266 DEBUG(0,("%s", msgbuf ));
1267 #endif
1268 SAFE_FREE(msgbuf);
1271 /******** Solaris EA helper function prototypes ********/
1272 #ifdef HAVE_ATTROPEN
1273 #define SOLARIS_ATTRMODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP
1274 static int solaris_write_xattr(int attrfd, const char *value, size_t size);
1275 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size);
1276 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size);
1277 static int solaris_unlinkat(int attrdirfd, const char *name);
1278 static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode);
1279 static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode);
1280 #endif
1282 /**************************************************************************
1283 Wrappers for extented attribute calls. Based on the Linux package with
1284 support for IRIX and (Net|Free)BSD also. Expand as other systems have them.
1285 ****************************************************************************/
1287 ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t size)
1289 #if defined(HAVE_GETXATTR)
1290 #ifndef XATTR_ADD_OPT
1291 return getxattr(path, name, value, size);
1292 #else
1293 int options = 0;
1294 return getxattr(path, name, value, size, 0, options);
1295 #endif
1296 #elif defined(HAVE_GETEA)
1297 return getea(path, name, value, size);
1298 #elif defined(HAVE_EXTATTR_GET_FILE)
1299 char *s;
1300 ssize_t retval;
1301 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1302 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1303 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1305 * The BSD implementation has a nasty habit of silently truncating
1306 * the returned value to the size of the buffer, so we have to check
1307 * that the buffer is large enough to fit the returned value.
1309 if((retval=extattr_get_file(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1310 if(retval > size) {
1311 errno = ERANGE;
1312 return -1;
1314 if((retval=extattr_get_file(path, attrnamespace, attrname, value, size)) >= 0)
1315 return retval;
1318 DEBUG(10,("sys_getxattr: extattr_get_file() failed with: %s\n", strerror(errno)));
1319 return -1;
1320 #elif defined(HAVE_ATTR_GET)
1321 int retval, flags = 0;
1322 int valuelength = (int)size;
1323 char *attrname = strchr(name,'.') + 1;
1325 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1327 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1329 return retval ? retval : valuelength;
1330 #elif defined(HAVE_ATTROPEN)
1331 ssize_t ret = -1;
1332 int attrfd = solaris_attropen(path, name, O_RDONLY, 0);
1333 if (attrfd >= 0) {
1334 ret = solaris_read_xattr(attrfd, value, size);
1335 close(attrfd);
1337 return ret;
1338 #else
1339 errno = ENOSYS;
1340 return -1;
1341 #endif
1344 ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t size)
1346 #if defined(HAVE_LGETXATTR)
1347 return lgetxattr(path, name, value, size);
1348 #elif defined(HAVE_GETXATTR) && defined(XATTR_ADD_OPT)
1349 int options = XATTR_NOFOLLOW;
1350 return getxattr(path, name, value, size, 0, options);
1351 #elif defined(HAVE_LGETEA)
1352 return lgetea(path, name, value, size);
1353 #elif defined(HAVE_EXTATTR_GET_LINK)
1354 char *s;
1355 ssize_t retval;
1356 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1357 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1358 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1360 if((retval=extattr_get_link(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1361 if(retval > size) {
1362 errno = ERANGE;
1363 return -1;
1365 if((retval=extattr_get_link(path, attrnamespace, attrname, value, size)) >= 0)
1366 return retval;
1369 DEBUG(10,("sys_lgetxattr: extattr_get_link() failed with: %s\n", strerror(errno)));
1370 return -1;
1371 #elif defined(HAVE_ATTR_GET)
1372 int retval, flags = ATTR_DONTFOLLOW;
1373 int valuelength = (int)size;
1374 char *attrname = strchr(name,'.') + 1;
1376 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1378 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1380 return retval ? retval : valuelength;
1381 #elif defined(HAVE_ATTROPEN)
1382 ssize_t ret = -1;
1383 int attrfd = solaris_attropen(path, name, O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1384 if (attrfd >= 0) {
1385 ret = solaris_read_xattr(attrfd, value, size);
1386 close(attrfd);
1388 return ret;
1389 #else
1390 errno = ENOSYS;
1391 return -1;
1392 #endif
1395 ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size)
1397 #if defined(HAVE_FGETXATTR)
1398 #ifndef XATTR_ADD_OPT
1399 return fgetxattr(filedes, name, value, size);
1400 #else
1401 int options = 0;
1402 return fgetxattr(filedes, name, value, size, 0, options);
1403 #endif
1404 #elif defined(HAVE_FGETEA)
1405 return fgetea(filedes, name, value, size);
1406 #elif defined(HAVE_EXTATTR_GET_FD)
1407 char *s;
1408 ssize_t retval;
1409 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1410 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1411 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1413 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0)) >= 0) {
1414 if(retval > size) {
1415 errno = ERANGE;
1416 return -1;
1418 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, value, size)) >= 0)
1419 return retval;
1422 DEBUG(10,("sys_fgetxattr: extattr_get_fd() failed with: %s\n", strerror(errno)));
1423 return -1;
1424 #elif defined(HAVE_ATTR_GETF)
1425 int retval, flags = 0;
1426 int valuelength = (int)size;
1427 char *attrname = strchr(name,'.') + 1;
1429 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1431 retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags);
1433 return retval ? retval : valuelength;
1434 #elif defined(HAVE_ATTROPEN)
1435 ssize_t ret = -1;
1436 int attrfd = solaris_openat(filedes, name, O_RDONLY|O_XATTR, 0);
1437 if (attrfd >= 0) {
1438 ret = solaris_read_xattr(attrfd, value, size);
1439 close(attrfd);
1441 return ret;
1442 #else
1443 errno = ENOSYS;
1444 return -1;
1445 #endif
1448 #if defined(HAVE_EXTATTR_LIST_FILE)
1450 #define EXTATTR_PREFIX(s) (s), (sizeof((s))-1)
1452 static struct {
1453 int space;
1454 const char *name;
1455 size_t len;
1457 extattr[] = {
1458 { EXTATTR_NAMESPACE_SYSTEM, EXTATTR_PREFIX("system.") },
1459 { EXTATTR_NAMESPACE_USER, EXTATTR_PREFIX("user.") },
1462 typedef union {
1463 const char *path;
1464 int filedes;
1465 } extattr_arg;
1467 static ssize_t bsd_attr_list (int type, extattr_arg arg, char *list, size_t size)
1469 ssize_t list_size, total_size = 0;
1470 int i, t, len;
1471 char *buf;
1472 /* Iterate through extattr(2) namespaces */
1473 for(t = 0; t < (sizeof(extattr)/sizeof(extattr[0])); t++) {
1474 switch(type) {
1475 #if defined(HAVE_EXTATTR_LIST_FILE)
1476 case 0:
1477 list_size = extattr_list_file(arg.path, extattr[t].space, list, size);
1478 break;
1479 #endif
1480 #if defined(HAVE_EXTATTR_LIST_LINK)
1481 case 1:
1482 list_size = extattr_list_link(arg.path, extattr[t].space, list, size);
1483 break;
1484 #endif
1485 #if defined(HAVE_EXTATTR_LIST_FD)
1486 case 2:
1487 list_size = extattr_list_fd(arg.filedes, extattr[t].space, list, size);
1488 break;
1489 #endif
1490 default:
1491 errno = ENOSYS;
1492 return -1;
1494 /* Some error happend. Errno should be set by the previous call */
1495 if(list_size < 0)
1496 return -1;
1497 /* No attributes */
1498 if(list_size == 0)
1499 continue;
1500 /* XXX: Call with an empty buffer may be used to calculate
1501 necessary buffer size. Unfortunately, we can't say, how
1502 many attributes were returned, so here is the potential
1503 problem with the emulation.
1505 if(list == NULL) {
1506 /* Take the worse case of one char attribute names -
1507 two bytes per name plus one more for sanity.
1509 total_size += list_size + (list_size/2 + 1)*extattr[t].len;
1510 continue;
1512 /* Count necessary offset to fit namespace prefixes */
1513 len = 0;
1514 for(i = 0; i < list_size; i += list[i] + 1)
1515 len += extattr[t].len;
1517 total_size += list_size + len;
1518 /* Buffer is too small to fit the results */
1519 if(total_size > size) {
1520 errno = ERANGE;
1521 return -1;
1523 /* Shift results back, so we can prepend prefixes */
1524 buf = memmove(list + len, list, list_size);
1526 for(i = 0; i < list_size; i += len + 1) {
1527 len = buf[i];
1528 strncpy(list, extattr[t].name, extattr[t].len + 1);
1529 list += extattr[t].len;
1530 strncpy(list, buf + i + 1, len);
1531 list[len] = '\0';
1532 list += len + 1;
1534 size -= total_size;
1536 return total_size;
1539 #endif
1541 #if defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1542 static char attr_buffer[ATTR_MAX_VALUELEN];
1544 static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags)
1546 int retval = 0, index;
1547 attrlist_cursor_t *cursor = 0;
1548 int total_size = 0;
1549 attrlist_t * al = (attrlist_t *)attr_buffer;
1550 attrlist_ent_t *ae;
1551 size_t ent_size, left = size;
1552 char *bp = list;
1554 while (True) {
1555 if (filedes)
1556 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1557 else
1558 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1559 if (retval) break;
1560 for (index = 0; index < al->al_count; index++) {
1561 ae = ATTR_ENTRY(attr_buffer, index);
1562 ent_size = strlen(ae->a_name) + sizeof("user.");
1563 if (left >= ent_size) {
1564 strncpy(bp, "user.", sizeof("user."));
1565 strncat(bp, ae->a_name, ent_size - sizeof("user."));
1566 bp += ent_size;
1567 left -= ent_size;
1568 } else if (size) {
1569 errno = ERANGE;
1570 retval = -1;
1571 break;
1573 total_size += ent_size;
1575 if (al->al_more == 0) break;
1577 if (retval == 0) {
1578 flags |= ATTR_ROOT;
1579 cursor = 0;
1580 while (True) {
1581 if (filedes)
1582 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1583 else
1584 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1585 if (retval) break;
1586 for (index = 0; index < al->al_count; index++) {
1587 ae = ATTR_ENTRY(attr_buffer, index);
1588 ent_size = strlen(ae->a_name) + sizeof("system.");
1589 if (left >= ent_size) {
1590 strncpy(bp, "system.", sizeof("system."));
1591 strncat(bp, ae->a_name, ent_size - sizeof("system."));
1592 bp += ent_size;
1593 left -= ent_size;
1594 } else if (size) {
1595 errno = ERANGE;
1596 retval = -1;
1597 break;
1599 total_size += ent_size;
1601 if (al->al_more == 0) break;
1604 return (ssize_t)(retval ? retval : total_size);
1607 #endif
1609 ssize_t sys_listxattr (const char *path, char *list, size_t size)
1611 #if defined(HAVE_LISTXATTR)
1612 #ifndef XATTR_ADD_OPT
1613 return listxattr(path, list, size);
1614 #else
1615 int options = 0;
1616 return listxattr(path, list, size, options);
1617 #endif
1618 #elif defined(HAVE_LISTEA)
1619 return listea(path, list, size);
1620 #elif defined(HAVE_EXTATTR_LIST_FILE)
1621 extattr_arg arg;
1622 arg.path = path;
1623 return bsd_attr_list(0, arg, list, size);
1624 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1625 return irix_attr_list(path, 0, list, size, 0);
1626 #elif defined(HAVE_ATTROPEN)
1627 ssize_t ret = -1;
1628 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
1629 if (attrdirfd >= 0) {
1630 ret = solaris_list_xattr(attrdirfd, list, size);
1631 close(attrdirfd);
1633 return ret;
1634 #else
1635 errno = ENOSYS;
1636 return -1;
1637 #endif
1640 ssize_t sys_llistxattr (const char *path, char *list, size_t size)
1642 #if defined(HAVE_LLISTXATTR)
1643 return llistxattr(path, list, size);
1644 #elif defined(HAVE_LISTXATTR) && defined(XATTR_ADD_OPT)
1645 int options = XATTR_NOFOLLOW;
1646 return listxattr(path, list, size, options);
1647 #elif defined(HAVE_LLISTEA)
1648 return llistea(path, list, size);
1649 #elif defined(HAVE_EXTATTR_LIST_LINK)
1650 extattr_arg arg;
1651 arg.path = path;
1652 return bsd_attr_list(1, arg, list, size);
1653 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1654 return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW);
1655 #elif defined(HAVE_ATTROPEN)
1656 ssize_t ret = -1;
1657 int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1658 if (attrdirfd >= 0) {
1659 ret = solaris_list_xattr(attrdirfd, list, size);
1660 close(attrdirfd);
1662 return ret;
1663 #else
1664 errno = ENOSYS;
1665 return -1;
1666 #endif
1669 ssize_t sys_flistxattr (int filedes, char *list, size_t size)
1671 #if defined(HAVE_FLISTXATTR)
1672 #ifndef XATTR_ADD_OPT
1673 return flistxattr(filedes, list, size);
1674 #else
1675 int options = 0;
1676 return flistxattr(filedes, list, size, options);
1677 #endif
1678 #elif defined(HAVE_FLISTEA)
1679 return flistea(filedes, list, size);
1680 #elif defined(HAVE_EXTATTR_LIST_FD)
1681 extattr_arg arg;
1682 arg.filedes = filedes;
1683 return bsd_attr_list(2, arg, list, size);
1684 #elif defined(HAVE_ATTR_LISTF)
1685 return irix_attr_list(NULL, filedes, list, size, 0);
1686 #elif defined(HAVE_ATTROPEN)
1687 ssize_t ret = -1;
1688 int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
1689 if (attrdirfd >= 0) {
1690 ret = solaris_list_xattr(attrdirfd, list, size);
1691 close(attrdirfd);
1693 return ret;
1694 #else
1695 errno = ENOSYS;
1696 return -1;
1697 #endif
1700 int sys_removexattr (const char *path, const char *name)
1702 #if defined(HAVE_REMOVEXATTR)
1703 #ifndef XATTR_ADD_OPT
1704 return removexattr(path, name);
1705 #else
1706 int options = 0;
1707 return removexattr(path, name, options);
1708 #endif
1709 #elif defined(HAVE_REMOVEEA)
1710 return removeea(path, name);
1711 #elif defined(HAVE_EXTATTR_DELETE_FILE)
1712 char *s;
1713 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1714 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1715 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1717 return extattr_delete_file(path, attrnamespace, attrname);
1718 #elif defined(HAVE_ATTR_REMOVE)
1719 int flags = 0;
1720 char *attrname = strchr(name,'.') + 1;
1722 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1724 return attr_remove(path, attrname, flags);
1725 #elif defined(HAVE_ATTROPEN)
1726 int ret = -1;
1727 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
1728 if (attrdirfd >= 0) {
1729 ret = solaris_unlinkat(attrdirfd, name);
1730 close(attrdirfd);
1732 return ret;
1733 #else
1734 errno = ENOSYS;
1735 return -1;
1736 #endif
1739 int sys_lremovexattr (const char *path, const char *name)
1741 #if defined(HAVE_LREMOVEXATTR)
1742 return lremovexattr(path, name);
1743 #elif defined(HAVE_REMOVEXATTR) && defined(XATTR_ADD_OPT)
1744 int options = XATTR_NOFOLLOW;
1745 return removexattr(path, name, options);
1746 #elif defined(HAVE_LREMOVEEA)
1747 return lremoveea(path, name);
1748 #elif defined(HAVE_EXTATTR_DELETE_LINK)
1749 char *s;
1750 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1751 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1752 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1754 return extattr_delete_link(path, attrnamespace, attrname);
1755 #elif defined(HAVE_ATTR_REMOVE)
1756 int flags = ATTR_DONTFOLLOW;
1757 char *attrname = strchr(name,'.') + 1;
1759 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1761 return attr_remove(path, attrname, flags);
1762 #elif defined(HAVE_ATTROPEN)
1763 int ret = -1;
1764 int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1765 if (attrdirfd >= 0) {
1766 ret = solaris_unlinkat(attrdirfd, name);
1767 close(attrdirfd);
1769 return ret;
1770 #else
1771 errno = ENOSYS;
1772 return -1;
1773 #endif
1776 int sys_fremovexattr (int filedes, const char *name)
1778 #if defined(HAVE_FREMOVEXATTR)
1779 #ifndef XATTR_ADD_OPT
1780 return fremovexattr(filedes, name);
1781 #else
1782 int options = 0;
1783 return fremovexattr(filedes, name, options);
1784 #endif
1785 #elif defined(HAVE_FREMOVEEA)
1786 return fremoveea(filedes, name);
1787 #elif defined(HAVE_EXTATTR_DELETE_FD)
1788 char *s;
1789 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1790 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1791 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1793 return extattr_delete_fd(filedes, attrnamespace, attrname);
1794 #elif defined(HAVE_ATTR_REMOVEF)
1795 int flags = 0;
1796 char *attrname = strchr(name,'.') + 1;
1798 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1800 return attr_removef(filedes, attrname, flags);
1801 #elif defined(HAVE_ATTROPEN)
1802 int ret = -1;
1803 int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
1804 if (attrdirfd >= 0) {
1805 ret = solaris_unlinkat(attrdirfd, name);
1806 close(attrdirfd);
1808 return ret;
1809 #else
1810 errno = ENOSYS;
1811 return -1;
1812 #endif
1815 int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags)
1817 #if defined(HAVE_SETXATTR)
1818 #ifndef XATTR_ADD_OPT
1819 return setxattr(path, name, value, size, flags);
1820 #else
1821 int options = 0;
1822 return setxattr(path, name, value, size, 0, options);
1823 #endif
1824 #elif defined(HAVE_SETEA)
1825 return setea(path, name, value, size, flags);
1826 #elif defined(HAVE_EXTATTR_SET_FILE)
1827 char *s;
1828 int retval = 0;
1829 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1830 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1831 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1832 if (flags) {
1833 /* Check attribute existence */
1834 retval = extattr_get_file(path, attrnamespace, attrname, NULL, 0);
1835 if (retval < 0) {
1836 /* REPLACE attribute, that doesn't exist */
1837 if (flags & XATTR_REPLACE && errno == ENOATTR) {
1838 errno = ENOATTR;
1839 return -1;
1841 /* Ignore other errors */
1843 else {
1844 /* CREATE attribute, that already exists */
1845 if (flags & XATTR_CREATE) {
1846 errno = EEXIST;
1847 return -1;
1851 retval = extattr_set_file(path, attrnamespace, attrname, value, size);
1852 return (retval < 0) ? -1 : 0;
1853 #elif defined(HAVE_ATTR_SET)
1854 int myflags = 0;
1855 char *attrname = strchr(name,'.') + 1;
1857 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
1858 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
1859 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
1861 return attr_set(path, attrname, (const char *)value, size, myflags);
1862 #elif defined(HAVE_ATTROPEN)
1863 int ret = -1;
1864 int myflags = O_RDWR;
1865 int attrfd;
1866 if (flags & XATTR_CREATE) myflags |= O_EXCL;
1867 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
1868 attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
1869 if (attrfd >= 0) {
1870 ret = solaris_write_xattr(attrfd, value, size);
1871 close(attrfd);
1873 return ret;
1874 #else
1875 errno = ENOSYS;
1876 return -1;
1877 #endif
1880 int sys_lsetxattr (const char *path, const char *name, const void *value, size_t size, int flags)
1882 #if defined(HAVE_LSETXATTR)
1883 return lsetxattr(path, name, value, size, flags);
1884 #elif defined(HAVE_SETXATTR) && defined(XATTR_ADD_OPT)
1885 int options = XATTR_NOFOLLOW;
1886 return setxattr(path, name, value, size, 0, options);
1887 #elif defined(LSETEA)
1888 return lsetea(path, name, value, size, flags);
1889 #elif defined(HAVE_EXTATTR_SET_LINK)
1890 char *s;
1891 int retval = 0;
1892 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1893 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1894 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1895 if (flags) {
1896 /* Check attribute existence */
1897 retval = extattr_get_link(path, attrnamespace, attrname, NULL, 0);
1898 if (retval < 0) {
1899 /* REPLACE attribute, that doesn't exist */
1900 if (flags & XATTR_REPLACE && errno == ENOATTR) {
1901 errno = ENOATTR;
1902 return -1;
1904 /* Ignore other errors */
1906 else {
1907 /* CREATE attribute, that already exists */
1908 if (flags & XATTR_CREATE) {
1909 errno = EEXIST;
1910 return -1;
1915 retval = extattr_set_link(path, attrnamespace, attrname, value, size);
1916 return (retval < 0) ? -1 : 0;
1917 #elif defined(HAVE_ATTR_SET)
1918 int myflags = ATTR_DONTFOLLOW;
1919 char *attrname = strchr(name,'.') + 1;
1921 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
1922 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
1923 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
1925 return attr_set(path, attrname, (const char *)value, size, myflags);
1926 #elif defined(HAVE_ATTROPEN)
1927 int ret = -1;
1928 int myflags = O_RDWR | AT_SYMLINK_NOFOLLOW;
1929 int attrfd;
1930 if (flags & XATTR_CREATE) myflags |= O_EXCL;
1931 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
1932 attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
1933 if (attrfd >= 0) {
1934 ret = solaris_write_xattr(attrfd, value, size);
1935 close(attrfd);
1937 return ret;
1938 #else
1939 errno = ENOSYS;
1940 return -1;
1941 #endif
1944 int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags)
1946 #if defined(HAVE_FSETXATTR)
1947 #ifndef XATTR_ADD_OPT
1948 return fsetxattr(filedes, name, value, size, flags);
1949 #else
1950 int options = 0;
1951 return fsetxattr(filedes, name, value, size, 0, options);
1952 #endif
1953 #elif defined(HAVE_FSETEA)
1954 return fsetea(filedes, name, value, size, flags);
1955 #elif defined(HAVE_EXTATTR_SET_FD)
1956 char *s;
1957 int retval = 0;
1958 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1959 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1960 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1961 if (flags) {
1962 /* Check attribute existence */
1963 retval = extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0);
1964 if (retval < 0) {
1965 /* REPLACE attribute, that doesn't exist */
1966 if (flags & XATTR_REPLACE && errno == ENOATTR) {
1967 errno = ENOATTR;
1968 return -1;
1970 /* Ignore other errors */
1972 else {
1973 /* CREATE attribute, that already exists */
1974 if (flags & XATTR_CREATE) {
1975 errno = EEXIST;
1976 return -1;
1980 retval = extattr_set_fd(filedes, attrnamespace, attrname, value, size);
1981 return (retval < 0) ? -1 : 0;
1982 #elif defined(HAVE_ATTR_SETF)
1983 int myflags = 0;
1984 char *attrname = strchr(name,'.') + 1;
1986 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
1987 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
1988 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
1990 return attr_setf(filedes, attrname, (const char *)value, size, myflags);
1991 #elif defined(HAVE_ATTROPEN)
1992 int ret = -1;
1993 int myflags = O_RDWR | O_XATTR;
1994 int attrfd;
1995 if (flags & XATTR_CREATE) myflags |= O_EXCL;
1996 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
1997 attrfd = solaris_openat(filedes, name, myflags, (mode_t) SOLARIS_ATTRMODE);
1998 if (attrfd >= 0) {
1999 ret = solaris_write_xattr(attrfd, value, size);
2000 close(attrfd);
2002 return ret;
2003 #else
2004 errno = ENOSYS;
2005 return -1;
2006 #endif
2009 /**************************************************************************
2010 helper functions for Solaris' EA support
2011 ****************************************************************************/
2012 #ifdef HAVE_ATTROPEN
2013 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size)
2015 struct stat sbuf;
2017 if (fstat(attrfd, &sbuf) == -1) {
2018 errno = ENOATTR;
2019 return -1;
2022 /* This is to return the current size of the named extended attribute */
2023 if (size == 0) {
2024 return sbuf.st_size;
2027 /* check size and read xattr */
2028 if (sbuf.st_size > size) {
2029 errno = ERANGE;
2030 return -1;
2033 return read(attrfd, value, sbuf.st_size);
2036 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size)
2038 ssize_t len = 0;
2039 DIR *dirp;
2040 struct dirent *de;
2041 int newfd = dup(attrdirfd);
2042 /* CAUTION: The originating file descriptor should not be
2043 used again following the call to fdopendir().
2044 For that reason we dup() the file descriptor
2045 here to make things more clear. */
2046 dirp = fdopendir(newfd);
2048 while ((de = readdir(dirp))) {
2049 size_t listlen = strlen(de->d_name);
2050 if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) {
2051 /* we don't want "." and ".." here: */
2052 DEBUG(10,("skipped EA %s\n",de->d_name));
2053 continue;
2056 if (size == 0) {
2057 /* return the current size of the list of extended attribute names*/
2058 len += listlen + 1;
2059 } else {
2060 /* check size and copy entrieѕ + nul into list. */
2061 if ((len + listlen + 1) > size) {
2062 errno = ERANGE;
2063 len = -1;
2064 break;
2065 } else {
2066 safe_strcpy(list + len, de->d_name, listlen);
2067 len += listlen;
2068 list[len] = '\0';
2069 ++len;
2074 if (closedir(dirp) == -1) {
2075 DEBUG(0,("closedir dirp failed: %s\n",strerror(errno)));
2076 return -1;
2078 return len;
2081 static int solaris_unlinkat(int attrdirfd, const char *name)
2083 if (unlinkat(attrdirfd, name, 0) == -1) {
2084 if (errno == ENOENT) {
2085 errno = ENOATTR;
2087 return -1;
2089 return 0;
2092 static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode)
2094 int filedes = attropen(path, attrpath, oflag, mode);
2095 if (filedes == -1) {
2096 DEBUG(10,("attropen FAILED: path: %s, name: %s, errno: %s\n",path,attrpath,strerror(errno)));
2097 if (errno == EINVAL) {
2098 errno = ENOTSUP;
2099 } else {
2100 errno = ENOATTR;
2103 return filedes;
2106 static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode)
2108 int filedes = openat(fildes, path, oflag, mode);
2109 if (filedes == -1) {
2110 DEBUG(10,("openat FAILED: fd: %d, path: %s, errno: %s\n",filedes,path,strerror(errno)));
2111 if (errno == EINVAL) {
2112 errno = ENOTSUP;
2113 } else {
2114 errno = ENOATTR;
2117 return filedes;
2120 static int solaris_write_xattr(int attrfd, const char *value, size_t size)
2122 if ((ftruncate(attrfd, 0) == 0) && (write(attrfd, value, size) == size)) {
2123 return 0;
2124 } else {
2125 DEBUG(10,("solaris_write_xattr FAILED!\n"));
2126 return -1;
2129 #endif /*HAVE_ATTROPEN*/
2132 /****************************************************************************
2133 Return the major devicenumber for UNIX extensions.
2134 ****************************************************************************/
2136 uint32 unix_dev_major(SMB_DEV_T dev)
2138 #if defined(HAVE_DEVICE_MAJOR_FN)
2139 return (uint32)major(dev);
2140 #else
2141 return (uint32)(dev >> 8);
2142 #endif
2145 /****************************************************************************
2146 Return the minor devicenumber for UNIX extensions.
2147 ****************************************************************************/
2149 uint32 unix_dev_minor(SMB_DEV_T dev)
2151 #if defined(HAVE_DEVICE_MINOR_FN)
2152 return (uint32)minor(dev);
2153 #else
2154 return (uint32)(dev & 0xff);
2155 #endif
2158 #if defined(WITH_AIO)
2160 /*******************************************************************
2161 An aio_read wrapper that will deal with 64-bit sizes.
2162 ********************************************************************/
2164 int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2166 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_READ64)
2167 return aio_read64(aiocb);
2168 #elif defined(HAVE_AIO_READ)
2169 return aio_read(aiocb);
2170 #else
2171 errno = ENOSYS;
2172 return -1;
2173 #endif
2176 /*******************************************************************
2177 An aio_write wrapper that will deal with 64-bit sizes.
2178 ********************************************************************/
2180 int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2182 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_WRITE64)
2183 return aio_write64(aiocb);
2184 #elif defined(HAVE_AIO_WRITE)
2185 return aio_write(aiocb);
2186 #else
2187 errno = ENOSYS;
2188 return -1;
2189 #endif
2192 /*******************************************************************
2193 An aio_return wrapper that will deal with 64-bit sizes.
2194 ********************************************************************/
2196 ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2198 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_RETURN64)
2199 return aio_return64(aiocb);
2200 #elif defined(HAVE_AIO_RETURN)
2201 return aio_return(aiocb);
2202 #else
2203 errno = ENOSYS;
2204 return -1;
2205 #endif
2208 /*******************************************************************
2209 An aio_cancel wrapper that will deal with 64-bit sizes.
2210 ********************************************************************/
2212 int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2214 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_CANCEL64)
2215 return aio_cancel64(fd, aiocb);
2216 #elif defined(HAVE_AIO_CANCEL)
2217 return aio_cancel(fd, aiocb);
2218 #else
2219 errno = ENOSYS;
2220 return -1;
2221 #endif
2224 /*******************************************************************
2225 An aio_error wrapper that will deal with 64-bit sizes.
2226 ********************************************************************/
2228 int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2230 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_ERROR64)
2231 return aio_error64(aiocb);
2232 #elif defined(HAVE_AIO_ERROR)
2233 return aio_error(aiocb);
2234 #else
2235 errno = ENOSYS;
2236 return -1;
2237 #endif
2240 /*******************************************************************
2241 An aio_fsync wrapper that will deal with 64-bit sizes.
2242 ********************************************************************/
2244 int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2246 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_FSYNC64)
2247 return aio_fsync64(op, aiocb);
2248 #elif defined(HAVE_AIO_FSYNC)
2249 return aio_fsync(op, aiocb);
2250 #else
2251 errno = ENOSYS;
2252 return -1;
2253 #endif
2256 /*******************************************************************
2257 An aio_fsync wrapper that will deal with 64-bit sizes.
2258 ********************************************************************/
2260 int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2262 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_SUSPEND64)
2263 return aio_suspend64(cblist, n, timeout);
2264 #elif defined(HAVE_AIO_FSYNC)
2265 return aio_suspend(cblist, n, timeout);
2266 #else
2267 errno = ENOSYS;
2268 return -1;
2269 #endif
2271 #else /* !WITH_AIO */
2273 int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2275 errno = ENOSYS;
2276 return -1;
2279 int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2281 errno = ENOSYS;
2282 return -1;
2285 ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2287 errno = ENOSYS;
2288 return -1;
2291 int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2293 errno = ENOSYS;
2294 return -1;
2297 int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2299 errno = ENOSYS;
2300 return -1;
2303 int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2305 errno = ENOSYS;
2306 return -1;
2309 int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2311 errno = ENOSYS;
2312 return -1;
2314 #endif /* WITH_AIO */
2316 int sys_getpeereid( int s, uid_t *uid)
2318 #if defined(HAVE_PEERCRED)
2319 struct ucred cred;
2320 socklen_t cred_len = sizeof(struct ucred);
2321 int ret;
2323 ret = getsockopt(s, SOL_SOCKET, SO_PEERCRED, (void *)&cred, &cred_len);
2324 if (ret != 0) {
2325 return -1;
2328 if (cred_len != sizeof(struct ucred)) {
2329 errno = EINVAL;
2330 return -1;
2333 *uid = cred.uid;
2334 return 0;
2335 #else
2336 errno = ENOSYS;
2337 return -1;
2338 #endif
2341 int sys_getnameinfo(const struct sockaddr *psa,
2342 socklen_t salen,
2343 char *host,
2344 size_t hostlen,
2345 char *service,
2346 size_t servlen,
2347 int flags)
2350 * For Solaris we must make sure salen is the
2351 * correct length for the incoming sa_family.
2354 if (salen == sizeof(struct sockaddr_storage)) {
2355 salen = sizeof(struct sockaddr_in);
2356 #if defined(HAVE_IPV6)
2357 if (psa->sa_family == AF_INET6) {
2358 salen = sizeof(struct sockaddr_in6);
2360 #endif
2362 return getnameinfo(psa, salen, host, hostlen, service, servlen, flags);
2365 int sys_connect(int fd, const struct sockaddr * addr)
2367 socklen_t salen = -1;
2369 if (addr->sa_family == AF_INET) {
2370 salen = sizeof(struct sockaddr_in);
2371 } else if (addr->sa_family == AF_UNIX) {
2372 salen = sizeof(struct sockaddr_un);
2374 #if defined(HAVE_IPV6)
2375 else if (addr->sa_family == AF_INET6) {
2376 salen = sizeof(struct sockaddr_in6);
2378 #endif
2380 return connect(fd, addr, salen);