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 3 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, see <http://www.gnu.org/licenses/>.
24 #define DBGC_CLASS DBGC_QUOTA
26 #ifndef HAVE_SYS_QUOTAS
27 #ifdef HAVE_QUOTACTL_LINUX
28 #undef HAVE_QUOTACTL_LINUX
32 #ifdef HAVE_QUOTACTL_LINUX
34 #include "samba_linux_quota.h"
36 /****************************************************************************
37 Abstract out the v1 Linux quota get calls.
38 ****************************************************************************/
39 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)
43 struct v1_kern_dqblk D;
44 uint64_t bsize = (uint64_t)QUOTABLOCK_SIZE;
49 case SMB_USER_QUOTA_TYPE:
50 DEBUG(10,("sys_get_linux_v1_quota: path[%s] bdev[%s] SMB_USER_QUOTA_TYPE uid[%u]\n",
51 path, bdev, (unsigned)id.uid));
53 if ((ret = quotactl(QCMD(Q_V1_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))&&errno != EDQUOT) {
58 case SMB_GROUP_QUOTA_TYPE:
59 DEBUG(10,("sys_get_linux_v1_quota: path[%s] bdev[%s] SMB_GROUP_QUOTA_TYPE gid[%u]\n",
60 path, bdev, (unsigned)id.gid));
62 if ((ret = quotactl(QCMD(Q_V1_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))&&errno != EDQUOT) {
67 case SMB_USER_FS_QUOTA_TYPE:
68 DEBUG(10,("sys_get_linux_v1_quota: path[%s] bdev[%s] SMB_USER_FS_QUOTA_TYPE (uid[%u])\n",
69 path, bdev, (unsigned)id.uid));
71 if ((ret = quotactl(QCMD(Q_V1_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))==0) {
72 qflags |= QUOTAS_DENY_DISK;
76 case SMB_GROUP_FS_QUOTA_TYPE:
77 DEBUG(10,("sys_get_linux_v1_quota: path[%s] bdev[%s] SMB_GROUP_FS_QUOTA_TYPE (gid[%u])\n",
78 path, bdev, (unsigned)id.gid));
80 if ((ret = quotactl(QCMD(Q_V1_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))==0) {
81 qflags |= QUOTAS_DENY_DISK;
91 dp->softlimit = (uint64_t)D.dqb_bsoftlimit;
92 dp->hardlimit = (uint64_t)D.dqb_bhardlimit;
93 dp->ihardlimit = (uint64_t)D.dqb_ihardlimit;
94 dp->isoftlimit = (uint64_t)D.dqb_isoftlimit;
95 dp->curinodes = (uint64_t)D.dqb_curinodes;
96 dp->curblocks = (uint64_t)D.dqb_curblocks;
104 /****************************************************************************
105 Abstract out the v1 Linux quota set calls.
106 ****************************************************************************/
107 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)
111 uint32 oldqflags = 0;
112 struct v1_kern_dqblk D;
113 uint64_t bsize = (uint64_t)QUOTABLOCK_SIZE;
117 if (bsize == dp->bsize) {
118 D.dqb_bsoftlimit = dp->softlimit;
119 D.dqb_bhardlimit = dp->hardlimit;
120 D.dqb_ihardlimit = dp->ihardlimit;
121 D.dqb_isoftlimit = dp->isoftlimit;
123 D.dqb_bsoftlimit = (dp->softlimit*dp->bsize)/bsize;
124 D.dqb_bhardlimit = (dp->hardlimit*dp->bsize)/bsize;
125 D.dqb_ihardlimit = (dp->ihardlimit*dp->bsize)/bsize;
126 D.dqb_isoftlimit = (dp->isoftlimit*dp->bsize)/bsize;
132 case SMB_USER_QUOTA_TYPE:
133 DEBUG(10,("sys_set_linux_v1_quota: path[%s] bdev[%s] SMB_USER_QUOTA_TYPE uid[%u]\n",
134 path, bdev, (unsigned)id.uid));
136 ret = quotactl(QCMD(Q_V1_SETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D);
138 case SMB_GROUP_QUOTA_TYPE:
139 DEBUG(10,("sys_set_linux_v1_quota: path[%s] bdev[%s] SMB_GROUP_QUOTA_TYPE gid[%u]\n",
140 path, bdev, (unsigned)id.gid));
142 ret = quotactl(QCMD(Q_V1_SETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D);
144 case SMB_USER_FS_QUOTA_TYPE:
145 DEBUG(10,("sys_set_linux_v1_quota: path[%s] bdev[%s] SMB_USER_FS_QUOTA_TYPE (uid[%u])\n",
146 path, bdev, (unsigned)id.uid));
148 if ((ret = quotactl(QCMD(Q_V1_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))==0) {
149 oldqflags |= QUOTAS_DENY_DISK;
153 case SMB_GROUP_FS_QUOTA_TYPE:
154 DEBUG(10,("sys_set_linux_v1_quota: path[%s] bdev[%s] SMB_GROUP_FS_QUOTA_TYPE (gid[%u])\n",
155 path, bdev, (unsigned)id.gid));
157 if ((ret = quotactl(QCMD(Q_V1_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))==0) {
158 oldqflags |= QUOTAS_DENY_DISK;
170 /****************************************************************************
171 Abstract out the v2 Linux quota get calls.
172 ****************************************************************************/
173 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)
177 struct v2_kern_dqblk D;
178 uint64_t bsize = (uint64_t)QUOTABLOCK_SIZE;
183 case SMB_USER_QUOTA_TYPE:
184 DEBUG(10,("sys_get_linux_v2_quota: path[%s] bdev[%s] SMB_USER_QUOTA_TYPE uid[%u]\n",
185 path, bdev, (unsigned)id.uid));
187 if ((ret = quotactl(QCMD(Q_V2_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))&&errno != EDQUOT) {
192 case SMB_GROUP_QUOTA_TYPE:
193 DEBUG(10,("sys_get_linux_v2_quota: path[%s] bdev[%s] SMB_GROUP_QUOTA_TYPE gid[%u]\n",
194 path, bdev, (unsigned)id.gid));
196 if ((ret = quotactl(QCMD(Q_V2_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))&&errno != EDQUOT) {
201 case SMB_USER_FS_QUOTA_TYPE:
202 DEBUG(10,("sys_get_linux_v2_quota: path[%s] bdev[%s] SMB_USER_FS_QUOTA_TYPE (uid[%u])\n",
203 path, bdev, (unsigned)id.uid));
205 if ((ret = quotactl(QCMD(Q_V2_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))==0) {
206 qflags |= QUOTAS_DENY_DISK;
210 case SMB_GROUP_FS_QUOTA_TYPE:
211 DEBUG(10,("sys_get_linux_v2_quota: path[%s] bdev[%s] SMB_GROUP_FS_QUOTA_TYPE (gid[%u])\n",
212 path, bdev, (unsigned)id.gid));
214 if ((ret = quotactl(QCMD(Q_V2_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))==0) {
215 qflags |= QUOTAS_DENY_DISK;
225 dp->softlimit = (uint64_t)D.dqb_bsoftlimit;
226 dp->hardlimit = (uint64_t)D.dqb_bhardlimit;
227 dp->ihardlimit = (uint64_t)D.dqb_ihardlimit;
228 dp->isoftlimit = (uint64_t)D.dqb_isoftlimit;
229 dp->curinodes = (uint64_t)D.dqb_curinodes;
230 dp->curblocks = (uint64_t)D.dqb_curspace/bsize;
238 /****************************************************************************
239 Abstract out the v2 Linux quota set calls.
240 ****************************************************************************/
241 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)
245 uint32 oldqflags = 0;
246 struct v2_kern_dqblk D;
247 uint64_t bsize = (uint64_t)QUOTABLOCK_SIZE;
251 if (bsize == dp->bsize) {
252 D.dqb_bsoftlimit = dp->softlimit;
253 D.dqb_bhardlimit = dp->hardlimit;
254 D.dqb_ihardlimit = dp->ihardlimit;
255 D.dqb_isoftlimit = dp->isoftlimit;
257 D.dqb_bsoftlimit = (dp->softlimit*dp->bsize)/bsize;
258 D.dqb_bhardlimit = (dp->hardlimit*dp->bsize)/bsize;
259 D.dqb_ihardlimit = (dp->ihardlimit*dp->bsize)/bsize;
260 D.dqb_isoftlimit = (dp->isoftlimit*dp->bsize)/bsize;
266 case SMB_USER_QUOTA_TYPE:
267 DEBUG(10,("sys_set_linux_v2_quota: path[%s] bdev[%s] SMB_USER_QUOTA_TYPE uid[%u]\n",
268 path, bdev, (unsigned)id.uid));
270 ret = quotactl(QCMD(Q_V2_SETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D);
272 case SMB_GROUP_QUOTA_TYPE:
273 DEBUG(10,("sys_set_linux_v2_quota: path[%s] bdev[%s] SMB_GROUP_QUOTA_TYPE gid[%u]\n",
274 path, bdev, (unsigned)id.gid));
276 ret = quotactl(QCMD(Q_V2_SETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D);
278 case SMB_USER_FS_QUOTA_TYPE:
279 DEBUG(10,("sys_set_linux_v2_quota: path[%s] bdev[%s] SMB_USER_FS_QUOTA_TYPE (uid[%u])\n",
280 path, bdev, (unsigned)id.uid));
282 if ((ret = quotactl(QCMD(Q_V2_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))==0) {
283 oldqflags |= QUOTAS_DENY_DISK;
287 case SMB_GROUP_FS_QUOTA_TYPE:
288 DEBUG(10,("sys_set_linux_v2_quota: path[%s] bdev[%s] SMB_GROUP_FS_QUOTA_TYPE (gid[%u])\n",
289 path, bdev, (unsigned)id.gid));
291 if ((ret = quotactl(QCMD(Q_V2_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))==0) {
292 oldqflags |= QUOTAS_DENY_DISK;
304 /****************************************************************************
305 Abstract out the generic Linux quota get calls.
306 ****************************************************************************/
307 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)
312 uint64_t bsize = (uint64_t)QUOTABLOCK_SIZE;
317 case SMB_USER_QUOTA_TYPE:
318 DEBUG(10,("sys_get_linux_gen_quota: path[%s] bdev[%s] SMB_USER_QUOTA_TYPE uid[%u]\n",
319 path, bdev, (unsigned)id.uid));
321 if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))&&errno != EDQUOT) {
326 case SMB_GROUP_QUOTA_TYPE:
327 DEBUG(10,("sys_get_linux_gen_quota: path[%s] bdev[%s] SMB_GROUP_QUOTA_TYPE gid[%u]\n",
328 path, bdev, (unsigned)id.gid));
330 if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))&&errno != EDQUOT) {
335 case SMB_USER_FS_QUOTA_TYPE:
336 DEBUG(10,("sys_get_linux_gen_quota: path[%s] bdev[%s] SMB_USER_FS_QUOTA_TYPE (uid[%u])\n",
337 path, bdev, (unsigned)id.uid));
339 if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))==0) {
340 qflags |= QUOTAS_DENY_DISK;
344 case SMB_GROUP_FS_QUOTA_TYPE:
345 DEBUG(10,("sys_get_linux_gen_quota: path[%s] bdev[%s] SMB_GROUP_FS_QUOTA_TYPE (gid[%u])\n",
346 path, bdev, (unsigned)id.gid));
348 if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))==0) {
349 qflags |= QUOTAS_DENY_DISK;
359 dp->softlimit = (uint64_t)D.dqb_bsoftlimit;
360 dp->hardlimit = (uint64_t)D.dqb_bhardlimit;
361 dp->ihardlimit = (uint64_t)D.dqb_ihardlimit;
362 dp->isoftlimit = (uint64_t)D.dqb_isoftlimit;
363 dp->curinodes = (uint64_t)D.dqb_curinodes;
364 dp->curblocks = (uint64_t)D.dqb_curspace/bsize;
372 /****************************************************************************
373 Abstract out the gen Linux quota set calls.
374 ****************************************************************************/
375 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)
379 uint32 oldqflags = 0;
381 uint64_t bsize = (uint64_t)QUOTABLOCK_SIZE;
385 if (bsize == dp->bsize) {
386 D.dqb_bsoftlimit = dp->softlimit;
387 D.dqb_bhardlimit = dp->hardlimit;
388 D.dqb_ihardlimit = dp->ihardlimit;
389 D.dqb_isoftlimit = dp->isoftlimit;
391 D.dqb_bsoftlimit = (dp->softlimit*dp->bsize)/bsize;
392 D.dqb_bhardlimit = (dp->hardlimit*dp->bsize)/bsize;
393 D.dqb_ihardlimit = (dp->ihardlimit*dp->bsize)/bsize;
394 D.dqb_isoftlimit = (dp->isoftlimit*dp->bsize)/bsize;
396 D.dqb_valid = QIF_LIMITS;
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_set_linux_gen_quota(path, bdev, qtype, id, dp))) {
529 if ((ret=sys_set_linux_v2_quota(path, bdev, qtype, id, dp))) {
530 ret=sys_set_linux_v1_quota(path, bdev, qtype, id, dp);
534 if (oldqflags == dp->qflags) {
540 case SMB_GROUP_FS_QUOTA_TYPE:
543 if ((ret=sys_set_linux_gen_quota(path, bdev, qtype, id, dp))) {
544 if ((ret=sys_set_linux_v2_quota(path, bdev, qtype, id, dp))) {
545 ret=sys_set_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 */