2 * Unix SMB/CIFS implementation.
3 * System QUOTA function wrappers for QUOTACTL_4B
5 * Copyright (C) 2011 James Peach.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #define DBGC_CLASS DBGC_QUOTA
27 #ifndef HAVE_SYS_QUOTAS
28 #undef HAVE_QUOTACTL_4B
31 #ifdef HAVE_QUOTACTL_4B
32 /* int quotactl(const char *path, int cmd, int id, char *addr)
34 * This is used by many (all?) BSD-derived systems. This implementation has
35 * been developed and tested on Darwin, but may also work on other BSD systems.
38 #ifdef HAVE_SYS_TYPES_H
39 #include <sys/types.h>
42 #ifdef HAVE_SYS_QUOTA_H
43 #include <sys/quota.h>
46 #ifdef HAVE_UFS_UFS_QUOTA_H
47 #include <ufs/ufs/quota.h>
50 #ifdef HAVE_JFS_QUOTA_H
51 #include <jfs/quota.h>
55 /* WorkARound broken HFS access checks in hfs_quotactl. Darwin only(?) */
56 #define HFS_QUOTACTL_WAR 1
59 #ifdef HAVE_STRUCT_DQBLK_DQB_CURBYTES
60 /* we handle the byte vs. block count dynamically via QUOTABLOCK_SIZE 1 */
61 #define dqb_curblocks dqb_curbytes
64 static void xlate_qblk_to_smb(const struct dqblk
* const qblk
,
69 DEBUG(10, ("unix softlimit=%u hardlimit=%u curblock=%u\n",
70 (unsigned)qblk
->dqb_bsoftlimit
, (unsigned)qblk
->dqb_bhardlimit
,
71 (unsigned)qblk
->dqb_curblocks
));
73 DEBUGADD(10, ("unix softinodes=%u hardinodes=%u curinodes=%u\n",
74 (unsigned)qblk
->dqb_isoftlimit
, (unsigned)qblk
->dqb_ihardlimit
,
75 (unsigned)qblk
->dqb_curinodes
));
77 dp
->bsize
= QUOTABLOCK_SIZE
;
79 dp
->softlimit
= qblk
->dqb_bsoftlimit
;
80 dp
->hardlimit
= qblk
->dqb_bhardlimit
;
81 dp
->curblocks
= qblk
->dqb_curblocks
;
82 /* our Darwin quotas used to never return 0byte usage but this is probably not needed,
83 * let's comment this out for now
84 #ifdef HAVE_STRUCT_DQBLK_DQB_CURBYTES
85 if (dp->curblocks == 0) {
91 dp
->ihardlimit
= qblk
->dqb_ihardlimit
;
92 dp
->isoftlimit
= qblk
->dqb_isoftlimit
;
93 dp
->curinodes
= qblk
->dqb_curinodes
;
95 dp
->qflags
= QUOTAS_ENABLED
| QUOTAS_DENY_DISK
;
97 DEBUG(10, ("softlimit=%u hardlimit=%u curblock=%u\n",
98 (unsigned)dp
->softlimit
, (unsigned)dp
->hardlimit
,
99 (unsigned)dp
->curblocks
));
101 DEBUGADD(10, ("softinodes=%u hardinodes=%u curinodes=%u\n",
102 (unsigned)dp
->isoftlimit
, (unsigned)dp
->ihardlimit
,
103 (unsigned)dp
->curinodes
));
107 static void xlate_smb_to_qblk(const SMB_DISK_QUOTA
* const dp
,
112 if (dp
->bsize
== QUOTABLOCK_SIZE
) {
113 qblk
->dqb_bsoftlimit
= dp
->softlimit
;
114 qblk
->dqb_bhardlimit
= dp
->hardlimit
;
116 qblk
->dqb_bsoftlimit
= dp
->softlimit
* dp
->bsize
/ QUOTABLOCK_SIZE
;
117 qblk
->dqb_bhardlimit
= dp
->hardlimit
* dp
->bsize
/ QUOTABLOCK_SIZE
;
119 qblk
->dqb_ihardlimit
= dp
->ihardlimit
;
120 qblk
->dqb_isoftlimit
= dp
->isoftlimit
;
123 static int sys_quotactl_4B(const char * path
, int cmd
,
124 int id
, struct dqblk
*qblk
)
128 /* NB: We must test GRPQUOTA here, because USRQUOTA is 0. */
129 DEBUG(10, ("%s quota for %s ID %u on %s\n",
130 (cmd
& QCMD(Q_GETQUOTA
, 0)) ? "getting" : "setting",
131 (cmd
& QCMD(0, GRPQUOTA
)) ? "group" : "user",
132 (unsigned)id
, path
));
134 #ifdef HFS_QUOTACTL_WAR
136 #endif /* HFS_QUOTACTL_WAR */
138 ret
= quotactl(path
, cmd
, id
, qblk
);
140 /* ENOTSUP means quota support is not compiled in. EINVAL
141 * means that quotas are not configured (commonly).
143 if (errno
!= ENOTSUP
&& errno
!= EINVAL
) {
144 DEBUG(5, ("failed to %s quota for %s ID %u on %s: %s\n",
145 (cmd
& QCMD(Q_GETQUOTA
, 0)) ? "get" : "set",
146 (cmd
& QCMD(0, GRPQUOTA
)) ? "group" : "user",
147 (unsigned)id
, path
, strerror(errno
)));
150 #ifdef HFS_QUOTACTL_WAR
152 #endif /* HFS_QUOTACTL_WAR */
158 #ifdef HFS_QUOTACTL_WAR
160 #endif /* HFS_QUOTACTL_WAR */
165 int sys_get_vfs_quota(const char *path
, const char *bdev
,
166 enum SMB_QUOTA_TYPE qtype
, unid_t id
, SMB_DISK_QUOTA
*dp
)
174 case SMB_USER_QUOTA_TYPE
:
175 /* Get quota for provided UID. */
176 ret
= sys_quotactl_4B(path
, QCMD(Q_GETQUOTA
, USRQUOTA
),
179 case SMB_USER_FS_QUOTA_TYPE
:
180 /* Get quota for current UID. */
181 ret
= sys_quotactl_4B(path
, QCMD(Q_GETQUOTA
, USRQUOTA
),
184 case SMB_GROUP_QUOTA_TYPE
:
185 /* Get quota for provided GID. */
186 ret
= sys_quotactl_4B(path
, QCMD(Q_GETQUOTA
, GRPQUOTA
),
189 case SMB_GROUP_FS_QUOTA_TYPE
:
190 /* Get quota for current GID. */
191 ret
= sys_quotactl_4B(path
, QCMD(Q_GETQUOTA
, GRPQUOTA
),
195 DEBUG(0, ("cannot get unsupported quota type: %u\n",
205 xlate_qblk_to_smb(&qblk
, dp
);
211 int sys_set_vfs_quota(const char *path
, const char *bdev
,
212 enum SMB_QUOTA_TYPE qtype
, unid_t id
, SMB_DISK_QUOTA
*dp
)
216 xlate_smb_to_qblk(dp
, &qblk
);
219 case SMB_USER_QUOTA_TYPE
:
220 /* Set quota for provided UID. */
221 return sys_quotactl_4B(path
, QCMD(Q_SETQUOTA
, USRQUOTA
),
223 case SMB_USER_FS_QUOTA_TYPE
:
224 /* Set quota for current UID. */
225 return sys_quotactl_4B(path
, QCMD(Q_SETQUOTA
, USRQUOTA
),
227 case SMB_GROUP_QUOTA_TYPE
:
228 /* Set quota for provided GID. */
229 return sys_quotactl_4B(path
, QCMD(Q_SETQUOTA
, GRPQUOTA
),
231 case SMB_GROUP_FS_QUOTA_TYPE
:
232 /* Set quota for current GID. */
233 return sys_quotactl_4B(path
, QCMD(Q_SETQUOTA
, GRPQUOTA
),
236 DEBUG(0, ("cannot set unsupported quota type: %u\n",
243 #endif /* HAVE_QUOTACTL_4B */