Add a sys_get_number_of_cores() function that calls sysconf or sysctl
[tridge/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
29 #ifdef HAVE_SYS_SYSCTL_H
30 #include <sys/sysctl.h>
31 #endif
32
33 #ifdef HAVE_SYS_PRCTL_H
34 #include <sys/prctl.h>
35 #endif
36
37 /*
38    The idea is that this file will eventually have wrappers around all
39    important system calls in samba. The aims are:
40
41    - to enable easier porting by putting OS dependent stuff in here
42
43    - to allow for hooks into other "pseudo-filesystems"
44
45    - to allow easier integration of things like the japanese extensions
46
47    - to support the philosophy of Samba to expose the features of
48      the OS within the SMB model. In general whatever file/printer/variable
49      expansions/etc make sense to the OS should be acceptable to Samba.
50 */
51
52
53
54 /*******************************************************************
55  A wrapper for usleep in case we don't have one.
56 ********************************************************************/
57
58 int sys_usleep(long usecs)
59 {
60 #ifndef HAVE_USLEEP
61         struct timeval tval;
62 #endif
63
64         /*
65          * We need this braindamage as the glibc usleep
66          * is not SPEC1170 complient... grumble... JRA.
67          */
68
69         if(usecs < 0 || usecs > 999999) {
70                 errno = EINVAL;
71                 return -1;
72         }
73
74 #if HAVE_USLEEP
75         usleep(usecs);
76         return 0;
77 #else /* HAVE_USLEEP */
78         /*
79          * Fake it with select...
80          */
81         tval.tv_sec = 0;
82         tval.tv_usec = usecs/1000;
83         select(0,NULL,NULL,NULL,&tval);
84         return 0;
85 #endif /* HAVE_USLEEP */
86 }
87
88 /*******************************************************************
89 A read wrapper that will deal with EINTR.
90 ********************************************************************/
91
92 ssize_t sys_read(int fd, void *buf, size_t count)
93 {
94         ssize_t ret;
95
96         do {
97                 ret = read(fd, buf, count);
98 #if defined(EWOULDBLOCK)
99         } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
100 #else
101         } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
102 #endif
103         return ret;
104 }
105
106 /*******************************************************************
107 A write wrapper that will deal with EINTR.
108 ********************************************************************/
109
110 ssize_t sys_write(int fd, const void *buf, size_t count)
111 {
112         ssize_t ret;
113
114         do {
115                 ret = write(fd, buf, count);
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 writev wrapper that will deal with EINTR.
126 ********************************************************************/
127
128 ssize_t sys_writev(int fd, const struct iovec *iov, int iovcnt)
129 {
130         ssize_t ret;
131
132 #if 0
133         /* Try to confuse write_data_iov a bit */
134         if ((random() % 5) == 0) {
135                 return sys_write(fd, iov[0].iov_base, iov[0].iov_len);
136         }
137         if (iov[0].iov_len > 1) {
138                 return sys_write(fd, iov[0].iov_base,
139                                  (random() % (iov[0].iov_len-1)) + 1);
140         }
141 #endif
142
143         do {
144                 ret = writev(fd, iov, iovcnt);
145 #if defined(EWOULDBLOCK)
146         } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
147 #else
148         } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
149 #endif
150         return ret;
151 }
152
153 /*******************************************************************
154 A pread wrapper that will deal with EINTR and 64-bit file offsets.
155 ********************************************************************/
156
157 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
158 ssize_t sys_pread(int fd, void *buf, size_t count, SMB_OFF_T off)
159 {
160         ssize_t ret;
161
162         do {
163 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_PREAD64)
164                 ret = pread64(fd, buf, count, off);
165 #else
166                 ret = pread(fd, buf, count, off);
167 #endif
168         } while (ret == -1 && errno == EINTR);
169         return ret;
170 }
171 #endif
172
173 /*******************************************************************
174 A write wrapper that will deal with EINTR and 64-bit file offsets.
175 ********************************************************************/
176
177 #if defined(HAVE_PWRITE) || defined(HAVE_PWRITE64)
178 ssize_t sys_pwrite(int fd, const void *buf, size_t count, SMB_OFF_T off)
179 {
180         ssize_t ret;
181
182         do {
183 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_PWRITE64)
184                 ret = pwrite64(fd, buf, count, off);
185 #else
186                 ret = pwrite(fd, buf, count, off);
187 #endif
188         } while (ret == -1 && errno == EINTR);
189         return ret;
190 }
191 #endif
192
193 /*******************************************************************
194 A send wrapper that will deal with EINTR or EAGAIN or EWOULDBLOCK.
195 ********************************************************************/
196
197 ssize_t sys_send(int s, const void *msg, size_t len, int flags)
198 {
199         ssize_t ret;
200
201         do {
202                 ret = send(s, msg, len, flags);
203 #if defined(EWOULDBLOCK)
204         } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
205 #else
206         } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
207 #endif
208         return ret;
209 }
210
211 /*******************************************************************
212 A sendto wrapper that will deal with EINTR or EAGAIN or EWOULDBLOCK.
213 ********************************************************************/
214
215 ssize_t sys_sendto(int s,  const void *msg, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
216 {
217         ssize_t ret;
218
219         do {
220                 ret = sendto(s, msg, len, flags, to, tolen);
221 #if defined(EWOULDBLOCK)
222         } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
223 #else
224         } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
225 #endif
226         return ret;
227 }
228
229 /*******************************************************************
230 A recv wrapper that will deal with EINTR or EAGAIN or EWOULDBLOCK.
231 ********************************************************************/
232
233 ssize_t sys_recv(int fd, void *buf, size_t count, int flags)
234 {
235         ssize_t ret;
236
237         do {
238                 ret = recv(fd, buf, count, flags);
239 #if defined(EWOULDBLOCK)
240         } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
241 #else
242         } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
243 #endif
244         return ret;
245 }
246
247 /*******************************************************************
248 A recvfrom wrapper that will deal with EINTR.
249 ********************************************************************/
250
251 ssize_t sys_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
252 {
253         ssize_t ret;
254
255         do {
256                 ret = recvfrom(s, buf, len, flags, from, fromlen);
257 #if defined(EWOULDBLOCK)
258         } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
259 #else
260         } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
261 #endif
262         return ret;
263 }
264
265 /*******************************************************************
266 A fcntl wrapper that will deal with EINTR.
267 ********************************************************************/
268
269 int sys_fcntl_ptr(int fd, int cmd, void *arg)
270 {
271         int ret;
272
273         do {
274                 ret = fcntl(fd, cmd, arg);
275         } while (ret == -1 && errno == EINTR);
276         return ret;
277 }
278
279 /*******************************************************************
280 A fcntl wrapper that will deal with EINTR.
281 ********************************************************************/
282
283 int sys_fcntl_long(int fd, int cmd, long arg)
284 {
285         int ret;
286
287         do {
288                 ret = fcntl(fd, cmd, arg);
289         } while (ret == -1 && errno == EINTR);
290         return ret;
291 }
292
293 /****************************************************************************
294  Get/Set all the possible time fields from a stat struct as a timespec.
295 ****************************************************************************/
296
297 static struct timespec get_atimespec(const struct stat *pst)
298 {
299 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
300         struct timespec ret;
301
302         /* Old system - no ns timestamp. */
303         ret.tv_sec = pst->st_atime;
304         ret.tv_nsec = 0;
305         return ret;
306 #else
307 #if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
308         return pst->st_atim;
309 #elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
310         struct timespec ret;
311         ret.tv_sec = pst->st_atime;
312         ret.tv_nsec = pst->st_atimensec;
313         return ret;
314 #elif defined(HAVE_STRUCT_STAT_ST_MTIME_N)
315         struct timespec ret;
316         ret.tv_sec = pst->st_atime;
317         ret.tv_nsec = pst->st_atime_n;
318         return ret;
319 #elif defined(HAVE_STRUCT_STAT_ST_UMTIME)
320         struct timespec ret;
321         ret.tv_sec = pst->st_atime;
322         ret.tv_nsec = pst->st_uatime * 1000;
323         return ret;
324 #elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
325         return pst->st_atimespec;
326 #else
327 #error  CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
328 #endif
329 #endif
330 }
331
332 static struct timespec get_mtimespec(const struct stat *pst)
333 {
334 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
335         struct timespec ret;
336
337         /* Old system - no ns timestamp. */
338         ret.tv_sec = pst->st_mtime;
339         ret.tv_nsec = 0;
340         return ret;
341 #else
342 #if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
343         return pst->st_mtim;
344 #elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
345         struct timespec ret;
346         ret.tv_sec = pst->st_mtime;
347         ret.tv_nsec = pst->st_mtimensec;
348         return ret;
349 #elif defined(HAVE_STRUCT_STAT_ST_MTIME_N)
350         struct timespec ret;
351         ret.tv_sec = pst->st_mtime;
352         ret.tv_nsec = pst->st_mtime_n;
353         return ret;
354 #elif defined(HAVE_STRUCT_STAT_ST_UMTIME)
355         struct timespec ret;
356         ret.tv_sec = pst->st_mtime;
357         ret.tv_nsec = pst->st_umtime * 1000;
358         return ret;
359 #elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
360         return pst->st_mtimespec;
361 #else
362 #error  CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
363 #endif
364 #endif
365 }
366
367 static struct timespec get_ctimespec(const struct stat *pst)
368 {
369 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
370         struct timespec ret;
371
372         /* Old system - no ns timestamp. */
373         ret.tv_sec = pst->st_ctime;
374         ret.tv_nsec = 0;
375         return ret;
376 #else
377 #if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
378         return pst->st_ctim;
379 #elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
380         struct timespec ret;
381         ret.tv_sec = pst->st_ctime;
382         ret.tv_nsec = pst->st_ctimensec;
383         return ret;
384 #elif defined(HAVE_STRUCT_STAT_ST_MTIME_N)
385         struct timespec ret;
386         ret.tv_sec = pst->st_ctime;
387         ret.tv_nsec = pst->st_ctime_n;
388         return ret;
389 #elif defined(HAVE_STRUCT_STAT_ST_UMTIME)
390         struct timespec ret;
391         ret.tv_sec = pst->st_ctime;
392         ret.tv_nsec = pst->st_uctime * 1000;
393         return ret;
394 #elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
395         return pst->st_ctimespec;
396 #else
397 #error  CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
398 #endif
399 #endif
400 }
401
402 /****************************************************************************
403  Return the best approximation to a 'create time' under UNIX from a stat
404  structure.
405 ****************************************************************************/
406
407 static struct timespec calc_create_time_stat(const struct stat *st)
408 {
409         struct timespec ret, ret1;
410         struct timespec c_time = get_ctimespec(st);
411         struct timespec m_time = get_mtimespec(st);
412         struct timespec a_time = get_atimespec(st);
413
414         ret = timespec_compare(&c_time, &m_time) < 0 ? c_time : m_time;
415         ret1 = timespec_compare(&ret, &a_time) < 0 ? ret : a_time;
416
417         if(!null_timespec(ret1)) {
418                 return ret1;
419         }
420
421         /*
422          * One of ctime, mtime or atime was zero (probably atime).
423          * Just return MIN(ctime, mtime).
424          */
425         return ret;
426 }
427
428 /****************************************************************************
429  Return the best approximation to a 'create time' under UNIX from a stat_ex
430  structure.
431 ****************************************************************************/
432
433 static struct timespec calc_create_time_stat_ex(const struct stat_ex *st)
434 {
435         struct timespec ret, ret1;
436         struct timespec c_time = st->st_ex_ctime;
437         struct timespec m_time = st->st_ex_mtime;
438         struct timespec a_time = st->st_ex_atime;
439
440         ret = timespec_compare(&c_time, &m_time) < 0 ? c_time : m_time;
441         ret1 = timespec_compare(&ret, &a_time) < 0 ? ret : a_time;
442
443         if(!null_timespec(ret1)) {
444                 return ret1;
445         }
446
447         /*
448          * One of ctime, mtime or atime was zero (probably atime).
449          * Just return MIN(ctime, mtime).
450          */
451         return ret;
452 }
453
454 /****************************************************************************
455  Return the 'create time' from a stat struct if it exists (birthtime) or else
456  use the best approximation.
457 ****************************************************************************/
458
459 static void make_create_timespec(const struct stat *pst, struct stat_ex *dst,
460                                  bool fake_dir_create_times)
461 {
462         if (S_ISDIR(pst->st_mode) && fake_dir_create_times) {
463                 dst->st_ex_btime.tv_sec = 315493200L;          /* 1/1/1980 */
464                 dst->st_ex_btime.tv_nsec = 0;
465         }
466
467         dst->st_ex_calculated_birthtime = false;
468
469 #if defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC)
470         dst->st_ex_btime = pst->st_birthtimespec;
471 #elif defined(HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC)
472         dst->st_ex_btime.tv_sec = pst->st_birthtime;
473         dst->st_ex_btime.tv_nsec = pst->st_birthtimenspec;
474 #elif defined(HAVE_STRUCT_STAT_ST_BIRTHTIME)
475         dst->st_ex_btime.tv_sec = pst->st_birthtime;
476         dst->st_ex_btime.tv_nsec = 0;
477 #else
478         dst->st_ex_btime = calc_create_time_stat(pst);
479         dst->st_ex_calculated_birthtime = true;
480 #endif
481
482         /* Deal with systems that don't initialize birthtime correctly.
483          * Pointed out by SATOH Fumiyasu <fumiyas@osstech.jp>.
484          */
485         if (null_timespec(dst->st_ex_btime)) {
486                 dst->st_ex_btime = calc_create_time_stat(pst);
487                 dst->st_ex_calculated_birthtime = true;
488         }
489 }
490
491 /****************************************************************************
492  If we update a timestamp in a stat_ex struct we may have to recalculate
493  the birthtime. For now only implement this for write time, but we may
494  also need to do it for atime and ctime. JRA.
495 ****************************************************************************/
496
497 void update_stat_ex_mtime(struct stat_ex *dst,
498                                 struct timespec write_ts)
499 {
500         dst->st_ex_mtime = write_ts;
501
502         /* We may have to recalculate btime. */
503         if (dst->st_ex_calculated_birthtime) {
504                 dst->st_ex_btime = calc_create_time_stat_ex(dst);
505         }
506 }
507
508 void update_stat_ex_create_time(struct stat_ex *dst,
509                                 struct timespec create_time)
510 {
511         dst->st_ex_btime = create_time;
512         dst->st_ex_calculated_birthtime = false;
513 }
514
515 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
516 void init_stat_ex_from_stat (struct stat_ex *dst,
517                             const struct stat64 *src,
518                             bool fake_dir_create_times)
519 #else
520 void init_stat_ex_from_stat (struct stat_ex *dst,
521                             const struct stat *src,
522                             bool fake_dir_create_times)
523 #endif
524 {
525         dst->st_ex_dev = src->st_dev;
526         dst->st_ex_ino = src->st_ino;
527         dst->st_ex_mode = src->st_mode;
528         dst->st_ex_nlink = src->st_nlink;
529         dst->st_ex_uid = src->st_uid;
530         dst->st_ex_gid = src->st_gid;
531         dst->st_ex_rdev = src->st_rdev;
532         dst->st_ex_size = src->st_size;
533         dst->st_ex_atime = get_atimespec(src);
534         dst->st_ex_mtime = get_mtimespec(src);
535         dst->st_ex_ctime = get_ctimespec(src);
536         make_create_timespec(src, dst, fake_dir_create_times);
537 #ifdef HAVE_STAT_ST_BLKSIZE
538         dst->st_ex_blksize = src->st_blksize;
539 #else
540         dst->st_ex_blksize = STAT_ST_BLOCKSIZE;
541 #endif
542
543 #ifdef HAVE_STAT_ST_BLOCKS
544         dst->st_ex_blocks = src->st_blocks;
545 #else
546         dst->st_ex_blocks = src->st_size / dst->st_ex_blksize + 1;
547 #endif
548
549 #ifdef HAVE_STAT_ST_FLAGS
550         dst->st_ex_flags = src->st_flags;
551 #else
552         dst->st_ex_flags = 0;
553 #endif
554 }
555
556 /*******************************************************************
557 A stat() wrapper that will deal with 64 bit filesizes.
558 ********************************************************************/
559
560 int sys_stat(const char *fname, SMB_STRUCT_STAT *sbuf,
561              bool fake_dir_create_times)
562 {
563         int ret;
564 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
565         struct stat64 statbuf;
566         ret = stat64(fname, &statbuf);
567 #else
568         struct stat statbuf;
569         ret = stat(fname, &statbuf);
570 #endif
571         if (ret == 0) {
572                 /* we always want directories to appear zero size */
573                 if (S_ISDIR(statbuf.st_mode)) {
574                         statbuf.st_size = 0;
575                 }
576                 init_stat_ex_from_stat(sbuf, &statbuf, fake_dir_create_times);
577         }
578         return ret;
579 }
580
581 /*******************************************************************
582  An fstat() wrapper that will deal with 64 bit filesizes.
583 ********************************************************************/
584
585 int sys_fstat(int fd, SMB_STRUCT_STAT *sbuf, bool fake_dir_create_times)
586 {
587         int ret;
588 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FSTAT64)
589         struct stat64 statbuf;
590         ret = fstat64(fd, &statbuf);
591 #else
592         struct stat statbuf;
593         ret = fstat(fd, &statbuf);
594 #endif
595         if (ret == 0) {
596                 /* we always want directories to appear zero size */
597                 if (S_ISDIR(statbuf.st_mode)) {
598                         statbuf.st_size = 0;
599                 }
600                 init_stat_ex_from_stat(sbuf, &statbuf, fake_dir_create_times);
601         }
602         return ret;
603 }
604
605 /*******************************************************************
606  An lstat() wrapper that will deal with 64 bit filesizes.
607 ********************************************************************/
608
609 int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf,
610               bool fake_dir_create_times)
611 {
612         int ret;
613 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSTAT64)
614         struct stat64 statbuf;
615         ret = lstat64(fname, &statbuf);
616 #else
617         struct stat statbuf;
618         ret = lstat(fname, &statbuf);
619 #endif
620         if (ret == 0) {
621                 /* we always want directories to appear zero size */
622                 if (S_ISDIR(statbuf.st_mode)) {
623                         statbuf.st_size = 0;
624                 }
625                 init_stat_ex_from_stat(sbuf, &statbuf, fake_dir_create_times);
626         }
627         return ret;
628 }
629
630 /*******************************************************************
631  An posix_fallocate() wrapper that will deal with 64 bit filesizes.
632 ********************************************************************/
633 int sys_posix_fallocate(int fd, SMB_OFF_T offset, SMB_OFF_T len)
634 {
635 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_POSIX_FALLOCATE64) && !defined(HAVE_BROKEN_POSIX_FALLOCATE)
636         return posix_fallocate64(fd, offset, len);
637 #elif defined(HAVE_POSIX_FALLOCATE) && !defined(HAVE_BROKEN_POSIX_FALLOCATE)
638         return posix_fallocate(fd, offset, len);
639 #elif defined(F_RESVSP64)
640         /* this handles XFS on IRIX */
641         struct flock64 fl;
642         SMB_OFF_T new_len = offset + len;
643         int ret;
644         struct stat64 sbuf;
645
646         /* unlikely to get a too large file on a 64bit system but ... */
647         if (new_len < 0)
648                 return EFBIG;
649
650         fl.l_whence = SEEK_SET;
651         fl.l_start = offset;
652         fl.l_len = len;
653
654         ret=fcntl(fd, F_RESVSP64, &fl);
655
656         if (ret != 0)
657                 return errno;
658
659         /* Make sure the file gets enlarged after we allocated space: */
660         fstat64(fd, &sbuf);
661         if (new_len > sbuf.st_size)
662                 ftruncate64(fd, new_len);
663         return 0;
664 #else
665         return ENOSYS;
666 #endif
667 }
668
669 /*******************************************************************
670  An fallocate() function that matches the semantics of the Linux one.
671 ********************************************************************/
672
673 #ifdef HAVE_LINUX_FALLOC_H
674 #include <linux/falloc.h>
675 #endif
676
677 int sys_fallocate(int fd, enum vfs_fallocate_mode mode, SMB_OFF_T offset, SMB_OFF_T len)
678 {
679 #if defined(HAVE_LINUX_FALLOCATE64) || defined(HAVE_LINUX_FALLOCATE)
680         int lmode;
681         switch (mode) {
682         case VFS_FALLOCATE_EXTEND_SIZE:
683                 lmode = 0;
684                 break;
685         case VFS_FALLOCATE_KEEP_SIZE:
686                 lmode = FALLOC_FL_KEEP_SIZE;
687                 break;
688         default:
689                 errno = EINVAL;
690                 return -1;
691         }
692 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LINUX_FALLOCATE64)
693         return fallocate64(fd, lmode, offset, len);
694 #elif defined(HAVE_LINUX_FALLOCATE)
695         return fallocate(fd, lmode, offset, len);
696 #endif
697 #else
698         /* TODO - plumb in fallocate from other filesysetms like VXFS etc. JRA. */
699         errno = ENOSYS;
700         return -1;
701 #endif
702 }
703
704 /*******************************************************************
705  An ftruncate() wrapper that will deal with 64 bit filesizes.
706 ********************************************************************/
707
708 int sys_ftruncate(int fd, SMB_OFF_T offset)
709 {
710 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FTRUNCATE64)
711         return ftruncate64(fd, offset);
712 #else
713         return ftruncate(fd, offset);
714 #endif
715 }
716
717 /*******************************************************************
718  An lseek() wrapper that will deal with 64 bit filesizes.
719 ********************************************************************/
720
721 SMB_OFF_T sys_lseek(int fd, SMB_OFF_T offset, int whence)
722 {
723 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSEEK64)
724         return lseek64(fd, offset, whence);
725 #else
726         return lseek(fd, offset, whence);
727 #endif
728 }
729
730 /*******************************************************************
731  An fseek() wrapper that will deal with 64 bit filesizes.
732 ********************************************************************/
733
734 int sys_fseek(FILE *fp, SMB_OFF_T offset, int whence)
735 {
736 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEK64)
737         return fseek64(fp, offset, whence);
738 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEKO64)
739         return fseeko64(fp, offset, whence);
740 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEKO)
741         return fseeko(fp, offset, whence);
742 #else
743         return fseek(fp, offset, whence);
744 #endif
745 }
746
747 /*******************************************************************
748  An ftell() wrapper that will deal with 64 bit filesizes.
749 ********************************************************************/
750
751 SMB_OFF_T sys_ftell(FILE *fp)
752 {
753 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELL64)
754         return (SMB_OFF_T)ftell64(fp);
755 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELLO64)
756         return (SMB_OFF_T)ftello64(fp);
757 #else
758         return (SMB_OFF_T)ftell(fp);
759 #endif
760 }
761
762 /*******************************************************************
763  A creat() wrapper that will deal with 64 bit filesizes.
764 ********************************************************************/
765
766 int sys_creat(const char *path, mode_t mode)
767 {
768 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CREAT64)
769         return creat64(path, mode);
770 #else
771         /*
772          * If creat64 isn't defined then ensure we call a potential open64.
773          * JRA.
774          */
775         return sys_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
776 #endif
777 }
778
779 /*******************************************************************
780  An open() wrapper that will deal with 64 bit filesizes.
781 ********************************************************************/
782
783 int sys_open(const char *path, int oflag, mode_t mode)
784 {
785 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPEN64)
786         return open64(path, oflag, mode);
787 #else
788         return open(path, oflag, mode);
789 #endif
790 }
791
792 /*******************************************************************
793  An fopen() wrapper that will deal with 64 bit filesizes.
794 ********************************************************************/
795
796 FILE *sys_fopen(const char *path, const char *type)
797 {
798 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FOPEN64)
799         return fopen64(path, type);
800 #else
801         return fopen(path, type);
802 #endif
803 }
804
805
806 #if HAVE_KERNEL_SHARE_MODES
807 #ifndef LOCK_MAND
808 #define LOCK_MAND       32      /* This is a mandatory flock */
809 #define LOCK_READ       64      /* ... Which allows concurrent read operations */
810 #define LOCK_WRITE      128     /* ... Which allows concurrent write operations */
811 #define LOCK_RW         192     /* ... Which allows concurrent read & write ops */
812 #endif
813 #endif
814
815 /*******************************************************************
816  A flock() wrapper that will perform the kernel flock.
817 ********************************************************************/
818
819 void kernel_flock(int fd, uint32 share_mode, uint32 access_mask)
820 {
821 #if HAVE_KERNEL_SHARE_MODES
822         int kernel_mode = 0;
823         if (share_mode == FILE_SHARE_WRITE) {
824                 kernel_mode = LOCK_MAND|LOCK_WRITE;
825         } else if (share_mode == FILE_SHARE_READ) {
826                 kernel_mode = LOCK_MAND|LOCK_READ;
827         } else if (share_mode == FILE_SHARE_NONE) {
828                 kernel_mode = LOCK_MAND;
829         }
830         if (kernel_mode) {
831                 flock(fd, kernel_mode);
832         }
833 #endif
834         ;
835 }
836
837
838
839 /*******************************************************************
840  An opendir wrapper that will deal with 64 bit filesizes.
841 ********************************************************************/
842
843 SMB_STRUCT_DIR *sys_opendir(const char *name)
844 {
845 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPENDIR64)
846         return opendir64(name);
847 #else
848         return opendir(name);
849 #endif
850 }
851
852 /*******************************************************************
853  An fdopendir wrapper that will deal with 64 bit filesizes.
854  Ugly hack - we need dirfd for this to work correctly in the
855  calling code.. JRA.
856 ********************************************************************/
857
858 SMB_STRUCT_DIR *sys_fdopendir(int fd)
859 {
860 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FDOPENDIR64) && defined(HAVE_DIRFD)
861         return fdopendir64(fd);
862 #elif defined(HAVE_FDOPENDIR) && defined(HAVE_DIRFD)
863         return fdopendir(fd);
864 #else
865         errno = ENOSYS;
866         return NULL;
867 #endif
868 }
869
870 /*******************************************************************
871  A readdir wrapper that will deal with 64 bit filesizes.
872 ********************************************************************/
873
874 SMB_STRUCT_DIRENT *sys_readdir(SMB_STRUCT_DIR *dirp)
875 {
876 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_READDIR64)
877         return readdir64(dirp);
878 #else
879         return readdir(dirp);
880 #endif
881 }
882
883 /*******************************************************************
884  A seekdir wrapper that will deal with 64 bit filesizes.
885 ********************************************************************/
886
887 void sys_seekdir(SMB_STRUCT_DIR *dirp, long offset)
888 {
889 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_SEEKDIR64)
890         seekdir64(dirp, offset);
891 #else
892         seekdir(dirp, offset);
893 #endif
894 }
895
896 /*******************************************************************
897  A telldir wrapper that will deal with 64 bit filesizes.
898 ********************************************************************/
899
900 long sys_telldir(SMB_STRUCT_DIR *dirp)
901 {
902 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_TELLDIR64)
903         return (long)telldir64(dirp);
904 #else
905         return (long)telldir(dirp);
906 #endif
907 }
908
909 /*******************************************************************
910  A rewinddir wrapper that will deal with 64 bit filesizes.
911 ********************************************************************/
912
913 void sys_rewinddir(SMB_STRUCT_DIR *dirp)
914 {
915 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_REWINDDIR64)
916         rewinddir64(dirp);
917 #else
918         rewinddir(dirp);
919 #endif
920 }
921
922 /*******************************************************************
923  A close wrapper that will deal with 64 bit filesizes.
924 ********************************************************************/
925
926 int sys_closedir(SMB_STRUCT_DIR *dirp)
927 {
928 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CLOSEDIR64)
929         return closedir64(dirp);
930 #else
931         return closedir(dirp);
932 #endif
933 }
934
935 /*******************************************************************
936  An mknod() wrapper that will deal with 64 bit filesizes.
937 ********************************************************************/
938
939 int sys_mknod(const char *path, mode_t mode, SMB_DEV_T dev)
940 {
941 #if defined(HAVE_MKNOD) || defined(HAVE_MKNOD64)
942 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_MKNOD64) && defined(HAVE_DEV64_T)
943         return mknod64(path, mode, dev);
944 #else
945         return mknod(path, mode, dev);
946 #endif
947 #else
948         /* No mknod system call. */
949         errno = ENOSYS;
950         return -1;
951 #endif
952 }
953
954 /*******************************************************************
955 The wait() calls vary between systems
956 ********************************************************************/
957
958 int sys_waitpid(pid_t pid,int *status,int options)
959 {
960 #ifdef HAVE_WAITPID
961         return waitpid(pid,status,options);
962 #else /* HAVE_WAITPID */
963         return wait4(pid, status, options, NULL);
964 #endif /* HAVE_WAITPID */
965 }
966
967 /*******************************************************************
968  System wrapper for getwd. Always returns MALLOC'ed memory, or NULL
969  on error (malloc fail usually).
970 ********************************************************************/
971
972 char *sys_getwd(void)
973 {
974 #ifdef GETCWD_TAKES_NULL
975         return getcwd(NULL, 0);
976 #elif HAVE_GETCWD
977         char *wd = NULL, *s = NULL;
978         size_t allocated = PATH_MAX;
979
980         while (1) {
981                 s = SMB_REALLOC_ARRAY(s, char, allocated);
982                 if (s == NULL) {
983                         return NULL;
984                 }
985                 wd = getcwd(s, allocated);
986                 if (wd) {
987                         break;
988                 }
989                 if (errno != ERANGE) {
990                         SAFE_FREE(s);
991                         break;
992                 }
993                 allocated *= 2;
994                 if (allocated < PATH_MAX) {
995                         SAFE_FREE(s);
996                         break;
997                 }
998         }
999         return wd;
1000 #else
1001         char *s = SMB_MALLOC_ARRAY(char, PATH_MAX);
1002         if (s == NULL) {
1003                 return NULL;
1004         }
1005         return getwd(s);
1006 #endif
1007 }
1008
1009 #if defined(HAVE_POSIX_CAPABILITIES)
1010
1011 /**************************************************************************
1012  Try and abstract process capabilities (for systems that have them).
1013 ****************************************************************************/
1014
1015 /* Set the POSIX capabilities needed for the given purpose into the effective
1016  * capability set of the current process. Make sure they are always removed
1017  * from the inheritable set, because there is no circumstance in which our
1018  * children should inherit our elevated privileges.
1019  */
1020 static bool set_process_capability(enum smbd_capability capability,
1021                                    bool enable)
1022 {
1023         cap_value_t cap_vals[2] = {0};
1024         int num_cap_vals = 0;
1025
1026         cap_t cap;
1027
1028 #if defined(HAVE_PRCTL) && defined(PR_GET_KEEPCAPS) && defined(PR_SET_KEEPCAPS)
1029         /* On Linux, make sure that any capabilities we grab are sticky
1030          * across UID changes. We expect that this would allow us to keep both
1031          * the effective and permitted capability sets, but as of circa 2.6.16,
1032          * only the permitted set is kept. It is a bug (which we work around)
1033          * that the effective set is lost, but we still require the effective
1034          * set to be kept.
1035          */
1036         if (!prctl(PR_GET_KEEPCAPS)) {
1037                 prctl(PR_SET_KEEPCAPS, 1);
1038         }
1039 #endif
1040
1041         cap = cap_get_proc();
1042         if (cap == NULL) {
1043                 DEBUG(0,("set_process_capability: cap_get_proc failed: %s\n",
1044                         strerror(errno)));
1045                 return False;
1046         }
1047
1048         switch (capability) {
1049                 case KERNEL_OPLOCK_CAPABILITY:
1050 #ifdef CAP_NETWORK_MGT
1051                         /* IRIX has CAP_NETWORK_MGT for oplocks. */
1052                         cap_vals[num_cap_vals++] = CAP_NETWORK_MGT;
1053 #endif
1054                         break;
1055                 case DMAPI_ACCESS_CAPABILITY:
1056 #ifdef CAP_DEVICE_MGT
1057                         /* IRIX has CAP_DEVICE_MGT for DMAPI access. */
1058                         cap_vals[num_cap_vals++] = CAP_DEVICE_MGT;
1059 #elif CAP_MKNOD
1060                         /* Linux has CAP_MKNOD for DMAPI access. */
1061                         cap_vals[num_cap_vals++] = CAP_MKNOD;
1062 #endif
1063                         break;
1064                 case LEASE_CAPABILITY:
1065 #ifdef CAP_LEASE
1066                         cap_vals[num_cap_vals++] = CAP_LEASE;
1067 #endif
1068                         break;
1069         }
1070
1071         SMB_ASSERT(num_cap_vals <= ARRAY_SIZE(cap_vals));
1072
1073         if (num_cap_vals == 0) {
1074                 cap_free(cap);
1075                 return True;
1076         }
1077
1078         cap_set_flag(cap, CAP_EFFECTIVE, num_cap_vals, cap_vals,
1079                 enable ? CAP_SET : CAP_CLEAR);
1080
1081         /* We never want to pass capabilities down to our children, so make
1082          * sure they are not inherited.
1083          */
1084         cap_set_flag(cap, CAP_INHERITABLE, num_cap_vals, cap_vals, CAP_CLEAR);
1085
1086         if (cap_set_proc(cap) == -1) {
1087                 DEBUG(0, ("set_process_capability: cap_set_proc failed: %s\n",
1088                         strerror(errno)));
1089                 cap_free(cap);
1090                 return False;
1091         }
1092
1093         cap_free(cap);
1094         return True;
1095 }
1096
1097 #endif /* HAVE_POSIX_CAPABILITIES */
1098
1099 /****************************************************************************
1100  Gain the oplock capability from the kernel if possible.
1101 ****************************************************************************/
1102
1103 void set_effective_capability(enum smbd_capability capability)
1104 {
1105 #if defined(HAVE_POSIX_CAPABILITIES)
1106         set_process_capability(capability, True);
1107 #endif /* HAVE_POSIX_CAPABILITIES */
1108 }
1109
1110 void drop_effective_capability(enum smbd_capability capability)
1111 {
1112 #if defined(HAVE_POSIX_CAPABILITIES)
1113         set_process_capability(capability, False);
1114 #endif /* HAVE_POSIX_CAPABILITIES */
1115 }
1116
1117 /**************************************************************************
1118  Wrapper for random().
1119 ****************************************************************************/
1120
1121 long sys_random(void)
1122 {
1123 #if defined(HAVE_RANDOM)
1124         return (long)random();
1125 #elif defined(HAVE_RAND)
1126         return (long)rand();
1127 #else
1128         DEBUG(0,("Error - no random function available !\n"));
1129         exit(1);
1130 #endif
1131 }
1132
1133 /**************************************************************************
1134  Wrapper for srandom().
1135 ****************************************************************************/
1136
1137 void sys_srandom(unsigned int seed)
1138 {
1139 #if defined(HAVE_SRANDOM)
1140         srandom(seed);
1141 #elif defined(HAVE_SRAND)
1142         srand(seed);
1143 #else
1144         DEBUG(0,("Error - no srandom function available !\n"));
1145         exit(1);
1146 #endif
1147 }
1148
1149 #ifndef NGROUPS_MAX
1150 #define NGROUPS_MAX 32 /* Guess... */
1151 #endif
1152
1153 /**************************************************************************
1154  Returns equivalent to NGROUPS_MAX - using sysconf if needed.
1155 ****************************************************************************/
1156
1157 int groups_max(void)
1158 {
1159 #if defined(SYSCONF_SC_NGROUPS_MAX)
1160         int ret = sysconf(_SC_NGROUPS_MAX);
1161         return (ret == -1) ? NGROUPS_MAX : ret;
1162 #else
1163         return NGROUPS_MAX;
1164 #endif
1165 }
1166
1167 /**************************************************************************
1168  Wrap setgroups and getgroups for systems that declare getgroups() as
1169  returning an array of gid_t, but actuall return an array of int.
1170 ****************************************************************************/
1171
1172 #if defined(HAVE_BROKEN_GETGROUPS)
1173
1174 #ifdef HAVE_BROKEN_GETGROUPS
1175 #define GID_T int
1176 #else
1177 #define GID_T gid_t
1178 #endif
1179
1180 static int sys_broken_getgroups(int setlen, gid_t *gidset)
1181 {
1182         GID_T gid;
1183         GID_T *group_list;
1184         int i, ngroups;
1185
1186         if(setlen == 0) {
1187                 return getgroups(setlen, &gid);
1188         }
1189
1190         /*
1191          * Broken case. We need to allocate a
1192          * GID_T array of size setlen.
1193          */
1194
1195         if(setlen < 0) {
1196                 errno = EINVAL; 
1197                 return -1;
1198         } 
1199
1200         if (setlen == 0)
1201                 setlen = groups_max();
1202
1203         if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
1204                 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
1205                 return -1;
1206         }
1207
1208         if((ngroups = getgroups(setlen, group_list)) < 0) {
1209                 int saved_errno = errno;
1210                 SAFE_FREE(group_list);
1211                 errno = saved_errno;
1212                 return -1;
1213         }
1214
1215         for(i = 0; i < ngroups; i++)
1216                 gidset[i] = (gid_t)group_list[i];
1217
1218         SAFE_FREE(group_list);
1219         return ngroups;
1220 }
1221
1222 static int sys_broken_setgroups(int setlen, gid_t *gidset)
1223 {
1224         GID_T *group_list;
1225         int i ; 
1226
1227         if (setlen == 0)
1228                 return 0 ;
1229
1230         if (setlen < 0 || setlen > groups_max()) {
1231                 errno = EINVAL; 
1232                 return -1;   
1233         }
1234
1235         /*
1236          * Broken case. We need to allocate a
1237          * GID_T array of size setlen.
1238          */
1239
1240         if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
1241                 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
1242                 return -1;    
1243         }
1244
1245         for(i = 0; i < setlen; i++) 
1246                 group_list[i] = (GID_T) gidset[i]; 
1247
1248         if(setgroups(setlen, group_list) != 0) {
1249                 int saved_errno = errno;
1250                 SAFE_FREE(group_list);
1251                 errno = saved_errno;
1252                 return -1;
1253         }
1254
1255         SAFE_FREE(group_list);
1256         return 0 ;
1257 }
1258
1259 #endif /* HAVE_BROKEN_GETGROUPS */
1260
1261 /* This is a list of systems that require the first GID passed to setgroups(2)
1262  * to be the effective GID. If your system is one of these, add it here.
1263  */
1264 #if defined (FREEBSD) || defined (DARWINOS)
1265 #define USE_BSD_SETGROUPS
1266 #endif
1267
1268 #if defined(USE_BSD_SETGROUPS)
1269 /* Depending on the particular BSD implementation, the first GID that is
1270  * passed to setgroups(2) will either be ignored or will set the credential's
1271  * effective GID. In either case, the right thing to do is to guarantee that
1272  * gidset[0] is the effective GID.
1273  */
1274 static int sys_bsd_setgroups(gid_t primary_gid, int setlen, const gid_t *gidset)
1275 {
1276         gid_t *new_gidset = NULL;
1277         int max;
1278         int ret;
1279
1280         /* setgroups(2) will fail with EINVAL if we pass too many groups. */
1281         max = groups_max();
1282
1283         /* No group list, just make sure we are setting the efective GID. */
1284         if (setlen == 0) {
1285                 return setgroups(1, &primary_gid);
1286         }
1287
1288         /* If the primary gid is not the first array element, grow the array
1289          * and insert it at the front.
1290          */
1291         if (gidset[0] != primary_gid) {
1292                 new_gidset = SMB_MALLOC_ARRAY(gid_t, setlen + 1);
1293                 if (new_gidset == NULL) {
1294                         return -1;
1295                 }
1296
1297                 memcpy(new_gidset + 1, gidset, (setlen * sizeof(gid_t)));
1298                 new_gidset[0] = primary_gid;
1299                 setlen++;
1300         }
1301
1302         if (setlen > max) {
1303                 DEBUG(3, ("forced to truncate group list from %d to %d\n",
1304                         setlen, max));
1305                 setlen = max;
1306         }
1307
1308 #if defined(HAVE_BROKEN_GETGROUPS)
1309         ret = sys_broken_setgroups(setlen, new_gidset ? new_gidset : gidset);
1310 #else
1311         ret = setgroups(setlen, new_gidset ? new_gidset : gidset);
1312 #endif
1313
1314         if (new_gidset) {
1315                 int errsav = errno;
1316                 SAFE_FREE(new_gidset);
1317                 errno = errsav;
1318         }
1319
1320         return ret;
1321 }
1322
1323 #endif /* USE_BSD_SETGROUPS */
1324
1325 /**************************************************************************
1326  Wrapper for getgroups. Deals with broken (int) case.
1327 ****************************************************************************/
1328
1329 int sys_getgroups(int setlen, gid_t *gidset)
1330 {
1331 #if defined(HAVE_BROKEN_GETGROUPS)
1332         return sys_broken_getgroups(setlen, gidset);
1333 #else
1334         return getgroups(setlen, gidset);
1335 #endif
1336 }
1337
1338 /**************************************************************************
1339  Wrapper for setgroups. Deals with broken (int) case and BSD case.
1340 ****************************************************************************/
1341
1342 int sys_setgroups(gid_t UNUSED(primary_gid), int setlen, gid_t *gidset)
1343 {
1344 #if !defined(HAVE_SETGROUPS)
1345         errno = ENOSYS;
1346         return -1;
1347 #endif /* HAVE_SETGROUPS */
1348
1349 #if defined(USE_BSD_SETGROUPS)
1350         return sys_bsd_setgroups(primary_gid, setlen, gidset);
1351 #elif defined(HAVE_BROKEN_GETGROUPS)
1352         return sys_broken_setgroups(setlen, gidset);
1353 #else
1354         return setgroups(setlen, gidset);
1355 #endif
1356 }
1357
1358 /**************************************************************************
1359  Extract a command into an arg list.
1360 ****************************************************************************/
1361
1362 static char **extract_args(TALLOC_CTX *mem_ctx, const char *command)
1363 {
1364         char *trunc_cmd;
1365         char *saveptr;
1366         char *ptr;
1367         int argcl;
1368         char **argl = NULL;
1369         int i;
1370
1371         if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1372                 DEBUG(0, ("talloc failed\n"));
1373                 goto nomem;
1374         }
1375
1376         if(!(ptr = strtok_r(trunc_cmd, " \t", &saveptr))) {
1377                 TALLOC_FREE(trunc_cmd);
1378                 errno = EINVAL;
1379                 return NULL;
1380         }
1381
1382         /*
1383          * Count the args.
1384          */
1385
1386         for( argcl = 1; ptr; ptr = strtok_r(NULL, " \t", &saveptr))
1387                 argcl++;
1388
1389         TALLOC_FREE(trunc_cmd);
1390
1391         if (!(argl = talloc_array(mem_ctx, char *, argcl + 1))) {
1392                 goto nomem;
1393         }
1394
1395         /*
1396          * Now do the extraction.
1397          */
1398
1399         if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1400                 goto nomem;
1401         }
1402
1403         ptr = strtok_r(trunc_cmd, " \t", &saveptr);
1404         i = 0;
1405
1406         if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1407                 goto nomem;
1408         }
1409
1410         while((ptr = strtok_r(NULL, " \t", &saveptr)) != NULL) {
1411
1412                 if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1413                         goto nomem;
1414                 }
1415         }
1416
1417         argl[i++] = NULL;
1418         TALLOC_FREE(trunc_cmd);
1419         return argl;
1420
1421  nomem:
1422         DEBUG(0, ("talloc failed\n"));
1423         TALLOC_FREE(trunc_cmd);
1424         TALLOC_FREE(argl);
1425         errno = ENOMEM;
1426         return NULL;
1427 }
1428
1429 /**************************************************************************
1430  Wrapper for popen. Safer as it doesn't search a path.
1431  Modified from the glibc sources.
1432  modified by tridge to return a file descriptor. We must kick our FILE* habit
1433 ****************************************************************************/
1434
1435 typedef struct _popen_list
1436 {
1437         int fd;
1438         pid_t child_pid;
1439         struct _popen_list *next;
1440 } popen_list;
1441
1442 static popen_list *popen_chain;
1443
1444 int sys_popen(const char *command)
1445 {
1446         int parent_end, child_end;
1447         int pipe_fds[2];
1448         popen_list *entry = NULL;
1449         char **argl = NULL;
1450
1451         if (pipe(pipe_fds) < 0)
1452                 return -1;
1453
1454         parent_end = pipe_fds[0];
1455         child_end = pipe_fds[1];
1456
1457         if (!*command) {
1458                 errno = EINVAL;
1459                 goto err_exit;
1460         }
1461
1462         if((entry = SMB_MALLOC_P(popen_list)) == NULL)
1463                 goto err_exit;
1464
1465         ZERO_STRUCTP(entry);
1466
1467         /*
1468          * Extract the command and args into a NULL terminated array.
1469          */
1470
1471         if(!(argl = extract_args(NULL, command)))
1472                 goto err_exit;
1473
1474         entry->child_pid = sys_fork();
1475
1476         if (entry->child_pid == -1) {
1477                 goto err_exit;
1478         }
1479
1480         if (entry->child_pid == 0) {
1481
1482                 /*
1483                  * Child !
1484                  */
1485
1486                 int child_std_end = STDOUT_FILENO;
1487                 popen_list *p;
1488
1489                 close(parent_end);
1490                 if (child_end != child_std_end) {
1491                         dup2 (child_end, child_std_end);
1492                         close (child_end);
1493                 }
1494
1495                 /*
1496                  * POSIX.2:  "popen() shall ensure that any streams from previous
1497                  * popen() calls that remain open in the parent process are closed
1498                  * in the new child process."
1499                  */
1500
1501                 for (p = popen_chain; p; p = p->next)
1502                         close(p->fd);
1503
1504                 execv(argl[0], argl);
1505                 _exit (127);
1506         }
1507
1508         /*
1509          * Parent.
1510          */
1511
1512         close (child_end);
1513         TALLOC_FREE(argl);
1514
1515         /* Link into popen_chain. */
1516         entry->next = popen_chain;
1517         popen_chain = entry;
1518         entry->fd = parent_end;
1519
1520         return entry->fd;
1521
1522 err_exit:
1523
1524         SAFE_FREE(entry);
1525         TALLOC_FREE(argl);
1526         close(pipe_fds[0]);
1527         close(pipe_fds[1]);
1528         return -1;
1529 }
1530
1531 /**************************************************************************
1532  Wrapper for pclose. Modified from the glibc sources.
1533 ****************************************************************************/
1534
1535 int sys_pclose(int fd)
1536 {
1537         int wstatus;
1538         popen_list **ptr = &popen_chain;
1539         popen_list *entry = NULL;
1540         pid_t wait_pid;
1541         int status = -1;
1542
1543         /* Unlink from popen_chain. */
1544         for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
1545                 if ((*ptr)->fd == fd) {
1546                         entry = *ptr;
1547                         *ptr = (*ptr)->next;
1548                         status = 0;
1549                         break;
1550                 }
1551         }
1552
1553         if (status < 0 || close(entry->fd) < 0)
1554                 return -1;
1555
1556         /*
1557          * As Samba is catching and eating child process
1558          * exits we don't really care about the child exit
1559          * code, a -1 with errno = ECHILD will do fine for us.
1560          */
1561
1562         do {
1563                 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
1564         } while (wait_pid == -1 && errno == EINTR);
1565
1566         SAFE_FREE(entry);
1567
1568         if (wait_pid == -1)
1569                 return -1;
1570         return wstatus;
1571 }
1572
1573 /**************************************************************************
1574  Wrapper for Admin Logs.
1575 ****************************************************************************/
1576
1577  void sys_adminlog(int priority, const char *format_str, ...) 
1578 {
1579         va_list ap;
1580         int ret;
1581         char *msgbuf = NULL;
1582
1583         va_start( ap, format_str );
1584         ret = vasprintf( &msgbuf, format_str, ap );
1585         va_end( ap );
1586
1587         if (ret == -1)
1588                 return;
1589
1590 #if defined(HAVE_SYSLOG)
1591         syslog( priority, "%s", msgbuf );
1592 #else
1593         DEBUG(0,("%s", msgbuf ));
1594 #endif
1595         SAFE_FREE(msgbuf);
1596 }
1597
1598 /******** Solaris EA helper function prototypes ********/
1599 #ifdef HAVE_ATTROPEN
1600 #define SOLARIS_ATTRMODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP
1601 static int solaris_write_xattr(int attrfd, const char *value, size_t size);
1602 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size);
1603 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size);
1604 static int solaris_unlinkat(int attrdirfd, const char *name);
1605 static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode);
1606 static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode);
1607 #endif
1608
1609 /**************************************************************************
1610  Wrappers for extented attribute calls. Based on the Linux package with
1611  support for IRIX and (Net|Free)BSD also. Expand as other systems have them.
1612 ****************************************************************************/
1613
1614 ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t size)
1615 {
1616 #if defined(HAVE_GETXATTR)
1617 #ifndef XATTR_ADD_OPT
1618         return getxattr(path, name, value, size);
1619 #else
1620         int options = 0;
1621         return getxattr(path, name, value, size, 0, options);
1622 #endif
1623 #elif defined(HAVE_GETEA)
1624         return getea(path, name, value, size);
1625 #elif defined(HAVE_EXTATTR_GET_FILE)
1626         char *s;
1627         ssize_t retval;
1628         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
1629                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1630         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1631         /*
1632          * The BSD implementation has a nasty habit of silently truncating
1633          * the returned value to the size of the buffer, so we have to check
1634          * that the buffer is large enough to fit the returned value.
1635          */
1636         if((retval=extattr_get_file(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1637                 if(retval > size) {
1638                         errno = ERANGE;
1639                         return -1;
1640                 }
1641                 if((retval=extattr_get_file(path, attrnamespace, attrname, value, size)) >= 0)
1642                         return retval;
1643         }
1644
1645         DEBUG(10,("sys_getxattr: extattr_get_file() failed with: %s\n", strerror(errno)));
1646         return -1;
1647 #elif defined(HAVE_ATTR_GET)
1648         int retval, flags = 0;
1649         int valuelength = (int)size;
1650         char *attrname = strchr(name,'.') + 1;
1651
1652         if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1653
1654         retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1655
1656         return retval ? retval : valuelength;
1657 #elif defined(HAVE_ATTROPEN)
1658         ssize_t ret = -1;
1659         int attrfd = solaris_attropen(path, name, O_RDONLY, 0);
1660         if (attrfd >= 0) {
1661                 ret = solaris_read_xattr(attrfd, value, size);
1662                 close(attrfd);
1663         }
1664         return ret;
1665 #else
1666         errno = ENOSYS;
1667         return -1;
1668 #endif
1669 }
1670
1671 ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t size)
1672 {
1673 #if defined(HAVE_LGETXATTR)
1674         return lgetxattr(path, name, value, size);
1675 #elif defined(HAVE_GETXATTR) && defined(XATTR_ADD_OPT)
1676         int options = XATTR_NOFOLLOW;
1677         return getxattr(path, name, value, size, 0, options);
1678 #elif defined(HAVE_LGETEA)
1679         return lgetea(path, name, value, size);
1680 #elif defined(HAVE_EXTATTR_GET_LINK)
1681         char *s;
1682         ssize_t retval;
1683         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
1684                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1685         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1686
1687         if((retval=extattr_get_link(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1688                 if(retval > size) {
1689                         errno = ERANGE;
1690                         return -1;
1691                 }
1692                 if((retval=extattr_get_link(path, attrnamespace, attrname, value, size)) >= 0)
1693                         return retval;
1694         }
1695
1696         DEBUG(10,("sys_lgetxattr: extattr_get_link() failed with: %s\n", strerror(errno)));
1697         return -1;
1698 #elif defined(HAVE_ATTR_GET)
1699         int retval, flags = ATTR_DONTFOLLOW;
1700         int valuelength = (int)size;
1701         char *attrname = strchr(name,'.') + 1;
1702
1703         if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1704
1705         retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1706
1707         return retval ? retval : valuelength;
1708 #elif defined(HAVE_ATTROPEN)
1709         ssize_t ret = -1;
1710         int attrfd = solaris_attropen(path, name, O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1711         if (attrfd >= 0) {
1712                 ret = solaris_read_xattr(attrfd, value, size);
1713                 close(attrfd);
1714         }
1715         return ret;
1716 #else
1717         errno = ENOSYS;
1718         return -1;
1719 #endif
1720 }
1721
1722 ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size)
1723 {
1724 #if defined(HAVE_FGETXATTR)
1725 #ifndef XATTR_ADD_OPT
1726         return fgetxattr(filedes, name, value, size);
1727 #else
1728         int options = 0;
1729         return fgetxattr(filedes, name, value, size, 0, options);
1730 #endif
1731 #elif defined(HAVE_FGETEA)
1732         return fgetea(filedes, name, value, size);
1733 #elif defined(HAVE_EXTATTR_GET_FD)
1734         char *s;
1735         ssize_t retval;
1736         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
1737                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1738         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1739
1740         if((retval=extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0)) >= 0) {
1741                 if(retval > size) {
1742                         errno = ERANGE;
1743                         return -1;
1744                 }
1745                 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, value, size)) >= 0)
1746                         return retval;
1747         }
1748
1749         DEBUG(10,("sys_fgetxattr: extattr_get_fd() failed with: %s\n", strerror(errno)));
1750         return -1;
1751 #elif defined(HAVE_ATTR_GETF)
1752         int retval, flags = 0;
1753         int valuelength = (int)size;
1754         char *attrname = strchr(name,'.') + 1;
1755
1756         if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1757
1758         retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags);
1759
1760         return retval ? retval : valuelength;
1761 #elif defined(HAVE_ATTROPEN)
1762         ssize_t ret = -1;
1763         int attrfd = solaris_openat(filedes, name, O_RDONLY|O_XATTR, 0);
1764         if (attrfd >= 0) {
1765                 ret = solaris_read_xattr(attrfd, value, size);
1766                 close(attrfd);
1767         }
1768         return ret;
1769 #else
1770         errno = ENOSYS;
1771         return -1;
1772 #endif
1773 }
1774
1775 #if defined(HAVE_EXTATTR_LIST_FILE)
1776
1777 #define EXTATTR_PREFIX(s)       (s), (sizeof((s))-1)
1778
1779 static struct {
1780         int space;
1781         const char *name;
1782         size_t len;
1783
1784 extattr[] = {
1785         { EXTATTR_NAMESPACE_SYSTEM, EXTATTR_PREFIX("system.") },
1786         { EXTATTR_NAMESPACE_USER, EXTATTR_PREFIX("user.") },
1787 };
1788
1789 typedef union {
1790         const char *path;
1791         int filedes;
1792 } extattr_arg;
1793
1794 static ssize_t bsd_attr_list (int type, extattr_arg arg, char *list, size_t size)
1795 {
1796         ssize_t list_size, total_size = 0;
1797         int i, t, len;
1798         char *buf;
1799         /* Iterate through extattr(2) namespaces */
1800         for(t = 0; t < (sizeof(extattr)/sizeof(extattr[0])); t++) {
1801                 switch(type) {
1802 #if defined(HAVE_EXTATTR_LIST_FILE)
1803                         case 0:
1804                                 list_size = extattr_list_file(arg.path, extattr[t].space, list, size);
1805                                 break;
1806 #endif
1807 #if defined(HAVE_EXTATTR_LIST_LINK)
1808                         case 1:
1809                                 list_size = extattr_list_link(arg.path, extattr[t].space, list, size);
1810                                 break;
1811 #endif
1812 #if defined(HAVE_EXTATTR_LIST_FD)
1813                         case 2:
1814                                 list_size = extattr_list_fd(arg.filedes, extattr[t].space, list, size);
1815                                 break;
1816 #endif
1817                         default:
1818                                 errno = ENOSYS;
1819                                 return -1;
1820                 }
1821                 /* Some error happend. Errno should be set by the previous call */
1822                 if(list_size < 0)
1823                         return -1;
1824                 /* No attributes */
1825                 if(list_size == 0)
1826                         continue;
1827                 /* XXX: Call with an empty buffer may be used to calculate
1828                    necessary buffer size. Unfortunately, we can't say, how
1829                    many attributes were returned, so here is the potential
1830                    problem with the emulation.
1831                 */
1832                 if(list == NULL) {
1833                         /* Take the worse case of one char attribute names - 
1834                            two bytes per name plus one more for sanity.
1835                         */
1836                         total_size += list_size + (list_size/2 + 1)*extattr[t].len;
1837                         continue;
1838                 }
1839                 /* Count necessary offset to fit namespace prefixes */
1840                 len = 0;
1841                 for(i = 0; i < list_size; i += list[i] + 1)
1842                         len += extattr[t].len;
1843
1844                 total_size += list_size + len;
1845                 /* Buffer is too small to fit the results */
1846                 if(total_size > size) {
1847                         errno = ERANGE;
1848                         return -1;
1849                 }
1850                 /* Shift results back, so we can prepend prefixes */
1851                 buf = (char *)memmove(list + len, list, list_size);
1852
1853                 for(i = 0; i < list_size; i += len + 1) {
1854                         len = buf[i];
1855                         strncpy(list, extattr[t].name, extattr[t].len + 1);
1856                         list += extattr[t].len;
1857                         strncpy(list, buf + i + 1, len);
1858                         list[len] = '\0';
1859                         list += len + 1;
1860                 }
1861                 size -= total_size;
1862         }
1863         return total_size;
1864 }
1865
1866 #endif
1867
1868 #if defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1869 static char attr_buffer[ATTR_MAX_VALUELEN];
1870
1871 static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags)
1872 {
1873         int retval = 0, index;
1874         attrlist_cursor_t *cursor = 0;
1875         int total_size = 0;
1876         attrlist_t * al = (attrlist_t *)attr_buffer;
1877         attrlist_ent_t *ae;
1878         size_t ent_size, left = size;
1879         char *bp = list;
1880
1881         while (True) {
1882             if (filedes)
1883                 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1884             else
1885                 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1886             if (retval) break;
1887             for (index = 0; index < al->al_count; index++) {
1888                 ae = ATTR_ENTRY(attr_buffer, index);
1889                 ent_size = strlen(ae->a_name) + sizeof("user.");
1890                 if (left >= ent_size) {
1891                     strncpy(bp, "user.", sizeof("user."));
1892                     strncat(bp, ae->a_name, ent_size - sizeof("user."));
1893                     bp += ent_size;
1894                     left -= ent_size;
1895                 } else if (size) {
1896                     errno = ERANGE;
1897                     retval = -1;
1898                     break;
1899                 }
1900                 total_size += ent_size;
1901             }
1902             if (al->al_more == 0) break;
1903         }
1904         if (retval == 0) {
1905             flags |= ATTR_ROOT;
1906             cursor = 0;
1907             while (True) {
1908                 if (filedes)
1909                     retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1910                 else
1911                     retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1912                 if (retval) break;
1913                 for (index = 0; index < al->al_count; index++) {
1914                     ae = ATTR_ENTRY(attr_buffer, index);
1915                     ent_size = strlen(ae->a_name) + sizeof("system.");
1916                     if (left >= ent_size) {
1917                         strncpy(bp, "system.", sizeof("system."));
1918                         strncat(bp, ae->a_name, ent_size - sizeof("system."));
1919                         bp += ent_size;
1920                         left -= ent_size;
1921                     } else if (size) {
1922                         errno = ERANGE;
1923                         retval = -1;
1924                         break;
1925                     }
1926                     total_size += ent_size;
1927                 }
1928                 if (al->al_more == 0) break;
1929             }
1930         }
1931         return (ssize_t)(retval ? retval : total_size);
1932 }
1933
1934 #endif
1935
1936 ssize_t sys_listxattr (const char *path, char *list, size_t size)
1937 {
1938 #if defined(HAVE_LISTXATTR)
1939 #ifndef XATTR_ADD_OPT
1940         return listxattr(path, list, size);
1941 #else
1942         int options = 0;
1943         return listxattr(path, list, size, options);
1944 #endif
1945 #elif defined(HAVE_LISTEA)
1946         return listea(path, list, size);
1947 #elif defined(HAVE_EXTATTR_LIST_FILE)
1948         extattr_arg arg;
1949         arg.path = path;
1950         return bsd_attr_list(0, arg, list, size);
1951 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1952         return irix_attr_list(path, 0, list, size, 0);
1953 #elif defined(HAVE_ATTROPEN)
1954         ssize_t ret = -1;
1955         int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
1956         if (attrdirfd >= 0) {
1957                 ret = solaris_list_xattr(attrdirfd, list, size);
1958                 close(attrdirfd);
1959         }
1960         return ret;
1961 #else
1962         errno = ENOSYS;
1963         return -1;
1964 #endif
1965 }
1966
1967 ssize_t sys_llistxattr (const char *path, char *list, size_t size)
1968 {
1969 #if defined(HAVE_LLISTXATTR)
1970         return llistxattr(path, list, size);
1971 #elif defined(HAVE_LISTXATTR) && defined(XATTR_ADD_OPT)
1972         int options = XATTR_NOFOLLOW;
1973         return listxattr(path, list, size, options);
1974 #elif defined(HAVE_LLISTEA)
1975         return llistea(path, list, size);
1976 #elif defined(HAVE_EXTATTR_LIST_LINK)
1977         extattr_arg arg;
1978         arg.path = path;
1979         return bsd_attr_list(1, arg, list, size);
1980 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1981         return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW);
1982 #elif defined(HAVE_ATTROPEN)
1983         ssize_t ret = -1;
1984         int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1985         if (attrdirfd >= 0) {
1986                 ret = solaris_list_xattr(attrdirfd, list, size);
1987                 close(attrdirfd);
1988         }
1989         return ret;
1990 #else
1991         errno = ENOSYS;
1992         return -1;
1993 #endif
1994 }
1995
1996 ssize_t sys_flistxattr (int filedes, char *list, size_t size)
1997 {
1998 #if defined(HAVE_FLISTXATTR)
1999 #ifndef XATTR_ADD_OPT
2000         return flistxattr(filedes, list, size);
2001 #else
2002         int options = 0;
2003         return flistxattr(filedes, list, size, options);
2004 #endif
2005 #elif defined(HAVE_FLISTEA)
2006         return flistea(filedes, list, size);
2007 #elif defined(HAVE_EXTATTR_LIST_FD)
2008         extattr_arg arg;
2009         arg.filedes = filedes;
2010         return bsd_attr_list(2, arg, list, size);
2011 #elif defined(HAVE_ATTR_LISTF)
2012         return irix_attr_list(NULL, filedes, list, size, 0);
2013 #elif defined(HAVE_ATTROPEN)
2014         ssize_t ret = -1;
2015         int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
2016         if (attrdirfd >= 0) {
2017                 ret = solaris_list_xattr(attrdirfd, list, size);
2018                 close(attrdirfd);
2019         }
2020         return ret;
2021 #else
2022         errno = ENOSYS;
2023         return -1;
2024 #endif
2025 }
2026
2027 int sys_removexattr (const char *path, const char *name)
2028 {
2029 #if defined(HAVE_REMOVEXATTR)
2030 #ifndef XATTR_ADD_OPT
2031         return removexattr(path, name);
2032 #else
2033         int options = 0;
2034         return removexattr(path, name, options);
2035 #endif
2036 #elif defined(HAVE_REMOVEEA)
2037         return removeea(path, name);
2038 #elif defined(HAVE_EXTATTR_DELETE_FILE)
2039         char *s;
2040         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
2041                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2042         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2043
2044         return extattr_delete_file(path, attrnamespace, attrname);
2045 #elif defined(HAVE_ATTR_REMOVE)
2046         int flags = 0;
2047         char *attrname = strchr(name,'.') + 1;
2048
2049         if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
2050
2051         return attr_remove(path, attrname, flags);
2052 #elif defined(HAVE_ATTROPEN)
2053         int ret = -1;
2054         int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
2055         if (attrdirfd >= 0) {
2056                 ret = solaris_unlinkat(attrdirfd, name);
2057                 close(attrdirfd);
2058         }
2059         return ret;
2060 #else
2061         errno = ENOSYS;
2062         return -1;
2063 #endif
2064 }
2065
2066 int sys_lremovexattr (const char *path, const char *name)
2067 {
2068 #if defined(HAVE_LREMOVEXATTR)
2069         return lremovexattr(path, name);
2070 #elif defined(HAVE_REMOVEXATTR) && defined(XATTR_ADD_OPT)
2071         int options = XATTR_NOFOLLOW;
2072         return removexattr(path, name, options);
2073 #elif defined(HAVE_LREMOVEEA)
2074         return lremoveea(path, name);
2075 #elif defined(HAVE_EXTATTR_DELETE_LINK)
2076         char *s;
2077         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
2078                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2079         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2080
2081         return extattr_delete_link(path, attrnamespace, attrname);
2082 #elif defined(HAVE_ATTR_REMOVE)
2083         int flags = ATTR_DONTFOLLOW;
2084         char *attrname = strchr(name,'.') + 1;
2085
2086         if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
2087
2088         return attr_remove(path, attrname, flags);
2089 #elif defined(HAVE_ATTROPEN)
2090         int ret = -1;
2091         int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
2092         if (attrdirfd >= 0) {
2093                 ret = solaris_unlinkat(attrdirfd, name);
2094                 close(attrdirfd);
2095         }
2096         return ret;
2097 #else
2098         errno = ENOSYS;
2099         return -1;
2100 #endif
2101 }
2102
2103 int sys_fremovexattr (int filedes, const char *name)
2104 {
2105 #if defined(HAVE_FREMOVEXATTR)
2106 #ifndef XATTR_ADD_OPT
2107         return fremovexattr(filedes, name);
2108 #else
2109         int options = 0;
2110         return fremovexattr(filedes, name, options);
2111 #endif
2112 #elif defined(HAVE_FREMOVEEA)
2113         return fremoveea(filedes, name);
2114 #elif defined(HAVE_EXTATTR_DELETE_FD)
2115         char *s;
2116         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
2117                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2118         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2119
2120         return extattr_delete_fd(filedes, attrnamespace, attrname);
2121 #elif defined(HAVE_ATTR_REMOVEF)
2122         int flags = 0;
2123         char *attrname = strchr(name,'.') + 1;
2124
2125         if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
2126
2127         return attr_removef(filedes, attrname, flags);
2128 #elif defined(HAVE_ATTROPEN)
2129         int ret = -1;
2130         int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
2131         if (attrdirfd >= 0) {
2132                 ret = solaris_unlinkat(attrdirfd, name);
2133                 close(attrdirfd);
2134         }
2135         return ret;
2136 #else
2137         errno = ENOSYS;
2138         return -1;
2139 #endif
2140 }
2141
2142 int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags)
2143 {
2144 #if defined(HAVE_SETXATTR)
2145 #ifndef XATTR_ADD_OPT
2146         return setxattr(path, name, value, size, flags);
2147 #else
2148         int options = 0;
2149         return setxattr(path, name, value, size, 0, options);
2150 #endif
2151 #elif defined(HAVE_SETEA)
2152         return setea(path, name, value, size, flags);
2153 #elif defined(HAVE_EXTATTR_SET_FILE)
2154         char *s;
2155         int retval = 0;
2156         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
2157                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2158         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2159         if (flags) {
2160                 /* Check attribute existence */
2161                 retval = extattr_get_file(path, attrnamespace, attrname, NULL, 0);
2162                 if (retval < 0) {
2163                         /* REPLACE attribute, that doesn't exist */
2164                         if (flags & XATTR_REPLACE && errno == ENOATTR) {
2165                                 errno = ENOATTR;
2166                                 return -1;
2167                         }
2168                         /* Ignore other errors */
2169                 }
2170                 else {
2171                         /* CREATE attribute, that already exists */
2172                         if (flags & XATTR_CREATE) {
2173                                 errno = EEXIST;
2174                                 return -1;
2175                         }
2176                 }
2177         }
2178         retval = extattr_set_file(path, attrnamespace, attrname, value, size);
2179         return (retval < 0) ? -1 : 0;
2180 #elif defined(HAVE_ATTR_SET)
2181         int myflags = 0;
2182         char *attrname = strchr(name,'.') + 1;
2183
2184         if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2185         if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2186         if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2187
2188         return attr_set(path, attrname, (const char *)value, size, myflags);
2189 #elif defined(HAVE_ATTROPEN)
2190         int ret = -1;
2191         int myflags = O_RDWR;
2192         int attrfd;
2193         if (flags & XATTR_CREATE) myflags |= O_EXCL;
2194         if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2195         attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2196         if (attrfd >= 0) {
2197                 ret = solaris_write_xattr(attrfd, value, size);
2198                 close(attrfd);
2199         }
2200         return ret;
2201 #else
2202         errno = ENOSYS;
2203         return -1;
2204 #endif
2205 }
2206
2207 int sys_lsetxattr (const char *path, const char *name, const void *value, size_t size, int flags)
2208 {
2209 #if defined(HAVE_LSETXATTR)
2210         return lsetxattr(path, name, value, size, flags);
2211 #elif defined(HAVE_SETXATTR) && defined(XATTR_ADD_OPT)
2212         int options = XATTR_NOFOLLOW;
2213         return setxattr(path, name, value, size, 0, options);
2214 #elif defined(LSETEA)
2215         return lsetea(path, name, value, size, flags);
2216 #elif defined(HAVE_EXTATTR_SET_LINK)
2217         char *s;
2218         int retval = 0;
2219         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
2220                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2221         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2222         if (flags) {
2223                 /* Check attribute existence */
2224                 retval = extattr_get_link(path, attrnamespace, attrname, NULL, 0);
2225                 if (retval < 0) {
2226                         /* REPLACE attribute, that doesn't exist */
2227                         if (flags & XATTR_REPLACE && errno == ENOATTR) {
2228                                 errno = ENOATTR;
2229                                 return -1;
2230                         }
2231                         /* Ignore other errors */
2232                 }
2233                 else {
2234                         /* CREATE attribute, that already exists */
2235                         if (flags & XATTR_CREATE) {
2236                                 errno = EEXIST;
2237                                 return -1;
2238                         }
2239                 }
2240         }
2241
2242         retval = extattr_set_link(path, attrnamespace, attrname, value, size);
2243         return (retval < 0) ? -1 : 0;
2244 #elif defined(HAVE_ATTR_SET)
2245         int myflags = ATTR_DONTFOLLOW;
2246         char *attrname = strchr(name,'.') + 1;
2247
2248         if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2249         if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2250         if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2251
2252         return attr_set(path, attrname, (const char *)value, size, myflags);
2253 #elif defined(HAVE_ATTROPEN)
2254         int ret = -1;
2255         int myflags = O_RDWR | AT_SYMLINK_NOFOLLOW;
2256         int attrfd;
2257         if (flags & XATTR_CREATE) myflags |= O_EXCL;
2258         if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2259         attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2260         if (attrfd >= 0) {
2261                 ret = solaris_write_xattr(attrfd, value, size);
2262                 close(attrfd);
2263         }
2264         return ret;
2265 #else
2266         errno = ENOSYS;
2267         return -1;
2268 #endif
2269 }
2270
2271 int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags)
2272 {
2273 #if defined(HAVE_FSETXATTR)
2274 #ifndef XATTR_ADD_OPT
2275         return fsetxattr(filedes, name, value, size, flags);
2276 #else
2277         int options = 0;
2278         return fsetxattr(filedes, name, value, size, 0, options);
2279 #endif
2280 #elif defined(HAVE_FSETEA)
2281         return fsetea(filedes, name, value, size, flags);
2282 #elif defined(HAVE_EXTATTR_SET_FD)
2283         char *s;
2284         int retval = 0;
2285         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
2286                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2287         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2288         if (flags) {
2289                 /* Check attribute existence */
2290                 retval = extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0);
2291                 if (retval < 0) {
2292                         /* REPLACE attribute, that doesn't exist */
2293                         if (flags & XATTR_REPLACE && errno == ENOATTR) {
2294                                 errno = ENOATTR;
2295                                 return -1;
2296                         }
2297                         /* Ignore other errors */
2298                 }
2299                 else {
2300                         /* CREATE attribute, that already exists */
2301                         if (flags & XATTR_CREATE) {
2302                                 errno = EEXIST;
2303                                 return -1;
2304                         }
2305                 }
2306         }
2307         retval = extattr_set_fd(filedes, attrnamespace, attrname, value, size);
2308         return (retval < 0) ? -1 : 0;
2309 #elif defined(HAVE_ATTR_SETF)
2310         int myflags = 0;
2311         char *attrname = strchr(name,'.') + 1;
2312
2313         if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2314         if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2315         if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2316
2317         return attr_setf(filedes, attrname, (const char *)value, size, myflags);
2318 #elif defined(HAVE_ATTROPEN)
2319         int ret = -1;
2320         int myflags = O_RDWR | O_XATTR;
2321         int attrfd;
2322         if (flags & XATTR_CREATE) myflags |= O_EXCL;
2323         if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2324         attrfd = solaris_openat(filedes, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2325         if (attrfd >= 0) {
2326                 ret = solaris_write_xattr(attrfd, value, size);
2327                 close(attrfd);
2328         }
2329         return ret;
2330 #else
2331         errno = ENOSYS;
2332         return -1;
2333 #endif
2334 }
2335
2336 /**************************************************************************
2337  helper functions for Solaris' EA support
2338 ****************************************************************************/
2339 #ifdef HAVE_ATTROPEN
2340 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size)
2341 {
2342         struct stat sbuf;
2343
2344         if (fstat(attrfd, &sbuf) == -1) {
2345                 errno = ENOATTR;
2346                 return -1;
2347         }
2348
2349         /* This is to return the current size of the named extended attribute */
2350         if (size == 0) {
2351                 return sbuf.st_size;
2352         }
2353
2354         /* check size and read xattr */
2355         if (sbuf.st_size > size) {
2356                 errno = ERANGE;
2357                 return -1;
2358         }
2359
2360         return read(attrfd, value, sbuf.st_size);
2361 }
2362
2363 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size)
2364 {
2365         ssize_t len = 0;
2366         DIR *dirp;
2367         struct dirent *de;
2368         int newfd = dup(attrdirfd);
2369         /* CAUTION: The originating file descriptor should not be
2370                     used again following the call to fdopendir().
2371                     For that reason we dup() the file descriptor
2372                     here to make things more clear. */
2373         dirp = fdopendir(newfd);
2374
2375         while ((de = readdir(dirp))) {
2376                 size_t listlen = strlen(de->d_name) + 1;
2377                 if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) {
2378                         /* we don't want "." and ".." here: */
2379                         DEBUG(10,("skipped EA %s\n",de->d_name));
2380                         continue;
2381                 }
2382
2383                 if (size == 0) {
2384                         /* return the current size of the list of extended attribute names*/
2385                         len += listlen;
2386                 } else {
2387                         /* check size and copy entrieÑ• + nul into list. */
2388                         if ((len + listlen) > size) {
2389                                 errno = ERANGE;
2390                                 len = -1;
2391                                 break;
2392                         } else {
2393                                 strlcpy(list + len, de->d_name, listlen);
2394                                 len += listlen;
2395                         }
2396                 }
2397         }
2398
2399         if (closedir(dirp) == -1) {
2400                 DEBUG(0,("closedir dirp failed: %s\n",strerror(errno)));
2401                 return -1;
2402         }
2403         return len;
2404 }
2405
2406 static int solaris_unlinkat(int attrdirfd, const char *name)
2407 {
2408         if (unlinkat(attrdirfd, name, 0) == -1) {
2409                 if (errno == ENOENT) {
2410                         errno = ENOATTR;
2411                 }
2412                 return -1;
2413         }
2414         return 0;
2415 }
2416
2417 static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode)
2418 {
2419         int filedes = attropen(path, attrpath, oflag, mode);
2420         if (filedes == -1) {
2421                 DEBUG(10,("attropen FAILED: path: %s, name: %s, errno: %s\n",path,attrpath,strerror(errno)));
2422                 if (errno == EINVAL) {
2423                         errno = ENOTSUP;
2424                 } else {
2425                         errno = ENOATTR;
2426                 }
2427         }
2428         return filedes;
2429 }
2430
2431 static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode)
2432 {
2433         int filedes = openat(fildes, path, oflag, mode);
2434         if (filedes == -1) {
2435                 DEBUG(10,("openat FAILED: fd: %d, path: %s, errno: %s\n",filedes,path,strerror(errno)));
2436                 if (errno == EINVAL) {
2437                         errno = ENOTSUP;
2438                 } else {
2439                         errno = ENOATTR;
2440                 }
2441         }
2442         return filedes;
2443 }
2444
2445 static int solaris_write_xattr(int attrfd, const char *value, size_t size)
2446 {
2447         if ((ftruncate(attrfd, 0) == 0) && (write(attrfd, value, size) == size)) {
2448                 return 0;
2449         } else {
2450                 DEBUG(10,("solaris_write_xattr FAILED!\n"));
2451                 return -1;
2452         }
2453 }
2454 #endif /*HAVE_ATTROPEN*/
2455
2456
2457 /****************************************************************************
2458  Return the major devicenumber for UNIX extensions.
2459 ****************************************************************************/
2460
2461 uint32 unix_dev_major(SMB_DEV_T dev)
2462 {
2463 #if defined(HAVE_DEVICE_MAJOR_FN)
2464         return (uint32)major(dev);
2465 #else
2466         return (uint32)(dev >> 8);
2467 #endif
2468 }
2469
2470 /****************************************************************************
2471  Return the minor devicenumber for UNIX extensions.
2472 ****************************************************************************/
2473
2474 uint32 unix_dev_minor(SMB_DEV_T dev)
2475 {
2476 #if defined(HAVE_DEVICE_MINOR_FN)
2477         return (uint32)minor(dev);
2478 #else
2479         return (uint32)(dev & 0xff);
2480 #endif
2481 }
2482
2483 /*******************************************************************
2484  Return the number of CPUs.
2485 ********************************************************************/
2486
2487 int sys_get_number_of_cores(void)
2488 {
2489         int ret = -1;
2490
2491 #if defined(HAVE_SYSCONF)
2492 #if defined(_SC_NPROCESSORS_ONLN)
2493         ret = (int)sysconf(_SC_NPROCESSORS_ONLN);
2494 #endif
2495 #if defined(_SC_NPROCESSORS_CONF)
2496         if (ret < 1) {
2497                 ret = (int)sysconf(_SC_NPROCESSORS_CONF);
2498         }
2499 #endif
2500 #elif defined(HAVE_SYSCTL) && defined(CTL_HW)
2501         int name[2];
2502         unsigned int len = sizeof(ret);
2503
2504         name[0] = CTL_HW;
2505 #if defined(HW_AVAILCPU)
2506         name[1] = HW_AVAILCPU;
2507
2508         if (sysctl(name, 2, &ret, &len, NULL, 0) == -1) {
2509                 ret = -1;
2510         }
2511 #endif
2512 #if defined(HW_NCPU)
2513         if(ret < 1) {
2514                 name[0] = CTL_HW;
2515                 name[1] = HW_NCPU;
2516                 if (sysctl(nm, 2, &count, &len, NULL, 0) == -1) {
2517                         ret = -1;
2518                 }
2519         }
2520 #endif
2521 #endif
2522         if (ret < 1) {
2523                 ret = 1;
2524         }
2525         return ret;
2526 }
2527
2528 #if defined(WITH_AIO)
2529
2530 /*******************************************************************
2531  An aio_read wrapper that will deal with 64-bit sizes.
2532 ********************************************************************/
2533
2534 int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2535 {
2536 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_READ64)
2537         return aio_read64(aiocb);
2538 #elif defined(HAVE_AIO_READ)
2539         return aio_read(aiocb);
2540 #else
2541         errno = ENOSYS;
2542         return -1;
2543 #endif
2544 }
2545
2546 /*******************************************************************
2547  An aio_write wrapper that will deal with 64-bit sizes.
2548 ********************************************************************/
2549
2550 int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2551 {
2552 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_WRITE64)
2553         return aio_write64(aiocb);
2554 #elif defined(HAVE_AIO_WRITE)
2555         return aio_write(aiocb);
2556 #else
2557         errno = ENOSYS;
2558         return -1;
2559 #endif
2560 }
2561
2562 /*******************************************************************
2563  An aio_return wrapper that will deal with 64-bit sizes.
2564 ********************************************************************/
2565
2566 ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2567 {
2568 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_RETURN64)
2569         return aio_return64(aiocb);
2570 #elif defined(HAVE_AIO_RETURN)
2571         return aio_return(aiocb);
2572 #else
2573         errno = ENOSYS;
2574         return -1;
2575 #endif
2576 }
2577
2578 /*******************************************************************
2579  An aio_cancel wrapper that will deal with 64-bit sizes.
2580 ********************************************************************/
2581
2582 int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2583 {
2584 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_CANCEL64)
2585         return aio_cancel64(fd, aiocb);
2586 #elif defined(HAVE_AIO_CANCEL)
2587         return aio_cancel(fd, aiocb);
2588 #else
2589         errno = ENOSYS;
2590         return -1;
2591 #endif
2592 }
2593
2594 /*******************************************************************
2595  An aio_error wrapper that will deal with 64-bit sizes.
2596 ********************************************************************/
2597
2598 int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2599 {
2600 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_ERROR64)
2601         return aio_error64(aiocb);
2602 #elif defined(HAVE_AIO_ERROR)
2603         return aio_error(aiocb);
2604 #else
2605         errno = ENOSYS;
2606         return -1;
2607 #endif
2608 }
2609
2610 /*******************************************************************
2611  An aio_fsync wrapper that will deal with 64-bit sizes.
2612 ********************************************************************/
2613
2614 int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2615 {
2616 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_FSYNC64)
2617         return aio_fsync64(op, aiocb);
2618 #elif defined(HAVE_AIO_FSYNC)
2619         return aio_fsync(op, aiocb);
2620 #else
2621         errno = ENOSYS;
2622         return -1;
2623 #endif
2624 }
2625
2626 /*******************************************************************
2627  An aio_fsync wrapper that will deal with 64-bit sizes.
2628 ********************************************************************/
2629
2630 int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2631 {
2632 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_SUSPEND64)
2633         return aio_suspend64(cblist, n, timeout);
2634 #elif defined(HAVE_AIO_FSYNC)
2635         return aio_suspend(cblist, n, timeout);
2636 #else
2637         errno = ENOSYS;
2638         return -1;
2639 #endif
2640 }
2641 #else /* !WITH_AIO */
2642
2643 int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2644 {
2645         errno = ENOSYS;
2646         return -1;
2647 }
2648
2649 int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2650 {
2651         errno = ENOSYS;
2652         return -1;
2653 }
2654
2655 ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2656 {
2657         errno = ENOSYS;
2658         return -1;
2659 }
2660
2661 int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2662 {
2663         errno = ENOSYS;
2664         return -1;
2665 }
2666
2667 int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2668 {
2669         errno = ENOSYS;
2670         return -1;
2671 }
2672
2673 int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2674 {
2675         errno = ENOSYS;
2676         return -1;
2677 }
2678
2679 int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2680 {
2681         errno = ENOSYS;
2682         return -1;
2683 }
2684 #endif /* WITH_AIO */