s4:provision Inline 'ldap_backend_shutdown' for clarity
[Samba.git] / source3 / lib / system.c
blobf9cd4a2355a114a082dbe898c2ab2f072b4e7168
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)
461 if (S_ISDIR(pst->st_mode) && lp_fake_dir_create_times()) {
462 dst->st_ex_btime.tv_sec = 315493200L; /* 1/1/1980 */
463 dst->st_ex_btime.tv_nsec = 0;
466 dst->st_ex_calculated_birthtime = false;
468 #if defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC)
469 dst->st_ex_btime = pst->st_birthtimespec;
470 #elif defined(HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC)
471 dst->st_ex_btime.tv_sec = pst->st_birthtime;
472 dst->st_ex_btime.tv_nsec = pst->st_birthtimenspec;
473 #elif defined(HAVE_STRUCT_STAT_ST_BIRTHTIME)
474 dst->st_ex_btime.tv_sec = pst->st_birthtime;
475 dst->st_ex_btime.tv_nsec = 0;
476 #else
477 dst->st_ex_btime = calc_create_time_stat(pst);
478 dst->st_ex_calculated_birthtime = true;
479 #endif
481 /* Deal with systems that don't initialize birthtime correctly.
482 * Pointed out by SATOH Fumiyasu <fumiyas@osstech.jp>.
484 if (null_timespec(dst->st_ex_btime)) {
485 dst->st_ex_btime = calc_create_time_stat(pst);
486 dst->st_ex_calculated_birthtime = true;
490 /****************************************************************************
491 If we update a timestamp in a stat_ex struct we may have to recalculate
492 the birthtime. For now only implement this for write time, but we may
493 also need to do it for atime and ctime. JRA.
494 ****************************************************************************/
496 void update_stat_ex_mtime(struct stat_ex *dst,
497 struct timespec write_ts)
499 dst->st_ex_mtime = write_ts;
501 /* We may have to recalculate btime. */
502 if (dst->st_ex_calculated_birthtime) {
503 dst->st_ex_btime = calc_create_time_stat_ex(dst);
507 static void init_stat_ex_from_stat (struct stat_ex *dst,
508 const struct stat *src)
510 dst->st_ex_dev = src->st_dev;
511 dst->st_ex_ino = src->st_ino;
512 dst->st_ex_mode = src->st_mode;
513 dst->st_ex_nlink = src->st_nlink;
514 dst->st_ex_uid = src->st_uid;
515 dst->st_ex_gid = src->st_gid;
516 dst->st_ex_rdev = src->st_rdev;
517 dst->st_ex_size = src->st_size;
518 dst->st_ex_atime = get_atimespec(src);
519 dst->st_ex_mtime = get_mtimespec(src);
520 dst->st_ex_ctime = get_ctimespec(src);
521 make_create_timespec(src, dst);
522 dst->st_ex_blksize = src->st_blksize;
523 dst->st_ex_blocks = src->st_blocks;
525 #ifdef HAVE_STAT_ST_FLAGS
526 dst->st_ex_flags = src->st_flags;
527 #else
528 dst->st_ex_flags = 0;
529 #endif
532 /*******************************************************************
533 A stat() wrapper that will deal with 64 bit filesizes.
534 ********************************************************************/
536 int sys_stat(const char *fname,SMB_STRUCT_STAT *sbuf)
538 int ret;
539 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
540 ret = stat64(fname, sbuf);
541 #else
542 struct stat statbuf;
543 ret = stat(fname, &statbuf);
544 #endif
545 if (ret == 0) {
546 /* we always want directories to appear zero size */
547 if (S_ISDIR(statbuf.st_mode)) {
548 statbuf.st_size = 0;
550 init_stat_ex_from_stat(sbuf, &statbuf);
552 return ret;
555 /*******************************************************************
556 An fstat() wrapper that will deal with 64 bit filesizes.
557 ********************************************************************/
559 int sys_fstat(int fd,SMB_STRUCT_STAT *sbuf)
561 int ret;
562 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FSTAT64)
563 ret = fstat64(fd, sbuf);
564 #else
565 struct stat statbuf;
566 ret = fstat(fd, &statbuf);
567 #endif
568 if (ret == 0) {
569 /* we always want directories to appear zero size */
570 if (S_ISDIR(statbuf.st_mode)) {
571 statbuf.st_size = 0;
573 init_stat_ex_from_stat(sbuf, &statbuf);
575 return ret;
578 /*******************************************************************
579 An lstat() wrapper that will deal with 64 bit filesizes.
580 ********************************************************************/
582 int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf)
584 int ret;
585 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSTAT64)
586 ret = lstat64(fname, sbuf);
587 #else
588 struct stat statbuf;
589 ret = lstat(fname, &statbuf);
590 #endif
591 if (ret == 0) {
592 /* we always want directories to appear zero size */
593 if (S_ISDIR(statbuf.st_mode)) {
594 statbuf.st_size = 0;
596 init_stat_ex_from_stat(sbuf, &statbuf);
598 return ret;
601 /*******************************************************************
602 An ftruncate() wrapper that will deal with 64 bit filesizes.
603 ********************************************************************/
605 int sys_ftruncate(int fd, SMB_OFF_T offset)
607 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FTRUNCATE64)
608 return ftruncate64(fd, offset);
609 #else
610 return ftruncate(fd, offset);
611 #endif
614 /*******************************************************************
615 An lseek() wrapper that will deal with 64 bit filesizes.
616 ********************************************************************/
618 SMB_OFF_T sys_lseek(int fd, SMB_OFF_T offset, int whence)
620 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSEEK64)
621 return lseek64(fd, offset, whence);
622 #else
623 return lseek(fd, offset, whence);
624 #endif
627 /*******************************************************************
628 An fseek() wrapper that will deal with 64 bit filesizes.
629 ********************************************************************/
631 int sys_fseek(FILE *fp, SMB_OFF_T offset, int whence)
633 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEK64)
634 return fseek64(fp, offset, whence);
635 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEKO64)
636 return fseeko64(fp, offset, whence);
637 #else
638 return fseek(fp, offset, whence);
639 #endif
642 /*******************************************************************
643 An ftell() wrapper that will deal with 64 bit filesizes.
644 ********************************************************************/
646 SMB_OFF_T sys_ftell(FILE *fp)
648 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELL64)
649 return (SMB_OFF_T)ftell64(fp);
650 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELLO64)
651 return (SMB_OFF_T)ftello64(fp);
652 #else
653 return (SMB_OFF_T)ftell(fp);
654 #endif
657 /*******************************************************************
658 A creat() wrapper that will deal with 64 bit filesizes.
659 ********************************************************************/
661 int sys_creat(const char *path, mode_t mode)
663 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CREAT64)
664 return creat64(path, mode);
665 #else
667 * If creat64 isn't defined then ensure we call a potential open64.
668 * JRA.
670 return sys_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
671 #endif
674 /*******************************************************************
675 An open() wrapper that will deal with 64 bit filesizes.
676 ********************************************************************/
678 int sys_open(const char *path, int oflag, mode_t mode)
680 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPEN64)
681 return open64(path, oflag, mode);
682 #else
683 return open(path, oflag, mode);
684 #endif
687 /*******************************************************************
688 An fopen() wrapper that will deal with 64 bit filesizes.
689 ********************************************************************/
691 FILE *sys_fopen(const char *path, const char *type)
693 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FOPEN64)
694 return fopen64(path, type);
695 #else
696 return fopen(path, type);
697 #endif
701 /*******************************************************************
702 A flock() wrapper that will perform the kernel flock.
703 ********************************************************************/
705 void kernel_flock(int fd, uint32 share_mode, uint32 access_mask)
707 #if HAVE_KERNEL_SHARE_MODES
708 int kernel_mode = 0;
709 if (share_mode == FILE_SHARE_WRITE) {
710 kernel_mode = LOCK_MAND|LOCK_WRITE;
711 } else if (share_mode == FILE_SHARE_READ) {
712 kernel_mode = LOCK_MAND|LOCK_READ;
713 } else if (share_mode == FILE_SHARE_NONE) {
714 kernel_mode = LOCK_MAND;
716 if (kernel_mode) {
717 flock(fd, kernel_mode);
719 #endif
725 /*******************************************************************
726 An opendir wrapper that will deal with 64 bit filesizes.
727 ********************************************************************/
729 SMB_STRUCT_DIR *sys_opendir(const char *name)
731 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPENDIR64)
732 return opendir64(name);
733 #else
734 return opendir(name);
735 #endif
738 /*******************************************************************
739 A readdir wrapper that will deal with 64 bit filesizes.
740 ********************************************************************/
742 SMB_STRUCT_DIRENT *sys_readdir(SMB_STRUCT_DIR *dirp)
744 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_READDIR64)
745 return readdir64(dirp);
746 #else
747 return readdir(dirp);
748 #endif
751 /*******************************************************************
752 A seekdir wrapper that will deal with 64 bit filesizes.
753 ********************************************************************/
755 void sys_seekdir(SMB_STRUCT_DIR *dirp, long offset)
757 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_SEEKDIR64)
758 seekdir64(dirp, offset);
759 #else
760 seekdir(dirp, offset);
761 #endif
764 /*******************************************************************
765 A telldir wrapper that will deal with 64 bit filesizes.
766 ********************************************************************/
768 long sys_telldir(SMB_STRUCT_DIR *dirp)
770 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_TELLDIR64)
771 return (long)telldir64(dirp);
772 #else
773 return (long)telldir(dirp);
774 #endif
777 /*******************************************************************
778 A rewinddir wrapper that will deal with 64 bit filesizes.
779 ********************************************************************/
781 void sys_rewinddir(SMB_STRUCT_DIR *dirp)
783 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_REWINDDIR64)
784 rewinddir64(dirp);
785 #else
786 rewinddir(dirp);
787 #endif
790 /*******************************************************************
791 A close wrapper that will deal with 64 bit filesizes.
792 ********************************************************************/
794 int sys_closedir(SMB_STRUCT_DIR *dirp)
796 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CLOSEDIR64)
797 return closedir64(dirp);
798 #else
799 return closedir(dirp);
800 #endif
803 /*******************************************************************
804 An mknod() wrapper that will deal with 64 bit filesizes.
805 ********************************************************************/
807 int sys_mknod(const char *path, mode_t mode, SMB_DEV_T dev)
809 #if defined(HAVE_MKNOD) || defined(HAVE_MKNOD64)
810 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_MKNOD64) && defined(HAVE_DEV64_T)
811 return mknod64(path, mode, dev);
812 #else
813 return mknod(path, mode, dev);
814 #endif
815 #else
816 /* No mknod system call. */
817 errno = ENOSYS;
818 return -1;
819 #endif
822 /*******************************************************************
823 The wait() calls vary between systems
824 ********************************************************************/
826 int sys_waitpid(pid_t pid,int *status,int options)
828 #ifdef HAVE_WAITPID
829 return waitpid(pid,status,options);
830 #else /* HAVE_WAITPID */
831 return wait4(pid, status, options, NULL);
832 #endif /* HAVE_WAITPID */
835 /*******************************************************************
836 System wrapper for getwd
837 ********************************************************************/
839 char *sys_getwd(char *s)
841 char *wd;
842 #ifdef HAVE_GETCWD
843 wd = (char *)getcwd(s, PATH_MAX);
844 #else
845 wd = (char *)getwd(s);
846 #endif
847 return wd;
850 #if defined(HAVE_POSIX_CAPABILITIES)
852 /**************************************************************************
853 Try and abstract process capabilities (for systems that have them).
854 ****************************************************************************/
856 /* Set the POSIX capabilities needed for the given purpose into the effective
857 * capability set of the current process. Make sure they are always removed
858 * from the inheritable set, because there is no circumstance in which our
859 * children should inherit our elevated privileges.
861 static bool set_process_capability(enum smbd_capability capability,
862 bool enable)
864 cap_value_t cap_vals[2] = {0};
865 int num_cap_vals = 0;
867 cap_t cap;
869 #if defined(HAVE_PRCTL) && defined(PR_GET_KEEPCAPS) && defined(PR_SET_KEEPCAPS)
870 /* On Linux, make sure that any capabilities we grab are sticky
871 * across UID changes. We expect that this would allow us to keep both
872 * the effective and permitted capability sets, but as of circa 2.6.16,
873 * only the permitted set is kept. It is a bug (which we work around)
874 * that the effective set is lost, but we still require the effective
875 * set to be kept.
877 if (!prctl(PR_GET_KEEPCAPS)) {
878 prctl(PR_SET_KEEPCAPS, 1);
880 #endif
882 cap = cap_get_proc();
883 if (cap == NULL) {
884 DEBUG(0,("set_process_capability: cap_get_proc failed: %s\n",
885 strerror(errno)));
886 return False;
889 switch (capability) {
890 case KERNEL_OPLOCK_CAPABILITY:
891 #ifdef CAP_NETWORK_MGT
892 /* IRIX has CAP_NETWORK_MGT for oplocks. */
893 cap_vals[num_cap_vals++] = CAP_NETWORK_MGT;
894 #endif
895 break;
896 case DMAPI_ACCESS_CAPABILITY:
897 #ifdef CAP_DEVICE_MGT
898 /* IRIX has CAP_DEVICE_MGT for DMAPI access. */
899 cap_vals[num_cap_vals++] = CAP_DEVICE_MGT;
900 #elif CAP_MKNOD
901 /* Linux has CAP_MKNOD for DMAPI access. */
902 cap_vals[num_cap_vals++] = CAP_MKNOD;
903 #endif
904 break;
905 case LEASE_CAPABILITY:
906 #ifdef CAP_LEASE
907 cap_vals[num_cap_vals++] = CAP_LEASE;
908 #endif
909 break;
912 SMB_ASSERT(num_cap_vals <= ARRAY_SIZE(cap_vals));
914 if (num_cap_vals == 0) {
915 cap_free(cap);
916 return True;
919 cap_set_flag(cap, CAP_EFFECTIVE, num_cap_vals, cap_vals,
920 enable ? CAP_SET : CAP_CLEAR);
922 /* We never want to pass capabilities down to our children, so make
923 * sure they are not inherited.
925 cap_set_flag(cap, CAP_INHERITABLE, num_cap_vals, cap_vals, CAP_CLEAR);
927 if (cap_set_proc(cap) == -1) {
928 DEBUG(0, ("set_process_capability: cap_set_proc failed: %s\n",
929 strerror(errno)));
930 cap_free(cap);
931 return False;
934 cap_free(cap);
935 return True;
938 #endif /* HAVE_POSIX_CAPABILITIES */
940 /****************************************************************************
941 Gain the oplock capability from the kernel if possible.
942 ****************************************************************************/
944 void set_effective_capability(enum smbd_capability capability)
946 #if defined(HAVE_POSIX_CAPABILITIES)
947 set_process_capability(capability, True);
948 #endif /* HAVE_POSIX_CAPABILITIES */
951 void drop_effective_capability(enum smbd_capability capability)
953 #if defined(HAVE_POSIX_CAPABILITIES)
954 set_process_capability(capability, False);
955 #endif /* HAVE_POSIX_CAPABILITIES */
958 /**************************************************************************
959 Wrapper for random().
960 ****************************************************************************/
962 long sys_random(void)
964 #if defined(HAVE_RANDOM)
965 return (long)random();
966 #elif defined(HAVE_RAND)
967 return (long)rand();
968 #else
969 DEBUG(0,("Error - no random function available !\n"));
970 exit(1);
971 #endif
974 /**************************************************************************
975 Wrapper for srandom().
976 ****************************************************************************/
978 void sys_srandom(unsigned int seed)
980 #if defined(HAVE_SRANDOM)
981 srandom(seed);
982 #elif defined(HAVE_SRAND)
983 srand(seed);
984 #else
985 DEBUG(0,("Error - no srandom function available !\n"));
986 exit(1);
987 #endif
990 /**************************************************************************
991 Returns equivalent to NGROUPS_MAX - using sysconf if needed.
992 ****************************************************************************/
994 int groups_max(void)
996 #if defined(SYSCONF_SC_NGROUPS_MAX)
997 int ret = sysconf(_SC_NGROUPS_MAX);
998 return (ret == -1) ? NGROUPS_MAX : ret;
999 #else
1000 return NGROUPS_MAX;
1001 #endif
1004 /**************************************************************************
1005 Wrap setgroups and getgroups for systems that declare getgroups() as
1006 returning an array of gid_t, but actuall return an array of int.
1007 ****************************************************************************/
1009 #if defined(HAVE_BROKEN_GETGROUPS)
1010 static int sys_broken_getgroups(int setlen, gid_t *gidset)
1012 GID_T gid;
1013 GID_T *group_list;
1014 int i, ngroups;
1016 if(setlen == 0) {
1017 return getgroups(setlen, &gid);
1021 * Broken case. We need to allocate a
1022 * GID_T array of size setlen.
1025 if(setlen < 0) {
1026 errno = EINVAL;
1027 return -1;
1030 if (setlen == 0)
1031 setlen = groups_max();
1033 if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
1034 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
1035 return -1;
1038 if((ngroups = getgroups(setlen, group_list)) < 0) {
1039 int saved_errno = errno;
1040 SAFE_FREE(group_list);
1041 errno = saved_errno;
1042 return -1;
1045 for(i = 0; i < ngroups; i++)
1046 gidset[i] = (gid_t)group_list[i];
1048 SAFE_FREE(group_list);
1049 return ngroups;
1052 static int sys_broken_setgroups(int setlen, gid_t *gidset)
1054 GID_T *group_list;
1055 int i ;
1057 if (setlen == 0)
1058 return 0 ;
1060 if (setlen < 0 || setlen > groups_max()) {
1061 errno = EINVAL;
1062 return -1;
1066 * Broken case. We need to allocate a
1067 * GID_T array of size setlen.
1070 if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
1071 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
1072 return -1;
1075 for(i = 0; i < setlen; i++)
1076 group_list[i] = (GID_T) gidset[i];
1078 if(setgroups(setlen, group_list) != 0) {
1079 int saved_errno = errno;
1080 SAFE_FREE(group_list);
1081 errno = saved_errno;
1082 return -1;
1085 SAFE_FREE(group_list);
1086 return 0 ;
1089 #endif /* HAVE_BROKEN_GETGROUPS */
1091 /* This is a list of systems that require the first GID passed to setgroups(2)
1092 * to be the effective GID. If your system is one of these, add it here.
1094 #if defined (FREEBSD) || defined (DARWINOS)
1095 #define USE_BSD_SETGROUPS
1096 #endif
1098 #if defined(USE_BSD_SETGROUPS)
1099 /* Depending on the particular BSD implementation, the first GID that is
1100 * passed to setgroups(2) will either be ignored or will set the credential's
1101 * effective GID. In either case, the right thing to do is to guarantee that
1102 * gidset[0] is the effective GID.
1104 static int sys_bsd_setgroups(gid_t primary_gid, int setlen, const gid_t *gidset)
1106 gid_t *new_gidset = NULL;
1107 int max;
1108 int ret;
1110 /* setgroups(2) will fail with EINVAL if we pass too many groups. */
1111 max = groups_max();
1113 /* No group list, just make sure we are setting the efective GID. */
1114 if (setlen == 0) {
1115 return setgroups(1, &primary_gid);
1118 /* If the primary gid is not the first array element, grow the array
1119 * and insert it at the front.
1121 if (gidset[0] != primary_gid) {
1122 new_gidset = SMB_MALLOC_ARRAY(gid_t, setlen + 1);
1123 if (new_gidset == NULL) {
1124 return -1;
1127 memcpy(new_gidset + 1, gidset, (setlen * sizeof(gid_t)));
1128 new_gidset[0] = primary_gid;
1129 setlen++;
1132 if (setlen > max) {
1133 DEBUG(3, ("forced to truncate group list from %d to %d\n",
1134 setlen, max));
1135 setlen = max;
1138 #if defined(HAVE_BROKEN_GETGROUPS)
1139 ret = sys_broken_setgroups(setlen, new_gidset ? new_gidset : gidset);
1140 #else
1141 ret = setgroups(setlen, new_gidset ? new_gidset : gidset);
1142 #endif
1144 if (new_gidset) {
1145 int errsav = errno;
1146 SAFE_FREE(new_gidset);
1147 errno = errsav;
1150 return ret;
1153 #endif /* USE_BSD_SETGROUPS */
1155 /**************************************************************************
1156 Wrapper for getgroups. Deals with broken (int) case.
1157 ****************************************************************************/
1159 int sys_getgroups(int setlen, gid_t *gidset)
1161 #if defined(HAVE_BROKEN_GETGROUPS)
1162 return sys_broken_getgroups(setlen, gidset);
1163 #else
1164 return getgroups(setlen, gidset);
1165 #endif
1168 /**************************************************************************
1169 Wrapper for setgroups. Deals with broken (int) case and BSD case.
1170 ****************************************************************************/
1172 int sys_setgroups(gid_t UNUSED(primary_gid), int setlen, gid_t *gidset)
1174 #if !defined(HAVE_SETGROUPS)
1175 errno = ENOSYS;
1176 return -1;
1177 #endif /* HAVE_SETGROUPS */
1179 #if defined(USE_BSD_SETGROUPS)
1180 return sys_bsd_setgroups(primary_gid, setlen, gidset);
1181 #elif defined(HAVE_BROKEN_GETGROUPS)
1182 return sys_broken_setgroups(setlen, gidset);
1183 #else
1184 return setgroups(setlen, gidset);
1185 #endif
1188 /**************************************************************************
1189 Wrappers for setpwent(), getpwent() and endpwent()
1190 ****************************************************************************/
1192 void sys_setpwent(void)
1194 setpwent();
1197 struct passwd *sys_getpwent(void)
1199 return getpwent();
1202 void sys_endpwent(void)
1204 endpwent();
1207 /**************************************************************************
1208 Wrappers for getpwnam(), getpwuid(), getgrnam(), getgrgid()
1209 ****************************************************************************/
1212 struct passwd *sys_getpwnam(const char *name)
1214 return getpwnam(name);
1217 struct passwd *sys_getpwuid(uid_t uid)
1219 return getpwuid(uid);
1222 struct group *sys_getgrnam(const char *name)
1224 return getgrnam(name);
1227 struct group *sys_getgrgid(gid_t gid)
1229 return getgrgid(gid);
1232 /**************************************************************************
1233 Extract a command into an arg list.
1234 ****************************************************************************/
1236 static char **extract_args(TALLOC_CTX *mem_ctx, const char *command)
1238 char *trunc_cmd;
1239 char *saveptr;
1240 char *ptr;
1241 int argcl;
1242 char **argl = NULL;
1243 int i;
1245 if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1246 DEBUG(0, ("talloc failed\n"));
1247 goto nomem;
1250 if(!(ptr = strtok_r(trunc_cmd, " \t", &saveptr))) {
1251 TALLOC_FREE(trunc_cmd);
1252 errno = EINVAL;
1253 return NULL;
1257 * Count the args.
1260 for( argcl = 1; ptr; ptr = strtok_r(NULL, " \t", &saveptr))
1261 argcl++;
1263 TALLOC_FREE(trunc_cmd);
1265 if (!(argl = TALLOC_ARRAY(mem_ctx, char *, argcl + 1))) {
1266 goto nomem;
1270 * Now do the extraction.
1273 if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1274 goto nomem;
1277 ptr = strtok_r(trunc_cmd, " \t", &saveptr);
1278 i = 0;
1280 if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1281 goto nomem;
1284 while((ptr = strtok_r(NULL, " \t", &saveptr)) != NULL) {
1286 if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1287 goto nomem;
1291 argl[i++] = NULL;
1292 return argl;
1294 nomem:
1295 DEBUG(0, ("talloc failed\n"));
1296 TALLOC_FREE(trunc_cmd);
1297 TALLOC_FREE(argl);
1298 errno = ENOMEM;
1299 return NULL;
1302 /**************************************************************************
1303 Wrapper for popen. Safer as it doesn't search a path.
1304 Modified from the glibc sources.
1305 modified by tridge to return a file descriptor. We must kick our FILE* habit
1306 ****************************************************************************/
1308 typedef struct _popen_list
1310 int fd;
1311 pid_t child_pid;
1312 struct _popen_list *next;
1313 } popen_list;
1315 static popen_list *popen_chain;
1317 int sys_popen(const char *command)
1319 int parent_end, child_end;
1320 int pipe_fds[2];
1321 popen_list *entry = NULL;
1322 char **argl = NULL;
1324 if (pipe(pipe_fds) < 0)
1325 return -1;
1327 parent_end = pipe_fds[0];
1328 child_end = pipe_fds[1];
1330 if (!*command) {
1331 errno = EINVAL;
1332 goto err_exit;
1335 if((entry = SMB_MALLOC_P(popen_list)) == NULL)
1336 goto err_exit;
1338 ZERO_STRUCTP(entry);
1341 * Extract the command and args into a NULL terminated array.
1344 if(!(argl = extract_args(NULL, command)))
1345 goto err_exit;
1347 entry->child_pid = sys_fork();
1349 if (entry->child_pid == -1) {
1350 goto err_exit;
1353 if (entry->child_pid == 0) {
1356 * Child !
1359 int child_std_end = STDOUT_FILENO;
1360 popen_list *p;
1362 close(parent_end);
1363 if (child_end != child_std_end) {
1364 dup2 (child_end, child_std_end);
1365 close (child_end);
1369 * POSIX.2: "popen() shall ensure that any streams from previous
1370 * popen() calls that remain open in the parent process are closed
1371 * in the new child process."
1374 for (p = popen_chain; p; p = p->next)
1375 close(p->fd);
1377 execv(argl[0], argl);
1378 _exit (127);
1382 * Parent.
1385 close (child_end);
1386 TALLOC_FREE(argl);
1388 /* Link into popen_chain. */
1389 entry->next = popen_chain;
1390 popen_chain = entry;
1391 entry->fd = parent_end;
1393 return entry->fd;
1395 err_exit:
1397 SAFE_FREE(entry);
1398 SAFE_FREE(argl);
1399 close(pipe_fds[0]);
1400 close(pipe_fds[1]);
1401 return -1;
1404 /**************************************************************************
1405 Wrapper for pclose. Modified from the glibc sources.
1406 ****************************************************************************/
1408 int sys_pclose(int fd)
1410 int wstatus;
1411 popen_list **ptr = &popen_chain;
1412 popen_list *entry = NULL;
1413 pid_t wait_pid;
1414 int status = -1;
1416 /* Unlink from popen_chain. */
1417 for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
1418 if ((*ptr)->fd == fd) {
1419 entry = *ptr;
1420 *ptr = (*ptr)->next;
1421 status = 0;
1422 break;
1426 if (status < 0 || close(entry->fd) < 0)
1427 return -1;
1430 * As Samba is catching and eating child process
1431 * exits we don't really care about the child exit
1432 * code, a -1 with errno = ECHILD will do fine for us.
1435 do {
1436 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
1437 } while (wait_pid == -1 && errno == EINTR);
1439 SAFE_FREE(entry);
1441 if (wait_pid == -1)
1442 return -1;
1443 return wstatus;
1446 /**************************************************************************
1447 Wrapper for Admin Logs.
1448 ****************************************************************************/
1450 void sys_adminlog(int priority, const char *format_str, ...)
1452 va_list ap;
1453 int ret;
1454 char *msgbuf = NULL;
1456 va_start( ap, format_str );
1457 ret = vasprintf( &msgbuf, format_str, ap );
1458 va_end( ap );
1460 if (ret == -1)
1461 return;
1463 #if defined(HAVE_SYSLOG)
1464 syslog( priority, "%s", msgbuf );
1465 #else
1466 DEBUG(0,("%s", msgbuf ));
1467 #endif
1468 SAFE_FREE(msgbuf);
1471 /******** Solaris EA helper function prototypes ********/
1472 #ifdef HAVE_ATTROPEN
1473 #define SOLARIS_ATTRMODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP
1474 static int solaris_write_xattr(int attrfd, const char *value, size_t size);
1475 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size);
1476 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size);
1477 static int solaris_unlinkat(int attrdirfd, const char *name);
1478 static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode);
1479 static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode);
1480 #endif
1482 /**************************************************************************
1483 Wrappers for extented attribute calls. Based on the Linux package with
1484 support for IRIX and (Net|Free)BSD also. Expand as other systems have them.
1485 ****************************************************************************/
1487 ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t size)
1489 #if defined(HAVE_GETXATTR)
1490 #ifndef XATTR_ADD_OPT
1491 return getxattr(path, name, value, size);
1492 #else
1493 int options = 0;
1494 return getxattr(path, name, value, size, 0, options);
1495 #endif
1496 #elif defined(HAVE_GETEA)
1497 return getea(path, name, value, size);
1498 #elif defined(HAVE_EXTATTR_GET_FILE)
1499 char *s;
1500 ssize_t retval;
1501 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1502 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1503 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1505 * The BSD implementation has a nasty habit of silently truncating
1506 * the returned value to the size of the buffer, so we have to check
1507 * that the buffer is large enough to fit the returned value.
1509 if((retval=extattr_get_file(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1510 if(retval > size) {
1511 errno = ERANGE;
1512 return -1;
1514 if((retval=extattr_get_file(path, attrnamespace, attrname, value, size)) >= 0)
1515 return retval;
1518 DEBUG(10,("sys_getxattr: extattr_get_file() failed with: %s\n", strerror(errno)));
1519 return -1;
1520 #elif defined(HAVE_ATTR_GET)
1521 int retval, flags = 0;
1522 int valuelength = (int)size;
1523 char *attrname = strchr(name,'.') + 1;
1525 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1527 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1529 return retval ? retval : valuelength;
1530 #elif defined(HAVE_ATTROPEN)
1531 ssize_t ret = -1;
1532 int attrfd = solaris_attropen(path, name, O_RDONLY, 0);
1533 if (attrfd >= 0) {
1534 ret = solaris_read_xattr(attrfd, value, size);
1535 close(attrfd);
1537 return ret;
1538 #else
1539 errno = ENOSYS;
1540 return -1;
1541 #endif
1544 ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t size)
1546 #if defined(HAVE_LGETXATTR)
1547 return lgetxattr(path, name, value, size);
1548 #elif defined(HAVE_GETXATTR) && defined(XATTR_ADD_OPT)
1549 int options = XATTR_NOFOLLOW;
1550 return getxattr(path, name, value, size, 0, options);
1551 #elif defined(HAVE_LGETEA)
1552 return lgetea(path, name, value, size);
1553 #elif defined(HAVE_EXTATTR_GET_LINK)
1554 char *s;
1555 ssize_t retval;
1556 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1557 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1558 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1560 if((retval=extattr_get_link(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1561 if(retval > size) {
1562 errno = ERANGE;
1563 return -1;
1565 if((retval=extattr_get_link(path, attrnamespace, attrname, value, size)) >= 0)
1566 return retval;
1569 DEBUG(10,("sys_lgetxattr: extattr_get_link() failed with: %s\n", strerror(errno)));
1570 return -1;
1571 #elif defined(HAVE_ATTR_GET)
1572 int retval, flags = ATTR_DONTFOLLOW;
1573 int valuelength = (int)size;
1574 char *attrname = strchr(name,'.') + 1;
1576 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1578 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1580 return retval ? retval : valuelength;
1581 #elif defined(HAVE_ATTROPEN)
1582 ssize_t ret = -1;
1583 int attrfd = solaris_attropen(path, name, O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1584 if (attrfd >= 0) {
1585 ret = solaris_read_xattr(attrfd, value, size);
1586 close(attrfd);
1588 return ret;
1589 #else
1590 errno = ENOSYS;
1591 return -1;
1592 #endif
1595 ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size)
1597 #if defined(HAVE_FGETXATTR)
1598 #ifndef XATTR_ADD_OPT
1599 return fgetxattr(filedes, name, value, size);
1600 #else
1601 int options = 0;
1602 return fgetxattr(filedes, name, value, size, 0, options);
1603 #endif
1604 #elif defined(HAVE_FGETEA)
1605 return fgetea(filedes, name, value, size);
1606 #elif defined(HAVE_EXTATTR_GET_FD)
1607 char *s;
1608 ssize_t retval;
1609 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1610 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1611 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1613 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0)) >= 0) {
1614 if(retval > size) {
1615 errno = ERANGE;
1616 return -1;
1618 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, value, size)) >= 0)
1619 return retval;
1622 DEBUG(10,("sys_fgetxattr: extattr_get_fd() failed with: %s\n", strerror(errno)));
1623 return -1;
1624 #elif defined(HAVE_ATTR_GETF)
1625 int retval, flags = 0;
1626 int valuelength = (int)size;
1627 char *attrname = strchr(name,'.') + 1;
1629 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1631 retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags);
1633 return retval ? retval : valuelength;
1634 #elif defined(HAVE_ATTROPEN)
1635 ssize_t ret = -1;
1636 int attrfd = solaris_openat(filedes, name, O_RDONLY|O_XATTR, 0);
1637 if (attrfd >= 0) {
1638 ret = solaris_read_xattr(attrfd, value, size);
1639 close(attrfd);
1641 return ret;
1642 #else
1643 errno = ENOSYS;
1644 return -1;
1645 #endif
1648 #if defined(HAVE_EXTATTR_LIST_FILE)
1650 #define EXTATTR_PREFIX(s) (s), (sizeof((s))-1)
1652 static struct {
1653 int space;
1654 const char *name;
1655 size_t len;
1657 extattr[] = {
1658 { EXTATTR_NAMESPACE_SYSTEM, EXTATTR_PREFIX("system.") },
1659 { EXTATTR_NAMESPACE_USER, EXTATTR_PREFIX("user.") },
1662 typedef union {
1663 const char *path;
1664 int filedes;
1665 } extattr_arg;
1667 static ssize_t bsd_attr_list (int type, extattr_arg arg, char *list, size_t size)
1669 ssize_t list_size, total_size = 0;
1670 int i, t, len;
1671 char *buf;
1672 /* Iterate through extattr(2) namespaces */
1673 for(t = 0; t < (sizeof(extattr)/sizeof(extattr[0])); t++) {
1674 switch(type) {
1675 #if defined(HAVE_EXTATTR_LIST_FILE)
1676 case 0:
1677 list_size = extattr_list_file(arg.path, extattr[t].space, list, size);
1678 break;
1679 #endif
1680 #if defined(HAVE_EXTATTR_LIST_LINK)
1681 case 1:
1682 list_size = extattr_list_link(arg.path, extattr[t].space, list, size);
1683 break;
1684 #endif
1685 #if defined(HAVE_EXTATTR_LIST_FD)
1686 case 2:
1687 list_size = extattr_list_fd(arg.filedes, extattr[t].space, list, size);
1688 break;
1689 #endif
1690 default:
1691 errno = ENOSYS;
1692 return -1;
1694 /* Some error happend. Errno should be set by the previous call */
1695 if(list_size < 0)
1696 return -1;
1697 /* No attributes */
1698 if(list_size == 0)
1699 continue;
1700 /* XXX: Call with an empty buffer may be used to calculate
1701 necessary buffer size. Unfortunately, we can't say, how
1702 many attributes were returned, so here is the potential
1703 problem with the emulation.
1705 if(list == NULL) {
1706 /* Take the worse case of one char attribute names -
1707 two bytes per name plus one more for sanity.
1709 total_size += list_size + (list_size/2 + 1)*extattr[t].len;
1710 continue;
1712 /* Count necessary offset to fit namespace prefixes */
1713 len = 0;
1714 for(i = 0; i < list_size; i += list[i] + 1)
1715 len += extattr[t].len;
1717 total_size += list_size + len;
1718 /* Buffer is too small to fit the results */
1719 if(total_size > size) {
1720 errno = ERANGE;
1721 return -1;
1723 /* Shift results back, so we can prepend prefixes */
1724 buf = memmove(list + len, list, list_size);
1726 for(i = 0; i < list_size; i += len + 1) {
1727 len = buf[i];
1728 strncpy(list, extattr[t].name, extattr[t].len + 1);
1729 list += extattr[t].len;
1730 strncpy(list, buf + i + 1, len);
1731 list[len] = '\0';
1732 list += len + 1;
1734 size -= total_size;
1736 return total_size;
1739 #endif
1741 #if defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1742 static char attr_buffer[ATTR_MAX_VALUELEN];
1744 static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags)
1746 int retval = 0, index;
1747 attrlist_cursor_t *cursor = 0;
1748 int total_size = 0;
1749 attrlist_t * al = (attrlist_t *)attr_buffer;
1750 attrlist_ent_t *ae;
1751 size_t ent_size, left = size;
1752 char *bp = list;
1754 while (True) {
1755 if (filedes)
1756 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1757 else
1758 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1759 if (retval) break;
1760 for (index = 0; index < al->al_count; index++) {
1761 ae = ATTR_ENTRY(attr_buffer, index);
1762 ent_size = strlen(ae->a_name) + sizeof("user.");
1763 if (left >= ent_size) {
1764 strncpy(bp, "user.", sizeof("user."));
1765 strncat(bp, ae->a_name, ent_size - sizeof("user."));
1766 bp += ent_size;
1767 left -= ent_size;
1768 } else if (size) {
1769 errno = ERANGE;
1770 retval = -1;
1771 break;
1773 total_size += ent_size;
1775 if (al->al_more == 0) break;
1777 if (retval == 0) {
1778 flags |= ATTR_ROOT;
1779 cursor = 0;
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("system.");
1789 if (left >= ent_size) {
1790 strncpy(bp, "system.", sizeof("system."));
1791 strncat(bp, ae->a_name, ent_size - sizeof("system."));
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;
1804 return (ssize_t)(retval ? retval : total_size);
1807 #endif
1809 ssize_t sys_listxattr (const char *path, char *list, size_t size)
1811 #if defined(HAVE_LISTXATTR)
1812 #ifndef XATTR_ADD_OPT
1813 return listxattr(path, list, size);
1814 #else
1815 int options = 0;
1816 return listxattr(path, list, size, options);
1817 #endif
1818 #elif defined(HAVE_LISTEA)
1819 return listea(path, list, size);
1820 #elif defined(HAVE_EXTATTR_LIST_FILE)
1821 extattr_arg arg;
1822 arg.path = path;
1823 return bsd_attr_list(0, arg, list, size);
1824 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1825 return irix_attr_list(path, 0, list, size, 0);
1826 #elif defined(HAVE_ATTROPEN)
1827 ssize_t ret = -1;
1828 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
1829 if (attrdirfd >= 0) {
1830 ret = solaris_list_xattr(attrdirfd, list, size);
1831 close(attrdirfd);
1833 return ret;
1834 #else
1835 errno = ENOSYS;
1836 return -1;
1837 #endif
1840 ssize_t sys_llistxattr (const char *path, char *list, size_t size)
1842 #if defined(HAVE_LLISTXATTR)
1843 return llistxattr(path, list, size);
1844 #elif defined(HAVE_LISTXATTR) && defined(XATTR_ADD_OPT)
1845 int options = XATTR_NOFOLLOW;
1846 return listxattr(path, list, size, options);
1847 #elif defined(HAVE_LLISTEA)
1848 return llistea(path, list, size);
1849 #elif defined(HAVE_EXTATTR_LIST_LINK)
1850 extattr_arg arg;
1851 arg.path = path;
1852 return bsd_attr_list(1, arg, list, size);
1853 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1854 return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW);
1855 #elif defined(HAVE_ATTROPEN)
1856 ssize_t ret = -1;
1857 int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1858 if (attrdirfd >= 0) {
1859 ret = solaris_list_xattr(attrdirfd, list, size);
1860 close(attrdirfd);
1862 return ret;
1863 #else
1864 errno = ENOSYS;
1865 return -1;
1866 #endif
1869 ssize_t sys_flistxattr (int filedes, char *list, size_t size)
1871 #if defined(HAVE_FLISTXATTR)
1872 #ifndef XATTR_ADD_OPT
1873 return flistxattr(filedes, list, size);
1874 #else
1875 int options = 0;
1876 return flistxattr(filedes, list, size, options);
1877 #endif
1878 #elif defined(HAVE_FLISTEA)
1879 return flistea(filedes, list, size);
1880 #elif defined(HAVE_EXTATTR_LIST_FD)
1881 extattr_arg arg;
1882 arg.filedes = filedes;
1883 return bsd_attr_list(2, arg, list, size);
1884 #elif defined(HAVE_ATTR_LISTF)
1885 return irix_attr_list(NULL, filedes, list, size, 0);
1886 #elif defined(HAVE_ATTROPEN)
1887 ssize_t ret = -1;
1888 int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
1889 if (attrdirfd >= 0) {
1890 ret = solaris_list_xattr(attrdirfd, list, size);
1891 close(attrdirfd);
1893 return ret;
1894 #else
1895 errno = ENOSYS;
1896 return -1;
1897 #endif
1900 int sys_removexattr (const char *path, const char *name)
1902 #if defined(HAVE_REMOVEXATTR)
1903 #ifndef XATTR_ADD_OPT
1904 return removexattr(path, name);
1905 #else
1906 int options = 0;
1907 return removexattr(path, name, options);
1908 #endif
1909 #elif defined(HAVE_REMOVEEA)
1910 return removeea(path, name);
1911 #elif defined(HAVE_EXTATTR_DELETE_FILE)
1912 char *s;
1913 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1914 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1915 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1917 return extattr_delete_file(path, attrnamespace, attrname);
1918 #elif defined(HAVE_ATTR_REMOVE)
1919 int flags = 0;
1920 char *attrname = strchr(name,'.') + 1;
1922 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1924 return attr_remove(path, attrname, flags);
1925 #elif defined(HAVE_ATTROPEN)
1926 int ret = -1;
1927 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
1928 if (attrdirfd >= 0) {
1929 ret = solaris_unlinkat(attrdirfd, name);
1930 close(attrdirfd);
1932 return ret;
1933 #else
1934 errno = ENOSYS;
1935 return -1;
1936 #endif
1939 int sys_lremovexattr (const char *path, const char *name)
1941 #if defined(HAVE_LREMOVEXATTR)
1942 return lremovexattr(path, name);
1943 #elif defined(HAVE_REMOVEXATTR) && defined(XATTR_ADD_OPT)
1944 int options = XATTR_NOFOLLOW;
1945 return removexattr(path, name, options);
1946 #elif defined(HAVE_LREMOVEEA)
1947 return lremoveea(path, name);
1948 #elif defined(HAVE_EXTATTR_DELETE_LINK)
1949 char *s;
1950 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1951 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1952 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1954 return extattr_delete_link(path, attrnamespace, attrname);
1955 #elif defined(HAVE_ATTR_REMOVE)
1956 int flags = ATTR_DONTFOLLOW;
1957 char *attrname = strchr(name,'.') + 1;
1959 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1961 return attr_remove(path, attrname, flags);
1962 #elif defined(HAVE_ATTROPEN)
1963 int ret = -1;
1964 int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1965 if (attrdirfd >= 0) {
1966 ret = solaris_unlinkat(attrdirfd, name);
1967 close(attrdirfd);
1969 return ret;
1970 #else
1971 errno = ENOSYS;
1972 return -1;
1973 #endif
1976 int sys_fremovexattr (int filedes, const char *name)
1978 #if defined(HAVE_FREMOVEXATTR)
1979 #ifndef XATTR_ADD_OPT
1980 return fremovexattr(filedes, name);
1981 #else
1982 int options = 0;
1983 return fremovexattr(filedes, name, options);
1984 #endif
1985 #elif defined(HAVE_FREMOVEEA)
1986 return fremoveea(filedes, name);
1987 #elif defined(HAVE_EXTATTR_DELETE_FD)
1988 char *s;
1989 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1990 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1991 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1993 return extattr_delete_fd(filedes, attrnamespace, attrname);
1994 #elif defined(HAVE_ATTR_REMOVEF)
1995 int flags = 0;
1996 char *attrname = strchr(name,'.') + 1;
1998 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
2000 return attr_removef(filedes, attrname, flags);
2001 #elif defined(HAVE_ATTROPEN)
2002 int ret = -1;
2003 int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
2004 if (attrdirfd >= 0) {
2005 ret = solaris_unlinkat(attrdirfd, name);
2006 close(attrdirfd);
2008 return ret;
2009 #else
2010 errno = ENOSYS;
2011 return -1;
2012 #endif
2015 int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags)
2017 #if defined(HAVE_SETXATTR)
2018 #ifndef XATTR_ADD_OPT
2019 return setxattr(path, name, value, size, flags);
2020 #else
2021 int options = 0;
2022 return setxattr(path, name, value, size, 0, options);
2023 #endif
2024 #elif defined(HAVE_SETEA)
2025 return setea(path, name, value, size, flags);
2026 #elif defined(HAVE_EXTATTR_SET_FILE)
2027 char *s;
2028 int retval = 0;
2029 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2030 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2031 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2032 if (flags) {
2033 /* Check attribute existence */
2034 retval = extattr_get_file(path, attrnamespace, attrname, NULL, 0);
2035 if (retval < 0) {
2036 /* REPLACE attribute, that doesn't exist */
2037 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2038 errno = ENOATTR;
2039 return -1;
2041 /* Ignore other errors */
2043 else {
2044 /* CREATE attribute, that already exists */
2045 if (flags & XATTR_CREATE) {
2046 errno = EEXIST;
2047 return -1;
2051 retval = extattr_set_file(path, attrnamespace, attrname, value, size);
2052 return (retval < 0) ? -1 : 0;
2053 #elif defined(HAVE_ATTR_SET)
2054 int myflags = 0;
2055 char *attrname = strchr(name,'.') + 1;
2057 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2058 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2059 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2061 return attr_set(path, attrname, (const char *)value, size, myflags);
2062 #elif defined(HAVE_ATTROPEN)
2063 int ret = -1;
2064 int myflags = O_RDWR;
2065 int attrfd;
2066 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2067 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2068 attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2069 if (attrfd >= 0) {
2070 ret = solaris_write_xattr(attrfd, value, size);
2071 close(attrfd);
2073 return ret;
2074 #else
2075 errno = ENOSYS;
2076 return -1;
2077 #endif
2080 int sys_lsetxattr (const char *path, const char *name, const void *value, size_t size, int flags)
2082 #if defined(HAVE_LSETXATTR)
2083 return lsetxattr(path, name, value, size, flags);
2084 #elif defined(HAVE_SETXATTR) && defined(XATTR_ADD_OPT)
2085 int options = XATTR_NOFOLLOW;
2086 return setxattr(path, name, value, size, 0, options);
2087 #elif defined(LSETEA)
2088 return lsetea(path, name, value, size, flags);
2089 #elif defined(HAVE_EXTATTR_SET_LINK)
2090 char *s;
2091 int retval = 0;
2092 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2093 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2094 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2095 if (flags) {
2096 /* Check attribute existence */
2097 retval = extattr_get_link(path, attrnamespace, attrname, NULL, 0);
2098 if (retval < 0) {
2099 /* REPLACE attribute, that doesn't exist */
2100 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2101 errno = ENOATTR;
2102 return -1;
2104 /* Ignore other errors */
2106 else {
2107 /* CREATE attribute, that already exists */
2108 if (flags & XATTR_CREATE) {
2109 errno = EEXIST;
2110 return -1;
2115 retval = extattr_set_link(path, attrnamespace, attrname, value, size);
2116 return (retval < 0) ? -1 : 0;
2117 #elif defined(HAVE_ATTR_SET)
2118 int myflags = ATTR_DONTFOLLOW;
2119 char *attrname = strchr(name,'.') + 1;
2121 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2122 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2123 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2125 return attr_set(path, attrname, (const char *)value, size, myflags);
2126 #elif defined(HAVE_ATTROPEN)
2127 int ret = -1;
2128 int myflags = O_RDWR | AT_SYMLINK_NOFOLLOW;
2129 int attrfd;
2130 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2131 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2132 attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2133 if (attrfd >= 0) {
2134 ret = solaris_write_xattr(attrfd, value, size);
2135 close(attrfd);
2137 return ret;
2138 #else
2139 errno = ENOSYS;
2140 return -1;
2141 #endif
2144 int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags)
2146 #if defined(HAVE_FSETXATTR)
2147 #ifndef XATTR_ADD_OPT
2148 return fsetxattr(filedes, name, value, size, flags);
2149 #else
2150 int options = 0;
2151 return fsetxattr(filedes, name, value, size, 0, options);
2152 #endif
2153 #elif defined(HAVE_FSETEA)
2154 return fsetea(filedes, name, value, size, flags);
2155 #elif defined(HAVE_EXTATTR_SET_FD)
2156 char *s;
2157 int retval = 0;
2158 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2159 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2160 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2161 if (flags) {
2162 /* Check attribute existence */
2163 retval = extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0);
2164 if (retval < 0) {
2165 /* REPLACE attribute, that doesn't exist */
2166 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2167 errno = ENOATTR;
2168 return -1;
2170 /* Ignore other errors */
2172 else {
2173 /* CREATE attribute, that already exists */
2174 if (flags & XATTR_CREATE) {
2175 errno = EEXIST;
2176 return -1;
2180 retval = extattr_set_fd(filedes, attrnamespace, attrname, value, size);
2181 return (retval < 0) ? -1 : 0;
2182 #elif defined(HAVE_ATTR_SETF)
2183 int myflags = 0;
2184 char *attrname = strchr(name,'.') + 1;
2186 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2187 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2188 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2190 return attr_setf(filedes, attrname, (const char *)value, size, myflags);
2191 #elif defined(HAVE_ATTROPEN)
2192 int ret = -1;
2193 int myflags = O_RDWR | O_XATTR;
2194 int attrfd;
2195 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2196 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2197 attrfd = solaris_openat(filedes, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2198 if (attrfd >= 0) {
2199 ret = solaris_write_xattr(attrfd, value, size);
2200 close(attrfd);
2202 return ret;
2203 #else
2204 errno = ENOSYS;
2205 return -1;
2206 #endif
2209 /**************************************************************************
2210 helper functions for Solaris' EA support
2211 ****************************************************************************/
2212 #ifdef HAVE_ATTROPEN
2213 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size)
2215 struct stat sbuf;
2217 if (fstat(attrfd, &sbuf) == -1) {
2218 errno = ENOATTR;
2219 return -1;
2222 /* This is to return the current size of the named extended attribute */
2223 if (size == 0) {
2224 return sbuf.st_size;
2227 /* check size and read xattr */
2228 if (sbuf.st_size > size) {
2229 errno = ERANGE;
2230 return -1;
2233 return read(attrfd, value, sbuf.st_size);
2236 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size)
2238 ssize_t len = 0;
2239 DIR *dirp;
2240 struct dirent *de;
2241 int newfd = dup(attrdirfd);
2242 /* CAUTION: The originating file descriptor should not be
2243 used again following the call to fdopendir().
2244 For that reason we dup() the file descriptor
2245 here to make things more clear. */
2246 dirp = fdopendir(newfd);
2248 while ((de = readdir(dirp))) {
2249 size_t listlen = strlen(de->d_name);
2250 if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) {
2251 /* we don't want "." and ".." here: */
2252 DEBUG(10,("skipped EA %s\n",de->d_name));
2253 continue;
2256 if (size == 0) {
2257 /* return the current size of the list of extended attribute names*/
2258 len += listlen + 1;
2259 } else {
2260 /* check size and copy entrieѕ + nul into list. */
2261 if ((len + listlen + 1) > size) {
2262 errno = ERANGE;
2263 len = -1;
2264 break;
2265 } else {
2266 safe_strcpy(list + len, de->d_name, listlen);
2267 len += listlen;
2268 list[len] = '\0';
2269 ++len;
2274 if (closedir(dirp) == -1) {
2275 DEBUG(0,("closedir dirp failed: %s\n",strerror(errno)));
2276 return -1;
2278 return len;
2281 static int solaris_unlinkat(int attrdirfd, const char *name)
2283 if (unlinkat(attrdirfd, name, 0) == -1) {
2284 if (errno == ENOENT) {
2285 errno = ENOATTR;
2287 return -1;
2289 return 0;
2292 static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode)
2294 int filedes = attropen(path, attrpath, oflag, mode);
2295 if (filedes == -1) {
2296 DEBUG(10,("attropen FAILED: path: %s, name: %s, errno: %s\n",path,attrpath,strerror(errno)));
2297 if (errno == EINVAL) {
2298 errno = ENOTSUP;
2299 } else {
2300 errno = ENOATTR;
2303 return filedes;
2306 static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode)
2308 int filedes = openat(fildes, path, oflag, mode);
2309 if (filedes == -1) {
2310 DEBUG(10,("openat FAILED: fd: %d, path: %s, errno: %s\n",filedes,path,strerror(errno)));
2311 if (errno == EINVAL) {
2312 errno = ENOTSUP;
2313 } else {
2314 errno = ENOATTR;
2317 return filedes;
2320 static int solaris_write_xattr(int attrfd, const char *value, size_t size)
2322 if ((ftruncate(attrfd, 0) == 0) && (write(attrfd, value, size) == size)) {
2323 return 0;
2324 } else {
2325 DEBUG(10,("solaris_write_xattr FAILED!\n"));
2326 return -1;
2329 #endif /*HAVE_ATTROPEN*/
2332 /****************************************************************************
2333 Return the major devicenumber for UNIX extensions.
2334 ****************************************************************************/
2336 uint32 unix_dev_major(SMB_DEV_T dev)
2338 #if defined(HAVE_DEVICE_MAJOR_FN)
2339 return (uint32)major(dev);
2340 #else
2341 return (uint32)(dev >> 8);
2342 #endif
2345 /****************************************************************************
2346 Return the minor devicenumber for UNIX extensions.
2347 ****************************************************************************/
2349 uint32 unix_dev_minor(SMB_DEV_T dev)
2351 #if defined(HAVE_DEVICE_MINOR_FN)
2352 return (uint32)minor(dev);
2353 #else
2354 return (uint32)(dev & 0xff);
2355 #endif
2358 #if defined(WITH_AIO)
2360 /*******************************************************************
2361 An aio_read wrapper that will deal with 64-bit sizes.
2362 ********************************************************************/
2364 int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2366 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_READ64)
2367 return aio_read64(aiocb);
2368 #elif defined(HAVE_AIO_READ)
2369 return aio_read(aiocb);
2370 #else
2371 errno = ENOSYS;
2372 return -1;
2373 #endif
2376 /*******************************************************************
2377 An aio_write wrapper that will deal with 64-bit sizes.
2378 ********************************************************************/
2380 int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2382 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_WRITE64)
2383 return aio_write64(aiocb);
2384 #elif defined(HAVE_AIO_WRITE)
2385 return aio_write(aiocb);
2386 #else
2387 errno = ENOSYS;
2388 return -1;
2389 #endif
2392 /*******************************************************************
2393 An aio_return wrapper that will deal with 64-bit sizes.
2394 ********************************************************************/
2396 ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2398 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_RETURN64)
2399 return aio_return64(aiocb);
2400 #elif defined(HAVE_AIO_RETURN)
2401 return aio_return(aiocb);
2402 #else
2403 errno = ENOSYS;
2404 return -1;
2405 #endif
2408 /*******************************************************************
2409 An aio_cancel wrapper that will deal with 64-bit sizes.
2410 ********************************************************************/
2412 int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2414 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_CANCEL64)
2415 return aio_cancel64(fd, aiocb);
2416 #elif defined(HAVE_AIO_CANCEL)
2417 return aio_cancel(fd, aiocb);
2418 #else
2419 errno = ENOSYS;
2420 return -1;
2421 #endif
2424 /*******************************************************************
2425 An aio_error wrapper that will deal with 64-bit sizes.
2426 ********************************************************************/
2428 int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2430 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_ERROR64)
2431 return aio_error64(aiocb);
2432 #elif defined(HAVE_AIO_ERROR)
2433 return aio_error(aiocb);
2434 #else
2435 errno = ENOSYS;
2436 return -1;
2437 #endif
2440 /*******************************************************************
2441 An aio_fsync wrapper that will deal with 64-bit sizes.
2442 ********************************************************************/
2444 int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2446 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_FSYNC64)
2447 return aio_fsync64(op, aiocb);
2448 #elif defined(HAVE_AIO_FSYNC)
2449 return aio_fsync(op, aiocb);
2450 #else
2451 errno = ENOSYS;
2452 return -1;
2453 #endif
2456 /*******************************************************************
2457 An aio_fsync wrapper that will deal with 64-bit sizes.
2458 ********************************************************************/
2460 int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2462 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_SUSPEND64)
2463 return aio_suspend64(cblist, n, timeout);
2464 #elif defined(HAVE_AIO_FSYNC)
2465 return aio_suspend(cblist, n, timeout);
2466 #else
2467 errno = ENOSYS;
2468 return -1;
2469 #endif
2471 #else /* !WITH_AIO */
2473 int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2475 errno = ENOSYS;
2476 return -1;
2479 int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2481 errno = ENOSYS;
2482 return -1;
2485 ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2487 errno = ENOSYS;
2488 return -1;
2491 int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2493 errno = ENOSYS;
2494 return -1;
2497 int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2499 errno = ENOSYS;
2500 return -1;
2503 int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2505 errno = ENOSYS;
2506 return -1;
2509 int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2511 errno = ENOSYS;
2512 return -1;
2514 #endif /* WITH_AIO */
2516 int sys_getpeereid( int s, uid_t *uid)
2518 #if defined(HAVE_PEERCRED)
2519 struct ucred cred;
2520 socklen_t cred_len = sizeof(struct ucred);
2521 int ret;
2523 ret = getsockopt(s, SOL_SOCKET, SO_PEERCRED, (void *)&cred, &cred_len);
2524 if (ret != 0) {
2525 return -1;
2528 if (cred_len != sizeof(struct ucred)) {
2529 errno = EINVAL;
2530 return -1;
2533 *uid = cred.uid;
2534 return 0;
2535 #else
2536 errno = ENOSYS;
2537 return -1;
2538 #endif
2541 int sys_getnameinfo(const struct sockaddr *psa,
2542 socklen_t salen,
2543 char *host,
2544 size_t hostlen,
2545 char *service,
2546 size_t servlen,
2547 int flags)
2550 * For Solaris we must make sure salen is the
2551 * correct length for the incoming sa_family.
2554 if (salen == sizeof(struct sockaddr_storage)) {
2555 salen = sizeof(struct sockaddr_in);
2556 #if defined(HAVE_IPV6)
2557 if (psa->sa_family == AF_INET6) {
2558 salen = sizeof(struct sockaddr_in6);
2560 #endif
2562 return getnameinfo(psa, salen, host, hostlen, service, servlen, flags);
2565 int sys_connect(int fd, const struct sockaddr * addr)
2567 socklen_t salen = -1;
2569 if (addr->sa_family == AF_INET) {
2570 salen = sizeof(struct sockaddr_in);
2571 } else if (addr->sa_family == AF_UNIX) {
2572 salen = sizeof(struct sockaddr_un);
2574 #if defined(HAVE_IPV6)
2575 else if (addr->sa_family == AF_INET6) {
2576 salen = sizeof(struct sockaddr_in6);
2578 #endif
2580 return connect(fd, addr, salen);