+/*******************************************************************
+ 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.
********************************************************************/
#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
********************************************************************/
}
/**************************************************************************
- 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;
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;
}
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(gid_t primary_gid, 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 ;
* 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;
}
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) {
+ gid_t *new_gidset;
+
+ new_gidset = SMB_MALLOC_ARRAY(gid_t, setlen + 1);
+ if (new_gidset == NULL) {
+ return -1;
+ }
+
+ memcpy(new_gidset + 1, gidset, ((setlen + 1) * sizeof(gid_t)));
+ new_gidset[0] = primary_gid;
+ setlen++;
+ }
+
+ if (setlen > max) {
+ DEBUG(10, ("forced to truncate group list from %d to %d\n",
+ setlen, max));
+ setlen = max;
+ }
+
+#if defined(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(HAVE_BROKEN_GETGROUPS)
+ return sys_broken_setgroups(setlen, gidset);
+#elif defined(USE_BSD_SETGROUPS)
+ return sys_bsd_setgroups(primary_gid, setlen, gidset);
+#else
+ return setgroups(setlen, gidset);
+#endif
}
/**************************************************************************