s3: prefer posix_fallocate for doing "strict allocate"
[Samba/ekacnet.git] / source3 / lib / system.c
blobb18358d8b2cfeec31c79cf5f89a253f9421c5cf0
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 static void init_stat_ex_from_stat (struct stat_ex *dst,
516 const struct stat *src,
517 bool fake_dir_create_times)
519 dst->st_ex_dev = src->st_dev;
520 dst->st_ex_ino = src->st_ino;
521 dst->st_ex_mode = src->st_mode;
522 dst->st_ex_nlink = src->st_nlink;
523 dst->st_ex_uid = src->st_uid;
524 dst->st_ex_gid = src->st_gid;
525 dst->st_ex_rdev = src->st_rdev;
526 dst->st_ex_size = src->st_size;
527 dst->st_ex_atime = get_atimespec(src);
528 dst->st_ex_mtime = get_mtimespec(src);
529 dst->st_ex_ctime = get_ctimespec(src);
530 make_create_timespec(src, dst, fake_dir_create_times);
531 dst->st_ex_blksize = src->st_blksize;
532 dst->st_ex_blocks = src->st_blocks;
534 #ifdef HAVE_STAT_ST_FLAGS
535 dst->st_ex_flags = src->st_flags;
536 #else
537 dst->st_ex_flags = 0;
538 #endif
541 /*******************************************************************
542 A stat() wrapper that will deal with 64 bit filesizes.
543 ********************************************************************/
545 int sys_stat(const char *fname, SMB_STRUCT_STAT *sbuf,
546 bool fake_dir_create_times)
548 int ret;
549 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
550 ret = stat64(fname, sbuf);
551 #else
552 struct stat statbuf;
553 ret = stat(fname, &statbuf);
554 #endif
555 if (ret == 0) {
556 /* we always want directories to appear zero size */
557 if (S_ISDIR(statbuf.st_mode)) {
558 statbuf.st_size = 0;
560 init_stat_ex_from_stat(sbuf, &statbuf, fake_dir_create_times);
562 return ret;
565 /*******************************************************************
566 An fstat() wrapper that will deal with 64 bit filesizes.
567 ********************************************************************/
569 int sys_fstat(int fd, SMB_STRUCT_STAT *sbuf, bool fake_dir_create_times)
571 int ret;
572 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FSTAT64)
573 ret = fstat64(fd, sbuf);
574 #else
575 struct stat statbuf;
576 ret = fstat(fd, &statbuf);
577 #endif
578 if (ret == 0) {
579 /* we always want directories to appear zero size */
580 if (S_ISDIR(statbuf.st_mode)) {
581 statbuf.st_size = 0;
583 init_stat_ex_from_stat(sbuf, &statbuf, fake_dir_create_times);
585 return ret;
588 /*******************************************************************
589 An lstat() wrapper that will deal with 64 bit filesizes.
590 ********************************************************************/
592 int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf,
593 bool fake_dir_create_times)
595 int ret;
596 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSTAT64)
597 ret = lstat64(fname, sbuf);
598 #else
599 struct stat statbuf;
600 ret = lstat(fname, &statbuf);
601 #endif
602 if (ret == 0) {
603 /* we always want directories to appear zero size */
604 if (S_ISDIR(statbuf.st_mode)) {
605 statbuf.st_size = 0;
607 init_stat_ex_from_stat(sbuf, &statbuf, fake_dir_create_times);
609 return ret;
612 /*******************************************************************
613 An posix_fallocate() wrapper that will deal with 64 bit filesizes.
614 ********************************************************************/
615 #if defined(HAVE_POSIX_FALLOCATE64) || defined(HAVE_POSIX_FALLOCATE)
616 int sys_posix_fallocate(int fd, SMB_OFF_T offset, SMB_OFF_T len)
618 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_POSIX_FALLOCATE64)
619 return posix_fallocate64(fd, offset, len);
620 #else
621 return posix_fallocate(fd, offset, len);
622 #endif
624 #endif
626 /*******************************************************************
627 An ftruncate() wrapper that will deal with 64 bit filesizes.
628 ********************************************************************/
630 int sys_ftruncate(int fd, SMB_OFF_T offset)
632 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FTRUNCATE64)
633 return ftruncate64(fd, offset);
634 #else
635 return ftruncate(fd, offset);
636 #endif
639 /*******************************************************************
640 An lseek() wrapper that will deal with 64 bit filesizes.
641 ********************************************************************/
643 SMB_OFF_T sys_lseek(int fd, SMB_OFF_T offset, int whence)
645 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSEEK64)
646 return lseek64(fd, offset, whence);
647 #else
648 return lseek(fd, offset, whence);
649 #endif
652 /*******************************************************************
653 An fseek() wrapper that will deal with 64 bit filesizes.
654 ********************************************************************/
656 int sys_fseek(FILE *fp, SMB_OFF_T offset, int whence)
658 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEK64)
659 return fseek64(fp, offset, whence);
660 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEKO64)
661 return fseeko64(fp, offset, whence);
662 #else
663 return fseek(fp, offset, whence);
664 #endif
667 /*******************************************************************
668 An ftell() wrapper that will deal with 64 bit filesizes.
669 ********************************************************************/
671 SMB_OFF_T sys_ftell(FILE *fp)
673 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELL64)
674 return (SMB_OFF_T)ftell64(fp);
675 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELLO64)
676 return (SMB_OFF_T)ftello64(fp);
677 #else
678 return (SMB_OFF_T)ftell(fp);
679 #endif
682 /*******************************************************************
683 A creat() wrapper that will deal with 64 bit filesizes.
684 ********************************************************************/
686 int sys_creat(const char *path, mode_t mode)
688 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CREAT64)
689 return creat64(path, mode);
690 #else
692 * If creat64 isn't defined then ensure we call a potential open64.
693 * JRA.
695 return sys_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
696 #endif
699 /*******************************************************************
700 An open() wrapper that will deal with 64 bit filesizes.
701 ********************************************************************/
703 int sys_open(const char *path, int oflag, mode_t mode)
705 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPEN64)
706 return open64(path, oflag, mode);
707 #else
708 return open(path, oflag, mode);
709 #endif
712 /*******************************************************************
713 An fopen() wrapper that will deal with 64 bit filesizes.
714 ********************************************************************/
716 FILE *sys_fopen(const char *path, const char *type)
718 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FOPEN64)
719 return fopen64(path, type);
720 #else
721 return fopen(path, type);
722 #endif
726 /*******************************************************************
727 A flock() wrapper that will perform the kernel flock.
728 ********************************************************************/
730 void kernel_flock(int fd, uint32 share_mode, uint32 access_mask)
732 #if HAVE_KERNEL_SHARE_MODES
733 int kernel_mode = 0;
734 if (share_mode == FILE_SHARE_WRITE) {
735 kernel_mode = LOCK_MAND|LOCK_WRITE;
736 } else if (share_mode == FILE_SHARE_READ) {
737 kernel_mode = LOCK_MAND|LOCK_READ;
738 } else if (share_mode == FILE_SHARE_NONE) {
739 kernel_mode = LOCK_MAND;
741 if (kernel_mode) {
742 flock(fd, kernel_mode);
744 #endif
750 /*******************************************************************
751 An opendir wrapper that will deal with 64 bit filesizes.
752 ********************************************************************/
754 SMB_STRUCT_DIR *sys_opendir(const char *name)
756 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPENDIR64)
757 return opendir64(name);
758 #else
759 return opendir(name);
760 #endif
763 /*******************************************************************
764 A readdir wrapper that will deal with 64 bit filesizes.
765 ********************************************************************/
767 SMB_STRUCT_DIRENT *sys_readdir(SMB_STRUCT_DIR *dirp)
769 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_READDIR64)
770 return readdir64(dirp);
771 #else
772 return readdir(dirp);
773 #endif
776 /*******************************************************************
777 A seekdir wrapper that will deal with 64 bit filesizes.
778 ********************************************************************/
780 void sys_seekdir(SMB_STRUCT_DIR *dirp, long offset)
782 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_SEEKDIR64)
783 seekdir64(dirp, offset);
784 #else
785 seekdir(dirp, offset);
786 #endif
789 /*******************************************************************
790 A telldir wrapper that will deal with 64 bit filesizes.
791 ********************************************************************/
793 long sys_telldir(SMB_STRUCT_DIR *dirp)
795 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_TELLDIR64)
796 return (long)telldir64(dirp);
797 #else
798 return (long)telldir(dirp);
799 #endif
802 /*******************************************************************
803 A rewinddir wrapper that will deal with 64 bit filesizes.
804 ********************************************************************/
806 void sys_rewinddir(SMB_STRUCT_DIR *dirp)
808 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_REWINDDIR64)
809 rewinddir64(dirp);
810 #else
811 rewinddir(dirp);
812 #endif
815 /*******************************************************************
816 A close wrapper that will deal with 64 bit filesizes.
817 ********************************************************************/
819 int sys_closedir(SMB_STRUCT_DIR *dirp)
821 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CLOSEDIR64)
822 return closedir64(dirp);
823 #else
824 return closedir(dirp);
825 #endif
828 /*******************************************************************
829 An mknod() wrapper that will deal with 64 bit filesizes.
830 ********************************************************************/
832 int sys_mknod(const char *path, mode_t mode, SMB_DEV_T dev)
834 #if defined(HAVE_MKNOD) || defined(HAVE_MKNOD64)
835 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_MKNOD64) && defined(HAVE_DEV64_T)
836 return mknod64(path, mode, dev);
837 #else
838 return mknod(path, mode, dev);
839 #endif
840 #else
841 /* No mknod system call. */
842 errno = ENOSYS;
843 return -1;
844 #endif
847 /*******************************************************************
848 The wait() calls vary between systems
849 ********************************************************************/
851 int sys_waitpid(pid_t pid,int *status,int options)
853 #ifdef HAVE_WAITPID
854 return waitpid(pid,status,options);
855 #else /* HAVE_WAITPID */
856 return wait4(pid, status, options, NULL);
857 #endif /* HAVE_WAITPID */
860 /*******************************************************************
861 System wrapper for getwd
862 ********************************************************************/
864 char *sys_getwd(char *s)
866 char *wd;
867 #ifdef HAVE_GETCWD
868 wd = (char *)getcwd(s, PATH_MAX);
869 #else
870 wd = (char *)getwd(s);
871 #endif
872 return wd;
875 #if defined(HAVE_POSIX_CAPABILITIES)
877 /**************************************************************************
878 Try and abstract process capabilities (for systems that have them).
879 ****************************************************************************/
881 /* Set the POSIX capabilities needed for the given purpose into the effective
882 * capability set of the current process. Make sure they are always removed
883 * from the inheritable set, because there is no circumstance in which our
884 * children should inherit our elevated privileges.
886 static bool set_process_capability(enum smbd_capability capability,
887 bool enable)
889 cap_value_t cap_vals[2] = {0};
890 int num_cap_vals = 0;
892 cap_t cap;
894 #if defined(HAVE_PRCTL) && defined(PR_GET_KEEPCAPS) && defined(PR_SET_KEEPCAPS)
895 /* On Linux, make sure that any capabilities we grab are sticky
896 * across UID changes. We expect that this would allow us to keep both
897 * the effective and permitted capability sets, but as of circa 2.6.16,
898 * only the permitted set is kept. It is a bug (which we work around)
899 * that the effective set is lost, but we still require the effective
900 * set to be kept.
902 if (!prctl(PR_GET_KEEPCAPS)) {
903 prctl(PR_SET_KEEPCAPS, 1);
905 #endif
907 cap = cap_get_proc();
908 if (cap == NULL) {
909 DEBUG(0,("set_process_capability: cap_get_proc failed: %s\n",
910 strerror(errno)));
911 return False;
914 switch (capability) {
915 case KERNEL_OPLOCK_CAPABILITY:
916 #ifdef CAP_NETWORK_MGT
917 /* IRIX has CAP_NETWORK_MGT for oplocks. */
918 cap_vals[num_cap_vals++] = CAP_NETWORK_MGT;
919 #endif
920 break;
921 case DMAPI_ACCESS_CAPABILITY:
922 #ifdef CAP_DEVICE_MGT
923 /* IRIX has CAP_DEVICE_MGT for DMAPI access. */
924 cap_vals[num_cap_vals++] = CAP_DEVICE_MGT;
925 #elif CAP_MKNOD
926 /* Linux has CAP_MKNOD for DMAPI access. */
927 cap_vals[num_cap_vals++] = CAP_MKNOD;
928 #endif
929 break;
930 case LEASE_CAPABILITY:
931 #ifdef CAP_LEASE
932 cap_vals[num_cap_vals++] = CAP_LEASE;
933 #endif
934 break;
937 SMB_ASSERT(num_cap_vals <= ARRAY_SIZE(cap_vals));
939 if (num_cap_vals == 0) {
940 cap_free(cap);
941 return True;
944 cap_set_flag(cap, CAP_EFFECTIVE, num_cap_vals, cap_vals,
945 enable ? CAP_SET : CAP_CLEAR);
947 /* We never want to pass capabilities down to our children, so make
948 * sure they are not inherited.
950 cap_set_flag(cap, CAP_INHERITABLE, num_cap_vals, cap_vals, CAP_CLEAR);
952 if (cap_set_proc(cap) == -1) {
953 DEBUG(0, ("set_process_capability: cap_set_proc failed: %s\n",
954 strerror(errno)));
955 cap_free(cap);
956 return False;
959 cap_free(cap);
960 return True;
963 #endif /* HAVE_POSIX_CAPABILITIES */
965 /****************************************************************************
966 Gain the oplock capability from the kernel if possible.
967 ****************************************************************************/
969 void set_effective_capability(enum smbd_capability capability)
971 #if defined(HAVE_POSIX_CAPABILITIES)
972 set_process_capability(capability, True);
973 #endif /* HAVE_POSIX_CAPABILITIES */
976 void drop_effective_capability(enum smbd_capability capability)
978 #if defined(HAVE_POSIX_CAPABILITIES)
979 set_process_capability(capability, False);
980 #endif /* HAVE_POSIX_CAPABILITIES */
983 /**************************************************************************
984 Wrapper for random().
985 ****************************************************************************/
987 long sys_random(void)
989 #if defined(HAVE_RANDOM)
990 return (long)random();
991 #elif defined(HAVE_RAND)
992 return (long)rand();
993 #else
994 DEBUG(0,("Error - no random function available !\n"));
995 exit(1);
996 #endif
999 /**************************************************************************
1000 Wrapper for srandom().
1001 ****************************************************************************/
1003 void sys_srandom(unsigned int seed)
1005 #if defined(HAVE_SRANDOM)
1006 srandom(seed);
1007 #elif defined(HAVE_SRAND)
1008 srand(seed);
1009 #else
1010 DEBUG(0,("Error - no srandom function available !\n"));
1011 exit(1);
1012 #endif
1015 /**************************************************************************
1016 Returns equivalent to NGROUPS_MAX - using sysconf if needed.
1017 ****************************************************************************/
1019 int groups_max(void)
1021 #if defined(SYSCONF_SC_NGROUPS_MAX)
1022 int ret = sysconf(_SC_NGROUPS_MAX);
1023 return (ret == -1) ? NGROUPS_MAX : ret;
1024 #else
1025 return NGROUPS_MAX;
1026 #endif
1029 /**************************************************************************
1030 Wrap setgroups and getgroups for systems that declare getgroups() as
1031 returning an array of gid_t, but actuall return an array of int.
1032 ****************************************************************************/
1034 #if defined(HAVE_BROKEN_GETGROUPS)
1035 static int sys_broken_getgroups(int setlen, gid_t *gidset)
1037 GID_T gid;
1038 GID_T *group_list;
1039 int i, ngroups;
1041 if(setlen == 0) {
1042 return getgroups(setlen, &gid);
1046 * Broken case. We need to allocate a
1047 * GID_T array of size setlen.
1050 if(setlen < 0) {
1051 errno = EINVAL;
1052 return -1;
1055 if (setlen == 0)
1056 setlen = groups_max();
1058 if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
1059 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
1060 return -1;
1063 if((ngroups = getgroups(setlen, group_list)) < 0) {
1064 int saved_errno = errno;
1065 SAFE_FREE(group_list);
1066 errno = saved_errno;
1067 return -1;
1070 for(i = 0; i < ngroups; i++)
1071 gidset[i] = (gid_t)group_list[i];
1073 SAFE_FREE(group_list);
1074 return ngroups;
1077 static int sys_broken_setgroups(int setlen, gid_t *gidset)
1079 GID_T *group_list;
1080 int i ;
1082 if (setlen == 0)
1083 return 0 ;
1085 if (setlen < 0 || setlen > groups_max()) {
1086 errno = EINVAL;
1087 return -1;
1091 * Broken case. We need to allocate a
1092 * GID_T array of size setlen.
1095 if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
1096 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
1097 return -1;
1100 for(i = 0; i < setlen; i++)
1101 group_list[i] = (GID_T) gidset[i];
1103 if(setgroups(setlen, group_list) != 0) {
1104 int saved_errno = errno;
1105 SAFE_FREE(group_list);
1106 errno = saved_errno;
1107 return -1;
1110 SAFE_FREE(group_list);
1111 return 0 ;
1114 #endif /* HAVE_BROKEN_GETGROUPS */
1116 /* This is a list of systems that require the first GID passed to setgroups(2)
1117 * to be the effective GID. If your system is one of these, add it here.
1119 #if defined (FREEBSD) || defined (DARWINOS)
1120 #define USE_BSD_SETGROUPS
1121 #endif
1123 #if defined(USE_BSD_SETGROUPS)
1124 /* Depending on the particular BSD implementation, the first GID that is
1125 * passed to setgroups(2) will either be ignored or will set the credential's
1126 * effective GID. In either case, the right thing to do is to guarantee that
1127 * gidset[0] is the effective GID.
1129 static int sys_bsd_setgroups(gid_t primary_gid, int setlen, const gid_t *gidset)
1131 gid_t *new_gidset = NULL;
1132 int max;
1133 int ret;
1135 /* setgroups(2) will fail with EINVAL if we pass too many groups. */
1136 max = groups_max();
1138 /* No group list, just make sure we are setting the efective GID. */
1139 if (setlen == 0) {
1140 return setgroups(1, &primary_gid);
1143 /* If the primary gid is not the first array element, grow the array
1144 * and insert it at the front.
1146 if (gidset[0] != primary_gid) {
1147 new_gidset = SMB_MALLOC_ARRAY(gid_t, setlen + 1);
1148 if (new_gidset == NULL) {
1149 return -1;
1152 memcpy(new_gidset + 1, gidset, (setlen * sizeof(gid_t)));
1153 new_gidset[0] = primary_gid;
1154 setlen++;
1157 if (setlen > max) {
1158 DEBUG(3, ("forced to truncate group list from %d to %d\n",
1159 setlen, max));
1160 setlen = max;
1163 #if defined(HAVE_BROKEN_GETGROUPS)
1164 ret = sys_broken_setgroups(setlen, new_gidset ? new_gidset : gidset);
1165 #else
1166 ret = setgroups(setlen, new_gidset ? new_gidset : gidset);
1167 #endif
1169 if (new_gidset) {
1170 int errsav = errno;
1171 SAFE_FREE(new_gidset);
1172 errno = errsav;
1175 return ret;
1178 #endif /* USE_BSD_SETGROUPS */
1180 /**************************************************************************
1181 Wrapper for getgroups. Deals with broken (int) case.
1182 ****************************************************************************/
1184 int sys_getgroups(int setlen, gid_t *gidset)
1186 #if defined(HAVE_BROKEN_GETGROUPS)
1187 return sys_broken_getgroups(setlen, gidset);
1188 #else
1189 return getgroups(setlen, gidset);
1190 #endif
1193 /**************************************************************************
1194 Wrapper for setgroups. Deals with broken (int) case and BSD case.
1195 ****************************************************************************/
1197 int sys_setgroups(gid_t UNUSED(primary_gid), int setlen, gid_t *gidset)
1199 #if !defined(HAVE_SETGROUPS)
1200 errno = ENOSYS;
1201 return -1;
1202 #endif /* HAVE_SETGROUPS */
1204 #if defined(USE_BSD_SETGROUPS)
1205 return sys_bsd_setgroups(primary_gid, setlen, gidset);
1206 #elif defined(HAVE_BROKEN_GETGROUPS)
1207 return sys_broken_setgroups(setlen, gidset);
1208 #else
1209 return setgroups(setlen, gidset);
1210 #endif
1213 /**************************************************************************
1214 Wrappers for setpwent(), getpwent() and endpwent()
1215 ****************************************************************************/
1217 void sys_setpwent(void)
1219 setpwent();
1222 struct passwd *sys_getpwent(void)
1224 return getpwent();
1227 void sys_endpwent(void)
1229 endpwent();
1232 /**************************************************************************
1233 Wrappers for getpwnam(), getpwuid(), getgrnam(), getgrgid()
1234 ****************************************************************************/
1237 struct passwd *sys_getpwnam(const char *name)
1239 return getpwnam(name);
1242 struct passwd *sys_getpwuid(uid_t uid)
1244 return getpwuid(uid);
1247 struct group *sys_getgrnam(const char *name)
1249 return getgrnam(name);
1252 struct group *sys_getgrgid(gid_t gid)
1254 return getgrgid(gid);
1257 /**************************************************************************
1258 Extract a command into an arg list.
1259 ****************************************************************************/
1261 static char **extract_args(TALLOC_CTX *mem_ctx, const char *command)
1263 char *trunc_cmd;
1264 char *saveptr;
1265 char *ptr;
1266 int argcl;
1267 char **argl = NULL;
1268 int i;
1270 if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1271 DEBUG(0, ("talloc failed\n"));
1272 goto nomem;
1275 if(!(ptr = strtok_r(trunc_cmd, " \t", &saveptr))) {
1276 TALLOC_FREE(trunc_cmd);
1277 errno = EINVAL;
1278 return NULL;
1282 * Count the args.
1285 for( argcl = 1; ptr; ptr = strtok_r(NULL, " \t", &saveptr))
1286 argcl++;
1288 TALLOC_FREE(trunc_cmd);
1290 if (!(argl = TALLOC_ARRAY(mem_ctx, char *, argcl + 1))) {
1291 goto nomem;
1295 * Now do the extraction.
1298 if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1299 goto nomem;
1302 ptr = strtok_r(trunc_cmd, " \t", &saveptr);
1303 i = 0;
1305 if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1306 goto nomem;
1309 while((ptr = strtok_r(NULL, " \t", &saveptr)) != NULL) {
1311 if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1312 goto nomem;
1316 argl[i++] = NULL;
1317 TALLOC_FREE(trunc_cmd);
1318 return argl;
1320 nomem:
1321 DEBUG(0, ("talloc failed\n"));
1322 TALLOC_FREE(trunc_cmd);
1323 TALLOC_FREE(argl);
1324 errno = ENOMEM;
1325 return NULL;
1328 /**************************************************************************
1329 Wrapper for popen. Safer as it doesn't search a path.
1330 Modified from the glibc sources.
1331 modified by tridge to return a file descriptor. We must kick our FILE* habit
1332 ****************************************************************************/
1334 typedef struct _popen_list
1336 int fd;
1337 pid_t child_pid;
1338 struct _popen_list *next;
1339 } popen_list;
1341 static popen_list *popen_chain;
1343 int sys_popen(const char *command)
1345 int parent_end, child_end;
1346 int pipe_fds[2];
1347 popen_list *entry = NULL;
1348 char **argl = NULL;
1350 if (pipe(pipe_fds) < 0)
1351 return -1;
1353 parent_end = pipe_fds[0];
1354 child_end = pipe_fds[1];
1356 if (!*command) {
1357 errno = EINVAL;
1358 goto err_exit;
1361 if((entry = SMB_MALLOC_P(popen_list)) == NULL)
1362 goto err_exit;
1364 ZERO_STRUCTP(entry);
1367 * Extract the command and args into a NULL terminated array.
1370 if(!(argl = extract_args(NULL, command)))
1371 goto err_exit;
1373 entry->child_pid = sys_fork();
1375 if (entry->child_pid == -1) {
1376 goto err_exit;
1379 if (entry->child_pid == 0) {
1382 * Child !
1385 int child_std_end = STDOUT_FILENO;
1386 popen_list *p;
1388 close(parent_end);
1389 if (child_end != child_std_end) {
1390 dup2 (child_end, child_std_end);
1391 close (child_end);
1395 * POSIX.2: "popen() shall ensure that any streams from previous
1396 * popen() calls that remain open in the parent process are closed
1397 * in the new child process."
1400 for (p = popen_chain; p; p = p->next)
1401 close(p->fd);
1403 execv(argl[0], argl);
1404 _exit (127);
1408 * Parent.
1411 close (child_end);
1412 TALLOC_FREE(argl);
1414 /* Link into popen_chain. */
1415 entry->next = popen_chain;
1416 popen_chain = entry;
1417 entry->fd = parent_end;
1419 return entry->fd;
1421 err_exit:
1423 SAFE_FREE(entry);
1424 SAFE_FREE(argl);
1425 close(pipe_fds[0]);
1426 close(pipe_fds[1]);
1427 return -1;
1430 /**************************************************************************
1431 Wrapper for pclose. Modified from the glibc sources.
1432 ****************************************************************************/
1434 int sys_pclose(int fd)
1436 int wstatus;
1437 popen_list **ptr = &popen_chain;
1438 popen_list *entry = NULL;
1439 pid_t wait_pid;
1440 int status = -1;
1442 /* Unlink from popen_chain. */
1443 for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
1444 if ((*ptr)->fd == fd) {
1445 entry = *ptr;
1446 *ptr = (*ptr)->next;
1447 status = 0;
1448 break;
1452 if (status < 0 || close(entry->fd) < 0)
1453 return -1;
1456 * As Samba is catching and eating child process
1457 * exits we don't really care about the child exit
1458 * code, a -1 with errno = ECHILD will do fine for us.
1461 do {
1462 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
1463 } while (wait_pid == -1 && errno == EINTR);
1465 SAFE_FREE(entry);
1467 if (wait_pid == -1)
1468 return -1;
1469 return wstatus;
1472 /**************************************************************************
1473 Wrapper for Admin Logs.
1474 ****************************************************************************/
1476 void sys_adminlog(int priority, const char *format_str, ...)
1478 va_list ap;
1479 int ret;
1480 char *msgbuf = NULL;
1482 va_start( ap, format_str );
1483 ret = vasprintf( &msgbuf, format_str, ap );
1484 va_end( ap );
1486 if (ret == -1)
1487 return;
1489 #if defined(HAVE_SYSLOG)
1490 syslog( priority, "%s", msgbuf );
1491 #else
1492 DEBUG(0,("%s", msgbuf ));
1493 #endif
1494 SAFE_FREE(msgbuf);
1497 /******** Solaris EA helper function prototypes ********/
1498 #ifdef HAVE_ATTROPEN
1499 #define SOLARIS_ATTRMODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP
1500 static int solaris_write_xattr(int attrfd, const char *value, size_t size);
1501 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size);
1502 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size);
1503 static int solaris_unlinkat(int attrdirfd, const char *name);
1504 static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode);
1505 static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode);
1506 #endif
1508 /**************************************************************************
1509 Wrappers for extented attribute calls. Based on the Linux package with
1510 support for IRIX and (Net|Free)BSD also. Expand as other systems have them.
1511 ****************************************************************************/
1513 ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t size)
1515 #if defined(HAVE_GETXATTR)
1516 #ifndef XATTR_ADD_OPT
1517 return getxattr(path, name, value, size);
1518 #else
1519 int options = 0;
1520 return getxattr(path, name, value, size, 0, options);
1521 #endif
1522 #elif defined(HAVE_GETEA)
1523 return getea(path, name, value, size);
1524 #elif defined(HAVE_EXTATTR_GET_FILE)
1525 char *s;
1526 ssize_t retval;
1527 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1528 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1529 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1531 * The BSD implementation has a nasty habit of silently truncating
1532 * the returned value to the size of the buffer, so we have to check
1533 * that the buffer is large enough to fit the returned value.
1535 if((retval=extattr_get_file(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1536 if(retval > size) {
1537 errno = ERANGE;
1538 return -1;
1540 if((retval=extattr_get_file(path, attrnamespace, attrname, value, size)) >= 0)
1541 return retval;
1544 DEBUG(10,("sys_getxattr: extattr_get_file() failed with: %s\n", strerror(errno)));
1545 return -1;
1546 #elif defined(HAVE_ATTR_GET)
1547 int retval, flags = 0;
1548 int valuelength = (int)size;
1549 char *attrname = strchr(name,'.') + 1;
1551 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1553 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1555 return retval ? retval : valuelength;
1556 #elif defined(HAVE_ATTROPEN)
1557 ssize_t ret = -1;
1558 int attrfd = solaris_attropen(path, name, O_RDONLY, 0);
1559 if (attrfd >= 0) {
1560 ret = solaris_read_xattr(attrfd, value, size);
1561 close(attrfd);
1563 return ret;
1564 #else
1565 errno = ENOSYS;
1566 return -1;
1567 #endif
1570 ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t size)
1572 #if defined(HAVE_LGETXATTR)
1573 return lgetxattr(path, name, value, size);
1574 #elif defined(HAVE_GETXATTR) && defined(XATTR_ADD_OPT)
1575 int options = XATTR_NOFOLLOW;
1576 return getxattr(path, name, value, size, 0, options);
1577 #elif defined(HAVE_LGETEA)
1578 return lgetea(path, name, value, size);
1579 #elif defined(HAVE_EXTATTR_GET_LINK)
1580 char *s;
1581 ssize_t retval;
1582 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1583 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1584 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1586 if((retval=extattr_get_link(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1587 if(retval > size) {
1588 errno = ERANGE;
1589 return -1;
1591 if((retval=extattr_get_link(path, attrnamespace, attrname, value, size)) >= 0)
1592 return retval;
1595 DEBUG(10,("sys_lgetxattr: extattr_get_link() failed with: %s\n", strerror(errno)));
1596 return -1;
1597 #elif defined(HAVE_ATTR_GET)
1598 int retval, flags = ATTR_DONTFOLLOW;
1599 int valuelength = (int)size;
1600 char *attrname = strchr(name,'.') + 1;
1602 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1604 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1606 return retval ? retval : valuelength;
1607 #elif defined(HAVE_ATTROPEN)
1608 ssize_t ret = -1;
1609 int attrfd = solaris_attropen(path, name, O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1610 if (attrfd >= 0) {
1611 ret = solaris_read_xattr(attrfd, value, size);
1612 close(attrfd);
1614 return ret;
1615 #else
1616 errno = ENOSYS;
1617 return -1;
1618 #endif
1621 ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size)
1623 #if defined(HAVE_FGETXATTR)
1624 #ifndef XATTR_ADD_OPT
1625 return fgetxattr(filedes, name, value, size);
1626 #else
1627 int options = 0;
1628 return fgetxattr(filedes, name, value, size, 0, options);
1629 #endif
1630 #elif defined(HAVE_FGETEA)
1631 return fgetea(filedes, name, value, size);
1632 #elif defined(HAVE_EXTATTR_GET_FD)
1633 char *s;
1634 ssize_t retval;
1635 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1636 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1637 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1639 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0)) >= 0) {
1640 if(retval > size) {
1641 errno = ERANGE;
1642 return -1;
1644 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, value, size)) >= 0)
1645 return retval;
1648 DEBUG(10,("sys_fgetxattr: extattr_get_fd() failed with: %s\n", strerror(errno)));
1649 return -1;
1650 #elif defined(HAVE_ATTR_GETF)
1651 int retval, flags = 0;
1652 int valuelength = (int)size;
1653 char *attrname = strchr(name,'.') + 1;
1655 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1657 retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags);
1659 return retval ? retval : valuelength;
1660 #elif defined(HAVE_ATTROPEN)
1661 ssize_t ret = -1;
1662 int attrfd = solaris_openat(filedes, name, O_RDONLY|O_XATTR, 0);
1663 if (attrfd >= 0) {
1664 ret = solaris_read_xattr(attrfd, value, size);
1665 close(attrfd);
1667 return ret;
1668 #else
1669 errno = ENOSYS;
1670 return -1;
1671 #endif
1674 #if defined(HAVE_EXTATTR_LIST_FILE)
1676 #define EXTATTR_PREFIX(s) (s), (sizeof((s))-1)
1678 static struct {
1679 int space;
1680 const char *name;
1681 size_t len;
1683 extattr[] = {
1684 { EXTATTR_NAMESPACE_SYSTEM, EXTATTR_PREFIX("system.") },
1685 { EXTATTR_NAMESPACE_USER, EXTATTR_PREFIX("user.") },
1688 typedef union {
1689 const char *path;
1690 int filedes;
1691 } extattr_arg;
1693 static ssize_t bsd_attr_list (int type, extattr_arg arg, char *list, size_t size)
1695 ssize_t list_size, total_size = 0;
1696 int i, t, len;
1697 char *buf;
1698 /* Iterate through extattr(2) namespaces */
1699 for(t = 0; t < (sizeof(extattr)/sizeof(extattr[0])); t++) {
1700 switch(type) {
1701 #if defined(HAVE_EXTATTR_LIST_FILE)
1702 case 0:
1703 list_size = extattr_list_file(arg.path, extattr[t].space, list, size);
1704 break;
1705 #endif
1706 #if defined(HAVE_EXTATTR_LIST_LINK)
1707 case 1:
1708 list_size = extattr_list_link(arg.path, extattr[t].space, list, size);
1709 break;
1710 #endif
1711 #if defined(HAVE_EXTATTR_LIST_FD)
1712 case 2:
1713 list_size = extattr_list_fd(arg.filedes, extattr[t].space, list, size);
1714 break;
1715 #endif
1716 default:
1717 errno = ENOSYS;
1718 return -1;
1720 /* Some error happend. Errno should be set by the previous call */
1721 if(list_size < 0)
1722 return -1;
1723 /* No attributes */
1724 if(list_size == 0)
1725 continue;
1726 /* XXX: Call with an empty buffer may be used to calculate
1727 necessary buffer size. Unfortunately, we can't say, how
1728 many attributes were returned, so here is the potential
1729 problem with the emulation.
1731 if(list == NULL) {
1732 /* Take the worse case of one char attribute names -
1733 two bytes per name plus one more for sanity.
1735 total_size += list_size + (list_size/2 + 1)*extattr[t].len;
1736 continue;
1738 /* Count necessary offset to fit namespace prefixes */
1739 len = 0;
1740 for(i = 0; i < list_size; i += list[i] + 1)
1741 len += extattr[t].len;
1743 total_size += list_size + len;
1744 /* Buffer is too small to fit the results */
1745 if(total_size > size) {
1746 errno = ERANGE;
1747 return -1;
1749 /* Shift results back, so we can prepend prefixes */
1750 buf = memmove(list + len, list, list_size);
1752 for(i = 0; i < list_size; i += len + 1) {
1753 len = buf[i];
1754 strncpy(list, extattr[t].name, extattr[t].len + 1);
1755 list += extattr[t].len;
1756 strncpy(list, buf + i + 1, len);
1757 list[len] = '\0';
1758 list += len + 1;
1760 size -= total_size;
1762 return total_size;
1765 #endif
1767 #if defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1768 static char attr_buffer[ATTR_MAX_VALUELEN];
1770 static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags)
1772 int retval = 0, index;
1773 attrlist_cursor_t *cursor = 0;
1774 int total_size = 0;
1775 attrlist_t * al = (attrlist_t *)attr_buffer;
1776 attrlist_ent_t *ae;
1777 size_t ent_size, left = size;
1778 char *bp = list;
1780 while (True) {
1781 if (filedes)
1782 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1783 else
1784 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1785 if (retval) break;
1786 for (index = 0; index < al->al_count; index++) {
1787 ae = ATTR_ENTRY(attr_buffer, index);
1788 ent_size = strlen(ae->a_name) + sizeof("user.");
1789 if (left >= ent_size) {
1790 strncpy(bp, "user.", sizeof("user."));
1791 strncat(bp, ae->a_name, ent_size - sizeof("user."));
1792 bp += ent_size;
1793 left -= ent_size;
1794 } else if (size) {
1795 errno = ERANGE;
1796 retval = -1;
1797 break;
1799 total_size += ent_size;
1801 if (al->al_more == 0) break;
1803 if (retval == 0) {
1804 flags |= ATTR_ROOT;
1805 cursor = 0;
1806 while (True) {
1807 if (filedes)
1808 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1809 else
1810 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1811 if (retval) break;
1812 for (index = 0; index < al->al_count; index++) {
1813 ae = ATTR_ENTRY(attr_buffer, index);
1814 ent_size = strlen(ae->a_name) + sizeof("system.");
1815 if (left >= ent_size) {
1816 strncpy(bp, "system.", sizeof("system."));
1817 strncat(bp, ae->a_name, ent_size - sizeof("system."));
1818 bp += ent_size;
1819 left -= ent_size;
1820 } else if (size) {
1821 errno = ERANGE;
1822 retval = -1;
1823 break;
1825 total_size += ent_size;
1827 if (al->al_more == 0) break;
1830 return (ssize_t)(retval ? retval : total_size);
1833 #endif
1835 ssize_t sys_listxattr (const char *path, char *list, size_t size)
1837 #if defined(HAVE_LISTXATTR)
1838 #ifndef XATTR_ADD_OPT
1839 return listxattr(path, list, size);
1840 #else
1841 int options = 0;
1842 return listxattr(path, list, size, options);
1843 #endif
1844 #elif defined(HAVE_LISTEA)
1845 return listea(path, list, size);
1846 #elif defined(HAVE_EXTATTR_LIST_FILE)
1847 extattr_arg arg;
1848 arg.path = path;
1849 return bsd_attr_list(0, arg, list, size);
1850 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1851 return irix_attr_list(path, 0, list, size, 0);
1852 #elif defined(HAVE_ATTROPEN)
1853 ssize_t ret = -1;
1854 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
1855 if (attrdirfd >= 0) {
1856 ret = solaris_list_xattr(attrdirfd, list, size);
1857 close(attrdirfd);
1859 return ret;
1860 #else
1861 errno = ENOSYS;
1862 return -1;
1863 #endif
1866 ssize_t sys_llistxattr (const char *path, char *list, size_t size)
1868 #if defined(HAVE_LLISTXATTR)
1869 return llistxattr(path, list, size);
1870 #elif defined(HAVE_LISTXATTR) && defined(XATTR_ADD_OPT)
1871 int options = XATTR_NOFOLLOW;
1872 return listxattr(path, list, size, options);
1873 #elif defined(HAVE_LLISTEA)
1874 return llistea(path, list, size);
1875 #elif defined(HAVE_EXTATTR_LIST_LINK)
1876 extattr_arg arg;
1877 arg.path = path;
1878 return bsd_attr_list(1, arg, list, size);
1879 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1880 return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW);
1881 #elif defined(HAVE_ATTROPEN)
1882 ssize_t ret = -1;
1883 int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1884 if (attrdirfd >= 0) {
1885 ret = solaris_list_xattr(attrdirfd, list, size);
1886 close(attrdirfd);
1888 return ret;
1889 #else
1890 errno = ENOSYS;
1891 return -1;
1892 #endif
1895 ssize_t sys_flistxattr (int filedes, char *list, size_t size)
1897 #if defined(HAVE_FLISTXATTR)
1898 #ifndef XATTR_ADD_OPT
1899 return flistxattr(filedes, list, size);
1900 #else
1901 int options = 0;
1902 return flistxattr(filedes, list, size, options);
1903 #endif
1904 #elif defined(HAVE_FLISTEA)
1905 return flistea(filedes, list, size);
1906 #elif defined(HAVE_EXTATTR_LIST_FD)
1907 extattr_arg arg;
1908 arg.filedes = filedes;
1909 return bsd_attr_list(2, arg, list, size);
1910 #elif defined(HAVE_ATTR_LISTF)
1911 return irix_attr_list(NULL, filedes, list, size, 0);
1912 #elif defined(HAVE_ATTROPEN)
1913 ssize_t ret = -1;
1914 int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
1915 if (attrdirfd >= 0) {
1916 ret = solaris_list_xattr(attrdirfd, list, size);
1917 close(attrdirfd);
1919 return ret;
1920 #else
1921 errno = ENOSYS;
1922 return -1;
1923 #endif
1926 int sys_removexattr (const char *path, const char *name)
1928 #if defined(HAVE_REMOVEXATTR)
1929 #ifndef XATTR_ADD_OPT
1930 return removexattr(path, name);
1931 #else
1932 int options = 0;
1933 return removexattr(path, name, options);
1934 #endif
1935 #elif defined(HAVE_REMOVEEA)
1936 return removeea(path, name);
1937 #elif defined(HAVE_EXTATTR_DELETE_FILE)
1938 char *s;
1939 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1940 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1941 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1943 return extattr_delete_file(path, attrnamespace, attrname);
1944 #elif defined(HAVE_ATTR_REMOVE)
1945 int flags = 0;
1946 char *attrname = strchr(name,'.') + 1;
1948 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1950 return attr_remove(path, attrname, flags);
1951 #elif defined(HAVE_ATTROPEN)
1952 int ret = -1;
1953 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
1954 if (attrdirfd >= 0) {
1955 ret = solaris_unlinkat(attrdirfd, name);
1956 close(attrdirfd);
1958 return ret;
1959 #else
1960 errno = ENOSYS;
1961 return -1;
1962 #endif
1965 int sys_lremovexattr (const char *path, const char *name)
1967 #if defined(HAVE_LREMOVEXATTR)
1968 return lremovexattr(path, name);
1969 #elif defined(HAVE_REMOVEXATTR) && defined(XATTR_ADD_OPT)
1970 int options = XATTR_NOFOLLOW;
1971 return removexattr(path, name, options);
1972 #elif defined(HAVE_LREMOVEEA)
1973 return lremoveea(path, name);
1974 #elif defined(HAVE_EXTATTR_DELETE_LINK)
1975 char *s;
1976 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1977 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1978 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1980 return extattr_delete_link(path, attrnamespace, attrname);
1981 #elif defined(HAVE_ATTR_REMOVE)
1982 int flags = ATTR_DONTFOLLOW;
1983 char *attrname = strchr(name,'.') + 1;
1985 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1987 return attr_remove(path, attrname, flags);
1988 #elif defined(HAVE_ATTROPEN)
1989 int ret = -1;
1990 int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1991 if (attrdirfd >= 0) {
1992 ret = solaris_unlinkat(attrdirfd, name);
1993 close(attrdirfd);
1995 return ret;
1996 #else
1997 errno = ENOSYS;
1998 return -1;
1999 #endif
2002 int sys_fremovexattr (int filedes, const char *name)
2004 #if defined(HAVE_FREMOVEXATTR)
2005 #ifndef XATTR_ADD_OPT
2006 return fremovexattr(filedes, name);
2007 #else
2008 int options = 0;
2009 return fremovexattr(filedes, name, options);
2010 #endif
2011 #elif defined(HAVE_FREMOVEEA)
2012 return fremoveea(filedes, name);
2013 #elif defined(HAVE_EXTATTR_DELETE_FD)
2014 char *s;
2015 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2016 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2017 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2019 return extattr_delete_fd(filedes, attrnamespace, attrname);
2020 #elif defined(HAVE_ATTR_REMOVEF)
2021 int flags = 0;
2022 char *attrname = strchr(name,'.') + 1;
2024 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
2026 return attr_removef(filedes, attrname, flags);
2027 #elif defined(HAVE_ATTROPEN)
2028 int ret = -1;
2029 int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
2030 if (attrdirfd >= 0) {
2031 ret = solaris_unlinkat(attrdirfd, name);
2032 close(attrdirfd);
2034 return ret;
2035 #else
2036 errno = ENOSYS;
2037 return -1;
2038 #endif
2041 int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags)
2043 #if defined(HAVE_SETXATTR)
2044 #ifndef XATTR_ADD_OPT
2045 return setxattr(path, name, value, size, flags);
2046 #else
2047 int options = 0;
2048 return setxattr(path, name, value, size, 0, options);
2049 #endif
2050 #elif defined(HAVE_SETEA)
2051 return setea(path, name, value, size, flags);
2052 #elif defined(HAVE_EXTATTR_SET_FILE)
2053 char *s;
2054 int retval = 0;
2055 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2056 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2057 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2058 if (flags) {
2059 /* Check attribute existence */
2060 retval = extattr_get_file(path, attrnamespace, attrname, NULL, 0);
2061 if (retval < 0) {
2062 /* REPLACE attribute, that doesn't exist */
2063 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2064 errno = ENOATTR;
2065 return -1;
2067 /* Ignore other errors */
2069 else {
2070 /* CREATE attribute, that already exists */
2071 if (flags & XATTR_CREATE) {
2072 errno = EEXIST;
2073 return -1;
2077 retval = extattr_set_file(path, attrnamespace, attrname, value, size);
2078 return (retval < 0) ? -1 : 0;
2079 #elif defined(HAVE_ATTR_SET)
2080 int myflags = 0;
2081 char *attrname = strchr(name,'.') + 1;
2083 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2084 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2085 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2087 return attr_set(path, attrname, (const char *)value, size, myflags);
2088 #elif defined(HAVE_ATTROPEN)
2089 int ret = -1;
2090 int myflags = O_RDWR;
2091 int attrfd;
2092 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2093 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2094 attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2095 if (attrfd >= 0) {
2096 ret = solaris_write_xattr(attrfd, value, size);
2097 close(attrfd);
2099 return ret;
2100 #else
2101 errno = ENOSYS;
2102 return -1;
2103 #endif
2106 int sys_lsetxattr (const char *path, const char *name, const void *value, size_t size, int flags)
2108 #if defined(HAVE_LSETXATTR)
2109 return lsetxattr(path, name, value, size, flags);
2110 #elif defined(HAVE_SETXATTR) && defined(XATTR_ADD_OPT)
2111 int options = XATTR_NOFOLLOW;
2112 return setxattr(path, name, value, size, 0, options);
2113 #elif defined(LSETEA)
2114 return lsetea(path, name, value, size, flags);
2115 #elif defined(HAVE_EXTATTR_SET_LINK)
2116 char *s;
2117 int retval = 0;
2118 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2119 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2120 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2121 if (flags) {
2122 /* Check attribute existence */
2123 retval = extattr_get_link(path, attrnamespace, attrname, NULL, 0);
2124 if (retval < 0) {
2125 /* REPLACE attribute, that doesn't exist */
2126 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2127 errno = ENOATTR;
2128 return -1;
2130 /* Ignore other errors */
2132 else {
2133 /* CREATE attribute, that already exists */
2134 if (flags & XATTR_CREATE) {
2135 errno = EEXIST;
2136 return -1;
2141 retval = extattr_set_link(path, attrnamespace, attrname, value, size);
2142 return (retval < 0) ? -1 : 0;
2143 #elif defined(HAVE_ATTR_SET)
2144 int myflags = ATTR_DONTFOLLOW;
2145 char *attrname = strchr(name,'.') + 1;
2147 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2148 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2149 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2151 return attr_set(path, attrname, (const char *)value, size, myflags);
2152 #elif defined(HAVE_ATTROPEN)
2153 int ret = -1;
2154 int myflags = O_RDWR | AT_SYMLINK_NOFOLLOW;
2155 int attrfd;
2156 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2157 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2158 attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2159 if (attrfd >= 0) {
2160 ret = solaris_write_xattr(attrfd, value, size);
2161 close(attrfd);
2163 return ret;
2164 #else
2165 errno = ENOSYS;
2166 return -1;
2167 #endif
2170 int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags)
2172 #if defined(HAVE_FSETXATTR)
2173 #ifndef XATTR_ADD_OPT
2174 return fsetxattr(filedes, name, value, size, flags);
2175 #else
2176 int options = 0;
2177 return fsetxattr(filedes, name, value, size, 0, options);
2178 #endif
2179 #elif defined(HAVE_FSETEA)
2180 return fsetea(filedes, name, value, size, flags);
2181 #elif defined(HAVE_EXTATTR_SET_FD)
2182 char *s;
2183 int retval = 0;
2184 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2185 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2186 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2187 if (flags) {
2188 /* Check attribute existence */
2189 retval = extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0);
2190 if (retval < 0) {
2191 /* REPLACE attribute, that doesn't exist */
2192 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2193 errno = ENOATTR;
2194 return -1;
2196 /* Ignore other errors */
2198 else {
2199 /* CREATE attribute, that already exists */
2200 if (flags & XATTR_CREATE) {
2201 errno = EEXIST;
2202 return -1;
2206 retval = extattr_set_fd(filedes, attrnamespace, attrname, value, size);
2207 return (retval < 0) ? -1 : 0;
2208 #elif defined(HAVE_ATTR_SETF)
2209 int myflags = 0;
2210 char *attrname = strchr(name,'.') + 1;
2212 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2213 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2214 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2216 return attr_setf(filedes, attrname, (const char *)value, size, myflags);
2217 #elif defined(HAVE_ATTROPEN)
2218 int ret = -1;
2219 int myflags = O_RDWR | O_XATTR;
2220 int attrfd;
2221 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2222 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2223 attrfd = solaris_openat(filedes, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2224 if (attrfd >= 0) {
2225 ret = solaris_write_xattr(attrfd, value, size);
2226 close(attrfd);
2228 return ret;
2229 #else
2230 errno = ENOSYS;
2231 return -1;
2232 #endif
2235 /**************************************************************************
2236 helper functions for Solaris' EA support
2237 ****************************************************************************/
2238 #ifdef HAVE_ATTROPEN
2239 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size)
2241 struct stat sbuf;
2243 if (fstat(attrfd, &sbuf) == -1) {
2244 errno = ENOATTR;
2245 return -1;
2248 /* This is to return the current size of the named extended attribute */
2249 if (size == 0) {
2250 return sbuf.st_size;
2253 /* check size and read xattr */
2254 if (sbuf.st_size > size) {
2255 errno = ERANGE;
2256 return -1;
2259 return read(attrfd, value, sbuf.st_size);
2262 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size)
2264 ssize_t len = 0;
2265 DIR *dirp;
2266 struct dirent *de;
2267 int newfd = dup(attrdirfd);
2268 /* CAUTION: The originating file descriptor should not be
2269 used again following the call to fdopendir().
2270 For that reason we dup() the file descriptor
2271 here to make things more clear. */
2272 dirp = fdopendir(newfd);
2274 while ((de = readdir(dirp))) {
2275 size_t listlen = strlen(de->d_name);
2276 if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) {
2277 /* we don't want "." and ".." here: */
2278 DEBUG(10,("skipped EA %s\n",de->d_name));
2279 continue;
2282 if (size == 0) {
2283 /* return the current size of the list of extended attribute names*/
2284 len += listlen + 1;
2285 } else {
2286 /* check size and copy entrieѕ + nul into list. */
2287 if ((len + listlen + 1) > size) {
2288 errno = ERANGE;
2289 len = -1;
2290 break;
2291 } else {
2292 safe_strcpy(list + len, de->d_name, listlen);
2293 len += listlen;
2294 list[len] = '\0';
2295 ++len;
2300 if (closedir(dirp) == -1) {
2301 DEBUG(0,("closedir dirp failed: %s\n",strerror(errno)));
2302 return -1;
2304 return len;
2307 static int solaris_unlinkat(int attrdirfd, const char *name)
2309 if (unlinkat(attrdirfd, name, 0) == -1) {
2310 if (errno == ENOENT) {
2311 errno = ENOATTR;
2313 return -1;
2315 return 0;
2318 static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode)
2320 int filedes = attropen(path, attrpath, oflag, mode);
2321 if (filedes == -1) {
2322 DEBUG(10,("attropen FAILED: path: %s, name: %s, errno: %s\n",path,attrpath,strerror(errno)));
2323 if (errno == EINVAL) {
2324 errno = ENOTSUP;
2325 } else {
2326 errno = ENOATTR;
2329 return filedes;
2332 static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode)
2334 int filedes = openat(fildes, path, oflag, mode);
2335 if (filedes == -1) {
2336 DEBUG(10,("openat FAILED: fd: %d, path: %s, errno: %s\n",filedes,path,strerror(errno)));
2337 if (errno == EINVAL) {
2338 errno = ENOTSUP;
2339 } else {
2340 errno = ENOATTR;
2343 return filedes;
2346 static int solaris_write_xattr(int attrfd, const char *value, size_t size)
2348 if ((ftruncate(attrfd, 0) == 0) && (write(attrfd, value, size) == size)) {
2349 return 0;
2350 } else {
2351 DEBUG(10,("solaris_write_xattr FAILED!\n"));
2352 return -1;
2355 #endif /*HAVE_ATTROPEN*/
2358 /****************************************************************************
2359 Return the major devicenumber for UNIX extensions.
2360 ****************************************************************************/
2362 uint32 unix_dev_major(SMB_DEV_T dev)
2364 #if defined(HAVE_DEVICE_MAJOR_FN)
2365 return (uint32)major(dev);
2366 #else
2367 return (uint32)(dev >> 8);
2368 #endif
2371 /****************************************************************************
2372 Return the minor devicenumber for UNIX extensions.
2373 ****************************************************************************/
2375 uint32 unix_dev_minor(SMB_DEV_T dev)
2377 #if defined(HAVE_DEVICE_MINOR_FN)
2378 return (uint32)minor(dev);
2379 #else
2380 return (uint32)(dev & 0xff);
2381 #endif
2384 #if defined(WITH_AIO)
2386 /*******************************************************************
2387 An aio_read wrapper that will deal with 64-bit sizes.
2388 ********************************************************************/
2390 int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2392 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_READ64)
2393 return aio_read64(aiocb);
2394 #elif defined(HAVE_AIO_READ)
2395 return aio_read(aiocb);
2396 #else
2397 errno = ENOSYS;
2398 return -1;
2399 #endif
2402 /*******************************************************************
2403 An aio_write wrapper that will deal with 64-bit sizes.
2404 ********************************************************************/
2406 int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2408 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_WRITE64)
2409 return aio_write64(aiocb);
2410 #elif defined(HAVE_AIO_WRITE)
2411 return aio_write(aiocb);
2412 #else
2413 errno = ENOSYS;
2414 return -1;
2415 #endif
2418 /*******************************************************************
2419 An aio_return wrapper that will deal with 64-bit sizes.
2420 ********************************************************************/
2422 ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2424 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_RETURN64)
2425 return aio_return64(aiocb);
2426 #elif defined(HAVE_AIO_RETURN)
2427 return aio_return(aiocb);
2428 #else
2429 errno = ENOSYS;
2430 return -1;
2431 #endif
2434 /*******************************************************************
2435 An aio_cancel wrapper that will deal with 64-bit sizes.
2436 ********************************************************************/
2438 int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2440 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_CANCEL64)
2441 return aio_cancel64(fd, aiocb);
2442 #elif defined(HAVE_AIO_CANCEL)
2443 return aio_cancel(fd, aiocb);
2444 #else
2445 errno = ENOSYS;
2446 return -1;
2447 #endif
2450 /*******************************************************************
2451 An aio_error wrapper that will deal with 64-bit sizes.
2452 ********************************************************************/
2454 int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2456 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_ERROR64)
2457 return aio_error64(aiocb);
2458 #elif defined(HAVE_AIO_ERROR)
2459 return aio_error(aiocb);
2460 #else
2461 errno = ENOSYS;
2462 return -1;
2463 #endif
2466 /*******************************************************************
2467 An aio_fsync wrapper that will deal with 64-bit sizes.
2468 ********************************************************************/
2470 int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2472 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_FSYNC64)
2473 return aio_fsync64(op, aiocb);
2474 #elif defined(HAVE_AIO_FSYNC)
2475 return aio_fsync(op, aiocb);
2476 #else
2477 errno = ENOSYS;
2478 return -1;
2479 #endif
2482 /*******************************************************************
2483 An aio_fsync wrapper that will deal with 64-bit sizes.
2484 ********************************************************************/
2486 int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2488 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_SUSPEND64)
2489 return aio_suspend64(cblist, n, timeout);
2490 #elif defined(HAVE_AIO_FSYNC)
2491 return aio_suspend(cblist, n, timeout);
2492 #else
2493 errno = ENOSYS;
2494 return -1;
2495 #endif
2497 #else /* !WITH_AIO */
2499 int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2501 errno = ENOSYS;
2502 return -1;
2505 int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2507 errno = ENOSYS;
2508 return -1;
2511 ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2513 errno = ENOSYS;
2514 return -1;
2517 int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2519 errno = ENOSYS;
2520 return -1;
2523 int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2525 errno = ENOSYS;
2526 return -1;
2529 int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2531 errno = ENOSYS;
2532 return -1;
2535 int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2537 errno = ENOSYS;
2538 return -1;
2540 #endif /* WITH_AIO */
2542 int sys_getpeereid( int s, uid_t *uid)
2544 #if defined(HAVE_PEERCRED)
2545 struct ucred cred;
2546 socklen_t cred_len = sizeof(struct ucred);
2547 int ret;
2549 ret = getsockopt(s, SOL_SOCKET, SO_PEERCRED, (void *)&cred, &cred_len);
2550 if (ret != 0) {
2551 return -1;
2554 if (cred_len != sizeof(struct ucred)) {
2555 errno = EINVAL;
2556 return -1;
2559 *uid = cred.uid;
2560 return 0;
2561 #else
2562 errno = ENOSYS;
2563 return -1;
2564 #endif
2567 int sys_getnameinfo(const struct sockaddr *psa,
2568 socklen_t salen,
2569 char *host,
2570 size_t hostlen,
2571 char *service,
2572 size_t servlen,
2573 int flags)
2576 * For Solaris we must make sure salen is the
2577 * correct length for the incoming sa_family.
2580 if (salen == sizeof(struct sockaddr_storage)) {
2581 salen = sizeof(struct sockaddr_in);
2582 #if defined(HAVE_IPV6)
2583 if (psa->sa_family == AF_INET6) {
2584 salen = sizeof(struct sockaddr_in6);
2586 #endif
2588 return getnameinfo(psa, salen, host, hostlen, service, servlen, flags);
2591 int sys_connect(int fd, const struct sockaddr * addr)
2593 socklen_t salen = -1;
2595 if (addr->sa_family == AF_INET) {
2596 salen = sizeof(struct sockaddr_in);
2597 } else if (addr->sa_family == AF_UNIX) {
2598 salen = sizeof(struct sockaddr_un);
2600 #if defined(HAVE_IPV6)
2601 else if (addr->sa_family == AF_INET6) {
2602 salen = sizeof(struct sockaddr_in6);
2604 #endif
2606 return connect(fd, addr, salen);