expansions/etc make sense to the OS should be acceptable to Samba.
*/
-
-
-/*******************************************************************
-A read wrapper that will deal with EINTR.
-********************************************************************/
-
-ssize_t sys_read(int fd, void *buf, size_t count)
-{
- ssize_t ret;
-
- do {
- ret = read(fd, buf, count);
-#if defined(EWOULDBLOCK)
- } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
-#else
- } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
-#endif
- return ret;
-}
-
/*******************************************************************
-A write wrapper that will deal with EINTR.
+A send wrapper that will deal with EINTR or EAGAIN or EWOULDBLOCK.
********************************************************************/
-ssize_t sys_write(int fd, const void *buf, size_t count)
+ssize_t sys_send(int s, const void *msg, size_t len, int flags)
{
ssize_t ret;
do {
- ret = write(fd, buf, count);
-#if defined(EWOULDBLOCK)
+ ret = send(s, msg, len, flags);
} while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
-#else
- } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
-#endif
- return ret;
-}
-
-/*******************************************************************
-A writev wrapper that will deal with EINTR.
-********************************************************************/
-
-ssize_t sys_writev(int fd, const struct iovec *iov, int iovcnt)
-{
- ssize_t ret;
-
-#if 0
- /* Try to confuse write_data_iov a bit */
- if ((random() % 5) == 0) {
- return sys_write(fd, iov[0].iov_base, iov[0].iov_len);
- }
- if (iov[0].iov_len > 1) {
- return sys_write(fd, iov[0].iov_base,
- (random() % (iov[0].iov_len-1)) + 1);
- }
-#endif
- do {
- ret = writev(fd, iov, iovcnt);
-#if defined(EWOULDBLOCK)
- } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
-#else
- } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
-#endif
return ret;
}
/*******************************************************************
-A pread wrapper that will deal with EINTR
+A recvfrom wrapper that will deal with EINTR.
+NB. As used with non-blocking sockets, return on EAGAIN/EWOULDBLOCK
********************************************************************/
-#if defined(HAVE_PREAD)
-ssize_t sys_pread(int fd, void *buf, size_t count, off_t off)
+ssize_t sys_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
{
ssize_t ret;
do {
- ret = pread(fd, buf, count, off);
- } while (ret == -1 && errno == EINTR);
+ ret = recvfrom(s, buf, len, flags, from, fromlen);
+ } while (ret == -1 && (errno == EINTR));
return ret;
}
-#endif
/*******************************************************************
-A write wrapper that will deal with EINTR
+A fcntl wrapper that will deal with EINTR.
********************************************************************/
-#if defined(HAVE_PWRITE)
-ssize_t sys_pwrite(int fd, const void *buf, size_t count, off_t off)
+int sys_fcntl_ptr(int fd, int cmd, void *arg)
{
- ssize_t ret;
+ int ret;
do {
- ret = pwrite(fd, buf, count, off);
+ ret = fcntl(fd, cmd, arg);
} while (ret == -1 && errno == EINTR);
return ret;
}
-#endif
-
-/*******************************************************************
-A send wrapper that will deal with EINTR or EAGAIN or EWOULDBLOCK.
-********************************************************************/
-
-ssize_t sys_send(int s, const void *msg, size_t len, int flags)
-{
- ssize_t ret;
-
- do {
- ret = send(s, msg, len, flags);
-#if defined(EWOULDBLOCK)
- } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
-#else
- } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
-#endif
- return ret;
-}
-
-/*******************************************************************
-A recvfrom wrapper that will deal with EINTR.
-********************************************************************/
-
-ssize_t sys_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
-{
- ssize_t ret;
-
- do {
- ret = recvfrom(s, buf, len, flags, from, fromlen);
-#if defined(EWOULDBLOCK)
- } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
-#else
- } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
-#endif
- return ret;
-}
/*******************************************************************
A fcntl wrapper that will deal with EINTR.
********************************************************************/
-int sys_fcntl_ptr(int fd, int cmd, void *arg)
+int sys_fcntl_long(int fd, int cmd, long arg)
{
int ret;
A fcntl wrapper that will deal with EINTR.
********************************************************************/
-int sys_fcntl_long(int fd, int cmd, long arg)
+int sys_fcntl_int(int fd, int cmd, int arg)
{
int ret;
return ret;
#else
#if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
- return pst->st_atim;
+ struct timespec ret;
+ ret.tv_sec = pst->st_atim.tv_sec;
+ ret.tv_nsec = pst->st_atim.tv_nsec;
+ return ret;
#elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
struct timespec ret;
ret.tv_sec = pst->st_atime;
return ret;
#else
#if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
- return pst->st_mtim;
+ struct timespec ret;
+ ret.tv_sec = pst->st_mtim.tv_sec;
+ ret.tv_nsec = pst->st_mtim.tv_nsec;
+ return ret;
#elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
struct timespec ret;
ret.tv_sec = pst->st_mtime;
return ret;
#else
#if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
- return pst->st_ctim;
+ struct timespec ret;
+ ret.tv_sec = pst->st_ctim.tv_sec;
+ ret.tv_nsec = pst->st_ctim.tv_nsec;
+ return ret;
#elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
struct timespec ret;
ret.tv_sec = pst->st_ctime;
dst->st_ex_btime.tv_nsec = 0;
}
- dst->st_ex_calculated_birthtime = false;
+ dst->st_ex_iflags &= ~ST_EX_IFLAG_CALCULATED_BTIME;
#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC)
dst->st_ex_btime = pst->st_birthtimespec;
dst->st_ex_btime.tv_nsec = 0;
#else
dst->st_ex_btime = calc_create_time_stat(pst);
- dst->st_ex_calculated_birthtime = true;
+ dst->st_ex_iflags |= ST_EX_IFLAG_CALCULATED_BTIME;
#endif
/* Deal with systems that don't initialize birthtime correctly.
*/
if (null_timespec(dst->st_ex_btime)) {
dst->st_ex_btime = calc_create_time_stat(pst);
- dst->st_ex_calculated_birthtime = true;
+ dst->st_ex_iflags |= ST_EX_IFLAG_CALCULATED_BTIME;
}
+
+ dst->st_ex_itime = dst->st_ex_btime;
+ dst->st_ex_iflags |= ST_EX_IFLAG_CALCULATED_ITIME;
}
/****************************************************************************
dst->st_ex_mtime = write_ts;
/* We may have to recalculate btime. */
- if (dst->st_ex_calculated_birthtime) {
+ if (dst->st_ex_iflags & ST_EX_IFLAG_CALCULATED_BTIME) {
dst->st_ex_btime = calc_create_time_stat_ex(dst);
}
}
struct timespec create_time)
{
dst->st_ex_btime = create_time;
- dst->st_ex_calculated_birthtime = false;
+ dst->st_ex_iflags &= ~ST_EX_IFLAG_CALCULATED_BTIME;
+}
+
+void update_stat_ex_itime(struct stat_ex *dst,
+ struct timespec itime)
+{
+ dst->st_ex_itime = itime;
+ dst->st_ex_iflags &= ~ST_EX_IFLAG_CALCULATED_ITIME;
+}
+
+void update_stat_ex_file_id(struct stat_ex *dst, uint64_t file_id)
+{
+ dst->st_ex_file_id = file_id;
+ dst->st_ex_iflags &= ~ST_EX_IFLAG_CALCULATED_FILE_ID;
+}
+
+void update_stat_ex_from_saved_stat(struct stat_ex *dst,
+ const struct stat_ex *src)
+{
+ if (!VALID_STAT(*src)) {
+ return;
+ }
+
+ if (!(src->st_ex_iflags & ST_EX_IFLAG_CALCULATED_BTIME)) {
+ update_stat_ex_create_time(dst, src->st_ex_btime);
+ }
+
+ if (!(src->st_ex_iflags & ST_EX_IFLAG_CALCULATED_ITIME)) {
+ update_stat_ex_itime(dst, src->st_ex_itime);
+ }
+
+ if (!(src->st_ex_iflags & ST_EX_IFLAG_CALCULATED_FILE_ID)) {
+ update_stat_ex_file_id(dst, src->st_ex_file_id);
+ }
}
void init_stat_ex_from_stat (struct stat_ex *dst,
dst->st_ex_atime = get_atimespec(src);
dst->st_ex_mtime = get_mtimespec(src);
dst->st_ex_ctime = get_ctimespec(src);
+ dst->st_ex_iflags = 0;
make_create_timespec(src, dst, fake_dir_create_times);
#ifdef HAVE_STAT_ST_BLKSIZE
dst->st_ex_blksize = src->st_blksize;
#else
dst->st_ex_flags = 0;
#endif
+ dst->st_ex_file_id = dst->st_ex_ino;
+ dst->st_ex_iflags |= ST_EX_IFLAG_CALCULATED_FILE_ID;
}
/*******************************************************************
********************************************************************/
int sys_posix_fallocate(int fd, off_t offset, off_t len)
{
-#if defined(HAVE_POSIX_FALLOCATE) && !defined(HAVE_BROKEN_POSIX_FALLOCATE)
+#if defined(HAVE_POSIX_FALLOCATE)
return posix_fallocate(fd, offset, len);
#elif defined(F_RESVSP64)
/* this handles XFS on IRIX */
#include <linux/falloc.h>
#endif
-int sys_fallocate(int fd, enum vfs_fallocate_mode mode, off_t offset, off_t len)
+int sys_fallocate(int fd, uint32_t mode, off_t offset, off_t len)
{
-#if defined(HAVE_LINUX_FALLOCATE64) || defined(HAVE_LINUX_FALLOCATE)
- int lmode;
- switch (mode) {
- case VFS_FALLOCATE_EXTEND_SIZE:
- lmode = 0;
- break;
- case VFS_FALLOCATE_KEEP_SIZE:
- lmode = FALLOC_FL_KEEP_SIZE;
- break;
- default:
+#if defined(HAVE_LINUX_FALLOCATE)
+ int lmode = 0;
+
+ if (mode & VFS_FALLOCATE_FL_KEEP_SIZE) {
+ lmode |= FALLOC_FL_KEEP_SIZE;
+ mode &= ~VFS_FALLOCATE_FL_KEEP_SIZE;
+ }
+
+#if defined(HAVE_FALLOC_FL_PUNCH_HOLE)
+ if (mode & VFS_FALLOCATE_FL_PUNCH_HOLE) {
+ lmode |= FALLOC_FL_PUNCH_HOLE;
+ mode &= ~VFS_FALLOCATE_FL_PUNCH_HOLE;
+ }
+#endif /* HAVE_FALLOC_FL_PUNCH_HOLE */
+
+ if (mode != 0) {
+ DEBUG(2, ("unmapped fallocate flags: %lx\n",
+ (unsigned long)mode));
errno = EINVAL;
return -1;
}
-#if defined(HAVE_LINUX_FALLOCATE)
return fallocate(fd, lmode, offset, len);
-#endif
-#else
+#else /* HAVE_LINUX_FALLOCATE */
/* TODO - plumb in fallocate from other filesysetms like VXFS etc. JRA. */
errno = ENOSYS;
return -1;
-#endif
+#endif /* HAVE_LINUX_FALLOCATE */
}
-#if HAVE_KERNEL_SHARE_MODES
+#ifdef HAVE_KERNEL_SHARE_MODES
#ifndef LOCK_MAND
#define LOCK_MAND 32 /* This is a mandatory flock */
#define LOCK_READ 64 /* ... Which allows concurrent read operations */
A flock() wrapper that will perform the kernel flock.
********************************************************************/
-void kernel_flock(int fd, uint32 share_mode, uint32 access_mask)
+void kernel_flock(int fd, uint32_t share_mode, uint32_t access_mask)
{
-#if HAVE_KERNEL_SHARE_MODES
+#ifdef HAVE_KERNEL_SHARE_MODES
int kernel_mode = 0;
if (share_mode == FILE_SHARE_WRITE) {
kernel_mode = LOCK_MAND|LOCK_WRITE;
/*******************************************************************
An fdopendir wrapper.
- Ugly hack - we need dirfd for this to work correctly in the
- calling code.. JRA.
********************************************************************/
DIR *sys_fdopendir(int fd)
{
-#if defined(HAVE_FDOPENDIR) && defined(HAVE_DIRFD)
+#if defined(HAVE_FDOPENDIR)
return fdopendir(fd);
#else
errno = ENOSYS;
}
/*******************************************************************
-The wait() calls vary between systems
+ A mknodat() wrapper.
********************************************************************/
-int sys_waitpid(pid_t pid,int *status,int options)
+int sys_mknodat(int dirfd, const char *path, mode_t mode, SMB_DEV_T dev)
{
-#ifdef HAVE_WAITPID
- return waitpid(pid,status,options);
-#else /* HAVE_WAITPID */
- return wait4(pid, status, options, NULL);
-#endif /* HAVE_WAITPID */
+#if defined(HAVE_MKNODAT)
+ return mknodat(dirfd, path, mode, dev);
+#else
+ /* No mknod system call. */
+ errno = ENOSYS;
+ return -1;
+#endif
}
/*******************************************************************
{
#ifdef GETCWD_TAKES_NULL
return getcwd(NULL, 0);
-#elif HAVE_GETCWD
+#elif defined(HAVE_GETCWD)
char *wd = NULL, *s = NULL;
size_t allocated = PATH_MAX;
break;
}
if (errno != ERANGE) {
+ int saved_errno = errno;
SAFE_FREE(s);
+ errno = saved_errno;
break;
}
allocated *= 2;
}
return wd;
#else
+ char *wd = NULL;
char *s = SMB_MALLOC_ARRAY(char, PATH_MAX);
if (s == NULL) {
return NULL;
}
- return getwd(s);
+ wd = getwd(s);
+ if (wd == NULL) {
+ int saved_errno = errno;
+ SAFE_FREE(s);
+ errno = saved_errno;
+ }
+ return wd;
#endif
}
cap_vals[num_cap_vals++] = CAP_LEASE;
#endif
break;
+ case DAC_OVERRIDE_CAPABILITY:
+#ifdef CAP_DAC_OVERRIDE
+ cap_vals[num_cap_vals++] = CAP_DAC_OVERRIDE;
+#endif
}
SMB_ASSERT(num_cap_vals <= ARRAY_SIZE(cap_vals));
static int sys_broken_getgroups(int setlen, gid_t *gidset)
{
- GID_T gid;
GID_T *group_list;
int i, ngroups;
if(setlen == 0) {
- return getgroups(setlen, &gid);
+ return getgroups(0, NULL);
}
/*
return -1;
}
- if (setlen == 0)
- setlen = groups_max();
-
if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
DEBUG(0,("sys_getgroups: Malloc fail.\n"));
return -1;
return -1;
}
+ /*
+ * We're safe here as if ngroups > setlen then
+ * getgroups *must* return EINVAL.
+ * pubs.opengroup.org/onlinepubs/009695399/functions/getgroups.html
+ */
+
for(i = 0; i < ngroups; i++)
gidset[i] = (gid_t)group_list[i];
#endif
}
-/**************************************************************************
- Extract a command into an arg list.
-****************************************************************************/
-
-static char **extract_args(TALLOC_CTX *mem_ctx, const char *command)
-{
- char *trunc_cmd;
- char *saveptr;
- char *ptr;
- int argcl;
- char **argl = NULL;
- int i;
-
- if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
- DEBUG(0, ("talloc failed\n"));
- goto nomem;
- }
-
- if(!(ptr = strtok_r(trunc_cmd, " \t", &saveptr))) {
- TALLOC_FREE(trunc_cmd);
- errno = EINVAL;
- return NULL;
- }
-
- /*
- * Count the args.
- */
-
- for( argcl = 1; ptr; ptr = strtok_r(NULL, " \t", &saveptr))
- argcl++;
-
- TALLOC_FREE(trunc_cmd);
-
- if (!(argl = talloc_array(mem_ctx, char *, argcl + 1))) {
- goto nomem;
- }
-
- /*
- * Now do the extraction.
- */
-
- if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
- goto nomem;
- }
-
- ptr = strtok_r(trunc_cmd, " \t", &saveptr);
- i = 0;
-
- if (!(argl[i++] = talloc_strdup(argl, ptr))) {
- goto nomem;
- }
-
- while((ptr = strtok_r(NULL, " \t", &saveptr)) != NULL) {
-
- if (!(argl[i++] = talloc_strdup(argl, ptr))) {
- goto nomem;
- }
- }
-
- argl[i++] = NULL;
- TALLOC_FREE(trunc_cmd);
- return argl;
-
- nomem:
- DEBUG(0, ("talloc failed\n"));
- TALLOC_FREE(trunc_cmd);
- TALLOC_FREE(argl);
- errno = ENOMEM;
- return NULL;
-}
-
-/**************************************************************************
- Wrapper for popen. Safer as it doesn't search a path.
- Modified from the glibc sources.
- modified by tridge to return a file descriptor. We must kick our FILE* habit
-****************************************************************************/
-
-typedef struct _popen_list
-{
- int fd;
- pid_t child_pid;
- struct _popen_list *next;
-} popen_list;
-
-static popen_list *popen_chain;
-
-int sys_popen(const char *command)
-{
- int parent_end, child_end;
- int pipe_fds[2];
- popen_list *entry = NULL;
- char **argl = NULL;
-
- if (pipe(pipe_fds) < 0)
- return -1;
-
- parent_end = pipe_fds[0];
- child_end = pipe_fds[1];
-
- if (!*command) {
- errno = EINVAL;
- goto err_exit;
- }
-
- if((entry = SMB_MALLOC_P(popen_list)) == NULL)
- goto err_exit;
-
- ZERO_STRUCTP(entry);
-
- /*
- * Extract the command and args into a NULL terminated array.
- */
-
- if(!(argl = extract_args(NULL, command)))
- goto err_exit;
-
- entry->child_pid = fork();
-
- if (entry->child_pid == -1) {
- goto err_exit;
- }
-
- if (entry->child_pid == 0) {
-
- /*
- * Child !
- */
-
- int child_std_end = STDOUT_FILENO;
- popen_list *p;
-
- close(parent_end);
- if (child_end != child_std_end) {
- dup2 (child_end, child_std_end);
- close (child_end);
- }
-
- /*
- * POSIX.2: "popen() shall ensure that any streams from previous
- * popen() calls that remain open in the parent process are closed
- * in the new child process."
- */
-
- for (p = popen_chain; p; p = p->next)
- close(p->fd);
-
- execv(argl[0], argl);
- _exit (127);
- }
-
- /*
- * Parent.
- */
-
- close (child_end);
- TALLOC_FREE(argl);
-
- /* Link into popen_chain. */
- entry->next = popen_chain;
- popen_chain = entry;
- entry->fd = parent_end;
-
- return entry->fd;
-
-err_exit:
-
- SAFE_FREE(entry);
- TALLOC_FREE(argl);
- close(pipe_fds[0]);
- close(pipe_fds[1]);
- return -1;
-}
-
-/**************************************************************************
- Wrapper for pclose. Modified from the glibc sources.
-****************************************************************************/
-
-int sys_pclose(int fd)
-{
- int wstatus;
- popen_list **ptr = &popen_chain;
- popen_list *entry = NULL;
- pid_t wait_pid;
- int status = -1;
-
- /* Unlink from popen_chain. */
- for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
- if ((*ptr)->fd == fd) {
- entry = *ptr;
- *ptr = (*ptr)->next;
- status = 0;
- break;
- }
- }
-
- if (status < 0 || close(entry->fd) < 0)
- return -1;
-
- /*
- * As Samba is catching and eating child process
- * exits we don't really care about the child exit
- * code, a -1 with errno = ECHILD will do fine for us.
- */
-
- do {
- wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
- } while (wait_pid == -1 && errno == EINTR);
-
- SAFE_FREE(entry);
-
- if (wait_pid == -1)
- return -1;
- return wstatus;
-}
-
-/**************************************************************************
- Wrapper for Admin Logs.
+/****************************************************************************
+ Return the major devicenumber for UNIX extensions.
****************************************************************************/
- void sys_adminlog(int priority, const char *format_str, ...)
+uint32_t unix_dev_major(SMB_DEV_T dev)
{
- va_list ap;
- int ret;
- char *msgbuf = NULL;
-
- va_start( ap, format_str );
- ret = vasprintf( &msgbuf, format_str, ap );
- va_end( ap );
-
- if (ret == -1)
- return;
-
-#if defined(HAVE_SYSLOG)
- syslog( priority, "%s", msgbuf );
+#if defined(HAVE_DEVICE_MAJOR_FN)
+ return (uint32_t)major(dev);
#else
- DEBUG(0,("%s", msgbuf ));
+ return (uint32_t)(dev >> 8);
#endif
- SAFE_FREE(msgbuf);
}
/****************************************************************************
- Return the major devicenumber for UNIX extensions.
+ Return the minor devicenumber for UNIX extensions.
****************************************************************************/
-uint32 unix_dev_major(SMB_DEV_T dev)
+uint32_t unix_dev_minor(SMB_DEV_T dev)
{
-#if defined(HAVE_DEVICE_MAJOR_FN)
- return (uint32)major(dev);
+#if defined(HAVE_DEVICE_MINOR_FN)
+ return (uint32_t)minor(dev);
#else
- return (uint32)(dev >> 8);
+ return (uint32_t)(dev & 0xff);
#endif
}
-/****************************************************************************
- Return the minor devicenumber for UNIX extensions.
+/**************************************************************************
+ Wrapper for realpath.
****************************************************************************/
-uint32 unix_dev_minor(SMB_DEV_T dev)
+char *sys_realpath(const char *path)
{
-#if defined(HAVE_DEVICE_MINOR_FN)
- return (uint32)minor(dev);
+ char *result;
+
+#ifdef REALPATH_TAKES_NULL
+ result = realpath(path, NULL);
#else
- return (uint32)(dev & 0xff);
+ result = SMB_MALLOC_ARRAY(char, PATH_MAX + 1);
+ if (result) {
+ char *resolved_path = realpath(path, result);
+ if (!resolved_path) {
+ SAFE_FREE(result);
+ } else {
+ /* SMB_ASSERT(result == resolved_path) ? */
+ result = resolved_path;
+ }
+ }
#endif
+ return result;
}
#if 0