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.
25 #define DBGC_CLASS DBGC_QUOTA
27 #ifndef HAVE_SYS_QUOTAS
28 #ifdef HAVE_QUOTACTL_LINUX
29 #undef HAVE_QUOTACTL_LINUX
33 #ifdef HAVE_QUOTACTL_LINUX
35 #include "samba_linux_quota.h"
37 /****************************************************************************
38 Abstract out the v1 Linux quota get calls.
39 ****************************************************************************/
40 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)
44 struct v1_kern_dqblk D;
45 SMB_BIG_UINT bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
50 case SMB_USER_QUOTA_TYPE:
51 DEBUG(10,("sys_get_linux_v1_quota: path[%s] bdev[%s] SMB_USER_QUOTA_TYPE uid[%u]\n",
52 path, bdev, (unsigned)id.uid));
54 if ((ret = quotactl(QCMD(Q_V1_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))&&errno != EDQUOT) {
59 case SMB_GROUP_QUOTA_TYPE:
60 DEBUG(10,("sys_get_linux_v1_quota: path[%s] bdev[%s] SMB_GROUP_QUOTA_TYPE gid[%u]\n",
61 path, bdev, (unsigned)id.gid));
63 if ((ret = quotactl(QCMD(Q_V1_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))&&errno != EDQUOT) {
68 case SMB_USER_FS_QUOTA_TYPE:
69 DEBUG(10,("sys_get_linux_v1_quota: path[%s] bdev[%s] SMB_USER_FS_QUOTA_TYPE (uid[%u])\n",
70 path, bdev, (unsigned)id.uid));
72 if ((ret = quotactl(QCMD(Q_V1_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))==0) {
73 qflags |= QUOTAS_DENY_DISK;
77 case SMB_GROUP_FS_QUOTA_TYPE:
78 DEBUG(10,("sys_get_linux_v1_quota: path[%s] bdev[%s] SMB_GROUP_FS_QUOTA_TYPE (gid[%u])\n",
79 path, bdev, (unsigned)id.gid));
81 if ((ret = quotactl(QCMD(Q_V1_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))==0) {
82 qflags |= QUOTAS_DENY_DISK;
92 dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit;
93 dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit;
94 dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit;
95 dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit;
96 dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes;
97 dp->curblocks = (SMB_BIG_UINT)D.dqb_curblocks;
105 /****************************************************************************
106 Abstract out the v1 Linux quota set calls.
107 ****************************************************************************/
108 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)
112 uint32 oldqflags = 0;
113 struct v1_kern_dqblk D;
114 SMB_BIG_UINT bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
118 if (bsize == dp->bsize) {
119 D.dqb_bsoftlimit = dp->softlimit;
120 D.dqb_bhardlimit = dp->hardlimit;
121 D.dqb_ihardlimit = dp->ihardlimit;
122 D.dqb_isoftlimit = dp->isoftlimit;
124 D.dqb_bsoftlimit = (dp->softlimit*dp->bsize)/bsize;
125 D.dqb_bhardlimit = (dp->hardlimit*dp->bsize)/bsize;
126 D.dqb_ihardlimit = (dp->ihardlimit*dp->bsize)/bsize;
127 D.dqb_isoftlimit = (dp->isoftlimit*dp->bsize)/bsize;
133 case SMB_USER_QUOTA_TYPE:
134 DEBUG(10,("sys_set_linux_v1_quota: path[%s] bdev[%s] SMB_USER_QUOTA_TYPE uid[%u]\n",
135 path, bdev, (unsigned)id.uid));
137 ret = quotactl(QCMD(Q_V1_SETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D);
139 case SMB_GROUP_QUOTA_TYPE:
140 DEBUG(10,("sys_set_linux_v1_quota: path[%s] bdev[%s] SMB_GROUP_QUOTA_TYPE gid[%u]\n",
141 path, bdev, (unsigned)id.gid));
143 ret = quotactl(QCMD(Q_V1_SETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D);
145 case SMB_USER_FS_QUOTA_TYPE:
146 DEBUG(10,("sys_set_linux_v1_quota: path[%s] bdev[%s] SMB_USER_FS_QUOTA_TYPE (uid[%u])\n",
147 path, bdev, (unsigned)id.uid));
149 if ((ret = quotactl(QCMD(Q_V1_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))==0) {
150 oldqflags |= QUOTAS_DENY_DISK;
154 case SMB_GROUP_FS_QUOTA_TYPE:
155 DEBUG(10,("sys_set_linux_v1_quota: path[%s] bdev[%s] SMB_GROUP_FS_QUOTA_TYPE (gid[%u])\n",
156 path, bdev, (unsigned)id.gid));
158 if ((ret = quotactl(QCMD(Q_V1_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))==0) {
159 oldqflags |= QUOTAS_DENY_DISK;
171 /****************************************************************************
172 Abstract out the v2 Linux quota get calls.
173 ****************************************************************************/
174 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)
178 struct v2_kern_dqblk D;
179 SMB_BIG_UINT bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
184 case SMB_USER_QUOTA_TYPE:
185 DEBUG(10,("sys_get_linux_v2_quota: path[%s] bdev[%s] SMB_USER_QUOTA_TYPE uid[%u]\n",
186 path, bdev, (unsigned)id.uid));
188 if ((ret = quotactl(QCMD(Q_V2_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))&&errno != EDQUOT) {
193 case SMB_GROUP_QUOTA_TYPE:
194 DEBUG(10,("sys_get_linux_v2_quota: path[%s] bdev[%s] SMB_GROUP_QUOTA_TYPE gid[%u]\n",
195 path, bdev, (unsigned)id.gid));
197 if ((ret = quotactl(QCMD(Q_V2_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))&&errno != EDQUOT) {
202 case SMB_USER_FS_QUOTA_TYPE:
203 DEBUG(10,("sys_get_linux_v2_quota: path[%s] bdev[%s] SMB_USER_FS_QUOTA_TYPE (uid[%u])\n",
204 path, bdev, (unsigned)id.uid));
206 if ((ret = quotactl(QCMD(Q_V2_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))==0) {
207 qflags |= QUOTAS_DENY_DISK;
211 case SMB_GROUP_FS_QUOTA_TYPE:
212 DEBUG(10,("sys_get_linux_v2_quota: path[%s] bdev[%s] SMB_GROUP_FS_QUOTA_TYPE (gid[%u])\n",
213 path, bdev, (unsigned)id.gid));
215 if ((ret = quotactl(QCMD(Q_V2_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))==0) {
216 qflags |= QUOTAS_DENY_DISK;
226 dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit;
227 dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit;
228 dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit;
229 dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit;
230 dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes;
231 dp->curblocks = (SMB_BIG_UINT)D.dqb_curspace/bsize;
239 /****************************************************************************
240 Abstract out the v2 Linux quota set calls.
241 ****************************************************************************/
242 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)
246 uint32 oldqflags = 0;
247 struct v2_kern_dqblk D;
248 SMB_BIG_UINT bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
252 if (bsize == dp->bsize) {
253 D.dqb_bsoftlimit = dp->softlimit;
254 D.dqb_bhardlimit = dp->hardlimit;
255 D.dqb_ihardlimit = dp->ihardlimit;
256 D.dqb_isoftlimit = dp->isoftlimit;
258 D.dqb_bsoftlimit = (dp->softlimit*dp->bsize)/bsize;
259 D.dqb_bhardlimit = (dp->hardlimit*dp->bsize)/bsize;
260 D.dqb_ihardlimit = (dp->ihardlimit*dp->bsize)/bsize;
261 D.dqb_isoftlimit = (dp->isoftlimit*dp->bsize)/bsize;
267 case SMB_USER_QUOTA_TYPE:
268 DEBUG(10,("sys_set_linux_v2_quota: path[%s] bdev[%s] SMB_USER_QUOTA_TYPE uid[%u]\n",
269 path, bdev, (unsigned)id.uid));
271 ret = quotactl(QCMD(Q_V2_SETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D);
273 case SMB_GROUP_QUOTA_TYPE:
274 DEBUG(10,("sys_set_linux_v2_quota: path[%s] bdev[%s] SMB_GROUP_QUOTA_TYPE gid[%u]\n",
275 path, bdev, (unsigned)id.gid));
277 ret = quotactl(QCMD(Q_V2_SETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D);
279 case SMB_USER_FS_QUOTA_TYPE:
280 DEBUG(10,("sys_set_linux_v2_quota: path[%s] bdev[%s] SMB_USER_FS_QUOTA_TYPE (uid[%u])\n",
281 path, bdev, (unsigned)id.uid));
283 if ((ret = quotactl(QCMD(Q_V2_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))==0) {
284 oldqflags |= QUOTAS_DENY_DISK;
288 case SMB_GROUP_FS_QUOTA_TYPE:
289 DEBUG(10,("sys_set_linux_v2_quota: path[%s] bdev[%s] SMB_GROUP_FS_QUOTA_TYPE (gid[%u])\n",
290 path, bdev, (unsigned)id.gid));
292 if ((ret = quotactl(QCMD(Q_V2_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))==0) {
293 oldqflags |= QUOTAS_DENY_DISK;
305 /****************************************************************************
306 Abstract out the generic Linux quota get calls.
307 ****************************************************************************/
308 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)
313 SMB_BIG_UINT bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
318 case SMB_USER_QUOTA_TYPE:
319 DEBUG(10,("sys_get_linux_gen_quota: path[%s] bdev[%s] SMB_USER_QUOTA_TYPE uid[%u]\n",
320 path, bdev, (unsigned)id.uid));
322 if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))&&errno != EDQUOT) {
327 case SMB_GROUP_QUOTA_TYPE:
328 DEBUG(10,("sys_get_linux_gen_quota: path[%s] bdev[%s] SMB_GROUP_QUOTA_TYPE gid[%u]\n",
329 path, bdev, (unsigned)id.gid));
331 if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))&&errno != EDQUOT) {
336 case SMB_USER_FS_QUOTA_TYPE:
337 DEBUG(10,("sys_get_linux_gen_quota: path[%s] bdev[%s] SMB_USER_FS_QUOTA_TYPE (uid[%u])\n",
338 path, bdev, (unsigned)id.uid));
340 if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))==0) {
341 qflags |= QUOTAS_DENY_DISK;
345 case SMB_GROUP_FS_QUOTA_TYPE:
346 DEBUG(10,("sys_get_linux_gen_quota: path[%s] bdev[%s] SMB_GROUP_FS_QUOTA_TYPE (gid[%u])\n",
347 path, bdev, (unsigned)id.gid));
349 if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))==0) {
350 qflags |= QUOTAS_DENY_DISK;
360 dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit;
361 dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit;
362 dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit;
363 dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit;
364 dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes;
365 dp->curblocks = (SMB_BIG_UINT)D.dqb_curspace/bsize;
373 /****************************************************************************
374 Abstract out the gen Linux quota set calls.
375 ****************************************************************************/
376 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)
380 uint32 oldqflags = 0;
382 SMB_BIG_UINT bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
386 if (bsize == dp->bsize) {
387 D.dqb_bsoftlimit = dp->softlimit;
388 D.dqb_bhardlimit = dp->hardlimit;
389 D.dqb_ihardlimit = dp->ihardlimit;
390 D.dqb_isoftlimit = dp->isoftlimit;
392 D.dqb_bsoftlimit = (dp->softlimit*dp->bsize)/bsize;
393 D.dqb_bhardlimit = (dp->hardlimit*dp->bsize)/bsize;
394 D.dqb_ihardlimit = (dp->ihardlimit*dp->bsize)/bsize;
395 D.dqb_isoftlimit = (dp->isoftlimit*dp->bsize)/bsize;
401 case SMB_USER_QUOTA_TYPE:
402 DEBUG(10,("sys_set_linux_gen_quota: path[%s] bdev[%s] SMB_USER_QUOTA_TYPE uid[%u]\n",
403 path, bdev, (unsigned)id.uid));
405 ret = quotactl(QCMD(Q_SETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D);
407 case SMB_GROUP_QUOTA_TYPE:
408 DEBUG(10,("sys_set_linux_gen_quota: path[%s] bdev[%s] SMB_GROUP_QUOTA_TYPE gid[%u]\n",
409 path, bdev, (unsigned)id.gid));
411 ret = quotactl(QCMD(Q_SETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D);
413 case SMB_USER_FS_QUOTA_TYPE:
414 DEBUG(10,("sys_set_linux_gen_quota: path[%s] bdev[%s] SMB_USER_FS_QUOTA_TYPE (uid[%u])\n",
415 path, bdev, (unsigned)id.uid));
417 if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))==0) {
418 oldqflags |= QUOTAS_DENY_DISK;
422 case SMB_GROUP_FS_QUOTA_TYPE:
423 DEBUG(10,("sys_set_linux_gen_quota: path[%s] bdev[%s] SMB_GROUP_FS_QUOTA_TYPE (gid[%u])\n",
424 path, bdev, (unsigned)id.gid));
426 if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))==0) {
427 oldqflags |= QUOTAS_DENY_DISK;
439 /****************************************************************************
440 Abstract out the Linux quota get calls.
441 ****************************************************************************/
442 int sys_get_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
446 if (!path||!bdev||!dp)
447 smb_panic("sys_set_vfs_quota: called with NULL pointer");
453 case SMB_USER_QUOTA_TYPE:
454 case SMB_GROUP_QUOTA_TYPE:
455 if ((ret=sys_get_linux_gen_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
456 if ((ret=sys_get_linux_v2_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
457 if ((ret=sys_get_linux_v1_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
463 if ((dp->curblocks==0)&&
465 (dp->hardlimit==0)) {
466 /* the upper layer functions don't want empty quota records...*/
471 case SMB_USER_FS_QUOTA_TYPE:
474 if ((ret=sys_get_linux_gen_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
475 if ((ret=sys_get_linux_v2_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
476 ret=sys_get_linux_v1_quota(path, bdev, qtype, id, dp);
482 case SMB_GROUP_FS_QUOTA_TYPE:
485 if ((ret=sys_get_linux_gen_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
486 if ((ret=sys_get_linux_v2_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
487 ret=sys_get_linux_v1_quota(path, bdev, qtype, id, dp);
501 /****************************************************************************
502 Abstract out the Linux quota set calls.
503 ****************************************************************************/
504 int sys_set_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
507 uint32 oldqflags = 0;
509 if (!path||!bdev||!dp)
510 smb_panic("sys_set_vfs_quota: called with NULL pointer");
512 oldqflags = dp->qflags;
515 case SMB_USER_QUOTA_TYPE:
516 case SMB_GROUP_QUOTA_TYPE:
517 if ((ret=sys_set_linux_gen_quota(path, bdev, qtype, id, dp))) {
518 if ((ret=sys_set_linux_v2_quota(path, bdev, qtype, id, dp))) {
519 if ((ret=sys_set_linux_v1_quota(path, bdev, qtype, id, dp))) {
525 case SMB_USER_FS_QUOTA_TYPE:
528 if ((ret=sys_get_linux_gen_quota(path, bdev, qtype, id, dp))) {
529 if ((ret=sys_get_linux_v2_quota(path, bdev, qtype, id, dp))) {
530 ret=sys_get_linux_v1_quota(path, bdev, qtype, id, dp);
534 if (oldqflags == dp->qflags) {
540 case SMB_GROUP_FS_QUOTA_TYPE:
543 if ((ret=sys_get_linux_gen_quota(path, bdev, qtype, id, dp))) {
544 if ((ret=sys_get_linux_v2_quota(path, bdev, qtype, id, dp))) {
545 ret=sys_get_linux_v1_quota(path, bdev, qtype, id, dp);
549 if (oldqflags == dp->qflags) {
564 #else /* HAVE_QUOTACTL_LINUX */
565 void dummy_sysquotas_linux(void);
567 void dummy_sysquotas_linux(void){}
568 #endif /* HAVE_QUOTACTL_LINUX */