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

Last change on this file since 216 was 137, checked in by Paul Smedley, 17 years ago

Update trunk to 3.2.0rc2

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