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