dnscrypto-proxy: Support files updated.
[tomato.git] / release / src / router / samba3 / source / lib / system.c
blobb8f5a739c9387f4029ada3b8400832008b155e05
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 2 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, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "includes.h"
26 #ifdef HAVE_SYS_PRCTL_H
27 #include <sys/prctl.h>
28 #endif
31 The idea is that this file will eventually have wrappers around all
32 important system calls in samba. The aims are:
34 - to enable easier porting by putting OS dependent stuff in here
36 - to allow for hooks into other "pseudo-filesystems"
38 - to allow easier integration of things like the japanese extensions
40 - to support the philosophy of Samba to expose the features of
41 the OS within the SMB model. In general whatever file/printer/variable
42 expansions/etc make sense to the OS should be acceptable to Samba.
47 /*******************************************************************
48 A wrapper for memalign
49 ********************************************************************/
51 void *sys_memalign( size_t align, size_t size )
53 #if defined(HAVE_POSIX_MEMALIGN)
54 void *p = NULL;
55 int ret = posix_memalign( &p, align, size );
56 if ( ret == 0 )
57 return p;
59 return NULL;
60 #elif defined(HAVE_MEMALIGN)
61 return memalign( align, size );
62 #else
63 /* On *BSD systems memaligns doesn't exist, but memory will
64 * be aligned on allocations of > pagesize. */
65 #if defined(SYSCONF_SC_PAGESIZE)
66 size_t pagesize = (size_t)sysconf(_SC_PAGESIZE);
67 #elif defined(HAVE_GETPAGESIZE)
68 size_t pagesize = (size_t)getpagesize();
69 #else
70 size_t pagesize = (size_t)-1;
71 #endif
72 if (pagesize == (size_t)-1) {
73 DEBUG(0,("memalign functionalaity not available on this platform!\n"));
74 return NULL;
76 if (size < pagesize) {
77 size = pagesize;
79 return SMB_MALLOC(size);
80 #endif
83 /*******************************************************************
84 A wrapper for usleep in case we don't have one.
85 ********************************************************************/
87 int sys_usleep(long usecs)
89 #ifndef HAVE_USLEEP
90 struct timeval tval;
91 #endif
94 * We need this braindamage as the glibc usleep
95 * is not SPEC1170 complient... grumble... JRA.
98 if(usecs < 0 || usecs > 1000000) {
99 errno = EINVAL;
100 return -1;
103 #if HAVE_USLEEP
104 usleep(usecs);
105 return 0;
106 #else /* HAVE_USLEEP */
108 * Fake it with select...
110 tval.tv_sec = 0;
111 tval.tv_usec = usecs/1000;
112 select(0,NULL,NULL,NULL,&tval);
113 return 0;
114 #endif /* HAVE_USLEEP */
117 /*******************************************************************
118 A read wrapper that will deal with EINTR.
119 ********************************************************************/
121 ssize_t sys_read(int fd, void *buf, size_t count)
123 ssize_t ret;
125 do {
126 ret = read(fd, buf, count);
127 } while (ret == -1 && errno == EINTR);
128 return ret;
131 /*******************************************************************
132 A write wrapper that will deal with EINTR.
133 ********************************************************************/
135 ssize_t sys_write(int fd, const void *buf, size_t count)
137 ssize_t ret;
139 do {
140 ret = write(fd, buf, count);
141 } while (ret == -1 && errno == EINTR);
142 return ret;
145 /*******************************************************************
146 A pread wrapper that will deal with EINTR and 64-bit file offsets.
147 ********************************************************************/
149 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
150 ssize_t sys_pread(int fd, void *buf, size_t count, SMB_OFF_T off)
152 ssize_t ret;
154 do {
155 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_PREAD64)
156 ret = pread64(fd, buf, count, off);
157 #else
158 ret = pread(fd, buf, count, off);
159 #endif
160 } while (ret == -1 && errno == EINTR);
161 return ret;
163 #endif
165 /*******************************************************************
166 A write wrapper that will deal with EINTR and 64-bit file offsets.
167 ********************************************************************/
169 #if defined(HAVE_PWRITE) || defined(HAVE_PWRITE64)
170 ssize_t sys_pwrite(int fd, const void *buf, size_t count, SMB_OFF_T off)
172 ssize_t ret;
174 do {
175 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_PWRITE64)
176 ret = pwrite64(fd, buf, count, off);
177 #else
178 ret = pwrite(fd, buf, count, off);
179 #endif
180 } while (ret == -1 && errno == EINTR);
181 return ret;
183 #endif
185 /*******************************************************************
186 A send wrapper that will deal with EINTR.
187 ********************************************************************/
189 ssize_t sys_send(int s, const void *msg, size_t len, int flags)
191 ssize_t ret;
193 do {
194 ret = send(s, msg, len, flags);
195 } while (ret == -1 && errno == EINTR);
196 return ret;
199 /*******************************************************************
200 A sendto wrapper that will deal with EINTR.
201 ********************************************************************/
203 ssize_t sys_sendto(int s, const void *msg, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
205 ssize_t ret;
207 do {
208 ret = sendto(s, msg, len, flags, to, tolen);
209 } while (ret == -1 && errno == EINTR);
210 return ret;
213 /*******************************************************************
214 A recv wrapper that will deal with EINTR.
215 ********************************************************************/
217 ssize_t sys_recv(int fd, void *buf, size_t count, int flags)
219 ssize_t ret;
221 do {
222 ret = recv(fd, buf, count, flags);
223 } while (ret == -1 && errno == EINTR);
224 return ret;
227 /*******************************************************************
228 A recvfrom wrapper that will deal with EINTR.
229 ********************************************************************/
231 ssize_t sys_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
233 ssize_t ret;
235 do {
236 ret = recvfrom(s, buf, len, flags, from, fromlen);
237 } while (ret == -1 && errno == EINTR);
238 return ret;
241 /*******************************************************************
242 A fcntl wrapper that will deal with EINTR.
243 ********************************************************************/
245 int sys_fcntl_ptr(int fd, int cmd, void *arg)
247 int ret;
249 do {
250 ret = fcntl(fd, cmd, arg);
251 } while (ret == -1 && errno == EINTR);
252 return ret;
255 /*******************************************************************
256 A fcntl wrapper that will deal with EINTR.
257 ********************************************************************/
259 int sys_fcntl_long(int fd, int cmd, long arg)
261 int ret;
263 do {
264 ret = fcntl(fd, cmd, arg);
265 } while (ret == -1 && errno == EINTR);
266 return ret;
269 /*******************************************************************
270 A stat() wrapper that will deal with 64 bit filesizes.
271 ********************************************************************/
273 int sys_stat(const char *fname,SMB_STRUCT_STAT *sbuf)
275 int ret;
276 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
277 ret = stat64(fname, sbuf);
278 #else
279 ret = stat(fname, sbuf);
280 #endif
281 /* we always want directories to appear zero size */
282 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
283 return ret;
286 /*******************************************************************
287 An fstat() wrapper that will deal with 64 bit filesizes.
288 ********************************************************************/
290 int sys_fstat(int fd,SMB_STRUCT_STAT *sbuf)
292 int ret;
293 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FSTAT64)
294 ret = fstat64(fd, sbuf);
295 #else
296 ret = fstat(fd, sbuf);
297 #endif
298 /* we always want directories to appear zero size */
299 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
300 return ret;
303 /*******************************************************************
304 An lstat() wrapper that will deal with 64 bit filesizes.
305 ********************************************************************/
307 int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf)
309 int ret;
310 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSTAT64)
311 ret = lstat64(fname, sbuf);
312 #else
313 ret = lstat(fname, sbuf);
314 #endif
315 /* we always want directories to appear zero size */
316 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
317 return ret;
320 /*******************************************************************
321 An ftruncate() wrapper that will deal with 64 bit filesizes.
322 ********************************************************************/
324 int sys_ftruncate(int fd, SMB_OFF_T offset)
326 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FTRUNCATE64)
327 return ftruncate64(fd, offset);
328 #else
329 return ftruncate(fd, offset);
330 #endif
333 /*******************************************************************
334 An lseek() wrapper that will deal with 64 bit filesizes.
335 ********************************************************************/
337 SMB_OFF_T sys_lseek(int fd, SMB_OFF_T offset, int whence)
339 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSEEK64)
340 return lseek64(fd, offset, whence);
341 #else
342 return lseek(fd, offset, whence);
343 #endif
346 /*******************************************************************
347 An fseek() wrapper that will deal with 64 bit filesizes.
348 ********************************************************************/
350 int sys_fseek(FILE *fp, SMB_OFF_T offset, int whence)
352 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEK64)
353 return fseek64(fp, offset, whence);
354 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEKO64)
355 return fseeko64(fp, offset, whence);
356 #else
357 return fseek(fp, offset, whence);
358 #endif
361 /*******************************************************************
362 An ftell() wrapper that will deal with 64 bit filesizes.
363 ********************************************************************/
365 SMB_OFF_T sys_ftell(FILE *fp)
367 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELL64)
368 return (SMB_OFF_T)ftell64(fp);
369 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELLO64)
370 return (SMB_OFF_T)ftello64(fp);
371 #else
372 return (SMB_OFF_T)ftell(fp);
373 #endif
376 /*******************************************************************
377 A creat() wrapper that will deal with 64 bit filesizes.
378 ********************************************************************/
380 int sys_creat(const char *path, mode_t mode)
382 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CREAT64)
383 return creat64(path, mode);
384 #else
386 * If creat64 isn't defined then ensure we call a potential open64.
387 * JRA.
389 return sys_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
390 #endif
393 /*******************************************************************
394 An open() wrapper that will deal with 64 bit filesizes.
395 ********************************************************************/
397 int sys_open(const char *path, int oflag, mode_t mode)
399 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPEN64)
400 return open64(path, oflag, mode);
401 #else
402 return open(path, oflag, mode);
403 #endif
406 /*******************************************************************
407 An fopen() wrapper that will deal with 64 bit filesizes.
408 ********************************************************************/
410 FILE *sys_fopen(const char *path, const char *type)
412 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FOPEN64)
413 return fopen64(path, type);
414 #else
415 return fopen(path, type);
416 #endif
420 /*******************************************************************
421 A flock() wrapper that will perform the kernel flock.
422 ********************************************************************/
424 void kernel_flock(int fd, uint32 share_mode)
426 #if HAVE_KERNEL_SHARE_MODES
427 int kernel_mode = 0;
428 if (share_mode == FILE_SHARE_WRITE) {
429 kernel_mode = LOCK_MAND|LOCK_WRITE;
430 } else if (share_mode == FILE_SHARE_READ) {
431 kernel_mode = LOCK_MAND|LOCK_READ;
432 } else if (share_mode == FILE_SHARE_NONE) {
433 kernel_mode = LOCK_MAND;
435 if (kernel_mode) {
436 flock(fd, kernel_mode);
438 #endif
444 /*******************************************************************
445 An opendir wrapper that will deal with 64 bit filesizes.
446 ********************************************************************/
448 SMB_STRUCT_DIR *sys_opendir(const char *name)
450 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPENDIR64)
451 return opendir64(name);
452 #else
453 return opendir(name);
454 #endif
457 /*******************************************************************
458 A readdir wrapper that will deal with 64 bit filesizes.
459 ********************************************************************/
461 SMB_STRUCT_DIRENT *sys_readdir(SMB_STRUCT_DIR *dirp)
463 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_READDIR64)
464 return readdir64(dirp);
465 #else
466 return readdir(dirp);
467 #endif
470 /*******************************************************************
471 A seekdir wrapper that will deal with 64 bit filesizes.
472 ********************************************************************/
474 void sys_seekdir(SMB_STRUCT_DIR *dirp, long offset)
476 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_SEEKDIR64)
477 seekdir64(dirp, offset);
478 #else
479 seekdir(dirp, offset);
480 #endif
483 /*******************************************************************
484 A telldir wrapper that will deal with 64 bit filesizes.
485 ********************************************************************/
487 long sys_telldir(SMB_STRUCT_DIR *dirp)
489 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_TELLDIR64)
490 return (long)telldir64(dirp);
491 #else
492 return (long)telldir(dirp);
493 #endif
496 /*******************************************************************
497 A rewinddir wrapper that will deal with 64 bit filesizes.
498 ********************************************************************/
500 void sys_rewinddir(SMB_STRUCT_DIR *dirp)
502 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_REWINDDIR64)
503 rewinddir64(dirp);
504 #else
505 rewinddir(dirp);
506 #endif
509 /*******************************************************************
510 A close wrapper that will deal with 64 bit filesizes.
511 ********************************************************************/
513 int sys_closedir(SMB_STRUCT_DIR *dirp)
515 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CLOSEDIR64)
516 return closedir64(dirp);
517 #else
518 return closedir(dirp);
519 #endif
522 /*******************************************************************
523 An mknod() wrapper that will deal with 64 bit filesizes.
524 ********************************************************************/
526 int sys_mknod(const char *path, mode_t mode, SMB_DEV_T dev)
528 #if defined(HAVE_MKNOD) || defined(HAVE_MKNOD64)
529 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_MKNOD64) && defined(HAVE_DEV64_T)
530 return mknod64(path, mode, dev);
531 #else
532 return mknod(path, mode, dev);
533 #endif
534 #else
535 /* No mknod system call. */
536 errno = ENOSYS;
537 return -1;
538 #endif
541 /*******************************************************************
542 Wrapper for realpath.
543 ********************************************************************/
545 char *sys_realpath(const char *path, char *resolved_path)
547 #if defined(HAVE_REALPATH)
548 return realpath(path, resolved_path);
549 #else
550 /* As realpath is not a system call we can't return ENOSYS. */
551 errno = EINVAL;
552 return NULL;
553 #endif
556 /*******************************************************************
557 The wait() calls vary between systems
558 ********************************************************************/
560 int sys_waitpid(pid_t pid,int *status,int options)
562 #ifdef HAVE_WAITPID
563 return waitpid(pid,status,options);
564 #else /* HAVE_WAITPID */
565 return wait4(pid, status, options, NULL);
566 #endif /* HAVE_WAITPID */
569 /*******************************************************************
570 System wrapper for getwd
571 ********************************************************************/
573 char *sys_getwd(char *s)
575 char *wd;
576 #ifdef HAVE_GETCWD
577 wd = (char *)getcwd(s, sizeof (pstring));
578 #else
579 wd = (char *)getwd(s);
580 #endif
581 return wd;
584 /*******************************************************************
585 system wrapper for symlink
586 ********************************************************************/
588 int sys_symlink(const char *oldpath, const char *newpath)
590 #ifndef HAVE_SYMLINK
591 errno = ENOSYS;
592 return -1;
593 #else
594 return symlink(oldpath, newpath);
595 #endif
598 /*******************************************************************
599 system wrapper for readlink
600 ********************************************************************/
602 int sys_readlink(const char *path, char *buf, size_t bufsiz)
604 #ifndef HAVE_READLINK
605 errno = ENOSYS;
606 return -1;
607 #else
608 return readlink(path, buf, bufsiz);
609 #endif
612 /*******************************************************************
613 system wrapper for link
614 ********************************************************************/
616 int sys_link(const char *oldpath, const char *newpath)
618 #ifndef HAVE_LINK
619 errno = ENOSYS;
620 return -1;
621 #else
622 return link(oldpath, newpath);
623 #endif
626 /*******************************************************************
627 chown isn't used much but OS/2 doesn't have it
628 ********************************************************************/
630 int sys_chown(const char *fname,uid_t uid,gid_t gid)
632 #ifndef HAVE_CHOWN
633 static int done;
634 if (!done) {
635 DEBUG(1,("WARNING: no chown!\n"));
636 done=1;
638 errno = ENOSYS;
639 return -1;
640 #else
641 return(chown(fname,uid,gid));
642 #endif
645 /*******************************************************************
646 os/2 also doesn't have chroot
647 ********************************************************************/
648 int sys_chroot(const char *dname)
650 #ifndef HAVE_CHROOT
651 static int done;
652 if (!done) {
653 DEBUG(1,("WARNING: no chroot!\n"));
654 done=1;
656 errno = ENOSYS;
657 return -1;
658 #else
659 return(chroot(dname));
660 #endif
663 /**************************************************************************
664 A wrapper for gethostbyname() that tries avoids looking up hostnames
665 in the root domain, which can cause dial-on-demand links to come up for no
666 apparent reason.
667 ****************************************************************************/
669 struct hostent *sys_gethostbyname(const char *name)
671 #ifdef REDUCE_ROOT_DNS_LOOKUPS
672 char query[256], hostname[256];
673 char *domain;
675 /* Does this name have any dots in it? If so, make no change */
677 if (strchr_m(name, '.'))
678 return(gethostbyname(name));
680 /* Get my hostname, which should have domain name
681 attached. If not, just do the gethostname on the
682 original string.
685 gethostname(hostname, sizeof(hostname) - 1);
686 hostname[sizeof(hostname) - 1] = 0;
687 if ((domain = strchr_m(hostname, '.')) == NULL)
688 return(gethostbyname(name));
690 /* Attach domain name to query and do modified query.
691 If names too large, just do gethostname on the
692 original string.
695 if((strlen(name) + strlen(domain)) >= sizeof(query))
696 return(gethostbyname(name));
698 slprintf(query, sizeof(query)-1, "%s%s", name, domain);
699 return(gethostbyname(query));
700 #else /* REDUCE_ROOT_DNS_LOOKUPS */
701 return(gethostbyname(name));
702 #endif /* REDUCE_ROOT_DNS_LOOKUPS */
706 #if defined(HAVE_POSIX_CAPABILITIES)
708 #ifdef HAVE_SYS_CAPABILITY_H
710 #if defined(BROKEN_REDHAT_7_SYSTEM_HEADERS) && !defined(_I386_STATFS_H) && !defined(_PPC_STATFS_H)
711 #define _I386_STATFS_H
712 #define _PPC_STATFS_H
713 #define BROKEN_REDHAT_7_STATFS_WORKAROUND
714 #endif
716 #include <sys/capability.h>
718 #ifdef BROKEN_REDHAT_7_STATFS_WORKAROUND
719 #undef _I386_STATFS_H
720 #undef _PPC_STATFS_H
721 #undef BROKEN_REDHAT_7_STATFS_WORKAROUND
722 #endif
724 #endif /* HAVE_SYS_CAPABILITY_H */
726 /**************************************************************************
727 Try and abstract process capabilities (for systems that have them).
728 ****************************************************************************/
730 /* Set the POSIX capabilities needed for the given purpose into the effective
731 * capability set of the current process. Make sure they are always removed
732 * from the inheritable set, because there is no circumstance in which our
733 * children should inherit our elevated privileges.
735 static BOOL set_process_capability(enum smbd_capability capability,
736 BOOL enable)
738 cap_value_t cap_vals[2] = {0};
739 int num_cap_vals = 0;
741 cap_t cap;
743 #if defined(HAVE_PRCTL) && defined(PR_GET_KEEPCAPS) && defined(PR_SET_KEEPCAPS)
744 /* On Linux, make sure that any capabilities we grab are sticky
745 * across UID changes. We expect that this would allow us to keep both
746 * the effective and permitted capability sets, but as of circa 2.6.16,
747 * only the permitted set is kept. It is a bug (which we work around)
748 * that the effective set is lost, but we still require the effective
749 * set to be kept.
751 if (!prctl(PR_GET_KEEPCAPS)) {
752 prctl(PR_SET_KEEPCAPS, 1);
754 #endif
756 cap = cap_get_proc();
757 if (cap == NULL) {
758 DEBUG(0,("set_process_capability: cap_get_proc failed: %s\n",
759 strerror(errno)));
760 return False;
763 switch (capability) {
764 case KERNEL_OPLOCK_CAPABILITY:
765 #ifdef CAP_NETWORK_MGT
766 /* IRIX has CAP_NETWORK_MGT for oplocks. */
767 cap_vals[num_cap_vals++] = CAP_NETWORK_MGT;
768 #endif
769 break;
770 case DMAPI_ACCESS_CAPABILITY:
771 #ifdef CAP_DEVICE_MGT
772 /* IRIX has CAP_DEVICE_MGT for DMAPI access. */
773 cap_vals[num_cap_vals++] = CAP_DEVICE_MGT;
774 #elif CAP_MKNOD
775 /* Linux has CAP_MKNOD for DMAPI access. */
776 cap_vals[num_cap_vals++] = CAP_MKNOD;
777 #endif
778 break;
779 case LEASE_CAPABILITY:
780 #ifdef CAP_LEASE
781 cap_vals[num_cap_vals++] = CAP_LEASE;
782 #endif
783 break;
786 SMB_ASSERT(num_cap_vals <= ARRAY_SIZE(cap_vals));
788 if (num_cap_vals == 0) {
789 cap_free(cap);
790 return True;
793 cap_set_flag(cap, CAP_EFFECTIVE, num_cap_vals, cap_vals,
794 enable ? CAP_SET : CAP_CLEAR);
796 /* We never want to pass capabilities down to our children, so make
797 * sure they are not inherited.
799 cap_set_flag(cap, CAP_INHERITABLE, num_cap_vals, cap_vals, CAP_CLEAR);
801 if (cap_set_proc(cap) == -1) {
802 DEBUG(0, ("set_process_capability: cap_set_proc failed: %s\n",
803 strerror(errno)));
804 cap_free(cap);
805 return False;
808 cap_free(cap);
809 return True;
812 #endif /* HAVE_POSIX_CAPABILITIES */
814 /****************************************************************************
815 Gain the oplock capability from the kernel if possible.
816 ****************************************************************************/
818 void set_effective_capability(enum smbd_capability capability)
820 #if defined(HAVE_POSIX_CAPABILITIES)
821 set_process_capability(capability, True);
822 #endif /* HAVE_POSIX_CAPABILITIES */
825 void drop_effective_capability(enum smbd_capability capability)
827 #if defined(HAVE_POSIX_CAPABILITIES)
828 set_process_capability(capability, False);
829 #endif /* HAVE_POSIX_CAPABILITIES */
832 /**************************************************************************
833 Wrapper for random().
834 ****************************************************************************/
836 long sys_random(void)
838 #if defined(HAVE_RANDOM)
839 return (long)random();
840 #elif defined(HAVE_RAND)
841 return (long)rand();
842 #else
843 DEBUG(0,("Error - no random function available !\n"));
844 exit(1);
845 #endif
848 /**************************************************************************
849 Wrapper for srandom().
850 ****************************************************************************/
852 void sys_srandom(unsigned int seed)
854 #if defined(HAVE_SRANDOM)
855 srandom(seed);
856 #elif defined(HAVE_SRAND)
857 srand(seed);
858 #else
859 DEBUG(0,("Error - no srandom function available !\n"));
860 exit(1);
861 #endif
864 /**************************************************************************
865 Returns equivalent to NGROUPS_MAX - using sysconf if needed.
866 ****************************************************************************/
868 int groups_max(void)
870 #if defined(SYSCONF_SC_NGROUPS_MAX)
871 int ret = sysconf(_SC_NGROUPS_MAX);
872 return (ret == -1) ? NGROUPS_MAX : ret;
873 #else
874 return NGROUPS_MAX;
875 #endif
878 /**************************************************************************
879 Wrapper for getgroups. Deals with broken (int) case.
880 ****************************************************************************/
882 int sys_getgroups(int setlen, gid_t *gidset)
884 #if !defined(HAVE_BROKEN_GETGROUPS)
885 return getgroups(setlen, gidset);
886 #else
888 GID_T gid;
889 GID_T *group_list;
890 int i, ngroups;
892 if(setlen == 0) {
893 return getgroups(setlen, &gid);
897 * Broken case. We need to allocate a
898 * GID_T array of size setlen.
901 if(setlen < 0) {
902 errno = EINVAL;
903 return -1;
906 if (setlen == 0)
907 setlen = groups_max();
909 if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
910 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
911 return -1;
914 if((ngroups = getgroups(setlen, group_list)) < 0) {
915 int saved_errno = errno;
916 SAFE_FREE(group_list);
917 errno = saved_errno;
918 return -1;
921 for(i = 0; i < ngroups; i++)
922 gidset[i] = (gid_t)group_list[i];
924 SAFE_FREE(group_list);
925 return ngroups;
926 #endif /* HAVE_BROKEN_GETGROUPS */
930 /**************************************************************************
931 Wrapper for setgroups. Deals with broken (int) case. Automatically used
932 if we have broken getgroups.
933 ****************************************************************************/
935 int sys_setgroups(int setlen, gid_t *gidset)
937 #if !defined(HAVE_SETGROUPS)
938 errno = ENOSYS;
939 return -1;
940 #endif /* HAVE_SETGROUPS */
942 #if !defined(HAVE_BROKEN_GETGROUPS)
943 return setgroups(setlen, gidset);
944 #else
946 GID_T *group_list;
947 int i ;
949 if (setlen == 0)
950 return 0 ;
952 if (setlen < 0 || setlen > groups_max()) {
953 errno = EINVAL;
954 return -1;
958 * Broken case. We need to allocate a
959 * GID_T array of size setlen.
962 if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
963 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
964 return -1;
967 for(i = 0; i < setlen; i++)
968 group_list[i] = (GID_T) gidset[i];
970 if(setgroups(setlen, group_list) != 0) {
971 int saved_errno = errno;
972 SAFE_FREE(group_list);
973 errno = saved_errno;
974 return -1;
977 SAFE_FREE(group_list);
978 return 0 ;
979 #endif /* HAVE_BROKEN_GETGROUPS */
982 /**************************************************************************
983 Wrappers for setpwent(), getpwent() and endpwent()
984 ****************************************************************************/
986 void sys_setpwent(void)
988 setpwent();
991 struct passwd *sys_getpwent(void)
993 return getpwent();
996 void sys_endpwent(void)
998 endpwent();
1001 /**************************************************************************
1002 Wrappers for getpwnam(), getpwuid(), getgrnam(), getgrgid()
1003 ****************************************************************************/
1005 #ifdef ENABLE_BUILD_FARM_HACKS
1008 * In the build farm we want to be able to join machines to the domain. As we
1009 * don't have root access, we need to bypass direct access to /etc/passwd
1010 * after a user has been created via samr. Fake those users.
1013 static struct passwd *fake_pwd;
1014 static int num_fake_pwd;
1016 struct passwd *sys_getpwnam(const char *name)
1018 int i;
1020 for (i=0; i<num_fake_pwd; i++) {
1021 if (strcmp(fake_pwd[i].pw_name, name) == 0) {
1022 DEBUG(10, ("Returning fake user %s\n", name));
1023 return &fake_pwd[i];
1027 return getpwnam(name);
1030 struct passwd *sys_getpwuid(uid_t uid)
1032 int i;
1034 for (i=0; i<num_fake_pwd; i++) {
1035 if (fake_pwd[i].pw_uid == uid) {
1036 DEBUG(10, ("Returning fake user %s\n",
1037 fake_pwd[i].pw_name));
1038 return &fake_pwd[i];
1042 return getpwuid(uid);
1045 void faked_create_user(const char *name)
1047 int i;
1048 uid_t uid;
1049 struct passwd new_pwd;
1051 for (i=0; i<10; i++) {
1052 generate_random_buffer((unsigned char *)&uid,
1053 sizeof(uid));
1054 if (getpwuid(uid) == NULL) {
1055 break;
1059 if (i==10) {
1060 /* Weird. No free uid found... */
1061 return;
1064 new_pwd.pw_name = SMB_STRDUP(name);
1065 new_pwd.pw_passwd = SMB_STRDUP("x");
1066 new_pwd.pw_uid = uid;
1067 new_pwd.pw_gid = 100;
1068 new_pwd.pw_gecos = SMB_STRDUP("faked user");
1069 new_pwd.pw_dir = SMB_STRDUP("/nodir");
1070 new_pwd.pw_shell = SMB_STRDUP("/bin/false");
1072 ADD_TO_ARRAY(NULL, struct passwd, new_pwd, &fake_pwd,
1073 &num_fake_pwd);
1075 DEBUG(10, ("Added fake user %s, have %d fake users\n",
1076 name, num_fake_pwd));
1079 #else
1081 struct passwd *sys_getpwnam(const char *name)
1083 return getpwnam(name);
1086 struct passwd *sys_getpwuid(uid_t uid)
1088 return getpwuid(uid);
1091 #endif
1093 struct group *sys_getgrnam(const char *name)
1095 return getgrnam(name);
1098 struct group *sys_getgrgid(gid_t gid)
1100 return getgrgid(gid);
1103 #if 0 /* NOT CURRENTLY USED - JRA */
1104 /**************************************************************************
1105 The following are the UNICODE versions of *all* system interface functions
1106 called within Samba. Ok, ok, the exceptions are the gethostbyXX calls,
1107 which currently are left as ascii as they are not used other than in name
1108 resolution.
1109 ****************************************************************************/
1111 /**************************************************************************
1112 Wide stat. Just narrow and call sys_xxx.
1113 ****************************************************************************/
1115 int wsys_stat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
1117 pstring fname;
1118 return sys_stat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
1121 /**************************************************************************
1122 Wide lstat. Just narrow and call sys_xxx.
1123 ****************************************************************************/
1125 int wsys_lstat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
1127 pstring fname;
1128 return sys_lstat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
1131 /**************************************************************************
1132 Wide creat. Just narrow and call sys_xxx.
1133 ****************************************************************************/
1135 int wsys_creat(const smb_ucs2_t *wfname, mode_t mode)
1137 pstring fname;
1138 return sys_creat(unicode_to_unix(fname,wfname,sizeof(fname)), mode);
1141 /**************************************************************************
1142 Wide open. Just narrow and call sys_xxx.
1143 ****************************************************************************/
1145 int wsys_open(const smb_ucs2_t *wfname, int oflag, mode_t mode)
1147 pstring fname;
1148 return sys_open(unicode_to_unix(fname,wfname,sizeof(fname)), oflag, mode);
1151 /**************************************************************************
1152 Wide fopen. Just narrow and call sys_xxx.
1153 ****************************************************************************/
1155 FILE *wsys_fopen(const smb_ucs2_t *wfname, const char *type)
1157 pstring fname;
1158 return sys_fopen(unicode_to_unix(fname,wfname,sizeof(fname)), type);
1161 /**************************************************************************
1162 Wide opendir. Just narrow and call sys_xxx.
1163 ****************************************************************************/
1165 SMB_STRUCT_DIR *wsys_opendir(const smb_ucs2_t *wfname)
1167 pstring fname;
1168 return opendir(unicode_to_unix(fname,wfname,sizeof(fname)));
1171 /**************************************************************************
1172 Wide readdir. Return a structure pointer containing a wide filename.
1173 ****************************************************************************/
1175 SMB_STRUCT_WDIRENT *wsys_readdir(SMB_STRUCT_DIR *dirp)
1177 static SMB_STRUCT_WDIRENT retval;
1178 SMB_STRUCT_DIRENT *dirval = sys_readdir(dirp);
1180 if(!dirval)
1181 return NULL;
1184 * The only POSIX defined member of this struct is d_name.
1187 unix_to_unicode(retval.d_name,dirval->d_name,sizeof(retval.d_name));
1189 return &retval;
1192 /**************************************************************************
1193 Wide getwd. Call sys_xxx and widen. Assumes s points to a wpstring.
1194 ****************************************************************************/
1196 smb_ucs2_t *wsys_getwd(smb_ucs2_t *s)
1198 pstring fname;
1199 char *p = sys_getwd(fname);
1201 if(!p)
1202 return NULL;
1204 return unix_to_unicode(s, p, sizeof(wpstring));
1207 /**************************************************************************
1208 Wide chown. Just narrow and call sys_xxx.
1209 ****************************************************************************/
1211 int wsys_chown(const smb_ucs2_t *wfname, uid_t uid, gid_t gid)
1213 pstring fname;
1214 return chown(unicode_to_unix(fname,wfname,sizeof(fname)), uid, gid);
1217 /**************************************************************************
1218 Wide chroot. Just narrow and call sys_xxx.
1219 ****************************************************************************/
1221 int wsys_chroot(const smb_ucs2_t *wfname)
1223 pstring fname;
1224 return chroot(unicode_to_unix(fname,wfname,sizeof(fname)));
1227 /**************************************************************************
1228 Wide getpwnam. Return a structure pointer containing wide names.
1229 ****************************************************************************/
1231 SMB_STRUCT_WPASSWD *wsys_getpwnam(const smb_ucs2_t *wname)
1233 static SMB_STRUCT_WPASSWD retval;
1234 fstring name;
1235 struct passwd *pwret = sys_getpwnam(unicode_to_unix(name,wname,sizeof(name)));
1237 if(!pwret)
1238 return NULL;
1240 unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
1241 retval.pw_passwd = pwret->pw_passwd;
1242 retval.pw_uid = pwret->pw_uid;
1243 retval.pw_gid = pwret->pw_gid;
1244 unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
1245 unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
1246 unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
1248 return &retval;
1251 /**************************************************************************
1252 Wide getpwuid. Return a structure pointer containing wide names.
1253 ****************************************************************************/
1255 SMB_STRUCT_WPASSWD *wsys_getpwuid(uid_t uid)
1257 static SMB_STRUCT_WPASSWD retval;
1258 struct passwd *pwret = sys_getpwuid(uid);
1260 if(!pwret)
1261 return NULL;
1263 unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
1264 retval.pw_passwd = pwret->pw_passwd;
1265 retval.pw_uid = pwret->pw_uid;
1266 retval.pw_gid = pwret->pw_gid;
1267 unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
1268 unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
1269 unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
1271 return &retval;
1273 #endif /* NOT CURRENTLY USED - JRA */
1275 /**************************************************************************
1276 Extract a command into an arg list. Uses a static pstring for storage.
1277 Caller frees returned arg list (which contains pointers into the static pstring).
1278 ****************************************************************************/
1280 static char **extract_args(const char *command)
1282 static pstring trunc_cmd;
1283 char *ptr;
1284 int argcl;
1285 char **argl = NULL;
1286 int i;
1288 pstrcpy(trunc_cmd, command);
1290 if(!(ptr = strtok(trunc_cmd, " \t"))) {
1291 errno = EINVAL;
1292 return NULL;
1296 * Count the args.
1299 for( argcl = 1; ptr; ptr = strtok(NULL, " \t"))
1300 argcl++;
1302 if((argl = (char **)SMB_MALLOC((argcl + 1) * sizeof(char *))) == NULL)
1303 return NULL;
1306 * Now do the extraction.
1309 pstrcpy(trunc_cmd, command);
1311 ptr = strtok(trunc_cmd, " \t");
1312 i = 0;
1313 argl[i++] = ptr;
1315 while((ptr = strtok(NULL, " \t")) != NULL)
1316 argl[i++] = ptr;
1318 argl[i++] = NULL;
1319 return argl;
1322 /**************************************************************************
1323 Wrapper for fork. Ensures that mypid is reset. Used so we can write
1324 a sys_getpid() that only does a system call *once*.
1325 ****************************************************************************/
1327 static pid_t mypid = (pid_t)-1;
1329 pid_t sys_fork(void)
1331 pid_t forkret = fork();
1333 if (forkret == (pid_t)0) /* Child - reset mypid so sys_getpid does a system call. */
1334 mypid = (pid_t) -1;
1336 return forkret;
1339 /**************************************************************************
1340 Wrapper for getpid. Ensures we only do a system call *once*.
1341 ****************************************************************************/
1343 pid_t sys_getpid(void)
1345 if (mypid == (pid_t)-1)
1346 mypid = getpid();
1348 return mypid;
1351 /**************************************************************************
1352 Wrapper for popen. Safer as it doesn't search a path.
1353 Modified from the glibc sources.
1354 modified by tridge to return a file descriptor. We must kick our FILE* habit
1355 ****************************************************************************/
1357 typedef struct _popen_list
1359 int fd;
1360 pid_t child_pid;
1361 struct _popen_list *next;
1362 } popen_list;
1364 static popen_list *popen_chain;
1366 int sys_popen(const char *command)
1368 int parent_end, child_end;
1369 int pipe_fds[2];
1370 popen_list *entry = NULL;
1371 char **argl = NULL;
1373 if (pipe(pipe_fds) < 0)
1374 return -1;
1376 parent_end = pipe_fds[0];
1377 child_end = pipe_fds[1];
1379 if (!*command) {
1380 errno = EINVAL;
1381 goto err_exit;
1384 if((entry = SMB_MALLOC_P(popen_list)) == NULL)
1385 goto err_exit;
1387 ZERO_STRUCTP(entry);
1390 * Extract the command and args into a NULL terminated array.
1393 if(!(argl = extract_args(command)))
1394 goto err_exit;
1396 entry->child_pid = sys_fork();
1398 if (entry->child_pid == -1) {
1399 goto err_exit;
1402 if (entry->child_pid == 0) {
1405 * Child !
1408 int child_std_end = STDOUT_FILENO;
1409 popen_list *p;
1411 close(parent_end);
1412 if (child_end != child_std_end) {
1413 dup2 (child_end, child_std_end);
1414 close (child_end);
1418 * POSIX.2: "popen() shall ensure that any streams from previous
1419 * popen() calls that remain open in the parent process are closed
1420 * in the new child process."
1423 for (p = popen_chain; p; p = p->next)
1424 close(p->fd);
1426 execv(argl[0], argl);
1427 _exit (127);
1431 * Parent.
1434 close (child_end);
1435 SAFE_FREE(argl);
1437 /* Link into popen_chain. */
1438 entry->next = popen_chain;
1439 popen_chain = entry;
1440 entry->fd = parent_end;
1442 return entry->fd;
1444 err_exit:
1446 SAFE_FREE(entry);
1447 SAFE_FREE(argl);
1448 close(pipe_fds[0]);
1449 close(pipe_fds[1]);
1450 return -1;
1453 /**************************************************************************
1454 Wrapper for pclose. Modified from the glibc sources.
1455 ****************************************************************************/
1457 int sys_pclose(int fd)
1459 int wstatus;
1460 popen_list **ptr = &popen_chain;
1461 popen_list *entry = NULL;
1462 pid_t wait_pid;
1463 int status = -1;
1465 /* Unlink from popen_chain. */
1466 for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
1467 if ((*ptr)->fd == fd) {
1468 entry = *ptr;
1469 *ptr = (*ptr)->next;
1470 status = 0;
1471 break;
1475 if (status < 0 || close(entry->fd) < 0)
1476 return -1;
1479 * As Samba is catching and eating child process
1480 * exits we don't really care about the child exit
1481 * code, a -1 with errno = ECHILD will do fine for us.
1484 do {
1485 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
1486 } while (wait_pid == -1 && errno == EINTR);
1488 SAFE_FREE(entry);
1490 if (wait_pid == -1)
1491 return -1;
1492 return wstatus;
1495 /**************************************************************************
1496 Wrappers for dlopen, dlsym, dlclose.
1497 ****************************************************************************/
1499 void *sys_dlopen(const char *name, int flags)
1501 #if defined(HAVE_DLOPEN)
1502 #if 1 /* AVM */
1503 return NULL;
1504 #else
1505 return dlopen(name, flags);
1506 #endif
1507 #else
1508 return NULL;
1509 #endif
1512 void *sys_dlsym(void *handle, const char *symbol)
1514 #if defined(HAVE_DLSYM)
1515 return dlsym(handle, symbol);
1516 #else
1517 return NULL;
1518 #endif
1521 int sys_dlclose (void *handle)
1523 #if defined(HAVE_DLCLOSE)
1524 return dlclose(handle);
1525 #else
1526 return 0;
1527 #endif
1530 const char *sys_dlerror(void)
1532 #if defined(HAVE_DLERROR)
1533 return dlerror();
1534 #else
1535 return NULL;
1536 #endif
1539 int sys_dup2(int oldfd, int newfd)
1541 #if defined(HAVE_DUP2)
1542 return dup2(oldfd, newfd);
1543 #else
1544 errno = ENOSYS;
1545 return -1;
1546 #endif
1549 /**************************************************************************
1550 Wrapper for Admin Logs.
1551 ****************************************************************************/
1553 void sys_adminlog(int priority, const char *format_str, ...)
1555 va_list ap;
1556 int ret;
1557 char *msgbuf = NULL;
1559 va_start( ap, format_str );
1560 ret = vasprintf( &msgbuf, format_str, ap );
1561 va_end( ap );
1563 if (ret == -1)
1564 return;
1566 #if defined(HAVE_SYSLOG)
1567 syslog( priority, "%s", msgbuf );
1568 #else
1569 DEBUG(0,("%s", msgbuf ));
1570 #endif
1571 SAFE_FREE(msgbuf);
1574 /******** Solaris EA helper function prototypes ********/
1575 #ifdef HAVE_ATTROPEN
1576 #define SOLARIS_ATTRMODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP
1577 static int solaris_write_xattr(int attrfd, const char *value, size_t size);
1578 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size);
1579 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size);
1580 static int solaris_unlinkat(int attrdirfd, const char *name);
1581 static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode);
1582 static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode);
1583 #endif
1585 /**************************************************************************
1586 Wrappers for extented attribute calls. Based on the Linux package with
1587 support for IRIX and (Net|Free)BSD also. Expand as other systems have them.
1588 ****************************************************************************/
1590 ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t size)
1592 #if defined(HAVE_GETXATTR)
1593 #ifndef XATTR_ADD_OPT
1594 return getxattr(path, name, value, size);
1595 #else
1596 int options = 0;
1597 return getxattr(path, name, value, size, 0, options);
1598 #endif
1599 #elif defined(HAVE_GETEA)
1600 return getea(path, name, value, size);
1601 #elif defined(HAVE_EXTATTR_GET_FILE)
1602 char *s;
1603 ssize_t retval;
1604 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1605 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1606 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1608 * The BSD implementation has a nasty habit of silently truncating
1609 * the returned value to the size of the buffer, so we have to check
1610 * that the buffer is large enough to fit the returned value.
1612 if((retval=extattr_get_file(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1613 if(retval > size) {
1614 errno = ERANGE;
1615 return -1;
1617 if((retval=extattr_get_file(path, attrnamespace, attrname, value, size)) >= 0)
1618 return retval;
1621 DEBUG(10,("sys_getxattr: extattr_get_file() failed with: %s\n", strerror(errno)));
1622 return -1;
1623 #elif defined(HAVE_ATTR_GET)
1624 int retval, flags = 0;
1625 int valuelength = (int)size;
1626 char *attrname = strchr(name,'.') + 1;
1628 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1630 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1632 return retval ? retval : valuelength;
1633 #elif defined(HAVE_ATTROPEN)
1634 ssize_t ret = -1;
1635 int attrfd = solaris_attropen(path, name, O_RDONLY, 0);
1636 if (attrfd >= 0) {
1637 ret = solaris_read_xattr(attrfd, value, size);
1638 close(attrfd);
1640 return ret;
1641 #else
1642 errno = ENOSYS;
1643 return -1;
1644 #endif
1647 ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t size)
1649 #if defined(HAVE_LGETXATTR)
1650 return lgetxattr(path, name, value, size);
1651 #elif defined(HAVE_GETXATTR) && defined(XATTR_ADD_OPT)
1652 int options = XATTR_NOFOLLOW;
1653 return getxattr(path, name, value, size, 0, options);
1654 #elif defined(HAVE_LGETEA)
1655 return lgetea(path, name, value, size);
1656 #elif defined(HAVE_EXTATTR_GET_LINK)
1657 char *s;
1658 ssize_t retval;
1659 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1660 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1661 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1663 if((retval=extattr_get_link(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1664 if(retval > size) {
1665 errno = ERANGE;
1666 return -1;
1668 if((retval=extattr_get_link(path, attrnamespace, attrname, value, size)) >= 0)
1669 return retval;
1672 DEBUG(10,("sys_lgetxattr: extattr_get_link() failed with: %s\n", strerror(errno)));
1673 return -1;
1674 #elif defined(HAVE_ATTR_GET)
1675 int retval, flags = ATTR_DONTFOLLOW;
1676 int valuelength = (int)size;
1677 char *attrname = strchr(name,'.') + 1;
1679 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1681 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1683 return retval ? retval : valuelength;
1684 #elif defined(HAVE_ATTROPEN)
1685 ssize_t ret = -1;
1686 int attrfd = solaris_attropen(path, name, O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1687 if (attrfd >= 0) {
1688 ret = solaris_read_xattr(attrfd, value, size);
1689 close(attrfd);
1691 return ret;
1692 #else
1693 errno = ENOSYS;
1694 return -1;
1695 #endif
1698 ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size)
1700 #if defined(HAVE_FGETXATTR)
1701 #ifndef XATTR_ADD_OPT
1702 return fgetxattr(filedes, name, value, size);
1703 #else
1704 int options = 0;
1705 return fgetxattr(filedes, name, value, size, 0, options);
1706 #endif
1707 #elif defined(HAVE_FGETEA)
1708 return fgetea(filedes, name, value, size);
1709 #elif defined(HAVE_EXTATTR_GET_FD)
1710 char *s;
1711 ssize_t retval;
1712 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1713 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1714 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1716 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0)) >= 0) {
1717 if(retval > size) {
1718 errno = ERANGE;
1719 return -1;
1721 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, value, size)) >= 0)
1722 return retval;
1725 DEBUG(10,("sys_fgetxattr: extattr_get_fd() failed with: %s\n", strerror(errno)));
1726 return -1;
1727 #elif defined(HAVE_ATTR_GETF)
1728 int retval, flags = 0;
1729 int valuelength = (int)size;
1730 char *attrname = strchr(name,'.') + 1;
1732 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1734 retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags);
1736 return retval ? retval : valuelength;
1737 #elif defined(HAVE_ATTROPEN)
1738 ssize_t ret = -1;
1739 int attrfd = solaris_openat(filedes, name, O_RDONLY|O_XATTR, 0);
1740 if (attrfd >= 0) {
1741 ret = solaris_read_xattr(attrfd, value, size);
1742 close(attrfd);
1744 return ret;
1745 #else
1746 errno = ENOSYS;
1747 return -1;
1748 #endif
1751 #if defined(HAVE_EXTATTR_LIST_FILE)
1753 #define EXTATTR_PREFIX(s) (s), (sizeof((s))-1)
1755 static struct {
1756 int space;
1757 const char *name;
1758 size_t len;
1760 extattr[] = {
1761 { EXTATTR_NAMESPACE_SYSTEM, EXTATTR_PREFIX("system.") },
1762 { EXTATTR_NAMESPACE_USER, EXTATTR_PREFIX("user.") },
1765 typedef union {
1766 const char *path;
1767 int filedes;
1768 } extattr_arg;
1770 static ssize_t bsd_attr_list (int type, extattr_arg arg, char *list, size_t size)
1772 ssize_t list_size, total_size = 0;
1773 int i, t, len;
1774 char *buf;
1775 /* Iterate through extattr(2) namespaces */
1776 for(t = 0; t < (sizeof(extattr)/sizeof(extattr[0])); t++) {
1777 switch(type) {
1778 #if defined(HAVE_EXTATTR_LIST_FILE)
1779 case 0:
1780 list_size = extattr_list_file(arg.path, extattr[t].space, list, size);
1781 break;
1782 #endif
1783 #if defined(HAVE_EXTATTR_LIST_LINK)
1784 case 1:
1785 list_size = extattr_list_link(arg.path, extattr[t].space, list, size);
1786 break;
1787 #endif
1788 #if defined(HAVE_EXTATTR_LIST_FD)
1789 case 2:
1790 list_size = extattr_list_fd(arg.filedes, extattr[t].space, list, size);
1791 break;
1792 #endif
1793 default:
1794 errno = ENOSYS;
1795 return -1;
1797 /* Some error happend. Errno should be set by the previous call */
1798 if(list_size < 0)
1799 return -1;
1800 /* No attributes */
1801 if(list_size == 0)
1802 continue;
1803 /* XXX: Call with an empty buffer may be used to calculate
1804 necessary buffer size. Unfortunately, we can't say, how
1805 many attributes were returned, so here is the potential
1806 problem with the emulation.
1808 if(list == NULL) {
1809 /* Take the worse case of one char attribute names -
1810 two bytes per name plus one more for sanity.
1812 total_size += list_size + (list_size/2 + 1)*extattr[t].len;
1813 continue;
1815 /* Count necessary offset to fit namespace prefixes */
1816 len = 0;
1817 for(i = 0; i < list_size; i += list[i] + 1)
1818 len += extattr[t].len;
1820 total_size += list_size + len;
1821 /* Buffer is too small to fit the results */
1822 if(total_size > size) {
1823 errno = ERANGE;
1824 return -1;
1826 /* Shift results back, so we can prepend prefixes */
1827 buf = memmove(list + len, list, list_size);
1829 for(i = 0; i < list_size; i += len + 1) {
1830 len = buf[i];
1831 strncpy(list, extattr[t].name, extattr[t].len + 1);
1832 list += extattr[t].len;
1833 strncpy(list, buf + i + 1, len);
1834 list[len] = '\0';
1835 list += len + 1;
1837 size -= total_size;
1839 return total_size;
1842 #endif
1844 #if defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1845 static char attr_buffer[ATTR_MAX_VALUELEN];
1847 static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags)
1849 int retval = 0, index;
1850 attrlist_cursor_t *cursor = 0;
1851 int total_size = 0;
1852 attrlist_t * al = (attrlist_t *)attr_buffer;
1853 attrlist_ent_t *ae;
1854 size_t ent_size, left = size;
1855 char *bp = list;
1857 while (True) {
1858 if (filedes)
1859 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1860 else
1861 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1862 if (retval) break;
1863 for (index = 0; index < al->al_count; index++) {
1864 ae = ATTR_ENTRY(attr_buffer, index);
1865 ent_size = strlen(ae->a_name) + sizeof("user.");
1866 if (left >= ent_size) {
1867 strncpy(bp, "user.", sizeof("user."));
1868 strncat(bp, ae->a_name, ent_size - sizeof("user."));
1869 bp += ent_size;
1870 left -= ent_size;
1871 } else if (size) {
1872 errno = ERANGE;
1873 retval = -1;
1874 break;
1876 total_size += ent_size;
1878 if (al->al_more == 0) break;
1880 if (retval == 0) {
1881 flags |= ATTR_ROOT;
1882 cursor = 0;
1883 while (True) {
1884 if (filedes)
1885 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1886 else
1887 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1888 if (retval) break;
1889 for (index = 0; index < al->al_count; index++) {
1890 ae = ATTR_ENTRY(attr_buffer, index);
1891 ent_size = strlen(ae->a_name) + sizeof("system.");
1892 if (left >= ent_size) {
1893 strncpy(bp, "system.", sizeof("system."));
1894 strncat(bp, ae->a_name, ent_size - sizeof("system."));
1895 bp += ent_size;
1896 left -= ent_size;
1897 } else if (size) {
1898 errno = ERANGE;
1899 retval = -1;
1900 break;
1902 total_size += ent_size;
1904 if (al->al_more == 0) break;
1907 return (ssize_t)(retval ? retval : total_size);
1910 #endif
1912 ssize_t sys_listxattr (const char *path, char *list, size_t size)
1914 #if defined(HAVE_LISTXATTR)
1915 #ifndef XATTR_ADD_OPT
1916 return listxattr(path, list, size);
1917 #else
1918 int options = 0;
1919 return listxattr(path, list, size, options);
1920 #endif
1921 #elif defined(HAVE_LISTEA)
1922 return listea(path, list, size);
1923 #elif defined(HAVE_EXTATTR_LIST_FILE)
1924 extattr_arg arg;
1925 arg.path = path;
1926 return bsd_attr_list(0, arg, list, size);
1927 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1928 return irix_attr_list(path, 0, list, size, 0);
1929 #elif defined(HAVE_ATTROPEN)
1930 ssize_t ret = -1;
1931 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
1932 if (attrdirfd >= 0) {
1933 ret = solaris_list_xattr(attrdirfd, list, size);
1934 close(attrdirfd);
1936 return ret;
1937 #else
1938 errno = ENOSYS;
1939 return -1;
1940 #endif
1943 ssize_t sys_llistxattr (const char *path, char *list, size_t size)
1945 #if defined(HAVE_LLISTXATTR)
1946 return llistxattr(path, list, size);
1947 #elif defined(HAVE_LISTXATTR) && defined(XATTR_ADD_OPT)
1948 int options = XATTR_NOFOLLOW;
1949 return listxattr(path, list, size, options);
1950 #elif defined(HAVE_LLISTEA)
1951 return llistea(path, list, size);
1952 #elif defined(HAVE_EXTATTR_LIST_LINK)
1953 extattr_arg arg;
1954 arg.path = path;
1955 return bsd_attr_list(1, arg, list, size);
1956 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1957 return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW);
1958 #elif defined(HAVE_ATTROPEN)
1959 ssize_t ret = -1;
1960 int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1961 if (attrdirfd >= 0) {
1962 ret = solaris_list_xattr(attrdirfd, list, size);
1963 close(attrdirfd);
1965 return ret;
1966 #else
1967 errno = ENOSYS;
1968 return -1;
1969 #endif
1972 ssize_t sys_flistxattr (int filedes, char *list, size_t size)
1974 #if defined(HAVE_FLISTXATTR)
1975 #ifndef XATTR_ADD_OPT
1976 return flistxattr(filedes, list, size);
1977 #else
1978 int options = 0;
1979 return flistxattr(filedes, list, size, options);
1980 #endif
1981 #elif defined(HAVE_FLISTEA)
1982 return flistea(filedes, list, size);
1983 #elif defined(HAVE_EXTATTR_LIST_FD)
1984 extattr_arg arg;
1985 arg.filedes = filedes;
1986 return bsd_attr_list(2, arg, list, size);
1987 #elif defined(HAVE_ATTR_LISTF)
1988 return irix_attr_list(NULL, filedes, list, size, 0);
1989 #elif defined(HAVE_ATTROPEN)
1990 ssize_t ret = -1;
1991 int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
1992 if (attrdirfd >= 0) {
1993 ret = solaris_list_xattr(attrdirfd, list, size);
1994 close(attrdirfd);
1996 return ret;
1997 #else
1998 errno = ENOSYS;
1999 return -1;
2000 #endif
2003 int sys_removexattr (const char *path, const char *name)
2005 #if defined(HAVE_REMOVEXATTR)
2006 #ifndef XATTR_ADD_OPT
2007 return removexattr(path, name);
2008 #else
2009 int options = 0;
2010 return removexattr(path, name, options);
2011 #endif
2012 #elif defined(HAVE_REMOVEEA)
2013 return removeea(path, name);
2014 #elif defined(HAVE_EXTATTR_DELETE_FILE)
2015 char *s;
2016 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2017 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2018 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2020 return extattr_delete_file(path, attrnamespace, attrname);
2021 #elif defined(HAVE_ATTR_REMOVE)
2022 int flags = 0;
2023 char *attrname = strchr(name,'.') + 1;
2025 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
2027 return attr_remove(path, attrname, flags);
2028 #elif defined(HAVE_ATTROPEN)
2029 int ret = -1;
2030 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
2031 if (attrdirfd >= 0) {
2032 ret = solaris_unlinkat(attrdirfd, name);
2033 close(attrdirfd);
2035 return ret;
2036 #else
2037 errno = ENOSYS;
2038 return -1;
2039 #endif
2042 int sys_lremovexattr (const char *path, const char *name)
2044 #if defined(HAVE_LREMOVEXATTR)
2045 return lremovexattr(path, name);
2046 #elif defined(HAVE_REMOVEXATTR) && defined(XATTR_ADD_OPT)
2047 int options = XATTR_NOFOLLOW;
2048 return removexattr(path, name, options);
2049 #elif defined(HAVE_LREMOVEEA)
2050 return lremoveea(path, name);
2051 #elif defined(HAVE_EXTATTR_DELETE_LINK)
2052 char *s;
2053 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2054 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2055 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2057 return extattr_delete_link(path, attrnamespace, attrname);
2058 #elif defined(HAVE_ATTR_REMOVE)
2059 int flags = ATTR_DONTFOLLOW;
2060 char *attrname = strchr(name,'.') + 1;
2062 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
2064 return attr_remove(path, attrname, flags);
2065 #elif defined(HAVE_ATTROPEN)
2066 int ret = -1;
2067 int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
2068 if (attrdirfd >= 0) {
2069 ret = solaris_unlinkat(attrdirfd, name);
2070 close(attrdirfd);
2072 return ret;
2073 #else
2074 errno = ENOSYS;
2075 return -1;
2076 #endif
2079 int sys_fremovexattr (int filedes, const char *name)
2081 #if defined(HAVE_FREMOVEXATTR)
2082 #ifndef XATTR_ADD_OPT
2083 return fremovexattr(filedes, name);
2084 #else
2085 int options = 0;
2086 return fremovexattr(filedes, name, options);
2087 #endif
2088 #elif defined(HAVE_FREMOVEEA)
2089 return fremoveea(filedes, name);
2090 #elif defined(HAVE_EXTATTR_DELETE_FD)
2091 char *s;
2092 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2093 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2094 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2096 return extattr_delete_fd(filedes, attrnamespace, attrname);
2097 #elif defined(HAVE_ATTR_REMOVEF)
2098 int flags = 0;
2099 char *attrname = strchr(name,'.') + 1;
2101 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
2103 return attr_removef(filedes, attrname, flags);
2104 #elif defined(HAVE_ATTROPEN)
2105 int ret = -1;
2106 int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
2107 if (attrdirfd >= 0) {
2108 ret = solaris_unlinkat(attrdirfd, name);
2109 close(attrdirfd);
2111 return ret;
2112 #else
2113 errno = ENOSYS;
2114 return -1;
2115 #endif
2118 #if !defined(HAVE_SETXATTR)
2119 #define XATTR_CREATE 0x1 /* set value, fail if attr already exists */
2120 #define XATTR_REPLACE 0x2 /* set value, fail if attr does not exist */
2121 #endif
2123 int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags)
2125 #if defined(HAVE_SETXATTR)
2126 #ifndef XATTR_ADD_OPT
2127 return setxattr(path, name, value, size, flags);
2128 #else
2129 int options = 0;
2130 return setxattr(path, name, value, size, 0, options);
2131 #endif
2132 #elif defined(HAVE_SETEA)
2133 return setea(path, name, value, size, flags);
2134 #elif defined(HAVE_EXTATTR_SET_FILE)
2135 char *s;
2136 int retval = 0;
2137 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2138 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2139 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2140 if (flags) {
2141 /* Check attribute existence */
2142 retval = extattr_get_file(path, attrnamespace, attrname, NULL, 0);
2143 if (retval < 0) {
2144 /* REPLACE attribute, that doesn't exist */
2145 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2146 errno = ENOATTR;
2147 return -1;
2149 /* Ignore other errors */
2151 else {
2152 /* CREATE attribute, that already exists */
2153 if (flags & XATTR_CREATE) {
2154 errno = EEXIST;
2155 return -1;
2159 retval = extattr_set_file(path, attrnamespace, attrname, value, size);
2160 return (retval < 0) ? -1 : 0;
2161 #elif defined(HAVE_ATTR_SET)
2162 int myflags = 0;
2163 char *attrname = strchr(name,'.') + 1;
2165 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2166 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2167 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2169 return attr_set(path, attrname, (const char *)value, size, myflags);
2170 #elif defined(HAVE_ATTROPEN)
2171 int ret = -1;
2172 int myflags = O_RDWR;
2173 int attrfd;
2174 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2175 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2176 attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2177 if (attrfd >= 0) {
2178 ret = solaris_write_xattr(attrfd, value, size);
2179 close(attrfd);
2181 return ret;
2182 #else
2183 errno = ENOSYS;
2184 return -1;
2185 #endif
2188 int sys_lsetxattr (const char *path, const char *name, const void *value, size_t size, int flags)
2190 #if defined(HAVE_LSETXATTR)
2191 return lsetxattr(path, name, value, size, flags);
2192 #elif defined(HAVE_SETXATTR) && defined(XATTR_ADD_OPT)
2193 int options = XATTR_NOFOLLOW;
2194 return setxattr(path, name, value, size, 0, options);
2195 #elif defined(LSETEA)
2196 return lsetea(path, name, value, size, flags);
2197 #elif defined(HAVE_EXTATTR_SET_LINK)
2198 char *s;
2199 int retval = 0;
2200 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2201 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2202 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2203 if (flags) {
2204 /* Check attribute existence */
2205 retval = extattr_get_link(path, attrnamespace, attrname, NULL, 0);
2206 if (retval < 0) {
2207 /* REPLACE attribute, that doesn't exist */
2208 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2209 errno = ENOATTR;
2210 return -1;
2212 /* Ignore other errors */
2214 else {
2215 /* CREATE attribute, that already exists */
2216 if (flags & XATTR_CREATE) {
2217 errno = EEXIST;
2218 return -1;
2223 retval = extattr_set_link(path, attrnamespace, attrname, value, size);
2224 return (retval < 0) ? -1 : 0;
2225 #elif defined(HAVE_ATTR_SET)
2226 int myflags = ATTR_DONTFOLLOW;
2227 char *attrname = strchr(name,'.') + 1;
2229 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2230 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2231 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2233 return attr_set(path, attrname, (const char *)value, size, myflags);
2234 #elif defined(HAVE_ATTROPEN)
2235 int ret = -1;
2236 int myflags = O_RDWR | AT_SYMLINK_NOFOLLOW;
2237 int attrfd;
2238 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2239 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2240 attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2241 if (attrfd >= 0) {
2242 ret = solaris_write_xattr(attrfd, value, size);
2243 close(attrfd);
2245 return ret;
2246 #else
2247 errno = ENOSYS;
2248 return -1;
2249 #endif
2252 int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags)
2254 #if defined(HAVE_FSETXATTR)
2255 #ifndef XATTR_ADD_OPT
2256 return fsetxattr(filedes, name, value, size, flags);
2257 #else
2258 int options = 0;
2259 return fsetxattr(filedes, name, value, size, 0, options);
2260 #endif
2261 #elif defined(HAVE_FSETEA)
2262 return fsetea(filedes, name, value, size, flags);
2263 #elif defined(HAVE_EXTATTR_SET_FD)
2264 char *s;
2265 int retval = 0;
2266 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2267 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2268 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2269 if (flags) {
2270 /* Check attribute existence */
2271 retval = extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0);
2272 if (retval < 0) {
2273 /* REPLACE attribute, that doesn't exist */
2274 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2275 errno = ENOATTR;
2276 return -1;
2278 /* Ignore other errors */
2280 else {
2281 /* CREATE attribute, that already exists */
2282 if (flags & XATTR_CREATE) {
2283 errno = EEXIST;
2284 return -1;
2288 retval = extattr_set_fd(filedes, attrnamespace, attrname, value, size);
2289 return (retval < 0) ? -1 : 0;
2290 #elif defined(HAVE_ATTR_SETF)
2291 int myflags = 0;
2292 char *attrname = strchr(name,'.') + 1;
2294 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2295 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2296 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2298 return attr_setf(filedes, attrname, (const char *)value, size, myflags);
2299 #elif defined(HAVE_ATTROPEN)
2300 int ret = -1;
2301 int myflags = O_RDWR | O_XATTR;
2302 int attrfd;
2303 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2304 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2305 attrfd = solaris_openat(filedes, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2306 if (attrfd >= 0) {
2307 ret = solaris_write_xattr(attrfd, value, size);
2308 close(attrfd);
2310 return ret;
2311 #else
2312 errno = ENOSYS;
2313 return -1;
2314 #endif
2317 /**************************************************************************
2318 helper functions for Solaris' EA support
2319 ****************************************************************************/
2320 #ifdef HAVE_ATTROPEN
2321 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size)
2323 struct stat sbuf;
2325 if (fstat(attrfd, &sbuf) == -1) {
2326 errno = ENOATTR;
2327 return -1;
2330 /* This is to return the current size of the named extended attribute */
2331 if (size == 0) {
2332 return sbuf.st_size;
2335 /* check size and read xattr */
2336 if (sbuf.st_size > size) {
2337 errno = ERANGE;
2338 return -1;
2341 return read(attrfd, value, sbuf.st_size);
2344 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size)
2346 ssize_t len = 0;
2347 int stop = 0;
2348 DIR *dirp;
2349 struct dirent *de;
2350 int newfd = dup(attrdirfd);
2351 /* CAUTION: The originating file descriptor should not be
2352 used again following the call to fdopendir().
2353 For that reason we dup() the file descriptor
2354 here to make things more clear. */
2355 dirp = fdopendir(newfd);
2357 while ((de = readdir(dirp))) {
2358 size_t listlen = strlen(de->d_name);
2359 if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) {
2360 /* we don't want "." and ".." here: */
2361 DEBUG(10,("skipped EA %s\n",de->d_name));
2362 continue;
2365 if (size == 0) {
2366 /* return the current size of the list of extended attribute names*/
2367 len += listlen + 1;
2368 } else {
2369 /* check size and copy entrieѕ + nul into list. */
2370 if ((len + listlen + 1) > size) {
2371 errno = ERANGE;
2372 len = -1;
2373 break;
2374 } else {
2375 safe_strcpy(list + len, de->d_name, listlen);
2376 pstrcpy(list + len, de->d_name);
2377 len += listlen;
2378 list[len] = '\0';
2379 ++len;
2384 if (closedir(dirp) == -1) {
2385 DEBUG(0,("closedir dirp failed: %s\n",strerror(errno)));
2386 return -1;
2388 return len;
2391 static int solaris_unlinkat(int attrdirfd, const char *name)
2393 if (unlinkat(attrdirfd, name, 0) == -1) {
2394 if (errno == ENOENT) {
2395 errno = ENOATTR;
2397 return -1;
2399 return 0;
2402 static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode)
2404 int filedes = attropen(path, attrpath, oflag, mode);
2405 if (filedes == -1) {
2406 DEBUG(10,("attropen FAILED: path: %s, name: %s, errno: %s\n",path,attrpath,strerror(errno)));
2407 if (errno == EINVAL) {
2408 errno = ENOTSUP;
2409 } else {
2410 errno = ENOATTR;
2413 return filedes;
2416 static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode)
2418 int filedes = openat(fildes, path, oflag, mode);
2419 if (filedes == -1) {
2420 DEBUG(10,("openat FAILED: fd: %s, path: %s, errno: %s\n",filedes,path,strerror(errno)));
2421 if (errno == EINVAL) {
2422 errno = ENOTSUP;
2423 } else {
2424 errno = ENOATTR;
2427 return filedes;
2430 static int solaris_write_xattr(int attrfd, const char *value, size_t size)
2432 if ((ftruncate(attrfd, 0) == 0) && (write(attrfd, value, size) == size)) {
2433 return 0;
2434 } else {
2435 DEBUG(10,("solaris_write_xattr FAILED!\n"));
2436 return -1;
2439 #endif /*HAVE_ATTROPEN*/
2441 /****************************************************************************
2442 Return the major devicenumber for UNIX extensions.
2443 ****************************************************************************/
2445 uint32 unix_dev_major(SMB_DEV_T dev)
2447 #if defined(HAVE_DEVICE_MAJOR_FN)
2448 return (uint32)major(dev);
2449 #else
2450 return (uint32)(dev >> 8);
2451 #endif
2454 /****************************************************************************
2455 Return the minor devicenumber for UNIX extensions.
2456 ****************************************************************************/
2458 uint32 unix_dev_minor(SMB_DEV_T dev)
2460 #if defined(HAVE_DEVICE_MINOR_FN)
2461 return (uint32)minor(dev);
2462 #else
2463 return (uint32)(dev & 0xff);
2464 #endif
2467 #if defined(WITH_AIO)
2469 /*******************************************************************
2470 An aio_read wrapper that will deal with 64-bit sizes.
2471 ********************************************************************/
2473 int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2475 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_READ64)
2476 return aio_read64(aiocb);
2477 #elif defined(HAVE_AIO_READ)
2478 return aio_read(aiocb);
2479 #else
2480 errno = ENOSYS;
2481 return -1;
2482 #endif
2485 /*******************************************************************
2486 An aio_write wrapper that will deal with 64-bit sizes.
2487 ********************************************************************/
2489 int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2491 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_WRITE64)
2492 return aio_write64(aiocb);
2493 #elif defined(HAVE_AIO_WRITE)
2494 return aio_write(aiocb);
2495 #else
2496 errno = ENOSYS;
2497 return -1;
2498 #endif
2501 /*******************************************************************
2502 An aio_return wrapper that will deal with 64-bit sizes.
2503 ********************************************************************/
2505 ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2507 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_RETURN64)
2508 return aio_return64(aiocb);
2509 #elif defined(HAVE_AIO_RETURN)
2510 return aio_return(aiocb);
2511 #else
2512 errno = ENOSYS;
2513 return -1;
2514 #endif
2517 /*******************************************************************
2518 An aio_cancel wrapper that will deal with 64-bit sizes.
2519 ********************************************************************/
2521 int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2523 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_CANCEL64)
2524 return aio_cancel64(fd, aiocb);
2525 #elif defined(HAVE_AIO_CANCEL)
2526 return aio_cancel(fd, aiocb);
2527 #else
2528 errno = ENOSYS;
2529 return -1;
2530 #endif
2533 /*******************************************************************
2534 An aio_error wrapper that will deal with 64-bit sizes.
2535 ********************************************************************/
2537 int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2539 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_ERROR64)
2540 return aio_error64(aiocb);
2541 #elif defined(HAVE_AIO_ERROR)
2542 return aio_error(aiocb);
2543 #else
2544 errno = ENOSYS;
2545 return -1;
2546 #endif
2549 /*******************************************************************
2550 An aio_fsync wrapper that will deal with 64-bit sizes.
2551 ********************************************************************/
2553 int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2555 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_FSYNC64)
2556 return aio_fsync64(op, aiocb);
2557 #elif defined(HAVE_AIO_FSYNC)
2558 return aio_fsync(op, aiocb);
2559 #else
2560 errno = ENOSYS;
2561 return -1;
2562 #endif
2565 /*******************************************************************
2566 An aio_fsync wrapper that will deal with 64-bit sizes.
2567 ********************************************************************/
2569 int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2571 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_SUSPEND64)
2572 return aio_suspend64(cblist, n, timeout);
2573 #elif defined(HAVE_AIO_FSYNC)
2574 return aio_suspend(cblist, n, timeout);
2575 #else
2576 errno = ENOSYS;
2577 return -1;
2578 #endif
2580 #else /* !WITH_AIO */
2582 int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2584 errno = ENOSYS;
2585 return -1;
2588 int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2590 errno = ENOSYS;
2591 return -1;
2594 ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2596 errno = ENOSYS;
2597 return -1;
2600 int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2602 errno = ENOSYS;
2603 return -1;
2606 int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2608 errno = ENOSYS;
2609 return -1;
2612 int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2614 errno = ENOSYS;
2615 return -1;
2618 int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2620 errno = ENOSYS;
2621 return -1;
2623 #endif /* WITH_AIO */
2625 int sys_getpeereid( int s, uid_t *uid)
2627 #if defined(HAVE_PEERCRED)
2628 struct ucred cred;
2629 socklen_t cred_len = sizeof(struct ucred);
2630 int ret;
2632 ret = getsockopt(s, SOL_SOCKET, SO_PEERCRED, (void *)&cred, &cred_len);
2633 if (ret != 0) {
2634 return -1;
2637 if (cred_len != sizeof(struct ucred)) {
2638 errno = EINVAL;
2639 return -1;
2642 *uid = cred.uid;
2643 return 0;
2644 #else
2645 errno = ENOSYS;
2646 return -1;
2647 #endif