Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : System QUOTA function wrappers for QUOTACTL_4A
4 : Copyright (C) Stefan (metze) Metzmacher 2003
5 :
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.
10 :
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.
15 :
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/>.
18 : */
19 :
20 :
21 : #include "includes.h"
22 :
23 : #undef DBGC_CLASS
24 : #define DBGC_CLASS DBGC_QUOTA
25 :
26 : #ifndef HAVE_SYS_QUOTAS
27 : #ifdef HAVE_QUOTACTL_4A
28 : #undef HAVE_QUOTACTL_4A
29 : #endif
30 : #endif
31 :
32 : #ifdef HAVE_QUOTACTL_4A
33 : /* long quotactl(int cmd, char *special, qid_t id, caddr_t addr) */
34 : /* this is used by: HPUX,IRIX */
35 :
36 : #ifdef HAVE_SYS_TYPES_H
37 : #include <sys/types.h>
38 : #endif
39 :
40 : #ifdef HAVE_ASM_TYPES_H
41 : #include <asm/types.h>
42 : #endif
43 :
44 : #ifdef HAVE_SYS_QUOTA_H
45 : #include <sys/quota.h>
46 : #endif
47 :
48 : #ifndef Q_SETQLIM
49 : #define Q_SETQLIM Q_SETQUOTA
50 : #endif
51 :
52 : #ifndef QCMD
53 : #define QCMD(x,y) x
54 : #endif
55 :
56 : #ifndef QCMD
57 : #define QCMD(x,y) x
58 : #endif
59 :
60 : #ifdef GRPQUOTA
61 : #define HAVE_GROUP_QUOTA
62 : #endif
63 :
64 : #ifndef QUOTABLOCK_SIZE
65 : #define QUOTABLOCK_SIZE DEV_BSIZE
66 : #endif
67 :
68 : #ifdef HAVE_DQB_FSOFTLIMIT
69 : #define dqb_isoftlimit dqb_fsoftlimit
70 : #define dqb_ihardlimit dqb_fhardlimit
71 : #define dqb_curinodes dqb_curfiles
72 : #endif
73 :
74 : #ifdef INITQFNAMES
75 : #define USERQUOTAFILE_EXTENSION ".user"
76 : #else
77 : #define USERQUOTAFILE_EXTENSION ""
78 : #endif
79 :
80 : #if !defined(QUOTAFILENAME) && defined(QFILENAME)
81 : #define QUOTAFILENAME QFILENAME
82 : #endif
83 :
84 : /****************************************************************************
85 : Abstract out the quotactl_4A get calls.
86 : ****************************************************************************/
87 : int sys_get_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
88 : {
89 : int ret = -1;
90 : uint32_t qflags = 0;
91 : struct dqblk D;
92 : uint64_t bsize = (uint64_t)QUOTABLOCK_SIZE;
93 :
94 : ZERO_STRUCT(D);
95 : ZERO_STRUCT(*dp);
96 : dp->qtype = qtype;
97 :
98 : switch (qtype) {
99 : case SMB_USER_QUOTA_TYPE:
100 : DEBUG(10,("sys_get_vfs_quota: path[%s] bdev[%s] SMB_USER_QUOTA_TYPE uid[%u]\n",
101 : path, bdev, (unsigned)id.uid));
102 :
103 : if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), (caddr_t)bdev, id.uid, (void *)&D))&&errno != EDQUOT) {
104 : return ret;
105 : }
106 :
107 : ret = 0;
108 : break;
109 : #ifdef HAVE_GROUP_QUOTA
110 : case SMB_GROUP_QUOTA_TYPE:
111 : DEBUG(10,("sys_get_vfs_quota: path[%s] bdev[%s] SMB_GROUP_QUOTA_TYPE gid[%u]\n",
112 : path, bdev, (unsigned)id.gid));
113 :
114 : if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), (caddr_t)bdev, id.gid, (void *)&D))&&errno != EDQUOT) {
115 : return ret;
116 : }
117 :
118 : ret = 0;
119 : break;
120 : #endif /* HAVE_GROUP_QUOTA */
121 : case SMB_USER_FS_QUOTA_TYPE:
122 : id.uid = getuid();
123 :
124 : DEBUG(10,("sys_get_vfs_quota: path[%s] bdev[%s] SMB_USER_FS_QUOTA_TYPE (uid[%u])\n",
125 : path, (caddr_t)bdev, (unsigned)id.uid));
126 :
127 : if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), (caddr_t)bdev, id.uid, (void *)&D))==0) {
128 : qflags |= QUOTAS_DENY_DISK;
129 : }
130 :
131 : ret = 0;
132 : break;
133 : #ifdef HAVE_GROUP_QUOTA
134 : case SMB_GROUP_FS_QUOTA_TYPE:
135 : id.gid = getgid();
136 :
137 : DEBUG(10,("sys_get_vfs_quota: path[%s] bdev[%s] SMB_GROUP_FS_QUOTA_TYPE (gid[%u])\n",
138 : path, bdev, (unsigned)id.gid));
139 :
140 : if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), (caddr_t)bdev, id.gid, (void *)&D))==0) {
141 : qflags |= QUOTAS_DENY_DISK;
142 : }
143 :
144 : ret = 0;
145 : break;
146 : #endif /* HAVE_GROUP_QUOTA */
147 : default:
148 : errno = ENOSYS;
149 : return -1;
150 : }
151 :
152 : dp->bsize = bsize;
153 : dp->softlimit = (uint64_t)D.dqb_bsoftlimit;
154 : dp->hardlimit = (uint64_t)D.dqb_bhardlimit;
155 : dp->ihardlimit = (uint64_t)D.dqb_ihardlimit;
156 : dp->isoftlimit = (uint64_t)D.dqb_isoftlimit;
157 : dp->curinodes = (uint64_t)D.dqb_curinodes;
158 : dp->curblocks = (uint64_t)D.dqb_curblocks;
159 :
160 :
161 : dp->qflags = qflags;
162 :
163 : return ret;
164 : }
165 :
166 : /****************************************************************************
167 : Abstract out the quotactl_4A set calls.
168 : ****************************************************************************/
169 : int sys_set_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
170 : {
171 : int ret = -1;
172 : uint32_t qflags = 0;
173 : uint32_t oldqflags = 0;
174 : struct dqblk D;
175 : uint64_t bsize = (uint64_t)QUOTABLOCK_SIZE;
176 :
177 : ZERO_STRUCT(D);
178 :
179 : if (bsize == dp->bsize) {
180 : D.dqb_bsoftlimit = dp->softlimit;
181 : D.dqb_bhardlimit = dp->hardlimit;
182 : D.dqb_ihardlimit = dp->ihardlimit;
183 : D.dqb_isoftlimit = dp->isoftlimit;
184 : } else {
185 : D.dqb_bsoftlimit = (dp->softlimit*dp->bsize)/bsize;
186 : D.dqb_bhardlimit = (dp->hardlimit*dp->bsize)/bsize;
187 : D.dqb_ihardlimit = (dp->ihardlimit*dp->bsize)/bsize;
188 : D.dqb_isoftlimit = (dp->isoftlimit*dp->bsize)/bsize;
189 : }
190 :
191 : qflags = dp->qflags;
192 :
193 : switch (qtype) {
194 : case SMB_USER_QUOTA_TYPE:
195 : DEBUG(10,("sys_set_vfs_quota: path[%s] bdev[%s] SMB_USER_QUOTA_TYPE uid[%u]\n",
196 : path, bdev, (unsigned)id.uid));
197 :
198 : ret = quotactl(QCMD(Q_SETQLIM,USRQUOTA), (caddr_t)bdev, id.uid, (void *)&D);
199 : break;
200 : #ifdef HAVE_GROUP_QUOTA
201 : case SMB_GROUP_QUOTA_TYPE:
202 : DEBUG(10,("sys_set_vfs_quota: path[%s] bdev[%s] SMB_GROUP_QUOTA_TYPE gid[%u]\n",
203 : path, bdev, (unsigned)id.gid));
204 :
205 : ret = quotactl(QCMD(Q_SETQLIM,GRPQUOTA), (caddr_t)bdev, id.gid, (void *)&D);
206 : break;
207 : #endif /* HAVE_GROUP_QUOTA */
208 : case SMB_USER_FS_QUOTA_TYPE:
209 : /* this stuff didn't work as it should:
210 : * switching on/off quota via quotactl()
211 : * didn't work!
212 : * So we just return 0
213 : * --metze
214 : *
215 : * On HPUX we didn't have the mount path,
216 : * we need to fix sys_path_to_bdev()
217 : *
218 : */
219 : id.uid = getuid();
220 : DEBUG(10,("sys_set_vfs_quota: path[%s] bdev[%s] SMB_USER_FS_QUOTA_TYPE (uid[%u])\n",
221 : path, bdev, (unsigned)id.uid));
222 :
223 : #if 0
224 : ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), (caddr_t)bdev, id.uid, (void *)&D);
225 :
226 : if ((qflags"AS_DENY_DISK)||(qflags"AS_ENABLED)) {
227 : if (ret == 0) {
228 : char *quota_file = NULL;
229 :
230 : asprintf("a_file,"/%s/%s%s",path, QUOTAFILENAME,USERQUOTAFILE_EXTENSION);
231 : if (quota_file == NULL) {
232 : DEBUG(0,("asprintf() failed!\n"));
233 : errno = ENOMEM;
234 : return -1;
235 : }
236 :
237 : ret = quotactl(QCMD(Q_QUOTAON,USRQUOTA), (caddr_t)bdev, -1,(void *)quota_file);
238 : } else {
239 : ret = 0;
240 : }
241 : } else {
242 : if (ret != 0) {
243 : /* turn off */
244 : ret = quotactl(QCMD(Q_QUOTAOFF,USRQUOTA), (caddr_t)bdev, -1, (void *)0);
245 : } else {
246 : ret = 0;
247 : }
248 : }
249 :
250 : DEBUG(0,("sys_set_vfs_quota: ret(%d) errno(%d)[%s] uid(%d) bdev[%s]\n",
251 : ret,errno,strerror(errno),id.uid,bdev));
252 : #else
253 : if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), (caddr_t)bdev, id.uid, (void *)&D))==0) {
254 : oldqflags |= QUOTAS_DENY_DISK;
255 : }
256 :
257 : if (oldqflags == qflags) {
258 : ret = 0;
259 : } else {
260 : ret = -1;
261 : }
262 : #endif
263 : break;
264 : #ifdef HAVE_GROUP_QUOTA
265 : case SMB_GROUP_FS_QUOTA_TYPE:
266 : /* this stuff didn't work as it should:
267 : * switching on/off quota via quotactl()
268 : * didn't work!
269 : * So we just return 0
270 : * --metze
271 : *
272 : * On HPUX we didn't have the mount path,
273 : * we need to fix sys_path_to_bdev()
274 : *
275 : */
276 : id.gid = getgid();
277 : DEBUG(10,("sys_set_vfs_quota: path[%s] bdev[%s] SMB_GROUP_FS_QUOTA_TYPE (gid[%u])\n",
278 : path, bdev, (unsigned)id.gid));
279 :
280 : #if 0
281 : ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id, (void *)&D);
282 :
283 : if ((qflags"AS_DENY_DISK)||(qflags"AS_ENABLED)) {
284 : if (ret == 0) {
285 : char *quota_file = NULL;
286 :
287 : asprintf("a_file,"/%s/%s%s",path, QUOTAFILENAME,GROUPQUOTAFILE_EXTENSION);
288 : if (quota_file == NULL) {
289 : DEBUG(0,("asprintf() failed!\n"));
290 : errno = ENOMEM;
291 : return -1;
292 : }
293 :
294 : ret = quotactl(QCMD(Q_QUOTAON,GRPQUOTA), (caddr_t)bdev, -1,(void *)quota_file);
295 : } else {
296 : ret = 0;
297 : }
298 : } else {
299 : if (ret != 0) {
300 : /* turn off */
301 : ret = quotactl(QCMD(Q_QUOTAOFF,GRPQUOTA), (caddr_t)bdev, -1, (void *)0);
302 : } else {
303 : ret = 0;
304 : }
305 : }
306 :
307 : DEBUG(0,("sys_set_vfs_quota: ret(%d) errno(%d)[%s] uid(%d) bdev[%s]\n",
308 : ret,errno,strerror(errno),id.gid,bdev));
309 : #else
310 : if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), (caddr_t)bdev, id.gid, (void *)&D))==0) {
311 : oldqflags |= QUOTAS_DENY_DISK;
312 : }
313 :
314 : if (oldqflags == qflags) {
315 : ret = 0;
316 : } else {
317 : ret = -1;
318 : }
319 : #endif
320 : break;
321 : #endif /* HAVE_GROUP_QUOTA */
322 : default:
323 : errno = ENOSYS;
324 : return -1;
325 : }
326 :
327 : return ret;
328 : }
329 :
330 : #else /* HAVE_QUOTACTL_4A */
331 : void dummy_sysquotas_4A(void);
332 :
333 0 : void dummy_sysquotas_4A(void){}
334 : #endif /* HAVE_QUOTACTL_4A */
|