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