2 Unix SMB/CIFS implementation.
3 System QUOTA function wrappers for XFS
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 #if defined(HAVE_SYS_QUOTAS) && defined(HAVE_XFS_QUOTAS)
28 #ifdef HAVE_SYS_QUOTA_H
29 #include <sys/quota.h>
32 /* this one should actually come from glibc: */
33 /* #include "samba_linux_quota.h" */
39 #define HAVE_GROUP_QUOTA
43 #define Q_XQUOTAON Q_QUOTAON
44 #endif /* Q_XQUOTAON */
46 #define Q_XQUOTAOFF Q_QUOTAOFF
47 #endif /* Q_XQUOTAOFF */
49 #define Q_XGETQSTAT Q_GETQSTAT
50 #endif /* Q_XGETQSTAT */
52 /* currently doesn't support Group and Project quotas on IRIX
60 * IRIX has BBSIZE in <sys/param.h>
66 #define BBSIZE (1<<BBSHIFT)
69 /****************************************************************************
70 Abstract out the XFS Quota Manager quota get call.
71 ****************************************************************************/
72 int sys_get_xfs_quota(const char *path
, const char *bdev
, enum SMB_QUOTA_TYPE qtype
, unid_t id
, SMB_DISK_QUOTA
*dp
)
76 uint64_t bsize
= (uint64_t)BBSIZE
;
77 struct fs_disk_quota D
;
78 struct fs_quota_stat F
;
83 smb_panic("sys_get_xfs_quota: called with NULL pointer");
89 case SMB_USER_QUOTA_TYPE
:
90 DEBUG(10,("sys_get_xfs_quota: path[%s] bdev[%s] SMB_USER_QUOTA_TYPE uid[%u]\n",
91 path
, bdev
, (unsigned)id
.uid
));
93 ret
=quotactl(QCMD(Q_XGETQUOTA
,USRQUOTA
), bdev
, id
.uid
, (caddr_t
)&D
);
94 /* XFS fails with ENOENT if the user has no
95 * quota. Our protocol in that case is to
96 * succeed and return 0 as quota.
98 if (ret
!= 0 && errno
!= ENOENT
) {
104 #ifdef HAVE_GROUP_QUOTA
105 case SMB_GROUP_QUOTA_TYPE
:
106 DEBUG(10,("sys_get_xfs_quota: path[%s] bdev[%s] SMB_GROUP_QUOTA_TYPE gid[%u]\n",
107 path
, bdev
, (unsigned)id
.gid
));
109 ret
=quotactl(QCMD(Q_XGETQUOTA
,GRPQUOTA
), bdev
, id
.gid
, (caddr_t
)&D
);
110 /* XFS fails with ENOENT if the user has no
111 * quota. Our protocol in that case is to
112 * succeed and return 0 as quota.
114 if (ret
!= 0 && errno
!= ENOENT
) {
118 #endif /* HAVE_GROUP_QUOTA */
119 case SMB_USER_FS_QUOTA_TYPE
:
120 DEBUG(10,("sys_get_xfs_quota: path[%s] bdev[%s] SMB_USER_FS_QUOTA_TYPE (uid[%u])\n",
121 path
, bdev
, (unsigned)id
.uid
));
123 quotactl(QCMD(Q_XGETQSTAT
,USRQUOTA
), bdev
, -1, (caddr_t
)&F
);
125 if (F
.qs_flags
& XFS_QUOTA_UDQ_ENFD
) {
126 qflags
|= QUOTAS_DENY_DISK
;
128 else if (F
.qs_flags
& XFS_QUOTA_UDQ_ACCT
) {
129 qflags
|= QUOTAS_ENABLED
;
135 #ifdef HAVE_GROUP_QUOTA
136 case SMB_GROUP_FS_QUOTA_TYPE
:
137 DEBUG(10,("sys_get_xfs_quota: path[%s] bdev[%s] SMB_GROUP_FS_QUOTA_TYPE (gid[%u])\n",
138 path
, bdev
, (unsigned)id
.gid
));
140 quotactl(QCMD(Q_XGETQSTAT
,GRPQUOTA
), bdev
, -1, (caddr_t
)&F
);
142 if (F
.qs_flags
& XFS_QUOTA_GDQ_ENFD
) {
143 qflags
|= QUOTAS_DENY_DISK
;
145 else if (F
.qs_flags
& XFS_QUOTA_GDQ_ACCT
) {
146 qflags
|= QUOTAS_ENABLED
;
152 #endif /* HAVE_GROUP_QUOTA */
159 dp
->softlimit
= (uint64_t)D
.d_blk_softlimit
;
160 dp
->hardlimit
= (uint64_t)D
.d_blk_hardlimit
;
161 dp
->ihardlimit
= (uint64_t)D
.d_ino_hardlimit
;
162 dp
->isoftlimit
= (uint64_t)D
.d_ino_softlimit
;
163 dp
->curinodes
= (uint64_t)D
.d_icount
;
164 dp
->curblocks
= (uint64_t)D
.d_bcount
;
170 /****************************************************************************
171 Abstract out the XFS Quota Manager quota set call.
172 ****************************************************************************/
173 int sys_set_xfs_quota(const char *path
, const char *bdev
, enum SMB_QUOTA_TYPE qtype
, unid_t id
, SMB_DISK_QUOTA
*dp
)
177 uint64_t bsize
= (uint64_t)BBSIZE
;
178 struct fs_disk_quota D
;
179 struct fs_quota_stat F
;
186 smb_panic("sys_set_xfs_quota: called with NULL pointer");
188 if (bsize
== dp
->bsize
) {
189 D
.d_blk_softlimit
= dp
->softlimit
;
190 D
.d_blk_hardlimit
= dp
->hardlimit
;
192 D
.d_blk_softlimit
= (dp
->softlimit
*dp
->bsize
)/bsize
;
193 D
.d_blk_hardlimit
= (dp
->hardlimit
*dp
->bsize
)/bsize
;
195 D
.d_ino_hardlimit
= dp
->ihardlimit
;
196 D
.d_ino_softlimit
= dp
->isoftlimit
;
201 case SMB_USER_QUOTA_TYPE
:
202 DEBUG(10,("sys_set_xfs_quota: path[%s] bdev[%s] SMB_USER_QUOTA_TYPE uid[%u]\n",
203 path
, bdev
, (unsigned)id
.uid
));
205 D
.d_fieldmask
|= FS_DQ_LIMIT_MASK
;
206 ret
= quotactl(QCMD(Q_XSETQLIM
,USRQUOTA
), bdev
, id
.uid
, (caddr_t
)&D
);
208 #ifdef HAVE_GROUP_QUOTA
209 case SMB_GROUP_QUOTA_TYPE
:
210 DEBUG(10,("sys_set_xfs_quota: path[%s] bdev[%s] SMB_GROUP_QUOTA_TYPE gid[%u]\n",
211 path
, bdev
, (unsigned)id
.gid
));
213 D
.d_fieldmask
|= FS_DQ_LIMIT_MASK
;
214 ret
= quotactl(QCMD(Q_XSETQLIM
,GRPQUOTA
), bdev
, id
.gid
, (caddr_t
)&D
);
216 #endif /* HAVE_GROUP_QUOTA */
217 case SMB_USER_FS_QUOTA_TYPE
:
218 DEBUG(10,("sys_set_xfs_quota: path[%s] bdev[%s] SMB_USER_FS_QUOTA_TYPE (uid[%u])\n",
219 path
, bdev
, (unsigned)id
.uid
));
221 quotactl(QCMD(Q_XGETQSTAT
,USRQUOTA
), bdev
, -1, (caddr_t
)&F
);
223 if (qflags
& QUOTAS_DENY_DISK
) {
224 if (!(F
.qs_flags
& XFS_QUOTA_UDQ_ENFD
))
225 q_on
|= XFS_QUOTA_UDQ_ENFD
;
226 if (!(F
.qs_flags
& XFS_QUOTA_UDQ_ACCT
))
227 q_on
|= XFS_QUOTA_UDQ_ACCT
;
230 ret
= quotactl(QCMD(Q_XQUOTAON
,USRQUOTA
),bdev
, -1, (caddr_t
)&q_on
);
235 } else if (qflags
& QUOTAS_ENABLED
) {
236 if (F
.qs_flags
& XFS_QUOTA_UDQ_ENFD
)
237 q_off
|= XFS_QUOTA_UDQ_ENFD
;
240 ret
= quotactl(QCMD(Q_XQUOTAOFF
,USRQUOTA
),bdev
, -1, (caddr_t
)&q_off
);
245 if (!(F
.qs_flags
& XFS_QUOTA_UDQ_ACCT
))
246 q_on
|= XFS_QUOTA_UDQ_ACCT
;
249 ret
= quotactl(QCMD(Q_XQUOTAON
,USRQUOTA
),bdev
, -1, (caddr_t
)&q_on
);
255 /* Switch on XFS_QUOTA_UDQ_ACCT didn't work!
256 * only swittching off XFS_QUOTA_UDQ_ACCT work
258 if (F
.qs_flags
& XFS_QUOTA_UDQ_ENFD
)
259 q_off
|= XFS_QUOTA_UDQ_ENFD
;
260 if (F
.qs_flags
& XFS_QUOTA_UDQ_ACCT
)
261 q_off
|= XFS_QUOTA_UDQ_ACCT
;
264 ret
= quotactl(QCMD(Q_XQUOTAOFF
,USRQUOTA
),bdev
, -1, (caddr_t
)&q_off
);
274 #ifdef HAVE_GROUP_QUOTA
275 case SMB_GROUP_FS_QUOTA_TYPE
:
276 DEBUG(10,("sys_set_xfs_quota: path[%s] bdev[%s] SMB_GROUP_FS_QUOTA_TYPE (gid[%u])\n",
277 path
, bdev
, (unsigned)id
.gid
));
279 quotactl(QCMD(Q_XGETQSTAT
,GRPQUOTA
), bdev
, -1, (caddr_t
)&F
);
281 if (qflags
& QUOTAS_DENY_DISK
) {
282 if (!(F
.qs_flags
& XFS_QUOTA_GDQ_ENFD
))
283 q_on
|= XFS_QUOTA_GDQ_ENFD
;
284 if (!(F
.qs_flags
& XFS_QUOTA_GDQ_ACCT
))
285 q_on
|= XFS_QUOTA_GDQ_ACCT
;
288 ret
= quotactl(QCMD(Q_XQUOTAON
,GRPQUOTA
),bdev
, -1, (caddr_t
)&q_on
);
293 } else if (qflags
& QUOTAS_ENABLED
) {
294 if (F
.qs_flags
& XFS_QUOTA_GDQ_ENFD
)
295 q_off
|= XFS_QUOTA_GDQ_ENFD
;
298 ret
= quotactl(QCMD(Q_XQUOTAOFF
,GRPQUOTA
),bdev
, -1, (caddr_t
)&q_off
);
303 if (!(F
.qs_flags
& XFS_QUOTA_GDQ_ACCT
))
304 q_on
|= XFS_QUOTA_GDQ_ACCT
;
307 ret
= quotactl(QCMD(Q_XQUOTAON
,GRPQUOTA
),bdev
, -1, (caddr_t
)&q_on
);
313 /* Switch on XFS_QUOTA_UDQ_ACCT didn't work!
314 * only swittching off XFS_QUOTA_UDQ_ACCT work
316 if (F
.qs_flags
& XFS_QUOTA_GDQ_ENFD
)
317 q_off
|= XFS_QUOTA_GDQ_ENFD
;
318 if (F
.qs_flags
& XFS_QUOTA_GDQ_ACCT
)
319 q_off
|= XFS_QUOTA_GDQ_ACCT
;
322 ret
= quotactl(QCMD(Q_XQUOTAOFF
,GRPQUOTA
),bdev
, -1, (caddr_t
)&q_off
);
332 #endif /* HAVE_GROUP_QUOTA */
341 #else /* HAVE_XFS_QUOTAS */
342 void dummy_sysquotas_xfs(void);
344 void dummy_sysquotas_xfs(void){}
345 #endif /* HAVE_XFS_QUOTAS */