source: branches/samba-3.0/source/lib/system.c@ 279

Last change on this file since 279 was 170, checked in by Herwig Bauernfeind, 16 years ago

Fix for Ticket #69 and #71

File size: 72.3 KB
Line 
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
8
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23*/
24
25#include "includes.h"
26
27#ifdef HAVE_SYS_PRCTL_H
28#include <sys/prctl.h>
29#endif
30
31/*
32 The idea is that this file will eventually have wrappers around all
33 important system calls in samba. The aims are:
34
35 - to enable easier porting by putting OS dependent stuff in here
36
37 - to allow for hooks into other "pseudo-filesystems"
38
39 - to allow easier integration of things like the japanese extensions
40
41 - to support the philosophy of Samba to expose the features of
42 the OS within the SMB model. In general whatever file/printer/variable
43 expansions/etc make sense to the OS should be acceptable to Samba.
44*/
45
46
47
48/*******************************************************************
49 A wrapper for memalign
50********************************************************************/
51
52void *sys_memalign( size_t align, size_t size )
53{
54#if defined(HAVE_POSIX_MEMALIGN)
55 void *p = NULL;
56 int ret = posix_memalign( &p, align, size );
57 if ( ret == 0 )
58 return p;
59
60 return NULL;
61#elif defined(HAVE_MEMALIGN)
62 return memalign( align, size );
63#else
64 /* On *BSD systems memaligns doesn't exist, but memory will
65 * be aligned on allocations of > pagesize. */
66#if defined(SYSCONF_SC_PAGESIZE)
67 size_t pagesize = (size_t)sysconf(_SC_PAGESIZE);
68#elif defined(HAVE_GETPAGESIZE)
69 size_t pagesize = (size_t)getpagesize();
70#else
71 size_t pagesize = (size_t)-1;
72#endif
73 if (pagesize == (size_t)-1) {
74 DEBUG(0,("memalign functionalaity not available on this platform!\n"));
75 return NULL;
76 }
77 if (size < pagesize) {
78 size = pagesize;
79 }
80 return SMB_MALLOC(size);
81#endif
82}
83
84/*******************************************************************
85 A wrapper for usleep in case we don't have one.
86********************************************************************/
87
88int sys_usleep(long usecs)
89{
90#ifndef HAVE_USLEEP
91 struct timeval tval;
92#endif
93
94 /*
95 * We need this braindamage as the glibc usleep
96 * is not SPEC1170 complient... grumble... JRA.
97 */
98
99 if(usecs < 0 || usecs > 1000000) {
100 errno = EINVAL;
101 return -1;
102 }
103
104#if HAVE_USLEEP
105 usleep(usecs);
106 return 0;
107#else /* HAVE_USLEEP */
108 /*
109 * Fake it with select...
110 */
111 tval.tv_sec = 0;
112 tval.tv_usec = usecs/1000;
113 select(0,NULL,NULL,NULL,&tval);
114 return 0;
115#endif /* HAVE_USLEEP */
116}
117/*******************************************************************
118A read wrapper that will deal with EINTR.
119********************************************************************/
120ssize_t sys_read(int fd, void *buf, size_t count)
121{
122 ssize_t ret;
123 do {
124 ret = read(fd, buf, count);
125 } while (ret == -1 && errno == EINTR);
126 return ret;
127}
128/*******************************************************************
129A write wrapper that will deal with EINTR.
130********************************************************************/
131ssize_t sys_write(int fd, const void *buf, size_t count)
132{
133 ssize_t ret;
134 do {
135 ret = write(fd, buf, count);
136 } while (ret == -1 && errno == EINTR);
137 return ret;
138}
139/*******************************************************************
140A pread wrapper that will deal with EINTR and 64-bit file offsets.
141********************************************************************/
142#if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
143ssize_t sys_pread(int fd, void *buf, size_t count, SMB_OFF_T off)
144{
145 ssize_t ret;
146 do {
147#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_PREAD64)
148 ret = pread64(fd, buf, count, off);
149#else
150 ret = pread(fd, buf, count, off);
151#endif
152 } while (ret == -1 && errno == EINTR);
153 return ret;
154}
155#endif
156/*******************************************************************
157A write wrapper that will deal with EINTR and 64-bit file offsets.
158********************************************************************/
159#if defined(HAVE_PWRITE) || defined(HAVE_PWRITE64)
160ssize_t sys_pwrite(int fd, const void *buf, size_t count, SMB_OFF_T off)
161{
162 ssize_t ret;
163 do {
164#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_PWRITE64)
165 ret = pwrite64(fd, buf, count, off);
166#else
167 ret = pwrite(fd, buf, count, off);
168#endif
169 } while (ret == -1 && errno == EINTR);
170 return ret;
171}
172#endif
173/*******************************************************************
174A send wrapper that will deal with EINTR.
175********************************************************************/
176ssize_t sys_send(int s, const void *msg, size_t len, int flags)
177{
178 ssize_t ret;
179 do {
180 ret = send(s, msg, len, flags);
181 } while (ret == -1 && errno == EINTR);
182 return ret;
183}
184/*******************************************************************
185A sendto wrapper that will deal with EINTR.
186********************************************************************/
187ssize_t sys_sendto(int s, const void *msg, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
188{
189 ssize_t ret;
190 do {
191 ret = sendto(s, msg, len, flags, to, tolen);
192 } while (ret == -1 && errno == EINTR);
193 return ret;
194}
195/*******************************************************************
196A recv wrapper that will deal with EINTR.
197********************************************************************/
198ssize_t sys_recv(int fd, void *buf, size_t count, int flags)
199{
200 ssize_t ret;
201 do {
202 ret = recv(fd, buf, count, flags);
203 } while (ret == -1 && errno == EINTR);
204 return ret;
205}
206/*******************************************************************
207A recvfrom wrapper that will deal with EINTR.
208********************************************************************/
209ssize_t sys_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
210{
211 ssize_t ret;
212 do {
213 ret = recvfrom(s, buf, len, flags, from, fromlen);
214 } while (ret == -1 && errno == EINTR);
215 return ret;
216}
217/*******************************************************************
218A fcntl wrapper that will deal with EINTR.
219********************************************************************/
220int sys_fcntl_ptr(int fd, int cmd, void *arg)
221{
222 int ret;
223 do {
224 ret = fcntl(fd, cmd, arg);
225 } while (ret == -1 && errno == EINTR);
226 return ret;
227}
228/*******************************************************************
229A fcntl wrapper that will deal with EINTR.
230********************************************************************/
231int sys_fcntl_long(int fd, int cmd, long arg)
232{
233 int ret;
234 do {
235 ret = fcntl(fd, cmd, arg);
236 } while (ret == -1 && errno == EINTR);
237 return ret;
238}
239
240/*******************************************************************
241A stat() wrapper that will deal with 64 bit filesizes.
242********************************************************************/
243
244int sys_stat(const char *fname,SMB_STRUCT_STAT *sbuf)
245{
246 int ret;
247#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
248 ret = stat64(fname, sbuf);
249#else
250 ret = stat(fname, sbuf);
251#endif
252 /* we always want directories to appear zero size */
253 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
254 return ret;
255}
256
257/*******************************************************************
258 An fstat() wrapper that will deal with 64 bit filesizes.
259********************************************************************/
260
261int sys_fstat(int fd,SMB_STRUCT_STAT *sbuf)
262{
263 int ret;
264#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FSTAT64)
265 ret = fstat64(fd, sbuf);
266#else
267 ret = fstat(fd, sbuf);
268#endif
269 /* we always want directories to appear zero size */
270 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
271 return ret;
272}
273
274/*******************************************************************
275 An lstat() wrapper that will deal with 64 bit filesizes.
276********************************************************************/
277
278int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf)
279{
280 int ret;
281#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSTAT64)
282 ret = lstat64(fname, sbuf);
283#else
284 ret = lstat(fname, sbuf);
285#endif
286 /* we always want directories to appear zero size */
287 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
288 return ret;
289}
290
291/*******************************************************************
292 An ftruncate() wrapper that will deal with 64 bit filesizes.
293********************************************************************/
294
295int sys_ftruncate(int fd, SMB_OFF_T offset)
296{
297#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FTRUNCATE64)
298 return ftruncate64(fd, offset);
299#elif defined(__OS2__)
300 return os2_ftruncate(fd, offset);
301#else
302 return ftruncate(fd, offset);
303#endif
304}
305
306/*******************************************************************
307 An lseek() wrapper that will deal with 64 bit filesizes.
308********************************************************************/
309
310SMB_OFF_T sys_lseek(int fd, SMB_OFF_T offset, int whence)
311{
312#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSEEK64)
313 return lseek64(fd, offset, whence);
314#else
315 return lseek(fd, offset, whence);
316#endif
317}
318
319/*******************************************************************
320 An fseek() wrapper that will deal with 64 bit filesizes.
321********************************************************************/
322
323int sys_fseek(FILE *fp, SMB_OFF_T offset, int whence)
324{
325#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEK64)
326 return fseek64(fp, offset, whence);
327#elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEKO64)
328 return fseeko64(fp, offset, whence);
329#else
330 return fseek(fp, offset, whence);
331#endif
332}
333
334/*******************************************************************
335 An ftell() wrapper that will deal with 64 bit filesizes.
336********************************************************************/
337
338SMB_OFF_T sys_ftell(FILE *fp)
339{
340#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELL64)
341 return (SMB_OFF_T)ftell64(fp);
342#elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELLO64)
343 return (SMB_OFF_T)ftello64(fp);
344#else
345 return (SMB_OFF_T)ftell(fp);
346#endif
347}
348
349/*******************************************************************
350 A creat() wrapper that will deal with 64 bit filesizes.
351********************************************************************/
352
353int sys_creat(const char *path, mode_t mode)
354{
355#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CREAT64)
356 return creat64(path, mode);
357#else
358 /*
359 * If creat64 isn't defined then ensure we call a potential open64.
360 * JRA.
361 */
362 return sys_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
363#endif
364}
365
366/*******************************************************************
367 An open() wrapper that will deal with 64 bit filesizes.
368********************************************************************/
369
370int sys_open(const char *path, int oflag, mode_t mode)
371{
372#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPEN64)
373 return open64(path, oflag, mode);
374#else
375 return open(path, oflag, mode);
376#endif
377}
378
379/*******************************************************************
380 An fopen() wrapper that will deal with 64 bit filesizes.
381********************************************************************/
382
383FILE *sys_fopen(const char *path, const char *type)
384{
385#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FOPEN64)
386 return fopen64(path, type);
387#else
388 return fopen(path, type);
389#endif
390}
391
392
393/*******************************************************************
394 A flock() wrapper that will perform the kernel flock.
395********************************************************************/
396
397void kernel_flock(int fd, uint32 share_mode)
398{
399#if HAVE_KERNEL_SHARE_MODES
400 int kernel_mode = 0;
401 if (share_mode == FILE_SHARE_WRITE) {
402 kernel_mode = LOCK_MAND|LOCK_WRITE;
403 } else if (share_mode == FILE_SHARE_READ) {
404 kernel_mode = LOCK_MAND|LOCK_READ;
405 } else if (share_mode == FILE_SHARE_NONE) {
406 kernel_mode = LOCK_MAND;
407 }
408 if (kernel_mode) {
409 flock(fd, kernel_mode);
410 }
411#endif
412 ;
413}
414
415
416
417/*******************************************************************
418 An opendir wrapper that will deal with 64 bit filesizes.
419********************************************************************/
420
421SMB_STRUCT_DIR *sys_opendir(const char *name)
422{
423#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPENDIR64)
424 return opendir64(name);
425#else
426 return opendir(name);
427#endif
428}
429
430/*******************************************************************
431 A readdir wrapper that will deal with 64 bit filesizes.
432********************************************************************/
433
434SMB_STRUCT_DIRENT *sys_readdir(SMB_STRUCT_DIR *dirp)
435{
436#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_READDIR64)
437 return readdir64(dirp);
438#else
439 return readdir(dirp);
440#endif
441}
442
443/*******************************************************************
444 A seekdir wrapper that will deal with 64 bit filesizes.
445********************************************************************/
446
447void sys_seekdir(SMB_STRUCT_DIR *dirp, long offset)
448{
449#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_SEEKDIR64)
450 seekdir64(dirp, offset);
451#else
452 seekdir(dirp, offset);
453#endif
454}
455
456/*******************************************************************
457 A telldir wrapper that will deal with 64 bit filesizes.
458********************************************************************/
459
460long sys_telldir(SMB_STRUCT_DIR *dirp)
461{
462#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_TELLDIR64)
463 return (long)telldir64(dirp);
464#else
465 return (long)telldir(dirp);
466#endif
467}
468
469/*******************************************************************
470 A rewinddir wrapper that will deal with 64 bit filesizes.
471********************************************************************/
472
473void sys_rewinddir(SMB_STRUCT_DIR *dirp)
474{
475#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_REWINDDIR64)
476 rewinddir64(dirp);
477#else
478 rewinddir(dirp);
479#endif
480}
481
482/*******************************************************************
483 A close wrapper that will deal with 64 bit filesizes.
484********************************************************************/
485
486int sys_closedir(SMB_STRUCT_DIR *dirp)
487{
488#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CLOSEDIR64)
489 return closedir64(dirp);
490#else
491 return closedir(dirp);
492#endif
493}
494
495/*******************************************************************
496 An mknod() wrapper that will deal with 64 bit filesizes.
497********************************************************************/
498
499int sys_mknod(const char *path, mode_t mode, SMB_DEV_T dev)
500{
501#if defined(HAVE_MKNOD) || defined(HAVE_MKNOD64)
502#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_MKNOD64) && defined(HAVE_DEV64_T)
503 return mknod64(path, mode, dev);
504#else
505 return mknod(path, mode, dev);
506#endif
507#else
508 /* No mknod system call. */
509 errno = ENOSYS;
510 return -1;
511#endif
512}
513
514/*******************************************************************
515 Wrapper for realpath.
516********************************************************************/
517
518char *sys_realpath(const char *path, char *resolved_path)
519{
520#if defined(HAVE_REALPATH)
521 return realpath(path, resolved_path);
522#else
523 /* As realpath is not a system call we can't return ENOSYS. */
524 errno = EINVAL;
525 return NULL;
526#endif
527}
528
529/*******************************************************************
530The wait() calls vary between systems
531********************************************************************/
532
533int sys_waitpid(pid_t pid,int *status,int options)
534{
535#ifdef HAVE_WAITPID
536 return waitpid(pid,status,options);
537#else /* HAVE_WAITPID */
538 return wait4(pid, status, options, NULL);
539#endif /* HAVE_WAITPID */
540}
541
542/*******************************************************************
543 System wrapper for getwd
544********************************************************************/
545
546char *sys_getwd(char *s)
547{
548 char *wd;
549#ifdef HAVE_GETCWD
550 wd = (char *)getcwd(s, sizeof (pstring));
551#else
552 wd = (char *)getwd(s);
553#endif
554 return wd;
555}
556
557/*******************************************************************
558system wrapper for symlink
559********************************************************************/
560
561int sys_symlink(const char *oldpath, const char *newpath)
562{
563#ifndef HAVE_SYMLINK
564 errno = ENOSYS;
565 return -1;
566#else
567 return symlink(oldpath, newpath);
568#endif
569}
570
571/*******************************************************************
572system wrapper for readlink
573********************************************************************/
574
575int sys_readlink(const char *path, char *buf, size_t bufsiz)
576{
577#ifndef HAVE_READLINK
578 errno = ENOSYS;
579 return -1;
580#else
581 return readlink(path, buf, bufsiz);
582#endif
583}
584
585/*******************************************************************
586system wrapper for link
587********************************************************************/
588
589int sys_link(const char *oldpath, const char *newpath)
590{
591#ifndef HAVE_LINK
592 errno = ENOSYS;
593 return -1;
594#else
595 return link(oldpath, newpath);
596#endif
597}
598
599/*******************************************************************
600chown isn't used much but OS/2 doesn't have it
601********************************************************************/
602
603int sys_chown(const char *fname,uid_t uid,gid_t gid)
604{
605#ifndef HAVE_CHOWN
606 static int done;
607 if (!done) {
608 DEBUG(1,("WARNING: no chown!\n"));
609 done=1;
610 }
611 errno = ENOSYS;
612 return -1;
613#else
614 return(chown(fname,uid,gid));
615#endif
616}
617
618/*******************************************************************
619os/2 also doesn't have chroot
620********************************************************************/
621int sys_chroot(const char *dname)
622{
623#ifndef HAVE_CHROOT
624 static int done;
625 if (!done) {
626 DEBUG(1,("WARNING: no chroot!\n"));
627 done=1;
628 }
629 errno = ENOSYS;
630 return -1;
631#else
632 return(chroot(dname));
633#endif
634}
635
636/**************************************************************************
637A wrapper for gethostbyname() that tries avoids looking up hostnames
638in the root domain, which can cause dial-on-demand links to come up for no
639apparent reason.
640****************************************************************************/
641
642struct hostent *sys_gethostbyname(const char *name)
643{
644#ifdef REDUCE_ROOT_DNS_LOOKUPS
645 char query[256], hostname[256];
646 char *domain;
647
648 /* Does this name have any dots in it? If so, make no change */
649
650 if (strchr_m(name, '.'))
651 return(gethostbyname(name));
652
653 /* Get my hostname, which should have domain name
654 attached. If not, just do the gethostname on the
655 original string.
656 */
657
658 gethostname(hostname, sizeof(hostname) - 1);
659 hostname[sizeof(hostname) - 1] = 0;
660 if ((domain = strchr_m(hostname, '.')) == NULL)
661 return(gethostbyname(name));
662
663 /* Attach domain name to query and do modified query.
664 If names too large, just do gethostname on the
665 original string.
666 */
667
668 if((strlen(name) + strlen(domain)) >= sizeof(query))
669 return(gethostbyname(name));
670
671 slprintf(query, sizeof(query)-1, "%s%s", name, domain);
672 return(gethostbyname(query));
673#else /* REDUCE_ROOT_DNS_LOOKUPS */
674 return(gethostbyname(name));
675#endif /* REDUCE_ROOT_DNS_LOOKUPS */
676}
677
678
679#if defined(HAVE_POSIX_CAPABILITIES)
680
681#ifdef HAVE_SYS_CAPABILITY_H
682
683#if defined(BROKEN_REDHAT_7_SYSTEM_HEADERS) && !defined(_I386_STATFS_H) && !defined(_PPC_STATFS_H)
684#define _I386_STATFS_H
685#define _PPC_STATFS_H
686#define BROKEN_REDHAT_7_STATFS_WORKAROUND
687#endif
688
689#include <sys/capability.h>
690
691#ifdef BROKEN_REDHAT_7_STATFS_WORKAROUND
692#undef _I386_STATFS_H
693#undef _PPC_STATFS_H
694#undef BROKEN_REDHAT_7_STATFS_WORKAROUND
695#endif
696
697#endif /* HAVE_SYS_CAPABILITY_H */
698
699/**************************************************************************
700 Try and abstract process capabilities (for systems that have them).
701****************************************************************************/
702
703/* Set the POSIX capabilities needed for the given purpose into the effective
704 * capability set of the current process. Make sure they are always removed
705 * from the inheritable set, because there is no circumstance in which our
706 * children should inherit our elevated privileges.
707 */
708static BOOL set_process_capability(enum smbd_capability capability,
709 BOOL enable)
710{
711 cap_value_t cap_vals[2] = {0};
712 int num_cap_vals = 0;
713
714 cap_t cap;
715
716#if defined(HAVE_PRCTL) && defined(PR_GET_KEEPCAPS) && defined(PR_SET_KEEPCAPS)
717 /* On Linux, make sure that any capabilities we grab are sticky
718 * across UID changes. We expect that this would allow us to keep both
719 * the effective and permitted capability sets, but as of circa 2.6.16,
720 * only the permitted set is kept. It is a bug (which we work around)
721 * that the effective set is lost, but we still require the effective
722 * set to be kept.
723 */
724 if (!prctl(PR_GET_KEEPCAPS)) {
725 prctl(PR_SET_KEEPCAPS, 1);
726 }
727#endif
728
729 cap = cap_get_proc();
730 if (cap == NULL) {
731 DEBUG(0,("set_process_capability: cap_get_proc failed: %s\n",
732 strerror(errno)));
733 return False;
734 }
735
736 switch (capability) {
737 case KERNEL_OPLOCK_CAPABILITY:
738#ifdef CAP_NETWORK_MGT
739 /* IRIX has CAP_NETWORK_MGT for oplocks. */
740 cap_vals[num_cap_vals++] = CAP_NETWORK_MGT;
741#endif
742 break;
743 case DMAPI_ACCESS_CAPABILITY:
744#ifdef CAP_DEVICE_MGT
745 /* IRIX has CAP_DEVICE_MGT for DMAPI access. */
746 cap_vals[num_cap_vals++] = CAP_DEVICE_MGT;
747#elif CAP_MKNOD
748 /* Linux has CAP_MKNOD for DMAPI access. */
749 cap_vals[num_cap_vals++] = CAP_MKNOD;
750#endif
751 break;
752 case LEASE_CAPABILITY:
753#ifdef CAP_LEASE
754 cap_vals[num_cap_vals++] = CAP_LEASE;
755#endif
756 break;
757 }
758
759 SMB_ASSERT(num_cap_vals <= ARRAY_SIZE(cap_vals));
760
761 if (num_cap_vals == 0) {
762 cap_free(cap);
763 return True;
764 }
765
766 cap_set_flag(cap, CAP_EFFECTIVE, num_cap_vals, cap_vals,
767 enable ? CAP_SET : CAP_CLEAR);
768
769 /* We never want to pass capabilities down to our children, so make
770 * sure they are not inherited.
771 */
772 cap_set_flag(cap, CAP_INHERITABLE, num_cap_vals, cap_vals, CAP_CLEAR);
773
774 if (cap_set_proc(cap) == -1) {
775 DEBUG(0, ("set_process_capability: cap_set_proc failed: %s\n",
776 strerror(errno)));
777 cap_free(cap);
778 return False;
779 }
780
781 cap_free(cap);
782 return True;
783}
784
785#endif /* HAVE_POSIX_CAPABILITIES */
786
787/****************************************************************************
788 Gain the oplock capability from the kernel if possible.
789****************************************************************************/
790
791void set_effective_capability(enum smbd_capability capability)
792{
793#if defined(HAVE_POSIX_CAPABILITIES)
794 set_process_capability(capability, True);
795#endif /* HAVE_POSIX_CAPABILITIES */
796}
797
798void drop_effective_capability(enum smbd_capability capability)
799{
800#if defined(HAVE_POSIX_CAPABILITIES)
801 set_process_capability(capability, False);
802#endif /* HAVE_POSIX_CAPABILITIES */
803}
804
805/**************************************************************************
806 Wrapper for random().
807****************************************************************************/
808
809long sys_random(void)
810{
811#if defined(HAVE_RANDOM)
812 return (long)random();
813#elif defined(HAVE_RAND)
814 return (long)rand();
815#else
816 DEBUG(0,("Error - no random function available !\n"));
817 exit(1);
818#endif
819}
820
821/**************************************************************************
822 Wrapper for srandom().
823****************************************************************************/
824
825void sys_srandom(unsigned int seed)
826{
827#if defined(HAVE_SRANDOM)
828 srandom(seed);
829#elif defined(HAVE_SRAND)
830 srand(seed);
831#else
832 DEBUG(0,("Error - no srandom function available !\n"));
833 exit(1);
834#endif
835}
836
837/**************************************************************************
838 Returns equivalent to NGROUPS_MAX - using sysconf if needed.
839****************************************************************************/
840
841int groups_max(void)
842{
843#if defined(SYSCONF_SC_NGROUPS_MAX)
844 int ret = sysconf(_SC_NGROUPS_MAX);
845 return (ret == -1) ? NGROUPS_MAX : ret;
846#else
847 return NGROUPS_MAX;
848#endif
849}
850
851/**************************************************************************
852 Wrapper for getgroups. Deals with broken (int) case.
853****************************************************************************/
854
855int sys_getgroups(int setlen, gid_t *gidset)
856{
857#if !defined(HAVE_BROKEN_GETGROUPS)
858 return getgroups(setlen, gidset);
859#else
860
861 GID_T gid;
862 GID_T *group_list;
863 int i, ngroups;
864
865 if(setlen == 0) {
866 return getgroups(setlen, &gid);
867 }
868
869 /*
870 * Broken case. We need to allocate a
871 * GID_T array of size setlen.
872 */
873
874 if(setlen < 0) {
875 errno = EINVAL;
876 return -1;
877 }
878
879 if (setlen == 0)
880 setlen = groups_max();
881
882 if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
883 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
884 return -1;
885 }
886
887 if((ngroups = getgroups(setlen, group_list)) < 0) {
888 int saved_errno = errno;
889 SAFE_FREE(group_list);
890 errno = saved_errno;
891 return -1;
892 }
893
894 for(i = 0; i < ngroups; i++)
895 gidset[i] = (gid_t)group_list[i];
896
897 SAFE_FREE(group_list);
898 return ngroups;
899#endif /* HAVE_BROKEN_GETGROUPS */
900}
901
902
903/**************************************************************************
904 Wrapper for setgroups. Deals with broken (int) case. Automatically used
905 if we have broken getgroups.
906****************************************************************************/
907
908int sys_setgroups(int setlen, gid_t *gidset)
909{
910#ifdef __OS2__x
911 return 0;
912#endif
913#if !defined(HAVE_SETGROUPS)
914 errno = ENOSYS;
915 return -1;
916#endif /* HAVE_SETGROUPS */
917
918#if !defined(HAVE_BROKEN_GETGROUPS)
919 return setgroups(setlen, gidset);
920#else
921
922 GID_T *group_list;
923 int i ;
924
925 if (setlen == 0)
926 return 0 ;
927
928 if (setlen < 0 || setlen > groups_max()) {
929 errno = EINVAL;
930 return -1;
931 }
932
933 /*
934 * Broken case. We need to allocate a
935 * GID_T array of size setlen.
936 */
937
938 if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
939 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
940 return -1;
941 }
942
943 for(i = 0; i < setlen; i++)
944 group_list[i] = (GID_T) gidset[i];
945
946 if(setgroups(setlen, group_list) != 0) {
947 int saved_errno = errno;
948 SAFE_FREE(group_list);
949 errno = saved_errno;
950 return -1;
951 }
952
953 SAFE_FREE(group_list);
954 return 0 ;
955#endif /* HAVE_BROKEN_GETGROUPS */
956}
957
958/**************************************************************************
959 Wrappers for setpwent(), getpwent() and endpwent()
960****************************************************************************/
961
962void sys_setpwent(void)
963{
964 setpwent();
965}
966
967struct passwd *sys_getpwent(void)
968{
969 return getpwent();
970}
971
972void sys_endpwent(void)
973{
974 endpwent();
975}
976
977/**************************************************************************
978 Wrappers for getpwnam(), getpwuid(), getgrnam(), getgrgid()
979****************************************************************************/
980
981#ifdef ENABLE_BUILD_FARM_HACKS
982
983/*
984 * In the build farm we want to be able to join machines to the domain. As we
985 * don't have root access, we need to bypass direct access to /etc/passwd
986 * after a user has been created via samr. Fake those users.
987 */
988
989static struct passwd *fake_pwd;
990static int num_fake_pwd;
991
992struct passwd *sys_getpwnam(const char *name)
993{
994 int i;
995
996 for (i=0; i<num_fake_pwd; i++) {
997 if (strcmp(fake_pwd[i].pw_name, name) == 0) {
998 DEBUG(10, ("Returning fake user %s\n", name));
999 return &fake_pwd[i];
1000 }
1001 }
1002
1003 return getpwnam(name);
1004}
1005
1006struct passwd *sys_getpwuid(uid_t uid)
1007{
1008 int i;
1009
1010 for (i=0; i<num_fake_pwd; i++) {
1011 if (fake_pwd[i].pw_uid == uid) {
1012 DEBUG(10, ("Returning fake user %s\n",
1013 fake_pwd[i].pw_name));
1014 return &fake_pwd[i];
1015 }
1016 }
1017
1018 return getpwuid(uid);
1019}
1020
1021void faked_create_user(const char *name)
1022{
1023 int i;
1024 uid_t uid;
1025 struct passwd new_pwd;
1026
1027 for (i=0; i<10; i++) {
1028 generate_random_buffer((unsigned char *)&uid,
1029 sizeof(uid));
1030 if (getpwuid(uid) == NULL) {
1031 break;
1032 }
1033 }
1034
1035 if (i==10) {
1036 /* Weird. No free uid found... */
1037 return;
1038 }
1039
1040 new_pwd.pw_name = SMB_STRDUP(name);
1041 new_pwd.pw_passwd = SMB_STRDUP("x");
1042 new_pwd.pw_uid = uid;
1043 new_pwd.pw_gid = 100;
1044 new_pwd.pw_gecos = SMB_STRDUP("faked user");
1045 new_pwd.pw_dir = SMB_STRDUP("/nodir");
1046 new_pwd.pw_shell = SMB_STRDUP("/bin/false");
1047
1048 ADD_TO_ARRAY(NULL, struct passwd, new_pwd, &fake_pwd,
1049 &num_fake_pwd);
1050
1051 DEBUG(10, ("Added fake user %s, have %d fake users\n",
1052 name, num_fake_pwd));
1053}
1054
1055#else
1056
1057struct passwd *sys_getpwnam(const char *name)
1058{
1059 return getpwnam(name);
1060}
1061
1062struct passwd *sys_getpwuid(uid_t uid)
1063{
1064 return getpwuid(uid);
1065}
1066
1067#endif
1068
1069struct group *sys_getgrnam(const char *name)
1070{
1071 return getgrnam(name);
1072}
1073
1074struct group *sys_getgrgid(gid_t gid)
1075{
1076 return getgrgid(gid);
1077}
1078
1079#if 0 /* NOT CURRENTLY USED - JRA */
1080/**************************************************************************
1081 The following are the UNICODE versions of *all* system interface functions
1082 called within Samba. Ok, ok, the exceptions are the gethostbyXX calls,
1083 which currently are left as ascii as they are not used other than in name
1084 resolution.
1085****************************************************************************/
1086
1087/**************************************************************************
1088 Wide stat. Just narrow and call sys_xxx.
1089****************************************************************************/
1090
1091int wsys_stat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
1092{
1093 pstring fname;
1094 return sys_stat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
1095}
1096
1097/**************************************************************************
1098 Wide lstat. Just narrow and call sys_xxx.
1099****************************************************************************/
1100
1101int wsys_lstat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
1102{
1103 pstring fname;
1104 return sys_lstat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
1105}
1106
1107/**************************************************************************
1108 Wide creat. Just narrow and call sys_xxx.
1109****************************************************************************/
1110
1111int wsys_creat(const smb_ucs2_t *wfname, mode_t mode)
1112{
1113 pstring fname;
1114 return sys_creat(unicode_to_unix(fname,wfname,sizeof(fname)), mode);
1115}
1116
1117/**************************************************************************
1118 Wide open. Just narrow and call sys_xxx.
1119****************************************************************************/
1120
1121int wsys_open(const smb_ucs2_t *wfname, int oflag, mode_t mode)
1122{
1123 pstring fname;
1124 return sys_open(unicode_to_unix(fname,wfname,sizeof(fname)), oflag, mode);
1125}
1126
1127/**************************************************************************
1128 Wide fopen. Just narrow and call sys_xxx.
1129****************************************************************************/
1130
1131FILE *wsys_fopen(const smb_ucs2_t *wfname, const char *type)
1132{
1133 pstring fname;
1134 return sys_fopen(unicode_to_unix(fname,wfname,sizeof(fname)), type);
1135}
1136
1137/**************************************************************************
1138 Wide opendir. Just narrow and call sys_xxx.
1139****************************************************************************/
1140
1141SMB_STRUCT_DIR *wsys_opendir(const smb_ucs2_t *wfname)
1142{
1143 pstring fname;
1144 return opendir(unicode_to_unix(fname,wfname,sizeof(fname)));
1145}
1146
1147/**************************************************************************
1148 Wide readdir. Return a structure pointer containing a wide filename.
1149****************************************************************************/
1150
1151SMB_STRUCT_WDIRENT *wsys_readdir(SMB_STRUCT_DIR *dirp)
1152{
1153 static SMB_STRUCT_WDIRENT retval;
1154 SMB_STRUCT_DIRENT *dirval = sys_readdir(dirp);
1155
1156 if(!dirval)
1157 return NULL;
1158
1159 /*
1160 * The only POSIX defined member of this struct is d_name.
1161 */
1162
1163 unix_to_unicode(retval.d_name,dirval->d_name,sizeof(retval.d_name));
1164
1165 return &retval;
1166}
1167
1168/**************************************************************************
1169 Wide getwd. Call sys_xxx and widen. Assumes s points to a wpstring.
1170****************************************************************************/
1171
1172smb_ucs2_t *wsys_getwd(smb_ucs2_t *s)
1173{
1174 pstring fname;
1175 char *p = sys_getwd(fname);
1176
1177 if(!p)
1178 return NULL;
1179
1180 return unix_to_unicode(s, p, sizeof(wpstring));
1181}
1182
1183/**************************************************************************
1184 Wide chown. Just narrow and call sys_xxx.
1185****************************************************************************/
1186
1187int wsys_chown(const smb_ucs2_t *wfname, uid_t uid, gid_t gid)
1188{
1189 pstring fname;
1190 return chown(unicode_to_unix(fname,wfname,sizeof(fname)), uid, gid);
1191}
1192
1193/**************************************************************************
1194 Wide chroot. Just narrow and call sys_xxx.
1195****************************************************************************/
1196
1197int wsys_chroot(const smb_ucs2_t *wfname)
1198{
1199 pstring fname;
1200 return chroot(unicode_to_unix(fname,wfname,sizeof(fname)));
1201}
1202
1203/**************************************************************************
1204 Wide getpwnam. Return a structure pointer containing wide names.
1205****************************************************************************/
1206
1207SMB_STRUCT_WPASSWD *wsys_getpwnam(const smb_ucs2_t *wname)
1208{
1209 static SMB_STRUCT_WPASSWD retval;
1210 fstring name;
1211 struct passwd *pwret = sys_getpwnam(unicode_to_unix(name,wname,sizeof(name)));
1212
1213 if(!pwret)
1214 return NULL;
1215
1216 unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
1217 retval.pw_passwd = pwret->pw_passwd;
1218 retval.pw_uid = pwret->pw_uid;
1219 retval.pw_gid = pwret->pw_gid;
1220 unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
1221 unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
1222 unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
1223
1224 return &retval;
1225}
1226
1227/**************************************************************************
1228 Wide getpwuid. Return a structure pointer containing wide names.
1229****************************************************************************/
1230
1231SMB_STRUCT_WPASSWD *wsys_getpwuid(uid_t uid)
1232{
1233 static SMB_STRUCT_WPASSWD retval;
1234 struct passwd *pwret = sys_getpwuid(uid);
1235
1236 if(!pwret)
1237 return NULL;
1238
1239 unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
1240 retval.pw_passwd = pwret->pw_passwd;
1241 retval.pw_uid = pwret->pw_uid;
1242 retval.pw_gid = pwret->pw_gid;
1243 unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
1244 unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
1245 unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
1246
1247 return &retval;
1248}
1249#endif /* NOT CURRENTLY USED - JRA */
1250
1251/**************************************************************************
1252 Extract a command into an arg list. Uses a static pstring for storage.
1253 Caller frees returned arg list (which contains pointers into the static pstring).
1254****************************************************************************/
1255
1256static char **extract_args(const char *command)
1257{
1258 static pstring trunc_cmd;
1259 char *ptr;
1260 int argcl;
1261 char **argl = NULL;
1262 int i;
1263
1264 pstrcpy(trunc_cmd, command);
1265
1266 if(!(ptr = strtok(trunc_cmd, " \t"))) {
1267 errno = EINVAL;
1268 return NULL;
1269 }
1270
1271 /*
1272 * Count the args.
1273 */
1274
1275 for( argcl = 1; ptr; ptr = strtok(NULL, " \t"))
1276 argcl++;
1277
1278 if((argl = (char **)SMB_MALLOC((argcl + 1) * sizeof(char *))) == NULL)
1279 return NULL;
1280
1281 /*
1282 * Now do the extraction.
1283 */
1284
1285 pstrcpy(trunc_cmd, command);
1286
1287 ptr = strtok(trunc_cmd, " \t");
1288 i = 0;
1289 argl[i++] = ptr;
1290
1291 while((ptr = strtok(NULL, " \t")) != NULL)
1292 argl[i++] = ptr;
1293
1294 argl[i++] = NULL;
1295 return argl;
1296}
1297
1298/**************************************************************************
1299 Wrapper for fork. Ensures that mypid is reset. Used so we can write
1300 a sys_getpid() that only does a system call *once*.
1301****************************************************************************/
1302
1303static pid_t mypid = (pid_t)-1;
1304
1305pid_t sys_fork(void)
1306{
1307 pid_t forkret = fork();
1308
1309 if (forkret == (pid_t)0) /* Child - reset mypid so sys_getpid does a system call. */
1310 mypid = (pid_t) -1;
1311
1312 return forkret;
1313}
1314
1315/**************************************************************************
1316 Wrapper for getpid. Ensures we only do a system call *once*.
1317****************************************************************************/
1318
1319pid_t sys_getpid(void)
1320{
1321 if (mypid == (pid_t)-1)
1322 mypid = getpid();
1323
1324 return mypid;
1325}
1326
1327/**************************************************************************
1328 Wrapper for popen. Safer as it doesn't search a path.
1329 Modified from the glibc sources.
1330 modified by tridge to return a file descriptor. We must kick our FILE* habit
1331****************************************************************************/
1332
1333typedef struct _popen_list
1334{
1335 int fd;
1336 pid_t child_pid;
1337 struct _popen_list *next;
1338} popen_list;
1339
1340static popen_list *popen_chain;
1341
1342int sys_popen(const char *command)
1343{
1344 int parent_end, child_end;
1345 int pipe_fds[2];
1346 popen_list *entry = NULL;
1347 char **argl = NULL;
1348
1349 if (pipe(pipe_fds) < 0)
1350 return -1;
1351
1352 parent_end = pipe_fds[0];
1353 child_end = pipe_fds[1];
1354
1355 if (!*command) {
1356 errno = EINVAL;
1357 goto err_exit;
1358 }
1359
1360 if((entry = SMB_MALLOC_P(popen_list)) == NULL)
1361 goto err_exit;
1362
1363 ZERO_STRUCTP(entry);
1364
1365 /*
1366 * Extract the command and args into a NULL terminated array.
1367 */
1368
1369 if(!(argl = extract_args(command)))
1370 goto err_exit;
1371
1372 entry->child_pid = sys_fork();
1373
1374 if (entry->child_pid == -1) {
1375 goto err_exit;
1376 }
1377
1378 if (entry->child_pid == 0) {
1379
1380 /*
1381 * Child !
1382 */
1383
1384 int child_std_end = STDOUT_FILENO;
1385 popen_list *p;
1386
1387 close(parent_end);
1388 if (child_end != child_std_end) {
1389 dup2 (child_end, child_std_end);
1390 close (child_end);
1391 }
1392
1393 /*
1394 * POSIX.2: "popen() shall ensure that any streams from previous
1395 * popen() calls that remain open in the parent process are closed
1396 * in the new child process."
1397 */
1398
1399 for (p = popen_chain; p; p = p->next)
1400 close(p->fd);
1401
1402 execv(argl[0], argl);
1403 _exit (127);
1404 }
1405
1406 /*
1407 * Parent.
1408 */
1409
1410 close (child_end);
1411 SAFE_FREE(argl);
1412
1413 /* Link into popen_chain. */
1414 entry->next = popen_chain;
1415 popen_chain = entry;
1416 entry->fd = parent_end;
1417
1418 return entry->fd;
1419
1420err_exit:
1421
1422 SAFE_FREE(entry);
1423 SAFE_FREE(argl);
1424 close(pipe_fds[0]);
1425 close(pipe_fds[1]);
1426 return -1;
1427}
1428
1429/**************************************************************************
1430 Wrapper for pclose. Modified from the glibc sources.
1431****************************************************************************/
1432
1433int sys_pclose(int fd)
1434{
1435 int wstatus;
1436 popen_list **ptr = &popen_chain;
1437 popen_list *entry = NULL;
1438 pid_t wait_pid;
1439 int status = -1;
1440
1441 /* Unlink from popen_chain. */
1442 for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
1443 if ((*ptr)->fd == fd) {
1444 entry = *ptr;
1445 *ptr = (*ptr)->next;
1446 status = 0;
1447 break;
1448 }
1449 }
1450
1451 if (status < 0 || close(entry->fd) < 0)
1452 return -1;
1453
1454 /*
1455 * As Samba is catching and eating child process
1456 * exits we don't really care about the child exit
1457 * code, a -1 with errno = ECHILD will do fine for us.
1458 */
1459
1460 do {
1461 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
1462 } while (wait_pid == -1 && errno == EINTR);
1463
1464 SAFE_FREE(entry);
1465
1466 if (wait_pid == -1)
1467 return -1;
1468 return wstatus;
1469}
1470
1471/**************************************************************************
1472 Wrappers for dlopen, dlsym, dlclose.
1473****************************************************************************/
1474
1475void *sys_dlopen(const char *name, int flags)
1476{
1477#if defined(HAVE_DLOPEN)
1478 return dlopen(name, flags);
1479#else
1480 return NULL;
1481#endif
1482}
1483
1484void *sys_dlsym(void *handle, const char *symbol)
1485{
1486#if defined(HAVE_DLSYM)
1487 return dlsym(handle, symbol);
1488#else
1489 return NULL;
1490#endif
1491}
1492
1493int sys_dlclose (void *handle)
1494{
1495#if defined(HAVE_DLCLOSE)
1496 return dlclose(handle);
1497#else
1498 return 0;
1499#endif
1500}
1501
1502const char *sys_dlerror(void)
1503{
1504#if defined(HAVE_DLERROR)
1505 return dlerror();
1506#else
1507 return NULL;
1508#endif
1509}
1510
1511int sys_dup2(int oldfd, int newfd)
1512{
1513#if defined(HAVE_DUP2)
1514 return dup2(oldfd, newfd);
1515#else
1516 errno = ENOSYS;
1517 return -1;
1518#endif
1519}
1520
1521/**************************************************************************
1522 Wrapper for Admin Logs.
1523****************************************************************************/
1524
1525 void sys_adminlog(int priority, const char *format_str, ...)
1526{
1527 va_list ap;
1528 int ret;
1529 char *msgbuf = NULL;
1530
1531 va_start( ap, format_str );
1532 ret = vasprintf( &msgbuf, format_str, ap );
1533 va_end( ap );
1534
1535 if (ret == -1)
1536 return;
1537
1538#if defined(HAVE_SYSLOG)
1539 syslog( priority, "%s", msgbuf );
1540#else
1541 DEBUG(0,("%s", msgbuf ));
1542#endif
1543 SAFE_FREE(msgbuf);
1544}
1545
1546/******** Solaris EA helper function prototypes ********/
1547#ifdef HAVE_ATTROPEN
1548#define SOLARIS_ATTRMODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP
1549static int solaris_write_xattr(int attrfd, const char *value, size_t size);
1550static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size);
1551static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size);
1552static int solaris_unlinkat(int attrdirfd, const char *name);
1553static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode);
1554static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode);
1555#endif
1556
1557/**************************************************************************
1558 Wrappers for extented attribute calls. Based on the Linux package with
1559 support for IRIX and (Net|Free)BSD also. Expand as other systems have them.
1560****************************************************************************/
1561
1562ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t size)
1563{
1564#if defined(HAVE_GETXATTR)
1565#ifndef XATTR_ADD_OPT
1566 return getxattr(path, name, value, size);
1567#else
1568 int options = 0;
1569 return getxattr(path, name, value, size, 0, options);
1570#endif
1571#elif defined(HAVE_GETEA)
1572 return getea(path, name, value, size);
1573#elif defined(HAVE_EXTATTR_GET_FILE)
1574 char *s;
1575 ssize_t retval;
1576 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1577 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1578 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1579 /*
1580 * The BSD implementation has a nasty habit of silently truncating
1581 * the returned value to the size of the buffer, so we have to check
1582 * that the buffer is large enough to fit the returned value.
1583 */
1584 if((retval=extattr_get_file(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1585 if(retval > size) {
1586 errno = ERANGE;
1587 return -1;
1588 }
1589 if((retval=extattr_get_file(path, attrnamespace, attrname, value, size)) >= 0)
1590 return retval;
1591 }
1592
1593 DEBUG(10,("sys_getxattr: extattr_get_file() failed with: %s\n", strerror(errno)));
1594 return -1;
1595#elif defined(HAVE_ATTR_GET)
1596 int retval, flags = 0;
1597 int valuelength = (int)size;
1598 char *attrname = strchr(name,'.') + 1;
1599
1600 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1601
1602 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1603
1604 return retval ? retval : valuelength;
1605#elif defined(HAVE_ATTROPEN)
1606 ssize_t ret = -1;
1607 int attrfd = solaris_attropen(path, name, O_RDONLY, 0);
1608 if (attrfd >= 0) {
1609 ret = solaris_read_xattr(attrfd, value, size);
1610 close(attrfd);
1611 }
1612 return ret;
1613#elif defined(__OS2__)
1614 return unigetxattr(path, 0, name, value, size);
1615#else
1616 errno = ENOSYS;
1617 return -1;
1618#endif
1619}
1620
1621ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t size)
1622{
1623#if defined(HAVE_LGETXATTR)
1624 return lgetxattr(path, name, value, size);
1625#elif defined(HAVE_GETXATTR) && defined(XATTR_ADD_OPT)
1626 int options = XATTR_NOFOLLOW;
1627 return getxattr(path, name, value, size, 0, options);
1628#elif defined(HAVE_LGETEA)
1629 return lgetea(path, name, value, size);
1630#elif defined(HAVE_EXTATTR_GET_LINK)
1631 char *s;
1632 ssize_t retval;
1633 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1634 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1635 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1636
1637 if((retval=extattr_get_link(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1638 if(retval > size) {
1639 errno = ERANGE;
1640 return -1;
1641 }
1642 if((retval=extattr_get_link(path, attrnamespace, attrname, value, size)) >= 0)
1643 return retval;
1644 }
1645
1646 DEBUG(10,("sys_lgetxattr: extattr_get_link() failed with: %s\n", strerror(errno)));
1647 return -1;
1648#elif defined(HAVE_ATTR_GET)
1649 int retval, flags = ATTR_DONTFOLLOW;
1650 int valuelength = (int)size;
1651 char *attrname = strchr(name,'.') + 1;
1652
1653 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1654
1655 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1656
1657 return retval ? retval : valuelength;
1658#elif defined(HAVE_ATTROPEN)
1659 ssize_t ret = -1;
1660 int attrfd = solaris_attropen(path, name, O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1661 if (attrfd >= 0) {
1662 ret = solaris_read_xattr(attrfd, value, size);
1663 close(attrfd);
1664 }
1665 return ret;
1666#elif defined(__OS2__)
1667 return unigetxattr(path, 0, name, value, size);
1668#else
1669 errno = ENOSYS;
1670 return -1;
1671#endif
1672}
1673
1674ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size)
1675{
1676#if defined(HAVE_FGETXATTR)
1677#ifndef XATTR_ADD_OPT
1678 return fgetxattr(filedes, name, value, size);
1679#else
1680 int options = 0;
1681 return fgetxattr(filedes, name, value, size, 0, options);
1682#endif
1683#elif defined(HAVE_FGETEA)
1684 return fgetea(filedes, name, value, size);
1685#elif defined(HAVE_EXTATTR_GET_FD)
1686 char *s;
1687 ssize_t retval;
1688 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1689 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1690 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1691
1692 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0)) >= 0) {
1693 if(retval > size) {
1694 errno = ERANGE;
1695 return -1;
1696 }
1697 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, value, size)) >= 0)
1698 return retval;
1699 }
1700
1701 DEBUG(10,("sys_fgetxattr: extattr_get_fd() failed with: %s\n", strerror(errno)));
1702 return -1;
1703#elif defined(HAVE_ATTR_GETF)
1704 int retval, flags = 0;
1705 int valuelength = (int)size;
1706 char *attrname = strchr(name,'.') + 1;
1707
1708 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1709
1710 retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags);
1711
1712 return retval ? retval : valuelength;
1713 return retval ? retval : valuelength;
1714#elif defined(HAVE_ATTROPEN)
1715 ssize_t ret = -1;
1716 int attrfd = solaris_openat(filedes, name, O_RDONLY|O_XATTR, 0);
1717 if (attrfd >= 0) {
1718 ret = solaris_read_xattr(attrfd, value, size);
1719 close(attrfd);
1720 }
1721 return ret;
1722#elif defined(__OS2__)
1723 return unigetxattr(0, filedes, name, value, size);
1724#else
1725 errno = ENOSYS;
1726 return -1;
1727#endif
1728}
1729
1730#if defined(HAVE_EXTATTR_LIST_FILE)
1731
1732#define EXTATTR_PREFIX(s) (s), (sizeof((s))-1)
1733
1734static struct {
1735 int space;
1736 const char *name;
1737 size_t len;
1738}
1739extattr[] = {
1740 { EXTATTR_NAMESPACE_SYSTEM, EXTATTR_PREFIX("system.") },
1741 { EXTATTR_NAMESPACE_USER, EXTATTR_PREFIX("user.") },
1742};
1743
1744typedef union {
1745 const char *path;
1746 int filedes;
1747} extattr_arg;
1748
1749static ssize_t bsd_attr_list (int type, extattr_arg arg, char *list, size_t size)
1750{
1751 ssize_t list_size, total_size = 0;
1752 int i, t, len;
1753 char *buf;
1754 /* Iterate through extattr(2) namespaces */
1755 for(t = 0; t < (sizeof(extattr)/sizeof(extattr[0])); t++) {
1756 switch(type) {
1757#if defined(HAVE_EXTATTR_LIST_FILE)
1758 case 0:
1759 list_size = extattr_list_file(arg.path, extattr[t].space, list, size);
1760 break;
1761#endif
1762#if defined(HAVE_EXTATTR_LIST_LINK)
1763 case 1:
1764 list_size = extattr_list_link(arg.path, extattr[t].space, list, size);
1765 break;
1766#endif
1767#if defined(HAVE_EXTATTR_LIST_FD)
1768 case 2:
1769 list_size = extattr_list_fd(arg.filedes, extattr[t].space, list, size);
1770 break;
1771#endif
1772 default:
1773 errno = ENOSYS;
1774 return -1;
1775 }
1776 /* Some error happend. Errno should be set by the previous call */
1777 if(list_size < 0)
1778 return -1;
1779 /* No attributes */
1780 if(list_size == 0)
1781 continue;
1782 /* XXX: Call with an empty buffer may be used to calculate
1783 necessary buffer size. Unfortunately, we can't say, how
1784 many attributes were returned, so here is the potential
1785 problem with the emulation.
1786 */
1787 if(list == NULL) {
1788 /* Take the worse case of one char attribute names -
1789 two bytes per name plus one more for sanity.
1790 */
1791 total_size += list_size + (list_size/2 + 1)*extattr[t].len;
1792 continue;
1793 }
1794 /* Count necessary offset to fit namespace prefixes */
1795 len = 0;
1796 for(i = 0; i < list_size; i += list[i] + 1)
1797 len += extattr[t].len;
1798
1799 total_size += list_size + len;
1800 /* Buffer is too small to fit the results */
1801 if(total_size > size) {
1802 errno = ERANGE;
1803 return -1;
1804 }
1805 /* Shift results back, so we can prepend prefixes */
1806 buf = memmove(list + len, list, list_size);
1807
1808 for(i = 0; i < list_size; i += len + 1) {
1809 len = buf[i];
1810 strncpy(list, extattr[t].name, extattr[t].len + 1);
1811 list += extattr[t].len;
1812 strncpy(list, buf + i + 1, len);
1813 list[len] = '\0';
1814 list += len + 1;
1815 }
1816 size -= total_size;
1817 }
1818 return total_size;
1819}
1820
1821#endif
1822
1823#if defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1824static char attr_buffer[ATTR_MAX_VALUELEN];
1825
1826static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags)
1827{
1828 int retval = 0, index;
1829 attrlist_cursor_t *cursor = 0;
1830 int total_size = 0;
1831 attrlist_t * al = (attrlist_t *)attr_buffer;
1832 attrlist_ent_t *ae;
1833 size_t ent_size, left = size;
1834 char *bp = list;
1835
1836 while (True) {
1837 if (filedes)
1838 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1839 else
1840 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1841 if (retval) break;
1842 for (index = 0; index < al->al_count; index++) {
1843 ae = ATTR_ENTRY(attr_buffer, index);
1844 ent_size = strlen(ae->a_name) + sizeof("user.");
1845 if (left >= ent_size) {
1846 strncpy(bp, "user.", sizeof("user."));
1847 strncat(bp, ae->a_name, ent_size - sizeof("user."));
1848 bp += ent_size;
1849 left -= ent_size;
1850 } else if (size) {
1851 errno = ERANGE;
1852 retval = -1;
1853 break;
1854 }
1855 total_size += ent_size;
1856 }
1857 if (al->al_more == 0) break;
1858 }
1859 if (retval == 0) {
1860 flags |= ATTR_ROOT;
1861 cursor = 0;
1862 while (True) {
1863 if (filedes)
1864 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1865 else
1866 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1867 if (retval) break;
1868 for (index = 0; index < al->al_count; index++) {
1869 ae = ATTR_ENTRY(attr_buffer, index);
1870 ent_size = strlen(ae->a_name) + sizeof("system.");
1871 if (left >= ent_size) {
1872 strncpy(bp, "system.", sizeof("system."));
1873 strncat(bp, ae->a_name, ent_size - sizeof("system."));
1874 bp += ent_size;
1875 left -= ent_size;
1876 } else if (size) {
1877 errno = ERANGE;
1878 retval = -1;
1879 break;
1880 }
1881 total_size += ent_size;
1882 }
1883 if (al->al_more == 0) break;
1884 }
1885 }
1886 return (ssize_t)(retval ? retval : total_size);
1887}
1888
1889#endif
1890
1891ssize_t sys_listxattr (const char *path, char *list, size_t size)
1892{
1893#if defined(HAVE_LISTXATTR)
1894#ifndef XATTR_ADD_OPT
1895 return listxattr(path, list, size);
1896#else
1897 int options = 0;
1898 return listxattr(path, list, size, options);
1899#endif
1900#elif defined(HAVE_LISTEA)
1901 return listea(path, list, size);
1902#elif defined(HAVE_EXTATTR_LIST_FILE)
1903 extattr_arg arg;
1904 arg.path = path;
1905 return bsd_attr_list(0, arg, list, size);
1906#elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1907 return irix_attr_list(path, 0, list, size, 0);
1908#elif defined(HAVE_ATTROPEN)
1909 ssize_t ret = -1;
1910 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
1911 if (attrdirfd >= 0) {
1912 ret = solaris_list_xattr(attrdirfd, list, size);
1913 close(attrdirfd);
1914 }
1915 return ret;
1916#elif defined(__OS2__)
1917 return unilistxattr(path, 0, list, size);
1918#else
1919 errno = ENOSYS;
1920 return -1;
1921#endif
1922}
1923
1924ssize_t sys_llistxattr (const char *path, char *list, size_t size)
1925{
1926#if defined(HAVE_LLISTXATTR)
1927 return llistxattr(path, list, size);
1928#elif defined(HAVE_LISTXATTR) && defined(XATTR_ADD_OPT)
1929 int options = XATTR_NOFOLLOW;
1930 return listxattr(path, list, size, options);
1931#elif defined(HAVE_LLISTEA)
1932 return llistea(path, list, size);
1933#elif defined(HAVE_EXTATTR_LIST_LINK)
1934 extattr_arg arg;
1935 arg.path = path;
1936 return bsd_attr_list(1, arg, list, size);
1937#elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1938 return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW);
1939#elif defined(HAVE_ATTROPEN)
1940 ssize_t ret = -1;
1941 int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1942 if (attrdirfd >= 0) {
1943 ret = solaris_list_xattr(attrdirfd, list, size);
1944 close(attrdirfd);
1945 }
1946 return ret;
1947#elif defined(__OS2__)
1948 return unilistxattr(path, 0, list, size);
1949#else
1950 errno = ENOSYS;
1951 return -1;
1952#endif
1953}
1954
1955ssize_t sys_flistxattr (int filedes, char *list, size_t size)
1956{
1957#if defined(HAVE_FLISTXATTR)
1958#ifndef XATTR_ADD_OPT
1959 return flistxattr(filedes, list, size);
1960#else
1961 int options = 0;
1962 return flistxattr(filedes, list, size, options);
1963#endif
1964#elif defined(HAVE_FLISTEA)
1965 return flistea(filedes, list, size);
1966#elif defined(HAVE_EXTATTR_LIST_FD)
1967 extattr_arg arg;
1968 arg.filedes = filedes;
1969 return bsd_attr_list(2, arg, list, size);
1970#elif defined(HAVE_ATTR_LISTF)
1971 return irix_attr_list(NULL, filedes, list, size, 0);
1972#elif defined(HAVE_ATTROPEN)
1973 ssize_t ret = -1;
1974 int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
1975 if (attrdirfd >= 0) {
1976 ret = solaris_list_xattr(attrdirfd, list, size);
1977 close(attrdirfd);
1978 }
1979 return ret;
1980#elif defined(__OS2__)
1981 return unilistxattr(0, filedes, list, size);
1982#else
1983 errno = ENOSYS;
1984 return -1;
1985#endif
1986}
1987
1988int sys_removexattr (const char *path, const char *name)
1989{
1990#if defined(HAVE_REMOVEXATTR)
1991#ifndef XATTR_ADD_OPT
1992 return removexattr(path, name);
1993#else
1994 int options = 0;
1995 return removexattr(path, name, options);
1996#endif
1997#elif defined(HAVE_REMOVEEA)
1998 return removeea(path, name);
1999#elif defined(HAVE_EXTATTR_DELETE_FILE)
2000 char *s;
2001 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2002 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2003 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2004
2005 return extattr_delete_file(path, attrnamespace, attrname);
2006#elif defined(HAVE_ATTR_REMOVE)
2007 int flags = 0;
2008 char *attrname = strchr(name,'.') + 1;
2009
2010 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
2011
2012 return attr_remove(path, attrname, flags);
2013#elif defined(HAVE_ATTROPEN)
2014 int ret = -1;
2015 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
2016 if (attrdirfd >= 0) {
2017 ret = solaris_unlinkat(attrdirfd, name);
2018 close(attrdirfd);
2019 }
2020 return ret;
2021#elif defined(__OS2__)
2022 return uniremovexattr (path, 0, name);
2023#else
2024 errno = ENOSYS;
2025 return -1;
2026#endif
2027}
2028
2029int sys_lremovexattr (const char *path, const char *name)
2030{
2031#if defined(HAVE_LREMOVEXATTR)
2032 return lremovexattr(path, name);
2033#elif defined(HAVE_REMOVEXATTR) && defined(XATTR_ADD_OPT)
2034 int options = XATTR_NOFOLLOW;
2035 return removexattr(path, name, options);
2036#elif defined(HAVE_LREMOVEEA)
2037 return lremoveea(path, name);
2038#elif defined(HAVE_EXTATTR_DELETE_LINK)
2039 char *s;
2040 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2041 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2042 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2043
2044 return extattr_delete_link(path, attrnamespace, attrname);
2045#elif defined(HAVE_ATTR_REMOVE)
2046 int flags = ATTR_DONTFOLLOW;
2047 char *attrname = strchr(name,'.') + 1;
2048
2049 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
2050
2051 return attr_remove(path, attrname, flags);
2052#elif defined(HAVE_ATTROPEN)
2053 int ret = -1;
2054 int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
2055 if (attrdirfd >= 0) {
2056 ret = solaris_unlinkat(attrdirfd, name);
2057 close(attrdirfd);
2058 }
2059 return ret;
2060#elif defined(__OS2__)
2061 return uniremovexattr (path, 0, name);
2062#else
2063 errno = ENOSYS;
2064 return -1;
2065#endif
2066}
2067
2068int sys_fremovexattr (int filedes, const char *name)
2069{
2070#if defined(HAVE_FREMOVEXATTR)
2071#ifndef XATTR_ADD_OPT
2072 return fremovexattr(filedes, name);
2073#else
2074 int options = 0;
2075 return fremovexattr(filedes, name, options);
2076#endif
2077#elif defined(HAVE_FREMOVEEA)
2078 return fremoveea(filedes, name);
2079#elif defined(HAVE_EXTATTR_DELETE_FD)
2080 char *s;
2081 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2082 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2083 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2084
2085 return extattr_delete_fd(filedes, attrnamespace, attrname);
2086#elif defined(HAVE_ATTR_REMOVEF)
2087 int flags = 0;
2088 char *attrname = strchr(name,'.') + 1;
2089
2090 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
2091
2092 return attr_removef(filedes, attrname, flags);
2093#elif defined(HAVE_ATTROPEN)
2094 int ret = -1;
2095 int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
2096 if (attrdirfd >= 0) {
2097 ret = solaris_unlinkat(attrdirfd, name);
2098 close(attrdirfd);
2099 }
2100 return ret;
2101#elif defined(__OS2__)
2102 return uniremovexattr (0, filedes, name);
2103#else
2104 errno = ENOSYS;
2105 return -1;
2106#endif
2107}
2108
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
2113
2114int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags)
2115{
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;
2139 }
2140 /* Ignore other errors */
2141 }
2142 else {
2143 /* CREATE attribute, that already exists */
2144 if (flags & XATTR_CREATE) {
2145 errno = EEXIST;
2146 return -1;
2147 }
2148 }
2149 }
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;
2155
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;
2159
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 int attrfd;
2165 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2166 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2167 attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2168 if (attrfd >= 0) {
2169 ret = solaris_write_xattr(attrfd, value, size);
2170 close(attrfd);
2171 }
2172 return ret;
2173#elif defined(__OS2__)
2174 return unisetxattr (path, 0, name, value, size, flags);
2175#else
2176 errno = ENOSYS;
2177 return -1;
2178#endif
2179}
2180
2181int sys_lsetxattr (const char *path, const char *name, const void *value, size_t size, int flags)
2182{
2183#if defined(HAVE_LSETXATTR)
2184 return lsetxattr(path, name, value, size, flags);
2185#elif defined(HAVE_SETXATTR) && defined(XATTR_ADD_OPT)
2186 int options = XATTR_NOFOLLOW;
2187 return setxattr(path, name, value, size, 0, options);
2188#elif defined(LSETEA)
2189 return lsetea(path, name, value, size, flags);
2190#elif defined(HAVE_EXTATTR_SET_LINK)
2191 char *s;
2192 int retval = 0;
2193 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2194 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2195 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2196 if (flags) {
2197 /* Check attribute existence */
2198 retval = extattr_get_link(path, attrnamespace, attrname, NULL, 0);
2199 if (retval < 0) {
2200 /* REPLACE attribute, that doesn't exist */
2201 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2202 errno = ENOATTR;
2203 return -1;
2204 }
2205 /* Ignore other errors */
2206 }
2207 else {
2208 /* CREATE attribute, that already exists */
2209 if (flags & XATTR_CREATE) {
2210 errno = EEXIST;
2211 return -1;
2212 }
2213 }
2214 }
2215
2216 retval = extattr_set_link(path, attrnamespace, attrname, value, size);
2217 return (retval < 0) ? -1 : 0;
2218#elif defined(HAVE_ATTR_SET)
2219 int myflags = ATTR_DONTFOLLOW;
2220 char *attrname = strchr(name,'.') + 1;
2221
2222 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2223 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2224 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2225
2226 return attr_set(path, attrname, (const char *)value, size, myflags);
2227#elif defined(HAVE_ATTROPEN)
2228 int ret = -1;
2229 int myflags = O_RDWR | AT_SYMLINK_NOFOLLOW;
2230 int attrfd;
2231 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2232 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2233 attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2234 if (attrfd >= 0) {
2235 ret = solaris_write_xattr(attrfd, value, size);
2236 close(attrfd);
2237 }
2238 return ret;
2239#elif defined(__OS2__)
2240 return unisetxattr (path, 0, name, value, size, flags);
2241#else
2242 errno = ENOSYS;
2243 return -1;
2244#endif
2245}
2246
2247int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags)
2248{
2249#if defined(HAVE_FSETXATTR)
2250#ifndef XATTR_ADD_OPT
2251 return fsetxattr(filedes, name, value, size, flags);
2252#else
2253 int options = 0;
2254 return fsetxattr(filedes, name, value, size, 0, options);
2255#endif
2256#elif defined(HAVE_FSETEA)
2257 return fsetea(filedes, name, value, size, flags);
2258#elif defined(HAVE_EXTATTR_SET_FD)
2259 char *s;
2260 int retval = 0;
2261 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2262 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2263 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2264 if (flags) {
2265 /* Check attribute existence */
2266 retval = extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0);
2267 if (retval < 0) {
2268 /* REPLACE attribute, that doesn't exist */
2269 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2270 errno = ENOATTR;
2271 return -1;
2272 }
2273 /* Ignore other errors */
2274 }
2275 else {
2276 /* CREATE attribute, that already exists */
2277 if (flags & XATTR_CREATE) {
2278 errno = EEXIST;
2279 return -1;
2280 }
2281 }
2282 }
2283 retval = extattr_set_fd(filedes, attrnamespace, attrname, value, size);
2284 return (retval < 0) ? -1 : 0;
2285#elif defined(HAVE_ATTR_SETF)
2286 int myflags = 0;
2287 char *attrname = strchr(name,'.') + 1;
2288
2289 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2290 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2291 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2292
2293 return attr_setf(filedes, attrname, (const char *)value, size, myflags);
2294#elif defined(HAVE_ATTROPEN)
2295 int ret = -1;
2296 int myflags = O_RDWR | O_XATTR;
2297 int attrfd;
2298 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2299 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2300 attrfd = solaris_openat(filedes, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2301 if (attrfd >= 0) {
2302 ret = solaris_write_xattr(attrfd, value, size);
2303 close(attrfd);
2304 }
2305 return ret;
2306#elif defined(__OS2__)
2307 return unisetxattr (0, filedes, name, value, size, flags);
2308#else
2309 errno = ENOSYS;
2310 return -1;
2311#endif
2312}
2313
2314/**************************************************************************
2315 helper functions for Solaris' EA support
2316****************************************************************************/
2317#ifdef HAVE_ATTROPEN
2318static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size)
2319{
2320 struct stat sbuf;
2321
2322 if (fstat(attrfd, &sbuf) == -1) {
2323 errno = ENOATTR;
2324 return -1;
2325 }
2326
2327 /* This is to return the current size of the named extended attribute */
2328 if (size == 0) {
2329 return sbuf.st_size;
2330 }
2331
2332 /* check size and read xattr */
2333 if (sbuf.st_size > size) {
2334 errno = ERANGE;
2335 return -1;
2336 }
2337
2338 return read(attrfd, value, sbuf.st_size);
2339}
2340
2341static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size)
2342{
2343 ssize_t len = 0;
2344 int stop = 0;
2345 DIR *dirp;
2346 struct dirent *de;
2347 int newfd = dup(attrdirfd);
2348 /* CAUTION: The originating file descriptor should not be
2349 used again following the call to fdopendir().
2350 For that reason we dup() the file descriptor
2351 here to make things more clear. */
2352 dirp = fdopendir(newfd);
2353
2354 while ((de = readdir(dirp))) {
2355 size_t listlen = strlen(de->d_name);
2356 if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) {
2357 /* we don't want "." and ".." here: */
2358 DEBUG(10,("skipped EA %s\n",de->d_name));
2359 continue;
2360 }
2361
2362 if (size == 0) {
2363 /* return the current size of the list of extended attribute names*/
2364 len += listlen + 1;
2365 } else {
2366 /* check size and copy entrieѕ + nul into list. */
2367 if ((len + listlen + 1) > size) {
2368 errno = ERANGE;
2369 len = -1;
2370 break;
2371 } else {
2372 safe_strcpy(list + len, de->d_name, listlen);
2373 pstrcpy(list + len, de->d_name);
2374 len += listlen;
2375 list[len] = '\0';
2376 ++len;
2377 }
2378 }
2379 }
2380
2381 if (closedir(dirp) == -1) {
2382 DEBUG(0,("closedir dirp failed: %s\n",strerror(errno)));
2383 return -1;
2384 }
2385 return len;
2386}
2387
2388static int solaris_unlinkat(int attrdirfd, const char *name)
2389{
2390 if (unlinkat(attrdirfd, name, 0) == -1) {
2391 if (errno == ENOENT) {
2392 errno = ENOATTR;
2393 }
2394 return -1;
2395 }
2396 return 0;
2397}
2398
2399static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode)
2400{
2401 int filedes = attropen(path, attrpath, oflag, mode);
2402 if (filedes == -1) {
2403 DEBUG(10,("attropen FAILED: path: %s, name: %s, errno: %s\n",path,attrpath,strerror(errno)));
2404 if (errno == EINVAL) {
2405 errno = ENOTSUP;
2406 } else {
2407 errno = ENOATTR;
2408 }
2409 }
2410 return filedes;
2411}
2412
2413static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode)
2414{
2415 int filedes = openat(fildes, path, oflag, mode);
2416 if (filedes == -1) {
2417 DEBUG(10,("openat FAILED: fd: %s, path: %s, errno: %s\n",filedes,path,strerror(errno)));
2418 if (errno == EINVAL) {
2419 errno = ENOTSUP;
2420 } else {
2421 errno = ENOATTR;
2422 }
2423 }
2424 return filedes;
2425}
2426
2427static int solaris_write_xattr(int attrfd, const char *value, size_t size)
2428{
2429 if ((ftruncate(attrfd, 0) == 0) && (write(attrfd, value, size) == size)) {
2430 return 0;
2431 } else {
2432 DEBUG(10,("solaris_write_xattr FAILED!\n"));
2433 return -1;
2434 }
2435}
2436#endif /*HAVE_ATTROPEN*/
2437
2438/****************************************************************************
2439 Return the major devicenumber for UNIX extensions.
2440****************************************************************************/
2441
2442uint32 unix_dev_major(SMB_DEV_T dev)
2443{
2444#if defined(HAVE_DEVICE_MAJOR_FN)
2445 return (uint32)major(dev);
2446#else
2447 return (uint32)(dev >> 8);
2448#endif
2449}
2450
2451/****************************************************************************
2452 Return the minor devicenumber for UNIX extensions.
2453****************************************************************************/
2454
2455uint32 unix_dev_minor(SMB_DEV_T dev)
2456{
2457#if defined(HAVE_DEVICE_MINOR_FN)
2458 return (uint32)minor(dev);
2459#else
2460 return (uint32)(dev & 0xff);
2461#endif
2462}
2463
2464#if defined(WITH_AIO)
2465
2466/*******************************************************************
2467 An aio_read wrapper that will deal with 64-bit sizes.
2468********************************************************************/
2469
2470int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2471{
2472#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_READ64)
2473 return aio_read64(aiocb);
2474#elif defined(HAVE_AIO_READ)
2475 return aio_read(aiocb);
2476#else
2477 errno = ENOSYS;
2478 return -1;
2479#endif
2480}
2481
2482/*******************************************************************
2483 An aio_write wrapper that will deal with 64-bit sizes.
2484********************************************************************/
2485
2486int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2487{
2488#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_WRITE64)
2489 return aio_write64(aiocb);
2490#elif defined(HAVE_AIO_WRITE)
2491 return aio_write(aiocb);
2492#else
2493 errno = ENOSYS;
2494 return -1;
2495#endif
2496}
2497
2498/*******************************************************************
2499 An aio_return wrapper that will deal with 64-bit sizes.
2500********************************************************************/
2501
2502ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2503{
2504#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_RETURN64)
2505 return aio_return64(aiocb);
2506#elif defined(HAVE_AIO_RETURN)
2507 return aio_return(aiocb);
2508#else
2509 errno = ENOSYS;
2510 return -1;
2511#endif
2512}
2513
2514/*******************************************************************
2515 An aio_cancel wrapper that will deal with 64-bit sizes.
2516********************************************************************/
2517
2518int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2519{
2520#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_CANCEL64)
2521 return aio_cancel64(fd, aiocb);
2522#elif defined(HAVE_AIO_CANCEL)
2523 return aio_cancel(fd, aiocb);
2524#else
2525 errno = ENOSYS;
2526 return -1;
2527#endif
2528}
2529
2530/*******************************************************************
2531 An aio_error wrapper that will deal with 64-bit sizes.
2532********************************************************************/
2533
2534int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2535{
2536#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_ERROR64)
2537 return aio_error64(aiocb);
2538#elif defined(HAVE_AIO_ERROR)
2539 return aio_error(aiocb);
2540#else
2541 errno = ENOSYS;
2542 return -1;
2543#endif
2544}
2545
2546/*******************************************************************
2547 An aio_fsync wrapper that will deal with 64-bit sizes.
2548********************************************************************/
2549
2550int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2551{
2552#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_FSYNC64)
2553 return aio_fsync64(op, aiocb);
2554#elif defined(HAVE_AIO_FSYNC)
2555 return aio_fsync(op, aiocb);
2556#else
2557 errno = ENOSYS;
2558 return -1;
2559#endif
2560}
2561
2562/*******************************************************************
2563 An aio_fsync wrapper that will deal with 64-bit sizes.
2564********************************************************************/
2565
2566int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2567{
2568#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_SUSPEND64)
2569 return aio_suspend64(cblist, n, timeout);
2570#elif defined(HAVE_AIO_FSYNC)
2571 return aio_suspend(cblist, n, timeout);
2572#else
2573 errno = ENOSYS;
2574 return -1;
2575#endif
2576}
2577#else /* !WITH_AIO */
2578
2579int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2580{
2581 errno = ENOSYS;
2582 return -1;
2583}
2584
2585int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2586{
2587 errno = ENOSYS;
2588 return -1;
2589}
2590
2591ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2592{
2593 errno = ENOSYS;
2594 return -1;
2595}
2596
2597int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2598{
2599 errno = ENOSYS;
2600 return -1;
2601}
2602
2603int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2604{
2605 errno = ENOSYS;
2606 return -1;
2607}
2608
2609int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2610{
2611 errno = ENOSYS;
2612 return -1;
2613}
2614
2615int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2616{
2617 errno = ENOSYS;
2618 return -1;
2619}
2620#endif /* WITH_AIO */
2621
2622int sys_getpeereid( int s, uid_t *uid)
2623{
2624#if defined(HAVE_PEERCRED)
2625 struct ucred cred;
2626 socklen_t cred_len = sizeof(struct ucred);
2627 int ret;
2628
2629 ret = getsockopt(s, SOL_SOCKET, SO_PEERCRED, (void *)&cred, &cred_len);
2630 if (ret != 0) {
2631 return -1;
2632 }
2633
2634 if (cred_len != sizeof(struct ucred)) {
2635 errno = EINVAL;
2636 return -1;
2637 }
2638
2639 *uid = cred.uid;
2640 return 0;
2641#else
2642 errno = ENOSYS;
2643 return -1;
2644#endif
2645}
Note: See TracBrowser for help on using the repository browser.