selftest split $PERL into multiple arguments for Test::More check
[Samba.git] / source3 / lib / system.c
blob24d3c09d58a4b5bd15e9f20989f879fcf173edb1
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
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.
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.
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/>.
23 #include "includes.h"
25 #ifdef HAVE_SYS_PRCTL_H
26 #include <sys/prctl.h>
27 #endif
30 The idea is that this file will eventually have wrappers around all
31 important system calls in samba. The aims are:
33 - to enable easier porting by putting OS dependent stuff in here
35 - to allow for hooks into other "pseudo-filesystems"
37 - to allow easier integration of things like the japanese extensions
39 - to support the philosophy of Samba to expose the features of
40 the OS within the SMB model. In general whatever file/printer/variable
41 expansions/etc make sense to the OS should be acceptable to Samba.
46 /*******************************************************************
47 A wrapper for memalign
48 ********************************************************************/
50 void *sys_memalign( size_t align, size_t size )
52 #if defined(HAVE_POSIX_MEMALIGN)
53 void *p = NULL;
54 int ret = posix_memalign( &p, align, size );
55 if ( ret == 0 )
56 return p;
58 return NULL;
59 #elif defined(HAVE_MEMALIGN)
60 return memalign( align, size );
61 #else
62 /* On *BSD systems memaligns doesn't exist, but memory will
63 * be aligned on allocations of > pagesize. */
64 #if defined(SYSCONF_SC_PAGESIZE)
65 size_t pagesize = (size_t)sysconf(_SC_PAGESIZE);
66 #elif defined(HAVE_GETPAGESIZE)
67 size_t pagesize = (size_t)getpagesize();
68 #else
69 size_t pagesize = (size_t)-1;
70 #endif
71 if (pagesize == (size_t)-1) {
72 DEBUG(0,("memalign functionalaity not available on this platform!\n"));
73 return NULL;
75 if (size < pagesize) {
76 size = pagesize;
78 return SMB_MALLOC(size);
79 #endif
82 /*******************************************************************
83 A wrapper for usleep in case we don't have one.
84 ********************************************************************/
86 int sys_usleep(long usecs)
88 #ifndef HAVE_USLEEP
89 struct timeval tval;
90 #endif
93 * We need this braindamage as the glibc usleep
94 * is not SPEC1170 complient... grumble... JRA.
97 if(usecs < 0 || usecs > 999999) {
98 errno = EINVAL;
99 return -1;
102 #if HAVE_USLEEP
103 usleep(usecs);
104 return 0;
105 #else /* HAVE_USLEEP */
107 * Fake it with select...
109 tval.tv_sec = 0;
110 tval.tv_usec = usecs/1000;
111 select(0,NULL,NULL,NULL,&tval);
112 return 0;
113 #endif /* HAVE_USLEEP */
116 /*******************************************************************
117 A read wrapper that will deal with EINTR.
118 ********************************************************************/
120 ssize_t sys_read(int fd, void *buf, size_t count)
122 ssize_t ret;
124 do {
125 ret = read(fd, buf, count);
126 #if defined(EWOULDBLOCK)
127 } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
128 #else
129 } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
130 #endif
131 return ret;
134 /*******************************************************************
135 A write wrapper that will deal with EINTR.
136 ********************************************************************/
138 ssize_t sys_write(int fd, const void *buf, size_t count)
140 ssize_t ret;
142 do {
143 ret = write(fd, buf, count);
144 #if defined(EWOULDBLOCK)
145 } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
146 #else
147 } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
148 #endif
149 return ret;
152 /*******************************************************************
153 A writev wrapper that will deal with EINTR.
154 ********************************************************************/
156 ssize_t sys_writev(int fd, const struct iovec *iov, int iovcnt)
158 ssize_t ret;
160 #if 0
161 /* Try to confuse write_data_iov a bit */
162 if ((random() % 5) == 0) {
163 return sys_write(fd, iov[0].iov_base, iov[0].iov_len);
165 if (iov[0].iov_len > 1) {
166 return sys_write(fd, iov[0].iov_base,
167 (random() % (iov[0].iov_len-1)) + 1);
169 #endif
171 do {
172 ret = writev(fd, iov, iovcnt);
173 #if defined(EWOULDBLOCK)
174 } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
175 #else
176 } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
177 #endif
178 return ret;
181 /*******************************************************************
182 A pread wrapper that will deal with EINTR and 64-bit file offsets.
183 ********************************************************************/
185 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
186 ssize_t sys_pread(int fd, void *buf, size_t count, SMB_OFF_T off)
188 ssize_t ret;
190 do {
191 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_PREAD64)
192 ret = pread64(fd, buf, count, off);
193 #else
194 ret = pread(fd, buf, count, off);
195 #endif
196 } while (ret == -1 && errno == EINTR);
197 return ret;
199 #endif
201 /*******************************************************************
202 A write wrapper that will deal with EINTR and 64-bit file offsets.
203 ********************************************************************/
205 #if defined(HAVE_PWRITE) || defined(HAVE_PWRITE64)
206 ssize_t sys_pwrite(int fd, const void *buf, size_t count, SMB_OFF_T off)
208 ssize_t ret;
210 do {
211 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_PWRITE64)
212 ret = pwrite64(fd, buf, count, off);
213 #else
214 ret = pwrite(fd, buf, count, off);
215 #endif
216 } while (ret == -1 && errno == EINTR);
217 return ret;
219 #endif
221 /*******************************************************************
222 A send wrapper that will deal with EINTR or EAGAIN or EWOULDBLOCK.
223 ********************************************************************/
225 ssize_t sys_send(int s, const void *msg, size_t len, int flags)
227 ssize_t ret;
229 do {
230 ret = send(s, msg, len, flags);
231 #if defined(EWOULDBLOCK)
232 } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
233 #else
234 } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
235 #endif
236 return ret;
239 /*******************************************************************
240 A sendto wrapper that will deal with EINTR or EAGAIN or EWOULDBLOCK.
241 ********************************************************************/
243 ssize_t sys_sendto(int s, const void *msg, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
245 ssize_t ret;
247 do {
248 ret = sendto(s, msg, len, flags, to, tolen);
249 #if defined(EWOULDBLOCK)
250 } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
251 #else
252 } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
253 #endif
254 return ret;
257 /*******************************************************************
258 A recv wrapper that will deal with EINTR or EAGAIN or EWOULDBLOCK.
259 ********************************************************************/
261 ssize_t sys_recv(int fd, void *buf, size_t count, int flags)
263 ssize_t ret;
265 do {
266 ret = recv(fd, buf, count, flags);
267 #if defined(EWOULDBLOCK)
268 } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
269 #else
270 } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
271 #endif
272 return ret;
275 /*******************************************************************
276 A recvfrom wrapper that will deal with EINTR.
277 ********************************************************************/
279 ssize_t sys_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
281 ssize_t ret;
283 do {
284 ret = recvfrom(s, buf, len, flags, from, fromlen);
285 #if defined(EWOULDBLOCK)
286 } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
287 #else
288 } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
289 #endif
290 return ret;
293 /*******************************************************************
294 A fcntl wrapper that will deal with EINTR.
295 ********************************************************************/
297 int sys_fcntl_ptr(int fd, int cmd, void *arg)
299 int ret;
301 do {
302 ret = fcntl(fd, cmd, arg);
303 } while (ret == -1 && errno == EINTR);
304 return ret;
307 /*******************************************************************
308 A fcntl wrapper that will deal with EINTR.
309 ********************************************************************/
311 int sys_fcntl_long(int fd, int cmd, long arg)
313 int ret;
315 do {
316 ret = fcntl(fd, cmd, arg);
317 } while (ret == -1 && errno == EINTR);
318 return ret;
321 /****************************************************************************
322 Get/Set all the possible time fields from a stat struct as a timespec.
323 ****************************************************************************/
325 static struct timespec get_atimespec(const struct stat *pst)
327 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
328 struct timespec ret;
330 /* Old system - no ns timestamp. */
331 ret.tv_sec = pst->st_atime;
332 ret.tv_nsec = 0;
333 return ret;
334 #else
335 #if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
336 return pst->st_atim;
337 #elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
338 struct timespec ret;
339 ret.tv_sec = pst->st_atime;
340 ret.tv_nsec = pst->st_atimensec;
341 return ret;
342 #elif defined(HAVE_STRUCT_STAT_ST_MTIME_N)
343 struct timespec ret;
344 ret.tv_sec = pst->st_atime;
345 ret.tv_nsec = pst->st_atime_n;
346 return ret;
347 #elif defined(HAVE_STRUCT_STAT_ST_UMTIME)
348 struct timespec ret;
349 ret.tv_sec = pst->st_atime;
350 ret.tv_nsec = pst->st_uatime * 1000;
351 return ret;
352 #elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
353 return pst->st_atimespec;
354 #else
355 #error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
356 #endif
357 #endif
360 static struct timespec get_mtimespec(const struct stat *pst)
362 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
363 struct timespec ret;
365 /* Old system - no ns timestamp. */
366 ret.tv_sec = pst->st_mtime;
367 ret.tv_nsec = 0;
368 return ret;
369 #else
370 #if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
371 return pst->st_mtim;
372 #elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
373 struct timespec ret;
374 ret.tv_sec = pst->st_mtime;
375 ret.tv_nsec = pst->st_mtimensec;
376 return ret;
377 #elif defined(HAVE_STRUCT_STAT_ST_MTIME_N)
378 struct timespec ret;
379 ret.tv_sec = pst->st_mtime;
380 ret.tv_nsec = pst->st_mtime_n;
381 return ret;
382 #elif defined(HAVE_STRUCT_STAT_ST_UMTIME)
383 struct timespec ret;
384 ret.tv_sec = pst->st_mtime;
385 ret.tv_nsec = pst->st_umtime * 1000;
386 return ret;
387 #elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
388 return pst->st_mtimespec;
389 #else
390 #error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
391 #endif
392 #endif
395 static struct timespec get_ctimespec(const struct stat *pst)
397 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
398 struct timespec ret;
400 /* Old system - no ns timestamp. */
401 ret.tv_sec = pst->st_ctime;
402 ret.tv_nsec = 0;
403 return ret;
404 #else
405 #if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
406 return pst->st_ctim;
407 #elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
408 struct timespec ret;
409 ret.tv_sec = pst->st_ctime;
410 ret.tv_nsec = pst->st_ctimensec;
411 return ret;
412 #elif defined(HAVE_STRUCT_STAT_ST_MTIME_N)
413 struct timespec ret;
414 ret.tv_sec = pst->st_ctime;
415 ret.tv_nsec = pst->st_ctime_n;
416 return ret;
417 #elif defined(HAVE_STRUCT_STAT_ST_UMTIME)
418 struct timespec ret;
419 ret.tv_sec = pst->st_ctime;
420 ret.tv_nsec = pst->st_uctime * 1000;
421 return ret;
422 #elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
423 return pst->st_ctimespec;
424 #else
425 #error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
426 #endif
427 #endif
430 /****************************************************************************
431 Return the best approximation to a 'create time' under UNIX from a stat
432 structure.
433 ****************************************************************************/
435 static struct timespec calc_create_time_stat(const struct stat *st)
437 struct timespec ret, ret1;
438 struct timespec c_time = get_ctimespec(st);
439 struct timespec m_time = get_mtimespec(st);
440 struct timespec a_time = get_atimespec(st);
442 ret = timespec_compare(&c_time, &m_time) < 0 ? c_time : m_time;
443 ret1 = timespec_compare(&ret, &a_time) < 0 ? ret : a_time;
445 if(!null_timespec(ret1)) {
446 return ret1;
450 * One of ctime, mtime or atime was zero (probably atime).
451 * Just return MIN(ctime, mtime).
453 return ret;
456 /****************************************************************************
457 Return the best approximation to a 'create time' under UNIX from a stat_ex
458 structure.
459 ****************************************************************************/
461 static struct timespec calc_create_time_stat_ex(const struct stat_ex *st)
463 struct timespec ret, ret1;
464 struct timespec c_time = st->st_ex_ctime;
465 struct timespec m_time = st->st_ex_mtime;
466 struct timespec a_time = st->st_ex_atime;
468 ret = timespec_compare(&c_time, &m_time) < 0 ? c_time : m_time;
469 ret1 = timespec_compare(&ret, &a_time) < 0 ? ret : a_time;
471 if(!null_timespec(ret1)) {
472 return ret1;
476 * One of ctime, mtime or atime was zero (probably atime).
477 * Just return MIN(ctime, mtime).
479 return ret;
482 /****************************************************************************
483 Return the 'create time' from a stat struct if it exists (birthtime) or else
484 use the best approximation.
485 ****************************************************************************/
487 static void make_create_timespec(const struct stat *pst, struct stat_ex *dst,
488 bool fake_dir_create_times)
490 if (S_ISDIR(pst->st_mode) && fake_dir_create_times) {
491 dst->st_ex_btime.tv_sec = 315493200L; /* 1/1/1980 */
492 dst->st_ex_btime.tv_nsec = 0;
495 dst->st_ex_calculated_birthtime = false;
497 #if defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC)
498 dst->st_ex_btime = pst->st_birthtimespec;
499 #elif defined(HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC)
500 dst->st_ex_btime.tv_sec = pst->st_birthtime;
501 dst->st_ex_btime.tv_nsec = pst->st_birthtimenspec;
502 #elif defined(HAVE_STRUCT_STAT_ST_BIRTHTIME)
503 dst->st_ex_btime.tv_sec = pst->st_birthtime;
504 dst->st_ex_btime.tv_nsec = 0;
505 #else
506 dst->st_ex_btime = calc_create_time_stat(pst);
507 dst->st_ex_calculated_birthtime = true;
508 #endif
510 /* Deal with systems that don't initialize birthtime correctly.
511 * Pointed out by SATOH Fumiyasu <fumiyas@osstech.jp>.
513 if (null_timespec(dst->st_ex_btime)) {
514 dst->st_ex_btime = calc_create_time_stat(pst);
515 dst->st_ex_calculated_birthtime = true;
519 /****************************************************************************
520 If we update a timestamp in a stat_ex struct we may have to recalculate
521 the birthtime. For now only implement this for write time, but we may
522 also need to do it for atime and ctime. JRA.
523 ****************************************************************************/
525 void update_stat_ex_mtime(struct stat_ex *dst,
526 struct timespec write_ts)
528 dst->st_ex_mtime = write_ts;
530 /* We may have to recalculate btime. */
531 if (dst->st_ex_calculated_birthtime) {
532 dst->st_ex_btime = calc_create_time_stat_ex(dst);
536 void update_stat_ex_create_time(struct stat_ex *dst,
537 struct timespec create_time)
539 dst->st_ex_btime = create_time;
540 dst->st_ex_calculated_birthtime = false;
543 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
544 static void init_stat_ex_from_stat (struct stat_ex *dst,
545 const struct stat64 *src,
546 bool fake_dir_create_times)
547 #else
548 static void init_stat_ex_from_stat (struct stat_ex *dst,
549 const struct stat *src,
550 bool fake_dir_create_times)
551 #endif
553 dst->st_ex_dev = src->st_dev;
554 dst->st_ex_ino = src->st_ino;
555 dst->st_ex_mode = src->st_mode;
556 dst->st_ex_nlink = src->st_nlink;
557 dst->st_ex_uid = src->st_uid;
558 dst->st_ex_gid = src->st_gid;
559 dst->st_ex_rdev = src->st_rdev;
560 dst->st_ex_size = src->st_size;
561 dst->st_ex_atime = get_atimespec(src);
562 dst->st_ex_mtime = get_mtimespec(src);
563 dst->st_ex_ctime = get_ctimespec(src);
564 make_create_timespec(src, dst, fake_dir_create_times);
565 #ifdef HAVE_STAT_ST_BLKSIZE
566 dst->st_ex_blksize = src->st_blksize;
567 #else
568 dst->st_ex_blksize = STAT_ST_BLOCKSIZE;
569 #endif
571 #ifdef HAVE_STAT_ST_BLOCKS
572 dst->st_ex_blocks = src->st_blocks;
573 #else
574 dst->st_ex_blocks = src->st_size / dst->st_ex_blksize + 1;
575 #endif
577 #ifdef HAVE_STAT_ST_FLAGS
578 dst->st_ex_flags = src->st_flags;
579 #else
580 dst->st_ex_flags = 0;
581 #endif
584 /*******************************************************************
585 A stat() wrapper that will deal with 64 bit filesizes.
586 ********************************************************************/
588 int sys_stat(const char *fname, SMB_STRUCT_STAT *sbuf,
589 bool fake_dir_create_times)
591 int ret;
592 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
593 struct stat64 statbuf;
594 ret = stat64(fname, &statbuf);
595 #else
596 struct stat statbuf;
597 ret = stat(fname, &statbuf);
598 #endif
599 if (ret == 0) {
600 /* we always want directories to appear zero size */
601 if (S_ISDIR(statbuf.st_mode)) {
602 statbuf.st_size = 0;
604 init_stat_ex_from_stat(sbuf, &statbuf, fake_dir_create_times);
606 return ret;
609 /*******************************************************************
610 An fstat() wrapper that will deal with 64 bit filesizes.
611 ********************************************************************/
613 int sys_fstat(int fd, SMB_STRUCT_STAT *sbuf, bool fake_dir_create_times)
615 int ret;
616 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FSTAT64)
617 struct stat64 statbuf;
618 ret = fstat64(fd, &statbuf);
619 #else
620 struct stat statbuf;
621 ret = fstat(fd, &statbuf);
622 #endif
623 if (ret == 0) {
624 /* we always want directories to appear zero size */
625 if (S_ISDIR(statbuf.st_mode)) {
626 statbuf.st_size = 0;
628 init_stat_ex_from_stat(sbuf, &statbuf, fake_dir_create_times);
630 return ret;
633 /*******************************************************************
634 An lstat() wrapper that will deal with 64 bit filesizes.
635 ********************************************************************/
637 int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf,
638 bool fake_dir_create_times)
640 int ret;
641 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSTAT64)
642 struct stat64 statbuf;
643 ret = lstat64(fname, &statbuf);
644 #else
645 struct stat statbuf;
646 ret = lstat(fname, &statbuf);
647 #endif
648 if (ret == 0) {
649 /* we always want directories to appear zero size */
650 if (S_ISDIR(statbuf.st_mode)) {
651 statbuf.st_size = 0;
653 init_stat_ex_from_stat(sbuf, &statbuf, fake_dir_create_times);
655 return ret;
658 /*******************************************************************
659 An posix_fallocate() wrapper that will deal with 64 bit filesizes.
660 ********************************************************************/
661 int sys_posix_fallocate(int fd, SMB_OFF_T offset, SMB_OFF_T len)
663 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_POSIX_FALLOCATE64) && !defined(HAVE_BROKEN_POSIX_FALLOCATE)
664 return posix_fallocate64(fd, offset, len);
665 #elif defined(HAVE_POSIX_FALLOCATE) && !defined(HAVE_BROKEN_POSIX_FALLOCATE)
666 return posix_fallocate(fd, offset, len);
667 #elif defined(F_RESVSP64)
668 /* this handles XFS on IRIX */
669 struct flock64 fl;
670 SMB_OFF_T new_len = offset + len;
671 int ret;
672 struct stat64 sbuf;
674 /* unlikely to get a too large file on a 64bit system but ... */
675 if (new_len < 0)
676 return EFBIG;
678 fl.l_whence = SEEK_SET;
679 fl.l_start = offset;
680 fl.l_len = len;
682 ret=fcntl(fd, F_RESVSP64, &fl);
684 if (ret != 0)
685 return errno;
687 /* Make sure the file gets enlarged after we allocated space: */
688 fstat64(fd, &sbuf);
689 if (new_len > sbuf.st_size)
690 ftruncate64(fd, new_len);
691 return 0;
692 #else
693 return ENOSYS;
694 #endif
697 /*******************************************************************
698 An fallocate() function that matches the semantics of the Linux one.
699 ********************************************************************/
701 #ifdef HAVE_LINUX_FALLOC_H
702 #include <linux/falloc.h>
703 #endif
705 int sys_fallocate(int fd, enum vfs_fallocate_mode mode, SMB_OFF_T offset, SMB_OFF_T len)
707 #if defined(HAVE_LINUX_FALLOCATE64) || defined(HAVE_LINUX_FALLOCATE)
708 int lmode;
709 switch (mode) {
710 case VFS_FALLOCATE_EXTEND_SIZE:
711 lmode = 0;
712 break;
713 case VFS_FALLOCATE_KEEP_SIZE:
714 lmode = FALLOC_FL_KEEP_SIZE;
715 break;
716 default:
717 errno = EINVAL;
718 return -1;
720 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LINUX_FALLOCATE64)
721 return fallocate64(fd, lmode, offset, len);
722 #elif defined(HAVE_LINUX_FALLOCATE)
723 return fallocate(fd, lmode, offset, len);
724 #endif
725 #else
726 /* TODO - plumb in fallocate from other filesysetms like VXFS etc. JRA. */
727 errno = ENOSYS;
728 return -1;
729 #endif
732 /*******************************************************************
733 An ftruncate() wrapper that will deal with 64 bit filesizes.
734 ********************************************************************/
736 int sys_ftruncate(int fd, SMB_OFF_T offset)
738 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FTRUNCATE64)
739 return ftruncate64(fd, offset);
740 #else
741 return ftruncate(fd, offset);
742 #endif
745 /*******************************************************************
746 An lseek() wrapper that will deal with 64 bit filesizes.
747 ********************************************************************/
749 SMB_OFF_T sys_lseek(int fd, SMB_OFF_T offset, int whence)
751 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSEEK64)
752 return lseek64(fd, offset, whence);
753 #else
754 return lseek(fd, offset, whence);
755 #endif
758 /*******************************************************************
759 An fseek() wrapper that will deal with 64 bit filesizes.
760 ********************************************************************/
762 int sys_fseek(FILE *fp, SMB_OFF_T offset, int whence)
764 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEK64)
765 return fseek64(fp, offset, whence);
766 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEKO64)
767 return fseeko64(fp, offset, whence);
768 #else
769 return fseek(fp, offset, whence);
770 #endif
773 /*******************************************************************
774 An ftell() wrapper that will deal with 64 bit filesizes.
775 ********************************************************************/
777 SMB_OFF_T sys_ftell(FILE *fp)
779 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELL64)
780 return (SMB_OFF_T)ftell64(fp);
781 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELLO64)
782 return (SMB_OFF_T)ftello64(fp);
783 #else
784 return (SMB_OFF_T)ftell(fp);
785 #endif
788 /*******************************************************************
789 A creat() wrapper that will deal with 64 bit filesizes.
790 ********************************************************************/
792 int sys_creat(const char *path, mode_t mode)
794 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CREAT64)
795 return creat64(path, mode);
796 #else
798 * If creat64 isn't defined then ensure we call a potential open64.
799 * JRA.
801 return sys_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
802 #endif
805 /*******************************************************************
806 An open() wrapper that will deal with 64 bit filesizes.
807 ********************************************************************/
809 int sys_open(const char *path, int oflag, mode_t mode)
811 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPEN64)
812 return open64(path, oflag, mode);
813 #else
814 return open(path, oflag, mode);
815 #endif
818 /*******************************************************************
819 An fopen() wrapper that will deal with 64 bit filesizes.
820 ********************************************************************/
822 FILE *sys_fopen(const char *path, const char *type)
824 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FOPEN64)
825 return fopen64(path, type);
826 #else
827 return fopen(path, type);
828 #endif
832 /*******************************************************************
833 A flock() wrapper that will perform the kernel flock.
834 ********************************************************************/
836 void kernel_flock(int fd, uint32 share_mode, uint32 access_mask)
838 #if HAVE_KERNEL_SHARE_MODES
839 int kernel_mode = 0;
840 if (share_mode == FILE_SHARE_WRITE) {
841 kernel_mode = LOCK_MAND|LOCK_WRITE;
842 } else if (share_mode == FILE_SHARE_READ) {
843 kernel_mode = LOCK_MAND|LOCK_READ;
844 } else if (share_mode == FILE_SHARE_NONE) {
845 kernel_mode = LOCK_MAND;
847 if (kernel_mode) {
848 flock(fd, kernel_mode);
850 #endif
856 /*******************************************************************
857 An opendir wrapper that will deal with 64 bit filesizes.
858 ********************************************************************/
860 SMB_STRUCT_DIR *sys_opendir(const char *name)
862 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPENDIR64)
863 return opendir64(name);
864 #else
865 return opendir(name);
866 #endif
869 /*******************************************************************
870 An fdopendir wrapper that will deal with 64 bit filesizes.
871 ********************************************************************/
873 SMB_STRUCT_DIR *sys_fdopendir(int fd)
875 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FDOPENDIR64)
876 return fdopendir64(fd);
877 #elif defined(HAVE_FDOPENDIR)
878 return fdopendir(fd);
879 #else
880 errno = ENOSYS;
881 return NULL;
882 #endif
885 /*******************************************************************
886 A readdir wrapper that will deal with 64 bit filesizes.
887 ********************************************************************/
889 SMB_STRUCT_DIRENT *sys_readdir(SMB_STRUCT_DIR *dirp)
891 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_READDIR64)
892 return readdir64(dirp);
893 #else
894 return readdir(dirp);
895 #endif
898 /*******************************************************************
899 A seekdir wrapper that will deal with 64 bit filesizes.
900 ********************************************************************/
902 void sys_seekdir(SMB_STRUCT_DIR *dirp, long offset)
904 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_SEEKDIR64)
905 seekdir64(dirp, offset);
906 #else
907 seekdir(dirp, offset);
908 #endif
911 /*******************************************************************
912 A telldir wrapper that will deal with 64 bit filesizes.
913 ********************************************************************/
915 long sys_telldir(SMB_STRUCT_DIR *dirp)
917 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_TELLDIR64)
918 return (long)telldir64(dirp);
919 #else
920 return (long)telldir(dirp);
921 #endif
924 /*******************************************************************
925 A rewinddir wrapper that will deal with 64 bit filesizes.
926 ********************************************************************/
928 void sys_rewinddir(SMB_STRUCT_DIR *dirp)
930 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_REWINDDIR64)
931 rewinddir64(dirp);
932 #else
933 rewinddir(dirp);
934 #endif
937 /*******************************************************************
938 A close wrapper that will deal with 64 bit filesizes.
939 ********************************************************************/
941 int sys_closedir(SMB_STRUCT_DIR *dirp)
943 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CLOSEDIR64)
944 return closedir64(dirp);
945 #else
946 return closedir(dirp);
947 #endif
950 /*******************************************************************
951 An mknod() wrapper that will deal with 64 bit filesizes.
952 ********************************************************************/
954 int sys_mknod(const char *path, mode_t mode, SMB_DEV_T dev)
956 #if defined(HAVE_MKNOD) || defined(HAVE_MKNOD64)
957 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_MKNOD64) && defined(HAVE_DEV64_T)
958 return mknod64(path, mode, dev);
959 #else
960 return mknod(path, mode, dev);
961 #endif
962 #else
963 /* No mknod system call. */
964 errno = ENOSYS;
965 return -1;
966 #endif
969 /*******************************************************************
970 The wait() calls vary between systems
971 ********************************************************************/
973 int sys_waitpid(pid_t pid,int *status,int options)
975 #ifdef HAVE_WAITPID
976 return waitpid(pid,status,options);
977 #else /* HAVE_WAITPID */
978 return wait4(pid, status, options, NULL);
979 #endif /* HAVE_WAITPID */
982 /*******************************************************************
983 System wrapper for getwd
984 ********************************************************************/
986 char *sys_getwd(char *s)
988 char *wd;
989 #ifdef HAVE_GETCWD
990 wd = (char *)getcwd(s, PATH_MAX);
991 #else
992 wd = (char *)getwd(s);
993 #endif
994 return wd;
997 #if defined(HAVE_POSIX_CAPABILITIES)
999 /**************************************************************************
1000 Try and abstract process capabilities (for systems that have them).
1001 ****************************************************************************/
1003 /* Set the POSIX capabilities needed for the given purpose into the effective
1004 * capability set of the current process. Make sure they are always removed
1005 * from the inheritable set, because there is no circumstance in which our
1006 * children should inherit our elevated privileges.
1008 static bool set_process_capability(enum smbd_capability capability,
1009 bool enable)
1011 cap_value_t cap_vals[2] = {0};
1012 int num_cap_vals = 0;
1014 cap_t cap;
1016 #if defined(HAVE_PRCTL) && defined(PR_GET_KEEPCAPS) && defined(PR_SET_KEEPCAPS)
1017 /* On Linux, make sure that any capabilities we grab are sticky
1018 * across UID changes. We expect that this would allow us to keep both
1019 * the effective and permitted capability sets, but as of circa 2.6.16,
1020 * only the permitted set is kept. It is a bug (which we work around)
1021 * that the effective set is lost, but we still require the effective
1022 * set to be kept.
1024 if (!prctl(PR_GET_KEEPCAPS)) {
1025 prctl(PR_SET_KEEPCAPS, 1);
1027 #endif
1029 cap = cap_get_proc();
1030 if (cap == NULL) {
1031 DEBUG(0,("set_process_capability: cap_get_proc failed: %s\n",
1032 strerror(errno)));
1033 return False;
1036 switch (capability) {
1037 case KERNEL_OPLOCK_CAPABILITY:
1038 #ifdef CAP_NETWORK_MGT
1039 /* IRIX has CAP_NETWORK_MGT for oplocks. */
1040 cap_vals[num_cap_vals++] = CAP_NETWORK_MGT;
1041 #endif
1042 break;
1043 case DMAPI_ACCESS_CAPABILITY:
1044 #ifdef CAP_DEVICE_MGT
1045 /* IRIX has CAP_DEVICE_MGT for DMAPI access. */
1046 cap_vals[num_cap_vals++] = CAP_DEVICE_MGT;
1047 #elif CAP_MKNOD
1048 /* Linux has CAP_MKNOD for DMAPI access. */
1049 cap_vals[num_cap_vals++] = CAP_MKNOD;
1050 #endif
1051 break;
1052 case LEASE_CAPABILITY:
1053 #ifdef CAP_LEASE
1054 cap_vals[num_cap_vals++] = CAP_LEASE;
1055 #endif
1056 break;
1059 SMB_ASSERT(num_cap_vals <= ARRAY_SIZE(cap_vals));
1061 if (num_cap_vals == 0) {
1062 cap_free(cap);
1063 return True;
1066 cap_set_flag(cap, CAP_EFFECTIVE, num_cap_vals, cap_vals,
1067 enable ? CAP_SET : CAP_CLEAR);
1069 /* We never want to pass capabilities down to our children, so make
1070 * sure they are not inherited.
1072 cap_set_flag(cap, CAP_INHERITABLE, num_cap_vals, cap_vals, CAP_CLEAR);
1074 if (cap_set_proc(cap) == -1) {
1075 DEBUG(0, ("set_process_capability: cap_set_proc failed: %s\n",
1076 strerror(errno)));
1077 cap_free(cap);
1078 return False;
1081 cap_free(cap);
1082 return True;
1085 #endif /* HAVE_POSIX_CAPABILITIES */
1087 /****************************************************************************
1088 Gain the oplock capability from the kernel if possible.
1089 ****************************************************************************/
1091 void set_effective_capability(enum smbd_capability capability)
1093 #if defined(HAVE_POSIX_CAPABILITIES)
1094 set_process_capability(capability, True);
1095 #endif /* HAVE_POSIX_CAPABILITIES */
1098 void drop_effective_capability(enum smbd_capability capability)
1100 #if defined(HAVE_POSIX_CAPABILITIES)
1101 set_process_capability(capability, False);
1102 #endif /* HAVE_POSIX_CAPABILITIES */
1105 /**************************************************************************
1106 Wrapper for random().
1107 ****************************************************************************/
1109 long sys_random(void)
1111 #if defined(HAVE_RANDOM)
1112 return (long)random();
1113 #elif defined(HAVE_RAND)
1114 return (long)rand();
1115 #else
1116 DEBUG(0,("Error - no random function available !\n"));
1117 exit(1);
1118 #endif
1121 /**************************************************************************
1122 Wrapper for srandom().
1123 ****************************************************************************/
1125 void sys_srandom(unsigned int seed)
1127 #if defined(HAVE_SRANDOM)
1128 srandom(seed);
1129 #elif defined(HAVE_SRAND)
1130 srand(seed);
1131 #else
1132 DEBUG(0,("Error - no srandom function available !\n"));
1133 exit(1);
1134 #endif
1137 #ifndef NGROUPS_MAX
1138 #define NGROUPS_MAX 32 /* Guess... */
1139 #endif
1141 /**************************************************************************
1142 Returns equivalent to NGROUPS_MAX - using sysconf if needed.
1143 ****************************************************************************/
1145 int groups_max(void)
1147 #if defined(SYSCONF_SC_NGROUPS_MAX)
1148 int ret = sysconf(_SC_NGROUPS_MAX);
1149 return (ret == -1) ? NGROUPS_MAX : ret;
1150 #else
1151 return NGROUPS_MAX;
1152 #endif
1155 /**************************************************************************
1156 Wrap setgroups and getgroups for systems that declare getgroups() as
1157 returning an array of gid_t, but actuall return an array of int.
1158 ****************************************************************************/
1160 #if defined(HAVE_BROKEN_GETGROUPS)
1162 #ifdef HAVE_BROKEN_GETGROUPS
1163 #define GID_T int
1164 #else
1165 #define GID_T gid_t
1166 #endif
1168 static int sys_broken_getgroups(int setlen, gid_t *gidset)
1170 GID_T gid;
1171 GID_T *group_list;
1172 int i, ngroups;
1174 if(setlen == 0) {
1175 return getgroups(setlen, &gid);
1179 * Broken case. We need to allocate a
1180 * GID_T array of size setlen.
1183 if(setlen < 0) {
1184 errno = EINVAL;
1185 return -1;
1188 if (setlen == 0)
1189 setlen = groups_max();
1191 if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
1192 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
1193 return -1;
1196 if((ngroups = getgroups(setlen, group_list)) < 0) {
1197 int saved_errno = errno;
1198 SAFE_FREE(group_list);
1199 errno = saved_errno;
1200 return -1;
1203 for(i = 0; i < ngroups; i++)
1204 gidset[i] = (gid_t)group_list[i];
1206 SAFE_FREE(group_list);
1207 return ngroups;
1210 static int sys_broken_setgroups(int setlen, gid_t *gidset)
1212 GID_T *group_list;
1213 int i ;
1215 if (setlen == 0)
1216 return 0 ;
1218 if (setlen < 0 || setlen > groups_max()) {
1219 errno = EINVAL;
1220 return -1;
1224 * Broken case. We need to allocate a
1225 * GID_T array of size setlen.
1228 if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
1229 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
1230 return -1;
1233 for(i = 0; i < setlen; i++)
1234 group_list[i] = (GID_T) gidset[i];
1236 if(setgroups(setlen, group_list) != 0) {
1237 int saved_errno = errno;
1238 SAFE_FREE(group_list);
1239 errno = saved_errno;
1240 return -1;
1243 SAFE_FREE(group_list);
1244 return 0 ;
1247 #endif /* HAVE_BROKEN_GETGROUPS */
1249 /* This is a list of systems that require the first GID passed to setgroups(2)
1250 * to be the effective GID. If your system is one of these, add it here.
1252 #if defined (FREEBSD) || defined (DARWINOS)
1253 #define USE_BSD_SETGROUPS
1254 #endif
1256 #if defined(USE_BSD_SETGROUPS)
1257 /* Depending on the particular BSD implementation, the first GID that is
1258 * passed to setgroups(2) will either be ignored or will set the credential's
1259 * effective GID. In either case, the right thing to do is to guarantee that
1260 * gidset[0] is the effective GID.
1262 static int sys_bsd_setgroups(gid_t primary_gid, int setlen, const gid_t *gidset)
1264 gid_t *new_gidset = NULL;
1265 int max;
1266 int ret;
1268 /* setgroups(2) will fail with EINVAL if we pass too many groups. */
1269 max = groups_max();
1271 /* No group list, just make sure we are setting the efective GID. */
1272 if (setlen == 0) {
1273 return setgroups(1, &primary_gid);
1276 /* If the primary gid is not the first array element, grow the array
1277 * and insert it at the front.
1279 if (gidset[0] != primary_gid) {
1280 new_gidset = SMB_MALLOC_ARRAY(gid_t, setlen + 1);
1281 if (new_gidset == NULL) {
1282 return -1;
1285 memcpy(new_gidset + 1, gidset, (setlen * sizeof(gid_t)));
1286 new_gidset[0] = primary_gid;
1287 setlen++;
1290 if (setlen > max) {
1291 DEBUG(3, ("forced to truncate group list from %d to %d\n",
1292 setlen, max));
1293 setlen = max;
1296 #if defined(HAVE_BROKEN_GETGROUPS)
1297 ret = sys_broken_setgroups(setlen, new_gidset ? new_gidset : gidset);
1298 #else
1299 ret = setgroups(setlen, new_gidset ? new_gidset : gidset);
1300 #endif
1302 if (new_gidset) {
1303 int errsav = errno;
1304 SAFE_FREE(new_gidset);
1305 errno = errsav;
1308 return ret;
1311 #endif /* USE_BSD_SETGROUPS */
1313 /**************************************************************************
1314 Wrapper for getgroups. Deals with broken (int) case.
1315 ****************************************************************************/
1317 int sys_getgroups(int setlen, gid_t *gidset)
1319 #if defined(HAVE_BROKEN_GETGROUPS)
1320 return sys_broken_getgroups(setlen, gidset);
1321 #else
1322 return getgroups(setlen, gidset);
1323 #endif
1326 /**************************************************************************
1327 Wrapper for setgroups. Deals with broken (int) case and BSD case.
1328 ****************************************************************************/
1330 int sys_setgroups(gid_t UNUSED(primary_gid), int setlen, gid_t *gidset)
1332 #if !defined(HAVE_SETGROUPS)
1333 errno = ENOSYS;
1334 return -1;
1335 #endif /* HAVE_SETGROUPS */
1337 #if defined(USE_BSD_SETGROUPS)
1338 return sys_bsd_setgroups(primary_gid, setlen, gidset);
1339 #elif defined(HAVE_BROKEN_GETGROUPS)
1340 return sys_broken_setgroups(setlen, gidset);
1341 #else
1342 return setgroups(setlen, gidset);
1343 #endif
1346 /**************************************************************************
1347 Wrappers for setpwent(), getpwent() and endpwent()
1348 ****************************************************************************/
1350 void sys_setpwent(void)
1352 setpwent();
1355 struct passwd *sys_getpwent(void)
1357 return getpwent();
1360 void sys_endpwent(void)
1362 endpwent();
1365 /**************************************************************************
1366 Wrappers for getpwnam(), getpwuid(), getgrnam(), getgrgid()
1367 ****************************************************************************/
1370 struct passwd *sys_getpwnam(const char *name)
1372 return getpwnam(name);
1375 struct passwd *sys_getpwuid(uid_t uid)
1377 return getpwuid(uid);
1380 struct group *sys_getgrnam(const char *name)
1382 return getgrnam(name);
1385 struct group *sys_getgrgid(gid_t gid)
1387 return getgrgid(gid);
1390 /**************************************************************************
1391 Extract a command into an arg list.
1392 ****************************************************************************/
1394 static char **extract_args(TALLOC_CTX *mem_ctx, const char *command)
1396 char *trunc_cmd;
1397 char *saveptr;
1398 char *ptr;
1399 int argcl;
1400 char **argl = NULL;
1401 int i;
1403 if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1404 DEBUG(0, ("talloc failed\n"));
1405 goto nomem;
1408 if(!(ptr = strtok_r(trunc_cmd, " \t", &saveptr))) {
1409 TALLOC_FREE(trunc_cmd);
1410 errno = EINVAL;
1411 return NULL;
1415 * Count the args.
1418 for( argcl = 1; ptr; ptr = strtok_r(NULL, " \t", &saveptr))
1419 argcl++;
1421 TALLOC_FREE(trunc_cmd);
1423 if (!(argl = TALLOC_ARRAY(mem_ctx, char *, argcl + 1))) {
1424 goto nomem;
1428 * Now do the extraction.
1431 if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1432 goto nomem;
1435 ptr = strtok_r(trunc_cmd, " \t", &saveptr);
1436 i = 0;
1438 if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1439 goto nomem;
1442 while((ptr = strtok_r(NULL, " \t", &saveptr)) != NULL) {
1444 if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1445 goto nomem;
1449 argl[i++] = NULL;
1450 TALLOC_FREE(trunc_cmd);
1451 return argl;
1453 nomem:
1454 DEBUG(0, ("talloc failed\n"));
1455 TALLOC_FREE(trunc_cmd);
1456 TALLOC_FREE(argl);
1457 errno = ENOMEM;
1458 return NULL;
1461 /**************************************************************************
1462 Wrapper for popen. Safer as it doesn't search a path.
1463 Modified from the glibc sources.
1464 modified by tridge to return a file descriptor. We must kick our FILE* habit
1465 ****************************************************************************/
1467 typedef struct _popen_list
1469 int fd;
1470 pid_t child_pid;
1471 struct _popen_list *next;
1472 } popen_list;
1474 static popen_list *popen_chain;
1476 int sys_popen(const char *command)
1478 int parent_end, child_end;
1479 int pipe_fds[2];
1480 popen_list *entry = NULL;
1481 char **argl = NULL;
1483 if (pipe(pipe_fds) < 0)
1484 return -1;
1486 parent_end = pipe_fds[0];
1487 child_end = pipe_fds[1];
1489 if (!*command) {
1490 errno = EINVAL;
1491 goto err_exit;
1494 if((entry = SMB_MALLOC_P(popen_list)) == NULL)
1495 goto err_exit;
1497 ZERO_STRUCTP(entry);
1500 * Extract the command and args into a NULL terminated array.
1503 if(!(argl = extract_args(NULL, command)))
1504 goto err_exit;
1506 entry->child_pid = sys_fork();
1508 if (entry->child_pid == -1) {
1509 goto err_exit;
1512 if (entry->child_pid == 0) {
1515 * Child !
1518 int child_std_end = STDOUT_FILENO;
1519 popen_list *p;
1521 close(parent_end);
1522 if (child_end != child_std_end) {
1523 dup2 (child_end, child_std_end);
1524 close (child_end);
1528 * POSIX.2: "popen() shall ensure that any streams from previous
1529 * popen() calls that remain open in the parent process are closed
1530 * in the new child process."
1533 for (p = popen_chain; p; p = p->next)
1534 close(p->fd);
1536 execv(argl[0], argl);
1537 _exit (127);
1541 * Parent.
1544 close (child_end);
1545 TALLOC_FREE(argl);
1547 /* Link into popen_chain. */
1548 entry->next = popen_chain;
1549 popen_chain = entry;
1550 entry->fd = parent_end;
1552 return entry->fd;
1554 err_exit:
1556 SAFE_FREE(entry);
1557 TALLOC_FREE(argl);
1558 close(pipe_fds[0]);
1559 close(pipe_fds[1]);
1560 return -1;
1563 /**************************************************************************
1564 Wrapper for pclose. Modified from the glibc sources.
1565 ****************************************************************************/
1567 int sys_pclose(int fd)
1569 int wstatus;
1570 popen_list **ptr = &popen_chain;
1571 popen_list *entry = NULL;
1572 pid_t wait_pid;
1573 int status = -1;
1575 /* Unlink from popen_chain. */
1576 for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
1577 if ((*ptr)->fd == fd) {
1578 entry = *ptr;
1579 *ptr = (*ptr)->next;
1580 status = 0;
1581 break;
1585 if (status < 0 || close(entry->fd) < 0)
1586 return -1;
1589 * As Samba is catching and eating child process
1590 * exits we don't really care about the child exit
1591 * code, a -1 with errno = ECHILD will do fine for us.
1594 do {
1595 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
1596 } while (wait_pid == -1 && errno == EINTR);
1598 SAFE_FREE(entry);
1600 if (wait_pid == -1)
1601 return -1;
1602 return wstatus;
1605 /**************************************************************************
1606 Wrapper for Admin Logs.
1607 ****************************************************************************/
1609 void sys_adminlog(int priority, const char *format_str, ...)
1611 va_list ap;
1612 int ret;
1613 char *msgbuf = NULL;
1615 va_start( ap, format_str );
1616 ret = vasprintf( &msgbuf, format_str, ap );
1617 va_end( ap );
1619 if (ret == -1)
1620 return;
1622 #if defined(HAVE_SYSLOG)
1623 syslog( priority, "%s", msgbuf );
1624 #else
1625 DEBUG(0,("%s", msgbuf ));
1626 #endif
1627 SAFE_FREE(msgbuf);
1630 /******** Solaris EA helper function prototypes ********/
1631 #ifdef HAVE_ATTROPEN
1632 #define SOLARIS_ATTRMODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP
1633 static int solaris_write_xattr(int attrfd, const char *value, size_t size);
1634 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size);
1635 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size);
1636 static int solaris_unlinkat(int attrdirfd, const char *name);
1637 static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode);
1638 static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode);
1639 #endif
1641 /**************************************************************************
1642 Wrappers for extented attribute calls. Based on the Linux package with
1643 support for IRIX and (Net|Free)BSD also. Expand as other systems have them.
1644 ****************************************************************************/
1646 ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t size)
1648 #if defined(HAVE_GETXATTR)
1649 #ifndef XATTR_ADD_OPT
1650 return getxattr(path, name, value, size);
1651 #else
1652 int options = 0;
1653 return getxattr(path, name, value, size, 0, options);
1654 #endif
1655 #elif defined(HAVE_GETEA)
1656 return getea(path, name, value, size);
1657 #elif defined(HAVE_EXTATTR_GET_FILE)
1658 char *s;
1659 ssize_t retval;
1660 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1661 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1662 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1664 * The BSD implementation has a nasty habit of silently truncating
1665 * the returned value to the size of the buffer, so we have to check
1666 * that the buffer is large enough to fit the returned value.
1668 if((retval=extattr_get_file(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1669 if(retval > size) {
1670 errno = ERANGE;
1671 return -1;
1673 if((retval=extattr_get_file(path, attrnamespace, attrname, value, size)) >= 0)
1674 return retval;
1677 DEBUG(10,("sys_getxattr: extattr_get_file() failed with: %s\n", strerror(errno)));
1678 return -1;
1679 #elif defined(HAVE_ATTR_GET)
1680 int retval, flags = 0;
1681 int valuelength = (int)size;
1682 char *attrname = strchr(name,'.') + 1;
1684 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1686 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1688 return retval ? retval : valuelength;
1689 #elif defined(HAVE_ATTROPEN)
1690 ssize_t ret = -1;
1691 int attrfd = solaris_attropen(path, name, O_RDONLY, 0);
1692 if (attrfd >= 0) {
1693 ret = solaris_read_xattr(attrfd, value, size);
1694 close(attrfd);
1696 return ret;
1697 #else
1698 errno = ENOSYS;
1699 return -1;
1700 #endif
1703 ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t size)
1705 #if defined(HAVE_LGETXATTR)
1706 return lgetxattr(path, name, value, size);
1707 #elif defined(HAVE_GETXATTR) && defined(XATTR_ADD_OPT)
1708 int options = XATTR_NOFOLLOW;
1709 return getxattr(path, name, value, size, 0, options);
1710 #elif defined(HAVE_LGETEA)
1711 return lgetea(path, name, value, size);
1712 #elif defined(HAVE_EXTATTR_GET_LINK)
1713 char *s;
1714 ssize_t retval;
1715 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1716 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1717 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1719 if((retval=extattr_get_link(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1720 if(retval > size) {
1721 errno = ERANGE;
1722 return -1;
1724 if((retval=extattr_get_link(path, attrnamespace, attrname, value, size)) >= 0)
1725 return retval;
1728 DEBUG(10,("sys_lgetxattr: extattr_get_link() failed with: %s\n", strerror(errno)));
1729 return -1;
1730 #elif defined(HAVE_ATTR_GET)
1731 int retval, flags = ATTR_DONTFOLLOW;
1732 int valuelength = (int)size;
1733 char *attrname = strchr(name,'.') + 1;
1735 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1737 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1739 return retval ? retval : valuelength;
1740 #elif defined(HAVE_ATTROPEN)
1741 ssize_t ret = -1;
1742 int attrfd = solaris_attropen(path, name, O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1743 if (attrfd >= 0) {
1744 ret = solaris_read_xattr(attrfd, value, size);
1745 close(attrfd);
1747 return ret;
1748 #else
1749 errno = ENOSYS;
1750 return -1;
1751 #endif
1754 ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size)
1756 #if defined(HAVE_FGETXATTR)
1757 #ifndef XATTR_ADD_OPT
1758 return fgetxattr(filedes, name, value, size);
1759 #else
1760 int options = 0;
1761 return fgetxattr(filedes, name, value, size, 0, options);
1762 #endif
1763 #elif defined(HAVE_FGETEA)
1764 return fgetea(filedes, name, value, size);
1765 #elif defined(HAVE_EXTATTR_GET_FD)
1766 char *s;
1767 ssize_t retval;
1768 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1769 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1770 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1772 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0)) >= 0) {
1773 if(retval > size) {
1774 errno = ERANGE;
1775 return -1;
1777 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, value, size)) >= 0)
1778 return retval;
1781 DEBUG(10,("sys_fgetxattr: extattr_get_fd() failed with: %s\n", strerror(errno)));
1782 return -1;
1783 #elif defined(HAVE_ATTR_GETF)
1784 int retval, flags = 0;
1785 int valuelength = (int)size;
1786 char *attrname = strchr(name,'.') + 1;
1788 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1790 retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags);
1792 return retval ? retval : valuelength;
1793 #elif defined(HAVE_ATTROPEN)
1794 ssize_t ret = -1;
1795 int attrfd = solaris_openat(filedes, name, O_RDONLY|O_XATTR, 0);
1796 if (attrfd >= 0) {
1797 ret = solaris_read_xattr(attrfd, value, size);
1798 close(attrfd);
1800 return ret;
1801 #else
1802 errno = ENOSYS;
1803 return -1;
1804 #endif
1807 #if defined(HAVE_EXTATTR_LIST_FILE)
1809 #define EXTATTR_PREFIX(s) (s), (sizeof((s))-1)
1811 static struct {
1812 int space;
1813 const char *name;
1814 size_t len;
1816 extattr[] = {
1817 { EXTATTR_NAMESPACE_SYSTEM, EXTATTR_PREFIX("system.") },
1818 { EXTATTR_NAMESPACE_USER, EXTATTR_PREFIX("user.") },
1821 typedef union {
1822 const char *path;
1823 int filedes;
1824 } extattr_arg;
1826 static ssize_t bsd_attr_list (int type, extattr_arg arg, char *list, size_t size)
1828 ssize_t list_size, total_size = 0;
1829 int i, t, len;
1830 char *buf;
1831 /* Iterate through extattr(2) namespaces */
1832 for(t = 0; t < (sizeof(extattr)/sizeof(extattr[0])); t++) {
1833 switch(type) {
1834 #if defined(HAVE_EXTATTR_LIST_FILE)
1835 case 0:
1836 list_size = extattr_list_file(arg.path, extattr[t].space, list, size);
1837 break;
1838 #endif
1839 #if defined(HAVE_EXTATTR_LIST_LINK)
1840 case 1:
1841 list_size = extattr_list_link(arg.path, extattr[t].space, list, size);
1842 break;
1843 #endif
1844 #if defined(HAVE_EXTATTR_LIST_FD)
1845 case 2:
1846 list_size = extattr_list_fd(arg.filedes, extattr[t].space, list, size);
1847 break;
1848 #endif
1849 default:
1850 errno = ENOSYS;
1851 return -1;
1853 /* Some error happend. Errno should be set by the previous call */
1854 if(list_size < 0)
1855 return -1;
1856 /* No attributes */
1857 if(list_size == 0)
1858 continue;
1859 /* XXX: Call with an empty buffer may be used to calculate
1860 necessary buffer size. Unfortunately, we can't say, how
1861 many attributes were returned, so here is the potential
1862 problem with the emulation.
1864 if(list == NULL) {
1865 /* Take the worse case of one char attribute names -
1866 two bytes per name plus one more for sanity.
1868 total_size += list_size + (list_size/2 + 1)*extattr[t].len;
1869 continue;
1871 /* Count necessary offset to fit namespace prefixes */
1872 len = 0;
1873 for(i = 0; i < list_size; i += list[i] + 1)
1874 len += extattr[t].len;
1876 total_size += list_size + len;
1877 /* Buffer is too small to fit the results */
1878 if(total_size > size) {
1879 errno = ERANGE;
1880 return -1;
1882 /* Shift results back, so we can prepend prefixes */
1883 buf = (char *)memmove(list + len, list, list_size);
1885 for(i = 0; i < list_size; i += len + 1) {
1886 len = buf[i];
1887 strncpy(list, extattr[t].name, extattr[t].len + 1);
1888 list += extattr[t].len;
1889 strncpy(list, buf + i + 1, len);
1890 list[len] = '\0';
1891 list += len + 1;
1893 size -= total_size;
1895 return total_size;
1898 #endif
1900 #if defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1901 static char attr_buffer[ATTR_MAX_VALUELEN];
1903 static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags)
1905 int retval = 0, index;
1906 attrlist_cursor_t *cursor = 0;
1907 int total_size = 0;
1908 attrlist_t * al = (attrlist_t *)attr_buffer;
1909 attrlist_ent_t *ae;
1910 size_t ent_size, left = size;
1911 char *bp = list;
1913 while (True) {
1914 if (filedes)
1915 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1916 else
1917 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1918 if (retval) break;
1919 for (index = 0; index < al->al_count; index++) {
1920 ae = ATTR_ENTRY(attr_buffer, index);
1921 ent_size = strlen(ae->a_name) + sizeof("user.");
1922 if (left >= ent_size) {
1923 strncpy(bp, "user.", sizeof("user."));
1924 strncat(bp, ae->a_name, ent_size - sizeof("user."));
1925 bp += ent_size;
1926 left -= ent_size;
1927 } else if (size) {
1928 errno = ERANGE;
1929 retval = -1;
1930 break;
1932 total_size += ent_size;
1934 if (al->al_more == 0) break;
1936 if (retval == 0) {
1937 flags |= ATTR_ROOT;
1938 cursor = 0;
1939 while (True) {
1940 if (filedes)
1941 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1942 else
1943 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1944 if (retval) break;
1945 for (index = 0; index < al->al_count; index++) {
1946 ae = ATTR_ENTRY(attr_buffer, index);
1947 ent_size = strlen(ae->a_name) + sizeof("system.");
1948 if (left >= ent_size) {
1949 strncpy(bp, "system.", sizeof("system."));
1950 strncat(bp, ae->a_name, ent_size - sizeof("system."));
1951 bp += ent_size;
1952 left -= ent_size;
1953 } else if (size) {
1954 errno = ERANGE;
1955 retval = -1;
1956 break;
1958 total_size += ent_size;
1960 if (al->al_more == 0) break;
1963 return (ssize_t)(retval ? retval : total_size);
1966 #endif
1968 ssize_t sys_listxattr (const char *path, char *list, size_t size)
1970 #if defined(HAVE_LISTXATTR)
1971 #ifndef XATTR_ADD_OPT
1972 return listxattr(path, list, size);
1973 #else
1974 int options = 0;
1975 return listxattr(path, list, size, options);
1976 #endif
1977 #elif defined(HAVE_LISTEA)
1978 return listea(path, list, size);
1979 #elif defined(HAVE_EXTATTR_LIST_FILE)
1980 extattr_arg arg;
1981 arg.path = path;
1982 return bsd_attr_list(0, arg, list, size);
1983 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1984 return irix_attr_list(path, 0, list, size, 0);
1985 #elif defined(HAVE_ATTROPEN)
1986 ssize_t ret = -1;
1987 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
1988 if (attrdirfd >= 0) {
1989 ret = solaris_list_xattr(attrdirfd, list, size);
1990 close(attrdirfd);
1992 return ret;
1993 #else
1994 errno = ENOSYS;
1995 return -1;
1996 #endif
1999 ssize_t sys_llistxattr (const char *path, char *list, size_t size)
2001 #if defined(HAVE_LLISTXATTR)
2002 return llistxattr(path, list, size);
2003 #elif defined(HAVE_LISTXATTR) && defined(XATTR_ADD_OPT)
2004 int options = XATTR_NOFOLLOW;
2005 return listxattr(path, list, size, options);
2006 #elif defined(HAVE_LLISTEA)
2007 return llistea(path, list, size);
2008 #elif defined(HAVE_EXTATTR_LIST_LINK)
2009 extattr_arg arg;
2010 arg.path = path;
2011 return bsd_attr_list(1, arg, list, size);
2012 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
2013 return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW);
2014 #elif defined(HAVE_ATTROPEN)
2015 ssize_t ret = -1;
2016 int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
2017 if (attrdirfd >= 0) {
2018 ret = solaris_list_xattr(attrdirfd, list, size);
2019 close(attrdirfd);
2021 return ret;
2022 #else
2023 errno = ENOSYS;
2024 return -1;
2025 #endif
2028 ssize_t sys_flistxattr (int filedes, char *list, size_t size)
2030 #if defined(HAVE_FLISTXATTR)
2031 #ifndef XATTR_ADD_OPT
2032 return flistxattr(filedes, list, size);
2033 #else
2034 int options = 0;
2035 return flistxattr(filedes, list, size, options);
2036 #endif
2037 #elif defined(HAVE_FLISTEA)
2038 return flistea(filedes, list, size);
2039 #elif defined(HAVE_EXTATTR_LIST_FD)
2040 extattr_arg arg;
2041 arg.filedes = filedes;
2042 return bsd_attr_list(2, arg, list, size);
2043 #elif defined(HAVE_ATTR_LISTF)
2044 return irix_attr_list(NULL, filedes, list, size, 0);
2045 #elif defined(HAVE_ATTROPEN)
2046 ssize_t ret = -1;
2047 int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
2048 if (attrdirfd >= 0) {
2049 ret = solaris_list_xattr(attrdirfd, list, size);
2050 close(attrdirfd);
2052 return ret;
2053 #else
2054 errno = ENOSYS;
2055 return -1;
2056 #endif
2059 int sys_removexattr (const char *path, const char *name)
2061 #if defined(HAVE_REMOVEXATTR)
2062 #ifndef XATTR_ADD_OPT
2063 return removexattr(path, name);
2064 #else
2065 int options = 0;
2066 return removexattr(path, name, options);
2067 #endif
2068 #elif defined(HAVE_REMOVEEA)
2069 return removeea(path, name);
2070 #elif defined(HAVE_EXTATTR_DELETE_FILE)
2071 char *s;
2072 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2073 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2074 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2076 return extattr_delete_file(path, attrnamespace, attrname);
2077 #elif defined(HAVE_ATTR_REMOVE)
2078 int flags = 0;
2079 char *attrname = strchr(name,'.') + 1;
2081 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
2083 return attr_remove(path, attrname, flags);
2084 #elif defined(HAVE_ATTROPEN)
2085 int ret = -1;
2086 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
2087 if (attrdirfd >= 0) {
2088 ret = solaris_unlinkat(attrdirfd, name);
2089 close(attrdirfd);
2091 return ret;
2092 #else
2093 errno = ENOSYS;
2094 return -1;
2095 #endif
2098 int sys_lremovexattr (const char *path, const char *name)
2100 #if defined(HAVE_LREMOVEXATTR)
2101 return lremovexattr(path, name);
2102 #elif defined(HAVE_REMOVEXATTR) && defined(XATTR_ADD_OPT)
2103 int options = XATTR_NOFOLLOW;
2104 return removexattr(path, name, options);
2105 #elif defined(HAVE_LREMOVEEA)
2106 return lremoveea(path, name);
2107 #elif defined(HAVE_EXTATTR_DELETE_LINK)
2108 char *s;
2109 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2110 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2111 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2113 return extattr_delete_link(path, attrnamespace, attrname);
2114 #elif defined(HAVE_ATTR_REMOVE)
2115 int flags = ATTR_DONTFOLLOW;
2116 char *attrname = strchr(name,'.') + 1;
2118 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
2120 return attr_remove(path, attrname, flags);
2121 #elif defined(HAVE_ATTROPEN)
2122 int ret = -1;
2123 int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
2124 if (attrdirfd >= 0) {
2125 ret = solaris_unlinkat(attrdirfd, name);
2126 close(attrdirfd);
2128 return ret;
2129 #else
2130 errno = ENOSYS;
2131 return -1;
2132 #endif
2135 int sys_fremovexattr (int filedes, const char *name)
2137 #if defined(HAVE_FREMOVEXATTR)
2138 #ifndef XATTR_ADD_OPT
2139 return fremovexattr(filedes, name);
2140 #else
2141 int options = 0;
2142 return fremovexattr(filedes, name, options);
2143 #endif
2144 #elif defined(HAVE_FREMOVEEA)
2145 return fremoveea(filedes, name);
2146 #elif defined(HAVE_EXTATTR_DELETE_FD)
2147 char *s;
2148 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2149 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2150 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2152 return extattr_delete_fd(filedes, attrnamespace, attrname);
2153 #elif defined(HAVE_ATTR_REMOVEF)
2154 int flags = 0;
2155 char *attrname = strchr(name,'.') + 1;
2157 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
2159 return attr_removef(filedes, attrname, flags);
2160 #elif defined(HAVE_ATTROPEN)
2161 int ret = -1;
2162 int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
2163 if (attrdirfd >= 0) {
2164 ret = solaris_unlinkat(attrdirfd, name);
2165 close(attrdirfd);
2167 return ret;
2168 #else
2169 errno = ENOSYS;
2170 return -1;
2171 #endif
2174 int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags)
2176 #if defined(HAVE_SETXATTR)
2177 #ifndef XATTR_ADD_OPT
2178 return setxattr(path, name, value, size, flags);
2179 #else
2180 int options = 0;
2181 return setxattr(path, name, value, size, 0, options);
2182 #endif
2183 #elif defined(HAVE_SETEA)
2184 return setea(path, name, value, size, flags);
2185 #elif defined(HAVE_EXTATTR_SET_FILE)
2186 char *s;
2187 int retval = 0;
2188 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2189 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2190 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2191 if (flags) {
2192 /* Check attribute existence */
2193 retval = extattr_get_file(path, attrnamespace, attrname, NULL, 0);
2194 if (retval < 0) {
2195 /* REPLACE attribute, that doesn't exist */
2196 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2197 errno = ENOATTR;
2198 return -1;
2200 /* Ignore other errors */
2202 else {
2203 /* CREATE attribute, that already exists */
2204 if (flags & XATTR_CREATE) {
2205 errno = EEXIST;
2206 return -1;
2210 retval = extattr_set_file(path, attrnamespace, attrname, value, size);
2211 return (retval < 0) ? -1 : 0;
2212 #elif defined(HAVE_ATTR_SET)
2213 int myflags = 0;
2214 char *attrname = strchr(name,'.') + 1;
2216 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2217 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2218 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2220 return attr_set(path, attrname, (const char *)value, size, myflags);
2221 #elif defined(HAVE_ATTROPEN)
2222 int ret = -1;
2223 int myflags = O_RDWR;
2224 int attrfd;
2225 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2226 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2227 attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2228 if (attrfd >= 0) {
2229 ret = solaris_write_xattr(attrfd, value, size);
2230 close(attrfd);
2232 return ret;
2233 #else
2234 errno = ENOSYS;
2235 return -1;
2236 #endif
2239 int sys_lsetxattr (const char *path, const char *name, const void *value, size_t size, int flags)
2241 #if defined(HAVE_LSETXATTR)
2242 return lsetxattr(path, name, value, size, flags);
2243 #elif defined(HAVE_SETXATTR) && defined(XATTR_ADD_OPT)
2244 int options = XATTR_NOFOLLOW;
2245 return setxattr(path, name, value, size, 0, options);
2246 #elif defined(LSETEA)
2247 return lsetea(path, name, value, size, flags);
2248 #elif defined(HAVE_EXTATTR_SET_LINK)
2249 char *s;
2250 int retval = 0;
2251 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2252 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2253 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2254 if (flags) {
2255 /* Check attribute existence */
2256 retval = extattr_get_link(path, attrnamespace, attrname, NULL, 0);
2257 if (retval < 0) {
2258 /* REPLACE attribute, that doesn't exist */
2259 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2260 errno = ENOATTR;
2261 return -1;
2263 /* Ignore other errors */
2265 else {
2266 /* CREATE attribute, that already exists */
2267 if (flags & XATTR_CREATE) {
2268 errno = EEXIST;
2269 return -1;
2274 retval = extattr_set_link(path, attrnamespace, attrname, value, size);
2275 return (retval < 0) ? -1 : 0;
2276 #elif defined(HAVE_ATTR_SET)
2277 int myflags = ATTR_DONTFOLLOW;
2278 char *attrname = strchr(name,'.') + 1;
2280 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2281 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2282 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2284 return attr_set(path, attrname, (const char *)value, size, myflags);
2285 #elif defined(HAVE_ATTROPEN)
2286 int ret = -1;
2287 int myflags = O_RDWR | AT_SYMLINK_NOFOLLOW;
2288 int attrfd;
2289 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2290 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2291 attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2292 if (attrfd >= 0) {
2293 ret = solaris_write_xattr(attrfd, value, size);
2294 close(attrfd);
2296 return ret;
2297 #else
2298 errno = ENOSYS;
2299 return -1;
2300 #endif
2303 int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags)
2305 #if defined(HAVE_FSETXATTR)
2306 #ifndef XATTR_ADD_OPT
2307 return fsetxattr(filedes, name, value, size, flags);
2308 #else
2309 int options = 0;
2310 return fsetxattr(filedes, name, value, size, 0, options);
2311 #endif
2312 #elif defined(HAVE_FSETEA)
2313 return fsetea(filedes, name, value, size, flags);
2314 #elif defined(HAVE_EXTATTR_SET_FD)
2315 char *s;
2316 int retval = 0;
2317 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2318 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2319 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2320 if (flags) {
2321 /* Check attribute existence */
2322 retval = extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0);
2323 if (retval < 0) {
2324 /* REPLACE attribute, that doesn't exist */
2325 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2326 errno = ENOATTR;
2327 return -1;
2329 /* Ignore other errors */
2331 else {
2332 /* CREATE attribute, that already exists */
2333 if (flags & XATTR_CREATE) {
2334 errno = EEXIST;
2335 return -1;
2339 retval = extattr_set_fd(filedes, attrnamespace, attrname, value, size);
2340 return (retval < 0) ? -1 : 0;
2341 #elif defined(HAVE_ATTR_SETF)
2342 int myflags = 0;
2343 char *attrname = strchr(name,'.') + 1;
2345 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2346 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2347 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2349 return attr_setf(filedes, attrname, (const char *)value, size, myflags);
2350 #elif defined(HAVE_ATTROPEN)
2351 int ret = -1;
2352 int myflags = O_RDWR | O_XATTR;
2353 int attrfd;
2354 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2355 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2356 attrfd = solaris_openat(filedes, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2357 if (attrfd >= 0) {
2358 ret = solaris_write_xattr(attrfd, value, size);
2359 close(attrfd);
2361 return ret;
2362 #else
2363 errno = ENOSYS;
2364 return -1;
2365 #endif
2368 /**************************************************************************
2369 helper functions for Solaris' EA support
2370 ****************************************************************************/
2371 #ifdef HAVE_ATTROPEN
2372 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size)
2374 struct stat sbuf;
2376 if (fstat(attrfd, &sbuf) == -1) {
2377 errno = ENOATTR;
2378 return -1;
2381 /* This is to return the current size of the named extended attribute */
2382 if (size == 0) {
2383 return sbuf.st_size;
2386 /* check size and read xattr */
2387 if (sbuf.st_size > size) {
2388 errno = ERANGE;
2389 return -1;
2392 return read(attrfd, value, sbuf.st_size);
2395 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size)
2397 ssize_t len = 0;
2398 DIR *dirp;
2399 struct dirent *de;
2400 int newfd = dup(attrdirfd);
2401 /* CAUTION: The originating file descriptor should not be
2402 used again following the call to fdopendir().
2403 For that reason we dup() the file descriptor
2404 here to make things more clear. */
2405 dirp = fdopendir(newfd);
2407 while ((de = readdir(dirp))) {
2408 size_t listlen = strlen(de->d_name);
2409 if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) {
2410 /* we don't want "." and ".." here: */
2411 DEBUG(10,("skipped EA %s\n",de->d_name));
2412 continue;
2415 if (size == 0) {
2416 /* return the current size of the list of extended attribute names*/
2417 len += listlen + 1;
2418 } else {
2419 /* check size and copy entrieѕ + nul into list. */
2420 if ((len + listlen + 1) > size) {
2421 errno = ERANGE;
2422 len = -1;
2423 break;
2424 } else {
2425 safe_strcpy(list + len, de->d_name, listlen);
2426 len += listlen;
2427 list[len] = '\0';
2428 ++len;
2433 if (closedir(dirp) == -1) {
2434 DEBUG(0,("closedir dirp failed: %s\n",strerror(errno)));
2435 return -1;
2437 return len;
2440 static int solaris_unlinkat(int attrdirfd, const char *name)
2442 if (unlinkat(attrdirfd, name, 0) == -1) {
2443 if (errno == ENOENT) {
2444 errno = ENOATTR;
2446 return -1;
2448 return 0;
2451 static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode)
2453 int filedes = attropen(path, attrpath, oflag, mode);
2454 if (filedes == -1) {
2455 DEBUG(10,("attropen FAILED: path: %s, name: %s, errno: %s\n",path,attrpath,strerror(errno)));
2456 if (errno == EINVAL) {
2457 errno = ENOTSUP;
2458 } else {
2459 errno = ENOATTR;
2462 return filedes;
2465 static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode)
2467 int filedes = openat(fildes, path, oflag, mode);
2468 if (filedes == -1) {
2469 DEBUG(10,("openat FAILED: fd: %d, path: %s, errno: %s\n",filedes,path,strerror(errno)));
2470 if (errno == EINVAL) {
2471 errno = ENOTSUP;
2472 } else {
2473 errno = ENOATTR;
2476 return filedes;
2479 static int solaris_write_xattr(int attrfd, const char *value, size_t size)
2481 if ((ftruncate(attrfd, 0) == 0) && (write(attrfd, value, size) == size)) {
2482 return 0;
2483 } else {
2484 DEBUG(10,("solaris_write_xattr FAILED!\n"));
2485 return -1;
2488 #endif /*HAVE_ATTROPEN*/
2491 /****************************************************************************
2492 Return the major devicenumber for UNIX extensions.
2493 ****************************************************************************/
2495 uint32 unix_dev_major(SMB_DEV_T dev)
2497 #if defined(HAVE_DEVICE_MAJOR_FN)
2498 return (uint32)major(dev);
2499 #else
2500 return (uint32)(dev >> 8);
2501 #endif
2504 /****************************************************************************
2505 Return the minor devicenumber for UNIX extensions.
2506 ****************************************************************************/
2508 uint32 unix_dev_minor(SMB_DEV_T dev)
2510 #if defined(HAVE_DEVICE_MINOR_FN)
2511 return (uint32)minor(dev);
2512 #else
2513 return (uint32)(dev & 0xff);
2514 #endif
2517 #if defined(WITH_AIO)
2519 /*******************************************************************
2520 An aio_read wrapper that will deal with 64-bit sizes.
2521 ********************************************************************/
2523 int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2525 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_READ64)
2526 return aio_read64(aiocb);
2527 #elif defined(HAVE_AIO_READ)
2528 return aio_read(aiocb);
2529 #else
2530 errno = ENOSYS;
2531 return -1;
2532 #endif
2535 /*******************************************************************
2536 An aio_write wrapper that will deal with 64-bit sizes.
2537 ********************************************************************/
2539 int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2541 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_WRITE64)
2542 return aio_write64(aiocb);
2543 #elif defined(HAVE_AIO_WRITE)
2544 return aio_write(aiocb);
2545 #else
2546 errno = ENOSYS;
2547 return -1;
2548 #endif
2551 /*******************************************************************
2552 An aio_return wrapper that will deal with 64-bit sizes.
2553 ********************************************************************/
2555 ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2557 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_RETURN64)
2558 return aio_return64(aiocb);
2559 #elif defined(HAVE_AIO_RETURN)
2560 return aio_return(aiocb);
2561 #else
2562 errno = ENOSYS;
2563 return -1;
2564 #endif
2567 /*******************************************************************
2568 An aio_cancel wrapper that will deal with 64-bit sizes.
2569 ********************************************************************/
2571 int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2573 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_CANCEL64)
2574 return aio_cancel64(fd, aiocb);
2575 #elif defined(HAVE_AIO_CANCEL)
2576 return aio_cancel(fd, aiocb);
2577 #else
2578 errno = ENOSYS;
2579 return -1;
2580 #endif
2583 /*******************************************************************
2584 An aio_error wrapper that will deal with 64-bit sizes.
2585 ********************************************************************/
2587 int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2589 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_ERROR64)
2590 return aio_error64(aiocb);
2591 #elif defined(HAVE_AIO_ERROR)
2592 return aio_error(aiocb);
2593 #else
2594 errno = ENOSYS;
2595 return -1;
2596 #endif
2599 /*******************************************************************
2600 An aio_fsync wrapper that will deal with 64-bit sizes.
2601 ********************************************************************/
2603 int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2605 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_FSYNC64)
2606 return aio_fsync64(op, aiocb);
2607 #elif defined(HAVE_AIO_FSYNC)
2608 return aio_fsync(op, aiocb);
2609 #else
2610 errno = ENOSYS;
2611 return -1;
2612 #endif
2615 /*******************************************************************
2616 An aio_fsync wrapper that will deal with 64-bit sizes.
2617 ********************************************************************/
2619 int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2621 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_SUSPEND64)
2622 return aio_suspend64(cblist, n, timeout);
2623 #elif defined(HAVE_AIO_FSYNC)
2624 return aio_suspend(cblist, n, timeout);
2625 #else
2626 errno = ENOSYS;
2627 return -1;
2628 #endif
2630 #else /* !WITH_AIO */
2632 int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2634 errno = ENOSYS;
2635 return -1;
2638 int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2640 errno = ENOSYS;
2641 return -1;
2644 ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2646 errno = ENOSYS;
2647 return -1;
2650 int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2652 errno = ENOSYS;
2653 return -1;
2656 int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2658 errno = ENOSYS;
2659 return -1;
2662 int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2664 errno = ENOSYS;
2665 return -1;
2668 int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2670 errno = ENOSYS;
2671 return -1;
2673 #endif /* WITH_AIO */
2675 int sys_getpeereid( int s, uid_t *uid)
2677 #if defined(HAVE_PEERCRED)
2678 struct ucred cred;
2679 socklen_t cred_len = sizeof(struct ucred);
2680 int ret;
2682 ret = getsockopt(s, SOL_SOCKET, SO_PEERCRED, (void *)&cred, &cred_len);
2683 if (ret != 0) {
2684 return -1;
2687 if (cred_len != sizeof(struct ucred)) {
2688 errno = EINVAL;
2689 return -1;
2692 *uid = cred.uid;
2693 return 0;
2694 #else
2695 #if defined(HAVE_GETPEEREID)
2696 gid_t gid;
2697 return getpeereid(s, uid, &gid);
2698 #endif
2699 errno = ENOSYS;
2700 return -1;
2701 #endif
2704 int sys_getnameinfo(const struct sockaddr *psa,
2705 socklen_t salen,
2706 char *host,
2707 size_t hostlen,
2708 char *service,
2709 size_t servlen,
2710 int flags)
2713 * For Solaris we must make sure salen is the
2714 * correct length for the incoming sa_family.
2717 if (salen == sizeof(struct sockaddr_storage)) {
2718 salen = sizeof(struct sockaddr_in);
2719 #if defined(HAVE_IPV6)
2720 if (psa->sa_family == AF_INET6) {
2721 salen = sizeof(struct sockaddr_in6);
2723 #endif
2725 return getnameinfo(psa, salen, host, hostlen, service, servlen, flags);
2728 int sys_connect(int fd, const struct sockaddr * addr)
2730 socklen_t salen = (socklen_t)-1;
2732 if (addr->sa_family == AF_INET) {
2733 salen = sizeof(struct sockaddr_in);
2734 } else if (addr->sa_family == AF_UNIX) {
2735 salen = sizeof(struct sockaddr_un);
2737 #if defined(HAVE_IPV6)
2738 else if (addr->sa_family == AF_INET6) {
2739 salen = sizeof(struct sockaddr_in6);
2741 #endif
2743 return connect(fd, addr, salen);