source: branches/samba-3.3.x/source/lib/system.c@ 221

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

Update Samba 3.3 to 3.3.1

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