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