2 * Unix SMB/CIFS implementation.
3 * System QUOTA function wrappers for QUOTACTL_4B
5 * Copyright (C) 2011 James Peach.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #define DBGC_CLASS DBGC_QUOTA
27 #ifndef HAVE_SYS_QUOTAS
28 #undef HAVE_QUOTACTL_4B
31 #ifdef HAVE_QUOTACTL_4B
32 /* int quotactl(const char *path, int cmd, int id, char *addr)
34 * This is used by many (all?) BSD-derived systems. This implementation has
35 * been developed and tested on Darwin, but may also work on other BSD systems.
38 #ifdef HAVE_SYS_TYPES_H
39 #include <sys/types.h>
42 #ifdef HAVE_SYS_QUOTA_H
43 #include <sys/quota.h>
46 #ifdef HAVE_UFS_UFS_QUOTA_H
47 #include <ufs/ufs/quota.h>
51 /* WorkARound broken HFS access checks in hfs_quotactl. Darwin only(?) */
52 #define HFS_QUOTACTL_WAR 1
55 static void xlate_qblk_to_smb(const struct dqblk
* const qblk
,
60 DEBUG(10, ("unix softlimit=%u hardlimit=%u curblock=%u\n",
61 (unsigned)qblk
->dqb_bsoftlimit
, (unsigned)qblk
->dqb_bhardlimit
,
62 #ifdef HAVE_STRUCT_DQBLK_DQB_CURBYTES
63 (unsigned)qblk
->dqb_curbytes
));
65 (unsigned)qblk
->dqb_curblocks
));
68 DEBUGADD(10, ("unix softinodes=%u hardinodes=%u curinodes=%u\n",
69 (unsigned)qblk
->dqb_isoftlimit
, (unsigned)qblk
->dqb_ihardlimit
,
70 (unsigned)qblk
->dqb_curinodes
));
72 #ifdef HAVE_STRUCT_DQBLK_DQB_CURBYTES
73 /* On Darwin, quotas are counted in bytes. We report them
74 * in 512b blocks because various callers have assumptions
75 * about the block size.
77 #define XLATE_TO_BLOCKS(bytes) (((bytes) + 1) / 512)
80 dp
->softlimit
= XLATE_TO_BLOCKS(qblk
->dqb_bsoftlimit
);
81 dp
->hardlimit
= XLATE_TO_BLOCKS(qblk
->dqb_bhardlimit
);
82 dp
->curblocks
= XLATE_TO_BLOCKS(qblk
->dqb_curbytes
);
83 #undef XLATE_TO_BLOCKS
85 dp
->bsize
= DEV_BSIZE
;
87 dp
->softlimit
= qblk
->dqb_bsoftlimit
;
88 dp
->hardlimit
= qblk
->dqb_bhardlimit
;
89 dp
->curblocks
= qblk
->dqb_curblocks
;
92 dp
->ihardlimit
= qblk
->dqb_ihardlimit
;
93 dp
->isoftlimit
= qblk
->dqb_isoftlimit
;
94 dp
->curinodes
= qblk
->dqb_curinodes
;
96 dp
->qflags
= QUOTAS_ENABLED
| QUOTAS_DENY_DISK
;
98 DEBUG(10, ("softlimit=%u hardlimit=%u curblock=%u\n",
99 (unsigned)dp
->softlimit
, (unsigned)dp
->hardlimit
,
100 (unsigned)dp
->curblocks
));
102 DEBUGADD(10, ("softinodes=%u hardinodes=%u curinodes=%u\n",
103 (unsigned)dp
->isoftlimit
, (unsigned)dp
->ihardlimit
,
104 (unsigned)dp
->curinodes
));
108 static void xlate_smb_to_qblk(const SMB_DISK_QUOTA
* const dp
,
113 qblk
->dqb_bsoftlimit
= dp
->softlimit
;
114 qblk
->dqb_bhardlimit
= dp
->hardlimit
;
115 #ifdef HAVE_STRUCT_DQBLK_DQB_CURBYTES
116 /* On Darwin, quotas are counted in bytes. */
117 qblk
->dqb_bsoftlimit
*= dp
->bsize
;
118 qblk
->dqb_bhardlimit
*= dp
->bsize
;
120 qblk
->dqb_ihardlimit
= dp
->ihardlimit
;
121 qblk
->dqb_isoftlimit
= dp
->isoftlimit
;
124 static int sys_quotactl_4B(const char * path
, int cmd
,
125 int id
, struct dqblk
*qblk
)
129 /* NB: We must test GRPQUOTA here, because USRQUOTA is 0. */
130 DEBUG(10, ("%s quota for %s ID %u on %s\n",
131 (cmd
& QCMD(Q_GETQUOTA
, 0)) ? "getting" : "setting",
132 (cmd
& QCMD(0, GRPQUOTA
)) ? "group" : "user",
133 (unsigned)id
, path
));
135 #ifdef HFS_QUOTACTL_WAR
137 #endif /* HFS_QUOTACTL_WAR */
139 ret
= quotactl(path
, cmd
, id
, qblk
);
141 /* ENOTSUP means quota support is not compiled in. EINVAL
142 * means that quotas are not configured (commonly).
144 if (errno
!= ENOTSUP
&& errno
!= EINVAL
) {
145 DEBUG(0, ("failed to %s quota for %s ID %u on %s: %s\n",
146 (cmd
& QCMD(Q_GETQUOTA
, 0)) ? "get" : "set",
147 (cmd
& QCMD(0, GRPQUOTA
)) ? "group" : "user",
148 (unsigned)id
, path
, strerror(errno
)));
151 #ifdef HFS_QUOTACTL_WAR
153 #endif /* HFS_QUOTACTL_WAR */
159 #ifdef HFS_QUOTACTL_WAR
161 #endif /* HFS_QUOTACTL_WAR */
166 int sys_get_vfs_quota(const char *path
, const char *bdev
,
167 enum SMB_QUOTA_TYPE qtype
, unid_t id
, SMB_DISK_QUOTA
*dp
)
175 case SMB_USER_QUOTA_TYPE
:
176 /* Get quota for provided UID. */
177 ret
= sys_quotactl_4B(path
, QCMD(Q_GETQUOTA
, USRQUOTA
),
180 case SMB_USER_FS_QUOTA_TYPE
:
181 /* Get quota for current UID. */
182 ret
= sys_quotactl_4B(path
, QCMD(Q_GETQUOTA
, USRQUOTA
),
185 case SMB_GROUP_QUOTA_TYPE
:
186 /* Get quota for provided GID. */
187 ret
= sys_quotactl_4B(path
, QCMD(Q_GETQUOTA
, GRPQUOTA
),
190 case SMB_GROUP_FS_QUOTA_TYPE
:
191 /* Get quota for current GID. */
192 ret
= sys_quotactl_4B(path
, QCMD(Q_GETQUOTA
, GRPQUOTA
),
196 DEBUG(0, ("cannot get unsupported quota type: %u\n",
206 xlate_qblk_to_smb(&qblk
, dp
);
212 int sys_set_vfs_quota(const char *path
, const char *bdev
,
213 enum SMB_QUOTA_TYPE qtype
, unid_t id
, SMB_DISK_QUOTA
*dp
)
217 xlate_smb_to_qblk(dp
, &qblk
);
220 case SMB_USER_QUOTA_TYPE
:
221 /* Set quota for provided UID. */
222 return sys_quotactl_4B(path
, QCMD(Q_SETQUOTA
, USRQUOTA
),
224 case SMB_USER_FS_QUOTA_TYPE
:
225 /* Set quota for current UID. */
226 return sys_quotactl_4B(path
, QCMD(Q_SETQUOTA
, USRQUOTA
),
228 case SMB_GROUP_QUOTA_TYPE
:
229 /* Set quota for provided GID. */
230 return sys_quotactl_4B(path
, QCMD(Q_SETQUOTA
, GRPQUOTA
),
232 case SMB_GROUP_FS_QUOTA_TYPE
:
233 /* Set quota for current GID. */
234 return sys_quotactl_4B(path
, QCMD(Q_SETQUOTA
, GRPQUOTA
),
237 DEBUG(0, ("cannot set unsupported quota type: %u\n",
244 #endif /* HAVE_QUOTACTL_4B */