Do not start a transaction this way.
[Samba.git] / source3 / lib / system.c
blobed66666ddb018d2ca84ce3d2f8de84a7f3ca176f
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 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 /**************************************************************************
596 Try and abstract process capabilities (for systems that have them).
597 ****************************************************************************/
599 /* Set the POSIX capabilities needed for the given purpose into the effective
600 * capability set of the current process. Make sure they are always removed
601 * from the inheritable set, because there is no circumstance in which our
602 * children should inherit our elevated privileges.
604 static bool set_process_capability(enum smbd_capability capability,
605 bool enable)
607 cap_value_t cap_vals[2] = {0};
608 int num_cap_vals = 0;
610 cap_t cap;
612 #if defined(HAVE_PRCTL) && defined(PR_GET_KEEPCAPS) && defined(PR_SET_KEEPCAPS)
613 /* On Linux, make sure that any capabilities we grab are sticky
614 * across UID changes. We expect that this would allow us to keep both
615 * the effective and permitted capability sets, but as of circa 2.6.16,
616 * only the permitted set is kept. It is a bug (which we work around)
617 * that the effective set is lost, but we still require the effective
618 * set to be kept.
620 if (!prctl(PR_GET_KEEPCAPS)) {
621 prctl(PR_SET_KEEPCAPS, 1);
623 #endif
625 cap = cap_get_proc();
626 if (cap == NULL) {
627 DEBUG(0,("set_process_capability: cap_get_proc failed: %s\n",
628 strerror(errno)));
629 return False;
632 switch (capability) {
633 case KERNEL_OPLOCK_CAPABILITY:
634 #ifdef CAP_NETWORK_MGT
635 /* IRIX has CAP_NETWORK_MGT for oplocks. */
636 cap_vals[num_cap_vals++] = CAP_NETWORK_MGT;
637 #endif
638 break;
639 case DMAPI_ACCESS_CAPABILITY:
640 #ifdef CAP_DEVICE_MGT
641 /* IRIX has CAP_DEVICE_MGT for DMAPI access. */
642 cap_vals[num_cap_vals++] = CAP_DEVICE_MGT;
643 #elif CAP_MKNOD
644 /* Linux has CAP_MKNOD for DMAPI access. */
645 cap_vals[num_cap_vals++] = CAP_MKNOD;
646 #endif
647 break;
648 case LEASE_CAPABILITY:
649 #ifdef CAP_LEASE
650 cap_vals[num_cap_vals++] = CAP_LEASE;
651 #endif
652 break;
655 SMB_ASSERT(num_cap_vals <= ARRAY_SIZE(cap_vals));
657 if (num_cap_vals == 0) {
658 cap_free(cap);
659 return True;
662 cap_set_flag(cap, CAP_EFFECTIVE, num_cap_vals, cap_vals,
663 enable ? CAP_SET : CAP_CLEAR);
665 /* We never want to pass capabilities down to our children, so make
666 * sure they are not inherited.
668 cap_set_flag(cap, CAP_INHERITABLE, num_cap_vals, cap_vals, CAP_CLEAR);
670 if (cap_set_proc(cap) == -1) {
671 DEBUG(0, ("set_process_capability: cap_set_proc failed: %s\n",
672 strerror(errno)));
673 cap_free(cap);
674 return False;
677 cap_free(cap);
678 return True;
681 #endif /* HAVE_POSIX_CAPABILITIES */
683 /****************************************************************************
684 Gain the oplock capability from the kernel if possible.
685 ****************************************************************************/
687 void set_effective_capability(enum smbd_capability capability)
689 #if defined(HAVE_POSIX_CAPABILITIES)
690 set_process_capability(capability, True);
691 #endif /* HAVE_POSIX_CAPABILITIES */
694 void drop_effective_capability(enum smbd_capability capability)
696 #if defined(HAVE_POSIX_CAPABILITIES)
697 set_process_capability(capability, False);
698 #endif /* HAVE_POSIX_CAPABILITIES */
701 /**************************************************************************
702 Wrapper for random().
703 ****************************************************************************/
705 long sys_random(void)
707 #if defined(HAVE_RANDOM)
708 return (long)random();
709 #elif defined(HAVE_RAND)
710 return (long)rand();
711 #else
712 DEBUG(0,("Error - no random function available !\n"));
713 exit(1);
714 #endif
717 /**************************************************************************
718 Wrapper for srandom().
719 ****************************************************************************/
721 void sys_srandom(unsigned int seed)
723 #if defined(HAVE_SRANDOM)
724 srandom(seed);
725 #elif defined(HAVE_SRAND)
726 srand(seed);
727 #else
728 DEBUG(0,("Error - no srandom function available !\n"));
729 exit(1);
730 #endif
733 /**************************************************************************
734 Returns equivalent to NGROUPS_MAX - using sysconf if needed.
735 ****************************************************************************/
737 int groups_max(void)
739 #if defined(SYSCONF_SC_NGROUPS_MAX)
740 int ret = sysconf(_SC_NGROUPS_MAX);
741 return (ret == -1) ? NGROUPS_MAX : ret;
742 #else
743 return NGROUPS_MAX;
744 #endif
747 /**************************************************************************
748 Wrap setgroups and getgroups for systems that declare getgroups() as
749 returning an array of gid_t, but actuall return an array of int.
750 ****************************************************************************/
752 #if defined(HAVE_BROKEN_GETGROUPS)
753 static int sys_broken_getgroups(int setlen, gid_t *gidset)
755 GID_T gid;
756 GID_T *group_list;
757 int i, ngroups;
759 if(setlen == 0) {
760 return getgroups(setlen, &gid);
764 * Broken case. We need to allocate a
765 * GID_T array of size setlen.
768 if(setlen < 0) {
769 errno = EINVAL;
770 return -1;
773 if (setlen == 0)
774 setlen = groups_max();
776 if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
777 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
778 return -1;
781 if((ngroups = getgroups(setlen, group_list)) < 0) {
782 int saved_errno = errno;
783 SAFE_FREE(group_list);
784 errno = saved_errno;
785 return -1;
788 for(i = 0; i < ngroups; i++)
789 gidset[i] = (gid_t)group_list[i];
791 SAFE_FREE(group_list);
792 return ngroups;
795 static int sys_broken_setgroups(int setlen, gid_t *gidset)
797 GID_T *group_list;
798 int i ;
800 if (setlen == 0)
801 return 0 ;
803 if (setlen < 0 || setlen > groups_max()) {
804 errno = EINVAL;
805 return -1;
809 * Broken case. We need to allocate a
810 * GID_T array of size setlen.
813 if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
814 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
815 return -1;
818 for(i = 0; i < setlen; i++)
819 group_list[i] = (GID_T) gidset[i];
821 if(setgroups(setlen, group_list) != 0) {
822 int saved_errno = errno;
823 SAFE_FREE(group_list);
824 errno = saved_errno;
825 return -1;
828 SAFE_FREE(group_list);
829 return 0 ;
832 #endif /* HAVE_BROKEN_GETGROUPS */
834 /* This is a list of systems that require the first GID passed to setgroups(2)
835 * to be the effective GID. If your system is one of these, add it here.
837 #if defined (FREEBSD) || defined (DARWINOS)
838 #define USE_BSD_SETGROUPS
839 #endif
841 #if defined(USE_BSD_SETGROUPS)
842 /* Depending on the particular BSD implementation, the first GID that is
843 * passed to setgroups(2) will either be ignored or will set the credential's
844 * effective GID. In either case, the right thing to do is to guarantee that
845 * gidset[0] is the effective GID.
847 static int sys_bsd_setgroups(gid_t primary_gid, int setlen, const gid_t *gidset)
849 gid_t *new_gidset = NULL;
850 int max;
851 int ret;
853 /* setgroups(2) will fail with EINVAL if we pass too many groups. */
854 max = groups_max();
856 /* No group list, just make sure we are setting the efective GID. */
857 if (setlen == 0) {
858 return setgroups(1, &primary_gid);
861 /* If the primary gid is not the first array element, grow the array
862 * and insert it at the front.
864 if (gidset[0] != primary_gid) {
865 new_gidset = SMB_MALLOC_ARRAY(gid_t, setlen + 1);
866 if (new_gidset == NULL) {
867 return -1;
870 memcpy(new_gidset + 1, gidset, (setlen * sizeof(gid_t)));
871 new_gidset[0] = primary_gid;
872 setlen++;
875 if (setlen > max) {
876 DEBUG(3, ("forced to truncate group list from %d to %d\n",
877 setlen, max));
878 setlen = max;
881 #if defined(HAVE_BROKEN_GETGROUPS)
882 ret = sys_broken_setgroups(setlen, new_gidset ? new_gidset : gidset);
883 #else
884 ret = setgroups(setlen, new_gidset ? new_gidset : gidset);
885 #endif
887 if (new_gidset) {
888 int errsav = errno;
889 SAFE_FREE(new_gidset);
890 errno = errsav;
893 return ret;
896 #endif /* USE_BSD_SETGROUPS */
898 /**************************************************************************
899 Wrapper for getgroups. Deals with broken (int) case.
900 ****************************************************************************/
902 int sys_getgroups(int setlen, gid_t *gidset)
904 #if defined(HAVE_BROKEN_GETGROUPS)
905 return sys_broken_getgroups(setlen, gidset);
906 #else
907 return getgroups(setlen, gidset);
908 #endif
911 /**************************************************************************
912 Wrapper for setgroups. Deals with broken (int) case and BSD case.
913 ****************************************************************************/
915 int sys_setgroups(gid_t UNUSED(primary_gid), int setlen, gid_t *gidset)
917 #if !defined(HAVE_SETGROUPS)
918 errno = ENOSYS;
919 return -1;
920 #endif /* HAVE_SETGROUPS */
922 #if defined(USE_BSD_SETGROUPS)
923 return sys_bsd_setgroups(primary_gid, setlen, gidset);
924 #elif defined(HAVE_BROKEN_GETGROUPS)
925 return sys_broken_setgroups(setlen, gidset);
926 #else
927 return setgroups(setlen, gidset);
928 #endif
931 /**************************************************************************
932 Wrappers for setpwent(), getpwent() and endpwent()
933 ****************************************************************************/
935 void sys_setpwent(void)
937 setpwent();
940 struct passwd *sys_getpwent(void)
942 return getpwent();
945 void sys_endpwent(void)
947 endpwent();
950 /**************************************************************************
951 Wrappers for getpwnam(), getpwuid(), getgrnam(), getgrgid()
952 ****************************************************************************/
955 struct passwd *sys_getpwnam(const char *name)
957 return getpwnam(name);
960 struct passwd *sys_getpwuid(uid_t uid)
962 return getpwuid(uid);
965 struct group *sys_getgrnam(const char *name)
967 return getgrnam(name);
970 struct group *sys_getgrgid(gid_t gid)
972 return getgrgid(gid);
975 /**************************************************************************
976 Extract a command into an arg list.
977 ****************************************************************************/
979 static char **extract_args(TALLOC_CTX *mem_ctx, const char *command)
981 char *trunc_cmd;
982 char *saveptr;
983 char *ptr;
984 int argcl;
985 char **argl = NULL;
986 int i;
988 if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
989 DEBUG(0, ("talloc failed\n"));
990 goto nomem;
993 if(!(ptr = strtok_r(trunc_cmd, " \t", &saveptr))) {
994 TALLOC_FREE(trunc_cmd);
995 errno = EINVAL;
996 return NULL;
1000 * Count the args.
1003 for( argcl = 1; ptr; ptr = strtok_r(NULL, " \t", &saveptr))
1004 argcl++;
1006 TALLOC_FREE(trunc_cmd);
1008 if (!(argl = TALLOC_ARRAY(mem_ctx, char *, argcl + 1))) {
1009 goto nomem;
1013 * Now do the extraction.
1016 if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1017 goto nomem;
1020 ptr = strtok_r(trunc_cmd, " \t", &saveptr);
1021 i = 0;
1023 if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1024 goto nomem;
1027 while((ptr = strtok_r(NULL, " \t", &saveptr)) != NULL) {
1029 if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1030 goto nomem;
1034 argl[i++] = NULL;
1035 return argl;
1037 nomem:
1038 DEBUG(0, ("talloc failed\n"));
1039 TALLOC_FREE(trunc_cmd);
1040 TALLOC_FREE(argl);
1041 errno = ENOMEM;
1042 return NULL;
1045 /**************************************************************************
1046 Wrapper for fork. Ensures that mypid is reset. Used so we can write
1047 a sys_getpid() that only does a system call *once*.
1048 ****************************************************************************/
1050 static pid_t mypid = (pid_t)-1;
1052 pid_t sys_fork(void)
1054 pid_t forkret = fork();
1056 if (forkret == (pid_t)0) /* Child - reset mypid so sys_getpid does a system call. */
1057 mypid = (pid_t) -1;
1059 return forkret;
1062 /**************************************************************************
1063 Wrapper for getpid. Ensures we only do a system call *once*.
1064 ****************************************************************************/
1066 pid_t sys_getpid(void)
1068 if (mypid == (pid_t)-1)
1069 mypid = getpid();
1071 return mypid;
1074 /**************************************************************************
1075 Wrapper for popen. Safer as it doesn't search a path.
1076 Modified from the glibc sources.
1077 modified by tridge to return a file descriptor. We must kick our FILE* habit
1078 ****************************************************************************/
1080 typedef struct _popen_list
1082 int fd;
1083 pid_t child_pid;
1084 struct _popen_list *next;
1085 } popen_list;
1087 static popen_list *popen_chain;
1089 int sys_popen(const char *command)
1091 int parent_end, child_end;
1092 int pipe_fds[2];
1093 popen_list *entry = NULL;
1094 char **argl = NULL;
1096 if (pipe(pipe_fds) < 0)
1097 return -1;
1099 parent_end = pipe_fds[0];
1100 child_end = pipe_fds[1];
1102 if (!*command) {
1103 errno = EINVAL;
1104 goto err_exit;
1107 if((entry = SMB_MALLOC_P(popen_list)) == NULL)
1108 goto err_exit;
1110 ZERO_STRUCTP(entry);
1113 * Extract the command and args into a NULL terminated array.
1116 if(!(argl = extract_args(NULL, command)))
1117 goto err_exit;
1119 entry->child_pid = sys_fork();
1121 if (entry->child_pid == -1) {
1122 goto err_exit;
1125 if (entry->child_pid == 0) {
1128 * Child !
1131 int child_std_end = STDOUT_FILENO;
1132 popen_list *p;
1134 close(parent_end);
1135 if (child_end != child_std_end) {
1136 dup2 (child_end, child_std_end);
1137 close (child_end);
1141 * POSIX.2: "popen() shall ensure that any streams from previous
1142 * popen() calls that remain open in the parent process are closed
1143 * in the new child process."
1146 for (p = popen_chain; p; p = p->next)
1147 close(p->fd);
1149 execv(argl[0], argl);
1150 _exit (127);
1154 * Parent.
1157 close (child_end);
1158 TALLOC_FREE(argl);
1160 /* Link into popen_chain. */
1161 entry->next = popen_chain;
1162 popen_chain = entry;
1163 entry->fd = parent_end;
1165 return entry->fd;
1167 err_exit:
1169 SAFE_FREE(entry);
1170 SAFE_FREE(argl);
1171 close(pipe_fds[0]);
1172 close(pipe_fds[1]);
1173 return -1;
1176 /**************************************************************************
1177 Wrapper for pclose. Modified from the glibc sources.
1178 ****************************************************************************/
1180 int sys_pclose(int fd)
1182 int wstatus;
1183 popen_list **ptr = &popen_chain;
1184 popen_list *entry = NULL;
1185 pid_t wait_pid;
1186 int status = -1;
1188 /* Unlink from popen_chain. */
1189 for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
1190 if ((*ptr)->fd == fd) {
1191 entry = *ptr;
1192 *ptr = (*ptr)->next;
1193 status = 0;
1194 break;
1198 if (status < 0 || close(entry->fd) < 0)
1199 return -1;
1202 * As Samba is catching and eating child process
1203 * exits we don't really care about the child exit
1204 * code, a -1 with errno = ECHILD will do fine for us.
1207 do {
1208 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
1209 } while (wait_pid == -1 && errno == EINTR);
1211 SAFE_FREE(entry);
1213 if (wait_pid == -1)
1214 return -1;
1215 return wstatus;
1218 /**************************************************************************
1219 Wrapper for Admin Logs.
1220 ****************************************************************************/
1222 void sys_adminlog(int priority, const char *format_str, ...)
1224 va_list ap;
1225 int ret;
1226 char *msgbuf = NULL;
1228 va_start( ap, format_str );
1229 ret = vasprintf( &msgbuf, format_str, ap );
1230 va_end( ap );
1232 if (ret == -1)
1233 return;
1235 #if defined(HAVE_SYSLOG)
1236 syslog( priority, "%s", msgbuf );
1237 #else
1238 DEBUG(0,("%s", msgbuf ));
1239 #endif
1240 SAFE_FREE(msgbuf);
1243 /******** Solaris EA helper function prototypes ********/
1244 #ifdef HAVE_ATTROPEN
1245 #define SOLARIS_ATTRMODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP
1246 static int solaris_write_xattr(int attrfd, const char *value, size_t size);
1247 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size);
1248 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size);
1249 static int solaris_unlinkat(int attrdirfd, const char *name);
1250 static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode);
1251 static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode);
1252 #endif
1254 /**************************************************************************
1255 Wrappers for extented attribute calls. Based on the Linux package with
1256 support for IRIX and (Net|Free)BSD also. Expand as other systems have them.
1257 ****************************************************************************/
1259 ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t size)
1261 #if defined(HAVE_GETXATTR)
1262 #ifndef XATTR_ADD_OPT
1263 return getxattr(path, name, value, size);
1264 #else
1265 int options = 0;
1266 return getxattr(path, name, value, size, 0, options);
1267 #endif
1268 #elif defined(HAVE_GETEA)
1269 return getea(path, name, value, size);
1270 #elif defined(HAVE_EXTATTR_GET_FILE)
1271 char *s;
1272 ssize_t retval;
1273 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1274 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1275 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1277 * The BSD implementation has a nasty habit of silently truncating
1278 * the returned value to the size of the buffer, so we have to check
1279 * that the buffer is large enough to fit the returned value.
1281 if((retval=extattr_get_file(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1282 if(retval > size) {
1283 errno = ERANGE;
1284 return -1;
1286 if((retval=extattr_get_file(path, attrnamespace, attrname, value, size)) >= 0)
1287 return retval;
1290 DEBUG(10,("sys_getxattr: extattr_get_file() failed with: %s\n", strerror(errno)));
1291 return -1;
1292 #elif defined(HAVE_ATTR_GET)
1293 int retval, flags = 0;
1294 int valuelength = (int)size;
1295 char *attrname = strchr(name,'.') + 1;
1297 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1299 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1301 return retval ? retval : valuelength;
1302 #elif defined(HAVE_ATTROPEN)
1303 ssize_t ret = -1;
1304 int attrfd = solaris_attropen(path, name, O_RDONLY, 0);
1305 if (attrfd >= 0) {
1306 ret = solaris_read_xattr(attrfd, value, size);
1307 close(attrfd);
1309 return ret;
1310 #else
1311 errno = ENOSYS;
1312 return -1;
1313 #endif
1316 ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t size)
1318 #if defined(HAVE_LGETXATTR)
1319 return lgetxattr(path, name, value, size);
1320 #elif defined(HAVE_GETXATTR) && defined(XATTR_ADD_OPT)
1321 int options = XATTR_NOFOLLOW;
1322 return getxattr(path, name, value, size, 0, options);
1323 #elif defined(HAVE_LGETEA)
1324 return lgetea(path, name, value, size);
1325 #elif defined(HAVE_EXTATTR_GET_LINK)
1326 char *s;
1327 ssize_t retval;
1328 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1329 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1330 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1332 if((retval=extattr_get_link(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1333 if(retval > size) {
1334 errno = ERANGE;
1335 return -1;
1337 if((retval=extattr_get_link(path, attrnamespace, attrname, value, size)) >= 0)
1338 return retval;
1341 DEBUG(10,("sys_lgetxattr: extattr_get_link() failed with: %s\n", strerror(errno)));
1342 return -1;
1343 #elif defined(HAVE_ATTR_GET)
1344 int retval, flags = ATTR_DONTFOLLOW;
1345 int valuelength = (int)size;
1346 char *attrname = strchr(name,'.') + 1;
1348 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1350 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1352 return retval ? retval : valuelength;
1353 #elif defined(HAVE_ATTROPEN)
1354 ssize_t ret = -1;
1355 int attrfd = solaris_attropen(path, name, O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1356 if (attrfd >= 0) {
1357 ret = solaris_read_xattr(attrfd, value, size);
1358 close(attrfd);
1360 return ret;
1361 #else
1362 errno = ENOSYS;
1363 return -1;
1364 #endif
1367 ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size)
1369 #if defined(HAVE_FGETXATTR)
1370 #ifndef XATTR_ADD_OPT
1371 return fgetxattr(filedes, name, value, size);
1372 #else
1373 int options = 0;
1374 return fgetxattr(filedes, name, value, size, 0, options);
1375 #endif
1376 #elif defined(HAVE_FGETEA)
1377 return fgetea(filedes, name, value, size);
1378 #elif defined(HAVE_EXTATTR_GET_FD)
1379 char *s;
1380 ssize_t retval;
1381 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1382 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1383 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1385 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0)) >= 0) {
1386 if(retval > size) {
1387 errno = ERANGE;
1388 return -1;
1390 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, value, size)) >= 0)
1391 return retval;
1394 DEBUG(10,("sys_fgetxattr: extattr_get_fd() failed with: %s\n", strerror(errno)));
1395 return -1;
1396 #elif defined(HAVE_ATTR_GETF)
1397 int retval, flags = 0;
1398 int valuelength = (int)size;
1399 char *attrname = strchr(name,'.') + 1;
1401 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1403 retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags);
1405 return retval ? retval : valuelength;
1406 #elif defined(HAVE_ATTROPEN)
1407 ssize_t ret = -1;
1408 int attrfd = solaris_openat(filedes, name, O_RDONLY|O_XATTR, 0);
1409 if (attrfd >= 0) {
1410 ret = solaris_read_xattr(attrfd, value, size);
1411 close(attrfd);
1413 return ret;
1414 #else
1415 errno = ENOSYS;
1416 return -1;
1417 #endif
1420 #if defined(HAVE_EXTATTR_LIST_FILE)
1422 #define EXTATTR_PREFIX(s) (s), (sizeof((s))-1)
1424 static struct {
1425 int space;
1426 const char *name;
1427 size_t len;
1429 extattr[] = {
1430 { EXTATTR_NAMESPACE_SYSTEM, EXTATTR_PREFIX("system.") },
1431 { EXTATTR_NAMESPACE_USER, EXTATTR_PREFIX("user.") },
1434 typedef union {
1435 const char *path;
1436 int filedes;
1437 } extattr_arg;
1439 static ssize_t bsd_attr_list (int type, extattr_arg arg, char *list, size_t size)
1441 ssize_t list_size, total_size = 0;
1442 int i, t, len;
1443 char *buf;
1444 /* Iterate through extattr(2) namespaces */
1445 for(t = 0; t < (sizeof(extattr)/sizeof(extattr[0])); t++) {
1446 switch(type) {
1447 #if defined(HAVE_EXTATTR_LIST_FILE)
1448 case 0:
1449 list_size = extattr_list_file(arg.path, extattr[t].space, list, size);
1450 break;
1451 #endif
1452 #if defined(HAVE_EXTATTR_LIST_LINK)
1453 case 1:
1454 list_size = extattr_list_link(arg.path, extattr[t].space, list, size);
1455 break;
1456 #endif
1457 #if defined(HAVE_EXTATTR_LIST_FD)
1458 case 2:
1459 list_size = extattr_list_fd(arg.filedes, extattr[t].space, list, size);
1460 break;
1461 #endif
1462 default:
1463 errno = ENOSYS;
1464 return -1;
1466 /* Some error happend. Errno should be set by the previous call */
1467 if(list_size < 0)
1468 return -1;
1469 /* No attributes */
1470 if(list_size == 0)
1471 continue;
1472 /* XXX: Call with an empty buffer may be used to calculate
1473 necessary buffer size. Unfortunately, we can't say, how
1474 many attributes were returned, so here is the potential
1475 problem with the emulation.
1477 if(list == NULL) {
1478 /* Take the worse case of one char attribute names -
1479 two bytes per name plus one more for sanity.
1481 total_size += list_size + (list_size/2 + 1)*extattr[t].len;
1482 continue;
1484 /* Count necessary offset to fit namespace prefixes */
1485 len = 0;
1486 for(i = 0; i < list_size; i += list[i] + 1)
1487 len += extattr[t].len;
1489 total_size += list_size + len;
1490 /* Buffer is too small to fit the results */
1491 if(total_size > size) {
1492 errno = ERANGE;
1493 return -1;
1495 /* Shift results back, so we can prepend prefixes */
1496 buf = memmove(list + len, list, list_size);
1498 for(i = 0; i < list_size; i += len + 1) {
1499 len = buf[i];
1500 strncpy(list, extattr[t].name, extattr[t].len + 1);
1501 list += extattr[t].len;
1502 strncpy(list, buf + i + 1, len);
1503 list[len] = '\0';
1504 list += len + 1;
1506 size -= total_size;
1508 return total_size;
1511 #endif
1513 #if defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1514 static char attr_buffer[ATTR_MAX_VALUELEN];
1516 static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags)
1518 int retval = 0, index;
1519 attrlist_cursor_t *cursor = 0;
1520 int total_size = 0;
1521 attrlist_t * al = (attrlist_t *)attr_buffer;
1522 attrlist_ent_t *ae;
1523 size_t ent_size, left = size;
1524 char *bp = list;
1526 while (True) {
1527 if (filedes)
1528 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1529 else
1530 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1531 if (retval) break;
1532 for (index = 0; index < al->al_count; index++) {
1533 ae = ATTR_ENTRY(attr_buffer, index);
1534 ent_size = strlen(ae->a_name) + sizeof("user.");
1535 if (left >= ent_size) {
1536 strncpy(bp, "user.", sizeof("user."));
1537 strncat(bp, ae->a_name, ent_size - sizeof("user."));
1538 bp += ent_size;
1539 left -= ent_size;
1540 } else if (size) {
1541 errno = ERANGE;
1542 retval = -1;
1543 break;
1545 total_size += ent_size;
1547 if (al->al_more == 0) break;
1549 if (retval == 0) {
1550 flags |= ATTR_ROOT;
1551 cursor = 0;
1552 while (True) {
1553 if (filedes)
1554 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1555 else
1556 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1557 if (retval) break;
1558 for (index = 0; index < al->al_count; index++) {
1559 ae = ATTR_ENTRY(attr_buffer, index);
1560 ent_size = strlen(ae->a_name) + sizeof("system.");
1561 if (left >= ent_size) {
1562 strncpy(bp, "system.", sizeof("system."));
1563 strncat(bp, ae->a_name, ent_size - sizeof("system."));
1564 bp += ent_size;
1565 left -= ent_size;
1566 } else if (size) {
1567 errno = ERANGE;
1568 retval = -1;
1569 break;
1571 total_size += ent_size;
1573 if (al->al_more == 0) break;
1576 return (ssize_t)(retval ? retval : total_size);
1579 #endif
1581 ssize_t sys_listxattr (const char *path, char *list, size_t size)
1583 #if defined(HAVE_LISTXATTR)
1584 #ifndef XATTR_ADD_OPT
1585 return listxattr(path, list, size);
1586 #else
1587 int options = 0;
1588 return listxattr(path, list, size, options);
1589 #endif
1590 #elif defined(HAVE_LISTEA)
1591 return listea(path, list, size);
1592 #elif defined(HAVE_EXTATTR_LIST_FILE)
1593 extattr_arg arg;
1594 arg.path = path;
1595 return bsd_attr_list(0, arg, list, size);
1596 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1597 return irix_attr_list(path, 0, list, size, 0);
1598 #elif defined(HAVE_ATTROPEN)
1599 ssize_t ret = -1;
1600 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
1601 if (attrdirfd >= 0) {
1602 ret = solaris_list_xattr(attrdirfd, list, size);
1603 close(attrdirfd);
1605 return ret;
1606 #else
1607 errno = ENOSYS;
1608 return -1;
1609 #endif
1612 ssize_t sys_llistxattr (const char *path, char *list, size_t size)
1614 #if defined(HAVE_LLISTXATTR)
1615 return llistxattr(path, list, size);
1616 #elif defined(HAVE_LISTXATTR) && defined(XATTR_ADD_OPT)
1617 int options = XATTR_NOFOLLOW;
1618 return listxattr(path, list, size, options);
1619 #elif defined(HAVE_LLISTEA)
1620 return llistea(path, list, size);
1621 #elif defined(HAVE_EXTATTR_LIST_LINK)
1622 extattr_arg arg;
1623 arg.path = path;
1624 return bsd_attr_list(1, arg, list, size);
1625 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1626 return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW);
1627 #elif defined(HAVE_ATTROPEN)
1628 ssize_t ret = -1;
1629 int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1630 if (attrdirfd >= 0) {
1631 ret = solaris_list_xattr(attrdirfd, list, size);
1632 close(attrdirfd);
1634 return ret;
1635 #else
1636 errno = ENOSYS;
1637 return -1;
1638 #endif
1641 ssize_t sys_flistxattr (int filedes, char *list, size_t size)
1643 #if defined(HAVE_FLISTXATTR)
1644 #ifndef XATTR_ADD_OPT
1645 return flistxattr(filedes, list, size);
1646 #else
1647 int options = 0;
1648 return flistxattr(filedes, list, size, options);
1649 #endif
1650 #elif defined(HAVE_FLISTEA)
1651 return flistea(filedes, list, size);
1652 #elif defined(HAVE_EXTATTR_LIST_FD)
1653 extattr_arg arg;
1654 arg.filedes = filedes;
1655 return bsd_attr_list(2, arg, list, size);
1656 #elif defined(HAVE_ATTR_LISTF)
1657 return irix_attr_list(NULL, filedes, list, size, 0);
1658 #elif defined(HAVE_ATTROPEN)
1659 ssize_t ret = -1;
1660 int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
1661 if (attrdirfd >= 0) {
1662 ret = solaris_list_xattr(attrdirfd, list, size);
1663 close(attrdirfd);
1665 return ret;
1666 #else
1667 errno = ENOSYS;
1668 return -1;
1669 #endif
1672 int sys_removexattr (const char *path, const char *name)
1674 #if defined(HAVE_REMOVEXATTR)
1675 #ifndef XATTR_ADD_OPT
1676 return removexattr(path, name);
1677 #else
1678 int options = 0;
1679 return removexattr(path, name, options);
1680 #endif
1681 #elif defined(HAVE_REMOVEEA)
1682 return removeea(path, name);
1683 #elif defined(HAVE_EXTATTR_DELETE_FILE)
1684 char *s;
1685 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1686 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1687 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1689 return extattr_delete_file(path, attrnamespace, attrname);
1690 #elif defined(HAVE_ATTR_REMOVE)
1691 int flags = 0;
1692 char *attrname = strchr(name,'.') + 1;
1694 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1696 return attr_remove(path, attrname, flags);
1697 #elif defined(HAVE_ATTROPEN)
1698 int ret = -1;
1699 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
1700 if (attrdirfd >= 0) {
1701 ret = solaris_unlinkat(attrdirfd, name);
1702 close(attrdirfd);
1704 return ret;
1705 #else
1706 errno = ENOSYS;
1707 return -1;
1708 #endif
1711 int sys_lremovexattr (const char *path, const char *name)
1713 #if defined(HAVE_LREMOVEXATTR)
1714 return lremovexattr(path, name);
1715 #elif defined(HAVE_REMOVEXATTR) && defined(XATTR_ADD_OPT)
1716 int options = XATTR_NOFOLLOW;
1717 return removexattr(path, name, options);
1718 #elif defined(HAVE_LREMOVEEA)
1719 return lremoveea(path, name);
1720 #elif defined(HAVE_EXTATTR_DELETE_LINK)
1721 char *s;
1722 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1723 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1724 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1726 return extattr_delete_link(path, attrnamespace, attrname);
1727 #elif defined(HAVE_ATTR_REMOVE)
1728 int flags = ATTR_DONTFOLLOW;
1729 char *attrname = strchr(name,'.') + 1;
1731 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1733 return attr_remove(path, attrname, flags);
1734 #elif defined(HAVE_ATTROPEN)
1735 int ret = -1;
1736 int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1737 if (attrdirfd >= 0) {
1738 ret = solaris_unlinkat(attrdirfd, name);
1739 close(attrdirfd);
1741 return ret;
1742 #else
1743 errno = ENOSYS;
1744 return -1;
1745 #endif
1748 int sys_fremovexattr (int filedes, const char *name)
1750 #if defined(HAVE_FREMOVEXATTR)
1751 #ifndef XATTR_ADD_OPT
1752 return fremovexattr(filedes, name);
1753 #else
1754 int options = 0;
1755 return fremovexattr(filedes, name, options);
1756 #endif
1757 #elif defined(HAVE_FREMOVEEA)
1758 return fremoveea(filedes, name);
1759 #elif defined(HAVE_EXTATTR_DELETE_FD)
1760 char *s;
1761 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1762 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1763 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1765 return extattr_delete_fd(filedes, attrnamespace, attrname);
1766 #elif defined(HAVE_ATTR_REMOVEF)
1767 int flags = 0;
1768 char *attrname = strchr(name,'.') + 1;
1770 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1772 return attr_removef(filedes, attrname, flags);
1773 #elif defined(HAVE_ATTROPEN)
1774 int ret = -1;
1775 int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
1776 if (attrdirfd >= 0) {
1777 ret = solaris_unlinkat(attrdirfd, name);
1778 close(attrdirfd);
1780 return ret;
1781 #else
1782 errno = ENOSYS;
1783 return -1;
1784 #endif
1787 int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags)
1789 #if defined(HAVE_SETXATTR)
1790 #ifndef XATTR_ADD_OPT
1791 return setxattr(path, name, value, size, flags);
1792 #else
1793 int options = 0;
1794 return setxattr(path, name, value, size, 0, options);
1795 #endif
1796 #elif defined(HAVE_SETEA)
1797 return setea(path, name, value, size, flags);
1798 #elif defined(HAVE_EXTATTR_SET_FILE)
1799 char *s;
1800 int retval = 0;
1801 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1802 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1803 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1804 if (flags) {
1805 /* Check attribute existence */
1806 retval = extattr_get_file(path, attrnamespace, attrname, NULL, 0);
1807 if (retval < 0) {
1808 /* REPLACE attribute, that doesn't exist */
1809 if (flags & XATTR_REPLACE && errno == ENOATTR) {
1810 errno = ENOATTR;
1811 return -1;
1813 /* Ignore other errors */
1815 else {
1816 /* CREATE attribute, that already exists */
1817 if (flags & XATTR_CREATE) {
1818 errno = EEXIST;
1819 return -1;
1823 retval = extattr_set_file(path, attrnamespace, attrname, value, size);
1824 return (retval < 0) ? -1 : 0;
1825 #elif defined(HAVE_ATTR_SET)
1826 int myflags = 0;
1827 char *attrname = strchr(name,'.') + 1;
1829 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
1830 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
1831 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
1833 return attr_set(path, attrname, (const char *)value, size, myflags);
1834 #elif defined(HAVE_ATTROPEN)
1835 int ret = -1;
1836 int myflags = O_RDWR;
1837 int attrfd;
1838 if (flags & XATTR_CREATE) myflags |= O_EXCL;
1839 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
1840 attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
1841 if (attrfd >= 0) {
1842 ret = solaris_write_xattr(attrfd, value, size);
1843 close(attrfd);
1845 return ret;
1846 #else
1847 errno = ENOSYS;
1848 return -1;
1849 #endif
1852 int sys_lsetxattr (const char *path, const char *name, const void *value, size_t size, int flags)
1854 #if defined(HAVE_LSETXATTR)
1855 return lsetxattr(path, name, value, size, flags);
1856 #elif defined(HAVE_SETXATTR) && defined(XATTR_ADD_OPT)
1857 int options = XATTR_NOFOLLOW;
1858 return setxattr(path, name, value, size, 0, options);
1859 #elif defined(LSETEA)
1860 return lsetea(path, name, value, size, flags);
1861 #elif defined(HAVE_EXTATTR_SET_LINK)
1862 char *s;
1863 int retval = 0;
1864 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1865 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1866 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1867 if (flags) {
1868 /* Check attribute existence */
1869 retval = extattr_get_link(path, attrnamespace, attrname, NULL, 0);
1870 if (retval < 0) {
1871 /* REPLACE attribute, that doesn't exist */
1872 if (flags & XATTR_REPLACE && errno == ENOATTR) {
1873 errno = ENOATTR;
1874 return -1;
1876 /* Ignore other errors */
1878 else {
1879 /* CREATE attribute, that already exists */
1880 if (flags & XATTR_CREATE) {
1881 errno = EEXIST;
1882 return -1;
1887 retval = extattr_set_link(path, attrnamespace, attrname, value, size);
1888 return (retval < 0) ? -1 : 0;
1889 #elif defined(HAVE_ATTR_SET)
1890 int myflags = ATTR_DONTFOLLOW;
1891 char *attrname = strchr(name,'.') + 1;
1893 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
1894 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
1895 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
1897 return attr_set(path, attrname, (const char *)value, size, myflags);
1898 #elif defined(HAVE_ATTROPEN)
1899 int ret = -1;
1900 int myflags = O_RDWR | AT_SYMLINK_NOFOLLOW;
1901 int attrfd;
1902 if (flags & XATTR_CREATE) myflags |= O_EXCL;
1903 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
1904 attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
1905 if (attrfd >= 0) {
1906 ret = solaris_write_xattr(attrfd, value, size);
1907 close(attrfd);
1909 return ret;
1910 #else
1911 errno = ENOSYS;
1912 return -1;
1913 #endif
1916 int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags)
1918 #if defined(HAVE_FSETXATTR)
1919 #ifndef XATTR_ADD_OPT
1920 return fsetxattr(filedes, name, value, size, flags);
1921 #else
1922 int options = 0;
1923 return fsetxattr(filedes, name, value, size, 0, options);
1924 #endif
1925 #elif defined(HAVE_FSETEA)
1926 return fsetea(filedes, name, value, size, flags);
1927 #elif defined(HAVE_EXTATTR_SET_FD)
1928 char *s;
1929 int retval = 0;
1930 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1931 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1932 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1933 if (flags) {
1934 /* Check attribute existence */
1935 retval = extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0);
1936 if (retval < 0) {
1937 /* REPLACE attribute, that doesn't exist */
1938 if (flags & XATTR_REPLACE && errno == ENOATTR) {
1939 errno = ENOATTR;
1940 return -1;
1942 /* Ignore other errors */
1944 else {
1945 /* CREATE attribute, that already exists */
1946 if (flags & XATTR_CREATE) {
1947 errno = EEXIST;
1948 return -1;
1952 retval = extattr_set_fd(filedes, attrnamespace, attrname, value, size);
1953 return (retval < 0) ? -1 : 0;
1954 #elif defined(HAVE_ATTR_SETF)
1955 int myflags = 0;
1956 char *attrname = strchr(name,'.') + 1;
1958 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
1959 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
1960 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
1962 return attr_setf(filedes, attrname, (const char *)value, size, myflags);
1963 #elif defined(HAVE_ATTROPEN)
1964 int ret = -1;
1965 int myflags = O_RDWR | O_XATTR;
1966 int attrfd;
1967 if (flags & XATTR_CREATE) myflags |= O_EXCL;
1968 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
1969 attrfd = solaris_openat(filedes, name, myflags, (mode_t) SOLARIS_ATTRMODE);
1970 if (attrfd >= 0) {
1971 ret = solaris_write_xattr(attrfd, value, size);
1972 close(attrfd);
1974 return ret;
1975 #else
1976 errno = ENOSYS;
1977 return -1;
1978 #endif
1981 /**************************************************************************
1982 helper functions for Solaris' EA support
1983 ****************************************************************************/
1984 #ifdef HAVE_ATTROPEN
1985 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size)
1987 struct stat sbuf;
1989 if (fstat(attrfd, &sbuf) == -1) {
1990 errno = ENOATTR;
1991 return -1;
1994 /* This is to return the current size of the named extended attribute */
1995 if (size == 0) {
1996 return sbuf.st_size;
1999 /* check size and read xattr */
2000 if (sbuf.st_size > size) {
2001 errno = ERANGE;
2002 return -1;
2005 return read(attrfd, value, sbuf.st_size);
2008 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size)
2010 ssize_t len = 0;
2011 int stop = 0;
2012 DIR *dirp;
2013 struct dirent *de;
2014 int newfd = dup(attrdirfd);
2015 /* CAUTION: The originating file descriptor should not be
2016 used again following the call to fdopendir().
2017 For that reason we dup() the file descriptor
2018 here to make things more clear. */
2019 dirp = fdopendir(newfd);
2021 while ((de = readdir(dirp))) {
2022 size_t listlen = strlen(de->d_name);
2023 if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) {
2024 /* we don't want "." and ".." here: */
2025 DEBUG(10,("skipped EA %s\n",de->d_name));
2026 continue;
2029 if (size == 0) {
2030 /* return the current size of the list of extended attribute names*/
2031 len += listlen + 1;
2032 } else {
2033 /* check size and copy entrieѕ + nul into list. */
2034 if ((len + listlen + 1) > size) {
2035 errno = ERANGE;
2036 len = -1;
2037 break;
2038 } else {
2039 safe_strcpy(list + len, de->d_name, listlen);
2040 len += listlen;
2041 list[len] = '\0';
2042 ++len;
2047 if (closedir(dirp) == -1) {
2048 DEBUG(0,("closedir dirp failed: %s\n",strerror(errno)));
2049 return -1;
2051 return len;
2054 static int solaris_unlinkat(int attrdirfd, const char *name)
2056 if (unlinkat(attrdirfd, name, 0) == -1) {
2057 if (errno == ENOENT) {
2058 errno = ENOATTR;
2060 return -1;
2062 return 0;
2065 static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode)
2067 int filedes = attropen(path, attrpath, oflag, mode);
2068 if (filedes == -1) {
2069 DEBUG(10,("attropen FAILED: path: %s, name: %s, errno: %s\n",path,attrpath,strerror(errno)));
2070 if (errno == EINVAL) {
2071 errno = ENOTSUP;
2072 } else {
2073 errno = ENOATTR;
2076 return filedes;
2079 static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode)
2081 int filedes = openat(fildes, path, oflag, mode);
2082 if (filedes == -1) {
2083 DEBUG(10,("openat FAILED: fd: %s, path: %s, errno: %s\n",filedes,path,strerror(errno)));
2084 if (errno == EINVAL) {
2085 errno = ENOTSUP;
2086 } else {
2087 errno = ENOATTR;
2090 return filedes;
2093 static int solaris_write_xattr(int attrfd, const char *value, size_t size)
2095 if ((ftruncate(attrfd, 0) == 0) && (write(attrfd, value, size) == size)) {
2096 return 0;
2097 } else {
2098 DEBUG(10,("solaris_write_xattr FAILED!\n"));
2099 return -1;
2102 #endif /*HAVE_ATTROPEN*/
2105 /****************************************************************************
2106 Return the major devicenumber for UNIX extensions.
2107 ****************************************************************************/
2109 uint32 unix_dev_major(SMB_DEV_T dev)
2111 #if defined(HAVE_DEVICE_MAJOR_FN)
2112 return (uint32)major(dev);
2113 #else
2114 return (uint32)(dev >> 8);
2115 #endif
2118 /****************************************************************************
2119 Return the minor devicenumber for UNIX extensions.
2120 ****************************************************************************/
2122 uint32 unix_dev_minor(SMB_DEV_T dev)
2124 #if defined(HAVE_DEVICE_MINOR_FN)
2125 return (uint32)minor(dev);
2126 #else
2127 return (uint32)(dev & 0xff);
2128 #endif
2131 #if defined(WITH_AIO)
2133 /*******************************************************************
2134 An aio_read wrapper that will deal with 64-bit sizes.
2135 ********************************************************************/
2137 int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2139 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_READ64)
2140 return aio_read64(aiocb);
2141 #elif defined(HAVE_AIO_READ)
2142 return aio_read(aiocb);
2143 #else
2144 errno = ENOSYS;
2145 return -1;
2146 #endif
2149 /*******************************************************************
2150 An aio_write wrapper that will deal with 64-bit sizes.
2151 ********************************************************************/
2153 int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2155 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_WRITE64)
2156 return aio_write64(aiocb);
2157 #elif defined(HAVE_AIO_WRITE)
2158 return aio_write(aiocb);
2159 #else
2160 errno = ENOSYS;
2161 return -1;
2162 #endif
2165 /*******************************************************************
2166 An aio_return wrapper that will deal with 64-bit sizes.
2167 ********************************************************************/
2169 ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2171 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_RETURN64)
2172 return aio_return64(aiocb);
2173 #elif defined(HAVE_AIO_RETURN)
2174 return aio_return(aiocb);
2175 #else
2176 errno = ENOSYS;
2177 return -1;
2178 #endif
2181 /*******************************************************************
2182 An aio_cancel wrapper that will deal with 64-bit sizes.
2183 ********************************************************************/
2185 int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2187 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_CANCEL64)
2188 return aio_cancel64(fd, aiocb);
2189 #elif defined(HAVE_AIO_CANCEL)
2190 return aio_cancel(fd, aiocb);
2191 #else
2192 errno = ENOSYS;
2193 return -1;
2194 #endif
2197 /*******************************************************************
2198 An aio_error wrapper that will deal with 64-bit sizes.
2199 ********************************************************************/
2201 int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2203 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_ERROR64)
2204 return aio_error64(aiocb);
2205 #elif defined(HAVE_AIO_ERROR)
2206 return aio_error(aiocb);
2207 #else
2208 errno = ENOSYS;
2209 return -1;
2210 #endif
2213 /*******************************************************************
2214 An aio_fsync wrapper that will deal with 64-bit sizes.
2215 ********************************************************************/
2217 int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2219 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_FSYNC64)
2220 return aio_fsync64(op, aiocb);
2221 #elif defined(HAVE_AIO_FSYNC)
2222 return aio_fsync(op, aiocb);
2223 #else
2224 errno = ENOSYS;
2225 return -1;
2226 #endif
2229 /*******************************************************************
2230 An aio_fsync wrapper that will deal with 64-bit sizes.
2231 ********************************************************************/
2233 int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2235 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_SUSPEND64)
2236 return aio_suspend64(cblist, n, timeout);
2237 #elif defined(HAVE_AIO_FSYNC)
2238 return aio_suspend(cblist, n, timeout);
2239 #else
2240 errno = ENOSYS;
2241 return -1;
2242 #endif
2244 #else /* !WITH_AIO */
2246 int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2248 errno = ENOSYS;
2249 return -1;
2252 int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2254 errno = ENOSYS;
2255 return -1;
2258 ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2260 errno = ENOSYS;
2261 return -1;
2264 int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2266 errno = ENOSYS;
2267 return -1;
2270 int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2272 errno = ENOSYS;
2273 return -1;
2276 int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2278 errno = ENOSYS;
2279 return -1;
2282 int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2284 errno = ENOSYS;
2285 return -1;
2287 #endif /* WITH_AIO */
2289 int sys_getpeereid( int s, uid_t *uid)
2291 #if defined(HAVE_PEERCRED)
2292 struct ucred cred;
2293 socklen_t cred_len = sizeof(struct ucred);
2294 int ret;
2296 ret = getsockopt(s, SOL_SOCKET, SO_PEERCRED, (void *)&cred, &cred_len);
2297 if (ret != 0) {
2298 return -1;
2301 if (cred_len != sizeof(struct ucred)) {
2302 errno = EINVAL;
2303 return -1;
2306 *uid = cred.uid;
2307 return 0;
2308 #else
2309 errno = ENOSYS;
2310 return -1;
2311 #endif
2314 int sys_getnameinfo(const struct sockaddr *psa,
2315 socklen_t salen,
2316 char *host,
2317 size_t hostlen,
2318 char *service,
2319 size_t servlen,
2320 int flags)
2323 * For Solaris we must make sure salen is the
2324 * correct length for the incoming sa_family.
2327 if (salen == sizeof(struct sockaddr_storage)) {
2328 salen = sizeof(struct sockaddr_in);
2329 #if defined(HAVE_IPV6)
2330 if (psa->sa_family == AF_INET6) {
2331 salen = sizeof(struct sockaddr_in6);
2333 #endif
2335 return getnameinfo(psa, salen, host, hostlen, service, servlen, flags);
2338 int sys_connect(int fd, const struct sockaddr * addr)
2340 socklen_t salen = -1;
2342 if (addr->sa_family == AF_INET) {
2343 salen = sizeof(struct sockaddr_in);
2344 } else if (addr->sa_family == AF_UNIX) {
2345 salen = sizeof(struct sockaddr_un);
2347 #if defined(HAVE_IPV6)
2348 else if (addr->sa_family == AF_INET6) {
2349 salen = sizeof(struct sockaddr_in6);
2351 #endif
2353 return connect(fd, addr, salen);