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

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

Samba Server: updated trunk to 3.6.0

File size: 73.8 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#else
778 return fseek(fp, offset, whence);
779#endif
780}
781
782/*******************************************************************
783 An ftell() wrapper that will deal with 64 bit filesizes.
784********************************************************************/
785
786SMB_OFF_T sys_ftell(FILE *fp)
787{
788#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELL64)
789 return (SMB_OFF_T)ftell64(fp);
790#elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELLO64)
791 return (SMB_OFF_T)ftello64(fp);
792#else
793 return (SMB_OFF_T)ftell(fp);
794#endif
795}
796
797/*******************************************************************
798 A creat() wrapper that will deal with 64 bit filesizes.
799********************************************************************/
800
801int sys_creat(const char *path, mode_t mode)
802{
803#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CREAT64)
804 return creat64(path, mode);
805#else
806 /*
807 * If creat64 isn't defined then ensure we call a potential open64.
808 * JRA.
809 */
810 return sys_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
811#endif
812}
813
814/*******************************************************************
815 An open() wrapper that will deal with 64 bit filesizes.
816********************************************************************/
817
818int sys_open(const char *path, int oflag, mode_t mode)
819{
820#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPEN64)
821 return open64(path, oflag, mode);
822#else
823 return open(path, oflag, mode);
824#endif
825}
826
827/*******************************************************************
828 An fopen() wrapper that will deal with 64 bit filesizes.
829********************************************************************/
830
831FILE *sys_fopen(const char *path, const char *type)
832{
833#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FOPEN64)
834 return fopen64(path, type);
835#else
836 return fopen(path, type);
837#endif
838}
839
840
841#if HAVE_KERNEL_SHARE_MODES
842#ifndef LOCK_MAND
843#define LOCK_MAND 32 /* This is a mandatory flock */
844#define LOCK_READ 64 /* ... Which allows concurrent read operations */
845#define LOCK_WRITE 128 /* ... Which allows concurrent write operations */
846#define LOCK_RW 192 /* ... Which allows concurrent read & write ops */
847#endif
848#endif
849
850/*******************************************************************
851 A flock() wrapper that will perform the kernel flock.
852********************************************************************/
853
854void kernel_flock(int fd, uint32 share_mode, uint32 access_mask)
855{
856#if HAVE_KERNEL_SHARE_MODES
857 int kernel_mode = 0;
858 if (share_mode == FILE_SHARE_WRITE) {
859 kernel_mode = LOCK_MAND|LOCK_WRITE;
860 } else if (share_mode == FILE_SHARE_READ) {
861 kernel_mode = LOCK_MAND|LOCK_READ;
862 } else if (share_mode == FILE_SHARE_NONE) {
863 kernel_mode = LOCK_MAND;
864 }
865 if (kernel_mode) {
866 flock(fd, kernel_mode);
867 }
868#endif
869 ;
870}
871
872
873
874/*******************************************************************
875 An opendir wrapper that will deal with 64 bit filesizes.
876********************************************************************/
877
878SMB_STRUCT_DIR *sys_opendir(const char *name)
879{
880#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPENDIR64)
881 return opendir64(name);
882#else
883 return opendir(name);
884#endif
885}
886
887/*******************************************************************
888 An fdopendir wrapper that will deal with 64 bit filesizes.
889 Ugly hack - we need dirfd for this to work correctly in the
890 calling code.. JRA.
891********************************************************************/
892
893SMB_STRUCT_DIR *sys_fdopendir(int fd)
894{
895#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FDOPENDIR64) && defined(HAVE_DIRFD)
896 return fdopendir64(fd);
897#elif defined(HAVE_FDOPENDIR) && defined(HAVE_DIRFD)
898 return fdopendir(fd);
899#else
900 errno = ENOSYS;
901 return NULL;
902#endif
903}
904
905/*******************************************************************
906 A readdir wrapper that will deal with 64 bit filesizes.
907********************************************************************/
908
909SMB_STRUCT_DIRENT *sys_readdir(SMB_STRUCT_DIR *dirp)
910{
911#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_READDIR64)
912 return readdir64(dirp);
913#else
914 return readdir(dirp);
915#endif
916}
917
918/*******************************************************************
919 A seekdir wrapper that will deal with 64 bit filesizes.
920********************************************************************/
921
922void sys_seekdir(SMB_STRUCT_DIR *dirp, long offset)
923{
924#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_SEEKDIR64)
925 seekdir64(dirp, offset);
926#else
927 seekdir(dirp, offset);
928#endif
929}
930
931/*******************************************************************
932 A telldir wrapper that will deal with 64 bit filesizes.
933********************************************************************/
934
935long sys_telldir(SMB_STRUCT_DIR *dirp)
936{
937#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_TELLDIR64)
938 return (long)telldir64(dirp);
939#else
940 return (long)telldir(dirp);
941#endif
942}
943
944/*******************************************************************
945 A rewinddir wrapper that will deal with 64 bit filesizes.
946********************************************************************/
947
948void sys_rewinddir(SMB_STRUCT_DIR *dirp)
949{
950#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_REWINDDIR64)
951 rewinddir64(dirp);
952#else
953 rewinddir(dirp);
954#endif
955}
956
957/*******************************************************************
958 A close wrapper that will deal with 64 bit filesizes.
959********************************************************************/
960
961int sys_closedir(SMB_STRUCT_DIR *dirp)
962{
963#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CLOSEDIR64)
964 return closedir64(dirp);
965#else
966 return closedir(dirp);
967#endif
968}
969
970/*******************************************************************
971 An mknod() wrapper that will deal with 64 bit filesizes.
972********************************************************************/
973
974int sys_mknod(const char *path, mode_t mode, SMB_DEV_T dev)
975{
976#if defined(HAVE_MKNOD) || defined(HAVE_MKNOD64)
977#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_MKNOD64) && defined(HAVE_DEV64_T)
978 return mknod64(path, mode, dev);
979#else
980 return mknod(path, mode, dev);
981#endif
982#else
983 /* No mknod system call. */
984 errno = ENOSYS;
985 return -1;
986#endif
987}
988
989/*******************************************************************
990The wait() calls vary between systems
991********************************************************************/
992
993int sys_waitpid(pid_t pid,int *status,int options)
994{
995#ifdef HAVE_WAITPID
996 return waitpid(pid,status,options);
997#else /* HAVE_WAITPID */
998 return wait4(pid, status, options, NULL);
999#endif /* HAVE_WAITPID */
1000}
1001
1002/*******************************************************************
1003 System wrapper for getwd
1004********************************************************************/
1005
1006char *sys_getwd(char *s)
1007{
1008 char *wd;
1009#ifdef HAVE_GETCWD
1010 wd = (char *)getcwd(s, PATH_MAX);
1011#else
1012 wd = (char *)getwd(s);
1013#endif
1014 return wd;
1015}
1016
1017#if defined(HAVE_POSIX_CAPABILITIES)
1018
1019/**************************************************************************
1020 Try and abstract process capabilities (for systems that have them).
1021****************************************************************************/
1022
1023/* Set the POSIX capabilities needed for the given purpose into the effective
1024 * capability set of the current process. Make sure they are always removed
1025 * from the inheritable set, because there is no circumstance in which our
1026 * children should inherit our elevated privileges.
1027 */
1028static bool set_process_capability(enum smbd_capability capability,
1029 bool enable)
1030{
1031 cap_value_t cap_vals[2] = {0};
1032 int num_cap_vals = 0;
1033
1034 cap_t cap;
1035
1036#if defined(HAVE_PRCTL) && defined(PR_GET_KEEPCAPS) && defined(PR_SET_KEEPCAPS)
1037 /* On Linux, make sure that any capabilities we grab are sticky
1038 * across UID changes. We expect that this would allow us to keep both
1039 * the effective and permitted capability sets, but as of circa 2.6.16,
1040 * only the permitted set is kept. It is a bug (which we work around)
1041 * that the effective set is lost, but we still require the effective
1042 * set to be kept.
1043 */
1044 if (!prctl(PR_GET_KEEPCAPS)) {
1045 prctl(PR_SET_KEEPCAPS, 1);
1046 }
1047#endif
1048
1049 cap = cap_get_proc();
1050 if (cap == NULL) {
1051 DEBUG(0,("set_process_capability: cap_get_proc failed: %s\n",
1052 strerror(errno)));
1053 return False;
1054 }
1055
1056 switch (capability) {
1057 case KERNEL_OPLOCK_CAPABILITY:
1058#ifdef CAP_NETWORK_MGT
1059 /* IRIX has CAP_NETWORK_MGT for oplocks. */
1060 cap_vals[num_cap_vals++] = CAP_NETWORK_MGT;
1061#endif
1062 break;
1063 case DMAPI_ACCESS_CAPABILITY:
1064#ifdef CAP_DEVICE_MGT
1065 /* IRIX has CAP_DEVICE_MGT for DMAPI access. */
1066 cap_vals[num_cap_vals++] = CAP_DEVICE_MGT;
1067#elif CAP_MKNOD
1068 /* Linux has CAP_MKNOD for DMAPI access. */
1069 cap_vals[num_cap_vals++] = CAP_MKNOD;
1070#endif
1071 break;
1072 case LEASE_CAPABILITY:
1073#ifdef CAP_LEASE
1074 cap_vals[num_cap_vals++] = CAP_LEASE;
1075#endif
1076 break;
1077 }
1078
1079 SMB_ASSERT(num_cap_vals <= ARRAY_SIZE(cap_vals));
1080
1081 if (num_cap_vals == 0) {
1082 cap_free(cap);
1083 return True;
1084 }
1085
1086 cap_set_flag(cap, CAP_EFFECTIVE, num_cap_vals, cap_vals,
1087 enable ? CAP_SET : CAP_CLEAR);
1088
1089 /* We never want to pass capabilities down to our children, so make
1090 * sure they are not inherited.
1091 */
1092 cap_set_flag(cap, CAP_INHERITABLE, num_cap_vals, cap_vals, CAP_CLEAR);
1093
1094 if (cap_set_proc(cap) == -1) {
1095 DEBUG(0, ("set_process_capability: cap_set_proc failed: %s\n",
1096 strerror(errno)));
1097 cap_free(cap);
1098 return False;
1099 }
1100
1101 cap_free(cap);
1102 return True;
1103}
1104
1105#endif /* HAVE_POSIX_CAPABILITIES */
1106
1107/****************************************************************************
1108 Gain the oplock capability from the kernel if possible.
1109****************************************************************************/
1110
1111void set_effective_capability(enum smbd_capability capability)
1112{
1113#if defined(HAVE_POSIX_CAPABILITIES)
1114 set_process_capability(capability, True);
1115#endif /* HAVE_POSIX_CAPABILITIES */
1116}
1117
1118void drop_effective_capability(enum smbd_capability capability)
1119{
1120#if defined(HAVE_POSIX_CAPABILITIES)
1121 set_process_capability(capability, False);
1122#endif /* HAVE_POSIX_CAPABILITIES */
1123}
1124
1125/**************************************************************************
1126 Wrapper for random().
1127****************************************************************************/
1128
1129long sys_random(void)
1130{
1131#if defined(HAVE_RANDOM)
1132 return (long)random();
1133#elif defined(HAVE_RAND)
1134 return (long)rand();
1135#else
1136 DEBUG(0,("Error - no random function available !\n"));
1137 exit(1);
1138#endif
1139}
1140
1141/**************************************************************************
1142 Wrapper for srandom().
1143****************************************************************************/
1144
1145void sys_srandom(unsigned int seed)
1146{
1147#if defined(HAVE_SRANDOM)
1148 srandom(seed);
1149#elif defined(HAVE_SRAND)
1150 srand(seed);
1151#else
1152 DEBUG(0,("Error - no srandom function available !\n"));
1153 exit(1);
1154#endif
1155}
1156
1157#ifndef NGROUPS_MAX
1158#define NGROUPS_MAX 32 /* Guess... */
1159#endif
1160
1161/**************************************************************************
1162 Returns equivalent to NGROUPS_MAX - using sysconf if needed.
1163****************************************************************************/
1164
1165int groups_max(void)
1166{
1167#if defined(SYSCONF_SC_NGROUPS_MAX)
1168 int ret = sysconf(_SC_NGROUPS_MAX);
1169 return (ret == -1) ? NGROUPS_MAX : ret;
1170#else
1171 return NGROUPS_MAX;
1172#endif
1173}
1174
1175/**************************************************************************
1176 Wrap setgroups and getgroups for systems that declare getgroups() as
1177 returning an array of gid_t, but actuall return an array of int.
1178****************************************************************************/
1179
1180#if defined(HAVE_BROKEN_GETGROUPS)
1181
1182#ifdef HAVE_BROKEN_GETGROUPS
1183#define GID_T int
1184#else
1185#define GID_T gid_t
1186#endif
1187
1188static int sys_broken_getgroups(int setlen, gid_t *gidset)
1189{
1190 GID_T gid;
1191 GID_T *group_list;
1192 int i, ngroups;
1193
1194 if(setlen == 0) {
1195 return getgroups(setlen, &gid);
1196 }
1197
1198 /*
1199 * Broken case. We need to allocate a
1200 * GID_T array of size setlen.
1201 */
1202
1203 if(setlen < 0) {
1204 errno = EINVAL;
1205 return -1;
1206 }
1207
1208 if (setlen == 0)
1209 setlen = groups_max();
1210
1211 if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
1212 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
1213 return -1;
1214 }
1215
1216 if((ngroups = getgroups(setlen, group_list)) < 0) {
1217 int saved_errno = errno;
1218 SAFE_FREE(group_list);
1219 errno = saved_errno;
1220 return -1;
1221 }
1222
1223 for(i = 0; i < ngroups; i++)
1224 gidset[i] = (gid_t)group_list[i];
1225
1226 SAFE_FREE(group_list);
1227 return ngroups;
1228}
1229
1230static int sys_broken_setgroups(int setlen, gid_t *gidset)
1231{
1232 GID_T *group_list;
1233 int i ;
1234
1235 if (setlen == 0)
1236 return 0 ;
1237
1238 if (setlen < 0 || setlen > groups_max()) {
1239 errno = EINVAL;
1240 return -1;
1241 }
1242
1243 /*
1244 * Broken case. We need to allocate a
1245 * GID_T array of size setlen.
1246 */
1247
1248 if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
1249 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
1250 return -1;
1251 }
1252
1253 for(i = 0; i < setlen; i++)
1254 group_list[i] = (GID_T) gidset[i];
1255
1256 if(setgroups(setlen, group_list) != 0) {
1257 int saved_errno = errno;
1258 SAFE_FREE(group_list);
1259 errno = saved_errno;
1260 return -1;
1261 }
1262
1263 SAFE_FREE(group_list);
1264 return 0 ;
1265}
1266
1267#endif /* HAVE_BROKEN_GETGROUPS */
1268
1269/* This is a list of systems that require the first GID passed to setgroups(2)
1270 * to be the effective GID. If your system is one of these, add it here.
1271 */
1272#if defined (FREEBSD) || defined (DARWINOS)
1273#define USE_BSD_SETGROUPS
1274#endif
1275
1276#if defined(USE_BSD_SETGROUPS)
1277/* Depending on the particular BSD implementation, the first GID that is
1278 * passed to setgroups(2) will either be ignored or will set the credential's
1279 * effective GID. In either case, the right thing to do is to guarantee that
1280 * gidset[0] is the effective GID.
1281 */
1282static int sys_bsd_setgroups(gid_t primary_gid, int setlen, const gid_t *gidset)
1283{
1284 gid_t *new_gidset = NULL;
1285 int max;
1286 int ret;
1287
1288 /* setgroups(2) will fail with EINVAL if we pass too many groups. */
1289 max = groups_max();
1290
1291 /* No group list, just make sure we are setting the efective GID. */
1292 if (setlen == 0) {
1293 return setgroups(1, &primary_gid);
1294 }
1295
1296 /* If the primary gid is not the first array element, grow the array
1297 * and insert it at the front.
1298 */
1299 if (gidset[0] != primary_gid) {
1300 new_gidset = SMB_MALLOC_ARRAY(gid_t, setlen + 1);
1301 if (new_gidset == NULL) {
1302 return -1;
1303 }
1304
1305 memcpy(new_gidset + 1, gidset, (setlen * sizeof(gid_t)));
1306 new_gidset[0] = primary_gid;
1307 setlen++;
1308 }
1309
1310 if (setlen > max) {
1311 DEBUG(3, ("forced to truncate group list from %d to %d\n",
1312 setlen, max));
1313 setlen = max;
1314 }
1315
1316#if defined(HAVE_BROKEN_GETGROUPS)
1317 ret = sys_broken_setgroups(setlen, new_gidset ? new_gidset : gidset);
1318#else
1319 ret = setgroups(setlen, new_gidset ? new_gidset : gidset);
1320#endif
1321
1322 if (new_gidset) {
1323 int errsav = errno;
1324 SAFE_FREE(new_gidset);
1325 errno = errsav;
1326 }
1327
1328 return ret;
1329}
1330
1331#endif /* USE_BSD_SETGROUPS */
1332
1333/**************************************************************************
1334 Wrapper for getgroups. Deals with broken (int) case.
1335****************************************************************************/
1336
1337int sys_getgroups(int setlen, gid_t *gidset)
1338{
1339#if defined(HAVE_BROKEN_GETGROUPS)
1340 return sys_broken_getgroups(setlen, gidset);
1341#else
1342 return getgroups(setlen, gidset);
1343#endif
1344}
1345
1346/**************************************************************************
1347 Wrapper for setgroups. Deals with broken (int) case and BSD case.
1348****************************************************************************/
1349
1350int sys_setgroups(gid_t UNUSED(primary_gid), int setlen, gid_t *gidset)
1351{
1352#if !defined(HAVE_SETGROUPS)
1353 errno = ENOSYS;
1354 return -1;
1355#endif /* HAVE_SETGROUPS */
1356
1357#if defined(USE_BSD_SETGROUPS)
1358 return sys_bsd_setgroups(primary_gid, setlen, gidset);
1359#elif defined(HAVE_BROKEN_GETGROUPS)
1360 return sys_broken_setgroups(setlen, gidset);
1361#else
1362 return setgroups(setlen, gidset);
1363#endif
1364}
1365
1366/**************************************************************************
1367 Extract a command into an arg list.
1368****************************************************************************/
1369
1370static char **extract_args(TALLOC_CTX *mem_ctx, const char *command)
1371{
1372 char *trunc_cmd;
1373 char *saveptr;
1374 char *ptr;
1375 int argcl;
1376 char **argl = NULL;
1377 int i;
1378
1379 if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1380 DEBUG(0, ("talloc failed\n"));
1381 goto nomem;
1382 }
1383
1384 if(!(ptr = strtok_r(trunc_cmd, " \t", &saveptr))) {
1385 TALLOC_FREE(trunc_cmd);
1386 errno = EINVAL;
1387 return NULL;
1388 }
1389
1390 /*
1391 * Count the args.
1392 */
1393
1394 for( argcl = 1; ptr; ptr = strtok_r(NULL, " \t", &saveptr))
1395 argcl++;
1396
1397 TALLOC_FREE(trunc_cmd);
1398
1399 if (!(argl = TALLOC_ARRAY(mem_ctx, char *, argcl + 1))) {
1400 goto nomem;
1401 }
1402
1403 /*
1404 * Now do the extraction.
1405 */
1406
1407 if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1408 goto nomem;
1409 }
1410
1411 ptr = strtok_r(trunc_cmd, " \t", &saveptr);
1412 i = 0;
1413
1414 if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1415 goto nomem;
1416 }
1417
1418 while((ptr = strtok_r(NULL, " \t", &saveptr)) != NULL) {
1419
1420 if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1421 goto nomem;
1422 }
1423 }
1424
1425 argl[i++] = NULL;
1426 TALLOC_FREE(trunc_cmd);
1427 return argl;
1428
1429 nomem:
1430 DEBUG(0, ("talloc failed\n"));
1431 TALLOC_FREE(trunc_cmd);
1432 TALLOC_FREE(argl);
1433 errno = ENOMEM;
1434 return NULL;
1435}
1436
1437/**************************************************************************
1438 Wrapper for popen. Safer as it doesn't search a path.
1439 Modified from the glibc sources.
1440 modified by tridge to return a file descriptor. We must kick our FILE* habit
1441****************************************************************************/
1442
1443typedef struct _popen_list
1444{
1445 int fd;
1446 pid_t child_pid;
1447 struct _popen_list *next;
1448} popen_list;
1449
1450static popen_list *popen_chain;
1451
1452int sys_popen(const char *command)
1453{
1454 int parent_end, child_end;
1455 int pipe_fds[2];
1456 popen_list *entry = NULL;
1457 char **argl = NULL;
1458
1459 if (pipe(pipe_fds) < 0)
1460 return -1;
1461
1462 parent_end = pipe_fds[0];
1463 child_end = pipe_fds[1];
1464
1465 if (!*command) {
1466 errno = EINVAL;
1467 goto err_exit;
1468 }
1469
1470 if((entry = SMB_MALLOC_P(popen_list)) == NULL)
1471 goto err_exit;
1472
1473 ZERO_STRUCTP(entry);
1474
1475 /*
1476 * Extract the command and args into a NULL terminated array.
1477 */
1478
1479 if(!(argl = extract_args(NULL, command)))
1480 goto err_exit;
1481
1482 entry->child_pid = sys_fork();
1483
1484 if (entry->child_pid == -1) {
1485 goto err_exit;
1486 }
1487
1488 if (entry->child_pid == 0) {
1489
1490 /*
1491 * Child !
1492 */
1493
1494 int child_std_end = STDOUT_FILENO;
1495 popen_list *p;
1496
1497 close(parent_end);
1498 if (child_end != child_std_end) {
1499 dup2 (child_end, child_std_end);
1500 close (child_end);
1501 }
1502
1503 /*
1504 * POSIX.2: "popen() shall ensure that any streams from previous
1505 * popen() calls that remain open in the parent process are closed
1506 * in the new child process."
1507 */
1508
1509 for (p = popen_chain; p; p = p->next)
1510 close(p->fd);
1511
1512 execv(argl[0], argl);
1513 _exit (127);
1514 }
1515
1516 /*
1517 * Parent.
1518 */
1519
1520 close (child_end);
1521 TALLOC_FREE(argl);
1522
1523 /* Link into popen_chain. */
1524 entry->next = popen_chain;
1525 popen_chain = entry;
1526 entry->fd = parent_end;
1527
1528 return entry->fd;
1529
1530err_exit:
1531
1532 SAFE_FREE(entry);
1533 TALLOC_FREE(argl);
1534 close(pipe_fds[0]);
1535 close(pipe_fds[1]);
1536 return -1;
1537}
1538
1539/**************************************************************************
1540 Wrapper for pclose. Modified from the glibc sources.
1541****************************************************************************/
1542
1543int sys_pclose(int fd)
1544{
1545 int wstatus;
1546 popen_list **ptr = &popen_chain;
1547 popen_list *entry = NULL;
1548 pid_t wait_pid;
1549 int status = -1;
1550
1551 /* Unlink from popen_chain. */
1552 for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
1553 if ((*ptr)->fd == fd) {
1554 entry = *ptr;
1555 *ptr = (*ptr)->next;
1556 status = 0;
1557 break;
1558 }
1559 }
1560
1561 if (status < 0 || close(entry->fd) < 0)
1562 return -1;
1563
1564 /*
1565 * As Samba is catching and eating child process
1566 * exits we don't really care about the child exit
1567 * code, a -1 with errno = ECHILD will do fine for us.
1568 */
1569
1570 do {
1571 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
1572 } while (wait_pid == -1 && errno == EINTR);
1573
1574 SAFE_FREE(entry);
1575
1576 if (wait_pid == -1)
1577 return -1;
1578 return wstatus;
1579}
1580
1581/**************************************************************************
1582 Wrapper for Admin Logs.
1583****************************************************************************/
1584
1585 void sys_adminlog(int priority, const char *format_str, ...)
1586{
1587 va_list ap;
1588 int ret;
1589 char *msgbuf = NULL;
1590
1591 va_start( ap, format_str );
1592 ret = vasprintf( &msgbuf, format_str, ap );
1593 va_end( ap );
1594
1595 if (ret == -1)
1596 return;
1597
1598#if defined(HAVE_SYSLOG)
1599 syslog( priority, "%s", msgbuf );
1600#else
1601 DEBUG(0,("%s", msgbuf ));
1602#endif
1603 SAFE_FREE(msgbuf);
1604}
1605
1606/******** Solaris EA helper function prototypes ********/
1607#ifdef HAVE_ATTROPEN
1608#define SOLARIS_ATTRMODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP
1609static int solaris_write_xattr(int attrfd, const char *value, size_t size);
1610static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size);
1611static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size);
1612static int solaris_unlinkat(int attrdirfd, const char *name);
1613static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode);
1614static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode);
1615#endif
1616
1617/**************************************************************************
1618 Wrappers for extented attribute calls. Based on the Linux package with
1619 support for IRIX and (Net|Free)BSD also. Expand as other systems have them.
1620****************************************************************************/
1621
1622ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t size)
1623{
1624#if defined(HAVE_GETXATTR)
1625#ifndef XATTR_ADD_OPT
1626 return getxattr(path, name, value, size);
1627#else
1628 int options = 0;
1629 return getxattr(path, name, value, size, 0, options);
1630#endif
1631#elif defined(HAVE_GETEA)
1632 return getea(path, name, value, size);
1633#elif defined(HAVE_EXTATTR_GET_FILE)
1634 char *s;
1635 ssize_t retval;
1636 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1637 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1638 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1639 /*
1640 * The BSD implementation has a nasty habit of silently truncating
1641 * the returned value to the size of the buffer, so we have to check
1642 * that the buffer is large enough to fit the returned value.
1643 */
1644 if((retval=extattr_get_file(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1645 if(retval > size) {
1646 errno = ERANGE;
1647 return -1;
1648 }
1649 if((retval=extattr_get_file(path, attrnamespace, attrname, value, size)) >= 0)
1650 return retval;
1651 }
1652
1653 DEBUG(10,("sys_getxattr: extattr_get_file() failed with: %s\n", strerror(errno)));
1654 return -1;
1655#elif defined(HAVE_ATTR_GET)
1656 int retval, flags = 0;
1657 int valuelength = (int)size;
1658 char *attrname = strchr(name,'.') + 1;
1659
1660 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1661
1662 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1663
1664 return retval ? retval : valuelength;
1665#elif defined(HAVE_ATTROPEN)
1666 ssize_t ret = -1;
1667 int attrfd = solaris_attropen(path, name, O_RDONLY, 0);
1668 if (attrfd >= 0) {
1669 ret = solaris_read_xattr(attrfd, value, size);
1670 close(attrfd);
1671 }
1672 return ret;
1673#elif defined(__OS2__)
1674 return unigetxattr(path, 0, name, value, size);
1675#else
1676 errno = ENOSYS;
1677 return -1;
1678#endif
1679}
1680
1681ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t size)
1682{
1683#if defined(HAVE_LGETXATTR)
1684 return lgetxattr(path, name, value, size);
1685#elif defined(HAVE_GETXATTR) && defined(XATTR_ADD_OPT)
1686 int options = XATTR_NOFOLLOW;
1687 return getxattr(path, name, value, size, 0, options);
1688#elif defined(HAVE_LGETEA)
1689 return lgetea(path, name, value, size);
1690#elif defined(HAVE_EXTATTR_GET_LINK)
1691 char *s;
1692 ssize_t retval;
1693 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1694 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1695 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1696
1697 if((retval=extattr_get_link(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1698 if(retval > size) {
1699 errno = ERANGE;
1700 return -1;
1701 }
1702 if((retval=extattr_get_link(path, attrnamespace, attrname, value, size)) >= 0)
1703 return retval;
1704 }
1705
1706 DEBUG(10,("sys_lgetxattr: extattr_get_link() failed with: %s\n", strerror(errno)));
1707 return -1;
1708#elif defined(HAVE_ATTR_GET)
1709 int retval, flags = ATTR_DONTFOLLOW;
1710 int valuelength = (int)size;
1711 char *attrname = strchr(name,'.') + 1;
1712
1713 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1714
1715 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1716
1717 return retval ? retval : valuelength;
1718#elif defined(HAVE_ATTROPEN)
1719 ssize_t ret = -1;
1720 int attrfd = solaris_attropen(path, name, O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1721 if (attrfd >= 0) {
1722 ret = solaris_read_xattr(attrfd, value, size);
1723 close(attrfd);
1724 }
1725 return ret;
1726#elif defined(__OS2__)
1727 return unigetxattr(path, 0, name, value, size);
1728#else
1729 errno = ENOSYS;
1730 return -1;
1731#endif
1732}
1733
1734ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size)
1735{
1736#if defined(HAVE_FGETXATTR)
1737#ifndef XATTR_ADD_OPT
1738 return fgetxattr(filedes, name, value, size);
1739#else
1740 int options = 0;
1741 return fgetxattr(filedes, name, value, size, 0, options);
1742#endif
1743#elif defined(HAVE_FGETEA)
1744 return fgetea(filedes, name, value, size);
1745#elif defined(HAVE_EXTATTR_GET_FD)
1746 char *s;
1747 ssize_t retval;
1748 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1749 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1750 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1751
1752 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0)) >= 0) {
1753 if(retval > size) {
1754 errno = ERANGE;
1755 return -1;
1756 }
1757 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, value, size)) >= 0)
1758 return retval;
1759 }
1760
1761 DEBUG(10,("sys_fgetxattr: extattr_get_fd() failed with: %s\n", strerror(errno)));
1762 return -1;
1763#elif defined(HAVE_ATTR_GETF)
1764 int retval, flags = 0;
1765 int valuelength = (int)size;
1766 char *attrname = strchr(name,'.') + 1;
1767
1768 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1769
1770 retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags);
1771
1772 return retval ? retval : valuelength;
1773#elif defined(HAVE_ATTROPEN)
1774 ssize_t ret = -1;
1775 int attrfd = solaris_openat(filedes, name, O_RDONLY|O_XATTR, 0);
1776 if (attrfd >= 0) {
1777 ret = solaris_read_xattr(attrfd, value, size);
1778 close(attrfd);
1779 }
1780 return ret;
1781#elif defined(__OS2__)
1782 return unigetxattr(0, filedes, name, value, size);
1783#else
1784 errno = ENOSYS;
1785 return -1;
1786#endif
1787}
1788
1789#if defined(HAVE_EXTATTR_LIST_FILE)
1790
1791#define EXTATTR_PREFIX(s) (s), (sizeof((s))-1)
1792
1793static struct {
1794 int space;
1795 const char *name;
1796 size_t len;
1797}
1798extattr[] = {
1799 { EXTATTR_NAMESPACE_SYSTEM, EXTATTR_PREFIX("system.") },
1800 { EXTATTR_NAMESPACE_USER, EXTATTR_PREFIX("user.") },
1801};
1802
1803typedef union {
1804 const char *path;
1805 int filedes;
1806} extattr_arg;
1807
1808static ssize_t bsd_attr_list (int type, extattr_arg arg, char *list, size_t size)
1809{
1810 ssize_t list_size, total_size = 0;
1811 int i, t, len;
1812 char *buf;
1813 /* Iterate through extattr(2) namespaces */
1814 for(t = 0; t < (sizeof(extattr)/sizeof(extattr[0])); t++) {
1815 switch(type) {
1816#if defined(HAVE_EXTATTR_LIST_FILE)
1817 case 0:
1818 list_size = extattr_list_file(arg.path, extattr[t].space, list, size);
1819 break;
1820#endif
1821#if defined(HAVE_EXTATTR_LIST_LINK)
1822 case 1:
1823 list_size = extattr_list_link(arg.path, extattr[t].space, list, size);
1824 break;
1825#endif
1826#if defined(HAVE_EXTATTR_LIST_FD)
1827 case 2:
1828 list_size = extattr_list_fd(arg.filedes, extattr[t].space, list, size);
1829 break;
1830#endif
1831 default:
1832 errno = ENOSYS;
1833 return -1;
1834 }
1835 /* Some error happend. Errno should be set by the previous call */
1836 if(list_size < 0)
1837 return -1;
1838 /* No attributes */
1839 if(list_size == 0)
1840 continue;
1841 /* XXX: Call with an empty buffer may be used to calculate
1842 necessary buffer size. Unfortunately, we can't say, how
1843 many attributes were returned, so here is the potential
1844 problem with the emulation.
1845 */
1846 if(list == NULL) {
1847 /* Take the worse case of one char attribute names -
1848 two bytes per name plus one more for sanity.
1849 */
1850 total_size += list_size + (list_size/2 + 1)*extattr[t].len;
1851 continue;
1852 }
1853 /* Count necessary offset to fit namespace prefixes */
1854 len = 0;
1855 for(i = 0; i < list_size; i += list[i] + 1)
1856 len += extattr[t].len;
1857
1858 total_size += list_size + len;
1859 /* Buffer is too small to fit the results */
1860 if(total_size > size) {
1861 errno = ERANGE;
1862 return -1;
1863 }
1864 /* Shift results back, so we can prepend prefixes */
1865 buf = (char *)memmove(list + len, list, list_size);
1866
1867 for(i = 0; i < list_size; i += len + 1) {
1868 len = buf[i];
1869 strncpy(list, extattr[t].name, extattr[t].len + 1);
1870 list += extattr[t].len;
1871 strncpy(list, buf + i + 1, len);
1872 list[len] = '\0';
1873 list += len + 1;
1874 }
1875 size -= total_size;
1876 }
1877 return total_size;
1878}
1879
1880#endif
1881
1882#if defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1883static char attr_buffer[ATTR_MAX_VALUELEN];
1884
1885static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags)
1886{
1887 int retval = 0, index;
1888 attrlist_cursor_t *cursor = 0;
1889 int total_size = 0;
1890 attrlist_t * al = (attrlist_t *)attr_buffer;
1891 attrlist_ent_t *ae;
1892 size_t ent_size, left = size;
1893 char *bp = list;
1894
1895 while (True) {
1896 if (filedes)
1897 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1898 else
1899 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1900 if (retval) break;
1901 for (index = 0; index < al->al_count; index++) {
1902 ae = ATTR_ENTRY(attr_buffer, index);
1903 ent_size = strlen(ae->a_name) + sizeof("user.");
1904 if (left >= ent_size) {
1905 strncpy(bp, "user.", sizeof("user."));
1906 strncat(bp, ae->a_name, ent_size - sizeof("user."));
1907 bp += ent_size;
1908 left -= ent_size;
1909 } else if (size) {
1910 errno = ERANGE;
1911 retval = -1;
1912 break;
1913 }
1914 total_size += ent_size;
1915 }
1916 if (al->al_more == 0) break;
1917 }
1918 if (retval == 0) {
1919 flags |= ATTR_ROOT;
1920 cursor = 0;
1921 while (True) {
1922 if (filedes)
1923 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1924 else
1925 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1926 if (retval) break;
1927 for (index = 0; index < al->al_count; index++) {
1928 ae = ATTR_ENTRY(attr_buffer, index);
1929 ent_size = strlen(ae->a_name) + sizeof("system.");
1930 if (left >= ent_size) {
1931 strncpy(bp, "system.", sizeof("system."));
1932 strncat(bp, ae->a_name, ent_size - sizeof("system."));
1933 bp += ent_size;
1934 left -= ent_size;
1935 } else if (size) {
1936 errno = ERANGE;
1937 retval = -1;
1938 break;
1939 }
1940 total_size += ent_size;
1941 }
1942 if (al->al_more == 0) break;
1943 }
1944 }
1945 return (ssize_t)(retval ? retval : total_size);
1946}
1947
1948#endif
1949
1950ssize_t sys_listxattr (const char *path, char *list, size_t size)
1951{
1952#if defined(HAVE_LISTXATTR)
1953#ifndef XATTR_ADD_OPT
1954 return listxattr(path, list, size);
1955#else
1956 int options = 0;
1957 return listxattr(path, list, size, options);
1958#endif
1959#elif defined(HAVE_LISTEA)
1960 return listea(path, list, size);
1961#elif defined(HAVE_EXTATTR_LIST_FILE)
1962 extattr_arg arg;
1963 arg.path = path;
1964 return bsd_attr_list(0, arg, list, size);
1965#elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1966 return irix_attr_list(path, 0, list, size, 0);
1967#elif defined(HAVE_ATTROPEN)
1968 ssize_t ret = -1;
1969 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
1970 if (attrdirfd >= 0) {
1971 ret = solaris_list_xattr(attrdirfd, list, size);
1972 close(attrdirfd);
1973 }
1974 return ret;
1975#elif defined(__OS2__)
1976 return unilistxattr(path, 0, list, size);
1977#else
1978 errno = ENOSYS;
1979 return -1;
1980#endif
1981}
1982
1983ssize_t sys_llistxattr (const char *path, char *list, size_t size)
1984{
1985#if defined(HAVE_LLISTXATTR)
1986 return llistxattr(path, list, size);
1987#elif defined(HAVE_LISTXATTR) && defined(XATTR_ADD_OPT)
1988 int options = XATTR_NOFOLLOW;
1989 return listxattr(path, list, size, options);
1990#elif defined(HAVE_LLISTEA)
1991 return llistea(path, list, size);
1992#elif defined(HAVE_EXTATTR_LIST_LINK)
1993 extattr_arg arg;
1994 arg.path = path;
1995 return bsd_attr_list(1, arg, list, size);
1996#elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1997 return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW);
1998#elif defined(HAVE_ATTROPEN)
1999 ssize_t ret = -1;
2000 int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
2001 if (attrdirfd >= 0) {
2002 ret = solaris_list_xattr(attrdirfd, list, size);
2003 close(attrdirfd);
2004 }
2005 return ret;
2006#elif defined(__OS2__)
2007 return unilistxattr(path, 0, list, size);
2008#else
2009 errno = ENOSYS;
2010 return -1;
2011#endif
2012}
2013
2014ssize_t sys_flistxattr (int filedes, char *list, size_t size)
2015{
2016#if defined(HAVE_FLISTXATTR)
2017#ifndef XATTR_ADD_OPT
2018 return flistxattr(filedes, list, size);
2019#else
2020 int options = 0;
2021 return flistxattr(filedes, list, size, options);
2022#endif
2023#elif defined(HAVE_FLISTEA)
2024 return flistea(filedes, list, size);
2025#elif defined(HAVE_EXTATTR_LIST_FD)
2026 extattr_arg arg;
2027 arg.filedes = filedes;
2028 return bsd_attr_list(2, arg, list, size);
2029#elif defined(HAVE_ATTR_LISTF)
2030 return irix_attr_list(NULL, filedes, list, size, 0);
2031#elif defined(HAVE_ATTROPEN)
2032 ssize_t ret = -1;
2033 int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
2034 if (attrdirfd >= 0) {
2035 ret = solaris_list_xattr(attrdirfd, list, size);
2036 close(attrdirfd);
2037 }
2038 return ret;
2039#elif defined(__OS2__)
2040 return unilistxattr(0, filedes, list, size);
2041#else
2042 errno = ENOSYS;
2043 return -1;
2044#endif
2045}
2046
2047int sys_removexattr (const char *path, const char *name)
2048{
2049#if defined(HAVE_REMOVEXATTR)
2050#ifndef XATTR_ADD_OPT
2051 return removexattr(path, name);
2052#else
2053 int options = 0;
2054 return removexattr(path, name, options);
2055#endif
2056#elif defined(HAVE_REMOVEEA)
2057 return removeea(path, name);
2058#elif defined(HAVE_EXTATTR_DELETE_FILE)
2059 char *s;
2060 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2061 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2062 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2063
2064 return extattr_delete_file(path, attrnamespace, attrname);
2065#elif defined(HAVE_ATTR_REMOVE)
2066 int flags = 0;
2067 char *attrname = strchr(name,'.') + 1;
2068
2069 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
2070
2071 return attr_remove(path, attrname, flags);
2072#elif defined(HAVE_ATTROPEN)
2073 int ret = -1;
2074 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
2075 if (attrdirfd >= 0) {
2076 ret = solaris_unlinkat(attrdirfd, name);
2077 close(attrdirfd);
2078 }
2079 return ret;
2080#elif defined(__OS2__)
2081 return uniremovexattr (path, 0, name);
2082#else
2083 errno = ENOSYS;
2084 return -1;
2085#endif
2086}
2087
2088int sys_lremovexattr (const char *path, const char *name)
2089{
2090#if defined(HAVE_LREMOVEXATTR)
2091 return lremovexattr(path, name);
2092#elif defined(HAVE_REMOVEXATTR) && defined(XATTR_ADD_OPT)
2093 int options = XATTR_NOFOLLOW;
2094 return removexattr(path, name, options);
2095#elif defined(HAVE_LREMOVEEA)
2096 return lremoveea(path, name);
2097#elif defined(HAVE_EXTATTR_DELETE_LINK)
2098 char *s;
2099 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2100 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2101 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2102
2103 return extattr_delete_link(path, attrnamespace, attrname);
2104#elif defined(HAVE_ATTR_REMOVE)
2105 int flags = ATTR_DONTFOLLOW;
2106 char *attrname = strchr(name,'.') + 1;
2107
2108 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
2109
2110 return attr_remove(path, attrname, flags);
2111#elif defined(HAVE_ATTROPEN)
2112 int ret = -1;
2113 int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
2114 if (attrdirfd >= 0) {
2115 ret = solaris_unlinkat(attrdirfd, name);
2116 close(attrdirfd);
2117 }
2118 return ret;
2119#elif defined(__OS2__)
2120 return uniremovexattr (path, 0, name);
2121#else
2122 errno = ENOSYS;
2123 return -1;
2124#endif
2125}
2126
2127int sys_fremovexattr (int filedes, const char *name)
2128{
2129#if defined(HAVE_FREMOVEXATTR)
2130#ifndef XATTR_ADD_OPT
2131 return fremovexattr(filedes, name);
2132#else
2133 int options = 0;
2134 return fremovexattr(filedes, name, options);
2135#endif
2136#elif defined(HAVE_FREMOVEEA)
2137 return fremoveea(filedes, name);
2138#elif defined(HAVE_EXTATTR_DELETE_FD)
2139 char *s;
2140 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2141 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2142 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2143
2144 return extattr_delete_fd(filedes, attrnamespace, attrname);
2145#elif defined(HAVE_ATTR_REMOVEF)
2146 int flags = 0;
2147 char *attrname = strchr(name,'.') + 1;
2148
2149 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
2150
2151 return attr_removef(filedes, attrname, flags);
2152#elif defined(HAVE_ATTROPEN)
2153 int ret = -1;
2154 int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
2155 if (attrdirfd >= 0) {
2156 ret = solaris_unlinkat(attrdirfd, name);
2157 close(attrdirfd);
2158 }
2159 return ret;
2160#elif defined(__OS2__)
2161 return uniremovexattr (0, filedes, name);
2162#else
2163 errno = ENOSYS;
2164 return -1;
2165#endif
2166}
2167
2168int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags)
2169{
2170#if defined(HAVE_SETXATTR)
2171#ifndef XATTR_ADD_OPT
2172 return setxattr(path, name, value, size, flags);
2173#else
2174 int options = 0;
2175 return setxattr(path, name, value, size, 0, options);
2176#endif
2177#elif defined(HAVE_SETEA)
2178 return setea(path, name, value, size, flags);
2179#elif defined(HAVE_EXTATTR_SET_FILE)
2180 char *s;
2181 int retval = 0;
2182 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2183 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2184 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2185 if (flags) {
2186 /* Check attribute existence */
2187 retval = extattr_get_file(path, attrnamespace, attrname, NULL, 0);
2188 if (retval < 0) {
2189 /* REPLACE attribute, that doesn't exist */
2190 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2191 errno = ENOATTR;
2192 return -1;
2193 }
2194 /* Ignore other errors */
2195 }
2196 else {
2197 /* CREATE attribute, that already exists */
2198 if (flags & XATTR_CREATE) {
2199 errno = EEXIST;
2200 return -1;
2201 }
2202 }
2203 }
2204 retval = extattr_set_file(path, attrnamespace, attrname, value, size);
2205 return (retval < 0) ? -1 : 0;
2206#elif defined(HAVE_ATTR_SET)
2207 int myflags = 0;
2208 char *attrname = strchr(name,'.') + 1;
2209
2210 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2211 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2212 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2213
2214 return attr_set(path, attrname, (const char *)value, size, myflags);
2215#elif defined(HAVE_ATTROPEN)
2216 int ret = -1;
2217 int myflags = O_RDWR;
2218 int attrfd;
2219 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2220 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2221 attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2222 if (attrfd >= 0) {
2223 ret = solaris_write_xattr(attrfd, value, size);
2224 close(attrfd);
2225 }
2226 return ret;
2227#elif defined(__OS2__)
2228 return unisetxattr (path, 0, name, value, size, flags);
2229#else
2230 errno = ENOSYS;
2231 return -1;
2232#endif
2233}
2234
2235int sys_lsetxattr (const char *path, const char *name, const void *value, size_t size, int flags)
2236{
2237#if defined(HAVE_LSETXATTR)
2238 return lsetxattr(path, name, value, size, flags);
2239#elif defined(HAVE_SETXATTR) && defined(XATTR_ADD_OPT)
2240 int options = XATTR_NOFOLLOW;
2241 return setxattr(path, name, value, size, 0, options);
2242#elif defined(LSETEA)
2243 return lsetea(path, name, value, size, flags);
2244#elif defined(HAVE_EXTATTR_SET_LINK)
2245 char *s;
2246 int retval = 0;
2247 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2248 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2249 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2250 if (flags) {
2251 /* Check attribute existence */
2252 retval = extattr_get_link(path, attrnamespace, attrname, NULL, 0);
2253 if (retval < 0) {
2254 /* REPLACE attribute, that doesn't exist */
2255 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2256 errno = ENOATTR;
2257 return -1;
2258 }
2259 /* Ignore other errors */
2260 }
2261 else {
2262 /* CREATE attribute, that already exists */
2263 if (flags & XATTR_CREATE) {
2264 errno = EEXIST;
2265 return -1;
2266 }
2267 }
2268 }
2269
2270 retval = extattr_set_link(path, attrnamespace, attrname, value, size);
2271 return (retval < 0) ? -1 : 0;
2272#elif defined(HAVE_ATTR_SET)
2273 int myflags = ATTR_DONTFOLLOW;
2274 char *attrname = strchr(name,'.') + 1;
2275
2276 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2277 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2278 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2279
2280 return attr_set(path, attrname, (const char *)value, size, myflags);
2281#elif defined(HAVE_ATTROPEN)
2282 int ret = -1;
2283 int myflags = O_RDWR | AT_SYMLINK_NOFOLLOW;
2284 int attrfd;
2285 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2286 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2287 attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2288 if (attrfd >= 0) {
2289 ret = solaris_write_xattr(attrfd, value, size);
2290 close(attrfd);
2291 }
2292 return ret;
2293#elif defined(__OS2__)
2294 return unisetxattr (path, 0, name, value, size, flags);
2295#else
2296 errno = ENOSYS;
2297 return -1;
2298#endif
2299}
2300
2301int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags)
2302{
2303#if defined(HAVE_FSETXATTR)
2304#ifndef XATTR_ADD_OPT
2305 return fsetxattr(filedes, name, value, size, flags);
2306#else
2307 int options = 0;
2308 return fsetxattr(filedes, name, value, size, 0, options);
2309#endif
2310#elif defined(HAVE_FSETEA)
2311 return fsetea(filedes, name, value, size, flags);
2312#elif defined(HAVE_EXTATTR_SET_FD)
2313 char *s;
2314 int retval = 0;
2315 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2316 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2317 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2318 if (flags) {
2319 /* Check attribute existence */
2320 retval = extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0);
2321 if (retval < 0) {
2322 /* REPLACE attribute, that doesn't exist */
2323 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2324 errno = ENOATTR;
2325 return -1;
2326 }
2327 /* Ignore other errors */
2328 }
2329 else {
2330 /* CREATE attribute, that already exists */
2331 if (flags & XATTR_CREATE) {
2332 errno = EEXIST;
2333 return -1;
2334 }
2335 }
2336 }
2337 retval = extattr_set_fd(filedes, attrnamespace, attrname, value, size);
2338 return (retval < 0) ? -1 : 0;
2339#elif defined(HAVE_ATTR_SETF)
2340 int myflags = 0;
2341 char *attrname = strchr(name,'.') + 1;
2342
2343 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2344 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2345 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2346
2347 return attr_setf(filedes, attrname, (const char *)value, size, myflags);
2348#elif defined(HAVE_ATTROPEN)
2349 int ret = -1;
2350 int myflags = O_RDWR | O_XATTR;
2351 int attrfd;
2352 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2353 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2354 attrfd = solaris_openat(filedes, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2355 if (attrfd >= 0) {
2356 ret = solaris_write_xattr(attrfd, value, size);
2357 close(attrfd);
2358 }
2359 return ret;
2360#elif defined(__OS2__)
2361 return unisetxattr (0, filedes, name, value, size, flags);
2362#else
2363 errno = ENOSYS;
2364 return -1;
2365#endif
2366}
2367
2368/**************************************************************************
2369 helper functions for Solaris' EA support
2370****************************************************************************/
2371#ifdef HAVE_ATTROPEN
2372static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size)
2373{
2374 struct stat sbuf;
2375
2376 if (fstat(attrfd, &sbuf) == -1) {
2377 errno = ENOATTR;
2378 return -1;
2379 }
2380
2381 /* This is to return the current size of the named extended attribute */
2382 if (size == 0) {
2383 return sbuf.st_size;
2384 }
2385
2386 /* check size and read xattr */
2387 if (sbuf.st_size > size) {
2388 errno = ERANGE;
2389 return -1;
2390 }
2391
2392 return read(attrfd, value, sbuf.st_size);
2393}
2394
2395static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size)
2396{
2397 ssize_t len = 0;
2398 DIR *dirp;
2399 struct dirent *de;
2400 int newfd = dup(attrdirfd);
2401 /* CAUTION: The originating file descriptor should not be
2402 used again following the call to fdopendir().
2403 For that reason we dup() the file descriptor
2404 here to make things more clear. */
2405 dirp = fdopendir(newfd);
2406
2407 while ((de = readdir(dirp))) {
2408 size_t listlen = strlen(de->d_name);
2409 if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) {
2410 /* we don't want "." and ".." here: */
2411 DEBUG(10,("skipped EA %s\n",de->d_name));
2412 continue;
2413 }
2414
2415 if (size == 0) {
2416 /* return the current size of the list of extended attribute names*/
2417 len += listlen + 1;
2418 } else {
2419 /* check size and copy entrieѕ + nul into list. */
2420 if ((len + listlen + 1) > size) {
2421 errno = ERANGE;
2422 len = -1;
2423 break;
2424 } else {
2425 safe_strcpy(list + len, de->d_name, listlen);
2426 len += listlen;
2427 list[len] = '\0';
2428 ++len;
2429 }
2430 }
2431 }
2432
2433 if (closedir(dirp) == -1) {
2434 DEBUG(0,("closedir dirp failed: %s\n",strerror(errno)));
2435 return -1;
2436 }
2437 return len;
2438}
2439
2440static int solaris_unlinkat(int attrdirfd, const char *name)
2441{
2442 if (unlinkat(attrdirfd, name, 0) == -1) {
2443 if (errno == ENOENT) {
2444 errno = ENOATTR;
2445 }
2446 return -1;
2447 }
2448 return 0;
2449}
2450
2451static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode)
2452{
2453 int filedes = attropen(path, attrpath, oflag, mode);
2454 if (filedes == -1) {
2455 DEBUG(10,("attropen FAILED: path: %s, name: %s, errno: %s\n",path,attrpath,strerror(errno)));
2456 if (errno == EINVAL) {
2457 errno = ENOTSUP;
2458 } else {
2459 errno = ENOATTR;
2460 }
2461 }
2462 return filedes;
2463}
2464
2465static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode)
2466{
2467 int filedes = openat(fildes, path, oflag, mode);
2468 if (filedes == -1) {
2469 DEBUG(10,("openat FAILED: fd: %d, path: %s, errno: %s\n",filedes,path,strerror(errno)));
2470 if (errno == EINVAL) {
2471 errno = ENOTSUP;
2472 } else {
2473 errno = ENOATTR;
2474 }
2475 }
2476 return filedes;
2477}
2478
2479static int solaris_write_xattr(int attrfd, const char *value, size_t size)
2480{
2481 if ((ftruncate(attrfd, 0) == 0) && (write(attrfd, value, size) == size)) {
2482 return 0;
2483 } else {
2484 DEBUG(10,("solaris_write_xattr FAILED!\n"));
2485 return -1;
2486 }
2487}
2488#endif /*HAVE_ATTROPEN*/
2489
2490
2491/****************************************************************************
2492 Return the major devicenumber for UNIX extensions.
2493****************************************************************************/
2494
2495uint32 unix_dev_major(SMB_DEV_T dev)
2496{
2497#if defined(HAVE_DEVICE_MAJOR_FN)
2498 return (uint32)major(dev);
2499#else
2500 return (uint32)(dev >> 8);
2501#endif
2502}
2503
2504/****************************************************************************
2505 Return the minor devicenumber for UNIX extensions.
2506****************************************************************************/
2507
2508uint32 unix_dev_minor(SMB_DEV_T dev)
2509{
2510#if defined(HAVE_DEVICE_MINOR_FN)
2511 return (uint32)minor(dev);
2512#else
2513 return (uint32)(dev & 0xff);
2514#endif
2515}
2516
2517#if defined(WITH_AIO)
2518
2519/*******************************************************************
2520 An aio_read wrapper that will deal with 64-bit sizes.
2521********************************************************************/
2522
2523int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2524{
2525#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_READ64)
2526 return aio_read64(aiocb);
2527#elif defined(HAVE_AIO_READ)
2528 return aio_read(aiocb);
2529#else
2530 errno = ENOSYS;
2531 return -1;
2532#endif
2533}
2534
2535/*******************************************************************
2536 An aio_write wrapper that will deal with 64-bit sizes.
2537********************************************************************/
2538
2539int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2540{
2541#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_WRITE64)
2542 return aio_write64(aiocb);
2543#elif defined(HAVE_AIO_WRITE)
2544 return aio_write(aiocb);
2545#else
2546 errno = ENOSYS;
2547 return -1;
2548#endif
2549}
2550
2551/*******************************************************************
2552 An aio_return wrapper that will deal with 64-bit sizes.
2553********************************************************************/
2554
2555ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2556{
2557#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_RETURN64)
2558 return aio_return64(aiocb);
2559#elif defined(HAVE_AIO_RETURN)
2560 return aio_return(aiocb);
2561#else
2562 errno = ENOSYS;
2563 return -1;
2564#endif
2565}
2566
2567/*******************************************************************
2568 An aio_cancel wrapper that will deal with 64-bit sizes.
2569********************************************************************/
2570
2571int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2572{
2573#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_CANCEL64)
2574 return aio_cancel64(fd, aiocb);
2575#elif defined(HAVE_AIO_CANCEL)
2576 return aio_cancel(fd, aiocb);
2577#else
2578 errno = ENOSYS;
2579 return -1;
2580#endif
2581}
2582
2583/*******************************************************************
2584 An aio_error wrapper that will deal with 64-bit sizes.
2585********************************************************************/
2586
2587int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2588{
2589#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_ERROR64)
2590 return aio_error64(aiocb);
2591#elif defined(HAVE_AIO_ERROR)
2592 return aio_error(aiocb);
2593#else
2594 errno = ENOSYS;
2595 return -1;
2596#endif
2597}
2598
2599/*******************************************************************
2600 An aio_fsync wrapper that will deal with 64-bit sizes.
2601********************************************************************/
2602
2603int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2604{
2605#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_FSYNC64)
2606 return aio_fsync64(op, aiocb);
2607#elif defined(HAVE_AIO_FSYNC)
2608 return aio_fsync(op, aiocb);
2609#else
2610 errno = ENOSYS;
2611 return -1;
2612#endif
2613}
2614
2615/*******************************************************************
2616 An aio_fsync wrapper that will deal with 64-bit sizes.
2617********************************************************************/
2618
2619int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2620{
2621#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_SUSPEND64)
2622 return aio_suspend64(cblist, n, timeout);
2623#elif defined(HAVE_AIO_FSYNC)
2624 return aio_suspend(cblist, n, timeout);
2625#else
2626 errno = ENOSYS;
2627 return -1;
2628#endif
2629}
2630#else /* !WITH_AIO */
2631
2632int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2633{
2634 errno = ENOSYS;
2635 return -1;
2636}
2637
2638int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2639{
2640 errno = ENOSYS;
2641 return -1;
2642}
2643
2644ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2645{
2646 errno = ENOSYS;
2647 return -1;
2648}
2649
2650int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2651{
2652 errno = ENOSYS;
2653 return -1;
2654}
2655
2656int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2657{
2658 errno = ENOSYS;
2659 return -1;
2660}
2661
2662int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2663{
2664 errno = ENOSYS;
2665 return -1;
2666}
2667
2668int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2669{
2670 errno = ENOSYS;
2671 return -1;
2672}
2673#endif /* WITH_AIO */
Note: See TracBrowser for help on using the repository browser.