2 Unix SMB/CIFS implementation.
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/>.
24 #include "system/syslog.h"
25 #include "system/capability.h"
26 #include "system/passwd.h"
28 #ifdef HAVE_SYS_PRCTL_H
29 #include <sys/prctl.h>
33 The idea is that this file will eventually have wrappers around all
34 important system calls in samba. The aims are:
36 - to enable easier porting by putting OS dependent stuff in here
38 - to allow for hooks into other "pseudo-filesystems"
40 - to allow easier integration of things like the japanese extensions
42 - to support the philosophy of Samba to expose the features of
43 the OS within the SMB model. In general whatever file/printer/variable
44 expansions/etc make sense to the OS should be acceptable to Samba.
49 /*******************************************************************
50 A wrapper for memalign
51 ********************************************************************/
53 void *sys_memalign( size_t align
, size_t size
)
55 #if defined(HAVE_POSIX_MEMALIGN)
57 int ret
= posix_memalign( &p
, align
, size
);
62 #elif defined(HAVE_MEMALIGN)
63 return memalign( align
, size
);
65 /* On *BSD systems memaligns doesn't exist, but memory will
66 * be aligned on allocations of > pagesize. */
67 #if defined(SYSCONF_SC_PAGESIZE)
68 size_t pagesize
= (size_t)sysconf(_SC_PAGESIZE
);
69 #elif defined(HAVE_GETPAGESIZE)
70 size_t pagesize
= (size_t)getpagesize();
72 size_t pagesize
= (size_t)-1;
74 if (pagesize
== (size_t)-1) {
75 DEBUG(0,("memalign functionalaity not available on this platform!\n"));
78 if (size
< pagesize
) {
81 return SMB_MALLOC(size
);
85 /*******************************************************************
86 A wrapper for usleep in case we don't have one.
87 ********************************************************************/
89 int sys_usleep(long usecs
)
96 * We need this braindamage as the glibc usleep
97 * is not SPEC1170 complient... grumble... JRA.
100 if(usecs
< 0 || usecs
> 999999) {
108 #else /* HAVE_USLEEP */
110 * Fake it with select...
113 tval
.tv_usec
= usecs
/1000;
114 select(0,NULL
,NULL
,NULL
,&tval
);
116 #endif /* HAVE_USLEEP */
119 /*******************************************************************
120 A read wrapper that will deal with EINTR.
121 ********************************************************************/
123 ssize_t
sys_read(int fd
, void *buf
, size_t count
)
128 ret
= read(fd
, buf
, count
);
129 #if defined(EWOULDBLOCK)
130 } while (ret
== -1 && (errno
== EINTR
|| errno
== EAGAIN
|| errno
== EWOULDBLOCK
));
132 } while (ret
== -1 && (errno
== EINTR
|| errno
== EAGAIN
));
137 /*******************************************************************
138 A write wrapper that will deal with EINTR.
139 ********************************************************************/
141 ssize_t
sys_write(int fd
, const void *buf
, size_t count
)
146 ret
= write(fd
, buf
, count
);
147 #if defined(EWOULDBLOCK)
148 } while (ret
== -1 && (errno
== EINTR
|| errno
== EAGAIN
|| errno
== EWOULDBLOCK
));
150 } while (ret
== -1 && (errno
== EINTR
|| errno
== EAGAIN
));
155 /*******************************************************************
156 A writev wrapper that will deal with EINTR.
157 ********************************************************************/
159 ssize_t
sys_writev(int fd
, const struct iovec
*iov
, int iovcnt
)
164 /* Try to confuse write_data_iov a bit */
165 if ((random() % 5) == 0) {
166 return sys_write(fd
, iov
[0].iov_base
, iov
[0].iov_len
);
168 if (iov
[0].iov_len
> 1) {
169 return sys_write(fd
, iov
[0].iov_base
,
170 (random() % (iov
[0].iov_len
-1)) + 1);
175 ret
= writev(fd
, iov
, iovcnt
);
176 #if defined(EWOULDBLOCK)
177 } while (ret
== -1 && (errno
== EINTR
|| errno
== EAGAIN
|| errno
== EWOULDBLOCK
));
179 } while (ret
== -1 && (errno
== EINTR
|| errno
== EAGAIN
));
184 /*******************************************************************
185 A pread wrapper that will deal with EINTR and 64-bit file offsets.
186 ********************************************************************/
188 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
189 ssize_t
sys_pread(int fd
, void *buf
, size_t count
, SMB_OFF_T off
)
194 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_PREAD64)
195 ret
= pread64(fd
, buf
, count
, off
);
197 ret
= pread(fd
, buf
, count
, off
);
199 } while (ret
== -1 && errno
== EINTR
);
204 /*******************************************************************
205 A write wrapper that will deal with EINTR and 64-bit file offsets.
206 ********************************************************************/
208 #if defined(HAVE_PWRITE) || defined(HAVE_PWRITE64)
209 ssize_t
sys_pwrite(int fd
, const void *buf
, size_t count
, SMB_OFF_T off
)
214 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_PWRITE64)
215 ret
= pwrite64(fd
, buf
, count
, off
);
217 ret
= pwrite(fd
, buf
, count
, off
);
219 } while (ret
== -1 && errno
== EINTR
);
224 /*******************************************************************
225 A send wrapper that will deal with EINTR or EAGAIN or EWOULDBLOCK.
226 ********************************************************************/
228 ssize_t
sys_send(int s
, const void *msg
, size_t len
, int flags
)
233 ret
= send(s
, msg
, len
, flags
);
234 #if defined(EWOULDBLOCK)
235 } while (ret
== -1 && (errno
== EINTR
|| errno
== EAGAIN
|| errno
== EWOULDBLOCK
));
237 } while (ret
== -1 && (errno
== EINTR
|| errno
== EAGAIN
));
242 /*******************************************************************
243 A sendto wrapper that will deal with EINTR or EAGAIN or EWOULDBLOCK.
244 ********************************************************************/
246 ssize_t
sys_sendto(int s
, const void *msg
, size_t len
, int flags
, const struct sockaddr
*to
, socklen_t tolen
)
251 ret
= sendto(s
, msg
, len
, flags
, to
, tolen
);
252 #if defined(EWOULDBLOCK)
253 } while (ret
== -1 && (errno
== EINTR
|| errno
== EAGAIN
|| errno
== EWOULDBLOCK
));
255 } while (ret
== -1 && (errno
== EINTR
|| errno
== EAGAIN
));
260 /*******************************************************************
261 A recv wrapper that will deal with EINTR or EAGAIN or EWOULDBLOCK.
262 ********************************************************************/
264 ssize_t
sys_recv(int fd
, void *buf
, size_t count
, int flags
)
269 ret
= recv(fd
, buf
, count
, flags
);
270 #if defined(EWOULDBLOCK)
271 } while (ret
== -1 && (errno
== EINTR
|| errno
== EAGAIN
|| errno
== EWOULDBLOCK
));
273 } while (ret
== -1 && (errno
== EINTR
|| errno
== EAGAIN
));
278 /*******************************************************************
279 A recvfrom wrapper that will deal with EINTR.
280 ********************************************************************/
282 ssize_t
sys_recvfrom(int s
, void *buf
, size_t len
, int flags
, struct sockaddr
*from
, socklen_t
*fromlen
)
287 ret
= recvfrom(s
, buf
, len
, flags
, from
, fromlen
);
288 #if defined(EWOULDBLOCK)
289 } while (ret
== -1 && (errno
== EINTR
|| errno
== EAGAIN
|| errno
== EWOULDBLOCK
));
291 } while (ret
== -1 && (errno
== EINTR
|| errno
== EAGAIN
));
296 /*******************************************************************
297 A fcntl wrapper that will deal with EINTR.
298 ********************************************************************/
300 int sys_fcntl_ptr(int fd
, int cmd
, void *arg
)
305 ret
= fcntl(fd
, cmd
, arg
);
306 } while (ret
== -1 && errno
== EINTR
);
310 /*******************************************************************
311 A fcntl wrapper that will deal with EINTR.
312 ********************************************************************/
314 int sys_fcntl_long(int fd
, int cmd
, long arg
)
319 ret
= fcntl(fd
, cmd
, arg
);
320 } while (ret
== -1 && errno
== EINTR
);
324 /****************************************************************************
325 Get/Set all the possible time fields from a stat struct as a timespec.
326 ****************************************************************************/
328 static struct timespec
get_atimespec(const struct stat
*pst
)
330 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
333 /* Old system - no ns timestamp. */
334 ret
.tv_sec
= pst
->st_atime
;
338 #if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
340 #elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
342 ret
.tv_sec
= pst
->st_atime
;
343 ret
.tv_nsec
= pst
->st_atimensec
;
345 #elif defined(HAVE_STRUCT_STAT_ST_MTIME_N)
347 ret
.tv_sec
= pst
->st_atime
;
348 ret
.tv_nsec
= pst
->st_atime_n
;
350 #elif defined(HAVE_STRUCT_STAT_ST_UMTIME)
352 ret
.tv_sec
= pst
->st_atime
;
353 ret
.tv_nsec
= pst
->st_uatime
* 1000;
355 #elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
356 return pst
->st_atimespec
;
358 #error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
363 static struct timespec
get_mtimespec(const struct stat
*pst
)
365 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
368 /* Old system - no ns timestamp. */
369 ret
.tv_sec
= pst
->st_mtime
;
373 #if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
375 #elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
377 ret
.tv_sec
= pst
->st_mtime
;
378 ret
.tv_nsec
= pst
->st_mtimensec
;
380 #elif defined(HAVE_STRUCT_STAT_ST_MTIME_N)
382 ret
.tv_sec
= pst
->st_mtime
;
383 ret
.tv_nsec
= pst
->st_mtime_n
;
385 #elif defined(HAVE_STRUCT_STAT_ST_UMTIME)
387 ret
.tv_sec
= pst
->st_mtime
;
388 ret
.tv_nsec
= pst
->st_umtime
* 1000;
390 #elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
391 return pst
->st_mtimespec
;
393 #error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
398 static struct timespec
get_ctimespec(const struct stat
*pst
)
400 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
403 /* Old system - no ns timestamp. */
404 ret
.tv_sec
= pst
->st_ctime
;
408 #if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
410 #elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
412 ret
.tv_sec
= pst
->st_ctime
;
413 ret
.tv_nsec
= pst
->st_ctimensec
;
415 #elif defined(HAVE_STRUCT_STAT_ST_MTIME_N)
417 ret
.tv_sec
= pst
->st_ctime
;
418 ret
.tv_nsec
= pst
->st_ctime_n
;
420 #elif defined(HAVE_STRUCT_STAT_ST_UMTIME)
422 ret
.tv_sec
= pst
->st_ctime
;
423 ret
.tv_nsec
= pst
->st_uctime
* 1000;
425 #elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
426 return pst
->st_ctimespec
;
428 #error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
433 /****************************************************************************
434 Return the best approximation to a 'create time' under UNIX from a stat
436 ****************************************************************************/
438 static struct timespec
calc_create_time_stat(const struct stat
*st
)
440 struct timespec ret
, ret1
;
441 struct timespec c_time
= get_ctimespec(st
);
442 struct timespec m_time
= get_mtimespec(st
);
443 struct timespec a_time
= get_atimespec(st
);
445 ret
= timespec_compare(&c_time
, &m_time
) < 0 ? c_time
: m_time
;
446 ret1
= timespec_compare(&ret
, &a_time
) < 0 ? ret
: a_time
;
448 if(!null_timespec(ret1
)) {
453 * One of ctime, mtime or atime was zero (probably atime).
454 * Just return MIN(ctime, mtime).
459 /****************************************************************************
460 Return the best approximation to a 'create time' under UNIX from a stat_ex
462 ****************************************************************************/
464 static struct timespec
calc_create_time_stat_ex(const struct stat_ex
*st
)
466 struct timespec ret
, ret1
;
467 struct timespec c_time
= st
->st_ex_ctime
;
468 struct timespec m_time
= st
->st_ex_mtime
;
469 struct timespec a_time
= st
->st_ex_atime
;
471 ret
= timespec_compare(&c_time
, &m_time
) < 0 ? c_time
: m_time
;
472 ret1
= timespec_compare(&ret
, &a_time
) < 0 ? ret
: a_time
;
474 if(!null_timespec(ret1
)) {
479 * One of ctime, mtime or atime was zero (probably atime).
480 * Just return MIN(ctime, mtime).
485 /****************************************************************************
486 Return the 'create time' from a stat struct if it exists (birthtime) or else
487 use the best approximation.
488 ****************************************************************************/
490 static void make_create_timespec(const struct stat
*pst
, struct stat_ex
*dst
,
491 bool fake_dir_create_times
)
493 if (S_ISDIR(pst
->st_mode
) && fake_dir_create_times
) {
494 dst
->st_ex_btime
.tv_sec
= 315493200L; /* 1/1/1980 */
495 dst
->st_ex_btime
.tv_nsec
= 0;
498 dst
->st_ex_calculated_birthtime
= false;
500 #if defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC)
501 dst
->st_ex_btime
= pst
->st_birthtimespec
;
502 #elif defined(HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC)
503 dst
->st_ex_btime
.tv_sec
= pst
->st_birthtime
;
504 dst
->st_ex_btime
.tv_nsec
= pst
->st_birthtimenspec
;
505 #elif defined(HAVE_STRUCT_STAT_ST_BIRTHTIME)
506 dst
->st_ex_btime
.tv_sec
= pst
->st_birthtime
;
507 dst
->st_ex_btime
.tv_nsec
= 0;
509 dst
->st_ex_btime
= calc_create_time_stat(pst
);
510 dst
->st_ex_calculated_birthtime
= true;
513 /* Deal with systems that don't initialize birthtime correctly.
514 * Pointed out by SATOH Fumiyasu <fumiyas@osstech.jp>.
516 if (null_timespec(dst
->st_ex_btime
)) {
517 dst
->st_ex_btime
= calc_create_time_stat(pst
);
518 dst
->st_ex_calculated_birthtime
= true;
522 /****************************************************************************
523 If we update a timestamp in a stat_ex struct we may have to recalculate
524 the birthtime. For now only implement this for write time, but we may
525 also need to do it for atime and ctime. JRA.
526 ****************************************************************************/
528 void update_stat_ex_mtime(struct stat_ex
*dst
,
529 struct timespec write_ts
)
531 dst
->st_ex_mtime
= write_ts
;
533 /* We may have to recalculate btime. */
534 if (dst
->st_ex_calculated_birthtime
) {
535 dst
->st_ex_btime
= calc_create_time_stat_ex(dst
);
539 void update_stat_ex_create_time(struct stat_ex
*dst
,
540 struct timespec create_time
)
542 dst
->st_ex_btime
= create_time
;
543 dst
->st_ex_calculated_birthtime
= false;
546 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
547 static void init_stat_ex_from_stat (struct stat_ex
*dst
,
548 const struct stat64
*src
,
549 bool fake_dir_create_times
)
551 static void init_stat_ex_from_stat (struct stat_ex
*dst
,
552 const struct stat
*src
,
553 bool fake_dir_create_times
)
556 dst
->st_ex_dev
= src
->st_dev
;
557 dst
->st_ex_ino
= src
->st_ino
;
558 dst
->st_ex_mode
= src
->st_mode
;
559 dst
->st_ex_nlink
= src
->st_nlink
;
560 dst
->st_ex_uid
= src
->st_uid
;
561 dst
->st_ex_gid
= src
->st_gid
;
562 dst
->st_ex_rdev
= src
->st_rdev
;
563 dst
->st_ex_size
= src
->st_size
;
564 dst
->st_ex_atime
= get_atimespec(src
);
565 dst
->st_ex_mtime
= get_mtimespec(src
);
566 dst
->st_ex_ctime
= get_ctimespec(src
);
567 make_create_timespec(src
, dst
, fake_dir_create_times
);
568 #ifdef HAVE_STAT_ST_BLKSIZE
569 dst
->st_ex_blksize
= src
->st_blksize
;
571 dst
->st_ex_blksize
= STAT_ST_BLOCKSIZE
;
574 #ifdef HAVE_STAT_ST_BLOCKS
575 dst
->st_ex_blocks
= src
->st_blocks
;
577 dst
->st_ex_blocks
= src
->st_size
/ dst
->st_ex_blksize
+ 1;
580 #ifdef HAVE_STAT_ST_FLAGS
581 dst
->st_ex_flags
= src
->st_flags
;
583 dst
->st_ex_flags
= 0;
587 /*******************************************************************
588 A stat() wrapper that will deal with 64 bit filesizes.
589 ********************************************************************/
591 int sys_stat(const char *fname
, SMB_STRUCT_STAT
*sbuf
,
592 bool fake_dir_create_times
)
595 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
596 struct stat64 statbuf
;
597 ret
= stat64(fname
, &statbuf
);
600 ret
= stat(fname
, &statbuf
);
603 /* we always want directories to appear zero size */
604 if (S_ISDIR(statbuf
.st_mode
)) {
607 init_stat_ex_from_stat(sbuf
, &statbuf
, fake_dir_create_times
);
612 /*******************************************************************
613 An fstat() wrapper that will deal with 64 bit filesizes.
614 ********************************************************************/
616 int sys_fstat(int fd
, SMB_STRUCT_STAT
*sbuf
, bool fake_dir_create_times
)
619 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FSTAT64)
620 struct stat64 statbuf
;
621 ret
= fstat64(fd
, &statbuf
);
624 ret
= fstat(fd
, &statbuf
);
627 /* we always want directories to appear zero size */
628 if (S_ISDIR(statbuf
.st_mode
)) {
631 init_stat_ex_from_stat(sbuf
, &statbuf
, fake_dir_create_times
);
636 /*******************************************************************
637 An lstat() wrapper that will deal with 64 bit filesizes.
638 ********************************************************************/
640 int sys_lstat(const char *fname
,SMB_STRUCT_STAT
*sbuf
,
641 bool fake_dir_create_times
)
644 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSTAT64)
645 struct stat64 statbuf
;
646 ret
= lstat64(fname
, &statbuf
);
649 ret
= lstat(fname
, &statbuf
);
652 /* we always want directories to appear zero size */
653 if (S_ISDIR(statbuf
.st_mode
)) {
656 init_stat_ex_from_stat(sbuf
, &statbuf
, fake_dir_create_times
);
661 /*******************************************************************
662 An posix_fallocate() wrapper that will deal with 64 bit filesizes.
663 ********************************************************************/
664 int sys_posix_fallocate(int fd
, SMB_OFF_T offset
, SMB_OFF_T len
)
666 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_POSIX_FALLOCATE64) && !defined(HAVE_BROKEN_POSIX_FALLOCATE)
667 return posix_fallocate64(fd
, offset
, len
);
668 #elif defined(HAVE_POSIX_FALLOCATE) && !defined(HAVE_BROKEN_POSIX_FALLOCATE)
669 return posix_fallocate(fd
, offset
, len
);
670 #elif defined(F_RESVSP64)
671 /* this handles XFS on IRIX */
673 SMB_OFF_T new_len
= offset
+ len
;
677 /* unlikely to get a too large file on a 64bit system but ... */
681 fl
.l_whence
= SEEK_SET
;
685 ret
=fcntl(fd
, F_RESVSP64
, &fl
);
690 /* Make sure the file gets enlarged after we allocated space: */
692 if (new_len
> sbuf
.st_size
)
693 ftruncate64(fd
, new_len
);
700 /*******************************************************************
701 An fallocate() function that matches the semantics of the Linux one.
702 ********************************************************************/
704 #ifdef HAVE_LINUX_FALLOC_H
705 #include <linux/falloc.h>
708 int sys_fallocate(int fd
, enum vfs_fallocate_mode mode
, SMB_OFF_T offset
, SMB_OFF_T len
)
710 #if defined(HAVE_LINUX_FALLOCATE64) || defined(HAVE_LINUX_FALLOCATE)
713 case VFS_FALLOCATE_EXTEND_SIZE
:
716 case VFS_FALLOCATE_KEEP_SIZE
:
717 lmode
= FALLOC_FL_KEEP_SIZE
;
723 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LINUX_FALLOCATE64)
724 return fallocate64(fd
, lmode
, offset
, len
);
725 #elif defined(HAVE_LINUX_FALLOCATE)
726 return fallocate(fd
, lmode
, offset
, len
);
729 /* TODO - plumb in fallocate from other filesysetms like VXFS etc. JRA. */
735 /*******************************************************************
736 An ftruncate() wrapper that will deal with 64 bit filesizes.
737 ********************************************************************/
739 int sys_ftruncate(int fd
, SMB_OFF_T offset
)
741 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FTRUNCATE64)
742 return ftruncate64(fd
, offset
);
744 return ftruncate(fd
, offset
);
748 /*******************************************************************
749 An lseek() wrapper that will deal with 64 bit filesizes.
750 ********************************************************************/
752 SMB_OFF_T
sys_lseek(int fd
, SMB_OFF_T offset
, int whence
)
754 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSEEK64)
755 return lseek64(fd
, offset
, whence
);
757 return lseek(fd
, offset
, whence
);
761 /*******************************************************************
762 An fseek() wrapper that will deal with 64 bit filesizes.
763 ********************************************************************/
765 int sys_fseek(FILE *fp
, SMB_OFF_T offset
, int whence
)
767 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEK64)
768 return fseek64(fp
, offset
, whence
);
769 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEKO64)
770 return fseeko64(fp
, offset
, whence
);
772 return fseek(fp
, offset
, whence
);
776 /*******************************************************************
777 An ftell() wrapper that will deal with 64 bit filesizes.
778 ********************************************************************/
780 SMB_OFF_T
sys_ftell(FILE *fp
)
782 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELL64)
783 return (SMB_OFF_T
)ftell64(fp
);
784 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELLO64)
785 return (SMB_OFF_T
)ftello64(fp
);
787 return (SMB_OFF_T
)ftell(fp
);
791 /*******************************************************************
792 A creat() wrapper that will deal with 64 bit filesizes.
793 ********************************************************************/
795 int sys_creat(const char *path
, mode_t mode
)
797 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CREAT64)
798 return creat64(path
, mode
);
801 * If creat64 isn't defined then ensure we call a potential open64.
804 return sys_open(path
, O_WRONLY
| O_CREAT
| O_TRUNC
, mode
);
808 /*******************************************************************
809 An open() wrapper that will deal with 64 bit filesizes.
810 ********************************************************************/
812 int sys_open(const char *path
, int oflag
, mode_t mode
)
814 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPEN64)
815 return open64(path
, oflag
, mode
);
817 return open(path
, oflag
, mode
);
821 /*******************************************************************
822 An fopen() wrapper that will deal with 64 bit filesizes.
823 ********************************************************************/
825 FILE *sys_fopen(const char *path
, const char *type
)
827 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FOPEN64)
828 return fopen64(path
, type
);
830 return fopen(path
, type
);
835 /*******************************************************************
836 A flock() wrapper that will perform the kernel flock.
837 ********************************************************************/
839 void kernel_flock(int fd
, uint32 share_mode
, uint32 access_mask
)
841 #if HAVE_KERNEL_SHARE_MODES
843 if (share_mode
== FILE_SHARE_WRITE
) {
844 kernel_mode
= LOCK_MAND
|LOCK_WRITE
;
845 } else if (share_mode
== FILE_SHARE_READ
) {
846 kernel_mode
= LOCK_MAND
|LOCK_READ
;
847 } else if (share_mode
== FILE_SHARE_NONE
) {
848 kernel_mode
= LOCK_MAND
;
851 flock(fd
, kernel_mode
);
859 /*******************************************************************
860 An opendir wrapper that will deal with 64 bit filesizes.
861 ********************************************************************/
863 SMB_STRUCT_DIR
*sys_opendir(const char *name
)
865 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPENDIR64)
866 return opendir64(name
);
868 return opendir(name
);
872 /*******************************************************************
873 An fdopendir wrapper that will deal with 64 bit filesizes.
874 Ugly hack - we need dirfd for this to work correctly in the
876 ********************************************************************/
878 SMB_STRUCT_DIR
*sys_fdopendir(int fd
)
880 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FDOPENDIR64) && defined(HAVE_DIRFD)
881 return fdopendir64(fd
);
882 #elif defined(HAVE_FDOPENDIR) && defined(HAVE_DIRFD)
883 return fdopendir(fd
);
890 /*******************************************************************
891 A readdir wrapper that will deal with 64 bit filesizes.
892 ********************************************************************/
894 SMB_STRUCT_DIRENT
*sys_readdir(SMB_STRUCT_DIR
*dirp
)
896 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_READDIR64)
897 return readdir64(dirp
);
899 return readdir(dirp
);
903 /*******************************************************************
904 A seekdir wrapper that will deal with 64 bit filesizes.
905 ********************************************************************/
907 void sys_seekdir(SMB_STRUCT_DIR
*dirp
, long offset
)
909 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_SEEKDIR64)
910 seekdir64(dirp
, offset
);
912 seekdir(dirp
, offset
);
916 /*******************************************************************
917 A telldir wrapper that will deal with 64 bit filesizes.
918 ********************************************************************/
920 long sys_telldir(SMB_STRUCT_DIR
*dirp
)
922 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_TELLDIR64)
923 return (long)telldir64(dirp
);
925 return (long)telldir(dirp
);
929 /*******************************************************************
930 A rewinddir wrapper that will deal with 64 bit filesizes.
931 ********************************************************************/
933 void sys_rewinddir(SMB_STRUCT_DIR
*dirp
)
935 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_REWINDDIR64)
942 /*******************************************************************
943 A close wrapper that will deal with 64 bit filesizes.
944 ********************************************************************/
946 int sys_closedir(SMB_STRUCT_DIR
*dirp
)
948 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CLOSEDIR64)
949 return closedir64(dirp
);
951 return closedir(dirp
);
955 /*******************************************************************
956 An mknod() wrapper that will deal with 64 bit filesizes.
957 ********************************************************************/
959 int sys_mknod(const char *path
, mode_t mode
, SMB_DEV_T dev
)
961 #if defined(HAVE_MKNOD) || defined(HAVE_MKNOD64)
962 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_MKNOD64) && defined(HAVE_DEV64_T)
963 return mknod64(path
, mode
, dev
);
965 return mknod(path
, mode
, dev
);
968 /* No mknod system call. */
974 /*******************************************************************
975 The wait() calls vary between systems
976 ********************************************************************/
978 int sys_waitpid(pid_t pid
,int *status
,int options
)
981 return waitpid(pid
,status
,options
);
982 #else /* HAVE_WAITPID */
983 return wait4(pid
, status
, options
, NULL
);
984 #endif /* HAVE_WAITPID */
987 /*******************************************************************
988 System wrapper for getwd
989 ********************************************************************/
991 char *sys_getwd(char *s
)
995 wd
= (char *)getcwd(s
, PATH_MAX
);
997 wd
= (char *)getwd(s
);
1002 #if defined(HAVE_POSIX_CAPABILITIES)
1004 /**************************************************************************
1005 Try and abstract process capabilities (for systems that have them).
1006 ****************************************************************************/
1008 /* Set the POSIX capabilities needed for the given purpose into the effective
1009 * capability set of the current process. Make sure they are always removed
1010 * from the inheritable set, because there is no circumstance in which our
1011 * children should inherit our elevated privileges.
1013 static bool set_process_capability(enum smbd_capability capability
,
1016 cap_value_t cap_vals
[2] = {0};
1017 int num_cap_vals
= 0;
1021 #if defined(HAVE_PRCTL) && defined(PR_GET_KEEPCAPS) && defined(PR_SET_KEEPCAPS)
1022 /* On Linux, make sure that any capabilities we grab are sticky
1023 * across UID changes. We expect that this would allow us to keep both
1024 * the effective and permitted capability sets, but as of circa 2.6.16,
1025 * only the permitted set is kept. It is a bug (which we work around)
1026 * that the effective set is lost, but we still require the effective
1029 if (!prctl(PR_GET_KEEPCAPS
)) {
1030 prctl(PR_SET_KEEPCAPS
, 1);
1034 cap
= cap_get_proc();
1036 DEBUG(0,("set_process_capability: cap_get_proc failed: %s\n",
1041 switch (capability
) {
1042 case KERNEL_OPLOCK_CAPABILITY
:
1043 #ifdef CAP_NETWORK_MGT
1044 /* IRIX has CAP_NETWORK_MGT for oplocks. */
1045 cap_vals
[num_cap_vals
++] = CAP_NETWORK_MGT
;
1048 case DMAPI_ACCESS_CAPABILITY
:
1049 #ifdef CAP_DEVICE_MGT
1050 /* IRIX has CAP_DEVICE_MGT for DMAPI access. */
1051 cap_vals
[num_cap_vals
++] = CAP_DEVICE_MGT
;
1053 /* Linux has CAP_MKNOD for DMAPI access. */
1054 cap_vals
[num_cap_vals
++] = CAP_MKNOD
;
1057 case LEASE_CAPABILITY
:
1059 cap_vals
[num_cap_vals
++] = CAP_LEASE
;
1064 SMB_ASSERT(num_cap_vals
<= ARRAY_SIZE(cap_vals
));
1066 if (num_cap_vals
== 0) {
1071 cap_set_flag(cap
, CAP_EFFECTIVE
, num_cap_vals
, cap_vals
,
1072 enable
? CAP_SET
: CAP_CLEAR
);
1074 /* We never want to pass capabilities down to our children, so make
1075 * sure they are not inherited.
1077 cap_set_flag(cap
, CAP_INHERITABLE
, num_cap_vals
, cap_vals
, CAP_CLEAR
);
1079 if (cap_set_proc(cap
) == -1) {
1080 DEBUG(0, ("set_process_capability: cap_set_proc failed: %s\n",
1090 #endif /* HAVE_POSIX_CAPABILITIES */
1092 /****************************************************************************
1093 Gain the oplock capability from the kernel if possible.
1094 ****************************************************************************/
1096 void set_effective_capability(enum smbd_capability capability
)
1098 #if defined(HAVE_POSIX_CAPABILITIES)
1099 set_process_capability(capability
, True
);
1100 #endif /* HAVE_POSIX_CAPABILITIES */
1103 void drop_effective_capability(enum smbd_capability capability
)
1105 #if defined(HAVE_POSIX_CAPABILITIES)
1106 set_process_capability(capability
, False
);
1107 #endif /* HAVE_POSIX_CAPABILITIES */
1110 /**************************************************************************
1111 Wrapper for random().
1112 ****************************************************************************/
1114 long sys_random(void)
1116 #if defined(HAVE_RANDOM)
1117 return (long)random();
1118 #elif defined(HAVE_RAND)
1119 return (long)rand();
1121 DEBUG(0,("Error - no random function available !\n"));
1126 /**************************************************************************
1127 Wrapper for srandom().
1128 ****************************************************************************/
1130 void sys_srandom(unsigned int seed
)
1132 #if defined(HAVE_SRANDOM)
1134 #elif defined(HAVE_SRAND)
1137 DEBUG(0,("Error - no srandom function available !\n"));
1143 #define NGROUPS_MAX 32 /* Guess... */
1146 /**************************************************************************
1147 Returns equivalent to NGROUPS_MAX - using sysconf if needed.
1148 ****************************************************************************/
1150 int groups_max(void)
1152 #if defined(SYSCONF_SC_NGROUPS_MAX)
1153 int ret
= sysconf(_SC_NGROUPS_MAX
);
1154 return (ret
== -1) ? NGROUPS_MAX
: ret
;
1160 /**************************************************************************
1161 Wrap setgroups and getgroups for systems that declare getgroups() as
1162 returning an array of gid_t, but actuall return an array of int.
1163 ****************************************************************************/
1165 #if defined(HAVE_BROKEN_GETGROUPS)
1167 #ifdef HAVE_BROKEN_GETGROUPS
1173 static int sys_broken_getgroups(int setlen
, gid_t
*gidset
)
1180 return getgroups(setlen
, &gid
);
1184 * Broken case. We need to allocate a
1185 * GID_T array of size setlen.
1194 setlen
= groups_max();
1196 if((group_list
= SMB_MALLOC_ARRAY(GID_T
, setlen
)) == NULL
) {
1197 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
1201 if((ngroups
= getgroups(setlen
, group_list
)) < 0) {
1202 int saved_errno
= errno
;
1203 SAFE_FREE(group_list
);
1204 errno
= saved_errno
;
1208 for(i
= 0; i
< ngroups
; i
++)
1209 gidset
[i
] = (gid_t
)group_list
[i
];
1211 SAFE_FREE(group_list
);
1215 static int sys_broken_setgroups(int setlen
, gid_t
*gidset
)
1223 if (setlen
< 0 || setlen
> groups_max()) {
1229 * Broken case. We need to allocate a
1230 * GID_T array of size setlen.
1233 if((group_list
= SMB_MALLOC_ARRAY(GID_T
, setlen
)) == NULL
) {
1234 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
1238 for(i
= 0; i
< setlen
; i
++)
1239 group_list
[i
] = (GID_T
) gidset
[i
];
1241 if(setgroups(setlen
, group_list
) != 0) {
1242 int saved_errno
= errno
;
1243 SAFE_FREE(group_list
);
1244 errno
= saved_errno
;
1248 SAFE_FREE(group_list
);
1252 #endif /* HAVE_BROKEN_GETGROUPS */
1254 /* This is a list of systems that require the first GID passed to setgroups(2)
1255 * to be the effective GID. If your system is one of these, add it here.
1257 #if defined (FREEBSD) || defined (DARWINOS)
1258 #define USE_BSD_SETGROUPS
1261 #if defined(USE_BSD_SETGROUPS)
1262 /* Depending on the particular BSD implementation, the first GID that is
1263 * passed to setgroups(2) will either be ignored or will set the credential's
1264 * effective GID. In either case, the right thing to do is to guarantee that
1265 * gidset[0] is the effective GID.
1267 static int sys_bsd_setgroups(gid_t primary_gid
, int setlen
, const gid_t
*gidset
)
1269 gid_t
*new_gidset
= NULL
;
1273 /* setgroups(2) will fail with EINVAL if we pass too many groups. */
1276 /* No group list, just make sure we are setting the efective GID. */
1278 return setgroups(1, &primary_gid
);
1281 /* If the primary gid is not the first array element, grow the array
1282 * and insert it at the front.
1284 if (gidset
[0] != primary_gid
) {
1285 new_gidset
= SMB_MALLOC_ARRAY(gid_t
, setlen
+ 1);
1286 if (new_gidset
== NULL
) {
1290 memcpy(new_gidset
+ 1, gidset
, (setlen
* sizeof(gid_t
)));
1291 new_gidset
[0] = primary_gid
;
1296 DEBUG(3, ("forced to truncate group list from %d to %d\n",
1301 #if defined(HAVE_BROKEN_GETGROUPS)
1302 ret
= sys_broken_setgroups(setlen
, new_gidset
? new_gidset
: gidset
);
1304 ret
= setgroups(setlen
, new_gidset
? new_gidset
: gidset
);
1309 SAFE_FREE(new_gidset
);
1316 #endif /* USE_BSD_SETGROUPS */
1318 /**************************************************************************
1319 Wrapper for getgroups. Deals with broken (int) case.
1320 ****************************************************************************/
1322 int sys_getgroups(int setlen
, gid_t
*gidset
)
1324 #if defined(HAVE_BROKEN_GETGROUPS)
1325 return sys_broken_getgroups(setlen
, gidset
);
1327 return getgroups(setlen
, gidset
);
1331 /**************************************************************************
1332 Wrapper for setgroups. Deals with broken (int) case and BSD case.
1333 ****************************************************************************/
1335 int sys_setgroups(gid_t
UNUSED(primary_gid
), int setlen
, gid_t
*gidset
)
1337 #if !defined(HAVE_SETGROUPS)
1340 #endif /* HAVE_SETGROUPS */
1342 #if defined(USE_BSD_SETGROUPS)
1343 return sys_bsd_setgroups(primary_gid
, setlen
, gidset
);
1344 #elif defined(HAVE_BROKEN_GETGROUPS)
1345 return sys_broken_setgroups(setlen
, gidset
);
1347 return setgroups(setlen
, gidset
);
1351 /**************************************************************************
1352 Extract a command into an arg list.
1353 ****************************************************************************/
1355 static char **extract_args(TALLOC_CTX
*mem_ctx
, const char *command
)
1364 if (!(trunc_cmd
= talloc_strdup(mem_ctx
, command
))) {
1365 DEBUG(0, ("talloc failed\n"));
1369 if(!(ptr
= strtok_r(trunc_cmd
, " \t", &saveptr
))) {
1370 TALLOC_FREE(trunc_cmd
);
1379 for( argcl
= 1; ptr
; ptr
= strtok_r(NULL
, " \t", &saveptr
))
1382 TALLOC_FREE(trunc_cmd
);
1384 if (!(argl
= TALLOC_ARRAY(mem_ctx
, char *, argcl
+ 1))) {
1389 * Now do the extraction.
1392 if (!(trunc_cmd
= talloc_strdup(mem_ctx
, command
))) {
1396 ptr
= strtok_r(trunc_cmd
, " \t", &saveptr
);
1399 if (!(argl
[i
++] = talloc_strdup(argl
, ptr
))) {
1403 while((ptr
= strtok_r(NULL
, " \t", &saveptr
)) != NULL
) {
1405 if (!(argl
[i
++] = talloc_strdup(argl
, ptr
))) {
1411 TALLOC_FREE(trunc_cmd
);
1415 DEBUG(0, ("talloc failed\n"));
1416 TALLOC_FREE(trunc_cmd
);
1422 /**************************************************************************
1423 Wrapper for popen. Safer as it doesn't search a path.
1424 Modified from the glibc sources.
1425 modified by tridge to return a file descriptor. We must kick our FILE* habit
1426 ****************************************************************************/
1428 typedef struct _popen_list
1432 struct _popen_list
*next
;
1435 static popen_list
*popen_chain
;
1437 int sys_popen(const char *command
)
1439 int parent_end
, child_end
;
1441 popen_list
*entry
= NULL
;
1444 if (pipe(pipe_fds
) < 0)
1447 parent_end
= pipe_fds
[0];
1448 child_end
= pipe_fds
[1];
1455 if((entry
= SMB_MALLOC_P(popen_list
)) == NULL
)
1458 ZERO_STRUCTP(entry
);
1461 * Extract the command and args into a NULL terminated array.
1464 if(!(argl
= extract_args(NULL
, command
)))
1467 entry
->child_pid
= sys_fork();
1469 if (entry
->child_pid
== -1) {
1473 if (entry
->child_pid
== 0) {
1479 int child_std_end
= STDOUT_FILENO
;
1483 if (child_end
!= child_std_end
) {
1484 dup2 (child_end
, child_std_end
);
1489 * POSIX.2: "popen() shall ensure that any streams from previous
1490 * popen() calls that remain open in the parent process are closed
1491 * in the new child process."
1494 for (p
= popen_chain
; p
; p
= p
->next
)
1497 execv(argl
[0], argl
);
1508 /* Link into popen_chain. */
1509 entry
->next
= popen_chain
;
1510 popen_chain
= entry
;
1511 entry
->fd
= parent_end
;
1524 /**************************************************************************
1525 Wrapper for pclose. Modified from the glibc sources.
1526 ****************************************************************************/
1528 int sys_pclose(int fd
)
1531 popen_list
**ptr
= &popen_chain
;
1532 popen_list
*entry
= NULL
;
1536 /* Unlink from popen_chain. */
1537 for ( ; *ptr
!= NULL
; ptr
= &(*ptr
)->next
) {
1538 if ((*ptr
)->fd
== fd
) {
1540 *ptr
= (*ptr
)->next
;
1546 if (status
< 0 || close(entry
->fd
) < 0)
1550 * As Samba is catching and eating child process
1551 * exits we don't really care about the child exit
1552 * code, a -1 with errno = ECHILD will do fine for us.
1556 wait_pid
= sys_waitpid (entry
->child_pid
, &wstatus
, 0);
1557 } while (wait_pid
== -1 && errno
== EINTR
);
1566 /**************************************************************************
1567 Wrapper for Admin Logs.
1568 ****************************************************************************/
1570 void sys_adminlog(int priority
, const char *format_str
, ...)
1574 char *msgbuf
= NULL
;
1576 va_start( ap
, format_str
);
1577 ret
= vasprintf( &msgbuf
, format_str
, ap
);
1583 #if defined(HAVE_SYSLOG)
1584 syslog( priority
, "%s", msgbuf
);
1586 DEBUG(0,("%s", msgbuf
));
1591 /******** Solaris EA helper function prototypes ********/
1592 #ifdef HAVE_ATTROPEN
1593 #define SOLARIS_ATTRMODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP
1594 static int solaris_write_xattr(int attrfd
, const char *value
, size_t size
);
1595 static ssize_t
solaris_read_xattr(int attrfd
, void *value
, size_t size
);
1596 static ssize_t
solaris_list_xattr(int attrdirfd
, char *list
, size_t size
);
1597 static int solaris_unlinkat(int attrdirfd
, const char *name
);
1598 static int solaris_attropen(const char *path
, const char *attrpath
, int oflag
, mode_t mode
);
1599 static int solaris_openat(int fildes
, const char *path
, int oflag
, mode_t mode
);
1602 /**************************************************************************
1603 Wrappers for extented attribute calls. Based on the Linux package with
1604 support for IRIX and (Net|Free)BSD also. Expand as other systems have them.
1605 ****************************************************************************/
1607 ssize_t
sys_getxattr (const char *path
, const char *name
, void *value
, size_t size
)
1609 #if defined(HAVE_GETXATTR)
1610 #ifndef XATTR_ADD_OPT
1611 return getxattr(path
, name
, value
, size
);
1614 return getxattr(path
, name
, value
, size
, 0, options
);
1616 #elif defined(HAVE_GETEA)
1617 return getea(path
, name
, value
, size
);
1618 #elif defined(HAVE_EXTATTR_GET_FILE)
1621 int attrnamespace
= (strncmp(name
, "system", 6) == 0) ?
1622 EXTATTR_NAMESPACE_SYSTEM
: EXTATTR_NAMESPACE_USER
;
1623 const char *attrname
= ((s
=strchr_m(name
, '.')) == NULL
) ? name
: s
+ 1;
1625 * The BSD implementation has a nasty habit of silently truncating
1626 * the returned value to the size of the buffer, so we have to check
1627 * that the buffer is large enough to fit the returned value.
1629 if((retval
=extattr_get_file(path
, attrnamespace
, attrname
, NULL
, 0)) >= 0) {
1634 if((retval
=extattr_get_file(path
, attrnamespace
, attrname
, value
, size
)) >= 0)
1638 DEBUG(10,("sys_getxattr: extattr_get_file() failed with: %s\n", strerror(errno
)));
1640 #elif defined(HAVE_ATTR_GET)
1641 int retval
, flags
= 0;
1642 int valuelength
= (int)size
;
1643 char *attrname
= strchr(name
,'.') + 1;
1645 if (strncmp(name
, "system", 6) == 0) flags
|= ATTR_ROOT
;
1647 retval
= attr_get(path
, attrname
, (char *)value
, &valuelength
, flags
);
1649 return retval
? retval
: valuelength
;
1650 #elif defined(HAVE_ATTROPEN)
1652 int attrfd
= solaris_attropen(path
, name
, O_RDONLY
, 0);
1654 ret
= solaris_read_xattr(attrfd
, value
, size
);
1664 ssize_t
sys_lgetxattr (const char *path
, const char *name
, void *value
, size_t size
)
1666 #if defined(HAVE_LGETXATTR)
1667 return lgetxattr(path
, name
, value
, size
);
1668 #elif defined(HAVE_GETXATTR) && defined(XATTR_ADD_OPT)
1669 int options
= XATTR_NOFOLLOW
;
1670 return getxattr(path
, name
, value
, size
, 0, options
);
1671 #elif defined(HAVE_LGETEA)
1672 return lgetea(path
, name
, value
, size
);
1673 #elif defined(HAVE_EXTATTR_GET_LINK)
1676 int attrnamespace
= (strncmp(name
, "system", 6) == 0) ?
1677 EXTATTR_NAMESPACE_SYSTEM
: EXTATTR_NAMESPACE_USER
;
1678 const char *attrname
= ((s
=strchr_m(name
, '.')) == NULL
) ? name
: s
+ 1;
1680 if((retval
=extattr_get_link(path
, attrnamespace
, attrname
, NULL
, 0)) >= 0) {
1685 if((retval
=extattr_get_link(path
, attrnamespace
, attrname
, value
, size
)) >= 0)
1689 DEBUG(10,("sys_lgetxattr: extattr_get_link() failed with: %s\n", strerror(errno
)));
1691 #elif defined(HAVE_ATTR_GET)
1692 int retval
, flags
= ATTR_DONTFOLLOW
;
1693 int valuelength
= (int)size
;
1694 char *attrname
= strchr(name
,'.') + 1;
1696 if (strncmp(name
, "system", 6) == 0) flags
|= ATTR_ROOT
;
1698 retval
= attr_get(path
, attrname
, (char *)value
, &valuelength
, flags
);
1700 return retval
? retval
: valuelength
;
1701 #elif defined(HAVE_ATTROPEN)
1703 int attrfd
= solaris_attropen(path
, name
, O_RDONLY
|AT_SYMLINK_NOFOLLOW
, 0);
1705 ret
= solaris_read_xattr(attrfd
, value
, size
);
1715 ssize_t
sys_fgetxattr (int filedes
, const char *name
, void *value
, size_t size
)
1717 #if defined(HAVE_FGETXATTR)
1718 #ifndef XATTR_ADD_OPT
1719 return fgetxattr(filedes
, name
, value
, size
);
1722 return fgetxattr(filedes
, name
, value
, size
, 0, options
);
1724 #elif defined(HAVE_FGETEA)
1725 return fgetea(filedes
, name
, value
, size
);
1726 #elif defined(HAVE_EXTATTR_GET_FD)
1729 int attrnamespace
= (strncmp(name
, "system", 6) == 0) ?
1730 EXTATTR_NAMESPACE_SYSTEM
: EXTATTR_NAMESPACE_USER
;
1731 const char *attrname
= ((s
=strchr_m(name
, '.')) == NULL
) ? name
: s
+ 1;
1733 if((retval
=extattr_get_fd(filedes
, attrnamespace
, attrname
, NULL
, 0)) >= 0) {
1738 if((retval
=extattr_get_fd(filedes
, attrnamespace
, attrname
, value
, size
)) >= 0)
1742 DEBUG(10,("sys_fgetxattr: extattr_get_fd() failed with: %s\n", strerror(errno
)));
1744 #elif defined(HAVE_ATTR_GETF)
1745 int retval
, flags
= 0;
1746 int valuelength
= (int)size
;
1747 char *attrname
= strchr(name
,'.') + 1;
1749 if (strncmp(name
, "system", 6) == 0) flags
|= ATTR_ROOT
;
1751 retval
= attr_getf(filedes
, attrname
, (char *)value
, &valuelength
, flags
);
1753 return retval
? retval
: valuelength
;
1754 #elif defined(HAVE_ATTROPEN)
1756 int attrfd
= solaris_openat(filedes
, name
, O_RDONLY
|O_XATTR
, 0);
1758 ret
= solaris_read_xattr(attrfd
, value
, size
);
1768 #if defined(HAVE_EXTATTR_LIST_FILE)
1770 #define EXTATTR_PREFIX(s) (s), (sizeof((s))-1)
1778 { EXTATTR_NAMESPACE_SYSTEM
, EXTATTR_PREFIX("system.") },
1779 { EXTATTR_NAMESPACE_USER
, EXTATTR_PREFIX("user.") },
1787 static ssize_t
bsd_attr_list (int type
, extattr_arg arg
, char *list
, size_t size
)
1789 ssize_t list_size
, total_size
= 0;
1792 /* Iterate through extattr(2) namespaces */
1793 for(t
= 0; t
< (sizeof(extattr
)/sizeof(extattr
[0])); t
++) {
1795 #if defined(HAVE_EXTATTR_LIST_FILE)
1797 list_size
= extattr_list_file(arg
.path
, extattr
[t
].space
, list
, size
);
1800 #if defined(HAVE_EXTATTR_LIST_LINK)
1802 list_size
= extattr_list_link(arg
.path
, extattr
[t
].space
, list
, size
);
1805 #if defined(HAVE_EXTATTR_LIST_FD)
1807 list_size
= extattr_list_fd(arg
.filedes
, extattr
[t
].space
, list
, size
);
1814 /* Some error happend. Errno should be set by the previous call */
1820 /* XXX: Call with an empty buffer may be used to calculate
1821 necessary buffer size. Unfortunately, we can't say, how
1822 many attributes were returned, so here is the potential
1823 problem with the emulation.
1826 /* Take the worse case of one char attribute names -
1827 two bytes per name plus one more for sanity.
1829 total_size
+= list_size
+ (list_size
/2 + 1)*extattr
[t
].len
;
1832 /* Count necessary offset to fit namespace prefixes */
1834 for(i
= 0; i
< list_size
; i
+= list
[i
] + 1)
1835 len
+= extattr
[t
].len
;
1837 total_size
+= list_size
+ len
;
1838 /* Buffer is too small to fit the results */
1839 if(total_size
> size
) {
1843 /* Shift results back, so we can prepend prefixes */
1844 buf
= (char *)memmove(list
+ len
, list
, list_size
);
1846 for(i
= 0; i
< list_size
; i
+= len
+ 1) {
1848 strncpy(list
, extattr
[t
].name
, extattr
[t
].len
+ 1);
1849 list
+= extattr
[t
].len
;
1850 strncpy(list
, buf
+ i
+ 1, len
);
1861 #if defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1862 static char attr_buffer
[ATTR_MAX_VALUELEN
];
1864 static ssize_t
irix_attr_list(const char *path
, int filedes
, char *list
, size_t size
, int flags
)
1866 int retval
= 0, index
;
1867 attrlist_cursor_t
*cursor
= 0;
1869 attrlist_t
* al
= (attrlist_t
*)attr_buffer
;
1871 size_t ent_size
, left
= size
;
1876 retval
= attr_listf(filedes
, attr_buffer
, ATTR_MAX_VALUELEN
, flags
, cursor
);
1878 retval
= attr_list(path
, attr_buffer
, ATTR_MAX_VALUELEN
, flags
, cursor
);
1880 for (index
= 0; index
< al
->al_count
; index
++) {
1881 ae
= ATTR_ENTRY(attr_buffer
, index
);
1882 ent_size
= strlen(ae
->a_name
) + sizeof("user.");
1883 if (left
>= ent_size
) {
1884 strncpy(bp
, "user.", sizeof("user."));
1885 strncat(bp
, ae
->a_name
, ent_size
- sizeof("user."));
1893 total_size
+= ent_size
;
1895 if (al
->al_more
== 0) break;
1902 retval
= attr_listf(filedes
, attr_buffer
, ATTR_MAX_VALUELEN
, flags
, cursor
);
1904 retval
= attr_list(path
, attr_buffer
, ATTR_MAX_VALUELEN
, flags
, cursor
);
1906 for (index
= 0; index
< al
->al_count
; index
++) {
1907 ae
= ATTR_ENTRY(attr_buffer
, index
);
1908 ent_size
= strlen(ae
->a_name
) + sizeof("system.");
1909 if (left
>= ent_size
) {
1910 strncpy(bp
, "system.", sizeof("system."));
1911 strncat(bp
, ae
->a_name
, ent_size
- sizeof("system."));
1919 total_size
+= ent_size
;
1921 if (al
->al_more
== 0) break;
1924 return (ssize_t
)(retval
? retval
: total_size
);
1929 ssize_t
sys_listxattr (const char *path
, char *list
, size_t size
)
1931 #if defined(HAVE_LISTXATTR)
1932 #ifndef XATTR_ADD_OPT
1933 return listxattr(path
, list
, size
);
1936 return listxattr(path
, list
, size
, options
);
1938 #elif defined(HAVE_LISTEA)
1939 return listea(path
, list
, size
);
1940 #elif defined(HAVE_EXTATTR_LIST_FILE)
1943 return bsd_attr_list(0, arg
, list
, size
);
1944 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1945 return irix_attr_list(path
, 0, list
, size
, 0);
1946 #elif defined(HAVE_ATTROPEN)
1948 int attrdirfd
= solaris_attropen(path
, ".", O_RDONLY
, 0);
1949 if (attrdirfd
>= 0) {
1950 ret
= solaris_list_xattr(attrdirfd
, list
, size
);
1960 ssize_t
sys_llistxattr (const char *path
, char *list
, size_t size
)
1962 #if defined(HAVE_LLISTXATTR)
1963 return llistxattr(path
, list
, size
);
1964 #elif defined(HAVE_LISTXATTR) && defined(XATTR_ADD_OPT)
1965 int options
= XATTR_NOFOLLOW
;
1966 return listxattr(path
, list
, size
, options
);
1967 #elif defined(HAVE_LLISTEA)
1968 return llistea(path
, list
, size
);
1969 #elif defined(HAVE_EXTATTR_LIST_LINK)
1972 return bsd_attr_list(1, arg
, list
, size
);
1973 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1974 return irix_attr_list(path
, 0, list
, size
, ATTR_DONTFOLLOW
);
1975 #elif defined(HAVE_ATTROPEN)
1977 int attrdirfd
= solaris_attropen(path
, ".", O_RDONLY
|AT_SYMLINK_NOFOLLOW
, 0);
1978 if (attrdirfd
>= 0) {
1979 ret
= solaris_list_xattr(attrdirfd
, list
, size
);
1989 ssize_t
sys_flistxattr (int filedes
, char *list
, size_t size
)
1991 #if defined(HAVE_FLISTXATTR)
1992 #ifndef XATTR_ADD_OPT
1993 return flistxattr(filedes
, list
, size
);
1996 return flistxattr(filedes
, list
, size
, options
);
1998 #elif defined(HAVE_FLISTEA)
1999 return flistea(filedes
, list
, size
);
2000 #elif defined(HAVE_EXTATTR_LIST_FD)
2002 arg
.filedes
= filedes
;
2003 return bsd_attr_list(2, arg
, list
, size
);
2004 #elif defined(HAVE_ATTR_LISTF)
2005 return irix_attr_list(NULL
, filedes
, list
, size
, 0);
2006 #elif defined(HAVE_ATTROPEN)
2008 int attrdirfd
= solaris_openat(filedes
, ".", O_RDONLY
|O_XATTR
, 0);
2009 if (attrdirfd
>= 0) {
2010 ret
= solaris_list_xattr(attrdirfd
, list
, size
);
2020 int sys_removexattr (const char *path
, const char *name
)
2022 #if defined(HAVE_REMOVEXATTR)
2023 #ifndef XATTR_ADD_OPT
2024 return removexattr(path
, name
);
2027 return removexattr(path
, name
, options
);
2029 #elif defined(HAVE_REMOVEEA)
2030 return removeea(path
, name
);
2031 #elif defined(HAVE_EXTATTR_DELETE_FILE)
2033 int attrnamespace
= (strncmp(name
, "system", 6) == 0) ?
2034 EXTATTR_NAMESPACE_SYSTEM
: EXTATTR_NAMESPACE_USER
;
2035 const char *attrname
= ((s
=strchr_m(name
, '.')) == NULL
) ? name
: s
+ 1;
2037 return extattr_delete_file(path
, attrnamespace
, attrname
);
2038 #elif defined(HAVE_ATTR_REMOVE)
2040 char *attrname
= strchr(name
,'.') + 1;
2042 if (strncmp(name
, "system", 6) == 0) flags
|= ATTR_ROOT
;
2044 return attr_remove(path
, attrname
, flags
);
2045 #elif defined(HAVE_ATTROPEN)
2047 int attrdirfd
= solaris_attropen(path
, ".", O_RDONLY
, 0);
2048 if (attrdirfd
>= 0) {
2049 ret
= solaris_unlinkat(attrdirfd
, name
);
2059 int sys_lremovexattr (const char *path
, const char *name
)
2061 #if defined(HAVE_LREMOVEXATTR)
2062 return lremovexattr(path
, name
);
2063 #elif defined(HAVE_REMOVEXATTR) && defined(XATTR_ADD_OPT)
2064 int options
= XATTR_NOFOLLOW
;
2065 return removexattr(path
, name
, options
);
2066 #elif defined(HAVE_LREMOVEEA)
2067 return lremoveea(path
, name
);
2068 #elif defined(HAVE_EXTATTR_DELETE_LINK)
2070 int attrnamespace
= (strncmp(name
, "system", 6) == 0) ?
2071 EXTATTR_NAMESPACE_SYSTEM
: EXTATTR_NAMESPACE_USER
;
2072 const char *attrname
= ((s
=strchr_m(name
, '.')) == NULL
) ? name
: s
+ 1;
2074 return extattr_delete_link(path
, attrnamespace
, attrname
);
2075 #elif defined(HAVE_ATTR_REMOVE)
2076 int flags
= ATTR_DONTFOLLOW
;
2077 char *attrname
= strchr(name
,'.') + 1;
2079 if (strncmp(name
, "system", 6) == 0) flags
|= ATTR_ROOT
;
2081 return attr_remove(path
, attrname
, flags
);
2082 #elif defined(HAVE_ATTROPEN)
2084 int attrdirfd
= solaris_attropen(path
, ".", O_RDONLY
|AT_SYMLINK_NOFOLLOW
, 0);
2085 if (attrdirfd
>= 0) {
2086 ret
= solaris_unlinkat(attrdirfd
, name
);
2096 int sys_fremovexattr (int filedes
, const char *name
)
2098 #if defined(HAVE_FREMOVEXATTR)
2099 #ifndef XATTR_ADD_OPT
2100 return fremovexattr(filedes
, name
);
2103 return fremovexattr(filedes
, name
, options
);
2105 #elif defined(HAVE_FREMOVEEA)
2106 return fremoveea(filedes
, name
);
2107 #elif defined(HAVE_EXTATTR_DELETE_FD)
2109 int attrnamespace
= (strncmp(name
, "system", 6) == 0) ?
2110 EXTATTR_NAMESPACE_SYSTEM
: EXTATTR_NAMESPACE_USER
;
2111 const char *attrname
= ((s
=strchr_m(name
, '.')) == NULL
) ? name
: s
+ 1;
2113 return extattr_delete_fd(filedes
, attrnamespace
, attrname
);
2114 #elif defined(HAVE_ATTR_REMOVEF)
2116 char *attrname
= strchr(name
,'.') + 1;
2118 if (strncmp(name
, "system", 6) == 0) flags
|= ATTR_ROOT
;
2120 return attr_removef(filedes
, attrname
, flags
);
2121 #elif defined(HAVE_ATTROPEN)
2123 int attrdirfd
= solaris_openat(filedes
, ".", O_RDONLY
|O_XATTR
, 0);
2124 if (attrdirfd
>= 0) {
2125 ret
= solaris_unlinkat(attrdirfd
, name
);
2135 int sys_setxattr (const char *path
, const char *name
, const void *value
, size_t size
, int flags
)
2137 #if defined(HAVE_SETXATTR)
2138 #ifndef XATTR_ADD_OPT
2139 return setxattr(path
, name
, value
, size
, flags
);
2142 return setxattr(path
, name
, value
, size
, 0, options
);
2144 #elif defined(HAVE_SETEA)
2145 return setea(path
, name
, value
, size
, flags
);
2146 #elif defined(HAVE_EXTATTR_SET_FILE)
2149 int attrnamespace
= (strncmp(name
, "system", 6) == 0) ?
2150 EXTATTR_NAMESPACE_SYSTEM
: EXTATTR_NAMESPACE_USER
;
2151 const char *attrname
= ((s
=strchr_m(name
, '.')) == NULL
) ? name
: s
+ 1;
2153 /* Check attribute existence */
2154 retval
= extattr_get_file(path
, attrnamespace
, attrname
, NULL
, 0);
2156 /* REPLACE attribute, that doesn't exist */
2157 if (flags
& XATTR_REPLACE
&& errno
== ENOATTR
) {
2161 /* Ignore other errors */
2164 /* CREATE attribute, that already exists */
2165 if (flags
& XATTR_CREATE
) {
2171 retval
= extattr_set_file(path
, attrnamespace
, attrname
, value
, size
);
2172 return (retval
< 0) ? -1 : 0;
2173 #elif defined(HAVE_ATTR_SET)
2175 char *attrname
= strchr(name
,'.') + 1;
2177 if (strncmp(name
, "system", 6) == 0) myflags
|= ATTR_ROOT
;
2178 if (flags
& XATTR_CREATE
) myflags
|= ATTR_CREATE
;
2179 if (flags
& XATTR_REPLACE
) myflags
|= ATTR_REPLACE
;
2181 return attr_set(path
, attrname
, (const char *)value
, size
, myflags
);
2182 #elif defined(HAVE_ATTROPEN)
2184 int myflags
= O_RDWR
;
2186 if (flags
& XATTR_CREATE
) myflags
|= O_EXCL
;
2187 if (!(flags
& XATTR_REPLACE
)) myflags
|= O_CREAT
;
2188 attrfd
= solaris_attropen(path
, name
, myflags
, (mode_t
) SOLARIS_ATTRMODE
);
2190 ret
= solaris_write_xattr(attrfd
, value
, size
);
2200 int sys_lsetxattr (const char *path
, const char *name
, const void *value
, size_t size
, int flags
)
2202 #if defined(HAVE_LSETXATTR)
2203 return lsetxattr(path
, name
, value
, size
, flags
);
2204 #elif defined(HAVE_SETXATTR) && defined(XATTR_ADD_OPT)
2205 int options
= XATTR_NOFOLLOW
;
2206 return setxattr(path
, name
, value
, size
, 0, options
);
2207 #elif defined(LSETEA)
2208 return lsetea(path
, name
, value
, size
, flags
);
2209 #elif defined(HAVE_EXTATTR_SET_LINK)
2212 int attrnamespace
= (strncmp(name
, "system", 6) == 0) ?
2213 EXTATTR_NAMESPACE_SYSTEM
: EXTATTR_NAMESPACE_USER
;
2214 const char *attrname
= ((s
=strchr_m(name
, '.')) == NULL
) ? name
: s
+ 1;
2216 /* Check attribute existence */
2217 retval
= extattr_get_link(path
, attrnamespace
, attrname
, NULL
, 0);
2219 /* REPLACE attribute, that doesn't exist */
2220 if (flags
& XATTR_REPLACE
&& errno
== ENOATTR
) {
2224 /* Ignore other errors */
2227 /* CREATE attribute, that already exists */
2228 if (flags
& XATTR_CREATE
) {
2235 retval
= extattr_set_link(path
, attrnamespace
, attrname
, value
, size
);
2236 return (retval
< 0) ? -1 : 0;
2237 #elif defined(HAVE_ATTR_SET)
2238 int myflags
= ATTR_DONTFOLLOW
;
2239 char *attrname
= strchr(name
,'.') + 1;
2241 if (strncmp(name
, "system", 6) == 0) myflags
|= ATTR_ROOT
;
2242 if (flags
& XATTR_CREATE
) myflags
|= ATTR_CREATE
;
2243 if (flags
& XATTR_REPLACE
) myflags
|= ATTR_REPLACE
;
2245 return attr_set(path
, attrname
, (const char *)value
, size
, myflags
);
2246 #elif defined(HAVE_ATTROPEN)
2248 int myflags
= O_RDWR
| AT_SYMLINK_NOFOLLOW
;
2250 if (flags
& XATTR_CREATE
) myflags
|= O_EXCL
;
2251 if (!(flags
& XATTR_REPLACE
)) myflags
|= O_CREAT
;
2252 attrfd
= solaris_attropen(path
, name
, myflags
, (mode_t
) SOLARIS_ATTRMODE
);
2254 ret
= solaris_write_xattr(attrfd
, value
, size
);
2264 int sys_fsetxattr (int filedes
, const char *name
, const void *value
, size_t size
, int flags
)
2266 #if defined(HAVE_FSETXATTR)
2267 #ifndef XATTR_ADD_OPT
2268 return fsetxattr(filedes
, name
, value
, size
, flags
);
2271 return fsetxattr(filedes
, name
, value
, size
, 0, options
);
2273 #elif defined(HAVE_FSETEA)
2274 return fsetea(filedes
, name
, value
, size
, flags
);
2275 #elif defined(HAVE_EXTATTR_SET_FD)
2278 int attrnamespace
= (strncmp(name
, "system", 6) == 0) ?
2279 EXTATTR_NAMESPACE_SYSTEM
: EXTATTR_NAMESPACE_USER
;
2280 const char *attrname
= ((s
=strchr_m(name
, '.')) == NULL
) ? name
: s
+ 1;
2282 /* Check attribute existence */
2283 retval
= extattr_get_fd(filedes
, attrnamespace
, attrname
, NULL
, 0);
2285 /* REPLACE attribute, that doesn't exist */
2286 if (flags
& XATTR_REPLACE
&& errno
== ENOATTR
) {
2290 /* Ignore other errors */
2293 /* CREATE attribute, that already exists */
2294 if (flags
& XATTR_CREATE
) {
2300 retval
= extattr_set_fd(filedes
, attrnamespace
, attrname
, value
, size
);
2301 return (retval
< 0) ? -1 : 0;
2302 #elif defined(HAVE_ATTR_SETF)
2304 char *attrname
= strchr(name
,'.') + 1;
2306 if (strncmp(name
, "system", 6) == 0) myflags
|= ATTR_ROOT
;
2307 if (flags
& XATTR_CREATE
) myflags
|= ATTR_CREATE
;
2308 if (flags
& XATTR_REPLACE
) myflags
|= ATTR_REPLACE
;
2310 return attr_setf(filedes
, attrname
, (const char *)value
, size
, myflags
);
2311 #elif defined(HAVE_ATTROPEN)
2313 int myflags
= O_RDWR
| O_XATTR
;
2315 if (flags
& XATTR_CREATE
) myflags
|= O_EXCL
;
2316 if (!(flags
& XATTR_REPLACE
)) myflags
|= O_CREAT
;
2317 attrfd
= solaris_openat(filedes
, name
, myflags
, (mode_t
) SOLARIS_ATTRMODE
);
2319 ret
= solaris_write_xattr(attrfd
, value
, size
);
2329 /**************************************************************************
2330 helper functions for Solaris' EA support
2331 ****************************************************************************/
2332 #ifdef HAVE_ATTROPEN
2333 static ssize_t
solaris_read_xattr(int attrfd
, void *value
, size_t size
)
2337 if (fstat(attrfd
, &sbuf
) == -1) {
2342 /* This is to return the current size of the named extended attribute */
2344 return sbuf
.st_size
;
2347 /* check size and read xattr */
2348 if (sbuf
.st_size
> size
) {
2353 return read(attrfd
, value
, sbuf
.st_size
);
2356 static ssize_t
solaris_list_xattr(int attrdirfd
, char *list
, size_t size
)
2361 int newfd
= dup(attrdirfd
);
2362 /* CAUTION: The originating file descriptor should not be
2363 used again following the call to fdopendir().
2364 For that reason we dup() the file descriptor
2365 here to make things more clear. */
2366 dirp
= fdopendir(newfd
);
2368 while ((de
= readdir(dirp
))) {
2369 size_t listlen
= strlen(de
->d_name
);
2370 if (!strcmp(de
->d_name
, ".") || !strcmp(de
->d_name
, "..")) {
2371 /* we don't want "." and ".." here: */
2372 DEBUG(10,("skipped EA %s\n",de
->d_name
));
2377 /* return the current size of the list of extended attribute names*/
2380 /* check size and copy entrieѕ + nul into list. */
2381 if ((len
+ listlen
+ 1) > size
) {
2386 safe_strcpy(list
+ len
, de
->d_name
, listlen
);
2394 if (closedir(dirp
) == -1) {
2395 DEBUG(0,("closedir dirp failed: %s\n",strerror(errno
)));
2401 static int solaris_unlinkat(int attrdirfd
, const char *name
)
2403 if (unlinkat(attrdirfd
, name
, 0) == -1) {
2404 if (errno
== ENOENT
) {
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
) {
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
) {
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
)) {
2445 DEBUG(10,("solaris_write_xattr FAILED!\n"));
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
);
2461 return (uint32
)(dev
>> 8);
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
);
2474 return (uint32
)(dev
& 0xff);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
2591 #else /* !WITH_AIO */
2593 int sys_aio_read(SMB_STRUCT_AIOCB
*aiocb
)
2599 int sys_aio_write(SMB_STRUCT_AIOCB
*aiocb
)
2605 ssize_t
sys_aio_return(SMB_STRUCT_AIOCB
*aiocb
)
2611 int sys_aio_cancel(int fd
, SMB_STRUCT_AIOCB
*aiocb
)
2617 int sys_aio_error(const SMB_STRUCT_AIOCB
*aiocb
)
2623 int sys_aio_fsync(int op
, SMB_STRUCT_AIOCB
*aiocb
)
2629 int sys_aio_suspend(const SMB_STRUCT_AIOCB
* const cblist
[], int n
, const struct timespec
*timeout
)
2634 #endif /* WITH_AIO */
2636 int sys_getpeereid( int s
, uid_t
*uid
)
2638 #if defined(HAVE_PEERCRED)
2640 socklen_t cred_len
= sizeof(struct ucred
);
2643 ret
= getsockopt(s
, SOL_SOCKET
, SO_PEERCRED
, (void *)&cred
, &cred_len
);
2648 if (cred_len
!= sizeof(struct ucred
)) {
2656 #if defined(HAVE_GETPEEREID)
2658 return getpeereid(s
, uid
, &gid
);
2665 int sys_getnameinfo(const struct sockaddr
*psa
,
2674 * For Solaris we must make sure salen is the
2675 * correct length for the incoming sa_family.
2678 if (salen
== sizeof(struct sockaddr_storage
)) {
2679 salen
= sizeof(struct sockaddr_in
);
2680 #if defined(HAVE_IPV6)
2681 if (psa
->sa_family
== AF_INET6
) {
2682 salen
= sizeof(struct sockaddr_in6
);
2686 return getnameinfo(psa
, salen
, host
, hostlen
, service
, servlen
, flags
);
2689 int sys_connect(int fd
, const struct sockaddr
* addr
)
2691 socklen_t salen
= (socklen_t
)-1;
2693 if (addr
->sa_family
== AF_INET
) {
2694 salen
= sizeof(struct sockaddr_in
);
2695 } else if (addr
->sa_family
== AF_UNIX
) {
2696 salen
= sizeof(struct sockaddr_un
);
2698 #if defined(HAVE_IPV6)
2699 else if (addr
->sa_family
== AF_INET6
) {
2700 salen
= sizeof(struct sockaddr_in6
);
2704 return connect(fd
, addr
, salen
);