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