source: branches/samba-3.5.x/source3/lib/system.c@ 778

Last change on this file since 778 was 590, checked in by Herwig Bauernfeind, 14 years ago

Samba 3.5: Update trunk to 3.5.6

File size: 72.2 KB
Line 
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
8
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.
13
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.
18
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/>.
21*/
22
23#include "includes.h"
24
25#ifdef HAVE_SYS_PRCTL_H
26#include <sys/prctl.h>
27#endif
28
29/*
30 The idea is that this file will eventually have wrappers around all
31 important system calls in samba. The aims are:
32
33 - to enable easier porting by putting OS dependent stuff in here
34
35 - to allow for hooks into other "pseudo-filesystems"
36
37 - to allow easier integration of things like the japanese extensions
38
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.
42*/
43
44
45
46/*******************************************************************
47 A wrapper for memalign
48********************************************************************/
49
50void *sys_memalign( size_t align, size_t size )
51{
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;
57
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;
74 }
75 if (size < pagesize) {
76 size = pagesize;
77 }
78 return SMB_MALLOC(size);
79#endif
80}
81
82/*******************************************************************
83 A wrapper for usleep in case we don't have one.
84********************************************************************/
85
86int sys_usleep(long usecs)
87{
88#ifndef HAVE_USLEEP
89 struct timeval tval;
90#endif
91
92 /*
93 * We need this braindamage as the glibc usleep
94 * is not SPEC1170 complient... grumble... JRA.
95 */
96
97 if(usecs < 0 || usecs > 999999) {
98 errno = EINVAL;
99 return -1;
100 }
101
102#if HAVE_USLEEP
103 usleep(usecs);
104 return 0;
105#else /* HAVE_USLEEP */
106 /*
107 * Fake it with select...
108 */
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 */
114}
115
116/*******************************************************************
117A read wrapper that will deal with EINTR.
118********************************************************************/
119
120ssize_t sys_read(int fd, void *buf, size_t count)
121{
122 ssize_t ret;
123
124 do {
125 ret = read(fd, buf, count);
126 } while (ret == -1 && errno == EINTR);
127 return ret;
128}
129
130/*******************************************************************
131A write wrapper that will deal with EINTR.
132********************************************************************/
133
134ssize_t sys_write(int fd, const void *buf, size_t count)
135{
136 ssize_t ret;
137
138 do {
139 ret = write(fd, buf, count);
140 } while (ret == -1 && errno == EINTR);
141 return ret;
142}
143
144/*******************************************************************
145A writev wrapper that will deal with EINTR.
146********************************************************************/
147
148ssize_t sys_writev(int fd, const struct iovec *iov, int iovcnt)
149{
150 ssize_t ret;
151
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);
156 }
157 if (iov[0].iov_len > 1) {
158 return sys_write(fd, iov[0].iov_base,
159 (random() % (iov[0].iov_len-1)) + 1);
160 }
161#endif
162
163 do {
164 ret = writev(fd, iov, iovcnt);
165 } while (ret == -1 && errno == EINTR);
166 return ret;
167}
168
169/*******************************************************************
170A pread wrapper that will deal with EINTR and 64-bit file offsets.
171********************************************************************/
172
173#if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
174ssize_t sys_pread(int fd, void *buf, size_t count, SMB_OFF_T off)
175{
176 ssize_t ret;
177
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;
186}
187#endif
188
189/*******************************************************************
190A write wrapper that will deal with EINTR and 64-bit file offsets.
191********************************************************************/
192
193#if defined(HAVE_PWRITE) || defined(HAVE_PWRITE64)
194ssize_t sys_pwrite(int fd, const void *buf, size_t count, SMB_OFF_T off)
195{
196 ssize_t ret;
197
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;
206}
207#endif
208
209/*******************************************************************
210A send wrapper that will deal with EINTR.
211********************************************************************/
212
213ssize_t sys_send(int s, const void *msg, size_t len, int flags)
214{
215 ssize_t ret;
216
217 do {
218 ret = send(s, msg, len, flags);
219 } while (ret == -1 && errno == EINTR);
220 return ret;
221}
222
223/*******************************************************************
224A sendto wrapper that will deal with EINTR.
225********************************************************************/
226
227ssize_t sys_sendto(int s, const void *msg, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
228{
229 ssize_t ret;
230
231 do {
232 ret = sendto(s, msg, len, flags, to, tolen);
233 } while (ret == -1 && errno == EINTR);
234 return ret;
235}
236
237/*******************************************************************
238A recv wrapper that will deal with EINTR.
239********************************************************************/
240
241ssize_t sys_recv(int fd, void *buf, size_t count, int flags)
242{
243 ssize_t ret;
244
245 do {
246 ret = recv(fd, buf, count, flags);
247 } while (ret == -1 && errno == EINTR);
248 return ret;
249}
250
251/*******************************************************************
252A recvfrom wrapper that will deal with EINTR.
253********************************************************************/
254
255ssize_t sys_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
256{
257 ssize_t ret;
258
259 do {
260 ret = recvfrom(s, buf, len, flags, from, fromlen);
261 } while (ret == -1 && errno == EINTR);
262 return ret;
263}
264
265/*******************************************************************
266A fcntl wrapper that will deal with EINTR.
267********************************************************************/
268
269int sys_fcntl_ptr(int fd, int cmd, void *arg)
270{
271 int ret;
272
273 do {
274 ret = fcntl(fd, cmd, arg);
275 } while (ret == -1 && errno == EINTR);
276 return ret;
277}
278
279/*******************************************************************
280A fcntl wrapper that will deal with EINTR.
281********************************************************************/
282
283int sys_fcntl_long(int fd, int cmd, long arg)
284{
285 int ret;
286
287 do {
288 ret = fcntl(fd, cmd, arg);
289 } while (ret == -1 && errno == EINTR);
290 return ret;
291}
292
293/****************************************************************************
294 Get/Set all the possible time fields from a stat struct as a timespec.
295****************************************************************************/
296
297static struct timespec get_atimespec(const struct stat *pst)
298{
299#if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
300 struct timespec ret;
301
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
330}
331
332static struct timespec get_mtimespec(const struct stat *pst)
333{
334#if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
335 struct timespec ret;
336
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
365}
366
367static struct timespec get_ctimespec(const struct stat *pst)
368{
369#if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
370 struct timespec ret;
371
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
400}
401
402/****************************************************************************
403 Return the best approximation to a 'create time' under UNIX from a stat
404 structure.
405****************************************************************************/
406
407static struct timespec calc_create_time_stat(const struct stat *st)
408{
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);
413
414 ret = timespec_compare(&c_time, &m_time) < 0 ? c_time : m_time;
415 ret1 = timespec_compare(&ret, &a_time) < 0 ? ret : a_time;
416
417 if(!null_timespec(ret1)) {
418 return ret1;
419 }
420
421 /*
422 * One of ctime, mtime or atime was zero (probably atime).
423 * Just return MIN(ctime, mtime).
424 */
425 return ret;
426}
427
428/****************************************************************************
429 Return the best approximation to a 'create time' under UNIX from a stat_ex
430 structure.
431****************************************************************************/
432
433static struct timespec calc_create_time_stat_ex(const struct stat_ex *st)
434{
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;
439
440 ret = timespec_compare(&c_time, &m_time) < 0 ? c_time : m_time;
441 ret1 = timespec_compare(&ret, &a_time) < 0 ? ret : a_time;
442
443 if(!null_timespec(ret1)) {
444 return ret1;
445 }
446
447 /*
448 * One of ctime, mtime or atime was zero (probably atime).
449 * Just return MIN(ctime, mtime).
450 */
451 return ret;
452}
453
454/****************************************************************************
455 Return the 'create time' from a stat struct if it exists (birthtime) or else
456 use the best approximation.
457****************************************************************************/
458
459static void make_create_timespec(const struct stat *pst, struct stat_ex *dst,
460 bool fake_dir_create_times)
461{
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;
465 }
466
467 dst->st_ex_calculated_birthtime = false;
468
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
481
482 /* Deal with systems that don't initialize birthtime correctly.
483 * Pointed out by SATOH Fumiyasu <fumiyas@osstech.jp>.
484 */
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;
488 }
489}
490
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****************************************************************************/
496
497void update_stat_ex_mtime(struct stat_ex *dst,
498 struct timespec write_ts)
499{
500 dst->st_ex_mtime = write_ts;
501
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);
505 }
506}
507
508void update_stat_ex_create_time(struct stat_ex *dst,
509 struct timespec create_time)
510{
511 dst->st_ex_btime = create_time;
512 dst->st_ex_calculated_birthtime = false;
513}
514
515#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
516static void init_stat_ex_from_stat (struct stat_ex *dst,
517 const struct stat64 *src,
518 bool fake_dir_create_times)
519#else
520static void init_stat_ex_from_stat (struct stat_ex *dst,
521 const struct stat *src,
522 bool fake_dir_create_times)
523#endif
524{
525 dst->st_ex_dev = src->st_dev;
526 dst->st_ex_ino = src->st_ino;
527 dst->st_ex_mode = src->st_mode;
528 dst->st_ex_nlink = src->st_nlink;
529 dst->st_ex_uid = src->st_uid;
530 dst->st_ex_gid = src->st_gid;
531 dst->st_ex_rdev = src->st_rdev;
532 dst->st_ex_size = src->st_size;
533 dst->st_ex_atime = get_atimespec(src);
534 dst->st_ex_mtime = get_mtimespec(src);
535 dst->st_ex_ctime = get_ctimespec(src);
536 make_create_timespec(src, dst, fake_dir_create_times);
537#ifdef HAVE_STAT_ST_BLKSIZE
538 dst->st_ex_blksize = src->st_blksize;
539#else
540 dst->st_ex_blksize = STAT_ST_BLOCKSIZE;
541#endif
542
543#ifdef HAVE_STAT_ST_BLOCKS
544 dst->st_ex_blocks = src->st_blocks;
545#else
546 dst->st_ex_blocks = src->st_size / dst->st_ex_blksize + 1;
547#endif
548
549#ifdef HAVE_STAT_ST_FLAGS
550 dst->st_ex_flags = src->st_flags;
551#else
552 dst->st_ex_flags = 0;
553#endif
554}
555
556/*******************************************************************
557A stat() wrapper that will deal with 64 bit filesizes.
558********************************************************************/
559
560int sys_stat(const char *fname, SMB_STRUCT_STAT *sbuf,
561 bool fake_dir_create_times)
562{
563 int ret;
564#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
565 struct stat64 statbuf;
566 ret = stat64(fname, &statbuf);
567#else
568 struct stat statbuf;
569 ret = stat(fname, &statbuf);
570#endif
571 if (ret == 0) {
572 /* we always want directories to appear zero size */
573 if (S_ISDIR(statbuf.st_mode)) {
574 statbuf.st_size = 0;
575 }
576 init_stat_ex_from_stat(sbuf, &statbuf, fake_dir_create_times);
577 }
578 return ret;
579}
580
581/*******************************************************************
582 An fstat() wrapper that will deal with 64 bit filesizes.
583********************************************************************/
584
585int sys_fstat(int fd, SMB_STRUCT_STAT *sbuf, bool fake_dir_create_times)
586{
587 int ret;
588#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FSTAT64)
589 struct stat64 statbuf;
590 ret = fstat64(fd, &statbuf);
591#else
592 struct stat statbuf;
593 ret = fstat(fd, &statbuf);
594#endif
595 if (ret == 0) {
596 /* we always want directories to appear zero size */
597 if (S_ISDIR(statbuf.st_mode)) {
598 statbuf.st_size = 0;
599 }
600 init_stat_ex_from_stat(sbuf, &statbuf, fake_dir_create_times);
601 }
602 return ret;
603}
604
605/*******************************************************************
606 An lstat() wrapper that will deal with 64 bit filesizes.
607********************************************************************/
608
609int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf,
610 bool fake_dir_create_times)
611{
612 int ret;
613#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSTAT64)
614 struct stat64 statbuf;
615 ret = lstat64(fname, &statbuf);
616#else
617 struct stat statbuf;
618 ret = lstat(fname, &statbuf);
619#endif
620 if (ret == 0) {
621 /* we always want directories to appear zero size */
622 if (S_ISDIR(statbuf.st_mode)) {
623 statbuf.st_size = 0;
624 }
625 init_stat_ex_from_stat(sbuf, &statbuf, fake_dir_create_times);
626 }
627 return ret;
628}
629
630/*******************************************************************
631 An posix_fallocate() wrapper that will deal with 64 bit filesizes.
632********************************************************************/
633int sys_posix_fallocate(int fd, SMB_OFF_T offset, SMB_OFF_T len)
634{
635#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_POSIX_FALLOCATE64) && !defined(HAVE_BROKEN_POSIX_FALLOCATE)
636 return posix_fallocate64(fd, offset, len);
637#elif defined(HAVE_POSIX_FALLOCATE) && !defined(HAVE_BROKEN_POSIX_FALLOCATE)
638 return posix_fallocate(fd, offset, len);
639#else
640 return ENOSYS;
641#endif
642}
643
644/*******************************************************************
645 An ftruncate() wrapper that will deal with 64 bit filesizes.
646********************************************************************/
647
648int sys_ftruncate(int fd, SMB_OFF_T offset)
649{
650#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FTRUNCATE64)
651 return ftruncate64(fd, offset);
652#elif defined(__OS2__)
653 return os2_ftruncate(fd, offset);
654#else
655 return ftruncate(fd, offset);
656#endif
657}
658
659/*******************************************************************
660 An lseek() wrapper that will deal with 64 bit filesizes.
661********************************************************************/
662
663SMB_OFF_T sys_lseek(int fd, SMB_OFF_T offset, int whence)
664{
665#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSEEK64)
666 return lseek64(fd, offset, whence);
667#else
668 return lseek(fd, offset, whence);
669#endif
670}
671
672/*******************************************************************
673 An fseek() wrapper that will deal with 64 bit filesizes.
674********************************************************************/
675
676int sys_fseek(FILE *fp, SMB_OFF_T offset, int whence)
677{
678#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEK64)
679 return fseek64(fp, offset, whence);
680#elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEKO64)
681 return fseeko64(fp, offset, whence);
682#else
683 return fseek(fp, offset, whence);
684#endif
685}
686
687/*******************************************************************
688 An ftell() wrapper that will deal with 64 bit filesizes.
689********************************************************************/
690
691SMB_OFF_T sys_ftell(FILE *fp)
692{
693#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELL64)
694 return (SMB_OFF_T)ftell64(fp);
695#elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELLO64)
696 return (SMB_OFF_T)ftello64(fp);
697#else
698 return (SMB_OFF_T)ftell(fp);
699#endif
700}
701
702/*******************************************************************
703 A creat() wrapper that will deal with 64 bit filesizes.
704********************************************************************/
705
706int sys_creat(const char *path, mode_t mode)
707{
708#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CREAT64)
709 return creat64(path, mode);
710#else
711 /*
712 * If creat64 isn't defined then ensure we call a potential open64.
713 * JRA.
714 */
715 return sys_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
716#endif
717}
718
719/*******************************************************************
720 An open() wrapper that will deal with 64 bit filesizes.
721********************************************************************/
722
723int sys_open(const char *path, int oflag, mode_t mode)
724{
725#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPEN64)
726 return open64(path, oflag, mode);
727#else
728 return open(path, oflag, mode);
729#endif
730}
731
732/*******************************************************************
733 An fopen() wrapper that will deal with 64 bit filesizes.
734********************************************************************/
735
736FILE *sys_fopen(const char *path, const char *type)
737{
738#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FOPEN64)
739 return fopen64(path, type);
740#else
741 return fopen(path, type);
742#endif
743}
744
745
746/*******************************************************************
747 A flock() wrapper that will perform the kernel flock.
748********************************************************************/
749
750void kernel_flock(int fd, uint32 share_mode, uint32 access_mask)
751{
752#if HAVE_KERNEL_SHARE_MODES
753 int kernel_mode = 0;
754 if (share_mode == FILE_SHARE_WRITE) {
755 kernel_mode = LOCK_MAND|LOCK_WRITE;
756 } else if (share_mode == FILE_SHARE_READ) {
757 kernel_mode = LOCK_MAND|LOCK_READ;
758 } else if (share_mode == FILE_SHARE_NONE) {
759 kernel_mode = LOCK_MAND;
760 }
761 if (kernel_mode) {
762 flock(fd, kernel_mode);
763 }
764#endif
765 ;
766}
767
768
769
770/*******************************************************************
771 An opendir wrapper that will deal with 64 bit filesizes.
772********************************************************************/
773
774SMB_STRUCT_DIR *sys_opendir(const char *name)
775{
776#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPENDIR64)
777 return opendir64(name);
778#else
779 return opendir(name);
780#endif
781}
782
783/*******************************************************************
784 A readdir wrapper that will deal with 64 bit filesizes.
785********************************************************************/
786
787SMB_STRUCT_DIRENT *sys_readdir(SMB_STRUCT_DIR *dirp)
788{
789#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_READDIR64)
790 return readdir64(dirp);
791#else
792 return readdir(dirp);
793#endif
794}
795
796/*******************************************************************
797 A seekdir wrapper that will deal with 64 bit filesizes.
798********************************************************************/
799
800void sys_seekdir(SMB_STRUCT_DIR *dirp, long offset)
801{
802#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_SEEKDIR64)
803 seekdir64(dirp, offset);
804#else
805 seekdir(dirp, offset);
806#endif
807}
808
809/*******************************************************************
810 A telldir wrapper that will deal with 64 bit filesizes.
811********************************************************************/
812
813long sys_telldir(SMB_STRUCT_DIR *dirp)
814{
815#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_TELLDIR64)
816 return (long)telldir64(dirp);
817#else
818 return (long)telldir(dirp);
819#endif
820}
821
822/*******************************************************************
823 A rewinddir wrapper that will deal with 64 bit filesizes.
824********************************************************************/
825
826void sys_rewinddir(SMB_STRUCT_DIR *dirp)
827{
828#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_REWINDDIR64)
829 rewinddir64(dirp);
830#else
831 rewinddir(dirp);
832#endif
833}
834
835/*******************************************************************
836 A close wrapper that will deal with 64 bit filesizes.
837********************************************************************/
838
839int sys_closedir(SMB_STRUCT_DIR *dirp)
840{
841#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CLOSEDIR64)
842 return closedir64(dirp);
843#else
844 return closedir(dirp);
845#endif
846}
847
848/*******************************************************************
849 An mknod() wrapper that will deal with 64 bit filesizes.
850********************************************************************/
851
852int sys_mknod(const char *path, mode_t mode, SMB_DEV_T dev)
853{
854#if defined(HAVE_MKNOD) || defined(HAVE_MKNOD64)
855#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_MKNOD64) && defined(HAVE_DEV64_T)
856 return mknod64(path, mode, dev);
857#else
858 return mknod(path, mode, dev);
859#endif
860#else
861 /* No mknod system call. */
862 errno = ENOSYS;
863 return -1;
864#endif
865}
866
867/*******************************************************************
868The wait() calls vary between systems
869********************************************************************/
870
871int sys_waitpid(pid_t pid,int *status,int options)
872{
873#ifdef HAVE_WAITPID
874 return waitpid(pid,status,options);
875#else /* HAVE_WAITPID */
876 return wait4(pid, status, options, NULL);
877#endif /* HAVE_WAITPID */
878}
879
880/*******************************************************************
881 System wrapper for getwd
882********************************************************************/
883
884char *sys_getwd(char *s)
885{
886 char *wd;
887#ifdef HAVE_GETCWD
888 wd = (char *)getcwd(s, PATH_MAX);
889#else
890 wd = (char *)getwd(s);
891#endif
892 return wd;
893}
894
895#if defined(HAVE_POSIX_CAPABILITIES)
896
897/**************************************************************************
898 Try and abstract process capabilities (for systems that have them).
899****************************************************************************/
900
901/* Set the POSIX capabilities needed for the given purpose into the effective
902 * capability set of the current process. Make sure they are always removed
903 * from the inheritable set, because there is no circumstance in which our
904 * children should inherit our elevated privileges.
905 */
906static bool set_process_capability(enum smbd_capability capability,
907 bool enable)
908{
909 cap_value_t cap_vals[2] = {0};
910 int num_cap_vals = 0;
911
912 cap_t cap;
913
914#if defined(HAVE_PRCTL) && defined(PR_GET_KEEPCAPS) && defined(PR_SET_KEEPCAPS)
915 /* On Linux, make sure that any capabilities we grab are sticky
916 * across UID changes. We expect that this would allow us to keep both
917 * the effective and permitted capability sets, but as of circa 2.6.16,
918 * only the permitted set is kept. It is a bug (which we work around)
919 * that the effective set is lost, but we still require the effective
920 * set to be kept.
921 */
922 if (!prctl(PR_GET_KEEPCAPS)) {
923 prctl(PR_SET_KEEPCAPS, 1);
924 }
925#endif
926
927 cap = cap_get_proc();
928 if (cap == NULL) {
929 DEBUG(0,("set_process_capability: cap_get_proc failed: %s\n",
930 strerror(errno)));
931 return False;
932 }
933
934 switch (capability) {
935 case KERNEL_OPLOCK_CAPABILITY:
936#ifdef CAP_NETWORK_MGT
937 /* IRIX has CAP_NETWORK_MGT for oplocks. */
938 cap_vals[num_cap_vals++] = CAP_NETWORK_MGT;
939#endif
940 break;
941 case DMAPI_ACCESS_CAPABILITY:
942#ifdef CAP_DEVICE_MGT
943 /* IRIX has CAP_DEVICE_MGT for DMAPI access. */
944 cap_vals[num_cap_vals++] = CAP_DEVICE_MGT;
945#elif CAP_MKNOD
946 /* Linux has CAP_MKNOD for DMAPI access. */
947 cap_vals[num_cap_vals++] = CAP_MKNOD;
948#endif
949 break;
950 case LEASE_CAPABILITY:
951#ifdef CAP_LEASE
952 cap_vals[num_cap_vals++] = CAP_LEASE;
953#endif
954 break;
955 }
956
957 SMB_ASSERT(num_cap_vals <= ARRAY_SIZE(cap_vals));
958
959 if (num_cap_vals == 0) {
960 cap_free(cap);
961 return True;
962 }
963
964 cap_set_flag(cap, CAP_EFFECTIVE, num_cap_vals, cap_vals,
965 enable ? CAP_SET : CAP_CLEAR);
966
967 /* We never want to pass capabilities down to our children, so make
968 * sure they are not inherited.
969 */
970 cap_set_flag(cap, CAP_INHERITABLE, num_cap_vals, cap_vals, CAP_CLEAR);
971
972 if (cap_set_proc(cap) == -1) {
973 DEBUG(0, ("set_process_capability: cap_set_proc failed: %s\n",
974 strerror(errno)));
975 cap_free(cap);
976 return False;
977 }
978
979 cap_free(cap);
980 return True;
981}
982
983#endif /* HAVE_POSIX_CAPABILITIES */
984
985/****************************************************************************
986 Gain the oplock capability from the kernel if possible.
987****************************************************************************/
988
989void set_effective_capability(enum smbd_capability capability)
990{
991#if defined(HAVE_POSIX_CAPABILITIES)
992 set_process_capability(capability, True);
993#endif /* HAVE_POSIX_CAPABILITIES */
994}
995
996void drop_effective_capability(enum smbd_capability capability)
997{
998#if defined(HAVE_POSIX_CAPABILITIES)
999 set_process_capability(capability, False);
1000#endif /* HAVE_POSIX_CAPABILITIES */
1001}
1002
1003/**************************************************************************
1004 Wrapper for random().
1005****************************************************************************/
1006
1007long sys_random(void)
1008{
1009#if defined(HAVE_RANDOM)
1010 return (long)random();
1011#elif defined(HAVE_RAND)
1012 return (long)rand();
1013#else
1014 DEBUG(0,("Error - no random function available !\n"));
1015 exit(1);
1016#endif
1017}
1018
1019/**************************************************************************
1020 Wrapper for srandom().
1021****************************************************************************/
1022
1023void sys_srandom(unsigned int seed)
1024{
1025#if defined(HAVE_SRANDOM)
1026 srandom(seed);
1027#elif defined(HAVE_SRAND)
1028 srand(seed);
1029#else
1030 DEBUG(0,("Error - no srandom function available !\n"));
1031 exit(1);
1032#endif
1033}
1034
1035/**************************************************************************
1036 Returns equivalent to NGROUPS_MAX - using sysconf if needed.
1037****************************************************************************/
1038
1039int groups_max(void)
1040{
1041#if defined(SYSCONF_SC_NGROUPS_MAX)
1042 int ret = sysconf(_SC_NGROUPS_MAX);
1043 return (ret == -1) ? NGROUPS_MAX : ret;
1044#else
1045 return NGROUPS_MAX;
1046#endif
1047}
1048
1049/**************************************************************************
1050 Wrap setgroups and getgroups for systems that declare getgroups() as
1051 returning an array of gid_t, but actuall return an array of int.
1052****************************************************************************/
1053
1054#if defined(HAVE_BROKEN_GETGROUPS)
1055static int sys_broken_getgroups(int setlen, gid_t *gidset)
1056{
1057 GID_T gid;
1058 GID_T *group_list;
1059 int i, ngroups;
1060
1061 if(setlen == 0) {
1062 return getgroups(setlen, &gid);
1063 }
1064
1065 /*
1066 * Broken case. We need to allocate a
1067 * GID_T array of size setlen.
1068 */
1069
1070 if(setlen < 0) {
1071 errno = EINVAL;
1072 return -1;
1073 }
1074
1075 if (setlen == 0)
1076 setlen = groups_max();
1077
1078 if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
1079 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
1080 return -1;
1081 }
1082
1083 if((ngroups = getgroups(setlen, group_list)) < 0) {
1084 int saved_errno = errno;
1085 SAFE_FREE(group_list);
1086 errno = saved_errno;
1087 return -1;
1088 }
1089
1090 for(i = 0; i < ngroups; i++)
1091 gidset[i] = (gid_t)group_list[i];
1092
1093 SAFE_FREE(group_list);
1094 return ngroups;
1095}
1096
1097static int sys_broken_setgroups(int setlen, gid_t *gidset)
1098{
1099 GID_T *group_list;
1100 int i ;
1101
1102 if (setlen == 0)
1103 return 0 ;
1104
1105 if (setlen < 0 || setlen > groups_max()) {
1106 errno = EINVAL;
1107 return -1;
1108 }
1109
1110 /*
1111 * Broken case. We need to allocate a
1112 * GID_T array of size setlen.
1113 */
1114
1115 if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
1116 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
1117 return -1;
1118 }
1119
1120 for(i = 0; i < setlen; i++)
1121 group_list[i] = (GID_T) gidset[i];
1122
1123 if(setgroups(setlen, group_list) != 0) {
1124 int saved_errno = errno;
1125 SAFE_FREE(group_list);
1126 errno = saved_errno;
1127 return -1;
1128 }
1129
1130 SAFE_FREE(group_list);
1131 return 0 ;
1132}
1133
1134#endif /* HAVE_BROKEN_GETGROUPS */
1135
1136/* This is a list of systems that require the first GID passed to setgroups(2)
1137 * to be the effective GID. If your system is one of these, add it here.
1138 */
1139#if defined (FREEBSD) || defined (DARWINOS)
1140#define USE_BSD_SETGROUPS
1141#endif
1142
1143#if defined(USE_BSD_SETGROUPS)
1144/* Depending on the particular BSD implementation, the first GID that is
1145 * passed to setgroups(2) will either be ignored or will set the credential's
1146 * effective GID. In either case, the right thing to do is to guarantee that
1147 * gidset[0] is the effective GID.
1148 */
1149static int sys_bsd_setgroups(gid_t primary_gid, int setlen, const gid_t *gidset)
1150{
1151 gid_t *new_gidset = NULL;
1152 int max;
1153 int ret;
1154
1155 /* setgroups(2) will fail with EINVAL if we pass too many groups. */
1156 max = groups_max();
1157
1158 /* No group list, just make sure we are setting the efective GID. */
1159 if (setlen == 0) {
1160 return setgroups(1, &primary_gid);
1161 }
1162
1163 /* If the primary gid is not the first array element, grow the array
1164 * and insert it at the front.
1165 */
1166 if (gidset[0] != primary_gid) {
1167 new_gidset = SMB_MALLOC_ARRAY(gid_t, setlen + 1);
1168 if (new_gidset == NULL) {
1169 return -1;
1170 }
1171
1172 memcpy(new_gidset + 1, gidset, (setlen * sizeof(gid_t)));
1173 new_gidset[0] = primary_gid;
1174 setlen++;
1175 }
1176
1177 if (setlen > max) {
1178 DEBUG(3, ("forced to truncate group list from %d to %d\n",
1179 setlen, max));
1180 setlen = max;
1181 }
1182
1183#if defined(HAVE_BROKEN_GETGROUPS)
1184 ret = sys_broken_setgroups(setlen, new_gidset ? new_gidset : gidset);
1185#else
1186 ret = setgroups(setlen, new_gidset ? new_gidset : gidset);
1187#endif
1188
1189 if (new_gidset) {
1190 int errsav = errno;
1191 SAFE_FREE(new_gidset);
1192 errno = errsav;
1193 }
1194
1195 return ret;
1196}
1197
1198#endif /* USE_BSD_SETGROUPS */
1199
1200/**************************************************************************
1201 Wrapper for getgroups. Deals with broken (int) case.
1202****************************************************************************/
1203
1204int sys_getgroups(int setlen, gid_t *gidset)
1205{
1206#if defined(HAVE_BROKEN_GETGROUPS)
1207 return sys_broken_getgroups(setlen, gidset);
1208#else
1209 return getgroups(setlen, gidset);
1210#endif
1211}
1212
1213/**************************************************************************
1214 Wrapper for setgroups. Deals with broken (int) case and BSD case.
1215****************************************************************************/
1216
1217int sys_setgroups(gid_t UNUSED(primary_gid), int setlen, gid_t *gidset)
1218{
1219#if !defined(HAVE_SETGROUPS)
1220 errno = ENOSYS;
1221 return -1;
1222#endif /* HAVE_SETGROUPS */
1223
1224#if defined(USE_BSD_SETGROUPS)
1225 return sys_bsd_setgroups(primary_gid, setlen, gidset);
1226#elif defined(HAVE_BROKEN_GETGROUPS)
1227 return sys_broken_setgroups(setlen, gidset);
1228#else
1229 return setgroups(setlen, gidset);
1230#endif
1231}
1232
1233/**************************************************************************
1234 Wrappers for setpwent(), getpwent() and endpwent()
1235****************************************************************************/
1236
1237void sys_setpwent(void)
1238{
1239 setpwent();
1240}
1241
1242struct passwd *sys_getpwent(void)
1243{
1244 return getpwent();
1245}
1246
1247void sys_endpwent(void)
1248{
1249 endpwent();
1250}
1251
1252/**************************************************************************
1253 Wrappers for getpwnam(), getpwuid(), getgrnam(), getgrgid()
1254****************************************************************************/
1255
1256
1257struct passwd *sys_getpwnam(const char *name)
1258{
1259 return getpwnam(name);
1260}
1261
1262struct passwd *sys_getpwuid(uid_t uid)
1263{
1264 return getpwuid(uid);
1265}
1266
1267struct group *sys_getgrnam(const char *name)
1268{
1269 return getgrnam(name);
1270}
1271
1272struct group *sys_getgrgid(gid_t gid)
1273{
1274 return getgrgid(gid);
1275}
1276
1277/**************************************************************************
1278 Extract a command into an arg list.
1279****************************************************************************/
1280
1281static char **extract_args(TALLOC_CTX *mem_ctx, const char *command)
1282{
1283 char *trunc_cmd;
1284 char *saveptr;
1285 char *ptr;
1286 int argcl;
1287 char **argl = NULL;
1288 int i;
1289
1290 if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1291 DEBUG(0, ("talloc failed\n"));
1292 goto nomem;
1293 }
1294
1295 if(!(ptr = strtok_r(trunc_cmd, " \t", &saveptr))) {
1296 TALLOC_FREE(trunc_cmd);
1297 errno = EINVAL;
1298 return NULL;
1299 }
1300
1301 /*
1302 * Count the args.
1303 */
1304
1305 for( argcl = 1; ptr; ptr = strtok_r(NULL, " \t", &saveptr))
1306 argcl++;
1307
1308 TALLOC_FREE(trunc_cmd);
1309
1310 if (!(argl = TALLOC_ARRAY(mem_ctx, char *, argcl + 1))) {
1311 goto nomem;
1312 }
1313
1314 /*
1315 * Now do the extraction.
1316 */
1317
1318 if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1319 goto nomem;
1320 }
1321
1322 ptr = strtok_r(trunc_cmd, " \t", &saveptr);
1323 i = 0;
1324
1325 if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1326 goto nomem;
1327 }
1328
1329 while((ptr = strtok_r(NULL, " \t", &saveptr)) != NULL) {
1330
1331 if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1332 goto nomem;
1333 }
1334 }
1335
1336 argl[i++] = NULL;
1337 TALLOC_FREE(trunc_cmd);
1338 return argl;
1339
1340 nomem:
1341 DEBUG(0, ("talloc failed\n"));
1342 TALLOC_FREE(trunc_cmd);
1343 TALLOC_FREE(argl);
1344 errno = ENOMEM;
1345 return NULL;
1346}
1347
1348/**************************************************************************
1349 Wrapper for popen. Safer as it doesn't search a path.
1350 Modified from the glibc sources.
1351 modified by tridge to return a file descriptor. We must kick our FILE* habit
1352****************************************************************************/
1353
1354typedef struct _popen_list
1355{
1356 int fd;
1357 pid_t child_pid;
1358 struct _popen_list *next;
1359} popen_list;
1360
1361static popen_list *popen_chain;
1362
1363int sys_popen(const char *command)
1364{
1365 int parent_end, child_end;
1366 int pipe_fds[2];
1367 popen_list *entry = NULL;
1368 char **argl = NULL;
1369
1370 if (pipe(pipe_fds) < 0)
1371 return -1;
1372
1373 parent_end = pipe_fds[0];
1374 child_end = pipe_fds[1];
1375
1376 if (!*command) {
1377 errno = EINVAL;
1378 goto err_exit;
1379 }
1380
1381 if((entry = SMB_MALLOC_P(popen_list)) == NULL)
1382 goto err_exit;
1383
1384 ZERO_STRUCTP(entry);
1385
1386 /*
1387 * Extract the command and args into a NULL terminated array.
1388 */
1389
1390 if(!(argl = extract_args(NULL, command)))
1391 goto err_exit;
1392
1393 entry->child_pid = sys_fork();
1394
1395 if (entry->child_pid == -1) {
1396 goto err_exit;
1397 }
1398
1399 if (entry->child_pid == 0) {
1400
1401 /*
1402 * Child !
1403 */
1404
1405 int child_std_end = STDOUT_FILENO;
1406 popen_list *p;
1407
1408 close(parent_end);
1409 if (child_end != child_std_end) {
1410 dup2 (child_end, child_std_end);
1411 close (child_end);
1412 }
1413
1414 /*
1415 * POSIX.2: "popen() shall ensure that any streams from previous
1416 * popen() calls that remain open in the parent process are closed
1417 * in the new child process."
1418 */
1419
1420 for (p = popen_chain; p; p = p->next)
1421 close(p->fd);
1422
1423 execv(argl[0], argl);
1424 _exit (127);
1425 }
1426
1427 /*
1428 * Parent.
1429 */
1430
1431 close (child_end);
1432 TALLOC_FREE(argl);
1433
1434 /* Link into popen_chain. */
1435 entry->next = popen_chain;
1436 popen_chain = entry;
1437 entry->fd = parent_end;
1438
1439 return entry->fd;
1440
1441err_exit:
1442
1443 SAFE_FREE(entry);
1444 SAFE_FREE(argl);
1445 close(pipe_fds[0]);
1446 close(pipe_fds[1]);
1447 return -1;
1448}
1449
1450/**************************************************************************
1451 Wrapper for pclose. Modified from the glibc sources.
1452****************************************************************************/
1453
1454int sys_pclose(int fd)
1455{
1456 int wstatus;
1457 popen_list **ptr = &popen_chain;
1458 popen_list *entry = NULL;
1459 pid_t wait_pid;
1460 int status = -1;
1461
1462 /* Unlink from popen_chain. */
1463 for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
1464 if ((*ptr)->fd == fd) {
1465 entry = *ptr;
1466 *ptr = (*ptr)->next;
1467 status = 0;
1468 break;
1469 }
1470 }
1471
1472 if (status < 0 || close(entry->fd) < 0)
1473 return -1;
1474
1475 /*
1476 * As Samba is catching and eating child process
1477 * exits we don't really care about the child exit
1478 * code, a -1 with errno = ECHILD will do fine for us.
1479 */
1480
1481 do {
1482 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
1483 } while (wait_pid == -1 && errno == EINTR);
1484
1485 SAFE_FREE(entry);
1486
1487 if (wait_pid == -1)
1488 return -1;
1489 return wstatus;
1490}
1491
1492/**************************************************************************
1493 Wrapper for Admin Logs.
1494****************************************************************************/
1495
1496 void sys_adminlog(int priority, const char *format_str, ...)
1497{
1498 va_list ap;
1499 int ret;
1500 char *msgbuf = NULL;
1501
1502 va_start( ap, format_str );
1503 ret = vasprintf( &msgbuf, format_str, ap );
1504 va_end( ap );
1505
1506 if (ret == -1)
1507 return;
1508
1509#if defined(HAVE_SYSLOG)
1510 syslog( priority, "%s", msgbuf );
1511#else
1512 DEBUG(0,("%s", msgbuf ));
1513#endif
1514 SAFE_FREE(msgbuf);
1515}
1516
1517/******** Solaris EA helper function prototypes ********/
1518#ifdef HAVE_ATTROPEN
1519#define SOLARIS_ATTRMODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP
1520static int solaris_write_xattr(int attrfd, const char *value, size_t size);
1521static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size);
1522static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size);
1523static int solaris_unlinkat(int attrdirfd, const char *name);
1524static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode);
1525static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode);
1526#endif
1527
1528/**************************************************************************
1529 Wrappers for extented attribute calls. Based on the Linux package with
1530 support for IRIX and (Net|Free)BSD also. Expand as other systems have them.
1531****************************************************************************/
1532
1533ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t size)
1534{
1535#if defined(HAVE_GETXATTR)
1536#ifndef XATTR_ADD_OPT
1537 return getxattr(path, name, value, size);
1538#else
1539 int options = 0;
1540 return getxattr(path, name, value, size, 0, options);
1541#endif
1542#elif defined(HAVE_GETEA)
1543 return getea(path, name, value, size);
1544#elif defined(HAVE_EXTATTR_GET_FILE)
1545 char *s;
1546 ssize_t retval;
1547 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1548 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1549 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1550 /*
1551 * The BSD implementation has a nasty habit of silently truncating
1552 * the returned value to the size of the buffer, so we have to check
1553 * that the buffer is large enough to fit the returned value.
1554 */
1555 if((retval=extattr_get_file(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1556 if(retval > size) {
1557 errno = ERANGE;
1558 return -1;
1559 }
1560 if((retval=extattr_get_file(path, attrnamespace, attrname, value, size)) >= 0)
1561 return retval;
1562 }
1563
1564 DEBUG(10,("sys_getxattr: extattr_get_file() failed with: %s\n", strerror(errno)));
1565 return -1;
1566#elif defined(HAVE_ATTR_GET)
1567 int retval, flags = 0;
1568 int valuelength = (int)size;
1569 char *attrname = strchr(name,'.') + 1;
1570
1571 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1572
1573 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1574
1575 return retval ? retval : valuelength;
1576#elif defined(HAVE_ATTROPEN)
1577 ssize_t ret = -1;
1578 int attrfd = solaris_attropen(path, name, O_RDONLY, 0);
1579 if (attrfd >= 0) {
1580 ret = solaris_read_xattr(attrfd, value, size);
1581 close(attrfd);
1582 }
1583 return ret;
1584#elif defined(__OS2__)
1585 return unigetxattr(path, 0, name, value, size);
1586#else
1587 errno = ENOSYS;
1588 return -1;
1589#endif
1590}
1591
1592ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t size)
1593{
1594#if defined(HAVE_LGETXATTR)
1595 return lgetxattr(path, name, value, size);
1596#elif defined(HAVE_GETXATTR) && defined(XATTR_ADD_OPT)
1597 int options = XATTR_NOFOLLOW;
1598 return getxattr(path, name, value, size, 0, options);
1599#elif defined(HAVE_LGETEA)
1600 return lgetea(path, name, value, size);
1601#elif defined(HAVE_EXTATTR_GET_LINK)
1602 char *s;
1603 ssize_t retval;
1604 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1605 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1606 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1607
1608 if((retval=extattr_get_link(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1609 if(retval > size) {
1610 errno = ERANGE;
1611 return -1;
1612 }
1613 if((retval=extattr_get_link(path, attrnamespace, attrname, value, size)) >= 0)
1614 return retval;
1615 }
1616
1617 DEBUG(10,("sys_lgetxattr: extattr_get_link() failed with: %s\n", strerror(errno)));
1618 return -1;
1619#elif defined(HAVE_ATTR_GET)
1620 int retval, flags = ATTR_DONTFOLLOW;
1621 int valuelength = (int)size;
1622 char *attrname = strchr(name,'.') + 1;
1623
1624 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1625
1626 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1627
1628 return retval ? retval : valuelength;
1629#elif defined(HAVE_ATTROPEN)
1630 ssize_t ret = -1;
1631 int attrfd = solaris_attropen(path, name, O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1632 if (attrfd >= 0) {
1633 ret = solaris_read_xattr(attrfd, value, size);
1634 close(attrfd);
1635 }
1636 return ret;
1637#elif defined(__OS2__)
1638 return unigetxattr(path, 0, name, value, size);
1639#else
1640 errno = ENOSYS;
1641 return -1;
1642#endif
1643}
1644
1645ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size)
1646{
1647#if defined(HAVE_FGETXATTR)
1648#ifndef XATTR_ADD_OPT
1649 return fgetxattr(filedes, name, value, size);
1650#else
1651 int options = 0;
1652 return fgetxattr(filedes, name, value, size, 0, options);
1653#endif
1654#elif defined(HAVE_FGETEA)
1655 return fgetea(filedes, name, value, size);
1656#elif defined(HAVE_EXTATTR_GET_FD)
1657 char *s;
1658 ssize_t retval;
1659 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1660 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1661 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1662
1663 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0)) >= 0) {
1664 if(retval > size) {
1665 errno = ERANGE;
1666 return -1;
1667 }
1668 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, value, size)) >= 0)
1669 return retval;
1670 }
1671
1672 DEBUG(10,("sys_fgetxattr: extattr_get_fd() failed with: %s\n", strerror(errno)));
1673 return -1;
1674#elif defined(HAVE_ATTR_GETF)
1675 int retval, flags = 0;
1676 int valuelength = (int)size;
1677 char *attrname = strchr(name,'.') + 1;
1678
1679 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1680
1681 retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags);
1682
1683 return retval ? retval : valuelength;
1684#elif defined(HAVE_ATTROPEN)
1685 ssize_t ret = -1;
1686 int attrfd = solaris_openat(filedes, name, O_RDONLY|O_XATTR, 0);
1687 if (attrfd >= 0) {
1688 ret = solaris_read_xattr(attrfd, value, size);
1689 close(attrfd);
1690 }
1691 return ret;
1692#elif defined(__OS2__)
1693 return unigetxattr(0, filedes, name, value, size);
1694#else
1695 errno = ENOSYS;
1696 return -1;
1697#endif
1698}
1699
1700#if defined(HAVE_EXTATTR_LIST_FILE)
1701
1702#define EXTATTR_PREFIX(s) (s), (sizeof((s))-1)
1703
1704static struct {
1705 int space;
1706 const char *name;
1707 size_t len;
1708}
1709extattr[] = {
1710 { EXTATTR_NAMESPACE_SYSTEM, EXTATTR_PREFIX("system.") },
1711 { EXTATTR_NAMESPACE_USER, EXTATTR_PREFIX("user.") },
1712};
1713
1714typedef union {
1715 const char *path;
1716 int filedes;
1717} extattr_arg;
1718
1719static ssize_t bsd_attr_list (int type, extattr_arg arg, char *list, size_t size)
1720{
1721 ssize_t list_size, total_size = 0;
1722 int i, t, len;
1723 char *buf;
1724 /* Iterate through extattr(2) namespaces */
1725 for(t = 0; t < (sizeof(extattr)/sizeof(extattr[0])); t++) {
1726 switch(type) {
1727#if defined(HAVE_EXTATTR_LIST_FILE)
1728 case 0:
1729 list_size = extattr_list_file(arg.path, extattr[t].space, list, size);
1730 break;
1731#endif
1732#if defined(HAVE_EXTATTR_LIST_LINK)
1733 case 1:
1734 list_size = extattr_list_link(arg.path, extattr[t].space, list, size);
1735 break;
1736#endif
1737#if defined(HAVE_EXTATTR_LIST_FD)
1738 case 2:
1739 list_size = extattr_list_fd(arg.filedes, extattr[t].space, list, size);
1740 break;
1741#endif
1742 default:
1743 errno = ENOSYS;
1744 return -1;
1745 }
1746 /* Some error happend. Errno should be set by the previous call */
1747 if(list_size < 0)
1748 return -1;
1749 /* No attributes */
1750 if(list_size == 0)
1751 continue;
1752 /* XXX: Call with an empty buffer may be used to calculate
1753 necessary buffer size. Unfortunately, we can't say, how
1754 many attributes were returned, so here is the potential
1755 problem with the emulation.
1756 */
1757 if(list == NULL) {
1758 /* Take the worse case of one char attribute names -
1759 two bytes per name plus one more for sanity.
1760 */
1761 total_size += list_size + (list_size/2 + 1)*extattr[t].len;
1762 continue;
1763 }
1764 /* Count necessary offset to fit namespace prefixes */
1765 len = 0;
1766 for(i = 0; i < list_size; i += list[i] + 1)
1767 len += extattr[t].len;
1768
1769 total_size += list_size + len;
1770 /* Buffer is too small to fit the results */
1771 if(total_size > size) {
1772 errno = ERANGE;
1773 return -1;
1774 }
1775 /* Shift results back, so we can prepend prefixes */
1776 buf = memmove(list + len, list, list_size);
1777
1778 for(i = 0; i < list_size; i += len + 1) {
1779 len = buf[i];
1780 strncpy(list, extattr[t].name, extattr[t].len + 1);
1781 list += extattr[t].len;
1782 strncpy(list, buf + i + 1, len);
1783 list[len] = '\0';
1784 list += len + 1;
1785 }
1786 size -= total_size;
1787 }
1788 return total_size;
1789}
1790
1791#endif
1792
1793#if defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1794static char attr_buffer[ATTR_MAX_VALUELEN];
1795
1796static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags)
1797{
1798 int retval = 0, index;
1799 attrlist_cursor_t *cursor = 0;
1800 int total_size = 0;
1801 attrlist_t * al = (attrlist_t *)attr_buffer;
1802 attrlist_ent_t *ae;
1803 size_t ent_size, left = size;
1804 char *bp = list;
1805
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("user.");
1815 if (left >= ent_size) {
1816 strncpy(bp, "user.", sizeof("user."));
1817 strncat(bp, ae->a_name, ent_size - sizeof("user."));
1818 bp += ent_size;
1819 left -= ent_size;
1820 } else if (size) {
1821 errno = ERANGE;
1822 retval = -1;
1823 break;
1824 }
1825 total_size += ent_size;
1826 }
1827 if (al->al_more == 0) break;
1828 }
1829 if (retval == 0) {
1830 flags |= ATTR_ROOT;
1831 cursor = 0;
1832 while (True) {
1833 if (filedes)
1834 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1835 else
1836 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1837 if (retval) break;
1838 for (index = 0; index < al->al_count; index++) {
1839 ae = ATTR_ENTRY(attr_buffer, index);
1840 ent_size = strlen(ae->a_name) + sizeof("system.");
1841 if (left >= ent_size) {
1842 strncpy(bp, "system.", sizeof("system."));
1843 strncat(bp, ae->a_name, ent_size - sizeof("system."));
1844 bp += ent_size;
1845 left -= ent_size;
1846 } else if (size) {
1847 errno = ERANGE;
1848 retval = -1;
1849 break;
1850 }
1851 total_size += ent_size;
1852 }
1853 if (al->al_more == 0) break;
1854 }
1855 }
1856 return (ssize_t)(retval ? retval : total_size);
1857}
1858
1859#endif
1860
1861ssize_t sys_listxattr (const char *path, char *list, size_t size)
1862{
1863#if defined(HAVE_LISTXATTR)
1864#ifndef XATTR_ADD_OPT
1865 return listxattr(path, list, size);
1866#else
1867 int options = 0;
1868 return listxattr(path, list, size, options);
1869#endif
1870#elif defined(HAVE_LISTEA)
1871 return listea(path, list, size);
1872#elif defined(HAVE_EXTATTR_LIST_FILE)
1873 extattr_arg arg;
1874 arg.path = path;
1875 return bsd_attr_list(0, arg, list, size);
1876#elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1877 return irix_attr_list(path, 0, list, size, 0);
1878#elif defined(HAVE_ATTROPEN)
1879 ssize_t ret = -1;
1880 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
1881 if (attrdirfd >= 0) {
1882 ret = solaris_list_xattr(attrdirfd, list, size);
1883 close(attrdirfd);
1884 }
1885 return ret;
1886#elif defined(__OS2__)
1887 return unilistxattr(path, 0, list, size);
1888#else
1889 errno = ENOSYS;
1890 return -1;
1891#endif
1892}
1893
1894ssize_t sys_llistxattr (const char *path, char *list, size_t size)
1895{
1896#if defined(HAVE_LLISTXATTR)
1897 return llistxattr(path, list, size);
1898#elif defined(HAVE_LISTXATTR) && defined(XATTR_ADD_OPT)
1899 int options = XATTR_NOFOLLOW;
1900 return listxattr(path, list, size, options);
1901#elif defined(HAVE_LLISTEA)
1902 return llistea(path, list, size);
1903#elif defined(HAVE_EXTATTR_LIST_LINK)
1904 extattr_arg arg;
1905 arg.path = path;
1906 return bsd_attr_list(1, arg, list, size);
1907#elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1908 return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW);
1909#elif defined(HAVE_ATTROPEN)
1910 ssize_t ret = -1;
1911 int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1912 if (attrdirfd >= 0) {
1913 ret = solaris_list_xattr(attrdirfd, list, size);
1914 close(attrdirfd);
1915 }
1916 return ret;
1917#elif defined(__OS2__)
1918 return unilistxattr(path, 0, list, size);
1919#else
1920 errno = ENOSYS;
1921 return -1;
1922#endif
1923}
1924
1925ssize_t sys_flistxattr (int filedes, char *list, size_t size)
1926{
1927#if defined(HAVE_FLISTXATTR)
1928#ifndef XATTR_ADD_OPT
1929 return flistxattr(filedes, list, size);
1930#else
1931 int options = 0;
1932 return flistxattr(filedes, list, size, options);
1933#endif
1934#elif defined(HAVE_FLISTEA)
1935 return flistea(filedes, list, size);
1936#elif defined(HAVE_EXTATTR_LIST_FD)
1937 extattr_arg arg;
1938 arg.filedes = filedes;
1939 return bsd_attr_list(2, arg, list, size);
1940#elif defined(HAVE_ATTR_LISTF)
1941 return irix_attr_list(NULL, filedes, list, size, 0);
1942#elif defined(HAVE_ATTROPEN)
1943 ssize_t ret = -1;
1944 int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
1945 if (attrdirfd >= 0) {
1946 ret = solaris_list_xattr(attrdirfd, list, size);
1947 close(attrdirfd);
1948 }
1949 return ret;
1950#elif defined(__OS2__)
1951 return unilistxattr(0, filedes, list, size);
1952#else
1953 errno = ENOSYS;
1954 return -1;
1955#endif
1956}
1957
1958int sys_removexattr (const char *path, const char *name)
1959{
1960#if defined(HAVE_REMOVEXATTR)
1961#ifndef XATTR_ADD_OPT
1962 return removexattr(path, name);
1963#else
1964 int options = 0;
1965 return removexattr(path, name, options);
1966#endif
1967#elif defined(HAVE_REMOVEEA)
1968 return removeea(path, name);
1969#elif defined(HAVE_EXTATTR_DELETE_FILE)
1970 char *s;
1971 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1972 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1973 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1974
1975 return extattr_delete_file(path, attrnamespace, attrname);
1976#elif defined(HAVE_ATTR_REMOVE)
1977 int flags = 0;
1978 char *attrname = strchr(name,'.') + 1;
1979
1980 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1981
1982 return attr_remove(path, attrname, flags);
1983#elif defined(HAVE_ATTROPEN)
1984 int ret = -1;
1985 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
1986 if (attrdirfd >= 0) {
1987 ret = solaris_unlinkat(attrdirfd, name);
1988 close(attrdirfd);
1989 }
1990 return ret;
1991#elif defined(__OS2__)
1992 return uniremovexattr (path, 0, name);
1993#else
1994 errno = ENOSYS;
1995 return -1;
1996#endif
1997}
1998
1999int sys_lremovexattr (const char *path, const char *name)
2000{
2001#if defined(HAVE_LREMOVEXATTR)
2002 return lremovexattr(path, name);
2003#elif defined(HAVE_REMOVEXATTR) && defined(XATTR_ADD_OPT)
2004 int options = XATTR_NOFOLLOW;
2005 return removexattr(path, name, options);
2006#elif defined(HAVE_LREMOVEEA)
2007 return lremoveea(path, name);
2008#elif defined(HAVE_EXTATTR_DELETE_LINK)
2009 char *s;
2010 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2011 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2012 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2013
2014 return extattr_delete_link(path, attrnamespace, attrname);
2015#elif defined(HAVE_ATTR_REMOVE)
2016 int flags = ATTR_DONTFOLLOW;
2017 char *attrname = strchr(name,'.') + 1;
2018
2019 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
2020
2021 return attr_remove(path, attrname, flags);
2022#elif defined(HAVE_ATTROPEN)
2023 int ret = -1;
2024 int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
2025 if (attrdirfd >= 0) {
2026 ret = solaris_unlinkat(attrdirfd, name);
2027 close(attrdirfd);
2028 }
2029 return ret;
2030#elif defined(__OS2__)
2031 return uniremovexattr (path, 0, name);
2032#else
2033 errno = ENOSYS;
2034 return -1;
2035#endif
2036}
2037
2038int sys_fremovexattr (int filedes, const char *name)
2039{
2040#if defined(HAVE_FREMOVEXATTR)
2041#ifndef XATTR_ADD_OPT
2042 return fremovexattr(filedes, name);
2043#else
2044 int options = 0;
2045 return fremovexattr(filedes, name, options);
2046#endif
2047#elif defined(HAVE_FREMOVEEA)
2048 return fremoveea(filedes, name);
2049#elif defined(HAVE_EXTATTR_DELETE_FD)
2050 char *s;
2051 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2052 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2053 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2054
2055 return extattr_delete_fd(filedes, attrnamespace, attrname);
2056#elif defined(HAVE_ATTR_REMOVEF)
2057 int flags = 0;
2058 char *attrname = strchr(name,'.') + 1;
2059
2060 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
2061
2062 return attr_removef(filedes, attrname, flags);
2063#elif defined(HAVE_ATTROPEN)
2064 int ret = -1;
2065 int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
2066 if (attrdirfd >= 0) {
2067 ret = solaris_unlinkat(attrdirfd, name);
2068 close(attrdirfd);
2069 }
2070 return ret;
2071#elif defined(__OS2__)
2072 return uniremovexattr (0, filedes, name);
2073#else
2074 errno = ENOSYS;
2075 return -1;
2076#endif
2077}
2078
2079int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags)
2080{
2081#if defined(HAVE_SETXATTR)
2082#ifndef XATTR_ADD_OPT
2083 return setxattr(path, name, value, size, flags);
2084#else
2085 int options = 0;
2086 return setxattr(path, name, value, size, 0, options);
2087#endif
2088#elif defined(HAVE_SETEA)
2089 return setea(path, name, value, size, flags);
2090#elif defined(HAVE_EXTATTR_SET_FILE)
2091 char *s;
2092 int retval = 0;
2093 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2094 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2095 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2096 if (flags) {
2097 /* Check attribute existence */
2098 retval = extattr_get_file(path, attrnamespace, attrname, NULL, 0);
2099 if (retval < 0) {
2100 /* REPLACE attribute, that doesn't exist */
2101 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2102 errno = ENOATTR;
2103 return -1;
2104 }
2105 /* Ignore other errors */
2106 }
2107 else {
2108 /* CREATE attribute, that already exists */
2109 if (flags & XATTR_CREATE) {
2110 errno = EEXIST;
2111 return -1;
2112 }
2113 }
2114 }
2115 retval = extattr_set_file(path, attrnamespace, attrname, value, size);
2116 return (retval < 0) ? -1 : 0;
2117#elif defined(HAVE_ATTR_SET)
2118 int myflags = 0;
2119 char *attrname = strchr(name,'.') + 1;
2120
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;
2124
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;
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);
2136 }
2137 return ret;
2138#elif defined(__OS2__)
2139 return unisetxattr (path, 0, name, value, size, flags);
2140#else
2141 errno = ENOSYS;
2142 return -1;
2143#endif
2144}
2145
2146int sys_lsetxattr (const char *path, const char *name, const void *value, size_t size, int flags)
2147{
2148#if defined(HAVE_LSETXATTR)
2149 return lsetxattr(path, name, value, size, flags);
2150#elif defined(HAVE_SETXATTR) && defined(XATTR_ADD_OPT)
2151 int options = XATTR_NOFOLLOW;
2152 return setxattr(path, name, value, size, 0, options);
2153#elif defined(LSETEA)
2154 return lsetea(path, name, value, size, flags);
2155#elif defined(HAVE_EXTATTR_SET_LINK)
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_link(path, 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;
2169 }
2170 /* Ignore other errors */
2171 }
2172 else {
2173 /* CREATE attribute, that already exists */
2174 if (flags & XATTR_CREATE) {
2175 errno = EEXIST;
2176 return -1;
2177 }
2178 }
2179 }
2180
2181 retval = extattr_set_link(path, attrnamespace, attrname, value, size);
2182 return (retval < 0) ? -1 : 0;
2183#elif defined(HAVE_ATTR_SET)
2184 int myflags = ATTR_DONTFOLLOW;
2185 char *attrname = strchr(name,'.') + 1;
2186
2187 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2188 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2189 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2190
2191 return attr_set(path, attrname, (const char *)value, size, myflags);
2192#elif defined(HAVE_ATTROPEN)
2193 int ret = -1;
2194 int myflags = O_RDWR | AT_SYMLINK_NOFOLLOW;
2195 int attrfd;
2196 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2197 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2198 attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2199 if (attrfd >= 0) {
2200 ret = solaris_write_xattr(attrfd, value, size);
2201 close(attrfd);
2202 }
2203 return ret;
2204#elif defined(__OS2__)
2205 return unisetxattr (path, 0, name, value, size, flags);
2206#else
2207 errno = ENOSYS;
2208 return -1;
2209#endif
2210}
2211
2212int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags)
2213{
2214#if defined(HAVE_FSETXATTR)
2215#ifndef XATTR_ADD_OPT
2216 return fsetxattr(filedes, name, value, size, flags);
2217#else
2218 int options = 0;
2219 return fsetxattr(filedes, name, value, size, 0, options);
2220#endif
2221#elif defined(HAVE_FSETEA)
2222 return fsetea(filedes, name, value, size, flags);
2223#elif defined(HAVE_EXTATTR_SET_FD)
2224 char *s;
2225 int retval = 0;
2226 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2227 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2228 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2229 if (flags) {
2230 /* Check attribute existence */
2231 retval = extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0);
2232 if (retval < 0) {
2233 /* REPLACE attribute, that doesn't exist */
2234 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2235 errno = ENOATTR;
2236 return -1;
2237 }
2238 /* Ignore other errors */
2239 }
2240 else {
2241 /* CREATE attribute, that already exists */
2242 if (flags & XATTR_CREATE) {
2243 errno = EEXIST;
2244 return -1;
2245 }
2246 }
2247 }
2248 retval = extattr_set_fd(filedes, attrnamespace, attrname, value, size);
2249 return (retval < 0) ? -1 : 0;
2250#elif defined(HAVE_ATTR_SETF)
2251 int myflags = 0;
2252 char *attrname = strchr(name,'.') + 1;
2253
2254 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2255 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2256 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2257
2258 return attr_setf(filedes, attrname, (const char *)value, size, myflags);
2259#elif defined(HAVE_ATTROPEN)
2260 int ret = -1;
2261 int myflags = O_RDWR | O_XATTR;
2262 int attrfd;
2263 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2264 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2265 attrfd = solaris_openat(filedes, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2266 if (attrfd >= 0) {
2267 ret = solaris_write_xattr(attrfd, value, size);
2268 close(attrfd);
2269 }
2270 return ret;
2271#elif defined(__OS2__)
2272 return unisetxattr (0, filedes, name, value, size, flags);
2273#else
2274 errno = ENOSYS;
2275 return -1;
2276#endif
2277}
2278
2279/**************************************************************************
2280 helper functions for Solaris' EA support
2281****************************************************************************/
2282#ifdef HAVE_ATTROPEN
2283static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size)
2284{
2285 struct stat sbuf;
2286
2287 if (fstat(attrfd, &sbuf) == -1) {
2288 errno = ENOATTR;
2289 return -1;
2290 }
2291
2292 /* This is to return the current size of the named extended attribute */
2293 if (size == 0) {
2294 return sbuf.st_size;
2295 }
2296
2297 /* check size and read xattr */
2298 if (sbuf.st_size > size) {
2299 errno = ERANGE;
2300 return -1;
2301 }
2302
2303 return read(attrfd, value, sbuf.st_size);
2304}
2305
2306static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size)
2307{
2308 ssize_t len = 0;
2309 DIR *dirp;
2310 struct dirent *de;
2311 int newfd = dup(attrdirfd);
2312 /* CAUTION: The originating file descriptor should not be
2313 used again following the call to fdopendir().
2314 For that reason we dup() the file descriptor
2315 here to make things more clear. */
2316 dirp = fdopendir(newfd);
2317
2318 while ((de = readdir(dirp))) {
2319 size_t listlen = strlen(de->d_name);
2320 if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) {
2321 /* we don't want "." and ".." here: */
2322 DEBUG(10,("skipped EA %s\n",de->d_name));
2323 continue;
2324 }
2325
2326 if (size == 0) {
2327 /* return the current size of the list of extended attribute names*/
2328 len += listlen + 1;
2329 } else {
2330 /* check size and copy entrieѕ + nul into list. */
2331 if ((len + listlen + 1) > size) {
2332 errno = ERANGE;
2333 len = -1;
2334 break;
2335 } else {
2336 safe_strcpy(list + len, de->d_name, listlen);
2337 len += listlen;
2338 list[len] = '\0';
2339 ++len;
2340 }
2341 }
2342 }
2343
2344 if (closedir(dirp) == -1) {
2345 DEBUG(0,("closedir dirp failed: %s\n",strerror(errno)));
2346 return -1;
2347 }
2348 return len;
2349}
2350
2351static int solaris_unlinkat(int attrdirfd, const char *name)
2352{
2353 if (unlinkat(attrdirfd, name, 0) == -1) {
2354 if (errno == ENOENT) {
2355 errno = ENOATTR;
2356 }
2357 return -1;
2358 }
2359 return 0;
2360}
2361
2362static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode)
2363{
2364 int filedes = attropen(path, attrpath, oflag, mode);
2365 if (filedes == -1) {
2366 DEBUG(10,("attropen FAILED: path: %s, name: %s, errno: %s\n",path,attrpath,strerror(errno)));
2367 if (errno == EINVAL) {
2368 errno = ENOTSUP;
2369 } else {
2370 errno = ENOATTR;
2371 }
2372 }
2373 return filedes;
2374}
2375
2376static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode)
2377{
2378 int filedes = openat(fildes, path, oflag, mode);
2379 if (filedes == -1) {
2380 DEBUG(10,("openat FAILED: fd: %d, path: %s, errno: %s\n",filedes,path,strerror(errno)));
2381 if (errno == EINVAL) {
2382 errno = ENOTSUP;
2383 } else {
2384 errno = ENOATTR;
2385 }
2386 }
2387 return filedes;
2388}
2389
2390static int solaris_write_xattr(int attrfd, const char *value, size_t size)
2391{
2392 if ((ftruncate(attrfd, 0) == 0) && (write(attrfd, value, size) == size)) {
2393 return 0;
2394 } else {
2395 DEBUG(10,("solaris_write_xattr FAILED!\n"));
2396 return -1;
2397 }
2398}
2399#endif /*HAVE_ATTROPEN*/
2400
2401
2402/****************************************************************************
2403 Return the major devicenumber for UNIX extensions.
2404****************************************************************************/
2405
2406uint32 unix_dev_major(SMB_DEV_T dev)
2407{
2408#if defined(HAVE_DEVICE_MAJOR_FN)
2409 return (uint32)major(dev);
2410#else
2411 return (uint32)(dev >> 8);
2412#endif
2413}
2414
2415/****************************************************************************
2416 Return the minor devicenumber for UNIX extensions.
2417****************************************************************************/
2418
2419uint32 unix_dev_minor(SMB_DEV_T dev)
2420{
2421#if defined(HAVE_DEVICE_MINOR_FN)
2422 return (uint32)minor(dev);
2423#else
2424 return (uint32)(dev & 0xff);
2425#endif
2426}
2427
2428#if defined(WITH_AIO)
2429
2430/*******************************************************************
2431 An aio_read wrapper that will deal with 64-bit sizes.
2432********************************************************************/
2433
2434int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2435{
2436#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_READ64)
2437 return aio_read64(aiocb);
2438#elif defined(HAVE_AIO_READ)
2439 return aio_read(aiocb);
2440#else
2441 errno = ENOSYS;
2442 return -1;
2443#endif
2444}
2445
2446/*******************************************************************
2447 An aio_write wrapper that will deal with 64-bit sizes.
2448********************************************************************/
2449
2450int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2451{
2452#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_WRITE64)
2453 return aio_write64(aiocb);
2454#elif defined(HAVE_AIO_WRITE)
2455 return aio_write(aiocb);
2456#else
2457 errno = ENOSYS;
2458 return -1;
2459#endif
2460}
2461
2462/*******************************************************************
2463 An aio_return wrapper that will deal with 64-bit sizes.
2464********************************************************************/
2465
2466ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2467{
2468#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_RETURN64)
2469 return aio_return64(aiocb);
2470#elif defined(HAVE_AIO_RETURN)
2471 return aio_return(aiocb);
2472#else
2473 errno = ENOSYS;
2474 return -1;
2475#endif
2476}
2477
2478/*******************************************************************
2479 An aio_cancel wrapper that will deal with 64-bit sizes.
2480********************************************************************/
2481
2482int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2483{
2484#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_CANCEL64)
2485 return aio_cancel64(fd, aiocb);
2486#elif defined(HAVE_AIO_CANCEL)
2487 return aio_cancel(fd, aiocb);
2488#else
2489 errno = ENOSYS;
2490 return -1;
2491#endif
2492}
2493
2494/*******************************************************************
2495 An aio_error wrapper that will deal with 64-bit sizes.
2496********************************************************************/
2497
2498int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2499{
2500#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_ERROR64)
2501 return aio_error64(aiocb);
2502#elif defined(HAVE_AIO_ERROR)
2503 return aio_error(aiocb);
2504#else
2505 errno = ENOSYS;
2506 return -1;
2507#endif
2508}
2509
2510/*******************************************************************
2511 An aio_fsync wrapper that will deal with 64-bit sizes.
2512********************************************************************/
2513
2514int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2515{
2516#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_FSYNC64)
2517 return aio_fsync64(op, aiocb);
2518#elif defined(HAVE_AIO_FSYNC)
2519 return aio_fsync(op, aiocb);
2520#else
2521 errno = ENOSYS;
2522 return -1;
2523#endif
2524}
2525
2526/*******************************************************************
2527 An aio_fsync wrapper that will deal with 64-bit sizes.
2528********************************************************************/
2529
2530int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2531{
2532#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_SUSPEND64)
2533 return aio_suspend64(cblist, n, timeout);
2534#elif defined(HAVE_AIO_FSYNC)
2535 return aio_suspend(cblist, n, timeout);
2536#else
2537 errno = ENOSYS;
2538 return -1;
2539#endif
2540}
2541#else /* !WITH_AIO */
2542
2543int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2544{
2545 errno = ENOSYS;
2546 return -1;
2547}
2548
2549int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2550{
2551 errno = ENOSYS;
2552 return -1;
2553}
2554
2555ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2556{
2557 errno = ENOSYS;
2558 return -1;
2559}
2560
2561int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2562{
2563 errno = ENOSYS;
2564 return -1;
2565}
2566
2567int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2568{
2569 errno = ENOSYS;
2570 return -1;
2571}
2572
2573int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2574{
2575 errno = ENOSYS;
2576 return -1;
2577}
2578
2579int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2580{
2581 errno = ENOSYS;
2582 return -1;
2583}
2584#endif /* WITH_AIO */
2585
2586int sys_getpeereid( int s, uid_t *uid)
2587{
2588#if defined(HAVE_PEERCRED)
2589 struct ucred cred;
2590 socklen_t cred_len = sizeof(struct ucred);
2591 int ret;
2592
2593 ret = getsockopt(s, SOL_SOCKET, SO_PEERCRED, (void *)&cred, &cred_len);
2594 if (ret != 0) {
2595 return -1;
2596 }
2597
2598 if (cred_len != sizeof(struct ucred)) {
2599 errno = EINVAL;
2600 return -1;
2601 }
2602
2603 *uid = cred.uid;
2604 return 0;
2605#else
2606 errno = ENOSYS;
2607 return -1;
2608#endif
2609}
2610
2611int sys_getnameinfo(const struct sockaddr *psa,
2612 socklen_t salen,
2613 char *host,
2614 size_t hostlen,
2615 char *service,
2616 size_t servlen,
2617 int flags)
2618{
2619 /*
2620 * For Solaris we must make sure salen is the
2621 * correct length for the incoming sa_family.
2622 */
2623
2624 if (salen == sizeof(struct sockaddr_storage)) {
2625 salen = sizeof(struct sockaddr_in);
2626#if defined(HAVE_IPV6)
2627 if (psa->sa_family == AF_INET6) {
2628 salen = sizeof(struct sockaddr_in6);
2629 }
2630#endif
2631 }
2632 return getnameinfo(psa, salen, host, hostlen, service, servlen, flags);
2633}
2634
2635int sys_connect(int fd, const struct sockaddr * addr)
2636{
2637 socklen_t salen = -1;
2638
2639 if (addr->sa_family == AF_INET) {
2640 salen = sizeof(struct sockaddr_in);
2641 } else if (addr->sa_family == AF_UNIX) {
2642 salen = sizeof(struct sockaddr_un);
2643 }
2644#if defined(HAVE_IPV6)
2645 else if (addr->sa_family == AF_INET6) {
2646 salen = sizeof(struct sockaddr_in6);
2647 }
2648#endif
2649
2650 return connect(fd, addr, salen);
2651}
Note: See TracBrowser for help on using the repository browser.