source: branches/samba-3.2.x/source/lib/system.c@ 232

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

Update 3.2 branch to 3.2.8

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