r23658: One pstring a day....
[ira/wip.git] / source3 / lib / system.c
index ffb7031715049ec540ad472e6f337dce7e5363e3..79d37d702450a4a57fb0aba4f82b202670719067 100644 (file)
 
 #include "includes.h"
 
+#ifdef HAVE_SYS_PRCTL_H
+#include <sys/prctl.h>
+#endif
+
 /*
    The idea is that this file will eventually have wrappers around all
    important system calls in samba. The aims are:
 
 
 
+/*******************************************************************
+ A wrapper for memalign
+********************************************************************/
+
+void *sys_memalign( size_t align, size_t size )
+{
+#if defined(HAVE_POSIX_MEMALIGN)
+       void *p = NULL;
+       int ret = posix_memalign( &p, align, size );
+       if ( ret == 0 )
+               return p;
+               
+       return NULL;
+#elif defined(HAVE_MEMALIGN)
+       return memalign( align, size );
+#else
+       /* On *BSD systems memaligns doesn't exist, but memory will
+        * be aligned on allocations of > pagesize. */
+#if defined(SYSCONF_SC_PAGESIZE)
+       size_t pagesize = (size_t)sysconf(_SC_PAGESIZE);
+#elif defined(HAVE_GETPAGESIZE)
+       size_t pagesize = (size_t)getpagesize();
+#else
+       size_t pagesize = (size_t)-1;
+#endif
+       if (pagesize == (size_t)-1) {
+               DEBUG(0,("memalign functionalaity not available on this platform!\n"));
+               return NULL;
+       }
+       if (size < pagesize) {
+               size = pagesize;
+       }
+       return SMB_MALLOC(size);
+#endif
+}
+
 /*******************************************************************
  A wrapper for usleep in case we don't have one.
 ********************************************************************/
@@ -101,7 +141,6 @@ ssize_t sys_write(int fd, const void *buf, size_t count)
        return ret;
 }
 
-
 /*******************************************************************
 A pread wrapper that will deal with EINTR and 64-bit file offsets.
 ********************************************************************/
@@ -170,6 +209,20 @@ ssize_t sys_sendto(int s,  const void *msg, size_t len, int flags, const struct
        return ret;
 }
 
+/*******************************************************************
+A recv wrapper that will deal with EINTR.
+********************************************************************/
+
+ssize_t sys_recv(int fd, void *buf, size_t count, int flags)
+{
+       ssize_t ret;
+
+       do {
+               ret = recv(fd, buf, count, flags);
+       } while (ret == -1 && errno == EINTR);
+       return ret;
+}
+
 /*******************************************************************
 A recvfrom wrapper that will deal with EINTR.
 ********************************************************************/
@@ -362,6 +415,31 @@ FILE *sys_fopen(const char *path, const char *type)
 #endif
 }
 
+
+/*******************************************************************
+ A flock() wrapper that will perform the kernel flock.
+********************************************************************/
+
+void kernel_flock(int fd, uint32 share_mode)
+{
+#if HAVE_KERNEL_SHARE_MODES
+       int kernel_mode = 0;
+       if (share_mode == FILE_SHARE_WRITE) {
+               kernel_mode = LOCK_MAND|LOCK_WRITE;
+       } else if (share_mode == FILE_SHARE_READ) {
+               kernel_mode = LOCK_MAND|LOCK_READ;
+       } else if (share_mode == FILE_SHARE_NONE) {
+               kernel_mode = LOCK_MAND;
+       }
+       if (kernel_mode) {
+               flock(fd, kernel_mode);
+       }
+#endif
+       ;
+}
+
+
+
 /*******************************************************************
  An opendir wrapper that will deal with 64 bit filesizes.
 ********************************************************************/
@@ -563,6 +641,25 @@ int sys_chown(const char *fname,uid_t uid,gid_t gid)
 #endif
 }
 
+/*******************************************************************
+ Wrapper for lchown.
+********************************************************************/
+
+int sys_lchown(const char *fname,uid_t uid,gid_t gid)
+{
+#ifndef HAVE_LCHOWN
+       static int done;
+       if (!done) {
+               DEBUG(1,("WARNING: no lchown!\n"));
+               done=1;
+       }
+       errno = ENOSYS;
+       return -1;
+#else
+       return(lchown(fname,uid,gid));
+#endif
+}
+
 /*******************************************************************
 os/2 also doesn't have chroot
 ********************************************************************/
