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

Last change on this file since 902 was 902, checked in by Silvan Scherrer, 9 years ago

samba server: remove -Zbin-files, more bin work done

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