s3-includes: only include system/passwd.h when needed.
[Samba.git] / source3 / lib / system.c
blobf846dcac8956699ec47aeed9edc63b189044e782
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"
24 #include "system/syslog.h"
25 #include "system/capability.h"
26 #include "system/passwd.h"
28 #ifdef HAVE_SYS_PRCTL_H
29 #include <sys/prctl.h>
30 #endif
33 The idea is that this file will eventually have wrappers around all
34 important system calls in samba. The aims are:
36 - to enable easier porting by putting OS dependent stuff in here
38 - to allow for hooks into other "pseudo-filesystems"
40 - to allow easier integration of things like the japanese extensions
42 - to support the philosophy of Samba to expose the features of
43 the OS within the SMB model. In general whatever file/printer/variable
44 expansions/etc make sense to the OS should be acceptable to Samba.
49 /*******************************************************************
50 A wrapper for memalign
51 ********************************************************************/
53 void *sys_memalign( size_t align, size_t size )
55 #if defined(HAVE_POSIX_MEMALIGN)
56 void *p = NULL;
57 int ret = posix_memalign( &p, align, size );
58 if ( ret == 0 )
59 return p;
61 return NULL;
62 #elif defined(HAVE_MEMALIGN)
63 return memalign( align, size );
64 #else
65 /* On *BSD systems memaligns doesn't exist, but memory will
66 * be aligned on allocations of > pagesize. */
67 #if defined(SYSCONF_SC_PAGESIZE)
68 size_t pagesize = (size_t)sysconf(_SC_PAGESIZE);
69 #elif defined(HAVE_GETPAGESIZE)
70 size_t pagesize = (size_t)getpagesize();
71 #else
72 size_t pagesize = (size_t)-1;
73 #endif
74 if (pagesize == (size_t)-1) {
75 DEBUG(0,("memalign functionalaity not available on this platform!\n"));
76 return NULL;
78 if (size < pagesize) {
79 size = pagesize;
81 return SMB_MALLOC(size);
82 #endif
85 /*******************************************************************
86 A wrapper for usleep in case we don't have one.
87 ********************************************************************/
89 int sys_usleep(long usecs)
91 #ifndef HAVE_USLEEP
92 struct timeval tval;
93 #endif
96 * We need this braindamage as the glibc usleep
97 * is not SPEC1170 complient... grumble... JRA.
100 if(usecs < 0 || usecs > 999999) {
101 errno = EINVAL;
102 return -1;
105 #if HAVE_USLEEP
106 usleep(usecs);
107 return 0;
108 #else /* HAVE_USLEEP */
110 * Fake it with select...
112 tval.tv_sec = 0;
113 tval.tv_usec = usecs/1000;
114 select(0,NULL,NULL,NULL,&tval);
115 return 0;
116 #endif /* HAVE_USLEEP */
119 /*******************************************************************
120 A read wrapper that will deal with EINTR.
121 ********************************************************************/
123 ssize_t sys_read(int fd, void *buf, size_t count)
125 ssize_t ret;
127 do {
128 ret = read(fd, buf, count);
129 #if defined(EWOULDBLOCK)
130 } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
131 #else
132 } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
133 #endif
134 return ret;
137 /*******************************************************************
138 A write wrapper that will deal with EINTR.
139 ********************************************************************/
141 ssize_t sys_write(int fd, const void *buf, size_t count)
143 ssize_t ret;
145 do {
146 ret = write(fd, buf, count);
147 #if defined(EWOULDBLOCK)
148 } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
149 #else
150 } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
151 #endif
152 return ret;
155 /*******************************************************************
156 A writev wrapper that will deal with EINTR.
157 ********************************************************************/
159 ssize_t sys_writev(int fd, const struct iovec *iov, int iovcnt)
161 ssize_t ret;
163 #if 0
164 /* Try to confuse write_data_iov a bit */
165 if ((random() % 5) == 0) {
166 return sys_write(fd, iov[0].iov_base, iov[0].iov_len);
168 if (iov[0].iov_len > 1) {
169 return sys_write(fd, iov[0].iov_base,
170 (random() % (iov[0].iov_len-1)) + 1);
172 #endif
174 do {
175 ret = writev(fd, iov, iovcnt);
176 #if defined(EWOULDBLOCK)
177 } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
178 #else
179 } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
180 #endif
181 return ret;
184 /*******************************************************************
185 A pread wrapper that will deal with EINTR and 64-bit file offsets.
186 ********************************************************************/
188 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
189 ssize_t sys_pread(int fd, void *buf, size_t count, SMB_OFF_T off)
191 ssize_t ret;
193 do {
194 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_PREAD64)
195 ret = pread64(fd, buf, count, off);
196 #else
197 ret = pread(fd, buf, count, off);
198 #endif
199 } while (ret == -1 && errno == EINTR);
200 return ret;
202 #endif
204 /*******************************************************************
205 A write wrapper that will deal with EINTR and 64-bit file offsets.
206 ********************************************************************/
208 #if defined(HAVE_PWRITE) || defined(HAVE_PWRITE64)
209 ssize_t sys_pwrite(int fd, const void *buf, size_t count, SMB_OFF_T off)
211 ssize_t ret;
213 do {
214 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_PWRITE64)
215 ret = pwrite64(fd, buf, count, off);
216 #else
217 ret = pwrite(fd, buf, count, off);
218 #endif
219 } while (ret == -1 && errno == EINTR);
220 return ret;
222 #endif
224 /*******************************************************************
225 A send wrapper that will deal with EINTR or EAGAIN or EWOULDBLOCK.
226 ********************************************************************/
228 ssize_t sys_send(int s, const void *msg, size_t len, int flags)
230 ssize_t ret;
232 do {
233 ret = send(s, msg, len, flags);
234 #if defined(EWOULDBLOCK)
235 } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
236 #else
237 } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
238 #endif
239 return ret;
242 /*******************************************************************
243 A sendto wrapper that will deal with EINTR or EAGAIN or EWOULDBLOCK.
244 ********************************************************************/
246 ssize_t sys_sendto(int s, const void *msg, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
248 ssize_t ret;
250 do {
251 ret = sendto(s, msg, len, flags, to, tolen);
252 #if defined(EWOULDBLOCK)
253 } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
254 #else
255 } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
256 #endif
257 return ret;
260 /*******************************************************************
261 A recv wrapper that will deal with EINTR or EAGAIN or EWOULDBLOCK.
262 ********************************************************************/
264 ssize_t sys_recv(int fd, void *buf, size_t count, int flags)
266 ssize_t ret;
268 do {
269 ret = recv(fd, buf, count, flags);
270 #if defined(EWOULDBLOCK)
271 } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
272 #else
273 } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
274 #endif
275 return ret;
278 /*******************************************************************
279 A recvfrom wrapper that will deal with EINTR.
280 ********************************************************************/
282 ssize_t sys_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
284 ssize_t ret;
286 do {
287 ret = recvfrom(s, buf, len, flags, from, fromlen);
288 #if defined(EWOULDBLOCK)
289 } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
290 #else
291 } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
292 #endif
293 return ret;
296 /*******************************************************************
297 A fcntl wrapper that will deal with EINTR.
298 ********************************************************************/
300 int sys_fcntl_ptr(int fd, int cmd, void *arg)
302 int ret;
304 do {
305 ret = fcntl(fd, cmd, arg);
306 } while (ret == -1 && errno == EINTR);
307 return ret;
310 /*******************************************************************
311 A fcntl wrapper that will deal with EINTR.
312 ********************************************************************/
314 int sys_fcntl_long(int fd, int cmd, long arg)
316 int ret;
318 do {
319 ret = fcntl(fd, cmd, arg);
320 } while (ret == -1 && errno == EINTR);
321 return ret;
324 /****************************************************************************
325 Get/Set all the possible time fields from a stat struct as a timespec.
326 ****************************************************************************/
328 static struct timespec get_atimespec(const struct stat *pst)
330 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
331 struct timespec ret;
333 /* Old system - no ns timestamp. */
334 ret.tv_sec = pst->st_atime;
335 ret.tv_nsec = 0;
336 return ret;
337 #else
338 #if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
339 return pst->st_atim;
340 #elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
341 struct timespec ret;
342 ret.tv_sec = pst->st_atime;
343 ret.tv_nsec = pst->st_atimensec;
344 return ret;
345 #elif defined(HAVE_STRUCT_STAT_ST_MTIME_N)
346 struct timespec ret;
347 ret.tv_sec = pst->st_atime;
348 ret.tv_nsec = pst->st_atime_n;
349 return ret;
350 #elif defined(HAVE_STRUCT_STAT_ST_UMTIME)
351 struct timespec ret;
352 ret.tv_sec = pst->st_atime;
353 ret.tv_nsec = pst->st_uatime * 1000;
354 return ret;
355 #elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
356 return pst->st_atimespec;
357 #else
358 #error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
359 #endif
360 #endif
363 static struct timespec get_mtimespec(const struct stat *pst)
365 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
366 struct timespec ret;
368 /* Old system - no ns timestamp. */
369 ret.tv_sec = pst->st_mtime;
370 ret.tv_nsec = 0;
371 return ret;
372 #else
373 #if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
374 return pst->st_mtim;
375 #elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
376 struct timespec ret;
377 ret.tv_sec = pst->st_mtime;
378 ret.tv_nsec = pst->st_mtimensec;
379 return ret;
380 #elif defined(HAVE_STRUCT_STAT_ST_MTIME_N)
381 struct timespec ret;
382 ret.tv_sec = pst->st_mtime;
383 ret.tv_nsec = pst->st_mtime_n;
384 return ret;
385 #elif defined(HAVE_STRUCT_STAT_ST_UMTIME)
386 struct timespec ret;
387 ret.tv_sec = pst->st_mtime;
388 ret.tv_nsec = pst->st_umtime * 1000;
389 return ret;
390 #elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
391 return pst->st_mtimespec;
392 #else
393 #error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
394 #endif
395 #endif
398 static struct timespec get_ctimespec(const struct stat *pst)
400 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
401 struct timespec ret;
403 /* Old system - no ns timestamp. */
404 ret.tv_sec = pst->st_ctime;
405 ret.tv_nsec = 0;
406 return ret;
407 #else
408 #if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
409 return pst->st_ctim;
410 #elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
411 struct timespec ret;
412 ret.tv_sec = pst->st_ctime;
413 ret.tv_nsec = pst->st_ctimensec;
414 return ret;
415 #elif defined(HAVE_STRUCT_STAT_ST_MTIME_N)
416 struct timespec ret;
417 ret.tv_sec = pst->st_ctime;
418 ret.tv_nsec = pst->st_ctime_n;
419 return ret;
420 #elif defined(HAVE_STRUCT_STAT_ST_UMTIME)
421 struct timespec ret;
422 ret.tv_sec = pst->st_ctime;
423 ret.tv_nsec = pst->st_uctime * 1000;
424 return ret;
425 #elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
426 return pst->st_ctimespec;
427 #else
428 #error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
429 #endif
430 #endif
433 /****************************************************************************
434 Return the best approximation to a 'create time' under UNIX from a stat
435 structure.
436 ****************************************************************************/
438 static struct timespec calc_create_time_stat(const struct stat *st)
440 struct timespec ret, ret1;
441 struct timespec c_time = get_ctimespec(st);
442 struct timespec m_time = get_mtimespec(st);
443 struct timespec a_time = get_atimespec(st);
445 ret = timespec_compare(&c_time, &m_time) < 0 ? c_time : m_time;
446 ret1 = timespec_compare(&ret, &a_time) < 0 ? ret : a_time;
448 if(!null_timespec(ret1)) {
449 return ret1;
453 * One of ctime, mtime or atime was zero (probably atime).
454 * Just return MIN(ctime, mtime).
456 return ret;
459 /****************************************************************************
460 Return the best approximation to a 'create time' under UNIX from a stat_ex
461 structure.
462 ****************************************************************************/
464 static struct timespec calc_create_time_stat_ex(const struct stat_ex *st)
466 struct timespec ret, ret1;
467 struct timespec c_time = st->st_ex_ctime;
468 struct timespec m_time = st->st_ex_mtime;
469 struct timespec a_time = st->st_ex_atime;
471 ret = timespec_compare(&c_time, &m_time) < 0 ? c_time : m_time;
472 ret1 = timespec_compare(&ret, &a_time) < 0 ? ret : a_time;
474 if(!null_timespec(ret1)) {
475 return ret1;
479 * One of ctime, mtime or atime was zero (probably atime).
480 * Just return MIN(ctime, mtime).
482 return ret;
485 /****************************************************************************
486 Return the 'create time' from a stat struct if it exists (birthtime) or else
487 use the best approximation.
488 ****************************************************************************/
490 static void make_create_timespec(const struct stat *pst, struct stat_ex *dst,
491 bool fake_dir_create_times)
493 if (S_ISDIR(pst->st_mode) && fake_dir_create_times) {
494 dst->st_ex_btime.tv_sec = 315493200L; /* 1/1/1980 */
495 dst->st_ex_btime.tv_nsec = 0;
498 dst->st_ex_calculated_birthtime = false;
500 #if defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC)
501 dst->st_ex_btime = pst->st_birthtimespec;
502 #elif defined(HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC)
503 dst->st_ex_btime.tv_sec = pst->st_birthtime;
504 dst->st_ex_btime.tv_nsec = pst->st_birthtimenspec;
505 #elif defined(HAVE_STRUCT_STAT_ST_BIRTHTIME)
506 dst->st_ex_btime.tv_sec = pst->st_birthtime;
507 dst->st_ex_btime.tv_nsec = 0;
508 #else
509 dst->st_ex_btime = calc_create_time_stat(pst);
510 dst->st_ex_calculated_birthtime = true;
511 #endif
513 /* Deal with systems that don't initialize birthtime correctly.
514 * Pointed out by SATOH Fumiyasu <fumiyas@osstech.jp>.
516 if (null_timespec(dst->st_ex_btime)) {
517 dst->st_ex_btime = calc_create_time_stat(pst);
518 dst->st_ex_calculated_birthtime = true;
522 /****************************************************************************
523 If we update a timestamp in a stat_ex struct we may have to recalculate
524 the birthtime. For now only implement this for write time, but we may
525 also need to do it for atime and ctime. JRA.
526 ****************************************************************************/
528 void update_stat_ex_mtime(struct stat_ex *dst,
529 struct timespec write_ts)
531 dst->st_ex_mtime = write_ts;
533 /* We may have to recalculate btime. */
534 if (dst->st_ex_calculated_birthtime) {
535 dst->st_ex_btime = calc_create_time_stat_ex(dst);
539 void update_stat_ex_create_time(struct stat_ex *dst,
540 struct timespec create_time)
542 dst->st_ex_btime = create_time;
543 dst->st_ex_calculated_birthtime = false;
546 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
547 static void init_stat_ex_from_stat (struct stat_ex *dst,
548 const struct stat64 *src,
549 bool fake_dir_create_times)
550 #else
551 static void init_stat_ex_from_stat (struct stat_ex *dst,
552 const struct stat *src,
553 bool fake_dir_create_times)
554 #endif
556 dst->st_ex_dev = src->st_dev;
557 dst->st_ex_ino = src->st_ino;
558 dst->st_ex_mode = src->st_mode;
559 dst->st_ex_nlink = src->st_nlink;
560 dst->st_ex_uid = src->st_uid;
561 dst->st_ex_gid = src->st_gid;
562 dst->st_ex_rdev = src->st_rdev;
563 dst->st_ex_size = src->st_size;
564 dst->st_ex_atime = get_atimespec(src);
565 dst->st_ex_mtime = get_mtimespec(src);
566 dst->st_ex_ctime = get_ctimespec(src);
567 make_create_timespec(src, dst, fake_dir_create_times);
568 #ifdef HAVE_STAT_ST_BLKSIZE
569 dst->st_ex_blksize = src->st_blksize;
570 #else
571 dst->st_ex_blksize = STAT_ST_BLOCKSIZE;
572 #endif
574 #ifdef HAVE_STAT_ST_BLOCKS
575 dst->st_ex_blocks = src->st_blocks;
576 #else
577 dst->st_ex_blocks = src->st_size / dst->st_ex_blksize + 1;
578 #endif
580 #ifdef HAVE_STAT_ST_FLAGS
581 dst->st_ex_flags = src->st_flags;
582 #else
583 dst->st_ex_flags = 0;
584 #endif
587 /*******************************************************************
588 A stat() wrapper that will deal with 64 bit filesizes.
589 ********************************************************************/
591 int sys_stat(const char *fname, SMB_STRUCT_STAT *sbuf,
592 bool fake_dir_create_times)
594 int ret;
595 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
596 struct stat64 statbuf;
597 ret = stat64(fname, &statbuf);
598 #else
599 struct stat statbuf;
600 ret = stat(fname, &statbuf);
601 #endif
602 if (ret == 0) {
603 /* we always want directories to appear zero size */
604 if (S_ISDIR(statbuf.st_mode)) {
605 statbuf.st_size = 0;
607 init_stat_ex_from_stat(sbuf, &statbuf, fake_dir_create_times);
609 return ret;
612 /*******************************************************************
613 An fstat() wrapper that will deal with 64 bit filesizes.
614 ********************************************************************/
616 int sys_fstat(int fd, SMB_STRUCT_STAT *sbuf, bool fake_dir_create_times)
618 int ret;
619 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FSTAT64)
620 struct stat64 statbuf;
621 ret = fstat64(fd, &statbuf);
622 #else
623 struct stat statbuf;
624 ret = fstat(fd, &statbuf);
625 #endif
626 if (ret == 0) {
627 /* we always want directories to appear zero size */
628 if (S_ISDIR(statbuf.st_mode)) {
629 statbuf.st_size = 0;
631 init_stat_ex_from_stat(sbuf, &statbuf, fake_dir_create_times);
633 return ret;
636 /*******************************************************************
637 An lstat() wrapper that will deal with 64 bit filesizes.
638 ********************************************************************/
640 int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf,
641 bool fake_dir_create_times)
643 int ret;
644 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSTAT64)
645 struct stat64 statbuf;
646 ret = lstat64(fname, &statbuf);
647 #else
648 struct stat statbuf;
649 ret = lstat(fname, &statbuf);
650 #endif
651 if (ret == 0) {
652 /* we always want directories to appear zero size */
653 if (S_ISDIR(statbuf.st_mode)) {
654 statbuf.st_size = 0;
656 init_stat_ex_from_stat(sbuf, &statbuf, fake_dir_create_times);
658 return ret;
661 /*******************************************************************
662 An posix_fallocate() wrapper that will deal with 64 bit filesizes.
663 ********************************************************************/
664 int sys_posix_fallocate(int fd, SMB_OFF_T offset, SMB_OFF_T len)
666 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_POSIX_FALLOCATE64) && !defined(HAVE_BROKEN_POSIX_FALLOCATE)
667 return posix_fallocate64(fd, offset, len);
668 #elif defined(HAVE_POSIX_FALLOCATE) && !defined(HAVE_BROKEN_POSIX_FALLOCATE)
669 return posix_fallocate(fd, offset, len);
670 #elif defined(F_RESVSP64)
671 /* this handles XFS on IRIX */
672 struct flock64 fl;
673 SMB_OFF_T new_len = offset + len;
674 int ret;
675 struct stat64 sbuf;
677 /* unlikely to get a too large file on a 64bit system but ... */
678 if (new_len < 0)
679 return EFBIG;
681 fl.l_whence = SEEK_SET;
682 fl.l_start = offset;
683 fl.l_len = len;
685 ret=fcntl(fd, F_RESVSP64, &fl);
687 if (ret != 0)
688 return errno;
690 /* Make sure the file gets enlarged after we allocated space: */
691 fstat64(fd, &sbuf);
692 if (new_len > sbuf.st_size)
693 ftruncate64(fd, new_len);
694 return 0;
695 #else
696 return ENOSYS;
697 #endif
700 /*******************************************************************
701 An fallocate() function that matches the semantics of the Linux one.
702 ********************************************************************/
704 #ifdef HAVE_LINUX_FALLOC_H
705 #include <linux/falloc.h>
706 #endif
708 int sys_fallocate(int fd, enum vfs_fallocate_mode mode, SMB_OFF_T offset, SMB_OFF_T len)
710 #if defined(HAVE_LINUX_FALLOCATE64) || defined(HAVE_LINUX_FALLOCATE)
711 int lmode;
712 switch (mode) {
713 case VFS_FALLOCATE_EXTEND_SIZE:
714 lmode = 0;
715 break;
716 case VFS_FALLOCATE_KEEP_SIZE:
717 lmode = FALLOC_FL_KEEP_SIZE;
718 break;
719 default:
720 errno = EINVAL;
721 return -1;
723 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LINUX_FALLOCATE64)
724 return fallocate64(fd, lmode, offset, len);
725 #elif defined(HAVE_LINUX_FALLOCATE)
726 return fallocate(fd, lmode, offset, len);
727 #endif
728 #else
729 /* TODO - plumb in fallocate from other filesysetms like VXFS etc. JRA. */
730 errno = ENOSYS;
731 return -1;
732 #endif
735 /*******************************************************************
736 An ftruncate() wrapper that will deal with 64 bit filesizes.
737 ********************************************************************/
739 int sys_ftruncate(int fd, SMB_OFF_T offset)
741 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FTRUNCATE64)
742 return ftruncate64(fd, offset);
743 #else
744 return ftruncate(fd, offset);
745 #endif
748 /*******************************************************************
749 An lseek() wrapper that will deal with 64 bit filesizes.
750 ********************************************************************/
752 SMB_OFF_T sys_lseek(int fd, SMB_OFF_T offset, int whence)
754 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSEEK64)
755 return lseek64(fd, offset, whence);
756 #else
757 return lseek(fd, offset, whence);
758 #endif
761 /*******************************************************************
762 An fseek() wrapper that will deal with 64 bit filesizes.
763 ********************************************************************/
765 int sys_fseek(FILE *fp, SMB_OFF_T offset, int whence)
767 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEK64)
768 return fseek64(fp, offset, whence);
769 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEKO64)
770 return fseeko64(fp, offset, whence);
771 #else
772 return fseek(fp, offset, whence);
773 #endif
776 /*******************************************************************
777 An ftell() wrapper that will deal with 64 bit filesizes.
778 ********************************************************************/
780 SMB_OFF_T sys_ftell(FILE *fp)
782 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELL64)
783 return (SMB_OFF_T)ftell64(fp);
784 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELLO64)
785 return (SMB_OFF_T)ftello64(fp);
786 #else
787 return (SMB_OFF_T)ftell(fp);
788 #endif
791 /*******************************************************************
792 A creat() wrapper that will deal with 64 bit filesizes.
793 ********************************************************************/
795 int sys_creat(const char *path, mode_t mode)
797 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CREAT64)
798 return creat64(path, mode);
799 #else
801 * If creat64 isn't defined then ensure we call a potential open64.
802 * JRA.
804 return sys_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
805 #endif
808 /*******************************************************************
809 An open() wrapper that will deal with 64 bit filesizes.
810 ********************************************************************/
812 int sys_open(const char *path, int oflag, mode_t mode)
814 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPEN64)
815 return open64(path, oflag, mode);
816 #else
817 return open(path, oflag, mode);
818 #endif
821 /*******************************************************************
822 An fopen() wrapper that will deal with 64 bit filesizes.
823 ********************************************************************/
825 FILE *sys_fopen(const char *path, const char *type)
827 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FOPEN64)
828 return fopen64(path, type);
829 #else
830 return fopen(path, type);
831 #endif
835 /*******************************************************************
836 A flock() wrapper that will perform the kernel flock.
837 ********************************************************************/
839 void kernel_flock(int fd, uint32 share_mode, uint32 access_mask)
841 #if HAVE_KERNEL_SHARE_MODES
842 int kernel_mode = 0;
843 if (share_mode == FILE_SHARE_WRITE) {
844 kernel_mode = LOCK_MAND|LOCK_WRITE;
845 } else if (share_mode == FILE_SHARE_READ) {
846 kernel_mode = LOCK_MAND|LOCK_READ;
847 } else if (share_mode == FILE_SHARE_NONE) {
848 kernel_mode = LOCK_MAND;
850 if (kernel_mode) {
851 flock(fd, kernel_mode);
853 #endif
859 /*******************************************************************
860 An opendir wrapper that will deal with 64 bit filesizes.
861 ********************************************************************/
863 SMB_STRUCT_DIR *sys_opendir(const char *name)
865 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPENDIR64)
866 return opendir64(name);
867 #else
868 return opendir(name);
869 #endif
872 /*******************************************************************
873 An fdopendir wrapper that will deal with 64 bit filesizes.
874 Ugly hack - we need dirfd for this to work correctly in the
875 calling code.. JRA.
876 ********************************************************************/
878 SMB_STRUCT_DIR *sys_fdopendir(int fd)
880 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FDOPENDIR64) && defined(HAVE_DIRFD)
881 return fdopendir64(fd);
882 #elif defined(HAVE_FDOPENDIR) && defined(HAVE_DIRFD)
883 return fdopendir(fd);
884 #else
885 errno = ENOSYS;
886 return NULL;
887 #endif
890 /*******************************************************************
891 A readdir wrapper that will deal with 64 bit filesizes.
892 ********************************************************************/
894 SMB_STRUCT_DIRENT *sys_readdir(SMB_STRUCT_DIR *dirp)
896 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_READDIR64)
897 return readdir64(dirp);
898 #else
899 return readdir(dirp);
900 #endif
903 /*******************************************************************
904 A seekdir wrapper that will deal with 64 bit filesizes.
905 ********************************************************************/
907 void sys_seekdir(SMB_STRUCT_DIR *dirp, long offset)
909 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_SEEKDIR64)
910 seekdir64(dirp, offset);
911 #else
912 seekdir(dirp, offset);
913 #endif
916 /*******************************************************************
917 A telldir wrapper that will deal with 64 bit filesizes.
918 ********************************************************************/
920 long sys_telldir(SMB_STRUCT_DIR *dirp)
922 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_TELLDIR64)
923 return (long)telldir64(dirp);
924 #else
925 return (long)telldir(dirp);
926 #endif
929 /*******************************************************************
930 A rewinddir wrapper that will deal with 64 bit filesizes.
931 ********************************************************************/
933 void sys_rewinddir(SMB_STRUCT_DIR *dirp)
935 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_REWINDDIR64)
936 rewinddir64(dirp);
937 #else
938 rewinddir(dirp);
939 #endif
942 /*******************************************************************
943 A close wrapper that will deal with 64 bit filesizes.
944 ********************************************************************/
946 int sys_closedir(SMB_STRUCT_DIR *dirp)
948 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CLOSEDIR64)
949 return closedir64(dirp);
950 #else
951 return closedir(dirp);
952 #endif
955 /*******************************************************************
956 An mknod() wrapper that will deal with 64 bit filesizes.
957 ********************************************************************/
959 int sys_mknod(const char *path, mode_t mode, SMB_DEV_T dev)
961 #if defined(HAVE_MKNOD) || defined(HAVE_MKNOD64)
962 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_MKNOD64) && defined(HAVE_DEV64_T)
963 return mknod64(path, mode, dev);
964 #else
965 return mknod(path, mode, dev);
966 #endif
967 #else
968 /* No mknod system call. */
969 errno = ENOSYS;
970 return -1;
971 #endif
974 /*******************************************************************
975 The wait() calls vary between systems
976 ********************************************************************/
978 int sys_waitpid(pid_t pid,int *status,int options)
980 #ifdef HAVE_WAITPID
981 return waitpid(pid,status,options);
982 #else /* HAVE_WAITPID */
983 return wait4(pid, status, options, NULL);
984 #endif /* HAVE_WAITPID */
987 /*******************************************************************
988 System wrapper for getwd
989 ********************************************************************/
991 char *sys_getwd(char *s)
993 char *wd;
994 #ifdef HAVE_GETCWD
995 wd = (char *)getcwd(s, PATH_MAX);
996 #else
997 wd = (char *)getwd(s);
998 #endif
999 return wd;
1002 #if defined(HAVE_POSIX_CAPABILITIES)
1004 /**************************************************************************
1005 Try and abstract process capabilities (for systems that have them).
1006 ****************************************************************************/
1008 /* Set the POSIX capabilities needed for the given purpose into the effective
1009 * capability set of the current process. Make sure they are always removed
1010 * from the inheritable set, because there is no circumstance in which our
1011 * children should inherit our elevated privileges.
1013 static bool set_process_capability(enum smbd_capability capability,
1014 bool enable)
1016 cap_value_t cap_vals[2] = {0};
1017 int num_cap_vals = 0;
1019 cap_t cap;
1021 #if defined(HAVE_PRCTL) && defined(PR_GET_KEEPCAPS) && defined(PR_SET_KEEPCAPS)
1022 /* On Linux, make sure that any capabilities we grab are sticky
1023 * across UID changes. We expect that this would allow us to keep both
1024 * the effective and permitted capability sets, but as of circa 2.6.16,
1025 * only the permitted set is kept. It is a bug (which we work around)
1026 * that the effective set is lost, but we still require the effective
1027 * set to be kept.
1029 if (!prctl(PR_GET_KEEPCAPS)) {
1030 prctl(PR_SET_KEEPCAPS, 1);
1032 #endif
1034 cap = cap_get_proc();
1035 if (cap == NULL) {
1036 DEBUG(0,("set_process_capability: cap_get_proc failed: %s\n",
1037 strerror(errno)));
1038 return False;
1041 switch (capability) {
1042 case KERNEL_OPLOCK_CAPABILITY:
1043 #ifdef CAP_NETWORK_MGT
1044 /* IRIX has CAP_NETWORK_MGT for oplocks. */
1045 cap_vals[num_cap_vals++] = CAP_NETWORK_MGT;
1046 #endif
1047 break;
1048 case DMAPI_ACCESS_CAPABILITY:
1049 #ifdef CAP_DEVICE_MGT
1050 /* IRIX has CAP_DEVICE_MGT for DMAPI access. */
1051 cap_vals[num_cap_vals++] = CAP_DEVICE_MGT;
1052 #elif CAP_MKNOD
1053 /* Linux has CAP_MKNOD for DMAPI access. */
1054 cap_vals[num_cap_vals++] = CAP_MKNOD;
1055 #endif
1056 break;
1057 case LEASE_CAPABILITY:
1058 #ifdef CAP_LEASE
1059 cap_vals[num_cap_vals++] = CAP_LEASE;
1060 #endif
1061 break;
1064 SMB_ASSERT(num_cap_vals <= ARRAY_SIZE(cap_vals));
1066 if (num_cap_vals == 0) {
1067 cap_free(cap);
1068 return True;
1071 cap_set_flag(cap, CAP_EFFECTIVE, num_cap_vals, cap_vals,
1072 enable ? CAP_SET : CAP_CLEAR);
1074 /* We never want to pass capabilities down to our children, so make
1075 * sure they are not inherited.
1077 cap_set_flag(cap, CAP_INHERITABLE, num_cap_vals, cap_vals, CAP_CLEAR);
1079 if (cap_set_proc(cap) == -1) {
1080 DEBUG(0, ("set_process_capability: cap_set_proc failed: %s\n",
1081 strerror(errno)));
1082 cap_free(cap);
1083 return False;
1086 cap_free(cap);
1087 return True;
1090 #endif /* HAVE_POSIX_CAPABILITIES */
1092 /****************************************************************************
1093 Gain the oplock capability from the kernel if possible.
1094 ****************************************************************************/
1096 void set_effective_capability(enum smbd_capability capability)
1098 #if defined(HAVE_POSIX_CAPABILITIES)
1099 set_process_capability(capability, True);
1100 #endif /* HAVE_POSIX_CAPABILITIES */
1103 void drop_effective_capability(enum smbd_capability capability)
1105 #if defined(HAVE_POSIX_CAPABILITIES)
1106 set_process_capability(capability, False);
1107 #endif /* HAVE_POSIX_CAPABILITIES */
1110 /**************************************************************************
1111 Wrapper for random().
1112 ****************************************************************************/
1114 long sys_random(void)
1116 #if defined(HAVE_RANDOM)
1117 return (long)random();
1118 #elif defined(HAVE_RAND)
1119 return (long)rand();
1120 #else
1121 DEBUG(0,("Error - no random function available !\n"));
1122 exit(1);
1123 #endif
1126 /**************************************************************************
1127 Wrapper for srandom().
1128 ****************************************************************************/
1130 void sys_srandom(unsigned int seed)
1132 #if defined(HAVE_SRANDOM)
1133 srandom(seed);
1134 #elif defined(HAVE_SRAND)
1135 srand(seed);
1136 #else
1137 DEBUG(0,("Error - no srandom function available !\n"));
1138 exit(1);
1139 #endif
1142 #ifndef NGROUPS_MAX
1143 #define NGROUPS_MAX 32 /* Guess... */
1144 #endif
1146 /**************************************************************************
1147 Returns equivalent to NGROUPS_MAX - using sysconf if needed.
1148 ****************************************************************************/
1150 int groups_max(void)
1152 #if defined(SYSCONF_SC_NGROUPS_MAX)
1153 int ret = sysconf(_SC_NGROUPS_MAX);
1154 return (ret == -1) ? NGROUPS_MAX : ret;
1155 #else
1156 return NGROUPS_MAX;
1157 #endif
1160 /**************************************************************************
1161 Wrap setgroups and getgroups for systems that declare getgroups() as
1162 returning an array of gid_t, but actuall return an array of int.
1163 ****************************************************************************/
1165 #if defined(HAVE_BROKEN_GETGROUPS)
1167 #ifdef HAVE_BROKEN_GETGROUPS
1168 #define GID_T int
1169 #else
1170 #define GID_T gid_t
1171 #endif
1173 static int sys_broken_getgroups(int setlen, gid_t *gidset)
1175 GID_T gid;
1176 GID_T *group_list;
1177 int i, ngroups;
1179 if(setlen == 0) {
1180 return getgroups(setlen, &gid);
1184 * Broken case. We need to allocate a
1185 * GID_T array of size setlen.
1188 if(setlen < 0) {
1189 errno = EINVAL;
1190 return -1;
1193 if (setlen == 0)
1194 setlen = groups_max();
1196 if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
1197 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
1198 return -1;
1201 if((ngroups = getgroups(setlen, group_list)) < 0) {
1202 int saved_errno = errno;
1203 SAFE_FREE(group_list);
1204 errno = saved_errno;
1205 return -1;
1208 for(i = 0; i < ngroups; i++)
1209 gidset[i] = (gid_t)group_list[i];
1211 SAFE_FREE(group_list);
1212 return ngroups;
1215 static int sys_broken_setgroups(int setlen, gid_t *gidset)
1217 GID_T *group_list;
1218 int i ;
1220 if (setlen == 0)
1221 return 0 ;
1223 if (setlen < 0 || setlen > groups_max()) {
1224 errno = EINVAL;
1225 return -1;
1229 * Broken case. We need to allocate a
1230 * GID_T array of size setlen.
1233 if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
1234 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
1235 return -1;
1238 for(i = 0; i < setlen; i++)
1239 group_list[i] = (GID_T) gidset[i];
1241 if(setgroups(setlen, group_list) != 0) {
1242 int saved_errno = errno;
1243 SAFE_FREE(group_list);
1244 errno = saved_errno;
1245 return -1;
1248 SAFE_FREE(group_list);
1249 return 0 ;
1252 #endif /* HAVE_BROKEN_GETGROUPS */
1254 /* This is a list of systems that require the first GID passed to setgroups(2)
1255 * to be the effective GID. If your system is one of these, add it here.
1257 #if defined (FREEBSD) || defined (DARWINOS)
1258 #define USE_BSD_SETGROUPS
1259 #endif
1261 #if defined(USE_BSD_SETGROUPS)
1262 /* Depending on the particular BSD implementation, the first GID that is
1263 * passed to setgroups(2) will either be ignored or will set the credential's
1264 * effective GID. In either case, the right thing to do is to guarantee that
1265 * gidset[0] is the effective GID.
1267 static int sys_bsd_setgroups(gid_t primary_gid, int setlen, const gid_t *gidset)
1269 gid_t *new_gidset = NULL;
1270 int max;
1271 int ret;
1273 /* setgroups(2) will fail with EINVAL if we pass too many groups. */
1274 max = groups_max();
1276 /* No group list, just make sure we are setting the efective GID. */
1277 if (setlen == 0) {
1278 return setgroups(1, &primary_gid);
1281 /* If the primary gid is not the first array element, grow the array
1282 * and insert it at the front.
1284 if (gidset[0] != primary_gid) {
1285 new_gidset = SMB_MALLOC_ARRAY(gid_t, setlen + 1);
1286 if (new_gidset == NULL) {
1287 return -1;
1290 memcpy(new_gidset + 1, gidset, (setlen * sizeof(gid_t)));
1291 new_gidset[0] = primary_gid;
1292 setlen++;
1295 if (setlen > max) {
1296 DEBUG(3, ("forced to truncate group list from %d to %d\n",
1297 setlen, max));
1298 setlen = max;
1301 #if defined(HAVE_BROKEN_GETGROUPS)
1302 ret = sys_broken_setgroups(setlen, new_gidset ? new_gidset : gidset);
1303 #else
1304 ret = setgroups(setlen, new_gidset ? new_gidset : gidset);
1305 #endif
1307 if (new_gidset) {
1308 int errsav = errno;
1309 SAFE_FREE(new_gidset);
1310 errno = errsav;
1313 return ret;
1316 #endif /* USE_BSD_SETGROUPS */
1318 /**************************************************************************
1319 Wrapper for getgroups. Deals with broken (int) case.
1320 ****************************************************************************/
1322 int sys_getgroups(int setlen, gid_t *gidset)
1324 #if defined(HAVE_BROKEN_GETGROUPS)
1325 return sys_broken_getgroups(setlen, gidset);
1326 #else
1327 return getgroups(setlen, gidset);
1328 #endif
1331 /**************************************************************************
1332 Wrapper for setgroups. Deals with broken (int) case and BSD case.
1333 ****************************************************************************/
1335 int sys_setgroups(gid_t UNUSED(primary_gid), int setlen, gid_t *gidset)
1337 #if !defined(HAVE_SETGROUPS)
1338 errno = ENOSYS;
1339 return -1;
1340 #endif /* HAVE_SETGROUPS */
1342 #if defined(USE_BSD_SETGROUPS)
1343 return sys_bsd_setgroups(primary_gid, setlen, gidset);
1344 #elif defined(HAVE_BROKEN_GETGROUPS)
1345 return sys_broken_setgroups(setlen, gidset);
1346 #else
1347 return setgroups(setlen, gidset);
1348 #endif
1351 /**************************************************************************
1352 Extract a command into an arg list.
1353 ****************************************************************************/
1355 static char **extract_args(TALLOC_CTX *mem_ctx, const char *command)
1357 char *trunc_cmd;
1358 char *saveptr;
1359 char *ptr;
1360 int argcl;
1361 char **argl = NULL;
1362 int i;
1364 if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1365 DEBUG(0, ("talloc failed\n"));
1366 goto nomem;
1369 if(!(ptr = strtok_r(trunc_cmd, " \t", &saveptr))) {
1370 TALLOC_FREE(trunc_cmd);
1371 errno = EINVAL;
1372 return NULL;
1376 * Count the args.
1379 for( argcl = 1; ptr; ptr = strtok_r(NULL, " \t", &saveptr))
1380 argcl++;
1382 TALLOC_FREE(trunc_cmd);
1384 if (!(argl = TALLOC_ARRAY(mem_ctx, char *, argcl + 1))) {
1385 goto nomem;
1389 * Now do the extraction.
1392 if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1393 goto nomem;
1396 ptr = strtok_r(trunc_cmd, " \t", &saveptr);
1397 i = 0;
1399 if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1400 goto nomem;
1403 while((ptr = strtok_r(NULL, " \t", &saveptr)) != NULL) {
1405 if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1406 goto nomem;
1410 argl[i++] = NULL;
1411 TALLOC_FREE(trunc_cmd);
1412 return argl;
1414 nomem:
1415 DEBUG(0, ("talloc failed\n"));
1416 TALLOC_FREE(trunc_cmd);
1417 TALLOC_FREE(argl);
1418 errno = ENOMEM;
1419 return NULL;
1422 /**************************************************************************
1423 Wrapper for popen. Safer as it doesn't search a path.
1424 Modified from the glibc sources.
1425 modified by tridge to return a file descriptor. We must kick our FILE* habit
1426 ****************************************************************************/
1428 typedef struct _popen_list
1430 int fd;
1431 pid_t child_pid;
1432 struct _popen_list *next;
1433 } popen_list;
1435 static popen_list *popen_chain;
1437 int sys_popen(const char *command)
1439 int parent_end, child_end;
1440 int pipe_fds[2];
1441 popen_list *entry = NULL;
1442 char **argl = NULL;
1444 if (pipe(pipe_fds) < 0)
1445 return -1;
1447 parent_end = pipe_fds[0];
1448 child_end = pipe_fds[1];
1450 if (!*command) {
1451 errno = EINVAL;
1452 goto err_exit;
1455 if((entry = SMB_MALLOC_P(popen_list)) == NULL)
1456 goto err_exit;
1458 ZERO_STRUCTP(entry);
1461 * Extract the command and args into a NULL terminated array.
1464 if(!(argl = extract_args(NULL, command)))
1465 goto err_exit;
1467 entry->child_pid = sys_fork();
1469 if (entry->child_pid == -1) {
1470 goto err_exit;
1473 if (entry->child_pid == 0) {
1476 * Child !
1479 int child_std_end = STDOUT_FILENO;
1480 popen_list *p;
1482 close(parent_end);
1483 if (child_end != child_std_end) {
1484 dup2 (child_end, child_std_end);
1485 close (child_end);
1489 * POSIX.2: "popen() shall ensure that any streams from previous
1490 * popen() calls that remain open in the parent process are closed
1491 * in the new child process."
1494 for (p = popen_chain; p; p = p->next)
1495 close(p->fd);
1497 execv(argl[0], argl);
1498 _exit (127);
1502 * Parent.
1505 close (child_end);
1506 TALLOC_FREE(argl);
1508 /* Link into popen_chain. */
1509 entry->next = popen_chain;
1510 popen_chain = entry;
1511 entry->fd = parent_end;
1513 return entry->fd;
1515 err_exit:
1517 SAFE_FREE(entry);
1518 TALLOC_FREE(argl);
1519 close(pipe_fds[0]);
1520 close(pipe_fds[1]);
1521 return -1;
1524 /**************************************************************************
1525 Wrapper for pclose. Modified from the glibc sources.
1526 ****************************************************************************/
1528 int sys_pclose(int fd)
1530 int wstatus;
1531 popen_list **ptr = &popen_chain;
1532 popen_list *entry = NULL;
1533 pid_t wait_pid;
1534 int status = -1;
1536 /* Unlink from popen_chain. */
1537 for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
1538 if ((*ptr)->fd == fd) {
1539 entry = *ptr;
1540 *ptr = (*ptr)->next;
1541 status = 0;
1542 break;
1546 if (status < 0 || close(entry->fd) < 0)
1547 return -1;
1550 * As Samba is catching and eating child process
1551 * exits we don't really care about the child exit
1552 * code, a -1 with errno = ECHILD will do fine for us.
1555 do {
1556 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
1557 } while (wait_pid == -1 && errno == EINTR);
1559 SAFE_FREE(entry);
1561 if (wait_pid == -1)
1562 return -1;
1563 return wstatus;
1566 /**************************************************************************
1567 Wrapper for Admin Logs.
1568 ****************************************************************************/
1570 void sys_adminlog(int priority, const char *format_str, ...)
1572 va_list ap;
1573 int ret;
1574 char *msgbuf = NULL;
1576 va_start( ap, format_str );
1577 ret = vasprintf( &msgbuf, format_str, ap );
1578 va_end( ap );
1580 if (ret == -1)
1581 return;
1583 #if defined(HAVE_SYSLOG)
1584 syslog( priority, "%s", msgbuf );
1585 #else
1586 DEBUG(0,("%s", msgbuf ));
1587 #endif
1588 SAFE_FREE(msgbuf);
1591 /******** Solaris EA helper function prototypes ********/
1592 #ifdef HAVE_ATTROPEN
1593 #define SOLARIS_ATTRMODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP
1594 static int solaris_write_xattr(int attrfd, const char *value, size_t size);
1595 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size);
1596 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size);
1597 static int solaris_unlinkat(int attrdirfd, const char *name);
1598 static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode);
1599 static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode);
1600 #endif
1602 /**************************************************************************
1603 Wrappers for extented attribute calls. Based on the Linux package with
1604 support for IRIX and (Net|Free)BSD also. Expand as other systems have them.
1605 ****************************************************************************/
1607 ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t size)
1609 #if defined(HAVE_GETXATTR)
1610 #ifndef XATTR_ADD_OPT
1611 return getxattr(path, name, value, size);
1612 #else
1613 int options = 0;
1614 return getxattr(path, name, value, size, 0, options);
1615 #endif
1616 #elif defined(HAVE_GETEA)
1617 return getea(path, name, value, size);
1618 #elif defined(HAVE_EXTATTR_GET_FILE)
1619 char *s;
1620 ssize_t retval;
1621 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1622 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1623 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1625 * The BSD implementation has a nasty habit of silently truncating
1626 * the returned value to the size of the buffer, so we have to check
1627 * that the buffer is large enough to fit the returned value.
1629 if((retval=extattr_get_file(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1630 if(retval > size) {
1631 errno = ERANGE;
1632 return -1;
1634 if((retval=extattr_get_file(path, attrnamespace, attrname, value, size)) >= 0)
1635 return retval;
1638 DEBUG(10,("sys_getxattr: extattr_get_file() failed with: %s\n", strerror(errno)));
1639 return -1;
1640 #elif defined(HAVE_ATTR_GET)
1641 int retval, flags = 0;
1642 int valuelength = (int)size;
1643 char *attrname = strchr(name,'.') + 1;
1645 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1647 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1649 return retval ? retval : valuelength;
1650 #elif defined(HAVE_ATTROPEN)
1651 ssize_t ret = -1;
1652 int attrfd = solaris_attropen(path, name, O_RDONLY, 0);
1653 if (attrfd >= 0) {
1654 ret = solaris_read_xattr(attrfd, value, size);
1655 close(attrfd);
1657 return ret;
1658 #else
1659 errno = ENOSYS;
1660 return -1;
1661 #endif
1664 ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t size)
1666 #if defined(HAVE_LGETXATTR)
1667 return lgetxattr(path, name, value, size);
1668 #elif defined(HAVE_GETXATTR) && defined(XATTR_ADD_OPT)
1669 int options = XATTR_NOFOLLOW;
1670 return getxattr(path, name, value, size, 0, options);
1671 #elif defined(HAVE_LGETEA)
1672 return lgetea(path, name, value, size);
1673 #elif defined(HAVE_EXTATTR_GET_LINK)
1674 char *s;
1675 ssize_t retval;
1676 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1677 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1678 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1680 if((retval=extattr_get_link(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1681 if(retval > size) {
1682 errno = ERANGE;
1683 return -1;
1685 if((retval=extattr_get_link(path, attrnamespace, attrname, value, size)) >= 0)
1686 return retval;
1689 DEBUG(10,("sys_lgetxattr: extattr_get_link() failed with: %s\n", strerror(errno)));
1690 return -1;
1691 #elif defined(HAVE_ATTR_GET)
1692 int retval, flags = ATTR_DONTFOLLOW;
1693 int valuelength = (int)size;
1694 char *attrname = strchr(name,'.') + 1;
1696 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1698 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1700 return retval ? retval : valuelength;
1701 #elif defined(HAVE_ATTROPEN)
1702 ssize_t ret = -1;
1703 int attrfd = solaris_attropen(path, name, O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1704 if (attrfd >= 0) {
1705 ret = solaris_read_xattr(attrfd, value, size);
1706 close(attrfd);
1708 return ret;
1709 #else
1710 errno = ENOSYS;
1711 return -1;
1712 #endif
1715 ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size)
1717 #if defined(HAVE_FGETXATTR)
1718 #ifndef XATTR_ADD_OPT
1719 return fgetxattr(filedes, name, value, size);
1720 #else
1721 int options = 0;
1722 return fgetxattr(filedes, name, value, size, 0, options);
1723 #endif
1724 #elif defined(HAVE_FGETEA)
1725 return fgetea(filedes, name, value, size);
1726 #elif defined(HAVE_EXTATTR_GET_FD)
1727 char *s;
1728 ssize_t retval;
1729 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1730 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1731 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1733 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0)) >= 0) {
1734 if(retval > size) {
1735 errno = ERANGE;
1736 return -1;
1738 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, value, size)) >= 0)
1739 return retval;
1742 DEBUG(10,("sys_fgetxattr: extattr_get_fd() failed with: %s\n", strerror(errno)));
1743 return -1;
1744 #elif defined(HAVE_ATTR_GETF)
1745 int retval, flags = 0;
1746 int valuelength = (int)size;
1747 char *attrname = strchr(name,'.') + 1;
1749 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1751 retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags);
1753 return retval ? retval : valuelength;
1754 #elif defined(HAVE_ATTROPEN)
1755 ssize_t ret = -1;
1756 int attrfd = solaris_openat(filedes, name, O_RDONLY|O_XATTR, 0);
1757 if (attrfd >= 0) {
1758 ret = solaris_read_xattr(attrfd, value, size);
1759 close(attrfd);
1761 return ret;
1762 #else
1763 errno = ENOSYS;
1764 return -1;
1765 #endif
1768 #if defined(HAVE_EXTATTR_LIST_FILE)
1770 #define EXTATTR_PREFIX(s) (s), (sizeof((s))-1)
1772 static struct {
1773 int space;
1774 const char *name;
1775 size_t len;
1777 extattr[] = {
1778 { EXTATTR_NAMESPACE_SYSTEM, EXTATTR_PREFIX("system.") },
1779 { EXTATTR_NAMESPACE_USER, EXTATTR_PREFIX("user.") },
1782 typedef union {
1783 const char *path;
1784 int filedes;
1785 } extattr_arg;
1787 static ssize_t bsd_attr_list (int type, extattr_arg arg, char *list, size_t size)
1789 ssize_t list_size, total_size = 0;
1790 int i, t, len;
1791 char *buf;
1792 /* Iterate through extattr(2) namespaces */
1793 for(t = 0; t < (sizeof(extattr)/sizeof(extattr[0])); t++) {
1794 switch(type) {
1795 #if defined(HAVE_EXTATTR_LIST_FILE)
1796 case 0:
1797 list_size = extattr_list_file(arg.path, extattr[t].space, list, size);
1798 break;
1799 #endif
1800 #if defined(HAVE_EXTATTR_LIST_LINK)
1801 case 1:
1802 list_size = extattr_list_link(arg.path, extattr[t].space, list, size);
1803 break;
1804 #endif
1805 #if defined(HAVE_EXTATTR_LIST_FD)
1806 case 2:
1807 list_size = extattr_list_fd(arg.filedes, extattr[t].space, list, size);
1808 break;
1809 #endif
1810 default:
1811 errno = ENOSYS;
1812 return -1;
1814 /* Some error happend. Errno should be set by the previous call */
1815 if(list_size < 0)
1816 return -1;
1817 /* No attributes */
1818 if(list_size == 0)
1819 continue;
1820 /* XXX: Call with an empty buffer may be used to calculate
1821 necessary buffer size. Unfortunately, we can't say, how
1822 many attributes were returned, so here is the potential
1823 problem with the emulation.
1825 if(list == NULL) {
1826 /* Take the worse case of one char attribute names -
1827 two bytes per name plus one more for sanity.
1829 total_size += list_size + (list_size/2 + 1)*extattr[t].len;
1830 continue;
1832 /* Count necessary offset to fit namespace prefixes */
1833 len = 0;
1834 for(i = 0; i < list_size; i += list[i] + 1)
1835 len += extattr[t].len;
1837 total_size += list_size + len;
1838 /* Buffer is too small to fit the results */
1839 if(total_size > size) {
1840 errno = ERANGE;
1841 return -1;
1843 /* Shift results back, so we can prepend prefixes */
1844 buf = (char *)memmove(list + len, list, list_size);
1846 for(i = 0; i < list_size; i += len + 1) {
1847 len = buf[i];
1848 strncpy(list, extattr[t].name, extattr[t].len + 1);
1849 list += extattr[t].len;
1850 strncpy(list, buf + i + 1, len);
1851 list[len] = '\0';
1852 list += len + 1;
1854 size -= total_size;
1856 return total_size;
1859 #endif
1861 #if defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1862 static char attr_buffer[ATTR_MAX_VALUELEN];
1864 static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags)
1866 int retval = 0, index;
1867 attrlist_cursor_t *cursor = 0;
1868 int total_size = 0;
1869 attrlist_t * al = (attrlist_t *)attr_buffer;
1870 attrlist_ent_t *ae;
1871 size_t ent_size, left = size;
1872 char *bp = list;
1874 while (True) {
1875 if (filedes)
1876 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1877 else
1878 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1879 if (retval) break;
1880 for (index = 0; index < al->al_count; index++) {
1881 ae = ATTR_ENTRY(attr_buffer, index);
1882 ent_size = strlen(ae->a_name) + sizeof("user.");
1883 if (left >= ent_size) {
1884 strncpy(bp, "user.", sizeof("user."));
1885 strncat(bp, ae->a_name, ent_size - sizeof("user."));
1886 bp += ent_size;
1887 left -= ent_size;
1888 } else if (size) {
1889 errno = ERANGE;
1890 retval = -1;
1891 break;
1893 total_size += ent_size;
1895 if (al->al_more == 0) break;
1897 if (retval == 0) {
1898 flags |= ATTR_ROOT;
1899 cursor = 0;
1900 while (True) {
1901 if (filedes)
1902 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1903 else
1904 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1905 if (retval) break;
1906 for (index = 0; index < al->al_count; index++) {
1907 ae = ATTR_ENTRY(attr_buffer, index);
1908 ent_size = strlen(ae->a_name) + sizeof("system.");
1909 if (left >= ent_size) {
1910 strncpy(bp, "system.", sizeof("system."));
1911 strncat(bp, ae->a_name, ent_size - sizeof("system."));
1912 bp += ent_size;
1913 left -= ent_size;
1914 } else if (size) {
1915 errno = ERANGE;
1916 retval = -1;
1917 break;
1919 total_size += ent_size;
1921 if (al->al_more == 0) break;
1924 return (ssize_t)(retval ? retval : total_size);
1927 #endif
1929 ssize_t sys_listxattr (const char *path, char *list, size_t size)
1931 #if defined(HAVE_LISTXATTR)
1932 #ifndef XATTR_ADD_OPT
1933 return listxattr(path, list, size);
1934 #else
1935 int options = 0;
1936 return listxattr(path, list, size, options);
1937 #endif
1938 #elif defined(HAVE_LISTEA)
1939 return listea(path, list, size);
1940 #elif defined(HAVE_EXTATTR_LIST_FILE)
1941 extattr_arg arg;
1942 arg.path = path;
1943 return bsd_attr_list(0, arg, list, size);
1944 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1945 return irix_attr_list(path, 0, list, size, 0);
1946 #elif defined(HAVE_ATTROPEN)
1947 ssize_t ret = -1;
1948 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
1949 if (attrdirfd >= 0) {
1950 ret = solaris_list_xattr(attrdirfd, list, size);
1951 close(attrdirfd);
1953 return ret;
1954 #else
1955 errno = ENOSYS;
1956 return -1;
1957 #endif
1960 ssize_t sys_llistxattr (const char *path, char *list, size_t size)
1962 #if defined(HAVE_LLISTXATTR)
1963 return llistxattr(path, list, size);
1964 #elif defined(HAVE_LISTXATTR) && defined(XATTR_ADD_OPT)
1965 int options = XATTR_NOFOLLOW;
1966 return listxattr(path, list, size, options);
1967 #elif defined(HAVE_LLISTEA)
1968 return llistea(path, list, size);
1969 #elif defined(HAVE_EXTATTR_LIST_LINK)
1970 extattr_arg arg;
1971 arg.path = path;
1972 return bsd_attr_list(1, arg, list, size);
1973 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1974 return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW);
1975 #elif defined(HAVE_ATTROPEN)
1976 ssize_t ret = -1;
1977 int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1978 if (attrdirfd >= 0) {
1979 ret = solaris_list_xattr(attrdirfd, list, size);
1980 close(attrdirfd);
1982 return ret;
1983 #else
1984 errno = ENOSYS;
1985 return -1;
1986 #endif
1989 ssize_t sys_flistxattr (int filedes, char *list, size_t size)
1991 #if defined(HAVE_FLISTXATTR)
1992 #ifndef XATTR_ADD_OPT
1993 return flistxattr(filedes, list, size);
1994 #else
1995 int options = 0;
1996 return flistxattr(filedes, list, size, options);
1997 #endif
1998 #elif defined(HAVE_FLISTEA)
1999 return flistea(filedes, list, size);
2000 #elif defined(HAVE_EXTATTR_LIST_FD)
2001 extattr_arg arg;
2002 arg.filedes = filedes;
2003 return bsd_attr_list(2, arg, list, size);
2004 #elif defined(HAVE_ATTR_LISTF)
2005 return irix_attr_list(NULL, filedes, list, size, 0);
2006 #elif defined(HAVE_ATTROPEN)
2007 ssize_t ret = -1;
2008 int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
2009 if (attrdirfd >= 0) {
2010 ret = solaris_list_xattr(attrdirfd, list, size);
2011 close(attrdirfd);
2013 return ret;
2014 #else
2015 errno = ENOSYS;
2016 return -1;
2017 #endif
2020 int sys_removexattr (const char *path, const char *name)
2022 #if defined(HAVE_REMOVEXATTR)
2023 #ifndef XATTR_ADD_OPT
2024 return removexattr(path, name);
2025 #else
2026 int options = 0;
2027 return removexattr(path, name, options);
2028 #endif
2029 #elif defined(HAVE_REMOVEEA)
2030 return removeea(path, name);
2031 #elif defined(HAVE_EXTATTR_DELETE_FILE)
2032 char *s;
2033 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2034 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2035 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2037 return extattr_delete_file(path, attrnamespace, attrname);
2038 #elif defined(HAVE_ATTR_REMOVE)
2039 int flags = 0;
2040 char *attrname = strchr(name,'.') + 1;
2042 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
2044 return attr_remove(path, attrname, flags);
2045 #elif defined(HAVE_ATTROPEN)
2046 int ret = -1;
2047 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
2048 if (attrdirfd >= 0) {
2049 ret = solaris_unlinkat(attrdirfd, name);
2050 close(attrdirfd);
2052 return ret;
2053 #else
2054 errno = ENOSYS;
2055 return -1;
2056 #endif
2059 int sys_lremovexattr (const char *path, const char *name)
2061 #if defined(HAVE_LREMOVEXATTR)
2062 return lremovexattr(path, name);
2063 #elif defined(HAVE_REMOVEXATTR) && defined(XATTR_ADD_OPT)
2064 int options = XATTR_NOFOLLOW;
2065 return removexattr(path, name, options);
2066 #elif defined(HAVE_LREMOVEEA)
2067 return lremoveea(path, name);
2068 #elif defined(HAVE_EXTATTR_DELETE_LINK)
2069 char *s;
2070 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2071 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2072 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2074 return extattr_delete_link(path, attrnamespace, attrname);
2075 #elif defined(HAVE_ATTR_REMOVE)
2076 int flags = ATTR_DONTFOLLOW;
2077 char *attrname = strchr(name,'.') + 1;
2079 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
2081 return attr_remove(path, attrname, flags);
2082 #elif defined(HAVE_ATTROPEN)
2083 int ret = -1;
2084 int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
2085 if (attrdirfd >= 0) {
2086 ret = solaris_unlinkat(attrdirfd, name);
2087 close(attrdirfd);
2089 return ret;
2090 #else
2091 errno = ENOSYS;
2092 return -1;
2093 #endif
2096 int sys_fremovexattr (int filedes, const char *name)
2098 #if defined(HAVE_FREMOVEXATTR)
2099 #ifndef XATTR_ADD_OPT
2100 return fremovexattr(filedes, name);
2101 #else
2102 int options = 0;
2103 return fremovexattr(filedes, name, options);
2104 #endif
2105 #elif defined(HAVE_FREMOVEEA)
2106 return fremoveea(filedes, name);
2107 #elif defined(HAVE_EXTATTR_DELETE_FD)
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_fd(filedes, attrnamespace, attrname);
2114 #elif defined(HAVE_ATTR_REMOVEF)
2115 int flags = 0;
2116 char *attrname = strchr(name,'.') + 1;
2118 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
2120 return attr_removef(filedes, attrname, flags);
2121 #elif defined(HAVE_ATTROPEN)
2122 int ret = -1;
2123 int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 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_setxattr (const char *path, const char *name, const void *value, size_t size, int flags)
2137 #if defined(HAVE_SETXATTR)
2138 #ifndef XATTR_ADD_OPT
2139 return setxattr(path, name, value, size, flags);
2140 #else
2141 int options = 0;
2142 return setxattr(path, name, value, size, 0, options);
2143 #endif
2144 #elif defined(HAVE_SETEA)
2145 return setea(path, name, value, size, flags);
2146 #elif defined(HAVE_EXTATTR_SET_FILE)
2147 char *s;
2148 int retval = 0;
2149 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2150 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2151 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2152 if (flags) {
2153 /* Check attribute existence */
2154 retval = extattr_get_file(path, attrnamespace, attrname, NULL, 0);
2155 if (retval < 0) {
2156 /* REPLACE attribute, that doesn't exist */
2157 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2158 errno = ENOATTR;
2159 return -1;
2161 /* Ignore other errors */
2163 else {
2164 /* CREATE attribute, that already exists */
2165 if (flags & XATTR_CREATE) {
2166 errno = EEXIST;
2167 return -1;
2171 retval = extattr_set_file(path, attrnamespace, attrname, value, size);
2172 return (retval < 0) ? -1 : 0;
2173 #elif defined(HAVE_ATTR_SET)
2174 int myflags = 0;
2175 char *attrname = strchr(name,'.') + 1;
2177 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2178 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2179 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2181 return attr_set(path, attrname, (const char *)value, size, myflags);
2182 #elif defined(HAVE_ATTROPEN)
2183 int ret = -1;
2184 int myflags = O_RDWR;
2185 int attrfd;
2186 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2187 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2188 attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2189 if (attrfd >= 0) {
2190 ret = solaris_write_xattr(attrfd, value, size);
2191 close(attrfd);
2193 return ret;
2194 #else
2195 errno = ENOSYS;
2196 return -1;
2197 #endif
2200 int sys_lsetxattr (const char *path, const char *name, const void *value, size_t size, int flags)
2202 #if defined(HAVE_LSETXATTR)
2203 return lsetxattr(path, name, value, size, flags);
2204 #elif defined(HAVE_SETXATTR) && defined(XATTR_ADD_OPT)
2205 int options = XATTR_NOFOLLOW;
2206 return setxattr(path, name, value, size, 0, options);
2207 #elif defined(LSETEA)
2208 return lsetea(path, name, value, size, flags);
2209 #elif defined(HAVE_EXTATTR_SET_LINK)
2210 char *s;
2211 int retval = 0;
2212 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2213 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2214 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2215 if (flags) {
2216 /* Check attribute existence */
2217 retval = extattr_get_link(path, attrnamespace, attrname, NULL, 0);
2218 if (retval < 0) {
2219 /* REPLACE attribute, that doesn't exist */
2220 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2221 errno = ENOATTR;
2222 return -1;
2224 /* Ignore other errors */
2226 else {
2227 /* CREATE attribute, that already exists */
2228 if (flags & XATTR_CREATE) {
2229 errno = EEXIST;
2230 return -1;
2235 retval = extattr_set_link(path, attrnamespace, attrname, value, size);
2236 return (retval < 0) ? -1 : 0;
2237 #elif defined(HAVE_ATTR_SET)
2238 int myflags = ATTR_DONTFOLLOW;
2239 char *attrname = strchr(name,'.') + 1;
2241 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2242 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2243 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2245 return attr_set(path, attrname, (const char *)value, size, myflags);
2246 #elif defined(HAVE_ATTROPEN)
2247 int ret = -1;
2248 int myflags = O_RDWR | AT_SYMLINK_NOFOLLOW;
2249 int attrfd;
2250 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2251 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2252 attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2253 if (attrfd >= 0) {
2254 ret = solaris_write_xattr(attrfd, value, size);
2255 close(attrfd);
2257 return ret;
2258 #else
2259 errno = ENOSYS;
2260 return -1;
2261 #endif
2264 int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags)
2266 #if defined(HAVE_FSETXATTR)
2267 #ifndef XATTR_ADD_OPT
2268 return fsetxattr(filedes, name, value, size, flags);
2269 #else
2270 int options = 0;
2271 return fsetxattr(filedes, name, value, size, 0, options);
2272 #endif
2273 #elif defined(HAVE_FSETEA)
2274 return fsetea(filedes, name, value, size, flags);
2275 #elif defined(HAVE_EXTATTR_SET_FD)
2276 char *s;
2277 int retval = 0;
2278 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2279 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2280 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2281 if (flags) {
2282 /* Check attribute existence */
2283 retval = extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0);
2284 if (retval < 0) {
2285 /* REPLACE attribute, that doesn't exist */
2286 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2287 errno = ENOATTR;
2288 return -1;
2290 /* Ignore other errors */
2292 else {
2293 /* CREATE attribute, that already exists */
2294 if (flags & XATTR_CREATE) {
2295 errno = EEXIST;
2296 return -1;
2300 retval = extattr_set_fd(filedes, attrnamespace, attrname, value, size);
2301 return (retval < 0) ? -1 : 0;
2302 #elif defined(HAVE_ATTR_SETF)
2303 int myflags = 0;
2304 char *attrname = strchr(name,'.') + 1;
2306 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2307 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2308 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2310 return attr_setf(filedes, attrname, (const char *)value, size, myflags);
2311 #elif defined(HAVE_ATTROPEN)
2312 int ret = -1;
2313 int myflags = O_RDWR | O_XATTR;
2314 int attrfd;
2315 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2316 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2317 attrfd = solaris_openat(filedes, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2318 if (attrfd >= 0) {
2319 ret = solaris_write_xattr(attrfd, value, size);
2320 close(attrfd);
2322 return ret;
2323 #else
2324 errno = ENOSYS;
2325 return -1;
2326 #endif
2329 /**************************************************************************
2330 helper functions for Solaris' EA support
2331 ****************************************************************************/
2332 #ifdef HAVE_ATTROPEN
2333 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size)
2335 struct stat sbuf;
2337 if (fstat(attrfd, &sbuf) == -1) {
2338 errno = ENOATTR;
2339 return -1;
2342 /* This is to return the current size of the named extended attribute */
2343 if (size == 0) {
2344 return sbuf.st_size;
2347 /* check size and read xattr */
2348 if (sbuf.st_size > size) {
2349 errno = ERANGE;
2350 return -1;
2353 return read(attrfd, value, sbuf.st_size);
2356 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size)
2358 ssize_t len = 0;
2359 DIR *dirp;
2360 struct dirent *de;
2361 int newfd = dup(attrdirfd);
2362 /* CAUTION: The originating file descriptor should not be
2363 used again following the call to fdopendir().
2364 For that reason we dup() the file descriptor
2365 here to make things more clear. */
2366 dirp = fdopendir(newfd);
2368 while ((de = readdir(dirp))) {
2369 size_t listlen = strlen(de->d_name);
2370 if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) {
2371 /* we don't want "." and ".." here: */
2372 DEBUG(10,("skipped EA %s\n",de->d_name));
2373 continue;
2376 if (size == 0) {
2377 /* return the current size of the list of extended attribute names*/
2378 len += listlen + 1;
2379 } else {
2380 /* check size and copy entrieѕ + nul into list. */
2381 if ((len + listlen + 1) > size) {
2382 errno = ERANGE;
2383 len = -1;
2384 break;
2385 } else {
2386 safe_strcpy(list + len, de->d_name, listlen);
2387 len += listlen;
2388 list[len] = '\0';
2389 ++len;
2394 if (closedir(dirp) == -1) {
2395 DEBUG(0,("closedir dirp failed: %s\n",strerror(errno)));
2396 return -1;
2398 return len;
2401 static int solaris_unlinkat(int attrdirfd, const char *name)
2403 if (unlinkat(attrdirfd, name, 0) == -1) {
2404 if (errno == ENOENT) {
2405 errno = ENOATTR;
2407 return -1;
2409 return 0;
2412 static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode)
2414 int filedes = attropen(path, attrpath, oflag, mode);
2415 if (filedes == -1) {
2416 DEBUG(10,("attropen FAILED: path: %s, name: %s, errno: %s\n",path,attrpath,strerror(errno)));
2417 if (errno == EINVAL) {
2418 errno = ENOTSUP;
2419 } else {
2420 errno = ENOATTR;
2423 return filedes;
2426 static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode)
2428 int filedes = openat(fildes, path, oflag, mode);
2429 if (filedes == -1) {
2430 DEBUG(10,("openat FAILED: fd: %d, path: %s, errno: %s\n",filedes,path,strerror(errno)));
2431 if (errno == EINVAL) {
2432 errno = ENOTSUP;
2433 } else {
2434 errno = ENOATTR;
2437 return filedes;
2440 static int solaris_write_xattr(int attrfd, const char *value, size_t size)
2442 if ((ftruncate(attrfd, 0) == 0) && (write(attrfd, value, size) == size)) {
2443 return 0;
2444 } else {
2445 DEBUG(10,("solaris_write_xattr FAILED!\n"));
2446 return -1;
2449 #endif /*HAVE_ATTROPEN*/
2452 /****************************************************************************
2453 Return the major devicenumber for UNIX extensions.
2454 ****************************************************************************/
2456 uint32 unix_dev_major(SMB_DEV_T dev)
2458 #if defined(HAVE_DEVICE_MAJOR_FN)
2459 return (uint32)major(dev);
2460 #else
2461 return (uint32)(dev >> 8);
2462 #endif
2465 /****************************************************************************
2466 Return the minor devicenumber for UNIX extensions.
2467 ****************************************************************************/
2469 uint32 unix_dev_minor(SMB_DEV_T dev)
2471 #if defined(HAVE_DEVICE_MINOR_FN)
2472 return (uint32)minor(dev);
2473 #else
2474 return (uint32)(dev & 0xff);
2475 #endif
2478 #if defined(WITH_AIO)
2480 /*******************************************************************
2481 An aio_read wrapper that will deal with 64-bit sizes.
2482 ********************************************************************/
2484 int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2486 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_READ64)
2487 return aio_read64(aiocb);
2488 #elif defined(HAVE_AIO_READ)
2489 return aio_read(aiocb);
2490 #else
2491 errno = ENOSYS;
2492 return -1;
2493 #endif
2496 /*******************************************************************
2497 An aio_write wrapper that will deal with 64-bit sizes.
2498 ********************************************************************/
2500 int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2502 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_WRITE64)
2503 return aio_write64(aiocb);
2504 #elif defined(HAVE_AIO_WRITE)
2505 return aio_write(aiocb);
2506 #else
2507 errno = ENOSYS;
2508 return -1;
2509 #endif
2512 /*******************************************************************
2513 An aio_return wrapper that will deal with 64-bit sizes.
2514 ********************************************************************/
2516 ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2518 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_RETURN64)
2519 return aio_return64(aiocb);
2520 #elif defined(HAVE_AIO_RETURN)
2521 return aio_return(aiocb);
2522 #else
2523 errno = ENOSYS;
2524 return -1;
2525 #endif
2528 /*******************************************************************
2529 An aio_cancel wrapper that will deal with 64-bit sizes.
2530 ********************************************************************/
2532 int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2534 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_CANCEL64)
2535 return aio_cancel64(fd, aiocb);
2536 #elif defined(HAVE_AIO_CANCEL)
2537 return aio_cancel(fd, aiocb);
2538 #else
2539 errno = ENOSYS;
2540 return -1;
2541 #endif
2544 /*******************************************************************
2545 An aio_error wrapper that will deal with 64-bit sizes.
2546 ********************************************************************/
2548 int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2550 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_ERROR64)
2551 return aio_error64(aiocb);
2552 #elif defined(HAVE_AIO_ERROR)
2553 return aio_error(aiocb);
2554 #else
2555 errno = ENOSYS;
2556 return -1;
2557 #endif
2560 /*******************************************************************
2561 An aio_fsync wrapper that will deal with 64-bit sizes.
2562 ********************************************************************/
2564 int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2566 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_FSYNC64)
2567 return aio_fsync64(op, aiocb);
2568 #elif defined(HAVE_AIO_FSYNC)
2569 return aio_fsync(op, aiocb);
2570 #else
2571 errno = ENOSYS;
2572 return -1;
2573 #endif
2576 /*******************************************************************
2577 An aio_fsync wrapper that will deal with 64-bit sizes.
2578 ********************************************************************/
2580 int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2582 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_SUSPEND64)
2583 return aio_suspend64(cblist, n, timeout);
2584 #elif defined(HAVE_AIO_FSYNC)
2585 return aio_suspend(cblist, n, timeout);
2586 #else
2587 errno = ENOSYS;
2588 return -1;
2589 #endif
2591 #else /* !WITH_AIO */
2593 int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2595 errno = ENOSYS;
2596 return -1;
2599 int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2601 errno = ENOSYS;
2602 return -1;
2605 ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2607 errno = ENOSYS;
2608 return -1;
2611 int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2613 errno = ENOSYS;
2614 return -1;
2617 int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2619 errno = ENOSYS;
2620 return -1;
2623 int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2625 errno = ENOSYS;
2626 return -1;
2629 int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2631 errno = ENOSYS;
2632 return -1;
2634 #endif /* WITH_AIO */
2636 int sys_getpeereid( int s, uid_t *uid)
2638 #if defined(HAVE_PEERCRED)
2639 struct ucred cred;
2640 socklen_t cred_len = sizeof(struct ucred);
2641 int ret;
2643 ret = getsockopt(s, SOL_SOCKET, SO_PEERCRED, (void *)&cred, &cred_len);
2644 if (ret != 0) {
2645 return -1;
2648 if (cred_len != sizeof(struct ucred)) {
2649 errno = EINVAL;
2650 return -1;
2653 *uid = cred.uid;
2654 return 0;
2655 #else
2656 #if defined(HAVE_GETPEEREID)
2657 gid_t gid;
2658 return getpeereid(s, uid, &gid);
2659 #endif
2660 errno = ENOSYS;
2661 return -1;
2662 #endif
2665 int sys_getnameinfo(const struct sockaddr *psa,
2666 socklen_t salen,
2667 char *host,
2668 size_t hostlen,
2669 char *service,
2670 size_t servlen,
2671 int flags)
2674 * For Solaris we must make sure salen is the
2675 * correct length for the incoming sa_family.
2678 if (salen == sizeof(struct sockaddr_storage)) {
2679 salen = sizeof(struct sockaddr_in);
2680 #if defined(HAVE_IPV6)
2681 if (psa->sa_family == AF_INET6) {
2682 salen = sizeof(struct sockaddr_in6);
2684 #endif
2686 return getnameinfo(psa, salen, host, hostlen, service, servlen, flags);
2689 int sys_connect(int fd, const struct sockaddr * addr)
2691 socklen_t salen = (socklen_t)-1;
2693 if (addr->sa_family == AF_INET) {
2694 salen = sizeof(struct sockaddr_in);
2695 } else if (addr->sa_family == AF_UNIX) {
2696 salen = sizeof(struct sockaddr_un);
2698 #if defined(HAVE_IPV6)
2699 else if (addr->sa_family == AF_INET6) {
2700 salen = sizeof(struct sockaddr_in6);
2702 #endif
2704 return connect(fd, addr, salen);