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