summaryrefslogtreecommitdiff
path: root/source3
diff options
context:
space:
mode:
Diffstat (limited to 'source3')
-rw-r--r--source3/Makefile.in5
-rw-r--r--source3/configure.in64
-rw-r--r--source3/include/sysquotas.h152
-rw-r--r--source3/lib/sysquotas.c529
-rw-r--r--source3/smbd/quotas.c159
5 files changed, 133 insertions, 776 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in
index 6a60ef0221..e27e3761f3 100644
--- a/source3/Makefile.in
+++ b/source3/Makefile.in
@@ -351,8 +351,9 @@ SMBD_OBJ_SRV = smbd/files.o smbd/chgpasswd.o smbd/connection.o \
smbd/vfs.o smbd/vfs-wrap.o smbd/statcache.o \
smbd/posix_acls.o lib/sysacls.o lib/server_mutex.o \
smbd/process.o smbd/service.o smbd/error.o \
- printing/printfsp.o \
- lib/sysquotas.o smbd/change_trust_pw.o smbd/fake_file.o \
+ printing/printfsp.o lib/sysquotas.o lib/sysquotas_linux.o \
+ lib/sysquotas_xfs.o \
+ smbd/change_trust_pw.o smbd/fake_file.o \
smbd/quotas.o smbd/ntquotas.o lib/afs.o \
$(MANGLE_OBJ) @VFS_STATIC@
diff --git a/source3/configure.in b/source3/configure.in
index 02647bca47..2248bc7b34 100644
--- a/source3/configure.in
+++ b/source3/configure.in
@@ -3009,6 +3009,7 @@ samba_cv_TRY_QUOTAS=no
samba_cv_RUN_QUOTA_TESTS=auto
samba_cv_WITH_SYS_QUOTAS=auto
samba_cv_TRY_SYS_QUOTAS=no
+samba_cv_SYSQUOTA_FOUND=no;
AC_MSG_CHECKING(whether to try disk-quotas support)
AC_ARG_WITH(quotas,
@@ -3078,6 +3079,10 @@ AC_MSG_CHECKING(whether to try the lib/sysquotas.c interface on ${host_os})
AC_MSG_RESULT(yes)
samba_cv_TRY_SYS_QUOTAS=yes
samba_cv_RUN_QUOTA_TESTS=yes
+ samba_cv_SYSQUOTA_FOUND=yes
+ AC_DEFINE(HAVE_QUOTACTL_LINUX,1,[Whether Linux quota support is available])
+ AC_DEFINE(HAVE_LINUX_XFS_QUOTAS,1,[Whether Linux xfs quota support is available])
+ samba_cv_sysquotas_file="lib/sysquotas_linux.c"
;;
*)
AC_MSG_RESULT(no)
@@ -3090,21 +3095,21 @@ fi
# only check for quota stuff if --with-quotas
if test x"$samba_cv_RUN_QUOTA_TESTS" != x"no"; then
+# some broken header files need this
+AC_CHECK_HEADER(asm/types.h,[
+ AC_DEFINE(HAVE_ASM_TYPES_H,1,[check for <asm/types.h>])
+ AC_ADD_INCLUDE(<asm/types.h>)
+ ])
+
# For quotas on Veritas VxFS filesystems
AC_CHECK_HEADERS(sys/fs/vx_quota.h)
# For sys/quota.h and linux/quota.h
AC_CHECK_HEADERS(sys/quota.h)
-AC_CHECK_HEADERS(asm/types.h linux/quota.h)
-# For quotas on Linux XFS filesystems
-AC_CHECK_HEADERS(linux/xqm.h linux/xfs_fs.h)
-AC_CHECK_HEADERS(xfs/libxfs.h xfs/xqm.h xfs/xfs_fs.h)
-# For linux > 2.5.56
-AC_CHECK_HEADERS(linux/dqblk_xfs.h)
-
-# if we have struct if_dqblk in <linux/quota.h> we should use it
-AC_CACHE_CHECK([for struct if_dqblk in <linux/quota.h>],samba_cv_HAVE_STRUCT_IF_DQBLK, [
+if test x"$samba_cv_found_xfs_header" = x"no"; then
+# if we have xfs quota support <sys/quota.h> (IRIX) we should use it
+AC_CACHE_CHECK([for XFS QUOTA in <sys/quota.h>],samba_cv_HAVE_SYS_QUOTA_XFS, [
AC_TRY_COMPILE([
#include "confdefs.h"
#ifdef HAVE_SYS_TYPES_H
@@ -3113,30 +3118,15 @@ AC_TRY_COMPILE([
#ifdef HAVE_ASM_TYPES_H
#include <asm/types.h>
#endif
-#include <linux/quota.h>
-],[struct if_dqblk D;],
-samba_cv_HAVE_STRUCT_IF_DQBLK=yes,samba_cv_HAVE_STRUCT_IF_DQBLK=no)])
-if test "$samba_cv_HAVE_STRUCT_IF_DQBLK"x = "yes"x; then
- AC_DEFINE(HAVE_STRUCT_IF_DQBLK,1,[struct if_dqblk])
+#include <sys/quota.h>
+],[int i = Q_XGETQUOTA;],
+samba_cv_HAVE_SYS_QUOTA_XFS=yes,samba_cv_HAVE_SYS_QUOTA_XFS=no)])
+if test "$samba_cv_HAVE_SYS_QUOTA_XFS"x = "yes"x; then
+ AC_DEFINE(HAVE_IRIX_XFS_QUOTAS,1,[Whether IRIX xfs quota support is available])
fi
-
-# if we have struct mem_dqblk in <linux/quota.h> we should use it
-AC_CACHE_CHECK([for struct mem_dqblk in <linux/quota.h>],samba_cv_HAVE_STRUCT_MEM_DQBLK, [
-AC_TRY_COMPILE([
-#include "confdefs.h"
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_ASM_TYPES_H
-#include <asm/types.h>
-#endif
-#include <linux/quota.h>
-],[struct mem_dqblk D;],
-samba_cv_HAVE_STRUCT_MEM_DQBLK=yes,samba_cv_HAVE_STRUCT_MEM_DQBLK=no)])
-if test "$samba_cv_HAVE_STRUCT_MEM_DQBLK"x = "yes"x; then
- AC_DEFINE(HAVE_STRUCT_MEM_DQBLK,1,[struct mem_dqblk])
fi
+
# if we have struct dqblk .dqb_fsoftlimit instead of .dqb_isoftlimit on IRIX
AC_CACHE_CHECK([if struct dqblk has .dqb_fsoftlimit],samba_cv_HAVE_DQB_FSOFTLIMIT, [
AC_TRY_COMPILE([
@@ -3154,7 +3144,6 @@ fi
##################
# look for a working quota system
-samba_cv_SYSQUOTA_FOUND=no;
if test x"$samba_cv_SYSQUOTA_FOUND" != x"yes"; then
AC_CACHE_CHECK([for long quotactl(int cmd, char *special, qid_t id, caddr_t addr)],samba_cv_HAVE_QUOTACTL_4A,[
@@ -3165,7 +3154,9 @@ AC_TRY_RUN_STRICT([
#include "${srcdir-.}/tests/sysquotas.c"],[$Werror_FLAGS],[$CPPFLAGS],[$LDFLAGS],
samba_cv_HAVE_QUOTACTL_4A=yes,samba_cv_HAVE_QUOTACTL_4A=no,samba_cv_HAVE_QUOTACTL_4A=cross)])
if test x"$samba_cv_HAVE_QUOTACTL_4A" = x"yes"; then
- samba_cv_SYSQUOTA_FOUND=yes;AC_DEFINE(HAVE_QUOTACTL_4A,1,[Whether long quotactl(int cmd, char *special, qid_t id, caddr_t addr) is available])
+ samba_cv_SYSQUOTA_FOUND=yes;
+ AC_DEFINE(HAVE_QUOTACTL_4A,1,[Whether long quotactl(int cmd, char *special, qid_t id, caddr_t addr) is available])
+ samba_cv_sysquotas_file="lib/sysquotas_4A.c"
fi
fi
@@ -3179,7 +3170,9 @@ AC_TRY_RUN_STRICT([
samba_cv_HAVE_QUOTACTL_4B=yes,samba_cv_HAVE_QUOTACTL_4B=no,samba_cv_HAVE_QUOTACTL_4B=cross)])
if test x"$samba_cv_HAVE_QUOTACTL_4B" = x"yes"; then
echo "int quotactl(const char *path, int cmd, int id, char *addr) is not reworked for the new sys_quota api"
-# samba_cv_SYSQUOTA_FOUND=yes;AC_DEFINE(HAVE_QUOTACTL_4B,1,[Whether int quotactl(const char *path, int cmd, int id, char *addr) is available])
+ samba_cv_SYSQUOTA_FOUND=yes;
+ AC_DEFINE(HAVE_QUOTACTL_4B,1,[Whether int quotactl(const char *path, int cmd, int id, char *addr) is available])
+ samba_cv_sysquotas_file="lib/sysquotas_4B.c"
fi
fi
@@ -3193,7 +3186,9 @@ AC_TRY_RUN_STRICT([
samba_cv_HAVE_QUOTACTL_3=yes,samba_cv_HAVE_QUOTACTL_3=no,samba_cv_HAVE_QUOTACTL_3=cross)])
if test x"$samba_cv_HAVE_QUOTACTL_3" = x"yes"; then
echo "CRAY int quotactl (char *spec, int request, char *arg) is NOT reworked for the sys_quota api"
-# samba_cv_SYSQUOTA_FOUND=yes;AC_DEFINE(HAVE_QUOTACTL_3,1,[Whether CRAY int quotactl (char *spec, int request, char *arg); is available])
+ samba_cv_SYSQUOTA_FOUND=yes;
+ AC_DEFINE(HAVE_QUOTACTL_3,1,[Whether CRAY int quotactl (char *spec, int request, char *arg); is available])
+ samba_cv_sysquotas_file="lib/sysquotas_3.c"
fi
fi
@@ -3235,6 +3230,7 @@ AC_TRY_COMPILE([
#define NO_PROTO_H 1
#define NO_CONFIG_H 1
#define HAVE_SYS_QUOTAS 1
+#include "${srcdir-.}/${samba_cv_sysquotas_file}"
#include "${srcdir-.}/lib/sysquotas.c"
],[],samba_cv_SYSQUOTA_WORKS=yes,samba_cv_SYSQUOTA_WORKS=no)
CPPFLAGS="$SAVE_CPPFLAGS"
diff --git a/source3/include/sysquotas.h b/source3/include/sysquotas.h
index b803e6277a..bfb9466b39 100644
--- a/source3/include/sysquotas.h
+++ b/source3/include/sysquotas.h
@@ -23,150 +23,6 @@
#ifdef HAVE_SYS_QUOTAS
-/* Sometimes we need this on linux for linux/quota.h */
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#ifdef HAVE_ASM_TYPES_H
-#include <asm/types.h>
-#endif
-
-/*
- * This shouldn't be neccessary - it should be /usr/include/sys/quota.h
- * Unfortunately, RH7.1 ships with a different quota system using struct mem_dqblk
- * rather than the struct dqblk defined in /usr/include/sys/quota.h.
- * This means we must include linux/quota.h to have a hope of working on
- * RH7.1 systems. And it also means this breaks if the kernel is upgraded
- * to a Linus 2.4.x (where x > the minor number shipped with RH7.1) until
- * Linus synchronises with the AC patches. Sometimes I *hate* Linux :-). JRA.
- */
-#ifdef HAVE_LINUX_QUOTA_H
-#include <linux/quota.h>
-#elif defined(HAVE_SYS_QUOTA_H)
-#include <sys/quota.h>
-#endif
-
-#if defined(HAVE_STRUCT_IF_DQBLK)
-# define SYS_DQBLK if_dqblk
-# define dqb_curblocks dqb_curspace/bsize
-#elif defined(HAVE_STRUCT_MEM_DQBLK)
-# define SYS_DQBLK mem_dqblk
-# define dqb_curblocks dqb_curspace/bsize
-#else /* STRUCT_DQBLK */
-# define SYS_DQBLK dqblk
-#endif
-
-#ifndef Q_SETQLIM
-#define Q_SETQLIM Q_SETQUOTA
-#endif
-
-/*********************************************
- check for XFS QUOTA MANAGER
- *********************************************/
-/* on linux */
-#ifdef HAVE_LINUX_XQM_H
-# include <linux/xqm.h>
-# define HAVE_XFS_QUOTA
-#else
-# ifdef HAVE_XFS_XQM_H
-# include <xfs/xqm.h>
-# define HAVE_XFS_QUOTA
-# else
-# ifdef HAVE_LINUX_DQBLK_XFS_H
-# include <linux/dqblk_xfs.h>
-# define HAVE_XFS_QUOTA
-# endif
-# endif
-#endif
-/* on IRIX */
-#ifdef Q_XGETQUOTA
-# ifndef HAVE_XFS_QUOTA
-# define HAVE_XFS_QUOTA
-# ifndef Q_XQUOTAON
-# define Q_XQUOTAON Q_QUOTAON
-# endif /* Q_XQUOTAON */
-# ifndef Q_XQUOTAOFF
-# define Q_XQUOTAOFF Q_QUOTAOFF
-# endif /* Q_XQUOTAOFF */
-# ifndef Q_XGETQSTAT
-# define Q_XGETQSTAT Q_GETQSTAT
-# endif /* Q_XGETQSTAT */
-# endif /* HAVE_XFS_QUOTA */
-#endif /* Q_XGETQUOTA */
-
-#ifdef HAVE_XFS_QUOTA
-/* Linux has BBSIZE in <linux/xfs_fs.h>
- * or <xfs/xfs_fs.h>
- * IRIX has BBSIZE in <sys/param.h>
- */
-#ifdef HAVE_LINUX_XFS_FS_H
-#include <linux/xfs_fs.h>
-#elif defined(HAVE_XFS_XFS_FS_H)
-#include <xfs/xfs_fs.h>
-#endif /* *_XFS_FS_H */
-
-#ifndef BBSHIFT
-#define BBSHIFT 9
-#endif /* BBSHIFT */
-#ifndef BBSIZE
-#define BBSIZE (1<<BBSHIFT)
-#endif /* BBSIZE */
-
-#endif /* HAVE_XFS_QUOTA */
-
-#ifdef LINUX
-# ifndef QUOTABLOCK_SIZE
-# define QUOTABLOCK_SIZE 1024
-# endif
-/* end LINUX */
-#elif defined(IRIX6)
-# ifndef QUOTABLOCK_SIZE
-# define QUOTABLOCK_SIZE BBSIZE
-# endif
-/* end IRIX6 */
-#else /* HPUP,... */
-# ifndef QUOTABLOCK_SIZE
-# define QUOTABLOCK_SIZE DEV_BSIZE
-# endif
-#endif /* HPUP,... */
-
-#if !defined(QUOTAFILENAME) && defined(QFILENAME)
-#define QUOTAFILENAME QFILENAME
-#endif
-
-#ifdef INITQFNAMES
-#define USERQUOTAFILE_EXTENSION ".user"
-#else
-#define USERQUOTAFILE_EXTENSION ""
-#endif
-
-/* this check should be before the QCMD fake! */
-#if defined(QCMD)&&defined(GRPQUOTA)
-#define HAVE_GROUP_QUOTA
-#endif
-
-/* on some systems we have to fake this up ...*/
-#ifndef QCMD
-#define QCMD(cmd,type) (cmd)
-#endif /* QCMD */
-
-
-#ifdef HAVE_DQB_FSOFTLIMIT
-#define dqb_isoftlimit dqb_fsoftlimit
-#define dqb_ihardlimit dqb_fhardlimit
-#define dqb_curinodes dqb_curfiles
-#endif
-
-/* maybe we can add a configure test for HAVE_CADDR_T,
- * but it's not needed
- */
-#ifdef HAVE_CADDR_T
-#define CADDR_T caddr_t
-#else /* CADDR_T */
-#define CADDR_T void*
-#endif /* CADDR_T */
-
#if defined(HAVE_MNTENT_H)&&defined(HAVE_SETMNTENT)&&defined(HAVE_GETMNTENT)&&defined(HAVE_ENDMNTENT)
#include <mntent.h>
#define HAVE_MNTENT 1
@@ -178,10 +34,6 @@
#endif /* HAVE_SYS_QUOTAS */
-#ifndef QUOTABLOCK_SIZE
-#define QUOTABLOCK_SIZE 1024
-#endif
-
/**************************************************
Some stuff for the sys_quota api.
**************************************************/
@@ -217,4 +69,8 @@ typedef struct _SMB_DISK_QUOTA {
uint32 qflags;
} SMB_DISK_QUOTA;
+#ifndef QUOTABLOCK_SIZE
+#define QUOTABLOCK_SIZE 1024
+#endif
+
#endif /*_SYSQUOTAS_H */
diff --git a/source3/lib/sysquotas.c b/source3/lib/sysquotas.c
index 3223ecb580..6883444e00 100644
--- a/source3/lib/sysquotas.c
+++ b/source3/lib/sysquotas.c
@@ -24,255 +24,6 @@
#ifdef HAVE_SYS_QUOTAS
#if defined(HAVE_QUOTACTL_4A)
-/* long quotactl(int cmd, char *special, qid_t id, caddr_t addr) */
-/* this is used by: linux,HPUX,IRIX */
-
-/****************************************************************************
- Abstract out the old and new Linux quota get calls.
-****************************************************************************/
-static int sys_get_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
-{
- int ret = -1;
- uint32 qflags = 0;
- struct SYS_DQBLK D;
- SMB_BIG_UINT bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
-
- if (!path||!bdev||!dp)
- smb_panic("sys_get_vfs_quota: called with NULL pointer");
-
- ZERO_STRUCT(D);
- ZERO_STRUCT(*dp);
- dp->qtype = qtype;
-
- switch (qtype) {
- case SMB_USER_QUOTA_TYPE:
- if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (CADDR_T)&D))) {
- return ret;
- }
-
- if ((D.dqb_curblocks==0)&&
- (D.dqb_bsoftlimit==0)&&
- (D.dqb_bhardlimit==0)) {
- /* the upper layer functions don't want empty quota records...*/
- return -1;
- }
-
- break;
-#ifdef HAVE_GROUP_QUOTA
- case SMB_GROUP_QUOTA_TYPE:
- if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id.gid, (CADDR_T)&D))) {
- return ret;
- }
-
- if ((D.dqb_curblocks==0)&&
- (D.dqb_bsoftlimit==0)&&
- (D.dqb_bhardlimit==0)) {
- /* the upper layer functions don't want empty quota records...*/
- return -1;
- }
-
- break;
-#endif /* HAVE_GROUP_QUOTA */
- case SMB_USER_FS_QUOTA_TYPE:
- id.uid = getuid();
-
- if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (CADDR_T)&D))==0) {
- qflags |= QUOTAS_DENY_DISK;
- }
-
- ret = 0;
- break;
-#ifdef HAVE_GROUP_QUOTA
- case SMB_GROUP_FS_QUOTA_TYPE:
- id.gid = getgid();
-
- if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id.gid, (CADDR_T)&D))==0) {
- qflags |= QUOTAS_DENY_DISK;
- }
-
- ret = 0;
- break;
-#endif /* HAVE_GROUP_QUOTA */
- default:
- errno = ENOSYS;
- return -1;
- }
-
- dp->bsize = bsize;
- dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit;
- dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit;
- dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit;
- dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit;
- dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes;
- dp->curblocks = (SMB_BIG_UINT)D.dqb_curblocks;
-
-
- dp->qflags = qflags;
-
- return ret;
-}
-
-/****************************************************************************
- Abstract out the old and new Linux quota set calls.
-****************************************************************************/
-
-static int sys_set_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
-{
- int ret = -1;
- uint32 qflags = 0;
- uint32 oldqflags = 0;
- struct SYS_DQBLK D;
- SMB_BIG_UINT bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
-
- if (!path||!bdev||!dp)
- smb_panic("sys_set_vfs_quota: called with NULL pointer");
-
- ZERO_STRUCT(D);
-
- if (bsize == dp->bsize) {
- D.dqb_bsoftlimit = dp->softlimit;
- D.dqb_bhardlimit = dp->hardlimit;
- D.dqb_ihardlimit = dp->ihardlimit;
- D.dqb_isoftlimit = dp->isoftlimit;
- } else {
- D.dqb_bsoftlimit = (dp->softlimit*dp->bsize)/bsize;
- D.dqb_bhardlimit = (dp->hardlimit*dp->bsize)/bsize;
- D.dqb_ihardlimit = (dp->ihardlimit*dp->bsize)/bsize;
- D.dqb_isoftlimit = (dp->isoftlimit*dp->bsize)/bsize;
- }
-
- qflags = dp->qflags;
-
- switch (qtype) {
- case SMB_USER_QUOTA_TYPE:
- ret = quotactl(QCMD(Q_SETQLIM,USRQUOTA), bdev, id.uid, (CADDR_T)&D);
- break;
-#ifdef HAVE_GROUP_QUOTA
- case SMB_GROUP_QUOTA_TYPE:
- ret = quotactl(QCMD(Q_SETQLIM,GRPQUOTA), bdev, id.gid, (CADDR_T)&D);
- break;
-#endif /* HAVE_GROUP_QUOTA */
- case SMB_USER_FS_QUOTA_TYPE:
- /* this stuff didn't work as it should:
- * switching on/off quota via quotactl()
- * didn't work!
- * So we just return 0
- * --metze
- *
- * On HPUX we didn't have the mount path,
- * we need to fix sys_path_to_bdev()
- *
- */
-#if 0
- id.uid = getuid();
-
- ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (CADDR_T)&D);
-
- if ((qflags&QUOTAS_DENY_DISK)||(qflags&QUOTAS_ENABLED)) {
- if (ret == 0) {
- char *quota_file = NULL;
-
- asprintf(&quota_file,"/%s/%s%s",path, QUOTAFILENAME,USERQUOTAFILE_EXTENSION);
- if (quota_file == NULL) {
- DEBUG(0,("asprintf() failed!\n"));
- errno = ENOMEM;
- return -1;
- }
-
- ret = quotactl(QCMD(Q_QUOTAON,USRQUOTA), bdev, -1,(CADDR_T)quota_file);
- } else {
- ret = 0;
- }
- } else {
- if (ret != 0) {
- /* turn off */
- ret = quotactl(QCMD(Q_QUOTAOFF,USRQUOTA), bdev, -1, (CADDR_T)0);
- } else {
- ret = 0;
- }
- }
-
- DEBUG(0,("vfs_fs_quota: ret(%d) errno(%d)[%s] uid(%d) bdev[%s]\n",
- ret,errno,strerror(errno),id.uid,bdev));
-#else
- id.uid = getuid();
-
- if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (CADDR_T)&D))==0) {
- oldqflags |= QUOTAS_DENY_DISK;
- }
-
- if (oldqflags == qflags) {
- ret = 0;
- } else {
- ret = -1;
- }
-#endif
- break;
-#ifdef HAVE_GROUP_QUOTA
- case SMB_GROUP_FS_QUOTA_TYPE:
- /* this stuff didn't work as it should:
- * switching on/off quota via quotactl()
- * didn't work!
- * So we just return 0
- * --metze
- *
- * On HPUX we didn't have the mount path,
- * we need to fix sys_path_to_bdev()
- *
- */
-#if 0
- id.gid = getgid();
-
- ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id, (CADDR_T)&D);
-
- if ((qflags&QUOTAS_DENY_DISK)||(qflags&QUOTAS_ENABLED)) {
- if (ret == 0) {
- char *quota_file = NULL;
-
- asprintf(&quota_file,"/%s/%s%s",path, QUOTAFILENAME,GROUPQUOTAFILE_EXTENSION);
- if (quota_file == NULL) {
- DEBUG(0,("asprintf() failed!\n"));
- errno = ENOMEM;
- return -1;
- }
-
- ret = quotactl(QCMD(Q_QUOTAON,GRPQUOTA), bdev, -1,(CADDR_T)quota_file);
- } else {
- ret = 0;
- }
- } else {
- if (ret != 0) {
- /* turn off */
- ret = quotactl(QCMD(Q_QUOTAOFF,GRPQUOTA), bdev, -1, (CADDR_T)0);
- } else {
- ret = 0;
- }
- }
-
- DEBUG(0,("vfs_fs_quota: ret(%d) errno(%d)[%s] uid(%d) bdev[%s]\n",
- ret,errno,strerror(errno),id.gid,bdev));
-#else
- id.gid = getgid();
-
- if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id.gid, (CADDR_T)&D))==0) {
- oldqflags |= QUOTAS_DENY_DISK;
- }
-
- if (oldqflags == qflags) {
- ret = 0;
- } else {
- ret = -1;
- }
-#endif
- break;
-#endif /* HAVE_GROUP_QUOTA */
- default:
- errno = ENOSYS;
- return -1;
- }
-
- return ret;
-}
/*#endif HAVE_QUOTACTL_4A */
#elif defined(HAVE_QUOTACTL_4B)
@@ -287,30 +38,6 @@ static int sys_set_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_
/* #endif HAVE_QUOTACTL_3 */
#else /* NO_QUOTACTL_USED */
-static int sys_get_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
-{
- int ret = -1;
-
- if (!path||!bdev||!dp)
- smb_panic("sys_get_vfs_quota: called with NULL pointer");
-
- errno = ENOSYS;
-
- return ret;
-}
-
-static int sys_set_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
-{
- int ret = -1;
-
- if (!path||!bdev||!dp)
- smb_panic("sys_set_vfs_quota: called with NULL pointer");
-
- errno = ENOSYS;
-
- return ret;
-}
-
#endif /* NO_QUOTACTL_USED */
#ifdef HAVE_MNTENT
@@ -434,262 +161,6 @@ static int sys_path_to_bdev(const char *path, char **mntpath, char **bdev, char
}
#endif
-
-/*********************************************************
- if we have XFS QUOTAS we should use them
- *********************************************************/
-#ifdef HAVE_XFS_QUOTA
-/****************************************************************************
- Abstract out the XFS Quota Manager quota get call.
-****************************************************************************/
-static int sys_get_xfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
-{
- int ret = -1;
- uint32 qflags = 0;
- SMB_BIG_UINT bsize = (SMB_BIG_UINT)BBSIZE;
- struct fs_disk_quota D;
- struct fs_quota_stat F;
- ZERO_STRUCT(D);
- ZERO_STRUCT(F);
-
- if (!bdev||!dp)
- smb_panic("sys_get_xfs_quota: called with NULL pointer");
-
- ZERO_STRUCT(*dp);
- dp->qtype = qtype;
-
- switch (qtype) {
- case SMB_USER_QUOTA_TYPE:
- if ((ret=quotactl(QCMD(Q_XGETQUOTA,USRQUOTA), bdev, id.uid, (CADDR_T)&D)))
- return ret;
- break;
-#ifdef HAVE_GROUP_QUOTA
- case SMB_GROUP_QUOTA_TYPE:
- if ((ret=quotactl(QCMD(Q_XGETQUOTA,GRPQUOTA), bdev, id.gid, (CADDR_T)&D)))
- return ret;
- break;
-#endif /* HAVE_GROUP_QUOTA */
- case SMB_USER_FS_QUOTA_TYPE:
- quotactl(QCMD(Q_XGETQSTAT,USRQUOTA), bdev, -1, (CADDR_T)&F);
-
- if (F.qs_flags & XFS_QUOTA_UDQ_ENFD) {
- qflags |= QUOTAS_DENY_DISK;
- }
- else if (F.qs_flags & XFS_QUOTA_UDQ_ACCT) {
- qflags |= QUOTAS_ENABLED;
- }
-
- ret = 0;
-
- break;
-#ifdef HAVE_GROUP_QUOTA
- case SMB_GROUP_FS_QUOTA_TYPE:
- quotactl(QCMD(Q_XGETQSTAT,GRPQUOTA), bdev, -1, (CADDR_T)&F);
-
- if (F.qs_flags & XFS_QUOTA_UDQ_ENFD) {
- qflags |= QUOTAS_DENY_DISK;
- }
- else if (F.qs_flags & XFS_QUOTA_UDQ_ACCT) {
- qflags |= QUOTAS_ENABLED;
- }
-
- ret = 0;
-
- break;
-#endif /* HAVE_GROUP_QUOTA */
- default:
- errno = ENOSYS;
- return -1;
- }
-
- dp->bsize = bsize;
- dp->softlimit = (SMB_BIG_UINT)D.d_blk_softlimit;
- dp->hardlimit = (SMB_BIG_UINT)D.d_blk_hardlimit;
- dp->ihardlimit = (SMB_BIG_UINT)D.d_ino_hardlimit;
- dp->isoftlimit = (SMB_BIG_UINT)D.d_ino_softlimit;
- dp->curinodes = (SMB_BIG_UINT)D.d_icount;
- dp->curblocks = (SMB_BIG_UINT)D.d_bcount;
- dp->qflags = qflags;
-
- return ret;
-}
-
-/****************************************************************************
- Abstract out the XFS Quota Manager quota set call.
-****************************************************************************/
-static int sys_set_xfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
-{
- int ret = -1;
- uint32 qflags = 0;
- SMB_BIG_UINT bsize = (SMB_BIG_UINT)BBSIZE;
- struct fs_disk_quota D;
- struct fs_quota_stat F;
- int q_on = 0;
- int q_off = 0;
- ZERO_STRUCT(D);
- ZERO_STRUCT(F);
-
- if (!bdev||!dp)
- smb_panic("sys_set_xfs_quota: called with NULL pointer");
-
- if (bsize == dp->bsize) {
- D.d_blk_softlimit = dp->softlimit;
- D.d_blk_hardlimit = dp->hardlimit;
- D.d_ino_hardlimit = dp->ihardlimit;
- D.d_ino_softlimit = dp->isoftlimit;
- } else {
- D.d_blk_softlimit = (dp->softlimit*dp->bsize)/bsize;
- D.d_blk_hardlimit = (dp->hardlimit*dp->bsize)/bsize;
- D.d_ino_hardlimit = (dp->ihardlimit*dp->bsize)/bsize;
- D.d_ino_softlimit = (dp->isoftlimit*dp->bsize)/bsize;
- }
-
- qflags = dp->qflags;
-
- switch (qtype) {
- case SMB_USER_QUOTA_TYPE:
- D.d_fieldmask |= FS_DQ_LIMIT_MASK;
- ret = quotactl(QCMD(Q_XSETQLIM,USRQUOTA), bdev, id.uid, (CADDR_T)&D);
- break;
-#ifdef HAVE_GROUP_QUOTA
- case SMB_GROUP_QUOTA_TYPE:
- D.d_fieldmask |= FS_DQ_LIMIT_MASK;
- ret = quotactl(QCMD(Q_XSETQLIM,GRPQUOTA), bdev, id.gid, (CADDR_T)&D);
- break;
-#endif /* HAVE_GROUP_QUOTA */
- case SMB_USER_FS_QUOTA_TYPE:
- quotactl(QCMD(Q_XGETQSTAT,USRQUOTA), bdev, -1, (CADDR_T)&F);
-
- if (qflags & QUOTAS_DENY_DISK) {
- if (!(F.qs_flags & XFS_QUOTA_UDQ_ENFD))
- q_on |= XFS_QUOTA_UDQ_ENFD;
- if (!(F.qs_flags & XFS_QUOTA_UDQ_ACCT))
- q_on |= XFS_QUOTA_UDQ_ACCT;
-
- if (q_on != 0) {
- ret = quotactl(QCMD(Q_XQUOTAON,USRQUOTA),bdev, -1, (CADDR_T)&q_on);
- } else {
- ret = 0;
- }
-
- } else if (qflags & QUOTAS_ENABLED) {
- if (F.qs_flags & XFS_QUOTA_UDQ_ENFD)
- q_off |= XFS_QUOTA_UDQ_ENFD;
-
- if (q_off != 0) {
- ret = quotactl(QCMD(Q_XQUOTAOFF,USRQUOTA),bdev, -1, (CADDR_T)&q_off);
- } else {
- ret = 0;
- }
-
- if (!(F.qs_flags & XFS_QUOTA_UDQ_ACCT))
- q_on |= XFS_QUOTA_UDQ_ACCT;
-
- if (q_on != 0) {
- ret = quotactl(QCMD(Q_XQUOTAON,USRQUOTA),bdev, -1, (CADDR_T)&q_on);
- } else {
- ret = 0;
- }
- } else {
-#if 0
- /* Switch on XFS_QUOTA_UDQ_ACCT didn't work!
- * only swittching off XFS_QUOTA_UDQ_ACCT work
- */
- if (F.qs_flags & XFS_QUOTA_UDQ_ENFD)
- q_off |= XFS_QUOTA_UDQ_ENFD;
- if (F.qs_flags & XFS_QUOTA_UDQ_ACCT)
- q_off |= XFS_QUOTA_UDQ_ACCT;
-
- if (q_off !=0) {
- ret = quotactl(QCMD(Q_XQUOTAOFF,USRQUOTA),bdev, -1, (CADDR_T)&q_off);
- } else {
- ret = 0;
- }
-#else
- ret = -1;
-#endif
- }
-
- break;
-#ifdef HAVE_GROUP_QUOTA
- case SMB_GROUP_FS_QUOTA_TYPE:
- quotactl(QCMD(Q_XGETQSTAT,GRPQUOTA), bdev, -1, (CADDR_T)&F);
-
- if (qflags & QUOTAS_DENY_DISK) {
- if (!(F.qs_flags & XFS_QUOTA_UDQ_ENFD))
- q_on |= XFS_QUOTA_UDQ_ENFD;
- if (!(F.qs_flags & XFS_QUOTA_UDQ_ACCT))
- q_on |= XFS_QUOTA_UDQ_ACCT;
-
- if (q_on != 0) {
- ret = quotactl(QCMD(Q_XQUOTAON,GRPQUOTA),bdev, -1, (CADDR_T)&q_on);
- } else {
- ret = 0;
- }
-
- } else if (qflags & QUOTAS_ENABLED) {
- if (F.qs_flags & XFS_QUOTA_UDQ_ENFD)
- q_off |= XFS_QUOTA_UDQ_ENFD;
-
- if (q_off != 0) {
- ret = quotactl(QCMD(Q_XQUOTAOFF,GRPQUOTA),bdev, -1, (CADDR_T)&q_off);
- } else {
- ret = 0;
- }
-
- if (!(F.qs_flags & XFS_QUOTA_UDQ_ACCT))
- q_on |= XFS_QUOTA_UDQ_ACCT;
-
- if (q_on != 0) {
- ret = quotactl(QCMD(Q_XQUOTAON,GRPQUOTA),bdev, -1, (CADDR_T)&q_on);
- } else {
- ret = 0;
- }
- } else {
-#if 0
- /* Switch on XFS_QUOTA_UDQ_ACCT didn't work!
- * only swittching off XFS_QUOTA_UDQ_ACCT work
- */
- if (F.qs_flags & XFS_QUOTA_UDQ_ENFD)
- q_off |= XFS_QUOTA_UDQ_ENFD;
- if (F.qs_flags & XFS_QUOTA_UDQ_ACCT)
- q_off |= XFS_QUOTA_UDQ_ACCT;
-
- if (q_off !=0) {
- ret = quotactl(QCMD(Q_XQUOTAOFF,GRPQUOTA),bdev, -1, (CADDR_T)&q_off);
- } else {
- ret = 0;
- }
-#else
- ret = -1;
-#endif
- }
-
- break;
-#endif /* HAVE_GROUP_QUOTA */
- default:
- errno = ENOSYS;
- return -1;
- }
-
- return ret;
-}
-#endif /* HAVE_XFS_QUOTA */
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/*********************************************************************
Now the list of all filesystem specific quota systems we have found
**********************************************************************/
diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c
index 46f688a219..19f225e973 100644
--- a/source3/smbd/quotas.c
+++ b/source3/smbd/quotas.c
@@ -50,33 +50,16 @@ BOOL disk_quotas_vxfs(const pstring name, char *path, SMB_BIG_UINT *bsize, SMB_B
#ifdef LINUX
#include <sys/types.h>
-#include <asm/types.h>
+#include <mntent.h>
/*
* This shouldn't be neccessary - it should be /usr/include/sys/quota.h
- * Unfortunately, RH7.1 ships with a different quota system using struct mem_dqblk
- * rather than the struct dqblk defined in /usr/include/sys/quota.h.
- * This means we must include linux/quota.h to have a hope of working on
- * RH7.1 systems. And it also means this breaks if the kernel is upgraded
- * to a Linus 2.4.x (where x > the minor number shipped with RH7.1) until
- * Linus synchronises with the AC patches. Sometimes I *hate* Linux :-). JRA.
+ * So we include all the files has *should* be in the system into a large,
+ * grungy samba_linux_quoatas.h Sometimes I *hate* Linux :-). JRA.
*/
-#include <linux/quota.h>
-#ifdef HAVE_LINUX_XQM_H
-#include <linux/xqm.h>
-#else
-#ifdef HAVE_XFS_XQM_H
-#include <xfs/xqm.h>
-#define HAVE_LINUX_XQM_H
-#endif
-#endif
-
-#include <mntent.h>
-#include <linux/unistd.h>
-
-
-#define LINUX_QUOTAS_2
+#include "samba_linux_quota.h"
+#include "samba_xfs_quota.h"
typedef struct _LINUX_SMB_DISK_QUOTA {
SMB_BIG_UINT bsize;
@@ -92,22 +75,20 @@ typedef struct _LINUX_SMB_DISK_QUOTA {
Abstract out the XFS Quota Manager quota get call.
****************************************************************************/
-static int get_smb_linux_xfs_quota(char *path, uid_t euser_id, LINUX_SMB_DISK_QUOTA *dp)
+static int get_smb_linux_xfs_quota(char *path, uid_t euser_id, gid_t egrp_id, LINUX_SMB_DISK_QUOTA *dp)
{
- int ret = -1;
-#ifdef HAVE_LINUX_XQM_H
struct fs_disk_quota D;
+ int ret;
ZERO_STRUCT(D);
- ret = quotactl(QCMD(Q_XGETQUOTA,USRQUOTA), path, euser_id, (caddr_t)&D);
+ ret = quotactl(QCMD(Q_XGETQUOTA,XFS_USER_QUOTA), path, euser_id, (caddr_t)&D);
- /* As XFS has group quotas, if getting the user quota fails, try getting the group instead. */
- if (ret) {
- ret = quotactl(QCMD(Q_XGETQUOTA,GRPQUOTA), path, getegid(), (caddr_t)&D);
- if (ret)
- return ret;
- }
+ if (ret)
+ ret = quotactl(QCMD(Q_XGETQUOTA,XFS_GROUP_QUOTA), path, egrp_id, (caddr_t)&D);
+
+ if (ret)
+ return ret;
dp->bsize = (SMB_BIG_UINT)512;
dp->softlimit = (SMB_BIG_UINT)D.d_blk_softlimit;
@@ -116,7 +97,7 @@ static int get_smb_linux_xfs_quota(char *path, uid_t euser_id, LINUX_SMB_DISK_QU
dp->isoftlimit = (SMB_BIG_UINT)D.d_ino_softlimit;
dp->curinodes = (SMB_BIG_UINT)D.d_icount;
dp->curblocks = (SMB_BIG_UINT)D.d_bcount;
-#endif
+
return ret;
}
@@ -124,48 +105,90 @@ static int get_smb_linux_xfs_quota(char *path, uid_t euser_id, LINUX_SMB_DISK_QU
Abstract out the old and new Linux quota get calls.
****************************************************************************/
-static int get_smb_linux_vfs_quota(char *path, uid_t euser_id, LINUX_SMB_DISK_QUOTA *dp)
+static int get_smb_linux_v1_quota(char *path, uid_t euser_id, gid_t egrp_id, LINUX_SMB_DISK_QUOTA *dp)
{
- int ret = 0;
-#ifdef LINUX_QUOTAS_1
- struct dqblk D;
+ struct v1_kern_dqblk D;
+ int ret;
+
ZERO_STRUCT(D);
- dp->bsize = (SMB_BIG_UINT)1024;
-#else /* LINUX_QUOTAS_2 */
- struct mem_dqblk D;
+
+ ret = quotactl(QCMD(Q_V1_GETQUOTA,USRQUOTA), path, euser_id, (caddr_t)&D);
+
+ if (ret && errno != EDQUOT)
+ ret = quotactl(QCMD(Q_V1_GETQUOTA,GRPQUOTA), path, egrp_id, (caddr_t)&D);
+
+ if (ret && errno != EDQUOT)
+ return ret;
+
+ dp->bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
+ dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit;
+ dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit;
+ dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit;
+ dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit;
+ dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes;
+ dp->curblocks = (SMB_BIG_UINT)D.dqb_curblocks;
+
+ return ret;
+}
+
+static int get_smb_linux_v2_quota(char *path, uid_t euser_id, gid_t egrp_id, LINUX_SMB_DISK_QUOTA *dp)
+{
+ struct v2_kern_dqblk D;
+ int ret;
+
ZERO_STRUCT(D);
-#ifndef QUOTABLOCK_SIZE
-#define QUOTABLOCK_SIZE 1024
-#endif
+
+ ret = quotactl(QCMD(Q_V2_GETQUOTA,USRQUOTA), path, euser_id, (caddr_t)&D);
+
+ if (ret && errno != EDQUOT)
+ ret = quotactl(QCMD(Q_V2_GETQUOTA,GRPQUOTA), path, egrp_id, (caddr_t)&D);
+
+ if (ret && errno != EDQUOT)
+ return ret;
+
dp->bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
-#endif
+ dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit;
+ dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit;
+ dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit;
+ dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit;
+ dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes;
+ dp->curblocks = ((SMB_BIG_UINT)D.dqb_curspace) / dp->bsize;
+
+ return ret;
+}
+
+/****************************************************************************
+ Brand-new generic quota interface.
+****************************************************************************/
+
+static int get_smb_linux_gen_quota(char *path, uid_t euser_id, gid_t egrp_id, LINUX_SMB_DISK_QUOTA *dp)
+{
+ struct if_dqblk D;
+ int ret;
+
+ ZERO_STRUCT(D);
ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), path, euser_id, (caddr_t)&D);
- /* Linux can have group quotas, if getting the user quota fails, try getting the group instead. */
- if (ret) {
- ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), path, getegid(), (caddr_t)&D);
- if (ret)
- return ret;
- }
+ if (ret && errno != EDQUOT)
+ ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), path, egrp_id, (caddr_t)&D);
+ if (ret && errno != EDQUOT)
+ return ret;
+
+ dp->bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit;
dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit;
dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit;
dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit;
dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes;
-
-#ifdef LINUX_QUOTAS_1
- dp->curblocks = (SMB_BIG_UINT)D.dqb_curblocks;
-#else /* LINUX_QUOTAS_2 */
- dp->curblocks = ((SMB_BIG_UINT)D.dqb_curspace)/ dp->bsize;
-#endif
+ dp->curblocks = ((SMB_BIG_UINT)D.dqb_curspace) / dp->bsize;
return ret;
}
/****************************************************************************
-try to get the disk space from disk quotas (LINUX version)
+ Try to get the disk space from disk quotas (LINUX version).
****************************************************************************/
BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
@@ -178,9 +201,11 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB
SMB_DEV_T devno;
int found;
uid_t euser_id;
+ gid_t egrp_id;
euser_id = geteuid();
-
+ egrp_id = getegid();
+
/* find the block device file */
if ( sys_stat(path, &S) == -1 )
@@ -208,10 +233,18 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB
save_re_uid();
set_effective_uid(0);
- if (strcmp(mnt->mnt_type, "xfs") == 0)
- r=get_smb_linux_xfs_quota(mnt->mnt_fsname, euser_id, &D);
- else
- r=get_smb_linux_vfs_quota(mnt->mnt_fsname, euser_id, &D);
+
+ if (strcmp(mnt->mnt_type, "xfs")==0) {
+ r=get_smb_linux_xfs_quota(mnt->mnt_fsname, euser_id, egrp_id, &D);
+ } else {
+ r=get_smb_linux_gen_quota(mnt->mnt_fsname, euser_id, egrp_id, &D);
+ if (r == -1 && errno != EDQUOT) {
+ r=get_smb_linux_v2_quota(mnt->mnt_fsname, euser_id, egrp_id, &D);
+ if (r == -1 && errno != EDQUOT)
+ r=get_smb_linux_v1_quota(mnt->mnt_fsname, euser_id, egrp_id, &D);
+ }
+ }
+
restore_re_uid();
/* Use softlimit to determine disk space, except when it has been exceeded */
@@ -920,8 +953,8 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB
if ((sys_stat(path, &S)<0) || (devnm(S_IFBLK, S.st_dev, dev_disk, 256, 1)<0))
#else
if ((sys_stat(path, &S)<0) || (devnm(S_IFBLK, S.st_dev, dev_disk, 256, 0)<0))
-#endif /* ifdef HPUX */
return (False);
+#endif /* ifdef HPUX */
#endif /* !defined(__FreeBSD__) && !defined(AIX) && !defined(__OpenBSD__) */