Add code to test write_data_iov a bit
[Samba.git] / source / lib / system.c
blob48ecf903d94d65462b2b7d1587a007b64c421931
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 > 1000000) {
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 Wrapper for realpath.
567 ********************************************************************/
569 char *sys_realpath(const char *path, char *resolved_path)
571 #if defined(HAVE_REALPATH)
572 return realpath(path, resolved_path);
573 #else
574 /* As realpath is not a system call we can't return ENOSYS. */
575 errno = EINVAL;
576 return NULL;
577 #endif
580 /*******************************************************************
581 The wait() calls vary between systems
582 ********************************************************************/
584 int sys_waitpid(pid_t pid,int *status,int options)
586 #ifdef HAVE_WAITPID
587 return waitpid(pid,status,options);
588 #else /* HAVE_WAITPID */
589 return wait4(pid, status, options, NULL);
590 #endif /* HAVE_WAITPID */
593 /*******************************************************************
594 System wrapper for getwd
595 ********************************************************************/
597 char *sys_getwd(char *s)
599 char *wd;
600 #ifdef HAVE_GETCWD
601 wd = (char *)getcwd(s, PATH_MAX);
602 #else
603 wd = (char *)getwd(s);
604 #endif
605 return wd;
608 /*******************************************************************
609 system wrapper for symlink
610 ********************************************************************/
612 int sys_symlink(const char *oldpath, const char *newpath)
614 #ifndef HAVE_SYMLINK
615 errno = ENOSYS;
616 return -1;
617 #else
618 return symlink(oldpath, newpath);
619 #endif
622 /*******************************************************************
623 system wrapper for readlink
624 ********************************************************************/
626 int sys_readlink(const char *path, char *buf, size_t bufsiz)
628 #ifndef HAVE_READLINK
629 errno = ENOSYS;
630 return -1;
631 #else
632 return readlink(path, buf, bufsiz);
633 #endif
636 /*******************************************************************
637 system wrapper for link
638 ********************************************************************/
640 int sys_link(const char *oldpath, const char *newpath)
642 #ifndef HAVE_LINK
643 errno = ENOSYS;
644 return -1;
645 #else
646 return link(oldpath, newpath);
647 #endif
650 /*******************************************************************
651 chown isn't used much but OS/2 doesn't have it
652 ********************************************************************/
654 int sys_chown(const char *fname,uid_t uid,gid_t gid)
656 #ifndef HAVE_CHOWN
657 static int done;
658 if (!done) {
659 DEBUG(1,("WARNING: no chown!\n"));
660 done=1;
662 errno = ENOSYS;
663 return -1;
664 #else
665 return(chown(fname,uid,gid));
666 #endif
669 /*******************************************************************
670 Wrapper for lchown.
671 ********************************************************************/
673 int sys_lchown(const char *fname,uid_t uid,gid_t gid)
675 #ifndef HAVE_LCHOWN
676 static int done;
677 if (!done) {
678 DEBUG(1,("WARNING: no lchown!\n"));
679 done=1;
681 errno = ENOSYS;
682 return -1;
683 #else
684 return(lchown(fname,uid,gid));
685 #endif
688 /*******************************************************************
689 os/2 also doesn't have chroot
690 ********************************************************************/
691 int sys_chroot(const char *dname)
693 #ifndef HAVE_CHROOT
694 static int done;
695 if (!done) {
696 DEBUG(1,("WARNING: no chroot!\n"));
697 done=1;
699 errno = ENOSYS;
700 return -1;
701 #else
702 return(chroot(dname));
703 #endif
706 #if defined(HAVE_POSIX_CAPABILITIES)
708 /**************************************************************************
709 Try and abstract process capabilities (for systems that have them).
710 ****************************************************************************/
712 /* Set the POSIX capabilities needed for the given purpose into the effective
713 * capability set of the current process. Make sure they are always removed
714 * from the inheritable set, because there is no circumstance in which our
715 * children should inherit our elevated privileges.
717 static bool set_process_capability(enum smbd_capability capability,
718 bool enable)
720 cap_value_t cap_vals[2] = {0};
721 int num_cap_vals = 0;
723 cap_t cap;
725 #if defined(HAVE_PRCTL) && defined(PR_GET_KEEPCAPS) && defined(PR_SET_KEEPCAPS)
726 /* On Linux, make sure that any capabilities we grab are sticky
727 * across UID changes. We expect that this would allow us to keep both
728 * the effective and permitted capability sets, but as of circa 2.6.16,
729 * only the permitted set is kept. It is a bug (which we work around)
730 * that the effective set is lost, but we still require the effective
731 * set to be kept.
733 if (!prctl(PR_GET_KEEPCAPS)) {
734 prctl(PR_SET_KEEPCAPS, 1);
736 #endif
738 cap = cap_get_proc();
739 if (cap == NULL) {
740 DEBUG(0,("set_process_capability: cap_get_proc failed: %s\n",
741 strerror(errno)));
742 return False;
745 switch (capability) {
746 case KERNEL_OPLOCK_CAPABILITY:
747 #ifdef CAP_NETWORK_MGT
748 /* IRIX has CAP_NETWORK_MGT for oplocks. */
749 cap_vals[num_cap_vals++] = CAP_NETWORK_MGT;
750 #endif
751 break;
752 case DMAPI_ACCESS_CAPABILITY:
753 #ifdef CAP_DEVICE_MGT
754 /* IRIX has CAP_DEVICE_MGT for DMAPI access. */
755 cap_vals[num_cap_vals++] = CAP_DEVICE_MGT;
756 #elif CAP_MKNOD
757 /* Linux has CAP_MKNOD for DMAPI access. */
758 cap_vals[num_cap_vals++] = CAP_MKNOD;
759 #endif
760 break;
761 case LEASE_CAPABILITY:
762 #ifdef CAP_LEASE
763 cap_vals[num_cap_vals++] = CAP_LEASE;
764 #endif
765 break;
768 SMB_ASSERT(num_cap_vals <= ARRAY_SIZE(cap_vals));
770 if (num_cap_vals == 0) {
771 cap_free(cap);
772 return True;
775 cap_set_flag(cap, CAP_EFFECTIVE, num_cap_vals, cap_vals,
776 enable ? CAP_SET : CAP_CLEAR);
778 /* We never want to pass capabilities down to our children, so make
779 * sure they are not inherited.
781 cap_set_flag(cap, CAP_INHERITABLE, num_cap_vals, cap_vals, CAP_CLEAR);
783 if (cap_set_proc(cap) == -1) {
784 DEBUG(0, ("set_process_capability: cap_set_proc failed: %s\n",
785 strerror(errno)));
786 cap_free(cap);
787 return False;
790 cap_free(cap);
791 return True;
794 #endif /* HAVE_POSIX_CAPABILITIES */
796 /****************************************************************************
797 Gain the oplock capability from the kernel if possible.
798 ****************************************************************************/
800 void set_effective_capability(enum smbd_capability capability)
802 #if defined(HAVE_POSIX_CAPABILITIES)
803 set_process_capability(capability, True);
804 #endif /* HAVE_POSIX_CAPABILITIES */
807 void drop_effective_capability(enum smbd_capability capability)
809 #if defined(HAVE_POSIX_CAPABILITIES)
810 set_process_capability(capability, False);
811 #endif /* HAVE_POSIX_CAPABILITIES */
814 /**************************************************************************
815 Wrapper for random().
816 ****************************************************************************/
818 long sys_random(void)
820 #if defined(HAVE_RANDOM)
821 return (long)random();
822 #elif defined(HAVE_RAND)
823 return (long)rand();
824 #else
825 DEBUG(0,("Error - no random function available !\n"));
826 exit(1);
827 #endif
830 /**************************************************************************
831 Wrapper for srandom().
832 ****************************************************************************/
834 void sys_srandom(unsigned int seed)
836 #if defined(HAVE_SRANDOM)
837 srandom(seed);
838 #elif defined(HAVE_SRAND)
839 srand(seed);
840 #else
841 DEBUG(0,("Error - no srandom function available !\n"));
842 exit(1);
843 #endif
846 /**************************************************************************
847 Returns equivalent to NGROUPS_MAX - using sysconf if needed.
848 ****************************************************************************/
850 int groups_max(void)
852 #if defined(SYSCONF_SC_NGROUPS_MAX)
853 int ret = sysconf(_SC_NGROUPS_MAX);
854 return (ret == -1) ? NGROUPS_MAX : ret;
855 #else
856 return NGROUPS_MAX;
857 #endif
860 /**************************************************************************
861 Wrap setgroups and getgroups for systems that declare getgroups() as
862 returning an array of gid_t, but actuall return an array of int.
863 ****************************************************************************/
865 #if defined(HAVE_BROKEN_GETGROUPS)
866 static int sys_broken_getgroups(int setlen, gid_t *gidset)
868 GID_T gid;
869 GID_T *group_list;
870 int i, ngroups;
872 if(setlen == 0) {
873 return getgroups(setlen, &gid);
877 * Broken case. We need to allocate a
878 * GID_T array of size setlen.
881 if(setlen < 0) {
882 errno = EINVAL;
883 return -1;
886 if (setlen == 0)
887 setlen = groups_max();
889 if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
890 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
891 return -1;
894 if((ngroups = getgroups(setlen, group_list)) < 0) {
895 int saved_errno = errno;
896 SAFE_FREE(group_list);
897 errno = saved_errno;
898 return -1;
901 for(i = 0; i < ngroups; i++)
902 gidset[i] = (gid_t)group_list[i];
904 SAFE_FREE(group_list);
905 return ngroups;
908 static int sys_broken_setgroups(int setlen, gid_t *gidset)
910 GID_T *group_list;
911 int i ;
913 if (setlen == 0)
914 return 0 ;
916 if (setlen < 0 || setlen > groups_max()) {
917 errno = EINVAL;
918 return -1;
922 * Broken case. We need to allocate a
923 * GID_T array of size setlen.
926 if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
927 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
928 return -1;
931 for(i = 0; i < setlen; i++)
932 group_list[i] = (GID_T) gidset[i];
934 if(setgroups(setlen, group_list) != 0) {
935 int saved_errno = errno;
936 SAFE_FREE(group_list);
937 errno = saved_errno;
938 return -1;
941 SAFE_FREE(group_list);
942 return 0 ;
945 #endif /* HAVE_BROKEN_GETGROUPS */
947 /* This is a list of systems that require the first GID passed to setgroups(2)
948 * to be the effective GID. If your system is one of these, add it here.
950 #if defined (FREEBSD) || defined (DARWINOS)
951 #define USE_BSD_SETGROUPS
952 #endif
954 #if defined(USE_BSD_SETGROUPS)
955 /* Depending on the particular BSD implementation, the first GID that is
956 * passed to setgroups(2) will either be ignored or will set the credential's
957 * effective GID. In either case, the right thing to do is to guarantee that
958 * gidset[0] is the effective GID.
960 static int sys_bsd_setgroups(gid_t primary_gid, int setlen, const gid_t *gidset)
962 gid_t *new_gidset = NULL;
963 int max;
964 int ret;
966 /* setgroups(2) will fail with EINVAL if we pass too many groups. */
967 max = groups_max();
969 /* No group list, just make sure we are setting the efective GID. */
970 if (setlen == 0) {
971 return setgroups(1, &primary_gid);
974 /* If the primary gid is not the first array element, grow the array
975 * and insert it at the front.
977 if (gidset[0] != primary_gid) {
978 new_gidset = SMB_MALLOC_ARRAY(gid_t, setlen + 1);
979 if (new_gidset == NULL) {
980 return -1;
983 memcpy(new_gidset + 1, gidset, (setlen * sizeof(gid_t)));
984 new_gidset[0] = primary_gid;
985 setlen++;
988 if (setlen > max) {
989 DEBUG(3, ("forced to truncate group list from %d to %d\n",
990 setlen, max));
991 setlen = max;
994 #if defined(HAVE_BROKEN_GETGROUPS)
995 ret = sys_broken_setgroups(setlen, new_gidset ? new_gidset : gidset);
996 #else
997 ret = setgroups(setlen, new_gidset ? new_gidset : gidset);
998 #endif
1000 if (new_gidset) {
1001 int errsav = errno;
1002 SAFE_FREE(new_gidset);
1003 errno = errsav;
1006 return ret;
1009 #endif /* USE_BSD_SETGROUPS */
1011 /**************************************************************************
1012 Wrapper for getgroups. Deals with broken (int) case.
1013 ****************************************************************************/
1015 int sys_getgroups(int setlen, gid_t *gidset)
1017 #if defined(HAVE_BROKEN_GETGROUPS)
1018 return sys_broken_getgroups(setlen, gidset);
1019 #else
1020 return getgroups(setlen, gidset);
1021 #endif
1024 /**************************************************************************
1025 Wrapper for setgroups. Deals with broken (int) case and BSD case.
1026 ****************************************************************************/
1028 int sys_setgroups(gid_t UNUSED(primary_gid), int setlen, gid_t *gidset)
1030 #if !defined(HAVE_SETGROUPS)
1031 errno = ENOSYS;
1032 return -1;
1033 #endif /* HAVE_SETGROUPS */
1035 #if defined(USE_BSD_SETGROUPS)
1036 return sys_bsd_setgroups(primary_gid, setlen, gidset);
1037 #elif defined(HAVE_BROKEN_GETGROUPS)
1038 return sys_broken_setgroups(setlen, gidset);
1039 #else
1040 return setgroups(setlen, gidset);
1041 #endif
1044 /**************************************************************************
1045 Wrappers for setpwent(), getpwent() and endpwent()
1046 ****************************************************************************/
1048 void sys_setpwent(void)
1050 setpwent();
1053 struct passwd *sys_getpwent(void)
1055 return getpwent();
1058 void sys_endpwent(void)
1060 endpwent();
1063 /**************************************************************************
1064 Wrappers for getpwnam(), getpwuid(), getgrnam(), getgrgid()
1065 ****************************************************************************/
1068 struct passwd *sys_getpwnam(const char *name)
1070 return getpwnam(name);
1073 struct passwd *sys_getpwuid(uid_t uid)
1075 return getpwuid(uid);
1078 struct group *sys_getgrnam(const char *name)
1080 return getgrnam(name);
1083 struct group *sys_getgrgid(gid_t gid)
1085 return getgrgid(gid);
1088 /**************************************************************************
1089 Extract a command into an arg list.
1090 ****************************************************************************/
1092 static char **extract_args(TALLOC_CTX *mem_ctx, const char *command)
1094 char *trunc_cmd;
1095 char *saveptr;
1096 char *ptr;
1097 int argcl;
1098 char **argl = NULL;
1099 int i;
1101 if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1102 DEBUG(0, ("talloc failed\n"));
1103 goto nomem;
1106 if(!(ptr = strtok_r(trunc_cmd, " \t", &saveptr))) {
1107 TALLOC_FREE(trunc_cmd);
1108 errno = EINVAL;
1109 return NULL;
1113 * Count the args.
1116 for( argcl = 1; ptr; ptr = strtok_r(NULL, " \t", &saveptr))
1117 argcl++;
1119 TALLOC_FREE(trunc_cmd);
1121 if (!(argl = TALLOC_ARRAY(mem_ctx, char *, argcl + 1))) {
1122 goto nomem;
1126 * Now do the extraction.
1129 if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1130 goto nomem;
1133 ptr = strtok_r(trunc_cmd, " \t", &saveptr);
1134 i = 0;
1136 if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1137 goto nomem;
1140 while((ptr = strtok_r(NULL, " \t", &saveptr)) != NULL) {
1142 if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1143 goto nomem;
1147 argl[i++] = NULL;
1148 return argl;
1150 nomem:
1151 DEBUG(0, ("talloc failed\n"));
1152 TALLOC_FREE(trunc_cmd);
1153 TALLOC_FREE(argl);
1154 errno = ENOMEM;
1155 return NULL;
1158 /**************************************************************************
1159 Wrapper for fork. Ensures that mypid is reset. Used so we can write
1160 a sys_getpid() that only does a system call *once*.
1161 ****************************************************************************/
1163 static pid_t mypid = (pid_t)-1;
1165 pid_t sys_fork(void)
1167 pid_t forkret = fork();
1169 if (forkret == (pid_t)0) /* Child - reset mypid so sys_getpid does a system call. */
1170 mypid = (pid_t) -1;
1172 return forkret;
1175 /**************************************************************************
1176 Wrapper for getpid. Ensures we only do a system call *once*.
1177 ****************************************************************************/
1179 pid_t sys_getpid(void)
1181 if (mypid == (pid_t)-1)
1182 mypid = getpid();
1184 return mypid;
1187 /**************************************************************************
1188 Wrapper for popen. Safer as it doesn't search a path.
1189 Modified from the glibc sources.
1190 modified by tridge to return a file descriptor. We must kick our FILE* habit
1191 ****************************************************************************/
1193 typedef struct _popen_list
1195 int fd;
1196 pid_t child_pid;
1197 struct _popen_list *next;
1198 } popen_list;
1200 static popen_list *popen_chain;
1202 int sys_popen(const char *command)
1204 int parent_end, child_end;
1205 int pipe_fds[2];
1206 popen_list *entry = NULL;
1207 char **argl = NULL;
1209 if (pipe(pipe_fds) < 0)
1210 return -1;
1212 parent_end = pipe_fds[0];
1213 child_end = pipe_fds[1];
1215 if (!*command) {
1216 errno = EINVAL;
1217 goto err_exit;
1220 if((entry = SMB_MALLOC_P(popen_list)) == NULL)
1221 goto err_exit;
1223 ZERO_STRUCTP(entry);
1226 * Extract the command and args into a NULL terminated array.
1229 if(!(argl = extract_args(NULL, command)))
1230 goto err_exit;
1232 entry->child_pid = sys_fork();
1234 if (entry->child_pid == -1) {
1235 goto err_exit;
1238 if (entry->child_pid == 0) {
1241 * Child !
1244 int child_std_end = STDOUT_FILENO;
1245 popen_list *p;
1247 close(parent_end);
1248 if (child_end != child_std_end) {
1249 dup2 (child_end, child_std_end);
1250 close (child_end);
1254 * POSIX.2: "popen() shall ensure that any streams from previous
1255 * popen() calls that remain open in the parent process are closed
1256 * in the new child process."
1259 for (p = popen_chain; p; p = p->next)
1260 close(p->fd);
1262 execv(argl[0], argl);
1263 _exit (127);
1267 * Parent.
1270 close (child_end);
1271 TALLOC_FREE(argl);
1273 /* Link into popen_chain. */
1274 entry->next = popen_chain;
1275 popen_chain = entry;
1276 entry->fd = parent_end;
1278 return entry->fd;
1280 err_exit:
1282 SAFE_FREE(entry);
1283 SAFE_FREE(argl);
1284 close(pipe_fds[0]);
1285 close(pipe_fds[1]);
1286 return -1;
1289 /**************************************************************************
1290 Wrapper for pclose. Modified from the glibc sources.
1291 ****************************************************************************/
1293 int sys_pclose(int fd)
1295 int wstatus;
1296 popen_list **ptr = &popen_chain;
1297 popen_list *entry = NULL;
1298 pid_t wait_pid;
1299 int status = -1;
1301 /* Unlink from popen_chain. */
1302 for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
1303 if ((*ptr)->fd == fd) {
1304 entry = *ptr;
1305 *ptr = (*ptr)->next;
1306 status = 0;
1307 break;
1311 if (status < 0 || close(entry->fd) < 0)
1312 return -1;
1315 * As Samba is catching and eating child process
1316 * exits we don't really care about the child exit
1317 * code, a -1 with errno = ECHILD will do fine for us.
1320 do {
1321 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
1322 } while (wait_pid == -1 && errno == EINTR);
1324 SAFE_FREE(entry);
1326 if (wait_pid == -1)
1327 return -1;
1328 return wstatus;
1331 /**************************************************************************
1332 Wrappers for dlopen, dlsym, dlclose.
1333 ****************************************************************************/
1335 void *sys_dlopen(const char *name, int flags)
1337 #if defined(HAVE_DLOPEN)
1338 return dlopen(name, flags);
1339 #else
1340 return NULL;
1341 #endif
1344 void *sys_dlsym(void *handle, const char *symbol)
1346 #if defined(HAVE_DLSYM)
1347 return dlsym(handle, symbol);
1348 #else
1349 return NULL;
1350 #endif
1353 int sys_dlclose (void *handle)
1355 #if defined(HAVE_DLCLOSE)
1356 return dlclose(handle);
1357 #else
1358 return 0;
1359 #endif
1362 const char *sys_dlerror(void)
1364 #if defined(HAVE_DLERROR)
1365 return dlerror();
1366 #else
1367 return NULL;
1368 #endif
1371 int sys_dup2(int oldfd, int newfd)
1373 #if defined(HAVE_DUP2)
1374 return dup2(oldfd, newfd);
1375 #else
1376 errno = ENOSYS;
1377 return -1;
1378 #endif
1381 /**************************************************************************
1382 Wrapper for Admin Logs.
1383 ****************************************************************************/
1385 void sys_adminlog(int priority, const char *format_str, ...)
1387 va_list ap;
1388 int ret;
1389 char *msgbuf = NULL;
1391 va_start( ap, format_str );
1392 ret = vasprintf( &msgbuf, format_str, ap );
1393 va_end( ap );
1395 if (ret == -1)
1396 return;
1398 #if defined(HAVE_SYSLOG)
1399 syslog( priority, "%s", msgbuf );
1400 #else
1401 DEBUG(0,("%s", msgbuf ));
1402 #endif
1403 SAFE_FREE(msgbuf);
1406 /******** Solaris EA helper function prototypes ********/
1407 #ifdef HAVE_ATTROPEN
1408 #define SOLARIS_ATTRMODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP
1409 static int solaris_write_xattr(int attrfd, const char *value, size_t size);
1410 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size);
1411 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size);
1412 static int solaris_unlinkat(int attrdirfd, const char *name);
1413 static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode);
1414 static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode);
1415 #endif
1417 /**************************************************************************
1418 Wrappers for extented attribute calls. Based on the Linux package with
1419 support for IRIX and (Net|Free)BSD also. Expand as other systems have them.
1420 ****************************************************************************/
1422 ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t size)
1424 #if defined(HAVE_GETXATTR)
1425 #ifndef XATTR_ADD_OPT
1426 return getxattr(path, name, value, size);
1427 #else
1428 int options = 0;
1429 return getxattr(path, name, value, size, 0, options);
1430 #endif
1431 #elif defined(HAVE_GETEA)
1432 return getea(path, name, value, size);
1433 #elif defined(HAVE_EXTATTR_GET_FILE)
1434 char *s;
1435 ssize_t retval;
1436 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1437 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1438 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1440 * The BSD implementation has a nasty habit of silently truncating
1441 * the returned value to the size of the buffer, so we have to check
1442 * that the buffer is large enough to fit the returned value.
1444 if((retval=extattr_get_file(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1445 if(retval > size) {
1446 errno = ERANGE;
1447 return -1;
1449 if((retval=extattr_get_file(path, attrnamespace, attrname, value, size)) >= 0)
1450 return retval;
1453 DEBUG(10,("sys_getxattr: extattr_get_file() failed with: %s\n", strerror(errno)));
1454 return -1;
1455 #elif defined(HAVE_ATTR_GET)
1456 int retval, flags = 0;
1457 int valuelength = (int)size;
1458 char *attrname = strchr(name,'.') + 1;
1460 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1462 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1464 return retval ? retval : valuelength;
1465 #elif defined(HAVE_ATTROPEN)
1466 ssize_t ret = -1;
1467 int attrfd = solaris_attropen(path, name, O_RDONLY, 0);
1468 if (attrfd >= 0) {
1469 ret = solaris_read_xattr(attrfd, value, size);
1470 close(attrfd);
1472 return ret;
1473 #else
1474 errno = ENOSYS;
1475 return -1;
1476 #endif
1479 ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t size)
1481 #if defined(HAVE_LGETXATTR)
1482 return lgetxattr(path, name, value, size);
1483 #elif defined(HAVE_GETXATTR) && defined(XATTR_ADD_OPT)
1484 int options = XATTR_NOFOLLOW;
1485 return getxattr(path, name, value, size, 0, options);
1486 #elif defined(HAVE_LGETEA)
1487 return lgetea(path, name, value, size);
1488 #elif defined(HAVE_EXTATTR_GET_LINK)
1489 char *s;
1490 ssize_t retval;
1491 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1492 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1493 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1495 if((retval=extattr_get_link(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1496 if(retval > size) {
1497 errno = ERANGE;
1498 return -1;
1500 if((retval=extattr_get_link(path, attrnamespace, attrname, value, size)) >= 0)
1501 return retval;
1504 DEBUG(10,("sys_lgetxattr: extattr_get_link() failed with: %s\n", strerror(errno)));
1505 return -1;
1506 #elif defined(HAVE_ATTR_GET)
1507 int retval, flags = ATTR_DONTFOLLOW;
1508 int valuelength = (int)size;
1509 char *attrname = strchr(name,'.') + 1;
1511 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1513 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1515 return retval ? retval : valuelength;
1516 #elif defined(HAVE_ATTROPEN)
1517 ssize_t ret = -1;
1518 int attrfd = solaris_attropen(path, name, O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1519 if (attrfd >= 0) {
1520 ret = solaris_read_xattr(attrfd, value, size);
1521 close(attrfd);
1523 return ret;
1524 #else
1525 errno = ENOSYS;
1526 return -1;
1527 #endif
1530 ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size)
1532 #if defined(HAVE_FGETXATTR)
1533 #ifndef XATTR_ADD_OPT
1534 return fgetxattr(filedes, name, value, size);
1535 #else
1536 int options = 0;
1537 return fgetxattr(filedes, name, value, size, 0, options);
1538 #endif
1539 #elif defined(HAVE_FGETEA)
1540 return fgetea(filedes, name, value, size);
1541 #elif defined(HAVE_EXTATTR_GET_FD)
1542 char *s;
1543 ssize_t retval;
1544 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1545 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1546 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1548 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0)) >= 0) {
1549 if(retval > size) {
1550 errno = ERANGE;
1551 return -1;
1553 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, value, size)) >= 0)
1554 return retval;
1557 DEBUG(10,("sys_fgetxattr: extattr_get_fd() failed with: %s\n", strerror(errno)));
1558 return -1;
1559 #elif defined(HAVE_ATTR_GETF)
1560 int retval, flags = 0;
1561 int valuelength = (int)size;
1562 char *attrname = strchr(name,'.') + 1;
1564 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1566 retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags);
1568 return retval ? retval : valuelength;
1569 #elif defined(HAVE_ATTROPEN)
1570 ssize_t ret = -1;
1571 int attrfd = solaris_openat(filedes, name, O_RDONLY|O_XATTR, 0);
1572 if (attrfd >= 0) {
1573 ret = solaris_read_xattr(attrfd, value, size);
1574 close(attrfd);
1576 return ret;
1577 #else
1578 errno = ENOSYS;
1579 return -1;
1580 #endif
1583 #if defined(HAVE_EXTATTR_LIST_FILE)
1585 #define EXTATTR_PREFIX(s) (s), (sizeof((s))-1)
1587 static struct {
1588 int space;
1589 const char *name;
1590 size_t len;
1592 extattr[] = {
1593 { EXTATTR_NAMESPACE_SYSTEM, EXTATTR_PREFIX("system.") },
1594 { EXTATTR_NAMESPACE_USER, EXTATTR_PREFIX("user.") },
1597 typedef union {
1598 const char *path;
1599 int filedes;
1600 } extattr_arg;
1602 static ssize_t bsd_attr_list (int type, extattr_arg arg, char *list, size_t size)
1604 ssize_t list_size, total_size = 0;
1605 int i, t, len;
1606 char *buf;
1607 /* Iterate through extattr(2) namespaces */
1608 for(t = 0; t < (sizeof(extattr)/sizeof(extattr[0])); t++) {
1609 switch(type) {
1610 #if defined(HAVE_EXTATTR_LIST_FILE)
1611 case 0:
1612 list_size = extattr_list_file(arg.path, extattr[t].space, list, size);
1613 break;
1614 #endif
1615 #if defined(HAVE_EXTATTR_LIST_LINK)
1616 case 1:
1617 list_size = extattr_list_link(arg.path, extattr[t].space, list, size);
1618 break;
1619 #endif
1620 #if defined(HAVE_EXTATTR_LIST_FD)
1621 case 2:
1622 list_size = extattr_list_fd(arg.filedes, extattr[t].space, list, size);
1623 break;
1624 #endif
1625 default:
1626 errno = ENOSYS;
1627 return -1;
1629 /* Some error happend. Errno should be set by the previous call */
1630 if(list_size < 0)
1631 return -1;
1632 /* No attributes */
1633 if(list_size == 0)
1634 continue;
1635 /* XXX: Call with an empty buffer may be used to calculate
1636 necessary buffer size. Unfortunately, we can't say, how
1637 many attributes were returned, so here is the potential
1638 problem with the emulation.
1640 if(list == NULL) {
1641 /* Take the worse case of one char attribute names -
1642 two bytes per name plus one more for sanity.
1644 total_size += list_size + (list_size/2 + 1)*extattr[t].len;
1645 continue;
1647 /* Count necessary offset to fit namespace prefixes */
1648 len = 0;
1649 for(i = 0; i < list_size; i += list[i] + 1)
1650 len += extattr[t].len;
1652 total_size += list_size + len;
1653 /* Buffer is too small to fit the results */
1654 if(total_size > size) {
1655 errno = ERANGE;
1656 return -1;
1658 /* Shift results back, so we can prepend prefixes */
1659 buf = memmove(list + len, list, list_size);
1661 for(i = 0; i < list_size; i += len + 1) {
1662 len = buf[i];
1663 strncpy(list, extattr[t].name, extattr[t].len + 1);
1664 list += extattr[t].len;
1665 strncpy(list, buf + i + 1, len);
1666 list[len] = '\0';
1667 list += len + 1;
1669 size -= total_size;
1671 return total_size;
1674 #endif
1676 #if defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1677 static char attr_buffer[ATTR_MAX_VALUELEN];
1679 static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags)
1681 int retval = 0, index;
1682 attrlist_cursor_t *cursor = 0;
1683 int total_size = 0;
1684 attrlist_t * al = (attrlist_t *)attr_buffer;
1685 attrlist_ent_t *ae;
1686 size_t ent_size, left = size;
1687 char *bp = list;
1689 while (True) {
1690 if (filedes)
1691 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1692 else
1693 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1694 if (retval) break;
1695 for (index = 0; index < al->al_count; index++) {
1696 ae = ATTR_ENTRY(attr_buffer, index);
1697 ent_size = strlen(ae->a_name) + sizeof("user.");
1698 if (left >= ent_size) {
1699 strncpy(bp, "user.", sizeof("user."));
1700 strncat(bp, ae->a_name, ent_size - sizeof("user."));
1701 bp += ent_size;
1702 left -= ent_size;
1703 } else if (size) {
1704 errno = ERANGE;
1705 retval = -1;
1706 break;
1708 total_size += ent_size;
1710 if (al->al_more == 0) break;
1712 if (retval == 0) {
1713 flags |= ATTR_ROOT;
1714 cursor = 0;
1715 while (True) {
1716 if (filedes)
1717 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1718 else
1719 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1720 if (retval) break;
1721 for (index = 0; index < al->al_count; index++) {
1722 ae = ATTR_ENTRY(attr_buffer, index);
1723 ent_size = strlen(ae->a_name) + sizeof("system.");
1724 if (left >= ent_size) {
1725 strncpy(bp, "system.", sizeof("system."));
1726 strncat(bp, ae->a_name, ent_size - sizeof("system."));
1727 bp += ent_size;
1728 left -= ent_size;
1729 } else if (size) {
1730 errno = ERANGE;
1731 retval = -1;
1732 break;
1734 total_size += ent_size;
1736 if (al->al_more == 0) break;
1739 return (ssize_t)(retval ? retval : total_size);
1742 #endif
1744 ssize_t sys_listxattr (const char *path, char *list, size_t size)
1746 #if defined(HAVE_LISTXATTR)
1747 #ifndef XATTR_ADD_OPT
1748 return listxattr(path, list, size);
1749 #else
1750 int options = 0;
1751 return listxattr(path, list, size, options);
1752 #endif
1753 #elif defined(HAVE_LISTEA)
1754 return listea(path, list, size);
1755 #elif defined(HAVE_EXTATTR_LIST_FILE)
1756 extattr_arg arg;
1757 arg.path = path;
1758 return bsd_attr_list(0, arg, list, size);
1759 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1760 return irix_attr_list(path, 0, list, size, 0);
1761 #elif defined(HAVE_ATTROPEN)
1762 ssize_t ret = -1;
1763 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
1764 if (attrdirfd >= 0) {
1765 ret = solaris_list_xattr(attrdirfd, list, size);
1766 close(attrdirfd);
1768 return ret;
1769 #else
1770 errno = ENOSYS;
1771 return -1;
1772 #endif
1775 ssize_t sys_llistxattr (const char *path, char *list, size_t size)
1777 #if defined(HAVE_LLISTXATTR)
1778 return llistxattr(path, list, size);
1779 #elif defined(HAVE_LISTXATTR) && defined(XATTR_ADD_OPT)
1780 int options = XATTR_NOFOLLOW;
1781 return listxattr(path, list, size, options);
1782 #elif defined(HAVE_LLISTEA)
1783 return llistea(path, list, size);
1784 #elif defined(HAVE_EXTATTR_LIST_LINK)
1785 extattr_arg arg;
1786 arg.path = path;
1787 return bsd_attr_list(1, arg, list, size);
1788 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1789 return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW);
1790 #elif defined(HAVE_ATTROPEN)
1791 ssize_t ret = -1;
1792 int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1793 if (attrdirfd >= 0) {
1794 ret = solaris_list_xattr(attrdirfd, list, size);
1795 close(attrdirfd);
1797 return ret;
1798 #else
1799 errno = ENOSYS;
1800 return -1;
1801 #endif
1804 ssize_t sys_flistxattr (int filedes, char *list, size_t size)
1806 #if defined(HAVE_FLISTXATTR)
1807 #ifndef XATTR_ADD_OPT
1808 return flistxattr(filedes, list, size);
1809 #else
1810 int options = 0;
1811 return flistxattr(filedes, list, size, options);
1812 #endif
1813 #elif defined(HAVE_FLISTEA)
1814 return flistea(filedes, list, size);
1815 #elif defined(HAVE_EXTATTR_LIST_FD)
1816 extattr_arg arg;
1817 arg.filedes = filedes;
1818 return bsd_attr_list(2, arg, list, size);
1819 #elif defined(HAVE_ATTR_LISTF)
1820 return irix_attr_list(NULL, filedes, list, size, 0);
1821 #elif defined(HAVE_ATTROPEN)
1822 ssize_t ret = -1;
1823 int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
1824 if (attrdirfd >= 0) {
1825 ret = solaris_list_xattr(attrdirfd, list, size);
1826 close(attrdirfd);
1828 return ret;
1829 #else
1830 errno = ENOSYS;
1831 return -1;
1832 #endif
1835 int sys_removexattr (const char *path, const char *name)
1837 #if defined(HAVE_REMOVEXATTR)
1838 #ifndef XATTR_ADD_OPT
1839 return removexattr(path, name);
1840 #else
1841 int options = 0;
1842 return removexattr(path, name, options);
1843 #endif
1844 #elif defined(HAVE_REMOVEEA)
1845 return removeea(path, name);
1846 #elif defined(HAVE_EXTATTR_DELETE_FILE)
1847 char *s;
1848 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1849 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1850 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1852 return extattr_delete_file(path, attrnamespace, attrname);
1853 #elif defined(HAVE_ATTR_REMOVE)
1854 int flags = 0;
1855 char *attrname = strchr(name,'.') + 1;
1857 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1859 return attr_remove(path, attrname, flags);
1860 #elif defined(HAVE_ATTROPEN)
1861 int ret = -1;
1862 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
1863 if (attrdirfd >= 0) {
1864 ret = solaris_unlinkat(attrdirfd, name);
1865 close(attrdirfd);
1867 return ret;
1868 #else
1869 errno = ENOSYS;
1870 return -1;
1871 #endif
1874 int sys_lremovexattr (const char *path, const char *name)
1876 #if defined(HAVE_LREMOVEXATTR)
1877 return lremovexattr(path, name);
1878 #elif defined(HAVE_REMOVEXATTR) && defined(XATTR_ADD_OPT)
1879 int options = XATTR_NOFOLLOW;
1880 return removexattr(path, name, options);
1881 #elif defined(HAVE_LREMOVEEA)
1882 return lremoveea(path, name);
1883 #elif defined(HAVE_EXTATTR_DELETE_LINK)
1884 char *s;
1885 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1886 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1887 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1889 return extattr_delete_link(path, attrnamespace, attrname);
1890 #elif defined(HAVE_ATTR_REMOVE)
1891 int flags = ATTR_DONTFOLLOW;
1892 char *attrname = strchr(name,'.') + 1;
1894 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1896 return attr_remove(path, attrname, flags);
1897 #elif defined(HAVE_ATTROPEN)
1898 int ret = -1;
1899 int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1900 if (attrdirfd >= 0) {
1901 ret = solaris_unlinkat(attrdirfd, name);
1902 close(attrdirfd);
1904 return ret;
1905 #else
1906 errno = ENOSYS;
1907 return -1;
1908 #endif
1911 int sys_fremovexattr (int filedes, const char *name)
1913 #if defined(HAVE_FREMOVEXATTR)
1914 #ifndef XATTR_ADD_OPT
1915 return fremovexattr(filedes, name);
1916 #else
1917 int options = 0;
1918 return fremovexattr(filedes, name, options);
1919 #endif
1920 #elif defined(HAVE_FREMOVEEA)
1921 return fremoveea(filedes, name);
1922 #elif defined(HAVE_EXTATTR_DELETE_FD)
1923 char *s;
1924 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1925 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1926 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1928 return extattr_delete_fd(filedes, attrnamespace, attrname);
1929 #elif defined(HAVE_ATTR_REMOVEF)
1930 int flags = 0;
1931 char *attrname = strchr(name,'.') + 1;
1933 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1935 return attr_removef(filedes, attrname, flags);
1936 #elif defined(HAVE_ATTROPEN)
1937 int ret = -1;
1938 int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
1939 if (attrdirfd >= 0) {
1940 ret = solaris_unlinkat(attrdirfd, name);
1941 close(attrdirfd);
1943 return ret;
1944 #else
1945 errno = ENOSYS;
1946 return -1;
1947 #endif
1950 int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags)
1952 #if defined(HAVE_SETXATTR)
1953 #ifndef XATTR_ADD_OPT
1954 return setxattr(path, name, value, size, flags);
1955 #else
1956 int options = 0;
1957 return setxattr(path, name, value, size, 0, options);
1958 #endif
1959 #elif defined(HAVE_SETEA)
1960 return setea(path, name, value, size, flags);
1961 #elif defined(HAVE_EXTATTR_SET_FILE)
1962 char *s;
1963 int retval = 0;
1964 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1965 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1966 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1967 if (flags) {
1968 /* Check attribute existence */
1969 retval = extattr_get_file(path, attrnamespace, attrname, NULL, 0);
1970 if (retval < 0) {
1971 /* REPLACE attribute, that doesn't exist */
1972 if (flags & XATTR_REPLACE && errno == ENOATTR) {
1973 errno = ENOATTR;
1974 return -1;
1976 /* Ignore other errors */
1978 else {
1979 /* CREATE attribute, that already exists */
1980 if (flags & XATTR_CREATE) {
1981 errno = EEXIST;
1982 return -1;
1986 retval = extattr_set_file(path, attrnamespace, attrname, value, size);
1987 return (retval < 0) ? -1 : 0;
1988 #elif defined(HAVE_ATTR_SET)
1989 int myflags = 0;
1990 char *attrname = strchr(name,'.') + 1;
1992 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
1993 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
1994 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
1996 return attr_set(path, attrname, (const char *)value, size, myflags);
1997 #elif defined(HAVE_ATTROPEN)
1998 int ret = -1;
1999 int myflags = O_RDWR;
2000 int attrfd;
2001 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2002 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2003 attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2004 if (attrfd >= 0) {
2005 ret = solaris_write_xattr(attrfd, value, size);
2006 close(attrfd);
2008 return ret;
2009 #else
2010 errno = ENOSYS;
2011 return -1;
2012 #endif
2015 int sys_lsetxattr (const char *path, const char *name, const void *value, size_t size, int flags)
2017 #if defined(HAVE_LSETXATTR)
2018 return lsetxattr(path, name, value, size, flags);
2019 #elif defined(HAVE_SETXATTR) && defined(XATTR_ADD_OPT)
2020 int options = XATTR_NOFOLLOW;
2021 return setxattr(path, name, value, size, 0, options);
2022 #elif defined(LSETEA)
2023 return lsetea(path, name, value, size, flags);
2024 #elif defined(HAVE_EXTATTR_SET_LINK)
2025 char *s;
2026 int retval = 0;
2027 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2028 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2029 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2030 if (flags) {
2031 /* Check attribute existence */
2032 retval = extattr_get_link(path, attrnamespace, attrname, NULL, 0);
2033 if (retval < 0) {
2034 /* REPLACE attribute, that doesn't exist */
2035 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2036 errno = ENOATTR;
2037 return -1;
2039 /* Ignore other errors */
2041 else {
2042 /* CREATE attribute, that already exists */
2043 if (flags & XATTR_CREATE) {
2044 errno = EEXIST;
2045 return -1;
2050 retval = extattr_set_link(path, attrnamespace, attrname, value, size);
2051 return (retval < 0) ? -1 : 0;
2052 #elif defined(HAVE_ATTR_SET)
2053 int myflags = ATTR_DONTFOLLOW;
2054 char *attrname = strchr(name,'.') + 1;
2056 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2057 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2058 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2060 return attr_set(path, attrname, (const char *)value, size, myflags);
2061 #elif defined(HAVE_ATTROPEN)
2062 int ret = -1;
2063 int myflags = O_RDWR | AT_SYMLINK_NOFOLLOW;
2064 int attrfd;
2065 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2066 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2067 attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2068 if (attrfd >= 0) {
2069 ret = solaris_write_xattr(attrfd, value, size);
2070 close(attrfd);
2072 return ret;
2073 #else
2074 errno = ENOSYS;
2075 return -1;
2076 #endif
2079 int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags)
2081 #if defined(HAVE_FSETXATTR)
2082 #ifndef XATTR_ADD_OPT
2083 return fsetxattr(filedes, name, value, size, flags);
2084 #else
2085 int options = 0;
2086 return fsetxattr(filedes, name, value, size, 0, options);
2087 #endif
2088 #elif defined(HAVE_FSETEA)
2089 return fsetea(filedes, name, value, size, flags);
2090 #elif defined(HAVE_EXTATTR_SET_FD)
2091 char *s;
2092 int retval = 0;
2093 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2094 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2095 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2096 if (flags) {
2097 /* Check attribute existence */
2098 retval = extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0);
2099 if (retval < 0) {
2100 /* REPLACE attribute, that doesn't exist */
2101 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2102 errno = ENOATTR;
2103 return -1;
2105 /* Ignore other errors */
2107 else {
2108 /* CREATE attribute, that already exists */
2109 if (flags & XATTR_CREATE) {
2110 errno = EEXIST;
2111 return -1;
2115 retval = extattr_set_fd(filedes, attrnamespace, attrname, value, size);
2116 return (retval < 0) ? -1 : 0;
2117 #elif defined(HAVE_ATTR_SETF)
2118 int myflags = 0;
2119 char *attrname = strchr(name,'.') + 1;
2121 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2122 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2123 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2125 return attr_setf(filedes, attrname, (const char *)value, size, myflags);
2126 #elif defined(HAVE_ATTROPEN)
2127 int ret = -1;
2128 int myflags = O_RDWR | O_XATTR;
2129 int attrfd;
2130 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2131 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2132 attrfd = solaris_openat(filedes, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2133 if (attrfd >= 0) {
2134 ret = solaris_write_xattr(attrfd, value, size);
2135 close(attrfd);
2137 return ret;
2138 #else
2139 errno = ENOSYS;
2140 return -1;
2141 #endif
2144 /**************************************************************************
2145 helper functions for Solaris' EA support
2146 ****************************************************************************/
2147 #ifdef HAVE_ATTROPEN
2148 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size)
2150 struct stat sbuf;
2152 if (fstat(attrfd, &sbuf) == -1) {
2153 errno = ENOATTR;
2154 return -1;
2157 /* This is to return the current size of the named extended attribute */
2158 if (size == 0) {
2159 return sbuf.st_size;
2162 /* check size and read xattr */
2163 if (sbuf.st_size > size) {
2164 errno = ERANGE;
2165 return -1;
2168 return read(attrfd, value, sbuf.st_size);
2171 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size)
2173 ssize_t len = 0;
2174 int stop = 0;
2175 DIR *dirp;
2176 struct dirent *de;
2177 int newfd = dup(attrdirfd);
2178 /* CAUTION: The originating file descriptor should not be
2179 used again following the call to fdopendir().
2180 For that reason we dup() the file descriptor
2181 here to make things more clear. */
2182 dirp = fdopendir(newfd);
2184 while ((de = readdir(dirp))) {
2185 size_t listlen = strlen(de->d_name);
2186 if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) {
2187 /* we don't want "." and ".." here: */
2188 DEBUG(10,("skipped EA %s\n",de->d_name));
2189 continue;
2192 if (size == 0) {
2193 /* return the current size of the list of extended attribute names*/
2194 len += listlen + 1;
2195 } else {
2196 /* check size and copy entrieѕ + nul into list. */
2197 if ((len + listlen + 1) > size) {
2198 errno = ERANGE;
2199 len = -1;
2200 break;
2201 } else {
2202 safe_strcpy(list + len, de->d_name, listlen);
2203 len += listlen;
2204 list[len] = '\0';
2205 ++len;
2210 if (closedir(dirp) == -1) {
2211 DEBUG(0,("closedir dirp failed: %s\n",strerror(errno)));
2212 return -1;
2214 return len;
2217 static int solaris_unlinkat(int attrdirfd, const char *name)
2219 if (unlinkat(attrdirfd, name, 0) == -1) {
2220 if (errno == ENOENT) {
2221 errno = ENOATTR;
2223 return -1;
2225 return 0;
2228 static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode)
2230 int filedes = attropen(path, attrpath, oflag, mode);
2231 if (filedes == -1) {
2232 DEBUG(10,("attropen FAILED: path: %s, name: %s, errno: %s\n",path,attrpath,strerror(errno)));
2233 if (errno == EINVAL) {
2234 errno = ENOTSUP;
2235 } else {
2236 errno = ENOATTR;
2239 return filedes;
2242 static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode)
2244 int filedes = openat(fildes, path, oflag, mode);
2245 if (filedes == -1) {
2246 DEBUG(10,("openat FAILED: fd: %s, path: %s, errno: %s\n",filedes,path,strerror(errno)));
2247 if (errno == EINVAL) {
2248 errno = ENOTSUP;
2249 } else {
2250 errno = ENOATTR;
2253 return filedes;
2256 static int solaris_write_xattr(int attrfd, const char *value, size_t size)
2258 if ((ftruncate(attrfd, 0) == 0) && (write(attrfd, value, size) == size)) {
2259 return 0;
2260 } else {
2261 DEBUG(10,("solaris_write_xattr FAILED!\n"));
2262 return -1;
2265 #endif /*HAVE_ATTROPEN*/
2268 /****************************************************************************
2269 Return the major devicenumber for UNIX extensions.
2270 ****************************************************************************/
2272 uint32 unix_dev_major(SMB_DEV_T dev)
2274 #if defined(HAVE_DEVICE_MAJOR_FN)
2275 return (uint32)major(dev);
2276 #else
2277 return (uint32)(dev >> 8);
2278 #endif
2281 /****************************************************************************
2282 Return the minor devicenumber for UNIX extensions.
2283 ****************************************************************************/
2285 uint32 unix_dev_minor(SMB_DEV_T dev)
2287 #if defined(HAVE_DEVICE_MINOR_FN)
2288 return (uint32)minor(dev);
2289 #else
2290 return (uint32)(dev & 0xff);
2291 #endif
2294 #if defined(WITH_AIO)
2296 /*******************************************************************
2297 An aio_read wrapper that will deal with 64-bit sizes.
2298 ********************************************************************/
2300 int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2302 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_READ64)
2303 return aio_read64(aiocb);
2304 #elif defined(HAVE_AIO_READ)
2305 return aio_read(aiocb);
2306 #else
2307 errno = ENOSYS;
2308 return -1;
2309 #endif
2312 /*******************************************************************
2313 An aio_write wrapper that will deal with 64-bit sizes.
2314 ********************************************************************/
2316 int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2318 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_WRITE64)
2319 return aio_write64(aiocb);
2320 #elif defined(HAVE_AIO_WRITE)
2321 return aio_write(aiocb);
2322 #else
2323 errno = ENOSYS;
2324 return -1;
2325 #endif
2328 /*******************************************************************
2329 An aio_return wrapper that will deal with 64-bit sizes.
2330 ********************************************************************/
2332 ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2334 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_RETURN64)
2335 return aio_return64(aiocb);
2336 #elif defined(HAVE_AIO_RETURN)
2337 return aio_return(aiocb);
2338 #else
2339 errno = ENOSYS;
2340 return -1;
2341 #endif
2344 /*******************************************************************
2345 An aio_cancel wrapper that will deal with 64-bit sizes.
2346 ********************************************************************/
2348 int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2350 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_CANCEL64)
2351 return aio_cancel64(fd, aiocb);
2352 #elif defined(HAVE_AIO_CANCEL)
2353 return aio_cancel(fd, aiocb);
2354 #else
2355 errno = ENOSYS;
2356 return -1;
2357 #endif
2360 /*******************************************************************
2361 An aio_error wrapper that will deal with 64-bit sizes.
2362 ********************************************************************/
2364 int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2366 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_ERROR64)
2367 return aio_error64(aiocb);
2368 #elif defined(HAVE_AIO_ERROR)
2369 return aio_error(aiocb);
2370 #else
2371 errno = ENOSYS;
2372 return -1;
2373 #endif
2376 /*******************************************************************
2377 An aio_fsync wrapper that will deal with 64-bit sizes.
2378 ********************************************************************/
2380 int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2382 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_FSYNC64)
2383 return aio_fsync64(op, aiocb);
2384 #elif defined(HAVE_AIO_FSYNC)
2385 return aio_fsync(op, aiocb);
2386 #else
2387 errno = ENOSYS;
2388 return -1;
2389 #endif
2392 /*******************************************************************
2393 An aio_fsync wrapper that will deal with 64-bit sizes.
2394 ********************************************************************/
2396 int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2398 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_SUSPEND64)
2399 return aio_suspend64(cblist, n, timeout);
2400 #elif defined(HAVE_AIO_FSYNC)
2401 return aio_suspend(cblist, n, timeout);
2402 #else
2403 errno = ENOSYS;
2404 return -1;
2405 #endif
2407 #else /* !WITH_AIO */
2409 int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2411 errno = ENOSYS;
2412 return -1;
2415 int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2417 errno = ENOSYS;
2418 return -1;
2421 ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2423 errno = ENOSYS;
2424 return -1;
2427 int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2429 errno = ENOSYS;
2430 return -1;
2433 int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2435 errno = ENOSYS;
2436 return -1;
2439 int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2441 errno = ENOSYS;
2442 return -1;
2445 int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2447 errno = ENOSYS;
2448 return -1;
2450 #endif /* WITH_AIO */
2452 int sys_getpeereid( int s, uid_t *uid)
2454 #if defined(HAVE_PEERCRED)
2455 struct ucred cred;
2456 socklen_t cred_len = sizeof(struct ucred);
2457 int ret;
2459 ret = getsockopt(s, SOL_SOCKET, SO_PEERCRED, (void *)&cred, &cred_len);
2460 if (ret != 0) {
2461 return -1;
2464 if (cred_len != sizeof(struct ucred)) {
2465 errno = EINVAL;
2466 return -1;
2469 *uid = cred.uid;
2470 return 0;
2471 #else
2472 errno = ENOSYS;
2473 return -1;
2474 #endif
2477 int sys_getnameinfo(const struct sockaddr *psa,
2478 socklen_t salen,
2479 char *host,
2480 size_t hostlen,
2481 char *service,
2482 size_t servlen,
2483 int flags)
2486 * For Solaris we must make sure salen is the
2487 * correct length for the incoming sa_family.
2490 if (salen == sizeof(struct sockaddr_storage)) {
2491 salen = sizeof(struct sockaddr_in);
2492 #if defined(HAVE_IPV6)
2493 if (psa->sa_family == AF_INET6) {
2494 salen = sizeof(struct sockaddr_in6);
2496 #endif
2498 return getnameinfo(psa, salen, host, hostlen, service, servlen, flags);
2501 int sys_connect(int fd, const struct sockaddr * addr)
2503 socklen_t salen = -1;
2505 if (addr->sa_family == AF_INET) {
2506 salen = sizeof(struct sockaddr_in);
2507 } else if (addr->sa_family == AF_UNIX) {
2508 salen = sizeof(struct sockaddr_un);
2510 #if defined(HAVE_IPV6)
2511 else if (addr->sa_family == AF_INET6) {
2512 salen = sizeof(struct sockaddr_in6);
2514 #endif
2516 return connect(fd, addr, salen);