ading new files from 3.0
[Samba/gebeck_regimport.git] / source / lib / sysquotas.c
blobefc9e65b9de71a28de28cce386f3d87cda6e4549
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 #ifndef AUTOCONF_TEST
24 #include "includes.h"
26 #ifdef HAVE_SYS_QUOTAS
28 #if defined(HAVE_QUOTACTL_4A)
29 /* long quotactl(int cmd, char *special, qid_t id, caddr_t addr) */
30 /* this is used by: linux,HPUX,IRIX */
32 /****************************************************************************
33 Abstract out the old and new Linux quota get calls.
34 ****************************************************************************/
35 static int sys_get_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
37 int ret = -1;
38 uint32 qflags = 0;
39 struct SYS_DQBLK D;
40 SMB_BIG_UINT bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
42 if (!path||!bdev||!dp)
43 smb_panic("sys_get_vfs_quota: called with NULL pointer");
45 ZERO_STRUCT(D);
46 ZERO_STRUCT(*dp);
47 dp->qtype = qtype;
49 switch (qtype) {
50 case SMB_USER_QUOTA_TYPE:
51 /* we use id.uid == 0 for default quotas */
52 if (id.uid == 0) {
53 ret = 0;
54 break;
57 if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (CADDR_T)&D))) {
58 return ret;
61 if ((D.dqb_curblocks==0)&&
62 (D.dqb_bsoftlimit==0)&&
63 (D.dqb_bhardlimit==0)) {
64 /* the upper layer functions don't want empty quota records...*/
65 return -1;
68 break;
69 #ifdef HAVE_GROUP_QUOTA
70 case SMB_GROUP_QUOTA_TYPE:
71 if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id.gid, (CADDR_T)&D))) {
72 return ret;
75 if ((D.dqb_curblocks==0)&&
76 (D.dqb_bsoftlimit==0)&&
77 (D.dqb_bhardlimit==0)) {
78 /* the upper layer functions don't want empty quota records...*/
79 return -1;
82 break;
83 #endif /* HAVE_GROUP_QUOTA */
84 case SMB_USER_FS_QUOTA_TYPE:
85 id.uid = getuid();
87 if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (CADDR_T)&D))==0) {
88 qflags |= QUOTAS_DENY_DISK;
91 /* get the default quotas stored in the root's (uid =0) record */
92 if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, 0, (CADDR_T)&D))) {
93 return ret;
96 ret = 0;
97 break;
98 default:
99 errno = ENOSYS;
100 return -1;
103 dp->bsize = bsize;
104 dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit;
105 dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit;
106 dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit;
107 dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit;
108 dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes;
109 dp->curblocks = (SMB_BIG_UINT)D.dqb_curblocks;
112 dp->qflags = qflags;
114 return ret;
117 /****************************************************************************
118 Abstract out the old and new Linux quota set calls.
119 ****************************************************************************/
121 static int sys_set_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
123 int ret = -1;
124 uint32 qflags = 0;
125 struct SYS_DQBLK D;
126 SMB_BIG_UINT bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
128 if (!path||!bdev||!dp)
129 smb_panic("sys_set_vfs_quota: called with NULL pointer");
131 ZERO_STRUCT(D);
133 if (bsize == dp->bsize) {
134 D.dqb_bsoftlimit = dp->softlimit;
135 D.dqb_bhardlimit = dp->hardlimit;
136 D.dqb_ihardlimit = dp->ihardlimit;
137 D.dqb_isoftlimit = dp->isoftlimit;
138 } else {
139 D.dqb_bsoftlimit = (dp->softlimit*dp->bsize)/bsize;
140 D.dqb_bhardlimit = (dp->hardlimit*dp->bsize)/bsize;
141 D.dqb_ihardlimit = (dp->ihardlimit*dp->bsize)/bsize;
142 D.dqb_isoftlimit = (dp->isoftlimit*dp->bsize)/bsize;
145 qflags = dp->qflags;
147 switch (qtype) {
148 case SMB_USER_QUOTA_TYPE:
149 /* we use id.uid == 0 for default quotas */
150 if (id.uid>0) {
151 ret = quotactl(QCMD(Q_SETQLIM,USRQUOTA), bdev, id.uid, (CADDR_T)&D);
153 break;
154 #ifdef HAVE_GROUP_QUOTA
155 case SMB_GROUP_QUOTA_TYPE:
156 ret = quotactl(QCMD(Q_SETQLIM,GRPQUOTA), bdev, id.gid, (CADDR_T)&D);
157 break;
158 #endif /* HAVE_GROUP_QUOTA */
159 case SMB_USER_FS_QUOTA_TYPE:
160 /* this stuff didn't work as it should:
161 * switching on/off quota via quotactl()
162 * didn't work!
163 * So we only set the default limits
164 * --metze
166 * On HPUX we didn't have the mount path,
167 * we need to fix sys_path_to_bdev()
170 #if 0
171 uid = getuid();
173 ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, uid, (CADDR_T)&D);
175 if ((qflags&QUOTAS_DENY_DISK)||(qflags&QUOTAS_ENABLED)) {
176 if (ret == 0) {
177 char *quota_file = NULL;
179 asprintf(&quota_file,"/%s/%s%s",path, QUOTAFILENAME,USERQUOTAFILE_EXTENSION);
180 if (quota_file == NULL) {
181 DEBUG(0,("asprintf() failed!\n"));
182 errno = ENOMEM;
183 return -1;
186 ret = quotactl(QCMD(Q_QUOTAON,USRQUOTA), bdev, -1,(CADDR_T)quota_file);
187 } else {
188 ret = 0;
190 } else {
191 if (ret != 0) {
192 /* turn off */
193 ret = quotactl(QCMD(Q_QUOTAOFF,USRQUOTA), bdev, -1, (CADDR_T)0);
194 } else {
195 ret = 0;
199 DEBUG(0,("vfs_fs_quota: ret(%d) errno(%d)[%s] uid(%d) bdev[%s]\n",
200 ret,errno,strerror(errno),uid,bdev));
201 #endif
203 /* we use uid == 0 for default quotas */
204 ret = quotactl(QCMD(Q_SETQLIM,USRQUOTA), bdev, 0, (CADDR_T)&D);
206 break;
208 default:
209 errno = ENOSYS;
210 return -1;
213 return ret;
216 /*#endif HAVE_QUOTACTL_4A */
217 #elif defined(HAVE_QUOTACTL_4B)
219 #error HAVE_QUOTACTL_4B not implemeted
221 /*#endif HAVE_QUOTACTL_4B */
222 #elif defined(HAVE_QUOTACTL_3)
224 #error HAVE_QUOTACTL_3 not implemented
226 /* #endif HAVE_QUOTACTL_3 */
227 #else /* NO_QUOTACTL_USED */
229 static int sys_get_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
231 int ret = -1;
233 if (!path||!bdev||!dp)
234 smb_panic("sys_get_vfs_quota: called with NULL pointer");
236 errno = ENOSYS;
238 return ret;
241 static int sys_set_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
243 int ret = -1;
245 if (!path||!bdev||!dp)
246 smb_panic("sys_set_vfs_quota: called with NULL pointer");
248 errno = ENOSYS;
250 return ret;
253 #endif /* NO_QUOTACTL_USED */
255 #ifdef HAVE_MNTENT
256 static int sys_path_to_bdev(const char *path, char **mntpath, char **bdev, char **fs)
258 int ret = -1;
259 SMB_STRUCT_STAT S;
260 FILE *fp;
261 struct mntent *mnt;
262 SMB_DEV_T devno;
264 /* find the block device file */
266 if (!path||!mntpath||!bdev||!fs)
267 smb_panic("sys_path_to_bdev: called with NULL pointer");
269 (*mntpath) = NULL;
270 (*bdev) = NULL;
271 (*fs) = NULL;
273 if ( sys_stat(path, &S) == -1 )
274 return (-1);
276 devno = S.st_dev ;
278 fp = setmntent(MOUNTED,"r");
280 while ((mnt = getmntent(fp))) {
281 if ( sys_stat(mnt->mnt_dir,&S) == -1 )
282 continue ;
284 if (S.st_dev == devno) {
285 (*mntpath) = strdup(mnt->mnt_dir);
286 (*bdev) = strdup(mnt->mnt_fsname);
287 (*fs) = strdup(mnt->mnt_type);
288 if ((*mntpath)&&(*bdev)&&(*fs)) {
289 ret = 0;
290 } else {
291 SAFE_FREE(*mntpath);
292 SAFE_FREE(*bdev);
293 SAFE_FREE(*fs);
294 ret = -1;
297 break;
301 endmntent(fp) ;
303 return ret;
305 /* #endif HAVE_MNTENT */
306 #elif defined(HAVE_DEVNM)
308 /* we have this on HPUX, ... */
309 static int sys_path_to_bdev(const char *path, char **mntpath, char **bdev, char **fs)
311 int ret = -1;
312 char dev_disk[256];
313 SMB_STRUCT_STAT S;
315 if (!path||!mntpath||!bdev||!fs)
316 smb_panic("sys_path_to_bdev: called with NULL pointer");
318 (*mntpath) = NULL;
319 (*bdev) = NULL;
320 (*fs) = NULL;
322 /* find the block device file */
324 if ((ret=sys_stat(path, &S))!=0) {
325 return ret;
328 if ((ret=devnm(S_IFBLK, S.st_dev, dev_disk, 256, 1))!=0) {
329 return ret;
332 /* we should get the mntpath right...
333 * but I don't know how
334 * --metze
336 (*mntpath) = strdup(path);
337 (*bdev) = strdup(dev_disk);
338 if ((*mntpath)&&(*bdev)) {
339 ret = 0;
340 } else {
341 SAFE_FREE(*mntpath);
342 SAFE_FREE(*bdev);
343 ret = -1;
347 return ret;
350 /* #endif HAVE_DEVNM */
351 #else
352 /* we should fake this up...*/
353 static int sys_path_to_bdev(const char *path, char **mntpath, char **bdev, char **fs)
355 int ret = -1;
357 if (!path||!mntpath||!bdev||!fs)
358 smb_panic("sys_path_to_bdev: called with NULL pointer");
360 (*mntpath) = NULL;
361 (*bdev) = NULL;
362 (*fs) = NULL;
364 (*mntpath) = strdup(path);
365 if (*mntpath) {
366 ret = 0;
367 } else {
368 SAFE_FREE(*mntpath);
369 ret = -1;
372 return ret;
374 #endif
377 /*********************************************************
378 if we have XFS QUOTAS we should use them
379 *********************************************************/
380 #ifdef HAVE_XFS_QUOTA
381 /****************************************************************************
382 Abstract out the XFS Quota Manager quota get call.
383 ****************************************************************************/
384 static int sys_get_xfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
386 int ret;
387 uint32 qflags = 0;
388 SMB_BIG_UINT bsize = (SMB_BIG_UINT)BBSIZE;
389 struct fs_disk_quota D;
390 struct fs_quota_stat F;
391 ZERO_STRUCT(D);
392 ZERO_STRUCT(F);
394 if (!bdev||!dp)
395 smb_panic("sys_get_xfs_quota: called with NULL pointer");
397 ZERO_STRUCT(*dp);
398 dp->qtype = qtype;
400 switch (qtype) {
401 case SMB_USER_QUOTA_TYPE:
402 /* we use id.uid == 0 for default quotas */
403 if (id.uid == 0) {
404 ret = 0;
405 break;
407 if ((ret=quotactl(QCMD(Q_XGETQUOTA,USRQUOTA), bdev, id.uid, (CADDR_T)&D)))
408 return ret;
409 break;
410 #ifdef HAVE_GROUP_QUOTA
411 case SMB_GROUP_QUOTA_TYPE:
412 if ((ret=quotactl(QCMD(Q_XGETQUOTA,GRPQUOTA), bdev, id.gid, (CADDR_T)&D)))
413 return ret;
414 break;
415 #endif /* HAVE_GROUP_QUOTA */
416 case SMB_USER_FS_QUOTA_TYPE:
417 /* TODO: get quota status from quotactl() ... */
418 if ((ret = quotactl(QCMD(Q_XGETQSTAT,USRQUOTA), bdev, -1, (CADDR_T)&F)))
419 return ret;
421 if (F.qs_flags & XFS_QUOTA_UDQ_ENFD) {
422 qflags |= QUOTAS_DENY_DISK;
424 else if (F.qs_flags & XFS_QUOTA_UDQ_ACCT) {
425 qflags |= QUOTAS_ENABLED;
428 /* we use uid == 0 for default quotas */
429 if ((ret=quotactl(QCMD(Q_XGETQUOTA,USRQUOTA), bdev, 0, (CADDR_T)&D)))
430 return ret;
432 break;
433 default:
434 errno = ENOSYS;
435 return -1;
438 dp->bsize = bsize;
439 dp->softlimit = (SMB_BIG_UINT)D.d_blk_softlimit;
440 dp->hardlimit = (SMB_BIG_UINT)D.d_blk_hardlimit;
441 dp->ihardlimit = (SMB_BIG_UINT)D.d_ino_hardlimit;
442 dp->isoftlimit = (SMB_BIG_UINT)D.d_ino_softlimit;
443 dp->curinodes = (SMB_BIG_UINT)D.d_icount;
444 dp->curblocks = (SMB_BIG_UINT)D.d_bcount;
445 dp->qflags = qflags;
447 return ret;
450 /****************************************************************************
451 Abstract out the XFS Quota Manager quota set call.
452 ****************************************************************************/
453 static int sys_set_xfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
455 int ret = -1;
456 uint32 qflags = 0;
457 SMB_BIG_UINT bsize = (SMB_BIG_UINT)BBSIZE;
458 struct fs_disk_quota D;
459 struct fs_quota_stat F;
460 int q_on = 0;
461 int q_off = 0;
462 ZERO_STRUCT(D);
463 ZERO_STRUCT(F);
465 if (!bdev||!dp)
466 smb_panic("sys_set_xfs_quota: called with NULL pointer");
468 if (bsize == dp->bsize) {
469 D.d_blk_softlimit = dp->softlimit;
470 D.d_blk_hardlimit = dp->hardlimit;
471 D.d_ino_hardlimit = dp->ihardlimit;
472 D.d_ino_softlimit = dp->isoftlimit;
473 } else {
474 D.d_blk_softlimit = (dp->softlimit*dp->bsize)/bsize;
475 D.d_blk_hardlimit = (dp->hardlimit*dp->bsize)/bsize;
476 D.d_ino_hardlimit = (dp->ihardlimit*dp->bsize)/bsize;
477 D.d_ino_softlimit = (dp->isoftlimit*dp->bsize)/bsize;
480 qflags = dp->qflags;
482 switch (qtype) {
483 case SMB_USER_QUOTA_TYPE:
484 /* we use uid == 0 for default quotas */
485 if (id.uid>0) {
486 D.d_fieldmask |= FS_DQ_LIMIT_MASK;
487 ret = quotactl(QCMD(Q_XSETQLIM,USRQUOTA), bdev, id.uid, (CADDR_T)&D);
489 break;
490 #ifdef HAVE_GROUP_QUOTA
491 case SMB_GROUP_QUOTA_TYPE:
492 D.d_fieldmask |= FS_DQ_LIMIT_MASK;
493 ret = quotactl(QCMD(Q_XSETQLIM,GRPQUOTA), bdev, id.gid, (CADDR_T)&D);
494 break;
495 #endif /* HAVE_GROUP_QUOTA */
496 case SMB_USER_FS_QUOTA_TYPE:
497 /* TODO */
498 quotactl(QCMD(Q_XGETQSTAT,USRQUOTA), bdev, -1, (CADDR_T)&F);
500 if (qflags & QUOTAS_DENY_DISK) {
501 if (!(F.qs_flags & XFS_QUOTA_UDQ_ENFD))
502 q_on |= XFS_QUOTA_UDQ_ENFD;
503 if (!(F.qs_flags & XFS_QUOTA_UDQ_ACCT))
504 q_on |= XFS_QUOTA_UDQ_ACCT;
506 if (q_on != 0) {
507 ret = quotactl(QCMD(Q_XQUOTAON,USRQUOTA),bdev, -1, (CADDR_T)&q_on);
510 } else if (qflags & QUOTAS_ENABLED) {
511 if (F.qs_flags & XFS_QUOTA_UDQ_ENFD)
512 q_off |= XFS_QUOTA_UDQ_ENFD;
514 if (q_off != 0) {
515 ret = quotactl(QCMD(Q_XQUOTAOFF,USRQUOTA),bdev, -1, (CADDR_T)&q_off);
518 if (!(F.qs_flags & XFS_QUOTA_UDQ_ACCT))
519 q_on |= XFS_QUOTA_UDQ_ACCT;
521 if (q_on != 0) {
522 ret = quotactl(QCMD(Q_XQUOTAON,USRQUOTA),bdev, -1, (CADDR_T)&q_on);
524 } else {
525 #if 0
526 /* Switch on XFS_QUOTA_UDQ_ACCT didn't work!
527 * only swittching off XFS_QUOTA_UDQ_ACCT work
529 if (F.qs_flags & XFS_QUOTA_UDQ_ENFD)
530 q_off |= XFS_QUOTA_UDQ_ENFD;
531 if (F.qs_flags & XFS_QUOTA_UDQ_ACCT)
532 q_off |= XFS_QUOTA_UDQ_ACCT;
534 if (q_off !=0) {
535 ret = quotactl(QCMD(Q_XQUOTAOFF,USRQUOTA),bdev, -1, (CADDR_T)&q_off);
537 #endif
540 /* we use uid == 0 for default quotas */
541 D.d_fieldmask |= FS_DQ_LIMIT_MASK;
542 ret = quotactl(QCMD(Q_XSETQLIM,USRQUOTA), bdev, 0, (CADDR_T)&D);
543 break;
544 default:
545 errno = ENOSYS;
546 return -1;
549 return ret;
551 #endif /* HAVE_XFS_QUOTA */
567 /*********************************************************************
568 Now the list of all filesystem specific quota systems we have found
569 **********************************************************************/
570 static struct {
571 const char *name;
572 int (*get_quota)(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp);
573 int (*set_quota)(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp);
574 } sys_quota_backends[] = {
575 #ifdef HAVE_XFS_QUOTA
576 {"xfs", sys_get_xfs_quota, sys_set_xfs_quota},
577 #endif /* HAVE_XFS_QUOTA */
578 {NULL, NULL, NULL}
581 static int command_get_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
583 const char *get_quota_command;
585 get_quota_command = lp_get_quota_command();
586 if (get_quota_command && *get_quota_command) {
587 const char *p;
588 char *p2;
589 char **lines;
590 pstring syscmd;
591 int _id = -1;
593 switch(qtype) {
594 case SMB_USER_QUOTA_TYPE:
595 case SMB_USER_FS_QUOTA_TYPE:
596 _id = id.uid;
597 break;
598 case SMB_GROUP_QUOTA_TYPE:
599 case SMB_GROUP_FS_QUOTA_TYPE:
600 _id = id.gid;
601 break;
602 default:
603 DEBUG(0,("invalid quota type.\n"));
604 return -1;
607 slprintf(syscmd, sizeof(syscmd)-1,
608 "%s \"%s\" %d %d",
609 get_quota_command, path, qtype, _id);
611 DEBUG (3, ("get_quota: Running command %s\n", syscmd));
613 lines = file_lines_pload(syscmd, NULL);
614 if (lines) {
615 char *line = lines[0];
617 DEBUG (3, ("Read output from get_quota, \"r%s\"\n", line));
619 /* we need to deal with long long unsigned here, if supported */
621 dp->qflags = (enum SMB_QUOTA_TYPE)strtoul(line, &p2, 10);
622 p = p2;
623 while (p && *p && isspace(*p))
624 p++;
625 if (p && *p)
626 dp->curblocks = STR_TO_SMB_BIG_UINT(p, &p);
627 else
628 goto invalid_param;
629 while (p && *p && isspace(*p))
630 p++;
631 if (p && *p)
632 dp->softlimit = STR_TO_SMB_BIG_UINT(p, &p);
633 else
634 goto invalid_param;
635 while (p && *p && isspace(*p))
636 p++;
637 if (p && *p)
638 dp->hardlimit = STR_TO_SMB_BIG_UINT(p, &p);
639 else
640 goto invalid_param;
641 while (p && *p && isspace(*p))
642 p++;
643 if (p && *p)
644 dp->curinodes = STR_TO_SMB_BIG_UINT(p, &p);
645 else
646 goto invalid_param;
647 while (p && *p && isspace(*p))
648 p++;
649 if (p && *p)
650 dp->isoftlimit = STR_TO_SMB_BIG_UINT(p, &p);
651 else
652 goto invalid_param;
653 while (p && *p && isspace(*p))
654 p++;
655 if (p && *p)
656 dp->ihardlimit = STR_TO_SMB_BIG_UINT(p, &p);
657 else
658 goto invalid_param;
659 while (p && *p && isspace(*p))
660 p++;
661 if (p && *p)
662 dp->bsize = STR_TO_SMB_BIG_UINT(p, NULL);
663 else
664 dp->bsize = 1024;
665 file_lines_free(lines);
666 DEBUG (3, ("Parsed output of get_quota, ...\n"));
668 #ifdef LARGE_SMB_OFF_T
669 DEBUGADD (5,(
670 "qflags:%u curblocks:%llu softlimit:%llu hardlimit:%llu\n"
671 "curinodes:%llu isoftlimit:%llu ihardlimit:%llu bsize:%llu\n",
672 dp->qflags,(long long unsigned)dp->curblocks,
673 (long long unsigned)dp->softlimit,(long long unsigned)dp->hardlimit,
674 (long long unsigned)dp->curinodes,
675 (long long unsigned)dp->isoftlimit,(long long unsigned)dp->ihardlimit,
676 (long long unsigned)dp->bsize));
677 #else /* LARGE_SMB_OFF_T */
678 DEBUGADD (5,(
679 "qflags:%u curblocks:%lu softlimit:%lu hardlimit:%lu\n"
680 "curinodes:%lu isoftlimit:%lu ihardlimit:%lu bsize:%lu\n",
681 dp->qflags,(long unsigned)dp->curblocks,
682 (long unsigned)dp->softlimit,(long unsigned)dp->hardlimit,
683 (long unsigned)dp->curinodes,
684 (long unsigned)dp->isoftlimit,(long unsigned)dp->ihardlimit,
685 (long unsigned)dp->bsize));
686 #endif /* LARGE_SMB_OFF_T */
687 return 0;
690 DEBUG (0, ("get_quota_command failed!\n"));
691 return -1;
694 errno = ENOSYS;
695 return -1;
697 invalid_param:
698 DEBUG(0,("The output of get_quota_command is invalid!\n"));
699 return -1;
702 static int command_set_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
704 const char *set_quota_command;
706 set_quota_command = lp_set_quota_command();
707 if (set_quota_command && *set_quota_command) {
708 char **lines;
709 pstring syscmd;
710 int _id = -1;
712 switch(qtype) {
713 case SMB_USER_QUOTA_TYPE:
714 case SMB_USER_FS_QUOTA_TYPE:
715 _id = id.uid;
716 break;
717 case SMB_GROUP_QUOTA_TYPE:
718 case SMB_GROUP_FS_QUOTA_TYPE:
719 _id = id.gid;
720 break;
721 default:
722 return -1;
725 #ifdef LARGE_SMB_OFF_T
726 slprintf(syscmd, sizeof(syscmd)-1,
727 "%s \"%s\" %d %d "
728 "%u %llu %llu "
729 "%llu %llu %llu ",
730 set_quota_command, path, qtype, _id, dp->qflags,
731 (long long unsigned)dp->softlimit,(long long unsigned)dp->hardlimit,
732 (long long unsigned)dp->isoftlimit,(long long unsigned)dp->ihardlimit,
733 (long long unsigned)dp->bsize);
734 #else /* LARGE_SMB_OFF_T */
735 slprintf(syscmd, sizeof(syscmd)-1,
736 "%s \"%s\" %d %d "
737 "%u %lu %lu "
738 "%lu %lu %lu ",
739 set_quota_command, path, qtype, _id, dp->qflags,
740 (long unsigned)dp->softlimit,(long unsigned)dp->hardlimit,
741 (long unsigned)dp->isoftlimit,(long unsigned)dp->ihardlimit,
742 (long unsigned)dp->bsize);
743 #endif /* LARGE_SMB_OFF_T */
747 DEBUG (3, ("get_quota: Running command %s\n", syscmd));
749 lines = file_lines_pload(syscmd, NULL);
750 if (lines) {
751 char *line = lines[0];
753 DEBUG (3, ("Read output from set_quota, \"%s\"\n", line));
755 file_lines_free(lines);
757 return 0;
759 DEBUG (0, ("set_quota_command failed!\n"));
760 return -1;
763 errno = ENOSYS;
764 return -1;
767 int sys_get_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
769 int ret = -1;
770 int i;
771 BOOL ready = False;
772 char *mntpath = NULL;
773 char *bdev = NULL;
774 char *fs = NULL;
776 if (!path||!dp)
777 smb_panic("sys_get_quota: called with NULL pointer");
779 if (command_get_quota(path, qtype, id, dp)==0) {
780 return 0;
781 } else if (errno != ENOSYS) {
782 return -1;
785 if ((ret=sys_path_to_bdev(path,&mntpath,&bdev,&fs))!=0) {
786 return ret;
789 for (i=0;(fs && sys_quota_backends[i].name && sys_quota_backends[i].get_quota);i++) {
790 if (strcmp(fs,sys_quota_backends[i].name)==0) {
791 ret = sys_quota_backends[i].get_quota(mntpath, bdev, qtype, id, dp);
792 ready = True;
793 break;
797 if (!ready) {
798 /* use the default vfs quota functions */
799 ret = sys_get_vfs_quota(mntpath, bdev, qtype, id, dp);
802 SAFE_FREE(mntpath);
803 SAFE_FREE(bdev);
804 SAFE_FREE(fs);
806 if ((ret!=0)&& (errno == EDQUOT)) {
807 return 0;
810 return ret;
813 int sys_set_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
815 int ret = -1;
816 int i;
817 BOOL ready = False;
818 char *mntpath = NULL;
819 char *bdev = NULL;
820 char *fs = NULL;
822 /* find the block device file */
824 if (!path||!dp)
825 smb_panic("get_smb_quota: called with NULL pointer");
827 if (command_set_quota(path, qtype, id, dp)==0) {
828 return 0;
829 } else if (errno != ENOSYS) {
830 return -1;
833 if ((ret=sys_path_to_bdev(path,&mntpath,&bdev,&fs))!=0) {
834 return ret;
837 for (i=0;(fs && sys_quota_backends[i].name && sys_quota_backends[i].set_quota);i++) {
838 if (strcmp(fs,sys_quota_backends[i].name)==0) {
839 ret = sys_quota_backends[i].set_quota(mntpath, bdev, qtype, id, dp);
840 ready = True;
841 break;
845 if (!ready) {
846 /* use the default vfs quota functions */
847 ret=sys_set_vfs_quota(mntpath, bdev, qtype, id, dp);
850 SAFE_FREE(mntpath);
851 SAFE_FREE(bdev);
852 SAFE_FREE(fs);
854 if ((ret!=0)&& (errno == EDQUOT)) {
855 return 0;
858 return ret;
861 #else /* HAVE_SYS_QUOTAS */
862 void dummy_sysquotas_c(void)
864 return;
866 #endif /* HAVE_SYS_QUOTAS */
868 #else /* ! AUTOCONF_TEST */
869 /* this is the autoconf driver to test witch quota system we should use */
871 #if defined(HAVE_QUOTACTL_4A)
872 /* long quotactl(int cmd, char *special, qid_t id, caddr_t addr) */
874 #ifdef HAVE_SYS_TYPES_H
875 #include <sys/types.h>
876 #endif
878 #ifdef HAVE_ASM_TYPES_H
879 #include <asm/types.h>
880 #endif
882 #if defined(HAVE_LINUX_QUOTA_H)
883 # include <linux/quota.h>
884 # if defined(HAVE_STRUCT_IF_DQBLK)
885 # define SYS_DQBLK if_dqblk
886 # elif defined(HAVE_STRUCT_MEM_DQBLK)
887 # define SYS_DQBLK mem_dqblk
888 # endif
889 #elif defined(HAVE_SYS_QUOTA_H)
890 # include <sys/quota.h>
891 #endif
893 #ifndef SYS_DQBLK
894 #define SYS_DQBLK dqblk
895 #endif
897 int autoconf_quota(void)
899 int ret = -1;
900 struct SYS_DQBLK D;
902 ret = quotactl(Q_GETQUOTA,"/dev/hda1",0,(void *)&D);
904 return ret;
907 #elif defined(HAVE_QUOTACTL_4B)
908 /* int quotactl(const char *path, int cmd, int id, char *addr); */
910 #ifdef HAVE_SYS_QUOTA_H
911 #include <sys/quota.h>
912 #else /* *BSD */
913 #include <sys/types.h>
914 #include <ufs/ufs/quota.h>
915 #include <machine/param.h>
916 #endif
918 int autoconf_quota(void)
920 int ret = -1;
921 struct dqblk D;
923 ret = quotactl("/",Q_GETQUOTA,0,(char *) &D);
925 return ret;
928 #elif defined(HAVE_QUOTACTL_3)
929 /* int quotactl (char *spec, int request, char *arg); */
931 #ifdef HAVE_SYS_TYPES_H
932 #include <sys/types.h>
933 #endif
934 #ifdef HAVE_SYS_QUOTA_H
935 #include <sys/quota.h>
936 #endif
938 int autoconf_quota(void)
940 int ret = -1;
941 struct q_request request;
943 ret = quotactl("/", Q_GETQUOTA, &request);
945 return ret;
948 #elif defined(HAVE_QUOTACTL_2)
950 #error HAVE_QUOTACTL_2 not implemented
952 #else
954 #error Unknow QUOTACTL prototype
956 #endif
958 int main(void)
960 autoconf_quota();
961 return 0;
963 #endif /* AUTOCONF_TEST */