Move sys_readlink() to libreplace.
[ira/wip.git] / source3 / 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, 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 ****************************************************************************/
39 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)
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 ****************************************************************************/
107 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)
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 ****************************************************************************/
173 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)
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 ****************************************************************************/
241 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)
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 ****************************************************************************/
307 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)
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 ****************************************************************************/
375 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)
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 ****************************************************************************/
442 int 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 ****************************************************************************/
504 int 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 */