2 Unix SMB/CIFS implementation.
3 System QUOTA function wrappers for LINUX
4 Copyright (C) Stefan (metze) Metzmacher 2003
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #ifdef HAVE_QUOTACTL_LINUX
26 #include "samba_linux_quota.h"
28 /****************************************************************************
29 Abstract out the v1 Linux quota get calls.
30 ****************************************************************************/
31 static int sys_get_linux_v1_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
35 struct v1_kern_dqblk D;
36 SMB_BIG_UINT bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
41 case SMB_USER_QUOTA_TYPE:
42 if ((ret = quotactl(QCMD(Q_V1_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))&&errno != EDQUOT) {
47 case SMB_GROUP_QUOTA_TYPE:
48 if ((ret = quotactl(QCMD(Q_V1_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))&&errno != EDQUOT) {
53 case SMB_USER_FS_QUOTA_TYPE:
54 if ((ret = quotactl(QCMD(Q_V1_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))==0) {
55 qflags |= QUOTAS_DENY_DISK;
59 case SMB_GROUP_FS_QUOTA_TYPE:
60 if ((ret = quotactl(QCMD(Q_V1_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))==0) {
61 qflags |= QUOTAS_DENY_DISK;
71 dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit;
72 dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit;
73 dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit;
74 dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit;
75 dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes;
76 dp->curblocks = (SMB_BIG_UINT)D.dqb_curblocks;
84 /****************************************************************************
85 Abstract out the v1 Linux quota set calls.
86 ****************************************************************************/
87 static int sys_set_linux_v1_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
92 struct v1_kern_dqblk D;
93 SMB_BIG_UINT bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
97 if (bsize == dp->bsize) {
98 D.dqb_bsoftlimit = dp->softlimit;
99 D.dqb_bhardlimit = dp->hardlimit;
100 D.dqb_ihardlimit = dp->ihardlimit;
101 D.dqb_isoftlimit = dp->isoftlimit;
103 D.dqb_bsoftlimit = (dp->softlimit*dp->bsize)/bsize;
104 D.dqb_bhardlimit = (dp->hardlimit*dp->bsize)/bsize;
105 D.dqb_ihardlimit = (dp->ihardlimit*dp->bsize)/bsize;
106 D.dqb_isoftlimit = (dp->isoftlimit*dp->bsize)/bsize;
112 case SMB_USER_QUOTA_TYPE:
113 ret = quotactl(QCMD(Q_V1_SETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D);
115 case SMB_GROUP_QUOTA_TYPE:
116 ret = quotactl(QCMD(Q_V1_SETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D);
118 case SMB_USER_FS_QUOTA_TYPE:
119 if ((ret = quotactl(QCMD(Q_V1_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))==0) {
120 oldqflags |= QUOTAS_DENY_DISK;
124 case SMB_GROUP_FS_QUOTA_TYPE:
125 if ((ret = quotactl(QCMD(Q_V1_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))==0) {
126 oldqflags |= QUOTAS_DENY_DISK;
138 /****************************************************************************
139 Abstract out the v2 Linux quota get calls.
140 ****************************************************************************/
141 static int sys_get_linux_v2_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
145 struct v2_kern_dqblk D;
146 SMB_BIG_UINT bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
151 case SMB_USER_QUOTA_TYPE:
152 if ((ret = quotactl(QCMD(Q_V2_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))&&errno != EDQUOT) {
157 case SMB_GROUP_QUOTA_TYPE:
158 if ((ret = quotactl(QCMD(Q_V2_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))&&errno != EDQUOT) {
163 case SMB_USER_FS_QUOTA_TYPE:
164 if ((ret = quotactl(QCMD(Q_V2_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))==0) {
165 qflags |= QUOTAS_DENY_DISK;
169 case SMB_GROUP_FS_QUOTA_TYPE:
170 if ((ret = quotactl(QCMD(Q_V2_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))==0) {
171 qflags |= QUOTAS_DENY_DISK;
181 dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit;
182 dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit;
183 dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit;
184 dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit;
185 dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes;
186 dp->curblocks = (SMB_BIG_UINT)D.dqb_curspace/bsize;
194 /****************************************************************************
195 Abstract out the v2 Linux quota set calls.
196 ****************************************************************************/
197 static int sys_set_linux_v2_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
201 uint32 oldqflags = 0;
202 struct v2_kern_dqblk D;
203 SMB_BIG_UINT bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
207 if (bsize == dp->bsize) {
208 D.dqb_bsoftlimit = dp->softlimit;
209 D.dqb_bhardlimit = dp->hardlimit;
210 D.dqb_ihardlimit = dp->ihardlimit;
211 D.dqb_isoftlimit = dp->isoftlimit;
213 D.dqb_bsoftlimit = (dp->softlimit*dp->bsize)/bsize;
214 D.dqb_bhardlimit = (dp->hardlimit*dp->bsize)/bsize;
215 D.dqb_ihardlimit = (dp->ihardlimit*dp->bsize)/bsize;
216 D.dqb_isoftlimit = (dp->isoftlimit*dp->bsize)/bsize;
222 case SMB_USER_QUOTA_TYPE:
223 ret = quotactl(QCMD(Q_V2_SETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D);
225 case SMB_GROUP_QUOTA_TYPE:
226 ret = quotactl(QCMD(Q_V2_SETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D);
228 case SMB_USER_FS_QUOTA_TYPE:
229 if ((ret = quotactl(QCMD(Q_V2_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))==0) {
230 oldqflags |= QUOTAS_DENY_DISK;
234 case SMB_GROUP_FS_QUOTA_TYPE:
235 if ((ret = quotactl(QCMD(Q_V2_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))==0) {
236 oldqflags |= QUOTAS_DENY_DISK;
248 /****************************************************************************
249 Abstract out the generic Linux quota get calls.
250 ****************************************************************************/
251 static int sys_get_linux_gen_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
256 SMB_BIG_UINT bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
261 case SMB_USER_QUOTA_TYPE:
262 if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))&&errno != EDQUOT) {
267 case SMB_GROUP_QUOTA_TYPE:
268 if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))&&errno != EDQUOT) {
273 case SMB_USER_FS_QUOTA_TYPE:
274 if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))==0) {
275 qflags |= QUOTAS_DENY_DISK;
279 case SMB_GROUP_FS_QUOTA_TYPE:
280 if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))==0) {
281 qflags |= QUOTAS_DENY_DISK;
291 dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit;
292 dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit;
293 dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit;
294 dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit;
295 dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes;
296 dp->curblocks = (SMB_BIG_UINT)D.dqb_curspace/bsize;
304 /****************************************************************************
305 Abstract out the gen Linux quota set calls.
306 ****************************************************************************/
307 static int sys_set_linux_gen_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
311 uint32 oldqflags = 0;
313 SMB_BIG_UINT bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
317 if (bsize == dp->bsize) {
318 D.dqb_bsoftlimit = dp->softlimit;
319 D.dqb_bhardlimit = dp->hardlimit;
320 D.dqb_ihardlimit = dp->ihardlimit;
321 D.dqb_isoftlimit = dp->isoftlimit;
323 D.dqb_bsoftlimit = (dp->softlimit*dp->bsize)/bsize;
324 D.dqb_bhardlimit = (dp->hardlimit*dp->bsize)/bsize;
325 D.dqb_ihardlimit = (dp->ihardlimit*dp->bsize)/bsize;
326 D.dqb_isoftlimit = (dp->isoftlimit*dp->bsize)/bsize;
332 case SMB_USER_QUOTA_TYPE:
333 ret = quotactl(QCMD(Q_SETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D);
335 case SMB_GROUP_QUOTA_TYPE:
336 ret = quotactl(QCMD(Q_SETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D);
338 case SMB_USER_FS_QUOTA_TYPE:
339 if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))==0) {
340 oldqflags |= QUOTAS_DENY_DISK;
344 case SMB_GROUP_FS_QUOTA_TYPE:
345 if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))==0) {
346 oldqflags |= QUOTAS_DENY_DISK;
358 /****************************************************************************
359 Abstract out the Linux quota get calls.
360 ****************************************************************************/
361 int sys_get_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
365 if (!path||!bdev||!dp)
366 smb_panic("sys_set_vfs_quota: called with NULL pointer");
372 case SMB_USER_QUOTA_TYPE:
373 case SMB_GROUP_QUOTA_TYPE:
374 if ((ret=sys_get_linux_gen_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
375 if ((ret=sys_get_linux_v2_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
376 if ((ret=sys_get_linux_v1_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
382 if ((dp->curblocks==0)&&
384 (dp->hardlimit==0)) {
385 /* the upper layer functions don't want empty quota records...*/
390 case SMB_USER_FS_QUOTA_TYPE:
393 if ((ret=sys_get_linux_gen_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
394 if ((ret=sys_get_linux_v2_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
395 ret=sys_get_linux_v1_quota(path, bdev, qtype, id, dp);
401 case SMB_GROUP_FS_QUOTA_TYPE:
404 if ((ret=sys_get_linux_gen_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
405 if ((ret=sys_get_linux_v2_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
406 ret=sys_get_linux_v1_quota(path, bdev, qtype, id, dp);
420 /****************************************************************************
421 Abstract out the Linux quota set calls.
422 ****************************************************************************/
423 int sys_set_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
426 uint32 oldqflags = 0;
428 if (!path||!bdev||!dp)
429 smb_panic("sys_set_vfs_quota: called with NULL pointer");
431 oldqflags = dp->qflags;
434 case SMB_USER_QUOTA_TYPE:
435 case SMB_GROUP_QUOTA_TYPE:
436 if ((ret=sys_set_linux_gen_quota(path, bdev, qtype, id, dp))) {
437 if ((ret=sys_set_linux_v2_quota(path, bdev, qtype, id, dp))) {
438 if ((ret=sys_set_linux_v1_quota(path, bdev, qtype, id, dp))) {
444 case SMB_USER_FS_QUOTA_TYPE:
447 if ((ret=sys_get_linux_gen_quota(path, bdev, qtype, id, dp))) {
448 if ((ret=sys_get_linux_v2_quota(path, bdev, qtype, id, dp))) {
449 ret=sys_get_linux_v1_quota(path, bdev, qtype, id, dp);
453 if (oldqflags == dp->qflags) {
459 case SMB_GROUP_FS_QUOTA_TYPE:
462 if ((ret=sys_get_linux_gen_quota(path, bdev, qtype, id, dp))) {
463 if ((ret=sys_get_linux_v2_quota(path, bdev, qtype, id, dp))) {
464 ret=sys_get_linux_v1_quota(path, bdev, qtype, id, dp);
468 if (oldqflags == dp->qflags) {
483 #else /* HAVE_QUOTACTL_LINUX */
484 void dummy_sysquotas_linux(void){}
485 #endif /* HAVE_QUOTACTL_LINUX */