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