@@ -661,6 +758,19 @@ static BOOL set_process_capability(enum smbd_capability capability,
 
        cap_t cap;
 
+#if defined(HAVE_PRCTL) && defined(PR_GET_KEEPCAPS) && defined(PR_SET_KEEPCAPS)
+       /* On Linux, make sure that any capabilities we grab are sticky
+        * across UID changes. We expect that this would allow us to keep both
+        * the effective and permitted capability sets, but as of circa 2.6.16,
+        * only the permitted set is kept. It is a bug (which we work around)
+        * that the effective set is lost, but we still require the effective
+        * set to be kept.
+        */
+       if (!prctl(PR_GET_KEEPCAPS)) {
+               prctl(PR_SET_KEEPCAPS, 1);
+       }
+#endif
+
        cap = cap_get_proc();
        if (cap == NULL) {
                DEBUG(0,("set_process_capability: cap_get_proc failed: %s\n",
@@ -673,6 +783,15 @@ static BOOL set_process_capability(enum smbd_capability capability,
 #ifdef CAP_NETWORK_MGT
                        /* IRIX has CAP_NETWORK_MGT for oplocks. */
                        cap_vals[num_cap_vals++] = CAP_NETWORK_MGT;
+#endif
+                       break;
+               case DMAPI_ACCESS_CAPABILITY:
+#ifdef CAP_DEVICE_MGT
+                       /* IRIX has CAP_DEVICE_MGT for DMAPI access. */
+                       cap_vals[num_cap_vals++] = CAP_DEVICE_MGT;
+#elif CAP_MKNOD
+                       /* Linux has CAP_MKNOD for DMAPI access. */
+                       cap_vals[num_cap_vals++] = CAP_MKNOD;
 #endif
                        break;
        }
@@ -686,6 +805,10 @@ static BOOL set_process_capability(enum smbd_capability capability,
 
        cap_set_flag(cap, CAP_EFFECTIVE, num_cap_vals, cap_vals,
                enable ? CAP_SET : CAP_CLEAR);
+
+       /* We never want to pass capabilities down to our children, so make
+        * sure they are not inherited.
+        */
        cap_set_flag(cap, CAP_INHERITABLE, num_cap_vals, cap_vals, CAP_CLEAR);
 
        if (cap_set_proc(cap) == -1) {
@@ -766,15 +889,13 @@ int groups_max(void)
 }
 
 /**************************************************************************
- Wrapper for getgroups. Deals with broken (int) case.
+ Wrap setgroups and getgroups for systems that declare getgroups() as
+ returning an array of gid_t, but actuall return an array of int.
 ****************************************************************************/
 
-int sys_getgroups(int setlen, gid_t *gidset)
+#if defined(HAVE_BROKEN_GETGROUPS)
+static int sys_broken_getgroups(int setlen, gid_t *gidset)
 {
-#if !defined(HAVE_BROKEN_GETGROUPS)
-       return getgroups(setlen, gidset);
-#else
-
        GID_T gid;
        GID_T *group_list;
        int i, ngroups;
@@ -796,7 +917,7 @@ int sys_getgroups(int setlen, gid_t *gidset)
        if (setlen == 0)
                setlen = groups_max();
 
-       if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
+       if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
                DEBUG(0,("sys_getgroups: Malloc fail.\n"));
                return -1;
        }
@@ -813,26 +934,10 @@ int sys_getgroups(int setlen, gid_t *gidset)
 
        SAFE_FREE(group_list);
        return ngroups;
-#endif /* HAVE_BROKEN_GETGROUPS */
 }
 
-
-/**************************************************************************
- Wrapper for setgroups. Deals with broken (int) case. Automatically used
- if we have broken getgroups.
-****************************************************************************/
-
-int sys_setgroups(int setlen, gid_t *gidset)
+static int sys_broken_setgroups(int setlen, gid_t *gidset)
 {
-#if !defined(HAVE_SETGROUPS)
-       errno = ENOSYS;
-       return -1;
-#endif /* HAVE_SETGROUPS */
-
-#if !defined(HAVE_BROKEN_GETGROUPS)
-       return setgroups(setlen, gidset);
-#else
-
        GID_T *group_list;
        int i ; 
 
@@ -849,7 +954,7 @@ int sys_setgroups(int setlen, gid_t *gidset)
         * GID_T array of size setlen.
         */
 
-       if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
+       if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
                DEBUG(0,("sys_setgroups: Malloc fail.\n"));
                return -1;    
        }
@@ -866,7 +971,105 @@ int sys_setgroups(int setlen, gid_t *gidset)
  
        SAFE_FREE(group_list);
        return 0 ;
+}
+
 #endif /* HAVE_BROKEN_GETGROUPS */
+
+/* This is a list of systems that require the first GID passed to setgroups(2)
+ * to be the effective GID. If your system is one of these, add it here.
+ */
+#if defined (FREEBSD) || defined (DARWINOS)
+#define USE_BSD_SETGROUPS
+#endif
+
+#if defined(USE_BSD_SETGROUPS)
+/* Depending on the particular BSD implementation, the first GID that is
+ * passed to setgroups(2) will either be ignored or will set the credential's
+ * effective GID. In either case, the right thing to do is to guarantee that
+ * gidset[0] is the effective GID.
+ */
+static int sys_bsd_setgroups(gid_t primary_gid, int setlen, const gid_t *gidset)
+{
+       gid_t *new_gidset = NULL;
+       int max;
+       int ret;
+
+       /* setgroups(2) will fail with EINVAL if we pass too many groups. */
+       max = groups_max();
+
+       /* No group list, just make sure we are setting the efective GID. */
+       if (setlen == 0) {
+               return setgroups(1, &primary_gid);
+       }
+
+       /* If the primary gid is not the first array element, grow the array
+        * and insert it at the front.
+        */
+       if (gidset[0] != primary_gid) {
+               new_gidset = SMB_MALLOC_ARRAY(gid_t, setlen + 1);
+               if (new_gidset == NULL) {
+                       return -1;
+               }
+
+               memcpy(new_gidset + 1, gidset, (setlen * sizeof(gid_t)));
+               new_gidset[0] = primary_gid;
+               setlen++;
+       }
+
+       if (setlen > max) {
+               DEBUG(3, ("forced to truncate group list from %d to %d\n",
+                       setlen, max));
+               setlen = max;
+       }
+
+#if defined(HAVE_BROKEN_GETGROUPS)
+       ret = sys_broken_setgroups(setlen, new_gidset ? new_gidset : gidset);
+#else
+       ret = setgroups(setlen, new_gidset ? new_gidset : gidset);
+#endif
+
+       if (new_gidset) {
+               int errsav = errno;
+               SAFE_FREE(new_gidset);
+               errno = errsav;
+       }
+
+       return ret;
+}
+
+#endif /* USE_BSD_SETGROUPS */
+
+/**************************************************************************
+ Wrapper for getgroups. Deals with broken (int) case.
+****************************************************************************/
+
+int sys_getgroups(int setlen, gid_t *gidset)
+{
+#if defined(HAVE_BROKEN_GETGROUPS)
+       return sys_broken_getgroups(setlen, gidset);
+#else
+       return getgroups(setlen, gidset);
+#endif
+}
+
+/**************************************************************************
+ Wrapper for setgroups. Deals with broken (int) case and BSD case.
+****************************************************************************/
+
+int sys_setgroups(gid_t UNUSED(primary_gid), int setlen, gid_t *gidset)
+{
+#if !defined(HAVE_SETGROUPS)
+       errno = ENOSYS;
+       return -1;
+#endif /* HAVE_SETGROUPS */
+
+#if defined(USE_BSD_SETGROUPS)
+       return sys_bsd_setgroups(primary_gid, setlen, gidset);
+#elif defined(HAVE_BROKEN_GETGROUPS)
+       return sys_broken_setgroups(setlen, gidset);
+#else
+       return setgroups(setlen, gidset);
+#endif
 }
 
 /**************************************************************************
@@ -892,6 +1095,82 @@ void sys_endpwent(void)
  Wrappers for getpwnam(), getpwuid(), getgrnam(), getgrgid()
 ****************************************************************************/
 
+#ifdef ENABLE_BUILD_FARM_HACKS
+
+/*
+ * In the build farm we want to be able to join machines to the domain. As we
+ * don't have root access, we need to bypass direct access to /etc/passwd
+ * after a user has been created via samr. Fake those users.
+ */
+
+static struct passwd *fake_pwd;
+static int num_fake_pwd;
+
+struct passwd *sys_getpwnam(const char *name)
+{
+       int i;
+
+       for (i=0; i<num_fake_pwd; i++) {
+               if (strcmp(fake_pwd[i].pw_name, name) == 0) {
+                       DEBUG(10, ("Returning fake user %s\n", name));
+                       return &fake_pwd[i];
+               }
+       }
+
+       return getpwnam(name);
+}
+
+struct passwd *sys_getpwuid(uid_t uid)
+{
+       int i;
+
+       for (i=0; i<num_fake_pwd; i++) {
+               if (fake_pwd[i].pw_uid == uid) {
+                       DEBUG(10, ("Returning fake user %s\n",
+                                  fake_pwd[i].pw_name));
+                       return &fake_pwd[i];
+               }
+       }
+
+       return getpwuid(uid);
+}
+
+void faked_create_user(const char *name)
+{
+       int i;
+       uid_t uid;
+       struct passwd new_pwd;
+
+       for (i=0; i<10; i++) {
+               generate_random_buffer((unsigned char *)&uid,
+                                      sizeof(uid));
+               if (getpwuid(uid) == NULL) {
+                       break;
+               }
+       }
+
+       if (i==10) {
+               /* Weird. No free uid found... */
+               return;
+       }
+
+       new_pwd.pw_name = SMB_STRDUP(name);
+       new_pwd.pw_passwd = SMB_STRDUP("x");
+       new_pwd.pw_uid = uid;
+       new_pwd.pw_gid = 100;
+       new_pwd.pw_gecos = SMB_STRDUP("faked user");
+       new_pwd.pw_dir = SMB_STRDUP("/nodir");
+       new_pwd.pw_shell = SMB_STRDUP("/bin/false");
+
+       ADD_TO_ARRAY(NULL, struct passwd, new_pwd, &fake_pwd,
+                    &num_fake_pwd);
+
+       DEBUG(10, ("Added fake user %s, have %d fake users\n",
+                  name, num_fake_pwd));
+}
+
+#else
+
 struct passwd *sys_getpwnam(const char *name)
 {
        return getpwnam(name);
@@ -902,6 +1181,8 @@ struct passwd *sys_getpwuid(uid_t uid)
        return getpwuid(uid);
 }
 
+#endif
+
 struct group *sys_getgrnam(const char *name)
 {
        return getgrnam(name);
@@ -1085,21 +1366,25 @@ SMB_STRUCT_WPASSWD *wsys_getpwuid(uid_t uid)
 #endif /* NOT CURRENTLY USED - JRA */
 
 /**************************************************************************
- Extract a command into an arg list. Uses a static pstring for storage.
- Caller frees returned arg list (which contains pointers into the static pstring).
+ Extract a command into an arg list.
 ****************************************************************************/
 
-static char **extract_args(const char *command)
+static char **extract_args(TALLOC_CTX *mem_ctx, const char *command)
 {
-       static pstring trunc_cmd;
+       char *trunc_cmd;
+       char *saveptr;
        char *ptr;
        int argcl;
        char **argl = NULL;
        int i;
 
-       pstrcpy(trunc_cmd, command);
+       if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
+               DEBUG(0, ("talloc failed\n"));
+               goto nomem;
+       }
 
-       if(!(ptr = strtok(trunc_cmd, " \t"))) {
+       if(!(ptr = strtok_r(trunc_cmd, " \t", &saveptr))) {
+               TALLOC_FREE(trunc_cmd);
                errno = EINVAL;
                return NULL;
        }
@@ -1108,27 +1393,46 @@ static char **extract_args(const char *command)
         * Count the args.
         */
 
-       for( argcl = 1; ptr; ptr = strtok(NULL, " \t"))
+       for( argcl = 1; ptr; ptr = strtok_r(NULL, " \t", &saveptr))
                argcl++;
 
-       if((argl = (char **)SMB_MALLOC((argcl + 1) * sizeof(char *))) == NULL)
-               return NULL;
+       TALLOC_FREE(trunc_cmd);
+
+       if (!(argl = TALLOC_ARRAY(mem_ctx, char *, argcl + 1))) {
+               goto nomem;
+       }
 
        /*
         * Now do the extraction.
         */
 
-       pstrcpy(trunc_cmd, command);
+       if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
+               goto nomem;
+       }
 
-       ptr = strtok(trunc_cmd, " \t");
+       ptr = strtok_r(trunc_cmd, " \t", &saveptr);
        i = 0;
-       argl[i++] = ptr;
 
-       while((ptr = strtok(NULL, " \t")) != NULL)
-               argl[i++] = ptr;
+       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;
        return argl;
+
+ nomem:
+       DEBUG(0, ("talloc failed\n"));
+       TALLOC_FREE(trunc_cmd);
+       TALLOC_FREE(argl);
+       errno = ENOMEM;
+       return NULL;
 }
 
 /**************************************************************************
@@ -1202,7 +1506,7 @@ int sys_popen(const char *command)
         * Extract the command and args into a NULL terminated array.
         */
 
-       if(!(argl = extract_args(command)))
+       if(!(argl = extract_args(NULL, command)))
                goto err_exit;
 
        entry->child_pid = sys_fork();
@@ -1244,7 +1548,7 @@ int sys_popen(const char *command)
         */
 
        close (child_end);
-       SAFE_FREE(argl);
+       TALLOC_FREE(argl);
 
        /* Link into popen_chain. */
        entry->next = popen_chain;
@@ -1387,7 +1691,12 @@ int sys_dup2(int oldfd, int newfd)
 ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t size)
 {
 #if defined(HAVE_GETXATTR)
+#ifndef XATTR_ADD_OPT
        return getxattr(path, name, value, size);
+#else
+       int options = 0;
+       return getxattr(path, name, value, size, 0, options);
+#endif
 #elif defined(HAVE_GETEA)
        return getea(path, name, value, size);
 #elif defined(HAVE_EXTATTR_GET_FILE)
@@ -1432,6 +1741,9 @@ ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t s
 {
 #if defined(HAVE_LGETXATTR)
        return lgetxattr(path, name, value, size);
+#elif defined(HAVE_GETXATTR) && defined(XATTR_ADD_OPT)
+       int options = XATTR_NOFOLLOW;
+       return getxattr(path, name, value, size, 0, options);
 #elif defined(HAVE_LGETEA)
        return lgetea(path, name, value, size);
 #elif defined(HAVE_EXTATTR_GET_LINK)
@@ -1471,7 +1783,12 @@ ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t s
 ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size)
 {
 #if defined(HAVE_FGETXATTR)
+#ifndef XATTR_ADD_OPT
        return fgetxattr(filedes, name, value, size);
+#else
+       int options = 0;
+       return fgetxattr(filedes, name, value, size, 0, options);
+#endif
 #elif defined(HAVE_FGETEA)
        return fgetea(filedes, name, value, size);
 #elif defined(HAVE_EXTATTR_GET_FD)
@@ -1672,7 +1989,12 @@ static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t
 ssize_t sys_listxattr (const char *path, char *list, size_t size)
 {
 #if defined(HAVE_LISTXATTR)
+#ifndef XATTR_ADD_OPT
        return listxattr(path, list, size);
+#else
+       int options = 0;
+       return listxattr(path, list, size, options);
+#endif
 #elif defined(HAVE_LISTEA)
        return listea(path, list, size);
 #elif defined(HAVE_EXTATTR_LIST_FILE)
@@ -1691,6 +2013,9 @@ ssize_t sys_llistxattr (const char *path, char *list, size_t size)
 {
 #if defined(HAVE_LLISTXATTR)
        return llistxattr(path, list, size);
+#elif defined(HAVE_LISTXATTR) && defined(XATTR_ADD_OPT)
+       int options = XATTR_NOFOLLOW;
+       return listxattr(path, list, size, options);
 #elif defined(HAVE_LLISTEA)
        return llistea(path, list, size);
 #elif defined(HAVE_EXTATTR_LIST_LINK)
@@ -1708,7 +2033,12 @@ ssize_t sys_llistxattr (const char *path, char *list, size_t size)
 ssize_t sys_flistxattr (int filedes, char *list, size_t size)
 {
 #if defined(HAVE_FLISTXATTR)
+#ifndef XATTR_ADD_OPT
        return flistxattr(filedes, list, size);
+#else
+       int options = 0;
+       return flistxattr(filedes, list, size, options);
+#endif
 #elif defined(HAVE_FLISTEA)
        return flistea(filedes, list, size);
 #elif defined(HAVE_EXTATTR_LIST_FD)
@@ -1726,7 +2056,12 @@ ssize_t sys_flistxattr (int filedes, char *list, size_t size)
 int sys_removexattr (const char *path, const char *name)
 {
 #if defined(HAVE_REMOVEXATTR)
+#ifndef XATTR_ADD_OPT
        return removexattr(path, name);
+#else
+       int options = 0;
+       return removexattr(path, name, options);
+#endif
 #elif defined(HAVE_REMOVEEA)
        return removeea(path, name);
 #elif defined(HAVE_EXTATTR_DELETE_FILE)
@@ -1753,6 +2088,9 @@ int sys_lremovexattr (const char *path, const char *name)
 {
 #if defined(HAVE_LREMOVEXATTR)
        return lremovexattr(path, name);
+#elif defined(HAVE_REMOVEXATTR) && defined(XATTR_ADD_OPT)
+       int options = XATTR_NOFOLLOW;
+       return removexattr(path, name, options);
 #elif defined(HAVE_LREMOVEEA)
        return lremoveea(path, name);
 #elif defined(HAVE_EXTATTR_DELETE_LINK)
@@ -1778,7 +2116,12 @@ int sys_lremovexattr (const char *path, const char *name)
 int sys_fremovexattr (int filedes, const char *name)
 {
 #if defined(HAVE_FREMOVEXATTR)
+#ifndef XATTR_ADD_OPT
        return fremovexattr(filedes, name);
+#else
+       int options = 0;
+       return fremovexattr(filedes, name, options);
+#endif
 #elif defined(HAVE_FREMOVEEA)
        return fremoveea(filedes, name);
 #elif defined(HAVE_EXTATTR_DELETE_FD)
@@ -1809,7 +2152,12 @@ int sys_fremovexattr (int filedes, const char *name)
 int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags)
 {
 #if defined(HAVE_SETXATTR)
+#ifndef XATTR_ADD_OPT
        return setxattr(path, name, value, size, flags);
+#else
+       int options = 0;
+       return setxattr(path, name, value, size, 0, options);
+#endif
 #elif defined(HAVE_SETEA)
        return setea(path, name, value, size, flags);
 #elif defined(HAVE_EXTATTR_SET_FILE)
@@ -1858,6 +2206,9 @@ int sys_lsetxattr (const char *path, const char *name, const void *value, size_t
 {
 #if defined(HAVE_LSETXATTR)
        return lsetxattr(path, name, value, size, flags);
+#elif defined(HAVE_SETXATTR) && defined(XATTR_ADD_OPT)
+       int options = XATTR_NOFOLLOW;
+       return setxattr(path, name, value, size, 0, options);
 #elif defined(LSETEA)
        return lsetea(path, name, value, size, flags);
 #elif defined(HAVE_EXTATTR_SET_LINK)
@@ -1906,7 +2257,12 @@ int sys_lsetxattr (const char *path, const char *name, const void *value, size_t
 int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags)
 {
 #if defined(HAVE_FSETXATTR)
+#ifndef XATTR_ADD_OPT
        return fsetxattr(filedes, name, value, size, flags);
+#else
+       int options = 0;
+       return fsetxattr(filedes, name, value, size, 0, options);
+#endif
 #elif defined(HAVE_FSETEA)
        return fsetea(filedes, name, value, size, flags);
 #elif defined(HAVE_EXTATTR_SET_FD)
@@ -2134,3 +2490,28 @@ int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct
        return -1;
 }
 #endif /* WITH_AIO */
+
+int sys_getpeereid( int s, uid_t *uid)
+{
+#if defined(HAVE_PEERCRED)
+       struct ucred cred;
+       socklen_t cred_len = sizeof(struct ucred);
+       int ret;
+
+       ret = getsockopt(s, SOL_SOCKET, SO_PEERCRED, (void *)&cred, &cred_len);
+       if (ret != 0) {
+               return -1;
+       }
+
+       if (cred_len != sizeof(struct ucred)) {
+               errno = EINVAL;
+               return -1;
+       }
+
+       *uid = cred.uid;
+       return 0;
+#else
+       errno = ENOSYS;
+       return -1;
+#endif
+}