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

Last change on this file since 873 was 862, checked in by Silvan Scherrer, 11 years ago

Samba Server: update trunk to 3.6.23

File size: 71.3 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.
891********************************************************************/
892
893SMB_STRUCT_DIR *sys_fdopendir(int fd)
894{
895#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FDOPENDIR64)
896 return fdopendir64(fd);
897#elif defined(HAVE_FDOPENDIR)
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 if (t != EXTATTR_NAMESPACE_USER && geteuid() != 0) {
1816 /* ignore all but user namespace when we are not root, see bug 10247 */
1817 continue;
1818 }
1819 switch(type) {
1820#if defined(HAVE_EXTATTR_LIST_FILE)
1821 case 0:
1822 list_size = extattr_list_file(arg.path, extattr[t].space, list, size);
1823 break;
1824#endif
1825#if defined(HAVE_EXTATTR_LIST_LINK)
1826 case 1:
1827 list_size = extattr_list_link(arg.path, extattr[t].space, list, size);
1828 break;
1829#endif
1830#if defined(HAVE_EXTATTR_LIST_FD)
1831 case 2:
1832 list_size = extattr_list_fd(arg.filedes, extattr[t].space, list, size);
1833 break;
1834#endif
1835 default:
1836 errno = ENOSYS;
1837 return -1;
1838 }
1839 /* Some error happend. Errno should be set by the previous call */
1840 if(list_size < 0)
1841 return -1;
1842 /* No attributes */
1843 if(list_size == 0)
1844 continue;
1845 /* XXX: Call with an empty buffer may be used to calculate
1846 necessary buffer size. Unfortunately, we can't say, how
1847 many attributes were returned, so here is the potential
1848 problem with the emulation.
1849 */
1850 if(list == NULL) {
1851 /* Take the worse case of one char attribute names -
1852 two bytes per name plus one more for sanity.
1853 */
1854 total_size += list_size + (list_size/2 + 1)*extattr[t].len;
1855 continue;
1856 }
1857 /* Count necessary offset to fit namespace prefixes */
1858 len = 0;
1859 for(i = 0; i < list_size; i += list[i] + 1)
1860 len += extattr[t].len;
1861
1862 total_size += list_size + len;
1863 /* Buffer is too small to fit the results */
1864 if(total_size > size) {
1865 errno = ERANGE;
1866 return -1;
1867 }
1868 /* Shift results back, so we can prepend prefixes */
1869 buf = (char *)memmove(list + len, list, list_size);
1870
1871 for(i = 0; i < list_size; i += len + 1) {
1872 len = buf[i];
1873 strncpy(list, extattr[t].name, extattr[t].len + 1);
1874 list += extattr[t].len;
1875 strncpy(list, buf + i + 1, len);
1876 list[len] = '\0';
1877 list += len + 1;
1878 }
1879 size -= total_size;
1880 }
1881 return total_size;
1882}
1883
1884#endif
1885
1886#if defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1887static char attr_buffer[ATTR_MAX_VALUELEN];
1888
1889static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags)
1890{
1891 int retval = 0, index;
1892 attrlist_cursor_t *cursor = 0;
1893 int total_size = 0;
1894 attrlist_t * al = (attrlist_t *)attr_buffer;
1895 attrlist_ent_t *ae;
1896 size_t ent_size, left = size;
1897 char *bp = list;
1898
1899 while (True) {
1900 if (filedes)
1901 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1902 else
1903 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1904 if (retval) break;
1905 for (index = 0; index < al->al_count; index++) {
1906 ae = ATTR_ENTRY(attr_buffer, index);
1907 ent_size = strlen(ae->a_name) + sizeof("user.");
1908 if (left >= ent_size) {
1909 strncpy(bp, "user.", sizeof("user."));
1910 strncat(bp, ae->a_name, ent_size - sizeof("user."));
1911 bp += ent_size;
1912 left -= ent_size;
1913 } else if (size) {
1914 errno = ERANGE;
1915 retval = -1;
1916 break;
1917 }
1918 total_size += ent_size;
1919 }
1920 if (al->al_more == 0) break;
1921 }
1922 if (retval == 0) {
1923 flags |= ATTR_ROOT;
1924 cursor = 0;
1925 while (True) {
1926 if (filedes)
1927 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1928 else
1929 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1930 if (retval) break;
1931 for (index = 0; index < al->al_count; index++) {
1932 ae = ATTR_ENTRY(attr_buffer, index);
1933 ent_size = strlen(ae->a_name) + sizeof("system.");
1934 if (left >= ent_size) {
1935 strncpy(bp, "system.", sizeof("system."));
1936 strncat(bp, ae->a_name, ent_size - sizeof("system."));
1937 bp += ent_size;
1938 left -= ent_size;
1939 } else if (size) {
1940 errno = ERANGE;
1941 retval = -1;
1942 break;
1943 }
1944 total_size += ent_size;
1945 }
1946 if (al->al_more == 0) break;
1947 }
1948 }
1949 return (ssize_t)(retval ? retval : total_size);
1950}
1951
1952#endif
1953
1954ssize_t sys_listxattr (const char *path, char *list, size_t size)
1955{
1956#if defined(HAVE_LISTXATTR)
1957#ifndef XATTR_ADD_OPT
1958 return listxattr(path, list, size);
1959#else
1960 int options = 0;
1961 return listxattr(path, list, size, options);
1962#endif
1963#elif defined(HAVE_LISTEA)
1964 return listea(path, list, size);
1965#elif defined(HAVE_EXTATTR_LIST_FILE)
1966 extattr_arg arg;
1967 arg.path = path;
1968 return bsd_attr_list(0, arg, list, size);
1969#elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1970 return irix_attr_list(path, 0, list, size, 0);
1971#elif defined(HAVE_ATTROPEN)
1972 ssize_t ret = -1;
1973 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
1974 if (attrdirfd >= 0) {
1975 ret = solaris_list_xattr(attrdirfd, list, size);
1976 close(attrdirfd);
1977 }
1978 return ret;
1979#elif defined(__OS2__)
1980 return unilistxattr(path, 0, list, size);
1981#else
1982 errno = ENOSYS;
1983 return -1;
1984#endif
1985}
1986
1987ssize_t sys_llistxattr (const char *path, char *list, size_t size)
1988{
1989#if defined(HAVE_LLISTXATTR)
1990 return llistxattr(path, list, size);
1991#elif defined(HAVE_LISTXATTR) && defined(XATTR_ADD_OPT)
1992 int options = XATTR_NOFOLLOW;
1993 return listxattr(path, list, size, options);
1994#elif defined(HAVE_LLISTEA)
1995 return llistea(path, list, size);
1996#elif defined(HAVE_EXTATTR_LIST_LINK)
1997 extattr_arg arg;
1998 arg.path = path;
1999 return bsd_attr_list(1, arg, list, size);
2000#elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
2001 return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW);
2002#elif defined(HAVE_ATTROPEN)
2003 ssize_t ret = -1;
2004 int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
2005 if (attrdirfd >= 0) {
2006 ret = solaris_list_xattr(attrdirfd, list, size);
2007 close(attrdirfd);
2008 }
2009 return ret;
2010#elif defined(__OS2__)
2011 return unilistxattr(path, 0, list, size);
2012#else
2013 errno = ENOSYS;
2014 return -1;
2015#endif
2016}
2017
2018ssize_t sys_flistxattr (int filedes, char *list, size_t size)
2019{
2020#if defined(HAVE_FLISTXATTR)
2021#ifndef XATTR_ADD_OPT
2022 return flistxattr(filedes, list, size);
2023#else
2024 int options = 0;
2025 return flistxattr(filedes, list, size, options);
2026#endif
2027#elif defined(HAVE_FLISTEA)
2028 return flistea(filedes, list, size);
2029#elif defined(HAVE_EXTATTR_LIST_FD)
2030 extattr_arg arg;
2031 arg.filedes = filedes;
2032 return bsd_attr_list(2, arg, list, size);
2033#elif defined(HAVE_ATTR_LISTF)
2034 return irix_attr_list(NULL, filedes, list, size, 0);
2035#elif defined(HAVE_ATTROPEN)
2036 ssize_t ret = -1;
2037 int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
2038 if (attrdirfd >= 0) {
2039 ret = solaris_list_xattr(attrdirfd, list, size);
2040 close(attrdirfd);
2041 }
2042 return ret;
2043#elif defined(__OS2__)
2044 return unilistxattr(0, filedes, list, size);
2045#else
2046 errno = ENOSYS;
2047 return -1;
2048#endif
2049}
2050
2051int sys_removexattr (const char *path, const char *name)
2052{
2053#if defined(HAVE_REMOVEXATTR)
2054#ifndef XATTR_ADD_OPT
2055 return removexattr(path, name);
2056#else
2057 int options = 0;
2058 return removexattr(path, name, options);
2059#endif
2060#elif defined(HAVE_REMOVEEA)
2061 return removeea(path, name);
2062#elif defined(HAVE_EXTATTR_DELETE_FILE)
2063 char *s;
2064 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2065 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2066 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2067
2068 return extattr_delete_file(path, attrnamespace, attrname);
2069#elif defined(HAVE_ATTR_REMOVE)
2070 int flags = 0;
2071 char *attrname = strchr(name,'.') + 1;
2072
2073 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
2074
2075 return attr_remove(path, attrname, flags);
2076#elif defined(HAVE_ATTROPEN)
2077 int ret = -1;
2078 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
2079 if (attrdirfd >= 0) {
2080 ret = solaris_unlinkat(attrdirfd, name);
2081 close(attrdirfd);
2082 }
2083 return ret;
2084#elif defined(__OS2__)
2085 return uniremovexattr (path, 0, name);
2086#else
2087 errno = ENOSYS;
2088 return -1;
2089#endif
2090}
2091
2092int sys_lremovexattr (const char *path, const char *name)
2093{
2094#if defined(HAVE_LREMOVEXATTR)
2095 return lremovexattr(path, name);
2096#elif defined(HAVE_REMOVEXATTR) && defined(XATTR_ADD_OPT)
2097 int options = XATTR_NOFOLLOW;
2098 return removexattr(path, name, options);
2099#elif defined(HAVE_LREMOVEEA)
2100 return lremoveea(path, name);
2101#elif defined(HAVE_EXTATTR_DELETE_LINK)
2102 char *s;
2103 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2104 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2105 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2106
2107 return extattr_delete_link(path, attrnamespace, attrname);
2108#elif defined(HAVE_ATTR_REMOVE)
2109 int flags = ATTR_DONTFOLLOW;
2110 char *attrname = strchr(name,'.') + 1;
2111
2112 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
2113
2114 return attr_remove(path, attrname, flags);
2115#elif defined(HAVE_ATTROPEN)
2116 int ret = -1;
2117 int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
2118 if (attrdirfd >= 0) {
2119 ret = solaris_unlinkat(attrdirfd, name);
2120 close(attrdirfd);
2121 }
2122 return ret;
2123#elif defined(__OS2__)
2124 return uniremovexattr (path, 0, name);
2125#else
2126 errno = ENOSYS;
2127 return -1;
2128#endif
2129}
2130
2131int sys_fremovexattr (int filedes, const char *name)
2132{
2133#if defined(HAVE_FREMOVEXATTR)
2134#ifndef XATTR_ADD_OPT
2135 return fremovexattr(filedes, name);
2136#else
2137 int options = 0;
2138 return fremovexattr(filedes, name, options);
2139#endif
2140#elif defined(HAVE_FREMOVEEA)
2141 return fremoveea(filedes, name);
2142#elif defined(HAVE_EXTATTR_DELETE_FD)
2143 char *s;
2144 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2145 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2146 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2147
2148 return extattr_delete_fd(filedes, attrnamespace, attrname);
2149#elif defined(HAVE_ATTR_REMOVEF)
2150 int flags = 0;
2151 char *attrname = strchr(name,'.') + 1;
2152
2153 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
2154
2155 return attr_removef(filedes, attrname, flags);
2156#elif defined(HAVE_ATTROPEN)
2157 int ret = -1;
2158 int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
2159 if (attrdirfd >= 0) {
2160 ret = solaris_unlinkat(attrdirfd, name);
2161 close(attrdirfd);
2162 }
2163 return ret;
2164#elif defined(__OS2__)
2165 return uniremovexattr (0, filedes, name);
2166#else
2167 errno = ENOSYS;
2168 return -1;
2169#endif
2170}
2171
2172int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags)
2173{
2174#if defined(HAVE_SETXATTR)
2175#ifndef XATTR_ADD_OPT
2176 return setxattr(path, name, value, size, flags);
2177#else
2178 int options = 0;
2179 return setxattr(path, name, value, size, 0, options);
2180#endif
2181#elif defined(HAVE_SETEA)
2182 return setea(path, name, value, size, flags);
2183#elif defined(HAVE_EXTATTR_SET_FILE)
2184 char *s;
2185 int retval = 0;
2186 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2187 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2188 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2189 if (flags) {
2190 /* Check attribute existence */
2191 retval = extattr_get_file(path, attrnamespace, attrname, NULL, 0);
2192 if (retval < 0) {
2193 /* REPLACE attribute, that doesn't exist */
2194 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2195 errno = ENOATTR;
2196 return -1;
2197 }
2198 /* Ignore other errors */
2199 }
2200 else {
2201 /* CREATE attribute, that already exists */
2202 if (flags & XATTR_CREATE) {
2203 errno = EEXIST;
2204 return -1;
2205 }
2206 }
2207 }
2208 retval = extattr_set_file(path, attrnamespace, attrname, value, size);
2209 return (retval < 0) ? -1 : 0;
2210#elif defined(HAVE_ATTR_SET)
2211 int myflags = 0;
2212 char *attrname = strchr(name,'.') + 1;
2213
2214 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2215 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2216 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2217
2218 return attr_set(path, attrname, (const char *)value, size, myflags);
2219#elif defined(HAVE_ATTROPEN)
2220 int ret = -1;
2221 int myflags = O_RDWR;
2222 int attrfd;
2223 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2224 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2225 attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2226 if (attrfd >= 0) {
2227 ret = solaris_write_xattr(attrfd, value, size);
2228 close(attrfd);
2229 }
2230 return ret;
2231#elif defined(__OS2__)
2232 return unisetxattr (path, 0, name, value, size, flags);
2233#else
2234 errno = ENOSYS;
2235 return -1;
2236#endif
2237}
2238
2239int sys_lsetxattr (const char *path, const char *name, const void *value, size_t size, int flags)
2240{
2241#if defined(HAVE_LSETXATTR)
2242 return lsetxattr(path, name, value, size, flags);
2243#elif defined(HAVE_SETXATTR) && defined(XATTR_ADD_OPT)
2244 int options = XATTR_NOFOLLOW;
2245 return setxattr(path, name, value, size, 0, options);
2246#elif defined(LSETEA)
2247 return lsetea(path, name, value, size, flags);
2248#elif defined(HAVE_EXTATTR_SET_LINK)
2249 char *s;
2250 int retval = 0;
2251 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2252 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2253 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2254 if (flags) {
2255 /* Check attribute existence */
2256 retval = extattr_get_link(path, attrnamespace, attrname, NULL, 0);
2257 if (retval < 0) {
2258 /* REPLACE attribute, that doesn't exist */
2259 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2260 errno = ENOATTR;
2261 return -1;
2262 }
2263 /* Ignore other errors */
2264 }
2265 else {
2266 /* CREATE attribute, that already exists */
2267 if (flags & XATTR_CREATE) {
2268 errno = EEXIST;
2269 return -1;
2270 }
2271 }
2272 }
2273
2274 retval = extattr_set_link(path, attrnamespace, attrname, value, size);
2275 return (retval < 0) ? -1 : 0;
2276#elif defined(HAVE_ATTR_SET)
2277 int myflags = ATTR_DONTFOLLOW;
2278 char *attrname = strchr(name,'.') + 1;
2279
2280 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2281 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2282 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2283
2284 return attr_set(path, attrname, (const char *)value, size, myflags);
2285#elif defined(HAVE_ATTROPEN)
2286 int ret = -1;
2287 int myflags = O_RDWR | AT_SYMLINK_NOFOLLOW;
2288 int attrfd;
2289 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2290 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2291 attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2292 if (attrfd >= 0) {
2293 ret = solaris_write_xattr(attrfd, value, size);
2294 close(attrfd);
2295 }
2296 return ret;
2297#elif defined(__OS2__)
2298 return unisetxattr (path, 0, name, value, size, flags);
2299#else
2300 errno = ENOSYS;
2301 return -1;
2302#endif
2303}
2304
2305int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags)
2306{
2307#if defined(HAVE_FSETXATTR)
2308#ifndef XATTR_ADD_OPT
2309 return fsetxattr(filedes, name, value, size, flags);
2310#else
2311 int options = 0;
2312 return fsetxattr(filedes, name, value, size, 0, options);
2313#endif
2314#elif defined(HAVE_FSETEA)
2315 return fsetea(filedes, name, value, size, flags);
2316#elif defined(HAVE_EXTATTR_SET_FD)
2317 char *s;
2318 int retval = 0;
2319 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2320 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2321 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2322 if (flags) {
2323 /* Check attribute existence */
2324 retval = extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0);
2325 if (retval < 0) {
2326 /* REPLACE attribute, that doesn't exist */
2327 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2328 errno = ENOATTR;
2329 return -1;
2330 }
2331 /* Ignore other errors */
2332 }
2333 else {
2334 /* CREATE attribute, that already exists */
2335 if (flags & XATTR_CREATE) {
2336 errno = EEXIST;
2337 return -1;
2338 }
2339 }
2340 }
2341 retval = extattr_set_fd(filedes, attrnamespace, attrname, value, size);
2342 return (retval < 0) ? -1 : 0;
2343#elif defined(HAVE_ATTR_SETF)
2344 int myflags = 0;
2345 char *attrname = strchr(name,'.') + 1;
2346
2347 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2348 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2349 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2350
2351 return attr_setf(filedes, attrname, (const char *)value, size, myflags);
2352#elif defined(HAVE_ATTROPEN)
2353 int ret = -1;
2354 int myflags = O_RDWR | O_XATTR;
2355 int attrfd;
2356 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2357 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2358 attrfd = solaris_openat(filedes, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2359 if (attrfd >= 0) {
2360 ret = solaris_write_xattr(attrfd, value, size);
2361 close(attrfd);
2362 }
2363 return ret;
2364#elif defined(__OS2__)
2365 return unisetxattr (0, filedes, name, value, size, flags);
2366#else
2367 errno = ENOSYS;
2368 return -1;
2369#endif
2370}
2371
2372/**************************************************************************
2373 helper functions for Solaris' EA support
2374****************************************************************************/
2375#ifdef HAVE_ATTROPEN
2376static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size)
2377{
2378 struct stat sbuf;
2379
2380 if (fstat(attrfd, &sbuf) == -1) {
2381 errno = ENOATTR;
2382 return -1;
2383 }
2384
2385 /* This is to return the current size of the named extended attribute */
2386 if (size == 0) {
2387 return sbuf.st_size;
2388 }
2389
2390 /* check size and read xattr */
2391 if (sbuf.st_size > size) {
2392 errno = ERANGE;
2393 return -1;
2394 }
2395
2396 return read(attrfd, value, sbuf.st_size);
2397}
2398
2399static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size)
2400{
2401 ssize_t len = 0;
2402 DIR *dirp;
2403 struct dirent *de;
2404 int newfd = dup(attrdirfd);
2405 /* CAUTION: The originating file descriptor should not be
2406 used again following the call to fdopendir().
2407 For that reason we dup() the file descriptor
2408 here to make things more clear. */
2409 dirp = fdopendir(newfd);
2410
2411 while ((de = readdir(dirp))) {
2412 size_t listlen = strlen(de->d_name);
2413 if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) {
2414 /* we don't want "." and ".." here: */
2415 DEBUG(10,("skipped EA %s\n",de->d_name));
2416 continue;
2417 }
2418
2419 if (size == 0) {
2420 /* return the current size of the list of extended attribute names*/
2421 len += listlen + 1;
2422 } else {
2423 /* check size and copy entrieѕ + nul into list. */
2424 if ((len + listlen + 1) > size) {
2425 errno = ERANGE;
2426 len = -1;
2427 break;
2428 } else {
2429 safe_strcpy(list + len, de->d_name, listlen);
2430 len += listlen;
2431 list[len] = '\0';
2432 ++len;
2433 }
2434 }
2435 }
2436
2437 if (closedir(dirp) == -1) {
2438 DEBUG(0,("closedir dirp failed: %s\n",strerror(errno)));
2439 return -1;
2440 }
2441 return len;
2442}
2443
2444static int solaris_unlinkat(int attrdirfd, const char *name)
2445{
2446 if (unlinkat(attrdirfd, name, 0) == -1) {
2447 if (errno == ENOENT) {
2448 errno = ENOATTR;
2449 }
2450 return -1;
2451 }
2452 return 0;
2453}
2454
2455static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode)
2456{
2457 int filedes = attropen(path, attrpath, oflag, mode);
2458 if (filedes == -1) {
2459 DEBUG(10,("attropen FAILED: path: %s, name: %s, errno: %s\n",path,attrpath,strerror(errno)));
2460 if (errno == EINVAL) {
2461 errno = ENOTSUP;
2462 } else {
2463 errno = ENOATTR;
2464 }
2465 }
2466 return filedes;
2467}
2468
2469static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode)
2470{
2471 int filedes = openat(fildes, path, oflag, mode);
2472 if (filedes == -1) {
2473 DEBUG(10,("openat FAILED: fd: %d, path: %s, errno: %s\n",filedes,path,strerror(errno)));
2474 if (errno == EINVAL) {
2475 errno = ENOTSUP;
2476 } else {
2477 errno = ENOATTR;
2478 }
2479 }
2480 return filedes;
2481}
2482
2483static int solaris_write_xattr(int attrfd, const char *value, size_t size)
2484{
2485 if ((ftruncate(attrfd, 0) == 0) && (write(attrfd, value, size) == size)) {
2486 return 0;
2487 } else {
2488 DEBUG(10,("solaris_write_xattr FAILED!\n"));
2489 return -1;
2490 }
2491}
2492#endif /*HAVE_ATTROPEN*/
2493
2494
2495/****************************************************************************
2496 Return the major devicenumber for UNIX extensions.
2497****************************************************************************/
2498
2499uint32 unix_dev_major(SMB_DEV_T dev)
2500{
2501#if defined(HAVE_DEVICE_MAJOR_FN)
2502 return (uint32)major(dev);
2503#else
2504 return (uint32)(dev >> 8);
2505#endif
2506}
2507
2508/****************************************************************************
2509 Return the minor devicenumber for UNIX extensions.
2510****************************************************************************/
2511
2512uint32 unix_dev_minor(SMB_DEV_T dev)
2513{
2514#if defined(HAVE_DEVICE_MINOR_FN)
2515 return (uint32)minor(dev);
2516#else
2517 return (uint32)(dev & 0xff);
2518#endif
2519}
2520
2521#if defined(WITH_AIO)
2522
2523/*******************************************************************
2524 An aio_read wrapper that will deal with 64-bit sizes.
2525********************************************************************/
2526
2527int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2528{
2529#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_READ64)
2530 return aio_read64(aiocb);
2531#elif defined(HAVE_AIO_READ)
2532 return aio_read(aiocb);
2533#else
2534 errno = ENOSYS;
2535 return -1;
2536#endif
2537}
2538
2539/*******************************************************************
2540 An aio_write wrapper that will deal with 64-bit sizes.
2541********************************************************************/
2542
2543int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2544{
2545#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_WRITE64)
2546 return aio_write64(aiocb);
2547#elif defined(HAVE_AIO_WRITE)
2548 return aio_write(aiocb);
2549#else
2550 errno = ENOSYS;
2551 return -1;
2552#endif
2553}
2554
2555/*******************************************************************
2556 An aio_return wrapper that will deal with 64-bit sizes.
2557********************************************************************/
2558
2559ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2560{
2561#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_RETURN64)
2562 return aio_return64(aiocb);
2563#elif defined(HAVE_AIO_RETURN)
2564 return aio_return(aiocb);
2565#else
2566 errno = ENOSYS;
2567 return -1;
2568#endif
2569}
2570
2571/*******************************************************************
2572 An aio_cancel wrapper that will deal with 64-bit sizes.
2573********************************************************************/
2574
2575int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2576{
2577#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_CANCEL64)
2578 return aio_cancel64(fd, aiocb);
2579#elif defined(HAVE_AIO_CANCEL)
2580 return aio_cancel(fd, aiocb);
2581#else
2582 errno = ENOSYS;
2583 return -1;
2584#endif
2585}
2586
2587/*******************************************************************
2588 An aio_error wrapper that will deal with 64-bit sizes.
2589********************************************************************/
2590
2591int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2592{
2593#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_ERROR64)
2594 return aio_error64(aiocb);
2595#elif defined(HAVE_AIO_ERROR)
2596 return aio_error(aiocb);
2597#else
2598 errno = ENOSYS;
2599 return -1;
2600#endif
2601}
2602
2603/*******************************************************************
2604 An aio_fsync wrapper that will deal with 64-bit sizes.
2605********************************************************************/
2606
2607int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2608{
2609#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_FSYNC64)
2610 return aio_fsync64(op, aiocb);
2611#elif defined(HAVE_AIO_FSYNC)
2612 return aio_fsync(op, aiocb);
2613#else
2614 errno = ENOSYS;
2615 return -1;
2616#endif
2617}
2618
2619/*******************************************************************
2620 An aio_fsync wrapper that will deal with 64-bit sizes.
2621********************************************************************/
2622
2623int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2624{
2625#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_SUSPEND64)
2626 return aio_suspend64(cblist, n, timeout);
2627#elif defined(HAVE_AIO_FSYNC)
2628 return aio_suspend(cblist, n, timeout);
2629#else
2630 errno = ENOSYS;
2631 return -1;
2632#endif
2633}
2634#else /* !WITH_AIO */
2635
2636int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2637{
2638 errno = ENOSYS;
2639 return -1;
2640}
2641
2642int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2643{
2644 errno = ENOSYS;
2645 return -1;
2646}
2647
2648ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2649{
2650 errno = ENOSYS;
2651 return -1;
2652}
2653
2654int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2655{
2656 errno = ENOSYS;
2657 return -1;
2658}
2659
2660int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2661{
2662 errno = ENOSYS;
2663 return -1;
2664}
2665
2666int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2667{
2668 errno = ENOSYS;
2669 return -1;
2670}
2671
2672int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2673{
2674 errno = ENOSYS;
2675 return -1;
2676}
2677#endif /* WITH_AIO */
Note: See TracBrowser for help on using the repository browser.