[GLUE] Rsync SAMBA_3_0 SVN r25598 in order to create the v3-0-test branch.
[Samba.git] / source / lib / system.c
blobac1add8fc19811e22a94a22279fe43ea2b1b1093
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;
781 SMB_ASSERT(num_cap_vals <= ARRAY_SIZE(cap_vals));
783 if (num_cap_vals == 0) {
784 cap_free(cap);
785 return True;
788 cap_set_flag(cap, CAP_EFFECTIVE, num_cap_vals, cap_vals,
789 enable ? CAP_SET : CAP_CLEAR);
791 /* We never want to pass capabilities down to our children, so make
792 * sure they are not inherited.
794 cap_set_flag(cap, CAP_INHERITABLE, num_cap_vals, cap_vals, CAP_CLEAR);
796 if (cap_set_proc(cap) == -1) {
797 DEBUG(0, ("set_process_capability: cap_set_proc failed: %s\n",
798 strerror(errno)));
799 cap_free(cap);
800 return False;
803 cap_free(cap);
804 return True;
807 #endif /* HAVE_POSIX_CAPABILITIES */
809 /****************************************************************************
810 Gain the oplock capability from the kernel if possible.
811 ****************************************************************************/
813 void set_effective_capability(enum smbd_capability capability)
815 #if defined(HAVE_POSIX_CAPABILITIES)
816 set_process_capability(capability, True);
817 #endif /* HAVE_POSIX_CAPABILITIES */
820 void drop_effective_capability(enum smbd_capability capability)
822 #if defined(HAVE_POSIX_CAPABILITIES)
823 set_process_capability(capability, False);
824 #endif /* HAVE_POSIX_CAPABILITIES */
827 /**************************************************************************
828 Wrapper for random().
829 ****************************************************************************/
831 long sys_random(void)
833 #if defined(HAVE_RANDOM)
834 return (long)random();
835 #elif defined(HAVE_RAND)
836 return (long)rand();
837 #else
838 DEBUG(0,("Error - no random function available !\n"));
839 exit(1);
840 #endif
843 /**************************************************************************
844 Wrapper for srandom().
845 ****************************************************************************/
847 void sys_srandom(unsigned int seed)
849 #if defined(HAVE_SRANDOM)
850 srandom(seed);
851 #elif defined(HAVE_SRAND)
852 srand(seed);
853 #else
854 DEBUG(0,("Error - no srandom function available !\n"));
855 exit(1);
856 #endif
859 /**************************************************************************
860 Returns equivalent to NGROUPS_MAX - using sysconf if needed.
861 ****************************************************************************/
863 int groups_max(void)
865 #if defined(SYSCONF_SC_NGROUPS_MAX)
866 int ret = sysconf(_SC_NGROUPS_MAX);
867 return (ret == -1) ? NGROUPS_MAX : ret;
868 #else
869 return NGROUPS_MAX;
870 #endif
873 /**************************************************************************
874 Wrapper for getgroups. Deals with broken (int) case.
875 ****************************************************************************/
877 int sys_getgroups(int setlen, gid_t *gidset)
879 #if !defined(HAVE_BROKEN_GETGROUPS)
880 return getgroups(setlen, gidset);
881 #else
883 GID_T gid;
884 GID_T *group_list;
885 int i, ngroups;
887 if(setlen == 0) {
888 return getgroups(setlen, &gid);
892 * Broken case. We need to allocate a
893 * GID_T array of size setlen.
896 if(setlen < 0) {
897 errno = EINVAL;
898 return -1;
901 if (setlen == 0)
902 setlen = groups_max();
904 if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
905 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
906 return -1;
909 if((ngroups = getgroups(setlen, group_list)) < 0) {
910 int saved_errno = errno;
911 SAFE_FREE(group_list);
912 errno = saved_errno;
913 return -1;
916 for(i = 0; i < ngroups; i++)
917 gidset[i] = (gid_t)group_list[i];
919 SAFE_FREE(group_list);
920 return ngroups;
921 #endif /* HAVE_BROKEN_GETGROUPS */
925 /**************************************************************************
926 Wrapper for setgroups. Deals with broken (int) case. Automatically used
927 if we have broken getgroups.
928 ****************************************************************************/
930 int sys_setgroups(int setlen, gid_t *gidset)
932 #if !defined(HAVE_SETGROUPS)
933 errno = ENOSYS;
934 return -1;
935 #endif /* HAVE_SETGROUPS */
937 #if !defined(HAVE_BROKEN_GETGROUPS)
938 return setgroups(setlen, gidset);
939 #else
941 GID_T *group_list;
942 int i ;
944 if (setlen == 0)
945 return 0 ;
947 if (setlen < 0 || setlen > groups_max()) {
948 errno = EINVAL;
949 return -1;
953 * Broken case. We need to allocate a
954 * GID_T array of size setlen.
957 if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
958 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
959 return -1;
962 for(i = 0; i < setlen; i++)
963 group_list[i] = (GID_T) gidset[i];
965 if(setgroups(setlen, group_list) != 0) {
966 int saved_errno = errno;
967 SAFE_FREE(group_list);
968 errno = saved_errno;
969 return -1;
972 SAFE_FREE(group_list);
973 return 0 ;
974 #endif /* HAVE_BROKEN_GETGROUPS */
977 /**************************************************************************
978 Wrappers for setpwent(), getpwent() and endpwent()
979 ****************************************************************************/
981 void sys_setpwent(void)
983 setpwent();
986 struct passwd *sys_getpwent(void)
988 return getpwent();
991 void sys_endpwent(void)
993 endpwent();
996 /**************************************************************************
997 Wrappers for getpwnam(), getpwuid(), getgrnam(), getgrgid()
998 ****************************************************************************/
1000 #ifdef ENABLE_BUILD_FARM_HACKS
1003 * In the build farm we want to be able to join machines to the domain. As we
1004 * don't have root access, we need to bypass direct access to /etc/passwd
1005 * after a user has been created via samr. Fake those users.
1008 static struct passwd *fake_pwd;
1009 static int num_fake_pwd;
1011 struct passwd *sys_getpwnam(const char *name)
1013 int i;
1015 for (i=0; i<num_fake_pwd; i++) {
1016 if (strcmp(fake_pwd[i].pw_name, name) == 0) {
1017 DEBUG(10, ("Returning fake user %s\n", name));
1018 return &fake_pwd[i];
1022 return getpwnam(name);
1025 struct passwd *sys_getpwuid(uid_t uid)
1027 int i;
1029 for (i=0; i<num_fake_pwd; i++) {
1030 if (fake_pwd[i].pw_uid == uid) {
1031 DEBUG(10, ("Returning fake user %s\n",
1032 fake_pwd[i].pw_name));
1033 return &fake_pwd[i];
1037 return getpwuid(uid);
1040 void faked_create_user(const char *name)
1042 int i;
1043 uid_t uid;
1044 struct passwd new_pwd;
1046 for (i=0; i<10; i++) {
1047 generate_random_buffer((unsigned char *)&uid,
1048 sizeof(uid));
1049 if (getpwuid(uid) == NULL) {
1050 break;
1054 if (i==10) {
1055 /* Weird. No free uid found... */
1056 return;
1059 new_pwd.pw_name = SMB_STRDUP(name);
1060 new_pwd.pw_passwd = SMB_STRDUP("x");
1061 new_pwd.pw_uid = uid;
1062 new_pwd.pw_gid = 100;
1063 new_pwd.pw_gecos = SMB_STRDUP("faked user");
1064 new_pwd.pw_dir = SMB_STRDUP("/nodir");
1065 new_pwd.pw_shell = SMB_STRDUP("/bin/false");
1067 ADD_TO_ARRAY(NULL, struct passwd, new_pwd, &fake_pwd,
1068 &num_fake_pwd);
1070 DEBUG(10, ("Added fake user %s, have %d fake users\n",
1071 name, num_fake_pwd));
1074 #else
1076 struct passwd *sys_getpwnam(const char *name)
1078 return getpwnam(name);
1081 struct passwd *sys_getpwuid(uid_t uid)
1083 return getpwuid(uid);
1086 #endif
1088 struct group *sys_getgrnam(const char *name)
1090 return getgrnam(name);
1093 struct group *sys_getgrgid(gid_t gid)
1095 return getgrgid(gid);
1098 #if 0 /* NOT CURRENTLY USED - JRA */
1099 /**************************************************************************
1100 The following are the UNICODE versions of *all* system interface functions
1101 called within Samba. Ok, ok, the exceptions are the gethostbyXX calls,
1102 which currently are left as ascii as they are not used other than in name
1103 resolution.
1104 ****************************************************************************/
1106 /**************************************************************************
1107 Wide stat. Just narrow and call sys_xxx.
1108 ****************************************************************************/
1110 int wsys_stat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
1112 pstring fname;
1113 return sys_stat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
1116 /**************************************************************************
1117 Wide lstat. Just narrow and call sys_xxx.
1118 ****************************************************************************/
1120 int wsys_lstat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
1122 pstring fname;
1123 return sys_lstat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
1126 /**************************************************************************
1127 Wide creat. Just narrow and call sys_xxx.
1128 ****************************************************************************/
1130 int wsys_creat(const smb_ucs2_t *wfname, mode_t mode)
1132 pstring fname;
1133 return sys_creat(unicode_to_unix(fname,wfname,sizeof(fname)), mode);
1136 /**************************************************************************
1137 Wide open. Just narrow and call sys_xxx.
1138 ****************************************************************************/
1140 int wsys_open(const smb_ucs2_t *wfname, int oflag, mode_t mode)
1142 pstring fname;
1143 return sys_open(unicode_to_unix(fname,wfname,sizeof(fname)), oflag, mode);
1146 /**************************************************************************
1147 Wide fopen. Just narrow and call sys_xxx.
1148 ****************************************************************************/
1150 FILE *wsys_fopen(const smb_ucs2_t *wfname, const char *type)
1152 pstring fname;
1153 return sys_fopen(unicode_to_unix(fname,wfname,sizeof(fname)), type);
1156 /**************************************************************************
1157 Wide opendir. Just narrow and call sys_xxx.
1158 ****************************************************************************/
1160 SMB_STRUCT_DIR *wsys_opendir(const smb_ucs2_t *wfname)
1162 pstring fname;
1163 return opendir(unicode_to_unix(fname,wfname,sizeof(fname)));
1166 /**************************************************************************
1167 Wide readdir. Return a structure pointer containing a wide filename.
1168 ****************************************************************************/
1170 SMB_STRUCT_WDIRENT *wsys_readdir(SMB_STRUCT_DIR *dirp)
1172 static SMB_STRUCT_WDIRENT retval;
1173 SMB_STRUCT_DIRENT *dirval = sys_readdir(dirp);
1175 if(!dirval)
1176 return NULL;
1179 * The only POSIX defined member of this struct is d_name.
1182 unix_to_unicode(retval.d_name,dirval->d_name,sizeof(retval.d_name));
1184 return &retval;
1187 /**************************************************************************
1188 Wide getwd. Call sys_xxx and widen. Assumes s points to a wpstring.
1189 ****************************************************************************/
1191 smb_ucs2_t *wsys_getwd(smb_ucs2_t *s)
1193 pstring fname;
1194 char *p = sys_getwd(fname);
1196 if(!p)
1197 return NULL;
1199 return unix_to_unicode(s, p, sizeof(wpstring));
1202 /**************************************************************************
1203 Wide chown. Just narrow and call sys_xxx.
1204 ****************************************************************************/
1206 int wsys_chown(const smb_ucs2_t *wfname, uid_t uid, gid_t gid)
1208 pstring fname;
1209 return chown(unicode_to_unix(fname,wfname,sizeof(fname)), uid, gid);
1212 /**************************************************************************
1213 Wide chroot. Just narrow and call sys_xxx.
1214 ****************************************************************************/
1216 int wsys_chroot(const smb_ucs2_t *wfname)
1218 pstring fname;
1219 return chroot(unicode_to_unix(fname,wfname,sizeof(fname)));
1222 /**************************************************************************
1223 Wide getpwnam. Return a structure pointer containing wide names.
1224 ****************************************************************************/
1226 SMB_STRUCT_WPASSWD *wsys_getpwnam(const smb_ucs2_t *wname)
1228 static SMB_STRUCT_WPASSWD retval;
1229 fstring name;
1230 struct passwd *pwret = sys_getpwnam(unicode_to_unix(name,wname,sizeof(name)));
1232 if(!pwret)
1233 return NULL;
1235 unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
1236 retval.pw_passwd = pwret->pw_passwd;
1237 retval.pw_uid = pwret->pw_uid;
1238 retval.pw_gid = pwret->pw_gid;
1239 unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
1240 unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
1241 unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
1243 return &retval;
1246 /**************************************************************************
1247 Wide getpwuid. Return a structure pointer containing wide names.
1248 ****************************************************************************/
1250 SMB_STRUCT_WPASSWD *wsys_getpwuid(uid_t uid)
1252 static SMB_STRUCT_WPASSWD retval;
1253 struct passwd *pwret = sys_getpwuid(uid);
1255 if(!pwret)
1256 return NULL;
1258 unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
1259 retval.pw_passwd = pwret->pw_passwd;
1260 retval.pw_uid = pwret->pw_uid;
1261 retval.pw_gid = pwret->pw_gid;
1262 unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
1263 unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
1264 unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
1266 return &retval;
1268 #endif /* NOT CURRENTLY USED - JRA */
1270 /**************************************************************************
1271 Extract a command into an arg list. Uses a static pstring for storage.
1272 Caller frees returned arg list (which contains pointers into the static pstring).
1273 ****************************************************************************/
1275 static char **extract_args(const char *command)
1277 static pstring trunc_cmd;
1278 char *ptr;
1279 int argcl;
1280 char **argl = NULL;
1281 int i;
1283 pstrcpy(trunc_cmd, command);
1285 if(!(ptr = strtok(trunc_cmd, " \t"))) {
1286 errno = EINVAL;
1287 return NULL;
1291 * Count the args.
1294 for( argcl = 1; ptr; ptr = strtok(NULL, " \t"))
1295 argcl++;
1297 if((argl = (char **)SMB_MALLOC((argcl + 1) * sizeof(char *))) == NULL)
1298 return NULL;
1301 * Now do the extraction.
1304 pstrcpy(trunc_cmd, command);
1306 ptr = strtok(trunc_cmd, " \t");
1307 i = 0;
1308 argl[i++] = ptr;
1310 while((ptr = strtok(NULL, " \t")) != NULL)
1311 argl[i++] = ptr;
1313 argl[i++] = NULL;
1314 return argl;
1317 /**************************************************************************
1318 Wrapper for fork. Ensures that mypid is reset. Used so we can write
1319 a sys_getpid() that only does a system call *once*.
1320 ****************************************************************************/
1322 static pid_t mypid = (pid_t)-1;
1324 pid_t sys_fork(void)
1326 pid_t forkret = fork();
1328 if (forkret == (pid_t)0) /* Child - reset mypid so sys_getpid does a system call. */
1329 mypid = (pid_t) -1;
1331 return forkret;
1334 /**************************************************************************
1335 Wrapper for getpid. Ensures we only do a system call *once*.
1336 ****************************************************************************/
1338 pid_t sys_getpid(void)
1340 if (mypid == (pid_t)-1)
1341 mypid = getpid();
1343 return mypid;
1346 /**************************************************************************
1347 Wrapper for popen. Safer as it doesn't search a path.
1348 Modified from the glibc sources.
1349 modified by tridge to return a file descriptor. We must kick our FILE* habit
1350 ****************************************************************************/
1352 typedef struct _popen_list
1354 int fd;
1355 pid_t child_pid;
1356 struct _popen_list *next;
1357 } popen_list;
1359 static popen_list *popen_chain;
1361 int sys_popen(const char *command)
1363 int parent_end, child_end;
1364 int pipe_fds[2];
1365 popen_list *entry = NULL;
1366 char **argl = NULL;
1368 if (pipe(pipe_fds) < 0)
1369 return -1;
1371 parent_end = pipe_fds[0];
1372 child_end = pipe_fds[1];
1374 if (!*command) {
1375 errno = EINVAL;
1376 goto err_exit;
1379 if((entry = SMB_MALLOC_P(popen_list)) == NULL)
1380 goto err_exit;
1382 ZERO_STRUCTP(entry);
1385 * Extract the command and args into a NULL terminated array.
1388 if(!(argl = extract_args(command)))
1389 goto err_exit;
1391 entry->child_pid = sys_fork();
1393 if (entry->child_pid == -1) {
1394 goto err_exit;
1397 if (entry->child_pid == 0) {
1400 * Child !
1403 int child_std_end = STDOUT_FILENO;
1404 popen_list *p;
1406 close(parent_end);
1407 if (child_end != child_std_end) {
1408 dup2 (child_end, child_std_end);
1409 close (child_end);
1413 * POSIX.2: "popen() shall ensure that any streams from previous
1414 * popen() calls that remain open in the parent process are closed
1415 * in the new child process."
1418 for (p = popen_chain; p; p = p->next)
1419 close(p->fd);
1421 execv(argl[0], argl);
1422 _exit (127);
1426 * Parent.
1429 close (child_end);
1430 SAFE_FREE(argl);
1432 /* Link into popen_chain. */
1433 entry->next = popen_chain;
1434 popen_chain = entry;
1435 entry->fd = parent_end;
1437 return entry->fd;
1439 err_exit:
1441 SAFE_FREE(entry);
1442 SAFE_FREE(argl);
1443 close(pipe_fds[0]);
1444 close(pipe_fds[1]);
1445 return -1;
1448 /**************************************************************************
1449 Wrapper for pclose. Modified from the glibc sources.
1450 ****************************************************************************/
1452 int sys_pclose(int fd)
1454 int wstatus;
1455 popen_list **ptr = &popen_chain;
1456 popen_list *entry = NULL;
1457 pid_t wait_pid;
1458 int status = -1;
1460 /* Unlink from popen_chain. */
1461 for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
1462 if ((*ptr)->fd == fd) {
1463 entry = *ptr;
1464 *ptr = (*ptr)->next;
1465 status = 0;
1466 break;
1470 if (status < 0 || close(entry->fd) < 0)
1471 return -1;
1474 * As Samba is catching and eating child process
1475 * exits we don't really care about the child exit
1476 * code, a -1 with errno = ECHILD will do fine for us.
1479 do {
1480 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
1481 } while (wait_pid == -1 && errno == EINTR);
1483 SAFE_FREE(entry);
1485 if (wait_pid == -1)
1486 return -1;
1487 return wstatus;
1490 /**************************************************************************
1491 Wrappers for dlopen, dlsym, dlclose.
1492 ****************************************************************************/
1494 void *sys_dlopen(const char *name, int flags)
1496 #if defined(HAVE_DLOPEN)
1497 return dlopen(name, flags);
1498 #else
1499 return NULL;
1500 #endif
1503 void *sys_dlsym(void *handle, const char *symbol)
1505 #if defined(HAVE_DLSYM)
1506 return dlsym(handle, symbol);
1507 #else
1508 return NULL;
1509 #endif
1512 int sys_dlclose (void *handle)
1514 #if defined(HAVE_DLCLOSE)
1515 return dlclose(handle);
1516 #else
1517 return 0;
1518 #endif
1521 const char *sys_dlerror(void)
1523 #if defined(HAVE_DLERROR)
1524 return dlerror();
1525 #else
1526 return NULL;
1527 #endif
1530 int sys_dup2(int oldfd, int newfd)
1532 #if defined(HAVE_DUP2)
1533 return dup2(oldfd, newfd);
1534 #else
1535 errno = ENOSYS;
1536 return -1;
1537 #endif
1540 /**************************************************************************
1541 Wrapper for Admin Logs.
1542 ****************************************************************************/
1544 void sys_adminlog(int priority, const char *format_str, ...)
1546 va_list ap;
1547 int ret;
1548 char *msgbuf = NULL;
1550 va_start( ap, format_str );
1551 ret = vasprintf( &msgbuf, format_str, ap );
1552 va_end( ap );
1554 if (ret == -1)
1555 return;
1557 #if defined(HAVE_SYSLOG)
1558 syslog( priority, "%s", msgbuf );
1559 #else
1560 DEBUG(0,("%s", msgbuf ));
1561 #endif
1562 SAFE_FREE(msgbuf);
1565 /******** Solaris EA helper function prototypes ********/
1566 #ifdef HAVE_ATTROPEN
1567 #define SOLARIS_ATTRMODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP
1568 static int solaris_write_xattr(int attrfd, const char *value, size_t size);
1569 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size);
1570 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size);
1571 static int solaris_unlinkat(int attrdirfd, const char *name);
1572 static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode);
1573 static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode);
1574 #endif
1576 /**************************************************************************
1577 Wrappers for extented attribute calls. Based on the Linux package with
1578 support for IRIX and (Net|Free)BSD also. Expand as other systems have them.
1579 ****************************************************************************/
1581 ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t size)
1583 #if defined(HAVE_GETXATTR)
1584 #ifndef XATTR_ADD_OPT
1585 return getxattr(path, name, value, size);
1586 #else
1587 int options = 0;
1588 return getxattr(path, name, value, size, 0, options);
1589 #endif
1590 #elif defined(HAVE_GETEA)
1591 return getea(path, name, value, size);
1592 #elif defined(HAVE_EXTATTR_GET_FILE)
1593 char *s;
1594 ssize_t retval;
1595 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1596 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1597 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1599 * The BSD implementation has a nasty habit of silently truncating
1600 * the returned value to the size of the buffer, so we have to check
1601 * that the buffer is large enough to fit the returned value.
1603 if((retval=extattr_get_file(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1604 if(retval > size) {
1605 errno = ERANGE;
1606 return -1;
1608 if((retval=extattr_get_file(path, attrnamespace, attrname, value, size)) >= 0)
1609 return retval;
1612 DEBUG(10,("sys_getxattr: extattr_get_file() failed with: %s\n", strerror(errno)));
1613 return -1;
1614 #elif defined(HAVE_ATTR_GET)
1615 int retval, flags = 0;
1616 int valuelength = (int)size;
1617 char *attrname = strchr(name,'.') + 1;
1619 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1621 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1623 return retval ? retval : valuelength;
1624 #elif defined(HAVE_ATTROPEN)
1625 ssize_t ret = -1;
1626 int attrfd = solaris_attropen(path, name, O_RDONLY, 0);
1627 if (attrfd >= 0) {
1628 ret = solaris_read_xattr(attrfd, value, size);
1629 close(attrfd);
1631 return ret;
1632 #else
1633 errno = ENOSYS;
1634 return -1;
1635 #endif
1638 ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t size)
1640 #if defined(HAVE_LGETXATTR)
1641 return lgetxattr(path, name, value, size);
1642 #elif defined(HAVE_GETXATTR) && defined(XATTR_ADD_OPT)
1643 int options = XATTR_NOFOLLOW;
1644 return getxattr(path, name, value, size, 0, options);
1645 #elif defined(HAVE_LGETEA)
1646 return lgetea(path, name, value, size);
1647 #elif defined(HAVE_EXTATTR_GET_LINK)
1648 char *s;
1649 ssize_t retval;
1650 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1651 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1652 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1654 if((retval=extattr_get_link(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1655 if(retval > size) {
1656 errno = ERANGE;
1657 return -1;
1659 if((retval=extattr_get_link(path, attrnamespace, attrname, value, size)) >= 0)
1660 return retval;
1663 DEBUG(10,("sys_lgetxattr: extattr_get_link() failed with: %s\n", strerror(errno)));
1664 return -1;
1665 #elif defined(HAVE_ATTR_GET)
1666 int retval, flags = ATTR_DONTFOLLOW;
1667 int valuelength = (int)size;
1668 char *attrname = strchr(name,'.') + 1;
1670 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1672 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1674 return retval ? retval : valuelength;
1675 #elif defined(HAVE_ATTROPEN)
1676 ssize_t ret = -1;
1677 int attrfd = solaris_attropen(path, name, O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1678 if (attrfd >= 0) {
1679 ret = solaris_read_xattr(attrfd, value, size);
1680 close(attrfd);
1682 return ret;
1683 #else
1684 errno = ENOSYS;
1685 return -1;
1686 #endif
1689 ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size)
1691 #if defined(HAVE_FGETXATTR)
1692 #ifndef XATTR_ADD_OPT
1693 return fgetxattr(filedes, name, value, size);
1694 #else
1695 int options = 0;
1696 return fgetxattr(filedes, name, value, size, 0, options);
1697 #endif
1698 #elif defined(HAVE_FGETEA)
1699 return fgetea(filedes, name, value, size);
1700 #elif defined(HAVE_EXTATTR_GET_FD)
1701 char *s;
1702 ssize_t retval;
1703 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1704 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1705 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1707 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0)) >= 0) {
1708 if(retval > size) {
1709 errno = ERANGE;
1710 return -1;
1712 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, value, size)) >= 0)
1713 return retval;
1716 DEBUG(10,("sys_fgetxattr: extattr_get_fd() failed with: %s\n", strerror(errno)));
1717 return -1;
1718 #elif defined(HAVE_ATTR_GETF)
1719 int retval, flags = 0;
1720 int valuelength = (int)size;
1721 char *attrname = strchr(name,'.') + 1;
1723 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1725 retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags);
1727 return retval ? retval : valuelength;
1728 #elif defined(HAVE_ATTROPEN)
1729 ssize_t ret = -1;
1730 int attrfd = solaris_openat(filedes, name, O_RDONLY|O_XATTR, 0);
1731 if (attrfd >= 0) {
1732 ret = solaris_read_xattr(attrfd, value, size);
1733 close(attrfd);
1735 return ret;
1736 #else
1737 errno = ENOSYS;
1738 return -1;
1739 #endif
1742 #if defined(HAVE_EXTATTR_LIST_FILE)
1744 #define EXTATTR_PREFIX(s) (s), (sizeof((s))-1)
1746 static struct {
1747 int space;
1748 const char *name;
1749 size_t len;
1751 extattr[] = {
1752 { EXTATTR_NAMESPACE_SYSTEM, EXTATTR_PREFIX("system.") },
1753 { EXTATTR_NAMESPACE_USER, EXTATTR_PREFIX("user.") },
1756 typedef union {
1757 const char *path;
1758 int filedes;
1759 } extattr_arg;
1761 static ssize_t bsd_attr_list (int type, extattr_arg arg, char *list, size_t size)
1763 ssize_t list_size, total_size = 0;
1764 int i, t, len;
1765 char *buf;
1766 /* Iterate through extattr(2) namespaces */
1767 for(t = 0; t < (sizeof(extattr)/sizeof(extattr[0])); t++) {
1768 switch(type) {
1769 #if defined(HAVE_EXTATTR_LIST_FILE)
1770 case 0:
1771 list_size = extattr_list_file(arg.path, extattr[t].space, list, size);
1772 break;
1773 #endif
1774 #if defined(HAVE_EXTATTR_LIST_LINK)
1775 case 1:
1776 list_size = extattr_list_link(arg.path, extattr[t].space, list, size);
1777 break;
1778 #endif
1779 #if defined(HAVE_EXTATTR_LIST_FD)
1780 case 2:
1781 list_size = extattr_list_fd(arg.filedes, extattr[t].space, list, size);
1782 break;
1783 #endif
1784 default:
1785 errno = ENOSYS;
1786 return -1;
1788 /* Some error happend. Errno should be set by the previous call */
1789 if(list_size < 0)
1790 return -1;
1791 /* No attributes */
1792 if(list_size == 0)
1793 continue;
1794 /* XXX: Call with an empty buffer may be used to calculate
1795 necessary buffer size. Unfortunately, we can't say, how
1796 many attributes were returned, so here is the potential
1797 problem with the emulation.
1799 if(list == NULL) {
1800 /* Take the worse case of one char attribute names -
1801 two bytes per name plus one more for sanity.
1803 total_size += list_size + (list_size/2 + 1)*extattr[t].len;
1804 continue;
1806 /* Count necessary offset to fit namespace prefixes */
1807 len = 0;
1808 for(i = 0; i < list_size; i += list[i] + 1)
1809 len += extattr[t].len;
1811 total_size += list_size + len;
1812 /* Buffer is too small to fit the results */
1813 if(total_size > size) {
1814 errno = ERANGE;
1815 return -1;
1817 /* Shift results back, so we can prepend prefixes */
1818 buf = memmove(list + len, list, list_size);
1820 for(i = 0; i < list_size; i += len + 1) {
1821 len = buf[i];
1822 strncpy(list, extattr[t].name, extattr[t].len + 1);
1823 list += extattr[t].len;
1824 strncpy(list, buf + i + 1, len);
1825 list[len] = '\0';
1826 list += len + 1;
1828 size -= total_size;
1830 return total_size;
1833 #endif
1835 #if defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1836 static char attr_buffer[ATTR_MAX_VALUELEN];
1838 static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags)
1840 int retval = 0, index;
1841 attrlist_cursor_t *cursor = 0;
1842 int total_size = 0;
1843 attrlist_t * al = (attrlist_t *)attr_buffer;
1844 attrlist_ent_t *ae;
1845 size_t ent_size, left = size;
1846 char *bp = list;
1848 while (True) {
1849 if (filedes)
1850 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1851 else
1852 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1853 if (retval) break;
1854 for (index = 0; index < al->al_count; index++) {
1855 ae = ATTR_ENTRY(attr_buffer, index);
1856 ent_size = strlen(ae->a_name) + sizeof("user.");
1857 if (left >= ent_size) {
1858 strncpy(bp, "user.", sizeof("user."));
1859 strncat(bp, ae->a_name, ent_size - sizeof("user."));
1860 bp += ent_size;
1861 left -= ent_size;
1862 } else if (size) {
1863 errno = ERANGE;
1864 retval = -1;
1865 break;
1867 total_size += ent_size;
1869 if (al->al_more == 0) break;
1871 if (retval == 0) {
1872 flags |= ATTR_ROOT;
1873 cursor = 0;
1874 while (True) {
1875 if (filedes)
1876 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1877 else
1878 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1879 if (retval) break;
1880 for (index = 0; index < al->al_count; index++) {
1881 ae = ATTR_ENTRY(attr_buffer, index);
1882 ent_size = strlen(ae->a_name) + sizeof("system.");
1883 if (left >= ent_size) {
1884 strncpy(bp, "system.", sizeof("system."));
1885 strncat(bp, ae->a_name, ent_size - sizeof("system."));
1886 bp += ent_size;
1887 left -= ent_size;
1888 } else if (size) {
1889 errno = ERANGE;
1890 retval = -1;
1891 break;
1893 total_size += ent_size;
1895 if (al->al_more == 0) break;
1898 return (ssize_t)(retval ? retval : total_size);
1901 #endif
1903 ssize_t sys_listxattr (const char *path, char *list, size_t size)
1905 #if defined(HAVE_LISTXATTR)
1906 #ifndef XATTR_ADD_OPT
1907 return listxattr(path, list, size);
1908 #else
1909 int options = 0;
1910 return listxattr(path, list, size, options);
1911 #endif
1912 #elif defined(HAVE_LISTEA)
1913 return listea(path, list, size);
1914 #elif defined(HAVE_EXTATTR_LIST_FILE)
1915 extattr_arg arg;
1916 arg.path = path;
1917 return bsd_attr_list(0, arg, list, size);
1918 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1919 return irix_attr_list(path, 0, list, size, 0);
1920 #elif defined(HAVE_ATTROPEN)
1921 ssize_t ret = -1;
1922 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
1923 if (attrdirfd >= 0) {
1924 ret = solaris_list_xattr(attrdirfd, list, size);
1925 close(attrdirfd);
1927 return ret;
1928 #else
1929 errno = ENOSYS;
1930 return -1;
1931 #endif
1934 ssize_t sys_llistxattr (const char *path, char *list, size_t size)
1936 #if defined(HAVE_LLISTXATTR)
1937 return llistxattr(path, list, size);
1938 #elif defined(HAVE_LISTXATTR) && defined(XATTR_ADD_OPT)
1939 int options = XATTR_NOFOLLOW;
1940 return listxattr(path, list, size, options);
1941 #elif defined(HAVE_LLISTEA)
1942 return llistea(path, list, size);
1943 #elif defined(HAVE_EXTATTR_LIST_LINK)
1944 extattr_arg arg;
1945 arg.path = path;
1946 return bsd_attr_list(1, arg, list, size);
1947 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1948 return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW);
1949 #elif defined(HAVE_ATTROPEN)
1950 ssize_t ret = -1;
1951 int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1952 if (attrdirfd >= 0) {
1953 ret = solaris_list_xattr(attrdirfd, list, size);
1954 close(attrdirfd);
1956 return ret;
1957 #else
1958 errno = ENOSYS;
1959 return -1;
1960 #endif
1963 ssize_t sys_flistxattr (int filedes, char *list, size_t size)
1965 #if defined(HAVE_FLISTXATTR)
1966 #ifndef XATTR_ADD_OPT
1967 return flistxattr(filedes, list, size);
1968 #else
1969 int options = 0;
1970 return flistxattr(filedes, list, size, options);
1971 #endif
1972 #elif defined(HAVE_FLISTEA)
1973 return flistea(filedes, list, size);
1974 #elif defined(HAVE_EXTATTR_LIST_FD)
1975 extattr_arg arg;
1976 arg.filedes = filedes;
1977 return bsd_attr_list(2, arg, list, size);
1978 #elif defined(HAVE_ATTR_LISTF)
1979 return irix_attr_list(NULL, filedes, list, size, 0);
1980 #elif defined(HAVE_ATTROPEN)
1981 ssize_t ret = -1;
1982 int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
1983 if (attrdirfd >= 0) {
1984 ret = solaris_list_xattr(attrdirfd, list, size);
1985 close(attrdirfd);
1987 return ret;
1988 #else
1989 errno = ENOSYS;
1990 return -1;
1991 #endif
1994 int sys_removexattr (const char *path, const char *name)
1996 #if defined(HAVE_REMOVEXATTR)
1997 #ifndef XATTR_ADD_OPT
1998 return removexattr(path, name);
1999 #else
2000 int options = 0;
2001 return removexattr(path, name, options);
2002 #endif
2003 #elif defined(HAVE_REMOVEEA)
2004 return removeea(path, name);
2005 #elif defined(HAVE_EXTATTR_DELETE_FILE)
2006 char *s;
2007 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2008 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2009 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2011 return extattr_delete_file(path, attrnamespace, attrname);
2012 #elif defined(HAVE_ATTR_REMOVE)
2013 int flags = 0;
2014 char *attrname = strchr(name,'.') + 1;
2016 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
2018 return attr_remove(path, attrname, flags);
2019 #elif defined(HAVE_ATTROPEN)
2020 int ret = -1;
2021 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
2022 if (attrdirfd >= 0) {
2023 ret = solaris_unlinkat(attrdirfd, name);
2024 close(attrdirfd);
2026 return ret;
2027 #else
2028 errno = ENOSYS;
2029 return -1;
2030 #endif
2033 int sys_lremovexattr (const char *path, const char *name)
2035 #if defined(HAVE_LREMOVEXATTR)
2036 return lremovexattr(path, name);
2037 #elif defined(HAVE_REMOVEXATTR) && defined(XATTR_ADD_OPT)
2038 int options = XATTR_NOFOLLOW;
2039 return removexattr(path, name, options);
2040 #elif defined(HAVE_LREMOVEEA)
2041 return lremoveea(path, name);
2042 #elif defined(HAVE_EXTATTR_DELETE_LINK)
2043 char *s;
2044 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2045 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2046 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2048 return extattr_delete_link(path, attrnamespace, attrname);
2049 #elif defined(HAVE_ATTR_REMOVE)
2050 int flags = ATTR_DONTFOLLOW;
2051 char *attrname = strchr(name,'.') + 1;
2053 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
2055 return attr_remove(path, attrname, flags);
2056 #elif defined(HAVE_ATTROPEN)
2057 int ret = -1;
2058 int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
2059 if (attrdirfd >= 0) {
2060 ret = solaris_unlinkat(attrdirfd, name);
2061 close(attrdirfd);
2063 return ret;
2064 #else
2065 errno = ENOSYS;
2066 return -1;
2067 #endif
2070 int sys_fremovexattr (int filedes, const char *name)
2072 #if defined(HAVE_FREMOVEXATTR)
2073 #ifndef XATTR_ADD_OPT
2074 return fremovexattr(filedes, name);
2075 #else
2076 int options = 0;
2077 return fremovexattr(filedes, name, options);
2078 #endif
2079 #elif defined(HAVE_FREMOVEEA)
2080 return fremoveea(filedes, name);
2081 #elif defined(HAVE_EXTATTR_DELETE_FD)
2082 char *s;
2083 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2084 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2085 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2087 return extattr_delete_fd(filedes, attrnamespace, attrname);
2088 #elif defined(HAVE_ATTR_REMOVEF)
2089 int flags = 0;
2090 char *attrname = strchr(name,'.') + 1;
2092 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
2094 return attr_removef(filedes, attrname, flags);
2095 #elif defined(HAVE_ATTROPEN)
2096 int ret = -1;
2097 int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
2098 if (attrdirfd >= 0) {
2099 ret = solaris_unlinkat(attrdirfd, name);
2100 close(attrdirfd);
2102 return ret;
2103 #else
2104 errno = ENOSYS;
2105 return -1;
2106 #endif
2109 #if !defined(HAVE_SETXATTR)
2110 #define XATTR_CREATE 0x1 /* set value, fail if attr already exists */
2111 #define XATTR_REPLACE 0x2 /* set value, fail if attr does not exist */
2112 #endif
2114 int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags)
2116 #if defined(HAVE_SETXATTR)
2117 #ifndef XATTR_ADD_OPT
2118 return setxattr(path, name, value, size, flags);
2119 #else
2120 int options = 0;
2121 return setxattr(path, name, value, size, 0, options);
2122 #endif
2123 #elif defined(HAVE_SETEA)
2124 return setea(path, name, value, size, flags);
2125 #elif defined(HAVE_EXTATTR_SET_FILE)
2126 char *s;
2127 int retval = 0;
2128 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2129 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2130 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2131 if (flags) {
2132 /* Check attribute existence */
2133 retval = extattr_get_file(path, attrnamespace, attrname, NULL, 0);
2134 if (retval < 0) {
2135 /* REPLACE attribute, that doesn't exist */
2136 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2137 errno = ENOATTR;
2138 return -1;
2140 /* Ignore other errors */
2142 else {
2143 /* CREATE attribute, that already exists */
2144 if (flags & XATTR_CREATE) {
2145 errno = EEXIST;
2146 return -1;
2150 retval = extattr_set_file(path, attrnamespace, attrname, value, size);
2151 return (retval < 0) ? -1 : 0;
2152 #elif defined(HAVE_ATTR_SET)
2153 int myflags = 0;
2154 char *attrname = strchr(name,'.') + 1;
2156 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2157 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2158 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2160 return attr_set(path, attrname, (const char *)value, size, myflags);
2161 #elif defined(HAVE_ATTROPEN)
2162 int ret = -1;
2163 int myflags = O_RDWR;
2164 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2165 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2166 int attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2167 if (attrfd >= 0) {
2168 ret = solaris_write_xattr(attrfd, value, size);
2169 close(attrfd);
2171 return ret;
2172 #else
2173 errno = ENOSYS;
2174 return -1;
2175 #endif
2178 int sys_lsetxattr (const char *path, const char *name, const void *value, size_t size, int flags)
2180 #if defined(HAVE_LSETXATTR)
2181 return lsetxattr(path, name, value, size, flags);
2182 #elif defined(HAVE_SETXATTR) && defined(XATTR_ADD_OPT)
2183 int options = XATTR_NOFOLLOW;
2184 return setxattr(path, name, value, size, 0, options);
2185 #elif defined(LSETEA)
2186 return lsetea(path, name, value, size, flags);
2187 #elif defined(HAVE_EXTATTR_SET_LINK)
2188 char *s;
2189 int retval = 0;
2190 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2191 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2192 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2193 if (flags) {
2194 /* Check attribute existence */
2195 retval = extattr_get_link(path, attrnamespace, attrname, NULL, 0);
2196 if (retval < 0) {
2197 /* REPLACE attribute, that doesn't exist */
2198 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2199 errno = ENOATTR;
2200 return -1;
2202 /* Ignore other errors */
2204 else {
2205 /* CREATE attribute, that already exists */
2206 if (flags & XATTR_CREATE) {
2207 errno = EEXIST;
2208 return -1;
2213 retval = extattr_set_link(path, attrnamespace, attrname, value, size);
2214 return (retval < 0) ? -1 : 0;
2215 #elif defined(HAVE_ATTR_SET)
2216 int myflags = ATTR_DONTFOLLOW;
2217 char *attrname = strchr(name,'.') + 1;
2219 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2220 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2221 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2223 return attr_set(path, attrname, (const char *)value, size, myflags);
2224 #elif defined(HAVE_ATTROPEN)
2225 int ret = -1;
2226 int myflags = O_RDWR | AT_SYMLINK_NOFOLLOW;
2227 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2228 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2229 int attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2230 if (attrfd >= 0) {
2231 ret = solaris_write_xattr(attrfd, value, size);
2232 close(attrfd);
2234 return ret;
2235 #else
2236 errno = ENOSYS;
2237 return -1;
2238 #endif
2241 int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags)
2243 #if defined(HAVE_FSETXATTR)
2244 #ifndef XATTR_ADD_OPT
2245 return fsetxattr(filedes, name, value, size, flags);
2246 #else
2247 int options = 0;
2248 return fsetxattr(filedes, name, value, size, 0, options);
2249 #endif
2250 #elif defined(HAVE_FSETEA)
2251 return fsetea(filedes, name, value, size, flags);
2252 #elif defined(HAVE_EXTATTR_SET_FD)
2253 char *s;
2254 int retval = 0;
2255 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2256 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2257 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2258 if (flags) {
2259 /* Check attribute existence */
2260 retval = extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0);
2261 if (retval < 0) {
2262 /* REPLACE attribute, that doesn't exist */
2263 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2264 errno = ENOATTR;
2265 return -1;
2267 /* Ignore other errors */
2269 else {
2270 /* CREATE attribute, that already exists */
2271 if (flags & XATTR_CREATE) {
2272 errno = EEXIST;
2273 return -1;
2277 retval = extattr_set_fd(filedes, attrnamespace, attrname, value, size);
2278 return (retval < 0) ? -1 : 0;
2279 #elif defined(HAVE_ATTR_SETF)
2280 int myflags = 0;
2281 char *attrname = strchr(name,'.') + 1;
2283 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2284 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2285 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2287 return attr_setf(filedes, attrname, (const char *)value, size, myflags);
2288 #elif defined(HAVE_ATTROPEN)
2289 int ret = -1;
2290 int myflags = O_RDWR | O_XATTR;
2291 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2292 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2293 int attrfd = solaris_openat(filedes, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2294 if (attrfd >= 0) {
2295 ret = solaris_write_xattr(attrfd, value, size);
2296 close(attrfd);
2298 return ret;
2299 #else
2300 errno = ENOSYS;
2301 return -1;
2302 #endif
2305 /**************************************************************************
2306 helper functions for Solaris' EA support
2307 ****************************************************************************/
2308 #ifdef HAVE_ATTROPEN
2309 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size)
2311 struct stat sbuf;
2313 if (fstat(attrfd, &sbuf) == -1) {
2314 errno = ENOATTR;
2315 return -1;
2318 /* This is to return the current size of the named extended attribute */
2319 if (size == 0) {
2320 return sbuf.st_size;
2323 /* check size and read xattr */
2324 if (sbuf.st_size > size) {
2325 errno = ERANGE;
2326 return -1;
2329 return read(attrfd, value, sbuf.st_size);
2332 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size)
2334 ssize_t len = 0;
2335 int stop = 0;
2336 DIR *dirp;
2337 struct dirent *de;
2338 int newfd = dup(attrdirfd);
2339 /* CAUTION: The originating file descriptor should not be
2340 used again following the call to fdopendir().
2341 For that reason we dup() the file descriptor
2342 here to make things more clear. */
2343 dirp = fdopendir(newfd);
2345 while ((de = readdir(dirp))) {
2346 size_t listlen = strlen(de->d_name);
2347 if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) {
2348 /* we don't want "." and ".." here: */
2349 DEBUG(10,("skipped EA %s\n",de->d_name));
2350 continue;
2353 if (size == 0) {
2354 /* return the current size of the list of extended attribute names*/
2355 len += listlen + 1;
2356 } else {
2357 /* check size and copy entrieѕ + nul into list. */
2358 if ((len + listlen + 1) > size) {
2359 errno = ERANGE;
2360 len = -1;
2361 break;
2362 } else {
2363 safe_strcpy(list + len, de->d_name, listlen);
2364 pstrcpy(list + len, de->d_name);
2365 len += listlen;
2366 list[len] = '\0';
2367 ++len;
2372 if (closedir(dirp) == -1) {
2373 DEBUG(0,("closedir dirp failed: %s\n",strerror(errno)));
2374 return -1;
2376 return len;
2379 static int solaris_unlinkat(int attrdirfd, const char *name)
2381 if (unlinkat(attrdirfd, name, 0) == -1) {
2382 if (errno == ENOENT) {
2383 errno = ENOATTR;
2385 return -1;
2387 return 0;
2390 static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode)
2392 int filedes = attropen(path, attrpath, oflag, mode);
2393 if (filedes == -1) {
2394 DEBUG(10,("attropen FAILED: path: %s, name: %s, errno: %s\n",path,attrpath,strerror(errno)));
2395 if (errno == EINVAL) {
2396 errno = ENOTSUP;
2397 } else {
2398 errno = ENOATTR;
2401 return filedes;
2404 static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode)
2406 int filedes = openat(fildes, path, oflag, mode);
2407 if (filedes == -1) {
2408 DEBUG(10,("openat FAILED: fd: %s, path: %s, errno: %s\n",filedes,path,strerror(errno)));
2409 if (errno == EINVAL) {
2410 errno = ENOTSUP;
2411 } else {
2412 errno = ENOATTR;
2415 return filedes;
2418 static int solaris_write_xattr(int attrfd, const char *value, size_t size)
2420 if ((ftruncate(attrfd, 0) == 0) && (write(attrfd, value, size) == size)) {
2421 return 0;
2422 } else {
2423 DEBUG(10,("solaris_write_xattr FAILED!\n"));
2424 return -1;
2427 #endif /*HAVE_ATTROPEN*/
2429 /****************************************************************************
2430 Return the major devicenumber for UNIX extensions.
2431 ****************************************************************************/
2433 uint32 unix_dev_major(SMB_DEV_T dev)
2435 #if defined(HAVE_DEVICE_MAJOR_FN)
2436 return (uint32)major(dev);
2437 #else
2438 return (uint32)(dev >> 8);
2439 #endif
2442 /****************************************************************************
2443 Return the minor devicenumber for UNIX extensions.
2444 ****************************************************************************/
2446 uint32 unix_dev_minor(SMB_DEV_T dev)
2448 #if defined(HAVE_DEVICE_MINOR_FN)
2449 return (uint32)minor(dev);
2450 #else
2451 return (uint32)(dev & 0xff);
2452 #endif
2455 #if defined(WITH_AIO)
2457 /*******************************************************************
2458 An aio_read wrapper that will deal with 64-bit sizes.
2459 ********************************************************************/
2461 int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2463 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_READ64)
2464 return aio_read64(aiocb);
2465 #elif defined(HAVE_AIO_READ)
2466 return aio_read(aiocb);
2467 #else
2468 errno = ENOSYS;
2469 return -1;
2470 #endif
2473 /*******************************************************************
2474 An aio_write wrapper that will deal with 64-bit sizes.
2475 ********************************************************************/
2477 int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2479 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_WRITE64)
2480 return aio_write64(aiocb);
2481 #elif defined(HAVE_AIO_WRITE)
2482 return aio_write(aiocb);
2483 #else
2484 errno = ENOSYS;
2485 return -1;
2486 #endif
2489 /*******************************************************************
2490 An aio_return wrapper that will deal with 64-bit sizes.
2491 ********************************************************************/
2493 ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2495 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_RETURN64)
2496 return aio_return64(aiocb);
2497 #elif defined(HAVE_AIO_RETURN)
2498 return aio_return(aiocb);
2499 #else
2500 errno = ENOSYS;
2501 return -1;
2502 #endif
2505 /*******************************************************************
2506 An aio_cancel wrapper that will deal with 64-bit sizes.
2507 ********************************************************************/
2509 int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2511 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_CANCEL64)
2512 return aio_cancel64(fd, aiocb);
2513 #elif defined(HAVE_AIO_CANCEL)
2514 return aio_cancel(fd, aiocb);
2515 #else
2516 errno = ENOSYS;
2517 return -1;
2518 #endif
2521 /*******************************************************************
2522 An aio_error wrapper that will deal with 64-bit sizes.
2523 ********************************************************************/
2525 int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2527 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_ERROR64)
2528 return aio_error64(aiocb);
2529 #elif defined(HAVE_AIO_ERROR)
2530 return aio_error(aiocb);
2531 #else
2532 errno = ENOSYS;
2533 return -1;
2534 #endif
2537 /*******************************************************************
2538 An aio_fsync wrapper that will deal with 64-bit sizes.
2539 ********************************************************************/
2541 int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2543 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_FSYNC64)
2544 return aio_fsync64(op, aiocb);
2545 #elif defined(HAVE_AIO_FSYNC)
2546 return aio_fsync(op, aiocb);
2547 #else
2548 errno = ENOSYS;
2549 return -1;
2550 #endif
2553 /*******************************************************************
2554 An aio_fsync wrapper that will deal with 64-bit sizes.
2555 ********************************************************************/
2557 int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2559 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_SUSPEND64)
2560 return aio_suspend64(cblist, n, timeout);
2561 #elif defined(HAVE_AIO_FSYNC)
2562 return aio_suspend(cblist, n, timeout);
2563 #else
2564 errno = ENOSYS;
2565 return -1;
2566 #endif
2568 #else /* !WITH_AIO */
2570 int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2572 errno = ENOSYS;
2573 return -1;
2576 int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2578 errno = ENOSYS;
2579 return -1;
2582 ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2584 errno = ENOSYS;
2585 return -1;
2588 int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2590 errno = ENOSYS;
2591 return -1;
2594 int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2596 errno = ENOSYS;
2597 return -1;
2600 int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2602 errno = ENOSYS;
2603 return -1;
2606 int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2608 errno = ENOSYS;
2609 return -1;
2611 #endif /* WITH_AIO */
2613 int sys_getpeereid( int s, uid_t *uid)
2615 #if defined(HAVE_PEERCRED)
2616 struct ucred cred;
2617 socklen_t cred_len = sizeof(struct ucred);
2618 int ret;
2620 ret = getsockopt(s, SOL_SOCKET, SO_PEERCRED, (void *)&cred, &cred_len);
2621 if (ret != 0) {
2622 return -1;
2625 if (cred_len != sizeof(struct ucred)) {
2626 errno = EINVAL;
2627 return -1;
2630 *uid = cred.uid;
2631 return 0;
2632 #else
2633 errno = ENOSYS;
2634 return -1;
2635 #endif