Apply the changes that Derrell Lipman supplied ...
[Samba/gebeck_regimport.git] / source3 / lib / sysquotas.c
blob3223ecb580b06b76437aebf4726bb87351be4638
1 /*
2 Unix SMB/CIFS implementation.
3 System QUOTA function wrappers
4 Copyright (C) Stefan (metze) Metzmacher 2003
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 2 of the License, or
9 (at your option) any later version.
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.
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.
22 #include "includes.h"
24 #ifdef HAVE_SYS_QUOTAS
26 #if defined(HAVE_QUOTACTL_4A)
27 /* long quotactl(int cmd, char *special, qid_t id, caddr_t addr) */
28 /* this is used by: linux,HPUX,IRIX */
30 /****************************************************************************
31 Abstract out the old and new Linux quota get calls.
32 ****************************************************************************/
33 static int sys_get_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
35 int ret = -1;
36 uint32 qflags = 0;
37 struct SYS_DQBLK D;
38 SMB_BIG_UINT bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
40 if (!path||!bdev||!dp)
41 smb_panic("sys_get_vfs_quota: called with NULL pointer");
43 ZERO_STRUCT(D);
44 ZERO_STRUCT(*dp);
45 dp->qtype = qtype;
47 switch (qtype) {
48 case SMB_USER_QUOTA_TYPE:
49 if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (CADDR_T)&D))) {
50 return ret;
53 if ((D.dqb_curblocks==0)&&
54 (D.dqb_bsoftlimit==0)&&
55 (D.dqb_bhardlimit==0)) {
56 /* the upper layer functions don't want empty quota records...*/
57 return -1;
60 break;
61 #ifdef HAVE_GROUP_QUOTA
62 case SMB_GROUP_QUOTA_TYPE:
63 if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id.gid, (CADDR_T)&D))) {
64 return ret;
67 if ((D.dqb_curblocks==0)&&
68 (D.dqb_bsoftlimit==0)&&
69 (D.dqb_bhardlimit==0)) {
70 /* the upper layer functions don't want empty quota records...*/
71 return -1;
74 break;
75 #endif /* HAVE_GROUP_QUOTA */
76 case SMB_USER_FS_QUOTA_TYPE:
77 id.uid = getuid();
79 if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (CADDR_T)&D))==0) {
80 qflags |= QUOTAS_DENY_DISK;
83 ret = 0;
84 break;
85 #ifdef HAVE_GROUP_QUOTA
86 case SMB_GROUP_FS_QUOTA_TYPE:
87 id.gid = getgid();
89 if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id.gid, (CADDR_T)&D))==0) {
90 qflags |= QUOTAS_DENY_DISK;
93 ret = 0;
94 break;
95 #endif /* HAVE_GROUP_QUOTA */
96 default:
97 errno = ENOSYS;
98 return -1;
101 dp->bsize = bsize;
102 dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit;
103 dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit;
104 dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit;
105 dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit;
106 dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes;
107 dp->curblocks = (SMB_BIG_UINT)D.dqb_curblocks;
110 dp->qflags = qflags;
112 return ret;
115 /****************************************************************************
116 Abstract out the old and new Linux quota set calls.
117 ****************************************************************************/
119 static int sys_set_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
121 int ret = -1;
122 uint32 qflags = 0;
123 uint32 oldqflags = 0;
124 struct SYS_DQBLK D;
125 SMB_BIG_UINT bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
127 if (!path||!bdev||!dp)
128 smb_panic("sys_set_vfs_quota: called with NULL pointer");
130 ZERO_STRUCT(D);
132 if (bsize == dp->bsize) {
133 D.dqb_bsoftlimit = dp->softlimit;
134 D.dqb_bhardlimit = dp->hardlimit;
135 D.dqb_ihardlimit = dp->ihardlimit;
136 D.dqb_isoftlimit = dp->isoftlimit;
137 } else {
138 D.dqb_bsoftlimit = (dp->softlimit*dp->bsize)/bsize;
139 D.dqb_bhardlimit = (dp->hardlimit*dp->bsize)/bsize;
140 D.dqb_ihardlimit = (dp->ihardlimit*dp->bsize)/bsize;
141 D.dqb_isoftlimit = (dp->isoftlimit*dp->bsize)/bsize;
144 qflags = dp->qflags;
146 switch (qtype) {
147 case SMB_USER_QUOTA_TYPE:
148 ret = quotactl(QCMD(Q_SETQLIM,USRQUOTA), bdev, id.uid, (CADDR_T)&D);
149 break;
150 #ifdef HAVE_GROUP_QUOTA
151 case SMB_GROUP_QUOTA_TYPE:
152 ret = quotactl(QCMD(Q_SETQLIM,GRPQUOTA), bdev, id.gid, (CADDR_T)&D);
153 break;
154 #endif /* HAVE_GROUP_QUOTA */
155 case SMB_USER_FS_QUOTA_TYPE:
156 /* this stuff didn't work as it should:
157 * switching on/off quota via quotactl()
158 * didn't work!
159 * So we just return 0
160 * --metze
162 * On HPUX we didn't have the mount path,
163 * we need to fix sys_path_to_bdev()
166 #if 0
167 id.uid = getuid();
169 ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (CADDR_T)&D);
171 if ((qflags&QUOTAS_DENY_DISK)||(qflags&QUOTAS_ENABLED)) {
172 if (ret == 0) {
173 char *quota_file = NULL;
175 asprintf(&quota_file,"/%s/%s%s",path, QUOTAFILENAME,USERQUOTAFILE_EXTENSION);
176 if (quota_file == NULL) {
177 DEBUG(0,("asprintf() failed!\n"));
178 errno = ENOMEM;
179 return -1;
182 ret = quotactl(QCMD(Q_QUOTAON,USRQUOTA), bdev, -1,(CADDR_T)quota_file);
183 } else {
184 ret = 0;
186 } else {
187 if (ret != 0) {
188 /* turn off */
189 ret = quotactl(QCMD(Q_QUOTAOFF,USRQUOTA), bdev, -1, (CADDR_T)0);
190 } else {
191 ret = 0;
195 DEBUG(0,("vfs_fs_quota: ret(%d) errno(%d)[%s] uid(%d) bdev[%s]\n",
196 ret,errno,strerror(errno),id.uid,bdev));
197 #else
198 id.uid = getuid();
200 if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (CADDR_T)&D))==0) {
201 oldqflags |= QUOTAS_DENY_DISK;
204 if (oldqflags == qflags) {
205 ret = 0;
206 } else {
207 ret = -1;
209 #endif
210 break;
211 #ifdef HAVE_GROUP_QUOTA
212 case SMB_GROUP_FS_QUOTA_TYPE:
213 /* this stuff didn't work as it should:
214 * switching on/off quota via quotactl()
215 * didn't work!
216 * So we just return 0
217 * --metze
219 * On HPUX we didn't have the mount path,
220 * we need to fix sys_path_to_bdev()
223 #if 0
224 id.gid = getgid();
226 ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id, (CADDR_T)&D);
228 if ((qflags&QUOTAS_DENY_DISK)||(qflags&QUOTAS_ENABLED)) {
229 if (ret == 0) {
230 char *quota_file = NULL;
232 asprintf(&quota_file,"/%s/%s%s",path, QUOTAFILENAME,GROUPQUOTAFILE_EXTENSION);
233 if (quota_file == NULL) {
234 DEBUG(0,("asprintf() failed!\n"));
235 errno = ENOMEM;
236 return -1;
239 ret = quotactl(QCMD(Q_QUOTAON,GRPQUOTA), bdev, -1,(CADDR_T)quota_file);
240 } else {
241 ret = 0;
243 } else {
244 if (ret != 0) {
245 /* turn off */
246 ret = quotactl(QCMD(Q_QUOTAOFF,GRPQUOTA), bdev, -1, (CADDR_T)0);
247 } else {
248 ret = 0;
252 DEBUG(0,("vfs_fs_quota: ret(%d) errno(%d)[%s] uid(%d) bdev[%s]\n",
253 ret,errno,strerror(errno),id.gid,bdev));
254 #else
255 id.gid = getgid();
257 if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id.gid, (CADDR_T)&D))==0) {
258 oldqflags |= QUOTAS_DENY_DISK;
261 if (oldqflags == qflags) {
262 ret = 0;
263 } else {
264 ret = -1;
266 #endif
267 break;
268 #endif /* HAVE_GROUP_QUOTA */
269 default:
270 errno = ENOSYS;
271 return -1;
274 return ret;
277 /*#endif HAVE_QUOTACTL_4A */
278 #elif defined(HAVE_QUOTACTL_4B)
280 #error HAVE_QUOTACTL_4B not implemeted
282 /*#endif HAVE_QUOTACTL_4B */
283 #elif defined(HAVE_QUOTACTL_3)
285 #error HAVE_QUOTACTL_3 not implemented
287 /* #endif HAVE_QUOTACTL_3 */
288 #else /* NO_QUOTACTL_USED */
290 static int sys_get_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
292 int ret = -1;
294 if (!path||!bdev||!dp)
295 smb_panic("sys_get_vfs_quota: called with NULL pointer");
297 errno = ENOSYS;
299 return ret;
302 static int sys_set_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
304 int ret = -1;
306 if (!path||!bdev||!dp)
307 smb_panic("sys_set_vfs_quota: called with NULL pointer");
309 errno = ENOSYS;
311 return ret;
314 #endif /* NO_QUOTACTL_USED */
316 #ifdef HAVE_MNTENT
317 static int sys_path_to_bdev(const char *path, char **mntpath, char **bdev, char **fs)
319 int ret = -1;
320 SMB_STRUCT_STAT S;
321 FILE *fp;
322 struct mntent *mnt;
323 SMB_DEV_T devno;
325 /* find the block device file */
327 if (!path||!mntpath||!bdev||!fs)
328 smb_panic("sys_path_to_bdev: called with NULL pointer");
330 (*mntpath) = NULL;
331 (*bdev) = NULL;
332 (*fs) = NULL;
334 if ( sys_stat(path, &S) == -1 )
335 return (-1);
337 devno = S.st_dev ;
339 fp = setmntent(MOUNTED,"r");
341 while ((mnt = getmntent(fp))) {
342 if ( sys_stat(mnt->mnt_dir,&S) == -1 )
343 continue ;
345 if (S.st_dev == devno) {
346 (*mntpath) = strdup(mnt->mnt_dir);
347 (*bdev) = strdup(mnt->mnt_fsname);
348 (*fs) = strdup(mnt->mnt_type);
349 if ((*mntpath)&&(*bdev)&&(*fs)) {
350 ret = 0;
351 } else {
352 SAFE_FREE(*mntpath);
353 SAFE_FREE(*bdev);
354 SAFE_FREE(*fs);
355 ret = -1;
358 break;
362 endmntent(fp) ;
364 return ret;
366 /* #endif HAVE_MNTENT */
367 #elif defined(HAVE_DEVNM)
369 /* we have this on HPUX, ... */
370 static int sys_path_to_bdev(const char *path, char **mntpath, char **bdev, char **fs)
372 int ret = -1;
373 char dev_disk[256];
374 SMB_STRUCT_STAT S;
376 if (!path||!mntpath||!bdev||!fs)
377 smb_panic("sys_path_to_bdev: called with NULL pointer");
379 (*mntpath) = NULL;
380 (*bdev) = NULL;
381 (*fs) = NULL;
383 /* find the block device file */
385 if ((ret=sys_stat(path, &S))!=0) {
386 return ret;
389 if ((ret=devnm(S_IFBLK, S.st_dev, dev_disk, 256, 1))!=0) {
390 return ret;
393 /* we should get the mntpath right...
394 * but I don't know how
395 * --metze
397 (*mntpath) = strdup(path);
398 (*bdev) = strdup(dev_disk);
399 if ((*mntpath)&&(*bdev)) {
400 ret = 0;
401 } else {
402 SAFE_FREE(*mntpath);
403 SAFE_FREE(*bdev);
404 ret = -1;
408 return ret;
411 /* #endif HAVE_DEVNM */
412 #else
413 /* we should fake this up...*/
414 static int sys_path_to_bdev(const char *path, char **mntpath, char **bdev, char **fs)
416 int ret = -1;
418 if (!path||!mntpath||!bdev||!fs)
419 smb_panic("sys_path_to_bdev: called with NULL pointer");
421 (*mntpath) = NULL;
422 (*bdev) = NULL;
423 (*fs) = NULL;
425 (*mntpath) = strdup(path);
426 if (*mntpath) {
427 ret = 0;
428 } else {
429 SAFE_FREE(*mntpath);
430 ret = -1;
433 return ret;
435 #endif
438 /*********************************************************
439 if we have XFS QUOTAS we should use them
440 *********************************************************/
441 #ifdef HAVE_XFS_QUOTA
442 /****************************************************************************
443 Abstract out the XFS Quota Manager quota get call.
444 ****************************************************************************/
445 static int sys_get_xfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
447 int ret = -1;
448 uint32 qflags = 0;
449 SMB_BIG_UINT bsize = (SMB_BIG_UINT)BBSIZE;
450 struct fs_disk_quota D;
451 struct fs_quota_stat F;
452 ZERO_STRUCT(D);
453 ZERO_STRUCT(F);
455 if (!bdev||!dp)
456 smb_panic("sys_get_xfs_quota: called with NULL pointer");
458 ZERO_STRUCT(*dp);
459 dp->qtype = qtype;
461 switch (qtype) {
462 case SMB_USER_QUOTA_TYPE:
463 if ((ret=quotactl(QCMD(Q_XGETQUOTA,USRQUOTA), bdev, id.uid, (CADDR_T)&D)))
464 return ret;
465 break;
466 #ifdef HAVE_GROUP_QUOTA
467 case SMB_GROUP_QUOTA_TYPE:
468 if ((ret=quotactl(QCMD(Q_XGETQUOTA,GRPQUOTA), bdev, id.gid, (CADDR_T)&D)))
469 return ret;
470 break;
471 #endif /* HAVE_GROUP_QUOTA */
472 case SMB_USER_FS_QUOTA_TYPE:
473 quotactl(QCMD(Q_XGETQSTAT,USRQUOTA), bdev, -1, (CADDR_T)&F);
475 if (F.qs_flags & XFS_QUOTA_UDQ_ENFD) {
476 qflags |= QUOTAS_DENY_DISK;
478 else if (F.qs_flags & XFS_QUOTA_UDQ_ACCT) {
479 qflags |= QUOTAS_ENABLED;
482 ret = 0;
484 break;
485 #ifdef HAVE_GROUP_QUOTA
486 case SMB_GROUP_FS_QUOTA_TYPE:
487 quotactl(QCMD(Q_XGETQSTAT,GRPQUOTA), bdev, -1, (CADDR_T)&F);
489 if (F.qs_flags & XFS_QUOTA_UDQ_ENFD) {
490 qflags |= QUOTAS_DENY_DISK;
492 else if (F.qs_flags & XFS_QUOTA_UDQ_ACCT) {
493 qflags |= QUOTAS_ENABLED;
496 ret = 0;
498 break;
499 #endif /* HAVE_GROUP_QUOTA */
500 default:
501 errno = ENOSYS;
502 return -1;
505 dp->bsize = bsize;
506 dp->softlimit = (SMB_BIG_UINT)D.d_blk_softlimit;
507 dp->hardlimit = (SMB_BIG_UINT)D.d_blk_hardlimit;
508 dp->ihardlimit = (SMB_BIG_UINT)D.d_ino_hardlimit;
509 dp->isoftlimit = (SMB_BIG_UINT)D.d_ino_softlimit;
510 dp->curinodes = (SMB_BIG_UINT)D.d_icount;
511 dp->curblocks = (SMB_BIG_UINT)D.d_bcount;
512 dp->qflags = qflags;
514 return ret;
517 /****************************************************************************
518 Abstract out the XFS Quota Manager quota set call.
519 ****************************************************************************/
520 static int sys_set_xfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
522 int ret = -1;
523 uint32 qflags = 0;
524 SMB_BIG_UINT bsize = (SMB_BIG_UINT)BBSIZE;
525 struct fs_disk_quota D;
526 struct fs_quota_stat F;
527 int q_on = 0;
528 int q_off = 0;
529 ZERO_STRUCT(D);
530 ZERO_STRUCT(F);
532 if (!bdev||!dp)
533 smb_panic("sys_set_xfs_quota: called with NULL pointer");
535 if (bsize == dp->bsize) {
536 D.d_blk_softlimit = dp->softlimit;
537 D.d_blk_hardlimit = dp->hardlimit;
538 D.d_ino_hardlimit = dp->ihardlimit;
539 D.d_ino_softlimit = dp->isoftlimit;
540 } else {
541 D.d_blk_softlimit = (dp->softlimit*dp->bsize)/bsize;
542 D.d_blk_hardlimit = (dp->hardlimit*dp->bsize)/bsize;
543 D.d_ino_hardlimit = (dp->ihardlimit*dp->bsize)/bsize;
544 D.d_ino_softlimit = (dp->isoftlimit*dp->bsize)/bsize;
547 qflags = dp->qflags;
549 switch (qtype) {
550 case SMB_USER_QUOTA_TYPE:
551 D.d_fieldmask |= FS_DQ_LIMIT_MASK;
552 ret = quotactl(QCMD(Q_XSETQLIM,USRQUOTA), bdev, id.uid, (CADDR_T)&D);
553 break;
554 #ifdef HAVE_GROUP_QUOTA
555 case SMB_GROUP_QUOTA_TYPE:
556 D.d_fieldmask |= FS_DQ_LIMIT_MASK;
557 ret = quotactl(QCMD(Q_XSETQLIM,GRPQUOTA), bdev, id.gid, (CADDR_T)&D);
558 break;
559 #endif /* HAVE_GROUP_QUOTA */
560 case SMB_USER_FS_QUOTA_TYPE:
561 quotactl(QCMD(Q_XGETQSTAT,USRQUOTA), bdev, -1, (CADDR_T)&F);
563 if (qflags & QUOTAS_DENY_DISK) {
564 if (!(F.qs_flags & XFS_QUOTA_UDQ_ENFD))
565 q_on |= XFS_QUOTA_UDQ_ENFD;
566 if (!(F.qs_flags & XFS_QUOTA_UDQ_ACCT))
567 q_on |= XFS_QUOTA_UDQ_ACCT;
569 if (q_on != 0) {
570 ret = quotactl(QCMD(Q_XQUOTAON,USRQUOTA),bdev, -1, (CADDR_T)&q_on);
571 } else {
572 ret = 0;
575 } else if (qflags & QUOTAS_ENABLED) {
576 if (F.qs_flags & XFS_QUOTA_UDQ_ENFD)
577 q_off |= XFS_QUOTA_UDQ_ENFD;
579 if (q_off != 0) {
580 ret = quotactl(QCMD(Q_XQUOTAOFF,USRQUOTA),bdev, -1, (CADDR_T)&q_off);
581 } else {
582 ret = 0;
585 if (!(F.qs_flags & XFS_QUOTA_UDQ_ACCT))
586 q_on |= XFS_QUOTA_UDQ_ACCT;
588 if (q_on != 0) {
589 ret = quotactl(QCMD(Q_XQUOTAON,USRQUOTA),bdev, -1, (CADDR_T)&q_on);
590 } else {
591 ret = 0;
593 } else {
594 #if 0
595 /* Switch on XFS_QUOTA_UDQ_ACCT didn't work!
596 * only swittching off XFS_QUOTA_UDQ_ACCT work
598 if (F.qs_flags & XFS_QUOTA_UDQ_ENFD)
599 q_off |= XFS_QUOTA_UDQ_ENFD;
600 if (F.qs_flags & XFS_QUOTA_UDQ_ACCT)
601 q_off |= XFS_QUOTA_UDQ_ACCT;
603 if (q_off !=0) {
604 ret = quotactl(QCMD(Q_XQUOTAOFF,USRQUOTA),bdev, -1, (CADDR_T)&q_off);
605 } else {
606 ret = 0;
608 #else
609 ret = -1;
610 #endif
613 break;
614 #ifdef HAVE_GROUP_QUOTA
615 case SMB_GROUP_FS_QUOTA_TYPE:
616 quotactl(QCMD(Q_XGETQSTAT,GRPQUOTA), bdev, -1, (CADDR_T)&F);
618 if (qflags & QUOTAS_DENY_DISK) {
619 if (!(F.qs_flags & XFS_QUOTA_UDQ_ENFD))
620 q_on |= XFS_QUOTA_UDQ_ENFD;
621 if (!(F.qs_flags & XFS_QUOTA_UDQ_ACCT))
622 q_on |= XFS_QUOTA_UDQ_ACCT;
624 if (q_on != 0) {
625 ret = quotactl(QCMD(Q_XQUOTAON,GRPQUOTA),bdev, -1, (CADDR_T)&q_on);
626 } else {
627 ret = 0;
630 } else if (qflags & QUOTAS_ENABLED) {
631 if (F.qs_flags & XFS_QUOTA_UDQ_ENFD)
632 q_off |= XFS_QUOTA_UDQ_ENFD;
634 if (q_off != 0) {
635 ret = quotactl(QCMD(Q_XQUOTAOFF,GRPQUOTA),bdev, -1, (CADDR_T)&q_off);
636 } else {
637 ret = 0;
640 if (!(F.qs_flags & XFS_QUOTA_UDQ_ACCT))
641 q_on |= XFS_QUOTA_UDQ_ACCT;
643 if (q_on != 0) {
644 ret = quotactl(QCMD(Q_XQUOTAON,GRPQUOTA),bdev, -1, (CADDR_T)&q_on);
645 } else {
646 ret = 0;
648 } else {
649 #if 0
650 /* Switch on XFS_QUOTA_UDQ_ACCT didn't work!
651 * only swittching off XFS_QUOTA_UDQ_ACCT work
653 if (F.qs_flags & XFS_QUOTA_UDQ_ENFD)
654 q_off |= XFS_QUOTA_UDQ_ENFD;
655 if (F.qs_flags & XFS_QUOTA_UDQ_ACCT)
656 q_off |= XFS_QUOTA_UDQ_ACCT;
658 if (q_off !=0) {
659 ret = quotactl(QCMD(Q_XQUOTAOFF,GRPQUOTA),bdev, -1, (CADDR_T)&q_off);
660 } else {
661 ret = 0;
663 #else
664 ret = -1;
665 #endif
668 break;
669 #endif /* HAVE_GROUP_QUOTA */
670 default:
671 errno = ENOSYS;
672 return -1;
675 return ret;
677 #endif /* HAVE_XFS_QUOTA */
693 /*********************************************************************
694 Now the list of all filesystem specific quota systems we have found
695 **********************************************************************/
696 static struct {
697 const char *name;
698 int (*get_quota)(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp);
699 int (*set_quota)(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp);
700 } sys_quota_backends[] = {
701 #ifdef HAVE_XFS_QUOTA
702 {"xfs", sys_get_xfs_quota, sys_set_xfs_quota},
703 #endif /* HAVE_XFS_QUOTA */
704 {NULL, NULL, NULL}
707 static int command_get_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
709 const char *get_quota_command;
711 get_quota_command = lp_get_quota_command();
712 if (get_quota_command && *get_quota_command) {
713 const char *p;
714 char *p2;
715 char **lines;
716 pstring syscmd;
717 int _id = -1;
719 switch(qtype) {
720 case SMB_USER_QUOTA_TYPE:
721 case SMB_USER_FS_QUOTA_TYPE:
722 _id = id.uid;
723 break;
724 case SMB_GROUP_QUOTA_TYPE:
725 case SMB_GROUP_FS_QUOTA_TYPE:
726 _id = id.gid;
727 break;
728 default:
729 DEBUG(0,("invalid quota type.\n"));
730 return -1;
733 slprintf(syscmd, sizeof(syscmd)-1,
734 "%s \"%s\" %d %d",
735 get_quota_command, path, qtype, _id);
737 DEBUG (3, ("get_quota: Running command %s\n", syscmd));
739 lines = file_lines_pload(syscmd, NULL);
740 if (lines) {
741 char *line = lines[0];
743 DEBUG (3, ("Read output from get_quota, \"%s\"\n", line));
745 /* we need to deal with long long unsigned here, if supported */
747 dp->qflags = (enum SMB_QUOTA_TYPE)strtoul(line, &p2, 10);
748 p = p2;
749 while (p && *p && isspace(*p))
750 p++;
751 if (p && *p)
752 dp->curblocks = STR_TO_SMB_BIG_UINT(p, &p);
753 else
754 goto invalid_param;
755 while (p && *p && isspace(*p))
756 p++;
757 if (p && *p)
758 dp->softlimit = STR_TO_SMB_BIG_UINT(p, &p);
759 else
760 goto invalid_param;
761 while (p && *p && isspace(*p))
762 p++;
763 if (p && *p)
764 dp->hardlimit = STR_TO_SMB_BIG_UINT(p, &p);
765 else
766 goto invalid_param;
767 while (p && *p && isspace(*p))
768 p++;
769 if (p && *p)
770 dp->curinodes = STR_TO_SMB_BIG_UINT(p, &p);
771 else
772 goto invalid_param;
773 while (p && *p && isspace(*p))
774 p++;
775 if (p && *p)
776 dp->isoftlimit = STR_TO_SMB_BIG_UINT(p, &p);
777 else
778 goto invalid_param;
779 while (p && *p && isspace(*p))
780 p++;
781 if (p && *p)
782 dp->ihardlimit = STR_TO_SMB_BIG_UINT(p, &p);
783 else
784 goto invalid_param;
785 while (p && *p && isspace(*p))
786 p++;
787 if (p && *p)
788 dp->bsize = STR_TO_SMB_BIG_UINT(p, NULL);
789 else
790 dp->bsize = 1024;
791 file_lines_free(lines);
792 DEBUG (3, ("Parsed output of get_quota, ...\n"));
794 #ifdef LARGE_SMB_OFF_T
795 DEBUGADD (5,(
796 "qflags:%u curblocks:%llu softlimit:%llu hardlimit:%llu\n"
797 "curinodes:%llu isoftlimit:%llu ihardlimit:%llu bsize:%llu\n",
798 dp->qflags,(long long unsigned)dp->curblocks,
799 (long long unsigned)dp->softlimit,(long long unsigned)dp->hardlimit,
800 (long long unsigned)dp->curinodes,
801 (long long unsigned)dp->isoftlimit,(long long unsigned)dp->ihardlimit,
802 (long long unsigned)dp->bsize));
803 #else /* LARGE_SMB_OFF_T */
804 DEBUGADD (5,(
805 "qflags:%u curblocks:%lu softlimit:%lu hardlimit:%lu\n"
806 "curinodes:%lu isoftlimit:%lu ihardlimit:%lu bsize:%lu\n",
807 dp->qflags,(long unsigned)dp->curblocks,
808 (long unsigned)dp->softlimit,(long unsigned)dp->hardlimit,
809 (long unsigned)dp->curinodes,
810 (long unsigned)dp->isoftlimit,(long unsigned)dp->ihardlimit,
811 (long unsigned)dp->bsize));
812 #endif /* LARGE_SMB_OFF_T */
813 return 0;
816 DEBUG (0, ("get_quota_command failed!\n"));
817 return -1;
820 errno = ENOSYS;
821 return -1;
823 invalid_param:
824 DEBUG(0,("The output of get_quota_command is invalid!\n"));
825 return -1;
828 static int command_set_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
830 const char *set_quota_command;
832 set_quota_command = lp_set_quota_command();
833 if (set_quota_command && *set_quota_command) {
834 char **lines;
835 pstring syscmd;
836 int _id = -1;
838 switch(qtype) {
839 case SMB_USER_QUOTA_TYPE:
840 case SMB_USER_FS_QUOTA_TYPE:
841 _id = id.uid;
842 break;
843 case SMB_GROUP_QUOTA_TYPE:
844 case SMB_GROUP_FS_QUOTA_TYPE:
845 _id = id.gid;
846 break;
847 default:
848 return -1;
851 #ifdef LARGE_SMB_OFF_T
852 slprintf(syscmd, sizeof(syscmd)-1,
853 "%s \"%s\" %d %d "
854 "%u %llu %llu "
855 "%llu %llu %llu ",
856 set_quota_command, path, qtype, _id, dp->qflags,
857 (long long unsigned)dp->softlimit,(long long unsigned)dp->hardlimit,
858 (long long unsigned)dp->isoftlimit,(long long unsigned)dp->ihardlimit,
859 (long long unsigned)dp->bsize);
860 #else /* LARGE_SMB_OFF_T */
861 slprintf(syscmd, sizeof(syscmd)-1,
862 "%s \"%s\" %d %d "
863 "%u %lu %lu "
864 "%lu %lu %lu ",
865 set_quota_command, path, qtype, _id, dp->qflags,
866 (long unsigned)dp->softlimit,(long unsigned)dp->hardlimit,
867 (long unsigned)dp->isoftlimit,(long unsigned)dp->ihardlimit,
868 (long unsigned)dp->bsize);
869 #endif /* LARGE_SMB_OFF_T */
873 DEBUG (3, ("get_quota: Running command %s\n", syscmd));
875 lines = file_lines_pload(syscmd, NULL);
876 if (lines) {
877 char *line = lines[0];
879 DEBUG (3, ("Read output from set_quota, \"%s\"\n", line));
881 file_lines_free(lines);
883 return 0;
885 DEBUG (0, ("set_quota_command failed!\n"));
886 return -1;
889 errno = ENOSYS;
890 return -1;
893 int sys_get_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
895 int ret = -1;
896 int i;
897 BOOL ready = False;
898 char *mntpath = NULL;
899 char *bdev = NULL;
900 char *fs = NULL;
902 if (!path||!dp)
903 smb_panic("sys_get_quota: called with NULL pointer");
905 if (command_get_quota(path, qtype, id, dp)==0) {
906 return 0;
907 } else if (errno != ENOSYS) {
908 return -1;
911 if ((ret=sys_path_to_bdev(path,&mntpath,&bdev,&fs))!=0) {
912 DEBUG(0,("sys_path_to_bdev() failed for path [%s]!\n",path));
913 return ret;
916 for (i=0;(fs && sys_quota_backends[i].name && sys_quota_backends[i].get_quota);i++) {
917 if (strcmp(fs,sys_quota_backends[i].name)==0) {
918 ret = sys_quota_backends[i].get_quota(mntpath, bdev, qtype, id, dp);
919 if (ret!=0) {
920 DEBUG(10,("sys_get_%s_quota() failed for mntpath[%s] bdev[%s] qtype[%d] id[%d] ret[%d].\n",
921 fs,mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid),ret));
923 ready = True;
924 break;
928 if (!ready) {
929 /* use the default vfs quota functions */
930 ret=sys_get_vfs_quota(mntpath, bdev, qtype, id, dp);
931 if (ret!=0) {
932 DEBUG(10,("sys_get_%s_quota() failed for mntpath[%s] bdev[%s] qtype[%d] id[%d] ret[%d].\n",
933 "vfs",mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid),ret));
937 SAFE_FREE(mntpath);
938 SAFE_FREE(bdev);
939 SAFE_FREE(fs);
941 if ((ret!=0)&& (errno == EDQUOT)) {
942 return 0;
945 return ret;
948 int sys_set_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
950 int ret = -1;
951 int i;
952 BOOL ready = False;
953 char *mntpath = NULL;
954 char *bdev = NULL;
955 char *fs = NULL;
957 /* find the block device file */
959 if (!path||!dp)
960 smb_panic("get_smb_quota: called with NULL pointer");
962 if (command_set_quota(path, qtype, id, dp)==0) {
963 return 0;
964 } else if (errno != ENOSYS) {
965 return -1;
968 if ((ret=sys_path_to_bdev(path,&mntpath,&bdev,&fs))!=0) {
969 DEBUG(0,("sys_path_to_bdev() failed for path [%s]!\n",path));
970 return ret;
973 for (i=0;(fs && sys_quota_backends[i].name && sys_quota_backends[i].set_quota);i++) {
974 if (strcmp(fs,sys_quota_backends[i].name)==0) {
975 ret = sys_quota_backends[i].set_quota(mntpath, bdev, qtype, id, dp);
976 if (ret!=0) {
977 DEBUG(10,("sys_set_%s_quota() failed for mntpath[%s] bdev[%s] qtype[%d] id[%d] ret[%d].\n",
978 fs,mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid),ret));
980 ready = True;
981 break;
985 if (!ready) {
986 /* use the default vfs quota functions */
987 ret=sys_set_vfs_quota(mntpath, bdev, qtype, id, dp);
988 if (ret!=0) {
989 DEBUG(10,("sys_set_%s_quota() failed for mntpath[%s] bdev[%s] qtype[%d] id[%d] ret[%d].\n",
990 "vfs",mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid),ret));
994 SAFE_FREE(mntpath);
995 SAFE_FREE(bdev);
996 SAFE_FREE(fs);
998 if ((ret!=0)&& (errno == EDQUOT)) {
999 return 0;
1002 return ret;
1005 #else /* HAVE_SYS_QUOTAS */
1006 void dummy_sysquotas_c(void)
1008 return;
1010 #endif /* HAVE_SYS_QUOTAS */