add sysquotas_jfs2.c
authorBjoern Jacke <bj@sernet.de>
Tue, 5 Feb 2019 22:52:33 +0000 (16:52 -0600)
committerBjoern Jacke <bjacke@samba.org>
Sun, 17 Feb 2019 12:33:13 +0000 (13:33 +0100)
Signed-off-by: Bjoern Jacke <bjacke@samba.org>
Reviewed-by: Uri Simchoni <uri@samba.org>
source3/include/proto.h
source3/lib/sysquotas.c
source3/lib/sysquotas_jfs2.c [new file with mode: 0644]
source3/wscript_build

index 9d6192967ba92b4d42f93364e3f905a4d3e3b217..93d01a06be0eb90bbddbdd11102744c1d9a09092 100644 (file)
@@ -203,6 +203,9 @@ int sys_set_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qt
 int sys_get_xfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp);
 int sys_set_xfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp);
 
+int sys_get_jfs2_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp);
+int sys_set_jfs2_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp);
+
 int sys_get_nfs_quota(const char *path, const char *bdev,
                      enum SMB_QUOTA_TYPE qtype,
                      unid_t id, SMB_DISK_QUOTA *dp);
index 9b2d37b837599e7a54930a28ce2800c529166a0c..40b421c056f855734773ed916b160bcb6bc5848f 100644 (file)
@@ -227,6 +227,9 @@ static struct {
        int (*get_quota)(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp);
        int (*set_quota)(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp);
 } sys_quota_backends[] = {
+#ifdef HAVE_JFS_QUOTA_H
+       {"jfs2", sys_get_jfs2_quota,    sys_set_jfs2_quota},
+#endif
 #if defined HAVE_XFS_QUOTAS
        {"xfs", sys_get_xfs_quota,      sys_set_xfs_quota},
        {"gfs", sys_get_xfs_quota,      sys_set_xfs_quota},
diff --git a/source3/lib/sysquotas_jfs2.c b/source3/lib/sysquotas_jfs2.c
new file mode 100644 (file)
index 0000000..999b7e0
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * System QUOTA function wrappers for JFS2 on AIX
+
+ * Copyright (C) 2019 Bjoern Jacke
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#include "includes.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_QUOTA
+
+#if defined(HAVE_JFS_QUOTA_H)
+#include <jfs/quota.h>
+
+#if defined(Q_J2GETQUOTA) /* when have JFS2 */
+
+/* int quotactl(const char *path, int cmd, int id, char *addr)
+ *
+ * This is very similar to sysquotas_4B but JFS2 has different quota cmds
+ * (why?) and for some reason wants root even for querying your own quota,
+ * which seems to be an AIX bug because the docs say root is only
+ * required for querying other users' quota
+ */
+
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#ifdef HAVE_JFS_QUOTA_H
+#include <jfs/quota.h>
+#endif
+
+
+static int sys_quotactl_JFS2(const char * path, int cmd,
+               int id, quota64_t *quota)
+{
+       int ret;
+
+       /* NB: We must test GRPQUOTA here, because USRQUOTA is 0. */
+       DEBUG(10, ("%s quota for %s ID %u on %s\n",
+                   (cmd & QCMD(Q_J2GETQUOTA, 0)) ? "getting" : "setting",
+                   (cmd & QCMD(0, GRPQUOTA)) ? "group" : "user",
+                   (unsigned)id, path));
+
+       become_root();
+
+       ret = quotactl((char *) path, cmd, id, (char *) quota);
+       if (ret == -1) {
+               /* ENOTSUP means quota support is not compiled in. EINVAL
+                * means that quotas are not configured (commonly).
+                */
+               if (errno != ENOTSUP && errno != EINVAL) {
+                       DEBUG(0, ("failed to %s quota for %s ID %u on %s: %s\n",
+                                   (cmd & QCMD(Q_J2GETQUOTA, 0)) ? "get" : "set",
+                                   (cmd & QCMD(0, GRPQUOTA)) ? "group" : "user",
+                                   (unsigned)id, path, strerror(errno)));
+               }
+       }
+
+       unbecome_root();
+
+       return ret;
+}
+
+
+int sys_get_jfs2_quota(const char *path, const char *bdev,
+       enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
+{
+       int ret;
+       quota64_t quota;
+
+       ZERO_STRUCT(quota);
+
+       switch (qtype) {
+       case SMB_USER_QUOTA_TYPE:
+               /* Get quota for provided UID. */
+               ret = sys_quotactl_JFS2(path, QCMD(Q_J2GETQUOTA, USRQUOTA),
+                                       id.uid, &quota);
+               break;
+       case SMB_USER_FS_QUOTA_TYPE:
+               /* Get quota for current UID. */
+               ret = sys_quotactl_JFS2(path, QCMD(Q_J2GETQUOTA, USRQUOTA),
+                                       geteuid(), &quota);
+               break;
+       case SMB_GROUP_QUOTA_TYPE:
+               /* Get quota for provided GID. */
+               ret = sys_quotactl_JFS2(path, QCMD(Q_J2GETQUOTA, GRPQUOTA),
+                                       id.gid, &quota);
+               break;
+       case SMB_GROUP_FS_QUOTA_TYPE:
+               /* Get quota for current GID. */
+               ret = sys_quotactl_JFS2(path, QCMD(Q_J2GETQUOTA, GRPQUOTA),
+                                       getegid(), &quota);
+               break;
+       default:
+               DEBUG(0, ("cannot get unsupported quota type: %u\n",
+                           (unsigned)qtype));
+               errno = ENOSYS;
+               return -1;
+       }
+
+       if (ret == -1) {
+               return -1;
+       }
+
+       dp->softlimit = quota.bsoft;
+       dp->hardlimit = quota.bhard;
+       dp->ihardlimit = quota.ihard;
+       dp->isoftlimit = quota.isoft;
+       dp->curinodes = quota.iused;
+       dp->curblocks = quota.bused;
+
+       dp->qflags = QUOTAS_ENABLED | QUOTAS_DENY_DISK;
+       dp->qtype = qtype;
+       dp->bsize = QUOTABLOCK_SIZE;
+
+       return ret;
+}
+
+int sys_set_jfs2_quota(const char *path, const char *bdev,
+       enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
+{
+       /* JFS2 supports fancy quota limit classes for setting user quota.
+        * Unfortunately, this makes them quite unmanagable for Samba.
+        */
+       DEBUG(1, ("cannot set quota on JFS2!\n"));
+       errno = ENOSYS;
+       return -1;
+}
+
+
+#endif /* JFS2 */
+#endif /* AIX quotas */
index 6f6d74211ba422773a8e642ce64f607a8839cd25..aa8fdc175674d8caafb9d8b327072fabe424024a 100644 (file)
@@ -611,6 +611,7 @@ bld.SAMBA3_SUBSYSTEM('sysquotas',
                         lib/sysquotas_xfs.c
                         lib/sysquotas_4A.c
                         lib/sysquotas_4B.c
+                        lib/sysquotas_jfs2.c
                         lib/sysquotas_nfs.c
                      ''',
                      allow_warnings=True,