s3: VFS: Add SMB_VFS_FCNTL
[samba.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 A send wrapper that will deal with EINTR or EAGAIN or EWOULDBLOCK.
55 ********************************************************************/
56
57 ssize_t sys_send(int s, const void *msg, size_t len, int flags)
58 {
59         ssize_t ret;
60
61         do {
62                 ret = send(s, msg, len, flags);
63         } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
64
65         return ret;
66 }
67
68 /*******************************************************************
69 A recvfrom wrapper that will deal with EINTR.
70 NB. As used with non-blocking sockets, return on EAGAIN/EWOULDBLOCK
71 ********************************************************************/
72
73 ssize_t sys_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
74 {
75         ssize_t ret;
76
77         do {
78                 ret = recvfrom(s, buf, len, flags, from, fromlen);
79         } while (ret == -1 && (errno == EINTR));
80         return ret;
81 }
82
83 /*******************************************************************
84 A fcntl wrapper that will deal with EINTR.
85 ********************************************************************/
86
87 int sys_fcntl_ptr(int fd, int cmd, void *arg)
88 {
89         int ret;
90
91         do {
92                 ret = fcntl(fd, cmd, arg);
93         } while (ret == -1 && errno == EINTR);
94         return ret;
95 }
96
97 /*******************************************************************
98 A fcntl wrapper that will deal with EINTR.
99 ********************************************************************/
100
101 int sys_fcntl_long(int fd, int cmd, long arg)
102 {
103         int ret;
104
105         do {
106                 ret = fcntl(fd, cmd, arg);
107         } while (ret == -1 && errno == EINTR);
108         return ret;
109 }
110
111 /*******************************************************************
112 A fcntl wrapper that will deal with EINTR.
113 ********************************************************************/
114
115 int sys_fcntl_int(int fd, int cmd, int arg)
116 {
117         int ret;
118
119         do {
120                 ret = fcntl(fd, cmd, arg);
121         } while (ret == -1 && errno == EINTR);
122         return ret;
123 }
124
125 /****************************************************************************
126  Get/Set all the possible time fields from a stat struct as a timespec.
127 ****************************************************************************/
128
129 static struct timespec get_atimespec(const struct stat *pst)
130 {
131 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
132         struct timespec ret;
133
134         /* Old system - no ns timestamp. */
135         ret.tv_sec = pst->st_atime;
136         ret.tv_nsec = 0;
137         return ret;
138 #else
139 #if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
140         struct timespec ret;
141         ret.tv_sec = pst->st_atim.tv_sec;
142         ret.tv_nsec = pst->st_atim.tv_nsec;
143         return ret;
144 #elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
145         struct timespec ret;
146         ret.tv_sec = pst->st_atime;
147         ret.tv_nsec = pst->st_atimensec;
148         return ret;
149 #elif defined(HAVE_STRUCT_STAT_ST_MTIME_N)
150         struct timespec ret;
151         ret.tv_sec = pst->st_atime;
152         ret.tv_nsec = pst->st_atime_n;
153         return ret;
154 #elif defined(HAVE_STRUCT_STAT_ST_UMTIME)
155         struct timespec ret;
156         ret.tv_sec = pst->st_atime;
157         ret.tv_nsec = pst->st_uatime * 1000;
158         return ret;
159 #elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
160         return pst->st_atimespec;
161 #else
162 #error  CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
163 #endif
164 #endif
165 }
166
167 static struct timespec get_mtimespec(const struct stat *pst)
168 {
169 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
170         struct timespec ret;
171
172         /* Old system - no ns timestamp. */
173         ret.tv_sec = pst->st_mtime;
174         ret.tv_nsec = 0;
175         return ret;
176 #else
177 #if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
178         struct timespec ret;
179         ret.tv_sec = pst->st_mtim.tv_sec;
180         ret.tv_nsec = pst->st_mtim.tv_nsec;
181         return ret;
182 #elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
183         struct timespec ret;
184         ret.tv_sec = pst->st_mtime;
185         ret.tv_nsec = pst->st_mtimensec;
186         return ret;
187 #elif defined(HAVE_STRUCT_STAT_ST_MTIME_N)
188         struct timespec ret;
189         ret.tv_sec = pst->st_mtime;
190         ret.tv_nsec = pst->st_mtime_n;
191         return ret;
192 #elif defined(HAVE_STRUCT_STAT_ST_UMTIME)
193         struct timespec ret;
194         ret.tv_sec = pst->st_mtime;
195         ret.tv_nsec = pst->st_umtime * 1000;
196         return ret;
197 #elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
198         return pst->st_mtimespec;
199 #else
200 #error  CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
201 #endif
202 #endif
203 }
204
205 static struct timespec get_ctimespec(const struct stat *pst)
206 {
207 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
208         struct timespec ret;
209
210         /* Old system - no ns timestamp. */
211         ret.tv_sec = pst->st_ctime;
212         ret.tv_nsec = 0;
213         return ret;
214 #else
215 #if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
216         struct timespec ret;
217         ret.tv_sec = pst->st_ctim.tv_sec;
218         ret.tv_nsec = pst->st_ctim.tv_nsec;
219         return ret;
220 #elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
221         struct timespec ret;
222         ret.tv_sec = pst->st_ctime;
223         ret.tv_nsec = pst->st_ctimensec;
224         return ret;
225 #elif defined(HAVE_STRUCT_STAT_ST_MTIME_N)
226         struct timespec ret;
227         ret.tv_sec = pst->st_ctime;
228         ret.tv_nsec = pst->st_ctime_n;
229         return ret;
230 #elif defined(HAVE_STRUCT_STAT_ST_UMTIME)
231         struct timespec ret;
232         ret.tv_sec = pst->st_ctime;
233         ret.tv_nsec = pst->st_uctime * 1000;
234         return ret;
235 #elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
236         return pst->st_ctimespec;
237 #else
238 #error  CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
239 #endif
240 #endif
241 }
242
243 /****************************************************************************
244  Return the best approximation to a 'create time' under UNIX from a stat
245  structure.
246 ****************************************************************************/
247
248 static struct timespec calc_create_time_stat(const struct stat *st)
249 {
250         struct timespec ret, ret1;
251         struct timespec c_time = get_ctimespec(st);
252         struct timespec m_time = get_mtimespec(st);
253         struct timespec a_time = get_atimespec(st);
254
255         ret = timespec_compare(&c_time, &m_time) < 0 ? c_time : m_time;
256         ret1 = timespec_compare(&ret, &a_time) < 0 ? ret : a_time;
257
258         if(!null_timespec(ret1)) {
259                 return ret1;
260         }
261
262         /*
263          * One of ctime, mtime or atime was zero (probably atime).
264          * Just return MIN(ctime, mtime).
265          */
266         return ret;
267 }
268
269 /****************************************************************************
270  Return the best approximation to a 'create time' under UNIX from a stat_ex
271  structure.
272 ****************************************************************************/
273
274 static struct timespec calc_create_time_stat_ex(const struct stat_ex *st)
275 {
276         struct timespec ret, ret1;
277         struct timespec c_time = st->st_ex_ctime;
278         struct timespec m_time = st->st_ex_mtime;
279         struct timespec a_time = st->st_ex_atime;
280
281         ret = timespec_compare(&c_time, &m_time) < 0 ? c_time : m_time;
282         ret1 = timespec_compare(&ret, &a_time) < 0 ? ret : a_time;
283
284         if(!null_timespec(ret1)) {
285                 return ret1;
286         }
287
288         /*
289          * One of ctime, mtime or atime was zero (probably atime).
290          * Just return MIN(ctime, mtime).
291          */
292         return ret;
293 }
294
295 /****************************************************************************
296  Return the 'create time' from a stat struct if it exists (birthtime) or else
297  use the best approximation.
298 ****************************************************************************/
299
300 static void make_create_timespec(const struct stat *pst, struct stat_ex *dst,
301                                  bool fake_dir_create_times)
302 {
303         if (S_ISDIR(pst->st_mode) && fake_dir_create_times) {
304                 dst->st_ex_btime.tv_sec = 315493200L;          /* 1/1/1980 */
305                 dst->st_ex_btime.tv_nsec = 0;
306         }
307
308         dst->st_ex_iflags &= ~ST_EX_IFLAG_CALCULATED_BTIME;
309
310 #if defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC)
311         dst->st_ex_btime = pst->st_birthtimespec;
312 #elif defined(HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC)
313         dst->st_ex_btime.tv_sec = pst->st_birthtime;
314         dst->st_ex_btime.tv_nsec = pst->st_birthtimenspec;
315 #elif defined(HAVE_STRUCT_STAT_ST_BIRTHTIME)
316         dst->st_ex_btime.tv_sec = pst->st_birthtime;
317         dst->st_ex_btime.tv_nsec = 0;
318 #else
319         dst->st_ex_btime = calc_create_time_stat(pst);
320         dst->st_ex_iflags |= ST_EX_IFLAG_CALCULATED_BTIME;
321 #endif
322
323         /* Deal with systems that don't initialize birthtime correctly.
324          * Pointed out by SATOH Fumiyasu <fumiyas@osstech.jp>.
325          */
326         if (null_timespec(dst->st_ex_btime)) {
327                 dst->st_ex_btime = calc_create_time_stat(pst);
328                 dst->st_ex_iflags |= ST_EX_IFLAG_CALCULATED_BTIME;
329         }
330
331         dst->st_ex_itime = dst->st_ex_btime;
332         dst->st_ex_iflags |= ST_EX_IFLAG_CALCULATED_ITIME;
333 }
334
335 /****************************************************************************
336  If we update a timestamp in a stat_ex struct we may have to recalculate
337  the birthtime. For now only implement this for write time, but we may
338  also need to do it for atime and ctime. JRA.
339 ****************************************************************************/
340
341 void update_stat_ex_mtime(struct stat_ex *dst,
342                                 struct timespec write_ts)
343 {
344         dst->st_ex_mtime = write_ts;
345
346         /* We may have to recalculate btime. */
347         if (dst->st_ex_iflags & ST_EX_IFLAG_CALCULATED_BTIME) {
348                 dst->st_ex_btime = calc_create_time_stat_ex(dst);
349         }
350 }
351
352 void update_stat_ex_create_time(struct stat_ex *dst,
353                                 struct timespec create_time)
354 {
355         dst->st_ex_btime = create_time;
356         dst->st_ex_iflags &= ~ST_EX_IFLAG_CALCULATED_BTIME;
357 }
358
359 void update_stat_ex_itime(struct stat_ex *dst,
360                           struct timespec itime)
361 {
362         dst->st_ex_itime = itime;
363         dst->st_ex_iflags &= ~ST_EX_IFLAG_CALCULATED_ITIME;
364 }
365
366 void update_stat_ex_file_id(struct stat_ex *dst, uint64_t file_id)
367 {
368         dst->st_ex_file_id = file_id;
369         dst->st_ex_iflags &= ~ST_EX_IFLAG_CALCULATED_FILE_ID;
370 }
371
372 void update_stat_ex_from_saved_stat(struct stat_ex *dst,
373                                     const struct stat_ex *src)
374 {
375         if (!VALID_STAT(*src)) {
376                 return;
377         }
378
379         if (!(src->st_ex_iflags & ST_EX_IFLAG_CALCULATED_BTIME)) {
380                 update_stat_ex_create_time(dst, src->st_ex_btime);
381         }
382
383         if (!(src->st_ex_iflags & ST_EX_IFLAG_CALCULATED_ITIME)) {
384                 update_stat_ex_itime(dst, src->st_ex_itime);
385         }
386
387         if (!(src->st_ex_iflags & ST_EX_IFLAG_CALCULATED_FILE_ID)) {
388                 update_stat_ex_file_id(dst, src->st_ex_file_id);
389         }
390 }
391
392 void init_stat_ex_from_stat (struct stat_ex *dst,
393                             const struct stat *src,
394                             bool fake_dir_create_times)
395 {
396         dst->st_ex_dev = src->st_dev;
397         dst->st_ex_ino = src->st_ino;
398         dst->st_ex_mode = src->st_mode;
399         dst->st_ex_nlink = src->st_nlink;
400         dst->st_ex_uid = src->st_uid;
401         dst->st_ex_gid = src->st_gid;
402         dst->st_ex_rdev = src->st_rdev;
403         dst->st_ex_size = src->st_size;
404         dst->st_ex_atime = get_atimespec(src);
405         dst->st_ex_mtime = get_mtimespec(src);
406         dst->st_ex_ctime = get_ctimespec(src);
407         dst->st_ex_iflags = 0;
408         make_create_timespec(src, dst, fake_dir_create_times);
409 #ifdef HAVE_STAT_ST_BLKSIZE
410         dst->st_ex_blksize = src->st_blksize;
411 #else
412         dst->st_ex_blksize = STAT_ST_BLOCKSIZE;
413 #endif
414
415 #ifdef HAVE_STAT_ST_BLOCKS
416         dst->st_ex_blocks = src->st_blocks;
417 #else
418         dst->st_ex_blocks = src->st_size / dst->st_ex_blksize + 1;
419 #endif
420
421 #ifdef HAVE_STAT_ST_FLAGS
422         dst->st_ex_flags = src->st_flags;
423 #else
424         dst->st_ex_flags = 0;
425 #endif
426         dst->st_ex_file_id = dst->st_ex_ino;
427         dst->st_ex_iflags |= ST_EX_IFLAG_CALCULATED_FILE_ID;
428 }
429
430 /*******************************************************************
431 A stat() wrapper.
432 ********************************************************************/
433
434 int sys_stat(const char *fname, SMB_STRUCT_STAT *sbuf,
435              bool fake_dir_create_times)
436 {
437         int ret;
438         struct stat statbuf;
439         ret = stat(fname, &statbuf);
440         if (ret == 0) {
441                 /* we always want directories to appear zero size */
442                 if (S_ISDIR(statbuf.st_mode)) {
443                         statbuf.st_size = 0;
444                 }
445                 init_stat_ex_from_stat(sbuf, &statbuf, fake_dir_create_times);
446         }
447         return ret;
448 }
449
450 /*******************************************************************
451  An fstat() wrapper.
452 ********************************************************************/
453
454 int sys_fstat(int fd, SMB_STRUCT_STAT *sbuf, bool fake_dir_create_times)
455 {
456         int ret;
457         struct stat statbuf;
458         ret = fstat(fd, &statbuf);
459         if (ret == 0) {
460                 /* we always want directories to appear zero size */
461                 if (S_ISDIR(statbuf.st_mode)) {
462                         statbuf.st_size = 0;
463                 }
464                 init_stat_ex_from_stat(sbuf, &statbuf, fake_dir_create_times);
465         }
466         return ret;
467 }
468
469 /*******************************************************************
470  An lstat() wrapper.
471 ********************************************************************/
472
473 int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf,
474               bool fake_dir_create_times)
475 {
476         int ret;
477         struct stat statbuf;
478         ret = lstat(fname, &statbuf);
479         if (ret == 0) {
480                 /* we always want directories to appear zero size */
481                 if (S_ISDIR(statbuf.st_mode)) {
482                         statbuf.st_size = 0;
483                 }
484                 init_stat_ex_from_stat(sbuf, &statbuf, fake_dir_create_times);
485         }
486         return ret;
487 }
488
489 /*******************************************************************
490  An posix_fallocate() wrapper.
491 ********************************************************************/
492 int sys_posix_fallocate(int fd, off_t offset, off_t len)
493 {
494 #if defined(HAVE_POSIX_FALLOCATE)
495         return posix_fallocate(fd, offset, len);
496 #elif defined(F_RESVSP64)
497         /* this handles XFS on IRIX */
498         struct flock64 fl;
499         off_t new_len = offset + len;
500         int ret;
501         struct stat64 sbuf;
502
503         /* unlikely to get a too large file on a 64bit system but ... */
504         if (new_len < 0)
505                 return EFBIG;
506
507         fl.l_whence = SEEK_SET;
508         fl.l_start = offset;
509         fl.l_len = len;
510
511         ret=fcntl(fd, F_RESVSP64, &fl);
512
513         if (ret != 0)
514                 return errno;
515
516         /* Make sure the file gets enlarged after we allocated space: */
517         fstat64(fd, &sbuf);
518         if (new_len > sbuf.st_size)
519                 ftruncate64(fd, new_len);
520         return 0;
521 #else
522         return ENOSYS;
523 #endif
524 }
525
526 /*******************************************************************
527  An fallocate() function that matches the semantics of the Linux one.
528 ********************************************************************/
529
530 #ifdef HAVE_LINUX_FALLOC_H
531 #include <linux/falloc.h>
532 #endif
533
534 int sys_fallocate(int fd, uint32_t mode, off_t offset, off_t len)
535 {
536 #if defined(HAVE_LINUX_FALLOCATE)
537         int lmode = 0;
538
539         if (mode & VFS_FALLOCATE_FL_KEEP_SIZE) {
540                 lmode |= FALLOC_FL_KEEP_SIZE;
541                 mode &= ~VFS_FALLOCATE_FL_KEEP_SIZE;
542         }
543
544 #if defined(HAVE_FALLOC_FL_PUNCH_HOLE)
545         if (mode & VFS_FALLOCATE_FL_PUNCH_HOLE) {
546                 lmode |= FALLOC_FL_PUNCH_HOLE;
547                 mode &= ~VFS_FALLOCATE_FL_PUNCH_HOLE;
548         }
549 #endif  /* HAVE_FALLOC_FL_PUNCH_HOLE */
550
551         if (mode != 0) {
552                 DEBUG(2, ("unmapped fallocate flags: %lx\n",
553                       (unsigned long)mode));
554                 errno = EINVAL;
555                 return -1;
556         }
557         return fallocate(fd, lmode, offset, len);
558 #else   /* HAVE_LINUX_FALLOCATE */
559         /* TODO - plumb in fallocate from other filesysetms like VXFS etc. JRA. */
560         errno = ENOSYS;
561         return -1;
562 #endif  /* HAVE_LINUX_FALLOCATE */
563 }
564
565 #ifdef HAVE_KERNEL_SHARE_MODES
566 #ifndef LOCK_MAND
567 #define LOCK_MAND       32      /* This is a mandatory flock */
568 #define LOCK_READ       64      /* ... Which allows concurrent read operations */
569 #define LOCK_WRITE      128     /* ... Which allows concurrent write operations */
570 #define LOCK_RW         192     /* ... Which allows concurrent read & write ops */
571 #endif
572 #endif
573
574 /*******************************************************************
575  A flock() wrapper that will perform the kernel flock.
576 ********************************************************************/
577
578 void kernel_flock(int fd, uint32_t share_mode, uint32_t access_mask)
579 {
580 #ifdef HAVE_KERNEL_SHARE_MODES
581         int kernel_mode = 0;
582         if (share_mode == FILE_SHARE_WRITE) {
583                 kernel_mode = LOCK_MAND|LOCK_WRITE;
584         } else if (share_mode == FILE_SHARE_READ) {
585                 kernel_mode = LOCK_MAND|LOCK_READ;
586         } else if (share_mode == FILE_SHARE_NONE) {
587                 kernel_mode = LOCK_MAND;
588         }
589         if (kernel_mode) {
590                 flock(fd, kernel_mode);
591         }
592 #endif
593         ;
594 }
595
596
597
598 /*******************************************************************
599  An fdopendir wrapper.
600 ********************************************************************/
601
602 DIR *sys_fdopendir(int fd)
603 {
604 #if defined(HAVE_FDOPENDIR)
605         return fdopendir(fd);
606 #else
607         errno = ENOSYS;
608         return NULL;
609 #endif
610 }
611
612 /*******************************************************************
613  An mknod() wrapper.
614 ********************************************************************/
615
616 int sys_mknod(const char *path, mode_t mode, SMB_DEV_T dev)
617 {
618 #if defined(HAVE_MKNOD)
619         return mknod(path, mode, dev);
620 #else
621         /* No mknod system call. */
622         errno = ENOSYS;
623         return -1;
624 #endif
625 }
626
627 /*******************************************************************
628  A mknodat() wrapper.
629 ********************************************************************/
630
631 int sys_mknodat(int dirfd, const char *path, mode_t mode, SMB_DEV_T dev)
632 {
633 #if defined(HAVE_MKNODAT)
634         return mknodat(dirfd, path, mode, dev);
635 #else
636         /* No mknod system call. */
637         errno = ENOSYS;
638         return -1;
639 #endif
640 }
641
642 /*******************************************************************
643  System wrapper for getwd. Always returns MALLOC'ed memory, or NULL
644  on error (malloc fail usually).
645 ********************************************************************/
646
647 char *sys_getwd(void)
648 {
649 #ifdef GETCWD_TAKES_NULL
650         return getcwd(NULL, 0);
651 #elif defined(HAVE_GETCWD)
652         char *wd = NULL, *s = NULL;
653         size_t allocated = PATH_MAX;
654
655         while (1) {
656                 s = SMB_REALLOC_ARRAY(s, char, allocated);
657                 if (s == NULL) {
658                         return NULL;
659                 }
660                 wd = getcwd(s, allocated);
661                 if (wd) {
662                         break;
663                 }
664                 if (errno != ERANGE) {
665                         int saved_errno = errno;
666                         SAFE_FREE(s);
667                         errno = saved_errno;
668                         break;
669                 }
670                 allocated *= 2;
671                 if (allocated < PATH_MAX) {
672                         SAFE_FREE(s);
673                         break;
674                 }
675         }
676         return wd;
677 #else
678         char *wd = NULL;
679         char *s = SMB_MALLOC_ARRAY(char, PATH_MAX);
680         if (s == NULL) {
681                 return NULL;
682         }
683         wd = getwd(s);
684         if (wd == NULL) {
685                 int saved_errno = errno;
686                 SAFE_FREE(s);
687                 errno = saved_errno;
688         }
689         return wd;
690 #endif
691 }
692
693 #if defined(HAVE_POSIX_CAPABILITIES)
694
695 /**************************************************************************
696  Try and abstract process capabilities (for systems that have them).
697 ****************************************************************************/
698
699 /* Set the POSIX capabilities needed for the given purpose into the effective
700  * capability set of the current process. Make sure they are always removed
701  * from the inheritable set, because there is no circumstance in which our
702  * children should inherit our elevated privileges.
703  */
704 static bool set_process_capability(enum smbd_capability capability,
705                                    bool enable)
706 {
707         cap_value_t cap_vals[2] = {0};
708         int num_cap_vals = 0;
709
710         cap_t cap;
711
712 #if defined(HAVE_PRCTL) && defined(PR_GET_KEEPCAPS) && defined(PR_SET_KEEPCAPS)
713         /* On Linux, make sure that any capabilities we grab are sticky
714          * across UID changes. We expect that this would allow us to keep both
715          * the effective and permitted capability sets, but as of circa 2.6.16,
716          * only the permitted set is kept. It is a bug (which we work around)
717          * that the effective set is lost, but we still require the effective
718          * set to be kept.
719          */
720         if (!prctl(PR_GET_KEEPCAPS)) {
721                 prctl(PR_SET_KEEPCAPS, 1);
722         }
723 #endif
724
725         cap = cap_get_proc();
726         if (cap == NULL) {
727                 DEBUG(0,("set_process_capability: cap_get_proc failed: %s\n",
728                         strerror(errno)));
729                 return False;
730         }
731
732         switch (capability) {
733                 case KERNEL_OPLOCK_CAPABILITY:
734 #ifdef CAP_NETWORK_MGT
735                         /* IRIX has CAP_NETWORK_MGT for oplocks. */
736                         cap_vals[num_cap_vals++] = CAP_NETWORK_MGT;
737 #endif
738                         break;
739                 case DMAPI_ACCESS_CAPABILITY:
740 #ifdef CAP_DEVICE_MGT
741                         /* IRIX has CAP_DEVICE_MGT for DMAPI access. */
742                         cap_vals[num_cap_vals++] = CAP_DEVICE_MGT;
743 #elif CAP_MKNOD
744                         /* Linux has CAP_MKNOD for DMAPI access. */
745                         cap_vals[num_cap_vals++] = CAP_MKNOD;
746 #endif
747                         break;
748                 case LEASE_CAPABILITY:
749 #ifdef CAP_LEASE
750                         cap_vals[num_cap_vals++] = CAP_LEASE;
751 #endif
752                         break;
753                 case DAC_OVERRIDE_CAPABILITY:
754 #ifdef CAP_DAC_OVERRIDE
755                         cap_vals[num_cap_vals++] = CAP_DAC_OVERRIDE;
756 #endif
757         }
758
759         SMB_ASSERT(num_cap_vals <= ARRAY_SIZE(cap_vals));
760
761         if (num_cap_vals == 0) {
762                 cap_free(cap);
763                 return True;
764         }
765
766         cap_set_flag(cap, CAP_EFFECTIVE, num_cap_vals, cap_vals,
767                 enable ? CAP_SET : CAP_CLEAR);
768
769         /* We never want to pass capabilities down to our children, so make
770          * sure they are not inherited.
771          */
772         cap_set_flag(cap, CAP_INHERITABLE, num_cap_vals, cap_vals, CAP_CLEAR);
773
774         if (cap_set_proc(cap) == -1) {
775                 DEBUG(0, ("set_process_capability: cap_set_proc failed: %s\n",
776                         strerror(errno)));
777                 cap_free(cap);
778                 return False;
779         }
780
781         cap_free(cap);
782         return True;
783 }
784
785 #endif /* HAVE_POSIX_CAPABILITIES */
786
787 /****************************************************************************
788  Gain the oplock capability from the kernel if possible.
789 ****************************************************************************/
790
791 void set_effective_capability(enum smbd_capability capability)
792 {
793 #if defined(HAVE_POSIX_CAPABILITIES)
794         set_process_capability(capability, True);
795 #endif /* HAVE_POSIX_CAPABILITIES */
796 }
797
798 void drop_effective_capability(enum smbd_capability capability)
799 {
800 #if defined(HAVE_POSIX_CAPABILITIES)
801         set_process_capability(capability, False);
802 #endif /* HAVE_POSIX_CAPABILITIES */
803 }
804
805 /**************************************************************************
806  Wrapper for random().
807 ****************************************************************************/
808
809 long sys_random(void)
810 {
811 #if defined(HAVE_RANDOM)
812         return (long)random();
813 #elif defined(HAVE_RAND)
814         return (long)rand();
815 #else
816         DEBUG(0,("Error - no random function available !\n"));
817         exit(1);
818 #endif
819 }
820
821 /**************************************************************************
822  Wrapper for srandom().
823 ****************************************************************************/
824
825 void sys_srandom(unsigned int seed)
826 {
827 #if defined(HAVE_SRANDOM)
828         srandom(seed);
829 #elif defined(HAVE_SRAND)
830         srand(seed);
831 #else
832         DEBUG(0,("Error - no srandom function available !\n"));
833         exit(1);
834 #endif
835 }
836
837 #ifndef NGROUPS_MAX
838 #define NGROUPS_MAX 32 /* Guess... */
839 #endif
840
841 /**************************************************************************
842  Returns equivalent to NGROUPS_MAX - using sysconf if needed.
843 ****************************************************************************/
844
845 int groups_max(void)
846 {
847 #if defined(SYSCONF_SC_NGROUPS_MAX)
848         int ret = sysconf(_SC_NGROUPS_MAX);
849         return (ret == -1) ? NGROUPS_MAX : ret;
850 #else
851         return NGROUPS_MAX;
852 #endif
853 }
854
855 /**************************************************************************
856  Wrap setgroups and getgroups for systems that declare getgroups() as
857  returning an array of gid_t, but actuall return an array of int.
858 ****************************************************************************/
859
860 #if defined(HAVE_BROKEN_GETGROUPS)
861
862 #ifdef HAVE_BROKEN_GETGROUPS
863 #define GID_T int
864 #else
865 #define GID_T gid_t
866 #endif
867
868 static int sys_broken_getgroups(int setlen, gid_t *gidset)
869 {
870         GID_T *group_list;
871         int i, ngroups;
872
873         if(setlen == 0) {
874                 return getgroups(0, NULL);
875         }
876
877         /*
878          * Broken case. We need to allocate a
879          * GID_T array of size setlen.
880          */
881
882         if(setlen < 0) {
883                 errno = EINVAL; 
884                 return -1;
885         } 
886
887         if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
888                 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
889                 return -1;
890         }
891
892         if((ngroups = getgroups(setlen, group_list)) < 0) {
893                 int saved_errno = errno;
894                 SAFE_FREE(group_list);
895                 errno = saved_errno;
896                 return -1;
897         }
898
899         /*
900          * We're safe here as if ngroups > setlen then
901          * getgroups *must* return EINVAL.
902          * pubs.opengroup.org/onlinepubs/009695399/functions/getgroups.html
903          */
904
905         for(i = 0; i < ngroups; i++)
906                 gidset[i] = (gid_t)group_list[i];
907
908         SAFE_FREE(group_list);
909         return ngroups;
910 }
911
912 static int sys_broken_setgroups(int setlen, gid_t *gidset)
913 {
914         GID_T *group_list;
915         int i ; 
916
917         if (setlen == 0)
918                 return 0 ;
919
920         if (setlen < 0 || setlen > groups_max()) {
921                 errno = EINVAL; 
922                 return -1;   
923         }
924
925         /*
926          * Broken case. We need to allocate a
927          * GID_T array of size setlen.
928          */
929
930         if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
931                 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
932                 return -1;    
933         }
934
935         for(i = 0; i < setlen; i++) 
936                 group_list[i] = (GID_T) gidset[i]; 
937
938         if(samba_setgroups(setlen, group_list) != 0) {
939                 int saved_errno = errno;
940                 SAFE_FREE(group_list);
941                 errno = saved_errno;
942                 return -1;
943         }
944
945         SAFE_FREE(group_list);
946         return 0 ;
947 }
948
949 #endif /* HAVE_BROKEN_GETGROUPS */
950
951 /* This is a list of systems that require the first GID passed to setgroups(2)
952  * to be the effective GID. If your system is one of these, add it here.
953  */
954 #if defined (FREEBSD) || defined (DARWINOS)
955 #define USE_BSD_SETGROUPS
956 #endif
957
958 #if defined(USE_BSD_SETGROUPS)
959 /* Depending on the particular BSD implementation, the first GID that is
960  * passed to setgroups(2) will either be ignored or will set the credential's
961  * effective GID. In either case, the right thing to do is to guarantee that
962  * gidset[0] is the effective GID.
963  */
964 static int sys_bsd_setgroups(gid_t primary_gid, int setlen, const gid_t *gidset)
965 {
966         gid_t *new_gidset = NULL;
967         int max;
968         int ret;
969
970         /* setgroups(2) will fail with EINVAL if we pass too many groups. */
971         max = groups_max();
972
973         /* No group list, just make sure we are setting the efective GID. */
974         if (setlen == 0) {
975                 return samba_setgroups(1, &primary_gid);
976         }
977
978         /* If the primary gid is not the first array element, grow the array
979          * and insert it at the front.
980          */
981         if (gidset[0] != primary_gid) {
982                 new_gidset = SMB_MALLOC_ARRAY(gid_t, setlen + 1);
983                 if (new_gidset == NULL) {
984                         return -1;
985                 }
986
987                 memcpy(new_gidset + 1, gidset, (setlen * sizeof(gid_t)));
988                 new_gidset[0] = primary_gid;
989                 setlen++;
990         }
991
992         if (setlen > max) {
993                 DEBUG(3, ("forced to truncate group list from %d to %d\n",
994                         setlen, max));
995                 setlen = max;
996         }
997
998 #if defined(HAVE_BROKEN_GETGROUPS)
999         ret = sys_broken_setgroups(setlen, new_gidset ? new_gidset : gidset);
1000 #else
1001         ret = samba_setgroups(setlen, new_gidset ? new_gidset : gidset);
1002 #endif
1003
1004         if (new_gidset) {
1005                 int errsav = errno;
1006                 SAFE_FREE(new_gidset);
1007                 errno = errsav;
1008         }
1009
1010         return ret;
1011 }
1012
1013 #endif /* USE_BSD_SETGROUPS */
1014
1015 /**************************************************************************
1016  Wrapper for getgroups. Deals with broken (int) case.
1017 ****************************************************************************/
1018
1019 int sys_getgroups(int setlen, gid_t *gidset)
1020 {
1021 #if defined(HAVE_BROKEN_GETGROUPS)
1022         return sys_broken_getgroups(setlen, gidset);
1023 #else
1024         return getgroups(setlen, gidset);
1025 #endif
1026 }
1027
1028 /**************************************************************************
1029  Wrapper for setgroups. Deals with broken (int) case and BSD case.
1030 ****************************************************************************/
1031
1032 int sys_setgroups(gid_t UNUSED(primary_gid), int setlen, gid_t *gidset)
1033 {
1034 #if !defined(HAVE_SETGROUPS)
1035         errno = ENOSYS;
1036         return -1;
1037 #endif /* HAVE_SETGROUPS */
1038
1039 #if defined(USE_BSD_SETGROUPS)
1040         return sys_bsd_setgroups(primary_gid, setlen, gidset);
1041 #elif defined(HAVE_BROKEN_GETGROUPS)
1042         return sys_broken_setgroups(setlen, gidset);
1043 #else
1044         return samba_setgroups(setlen, gidset);
1045 #endif
1046 }
1047
1048 /****************************************************************************
1049  Return the major devicenumber for UNIX extensions.
1050 ****************************************************************************/
1051
1052 uint32_t unix_dev_major(SMB_DEV_T dev)
1053 {
1054 #if defined(HAVE_DEVICE_MAJOR_FN)
1055         return (uint32_t)major(dev);
1056 #else
1057         return (uint32_t)(dev >> 8);
1058 #endif
1059 }
1060
1061 /****************************************************************************
1062  Return the minor devicenumber for UNIX extensions.
1063 ****************************************************************************/
1064
1065 uint32_t unix_dev_minor(SMB_DEV_T dev)
1066 {
1067 #if defined(HAVE_DEVICE_MINOR_FN)
1068         return (uint32_t)minor(dev);
1069 #else
1070         return (uint32_t)(dev & 0xff);
1071 #endif
1072 }
1073
1074 /**************************************************************************
1075  Wrapper for realpath.
1076 ****************************************************************************/
1077
1078 char *sys_realpath(const char *path)
1079 {
1080         char *result;
1081
1082 #ifdef REALPATH_TAKES_NULL
1083         result = realpath(path, NULL);
1084 #else
1085         result = SMB_MALLOC_ARRAY(char, PATH_MAX + 1);
1086         if (result) {
1087                 char *resolved_path = realpath(path, result);
1088                 if (!resolved_path) {
1089                         SAFE_FREE(result);
1090                 } else {
1091                         /* SMB_ASSERT(result == resolved_path) ? */
1092                         result = resolved_path;
1093                 }
1094         }
1095 #endif
1096         return result;
1097 }
1098
1099 #if 0
1100 /*******************************************************************
1101  Return the number of CPUs.
1102 ********************************************************************/
1103
1104 int sys_get_number_of_cores(void)
1105 {
1106         int ret = -1;
1107
1108 #if defined(HAVE_SYSCONF)
1109 #if defined(_SC_NPROCESSORS_ONLN)
1110         ret = (int)sysconf(_SC_NPROCESSORS_ONLN);
1111 #endif
1112 #if defined(_SC_NPROCESSORS_CONF)
1113         if (ret < 1) {
1114                 ret = (int)sysconf(_SC_NPROCESSORS_CONF);
1115         }
1116 #endif
1117 #elif defined(HAVE_SYSCTL) && defined(CTL_HW)
1118         int name[2];
1119         unsigned int len = sizeof(ret);
1120
1121         name[0] = CTL_HW;
1122 #if defined(HW_AVAILCPU)
1123         name[1] = HW_AVAILCPU;
1124
1125         if (sysctl(name, 2, &ret, &len, NULL, 0) == -1) {
1126                 ret = -1;
1127         }
1128 #endif
1129 #if defined(HW_NCPU)
1130         if(ret < 1) {
1131                 name[0] = CTL_HW;
1132                 name[1] = HW_NCPU;
1133                 if (sysctl(nm, 2, &count, &len, NULL, 0) == -1) {
1134                         ret = -1;
1135                 }
1136         }
1137 #endif
1138 #endif
1139         if (ret < 1) {
1140                 ret = 1;
1141         }
1142         return ret;
1143 }
1144 #endif