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
86 dp
->ihardlimit
= qblk
->dqb_ihardlimit
;
87 dp
->isoftlimit
= qblk
->dqb_isoftlimit
;
88 dp
->curinodes
= qblk
->dqb_curinodes
;
90 dp
->qflags
= QUOTAS_ENABLED
| QUOTAS_DENY_DISK
;
92 DEBUG(10, ("softlimit=%u hardlimit=%u curblock=%u\n",
93 (unsigned)dp
->softlimit
, (unsigned)dp
->hardlimit
,
94 (unsigned)dp
->curblocks
));
96 DEBUGADD(10, ("softinodes=%u hardinodes=%u curinodes=%u\n",
97 (unsigned)dp
->isoftlimit
, (unsigned)dp
->ihardlimit
,
98 (unsigned)dp
->curinodes
));
102 static void xlate_smb_to_qblk(const SMB_DISK_QUOTA
* const dp
,
107 qblk
->dqb_bsoftlimit
= dp
->softlimit
;
108 qblk
->dqb_bhardlimit
= dp
->hardlimit
;
109 #ifdef HAVE_STRUCT_DQBLK_DQB_CURBYTES
110 /* On Darwin, quotas are counted in bytes. */
111 qblk
->dqb_bsoftlimit
*= dp
->bsize
;
112 qblk
->dqb_bhardlimit
*= dp
->bsize
;
114 qblk
->dqb_ihardlimit
= dp
->ihardlimit
;
115 qblk
->dqb_isoftlimit
= dp
->isoftlimit
;
118 static int sys_quotactl_4B(const char * path
, int cmd
,
119 int id
, struct dqblk
*qblk
)
123 /* NB: We must test GRPQUOTA here, because USRQUOTA is 0. */
124 DEBUG(10, ("%s quota for %s ID %u on %s\n",
125 (cmd
& QCMD(Q_GETQUOTA
, 0)) ? "getting" : "setting",
126 (cmd
& QCMD(0, GRPQUOTA
)) ? "group" : "user",
127 (unsigned)id
, path
));
129 #ifdef HFS_QUOTACTL_WAR
131 #endif /* HFS_QUOTACTL_WAR */
133 ret
= quotactl(path
, cmd
, id
, qblk
);
135 /* ENOTSUP means quota support is not compiled in. EINVAL
136 * means that quotas are not configured (commonly).
138 if (errno
!= ENOTSUP
&& errno
!= EINVAL
) {
139 DEBUG(0, ("failed to %s quota for %s ID %u on %s: %s\n",
140 (cmd
& QCMD(Q_GETQUOTA
, 0)) ? "get" : "set",
141 (cmd
& QCMD(0, GRPQUOTA
)) ? "group" : "user",
142 (unsigned)id
, path
, strerror(errno
)));
145 #ifdef HFS_QUOTACTL_WAR
147 #endif /* HFS_QUOTACTL_WAR */
153 #ifdef HFS_QUOTACTL_WAR
155 #endif /* HFS_QUOTACTL_WAR */
160 int sys_get_vfs_quota(const char *path
, const char *bdev
,
161 enum SMB_QUOTA_TYPE qtype
, unid_t id
, SMB_DISK_QUOTA
*dp
)
169 case SMB_USER_QUOTA_TYPE
:
170 /* Get quota for provided UID. */
171 ret
= sys_quotactl_4B(path
, QCMD(Q_GETQUOTA
, USRQUOTA
),
174 case SMB_USER_FS_QUOTA_TYPE
:
175 /* Get quota for current UID. */
176 ret
= sys_quotactl_4B(path
, QCMD(Q_GETQUOTA
, USRQUOTA
),
179 case SMB_GROUP_QUOTA_TYPE
:
180 /* Get quota for provided GID. */
181 ret
= sys_quotactl_4B(path
, QCMD(Q_GETQUOTA
, GRPQUOTA
),
184 case SMB_GROUP_FS_QUOTA_TYPE
:
185 /* Get quota for current GID. */
186 ret
= sys_quotactl_4B(path
, QCMD(Q_GETQUOTA
, GRPQUOTA
),
190 DEBUG(0, ("cannot get unsupported quota type: %u\n",
200 xlate_qblk_to_smb(&qblk
, dp
);
206 int sys_set_vfs_quota(const char *path
, const char *bdev
,
207 enum SMB_QUOTA_TYPE qtype
, unid_t id
, SMB_DISK_QUOTA
*dp
)
211 xlate_smb_to_qblk(dp
, &qblk
);
214 case SMB_USER_QUOTA_TYPE
:
215 /* Set quota for provided UID. */
216 return sys_quotactl_4B(path
, QCMD(Q_SETQUOTA
, USRQUOTA
),
218 case SMB_USER_FS_QUOTA_TYPE
:
219 /* Set quota for current UID. */
220 return sys_quotactl_4B(path
, QCMD(Q_SETQUOTA
, USRQUOTA
),
222 case SMB_GROUP_QUOTA_TYPE
:
223 /* Set quota for provided GID. */
224 return sys_quotactl_4B(path
, QCMD(Q_SETQUOTA
, GRPQUOTA
),
226 case SMB_GROUP_FS_QUOTA_TYPE
:
227 /* Set quota for current GID. */
228 return sys_quotactl_4B(path
, QCMD(Q_SETQUOTA
, GRPQUOTA
),
231 DEBUG(0, ("cannot set unsupported quota type: %u\n",
238 #endif /* HAVE_QUOTACTL_4B */