s3: Make smbd/aio.c not depend on aio.h anymore
[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    Copyright (C) Bjoern Jacke    2006-2007
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "includes.h"
24 #include "system/syslog.h"
25 #include "system/capability.h"
26 #include "system/passwd.h"
27 #include "system/filesys.h"
28 #include "../lib/util/setid.h"
29
30 #ifdef HAVE_SYS_SYSCTL_H
31 #include <sys/sysctl.h>
32 #endif
33
34 #ifdef HAVE_SYS_PRCTL_H
35 #include <sys/prctl.h>
36 #endif
37
38 #if defined(HAVE_AIO_H)
39 #include <aio.h>
40 #endif
41
42 /*
43    The idea is that this file will eventually have wrappers around all
44    important system calls in samba. The aims are:
45
46    - to enable easier porting by putting OS dependent stuff in here
47
48    - to allow for hooks into other "pseudo-filesystems"
49
50    - to allow easier integration of things like the japanese extensions
51
52    - to support the philosophy of Samba to expose the features of
53      the OS within the SMB model. In general whatever file/printer/variable
54      expansions/etc make sense to the OS should be acceptable to Samba.
55 */
56
57
58
59 /*******************************************************************
60 A read wrapper that will deal with EINTR.
61 ********************************************************************/
62
63 ssize_t sys_read(int fd, void *buf, size_t count)
64 {
65         ssize_t ret;
66
67         do {
68                 ret = read(fd, buf, count);
69 #if defined(EWOULDBLOCK)
70         } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
71 #else
72         } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
73 #endif
74         return ret;
75 }
76
77 /*******************************************************************
78 A write wrapper that will deal with EINTR.
79 ********************************************************************/
80
81 ssize_t sys_write(int fd, const void *buf, size_t count)
82 {
83         ssize_t ret;
84
85         do {
86                 ret = write(fd, buf, count);
87 #if defined(EWOULDBLOCK)
88         } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
89 #else
90         } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
91 #endif
92         return ret;
93 }
94
95 /*******************************************************************
96 A writev wrapper that will deal with EINTR.
97 ********************************************************************/
98
99 ssize_t sys_writev(int fd, const struct iovec *iov, int iovcnt)
100 {
101         ssize_t ret;
102
103 #if 0
104         /* Try to confuse write_data_iov a bit */
105         if ((random() % 5) == 0) {
106                 return sys_write(fd, iov[0].iov_base, iov[0].iov_len);
107         }
108         if (iov[0].iov_len > 1) {
109                 return sys_write(fd, iov[0].iov_base,
110                                  (random() % (iov[0].iov_len-1)) + 1);
111         }
112 #endif
113
114         do {
115                 ret = writev(fd, iov, iovcnt);
116 #if defined(EWOULDBLOCK)
117         } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
118 #else
119         } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
120 #endif
121         return ret;
122 }
123
124 /*******************************************************************
125 A pread wrapper that will deal with EINTR
126 ********************************************************************/
127
128 #if defined(HAVE_PREAD)
129 ssize_t sys_pread(int fd, void *buf, size_t count, off_t off)
130 {
131         ssize_t ret;
132
133         do {
134                 ret = pread(fd, buf, count, off);
135         } while (ret == -1 && errno == EINTR);
136         return ret;
137 }
138 #endif
139
140 /*******************************************************************
141 A write wrapper that will deal with EINTR
142 ********************************************************************/
143
144 #if defined(HAVE_PWRITE)
145 ssize_t sys_pwrite(int fd, const void *buf, size_t count, off_t off)
146 {
147         ssize_t ret;
148
149         do {
150                 ret = pwrite(fd, buf, count, off);
151         } while (ret == -1 && errno == EINTR);
152         return ret;
153 }
154 #endif
155
156 /*******************************************************************
157 A send wrapper that will deal with EINTR or EAGAIN or EWOULDBLOCK.
158 ********************************************************************/
159
160 ssize_t sys_send(int s, const void *msg, size_t len, int flags)
161 {
162         ssize_t ret;
163
164         do {
165                 ret = send(s, msg, len, flags);
166 #if defined(EWOULDBLOCK)
167         } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
168 #else
169         } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
170 #endif
171         return ret;
172 }
173
174 /*******************************************************************
175 A recvfrom wrapper that will deal with EINTR.
176 ********************************************************************/
177
178 ssize_t sys_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
179 {
180         ssize_t ret;
181
182         do {
183                 ret = recvfrom(s, buf, len, flags, from, fromlen);
184 #if defined(EWOULDBLOCK)
185         } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
186 #else
187         } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
188 #endif
189         return ret;
190 }
191
192 /*******************************************************************
193 A fcntl wrapper that will deal with EINTR.
194 ********************************************************************/
195
196 int sys_fcntl_ptr(int fd, int cmd, void *arg)
197 {
198         int ret;
199
200         do {
201                 ret = fcntl(fd, cmd, arg);
202         } while (ret == -1 && errno == EINTR);
203         return ret;
204 }
205
206 /*******************************************************************
207 A fcntl wrapper that will deal with EINTR.
208 ********************************************************************/
209
210 int sys_fcntl_long(int fd, int cmd, long arg)
211 {
212         int ret;
213
214         do {
215                 ret = fcntl(fd, cmd, arg);
216         } while (ret == -1 && errno == EINTR);
217         return ret;
218 }
219
220 /****************************************************************************
221  Get/Set all the possible time fields from a stat struct as a timespec.
222 ****************************************************************************/
223
224 static struct timespec get_atimespec(const struct stat *pst)
225 {
226 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
227         struct timespec ret;
228
229         /* Old system - no ns timestamp. */
230         ret.tv_sec = pst->st_atime;
231         ret.tv_nsec = 0;
232         return ret;
233 #else
234 #if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
235         return pst->st_atim;
236 #elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
237         struct timespec ret;
238         ret.tv_sec = pst->st_atime;
239         ret.tv_nsec = pst->st_atimensec;
240         return ret;
241 #elif defined(HAVE_STRUCT_STAT_ST_MTIME_N)
242         struct timespec ret;
243         ret.tv_sec = pst->st_atime;
244         ret.tv_nsec = pst->st_atime_n;
245         return ret;
246 #elif defined(HAVE_STRUCT_STAT_ST_UMTIME)
247         struct timespec ret;
248         ret.tv_sec = pst->st_atime;
249         ret.tv_nsec = pst->st_uatime * 1000;
250         return ret;
251 #elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
252         return pst->st_atimespec;
253 #else
254 #error  CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
255 #endif
256 #endif
257 }
258
259 static struct timespec get_mtimespec(const struct stat *pst)
260 {
261 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
262         struct timespec ret;
263
264         /* Old system - no ns timestamp. */
265         ret.tv_sec = pst->st_mtime;
266         ret.tv_nsec = 0;
267         return ret;
268 #else
269 #if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
270         return pst->st_mtim;
271 #elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
272         struct timespec ret;
273         ret.tv_sec = pst->st_mtime;
274         ret.tv_nsec = pst->st_mtimensec;
275         return ret;
276 #elif defined(HAVE_STRUCT_STAT_ST_MTIME_N)
277         struct timespec ret;
278         ret.tv_sec = pst->st_mtime;
279         ret.tv_nsec = pst->st_mtime_n;
280         return ret;
281 #elif defined(HAVE_STRUCT_STAT_ST_UMTIME)
282         struct timespec ret;
283         ret.tv_sec = pst->st_mtime;
284         ret.tv_nsec = pst->st_umtime * 1000;
285         return ret;
286 #elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
287         return pst->st_mtimespec;
288 #else
289 #error  CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
290 #endif
291 #endif
292 }
293
294 static struct timespec get_ctimespec(const struct stat *pst)
295 {
296 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
297         struct timespec ret;
298
299         /* Old system - no ns timestamp. */
300         ret.tv_sec = pst->st_ctime;
301         ret.tv_nsec = 0;
302         return ret;
303 #else
304 #if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
305         return pst->st_ctim;
306 #elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
307         struct timespec ret;
308         ret.tv_sec = pst->st_ctime;
309         ret.tv_nsec = pst->st_ctimensec;
310         return ret;
311 #elif defined(HAVE_STRUCT_STAT_ST_MTIME_N)
312         struct timespec ret;
313         ret.tv_sec = pst->st_ctime;
314         ret.tv_nsec = pst->st_ctime_n;
315         return ret;
316 #elif defined(HAVE_STRUCT_STAT_ST_UMTIME)
317         struct timespec ret;
318         ret.tv_sec = pst->st_ctime;
319         ret.tv_nsec = pst->st_uctime * 1000;
320         return ret;
321 #elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
322         return pst->st_ctimespec;
323 #else
324 #error  CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
325 #endif
326 #endif
327 }
328
329 /****************************************************************************
330  Return the best approximation to a 'create time' under UNIX from a stat
331  structure.
332 ****************************************************************************/
333
334 static struct timespec calc_create_time_stat(const struct stat *st)
335 {
336         struct timespec ret, ret1;
337         struct timespec c_time = get_ctimespec(st);
338         struct timespec m_time = get_mtimespec(st);
339         struct timespec a_time = get_atimespec(st);
340
341         ret = timespec_compare(&c_time, &m_time) < 0 ? c_time : m_time;
342         ret1 = timespec_compare(&ret, &a_time) < 0 ? ret : a_time;
343
344         if(!null_timespec(ret1)) {
345                 return ret1;
346         }
347
348         /*
349          * One of ctime, mtime or atime was zero (probably atime).
350          * Just return MIN(ctime, mtime).
351          */
352         return ret;
353 }
354
355 /****************************************************************************
356  Return the best approximation to a 'create time' under UNIX from a stat_ex
357  structure.
358 ****************************************************************************/
359
360 static struct timespec calc_create_time_stat_ex(const struct stat_ex *st)
361 {
362         struct timespec ret, ret1;
363         struct timespec c_time = st->st_ex_ctime;
364         struct timespec m_time = st->st_ex_mtime;
365         struct timespec a_time = st->st_ex_atime;
366
367         ret = timespec_compare(&c_time, &m_time) < 0 ? c_time : m_time;
368         ret1 = timespec_compare(&ret, &a_time) < 0 ? ret : a_time;
369
370         if(!null_timespec(ret1)) {
371                 return ret1;
372         }
373
374         /*
375          * One of ctime, mtime or atime was zero (probably atime).
376          * Just return MIN(ctime, mtime).
377          */
378         return ret;
379 }
380
381 /****************************************************************************
382  Return the 'create time' from a stat struct if it exists (birthtime) or else
383  use the best approximation.
384 ****************************************************************************/
385
386 static void make_create_timespec(const struct stat *pst, struct stat_ex *dst,
387                                  bool fake_dir_create_times)
388 {
389         if (S_ISDIR(pst->st_mode) && fake_dir_create_times) {
390                 dst->st_ex_btime.tv_sec = 315493200L;          /* 1/1/1980 */
391                 dst->st_ex_btime.tv_nsec = 0;
392         }
393
394         dst->st_ex_calculated_birthtime = false;
395
396 #if defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC)
397         dst->st_ex_btime = pst->st_birthtimespec;
398 #elif defined(HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC)
399         dst->st_ex_btime.tv_sec = pst->st_birthtime;
400         dst->st_ex_btime.tv_nsec = pst->st_birthtimenspec;
401 #elif defined(HAVE_STRUCT_STAT_ST_BIRTHTIME)
402         dst->st_ex_btime.tv_sec = pst->st_birthtime;
403         dst->st_ex_btime.tv_nsec = 0;
404 #else
405         dst->st_ex_btime = calc_create_time_stat(pst);
406         dst->st_ex_calculated_birthtime = true;
407 #endif
408
409         /* Deal with systems that don't initialize birthtime correctly.
410          * Pointed out by SATOH Fumiyasu <fumiyas@osstech.jp>.
411          */
412         if (null_timespec(dst->st_ex_btime)) {
413                 dst->st_ex_btime = calc_create_time_stat(pst);
414                 dst->st_ex_calculated_birthtime = true;
415         }
416 }
417
418 /****************************************************************************
419  If we update a timestamp in a stat_ex struct we may have to recalculate
420  the birthtime. For now only implement this for write time, but we may
421  also need to do it for atime and ctime. JRA.
422 ****************************************************************************/
423
424 void update_stat_ex_mtime(struct stat_ex *dst,
425                                 struct timespec write_ts)
426 {
427         dst->st_ex_mtime = write_ts;
428
429         /* We may have to recalculate btime. */
430         if (dst->st_ex_calculated_birthtime) {
431                 dst->st_ex_btime = calc_create_time_stat_ex(dst);
432         }
433 }
434
435 void update_stat_ex_create_time(struct stat_ex *dst,
436                                 struct timespec create_time)
437 {
438         dst->st_ex_btime = create_time;
439         dst->st_ex_calculated_birthtime = false;
440 }
441
442 void init_stat_ex_from_stat (struct stat_ex *dst,
443                             const struct stat *src,
444                             bool fake_dir_create_times)
445 {
446         dst->st_ex_dev = src->st_dev;
447         dst->st_ex_ino = src->st_ino;
448         dst->st_ex_mode = src->st_mode;
449         dst->st_ex_nlink = src->st_nlink;
450         dst->st_ex_uid = src->st_uid;
451         dst->st_ex_gid = src->st_gid;
452         dst->st_ex_rdev = src->st_rdev;
453         dst->st_ex_size = src->st_size;
454         dst->st_ex_atime = get_atimespec(src);
455         dst->st_ex_mtime = get_mtimespec(src);
456         dst->st_ex_ctime = get_ctimespec(src);
457         make_create_timespec(src, dst, fake_dir_create_times);
458 #ifdef HAVE_STAT_ST_BLKSIZE
459         dst->st_ex_blksize = src->st_blksize;
460 #else
461         dst->st_ex_blksize = STAT_ST_BLOCKSIZE;
462 #endif
463
464 #ifdef HAVE_STAT_ST_BLOCKS
465         dst->st_ex_blocks = src->st_blocks;
466 #else
467         dst->st_ex_blocks = src->st_size / dst->st_ex_blksize + 1;
468 #endif
469
470 #ifdef HAVE_STAT_ST_FLAGS
471         dst->st_ex_flags = src->st_flags;
472 #else
473         dst->st_ex_flags = 0;
474 #endif
475 }
476
477 /*******************************************************************
478 A stat() wrapper.
479 ********************************************************************/
480
481 int sys_stat(const char *fname, SMB_STRUCT_STAT *sbuf,
482              bool fake_dir_create_times)
483 {
484         int ret;
485         struct stat statbuf;
486         ret = stat(fname, &statbuf);
487         if (ret == 0) {
488                 /* we always want directories to appear zero size */
489                 if (S_ISDIR(statbuf.st_mode)) {
490                         statbuf.st_size = 0;
491                 }
492                 init_stat_ex_from_stat(sbuf, &statbuf, fake_dir_create_times);
493         }
494         return ret;
495 }
496
497 /*******************************************************************
498  An fstat() wrapper.
499 ********************************************************************/
500
501 int sys_fstat(int fd, SMB_STRUCT_STAT *sbuf, bool fake_dir_create_times)
502 {
503         int ret;
504         struct stat statbuf;
505         ret = fstat(fd, &statbuf);
506         if (ret == 0) {
507                 /* we always want directories to appear zero size */
508                 if (S_ISDIR(statbuf.st_mode)) {
509                         statbuf.st_size = 0;
510                 }
511                 init_stat_ex_from_stat(sbuf, &statbuf, fake_dir_create_times);
512         }
513         return ret;
514 }
515
516 /*******************************************************************
517  An lstat() wrapper.
518 ********************************************************************/
519
520 int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf,
521               bool fake_dir_create_times)
522 {
523         int ret;
524         struct stat statbuf;
525         ret = lstat(fname, &statbuf);
526         if (ret == 0) {
527                 /* we always want directories to appear zero size */
528                 if (S_ISDIR(statbuf.st_mode)) {
529                         statbuf.st_size = 0;
530                 }
531                 init_stat_ex_from_stat(sbuf, &statbuf, fake_dir_create_times);
532         }
533         return ret;
534 }
535
536 /*******************************************************************
537  An posix_fallocate() wrapper.
538 ********************************************************************/
539 int sys_posix_fallocate(int fd, off_t offset, off_t len)
540 {
541 #if defined(HAVE_POSIX_FALLOCATE) && !defined(HAVE_BROKEN_POSIX_FALLOCATE)
542         return posix_fallocate(fd, offset, len);
543 #elif defined(F_RESVSP64)
544         /* this handles XFS on IRIX */
545         struct flock64 fl;
546         off_t new_len = offset + len;
547         int ret;
548         struct stat64 sbuf;
549
550         /* unlikely to get a too large file on a 64bit system but ... */
551         if (new_len < 0)
552                 return EFBIG;
553
554         fl.l_whence = SEEK_SET;
555         fl.l_start = offset;
556         fl.l_len = len;
557
558         ret=fcntl(fd, F_RESVSP64, &fl);
559
560         if (ret != 0)
561                 return errno;
562
563         /* Make sure the file gets enlarged after we allocated space: */
564         fstat64(fd, &sbuf);
565         if (new_len > sbuf.st_size)
566                 ftruncate64(fd, new_len);
567         return 0;
568 #else
569         return ENOSYS;
570 #endif
571 }
572
573 /*******************************************************************
574  An fallocate() function that matches the semantics of the Linux one.
575 ********************************************************************/
576
577 #ifdef HAVE_LINUX_FALLOC_H
578 #include <linux/falloc.h>
579 #endif
580
581 int sys_fallocate(int fd, enum vfs_fallocate_mode mode, off_t offset, off_t len)
582 {
583 #if defined(HAVE_LINUX_FALLOCATE64) || defined(HAVE_LINUX_FALLOCATE)
584         int lmode;
585         switch (mode) {
586         case VFS_FALLOCATE_EXTEND_SIZE:
587                 lmode = 0;
588                 break;
589         case VFS_FALLOCATE_KEEP_SIZE:
590                 lmode = FALLOC_FL_KEEP_SIZE;
591                 break;
592         default:
593                 errno = EINVAL;
594                 return -1;
595         }
596 #if defined(HAVE_LINUX_FALLOCATE)
597         return fallocate(fd, lmode, offset, len);
598 #endif
599 #else
600         /* TODO - plumb in fallocate from other filesysetms like VXFS etc. JRA. */
601         errno = ENOSYS;
602         return -1;
603 #endif
604 }
605
606 #if HAVE_KERNEL_SHARE_MODES
607 #ifndef LOCK_MAND
608 #define LOCK_MAND       32      /* This is a mandatory flock */
609 #define LOCK_READ       64      /* ... Which allows concurrent read operations */
610 #define LOCK_WRITE      128     /* ... Which allows concurrent write operations */
611 #define LOCK_RW         192     /* ... Which allows concurrent read & write ops */
612 #endif
613 #endif
614
615 /*******************************************************************
616  A flock() wrapper that will perform the kernel flock.
617 ********************************************************************/
618
619 void kernel_flock(int fd, uint32 share_mode, uint32 access_mask)
620 {
621 #if HAVE_KERNEL_SHARE_MODES
622         int kernel_mode = 0;
623         if (share_mode == FILE_SHARE_WRITE) {
624                 kernel_mode = LOCK_MAND|LOCK_WRITE;
625         } else if (share_mode == FILE_SHARE_READ) {
626                 kernel_mode = LOCK_MAND|LOCK_READ;
627         } else if (share_mode == FILE_SHARE_NONE) {
628                 kernel_mode = LOCK_MAND;
629         }
630         if (kernel_mode) {
631                 flock(fd, kernel_mode);
632         }
633 #endif
634         ;
635 }
636
637
638
639 /*******************************************************************
640  An fdopendir wrapper.
641  Ugly hack - we need dirfd for this to work correctly in the
642  calling code.. JRA.
643 ********************************************************************/
644
645 DIR *sys_fdopendir(int fd)
646 {
647 #if defined(HAVE_FDOPENDIR) && defined(HAVE_DIRFD)
648         return fdopendir(fd);
649 #else
650         errno = ENOSYS;
651         return NULL;
652 #endif
653 }
654
655 /*******************************************************************
656  An mknod() wrapper.
657 ********************************************************************/
658
659 int sys_mknod(const char *path, mode_t mode, SMB_DEV_T dev)
660 {
661 #if defined(HAVE_MKNOD)
662         return mknod(path, mode, dev);
663 #else
664         /* No mknod system call. */
665         errno = ENOSYS;
666         return -1;
667 #endif
668 }
669
670 /*******************************************************************
671 The wait() calls vary between systems
672 ********************************************************************/
673
674 int sys_waitpid(pid_t pid,int *status,int options)
675 {
676 #ifdef HAVE_WAITPID
677         return waitpid(pid,status,options);
678 #else /* HAVE_WAITPID */
679         return wait4(pid, status, options, NULL);
680 #endif /* HAVE_WAITPID */
681 }
682
683 /*******************************************************************
684  System wrapper for getwd. Always returns MALLOC'ed memory, or NULL
685  on error (malloc fail usually).
686 ********************************************************************/
687
688 char *sys_getwd(void)
689 {
690 #ifdef GETCWD_TAKES_NULL
691         return getcwd(NULL, 0);
692 #elif HAVE_GETCWD
693         char *wd = NULL, *s = NULL;
694         size_t allocated = PATH_MAX;
695
696         while (1) {
697                 s = SMB_REALLOC_ARRAY(s, char, allocated);
698                 if (s == NULL) {
699                         return NULL;
700                 }
701                 wd = getcwd(s, allocated);
702                 if (wd) {
703                         break;
704                 }
705                 if (errno != ERANGE) {
706                         SAFE_FREE(s);
707                         break;
708                 }
709                 allocated *= 2;
710                 if (allocated < PATH_MAX) {
711                         SAFE_FREE(s);
712                         break;
713                 }
714         }
715         return wd;
716 #else
717         char *s = SMB_MALLOC_ARRAY(char, PATH_MAX);
718         if (s == NULL) {
719                 return NULL;
720         }
721         return getwd(s);
722 #endif
723 }
724
725 #if defined(HAVE_POSIX_CAPABILITIES)
726
727 /**************************************************************************
728  Try and abstract process capabilities (for systems that have them).
729 ****************************************************************************/
730
731 /* Set the POSIX capabilities needed for the given purpose into the effective
732  * capability set of the current process. Make sure they are always removed
733  * from the inheritable set, because there is no circumstance in which our
734  * children should inherit our elevated privileges.
735  */
736 static bool set_process_capability(enum smbd_capability capability,
737                                    bool enable)
738 {
739         cap_value_t cap_vals[2] = {0};
740         int num_cap_vals = 0;
741
742         cap_t cap;
743
744 #if defined(HAVE_PRCTL) && defined(PR_GET_KEEPCAPS) && defined(PR_SET_KEEPCAPS)
745         /* On Linux, make sure that any capabilities we grab are sticky
746          * across UID changes. We expect that this would allow us to keep both
747          * the effective and permitted capability sets, but as of circa 2.6.16,
748          * only the permitted set is kept. It is a bug (which we work around)
749          * that the effective set is lost, but we still require the effective
750          * set to be kept.
751          */
752         if (!prctl(PR_GET_KEEPCAPS)) {
753                 prctl(PR_SET_KEEPCAPS, 1);
754         }
755 #endif
756
757         cap = cap_get_proc();
758         if (cap == NULL) {
759                 DEBUG(0,("set_process_capability: cap_get_proc failed: %s\n",
760                         strerror(errno)));
761                 return False;
762         }
763
764         switch (capability) {
765                 case KERNEL_OPLOCK_CAPABILITY:
766 #ifdef CAP_NETWORK_MGT
767                         /* IRIX has CAP_NETWORK_MGT for oplocks. */
768                         cap_vals[num_cap_vals++] = CAP_NETWORK_MGT;
769 #endif
770                         break;
771                 case DMAPI_ACCESS_CAPABILITY:
772 #ifdef CAP_DEVICE_MGT
773                         /* IRIX has CAP_DEVICE_MGT for DMAPI access. */
774                         cap_vals[num_cap_vals++] = CAP_DEVICE_MGT;
775 #elif CAP_MKNOD
776                         /* Linux has CAP_MKNOD for DMAPI access. */
777                         cap_vals[num_cap_vals++] = CAP_MKNOD;
778 #endif
779                         break;
780                 case LEASE_CAPABILITY:
781 #ifdef CAP_LEASE
782                         cap_vals[num_cap_vals++] = CAP_LEASE;
783 #endif
784                         break;
785         }
786
787         SMB_ASSERT(num_cap_vals <= ARRAY_SIZE(cap_vals));
788
789         if (num_cap_vals == 0) {
790                 cap_free(cap);
791                 return True;
792         }
793
794         cap_set_flag(cap, CAP_EFFECTIVE, num_cap_vals, cap_vals,
795                 enable ? CAP_SET : CAP_CLEAR);
796
797         /* We never want to pass capabilities down to our children, so make
798          * sure they are not inherited.
799          */
800         cap_set_flag(cap, CAP_INHERITABLE, num_cap_vals, cap_vals, CAP_CLEAR);
801
802         if (cap_set_proc(cap) == -1) {
803                 DEBUG(0, ("set_process_capability: cap_set_proc failed: %s\n",
804                         strerror(errno)));
805                 cap_free(cap);
806                 return False;
807         }
808
809         cap_free(cap);
810         return True;
811 }
812
813 #endif /* HAVE_POSIX_CAPABILITIES */
814
815 /****************************************************************************
816  Gain the oplock capability from the kernel if possible.
817 ****************************************************************************/
818
819 void set_effective_capability(enum smbd_capability capability)
820 {
821 #if defined(HAVE_POSIX_CAPABILITIES)
822         set_process_capability(capability, True);
823 #endif /* HAVE_POSIX_CAPABILITIES */
824 }
825
826 void drop_effective_capability(enum smbd_capability capability)
827 {
828 #if defined(HAVE_POSIX_CAPABILITIES)
829         set_process_capability(capability, False);
830 #endif /* HAVE_POSIX_CAPABILITIES */
831 }
832
833 /**************************************************************************
834  Wrapper for random().
835 ****************************************************************************/
836
837 long sys_random(void)
838 {
839 #if defined(HAVE_RANDOM)
840         return (long)random();
841 #elif defined(HAVE_RAND)
842         return (long)rand();
843 #else
844         DEBUG(0,("Error - no random function available !\n"));
845         exit(1);
846 #endif
847 }
848
849 /**************************************************************************
850  Wrapper for srandom().
851 ****************************************************************************/
852
853 void sys_srandom(unsigned int seed)
854 {
855 #if defined(HAVE_SRANDOM)
856         srandom(seed);
857 #elif defined(HAVE_SRAND)
858         srand(seed);
859 #else
860         DEBUG(0,("Error - no srandom function available !\n"));
861         exit(1);
862 #endif
863 }
864
865 #ifndef NGROUPS_MAX
866 #define NGROUPS_MAX 32 /* Guess... */
867 #endif
868
869 /**************************************************************************
870  Returns equivalent to NGROUPS_MAX - using sysconf if needed.
871 ****************************************************************************/
872
873 int groups_max(void)
874 {
875 #if defined(SYSCONF_SC_NGROUPS_MAX)
876         int ret = sysconf(_SC_NGROUPS_MAX);
877         return (ret == -1) ? NGROUPS_MAX : ret;
878 #else
879         return NGROUPS_MAX;
880 #endif
881 }
882
883 /**************************************************************************
884  Wrap setgroups and getgroups for systems that declare getgroups() as
885  returning an array of gid_t, but actuall return an array of int.
886 ****************************************************************************/
887
888 #if defined(HAVE_BROKEN_GETGROUPS)
889
890 #ifdef HAVE_BROKEN_GETGROUPS
891 #define GID_T int
892 #else
893 #define GID_T gid_t
894 #endif
895
896 static int sys_broken_getgroups(int setlen, gid_t *gidset)
897 {
898         GID_T gid;
899         GID_T *group_list;
900         int i, ngroups;
901
902         if(setlen == 0) {
903                 return getgroups(setlen, &gid);
904         }
905
906         /*
907          * Broken case. We need to allocate a
908          * GID_T array of size setlen.
909          */
910
911         if(setlen < 0) {
912                 errno = EINVAL; 
913                 return -1;
914         } 
915
916         if (setlen == 0)
917                 setlen = groups_max();
918
919         if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
920                 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
921                 return -1;
922         }
923
924         if((ngroups = getgroups(setlen, group_list)) < 0) {
925                 int saved_errno = errno;
926                 SAFE_FREE(group_list);
927                 errno = saved_errno;
928                 return -1;
929         }
930
931         for(i = 0; i < ngroups; i++)
932                 gidset[i] = (gid_t)group_list[i];
933
934         SAFE_FREE(group_list);
935         return ngroups;
936 }
937
938 static int sys_broken_setgroups(int setlen, gid_t *gidset)
939 {
940         GID_T *group_list;
941         int i ; 
942
943         if (setlen == 0)
944                 return 0 ;
945
946         if (setlen < 0 || setlen > groups_max()) {
947                 errno = EINVAL; 
948                 return -1;   
949         }
950
951         /*
952          * Broken case. We need to allocate a
953          * GID_T array of size setlen.
954          */
955
956         if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
957                 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
958                 return -1;    
959         }
960
961         for(i = 0; i < setlen; i++) 
962                 group_list[i] = (GID_T) gidset[i]; 
963
964         if(samba_setgroups(setlen, group_list) != 0) {
965                 int saved_errno = errno;
966                 SAFE_FREE(group_list);
967                 errno = saved_errno;
968                 return -1;
969         }
970
971         SAFE_FREE(group_list);
972         return 0 ;
973 }
974
975 #endif /* HAVE_BROKEN_GETGROUPS */
976
977 /* This is a list of systems that require the first GID passed to setgroups(2)
978  * to be the effective GID. If your system is one of these, add it here.
979  */
980 #if defined (FREEBSD) || defined (DARWINOS)
981 #define USE_BSD_SETGROUPS
982 #endif
983
984 #if defined(USE_BSD_SETGROUPS)
985 /* Depending on the particular BSD implementation, the first GID that is
986  * passed to setgroups(2) will either be ignored or will set the credential's
987  * effective GID. In either case, the right thing to do is to guarantee that
988  * gidset[0] is the effective GID.
989  */
990 static int sys_bsd_setgroups(gid_t primary_gid, int setlen, const gid_t *gidset)
991 {
992         gid_t *new_gidset = NULL;
993         int max;
994         int ret;
995
996         /* setgroups(2) will fail with EINVAL if we pass too many groups. */
997         max = groups_max();
998
999         /* No group list, just make sure we are setting the efective GID. */
1000         if (setlen == 0) {
1001                 return samba_setgroups(1, &primary_gid);
1002         }
1003
1004         /* If the primary gid is not the first array element, grow the array
1005          * and insert it at the front.
1006          */
1007         if (gidset[0] != primary_gid) {
1008                 new_gidset = SMB_MALLOC_ARRAY(gid_t, setlen + 1);
1009                 if (new_gidset == NULL) {
1010                         return -1;
1011                 }
1012
1013                 memcpy(new_gidset + 1, gidset, (setlen * sizeof(gid_t)));
1014                 new_gidset[0] = primary_gid;
1015                 setlen++;
1016         }
1017
1018         if (setlen > max) {
1019                 DEBUG(3, ("forced to truncate group list from %d to %d\n",
1020                         setlen, max));
1021                 setlen = max;
1022         }
1023
1024 #if defined(HAVE_BROKEN_GETGROUPS)
1025         ret = sys_broken_setgroups(setlen, new_gidset ? new_gidset : gidset);
1026 #else
1027         ret = samba_setgroups(setlen, new_gidset ? new_gidset : gidset);
1028 #endif
1029
1030         if (new_gidset) {
1031                 int errsav = errno;
1032                 SAFE_FREE(new_gidset);
1033                 errno = errsav;
1034         }
1035
1036         return ret;
1037 }
1038
1039 #endif /* USE_BSD_SETGROUPS */
1040
1041 /**************************************************************************
1042  Wrapper for getgroups. Deals with broken (int) case.
1043 ****************************************************************************/
1044
1045 int sys_getgroups(int setlen, gid_t *gidset)
1046 {
1047 #if defined(HAVE_BROKEN_GETGROUPS)
1048         return sys_broken_getgroups(setlen, gidset);
1049 #else
1050         return getgroups(setlen, gidset);
1051 #endif
1052 }
1053
1054 /**************************************************************************
1055  Wrapper for setgroups. Deals with broken (int) case and BSD case.
1056 ****************************************************************************/
1057
1058 int sys_setgroups(gid_t UNUSED(primary_gid), int setlen, gid_t *gidset)
1059 {
1060 #if !defined(HAVE_SETGROUPS)
1061         errno = ENOSYS;
1062         return -1;
1063 #endif /* HAVE_SETGROUPS */
1064
1065 #if defined(USE_BSD_SETGROUPS)
1066         return sys_bsd_setgroups(primary_gid, setlen, gidset);
1067 #elif defined(HAVE_BROKEN_GETGROUPS)
1068         return sys_broken_setgroups(setlen, gidset);
1069 #else
1070         return samba_setgroups(setlen, gidset);
1071 #endif
1072 }
1073
1074 /**************************************************************************
1075  Extract a command into an arg list.
1076 ****************************************************************************/
1077
1078 static char **extract_args(TALLOC_CTX *mem_ctx, const char *command)
1079 {
1080         char *trunc_cmd;
1081         char *saveptr;
1082         char *ptr;
1083         int argcl;
1084         char **argl = NULL;
1085         int i;
1086
1087         if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1088                 DEBUG(0, ("talloc failed\n"));
1089                 goto nomem;
1090         }
1091
1092         if(!(ptr = strtok_r(trunc_cmd, " \t", &saveptr))) {
1093                 TALLOC_FREE(trunc_cmd);
1094                 errno = EINVAL;
1095                 return NULL;
1096         }
1097
1098         /*
1099          * Count the args.
1100          */
1101
1102         for( argcl = 1; ptr; ptr = strtok_r(NULL, " \t", &saveptr))
1103                 argcl++;
1104
1105         TALLOC_FREE(trunc_cmd);
1106
1107         if (!(argl = talloc_array(mem_ctx, char *, argcl + 1))) {
1108                 goto nomem;
1109         }
1110
1111         /*
1112          * Now do the extraction.
1113          */
1114
1115         if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1116                 goto nomem;
1117         }
1118
1119         ptr = strtok_r(trunc_cmd, " \t", &saveptr);
1120         i = 0;
1121
1122         if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1123                 goto nomem;
1124         }
1125
1126         while((ptr = strtok_r(NULL, " \t", &saveptr)) != NULL) {
1127
1128                 if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1129                         goto nomem;
1130                 }
1131         }
1132
1133         argl[i++] = NULL;
1134         TALLOC_FREE(trunc_cmd);
1135         return argl;
1136
1137  nomem:
1138         DEBUG(0, ("talloc failed\n"));
1139         TALLOC_FREE(trunc_cmd);
1140         TALLOC_FREE(argl);
1141         errno = ENOMEM;
1142         return NULL;
1143 }
1144
1145 /**************************************************************************
1146  Wrapper for popen. Safer as it doesn't search a path.
1147  Modified from the glibc sources.
1148  modified by tridge to return a file descriptor. We must kick our FILE* habit
1149 ****************************************************************************/
1150
1151 typedef struct _popen_list
1152 {
1153         int fd;
1154         pid_t child_pid;
1155         struct _popen_list *next;
1156 } popen_list;
1157
1158 static popen_list *popen_chain;
1159
1160 int sys_popen(const char *command)
1161 {
1162         int parent_end, child_end;
1163         int pipe_fds[2];
1164         popen_list *entry = NULL;
1165         char **argl = NULL;
1166
1167         if (pipe(pipe_fds) < 0)
1168                 return -1;
1169
1170         parent_end = pipe_fds[0];
1171         child_end = pipe_fds[1];
1172
1173         if (!*command) {
1174                 errno = EINVAL;
1175                 goto err_exit;
1176         }
1177
1178         if((entry = SMB_MALLOC_P(popen_list)) == NULL)
1179                 goto err_exit;
1180
1181         ZERO_STRUCTP(entry);
1182
1183         /*
1184          * Extract the command and args into a NULL terminated array.
1185          */
1186
1187         if(!(argl = extract_args(NULL, command)))
1188                 goto err_exit;
1189
1190         entry->child_pid = fork();
1191
1192         if (entry->child_pid == -1) {
1193                 goto err_exit;
1194         }
1195
1196         if (entry->child_pid == 0) {
1197
1198                 /*
1199                  * Child !
1200                  */
1201
1202                 int child_std_end = STDOUT_FILENO;
1203                 popen_list *p;
1204
1205                 close(parent_end);
1206                 if (child_end != child_std_end) {
1207                         dup2 (child_end, child_std_end);
1208                         close (child_end);
1209                 }
1210
1211                 /*
1212                  * POSIX.2:  "popen() shall ensure that any streams from previous
1213                  * popen() calls that remain open in the parent process are closed
1214                  * in the new child process."
1215                  */
1216
1217                 for (p = popen_chain; p; p = p->next)
1218                         close(p->fd);
1219
1220                 execv(argl[0], argl);
1221                 _exit (127);
1222         }
1223
1224         /*
1225          * Parent.
1226          */
1227
1228         close (child_end);
1229         TALLOC_FREE(argl);
1230
1231         /* Link into popen_chain. */
1232         entry->next = popen_chain;
1233         popen_chain = entry;
1234         entry->fd = parent_end;
1235
1236         return entry->fd;
1237
1238 err_exit:
1239
1240         SAFE_FREE(entry);
1241         TALLOC_FREE(argl);
1242         close(pipe_fds[0]);
1243         close(pipe_fds[1]);
1244         return -1;
1245 }
1246
1247 /**************************************************************************
1248  Wrapper for pclose. Modified from the glibc sources.
1249 ****************************************************************************/
1250
1251 int sys_pclose(int fd)
1252 {
1253         int wstatus;
1254         popen_list **ptr = &popen_chain;
1255         popen_list *entry = NULL;
1256         pid_t wait_pid;
1257         int status = -1;
1258
1259         /* Unlink from popen_chain. */
1260         for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
1261                 if ((*ptr)->fd == fd) {
1262                         entry = *ptr;
1263                         *ptr = (*ptr)->next;
1264                         status = 0;
1265                         break;
1266                 }
1267         }
1268
1269         if (status < 0 || close(entry->fd) < 0)
1270                 return -1;
1271
1272         /*
1273          * As Samba is catching and eating child process
1274          * exits we don't really care about the child exit
1275          * code, a -1 with errno = ECHILD will do fine for us.
1276          */
1277
1278         do {
1279                 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
1280         } while (wait_pid == -1 && errno == EINTR);
1281
1282         SAFE_FREE(entry);
1283
1284         if (wait_pid == -1)
1285                 return -1;
1286         return wstatus;
1287 }
1288
1289 /**************************************************************************
1290  Wrapper for Admin Logs.
1291 ****************************************************************************/
1292
1293  void sys_adminlog(int priority, const char *format_str, ...) 
1294 {
1295         va_list ap;
1296         int ret;
1297         char *msgbuf = NULL;
1298
1299         va_start( ap, format_str );
1300         ret = vasprintf( &msgbuf, format_str, ap );
1301         va_end( ap );
1302
1303         if (ret == -1)
1304                 return;
1305
1306 #if defined(HAVE_SYSLOG)
1307         syslog( priority, "%s", msgbuf );
1308 #else
1309         DEBUG(0,("%s", msgbuf ));
1310 #endif
1311         SAFE_FREE(msgbuf);
1312 }
1313
1314 /****************************************************************************
1315  Return the major devicenumber for UNIX extensions.
1316 ****************************************************************************/
1317
1318 uint32 unix_dev_major(SMB_DEV_T dev)
1319 {
1320 #if defined(HAVE_DEVICE_MAJOR_FN)
1321         return (uint32)major(dev);
1322 #else
1323         return (uint32)(dev >> 8);
1324 #endif
1325 }
1326
1327 /****************************************************************************
1328  Return the minor devicenumber for UNIX extensions.
1329 ****************************************************************************/
1330
1331 uint32 unix_dev_minor(SMB_DEV_T dev)
1332 {
1333 #if defined(HAVE_DEVICE_MINOR_FN)
1334         return (uint32)minor(dev);
1335 #else
1336         return (uint32)(dev & 0xff);
1337 #endif
1338 }
1339
1340 #if 0
1341 /*******************************************************************
1342  Return the number of CPUs.
1343 ********************************************************************/
1344
1345 int sys_get_number_of_cores(void)
1346 {
1347         int ret = -1;
1348
1349 #if defined(HAVE_SYSCONF)
1350 #if defined(_SC_NPROCESSORS_ONLN)
1351         ret = (int)sysconf(_SC_NPROCESSORS_ONLN);
1352 #endif
1353 #if defined(_SC_NPROCESSORS_CONF)
1354         if (ret < 1) {
1355                 ret = (int)sysconf(_SC_NPROCESSORS_CONF);
1356         }
1357 #endif
1358 #elif defined(HAVE_SYSCTL) && defined(CTL_HW)
1359         int name[2];
1360         unsigned int len = sizeof(ret);
1361
1362         name[0] = CTL_HW;
1363 #if defined(HW_AVAILCPU)
1364         name[1] = HW_AVAILCPU;
1365
1366         if (sysctl(name, 2, &ret, &len, NULL, 0) == -1) {
1367                 ret = -1;
1368         }
1369 #endif
1370 #if defined(HW_NCPU)
1371         if(ret < 1) {
1372                 name[0] = CTL_HW;
1373                 name[1] = HW_NCPU;
1374                 if (sysctl(nm, 2, &count, &len, NULL, 0) == -1) {
1375                         ret = -1;
1376                 }
1377         }
1378 #endif
1379 #endif
1380         if (ret < 1) {
1381                 ret = 1;
1382         }
1383         return ret;
1384 }
1385 #endif
1386
1387 #if defined(HAVE_AIO)
1388
1389 /*******************************************************************
1390  An aio_read wrapper.
1391 ********************************************************************/
1392
1393 int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
1394 {
1395 #if defined(HAVE_AIO_READ)
1396         return aio_read(aiocb);
1397 #else
1398         errno = ENOSYS;
1399         return -1;
1400 #endif
1401 }
1402
1403 /*******************************************************************
1404  An aio_write wrapper.
1405 ********************************************************************/
1406
1407 int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
1408 {
1409 #if defined(HAVE_AIO_WRITE)
1410         return aio_write(aiocb);
1411 #else
1412         errno = ENOSYS;
1413         return -1;
1414 #endif
1415 }
1416
1417 /*******************************************************************
1418  An aio_return wrapper.
1419 ********************************************************************/
1420
1421 ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
1422 {
1423 #if defined(HAVE_AIO_RETURN)
1424         return aio_return(aiocb);
1425 #else
1426         errno = ENOSYS;
1427         return -1;
1428 #endif
1429 }
1430
1431 /*******************************************************************
1432  An aio_cancel wrapper.
1433 ********************************************************************/
1434
1435 int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
1436 {
1437 #if defined(HAVE_AIO_CANCEL)
1438         return aio_cancel(fd, aiocb);
1439 #else
1440         errno = ENOSYS;
1441         return -1;
1442 #endif
1443 }
1444
1445 /*******************************************************************
1446  An aio_error wrapper.
1447 ********************************************************************/
1448
1449 int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
1450 {
1451 #if defined(HAVE_AIO_ERROR)
1452         return aio_error(aiocb);
1453 #else
1454         errno = ENOSYS;
1455         return -1;
1456 #endif
1457 }
1458
1459 /*******************************************************************
1460  An aio_fsync wrapper.
1461 ********************************************************************/
1462
1463 int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
1464 {
1465 #if defined(HAVE_AIO_FSYNC)
1466         return aio_fsync(op, aiocb);
1467 #else
1468         errno = ENOSYS;
1469         return -1;
1470 #endif
1471 }
1472
1473 /*******************************************************************
1474  An aio_fsync wrapper.
1475 ********************************************************************/
1476
1477 int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
1478 {
1479 #if defined(HAVE_AIO_FSYNC)
1480         return aio_suspend(cblist, n, timeout);
1481 #else
1482         errno = ENOSYS;
1483         return -1;
1484 #endif
1485 }
1486 #else /* !HAVE_AIO */
1487
1488 int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
1489 {
1490         errno = ENOSYS;
1491         return -1;
1492 }
1493
1494 int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
1495 {
1496         errno = ENOSYS;
1497         return -1;
1498 }
1499
1500 ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
1501 {
1502         errno = ENOSYS;
1503         return -1;
1504 }
1505
1506 int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
1507 {
1508         errno = ENOSYS;
1509         return -1;
1510 }
1511
1512 int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
1513 {
1514         errno = ENOSYS;
1515         return -1;
1516 }
1517
1518 int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
1519 {
1520         errno = ENOSYS;
1521         return -1;
1522 }
1523
1524 int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
1525 {
1526         errno = ENOSYS;
1527         return -1;
1528 }
1529 #endif /* HAVE_AIO */