Beispiel #1
0
BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
{
	uid_t euser_id;
	int ret;
	struct dqblk D;
#if defined(SUNOS5)
	struct quotctl command;
	int file;
	static struct mnttab mnt;
	static pstring name;
	pstring devopt;
#else /* SunOS4 */
	struct mntent *mnt;
	static pstring name;
#endif
	FILE *fd;
	SMB_STRUCT_STAT sbuf;
	SMB_DEV_T devno ;
	static SMB_DEV_T devno_cached = 0 ;
	static int found ;

	euser_id = geteuid();
  
	if ( sys_stat(path,&sbuf) == -1 )
		return(False) ;
  
	devno = sbuf.st_dev ;
	DEBUG(5,("disk_quotas: looking for path \"%s\" devno=%x\n", path,(unsigned int)devno));
	if ( devno != devno_cached ) {
		devno_cached = devno ;
#if defined(SUNOS5)
		if ((fd = sys_fopen(MNTTAB, "r")) == NULL)
			return(False) ;
    
		found = False ;
		slprintf(devopt, sizeof(devopt) - 1, "dev=%x", (unsigned int)devno);
		while (getmntent(fd, &mnt) == 0) {
			if( !hasmntopt(&mnt, devopt) )
				continue;

			DEBUG(5,("disk_quotas: testing \"%s\" %s\n", mnt.mnt_mountp,devopt));

			/* quotas are only on vxfs, UFS or NFS */
			if ( strcmp( mnt.mnt_fstype, MNTTYPE_UFS ) == 0 ||
				strcmp( mnt.mnt_fstype, "nfs" ) == 0    ||
				strcmp( mnt.mnt_fstype, "vxfs" ) == 0  ) { 
					found = True ;
					break;
			}
		}
    
		pstrcpy(name,mnt.mnt_mountp) ;
		pstrcat(name,"/quotas") ;
		fclose(fd) ;
#else /* SunOS4 */
		if ((fd = setmntent(MOUNTED, "r")) == NULL)
			return(False) ;
    
		found = False ;
		while ((mnt = getmntent(fd)) != NULL) {
			if ( sys_stat(mnt->mnt_dir,&sbuf) == -1 )
				continue ;
			DEBUG(5,("disk_quotas: testing \"%s\" devno=%x\n", mnt->mnt_dir,(unsigned int)sbuf.st_dev));
			if (sbuf.st_dev == devno) {
				found = True ;
				break;
			}
		}
    
		pstrcpy(name,mnt->mnt_fsname) ;
		endmntent(fd) ;
#endif
	}

	if ( ! found )
		return(False) ;

	save_re_uid();
	set_effective_uid(0);

#if defined(SUNOS5)
	if ( strcmp( mnt.mnt_fstype, "nfs" ) == 0) {
		BOOL retval;
		DEBUG(5,("disk_quotas: looking for mountpath (NFS) \"%s\"\n", mnt.mnt_special));
		retval = nfs_quotas(mnt.mnt_special, euser_id, bsize, dfree, dsize);
		restore_re_uid();
		return retval;
	}

	DEBUG(5,("disk_quotas: looking for quotas file \"%s\"\n", name));
	if((file=sys_open(name, O_RDONLY,0))<0) {
		restore_re_uid();
		return(False);
	}
	command.op = Q_GETQUOTA;
	command.uid = euser_id;
	command.addr = (caddr_t) &D;
	ret = ioctl(file, Q_QUOTACTL, &command);
	close(file);
#else
	DEBUG(5,("disk_quotas: trying quotactl on device \"%s\"\n", name));
	ret = quotactl(Q_GETQUOTA, name, euser_id, &D);
#endif

	restore_re_uid();

	if (ret < 0) {
		DEBUG(5,("disk_quotas ioctl (Solaris) failed. Error = %s\n", strerror(errno) ));

#if defined(SUNOS5) && defined(VXFS_QUOTA)
		/* If normal quotactl() fails, try vxfs private calls */
		set_effective_uid(euser_id);
		DEBUG(5,("disk_quotas: mount type \"%s\"\n", mnt.mnt_fstype));
		if ( 0 == strcmp ( mnt.mnt_fstype, "vxfs" )) {
			BOOL retval;
			retval = disk_quotas_vxfs(name, path, bsize, dfree, dsize);
			return(retval);
		}
#else
		return(False);
#endif
	}

	/* If softlimit is zero, set it equal to hardlimit.
	 */
  
	if (D.dqb_bsoftlimit==0)
		D.dqb_bsoftlimit = D.dqb_bhardlimit;

	/* Use softlimit to determine disk space. A user exceeding the quota is told
	 * that there's no space left. Writes might actually work for a bit if the
	 * hardlimit is set higher than softlimit. Effectively the disk becomes
	 * made of rubber latex and begins to expand to accommodate the user :-)
	 */

	if (D.dqb_bsoftlimit==0)
		return(False);
	*bsize = DEV_BSIZE;
	*dsize = D.dqb_bsoftlimit;

	if (D.dqb_curblocks > D.dqb_bsoftlimit) {
		*dfree = 0;
		*dsize = D.dqb_curblocks;
	} else
		*dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
      
	DEBUG(5,("disk_quotas for path \"%s\" returning  bsize %.0f, dfree %.0f, dsize %.0f\n",
		path,(double)*bsize,(double)*dfree,(double)*dsize));

	return(True);
}
Beispiel #2
0
BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
{
  int r;
  struct dqblk D;
  uid_t euser_id;
#if !defined(__FreeBSD__) && !defined(AIX) && !defined(__OpenBSD__)
  char dev_disk[256];
  SMB_STRUCT_STAT S;

  /* find the block device file */

#ifdef HPUX
  /* Need to set the cache flag to 1 for HPUX. Seems
   * to have a significant performance boost when
   * lstat calls on /dev access this function.
   */
  if ((sys_stat(path, &S)<0) || (devnm(S_IFBLK, S.st_dev, dev_disk, 256, 1)<0))
#else
  if ((sys_stat(path, &S)<0) || (devnm(S_IFBLK, S.st_dev, dev_disk, 256, 0)<0)) 
	return (False);
#endif /* ifdef HPUX */

#endif /* !defined(__FreeBSD__) && !defined(AIX) && !defined(__OpenBSD__) */

  euser_id = geteuid();

#ifdef HPUX
  /* for HPUX, real uid must be same as euid to execute quotactl for euid */
  save_re_uid();
  if (set_re_uid() != 0) return False;
  
  r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D);

  restore_re_uid();
