1/*
2   Unix SMB/CIFS implementation.
3   System QUOTA function wrappers for LINUX
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_LINUX
28#undef HAVE_QUOTACTL_LINUX
29#endif
30#endif
31
32#ifdef HAVE_QUOTACTL_LINUX
33
34#include "samba_linux_quota.h"
35
36/****************************************************************************
37 Abstract out the v1 Linux quota get calls.
38****************************************************************************/
39static int sys_get_linux_v1_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
40{
41	int ret = -1;
42	uint32 qflags = 0;
43	struct v1_kern_dqblk D;
44	uint64_t bsize = (uint64_t)QUOTABLOCK_SIZE;
45
46	ZERO_STRUCT(D);
47
48	switch (qtype) {
49		case SMB_USER_QUOTA_TYPE:
50			DEBUG(10,("sys_get_linux_v1_quota: path[%s] bdev[%s] SMB_USER_QUOTA_TYPE uid[%u]\n",
51				path, bdev, (unsigned)id.uid));
52
53			if ((ret = quotactl(QCMD(Q_V1_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))&&errno != EDQUOT) {
54				return ret;
55			}
56
57			break;
58		case SMB_GROUP_QUOTA_TYPE:
59			DEBUG(10,("sys_get_linux_v1_quota: path[%s] bdev[%s] SMB_GROUP_QUOTA_TYPE gid[%u]\n",
60				path, bdev, (unsigned)id.gid));
61
62			if ((ret = quotactl(QCMD(Q_V1_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))&&errno != EDQUOT) {
63				return ret;
64			}
65
66			break;
67		case SMB_USER_FS_QUOTA_TYPE:
68			DEBUG(10,("sys_get_linux_v1_quota: path[%s] bdev[%s] SMB_USER_FS_QUOTA_TYPE (uid[%u])\n",
69				path, bdev, (unsigned)id.uid));
70
71			if ((ret = quotactl(QCMD(Q_V1_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))==0) {
72				qflags |= QUOTAS_DENY_DISK;
73			}
74
75			break;
76		case SMB_GROUP_FS_QUOTA_TYPE:
77			DEBUG(10,("sys_get_linux_v1_quota: path[%s] bdev[%s] SMB_GROUP_FS_QUOTA_TYPE (gid[%u])\n",
78				path, bdev, (unsigned)id.gid));
79
80			if ((ret = quotactl(QCMD(Q_V1_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))==0) {
81				qflags |= QUOTAS_DENY_DISK;
82			}
83
84			break;
85		default:
86			errno = ENOSYS;
87			return -1;
88	}
89
90	dp->bsize = bsize;
91	dp->softlimit = (uint64_t)D.dqb_bsoftlimit;
92	dp->hardlimit = (uint64_t)D.dqb_bhardlimit;
93	dp->ihardlimit = (uint64_t)D.dqb_ihardlimit;
94	dp->isoftlimit = (uint64_t)D.dqb_isoftlimit;
95	dp->curinodes = (uint64_t)D.dqb_curinodes;
96	dp->curblocks = (uint64_t)D.dqb_curblocks;
97
98
99	dp->qflags = qflags;
100
101	return ret;
102}
103
104/****************************************************************************
105 Abstract out the v1 Linux quota set calls.
106****************************************************************************/
107static int sys_set_linux_v1_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
108{
109	int ret = -1;
110	uint32 qflags = 0;
111	uint32 oldqflags = 0;
112	struct v1_kern_dqblk D;
113	uint64_t bsize = (uint64_t)QUOTABLOCK_SIZE;
114
115	ZERO_STRUCT(D);
116
117	if (bsize == dp->bsize) {
118		D.dqb_bsoftlimit = dp->softlimit;
119		D.dqb_bhardlimit = dp->hardlimit;
120		D.dqb_ihardlimit = dp->ihardlimit;
121		D.dqb_isoftlimit = dp->isoftlimit;
122	} else {
123		D.dqb_bsoftlimit = (dp->softlimit*dp->bsize)/bsize;
124		D.dqb_bhardlimit = (dp->hardlimit*dp->bsize)/bsize;
125		D.dqb_ihardlimit = (dp->ihardlimit*dp->bsize)/bsize;
126		D.dqb_isoftlimit = (dp->isoftlimit*dp->bsize)/bsize;
127	}
128
129	qflags = dp->qflags;
130
131	switch (qtype) {
132		case SMB_USER_QUOTA_TYPE:
133			DEBUG(10,("sys_set_linux_v1_quota: path[%s] bdev[%s] SMB_USER_QUOTA_TYPE uid[%u]\n",
134				path, bdev, (unsigned)id.uid));
135
136			ret = quotactl(QCMD(Q_V1_SETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D);
137			break;
138		case SMB_GROUP_QUOTA_TYPE:
139			DEBUG(10,("sys_set_linux_v1_quota: path[%s] bdev[%s] SMB_GROUP_QUOTA_TYPE gid[%u]\n",
140				path, bdev, (unsigned)id.gid));
141
142			ret = quotactl(QCMD(Q_V1_SETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D);
143			break;
144		case SMB_USER_FS_QUOTA_TYPE:
145			DEBUG(10,("sys_set_linux_v1_quota: path[%s] bdev[%s] SMB_USER_FS_QUOTA_TYPE (uid[%u])\n",
146				path, bdev, (unsigned)id.uid));
147
148			if ((ret = quotactl(QCMD(Q_V1_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))==0) {
149				oldqflags |= QUOTAS_DENY_DISK;
150			}
151
152			break;
153		case SMB_GROUP_FS_QUOTA_TYPE:
154			DEBUG(10,("sys_set_linux_v1_quota: path[%s] bdev[%s] SMB_GROUP_FS_QUOTA_TYPE (gid[%u])\n",
155				path, bdev, (unsigned)id.gid));
156
157			if ((ret = quotactl(QCMD(Q_V1_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))==0) {
158				oldqflags |= QUOTAS_DENY_DISK;
159			}
160
161			break;
162		default:
163			errno = ENOSYS;
164			return -1;
165	}
166
167	return ret;
168}
169
170/****************************************************************************
171 Abstract out the v2 Linux quota get calls.
172****************************************************************************/
173static int sys_get_linux_v2_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
174{
175	int ret = -1;
176	uint32 qflags = 0;
177	struct v2_kern_dqblk D;
178	uint64_t bsize = (uint64_t)QUOTABLOCK_SIZE;
179
180	ZERO_STRUCT(D);
181
182	switch (qtype) {
183		case SMB_USER_QUOTA_TYPE:
184			DEBUG(10,("sys_get_linux_v2_quota: path[%s] bdev[%s] SMB_USER_QUOTA_TYPE uid[%u]\n",
185				path, bdev, (unsigned)id.uid));
186
187			if ((ret = quotactl(QCMD(Q_V2_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))&&errno != EDQUOT) {
188				return ret;
189			}
190
191			break;
192		case SMB_GROUP_QUOTA_TYPE:
193			DEBUG(10,("sys_get_linux_v2_quota: path[%s] bdev[%s] SMB_GROUP_QUOTA_TYPE gid[%u]\n",
194				path, bdev, (unsigned)id.gid));
195
196			if ((ret = quotactl(QCMD(Q_V2_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))&&errno != EDQUOT) {
197				return ret;
198			}
199
200			break;
201		case SMB_USER_FS_QUOTA_TYPE:
202			DEBUG(10,("sys_get_linux_v2_quota: path[%s] bdev[%s] SMB_USER_FS_QUOTA_TYPE (uid[%u])\n",
203				path, bdev, (unsigned)id.uid));
204
205			if ((ret = quotactl(QCMD(Q_V2_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))==0) {
206				qflags |= QUOTAS_DENY_DISK;
207			}
208
209			break;
210		case SMB_GROUP_FS_QUOTA_TYPE:
211			DEBUG(10,("sys_get_linux_v2_quota: path[%s] bdev[%s] SMB_GROUP_FS_QUOTA_TYPE (gid[%u])\n",
212				path, bdev, (unsigned)id.gid));
213
214			if ((ret = quotactl(QCMD(Q_V2_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))==0) {
215				qflags |= QUOTAS_DENY_DISK;
216			}
217
218			break;
219		default:
220			errno = ENOSYS;
221			return -1;
222	}
223
224	dp->bsize = bsize;
225	dp->softlimit = (uint64_t)D.dqb_bsoftlimit;
226	dp->hardlimit = (uint64_t)D.dqb_bhardlimit;
227	dp->ihardlimit = (uint64_t)D.dqb_ihardlimit;
228	dp->isoftlimit = (uint64_t)D.dqb_isoftlimit;
229	dp->curinodes = (uint64_t)D.dqb_curinodes;
230	dp->curblocks = (uint64_t)D.dqb_curspace/bsize;
231
232
233	dp->qflags = qflags;
234
235	return ret;
236}
237
238/****************************************************************************
239 Abstract out the v2 Linux quota set calls.
240****************************************************************************/
241static int sys_set_linux_v2_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
242{
243	int ret = -1;
244	uint32 qflags = 0;
245	uint32 oldqflags = 0;
246	struct v2_kern_dqblk D;
247	uint64_t bsize = (uint64_t)QUOTABLOCK_SIZE;
248
249	ZERO_STRUCT(D);
250
251	if (bsize == dp->bsize) {
252		D.dqb_bsoftlimit = dp->softlimit;
253		D.dqb_bhardlimit = dp->hardlimit;
254		D.dqb_ihardlimit = dp->ihardlimit;
255		D.dqb_isoftlimit = dp->isoftlimit;
256	} else {
257		D.dqb_bsoftlimit = (dp->softlimit*dp->bsize)/bsize;
258		D.dqb_bhardlimit = (dp->hardlimit*dp->bsize)/bsize;
259		D.dqb_ihardlimit = (dp->ihardlimit*dp->bsize)/bsize;
260		D.dqb_isoftlimit = (dp->isoftlimit*dp->bsize)/bsize;
261	}
262
263	qflags = dp->qflags;
264
265	switch (qtype) {
266		case SMB_USER_QUOTA_TYPE:
267			DEBUG(10,("sys_set_linux_v2_quota: path[%s] bdev[%s] SMB_USER_QUOTA_TYPE uid[%u]\n",
268				path, bdev, (unsigned)id.uid));
269
270			ret = quotactl(QCMD(Q_V2_SETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D);
271			break;
272		case SMB_GROUP_QUOTA_TYPE:
273			DEBUG(10,("sys_set_linux_v2_quota: path[%s] bdev[%s] SMB_GROUP_QUOTA_TYPE gid[%u]\n",
274				path, bdev, (unsigned)id.gid));
275
276			ret = quotactl(QCMD(Q_V2_SETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D);
277			break;
278		case SMB_USER_FS_QUOTA_TYPE:
279			DEBUG(10,("sys_set_linux_v2_quota: path[%s] bdev[%s] SMB_USER_FS_QUOTA_TYPE (uid[%u])\n",
280				path, bdev, (unsigned)id.uid));
281
282			if ((ret = quotactl(QCMD(Q_V2_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))==0) {
283				oldqflags |= QUOTAS_DENY_DISK;
284			}
285
286			break;
287		case SMB_GROUP_FS_QUOTA_TYPE:
288			DEBUG(10,("sys_set_linux_v2_quota: path[%s] bdev[%s] SMB_GROUP_FS_QUOTA_TYPE (gid[%u])\n",
289				path, bdev, (unsigned)id.gid));
290
291			if ((ret = quotactl(QCMD(Q_V2_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))==0) {
292				oldqflags |= QUOTAS_DENY_DISK;
293			}
294
295			break;
296		default:
297			errno = ENOSYS;
298			return -1;
299	}
300
301	return ret;
302}
303
304/****************************************************************************
305 Abstract out the generic Linux quota get calls.
306****************************************************************************/
307static int sys_get_linux_gen_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
308{
309	int ret = -1;
310	uint32 qflags = 0;
311	struct if_dqblk D;
312	uint64_t bsize = (uint64_t)QUOTABLOCK_SIZE;
313
314	ZERO_STRUCT(D);
315
316	switch (qtype) {
317		case SMB_USER_QUOTA_TYPE:
318			DEBUG(10,("sys_get_linux_gen_quota: path[%s] bdev[%s] SMB_USER_QUOTA_TYPE uid[%u]\n",
319				path, bdev, (unsigned)id.uid));
320
321			if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))&&errno != EDQUOT) {
322				return ret;
323			}
324
325			break;
326		case SMB_GROUP_QUOTA_TYPE:
327			DEBUG(10,("sys_get_linux_gen_quota: path[%s] bdev[%s] SMB_GROUP_QUOTA_TYPE gid[%u]\n",
328				path, bdev, (unsigned)id.gid));
329
330			if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))&&errno != EDQUOT) {
331				return ret;
332			}
333
334			break;
335		case SMB_USER_FS_QUOTA_TYPE:
336			DEBUG(10,("sys_get_linux_gen_quota: path[%s] bdev[%s] SMB_USER_FS_QUOTA_TYPE (uid[%u])\n",
337				path, bdev, (unsigned)id.uid));
338
339			if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))==0) {
340				qflags |= QUOTAS_DENY_DISK;
341			}
342
343			break;
344		case SMB_GROUP_FS_QUOTA_TYPE:
345			DEBUG(10,("sys_get_linux_gen_quota: path[%s] bdev[%s] SMB_GROUP_FS_QUOTA_TYPE (gid[%u])\n",
346				path, bdev, (unsigned)id.gid));
347
348			if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))==0) {
349				qflags |= QUOTAS_DENY_DISK;
350			}
351
352			break;
353		default:
354			errno = ENOSYS;
355			return -1;
356	}
357
358	dp->bsize = bsize;
359	dp->softlimit = (uint64_t)D.dqb_bsoftlimit;
360	dp->hardlimit = (uint64_t)D.dqb_bhardlimit;
361	dp->ihardlimit = (uint64_t)D.dqb_ihardlimit;
362	dp->isoftlimit = (uint64_t)D.dqb_isoftlimit;
363	dp->curinodes = (uint64_t)D.dqb_curinodes;
364	dp->curblocks = (uint64_t)D.dqb_curspace/bsize;
365
366
367	dp->qflags = qflags;
368
369	return ret;
370}
371
372/****************************************************************************
373 Abstract out the gen Linux quota set calls.
374****************************************************************************/
375static int sys_set_linux_gen_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
376{
377	int ret = -1;
378	uint32 qflags = 0;
379	uint32 oldqflags = 0;
380	struct if_dqblk D;
381	uint64_t bsize = (uint64_t)QUOTABLOCK_SIZE;
382
383	ZERO_STRUCT(D);
384
385	if (bsize == dp->bsize) {
386		D.dqb_bsoftlimit = dp->softlimit;
387		D.dqb_bhardlimit = dp->hardlimit;
388		D.dqb_ihardlimit = dp->ihardlimit;
389		D.dqb_isoftlimit = dp->isoftlimit;
390	} else {
391		D.dqb_bsoftlimit = (dp->softlimit*dp->bsize)/bsize;
392		D.dqb_bhardlimit = (dp->hardlimit*dp->bsize)/bsize;
393		D.dqb_ihardlimit = (dp->ihardlimit*dp->bsize)/bsize;
394		D.dqb_isoftlimit = (dp->isoftlimit*dp->bsize)/bsize;
395	}
396	D.dqb_valid = QIF_LIMITS;
397
398	qflags = dp->qflags;
399
400	switch (qtype) {
401		case SMB_USER_QUOTA_TYPE:
402			DEBUG(10,("sys_set_linux_gen_quota: path[%s] bdev[%s] SMB_USER_QUOTA_TYPE uid[%u]\n",
403				path, bdev, (unsigned)id.uid));
404
405			ret = quotactl(QCMD(Q_SETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D);
406			break;
407		case SMB_GROUP_QUOTA_TYPE:
408			DEBUG(10,("sys_set_linux_gen_quota: path[%s] bdev[%s] SMB_GROUP_QUOTA_TYPE gid[%u]\n",
409				path, bdev, (unsigned)id.gid));
410
411			ret = quotactl(QCMD(Q_SETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D);
412			break;
413		case SMB_USER_FS_QUOTA_TYPE:
414			DEBUG(10,("sys_set_linux_gen_quota: path[%s] bdev[%s] SMB_USER_FS_QUOTA_TYPE (uid[%u])\n",
415				path, bdev, (unsigned)id.uid));
416
417			if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))==0) {
418				oldqflags |= QUOTAS_DENY_DISK;
419			}
420
421			break;
422		case SMB_GROUP_FS_QUOTA_TYPE:
423			DEBUG(10,("sys_set_linux_gen_quota: path[%s] bdev[%s] SMB_GROUP_FS_QUOTA_TYPE (gid[%u])\n",
424				path, bdev, (unsigned)id.gid));
425
426			if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))==0) {
427				oldqflags |= QUOTAS_DENY_DISK;
428			}
429
430			break;
431		default:
432			errno = ENOSYS;
433			return -1;
434	}
435
436	return ret;
437}
438
439/****************************************************************************
440 Abstract out the Linux quota get calls.
441****************************************************************************/
442int sys_get_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
443{
444	int ret = -1;
445
446	if (!path||!bdev||!dp)
447		smb_panic("sys_set_vfs_quota: called with NULL pointer");
448
449	ZERO_STRUCT(*dp);
450	dp->qtype = qtype;
451
452	switch (qtype) {
453		case SMB_USER_QUOTA_TYPE:
454		case SMB_GROUP_QUOTA_TYPE:
455			if ((ret=sys_get_linux_gen_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
456				if ((ret=sys_get_linux_v2_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
457					if ((ret=sys_get_linux_v1_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
458						return ret;
459					}
460				}
461			}
462
463			if ((dp->curblocks==0)&&
464				(dp->softlimit==0)&&
465				(dp->hardlimit==0)) {
466				/* the upper layer functions don't want empty quota records...*/
467				return -1;
468			}
469
470			break;
471		case SMB_USER_FS_QUOTA_TYPE:
472			id.uid = getuid();
473
474			if ((ret=sys_get_linux_gen_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
475				if ((ret=sys_get_linux_v2_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
476					ret=sys_get_linux_v1_quota(path, bdev, qtype, id, dp);
477				}
478			}
479
480			ret = 0;
481			break;
482		case SMB_GROUP_FS_QUOTA_TYPE:
483			id.gid = getgid();
484
485			if ((ret=sys_get_linux_gen_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
486				if ((ret=sys_get_linux_v2_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
487					ret=sys_get_linux_v1_quota(path, bdev, qtype, id, dp);
488				}
489			}
490
491			ret = 0;
492			break;
493		default:
494			errno = ENOSYS;
495			return -1;
496	}
497
498	return ret;
499}
500
501/****************************************************************************
502 Abstract out the Linux quota set calls.
503****************************************************************************/
504int sys_set_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
505{
506	int ret = -1;
507	uint32 oldqflags = 0;
508
509	if (!path||!bdev||!dp)
510		smb_panic("sys_set_vfs_quota: called with NULL pointer");
511
512	oldqflags = dp->qflags;
513
514	switch (qtype) {
515		case SMB_USER_QUOTA_TYPE:
516		case SMB_GROUP_QUOTA_TYPE:
517			if ((ret=sys_set_linux_gen_quota(path, bdev, qtype, id, dp))) {
518				if ((ret=sys_set_linux_v2_quota(path, bdev, qtype, id, dp))) {
519					if ((ret=sys_set_linux_v1_quota(path, bdev, qtype, id, dp))) {
520						return ret;
521					}
522				}
523			}
524			break;
525		case SMB_USER_FS_QUOTA_TYPE:
526			id.uid = getuid();
527
528			if ((ret=sys_set_linux_gen_quota(path, bdev, qtype, id, dp))) {
529				if ((ret=sys_set_linux_v2_quota(path, bdev, qtype, id, dp))) {
530					ret=sys_set_linux_v1_quota(path, bdev, qtype, id, dp);
531				}
532			}
533
534			if (oldqflags == dp->qflags) {
535				ret = 0;
536			} else {
537				ret = -1;
538			}
539			break;
540		case SMB_GROUP_FS_QUOTA_TYPE:
541			id.gid = getgid();
542
543			if ((ret=sys_set_linux_gen_quota(path, bdev, qtype, id, dp))) {
544				if ((ret=sys_set_linux_v2_quota(path, bdev, qtype, id, dp))) {
545					ret=sys_set_linux_v1_quota(path, bdev, qtype, id, dp);
546				}
547			}
548
549			if (oldqflags == dp->qflags) {
550				ret = 0;
551			} else {
552				ret = -1;
553			}
554
555			break;
556		default:
557			errno = ENOSYS;
558			return -1;
559	}
560
561	return ret;
562}
563
564#else /* HAVE_QUOTACTL_LINUX */
565 void dummy_sysquotas_linux(void);
566
567 void dummy_sysquotas_linux(void){}
568#endif /* HAVE_QUOTACTL_LINUX */
569