source: trunk/server/source3/lib/system.c@ 853

Last change on this file since 853 was 751, checked in by Silvan Scherrer, 13 years ago

Samba Server: updated trunk to 3.6.9

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