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