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 #ifdef HAVE_QUOTACTL_LINUX
29 #include "samba_linux_quota.h"
31 /****************************************************************************
32 Abstract out the v1 Linux quota get calls.
33 ****************************************************************************/
34 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
)
38 struct v1_kern_dqblk D
;
39 SMB_BIG_UINT bsize
= (SMB_BIG_UINT
)QUOTABLOCK_SIZE
;
44 case SMB_USER_QUOTA_TYPE
:
45 DEBUG(10,("sys_get_linux_v1_quota: path[%s] bdev[%s] SMB_USER_QUOTA_TYPE uid[%u]\n",
46 path
, bdev
, (unsigned)id
.uid
));
48 if ((ret
= quotactl(QCMD(Q_V1_GETQUOTA
,USRQUOTA
), bdev
, id
.uid
, (caddr_t
)&D
))&&errno
!= EDQUOT
) {
53 case SMB_GROUP_QUOTA_TYPE
:
54 DEBUG(10,("sys_get_linux_v1_quota: path[%s] bdev[%s] SMB_GROUP_QUOTA_TYPE gid[%u]\n",
55 path
, bdev
, (unsigned)id
.gid
));
57 if ((ret
= quotactl(QCMD(Q_V1_GETQUOTA
,GRPQUOTA
), bdev
, id
.gid
, (caddr_t
)&D
))&&errno
!= EDQUOT
) {
62 case SMB_USER_FS_QUOTA_TYPE
:
63 DEBUG(10,("sys_get_linux_v1_quota: path[%s] bdev[%s] SMB_USER_FS_QUOTA_TYPE (uid[%u])\n",
64 path
, bdev
, (unsigned)id
.uid
));
66 if ((ret
= quotactl(QCMD(Q_V1_GETQUOTA
,USRQUOTA
), bdev
, id
.uid
, (caddr_t
)&D
))==0) {
67 qflags
|= QUOTAS_DENY_DISK
;
71 case SMB_GROUP_FS_QUOTA_TYPE
:
72 DEBUG(10,("sys_get_linux_v1_quota: path[%s] bdev[%s] SMB_GROUP_FS_QUOTA_TYPE (gid[%u])\n",
73 path
, bdev
, (unsigned)id
.gid
));
75 if ((ret
= quotactl(QCMD(Q_V1_GETQUOTA
,GRPQUOTA
), bdev
, id
.gid
, (caddr_t
)&D
))==0) {
76 qflags
|= QUOTAS_DENY_DISK
;
86 dp
->softlimit
= (SMB_BIG_UINT
)D
.dqb_bsoftlimit
;
87 dp
->hardlimit
= (SMB_BIG_UINT
)D
.dqb_bhardlimit
;
88 dp
->ihardlimit
= (SMB_BIG_UINT
)D
.dqb_ihardlimit
;
89 dp
->isoftlimit
= (SMB_BIG_UINT
)D
.dqb_isoftlimit
;
90 dp
->curinodes
= (SMB_BIG_UINT
)D
.dqb_curinodes
;
91 dp
->curblocks
= (SMB_BIG_UINT
)D
.dqb_curblocks
;
99 /****************************************************************************
100 Abstract out the v1 Linux quota set calls.
101 ****************************************************************************/
102 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
)
106 uint32 oldqflags
= 0;
107 struct v1_kern_dqblk D
;
108 SMB_BIG_UINT bsize
= (SMB_BIG_UINT
)QUOTABLOCK_SIZE
;
112 if (bsize
== dp
->bsize
) {
113 D
.dqb_bsoftlimit
= dp
->softlimit
;
114 D
.dqb_bhardlimit
= dp
->hardlimit
;
115 D
.dqb_ihardlimit
= dp
->ihardlimit
;
116 D
.dqb_isoftlimit
= dp
->isoftlimit
;
118 D
.dqb_bsoftlimit
= (dp
->softlimit
*dp
->bsize
)/bsize
;
119 D
.dqb_bhardlimit
= (dp
->hardlimit
*dp
->bsize
)/bsize
;
120 D
.dqb_ihardlimit
= (dp
->ihardlimit
*dp
->bsize
)/bsize
;
121 D
.dqb_isoftlimit
= (dp
->isoftlimit
*dp
->bsize
)/bsize
;
127 case SMB_USER_QUOTA_TYPE
:
128 DEBUG(10,("sys_set_linux_v1_quota: path[%s] bdev[%s] SMB_USER_QUOTA_TYPE uid[%u]\n",
129 path
, bdev
, (unsigned)id
.uid
));
131 ret
= quotactl(QCMD(Q_V1_SETQUOTA
,USRQUOTA
), bdev
, id
.uid
, (caddr_t
)&D
);
133 case SMB_GROUP_QUOTA_TYPE
:
134 DEBUG(10,("sys_set_linux_v1_quota: path[%s] bdev[%s] SMB_GROUP_QUOTA_TYPE gid[%u]\n",
135 path
, bdev
, (unsigned)id
.gid
));
137 ret
= quotactl(QCMD(Q_V1_SETQUOTA
,GRPQUOTA
), bdev
, id
.gid
, (caddr_t
)&D
);
139 case SMB_USER_FS_QUOTA_TYPE
:
140 DEBUG(10,("sys_set_linux_v1_quota: path[%s] bdev[%s] SMB_USER_FS_QUOTA_TYPE (uid[%u])\n",
141 path
, bdev
, (unsigned)id
.uid
));
143 if ((ret
= quotactl(QCMD(Q_V1_GETQUOTA
,USRQUOTA
), bdev
, id
.uid
, (caddr_t
)&D
))==0) {
144 oldqflags
|= QUOTAS_DENY_DISK
;
148 case SMB_GROUP_FS_QUOTA_TYPE
:
149 DEBUG(10,("sys_set_linux_v1_quota: path[%s] bdev[%s] SMB_GROUP_FS_QUOTA_TYPE (gid[%u])\n",
150 path
, bdev
, (unsigned)id
.gid
));
152 if ((ret
= quotactl(QCMD(Q_V1_GETQUOTA
,GRPQUOTA
), bdev
, id
.gid
, (caddr_t
)&D
))==0) {
153 oldqflags
|= QUOTAS_DENY_DISK
;
165 /****************************************************************************
166 Abstract out the v2 Linux quota get calls.
167 ****************************************************************************/
168 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
)
172 struct v2_kern_dqblk D
;
173 SMB_BIG_UINT bsize
= (SMB_BIG_UINT
)QUOTABLOCK_SIZE
;
178 case SMB_USER_QUOTA_TYPE
:
179 DEBUG(10,("sys_get_linux_v2_quota: path[%s] bdev[%s] SMB_USER_QUOTA_TYPE uid[%u]\n",
180 path
, bdev
, (unsigned)id
.uid
));
182 if ((ret
= quotactl(QCMD(Q_V2_GETQUOTA
,USRQUOTA
), bdev
, id
.uid
, (caddr_t
)&D
))&&errno
!= EDQUOT
) {
187 case SMB_GROUP_QUOTA_TYPE
:
188 DEBUG(10,("sys_get_linux_v2_quota: path[%s] bdev[%s] SMB_GROUP_QUOTA_TYPE gid[%u]\n",
189 path
, bdev
, (unsigned)id
.gid
));
191 if ((ret
= quotactl(QCMD(Q_V2_GETQUOTA
,GRPQUOTA
), bdev
, id
.gid
, (caddr_t
)&D
))&&errno
!= EDQUOT
) {
196 case SMB_USER_FS_QUOTA_TYPE
:
197 DEBUG(10,("sys_get_linux_v2_quota: path[%s] bdev[%s] SMB_USER_FS_QUOTA_TYPE (uid[%u])\n",
198 path
, bdev
, (unsigned)id
.uid
));
200 if ((ret
= quotactl(QCMD(Q_V2_GETQUOTA
,USRQUOTA
), bdev
, id
.uid
, (caddr_t
)&D
))==0) {
201 qflags
|= QUOTAS_DENY_DISK
;
205 case SMB_GROUP_FS_QUOTA_TYPE
:
206 DEBUG(10,("sys_get_linux_v2_quota: path[%s] bdev[%s] SMB_GROUP_FS_QUOTA_TYPE (gid[%u])\n",
207 path
, bdev
, (unsigned)id
.gid
));
209 if ((ret
= quotactl(QCMD(Q_V2_GETQUOTA
,GRPQUOTA
), bdev
, id
.gid
, (caddr_t
)&D
))==0) {
210 qflags
|= QUOTAS_DENY_DISK
;
220 dp
->softlimit
= (SMB_BIG_UINT
)D
.dqb_bsoftlimit
;
221 dp
->hardlimit
= (SMB_BIG_UINT
)D
.dqb_bhardlimit
;
222 dp
->ihardlimit
= (SMB_BIG_UINT
)D
.dqb_ihardlimit
;
223 dp
->isoftlimit
= (SMB_BIG_UINT
)D
.dqb_isoftlimit
;
224 dp
->curinodes
= (SMB_BIG_UINT
)D
.dqb_curinodes
;
225 dp
->curblocks
= (SMB_BIG_UINT
)D
.dqb_curspace
/bsize
;
233 /****************************************************************************
234 Abstract out the v2 Linux quota set calls.
235 ****************************************************************************/
236 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
)
240 uint32 oldqflags
= 0;
241 struct v2_kern_dqblk D
;
242 SMB_BIG_UINT bsize
= (SMB_BIG_UINT
)QUOTABLOCK_SIZE
;
246 if (bsize
== dp
->bsize
) {
247 D
.dqb_bsoftlimit
= dp
->softlimit
;
248 D
.dqb_bhardlimit
= dp
->hardlimit
;
249 D
.dqb_ihardlimit
= dp
->ihardlimit
;
250 D
.dqb_isoftlimit
= dp
->isoftlimit
;
252 D
.dqb_bsoftlimit
= (dp
->softlimit
*dp
->bsize
)/bsize
;
253 D
.dqb_bhardlimit
= (dp
->hardlimit
*dp
->bsize
)/bsize
;
254 D
.dqb_ihardlimit
= (dp
->ihardlimit
*dp
->bsize
)/bsize
;
255 D
.dqb_isoftlimit
= (dp
->isoftlimit
*dp
->bsize
)/bsize
;
261 case SMB_USER_QUOTA_TYPE
:
262 DEBUG(10,("sys_set_linux_v2_quota: path[%s] bdev[%s] SMB_USER_QUOTA_TYPE uid[%u]\n",
263 path
, bdev
, (unsigned)id
.uid
));
265 ret
= quotactl(QCMD(Q_V2_SETQUOTA
,USRQUOTA
), bdev
, id
.uid
, (caddr_t
)&D
);
267 case SMB_GROUP_QUOTA_TYPE
:
268 DEBUG(10,("sys_set_linux_v2_quota: path[%s] bdev[%s] SMB_GROUP_QUOTA_TYPE gid[%u]\n",
269 path
, bdev
, (unsigned)id
.gid
));
271 ret
= quotactl(QCMD(Q_V2_SETQUOTA
,GRPQUOTA
), bdev
, id
.gid
, (caddr_t
)&D
);
273 case SMB_USER_FS_QUOTA_TYPE
:
274 DEBUG(10,("sys_set_linux_v2_quota: path[%s] bdev[%s] SMB_USER_FS_QUOTA_TYPE (uid[%u])\n",
275 path
, bdev
, (unsigned)id
.uid
));
277 if ((ret
= quotactl(QCMD(Q_V2_GETQUOTA
,USRQUOTA
), bdev
, id
.uid
, (caddr_t
)&D
))==0) {
278 oldqflags
|= QUOTAS_DENY_DISK
;
282 case SMB_GROUP_FS_QUOTA_TYPE
:
283 DEBUG(10,("sys_set_linux_v2_quota: path[%s] bdev[%s] SMB_GROUP_FS_QUOTA_TYPE (gid[%u])\n",
284 path
, bdev
, (unsigned)id
.gid
));
286 if ((ret
= quotactl(QCMD(Q_V2_GETQUOTA
,GRPQUOTA
), bdev
, id
.gid
, (caddr_t
)&D
))==0) {
287 oldqflags
|= QUOTAS_DENY_DISK
;
299 /****************************************************************************
300 Abstract out the generic Linux quota get calls.
301 ****************************************************************************/
302 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
)
307 SMB_BIG_UINT bsize
= (SMB_BIG_UINT
)QUOTABLOCK_SIZE
;
312 case SMB_USER_QUOTA_TYPE
:
313 DEBUG(10,("sys_get_linux_gen_quota: path[%s] bdev[%s] SMB_USER_QUOTA_TYPE uid[%u]\n",
314 path
, bdev
, (unsigned)id
.uid
));
316 if ((ret
= quotactl(QCMD(Q_GETQUOTA
,USRQUOTA
), bdev
, id
.uid
, (caddr_t
)&D
))&&errno
!= EDQUOT
) {
321 case SMB_GROUP_QUOTA_TYPE
:
322 DEBUG(10,("sys_get_linux_gen_quota: path[%s] bdev[%s] SMB_GROUP_QUOTA_TYPE gid[%u]\n",
323 path
, bdev
, (unsigned)id
.gid
));
325 if ((ret
= quotactl(QCMD(Q_GETQUOTA
,GRPQUOTA
), bdev
, id
.gid
, (caddr_t
)&D
))&&errno
!= EDQUOT
) {
330 case SMB_USER_FS_QUOTA_TYPE
:
331 DEBUG(10,("sys_get_linux_gen_quota: path[%s] bdev[%s] SMB_USER_FS_QUOTA_TYPE (uid[%u])\n",
332 path
, bdev
, (unsigned)id
.uid
));
334 if ((ret
= quotactl(QCMD(Q_GETQUOTA
,USRQUOTA
), bdev
, id
.uid
, (caddr_t
)&D
))==0) {
335 qflags
|= QUOTAS_DENY_DISK
;
339 case SMB_GROUP_FS_QUOTA_TYPE
:
340 DEBUG(10,("sys_get_linux_gen_quota: path[%s] bdev[%s] SMB_GROUP_FS_QUOTA_TYPE (gid[%u])\n",
341 path
, bdev
, (unsigned)id
.gid
));
343 if ((ret
= quotactl(QCMD(Q_GETQUOTA
,GRPQUOTA
), bdev
, id
.gid
, (caddr_t
)&D
))==0) {
344 qflags
|= QUOTAS_DENY_DISK
;
354 dp
->softlimit
= (SMB_BIG_UINT
)D
.dqb_bsoftlimit
;
355 dp
->hardlimit
= (SMB_BIG_UINT
)D
.dqb_bhardlimit
;
356 dp
->ihardlimit
= (SMB_BIG_UINT
)D
.dqb_ihardlimit
;
357 dp
->isoftlimit
= (SMB_BIG_UINT
)D
.dqb_isoftlimit
;
358 dp
->curinodes
= (SMB_BIG_UINT
)D
.dqb_curinodes
;
359 dp
->curblocks
= (SMB_BIG_UINT
)D
.dqb_curspace
/bsize
;
367 /****************************************************************************
368 Abstract out the gen Linux quota set calls.
369 ****************************************************************************/
370 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
)
374 uint32 oldqflags
= 0;
376 SMB_BIG_UINT bsize
= (SMB_BIG_UINT
)QUOTABLOCK_SIZE
;
380 if (bsize
== dp
->bsize
) {
381 D
.dqb_bsoftlimit
= dp
->softlimit
;
382 D
.dqb_bhardlimit
= dp
->hardlimit
;
383 D
.dqb_ihardlimit
= dp
->ihardlimit
;
384 D
.dqb_isoftlimit
= dp
->isoftlimit
;
386 D
.dqb_bsoftlimit
= (dp
->softlimit
*dp
->bsize
)/bsize
;
387 D
.dqb_bhardlimit
= (dp
->hardlimit
*dp
->bsize
)/bsize
;
388 D
.dqb_ihardlimit
= (dp
->ihardlimit
*dp
->bsize
)/bsize
;
389 D
.dqb_isoftlimit
= (dp
->isoftlimit
*dp
->bsize
)/bsize
;
395 case SMB_USER_QUOTA_TYPE
:
396 DEBUG(10,("sys_set_linux_gen_quota: path[%s] bdev[%s] SMB_USER_QUOTA_TYPE uid[%u]\n",
397 path
, bdev
, (unsigned)id
.uid
));
399 ret
= quotactl(QCMD(Q_SETQUOTA
,USRQUOTA
), bdev
, id
.uid
, (caddr_t
)&D
);
401 case SMB_GROUP_QUOTA_TYPE
:
402 DEBUG(10,("sys_set_linux_gen_quota: path[%s] bdev[%s] SMB_GROUP_QUOTA_TYPE gid[%u]\n",
403 path
, bdev
, (unsigned)id
.gid
));
405 ret
= quotactl(QCMD(Q_SETQUOTA
,GRPQUOTA
), bdev
, id
.gid
, (caddr_t
)&D
);
407 case SMB_USER_FS_QUOTA_TYPE
:
408 DEBUG(10,("sys_set_linux_gen_quota: path[%s] bdev[%s] SMB_USER_FS_QUOTA_TYPE (uid[%u])\n",
409 path
, bdev
, (unsigned)id
.uid
));
411 if ((ret
= quotactl(QCMD(Q_GETQUOTA
,USRQUOTA
), bdev
, id
.uid
, (caddr_t
)&D
))==0) {
412 oldqflags
|= QUOTAS_DENY_DISK
;
416 case SMB_GROUP_FS_QUOTA_TYPE
:
417 DEBUG(10,("sys_set_linux_gen_quota: path[%s] bdev[%s] SMB_GROUP_FS_QUOTA_TYPE (gid[%u])\n",
418 path
, bdev
, (unsigned)id
.gid
));
420 if ((ret
= quotactl(QCMD(Q_GETQUOTA
,GRPQUOTA
), bdev
, id
.gid
, (caddr_t
)&D
))==0) {
421 oldqflags
|= QUOTAS_DENY_DISK
;
433 /****************************************************************************
434 Abstract out the Linux quota get calls.
435 ****************************************************************************/
436 int sys_get_vfs_quota(const char *path
, const char *bdev
, enum SMB_QUOTA_TYPE qtype
, unid_t id
, SMB_DISK_QUOTA
*dp
)
440 if (!path
||!bdev
||!dp
)
441 smb_panic("sys_set_vfs_quota: called with NULL pointer");
447 case SMB_USER_QUOTA_TYPE
:
448 case SMB_GROUP_QUOTA_TYPE
:
449 if ((ret
=sys_get_linux_gen_quota(path
, bdev
, qtype
, id
, dp
))&&errno
!= EDQUOT
) {
450 if ((ret
=sys_get_linux_v2_quota(path
, bdev
, qtype
, id
, dp
))&&errno
!= EDQUOT
) {
451 if ((ret
=sys_get_linux_v1_quota(path
, bdev
, qtype
, id
, dp
))&&errno
!= EDQUOT
) {
457 if ((dp
->curblocks
==0)&&
459 (dp
->hardlimit
==0)) {
460 /* the upper layer functions don't want empty quota records...*/
465 case SMB_USER_FS_QUOTA_TYPE
:
468 if ((ret
=sys_get_linux_gen_quota(path
, bdev
, qtype
, id
, dp
))&&errno
!= EDQUOT
) {
469 if ((ret
=sys_get_linux_v2_quota(path
, bdev
, qtype
, id
, dp
))&&errno
!= EDQUOT
) {
470 ret
=sys_get_linux_v1_quota(path
, bdev
, qtype
, id
, dp
);
476 case SMB_GROUP_FS_QUOTA_TYPE
:
479 if ((ret
=sys_get_linux_gen_quota(path
, bdev
, qtype
, id
, dp
))&&errno
!= EDQUOT
) {
480 if ((ret
=sys_get_linux_v2_quota(path
, bdev
, qtype
, id
, dp
))&&errno
!= EDQUOT
) {
481 ret
=sys_get_linux_v1_quota(path
, bdev
, qtype
, id
, dp
);
495 /****************************************************************************
496 Abstract out the Linux quota set calls.
497 ****************************************************************************/
498 int sys_set_vfs_quota(const char *path
, const char *bdev
, enum SMB_QUOTA_TYPE qtype
, unid_t id
, SMB_DISK_QUOTA
*dp
)
501 uint32 oldqflags
= 0;
503 if (!path
||!bdev
||!dp
)
504 smb_panic("sys_set_vfs_quota: called with NULL pointer");
506 oldqflags
= dp
->qflags
;
509 case SMB_USER_QUOTA_TYPE
:
510 case SMB_GROUP_QUOTA_TYPE
:
511 if ((ret
=sys_set_linux_gen_quota(path
, bdev
, qtype
, id
, dp
))) {
512 if ((ret
=sys_set_linux_v2_quota(path
, bdev
, qtype
, id
, dp
))) {
513 if ((ret
=sys_set_linux_v1_quota(path
, bdev
, qtype
, id
, dp
))) {
519 case SMB_USER_FS_QUOTA_TYPE
:
522 if ((ret
=sys_get_linux_gen_quota(path
, bdev
, qtype
, id
, dp
))) {
523 if ((ret
=sys_get_linux_v2_quota(path
, bdev
, qtype
, id
, dp
))) {
524 ret
=sys_get_linux_v1_quota(path
, bdev
, qtype
, id
, dp
);
528 if (oldqflags
== dp
->qflags
) {
534 case SMB_GROUP_FS_QUOTA_TYPE
:
537 if ((ret
=sys_get_linux_gen_quota(path
, bdev
, qtype
, id
, dp
))) {
538 if ((ret
=sys_get_linux_v2_quota(path
, bdev
, qtype
, id
, dp
))) {
539 ret
=sys_get_linux_v1_quota(path
, bdev
, qtype
, id
, dp
);
543 if (oldqflags
== dp
->qflags
) {
558 #else /* HAVE_QUOTACTL_LINUX */
559 void dummy_sysquotas_linux(void){}
560 #endif /* HAVE_QUOTACTL_LINUX */