home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1998 July & August / Pcwk78a98.iso / Wtestowe / Clico / UNIX / SAMBA / SOURCE / SAMBA.TAR / samba-1.9.17 / source / quotas.c < prev    next >
C/C++ Source or Header  |  1997-08-19  |  12KB  |  501 lines

  1. #ifdef QUOTAS
  2. /* 
  3.    Unix SMB/Netbios implementation.
  4.    Version 1.9.
  5.    support for quotas
  6.    Copyright (C) Andrew Tridgell 1992-1997
  7.    
  8.    This program is free software; you can redistribute it and/or modify
  9.    it under the terms of the GNU General Public License as published by
  10.    the Free Software Foundation; either version 2 of the License, or
  11.    (at your option) any later version.
  12.    
  13.    This program is distributed in the hope that it will be useful,
  14.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.    GNU General Public License for more details.
  17.    
  18.    You should have received a copy of the GNU General Public License
  19.    along with this program; if not, write to the Free Software
  20.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21. */
  22.  
  23.  
  24. /* 
  25.  * This is one of the most system dependent parts of Samba, and its
  26.  * done a litle differently. Each system has its own way of doing 
  27.  * things :-(
  28.  */
  29.  
  30. #include "includes.h"
  31.  
  32. extern int DEBUGLEVEL;
  33.  
  34. #ifdef LINUX
  35.  
  36. #include <sys/types.h>
  37. #include <asm/types.h>
  38. #include <sys/quota.h>
  39.  
  40. #include <mntent.h>
  41. #include <linux/unistd.h>
  42.  
  43. _syscall4(int, quotactl, int, cmd, const char *, special, int, id, caddr_t, addr);
  44.  
  45. /****************************************************************************
  46. try to get the disk space from disk quotas (LINUX version)
  47. ****************************************************************************/
  48.  
  49. BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize)
  50. {
  51.   uid_t euser_id;
  52.   int r;
  53.   struct dqblk D;
  54.   struct stat S;
  55.   FILE *fp;
  56.   struct mntent *mnt;
  57.   int devno;
  58.   int found;
  59.   
  60.   /* find the block device file */
  61.   
  62.   if ( stat(path, &S) == -1 ) {
  63.     return(False) ;
  64.   }
  65.  
  66.   devno = S.st_dev ;
  67.   
  68.   fp = setmntent(MOUNTED,"r");
  69.   found = False ;
  70.   
  71.   while ((mnt = getmntent(fp))) {
  72.     if ( stat(mnt->mnt_dir,&S) == -1 )
  73.       continue ;
  74.     if (S.st_dev == devno) {
  75.       found = True ;
  76.       break ;
  77.     }
  78.   }
  79.   endmntent(fp) ;
  80.   
  81.   if (!found) {
  82.       return(False);
  83.     }
  84.  
  85.   euser_id=geteuid();
  86.   seteuid(0);  
  87.   r=quotactl(QCMD(Q_GETQUOTA,USRQUOTA), mnt->mnt_fsname, euser_id, (caddr_t)&D);
  88.       seteuid(euser_id);
  89.  
  90.   /* Use softlimit to determine disk space, except when it has been exceeded */
  91.   *bsize = 1024;
  92.   if (r)
  93.     {
  94.       if (errno == EDQUOT) 
  95.        {
  96.          *dfree =0;
  97.          *dsize =D.dqb_curblocks;
  98.          return (True);
  99.     }
  100.       else return(False);
  101.   }
  102.   /* Use softlimit to determine disk space, except when it has been exceeded */
  103.   if (
  104.       (D.dqb_bsoftlimit && D.dqb_curblocks>=D.dqb_bsoftlimit) ||
  105.       (D.dqb_bhardlimit && D.dqb_curblocks>=D.dqb_bhardlimit) ||
  106.       (D.dqb_isoftlimit && D.dqb_curinodes>=D.dqb_isoftlimit) ||
  107.       (D.dqb_ihardlimit && D.dqb_curinodes>=D.dqb_ihardlimit)
  108.      )
  109.     {
  110.       *dfree = 0;
  111.       *dsize = D.dqb_curblocks;
  112.     }
  113.   else if (D.dqb_bsoftlimit==0 && D.dqb_bhardlimit==0)
  114.     {
  115.       return(False);
  116.     }
  117.   else {
  118.     *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
  119.     *dsize = D.dqb_bsoftlimit;
  120.   }
  121.   return (True);
  122. }
  123.  
  124. #elif defined(CRAY)
  125.  
  126. #include <sys/quota.h>
  127. #include <mntent.h>
  128.  
  129. /****************************************************************************
  130. try to get the disk space from disk quotas (CRAY VERSION)
  131. ****************************************************************************/
  132. BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize)
  133. {
  134.   struct mntent *mnt;
  135.   FILE *fd;
  136.   struct stat sbuf;
  137.   dev_t devno ;
  138.   static dev_t devno_cached = 0 ;
  139.   static char name[MNTMAXSTR] ;
  140.   struct q_request request ;
  141.   struct qf_header header ;
  142.   static int quota_default = 0 ;
  143.   int found ;
  144.   
  145.   if ( stat(path,&sbuf) == -1 )
  146.     return(False) ;
  147.   
  148.   devno = sbuf.st_dev ;
  149.   
  150.   if ( devno != devno_cached ) {
  151.     
  152.     devno_cached = devno ;
  153.     
  154.     if ((fd = setmntent(KMTAB)) == NULL)
  155.       return(False) ;
  156.     
  157.     found = False ;
  158.     
  159.     while ((mnt = getmntent(fd)) != NULL) {
  160.       
  161.       if ( stat(mnt->mnt_dir,&sbuf) == -1 )
  162.     continue ;
  163.       
  164.       if (sbuf.st_dev == devno) {
  165.     
  166.     found = True ;
  167.     break ;
  168.     
  169.       }
  170.       
  171.     }
  172.     
  173.     strcpy(name,mnt->mnt_dir) ;
  174.     endmntent(fd) ;
  175.     
  176.     if ( ! found )
  177.       return(False) ;
  178.   }
  179.   
  180.   request.qf_magic = QF_MAGIC ;
  181.   request.qf_entry.id = geteuid() ;
  182.   
  183.   if (quotactl(name, Q_GETQUOTA, &request) == -1)
  184.     return(False) ;
  185.   
  186.   if ( ! request.user )
  187.     return(False) ;
  188.   
  189.   if ( request.qf_entry.user_q.f_quota == QFV_DEFAULT ) {
  190.     
  191.     if ( ! quota_default ) {
  192.       
  193.       if ( quotactl(name, Q_GETHEADER, &header) == -1 )
  194.     return(False) ;
  195.       else
  196.     quota_default = header.user_h.def_fq ;
  197.     }
  198.     
  199.     *dfree = quota_default ;
  200.     
  201.   }else if ( request.qf_entry.user_q.f_quota == QFV_PREVENT ) {
  202.     
  203.     *dfree = 0 ;
  204.     
  205.   }else{
  206.     
  207.     *dfree = request.qf_entry.user_q.f_quota ;
  208.     
  209.   }
  210.   
  211.   *dsize = request.qf_entry.user_q.f_use ;
  212.   
  213.   if ( *dfree )
  214.     *dfree -= *dsize ;
  215.   
  216.   if ( *dfree < 0 )
  217.     *dfree = 0 ;
  218.   
  219.   *bsize = 4096 ;  /* Cray blocksize */
  220.   
  221.   return(True) ;
  222.   
  223. }
  224.  
  225.  
  226. #elif defined(SUNOS5) || defined(SUNOS4)
  227.  
  228. #include <fcntl.h>
  229. #if defined(SUNOS5)
  230. #include <sys/fs/ufs_quota.h>
  231. #include <sys/mnttab.h>
  232. #else /* defined(SUNOS4) */
  233. #include <ufs/quota.h>
  234. #include <mntent.h>
  235. #endif
  236.  
  237. /****************************************************************************
  238. try to get the disk space from disk quotas (solaris 2 version)
  239. ****************************************************************************/
  240. /* Quota code by Peter Urbanec (amiga@cse.unsw.edu.au) */
  241. BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize)
  242. {
  243.   uid_t user_id, euser_id;
  244.   int ret;
  245.   struct dqblk D;
  246. #if defined(SUNOS5)
  247.   struct quotctl command;
  248.   int file;
  249.   struct mnttab mnt;
  250.   static char name[MNT_LINE_MAX] ;
  251. #else
  252.   struct mntent *mnt;
  253.   static char name[MNTMAXSTR] ;
  254. #endif
  255.   FILE *fd;
  256.   struct stat sbuf;
  257.   dev_t devno ;
  258.   static dev_t devno_cached = 0 ;
  259.   int found ;
  260.   
  261.   if ( stat(path,&sbuf) == -1 )
  262.     return(False) ;
  263.   
  264.   devno = sbuf.st_dev ;
  265.   DEBUG(5,("disk_quotas: looking for path \"%s\" devno=%o\n", path,devno));
  266.   if ( devno != devno_cached ) {
  267.     devno_cached = devno ;
  268. #if defined(SUNOS5)
  269.     if ((fd = fopen(MNTTAB, "r")) == NULL)
  270.       return(False) ;
  271.     
  272.     found = False ;
  273.     while (getmntent(fd, &mnt) == 0) {
  274.       if ( stat(mnt.mnt_mountp,&sbuf) == -1 )
  275.     continue ;
  276.       DEBUG(5,("disk_quotas: testing \"%s\" devno=%o\n", 
  277.            mnt.mnt_mountp,sbuf.st_dev));
  278.       if (sbuf.st_dev == devno) {
  279.     found = True ;
  280.     break ;
  281.       }
  282.     }
  283.     
  284.     strcpy(name,mnt.mnt_mountp) ;
  285.     strcat(name,"/quotas") ;
  286.     fclose(fd) ;
  287. #else
  288.     if ((fd = setmntent(MOUNTED, "r")) == NULL)
  289.       return(False) ;
  290.     
  291.     found = False ;
  292.     while ((mnt = getmntent(fd)) != NULL) {
  293.       if ( stat(mnt->mnt_dir,&sbuf) == -1 )
  294.     continue ;
  295.       DEBUG(5,("disk_quotas: testing \"%s\" devno=%o\n", 
  296.            mnt->mnt_dir,sbuf.st_dev));
  297.       if (sbuf.st_dev == devno) {
  298.     found = True ;
  299.     break ;
  300.       }
  301.     }
  302.     
  303.     strcpy(name,mnt->mnt_fsname) ;
  304.     endmntent(fd) ;
  305. #endif
  306.     
  307.     if ( ! found )
  308.       return(False) ;
  309.   }
  310.  
  311.   euser_id = geteuid();
  312.   user_id = getuid();
  313.  
  314.   setuid(0);  /* Solaris seems to want to give info only to super-user */
  315.   seteuid(0);
  316.  
  317. #if defined(SUNOS5)
  318.   DEBUG(5,("disk_quotas: looking for quotas file \"%s\"\n", name));
  319.   if((file=open(name, O_RDONLY))<0) {
  320.     setuid(user_id);  /* Restore the original UID status */
  321.     seteuid(euser_id);
  322.     return(False);
  323.   }
  324.   command.op = Q_GETQUOTA;
  325.   command.uid = euser_id;
  326.   command.addr = (caddr_t) &D;
  327.   ret = ioctl(file, Q_QUOTACTL, &command);
  328.   close(file);
  329. #else
  330.   DEBUG(5,("disk_quotas: trying quotactl on device \"%s\"\n", name));
  331.   ret = quotactl(Q_GETQUOTA, name, euser_id, &D);
  332. #endif
  333.  
  334.   setuid(user_id); /* Restore the original uid status. */
  335.   seteuid(euser_id);
  336.  
  337.   if (ret < 0) {
  338.     DEBUG(2,("disk_quotas ioctl (Solaris) failed\n"));
  339.     return(False);
  340.   }
  341.  
  342.  
  343.   /* Use softlimit to determine disk space. A user exceeding the quota is told
  344.    * that there's no space left. Writes might actually work for a bit if the
  345.    * hardlimit is set higher than softlimit. Effectively the disk becomes
  346.    * made of rubber latex and begins to expand to accommodate the user :-)
  347.    */
  348.  
  349.   if (D.dqb_bsoftlimit==0)
  350.     return(False);
  351.   *bsize = 512;
  352.   *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
  353.   *dsize = D.dqb_bsoftlimit;
  354.   if(*dfree < 0)
  355.     {
  356.      *dfree = 0;
  357.      *dsize = D.dqb_curblocks;
  358.     }
  359.       
  360. DEBUG(5,("disk_quotas for path \"%s\" returning  bsize %d, dfree %d, dsize %d\n",
  361.          path,*bsize,*dfree,*dsize));
  362.  
  363.       return(True);
  364. }
  365.  
  366.  
  367. #elif defined(OSF1)
  368. #include <ufs/quota.h>
  369.  
  370. /****************************************************************************
  371. try to get the disk space from disk quotas - OFS1 version
  372. ****************************************************************************/
  373. BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize)
  374. {
  375.   uid_t user_id, euser_id;
  376.   int r;
  377.   struct dqblk D;
  378.   struct stat S;
  379.  
  380.   euser_id = geteuid();
  381.   user_id = getuid();
  382.  
  383.   setreuid(euser_id, euser_id);
  384.   r= quotactl(path,QCMD(Q_GETQUOTA, USRQUOTA),euser_id,(char *) &D);
  385.   if (setreuid(user_id, euser_id) == -1)
  386.     DEBUG(5,("Unable to reset uid to %d\n", user_id));
  387.  
  388.   *bsize = DEV_BSIZE;
  389.  
  390.   if (r)
  391.       return(False);
  392.  
  393.   /* Use softlimit to determine disk space, except when it has been exceeded */
  394.  
  395.   if (D.dqb_bsoftlimit==0)
  396.     return(False);
  397.  
  398.   if ((D.dqb_curblocks>D.dqb_bsoftlimit)) {
  399.     *dfree = 0;
  400.     *dsize = D.dqb_curblocks;
  401.   } else {
  402.     *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
  403.     *dsize = D.dqb_bsoftlimit;
  404.   }
  405.   return (True);
  406. }
  407. #else
  408.  
  409. #ifdef        __FreeBSD__
  410. #include <ufs/ufs/quota.h>
  411. #elif         AIX
  412. /* AIX quota patch from Ole Holm Nielsen <ohnielse@fysik.dtu.dk> */
  413. #include <jfs/quota.h>
  414. /* AIX 4.X: Rename members of the dqblk structure (ohnielse@fysik.dtu.dk) */
  415. #define dqb_curfiles dqb_curinodes
  416. #define dqb_fhardlimit dqb_ihardlimit
  417. #define dqb_fsoftlimit dqb_isoftlimit
  418. #else /* !__FreeBSD__ && !AIX */
  419. #include <sys/quota.h>
  420. #include <devnm.h>
  421. #endif
  422.  
  423. /****************************************************************************
  424. try to get the disk space from disk quotas - default version
  425. ****************************************************************************/
  426. BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize)
  427. {
  428.   uid_t euser_id;
  429.   int r;
  430.   struct dqblk D;
  431. #if !defined(__FreeBSD__) && !defined(AIX)
  432.   char dev_disk[256];
  433.   struct stat S;
  434.   /* find the block device file */
  435.   if ((stat(path, &S)<0) ||
  436.       (devnm(S_IFBLK, S.st_dev, dev_disk, 256, 0)<0)) return (False);
  437. #endif
  438.  
  439.   euser_id = geteuid();
  440.  
  441. #ifdef USE_SETRES
  442.   {
  443.     uid_t user_id;
  444.  
  445.     /* for HPUX, real uid must be same as euid to execute quotactl for euid */
  446.     user_id = getuid();
  447.     setresuid(euser_id,-1,-1);
  448.     r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D);
  449.     if (setresuid(user_id,-1,-1))
  450.       DEBUG(5,("Unable to reset uid to %d\n", user_id));
  451.   }
  452. #else /* USE_SETRES */
  453. #if defined(__FreeBSD__)
  454.   r= quotactl(path,Q_GETQUOTA,euser_id,(char *) &D);
  455. #elif defined(AIX)
  456.   /* AIX has both USER and GROUP quotas: 
  457.      Get the USER quota (ohnielse@fysik.dtu.dk) */
  458.   r= quotactl(path,QCMD(Q_GETQUOTA,USRQUOTA),euser_id,(char *) &D);
  459. #else /* !__FreeBSD__ && !AIX */
  460.   r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D);
  461. #endif /* !__FreeBSD__ && !AIX */
  462. #endif /* USE_SETRES */
  463.  
  464.   /* Use softlimit to determine disk space, except when it has been exceeded */
  465.   *bsize = 1024;
  466.   if (r)
  467.     {
  468.       if (errno == EDQUOT) 
  469.     {
  470.        *dfree =0;
  471.        *dsize =D.dqb_curblocks;
  472.        return (True);
  473.     }
  474.       else return(False);
  475.     }
  476.   if (D.dqb_bsoftlimit==0)
  477.     return(False);
  478.   /* Use softlimit to determine disk space, except when it has been exceeded */
  479.   if ((D.dqb_curblocks>D.dqb_bsoftlimit)
  480. #if !defined(__FreeBSD__)
  481. ||((D.dqb_curfiles>D.dqb_fsoftlimit) && (D.dqb_fsoftlimit != 0))
  482. #endif
  483.     ) {
  484.       *dfree = 0;
  485.       *dsize = D.dqb_curblocks;
  486.     }
  487.   else {
  488.     *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
  489.     *dsize = D.dqb_bsoftlimit;
  490.   }
  491.   return (True);
  492. }
  493.  
  494. #endif
  495.  
  496. #else
  497. /* this keeps fussy compilers happy */
  498.  void quotas_dummy(void) {}
  499. #endif /* QUOTAS */
  500.  
  501.