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, 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;
397 D.dqb_valid = QIF_LIMITS;
402 case SMB_USER_QUOTA_TYPE:
403 DEBUG(10,("sys_set_linux_gen_quota: path[%s] bdev[%s] SMB_USER_QUOTA_TYPE uid[%u]\n",
404 path, bdev, (unsigned)id.uid));
406 ret = quotactl(QCMD(Q_SETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D);
408 case SMB_GROUP_QUOTA_TYPE:
409 DEBUG(10,("sys_set_linux_gen_quota: path[%s] bdev[%s] SMB_GROUP_QUOTA_TYPE gid[%u]\n",
410 path, bdev, (unsigned)id.gid));
412 ret = quotactl(QCMD(Q_SETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D);
414 case SMB_USER_FS_QUOTA_TYPE:
415 DEBUG(10,("sys_set_linux_gen_quota: path[%s] bdev[%s] SMB_USER_FS_QUOTA_TYPE (uid[%u])\n",
416 path, bdev, (unsigned)id.uid));
418 if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))==0) {
419 oldqflags |= QUOTAS_DENY_DISK;
423 case SMB_GROUP_FS_QUOTA_TYPE:
424 DEBUG(10,("sys_set_linux_gen_quota: path[%s] bdev[%s] SMB_GROUP_FS_QUOTA_TYPE (gid[%u])\n",
425 path, bdev, (unsigned)id.gid));
427 if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))==0) {
428 oldqflags |= QUOTAS_DENY_DISK;
440 /****************************************************************************
441 Abstract out the Linux quota get calls.
442 ****************************************************************************/
443 int sys_get_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
447 if (!path||!bdev||!dp)
448 smb_panic("sys_set_vfs_quota: called with NULL pointer");
454 case SMB_USER_QUOTA_TYPE:
455 case SMB_GROUP_QUOTA_TYPE:
456 if ((ret=sys_get_linux_gen_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
457 if ((ret=sys_get_linux_v2_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
458 if ((ret=sys_get_linux_v1_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
464 if ((dp->curblocks==0)&&
466 (dp->hardlimit==0)) {
467 /* the upper layer functions don't want empty quota records...*/
472 case SMB_USER_FS_QUOTA_TYPE:
475 if ((ret=sys_get_linux_gen_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
476 if ((ret=sys_get_linux_v2_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
477 ret=sys_get_linux_v1_quota(path, bdev, qtype, id, dp);
483 case SMB_GROUP_FS_QUOTA_TYPE:
486 if ((ret=sys_get_linux_gen_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
487 if ((ret=sys_get_linux_v2_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
488 ret=sys_get_linux_v1_quota(path, bdev, qtype, id, dp);
502 /****************************************************************************
503 Abstract out the Linux quota set calls.
504 ****************************************************************************/
505 int sys_set_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
508 uint32 oldqflags = 0;
510 if (!path||!bdev||!dp)
511 smb_panic("sys_set_vfs_quota: called with NULL pointer");
513 oldqflags = dp->qflags;
516 case SMB_USER_QUOTA_TYPE:
517 case SMB_GROUP_QUOTA_TYPE:
518 if ((ret=sys_set_linux_gen_quota(path, bdev, qtype, id, dp))) {
519 if ((ret=sys_set_linux_v2_quota(path, bdev, qtype, id, dp))) {
520 if ((ret=sys_set_linux_v1_quota(path, bdev, qtype, id, dp))) {
526 case SMB_USER_FS_QUOTA_TYPE:
529 if ((ret=sys_set_linux_gen_quota(path, bdev, qtype, id, dp))) {
530 if ((ret=sys_set_linux_v2_quota(path, bdev, qtype, id, dp))) {
531 ret=sys_set_linux_v1_quota(path, bdev, qtype, id, dp);
535 if (oldqflags == dp->qflags) {
541 case SMB_GROUP_FS_QUOTA_TYPE:
544 if ((ret=sys_set_linux_gen_quota(path, bdev, qtype, id, dp))) {
545 if ((ret=sys_set_linux_v2_quota(path, bdev, qtype, id, dp))) {
546 ret=sys_set_linux_v1_quota(path, bdev, qtype, id, dp);
550 if (oldqflags == dp->qflags) {
565 #else /* HAVE_QUOTACTL_LINUX */
566 void dummy_sysquotas_linux(void);
568 void dummy_sysquotas_linux(void){}
569 #endif /* HAVE_QUOTACTL_LINUX */