s3: Fix bug #9085.
[Samba.git] / source3 / lib / system.c
blob1ce635fef60cc15cba058478cc2d0dff016c7333
1 /*
2 Unix SMB/CIFS implementation.
3 Samba system utilities
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Jeremy Allison 1998-2005
6 Copyright (C) Timur Bakeyev 2005
7 Copyright (C) Bjoern Jacke 2006-2007
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "includes.h"
25 #ifdef HAVE_SYS_PRCTL_H
26 #include <sys/prctl.h>
27 #endif
30 The idea is that this file will eventually have wrappers around all
31 important system calls in samba. The aims are:
33 - to enable easier porting by putting OS dependent stuff in here
35 - to allow for hooks into other "pseudo-filesystems"
37 - to allow easier integration of things like the japanese extensions
39 - to support the philosophy of Samba to expose the features of
40 the OS within the SMB model. In general whatever file/printer/variable
41 expansions/etc make sense to the OS should be acceptable to Samba.
46 /*******************************************************************
47 A wrapper for memalign
48 ********************************************************************/
50 void *sys_memalign( size_t align, size_t size )
52 #if defined(HAVE_POSIX_MEMALIGN)
53 void *p = NULL;
54 int ret = posix_memalign( &p, align, size );
55 if ( ret == 0 )
56 return p;
58 return NULL;
59 #elif defined(HAVE_MEMALIGN)
60 return memalign( align, size );
61 #else
62 /* On *BSD systems memaligns doesn't exist, but memory will
63 * be aligned on allocations of > pagesize. */
64 #if defined(SYSCONF_SC_PAGESIZE)
65 size_t pagesize = (size_t)sysconf(_SC_PAGESIZE);
66 #elif defined(HAVE_GETPAGESIZE)
67 size_t pagesize = (size_t)getpagesize();
68 #else
69 size_t pagesize = (size_t)-1;
70 #endif
71 if (pagesize == (size_t)-1) {
72 DEBUG(0,("memalign functionalaity not available on this platform!\n"));
73 return NULL;
75 if (size < pagesize) {
76 size = pagesize;
78 return SMB_MALLOC(size);
79 #endif
82 /*******************************************************************
83 A wrapper for usleep in case we don't have one.
84 ********************************************************************/
86 int sys_usleep(long usecs)
88 #ifndef HAVE_USLEEP
89 struct timeval tval;
90 #endif
93 * We need this braindamage as the glibc usleep
94 * is not SPEC1170 complient... grumble... JRA.
97 if(usecs < 0 || usecs > 999999) {
98 errno = EINVAL;
99 return -1;
102 #if HAVE_USLEEP
103 usleep(usecs);
104 return 0;
105 #else /* HAVE_USLEEP */
107 * Fake it with select...
109 tval.tv_sec = 0;
110 tval.tv_usec = usecs/1000;
111 select(0,NULL,NULL,NULL,&tval);
112 return 0;
113 #endif /* HAVE_USLEEP */
116 /*******************************************************************
117 A read wrapper that will deal with EINTR.
118 ********************************************************************/
120 ssize_t sys_read(int fd, void *buf, size_t count)
122 ssize_t ret;
124 do {
125 ret = read(fd, buf, count);
126 } while (ret == -1 && errno == EINTR);
127 return ret;
130 /*******************************************************************
131 A write wrapper that will deal with EINTR.
132 ********************************************************************/
134 ssize_t sys_write(int fd, const void *buf, size_t count)
136 ssize_t ret;
138 do {
139 ret = write(fd, buf, count);
140 } while (ret == -1 && errno == EINTR);
141 return ret;
144 /*******************************************************************
145 A writev wrapper that will deal with EINTR.
146 ********************************************************************/
148 ssize_t sys_writev(int fd, const struct iovec *iov, int iovcnt)
150 ssize_t ret;
152 #if 0
153 /* Try to confuse write_data_iov a bit */
154 if ((random() % 5) == 0) {
155 return sys_write(fd, iov[0].iov_base, iov[0].iov_len);
157 if (iov[0].iov_len > 1) {
158 return sys_write(fd, iov[0].iov_base,
159 (random() % (iov[0].iov_len-1)) + 1);
161 #endif
163 do {
164 ret = writev(fd, iov, iovcnt);
165 } while (ret == -1 && errno == EINTR);
166 return ret;
169 /*******************************************************************
170 A pread wrapper that will deal with EINTR and 64-bit file offsets.
171 ********************************************************************/
173 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
174 ssize_t sys_pread(int fd, 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_PREAD64)
180 ret = pread64(fd, buf, count, off);
181 #else
182 ret = pread(fd, buf, count, off);
183 #endif
184 } while (ret == -1 && errno == EINTR);
185 return ret;
187 #endif
189 /*******************************************************************
190 A write wrapper that will deal with EINTR and 64-bit file offsets.
191 ********************************************************************/
193 #if defined(HAVE_PWRITE) || defined(HAVE_PWRITE64)
194 ssize_t sys_pwrite(int fd, const void *buf, size_t count, SMB_OFF_T off)
196 ssize_t ret;
198 do {
199 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_PWRITE64)
200 ret = pwrite64(fd, buf, count, off);
201 #else
202 ret = pwrite(fd, buf, count, off);
203 #endif
204 } while (ret == -1 && errno == EINTR);
205 return ret;
207 #endif
209 /*******************************************************************
210 A send wrapper that will deal with EINTR.
211 ********************************************************************/
213 ssize_t sys_send(int s, const void *msg, size_t len, int flags)
215 ssize_t ret;
217 do {
218 ret = send(s, msg, len, flags);
219 } while (ret == -1 && errno == EINTR);
220 return ret;
223 /*******************************************************************
224 A sendto wrapper that will deal with EINTR.
225 ********************************************************************/
227 ssize_t sys_sendto(int s, const void *msg, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
229 ssize_t ret;
231 do {
232 ret = sendto(s, msg, len, flags, to, tolen);
233 } while (ret == -1 && errno == EINTR);
234 return ret;
237 /*******************************************************************
238 A recv wrapper that will deal with EINTR.
239 ********************************************************************/
241 ssize_t sys_recv(int fd, void *buf, size_t count, int flags)
243 ssize_t ret;
245 do {
246 ret = recv(fd, buf, count, flags);
247 } while (ret == -1 && errno == EINTR);
248 return ret;
251 /*******************************************************************
252 A recvfrom wrapper that will deal with EINTR.
253 ********************************************************************/
255 ssize_t sys_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
257 ssize_t ret;
259 do {
260 ret = recvfrom(s, buf, len, flags, from, fromlen);
261 } while (ret == -1 && errno == EINTR);
262 return ret;
265 /*******************************************************************
266 A fcntl wrapper that will deal with EINTR.
267 ********************************************************************/
269 int sys_fcntl_ptr(int fd, int cmd, void *arg)
271 int ret;
273 do {
274 ret = fcntl(fd, cmd, arg);
275 } while (ret == -1 && errno == EINTR);
276 return ret;
279 /*******************************************************************
280 A fcntl wrapper that will deal with EINTR.
281 ********************************************************************/
283 int sys_fcntl_long(int fd, int cmd, long arg)
285 int ret;
287 do {
288 ret = fcntl(fd, cmd, arg);
289 } while (ret == -1 && errno == EINTR);
290 return ret;
293 /****************************************************************************
294 Get/Set all the possible time fields from a stat struct as a timespec.
295 ****************************************************************************/
297 static struct timespec get_atimespec(const struct stat *pst)
299 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
300 struct timespec ret;
302 /* Old system - no ns timestamp. */
303 ret.tv_sec = pst->st_atime;
304 ret.tv_nsec = 0;
305 return ret;
306 #else
307 #if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
308 return pst->st_atim;
309 #elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
310 struct timespec ret;
311 ret.tv_sec = pst->st_atime;
312 ret.tv_nsec = pst->st_atimensec;
313 return ret;
314 #elif defined(HAVE_STRUCT_STAT_ST_MTIME_N)
315 struct timespec ret;
316 ret.tv_sec = pst->st_atime;
317 ret.tv_nsec = pst->st_atime_n;
318 return ret;
319 #elif defined(HAVE_STRUCT_STAT_ST_UMTIME)
320 struct timespec ret;
321 ret.tv_sec = pst->st_atime;
322 ret.tv_nsec = pst->st_uatime * 1000;
323 return ret;
324 #elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
325 return pst->st_atimespec;
326 #else
327 #error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
328 #endif
329 #endif
332 static struct timespec get_mtimespec(const struct stat *pst)
334 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
335 struct timespec ret;
337 /* Old system - no ns timestamp. */
338 ret.tv_sec = pst->st_mtime;
339 ret.tv_nsec = 0;
340 return ret;
341 #else
342 #if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
343 return pst->st_mtim;
344 #elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
345 struct timespec ret;
346 ret.tv_sec = pst->st_mtime;
347 ret.tv_nsec = pst->st_mtimensec;
348 return ret;
349 #elif defined(HAVE_STRUCT_STAT_ST_MTIME_N)
350 struct timespec ret;
351 ret.tv_sec = pst->st_mtime;
352 ret.tv_nsec = pst->st_mtime_n;
353 return ret;
354 #elif defined(HAVE_STRUCT_STAT_ST_UMTIME)
355 struct timespec ret;
356 ret.tv_sec = pst->st_mtime;
357 ret.tv_nsec = pst->st_umtime * 1000;
358 return ret;
359 #elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
360 return pst->st_mtimespec;
361 #else
362 #error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
363 #endif
364 #endif
367 static struct timespec get_ctimespec(const struct stat *pst)
369 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
370 struct timespec ret;
372 /* Old system - no ns timestamp. */
373 ret.tv_sec = pst->st_ctime;
374 ret.tv_nsec = 0;
375 return ret;
376 #else
377 #if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
378 return pst->st_ctim;
379 #elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
380 struct timespec ret;
381 ret.tv_sec = pst->st_ctime;
382 ret.tv_nsec = pst->st_ctimensec;
383 return ret;
384 #elif defined(HAVE_STRUCT_STAT_ST_MTIME_N)
385 struct timespec ret;
386 ret.tv_sec = pst->st_ctime;
387 ret.tv_nsec = pst->st_ctime_n;
388 return ret;
389 #elif defined(HAVE_STRUCT_STAT_ST_UMTIME)
390 struct timespec ret;
391 ret.tv_sec = pst->st_ctime;
392 ret.tv_nsec = pst->st_uctime * 1000;
393 return ret;
394 #elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
395 return pst->st_ctimespec;
396 #else
397 #error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
398 #endif
399 #endif
402 /****************************************************************************
403 Return the best approximation to a 'create time' under UNIX from a stat
404 structure.
405 ****************************************************************************/
407 static struct timespec calc_create_time_stat(const struct stat *st)
409 struct timespec ret, ret1;
410 struct timespec c_time = get_ctimespec(st);
411 struct timespec m_time = get_mtimespec(st);
412 struct timespec a_time = get_atimespec(st);
414 ret = timespec_compare(&c_time, &m_time) < 0 ? c_time : m_time;
415 ret1 = timespec_compare(&ret, &a_time) < 0 ? ret : a_time;
417 if(!null_timespec(ret1)) {
418 return ret1;
422 * One of ctime, mtime or atime was zero (probably atime).
423 * Just return MIN(ctime, mtime).
425 return ret;
428 /****************************************************************************
429 Return the best approximation to a 'create time' under UNIX from a stat_ex
430 structure.
431 ****************************************************************************/
433 static struct timespec calc_create_time_stat_ex(const struct stat_ex *st)
435 struct timespec ret, ret1;
436 struct timespec c_time = st->st_ex_ctime;
437 struct timespec m_time = st->st_ex_mtime;
438 struct timespec a_time = st->st_ex_atime;
440 ret = timespec_compare(&c_time, &m_time) < 0 ? c_time : m_time;
441 ret1 = timespec_compare(&ret, &a_time) < 0 ? ret : a_time;
443 if(!null_timespec(ret1)) {
444 return ret1;
448 * One of ctime, mtime or atime was zero (probably atime).
449 * Just return MIN(ctime, mtime).
451 return ret;
454 /****************************************************************************
455 Return the 'create time' from a stat struct if it exists (birthtime) or else
456 use the best approximation.
457 ****************************************************************************/
459 static void make_create_timespec(const struct stat *pst, struct stat_ex *dst,
460 bool fake_dir_create_times)
462 if (S_ISDIR(pst->st_mode) && fake_dir_create_times) {
463 dst->st_ex_btime.tv_sec = 315493200L; /* 1/1/1980 */
464 dst->st_ex_btime.tv_nsec = 0;
467 dst->st_ex_calculated_birthtime = false;
469 #if defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC)
470 dst->st_ex_btime = pst->st_birthtimespec;
471 #elif defined(HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC)
472 dst->st_ex_btime.tv_sec = pst->st_birthtime;
473 dst->st_ex_btime.tv_nsec = pst->st_birthtimenspec;
474 #elif defined(HAVE_STRUCT_STAT_ST_BIRTHTIME)
475 dst->st_ex_btime.tv_sec = pst->st_birthtime;
476 dst->st_ex_btime.tv_nsec = 0;
477 #else
478 dst->st_ex_btime = calc_create_time_stat(pst);
479 dst->st_ex_calculated_birthtime = true;
480 #endif
482 /* Deal with systems that don't initialize birthtime correctly.
483 * Pointed out by SATOH Fumiyasu <fumiyas@osstech.jp>.
485 if (null_timespec(dst->st_ex_btime)) {
486 dst->st_ex_btime = calc_create_time_stat(pst);
487 dst->st_ex_calculated_birthtime = true;
491 /****************************************************************************
492 If we update a timestamp in a stat_ex struct we may have to recalculate
493 the birthtime. For now only implement this for write time, but we may
494 also need to do it for atime and ctime. JRA.
495 ****************************************************************************/
497 void update_stat_ex_mtime(struct stat_ex *dst,
498 struct timespec write_ts)
500 dst->st_ex_mtime = write_ts;
502 /* We may have to recalculate btime. */
503 if (dst->st_ex_calculated_birthtime) {
504 dst->st_ex_btime = calc_create_time_stat_ex(dst);
508 void update_stat_ex_create_time(struct stat_ex *dst,
509 struct timespec create_time)
511 dst->st_ex_btime = create_time;
512 dst->st_ex_calculated_birthtime = false;
515 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
516 static void init_stat_ex_from_stat (struct stat_ex *dst,
517 const struct stat64 *src,
518 bool fake_dir_create_times)
519 #else
520 static void init_stat_ex_from_stat (struct stat_ex *dst,
521 const struct stat *src,
522 bool fake_dir_create_times)
523 #endif
525 dst->st_ex_dev = src->st_dev;
526 dst->st_ex_ino = src->st_ino;
527 dst->st_ex_mode = src->st_mode;
528 dst->st_ex_nlink = src->st_nlink;
529 dst->st_ex_uid = src->st_uid;
530 dst->st_ex_gid = src->st_gid;
531 dst->st_ex_rdev = src->st_rdev;
532 dst->st_ex_size = src->st_size;
533 dst->st_ex_atime = get_atimespec(src);
534 dst->st_ex_mtime = get_mtimespec(src);
535 dst->st_ex_ctime = get_ctimespec(src);
536 make_create_timespec(src, dst, fake_dir_create_times);
537 #ifdef HAVE_STAT_ST_BLKSIZE
538 dst->st_ex_blksize = src->st_blksize;
539 #else
540 dst->st_ex_blksize = STAT_ST_BLOCKSIZE;
541 #endif
543 #ifdef HAVE_STAT_ST_BLOCKS
544 dst->st_ex_blocks = src->st_blocks;
545 #else
546 dst->st_ex_blocks = src->st_size / dst->st_ex_blksize + 1;
547 #endif
549 #ifdef HAVE_STAT_ST_FLAGS
550 dst->st_ex_flags = src->st_flags;
551 #else
552 dst->st_ex_flags = 0;
553 #endif
556 /*******************************************************************
557 A stat() wrapper that will deal with 64 bit filesizes.
558 ********************************************************************/
560 int sys_stat(const char *fname, SMB_STRUCT_STAT *sbuf,
561 bool fake_dir_create_times)
563 int ret;
564 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
565 struct stat64 statbuf;
566 ret = stat64(fname, &statbuf);
567 #else
568 struct stat statbuf;
569 ret = stat(fname, &statbuf);
570 #endif
571 if (ret == 0) {
572 /* we always want directories to appear zero size */
573 if (S_ISDIR(statbuf.st_mode)) {
574 statbuf.st_size = 0;
576 init_stat_ex_from_stat(sbuf, &statbuf, fake_dir_create_times);
578 return ret;
581 /*******************************************************************
582 An fstat() wrapper that will deal with 64 bit filesizes.
583 ********************************************************************/
585 int sys_fstat(int fd, SMB_STRUCT_STAT *sbuf, bool fake_dir_create_times)
587 int ret;
588 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FSTAT64)
589 struct stat64 statbuf;
590 ret = fstat64(fd, &statbuf);
591 #else
592 struct stat statbuf;
593 ret = fstat(fd, &statbuf);
594 #endif
595 if (ret == 0) {
596 /* we always want directories to appear zero size */
597 if (S_ISDIR(statbuf.st_mode)) {
598 statbuf.st_size = 0;
600 init_stat_ex_from_stat(sbuf, &statbuf, fake_dir_create_times);
602 return ret;
605 /*******************************************************************
606 An lstat() wrapper that will deal with 64 bit filesizes.
607 ********************************************************************/
609 int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf,
610 bool fake_dir_create_times)
612 int ret;
613 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSTAT64)
614 struct stat64 statbuf;
615 ret = lstat64(fname, &statbuf);
616 #else
617 struct stat statbuf;
618 ret = lstat(fname, &statbuf);
619 #endif
620 if (ret == 0) {
621 /* we always want directories to appear zero size */
622 if (S_ISDIR(statbuf.st_mode)) {
623 statbuf.st_size = 0;
625 init_stat_ex_from_stat(sbuf, &statbuf, fake_dir_create_times);
627 return ret;
630 /*******************************************************************
631 An posix_fallocate() wrapper that will deal with 64 bit filesizes.
632 ********************************************************************/
633 int sys_posix_fallocate(int fd, SMB_OFF_T offset, SMB_OFF_T len)
635 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_POSIX_FALLOCATE64) && !defined(HAVE_BROKEN_POSIX_FALLOCATE)
636 return posix_fallocate64(fd, offset, len);
637 #elif defined(HAVE_POSIX_FALLOCATE) && !defined(HAVE_BROKEN_POSIX_FALLOCATE)
638 return posix_fallocate(fd, offset, len);
639 #else
640 return ENOSYS;
641 #endif
644 /*******************************************************************
645 An ftruncate() wrapper that will deal with 64 bit filesizes.
646 ********************************************************************/
648 int sys_ftruncate(int fd, SMB_OFF_T offset)
650 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FTRUNCATE64)
651 return ftruncate64(fd, offset);
652 #else
653 return ftruncate(fd, offset);
654 #endif
657 /*******************************************************************
658 An lseek() wrapper that will deal with 64 bit filesizes.
659 ********************************************************************/
661 SMB_OFF_T sys_lseek(int fd, SMB_OFF_T offset, int whence)
663 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSEEK64)
664 return lseek64(fd, offset, whence);
665 #else
666 return lseek(fd, offset, whence);
667 #endif
670 /*******************************************************************
671 An fseek() wrapper that will deal with 64 bit filesizes.
672 ********************************************************************/
674 int sys_fseek(FILE *fp, SMB_OFF_T offset, int whence)
676 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEK64)
677 return fseek64(fp, offset, whence);
678 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEKO64)
679 return fseeko64(fp, offset, whence);
680 #else
681 return fseek(fp, offset, whence);
682 #endif
685 /*******************************************************************
686 An ftell() wrapper that will deal with 64 bit filesizes.
687 ********************************************************************/
689 SMB_OFF_T sys_ftell(FILE *fp)
691 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELL64)
692 return (SMB_OFF_T)ftell64(fp);
693 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELLO64)
694 return (SMB_OFF_T)ftello64(fp);
695 #else
696 return (SMB_OFF_T)ftell(fp);
697 #endif
700 /*******************************************************************
701 A creat() wrapper that will deal with 64 bit filesizes.
702 ********************************************************************/
704 int sys_creat(const char *path, mode_t mode)
706 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CREAT64)
707 return creat64(path, mode);
708 #else
710 * If creat64 isn't defined then ensure we call a potential open64.
711 * JRA.
713 return sys_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
714 #endif
717 /*******************************************************************
718 An open() wrapper that will deal with 64 bit filesizes.
719 ********************************************************************/
721 int sys_open(const char *path, int oflag, mode_t mode)
723 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPEN64)
724 return open64(path, oflag, mode);
725 #else
726 return open(path, oflag, mode);
727 #endif
730 /*******************************************************************
731 An fopen() wrapper that will deal with 64 bit filesizes.
732 ********************************************************************/
734 FILE *sys_fopen(const char *path, const char *type)
736 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FOPEN64)
737 return fopen64(path, type);
738 #else
739 return fopen(path, type);
740 #endif
744 /*******************************************************************
745 A flock() wrapper that will perform the kernel flock.
746 ********************************************************************/
748 void kernel_flock(int fd, uint32 share_mode, uint32 access_mask)
750 #if HAVE_KERNEL_SHARE_MODES
751 int kernel_mode = 0;
752 if (share_mode == FILE_SHARE_WRITE) {
753 kernel_mode = LOCK_MAND|LOCK_WRITE;
754 } else if (share_mode == FILE_SHARE_READ) {
755 kernel_mode = LOCK_MAND|LOCK_READ;
756 } else if (share_mode == FILE_SHARE_NONE) {
757 kernel_mode = LOCK_MAND;
759 if (kernel_mode) {
760 flock(fd, kernel_mode);
762 #endif
768 /*******************************************************************
769 An opendir wrapper that will deal with 64 bit filesizes.
770 ********************************************************************/
772 SMB_STRUCT_DIR *sys_opendir(const char *name)
774 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPENDIR64)
775 return opendir64(name);
776 #else
777 return opendir(name);
778 #endif
781 /*******************************************************************
782 A readdir wrapper that will deal with 64 bit filesizes.
783 ********************************************************************/
785 SMB_STRUCT_DIRENT *sys_readdir(SMB_STRUCT_DIR *dirp)
787 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_READDIR64)
788 return readdir64(dirp);
789 #else
790 return readdir(dirp);
791 #endif
794 /*******************************************************************
795 A seekdir wrapper that will deal with 64 bit filesizes.
796 ********************************************************************/
798 void sys_seekdir(SMB_STRUCT_DIR *dirp, long offset)
800 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_SEEKDIR64)
801 seekdir64(dirp, offset);
802 #else
803 seekdir(dirp, offset);
804 #endif
807 /*******************************************************************
808 A telldir wrapper that will deal with 64 bit filesizes.
809 ********************************************************************/
811 long sys_telldir(SMB_STRUCT_DIR *dirp)
813 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_TELLDIR64)
814 return (long)telldir64(dirp);
815 #else
816 return (long)telldir(dirp);
817 #endif
820 /*******************************************************************
821 A rewinddir wrapper that will deal with 64 bit filesizes.
822 ********************************************************************/
824 void sys_rewinddir(SMB_STRUCT_DIR *dirp)
826 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_REWINDDIR64)
827 rewinddir64(dirp);
828 #else
829 rewinddir(dirp);
830 #endif
833 /*******************************************************************
834 A close wrapper that will deal with 64 bit filesizes.
835 ********************************************************************/
837 int sys_closedir(SMB_STRUCT_DIR *dirp)
839 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CLOSEDIR64)
840 return closedir64(dirp);
841 #else
842 return closedir(dirp);
843 #endif
846 /*******************************************************************
847 An mknod() wrapper that will deal with 64 bit filesizes.
848 ********************************************************************/
850 int sys_mknod(const char *path, mode_t mode, SMB_DEV_T dev)
852 #if defined(HAVE_MKNOD) || defined(HAVE_MKNOD64)
853 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_MKNOD64) && defined(HAVE_DEV64_T)
854 return mknod64(path, mode, dev);
855 #else
856 return mknod(path, mode, dev);
857 #endif
858 #else
859 /* No mknod system call. */
860 errno = ENOSYS;
861 return -1;
862 #endif
865 /*******************************************************************
866 The wait() calls vary between systems
867 ********************************************************************/
869 int sys_waitpid(pid_t pid,int *status,int options)
871 #ifdef HAVE_WAITPID
872 return waitpid(pid,status,options);
873 #else /* HAVE_WAITPID */
874 return wait4(pid, status, options, NULL);
875 #endif /* HAVE_WAITPID */
878 /*******************************************************************
879 System wrapper for getwd
880 ********************************************************************/
882 char *sys_getwd(char *s)
884 char *wd;
885 #ifdef HAVE_GETCWD
886 wd = (char *)getcwd(s, PATH_MAX);
887 #else
888 wd = (char *)getwd(s);
889 #endif
890 return wd;
893 #if defined(HAVE_POSIX_CAPABILITIES)
895 /**************************************************************************
896 Try and abstract process capabilities (for systems that have them).
897 ****************************************************************************/
899 /* Set the POSIX capabilities needed for the given purpose into the effective
900 * capability set of the current process. Make sure they are always removed
901 * from the inheritable set, because there is no circumstance in which our
902 * children should inherit our elevated privileges.
904 static bool set_process_capability(enum smbd_capability capability,
905 bool enable)
907 cap_value_t cap_vals[2] = {0};
908 int num_cap_vals = 0;
910 cap_t cap;
912 #if defined(HAVE_PRCTL) && defined(PR_GET_KEEPCAPS) && defined(PR_SET_KEEPCAPS)
913 /* On Linux, make sure that any capabilities we grab are sticky
914 * across UID changes. We expect that this would allow us to keep both
915 * the effective and permitted capability sets, but as of circa 2.6.16,
916 * only the permitted set is kept. It is a bug (which we work around)
917 * that the effective set is lost, but we still require the effective
918 * set to be kept.
920 if (!prctl(PR_GET_KEEPCAPS)) {
921 prctl(PR_SET_KEEPCAPS, 1);
923 #endif
925 cap = cap_get_proc();
926 if (cap == NULL) {
927 DEBUG(0,("set_process_capability: cap_get_proc failed: %s\n",
928 strerror(errno)));
929 return False;
932 switch (capability) {
933 case KERNEL_OPLOCK_CAPABILITY:
934 #ifdef CAP_NETWORK_MGT
935 /* IRIX has CAP_NETWORK_MGT for oplocks. */
936 cap_vals[num_cap_vals++] = CAP_NETWORK_MGT;
937 #endif
938 break;
939 case DMAPI_ACCESS_CAPABILITY:
940 #ifdef CAP_DEVICE_MGT
941 /* IRIX has CAP_DEVICE_MGT for DMAPI access. */
942 cap_vals[num_cap_vals++] = CAP_DEVICE_MGT;
943 #elif CAP_MKNOD
944 /* Linux has CAP_MKNOD for DMAPI access. */
945 cap_vals[num_cap_vals++] = CAP_MKNOD;
946 #endif
947 break;
948 case LEASE_CAPABILITY:
949 #ifdef CAP_LEASE
950 cap_vals[num_cap_vals++] = CAP_LEASE;
951 #endif
952 break;
955 SMB_ASSERT(num_cap_vals <= ARRAY_SIZE(cap_vals));
957 if (num_cap_vals == 0) {
958 cap_free(cap);
959 return True;
962 cap_set_flag(cap, CAP_EFFECTIVE, num_cap_vals, cap_vals,
963 enable ? CAP_SET : CAP_CLEAR);
965 /* We never want to pass capabilities down to our children, so make
966 * sure they are not inherited.
968 cap_set_flag(cap, CAP_INHERITABLE, num_cap_vals, cap_vals, CAP_CLEAR);
970 if (cap_set_proc(cap) == -1) {
971 DEBUG(0, ("set_process_capability: cap_set_proc failed: %s\n",
972 strerror(errno)));
973 cap_free(cap);
974 return False;
977 cap_free(cap);
978 return True;
981 #endif /* HAVE_POSIX_CAPABILITIES */
983 /****************************************************************************
984 Gain the oplock capability from the kernel if possible.
985 ****************************************************************************/
987 void set_effective_capability(enum smbd_capability capability)
989 #if defined(HAVE_POSIX_CAPABILITIES)
990 set_process_capability(capability, True);
991 #endif /* HAVE_POSIX_CAPABILITIES */
994 void drop_effective_capability(enum smbd_capability capability)
996 #if defined(HAVE_POSIX_CAPABILITIES)
997 set_process_capability(capability, False);
998 #endif /* HAVE_POSIX_CAPABILITIES */
1001 /**************************************************************************
1002 Wrapper for random().
1003 ****************************************************************************/
1005 long sys_random(void)
1007 #if defined(HAVE_RANDOM)
1008 return (long)random();
1009 #elif defined(HAVE_RAND)
1010 return (long)rand();
1011 #else
1012 DEBUG(0,("Error - no random function available !\n"));
1013 exit(1);
1014 #endif
1017 /**************************************************************************
1018 Wrapper for srandom().
1019 ****************************************************************************/
1021 void sys_srandom(unsigned int seed)
1023 #if defined(HAVE_SRANDOM)
1024 srandom(seed);
1025 #elif defined(HAVE_SRAND)
1026 srand(seed);
1027 #else
1028 DEBUG(0,("Error - no srandom function available !\n"));
1029 exit(1);
1030 #endif
1033 /**************************************************************************
1034 Returns equivalent to NGROUPS_MAX - using sysconf if needed.
1035 ****************************************************************************/
1037 int groups_max(void)
1039 #if defined(SYSCONF_SC_NGROUPS_MAX)
1040 int ret = sysconf(_SC_NGROUPS_MAX);
1041 return (ret == -1) ? NGROUPS_MAX : ret;
1042 #else
1043 return NGROUPS_MAX;
1044 #endif
1047 /**************************************************************************
1048 Wrap setgroups and getgroups for systems that declare getgroups() as
1049 returning an array of gid_t, but actuall return an array of int.
1050 ****************************************************************************/
1052 #if defined(HAVE_BROKEN_GETGROUPS)
1053 static int sys_broken_getgroups(int setlen, gid_t *gidset)
1055 GID_T gid;
1056 GID_T *group_list;
1057 int i, ngroups;
1059 if(setlen == 0) {
1060 return getgroups(setlen, &gid);
1064 * Broken case. We need to allocate a
1065 * GID_T array of size setlen.
1068 if(setlen < 0) {
1069 errno = EINVAL;
1070 return -1;
1073 if (setlen == 0)
1074 setlen = groups_max();
1076 if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
1077 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
1078 return -1;
1081 if((ngroups = getgroups(setlen, group_list)) < 0) {
1082 int saved_errno = errno;
1083 SAFE_FREE(group_list);
1084 errno = saved_errno;
1085 return -1;
1088 for(i = 0; i < ngroups; i++)
1089 gidset[i] = (gid_t)group_list[i];
1091 SAFE_FREE(group_list);
1092 return ngroups;
1095 static int sys_broken_setgroups(int setlen, gid_t *gidset)
1097 GID_T *group_list;
1098 int i ;
1100 if (setlen == 0)
1101 return 0 ;
1103 if (setlen < 0 || setlen > groups_max()) {
1104 errno = EINVAL;
1105 return -1;
1109 * Broken case. We need to allocate a
1110 * GID_T array of size setlen.
1113 if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
1114 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
1115 return -1;
1118 for(i = 0; i < setlen; i++)
1119 group_list[i] = (GID_T) gidset[i];
1121 if(setgroups(setlen, group_list) != 0) {
1122 int saved_errno = errno;
1123 SAFE_FREE(group_list);
1124 errno = saved_errno;
1125 return -1;
1128 SAFE_FREE(group_list);
1129 return 0 ;
1132 #endif /* HAVE_BROKEN_GETGROUPS */
1134 /* This is a list of systems that require the first GID passed to setgroups(2)
1135 * to be the effective GID. If your system is one of these, add it here.
1137 #if defined (FREEBSD) || defined (DARWINOS)
1138 #define USE_BSD_SETGROUPS
1139 #endif
1141 #if defined(USE_BSD_SETGROUPS)
1142 /* Depending on the particular BSD implementation, the first GID that is
1143 * passed to setgroups(2) will either be ignored or will set the credential's
1144 * effective GID. In either case, the right thing to do is to guarantee that
1145 * gidset[0] is the effective GID.
1147 static int sys_bsd_setgroups(gid_t primary_gid, int setlen, const gid_t *gidset)
1149 gid_t *new_gidset = NULL;
1150 int max;
1151 int ret;
1153 /* setgroups(2) will fail with EINVAL if we pass too many groups. */
1154 max = groups_max();
1156 /* No group list, just make sure we are setting the efective GID. */
1157 if (setlen == 0) {
1158 return setgroups(1, &primary_gid);
1161 /* If the primary gid is not the first array element, grow the array
1162 * and insert it at the front.
1164 if (gidset[0] != primary_gid) {
1165 new_gidset = SMB_MALLOC_ARRAY(gid_t, setlen + 1);
1166 if (new_gidset == NULL) {
1167 return -1;
1170 memcpy(new_gidset + 1, gidset, (setlen * sizeof(gid_t)));
1171 new_gidset[0] = primary_gid;
1172 setlen++;
1175 if (setlen > max) {
1176 DEBUG(3, ("forced to truncate group list from %d to %d\n",
1177 setlen, max));
1178 setlen = max;
1181 #if defined(HAVE_BROKEN_GETGROUPS)
1182 ret = sys_broken_setgroups(setlen, new_gidset ? new_gidset : gidset);
1183 #else
1184 ret = setgroups(setlen, new_gidset ? new_gidset : gidset);
1185 #endif
1187 if (new_gidset) {
1188 int errsav = errno;
1189 SAFE_FREE(new_gidset);
1190 errno = errsav;
1193 return ret;
1196 #endif /* USE_BSD_SETGROUPS */
1198 /**************************************************************************
1199 Wrapper for getgroups. Deals with broken (int) case.
1200 ****************************************************************************/
1202 int sys_getgroups(int setlen, gid_t *gidset)
1204 #if defined(HAVE_BROKEN_GETGROUPS)
1205 return sys_broken_getgroups(setlen, gidset);
1206 #else
1207 return getgroups(setlen, gidset);
1208 #endif
1211 /**************************************************************************
1212 Wrapper for setgroups. Deals with broken (int) case and BSD case.
1213 ****************************************************************************/
1215 int sys_setgroups(gid_t UNUSED(primary_gid), int setlen, gid_t *gidset)
1217 #if !defined(HAVE_SETGROUPS)
1218 errno = ENOSYS;
1219 return -1;
1220 #endif /* HAVE_SETGROUPS */
1222 #if defined(USE_BSD_SETGROUPS)
1223 return sys_bsd_setgroups(primary_gid, setlen, gidset);
1224 #elif defined(HAVE_BROKEN_GETGROUPS)
1225 return sys_broken_setgroups(setlen, gidset);
1226 #else
1227 return setgroups(setlen, gidset);
1228 #endif
1231 /**************************************************************************
1232 Wrappers for setpwent(), getpwent() and endpwent()
1233 ****************************************************************************/
1235 void sys_setpwent(void)
1237 setpwent();
1240 struct passwd *sys_getpwent(void)
1242 return getpwent();
1245 void sys_endpwent(void)
1247 endpwent();
1250 /**************************************************************************
1251 Wrappers for getpwnam(), getpwuid(), getgrnam(), getgrgid()
1252 ****************************************************************************/
1255 struct passwd *sys_getpwnam(const char *name)
1257 return getpwnam(name);
1260 struct passwd *sys_getpwuid(uid_t uid)
1262 return getpwuid(uid);
1265 struct group *sys_getgrnam(const char *name)
1267 return getgrnam(name);
1270 struct group *sys_getgrgid(gid_t gid)
1272 return getgrgid(gid);
1275 /**************************************************************************
1276 Extract a command into an arg list.
1277 ****************************************************************************/
1279 static char **extract_args(TALLOC_CTX *mem_ctx, const char *command)
1281 char *trunc_cmd;
1282 char *saveptr;
1283 char *ptr;
1284 int argcl;
1285 char **argl = NULL;
1286 int i;
1288 if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1289 DEBUG(0, ("talloc failed\n"));
1290 goto nomem;
1293 if(!(ptr = strtok_r(trunc_cmd, " \t", &saveptr))) {
1294 TALLOC_FREE(trunc_cmd);
1295 errno = EINVAL;
1296 return NULL;
1300 * Count the args.
1303 for( argcl = 1; ptr; ptr = strtok_r(NULL, " \t", &saveptr))
1304 argcl++;
1306 TALLOC_FREE(trunc_cmd);
1308 if (!(argl = TALLOC_ARRAY(mem_ctx, char *, argcl + 1))) {
1309 goto nomem;
1313 * Now do the extraction.
1316 if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1317 goto nomem;
1320 ptr = strtok_r(trunc_cmd, " \t", &saveptr);
1321 i = 0;
1323 if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1324 goto nomem;
1327 while((ptr = strtok_r(NULL, " \t", &saveptr)) != NULL) {
1329 if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1330 goto nomem;
1334 argl[i++] = NULL;
1335 TALLOC_FREE(trunc_cmd);
1336 return argl;
1338 nomem:
1339 DEBUG(0, ("talloc failed\n"));
1340 TALLOC_FREE(trunc_cmd);
1341 TALLOC_FREE(argl);
1342 errno = ENOMEM;
1343 return NULL;
1346 /**************************************************************************
1347 Wrapper for popen. Safer as it doesn't search a path.
1348 Modified from the glibc sources.
1349 modified by tridge to return a file descriptor. We must kick our FILE* habit
1350 ****************************************************************************/
1352 typedef struct _popen_list
1354 int fd;
1355 pid_t child_pid;
1356 struct _popen_list *next;
1357 } popen_list;
1359 static popen_list *popen_chain;
1361 int sys_popen(const char *command)
1363 int parent_end, child_end;
1364 int pipe_fds[2];
1365 popen_list *entry = NULL;
1366 char **argl = NULL;
1368 if (pipe(pipe_fds) < 0)
1369 return -1;
1371 parent_end = pipe_fds[0];
1372 child_end = pipe_fds[1];
1374 if (!*command) {
1375 errno = EINVAL;
1376 goto err_exit;
1379 if((entry = SMB_MALLOC_P(popen_list)) == NULL)
1380 goto err_exit;
1382 ZERO_STRUCTP(entry);
1385 * Extract the command and args into a NULL terminated array.
1388 if(!(argl = extract_args(NULL, command)))
1389 goto err_exit;
1391 entry->child_pid = sys_fork();
1393 if (entry->child_pid == -1) {
1394 goto err_exit;
1397 if (entry->child_pid == 0) {
1400 * Child !
1403 int child_std_end = STDOUT_FILENO;
1404 popen_list *p;
1406 close(parent_end);
1407 if (child_end != child_std_end) {
1408 dup2 (child_end, child_std_end);
1409 close (child_end);
1413 * POSIX.2: "popen() shall ensure that any streams from previous
1414 * popen() calls that remain open in the parent process are closed
1415 * in the new child process."
1418 for (p = popen_chain; p; p = p->next)
1419 close(p->fd);
1421 execv(argl[0], argl);
1422 _exit (127);
1426 * Parent.
1429 close (child_end);
1430 TALLOC_FREE(argl);
1432 /* Link into popen_chain. */
1433 entry->next = popen_chain;
1434 popen_chain = entry;
1435 entry->fd = parent_end;
1437 return entry->fd;
1439 err_exit:
1441 SAFE_FREE(entry);
1442 SAFE_FREE(argl);
1443 close(pipe_fds[0]);
1444 close(pipe_fds[1]);
1445 return -1;
1448 /**************************************************************************
1449 Wrapper for pclose. Modified from the glibc sources.
1450 ****************************************************************************/
1452 int sys_pclose(int fd)
1454 int wstatus;
1455 popen_list **ptr = &popen_chain;
1456 popen_list *entry = NULL;
1457 pid_t wait_pid;
1458 int status = -1;
1460 /* Unlink from popen_chain. */
1461 for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
1462 if ((*ptr)->fd == fd) {
1463 entry = *ptr;
1464 *ptr = (*ptr)->next;
1465 status = 0;
1466 break;
1470 if (status < 0 || close(entry->fd) < 0)
1471 return -1;
1474 * As Samba is catching and eating child process
1475 * exits we don't really care about the child exit
1476 * code, a -1 with errno = ECHILD will do fine for us.
1479 do {
1480 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
1481 } while (wait_pid == -1 && errno == EINTR);
1483 SAFE_FREE(entry);
1485 if (wait_pid == -1)
1486 return -1;
1487 return wstatus;
1490 /**************************************************************************
1491 Wrapper for Admin Logs.
1492 ****************************************************************************/
1494 void sys_adminlog(int priority, const char *format_str, ...)
1496 va_list ap;
1497 int ret;
1498 char *msgbuf = NULL;
1500 va_start( ap, format_str );
1501 ret = vasprintf( &msgbuf, format_str, ap );
1502 va_end( ap );
1504 if (ret == -1)
1505 return;
1507 #if defined(HAVE_SYSLOG)
1508 syslog( priority, "%s", msgbuf );
1509 #else
1510 DEBUG(0,("%s", msgbuf ));
1511 #endif
1512 SAFE_FREE(msgbuf);
1515 /******** Solaris EA helper function prototypes ********/
1516 #ifdef HAVE_ATTROPEN
1517 #define SOLARIS_ATTRMODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP
1518 static int solaris_write_xattr(int attrfd, const char *value, size_t size);
1519 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size);
1520 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size);
1521 static int solaris_unlinkat(int attrdirfd, const char *name);
1522 static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode);
1523 static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode);
1524 #endif
1526 /**************************************************************************
1527 Wrappers for extented attribute calls. Based on the Linux package with
1528 support for IRIX and (Net|Free)BSD also. Expand as other systems have them.
1529 ****************************************************************************/
1531 ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t size)
1533 #if defined(HAVE_GETXATTR)
1534 #ifndef XATTR_ADD_OPT
1535 return getxattr(path, name, value, size);
1536 #else
1537 int options = 0;
1538 return getxattr(path, name, value, size, 0, options);
1539 #endif
1540 #elif defined(HAVE_GETEA)
1541 return getea(path, name, value, size);
1542 #elif defined(HAVE_EXTATTR_GET_FILE)
1543 char *s;
1544 ssize_t retval;
1545 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1546 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1547 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1549 * The BSD implementation has a nasty habit of silently truncating
1550 * the returned value to the size of the buffer, so we have to check
1551 * that the buffer is large enough to fit the returned value.
1553 if((retval=extattr_get_file(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1554 if(retval > size) {
1555 errno = ERANGE;
1556 return -1;
1558 if((retval=extattr_get_file(path, attrnamespace, attrname, value, size)) >= 0)
1559 return retval;
1562 DEBUG(10,("sys_getxattr: extattr_get_file() failed with: %s\n", strerror(errno)));
1563 return -1;
1564 #elif defined(HAVE_ATTR_GET)
1565 int retval, flags = 0;
1566 int valuelength = (int)size;
1567 char *attrname = strchr(name,'.') + 1;
1569 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1571 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1573 return retval ? retval : valuelength;
1574 #elif defined(HAVE_ATTROPEN)
1575 ssize_t ret = -1;
1576 int attrfd = solaris_attropen(path, name, O_RDONLY, 0);
1577 if (attrfd >= 0) {
1578 ret = solaris_read_xattr(attrfd, value, size);
1579 close(attrfd);
1581 return ret;
1582 #else
1583 errno = ENOSYS;
1584 return -1;
1585 #endif
1588 ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t size)
1590 #if defined(HAVE_LGETXATTR)
1591 return lgetxattr(path, name, value, size);
1592 #elif defined(HAVE_GETXATTR) && defined(XATTR_ADD_OPT)
1593 int options = XATTR_NOFOLLOW;
1594 return getxattr(path, name, value, size, 0, options);
1595 #elif defined(HAVE_LGETEA)
1596 return lgetea(path, name, value, size);
1597 #elif defined(HAVE_EXTATTR_GET_LINK)
1598 char *s;
1599 ssize_t retval;
1600 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1601 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1602 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1604 if((retval=extattr_get_link(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1605 if(retval > size) {
1606 errno = ERANGE;
1607 return -1;
1609 if((retval=extattr_get_link(path, attrnamespace, attrname, value, size)) >= 0)
1610 return retval;
1613 DEBUG(10,("sys_lgetxattr: extattr_get_link() failed with: %s\n", strerror(errno)));
1614 return -1;
1615 #elif defined(HAVE_ATTR_GET)
1616 int retval, flags = ATTR_DONTFOLLOW;
1617 int valuelength = (int)size;
1618 char *attrname = strchr(name,'.') + 1;
1620 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1622 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1624 return retval ? retval : valuelength;
1625 #elif defined(HAVE_ATTROPEN)
1626 ssize_t ret = -1;
1627 int attrfd = solaris_attropen(path, name, O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1628 if (attrfd >= 0) {
1629 ret = solaris_read_xattr(attrfd, value, size);
1630 close(attrfd);
1632 return ret;
1633 #else
1634 errno = ENOSYS;
1635 return -1;
1636 #endif
1639 ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size)
1641 #if defined(HAVE_FGETXATTR)
1642 #ifndef XATTR_ADD_OPT
1643 return fgetxattr(filedes, name, value, size);
1644 #else
1645 int options = 0;
1646 return fgetxattr(filedes, name, value, size, 0, options);
1647 #endif
1648 #elif defined(HAVE_FGETEA)
1649 return fgetea(filedes, name, value, size);
1650 #elif defined(HAVE_EXTATTR_GET_FD)
1651 char *s;
1652 ssize_t retval;
1653 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1654 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1655 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1657 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0)) >= 0) {
1658 if(retval > size) {
1659 errno = ERANGE;
1660 return -1;
1662 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, value, size)) >= 0)
1663 return retval;
1666 DEBUG(10,("sys_fgetxattr: extattr_get_fd() failed with: %s\n", strerror(errno)));
1667 return -1;
1668 #elif defined(HAVE_ATTR_GETF)
1669 int retval, flags = 0;
1670 int valuelength = (int)size;
1671 char *attrname = strchr(name,'.') + 1;
1673 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1675 retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags);
1677 return retval ? retval : valuelength;
1678 #elif defined(HAVE_ATTROPEN)
1679 ssize_t ret = -1;
1680 int attrfd = solaris_openat(filedes, name, O_RDONLY|O_XATTR, 0);
1681 if (attrfd >= 0) {
1682 ret = solaris_read_xattr(attrfd, value, size);
1683 close(attrfd);
1685 return ret;
1686 #else
1687 errno = ENOSYS;
1688 return -1;
1689 #endif
1692 #if defined(HAVE_EXTATTR_LIST_FILE)
1694 #define EXTATTR_PREFIX(s) (s), (sizeof((s))-1)
1696 static struct {
1697 int space;
1698 const char *name;
1699 size_t len;
1701 extattr[] = {
1702 { EXTATTR_NAMESPACE_SYSTEM, EXTATTR_PREFIX("system.") },
1703 { EXTATTR_NAMESPACE_USER, EXTATTR_PREFIX("user.") },
1706 typedef union {
1707 const char *path;
1708 int filedes;
1709 } extattr_arg;
1711 static ssize_t bsd_attr_list (int type, extattr_arg arg, char *list, size_t size)
1713 ssize_t list_size, total_size = 0;
1714 int i, t, len;
1715 char *buf;
1716 /* Iterate through extattr(2) namespaces */
1717 for(t = 0; t < (sizeof(extattr)/sizeof(extattr[0])); t++) {
1718 switch(type) {
1719 #if defined(HAVE_EXTATTR_LIST_FILE)
1720 case 0:
1721 list_size = extattr_list_file(arg.path, extattr[t].space, list, size);
1722 break;
1723 #endif
1724 #if defined(HAVE_EXTATTR_LIST_LINK)
1725 case 1:
1726 list_size = extattr_list_link(arg.path, extattr[t].space, list, size);
1727 break;
1728 #endif
1729 #if defined(HAVE_EXTATTR_LIST_FD)
1730 case 2:
1731 list_size = extattr_list_fd(arg.filedes, extattr[t].space, list, size);
1732 break;
1733 #endif
1734 default:
1735 errno = ENOSYS;
1736 return -1;
1738 /* Some error happend. Errno should be set by the previous call */
1739 if(list_size < 0)
1740 return -1;
1741 /* No attributes */
1742 if(list_size == 0)
1743 continue;
1744 /* XXX: Call with an empty buffer may be used to calculate
1745 necessary buffer size. Unfortunately, we can't say, how
1746 many attributes were returned, so here is the potential
1747 problem with the emulation.
1749 if(list == NULL) {
1750 /* Take the worse case of one char attribute names -
1751 two bytes per name plus one more for sanity.
1753 total_size += list_size + (list_size/2 + 1)*extattr[t].len;
1754 continue;
1756 /* Count necessary offset to fit namespace prefixes */
1757 len = 0;
1758 for(i = 0; i < list_size; i += list[i] + 1)
1759 len += extattr[t].len;
1761 total_size += list_size + len;
1762 /* Buffer is too small to fit the results */
1763 if(total_size > size) {
1764 errno = ERANGE;
1765 return -1;
1767 /* Shift results back, so we can prepend prefixes */
1768 buf = memmove(list + len, list, list_size);
1770 for(i = 0; i < list_size; i += len + 1) {
1771 len = buf[i];
1772 strncpy(list, extattr[t].name, extattr[t].len + 1);
1773 list += extattr[t].len;
1774 strncpy(list, buf + i + 1, len);
1775 list[len] = '\0';
1776 list += len + 1;
1778 size -= total_size;
1780 return total_size;
1783 #endif
1785 #if defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1786 static char attr_buffer[ATTR_MAX_VALUELEN];
1788 static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags)
1790 int retval = 0, index;
1791 attrlist_cursor_t *cursor = 0;
1792 int total_size = 0;
1793 attrlist_t * al = (attrlist_t *)attr_buffer;
1794 attrlist_ent_t *ae;
1795 size_t ent_size, left = size;
1796 char *bp = list;
1798 while (True) {
1799 if (filedes)
1800 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1801 else
1802 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1803 if (retval) break;
1804 for (index = 0; index < al->al_count; index++) {
1805 ae = ATTR_ENTRY(attr_buffer, index);
1806 ent_size = strlen(ae->a_name) + sizeof("user.");
1807 if (left >= ent_size) {
1808 strncpy(bp, "user.", sizeof("user."));
1809 strncat(bp, ae->a_name, ent_size - sizeof("user."));
1810 bp += ent_size;
1811 left -= ent_size;
1812 } else if (size) {
1813 errno = ERANGE;
1814 retval = -1;
1815 break;
1817 total_size += ent_size;
1819 if (al->al_more == 0) break;
1821 if (retval == 0) {
1822 flags |= ATTR_ROOT;
1823 cursor = 0;
1824 while (True) {
1825 if (filedes)
1826 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1827 else
1828 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1829 if (retval) break;
1830 for (index = 0; index < al->al_count; index++) {
1831 ae = ATTR_ENTRY(attr_buffer, index);
1832 ent_size = strlen(ae->a_name) + sizeof("system.");
1833 if (left >= ent_size) {
1834 strncpy(bp, "system.", sizeof("system."));
1835 strncat(bp, ae->a_name, ent_size - sizeof("system."));
1836 bp += ent_size;
1837 left -= ent_size;
1838 } else if (size) {
1839 errno = ERANGE;
1840 retval = -1;
1841 break;
1843 total_size += ent_size;
1845 if (al->al_more == 0) break;
1848 return (ssize_t)(retval ? retval : total_size);
1851 #endif
1853 ssize_t sys_listxattr (const char *path, char *list, size_t size)
1855 #if defined(HAVE_LISTXATTR)
1856 #ifndef XATTR_ADD_OPT
1857 return listxattr(path, list, size);
1858 #else
1859 int options = 0;
1860 return listxattr(path, list, size, options);
1861 #endif
1862 #elif defined(HAVE_LISTEA)
1863 return listea(path, list, size);
1864 #elif defined(HAVE_EXTATTR_LIST_FILE)
1865 extattr_arg arg;
1866 arg.path = path;
1867 return bsd_attr_list(0, arg, list, size);
1868 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1869 return irix_attr_list(path, 0, list, size, 0);
1870 #elif defined(HAVE_ATTROPEN)
1871 ssize_t ret = -1;
1872 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
1873 if (attrdirfd >= 0) {
1874 ret = solaris_list_xattr(attrdirfd, list, size);
1875 close(attrdirfd);
1877 return ret;
1878 #else
1879 errno = ENOSYS;
1880 return -1;
1881 #endif
1884 ssize_t sys_llistxattr (const char *path, char *list, size_t size)
1886 #if defined(HAVE_LLISTXATTR)
1887 return llistxattr(path, list, size);
1888 #elif defined(HAVE_LISTXATTR) && defined(XATTR_ADD_OPT)
1889 int options = XATTR_NOFOLLOW;
1890 return listxattr(path, list, size, options);
1891 #elif defined(HAVE_LLISTEA)
1892 return llistea(path, list, size);
1893 #elif defined(HAVE_EXTATTR_LIST_LINK)
1894 extattr_arg arg;
1895 arg.path = path;
1896 return bsd_attr_list(1, arg, list, size);
1897 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1898 return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW);
1899 #elif defined(HAVE_ATTROPEN)
1900 ssize_t ret = -1;
1901 int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1902 if (attrdirfd >= 0) {
1903 ret = solaris_list_xattr(attrdirfd, list, size);
1904 close(attrdirfd);
1906 return ret;
1907 #else
1908 errno = ENOSYS;
1909 return -1;
1910 #endif
1913 ssize_t sys_flistxattr (int filedes, char *list, size_t size)
1915 #if defined(HAVE_FLISTXATTR)
1916 #ifndef XATTR_ADD_OPT
1917 return flistxattr(filedes, list, size);
1918 #else
1919 int options = 0;
1920 return flistxattr(filedes, list, size, options);
1921 #endif
1922 #elif defined(HAVE_FLISTEA)
1923 return flistea(filedes, list, size);
1924 #elif defined(HAVE_EXTATTR_LIST_FD)
1925 extattr_arg arg;
1926 arg.filedes = filedes;
1927 return bsd_attr_list(2, arg, list, size);
1928 #elif defined(HAVE_ATTR_LISTF)
1929 return irix_attr_list(NULL, filedes, list, size, 0);
1930 #elif defined(HAVE_ATTROPEN)
1931 ssize_t ret = -1;
1932 int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
1933 if (attrdirfd >= 0) {
1934 ret = solaris_list_xattr(attrdirfd, list, size);
1935 close(attrdirfd);
1937 return ret;
1938 #else
1939 errno = ENOSYS;
1940 return -1;
1941 #endif
1944 int sys_removexattr (const char *path, const char *name)
1946 #if defined(HAVE_REMOVEXATTR)
1947 #ifndef XATTR_ADD_OPT
1948 return removexattr(path, name);
1949 #else
1950 int options = 0;
1951 return removexattr(path, name, options);
1952 #endif
1953 #elif defined(HAVE_REMOVEEA)
1954 return removeea(path, name);
1955 #elif defined(HAVE_EXTATTR_DELETE_FILE)
1956 char *s;
1957 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1958 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1959 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1961 return extattr_delete_file(path, attrnamespace, attrname);
1962 #elif defined(HAVE_ATTR_REMOVE)
1963 int flags = 0;
1964 char *attrname = strchr(name,'.') + 1;
1966 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1968 return attr_remove(path, attrname, flags);
1969 #elif defined(HAVE_ATTROPEN)
1970 int ret = -1;
1971 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
1972 if (attrdirfd >= 0) {
1973 ret = solaris_unlinkat(attrdirfd, name);
1974 close(attrdirfd);
1976 return ret;
1977 #else
1978 errno = ENOSYS;
1979 return -1;
1980 #endif
1983 int sys_lremovexattr (const char *path, const char *name)
1985 #if defined(HAVE_LREMOVEXATTR)
1986 return lremovexattr(path, name);
1987 #elif defined(HAVE_REMOVEXATTR) && defined(XATTR_ADD_OPT)
1988 int options = XATTR_NOFOLLOW;
1989 return removexattr(path, name, options);
1990 #elif defined(HAVE_LREMOVEEA)
1991 return lremoveea(path, name);
1992 #elif defined(HAVE_EXTATTR_DELETE_LINK)
1993 char *s;
1994 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1995 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1996 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1998 return extattr_delete_link(path, attrnamespace, attrname);
1999 #elif defined(HAVE_ATTR_REMOVE)
2000 int flags = ATTR_DONTFOLLOW;
2001 char *attrname = strchr(name,'.') + 1;
2003 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
2005 return attr_remove(path, attrname, flags);
2006 #elif defined(HAVE_ATTROPEN)
2007 int ret = -1;
2008 int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
2009 if (attrdirfd >= 0) {
2010 ret = solaris_unlinkat(attrdirfd, name);
2011 close(attrdirfd);
2013 return ret;
2014 #else
2015 errno = ENOSYS;
2016 return -1;
2017 #endif
2020 int sys_fremovexattr (int filedes, const char *name)
2022 #if defined(HAVE_FREMOVEXATTR)
2023 #ifndef XATTR_ADD_OPT
2024 return fremovexattr(filedes, name);
2025 #else
2026 int options = 0;
2027 return fremovexattr(filedes, name, options);
2028 #endif
2029 #elif defined(HAVE_FREMOVEEA)
2030 return fremoveea(filedes, name);
2031 #elif defined(HAVE_EXTATTR_DELETE_FD)
2032 char *s;
2033 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2034 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2035 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2037 return extattr_delete_fd(filedes, attrnamespace, attrname);
2038 #elif defined(HAVE_ATTR_REMOVEF)
2039 int flags = 0;
2040 char *attrname = strchr(name,'.') + 1;
2042 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
2044 return attr_removef(filedes, attrname, flags);
2045 #elif defined(HAVE_ATTROPEN)
2046 int ret = -1;
2047 int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
2048 if (attrdirfd >= 0) {
2049 ret = solaris_unlinkat(attrdirfd, name);
2050 close(attrdirfd);
2052 return ret;
2053 #else
2054 errno = ENOSYS;
2055 return -1;
2056 #endif
2059 int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags)
2061 #if defined(HAVE_SETXATTR)
2062 #ifndef XATTR_ADD_OPT
2063 return setxattr(path, name, value, size, flags);
2064 #else
2065 int options = 0;
2066 return setxattr(path, name, value, size, 0, options);
2067 #endif
2068 #elif defined(HAVE_SETEA)
2069 return setea(path, name, value, size, flags);
2070 #elif defined(HAVE_EXTATTR_SET_FILE)
2071 char *s;
2072 int retval = 0;
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;
2076 if (flags) {
2077 /* Check attribute existence */
2078 retval = extattr_get_file(path, attrnamespace, attrname, NULL, 0);
2079 if (retval < 0) {
2080 /* REPLACE attribute, that doesn't exist */
2081 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2082 errno = ENOATTR;
2083 return -1;
2085 /* Ignore other errors */
2087 else {
2088 /* CREATE attribute, that already exists */
2089 if (flags & XATTR_CREATE) {
2090 errno = EEXIST;
2091 return -1;
2095 retval = extattr_set_file(path, attrnamespace, attrname, value, size);
2096 return (retval < 0) ? -1 : 0;
2097 #elif defined(HAVE_ATTR_SET)
2098 int myflags = 0;
2099 char *attrname = strchr(name,'.') + 1;
2101 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2102 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2103 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2105 return attr_set(path, attrname, (const char *)value, size, myflags);
2106 #elif defined(HAVE_ATTROPEN)
2107 int ret = -1;
2108 int myflags = O_RDWR;
2109 int attrfd;
2110 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2111 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2112 attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2113 if (attrfd >= 0) {
2114 ret = solaris_write_xattr(attrfd, value, size);
2115 close(attrfd);
2117 return ret;
2118 #else
2119 errno = ENOSYS;
2120 return -1;
2121 #endif
2124 int sys_lsetxattr (const char *path, const char *name, const void *value, size_t size, int flags)
2126 #if defined(HAVE_LSETXATTR)
2127 return lsetxattr(path, name, value, size, flags);
2128 #elif defined(HAVE_SETXATTR) && defined(XATTR_ADD_OPT)
2129 int options = XATTR_NOFOLLOW;
2130 return setxattr(path, name, value, size, 0, options);
2131 #elif defined(LSETEA)
2132 return lsetea(path, name, value, size, flags);
2133 #elif defined(HAVE_EXTATTR_SET_LINK)
2134 char *s;
2135 int retval = 0;
2136 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2137 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2138 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2139 if (flags) {
2140 /* Check attribute existence */
2141 retval = extattr_get_link(path, attrnamespace, attrname, NULL, 0);
2142 if (retval < 0) {
2143 /* REPLACE attribute, that doesn't exist */
2144 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2145 errno = ENOATTR;
2146 return -1;
2148 /* Ignore other errors */
2150 else {
2151 /* CREATE attribute, that already exists */
2152 if (flags & XATTR_CREATE) {
2153 errno = EEXIST;
2154 return -1;
2159 retval = extattr_set_link(path, attrnamespace, attrname, value, size);
2160 return (retval < 0) ? -1 : 0;
2161 #elif defined(HAVE_ATTR_SET)
2162 int myflags = ATTR_DONTFOLLOW;
2163 char *attrname = strchr(name,'.') + 1;
2165 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2166 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2167 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2169 return attr_set(path, attrname, (const char *)value, size, myflags);
2170 #elif defined(HAVE_ATTROPEN)
2171 int ret = -1;
2172 int myflags = O_RDWR | AT_SYMLINK_NOFOLLOW;
2173 int attrfd;
2174 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2175 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2176 attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2177 if (attrfd >= 0) {
2178 ret = solaris_write_xattr(attrfd, value, size);
2179 close(attrfd);
2181 return ret;
2182 #else
2183 errno = ENOSYS;
2184 return -1;
2185 #endif
2188 int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags)
2190 #if defined(HAVE_FSETXATTR)
2191 #ifndef XATTR_ADD_OPT
2192 return fsetxattr(filedes, name, value, size, flags);
2193 #else
2194 int options = 0;
2195 return fsetxattr(filedes, name, value, size, 0, options);
2196 #endif
2197 #elif defined(HAVE_FSETEA)
2198 return fsetea(filedes, name, value, size, flags);
2199 #elif defined(HAVE_EXTATTR_SET_FD)
2200 char *s;
2201 int retval = 0;
2202 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2203 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2204 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2205 if (flags) {
2206 /* Check attribute existence */
2207 retval = extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0);
2208 if (retval < 0) {
2209 /* REPLACE attribute, that doesn't exist */
2210 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2211 errno = ENOATTR;
2212 return -1;
2214 /* Ignore other errors */
2216 else {
2217 /* CREATE attribute, that already exists */
2218 if (flags & XATTR_CREATE) {
2219 errno = EEXIST;
2220 return -1;
2224 retval = extattr_set_fd(filedes, attrnamespace, attrname, value, size);
2225 return (retval < 0) ? -1 : 0;
2226 #elif defined(HAVE_ATTR_SETF)
2227 int myflags = 0;
2228 char *attrname = strchr(name,'.') + 1;
2230 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2231 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2232 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2234 return attr_setf(filedes, attrname, (const char *)value, size, myflags);
2235 #elif defined(HAVE_ATTROPEN)
2236 int ret = -1;
2237 int myflags = O_RDWR | O_XATTR;
2238 int attrfd;
2239 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2240 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2241 attrfd = solaris_openat(filedes, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2242 if (attrfd >= 0) {
2243 ret = solaris_write_xattr(attrfd, value, size);
2244 close(attrfd);
2246 return ret;
2247 #else
2248 errno = ENOSYS;
2249 return -1;
2250 #endif
2253 /**************************************************************************
2254 helper functions for Solaris' EA support
2255 ****************************************************************************/
2256 #ifdef HAVE_ATTROPEN
2257 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size)
2259 struct stat sbuf;
2261 if (fstat(attrfd, &sbuf) == -1) {
2262 errno = ENOATTR;
2263 return -1;
2266 /* This is to return the current size of the named extended attribute */
2267 if (size == 0) {
2268 return sbuf.st_size;
2271 /* check size and read xattr */
2272 if (sbuf.st_size > size) {
2273 errno = ERANGE;
2274 return -1;
2277 return read(attrfd, value, sbuf.st_size);
2280 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size)
2282 ssize_t len = 0;
2283 DIR *dirp;
2284 struct dirent *de;
2285 int newfd = dup(attrdirfd);
2286 /* CAUTION: The originating file descriptor should not be
2287 used again following the call to fdopendir().
2288 For that reason we dup() the file descriptor
2289 here to make things more clear. */
2290 dirp = fdopendir(newfd);
2292 while ((de = readdir(dirp))) {
2293 size_t listlen = strlen(de->d_name);
2294 if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) {
2295 /* we don't want "." and ".." here: */
2296 DEBUG(10,("skipped EA %s\n",de->d_name));
2297 continue;
2300 if (size == 0) {
2301 /* return the current size of the list of extended attribute names*/
2302 len += listlen + 1;
2303 } else {
2304 /* check size and copy entrieѕ + nul into list. */
2305 if ((len + listlen + 1) > size) {
2306 errno = ERANGE;
2307 len = -1;
2308 break;
2309 } else {
2310 safe_strcpy(list + len, de->d_name, listlen);
2311 len += listlen;
2312 list[len] = '\0';
2313 ++len;
2318 if (closedir(dirp) == -1) {
2319 DEBUG(0,("closedir dirp failed: %s\n",strerror(errno)));
2320 return -1;
2322 return len;
2325 static int solaris_unlinkat(int attrdirfd, const char *name)
2327 if (unlinkat(attrdirfd, name, 0) == -1) {
2328 if (errno == ENOENT) {
2329 errno = ENOATTR;
2331 return -1;
2333 return 0;
2336 static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode)
2338 int filedes = attropen(path, attrpath, oflag, mode);
2339 if (filedes == -1) {
2340 DEBUG(10,("attropen FAILED: path: %s, name: %s, errno: %s\n",path,attrpath,strerror(errno)));
2341 if (errno == EINVAL) {
2342 errno = ENOTSUP;
2343 } else {
2344 errno = ENOATTR;
2347 return filedes;
2350 static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode)
2352 int filedes = openat(fildes, path, oflag, mode);
2353 if (filedes == -1) {
2354 DEBUG(10,("openat FAILED: fd: %d, path: %s, errno: %s\n",filedes,path,strerror(errno)));
2355 if (errno == EINVAL) {
2356 errno = ENOTSUP;
2357 } else {
2358 errno = ENOATTR;
2361 return filedes;
2364 static int solaris_write_xattr(int attrfd, const char *value, size_t size)
2366 if ((ftruncate(attrfd, 0) == 0) && (write(attrfd, value, size) == size)) {
2367 return 0;
2368 } else {
2369 DEBUG(10,("solaris_write_xattr FAILED!\n"));
2370 return -1;
2373 #endif /*HAVE_ATTROPEN*/
2376 /****************************************************************************
2377 Return the major devicenumber for UNIX extensions.
2378 ****************************************************************************/
2380 uint32 unix_dev_major(SMB_DEV_T dev)
2382 #if defined(HAVE_DEVICE_MAJOR_FN)
2383 return (uint32)major(dev);
2384 #else
2385 return (uint32)(dev >> 8);
2386 #endif
2389 /****************************************************************************
2390 Return the minor devicenumber for UNIX extensions.
2391 ****************************************************************************/
2393 uint32 unix_dev_minor(SMB_DEV_T dev)
2395 #if defined(HAVE_DEVICE_MINOR_FN)
2396 return (uint32)minor(dev);
2397 #else
2398 return (uint32)(dev & 0xff);
2399 #endif
2402 #if defined(WITH_AIO)
2404 /*******************************************************************
2405 An aio_read wrapper that will deal with 64-bit sizes.
2406 ********************************************************************/
2408 int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2410 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_READ64)
2411 return aio_read64(aiocb);
2412 #elif defined(HAVE_AIO_READ)
2413 return aio_read(aiocb);
2414 #else
2415 errno = ENOSYS;
2416 return -1;
2417 #endif
2420 /*******************************************************************
2421 An aio_write wrapper that will deal with 64-bit sizes.
2422 ********************************************************************/
2424 int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2426 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_WRITE64)
2427 return aio_write64(aiocb);
2428 #elif defined(HAVE_AIO_WRITE)
2429 return aio_write(aiocb);
2430 #else
2431 errno = ENOSYS;
2432 return -1;
2433 #endif
2436 /*******************************************************************
2437 An aio_return wrapper that will deal with 64-bit sizes.
2438 ********************************************************************/
2440 ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2442 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_RETURN64)
2443 return aio_return64(aiocb);
2444 #elif defined(HAVE_AIO_RETURN)
2445 return aio_return(aiocb);
2446 #else
2447 errno = ENOSYS;
2448 return -1;
2449 #endif
2452 /*******************************************************************
2453 An aio_cancel wrapper that will deal with 64-bit sizes.
2454 ********************************************************************/
2456 int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2458 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_CANCEL64)
2459 return aio_cancel64(fd, aiocb);
2460 #elif defined(HAVE_AIO_CANCEL)
2461 return aio_cancel(fd, aiocb);
2462 #else
2463 errno = ENOSYS;
2464 return -1;
2465 #endif
2468 /*******************************************************************
2469 An aio_error wrapper that will deal with 64-bit sizes.
2470 ********************************************************************/
2472 int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2474 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_ERROR64)
2475 return aio_error64(aiocb);
2476 #elif defined(HAVE_AIO_ERROR)
2477 return aio_error(aiocb);
2478 #else
2479 errno = ENOSYS;
2480 return -1;
2481 #endif
2484 /*******************************************************************
2485 An aio_fsync wrapper that will deal with 64-bit sizes.
2486 ********************************************************************/
2488 int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2490 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_FSYNC64)
2491 return aio_fsync64(op, aiocb);
2492 #elif defined(HAVE_AIO_FSYNC)
2493 return aio_fsync(op, aiocb);
2494 #else
2495 errno = ENOSYS;
2496 return -1;
2497 #endif
2500 /*******************************************************************
2501 An aio_fsync wrapper that will deal with 64-bit sizes.
2502 ********************************************************************/
2504 int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2506 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_SUSPEND64)
2507 return aio_suspend64(cblist, n, timeout);
2508 #elif defined(HAVE_AIO_FSYNC)
2509 return aio_suspend(cblist, n, timeout);
2510 #else
2511 errno = ENOSYS;
2512 return -1;
2513 #endif
2515 #else /* !WITH_AIO */
2517 int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2519 errno = ENOSYS;
2520 return -1;
2523 int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2525 errno = ENOSYS;
2526 return -1;
2529 ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2531 errno = ENOSYS;
2532 return -1;
2535 int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2537 errno = ENOSYS;
2538 return -1;
2541 int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2543 errno = ENOSYS;
2544 return -1;
2547 int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2549 errno = ENOSYS;
2550 return -1;
2553 int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2555 errno = ENOSYS;
2556 return -1;
2558 #endif /* WITH_AIO */
2560 int sys_getpeereid( int s, uid_t *uid)
2562 #if defined(HAVE_PEERCRED)
2563 struct ucred cred;
2564 socklen_t cred_len = sizeof(struct ucred);
2565 int ret;
2567 ret = getsockopt(s, SOL_SOCKET, SO_PEERCRED, (void *)&cred, &cred_len);
2568 if (ret != 0) {
2569 return -1;
2572 if (cred_len != sizeof(struct ucred)) {
2573 errno = EINVAL;
2574 return -1;
2577 *uid = cred.uid;
2578 return 0;
2579 #else
2580 errno = ENOSYS;
2581 return -1;
2582 #endif
2585 int sys_getnameinfo(const struct sockaddr *psa,
2586 socklen_t salen,
2587 char *host,
2588 size_t hostlen,
2589 char *service,
2590 size_t servlen,
2591 int flags)
2594 * For Solaris we must make sure salen is the
2595 * correct length for the incoming sa_family.
2598 if (salen == sizeof(struct sockaddr_storage)) {
2599 salen = sizeof(struct sockaddr_in);
2600 #if defined(HAVE_IPV6)
2601 if (psa->sa_family == AF_INET6) {
2602 salen = sizeof(struct sockaddr_in6);
2604 #endif
2606 return getnameinfo(psa, salen, host, hostlen, service, servlen, flags);
2609 int sys_connect(int fd, const struct sockaddr * addr)
2611 socklen_t salen = -1;
2613 if (addr->sa_family == AF_INET) {
2614 salen = sizeof(struct sockaddr_in);
2615 } else if (addr->sa_family == AF_UNIX) {
2616 salen = sizeof(struct sockaddr_un);
2618 #if defined(HAVE_IPV6)
2619 else if (addr->sa_family == AF_INET6) {
2620 salen = sizeof(struct sockaddr_in6);
2622 #endif
2624 return connect(fd, addr, salen);