1/* 2 Unix SMB/Netbios implementation. 3 Version 1.9. 4 support for quotas 5 Copyright (C) Andrew Tridgell 1992-1998 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 2 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program; if not, write to the Free Software 19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20*/ 21 22 23/* 24 * This is one of the most system dependent parts of Samba, and its 25 * done a litle differently. Each system has its own way of doing 26 * things :-( 27 */ 28 29#include "includes.h" 30 31extern int DEBUGLEVEL; 32 33#if defined(VXFS_QUOTA) 34 35/* 36 * In addition to their native filesystems, some systems have Veritas VxFS. 37 * Declare here, define at end: reduces likely "include" interaction problems. 38 * David Lee <T.D.Lee@durham.ac.uk> 39 */ 40static BOOL disk_quotas_vxfs(const pstring name, char *path, 41 SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, 42 SMB_BIG_UINT *dsize); 43 44#endif /* VXFS_QUOTA */ 45 46#ifdef LINUX 47 48#include <sys/types.h> 49#include <asm/types.h> 50#include <sys/quota.h> 51 52#include <mntent.h> 53#include <linux/unistd.h> 54 55_syscall4(int, quotactl, int, cmd, const char *, special, int, id, caddr_t, addr); 56 57/**************************************************************************** 58try to get the disk space from disk quotas (LINUX version) 59****************************************************************************/ 60 61BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) 62{ 63 int r; 64 struct dqblk D; 65 SMB_STRUCT_STAT S; 66 FILE *fp; 67 struct mntent *mnt; 68 SMB_DEV_T devno; 69 int found; 70 uid_t euser_id; 71 72 euser_id = geteuid(); 73 74 /* find the block device file */ 75 76 if ( sys_stat(path, &S) == -1 ) { 77 return(False) ; 78 } 79 80 devno = S.st_dev ; 81 82 fp = setmntent(MOUNTED,"r"); 83 found = False ; 84 85 while ((mnt = getmntent(fp))) { 86 if ( sys_stat(mnt->mnt_dir,&S) == -1 ) 87 continue ; 88 if (S.st_dev == devno) { 89 found = True ; 90 break ; 91 } 92 } 93 endmntent(fp) ; 94 95 if (!found) { 96 return(False); 97 } 98 99 save_re_uid(); 100 set_effective_uid(0); 101 r=quotactl(QCMD(Q_GETQUOTA,USRQUOTA), mnt->mnt_fsname, euser_id, (caddr_t)&D); 102 restore_re_uid(); 103 104 /* Use softlimit to determine disk space, except when it has been exceeded */ 105 *bsize = 1024; 106 if (r) 107 { 108 if (errno == EDQUOT) 109 { 110 *dfree =0; 111 *dsize =D.dqb_curblocks; 112 return (True); 113 } 114 else return(False); 115 } 116 /* Use softlimit to determine disk space, except when it has been exceeded */ 117 if ( 118 (D.dqb_bsoftlimit && D.dqb_curblocks>=D.dqb_bsoftlimit) || 119 (D.dqb_bhardlimit && D.dqb_curblocks>=D.dqb_bhardlimit) || 120 (D.dqb_isoftlimit && D.dqb_curinodes>=D.dqb_isoftlimit) || 121 (D.dqb_ihardlimit && D.dqb_curinodes>=D.dqb_ihardlimit) 122 ) 123 { 124 *dfree = 0; 125 *dsize = D.dqb_curblocks; 126 } 127 else if (D.dqb_bsoftlimit==0 && D.dqb_bhardlimit==0) 128 { 129 return(False); 130 } 131 else { 132 if (D.dqb_bsoftlimit == 0) 133 D.dqb_bsoftlimit = D.dqb_bhardlimit; 134 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks; 135 *dsize = D.dqb_bsoftlimit; 136 } 137 return (True); 138} 139 140#elif defined(CRAY) 141 142#include <sys/quota.h> 143#include <mntent.h> 144 145/**************************************************************************** 146try to get the disk space from disk quotas (CRAY VERSION) 147****************************************************************************/ 148 149BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) 150{ 151 struct mntent *mnt; 152 FILE *fd; 153 SMB_STRUCT_STAT sbuf; 154 SMB_DEV_T devno ; 155 static SMB_DEV_T devno_cached = 0 ; 156 static pstring name; 157 struct q_request request ; 158 struct qf_header header ; 159 static int quota_default = 0 ; 160 int found ; 161 162 if ( sys_stat(path,&sbuf) == -1 ) 163 return(False) ; 164 165 devno = sbuf.st_dev ; 166 167 if ( devno != devno_cached ) { 168 169 devno_cached = devno ; 170 171 if ((fd = setmntent(KMTAB)) == NULL) 172 return(False) ; 173 174 found = False ; 175 176 while ((mnt = getmntent(fd)) != NULL) { 177 178 if ( sys_stat(mnt->mnt_dir,&sbuf) == -1 ) 179 continue ; 180 181 if (sbuf.st_dev == devno) { 182 183 found = True ; 184 break ; 185 186 } 187 188 } 189 190 pstrcpy(name,mnt->mnt_dir) ; 191 endmntent(fd) ; 192 193 if ( ! found ) 194 return(False) ; 195 } 196 197 request.qf_magic = QF_MAGIC ; 198 request.qf_entry.id = geteuid() ; 199 200 if (quotactl(name, Q_GETQUOTA, &request) == -1) 201 return(False) ; 202 203 if ( ! request.user ) 204 return(False) ; 205 206 if ( request.qf_entry.user_q.f_quota == QFV_DEFAULT ) { 207 208 if ( ! quota_default ) { 209 210 if ( quotactl(name, Q_GETHEADER, &header) == -1 ) 211 return(False) ; 212 else 213 quota_default = header.user_h.def_fq ; 214 } 215 216 *dfree = quota_default ; 217 218 }else if ( request.qf_entry.user_q.f_quota == QFV_PREVENT ) { 219 220 *dfree = 0 ; 221 222 }else{ 223 224 *dfree = request.qf_entry.user_q.f_quota ; 225 226 } 227 228 *dsize = request.qf_entry.user_q.f_use ; 229 230 if ( *dfree < *dsize ) 231 *dfree = 0 ; 232 else 233 *dfree -= *dsize ; 234 235 *bsize = 4096 ; /* Cray blocksize */ 236 237 return(True) ; 238 239} 240 241 242#elif defined(SUNOS5) || defined(SUNOS4) 243 244#include <fcntl.h> 245#include <sys/param.h> 246#if defined(SUNOS5) 247#include <sys/fs/ufs_quota.h> 248#include <sys/mnttab.h> 249#else /* defined(SUNOS4) */ 250#include <ufs/quota.h> 251#include <mntent.h> 252#endif 253 254/**************************************************************************** 255try to get the disk space from disk quotas (SunOS & Solaris2 version) 256Quota code by Peter Urbanec (amiga@cse.unsw.edu.au). 257****************************************************************************/ 258 259BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) 260{ 261 uid_t euser_id; 262 int ret; 263 struct dqblk D; 264#if defined(SUNOS5) 265 struct quotctl command; 266 int file; 267 static struct mnttab mnt; 268 static pstring name; 269#else /* SunOS4 */ 270 struct mntent *mnt; 271 static pstring name; 272#endif 273 FILE *fd; 274 SMB_STRUCT_STAT sbuf; 275 SMB_DEV_T devno ; 276 static SMB_DEV_T devno_cached = 0 ; 277 int found ; 278 279 euser_id = geteuid(); 280 281 if ( sys_stat(path,&sbuf) == -1 ) 282 return(False) ; 283 284 devno = sbuf.st_dev ; 285 DEBUG(5,("disk_quotas: looking for path \"%s\" devno=%o\n", path,devno)); 286 if ( devno != devno_cached ) { 287 devno_cached = devno ; 288#if defined(SUNOS5) 289 if ((fd = sys_fopen(MNTTAB, "r")) == NULL) 290 return(False) ; 291 292 found = False ; 293 while (getmntent(fd, &mnt) == 0) { 294 if ( sys_stat(mnt.mnt_mountp,&sbuf) == -1 ) 295 continue ; 296 DEBUG(5,("disk_quotas: testing \"%s\" devno=%o\n", 297 mnt.mnt_mountp,sbuf.st_dev)); 298 if (sbuf.st_dev == devno) { 299 found = True ; 300 break ; 301 } 302 } 303 304 pstrcpy(name,mnt.mnt_mountp) ; 305 pstrcat(name,"/quotas") ; 306 fclose(fd) ; 307#else /* SunOS4 */ 308 if ((fd = setmntent(MOUNTED, "r")) == NULL) 309 return(False) ; 310 311 found = False ; 312 while ((mnt = getmntent(fd)) != NULL) { 313 if ( sys_stat(mnt->mnt_dir,&sbuf) == -1 ) 314 continue ; 315 DEBUG(5,("disk_quotas: testing \"%s\" devno=%o\n", 316 mnt->mnt_dir,sbuf.st_dev)); 317 if (sbuf.st_dev == devno) { 318 found = True ; 319 break ; 320 } 321 } 322 323 pstrcpy(name,mnt->mnt_fsname) ; 324 endmntent(fd) ; 325#endif 326 327 if ( ! found ) 328 return(False) ; 329 } 330 331 332 save_re_uid(); 333 set_effective_uid(0); 334 335#if defined(SUNOS5) 336 DEBUG(5,("disk_quotas: looking for quotas file \"%s\"\n", name)); 337 if((file=sys_open(name, O_RDONLY,0))<0) { 338 restore_re_uid(); 339 return(False); 340 } 341 command.op = Q_GETQUOTA; 342 command.uid = euser_id; 343 command.addr = (caddr_t) &D; 344 ret = ioctl(file, Q_QUOTACTL, &command); 345 close(file); 346#else 347 DEBUG(5,("disk_quotas: trying quotactl on device \"%s\"\n", name)); 348 ret = quotactl(Q_GETQUOTA, name, euser_id, &D); 349#endif 350 351 restore_re_uid(); 352 353 if (ret < 0) { 354 DEBUG(5,("disk_quotas ioctl (Solaris) failed. Error = %s\n", strerror(errno) )); 355#if defined(SUNOS5) && defined(VXFS_QUOTA) 356 /* If normal quotactl() fails, try vxfs private calls */ 357 set_effective_uid(euser_id); 358 DEBUG(5,("disk_quotas: VXFS_QUOTA: mount type \"%s\"\n", mnt.mnt_fstype)); 359 if ( 0 == strcmp ( mnt.mnt_fstype, "vxfs" )) { 360 DEBUG(5,("disk_quotas: Trying VxFS quotactl call..\n")); 361 ret = disk_quotas_vxfs(name, path, bsize, dfree, dsize); 362 363 return(ret); 364 } 365#endif 366 367 return(False); 368 } 369 370 /* If softlimit is zero, set it equal to hardlimit. 371 */ 372 373 if (D.dqb_bsoftlimit==0) 374 D.dqb_bsoftlimit = D.dqb_bhardlimit; 375 376 /* Use softlimit to determine disk space. A user exceeding the quota is told 377 * that there's no space left. Writes might actually work for a bit if the 378 * hardlimit is set higher than softlimit. Effectively the disk becomes 379 * made of rubber latex and begins to expand to accommodate the user :-) 380 */ 381 382 if (D.dqb_bsoftlimit==0) 383 return(False); 384 *bsize = DEV_BSIZE; 385 *dsize = D.dqb_bsoftlimit; 386 387 if (D.dqb_curblocks > D.dqb_bsoftlimit) { 388 *dfree = 0; 389 *dsize = D.dqb_curblocks; 390 } else 391 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks; 392 393 DEBUG(5,("disk_quotas for path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n", 394 path,(double)*bsize,(double)*dfree,(double)*dsize)); 395 396 return(True); 397} 398 399 400#elif defined(OSF1) 401#include <ufs/quota.h> 402 403/**************************************************************************** 404try to get the disk space from disk quotas - OSF1 version 405****************************************************************************/ 406 407BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) 408{ 409 int r, save_errno; 410 struct dqblk D; 411 SMB_STRUCT_STAT S; 412 uid_t euser_id; 413 414 /* 415 * This code presumes that OSF1 will only 416 * give out quota info when the real uid 417 * matches the effective uid. JRA. 418 */ 419 euser_id = geteuid(); 420 save_re_uid(); 421 if (set_re_uid() != 0) return False; 422 423 r= quotactl(path,QCMD(Q_GETQUOTA, USRQUOTA),euser_id,(char *) &D); 424 if (r) { 425 save_errno = errno; 426 } 427 428 restore_re_uid(); 429 430 *bsize = DEV_BSIZE; 431 432 if (r) 433 { 434 if (save_errno == EDQUOT) // disk quota exceeded 435 { 436 *dfree = 0; 437 *dsize = D.dqb_curblocks; 438 return (True); 439 } 440 else 441 return (False); 442 } 443 444 /* If softlimit is zero, set it equal to hardlimit. 445 */ 446 447 if (D.dqb_bsoftlimit==0) 448 D.dqb_bsoftlimit = D.dqb_bhardlimit; 449 450 /* Use softlimit to determine disk space, except when it has been exceeded */ 451 452 if (D.dqb_bsoftlimit==0) 453 return(False); 454 455 if ((D.dqb_curblocks>D.dqb_bsoftlimit)) { 456 *dfree = 0; 457 *dsize = D.dqb_curblocks; 458 } else { 459 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks; 460 *dsize = D.dqb_bsoftlimit; 461 } 462 return (True); 463} 464 465#elif defined (IRIX6) 466/**************************************************************************** 467try to get the disk space from disk quotas (IRIX 6.2 version) 468****************************************************************************/ 469 470#include <sys/quota.h> 471#include <mntent.h> 472 473BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) 474{ 475 uid_t euser_id; 476 int r; 477 struct dqblk D; 478 struct fs_disk_quota F; 479 SMB_STRUCT_STAT S; 480 FILE *fp; 481 struct mntent *mnt; 482 SMB_DEV_T devno; 483 int found; 484 485 /* find the block device file */ 486 487 if ( sys_stat(path, &S) == -1 ) { 488 return(False) ; 489 } 490 491 devno = S.st_dev ; 492 493 fp = setmntent(MOUNTED,"r"); 494 found = False ; 495 496 while ((mnt = getmntent(fp))) { 497 if ( sys_stat(mnt->mnt_dir,&S) == -1 ) 498 continue ; 499 if (S.st_dev == devno) { 500 found = True ; 501 break ; 502 } 503 } 504 endmntent(fp) ; 505 506 if (!found) { 507 return(False); 508 } 509 510 euser_id=geteuid(); 511 save_re_uid(); 512 set_effective_uid(0); 513 514 /* Use softlimit to determine disk space, except when it has been exceeded */ 515 516 *bsize = 512; 517 518 if ( 0 == strcmp ( mnt->mnt_type, "efs" )) 519 { 520 r=quotactl (Q_GETQUOTA, mnt->mnt_fsname, euser_id, (caddr_t) &D); 521 522 restore_re_uid(); 523 524 if (r==-1) 525 return(False); 526 527 /* Use softlimit to determine disk space, except when it has been exceeded */ 528 if ( 529 (D.dqb_bsoftlimit && D.dqb_curblocks>=D.dqb_bsoftlimit) || 530 (D.dqb_bhardlimit && D.dqb_curblocks>=D.dqb_bhardlimit) || 531 (D.dqb_fsoftlimit && D.dqb_curfiles>=D.dqb_fsoftlimit) || 532 (D.dqb_fhardlimit && D.dqb_curfiles>=D.dqb_fhardlimit) 533 ) 534 { 535 *dfree = 0; 536 *dsize = D.dqb_curblocks; 537 } 538 else if (D.dqb_bsoftlimit==0 && D.dqb_bhardlimit==0) 539 { 540 return(False); 541 } 542 else 543 { 544 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks; 545 *dsize = D.dqb_bsoftlimit; 546 } 547 548 } 549 else if ( 0 == strcmp ( mnt->mnt_type, "xfs" )) 550 { 551 r=quotactl (Q_XGETQUOTA, mnt->mnt_fsname, euser_id, (caddr_t) &F); 552 553 restore_re_uid(); 554 555 if (r==-1) 556 return(False); 557 558 /* Use softlimit to determine disk space, except when it has been exceeded */ 559 if ( 560 (F.d_blk_softlimit && F.d_bcount>=F.d_blk_softlimit) || 561 (F.d_blk_hardlimit && F.d_bcount>=F.d_blk_hardlimit) || 562 (F.d_ino_softlimit && F.d_icount>=F.d_ino_softlimit) || 563 (F.d_ino_hardlimit && F.d_icount>=F.d_ino_hardlimit) 564 ) 565 { 566 *dfree = 0; 567 *dsize = F.d_bcount; 568 } 569 else if (F.d_blk_softlimit==0 && F.d_blk_hardlimit==0) 570 { 571 return(False); 572 } 573 else 574 { 575 *dfree = (F.d_blk_softlimit - F.d_bcount); 576 *dsize = F.d_blk_softlimit; 577 } 578 579 } 580 else 581 { 582 restore_re_uid(); 583 return(False); 584 } 585 586 return (True); 587 588} 589 590#else 591 592#if defined(__FreeBSD__) || defined(__OpenBSD__) 593#include <ufs/ufs/quota.h> 594#include <machine/param.h> 595#elif AIX 596/* AIX quota patch from Ole Holm Nielsen <ohnielse@fysik.dtu.dk> */ 597#include <jfs/quota.h> 598/* AIX 4.X: Rename members of the dqblk structure (ohnielse@fysik.dtu.dk) */ 599#define dqb_curfiles dqb_curinodes 600#define dqb_fhardlimit dqb_ihardlimit 601#define dqb_fsoftlimit dqb_isoftlimit 602#else /* !__FreeBSD__ && !AIX && !__OpenBSD__ */ 603#include <sys/quota.h> 604#include <devnm.h> 605#endif 606 607/**************************************************************************** 608try to get the disk space from disk quotas - default version 609****************************************************************************/ 610 611BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) 612{ 613 int r; 614 struct dqblk D; 615 uid_t euser_id; 616#if !defined(__FreeBSD__) && !defined(AIX) && !defined(__OpenBSD__) 617 char dev_disk[256]; 618 SMB_STRUCT_STAT S; 619 /* find the block device file */ 620 if ((sys_stat(path, &S)<0) || 621 (devnm(S_IFBLK, S.st_dev, dev_disk, 256, 0)<0)) return (False); 622#endif 623 624 euser_id = geteuid(); 625 626#ifdef HPUX 627 /* for HPUX, real uid must be same as euid to execute quotactl for euid */ 628 save_re_uid(); 629 if (set_re_uid() != 0) return False; 630 631 r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D); 632 633 restore_re_uid(); 634#else 635#if defined(__FreeBSD__) || defined(__OpenBSD__) 636 { 637 /* FreeBSD patches from Marty Moll <martym@arbor.edu> */ 638 gid_t egrp_id; 639 640 save_re_uid(); 641 set_effective_uid(0); 642 643 egrp_id = getegid(); 644 r= quotactl(path,QCMD(Q_GETQUOTA,USRQUOTA),euser_id,(char *) &D); 645 646 /* As FreeBSD has group quotas, if getting the user 647 quota fails, try getting the group instead. */ 648 if (r) { 649 r= quotactl(path,QCMD(Q_GETQUOTA,GRPQUOTA),egrp_id,(char *) &D); 650 } 651 652 restore_re_uid(); 653 } 654#elif defined(AIX) 655 /* AIX has both USER and GROUP quotas: 656 Get the USER quota (ohnielse@fysik.dtu.dk) */ 657 r= quotactl(path,QCMD(Q_GETQUOTA,USRQUOTA),euser_id,(char *) &D); 658#else /* !__FreeBSD__ && !AIX && !__OpenBSD__ */ 659 r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D); 660#endif /* !__FreeBSD__ && !AIX && !__OpenBSD__ */ 661#endif /* HPUX */ 662 663 /* Use softlimit to determine disk space, except when it has been exceeded */ 664#if defined(__FreeBSD__) || defined(__OpenBSD__) 665 *bsize = DEV_BSIZE; 666#else /* !__FreeBSD__ && !__OpenBSD__ */ 667 *bsize = 1024; 668#endif /*!__FreeBSD__ && !__OpenBSD__ */ 669 670 if (r) 671 { 672 if (errno == EDQUOT) 673 { 674 *dfree =0; 675 *dsize =D.dqb_curblocks; 676 return (True); 677 } 678 else return(False); 679 } 680 681 /* If softlimit is zero, set it equal to hardlimit. 682 */ 683 684 if (D.dqb_bsoftlimit==0) 685 D.dqb_bsoftlimit = D.dqb_bhardlimit; 686 687 if (D.dqb_bsoftlimit==0) 688 return(False); 689 /* Use softlimit to determine disk space, except when it has been exceeded */ 690 if ((D.dqb_curblocks>D.dqb_bsoftlimit) 691#if !defined(__FreeBSD__) && !defined(__OpenBSD__) 692||((D.dqb_curfiles>D.dqb_fsoftlimit) && (D.dqb_fsoftlimit != 0)) 693#endif 694 ) { 695 *dfree = 0; 696 *dsize = D.dqb_curblocks; 697 } 698 else { 699 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks; 700 *dsize = D.dqb_bsoftlimit; 701 } 702 return (True); 703} 704 705#endif 706 707#if defined(VXFS_QUOTA) 708 709/**************************************************************************** 710Try to get the disk space from Veritas disk quotas. 711 David Lee <T.D.Lee@durham.ac.uk> August 1999. 712 713Warning: 714 It is understood that Veritas do not publicly support this ioctl interface. 715 Rather their preference would be for the user (us) to call the native 716 OS and then for the OS itself to call through to the VxFS filesystem. 717 Presumably HPUX 10 does this, which is why this patch is not required for 718 HPUX 10. 719 720****************************************************************************/ 721/*************************************************************************** 722 VERITAS Disclaimer: 723 The following code uses private VxFS interfaces that are subject 724 to change without notice. It is distributed in the hope that it will 725 be useful, but WITHOUT ANY WARRANTY whatsoever. 726 VERITAS disclaims all liability resulting from use of this code. 727 VERITAS is under no obligation to maintain these private 728 interfaces in future releases of VERITAS products. 729 ***************************************************************************/ 730 731#if defined(SUNOS5) 732#include <sys/fs/vx_solaris.h> 733#endif 734#include <sys/fs/vx_machdep.h> 735#include <sys/fs/vx_layout.h> 736#include <sys/fs/vx_quota.h> 737#include <sys/fs/vx_aioctl.h> 738#include <sys/fs/vx_ioctl.h> 739 740static BOOL disk_quotas_vxfs(const pstring name, char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) 741{ 742 uid_t user_id, euser_id; 743 int ret; 744 struct vx_dqblk D; 745 struct vx_quotctl quotabuf; 746 struct vx_genioctl genbuf; 747 pstring qfname; 748 int file; 749 750 /* 751 * "name" may or may not include a trailing "/quotas". 752 * Arranging consistency of calling here in "quotas.c" may not be easy and 753 * it might be easier to examine and adjust it here. 754 * Fortunately, VxFS seems not to mind at present. 755 */ 756 pstrcpy(qfname, name) ; 757 /* pstrcat(qfname, "/quotas") ; */ /* possibly examine and adjust "name" */ 758 759 euser_id = geteuid(); 760 set_effective_uid(0); 761 762 DEBUG(5,("disk_quotas: looking for VxFS quotas file \"%s\"\n", qfname)); 763 if((file=sys_open(qfname, O_RDONLY,0))<0) { 764 set_effective_uid(euser_id); 765 return(False); 766 } 767 genbuf.ioc_cmd = VX_QUOTACTL; 768 genbuf.ioc_up = (void *) "abuf; 769 770 quotabuf.cmd = VX_GETQUOTA; 771 quotabuf.uid = euser_id; 772 quotabuf.addr = (caddr_t) &D; 773 ret = ioctl(file, VX_ADMIN_IOCTL, &genbuf); 774 close(file); 775 776 set_effective_uid(euser_id); 777 778 if (ret < 0) { 779 DEBUG(5,("disk_quotas ioctl (VxFS) failed. Error = %s\n", strerror(errno) )); 780 return(False); 781 } 782 783 /* If softlimit is zero, set it equal to hardlimit. 784 */ 785 786 if (D.dqb_bsoftlimit==0) 787 D.dqb_bsoftlimit = D.dqb_bhardlimit; 788 789 /* Use softlimit to determine disk space. A user exceeding the quota is told 790 * that there's no space left. Writes might actually work for a bit if the 791 * hardlimit is set higher than softlimit. Effectively the disk becomes 792 * made of rubber latex and begins to expand to accommodate the user :-) 793 */ 794 DEBUG(5,("disk_quotas for path \"%s\" block c/s/h %ld/%ld/%ld; file c/s/h %ld/%ld/%ld\n", 795 path, D.dqb_curblocks, D.dqb_bsoftlimit, D.dqb_bhardlimit, 796 D.dqb_curfiles, D.dqb_fsoftlimit, D.dqb_fhardlimit)); 797 798 if (D.dqb_bsoftlimit==0) 799 return(False); 800 *bsize = DEV_BSIZE; 801 *dsize = D.dqb_bsoftlimit; 802 803 if (D.dqb_curblocks > D.dqb_bsoftlimit) { 804 *dfree = 0; 805 *dsize = D.dqb_curblocks; 806 } else 807 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks; 808 809 DEBUG(5,("disk_quotas for path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n", 810 path,(double)*bsize,(double)*dfree,(double)*dsize)); 811 812 return(True); 813} 814 815#endif /* VXFS_QUOTA */ 816