30f2ac6d008be79fee079015c55549e6773b1bce
[ambi/samba-autobuild/.git] / source3 / lib / system.c
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 #include "../lib/util/setid.h"
29
30 #ifdef HAVE_SYS_SYSCTL_H
31 #include <sys/sysctl.h>
32 #endif
33
34 #ifdef HAVE_SYS_PRCTL_H
35 #include <sys/prctl.h>
36 #endif
37
38 /*
39    The idea is that this file will eventually have wrappers around all
40    important system calls in samba. The aims are:
41
42    - to enable easier porting by putting OS dependent stuff in here
43
44    - to allow for hooks into other "pseudo-filesystems"
45
46    - to allow easier integration of things like the japanese extensions
47
48    - to support the philosophy of Samba to expose the features of
49      the OS within the SMB model. In general whatever file/printer/variable
50      expansions/etc make sense to the OS should be acceptable to Samba.
51 */
52
53
54
55 /*******************************************************************
56 A read wrapper that will deal with EINTR.
57 ********************************************************************/
58
59 ssize_t sys_read(int fd, void *buf, size_t count)
60 {
61         ssize_t ret;
62
63         do {
64                 ret = read(fd, buf, count);
65 #if defined(EWOULDBLOCK)
66         } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
67 #else
68         } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
69 #endif
70         return ret;
71 }
72
73 /*******************************************************************
74 A write wrapper that will deal with EINTR.
75 ********************************************************************/
76
77 ssize_t sys_write(int fd, const void *buf, size_t count)
78 {
79         ssize_t ret;
80
81         do {
82                 ret = write(fd, buf, count);
83 #if defined(EWOULDBLOCK)
84         } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
85 #else
86         } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
87 #endif
88         return ret;
89 }
90
91 /*******************************************************************
92 A writev wrapper that will deal with EINTR.
93 ********************************************************************/
94
95 ssize_t sys_writev(int fd, const struct iovec *iov, int iovcnt)
96 {
97         ssize_t ret;
98
99 #if 0
100         /* Try to confuse write_data_iov a bit */
101         if ((random() % 5) == 0) {
102                 return sys_write(fd, iov[0].iov_base, iov[0].iov_len);
103         }
104         if (iov[0].iov_len > 1) {
105                 return sys_write(fd, iov[0].iov_base,
106                                  (random() % (iov[0].iov_len-1)) + 1);
107         }
108 #endif
109
110         do {
111                 ret = writev(fd, iov, iovcnt);
112 #if defined(EWOULDBLOCK)
113         } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
114 #else
115         } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
116 #endif
117         return ret;
118 }
119
120 /*******************************************************************
121 A pread wrapper that will deal with EINTR
122 ********************************************************************/
123
124 #if defined(HAVE_PREAD)
125 ssize_t sys_pread(int fd, void *buf, size_t count, off_t off)
126 {
127         ssize_t ret;
128
129         do {
130                 ret = pread(fd, buf, count, off);
131         } while (ret == -1 && errno == EINTR);
132         return ret;
133 }
134 #endif
135
136 /*******************************************************************
137 A write wrapper that will deal with EINTR
138 ********************************************************************/
139
140 #if defined(HAVE_PWRITE)
141 ssize_t sys_pwrite(int fd, const void *buf, size_t count, off_t off)
142 {
143         ssize_t ret;
144
145         do {
146                 ret = pwrite(fd, buf, count, off);
147         } while (ret == -1 && errno == EINTR);
148         return ret;
149 }
150 #endif
151
152 /*******************************************************************
153 A send wrapper that will deal with EINTR or EAGAIN or EWOULDBLOCK.
154 ********************************************************************/
155
156 ssize_t sys_send(int s, const void *msg, size_t len, int flags)
157 {
158         ssize_t ret;
159
160         do {
161                 ret = send(s, msg, len, flags);
162 #if defined(EWOULDBLOCK)
163         } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
164 #else
165         } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
166 #endif
167         return ret;
168 }
169
170 /*******************************************************************
171 A recvfrom wrapper that will deal with EINTR.
172 ********************************************************************/
173
174 ssize_t sys_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
175 {
176         ssize_t ret;
177
178         do {
179                 ret = recvfrom(s, buf, len, flags, from, fromlen);
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 /*******************************************************************
189 A fcntl wrapper that will deal with EINTR.
190 ********************************************************************/
191
192 int sys_fcntl_ptr(int fd, int cmd, void *arg)
193 {
194         int ret;
195
196         do {
197                 ret = fcntl(fd, cmd, arg);
198         } while (ret == -1 && errno == EINTR);
199         return ret;
200 }
201
202 /*******************************************************************
203 A fcntl wrapper that will deal with EINTR.
204 ********************************************************************/
205
206 int sys_fcntl_long(int fd, int cmd, long arg)
207 {
208         int ret;
209
210         do {
211                 ret = fcntl(fd, cmd, arg);
212         } while (ret == -1 && errno == EINTR);
213         return ret;
214 }
215
216 /****************************************************************************
217  Get/Set all the possible time fields from a stat struct as a timespec.
218 ****************************************************************************/
219
220 static struct timespec get_atimespec(const struct stat *pst)
221 {
222 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
223         struct timespec ret;
224
225         /* Old system - no ns timestamp. */
226         ret.tv_sec = pst->st_atime;
227         ret.tv_nsec = 0;
228         return ret;
229 #else
230 #if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
231         return pst->st_atim;
232 #elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
233         struct timespec ret;
234         ret.tv_sec = pst->st_atime;
235         ret.tv_nsec = pst->st_atimensec;
236         return ret;
237 #elif defined(HAVE_STRUCT_STAT_ST_MTIME_N)
238         struct timespec ret;
239         ret.tv_sec = pst->st_atime;
240         ret.tv_nsec = pst->st_atime_n;
241         return ret;
242 #elif defined(HAVE_STRUCT_STAT_ST_UMTIME)
243         struct timespec ret;
244         ret.tv_sec = pst->st_atime;
245         ret.tv_nsec = pst->st_uatime * 1000;
246         return ret;
247 #elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
248         return pst->st_atimespec;
249 #else
250 #error  CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
251 #endif
252 #endif
253 }
254
255 static struct timespec get_mtimespec(const struct stat *pst)
256 {
257 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
258         struct timespec ret;
259
260         /* Old system - no ns timestamp. */
261         ret.tv_sec = pst->st_mtime;
262         ret.tv_nsec = 0;
263         return ret;
264 #else
265 #if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
266         return pst->st_mtim;
267 #elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
268         struct timespec ret;
269         ret.tv_sec = pst->st_mtime;
270         ret.tv_nsec = pst->st_mtimensec;
271         return ret;
272 #elif defined(HAVE_STRUCT_STAT_ST_MTIME_N)
273         struct timespec ret;
274         ret.tv_sec = pst->st_mtime;
275         ret.tv_nsec = pst->st_mtime_n;
276         return ret;
277 #elif defined(HAVE_STRUCT_STAT_ST_UMTIME)
278         struct timespec ret;
279         ret.tv_sec = pst->st_mtime;
280         ret.tv_nsec = pst->st_umtime * 1000;
281         return ret;
282 #elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
283         return pst->st_mtimespec;
284 #else
285 #error  CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
286 #endif
287 #endif
288 }
289
290 static struct timespec get_ctimespec(const struct stat *pst)
291 {
292 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
293         struct timespec ret;
294
295         /* Old system - no ns timestamp. */
296         ret.tv_sec = pst->st_ctime;
297         ret.tv_nsec = 0;
298         return ret;
299 #else
300 #if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
301         return pst->st_ctim;
302 #elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
303         struct timespec ret;
304         ret.tv_sec = pst->st_ctime;
305         ret.tv_nsec = pst->st_ctimensec;
306         return ret;
307 #elif defined(HAVE_STRUCT_STAT_ST_MTIME_N)
308         struct timespec ret;
309         ret.tv_sec = pst->st_ctime;
310         ret.tv_nsec = pst->st_ctime_n;
311         return ret;
312 #elif defined(HAVE_STRUCT_STAT_ST_UMTIME)
313         struct timespec ret;
314         ret.tv_sec = pst->st_ctime;
315         ret.tv_nsec = pst->st_uctime * 1000;
316         return ret;
317 #elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
318         return pst->st_ctimespec;
319 #else
320 #error  CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
321 #endif
322 #endif
323 }
324
325 /****************************************************************************
326  Return the best approximation to a 'create time' under UNIX from a stat
327  structure.
328 ****************************************************************************/
329
330 static struct timespec calc_create_time_stat(const struct stat *st)
331 {
332         struct timespec ret, ret1;
333         struct timespec c_time = get_ctimespec(st);
334         struct timespec m_time = get_mtimespec(st);
335         struct timespec a_time = get_atimespec(st);
336
337         ret = timespec_compare(&c_time, &m_time) < 0 ? c_time : m_time;
338         ret1 = timespec_compare(&ret, &a_time) < 0 ? ret : a_time;
339
340         if(!null_timespec(ret1)) {
341                 return ret1;
342         }
343
344         /*
345          * One of ctime, mtime or atime was zero (probably atime).
346          * Just return MIN(ctime, mtime).
347          */
348         return ret;
349 }
350
351 /****************************************************************************
352  Return the best approximation to a 'create time' under UNIX from a stat_ex
353  structure.
354 ****************************************************************************/
355
356 static struct timespec calc_create_time_stat_ex(const struct stat_ex *st)
357 {
358         struct timespec ret, ret1;
359         struct timespec c_time = st->st_ex_ctime;
360         struct timespec m_time = st->st_ex_mtime;
361         struct timespec a_time = st->st_ex_atime;
362
363         ret = timespec_compare(&c_time, &m_time) < 0 ? c_time : m_time;
364         ret1 = timespec_compare(&ret, &a_time) < 0 ? ret : a_time;
365
366         if(!null_timespec(ret1)) {
367                 return ret1;
368         }
369
370         /*
371          * One of ctime, mtime or atime was zero (probably atime).
372          * Just return MIN(ctime, mtime).
373          */
374         return ret;
375 }
376
377 /****************************************************************************
378  Return the 'create time' from a stat struct if it exists (birthtime) or else
379  use the best approximation.
380 ****************************************************************************/
381
382 static void make_create_timespec(const struct stat *pst, struct stat_ex *dst,
383                                  bool fake_dir_create_times)
384 {
385         if (S_ISDIR(pst->st_mode) && fake_dir_create_times) {
386                 dst->st_ex_btime.tv_sec = 315493200L;          /* 1/1/1980 */
387                 dst->st_ex_btime.tv_nsec = 0;
388         }
389
390         dst->st_ex_calculated_birthtime = false;
391
392 #if defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC)
393         dst->st_ex_btime = pst->st_birthtimespec;
394 #elif defined(HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC)
395         dst->st_ex_btime.tv_sec = pst->st_birthtime;
396         dst->st_ex_btime.tv_nsec = pst->st_birthtimenspec;
397 #elif defined(HAVE_STRUCT_STAT_ST_BIRTHTIME)
398         dst->st_ex_btime.tv_sec = pst->st_birthtime;
399         dst->st_ex_btime.tv_nsec = 0;
400 #else
401         dst->st_ex_btime = calc_create_time_stat(pst);
402         dst->st_ex_calculated_birthtime = true;
403 #endif
404
405         /* Deal with systems that don't initialize birthtime correctly.
406          * Pointed out by SATOH Fumiyasu <fumiyas@osstech.jp>.
407          */
408         if (null_timespec(dst->st_ex_btime)) {
409                 dst->st_ex_btime = calc_create_time_stat(pst);
410                 dst->st_ex_calculated_birthtime = true;
411         }
412 }
413
414 /****************************************************************************
415  If we update a timestamp in a stat_ex struct we may have to recalculate
416  the birthtime. For now only implement this for write time, but we may
417  also need to do it for atime and ctime. JRA.
418 ****************************************************************************/
419
420 void update_stat_ex_mtime(struct stat_ex *dst,
421                                 struct timespec write_ts)
422 {
423         dst->st_ex_mtime = write_ts;
424
425         /* We may have to recalculate btime. */
426         if (dst->st_ex_calculated_birthtime) {
427                 dst->st_ex_btime = calc_create_time_stat_ex(dst);
428         }
429 }
430
431 void update_stat_ex_create_time(struct stat_ex *dst,
432                                 struct timespec create_time)
433 {
434         dst->st_ex_btime = create_time;
435         dst->st_ex_calculated_birthtime = false;
436 }
437
438 void init_stat_ex_from_stat (struct stat_ex *dst,
439                             const struct stat *src,
440                             bool fake_dir_create_times)
441 {
442         dst->st_ex_dev = src->st_dev;
443         dst->st_ex_ino = src->st_ino;
444         dst->st_ex_mode = src->st_mode;
445         dst->st_ex_nlink = src->st_nlink;
446         dst->st_ex_uid = src->st_uid;
447         dst->st_ex_gid = src->st_gid;
448         dst->st_ex_rdev = src->st_rdev;
449         dst->st_ex_size = src->st_size;
450         dst->st_ex_atime = get_atimespec(src);
451         dst->st_ex_mtime = get_mtimespec(src);
452         dst->st_ex_ctime = get_ctimespec(src);
453         make_create_timespec(src, dst, fake_dir_create_times);
454 #ifdef HAVE_STAT_ST_BLKSIZE
455         dst->st_ex_blksize = src->st_blksize;
456 #else
457         dst->st_ex_blksize = STAT_ST_BLOCKSIZE;
458 #endif
459
460 #ifdef HAVE_STAT_ST_BLOCKS
461         dst->st_ex_blocks = src->st_blocks;
462 #else
463         dst->st_ex_blocks = src->st_size / dst->st_ex_blksize + 1;
464 #endif
465
466 #ifdef HAVE_STAT_ST_FLAGS
467         dst->st_ex_flags = src->st_flags;
468 #else
469         dst->st_ex_flags = 0;
470 #endif
471 }
472
473 /*******************************************************************
474 A stat() wrapper.
475 ********************************************************************/
476
477 int sys_stat(const char *fname, SMB_STRUCT_STAT *sbuf,
478              bool fake_dir_create_times)
479 {
480         int ret;
481         struct stat statbuf;
482         ret = stat(fname, &statbuf);
483         if (ret == 0) {
484                 /* we always want directories to appear zero size */
485                 if (S_ISDIR(statbuf.st_mode)) {
486                         statbuf.st_size = 0;
487                 }
488                 init_stat_ex_from_stat(sbuf, &statbuf, fake_dir_create_times);
489         }
490         return ret;
491 }
492
493 /*******************************************************************
494  An fstat() wrapper.
495 ********************************************************************/
496
497 int sys_fstat(int fd, SMB_STRUCT_STAT *sbuf, bool fake_dir_create_times)
498 {
499         int ret;
500         struct stat statbuf;
501         ret = fstat(fd, &statbuf);
502         if (ret == 0) {
503                 /* we always want directories to appear zero size */
504                 if (S_ISDIR(statbuf.st_mode)) {
505                         statbuf.st_size = 0;
506                 }
507                 init_stat_ex_from_stat(sbuf, &statbuf, fake_dir_create_times);
508         }
509         return ret;
510 }
511
512 /*******************************************************************
513  An lstat() wrapper.
514 ********************************************************************/
515
516 int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf,
517               bool fake_dir_create_times)
518 {
519         int ret;
520         struct stat statbuf;
521         ret = lstat(fname, &statbuf);
522         if (ret == 0) {
523                 /* we always want directories to appear zero size */
524                 if (S_ISDIR(statbuf.st_mode)) {
525                         statbuf.st_size = 0;
526                 }
527                 init_stat_ex_from_stat(sbuf, &statbuf, fake_dir_create_times);
528         }
529         return ret;
530 }
531
532 /*******************************************************************
533  An posix_fallocate() wrapper.
534 ********************************************************************/
535 int sys_posix_fallocate(int fd, off_t offset, off_t len)
536 {
537 #if defined(HAVE_POSIX_FALLOCATE) && !defined(HAVE_BROKEN_POSIX_FALLOCATE)
538         return posix_fallocate(fd, offset, len);
539 #elif defined(F_RESVSP64)
540         /* this handles XFS on IRIX */
541         struct flock64 fl;
542         off_t new_len = offset + len;
543         int ret;
544         struct stat64 sbuf;
545
546         /* unlikely to get a too large file on a 64bit system but ... */
547         if (new_len < 0)
548                 return EFBIG;
549
550         fl.l_whence = SEEK_SET;
551         fl.l_start = offset;
552         fl.l_len = len;
553
554         ret=fcntl(fd, F_RESVSP64, &fl);
555
556         if (ret != 0)
557                 return errno;
558
559         /* Make sure the file gets enlarged after we allocated space: */
560         fstat64(fd, &sbuf);
561         if (new_len > sbuf.st_size)
562                 ftruncate64(fd, new_len);
563         return 0;
564 #else
565         return ENOSYS;
566 #endif
567 }
568
569 /*******************************************************************
570  An fallocate() function that matches the semantics of the Linux one.
571 ********************************************************************/
572
573 #ifdef HAVE_LINUX_FALLOC_H
574 #include <linux/falloc.h>
575 #endif
576
577 int sys_fallocate(int fd, enum vfs_fallocate_mode mode, off_t offset, off_t len)
578 {
579 #if defined(HAVE_LINUX_FALLOCATE64) || defined(HAVE_LINUX_FALLOCATE)
580         int lmode;
581         switch (mode) {
582         case VFS_FALLOCATE_EXTEND_SIZE:
583                 lmode = 0;
584                 break;
585         case VFS_FALLOCATE_KEEP_SIZE:
586                 lmode = FALLOC_FL_KEEP_SIZE;
587                 break;
588         default:
589                 errno = EINVAL;
590                 return -1;
591         }
592 #if defined(HAVE_LINUX_FALLOCATE)
593         return fallocate(fd, lmode, offset, len);
594 #endif
595 #else
596         /* TODO - plumb in fallocate from other filesysetms like VXFS etc. JRA. */
597         errno = ENOSYS;
598         return -1;
599 #endif
600 }
601
602 #if HAVE_KERNEL_SHARE_MODES
603 #ifndef LOCK_MAND
604 #define LOCK_MAND       32      /* This is a mandatory flock */
605 #define LOCK_READ       64      /* ... Which allows concurrent read operations */
606 #define LOCK_WRITE      128     /* ... Which allows concurrent write operations */
607 #define LOCK_RW         192     /* ... Which allows concurrent read & write ops */
608 #endif
609 #endif
610
611 /*******************************************************************
612  A flock() wrapper that will perform the kernel flock.
613 ********************************************************************/
614
615 void kernel_flock(int fd, uint32 share_mode, uint32 access_mask)
616 {
617 #if HAVE_KERNEL_SHARE_MODES
618         int kernel_mode = 0;
619         if (share_mode == FILE_SHARE_WRITE) {
620                 kernel_mode = LOCK_MAND|LOCK_WRITE;
621         } else if (share_mode == FILE_SHARE_READ) {
622                 kernel_mode = LOCK_MAND|LOCK_READ;
623         } else if (share_mode == FILE_SHARE_NONE) {
624                 kernel_mode = LOCK_MAND;
625         }
626         if (kernel_mode) {
627                 flock(fd, kernel_mode);
628         }
629 #endif
630         ;
631 }
632
633
634
635 /*******************************************************************
636  An fdopendir wrapper.
637  Ugly hack - we need dirfd for this to work correctly in the
638  calling code.. JRA.
639 ********************************************************************/
640
641 DIR *sys_fdopendir(int fd)
642 {
643 #if defined(HAVE_FDOPENDIR) && defined(HAVE_DIRFD)
644         return fdopendir(fd);
645 #else
646         errno = ENOSYS;
647         return NULL;
648 #endif
649 }
650
651 /*******************************************************************
652  An mknod() wrapper.
653 ********************************************************************/
654
655 int sys_mknod(const char *path, mode_t mode, SMB_DEV_T dev)
656 {
657 #if defined(HAVE_MKNOD)
658         return mknod(path, mode, dev);
659 #else
660         /* No mknod system call. */
661         errno = ENOSYS;
662         return -1;
663 #endif
664 }
665
666 /*******************************************************************
667 The wait() calls vary between systems
668 ********************************************************************/
669
670 int sys_waitpid(pid_t pid,int *status,int options)
671 {
672 #ifdef HAVE_WAITPID
673         return waitpid(pid,status,options);
674 #else /* HAVE_WAITPID */
675         return wait4(pid, status, options, NULL);
676 #endif /* HAVE_WAITPID */
677 }
678
679 /*******************************************************************
680  System wrapper for getwd. Always returns MALLOC'ed memory, or NULL
681  on error (malloc fail usually).
682 ********************************************************************/
683
684 char *sys_getwd(void)
685 {
686 #ifdef GETCWD_TAKES_NULL
687         return getcwd(NULL, 0);
688 #elif HAVE_GETCWD
689         char *wd = NULL, *s = NULL;
690         size_t allocated = PATH_MAX;
691
692         while (1) {
693                 s = SMB_REALLOC_ARRAY(s, char, allocated);
694                 if (s == NULL) {
695                         return NULL;
696                 }
697                 wd = getcwd(s, allocated);
698                 if (wd) {
699                         break;
700                 }
701                 if (errno != ERANGE) {
702                         SAFE_FREE(s);
703                         break;
704                 }
705                 allocated *= 2;
706                 if (allocated < PATH_MAX) {
707                         SAFE_FREE(s);
708                         break;
709                 }
710         }
711         return wd;
712 #else
713         char *s = SMB_MALLOC_ARRAY(char, PATH_MAX);
714         if (s == NULL) {
715                 return NULL;
716         }
717         return getwd(s);
718 #endif
719 }
720
721 #if defined(HAVE_POSIX_CAPABILITIES)
722
723 /**************************************************************************
724  Try and abstract process capabilities (for systems that have them).
725 ****************************************************************************/
726
727 /* Set the POSIX capabilities needed for the given purpose into the effective
728  * capability set of the current process. Make sure they are always removed
729  * from the inheritable set, because there is no circumstance in which our
730  * children should inherit our elevated privileges.
731  */
732 static bool set_process_capability(enum smbd_capability capability,
733                                    bool enable)
734 {
735         cap_value_t cap_vals[2] = {0};
736         int num_cap_vals = 0;
737
738         cap_t cap;
739
740 #if defined(HAVE_PRCTL) && defined(PR_GET_KEEPCAPS) && defined(PR_SET_KEEPCAPS)
741         /* On Linux, make sure that any capabilities we grab are sticky
742          * across UID changes. We expect that this would allow us to keep both
743          * the effective and permitted capability sets, but as of circa 2.6.16,
744          * only the permitted set is kept. It is a bug (which we work around)
745          * that the effective set is lost, but we still require the effective
746          * set to be kept.
747          */
748         if (!prctl(PR_GET_KEEPCAPS)) {
749                 prctl(PR_SET_KEEPCAPS, 1);
750         }
751 #endif
752
753         cap = cap_get_proc();
754         if (cap == NULL) {
755                 DEBUG(0,("set_process_capability: cap_get_proc failed: %s\n",
756                         strerror(errno)));
757                 return False;
758         }
759
760         switch (capability) {
761                 case KERNEL_OPLOCK_CAPABILITY:
762 #ifdef CAP_NETWORK_MGT
763                         /* IRIX has CAP_NETWORK_MGT for oplocks. */
764                         cap_vals[num_cap_vals++] = CAP_NETWORK_MGT;
765 #endif
766                         break;
767                 case DMAPI_ACCESS_CAPABILITY:
768 #ifdef CAP_DEVICE_MGT
769                         /* IRIX has CAP_DEVICE_MGT for DMAPI access. */
770                         cap_vals[num_cap_vals++] = CAP_DEVICE_MGT;
771 #elif CAP_MKNOD
772                         /* Linux has CAP_MKNOD for DMAPI access. */
773                         cap_vals[num_cap_vals++] = CAP_MKNOD;
774 #endif
775                         break;
776                 case LEASE_CAPABILITY:
777 #ifdef CAP_LEASE
778                         cap_vals[num_cap_vals++] = CAP_LEASE;
779 #endif
780                         break;
781         }
782
783         SMB_ASSERT(num_cap_vals <= ARRAY_SIZE(cap_vals));
784
785         if (num_cap_vals == 0) {
786                 cap_free(cap);
787                 return True;
788         }
789
790         cap_set_flag(cap, CAP_EFFECTIVE, num_cap_vals, cap_vals,
791                 enable ? CAP_SET : CAP_CLEAR);
792
793         /* We never want to pass capabilities down to our children, so make
794          * sure they are not inherited.
795          */
796         cap_set_flag(cap, CAP_INHERITABLE, num_cap_vals, cap_vals, CAP_CLEAR);
797
798         if (cap_set_proc(cap) == -1) {
799                 DEBUG(0, ("set_process_capability: cap_set_proc failed: %s\n",
800                         strerror(errno)));
801                 cap_free(cap);
802                 return False;
803         }
804
805         cap_free(cap);
806         return True;
807 }
808
809 #endif /* HAVE_POSIX_CAPABILITIES */
810
811 /****************************************************************************
812  Gain the oplock capability from the kernel if possible.
813 ****************************************************************************/
814
815 void set_effective_capability(enum smbd_capability capability)
816 {
817 #if defined(HAVE_POSIX_CAPABILITIES)
818         set_process_capability(capability, True);
819 #endif /* HAVE_POSIX_CAPABILITIES */
820 }
821
822 void drop_effective_capability(enum smbd_capability capability)
823 {
824 #if defined(HAVE_POSIX_CAPABILITIES)
825         set_process_capability(capability, False);
826 #endif /* HAVE_POSIX_CAPABILITIES */
827 }
828
829 /**************************************************************************
830  Wrapper for random().
831 ****************************************************************************/
832
833 long sys_random(void)
834 {
835 #if defined(HAVE_RANDOM)
836         return (long)random();
837 #elif defined(HAVE_RAND)
838         return (long)rand();
839 #else
840         DEBUG(0,("Error - no random function available !\n"));
841         exit(1);
842 #endif
843 }
844
845 /**************************************************************************
846  Wrapper for srandom().
847 ****************************************************************************/
848
849 void sys_srandom(unsigned int seed)
850 {
851 #if defined(HAVE_SRANDOM)
852         srandom(seed);
853 #elif defined(HAVE_SRAND)
854         srand(seed);
855 #else
856         DEBUG(0,("Error - no srandom function available !\n"));
857         exit(1);
858 #endif
859 }
860
861 #ifndef NGROUPS_MAX
862 #define NGROUPS_MAX 32 /* Guess... */
863 #endif
864
865 /**************************************************************************
866  Returns equivalent to NGROUPS_MAX - using sysconf if needed.
867 ****************************************************************************/
868
869 int groups_max(void)
870 {
871 #if defined(SYSCONF_SC_NGROUPS_MAX)
872         int ret = sysconf(_SC_NGROUPS_MAX);
873         return (ret == -1) ? NGROUPS_MAX : ret;
874 #else
875         return NGROUPS_MAX;
876 #endif
877 }
878
879 /**************************************************************************
880  Wrap setgroups and getgroups for systems that declare getgroups() as
881  returning an array of gid_t, but actuall return an array of int.
882 ****************************************************************************/
883
884 #if defined(HAVE_BROKEN_GETGROUPS)
885
886 #ifdef HAVE_BROKEN_GETGROUPS
887 #define GID_T int
888 #else
889 #define GID_T gid_t
890 #endif
891
892 static int sys_broken_getgroups(int setlen, gid_t *gidset)
893 {
894         GID_T gid;
895         GID_T *group_list;
896         int i, ngroups;
897
898         if(setlen == 0) {
899                 return getgroups(setlen, &gid);
900         }
901
902         /*
903          * Broken case. We need to allocate a
904          * GID_T array of size setlen.
905          */
906
907         if(setlen < 0) {
908                 errno = EINVAL; 
909                 return -1;
910         } 
911
912         if (setlen == 0)
913                 setlen = groups_max();
914
915         if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
916                 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
917                 return -1;
918         }
919
920         if((ngroups = getgroups(setlen, group_list)) < 0) {
921                 int saved_errno = errno;
922                 SAFE_FREE(group_list);
923                 errno = saved_errno;
924                 return -1;
925         }
926
927         for(i = 0; i < ngroups; i++)
928                 gidset[i] = (gid_t)group_list[i];
929
930         SAFE_FREE(group_list);
931         return ngroups;
932 }
933
934 static int sys_broken_setgroups(int setlen, gid_t *gidset)
935 {
936         GID_T *group_list;
937         int i ; 
938
939         if (setlen == 0)
940                 return 0 ;
941
942         if (setlen < 0 || setlen > groups_max()) {
943                 errno = EINVAL; 
944                 return -1;   
945         }
946
947         /*
948          * Broken case. We need to allocate a
949          * GID_T array of size setlen.
950          */
951
952         if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
953                 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
954                 return -1;    
955         }
956
957         for(i = 0; i < setlen; i++) 
958                 group_list[i] = (GID_T) gidset[i]; 
959
960         if(samba_setgroups(setlen, group_list) != 0) {
961                 int saved_errno = errno;
962                 SAFE_FREE(group_list);
963                 errno = saved_errno;
964                 return -1;
965         }
966
967         SAFE_FREE(group_list);
968         return 0 ;
969 }
970
971 #endif /* HAVE_BROKEN_GETGROUPS */
972
973 /* This is a list of systems that require the first GID passed to setgroups(2)
974  * to be the effective GID. If your system is one of these, add it here.
975  */
976 #if defined (FREEBSD) || defined (DARWINOS)
977 #define USE_BSD_SETGROUPS
978 #endif
979
980 #if defined(USE_BSD_SETGROUPS)
981 /* Depending on the particular BSD implementation, the first GID that is
982  * passed to setgroups(2) will either be ignored or will set the credential's
983  * effective GID. In either case, the right thing to do is to guarantee that
984  * gidset[0] is the effective GID.
985  */
986 static int sys_bsd_setgroups(gid_t primary_gid, int setlen, const gid_t *gidset)
987 {
988         gid_t *new_gidset = NULL;
989         int max;
990         int ret;
991
992         /* setgroups(2) will fail with EINVAL if we pass too many groups. */
993         max = groups_max();
994
995         /* No group list, just make sure we are setting the efective GID. */
996         if (setlen == 0) {
997                 return samba_setgroups(1, &primary_gid);
998         }
999
1000         /* If the primary gid is not the first array element, grow the array
1001          * and insert it at the front.
1002          */
1003         if (gidset[0] != primary_gid) {
1004                 new_gidset = SMB_MALLOC_ARRAY(gid_t, setlen + 1);
1005                 if (new_gidset == NULL) {
1006                         return -1;
1007                 }
1008
1009                 memcpy(new_gidset + 1, gidset, (setlen * sizeof(gid_t)));
1010                 new_gidset[0] = primary_gid;
1011                 setlen++;
1012         }
1013
1014         if (setlen > max) {
1015                 DEBUG(3, ("forced to truncate group list from %d to %d\n",
1016                         setlen, max));
1017                 setlen = max;
1018         }
1019
1020 #if defined(HAVE_BROKEN_GETGROUPS)
1021         ret = sys_broken_setgroups(setlen, new_gidset ? new_gidset : gidset);
1022 #else
1023         ret = samba_setgroups(setlen, new_gidset ? new_gidset : gidset);
1024 #endif
1025
1026         if (new_gidset) {
1027                 int errsav = errno;
1028                 SAFE_FREE(new_gidset);
1029                 errno = errsav;
1030         }
1031
1032         return ret;
1033 }
1034
1035 #endif /* USE_BSD_SETGROUPS */
1036
1037 /**************************************************************************
1038  Wrapper for getgroups. Deals with broken (int) case.
1039 ****************************************************************************/
1040
1041 int sys_getgroups(int setlen, gid_t *gidset)
1042 {
1043 #if defined(HAVE_BROKEN_GETGROUPS)
1044         return sys_broken_getgroups(setlen, gidset);
1045 #else
1046         return getgroups(setlen, gidset);
1047 #endif
1048 }
1049
1050 /**************************************************************************
1051  Wrapper for setgroups. Deals with broken (int) case and BSD case.
1052 ****************************************************************************/
1053
1054 int sys_setgroups(gid_t UNUSED(primary_gid), int setlen, gid_t *gidset)
1055 {
1056 #if !defined(HAVE_SETGROUPS)
1057         errno = ENOSYS;
1058         return -1;
1059 #endif /* HAVE_SETGROUPS */
1060
1061 #if defined(USE_BSD_SETGROUPS)
1062         return sys_bsd_setgroups(primary_gid, setlen, gidset);
1063 #elif defined(HAVE_BROKEN_GETGROUPS)
1064         return sys_broken_setgroups(setlen, gidset);
1065 #else
1066         return samba_setgroups(setlen, gidset);
1067 #endif
1068 }
1069
1070 /**************************************************************************
1071  Extract a command into an arg list.
1072 ****************************************************************************/
1073
1074 static char **extract_args(TALLOC_CTX *mem_ctx, const char *command)
1075 {
1076         char *trunc_cmd;
1077         char *saveptr;
1078         char *ptr;
1079         int argcl;
1080         char **argl = NULL;
1081         int i;
1082
1083         if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1084                 DEBUG(0, ("talloc failed\n"));
1085                 goto nomem;
1086         }
1087
1088         if(!(ptr = strtok_r(trunc_cmd, " \t", &saveptr))) {
1089                 TALLOC_FREE(trunc_cmd);
1090                 errno = EINVAL;
1091                 return NULL;
1092         }
1093
1094         /*
1095          * Count the args.
1096          */
1097
1098         for( argcl = 1; ptr; ptr = strtok_r(NULL, " \t", &saveptr))
1099                 argcl++;
1100
1101         TALLOC_FREE(trunc_cmd);
1102
1103         if (!(argl = talloc_array(mem_ctx, char *, argcl + 1))) {
1104                 goto nomem;
1105         }
1106
1107         /*
1108          * Now do the extraction.
1109          */
1110
1111         if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1112                 goto nomem;
1113         }
1114
1115         ptr = strtok_r(trunc_cmd, " \t", &saveptr);
1116         i = 0;
1117
1118         if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1119                 goto nomem;
1120         }
1121
1122         while((ptr = strtok_r(NULL, " \t", &saveptr)) != NULL) {
1123
1124                 if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1125                         goto nomem;
1126                 }
1127         }
1128
1129         argl[i++] = NULL;
1130         TALLOC_FREE(trunc_cmd);
1131         return argl;
1132
1133  nomem:
1134         DEBUG(0, ("talloc failed\n"));
1135         TALLOC_FREE(trunc_cmd);
1136         TALLOC_FREE(argl);
1137         errno = ENOMEM;
1138         return NULL;
1139 }
1140
1141 /**************************************************************************
1142  Wrapper for popen. Safer as it doesn't search a path.
1143  Modified from the glibc sources.
1144  modified by tridge to return a file descriptor. We must kick our FILE* habit
1145 ****************************************************************************/
1146
1147 typedef struct _popen_list
1148 {
1149         int fd;
1150         pid_t child_pid;
1151         struct _popen_list *next;
1152 } popen_list;
1153
1154 static popen_list *popen_chain;
1155
1156 int sys_popen(const char *command)
1157 {
1158         int parent_end, child_end;
1159         int pipe_fds[2];
1160         popen_list *entry = NULL;
1161         char **argl = NULL;
1162         int ret;
1163
1164         if (!*command) {
1165                 errno = EINVAL;
1166                 return -1;
1167         }
1168
1169         ret = pipe(pipe_fds);
1170         if (ret < 0) {
1171                 DEBUG(0, ("sys_popen: error opening pipe: %s\n",
1172                           strerror(errno)));
1173                 return -1;
1174         }
1175
1176         parent_end = pipe_fds[0];
1177         child_end = pipe_fds[1];
1178
1179         if((entry = SMB_MALLOC_P(popen_list)) == NULL)
1180                 goto err_exit;
1181
1182         ZERO_STRUCTP(entry);
1183
1184         /*
1185          * Extract the command and args into a NULL terminated array.
1186          */
1187
1188         if(!(argl = extract_args(NULL, command)))
1189                 goto err_exit;
1190
1191         entry->child_pid = fork();
1192
1193         if (entry->child_pid == -1) {
1194                 goto err_exit;
1195         }
1196
1197         if (entry->child_pid == 0) {
1198
1199                 /*
1200                  * Child !
1201                  */
1202
1203                 int child_std_end = STDOUT_FILENO;
1204                 popen_list *p;
1205
1206                 close(parent_end);
1207                 if (child_end != child_std_end) {
1208                         dup2 (child_end, child_std_end);
1209                         close (child_end);
1210                 }
1211
1212                 /*
1213                  * POSIX.2:  "popen() shall ensure that any streams from previous
1214                  * popen() calls that remain open in the parent process are closed
1215                  * in the new child process."
1216                  */
1217
1218                 for (p = popen_chain; p; p = p->next)
1219                         close(p->fd);
1220
1221                 ret = execv(argl[0], argl);
1222                 if (ret == -1) {
1223                         DEBUG(0, ("sys_popen: ERROR executing command "
1224                                   "'%s': %s\n", command, strerror(errno)));
1225                 }
1226                 _exit (127);
1227         }
1228
1229         /*
1230          * Parent.
1231          */
1232
1233         close (child_end);
1234         TALLOC_FREE(argl);
1235
1236         /* Link into popen_chain. */
1237         entry->next = popen_chain;
1238         popen_chain = entry;
1239         entry->fd = parent_end;
1240
1241         return entry->fd;
1242
1243 err_exit:
1244
1245         SAFE_FREE(entry);
1246         TALLOC_FREE(argl);
1247         close(pipe_fds[0]);
1248         close(pipe_fds[1]);
1249         return -1;
1250 }
1251
1252 /**************************************************************************
1253  Wrapper for pclose. Modified from the glibc sources.
1254 ****************************************************************************/
1255
1256 int sys_pclose(int fd)
1257 {
1258         int wstatus;
1259         popen_list **ptr = &popen_chain;
1260         popen_list *entry = NULL;
1261         pid_t wait_pid;
1262         int status = -1;
1263
1264         /* Unlink from popen_chain. */
1265         for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
1266                 if ((*ptr)->fd == fd) {
1267                         entry = *ptr;
1268                         *ptr = (*ptr)->next;
1269                         status = 0;
1270                         break;
1271                 }
1272         }
1273
1274         if (status < 0 || close(entry->fd) < 0)
1275                 return -1;
1276
1277         /*
1278          * As Samba is catching and eating child process
1279          * exits we don't really care about the child exit
1280          * code, a -1 with errno = ECHILD will do fine for us.
1281          */
1282
1283         do {
1284                 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
1285         } while (wait_pid == -1 && errno == EINTR);
1286
1287         SAFE_FREE(entry);
1288
1289         if (wait_pid == -1)
1290                 return -1;
1291         return wstatus;
1292 }
1293
1294 /**************************************************************************
1295  Wrapper for Admin Logs.
1296 ****************************************************************************/
1297
1298  void sys_adminlog(int priority, const char *format_str, ...) 
1299 {
1300         va_list ap;
1301         int ret;
1302         char *msgbuf = NULL;
1303
1304         va_start( ap, format_str );
1305         ret = vasprintf( &msgbuf, format_str, ap );
1306         va_end( ap );
1307
1308         if (ret == -1)
1309                 return;
1310
1311 #if defined(HAVE_SYSLOG)
1312         syslog( priority, "%s", msgbuf );
1313 #else
1314         DEBUG(0,("%s", msgbuf ));
1315 #endif
1316         SAFE_FREE(msgbuf);
1317 }
1318
1319 /****************************************************************************
1320  Return the major devicenumber for UNIX extensions.
1321 ****************************************************************************/
1322
1323 uint32 unix_dev_major(SMB_DEV_T dev)
1324 {
1325 #if defined(HAVE_DEVICE_MAJOR_FN)
1326         return (uint32)major(dev);
1327 #else
1328         return (uint32)(dev >> 8);
1329 #endif
1330 }
1331
1332 /****************************************************************************
1333  Return the minor devicenumber for UNIX extensions.
1334 ****************************************************************************/
1335
1336 uint32 unix_dev_minor(SMB_DEV_T dev)
1337 {
1338 #if defined(HAVE_DEVICE_MINOR_FN)
1339         return (uint32)minor(dev);
1340 #else
1341         return (uint32)(dev & 0xff);
1342 #endif
1343 }
1344
1345 #if 0
1346 /*******************************************************************
1347  Return the number of CPUs.
1348 ********************************************************************/
1349
1350 int sys_get_number_of_cores(void)
1351 {
1352         int ret = -1;
1353
1354 #if defined(HAVE_SYSCONF)
1355 #if defined(_SC_NPROCESSORS_ONLN)
1356         ret = (int)sysconf(_SC_NPROCESSORS_ONLN);
1357 #endif
1358 #if defined(_SC_NPROCESSORS_CONF)
1359         if (ret < 1) {
1360                 ret = (int)sysconf(_SC_NPROCESSORS_CONF);
1361         }
1362 #endif
1363 #elif defined(HAVE_SYSCTL) && defined(CTL_HW)
1364         int name[2];
1365         unsigned int len = sizeof(ret);
1366
1367         name[0] = CTL_HW;
1368 #if defined(HW_AVAILCPU)
1369         name[1] = HW_AVAILCPU;
1370
1371         if (sysctl(name, 2, &ret, &len, NULL, 0) == -1) {
1372                 ret = -1;
1373         }
1374 #endif
1375 #if defined(HW_NCPU)
1376         if(ret < 1) {
1377                 name[0] = CTL_HW;
1378                 name[1] = HW_NCPU;
1379                 if (sysctl(nm, 2, &count, &len, NULL, 0) == -1) {
1380                         ret = -1;
1381                 }
1382         }
1383 #endif
1384 #endif
1385         if (ret < 1) {
1386                 ret = 1;
1387         }
1388         return ret;
1389 }
1390 #endif