s3:dbwrap: change dbwrap_fetch_uint32() to NTSTATUS return type (instead of bool)
[Samba/vl.git] / source3 / lib / system.c
blob0aefd6d9294c64caafdac0086c11ca80addb14ad
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"
27 #include "system/filesys.h"
28 #include "lib/uid_wrapper/uid_wrapper.h"
30 #ifdef HAVE_SYS_PRCTL_H
31 #include <sys/prctl.h>
32 #endif
35 The idea is that this file will eventually have wrappers around all
36 important system calls in samba. The aims are:
38 - to enable easier porting by putting OS dependent stuff in here
40 - to allow for hooks into other "pseudo-filesystems"
42 - to allow easier integration of things like the japanese extensions
44 - to support the philosophy of Samba to expose the features of
45 the OS within the SMB model. In general whatever file/printer/variable
46 expansions/etc make sense to the OS should be acceptable to Samba.
51 /*******************************************************************
52 A wrapper for usleep in case we don't have one.
53 ********************************************************************/
55 int sys_usleep(long usecs)
57 #ifndef HAVE_USLEEP
58 struct timeval tval;
59 #endif
62 * We need this braindamage as the glibc usleep
63 * is not SPEC1170 complient... grumble... JRA.
66 if(usecs < 0 || usecs > 999999) {
67 errno = EINVAL;
68 return -1;
71 #if HAVE_USLEEP
72 usleep(usecs);
73 return 0;
74 #else /* HAVE_USLEEP */
76 * Fake it with select...
78 tval.tv_sec = 0;
79 tval.tv_usec = usecs/1000;
80 select(0,NULL,NULL,NULL,&tval);
81 return 0;
82 #endif /* HAVE_USLEEP */
85 /*******************************************************************
86 A read wrapper that will deal with EINTR.
87 ********************************************************************/
89 ssize_t sys_read(int fd, void *buf, size_t count)
91 ssize_t ret;
93 do {
94 ret = read(fd, buf, count);
95 #if defined(EWOULDBLOCK)
96 } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
97 #else
98 } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
99 #endif
100 return ret;
103 /*******************************************************************
104 A write wrapper that will deal with EINTR.
105 ********************************************************************/
107 ssize_t sys_write(int fd, const void *buf, size_t count)
109 ssize_t ret;
111 do {
112 ret = write(fd, buf, count);
113 #if defined(EWOULDBLOCK)
114 } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
115 #else
116 } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
117 #endif
118 return ret;
121 /*******************************************************************
122 A writev wrapper that will deal with EINTR.
123 ********************************************************************/
125 ssize_t sys_writev(int fd, const struct iovec *iov, int iovcnt)
127 ssize_t ret;
129 #if 0
130 /* Try to confuse write_data_iov a bit */
131 if ((random() % 5) == 0) {
132 return sys_write(fd, iov[0].iov_base, iov[0].iov_len);
134 if (iov[0].iov_len > 1) {
135 return sys_write(fd, iov[0].iov_base,
136 (random() % (iov[0].iov_len-1)) + 1);
138 #endif
140 do {
141 ret = writev(fd, iov, iovcnt);
142 #if defined(EWOULDBLOCK)
143 } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
144 #else
145 } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
146 #endif
147 return ret;
150 /*******************************************************************
151 A pread wrapper that will deal with EINTR and 64-bit file offsets.
152 ********************************************************************/
154 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
155 ssize_t sys_pread(int fd, void *buf, size_t count, SMB_OFF_T off)
157 ssize_t ret;
159 do {
160 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_PREAD64)
161 ret = pread64(fd, buf, count, off);
162 #else
163 ret = pread(fd, buf, count, off);
164 #endif
165 } while (ret == -1 && errno == EINTR);
166 return ret;
168 #endif
170 /*******************************************************************
171 A write wrapper that will deal with EINTR and 64-bit file offsets.
172 ********************************************************************/
174 #if defined(HAVE_PWRITE) || defined(HAVE_PWRITE64)
175 ssize_t sys_pwrite(int fd, const void *buf, size_t count, SMB_OFF_T off)
177 ssize_t ret;
179 do {
180 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_PWRITE64)
181 ret = pwrite64(fd, buf, count, off);
182 #else
183 ret = pwrite(fd, buf, count, off);
184 #endif
185 } while (ret == -1 && errno == EINTR);
186 return ret;
188 #endif
190 /*******************************************************************
191 A send wrapper that will deal with EINTR or EAGAIN or EWOULDBLOCK.
192 ********************************************************************/
194 ssize_t sys_send(int s, const void *msg, size_t len, int flags)
196 ssize_t ret;
198 do {
199 ret = send(s, msg, len, flags);
200 #if defined(EWOULDBLOCK)
201 } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
202 #else
203 } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
204 #endif
205 return ret;
208 /*******************************************************************
209 A sendto wrapper that will deal with EINTR or EAGAIN or EWOULDBLOCK.
210 ********************************************************************/
212 ssize_t sys_sendto(int s, const void *msg, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
214 ssize_t ret;
216 do {
217 ret = sendto(s, msg, len, flags, to, tolen);
218 #if defined(EWOULDBLOCK)
219 } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
220 #else
221 } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
222 #endif
223 return ret;
226 /*******************************************************************
227 A recv wrapper that will deal with EINTR or EAGAIN or EWOULDBLOCK.
228 ********************************************************************/
230 ssize_t sys_recv(int fd, void *buf, size_t count, int flags)
232 ssize_t ret;
234 do {
235 ret = recv(fd, buf, count, flags);
236 #if defined(EWOULDBLOCK)
237 } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
238 #else
239 } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
240 #endif
241 return ret;
244 /*******************************************************************
245 A recvfrom wrapper that will deal with EINTR.
246 ********************************************************************/
248 ssize_t sys_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
250 ssize_t ret;
252 do {
253 ret = recvfrom(s, buf, len, flags, from, fromlen);
254 #if defined(EWOULDBLOCK)
255 } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
256 #else
257 } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
258 #endif
259 return ret;
262 /*******************************************************************
263 A fcntl wrapper that will deal with EINTR.
264 ********************************************************************/
266 int sys_fcntl_ptr(int fd, int cmd, void *arg)
268 int ret;
270 do {
271 ret = fcntl(fd, cmd, arg);
272 } while (ret == -1 && errno == EINTR);
273 return ret;
276 /*******************************************************************
277 A fcntl wrapper that will deal with EINTR.
278 ********************************************************************/
280 int sys_fcntl_long(int fd, int cmd, long arg)
282 int ret;
284 do {
285 ret = fcntl(fd, cmd, arg);
286 } while (ret == -1 && errno == EINTR);
287 return ret;
290 /****************************************************************************
291 Get/Set all the possible time fields from a stat struct as a timespec.
292 ****************************************************************************/
294 static struct timespec get_atimespec(const struct stat *pst)
296 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
297 struct timespec ret;
299 /* Old system - no ns timestamp. */
300 ret.tv_sec = pst->st_atime;
301 ret.tv_nsec = 0;
302 return ret;
303 #else
304 #if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
305 return pst->st_atim;
306 #elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
307 struct timespec ret;
308 ret.tv_sec = pst->st_atime;
309 ret.tv_nsec = pst->st_atimensec;
310 return ret;
311 #elif defined(HAVE_STRUCT_STAT_ST_MTIME_N)
312 struct timespec ret;
313 ret.tv_sec = pst->st_atime;
314 ret.tv_nsec = pst->st_atime_n;
315 return ret;
316 #elif defined(HAVE_STRUCT_STAT_ST_UMTIME)
317 struct timespec ret;
318 ret.tv_sec = pst->st_atime;
319 ret.tv_nsec = pst->st_uatime * 1000;
320 return ret;
321 #elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
322 return pst->st_atimespec;
323 #else
324 #error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
325 #endif
326 #endif
329 static struct timespec get_mtimespec(const struct stat *pst)
331 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
332 struct timespec ret;
334 /* Old system - no ns timestamp. */
335 ret.tv_sec = pst->st_mtime;
336 ret.tv_nsec = 0;
337 return ret;
338 #else
339 #if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
340 return pst->st_mtim;
341 #elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
342 struct timespec ret;
343 ret.tv_sec = pst->st_mtime;
344 ret.tv_nsec = pst->st_mtimensec;
345 return ret;
346 #elif defined(HAVE_STRUCT_STAT_ST_MTIME_N)
347 struct timespec ret;
348 ret.tv_sec = pst->st_mtime;
349 ret.tv_nsec = pst->st_mtime_n;
350 return ret;
351 #elif defined(HAVE_STRUCT_STAT_ST_UMTIME)
352 struct timespec ret;
353 ret.tv_sec = pst->st_mtime;
354 ret.tv_nsec = pst->st_umtime * 1000;
355 return ret;
356 #elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
357 return pst->st_mtimespec;
358 #else
359 #error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
360 #endif
361 #endif
364 static struct timespec get_ctimespec(const struct stat *pst)
366 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
367 struct timespec ret;
369 /* Old system - no ns timestamp. */
370 ret.tv_sec = pst->st_ctime;
371 ret.tv_nsec = 0;
372 return ret;
373 #else
374 #if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
375 return pst->st_ctim;
376 #elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
377 struct timespec ret;
378 ret.tv_sec = pst->st_ctime;
379 ret.tv_nsec = pst->st_ctimensec;
380 return ret;
381 #elif defined(HAVE_STRUCT_STAT_ST_MTIME_N)
382 struct timespec ret;
383 ret.tv_sec = pst->st_ctime;
384 ret.tv_nsec = pst->st_ctime_n;
385 return ret;
386 #elif defined(HAVE_STRUCT_STAT_ST_UMTIME)
387 struct timespec ret;
388 ret.tv_sec = pst->st_ctime;
389 ret.tv_nsec = pst->st_uctime * 1000;
390 return ret;
391 #elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
392 return pst->st_ctimespec;
393 #else
394 #error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
395 #endif
396 #endif
399 /****************************************************************************
400 Return the best approximation to a 'create time' under UNIX from a stat
401 structure.
402 ****************************************************************************/
404 static struct timespec calc_create_time_stat(const struct stat *st)
406 struct timespec ret, ret1;
407 struct timespec c_time = get_ctimespec(st);
408 struct timespec m_time = get_mtimespec(st);
409 struct timespec a_time = get_atimespec(st);
411 ret = timespec_compare(&c_time, &m_time) < 0 ? c_time : m_time;
412 ret1 = timespec_compare(&ret, &a_time) < 0 ? ret : a_time;
414 if(!null_timespec(ret1)) {
415 return ret1;
419 * One of ctime, mtime or atime was zero (probably atime).
420 * Just return MIN(ctime, mtime).
422 return ret;
425 /****************************************************************************
426 Return the best approximation to a 'create time' under UNIX from a stat_ex
427 structure.
428 ****************************************************************************/
430 static struct timespec calc_create_time_stat_ex(const struct stat_ex *st)
432 struct timespec ret, ret1;
433 struct timespec c_time = st->st_ex_ctime;
434 struct timespec m_time = st->st_ex_mtime;
435 struct timespec a_time = st->st_ex_atime;
437 ret = timespec_compare(&c_time, &m_time) < 0 ? c_time : m_time;
438 ret1 = timespec_compare(&ret, &a_time) < 0 ? ret : a_time;
440 if(!null_timespec(ret1)) {
441 return ret1;
445 * One of ctime, mtime or atime was zero (probably atime).
446 * Just return MIN(ctime, mtime).
448 return ret;
451 /****************************************************************************
452 Return the 'create time' from a stat struct if it exists (birthtime) or else
453 use the best approximation.
454 ****************************************************************************/
456 static void make_create_timespec(const struct stat *pst, struct stat_ex *dst,
457 bool fake_dir_create_times)
459 if (S_ISDIR(pst->st_mode) && fake_dir_create_times) {
460 dst->st_ex_btime.tv_sec = 315493200L; /* 1/1/1980 */
461 dst->st_ex_btime.tv_nsec = 0;
464 dst->st_ex_calculated_birthtime = false;
466 #if defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC)
467 dst->st_ex_btime = pst->st_birthtimespec;
468 #elif defined(HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC)
469 dst->st_ex_btime.tv_sec = pst->st_birthtime;
470 dst->st_ex_btime.tv_nsec = pst->st_birthtimenspec;
471 #elif defined(HAVE_STRUCT_STAT_ST_BIRTHTIME)
472 dst->st_ex_btime.tv_sec = pst->st_birthtime;
473 dst->st_ex_btime.tv_nsec = 0;
474 #else
475 dst->st_ex_btime = calc_create_time_stat(pst);
476 dst->st_ex_calculated_birthtime = true;
477 #endif
479 /* Deal with systems that don't initialize birthtime correctly.
480 * Pointed out by SATOH Fumiyasu <fumiyas@osstech.jp>.
482 if (null_timespec(dst->st_ex_btime)) {
483 dst->st_ex_btime = calc_create_time_stat(pst);
484 dst->st_ex_calculated_birthtime = true;
488 /****************************************************************************
489 If we update a timestamp in a stat_ex struct we may have to recalculate
490 the birthtime. For now only implement this for write time, but we may
491 also need to do it for atime and ctime. JRA.
492 ****************************************************************************/
494 void update_stat_ex_mtime(struct stat_ex *dst,
495 struct timespec write_ts)
497 dst->st_ex_mtime = write_ts;
499 /* We may have to recalculate btime. */
500 if (dst->st_ex_calculated_birthtime) {
501 dst->st_ex_btime = calc_create_time_stat_ex(dst);
505 void update_stat_ex_create_time(struct stat_ex *dst,
506 struct timespec create_time)
508 dst->st_ex_btime = create_time;
509 dst->st_ex_calculated_birthtime = false;
512 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
513 void init_stat_ex_from_stat (struct stat_ex *dst,
514 const struct stat64 *src,
515 bool fake_dir_create_times)
516 #else
517 void init_stat_ex_from_stat (struct stat_ex *dst,
518 const struct stat *src,
519 bool fake_dir_create_times)
520 #endif
522 dst->st_ex_dev = src->st_dev;
523 dst->st_ex_ino = src->st_ino;
524 dst->st_ex_mode = src->st_mode;
525 dst->st_ex_nlink = src->st_nlink;
526 dst->st_ex_uid = src->st_uid;
527 dst->st_ex_gid = src->st_gid;
528 dst->st_ex_rdev = src->st_rdev;
529 dst->st_ex_size = src->st_size;
530 dst->st_ex_atime = get_atimespec(src);
531 dst->st_ex_mtime = get_mtimespec(src);
532 dst->st_ex_ctime = get_ctimespec(src);
533 make_create_timespec(src, dst, fake_dir_create_times);
534 #ifdef HAVE_STAT_ST_BLKSIZE
535 dst->st_ex_blksize = src->st_blksize;
536 #else
537 dst->st_ex_blksize = STAT_ST_BLOCKSIZE;
538 #endif
540 #ifdef HAVE_STAT_ST_BLOCKS
541 dst->st_ex_blocks = src->st_blocks;
542 #else
543 dst->st_ex_blocks = src->st_size / dst->st_ex_blksize + 1;
544 #endif
546 #ifdef HAVE_STAT_ST_FLAGS
547 dst->st_ex_flags = src->st_flags;
548 #else
549 dst->st_ex_flags = 0;
550 #endif
553 /*******************************************************************
554 A stat() wrapper that will deal with 64 bit filesizes.
555 ********************************************************************/
557 int sys_stat(const char *fname, SMB_STRUCT_STAT *sbuf,
558 bool fake_dir_create_times)
560 int ret;
561 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
562 struct stat64 statbuf;
563 ret = stat64(fname, &statbuf);
564 #else
565 struct stat statbuf;
566 ret = stat(fname, &statbuf);
567 #endif
568 if (ret == 0) {
569 /* we always want directories to appear zero size */
570 if (S_ISDIR(statbuf.st_mode)) {
571 statbuf.st_size = 0;
573 init_stat_ex_from_stat(sbuf, &statbuf, fake_dir_create_times);
575 return ret;
578 /*******************************************************************
579 An fstat() wrapper that will deal with 64 bit filesizes.
580 ********************************************************************/
582 int sys_fstat(int fd, SMB_STRUCT_STAT *sbuf, bool fake_dir_create_times)
584 int ret;
585 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FSTAT64)
586 struct stat64 statbuf;
587 ret = fstat64(fd, &statbuf);
588 #else
589 struct stat statbuf;
590 ret = fstat(fd, &statbuf);
591 #endif
592 if (ret == 0) {
593 /* we always want directories to appear zero size */
594 if (S_ISDIR(statbuf.st_mode)) {
595 statbuf.st_size = 0;
597 init_stat_ex_from_stat(sbuf, &statbuf, fake_dir_create_times);
599 return ret;
602 /*******************************************************************
603 An lstat() wrapper that will deal with 64 bit filesizes.
604 ********************************************************************/
606 int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf,
607 bool fake_dir_create_times)
609 int ret;
610 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSTAT64)
611 struct stat64 statbuf;
612 ret = lstat64(fname, &statbuf);
613 #else
614 struct stat statbuf;
615 ret = lstat(fname, &statbuf);
616 #endif
617 if (ret == 0) {
618 /* we always want directories to appear zero size */
619 if (S_ISDIR(statbuf.st_mode)) {
620 statbuf.st_size = 0;
622 init_stat_ex_from_stat(sbuf, &statbuf, fake_dir_create_times);
624 return ret;
627 /*******************************************************************
628 An posix_fallocate() wrapper that will deal with 64 bit filesizes.
629 ********************************************************************/
630 int sys_posix_fallocate(int fd, SMB_OFF_T offset, SMB_OFF_T len)
632 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_POSIX_FALLOCATE64) && !defined(HAVE_BROKEN_POSIX_FALLOCATE)
633 return posix_fallocate64(fd, offset, len);
634 #elif defined(HAVE_POSIX_FALLOCATE) && !defined(HAVE_BROKEN_POSIX_FALLOCATE)
635 return posix_fallocate(fd, offset, len);
636 #elif defined(F_RESVSP64)
637 /* this handles XFS on IRIX */
638 struct flock64 fl;
639 SMB_OFF_T new_len = offset + len;
640 int ret;
641 struct stat64 sbuf;
643 /* unlikely to get a too large file on a 64bit system but ... */
644 if (new_len < 0)
645 return EFBIG;
647 fl.l_whence = SEEK_SET;
648 fl.l_start = offset;
649 fl.l_len = len;
651 ret=fcntl(fd, F_RESVSP64, &fl);
653 if (ret != 0)
654 return errno;
656 /* Make sure the file gets enlarged after we allocated space: */
657 fstat64(fd, &sbuf);
658 if (new_len > sbuf.st_size)
659 ftruncate64(fd, new_len);
660 return 0;
661 #else
662 return ENOSYS;
663 #endif
666 /*******************************************************************
667 An fallocate() function that matches the semantics of the Linux one.
668 ********************************************************************/
670 #ifdef HAVE_LINUX_FALLOC_H
671 #include <linux/falloc.h>
672 #endif
674 int sys_fallocate(int fd, enum vfs_fallocate_mode mode, SMB_OFF_T offset, SMB_OFF_T len)
676 #if defined(HAVE_LINUX_FALLOCATE64) || defined(HAVE_LINUX_FALLOCATE)
677 int lmode;
678 switch (mode) {
679 case VFS_FALLOCATE_EXTEND_SIZE:
680 lmode = 0;
681 break;
682 case VFS_FALLOCATE_KEEP_SIZE:
683 lmode = FALLOC_FL_KEEP_SIZE;
684 break;
685 default:
686 errno = EINVAL;
687 return -1;
689 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LINUX_FALLOCATE64)
690 return fallocate64(fd, lmode, offset, len);
691 #elif defined(HAVE_LINUX_FALLOCATE)
692 return fallocate(fd, lmode, offset, len);
693 #endif
694 #else
695 /* TODO - plumb in fallocate from other filesysetms like VXFS etc. JRA. */
696 errno = ENOSYS;
697 return -1;
698 #endif
701 /*******************************************************************
702 An ftruncate() wrapper that will deal with 64 bit filesizes.
703 ********************************************************************/
705 int sys_ftruncate(int fd, SMB_OFF_T offset)
707 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FTRUNCATE64)
708 return ftruncate64(fd, offset);
709 #else
710 return ftruncate(fd, offset);
711 #endif
714 /*******************************************************************
715 An lseek() wrapper that will deal with 64 bit filesizes.
716 ********************************************************************/
718 SMB_OFF_T sys_lseek(int fd, SMB_OFF_T offset, int whence)
720 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSEEK64)
721 return lseek64(fd, offset, whence);
722 #else
723 return lseek(fd, offset, whence);
724 #endif
727 /*******************************************************************
728 An fseek() wrapper that will deal with 64 bit filesizes.
729 ********************************************************************/
731 int sys_fseek(FILE *fp, SMB_OFF_T offset, int whence)
733 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEK64)
734 return fseek64(fp, offset, whence);
735 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEKO64)
736 return fseeko64(fp, offset, whence);
737 #else
738 return fseek(fp, offset, whence);
739 #endif
742 /*******************************************************************
743 An ftell() wrapper that will deal with 64 bit filesizes.
744 ********************************************************************/
746 SMB_OFF_T sys_ftell(FILE *fp)
748 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELL64)
749 return (SMB_OFF_T)ftell64(fp);
750 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELLO64)
751 return (SMB_OFF_T)ftello64(fp);
752 #else
753 return (SMB_OFF_T)ftell(fp);
754 #endif
757 /*******************************************************************
758 A creat() wrapper that will deal with 64 bit filesizes.
759 ********************************************************************/
761 int sys_creat(const char *path, mode_t mode)
763 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CREAT64)
764 return creat64(path, mode);
765 #else
767 * If creat64 isn't defined then ensure we call a potential open64.
768 * JRA.
770 return sys_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
771 #endif
774 /*******************************************************************
775 An open() wrapper that will deal with 64 bit filesizes.
776 ********************************************************************/
778 int sys_open(const char *path, int oflag, mode_t mode)
780 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPEN64)
781 return open64(path, oflag, mode);
782 #else
783 return open(path, oflag, mode);
784 #endif
787 /*******************************************************************
788 An fopen() wrapper that will deal with 64 bit filesizes.
789 ********************************************************************/
791 FILE *sys_fopen(const char *path, const char *type)
793 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FOPEN64)
794 return fopen64(path, type);
795 #else
796 return fopen(path, type);
797 #endif
801 #if HAVE_KERNEL_SHARE_MODES
802 #ifndef LOCK_MAND
803 #define LOCK_MAND 32 /* This is a mandatory flock */
804 #define LOCK_READ 64 /* ... Which allows concurrent read operations */
805 #define LOCK_WRITE 128 /* ... Which allows concurrent write operations */
806 #define LOCK_RW 192 /* ... Which allows concurrent read & write ops */
807 #endif
808 #endif
810 /*******************************************************************
811 A flock() wrapper that will perform the kernel flock.
812 ********************************************************************/
814 void kernel_flock(int fd, uint32 share_mode, uint32 access_mask)
816 #if HAVE_KERNEL_SHARE_MODES
817 int kernel_mode = 0;
818 if (share_mode == FILE_SHARE_WRITE) {
819 kernel_mode = LOCK_MAND|LOCK_WRITE;
820 } else if (share_mode == FILE_SHARE_READ) {
821 kernel_mode = LOCK_MAND|LOCK_READ;
822 } else if (share_mode == FILE_SHARE_NONE) {
823 kernel_mode = LOCK_MAND;
825 if (kernel_mode) {
826 flock(fd, kernel_mode);
828 #endif
834 /*******************************************************************
835 An opendir wrapper that will deal with 64 bit filesizes.
836 ********************************************************************/
838 SMB_STRUCT_DIR *sys_opendir(const char *name)
840 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPENDIR64)
841 return opendir64(name);
842 #else
843 return opendir(name);
844 #endif
847 /*******************************************************************
848 An fdopendir wrapper that will deal with 64 bit filesizes.
849 Ugly hack - we need dirfd for this to work correctly in the
850 calling code.. JRA.
851 ********************************************************************/
853 SMB_STRUCT_DIR *sys_fdopendir(int fd)
855 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FDOPENDIR64) && defined(HAVE_DIRFD)
856 return fdopendir64(fd);
857 #elif defined(HAVE_FDOPENDIR) && defined(HAVE_DIRFD)
858 return fdopendir(fd);
859 #else
860 errno = ENOSYS;
861 return NULL;
862 #endif
865 /*******************************************************************
866 A readdir wrapper that will deal with 64 bit filesizes.
867 ********************************************************************/
869 SMB_STRUCT_DIRENT *sys_readdir(SMB_STRUCT_DIR *dirp)
871 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_READDIR64)
872 return readdir64(dirp);
873 #else
874 return readdir(dirp);
875 #endif
878 /*******************************************************************
879 A seekdir wrapper that will deal with 64 bit filesizes.
880 ********************************************************************/
882 void sys_seekdir(SMB_STRUCT_DIR *dirp, long offset)
884 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_SEEKDIR64)
885 seekdir64(dirp, offset);
886 #else
887 seekdir(dirp, offset);
888 #endif
891 /*******************************************************************
892 A telldir wrapper that will deal with 64 bit filesizes.
893 ********************************************************************/
895 long sys_telldir(SMB_STRUCT_DIR *dirp)
897 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_TELLDIR64)
898 return (long)telldir64(dirp);
899 #else
900 return (long)telldir(dirp);
901 #endif
904 /*******************************************************************
905 A rewinddir wrapper that will deal with 64 bit filesizes.
906 ********************************************************************/
908 void sys_rewinddir(SMB_STRUCT_DIR *dirp)
910 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_REWINDDIR64)
911 rewinddir64(dirp);
912 #else
913 rewinddir(dirp);
914 #endif
917 /*******************************************************************
918 A close wrapper that will deal with 64 bit filesizes.
919 ********************************************************************/
921 int sys_closedir(SMB_STRUCT_DIR *dirp)
923 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CLOSEDIR64)
924 return closedir64(dirp);
925 #else
926 return closedir(dirp);
927 #endif
930 /*******************************************************************
931 An mknod() wrapper that will deal with 64 bit filesizes.
932 ********************************************************************/
934 int sys_mknod(const char *path, mode_t mode, SMB_DEV_T dev)
936 #if defined(HAVE_MKNOD) || defined(HAVE_MKNOD64)
937 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_MKNOD64) && defined(HAVE_DEV64_T)
938 return mknod64(path, mode, dev);
939 #else
940 return mknod(path, mode, dev);
941 #endif
942 #else
943 /* No mknod system call. */
944 errno = ENOSYS;
945 return -1;
946 #endif
949 /*******************************************************************
950 The wait() calls vary between systems
951 ********************************************************************/
953 int sys_waitpid(pid_t pid,int *status,int options)
955 #ifdef HAVE_WAITPID
956 return waitpid(pid,status,options);
957 #else /* HAVE_WAITPID */
958 return wait4(pid, status, options, NULL);
959 #endif /* HAVE_WAITPID */
962 /*******************************************************************
963 System wrapper for getwd. Always returns MALLOC'ed memory, or NULL
964 on error (malloc fail usually).
965 ********************************************************************/
967 char *sys_getwd(void)
969 #ifdef GETCWD_TAKES_NULL
970 return getcwd(NULL, 0);
971 #elif HAVE_GETCWD
972 char *wd = NULL, *s = NULL;
973 size_t allocated = PATH_MAX;
975 while (1) {
976 s = SMB_REALLOC_ARRAY(s, char, allocated);
977 if (s == NULL) {
978 return NULL;
980 wd = getcwd(s, allocated);
981 if (wd) {
982 break;
984 if (errno != ERANGE) {
985 SAFE_FREE(s);
986 break;
988 allocated *= 2;
989 if (allocated < PATH_MAX) {
990 SAFE_FREE(s);
991 break;
994 return wd;
995 #else
996 char *s = SMB_MALLOC_ARRAY(char, PATH_MAX);
997 if (s == NULL) {
998 return NULL;
1000 return getwd(s);
1001 #endif
1004 #if defined(HAVE_POSIX_CAPABILITIES)
1006 /**************************************************************************
1007 Try and abstract process capabilities (for systems that have them).
1008 ****************************************************************************/
1010 /* Set the POSIX capabilities needed for the given purpose into the effective
1011 * capability set of the current process. Make sure they are always removed
1012 * from the inheritable set, because there is no circumstance in which our
1013 * children should inherit our elevated privileges.
1015 static bool set_process_capability(enum smbd_capability capability,
1016 bool enable)
1018 cap_value_t cap_vals[2] = {0};
1019 int num_cap_vals = 0;
1021 cap_t cap;
1023 #if defined(HAVE_PRCTL) && defined(PR_GET_KEEPCAPS) && defined(PR_SET_KEEPCAPS)
1024 /* On Linux, make sure that any capabilities we grab are sticky
1025 * across UID changes. We expect that this would allow us to keep both
1026 * the effective and permitted capability sets, but as of circa 2.6.16,
1027 * only the permitted set is kept. It is a bug (which we work around)
1028 * that the effective set is lost, but we still require the effective
1029 * set to be kept.
1031 if (!prctl(PR_GET_KEEPCAPS)) {
1032 prctl(PR_SET_KEEPCAPS, 1);
1034 #endif
1036 cap = cap_get_proc();
1037 if (cap == NULL) {
1038 DEBUG(0,("set_process_capability: cap_get_proc failed: %s\n",
1039 strerror(errno)));
1040 return False;
1043 switch (capability) {
1044 case KERNEL_OPLOCK_CAPABILITY:
1045 #ifdef CAP_NETWORK_MGT
1046 /* IRIX has CAP_NETWORK_MGT for oplocks. */
1047 cap_vals[num_cap_vals++] = CAP_NETWORK_MGT;
1048 #endif
1049 break;
1050 case DMAPI_ACCESS_CAPABILITY:
1051 #ifdef CAP_DEVICE_MGT
1052 /* IRIX has CAP_DEVICE_MGT for DMAPI access. */
1053 cap_vals[num_cap_vals++] = CAP_DEVICE_MGT;
1054 #elif CAP_MKNOD
1055 /* Linux has CAP_MKNOD for DMAPI access. */
1056 cap_vals[num_cap_vals++] = CAP_MKNOD;
1057 #endif
1058 break;
1059 case LEASE_CAPABILITY:
1060 #ifdef CAP_LEASE
1061 cap_vals[num_cap_vals++] = CAP_LEASE;
1062 #endif
1063 break;
1066 SMB_ASSERT(num_cap_vals <= ARRAY_SIZE(cap_vals));
1068 if (num_cap_vals == 0) {
1069 cap_free(cap);
1070 return True;
1073 cap_set_flag(cap, CAP_EFFECTIVE, num_cap_vals, cap_vals,
1074 enable ? CAP_SET : CAP_CLEAR);
1076 /* We never want to pass capabilities down to our children, so make
1077 * sure they are not inherited.
1079 cap_set_flag(cap, CAP_INHERITABLE, num_cap_vals, cap_vals, CAP_CLEAR);
1081 if (cap_set_proc(cap) == -1) {
1082 DEBUG(0, ("set_process_capability: cap_set_proc failed: %s\n",
1083 strerror(errno)));
1084 cap_free(cap);
1085 return False;
1088 cap_free(cap);
1089 return True;
1092 #endif /* HAVE_POSIX_CAPABILITIES */
1094 /****************************************************************************
1095 Gain the oplock capability from the kernel if possible.
1096 ****************************************************************************/
1098 void set_effective_capability(enum smbd_capability capability)
1100 #if defined(HAVE_POSIX_CAPABILITIES)
1101 set_process_capability(capability, True);
1102 #endif /* HAVE_POSIX_CAPABILITIES */
1105 void drop_effective_capability(enum smbd_capability capability)
1107 #if defined(HAVE_POSIX_CAPABILITIES)
1108 set_process_capability(capability, False);
1109 #endif /* HAVE_POSIX_CAPABILITIES */
1112 /**************************************************************************
1113 Wrapper for random().
1114 ****************************************************************************/
1116 long sys_random(void)
1118 #if defined(HAVE_RANDOM)
1119 return (long)random();
1120 #elif defined(HAVE_RAND)
1121 return (long)rand();
1122 #else
1123 DEBUG(0,("Error - no random function available !\n"));
1124 exit(1);
1125 #endif
1128 /**************************************************************************
1129 Wrapper for srandom().
1130 ****************************************************************************/
1132 void sys_srandom(unsigned int seed)
1134 #if defined(HAVE_SRANDOM)
1135 srandom(seed);
1136 #elif defined(HAVE_SRAND)
1137 srand(seed);
1138 #else
1139 DEBUG(0,("Error - no srandom function available !\n"));
1140 exit(1);
1141 #endif
1144 #ifndef NGROUPS_MAX
1145 #define NGROUPS_MAX 32 /* Guess... */
1146 #endif
1148 /**************************************************************************
1149 Returns equivalent to NGROUPS_MAX - using sysconf if needed.
1150 ****************************************************************************/
1152 int groups_max(void)
1154 #if defined(SYSCONF_SC_NGROUPS_MAX)
1155 int ret = sysconf(_SC_NGROUPS_MAX);
1156 return (ret == -1) ? NGROUPS_MAX : ret;
1157 #else
1158 return NGROUPS_MAX;
1159 #endif
1162 /**************************************************************************
1163 Wrap setgroups and getgroups for systems that declare getgroups() as
1164 returning an array of gid_t, but actuall return an array of int.
1165 ****************************************************************************/
1167 #if defined(HAVE_BROKEN_GETGROUPS)
1169 #ifdef HAVE_BROKEN_GETGROUPS
1170 #define GID_T int
1171 #else
1172 #define GID_T gid_t
1173 #endif
1175 static int sys_broken_getgroups(int setlen, gid_t *gidset)
1177 GID_T gid;
1178 GID_T *group_list;
1179 int i, ngroups;
1181 if(setlen == 0) {
1182 return getgroups(setlen, &gid);
1186 * Broken case. We need to allocate a
1187 * GID_T array of size setlen.
1190 if(setlen < 0) {
1191 errno = EINVAL;
1192 return -1;
1195 if (setlen == 0)
1196 setlen = groups_max();
1198 if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
1199 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
1200 return -1;
1203 if((ngroups = getgroups(setlen, group_list)) < 0) {
1204 int saved_errno = errno;
1205 SAFE_FREE(group_list);
1206 errno = saved_errno;
1207 return -1;
1210 for(i = 0; i < ngroups; i++)
1211 gidset[i] = (gid_t)group_list[i];
1213 SAFE_FREE(group_list);
1214 return ngroups;
1217 static int sys_broken_setgroups(int setlen, gid_t *gidset)
1219 GID_T *group_list;
1220 int i ;
1222 if (setlen == 0)
1223 return 0 ;
1225 if (setlen < 0 || setlen > groups_max()) {
1226 errno = EINVAL;
1227 return -1;
1231 * Broken case. We need to allocate a
1232 * GID_T array of size setlen.
1235 if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
1236 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
1237 return -1;
1240 for(i = 0; i < setlen; i++)
1241 group_list[i] = (GID_T) gidset[i];
1243 if(setgroups(setlen, group_list) != 0) {
1244 int saved_errno = errno;
1245 SAFE_FREE(group_list);
1246 errno = saved_errno;
1247 return -1;
1250 SAFE_FREE(group_list);
1251 return 0 ;
1254 #endif /* HAVE_BROKEN_GETGROUPS */
1256 /* This is a list of systems that require the first GID passed to setgroups(2)
1257 * to be the effective GID. If your system is one of these, add it here.
1259 #if defined (FREEBSD) || defined (DARWINOS)
1260 #define USE_BSD_SETGROUPS
1261 #endif
1263 #if defined(USE_BSD_SETGROUPS)
1264 /* Depending on the particular BSD implementation, the first GID that is
1265 * passed to setgroups(2) will either be ignored or will set the credential's
1266 * effective GID. In either case, the right thing to do is to guarantee that
1267 * gidset[0] is the effective GID.
1269 static int sys_bsd_setgroups(gid_t primary_gid, int setlen, const gid_t *gidset)
1271 gid_t *new_gidset = NULL;
1272 int max;
1273 int ret;
1275 /* setgroups(2) will fail with EINVAL if we pass too many groups. */
1276 max = groups_max();
1278 /* No group list, just make sure we are setting the efective GID. */
1279 if (setlen == 0) {
1280 return setgroups(1, &primary_gid);
1283 /* If the primary gid is not the first array element, grow the array
1284 * and insert it at the front.
1286 if (gidset[0] != primary_gid) {
1287 new_gidset = SMB_MALLOC_ARRAY(gid_t, setlen + 1);
1288 if (new_gidset == NULL) {
1289 return -1;
1292 memcpy(new_gidset + 1, gidset, (setlen * sizeof(gid_t)));
1293 new_gidset[0] = primary_gid;
1294 setlen++;
1297 if (setlen > max) {
1298 DEBUG(3, ("forced to truncate group list from %d to %d\n",
1299 setlen, max));
1300 setlen = max;
1303 #if defined(HAVE_BROKEN_GETGROUPS)
1304 ret = sys_broken_setgroups(setlen, new_gidset ? new_gidset : gidset);
1305 #else
1306 ret = setgroups(setlen, new_gidset ? new_gidset : gidset);
1307 #endif
1309 if (new_gidset) {
1310 int errsav = errno;
1311 SAFE_FREE(new_gidset);
1312 errno = errsav;
1315 return ret;
1318 #endif /* USE_BSD_SETGROUPS */
1320 /**************************************************************************
1321 Wrapper for getgroups. Deals with broken (int) case.
1322 ****************************************************************************/
1324 int sys_getgroups(int setlen, gid_t *gidset)
1326 #if defined(HAVE_BROKEN_GETGROUPS)
1327 return sys_broken_getgroups(setlen, gidset);
1328 #else
1329 return getgroups(setlen, gidset);
1330 #endif
1333 /**************************************************************************
1334 Wrapper for setgroups. Deals with broken (int) case and BSD case.
1335 ****************************************************************************/
1337 int sys_setgroups(gid_t UNUSED(primary_gid), int setlen, gid_t *gidset)
1339 #if !defined(HAVE_SETGROUPS)
1340 errno = ENOSYS;
1341 return -1;
1342 #endif /* HAVE_SETGROUPS */
1344 #if defined(USE_BSD_SETGROUPS)
1345 return sys_bsd_setgroups(primary_gid, setlen, gidset);
1346 #elif defined(HAVE_BROKEN_GETGROUPS)
1347 return sys_broken_setgroups(setlen, gidset);
1348 #else
1349 return setgroups(setlen, gidset);
1350 #endif
1353 /**************************************************************************
1354 Extract a command into an arg list.
1355 ****************************************************************************/
1357 static char **extract_args(TALLOC_CTX *mem_ctx, const char *command)
1359 char *trunc_cmd;
1360 char *saveptr;
1361 char *ptr;
1362 int argcl;
1363 char **argl = NULL;
1364 int i;
1366 if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1367 DEBUG(0, ("talloc failed\n"));
1368 goto nomem;
1371 if(!(ptr = strtok_r(trunc_cmd, " \t", &saveptr))) {
1372 TALLOC_FREE(trunc_cmd);
1373 errno = EINVAL;
1374 return NULL;
1378 * Count the args.
1381 for( argcl = 1; ptr; ptr = strtok_r(NULL, " \t", &saveptr))
1382 argcl++;
1384 TALLOC_FREE(trunc_cmd);
1386 if (!(argl = talloc_array(mem_ctx, char *, argcl + 1))) {
1387 goto nomem;
1391 * Now do the extraction.
1394 if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1395 goto nomem;
1398 ptr = strtok_r(trunc_cmd, " \t", &saveptr);
1399 i = 0;
1401 if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1402 goto nomem;
1405 while((ptr = strtok_r(NULL, " \t", &saveptr)) != NULL) {
1407 if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1408 goto nomem;
1412 argl[i++] = NULL;
1413 TALLOC_FREE(trunc_cmd);
1414 return argl;
1416 nomem:
1417 DEBUG(0, ("talloc failed\n"));
1418 TALLOC_FREE(trunc_cmd);
1419 TALLOC_FREE(argl);
1420 errno = ENOMEM;
1421 return NULL;
1424 /**************************************************************************
1425 Wrapper for popen. Safer as it doesn't search a path.
1426 Modified from the glibc sources.
1427 modified by tridge to return a file descriptor. We must kick our FILE* habit
1428 ****************************************************************************/
1430 typedef struct _popen_list
1432 int fd;
1433 pid_t child_pid;
1434 struct _popen_list *next;
1435 } popen_list;
1437 static popen_list *popen_chain;
1439 int sys_popen(const char *command)
1441 int parent_end, child_end;
1442 int pipe_fds[2];
1443 popen_list *entry = NULL;
1444 char **argl = NULL;
1446 if (pipe(pipe_fds) < 0)
1447 return -1;
1449 parent_end = pipe_fds[0];
1450 child_end = pipe_fds[1];
1452 if (!*command) {
1453 errno = EINVAL;
1454 goto err_exit;
1457 if((entry = SMB_MALLOC_P(popen_list)) == NULL)
1458 goto err_exit;
1460 ZERO_STRUCTP(entry);
1463 * Extract the command and args into a NULL terminated array.
1466 if(!(argl = extract_args(NULL, command)))
1467 goto err_exit;
1469 entry->child_pid = sys_fork();
1471 if (entry->child_pid == -1) {
1472 goto err_exit;
1475 if (entry->child_pid == 0) {
1478 * Child !
1481 int child_std_end = STDOUT_FILENO;
1482 popen_list *p;
1484 close(parent_end);
1485 if (child_end != child_std_end) {
1486 dup2 (child_end, child_std_end);
1487 close (child_end);
1491 * POSIX.2: "popen() shall ensure that any streams from previous
1492 * popen() calls that remain open in the parent process are closed
1493 * in the new child process."
1496 for (p = popen_chain; p; p = p->next)
1497 close(p->fd);
1499 execv(argl[0], argl);
1500 _exit (127);
1504 * Parent.
1507 close (child_end);
1508 TALLOC_FREE(argl);
1510 /* Link into popen_chain. */
1511 entry->next = popen_chain;
1512 popen_chain = entry;
1513 entry->fd = parent_end;
1515 return entry->fd;
1517 err_exit:
1519 SAFE_FREE(entry);
1520 TALLOC_FREE(argl);
1521 close(pipe_fds[0]);
1522 close(pipe_fds[1]);
1523 return -1;
1526 /**************************************************************************
1527 Wrapper for pclose. Modified from the glibc sources.
1528 ****************************************************************************/
1530 int sys_pclose(int fd)
1532 int wstatus;
1533 popen_list **ptr = &popen_chain;
1534 popen_list *entry = NULL;
1535 pid_t wait_pid;
1536 int status = -1;
1538 /* Unlink from popen_chain. */
1539 for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
1540 if ((*ptr)->fd == fd) {
1541 entry = *ptr;
1542 *ptr = (*ptr)->next;
1543 status = 0;
1544 break;
1548 if (status < 0 || close(entry->fd) < 0)
1549 return -1;
1552 * As Samba is catching and eating child process
1553 * exits we don't really care about the child exit
1554 * code, a -1 with errno = ECHILD will do fine for us.
1557 do {
1558 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
1559 } while (wait_pid == -1 && errno == EINTR);
1561 SAFE_FREE(entry);
1563 if (wait_pid == -1)
1564 return -1;
1565 return wstatus;
1568 /**************************************************************************
1569 Wrapper for Admin Logs.
1570 ****************************************************************************/
1572 void sys_adminlog(int priority, const char *format_str, ...)
1574 va_list ap;
1575 int ret;
1576 char *msgbuf = NULL;
1578 va_start( ap, format_str );
1579 ret = vasprintf( &msgbuf, format_str, ap );
1580 va_end( ap );
1582 if (ret == -1)
1583 return;
1585 #if defined(HAVE_SYSLOG)
1586 syslog( priority, "%s", msgbuf );
1587 #else
1588 DEBUG(0,("%s", msgbuf ));
1589 #endif
1590 SAFE_FREE(msgbuf);
1593 /******** Solaris EA helper function prototypes ********/
1594 #ifdef HAVE_ATTROPEN
1595 #define SOLARIS_ATTRMODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP
1596 static int solaris_write_xattr(int attrfd, const char *value, size_t size);
1597 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size);
1598 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size);
1599 static int solaris_unlinkat(int attrdirfd, const char *name);
1600 static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode);
1601 static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode);
1602 #endif
1604 /**************************************************************************
1605 Wrappers for extented attribute calls. Based on the Linux package with
1606 support for IRIX and (Net|Free)BSD also. Expand as other systems have them.
1607 ****************************************************************************/
1609 ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t size)
1611 #if defined(HAVE_GETXATTR)
1612 #ifndef XATTR_ADD_OPT
1613 return getxattr(path, name, value, size);
1614 #else
1615 int options = 0;
1616 return getxattr(path, name, value, size, 0, options);
1617 #endif
1618 #elif defined(HAVE_GETEA)
1619 return getea(path, name, value, size);
1620 #elif defined(HAVE_EXTATTR_GET_FILE)
1621 char *s;
1622 ssize_t retval;
1623 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1624 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1625 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1627 * The BSD implementation has a nasty habit of silently truncating
1628 * the returned value to the size of the buffer, so we have to check
1629 * that the buffer is large enough to fit the returned value.
1631 if((retval=extattr_get_file(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1632 if(retval > size) {
1633 errno = ERANGE;
1634 return -1;
1636 if((retval=extattr_get_file(path, attrnamespace, attrname, value, size)) >= 0)
1637 return retval;
1640 DEBUG(10,("sys_getxattr: extattr_get_file() failed with: %s\n", strerror(errno)));
1641 return -1;
1642 #elif defined(HAVE_ATTR_GET)
1643 int retval, flags = 0;
1644 int valuelength = (int)size;
1645 char *attrname = strchr(name,'.') + 1;
1647 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1649 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1651 return retval ? retval : valuelength;
1652 #elif defined(HAVE_ATTROPEN)
1653 ssize_t ret = -1;
1654 int attrfd = solaris_attropen(path, name, O_RDONLY, 0);
1655 if (attrfd >= 0) {
1656 ret = solaris_read_xattr(attrfd, value, size);
1657 close(attrfd);
1659 return ret;
1660 #else
1661 errno = ENOSYS;
1662 return -1;
1663 #endif
1666 ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t size)
1668 #if defined(HAVE_LGETXATTR)
1669 return lgetxattr(path, name, value, size);
1670 #elif defined(HAVE_GETXATTR) && defined(XATTR_ADD_OPT)
1671 int options = XATTR_NOFOLLOW;
1672 return getxattr(path, name, value, size, 0, options);
1673 #elif defined(HAVE_LGETEA)
1674 return lgetea(path, name, value, size);
1675 #elif defined(HAVE_EXTATTR_GET_LINK)
1676 char *s;
1677 ssize_t retval;
1678 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1679 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1680 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1682 if((retval=extattr_get_link(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1683 if(retval > size) {
1684 errno = ERANGE;
1685 return -1;
1687 if((retval=extattr_get_link(path, attrnamespace, attrname, value, size)) >= 0)
1688 return retval;
1691 DEBUG(10,("sys_lgetxattr: extattr_get_link() failed with: %s\n", strerror(errno)));
1692 return -1;
1693 #elif defined(HAVE_ATTR_GET)
1694 int retval, flags = ATTR_DONTFOLLOW;
1695 int valuelength = (int)size;
1696 char *attrname = strchr(name,'.') + 1;
1698 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1700 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1702 return retval ? retval : valuelength;
1703 #elif defined(HAVE_ATTROPEN)
1704 ssize_t ret = -1;
1705 int attrfd = solaris_attropen(path, name, O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1706 if (attrfd >= 0) {
1707 ret = solaris_read_xattr(attrfd, value, size);
1708 close(attrfd);
1710 return ret;
1711 #else
1712 errno = ENOSYS;
1713 return -1;
1714 #endif
1717 ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size)
1719 #if defined(HAVE_FGETXATTR)
1720 #ifndef XATTR_ADD_OPT
1721 return fgetxattr(filedes, name, value, size);
1722 #else
1723 int options = 0;
1724 return fgetxattr(filedes, name, value, size, 0, options);
1725 #endif
1726 #elif defined(HAVE_FGETEA)
1727 return fgetea(filedes, name, value, size);
1728 #elif defined(HAVE_EXTATTR_GET_FD)
1729 char *s;
1730 ssize_t retval;
1731 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1732 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1733 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1735 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0)) >= 0) {
1736 if(retval > size) {
1737 errno = ERANGE;
1738 return -1;
1740 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, value, size)) >= 0)
1741 return retval;
1744 DEBUG(10,("sys_fgetxattr: extattr_get_fd() failed with: %s\n", strerror(errno)));
1745 return -1;
1746 #elif defined(HAVE_ATTR_GETF)
1747 int retval, flags = 0;
1748 int valuelength = (int)size;
1749 char *attrname = strchr(name,'.') + 1;
1751 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1753 retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags);
1755 return retval ? retval : valuelength;
1756 #elif defined(HAVE_ATTROPEN)
1757 ssize_t ret = -1;
1758 int attrfd = solaris_openat(filedes, name, O_RDONLY|O_XATTR, 0);
1759 if (attrfd >= 0) {
1760 ret = solaris_read_xattr(attrfd, value, size);
1761 close(attrfd);
1763 return ret;
1764 #else
1765 errno = ENOSYS;
1766 return -1;
1767 #endif
1770 #if defined(HAVE_EXTATTR_LIST_FILE)
1772 #define EXTATTR_PREFIX(s) (s), (sizeof((s))-1)
1774 static struct {
1775 int space;
1776 const char *name;
1777 size_t len;
1779 extattr[] = {
1780 { EXTATTR_NAMESPACE_SYSTEM, EXTATTR_PREFIX("system.") },
1781 { EXTATTR_NAMESPACE_USER, EXTATTR_PREFIX("user.") },
1784 typedef union {
1785 const char *path;
1786 int filedes;
1787 } extattr_arg;
1789 static ssize_t bsd_attr_list (int type, extattr_arg arg, char *list, size_t size)
1791 ssize_t list_size, total_size = 0;
1792 int i, t, len;
1793 char *buf;
1794 /* Iterate through extattr(2) namespaces */
1795 for(t = 0; t < (sizeof(extattr)/sizeof(extattr[0])); t++) {
1796 switch(type) {
1797 #if defined(HAVE_EXTATTR_LIST_FILE)
1798 case 0:
1799 list_size = extattr_list_file(arg.path, extattr[t].space, list, size);
1800 break;
1801 #endif
1802 #if defined(HAVE_EXTATTR_LIST_LINK)
1803 case 1:
1804 list_size = extattr_list_link(arg.path, extattr[t].space, list, size);
1805 break;
1806 #endif
1807 #if defined(HAVE_EXTATTR_LIST_FD)
1808 case 2:
1809 list_size = extattr_list_fd(arg.filedes, extattr[t].space, list, size);
1810 break;
1811 #endif
1812 default:
1813 errno = ENOSYS;
1814 return -1;
1816 /* Some error happend. Errno should be set by the previous call */
1817 if(list_size < 0)
1818 return -1;
1819 /* No attributes */
1820 if(list_size == 0)
1821 continue;
1822 /* XXX: Call with an empty buffer may be used to calculate
1823 necessary buffer size. Unfortunately, we can't say, how
1824 many attributes were returned, so here is the potential
1825 problem with the emulation.
1827 if(list == NULL) {
1828 /* Take the worse case of one char attribute names -
1829 two bytes per name plus one more for sanity.
1831 total_size += list_size + (list_size/2 + 1)*extattr[t].len;
1832 continue;
1834 /* Count necessary offset to fit namespace prefixes */
1835 len = 0;
1836 for(i = 0; i < list_size; i += list[i] + 1)
1837 len += extattr[t].len;
1839 total_size += list_size + len;
1840 /* Buffer is too small to fit the results */
1841 if(total_size > size) {
1842 errno = ERANGE;
1843 return -1;
1845 /* Shift results back, so we can prepend prefixes */
1846 buf = (char *)memmove(list + len, list, list_size);
1848 for(i = 0; i < list_size; i += len + 1) {
1849 len = buf[i];
1850 strncpy(list, extattr[t].name, extattr[t].len + 1);
1851 list += extattr[t].len;
1852 strncpy(list, buf + i + 1, len);
1853 list[len] = '\0';
1854 list += len + 1;
1856 size -= total_size;
1858 return total_size;
1861 #endif
1863 #if defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1864 static char attr_buffer[ATTR_MAX_VALUELEN];
1866 static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags)
1868 int retval = 0, index;
1869 attrlist_cursor_t *cursor = 0;
1870 int total_size = 0;
1871 attrlist_t * al = (attrlist_t *)attr_buffer;
1872 attrlist_ent_t *ae;
1873 size_t ent_size, left = size;
1874 char *bp = list;
1876 while (True) {
1877 if (filedes)
1878 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1879 else
1880 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1881 if (retval) break;
1882 for (index = 0; index < al->al_count; index++) {
1883 ae = ATTR_ENTRY(attr_buffer, index);
1884 ent_size = strlen(ae->a_name) + sizeof("user.");
1885 if (left >= ent_size) {
1886 strncpy(bp, "user.", sizeof("user."));
1887 strncat(bp, ae->a_name, ent_size - sizeof("user."));
1888 bp += ent_size;
1889 left -= ent_size;
1890 } else if (size) {
1891 errno = ERANGE;
1892 retval = -1;
1893 break;
1895 total_size += ent_size;
1897 if (al->al_more == 0) break;
1899 if (retval == 0) {
1900 flags |= ATTR_ROOT;
1901 cursor = 0;
1902 while (True) {
1903 if (filedes)
1904 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1905 else
1906 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1907 if (retval) break;
1908 for (index = 0; index < al->al_count; index++) {
1909 ae = ATTR_ENTRY(attr_buffer, index);
1910 ent_size = strlen(ae->a_name) + sizeof("system.");
1911 if (left >= ent_size) {
1912 strncpy(bp, "system.", sizeof("system."));
1913 strncat(bp, ae->a_name, ent_size - sizeof("system."));
1914 bp += ent_size;
1915 left -= ent_size;
1916 } else if (size) {
1917 errno = ERANGE;
1918 retval = -1;
1919 break;
1921 total_size += ent_size;
1923 if (al->al_more == 0) break;
1926 return (ssize_t)(retval ? retval : total_size);
1929 #endif
1931 ssize_t sys_listxattr (const char *path, char *list, size_t size)
1933 #if defined(HAVE_LISTXATTR)
1934 #ifndef XATTR_ADD_OPT
1935 return listxattr(path, list, size);
1936 #else
1937 int options = 0;
1938 return listxattr(path, list, size, options);
1939 #endif
1940 #elif defined(HAVE_LISTEA)
1941 return listea(path, list, size);
1942 #elif defined(HAVE_EXTATTR_LIST_FILE)
1943 extattr_arg arg;
1944 arg.path = path;
1945 return bsd_attr_list(0, arg, list, size);
1946 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1947 return irix_attr_list(path, 0, list, size, 0);
1948 #elif defined(HAVE_ATTROPEN)
1949 ssize_t ret = -1;
1950 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
1951 if (attrdirfd >= 0) {
1952 ret = solaris_list_xattr(attrdirfd, list, size);
1953 close(attrdirfd);
1955 return ret;
1956 #else
1957 errno = ENOSYS;
1958 return -1;
1959 #endif
1962 ssize_t sys_llistxattr (const char *path, char *list, size_t size)
1964 #if defined(HAVE_LLISTXATTR)
1965 return llistxattr(path, list, size);
1966 #elif defined(HAVE_LISTXATTR) && defined(XATTR_ADD_OPT)
1967 int options = XATTR_NOFOLLOW;
1968 return listxattr(path, list, size, options);
1969 #elif defined(HAVE_LLISTEA)
1970 return llistea(path, list, size);
1971 #elif defined(HAVE_EXTATTR_LIST_LINK)
1972 extattr_arg arg;
1973 arg.path = path;
1974 return bsd_attr_list(1, arg, list, size);
1975 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1976 return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW);
1977 #elif defined(HAVE_ATTROPEN)
1978 ssize_t ret = -1;
1979 int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1980 if (attrdirfd >= 0) {
1981 ret = solaris_list_xattr(attrdirfd, list, size);
1982 close(attrdirfd);
1984 return ret;
1985 #else
1986 errno = ENOSYS;
1987 return -1;
1988 #endif
1991 ssize_t sys_flistxattr (int filedes, char *list, size_t size)
1993 #if defined(HAVE_FLISTXATTR)
1994 #ifndef XATTR_ADD_OPT
1995 return flistxattr(filedes, list, size);
1996 #else
1997 int options = 0;
1998 return flistxattr(filedes, list, size, options);
1999 #endif
2000 #elif defined(HAVE_FLISTEA)
2001 return flistea(filedes, list, size);
2002 #elif defined(HAVE_EXTATTR_LIST_FD)
2003 extattr_arg arg;
2004 arg.filedes = filedes;
2005 return bsd_attr_list(2, arg, list, size);
2006 #elif defined(HAVE_ATTR_LISTF)
2007 return irix_attr_list(NULL, filedes, list, size, 0);
2008 #elif defined(HAVE_ATTROPEN)
2009 ssize_t ret = -1;
2010 int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
2011 if (attrdirfd >= 0) {
2012 ret = solaris_list_xattr(attrdirfd, list, size);
2013 close(attrdirfd);
2015 return ret;
2016 #else
2017 errno = ENOSYS;
2018 return -1;
2019 #endif
2022 int sys_removexattr (const char *path, const char *name)
2024 #if defined(HAVE_REMOVEXATTR)
2025 #ifndef XATTR_ADD_OPT
2026 return removexattr(path, name);
2027 #else
2028 int options = 0;
2029 return removexattr(path, name, options);
2030 #endif
2031 #elif defined(HAVE_REMOVEEA)
2032 return removeea(path, name);
2033 #elif defined(HAVE_EXTATTR_DELETE_FILE)
2034 char *s;
2035 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2036 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2037 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2039 return extattr_delete_file(path, attrnamespace, attrname);
2040 #elif defined(HAVE_ATTR_REMOVE)
2041 int flags = 0;
2042 char *attrname = strchr(name,'.') + 1;
2044 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
2046 return attr_remove(path, attrname, flags);
2047 #elif defined(HAVE_ATTROPEN)
2048 int ret = -1;
2049 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
2050 if (attrdirfd >= 0) {
2051 ret = solaris_unlinkat(attrdirfd, name);
2052 close(attrdirfd);
2054 return ret;
2055 #else
2056 errno = ENOSYS;
2057 return -1;
2058 #endif
2061 int sys_lremovexattr (const char *path, const char *name)
2063 #if defined(HAVE_LREMOVEXATTR)
2064 return lremovexattr(path, name);
2065 #elif defined(HAVE_REMOVEXATTR) && defined(XATTR_ADD_OPT)
2066 int options = XATTR_NOFOLLOW;
2067 return removexattr(path, name, options);
2068 #elif defined(HAVE_LREMOVEEA)
2069 return lremoveea(path, name);
2070 #elif defined(HAVE_EXTATTR_DELETE_LINK)
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_link(path, attrnamespace, attrname);
2077 #elif defined(HAVE_ATTR_REMOVE)
2078 int flags = ATTR_DONTFOLLOW;
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|AT_SYMLINK_NOFOLLOW, 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_fremovexattr (int filedes, const char *name)
2100 #if defined(HAVE_FREMOVEXATTR)
2101 #ifndef XATTR_ADD_OPT
2102 return fremovexattr(filedes, name);
2103 #else
2104 int options = 0;
2105 return fremovexattr(filedes, name, options);
2106 #endif
2107 #elif defined(HAVE_FREMOVEEA)
2108 return fremoveea(filedes, name);
2109 #elif defined(HAVE_EXTATTR_DELETE_FD)
2110 char *s;
2111 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2112 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2113 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2115 return extattr_delete_fd(filedes, attrnamespace, attrname);
2116 #elif defined(HAVE_ATTR_REMOVEF)
2117 int flags = 0;
2118 char *attrname = strchr(name,'.') + 1;
2120 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
2122 return attr_removef(filedes, attrname, flags);
2123 #elif defined(HAVE_ATTROPEN)
2124 int ret = -1;
2125 int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
2126 if (attrdirfd >= 0) {
2127 ret = solaris_unlinkat(attrdirfd, name);
2128 close(attrdirfd);
2130 return ret;
2131 #else
2132 errno = ENOSYS;
2133 return -1;
2134 #endif
2137 int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags)
2139 #if defined(HAVE_SETXATTR)
2140 #ifndef XATTR_ADD_OPT
2141 return setxattr(path, name, value, size, flags);
2142 #else
2143 int options = 0;
2144 return setxattr(path, name, value, size, 0, options);
2145 #endif
2146 #elif defined(HAVE_SETEA)
2147 return setea(path, name, value, size, flags);
2148 #elif defined(HAVE_EXTATTR_SET_FILE)
2149 char *s;
2150 int retval = 0;
2151 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2152 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2153 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2154 if (flags) {
2155 /* Check attribute existence */
2156 retval = extattr_get_file(path, attrnamespace, attrname, NULL, 0);
2157 if (retval < 0) {
2158 /* REPLACE attribute, that doesn't exist */
2159 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2160 errno = ENOATTR;
2161 return -1;
2163 /* Ignore other errors */
2165 else {
2166 /* CREATE attribute, that already exists */
2167 if (flags & XATTR_CREATE) {
2168 errno = EEXIST;
2169 return -1;
2173 retval = extattr_set_file(path, attrnamespace, attrname, value, size);
2174 return (retval < 0) ? -1 : 0;
2175 #elif defined(HAVE_ATTR_SET)
2176 int myflags = 0;
2177 char *attrname = strchr(name,'.') + 1;
2179 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2180 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2181 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2183 return attr_set(path, attrname, (const char *)value, size, myflags);
2184 #elif defined(HAVE_ATTROPEN)
2185 int ret = -1;
2186 int myflags = O_RDWR;
2187 int attrfd;
2188 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2189 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2190 attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2191 if (attrfd >= 0) {
2192 ret = solaris_write_xattr(attrfd, value, size);
2193 close(attrfd);
2195 return ret;
2196 #else
2197 errno = ENOSYS;
2198 return -1;
2199 #endif
2202 int sys_lsetxattr (const char *path, const char *name, const void *value, size_t size, int flags)
2204 #if defined(HAVE_LSETXATTR)
2205 return lsetxattr(path, name, value, size, flags);
2206 #elif defined(HAVE_SETXATTR) && defined(XATTR_ADD_OPT)
2207 int options = XATTR_NOFOLLOW;
2208 return setxattr(path, name, value, size, 0, options);
2209 #elif defined(LSETEA)
2210 return lsetea(path, name, value, size, flags);
2211 #elif defined(HAVE_EXTATTR_SET_LINK)
2212 char *s;
2213 int retval = 0;
2214 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2215 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2216 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2217 if (flags) {
2218 /* Check attribute existence */
2219 retval = extattr_get_link(path, attrnamespace, attrname, NULL, 0);
2220 if (retval < 0) {
2221 /* REPLACE attribute, that doesn't exist */
2222 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2223 errno = ENOATTR;
2224 return -1;
2226 /* Ignore other errors */
2228 else {
2229 /* CREATE attribute, that already exists */
2230 if (flags & XATTR_CREATE) {
2231 errno = EEXIST;
2232 return -1;
2237 retval = extattr_set_link(path, attrnamespace, attrname, value, size);
2238 return (retval < 0) ? -1 : 0;
2239 #elif defined(HAVE_ATTR_SET)
2240 int myflags = ATTR_DONTFOLLOW;
2241 char *attrname = strchr(name,'.') + 1;
2243 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2244 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2245 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2247 return attr_set(path, attrname, (const char *)value, size, myflags);
2248 #elif defined(HAVE_ATTROPEN)
2249 int ret = -1;
2250 int myflags = O_RDWR | AT_SYMLINK_NOFOLLOW;
2251 int attrfd;
2252 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2253 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2254 attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2255 if (attrfd >= 0) {
2256 ret = solaris_write_xattr(attrfd, value, size);
2257 close(attrfd);
2259 return ret;
2260 #else
2261 errno = ENOSYS;
2262 return -1;
2263 #endif
2266 int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags)
2268 #if defined(HAVE_FSETXATTR)
2269 #ifndef XATTR_ADD_OPT
2270 return fsetxattr(filedes, name, value, size, flags);
2271 #else
2272 int options = 0;
2273 return fsetxattr(filedes, name, value, size, 0, options);
2274 #endif
2275 #elif defined(HAVE_FSETEA)
2276 return fsetea(filedes, name, value, size, flags);
2277 #elif defined(HAVE_EXTATTR_SET_FD)
2278 char *s;
2279 int retval = 0;
2280 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2281 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2282 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2283 if (flags) {
2284 /* Check attribute existence */
2285 retval = extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0);
2286 if (retval < 0) {
2287 /* REPLACE attribute, that doesn't exist */
2288 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2289 errno = ENOATTR;
2290 return -1;
2292 /* Ignore other errors */
2294 else {
2295 /* CREATE attribute, that already exists */
2296 if (flags & XATTR_CREATE) {
2297 errno = EEXIST;
2298 return -1;
2302 retval = extattr_set_fd(filedes, attrnamespace, attrname, value, size);
2303 return (retval < 0) ? -1 : 0;
2304 #elif defined(HAVE_ATTR_SETF)
2305 int myflags = 0;
2306 char *attrname = strchr(name,'.') + 1;
2308 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2309 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2310 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2312 return attr_setf(filedes, attrname, (const char *)value, size, myflags);
2313 #elif defined(HAVE_ATTROPEN)
2314 int ret = -1;
2315 int myflags = O_RDWR | O_XATTR;
2316 int attrfd;
2317 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2318 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2319 attrfd = solaris_openat(filedes, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2320 if (attrfd >= 0) {
2321 ret = solaris_write_xattr(attrfd, value, size);
2322 close(attrfd);
2324 return ret;
2325 #else
2326 errno = ENOSYS;
2327 return -1;
2328 #endif
2331 /**************************************************************************
2332 helper functions for Solaris' EA support
2333 ****************************************************************************/
2334 #ifdef HAVE_ATTROPEN
2335 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size)
2337 struct stat sbuf;
2339 if (fstat(attrfd, &sbuf) == -1) {
2340 errno = ENOATTR;
2341 return -1;
2344 /* This is to return the current size of the named extended attribute */
2345 if (size == 0) {
2346 return sbuf.st_size;
2349 /* check size and read xattr */
2350 if (sbuf.st_size > size) {
2351 errno = ERANGE;
2352 return -1;
2355 return read(attrfd, value, sbuf.st_size);
2358 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size)
2360 ssize_t len = 0;
2361 DIR *dirp;
2362 struct dirent *de;
2363 int newfd = dup(attrdirfd);
2364 /* CAUTION: The originating file descriptor should not be
2365 used again following the call to fdopendir().
2366 For that reason we dup() the file descriptor
2367 here to make things more clear. */
2368 dirp = fdopendir(newfd);
2370 while ((de = readdir(dirp))) {
2371 size_t listlen = strlen(de->d_name) + 1;
2372 if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) {
2373 /* we don't want "." and ".." here: */
2374 DEBUG(10,("skipped EA %s\n",de->d_name));
2375 continue;
2378 if (size == 0) {
2379 /* return the current size of the list of extended attribute names*/
2380 len += listlen;
2381 } else {
2382 /* check size and copy entrieѕ + nul into list. */
2383 if ((len + listlen) > size) {
2384 errno = ERANGE;
2385 len = -1;
2386 break;
2387 } else {
2388 strlcpy(list + len, de->d_name, listlen);
2389 len += listlen;
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 */