#else 
#if defined(__FreeBSD__) || defined(__OpenBSD__)
  {
    /* FreeBSD patches from Marty Moll <*****@*****.**> */
    gid_t egrp_id;
#if defined(__FreeBSD__)
    SMB_DEV_T devno;
    struct statfs *mnts;
    SMB_STRUCT_STAT st;
    int mntsize, i;
    
    if (sys_stat(path,&st) < 0)
        return False;
    devno = st.st_dev;

    mntsize = getmntinfo(&mnts,MNT_NOWAIT);
    if (mntsize <= 0)
        return False;

    for (i = 0; i < mntsize; i++) {
        if (sys_stat(mnts[i].f_mntonname,&st) < 0)
            return False;
        if (st.st_dev == devno)
            break;
    }
    if (i == mntsize)
        return False;
#endif
    
    save_re_uid();
    set_effective_uid(0);

#if defined(__FreeBSD__)
    if (strcmp(mnts[i].f_fstypename,"nfs") == 0) {
        BOOL retval;
        retval = nfs_quotas(mnts[i].f_mntfromname,euser_id,bsize,dfree,dsize);
        restore_re_uid();
        return retval;
    }
#endif

    egrp_id = getegid();
    r= quotactl(path,QCMD(Q_GETQUOTA,USRQUOTA),euser_id,(char *) &D);

    /* As FreeBSD has group quotas, if getting the user
       quota fails, try getting the group instead. */
    if (r) {
	    r= quotactl(path,QCMD(Q_GETQUOTA,GRPQUOTA),egrp_id,(char *) &D);
    }

    restore_re_uid();
  }
#elif defined(AIX)
  /* AIX has both USER and GROUP quotas: 
     Get the USER quota ([email protected]) */
  save_re_uid();
  if (set_re_uid() != 0) 
    return False;
  r= quotactl(path,QCMD(Q_GETQUOTA,USRQUOTA),euser_id,(char *) &D);
  restore_re_uid();
#else /* !__FreeBSD__ && !AIX && !__OpenBSD__ */
  r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D);
#endif /* !__FreeBSD__ && !AIX && !__OpenBSD__ */
#endif /* HPUX */

  /* Use softlimit to determine disk space, except when it has been exceeded */
#if defined(__FreeBSD__) || defined(__OpenBSD__)
  *bsize = DEV_BSIZE;
#else /* !__FreeBSD__ && !__OpenBSD__ */
  *bsize = 1024;
#endif /*!__FreeBSD__ && !__OpenBSD__ */

  if (r)
    {
      if (errno == EDQUOT) 
	{
 	  *dfree =0;
 	  *dsize =D.dqb_curblocks;
 	  return (True);
	}
      else return(False);
    }

  /* If softlimit is zero, set it equal to hardlimit.
   */

  if (D.dqb_bsoftlimit==0)
    D.dqb_bsoftlimit = D.dqb_bhardlimit;

  if (D.dqb_bsoftlimit==0)
    return(False);
  /* Use softlimit to determine disk space, except when it has been exceeded */
  if ((D.dqb_curblocks>D.dqb_bsoftlimit)
#if !defined(__FreeBSD__) && !defined(__OpenBSD__)
||((D.dqb_curfiles>D.dqb_fsoftlimit) && (D.dqb_fsoftlimit != 0))
#endif
    ) {
      *dfree = 0;
      *dsize = D.dqb_curblocks;
    }
  else {
    *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
    *dsize = D.dqb_bsoftlimit;
  }
  return (True);
}