1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-31 01:48:16 +03:00
Andrew Tridgell 7e3b4a1c0d got rid of a lot of redundent header files as we now globally generate
prototypes automatically using "make proto". This is much less prone
to error than the old method of manually adding prototypes
(This used to be commit b551dc98f7cc194a5fc2e67a4ebae7fd67a01bbc)
1996-06-10 04:38:24 +00:00

442 lines
10 KiB
C

#ifdef QUOTAS
/*
Unix SMB/Netbios implementation.
Version 1.9.
support for quotas
Copyright (C) Andrew Tridgell 1992-1995
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* This is one of the most system dependent parts of Samba, and its
* done a litle differently. Each system has its own way of doing
* things :-(
*/
#include "includes.h"
extern int DEBUGLEVEL;
#ifdef LINUX
#ifdef __KERNEL__
# undef __KERNEL__
# include <sys/quota.h>
# define __KERNEL__
#else
# include <sys/quota.h>
#endif
#include <mntent.h>
/****************************************************************************
try to get the disk space from disk quotas (LINUX version)
****************************************************************************/
/*
If you didn't make the symlink to the quota package, too bad :(
*/
#include "quota/quotactl.c"
#include "quota/hasquota.c"
BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize)
{
uid_t euser_id;
struct dqblk D;
struct stat S;
dev_t devno ;
struct mntent *mnt;
FILE *fp;
int found ;
int qcmd, fd ;
char *qfpathname;
/* find the block device file */
if ( stat(path, &S) == -1 )
return(False) ;
devno = S.st_dev ;
fp = setmntent(MOUNTED,"r");
found = False ;
while ((mnt = getmntent(fp)) != (struct mntent *) 0) {
if ( stat(mnt->mnt_dir,&S) == -1 )
continue ;
if (S.st_dev == devno) {
found = True ;
break ;
}
}
endmntent(fp) ;
if ( ! found )
return(False) ;
qcmd = QCMD(Q_GETQUOTA, USRQUOTA);
if (hasmntopt(mnt, MNTOPT_NOAUTO) || hasmntopt(mnt, MNTOPT_NOQUOTA))
return(False) ;
if (!hasquota(mnt, USRQUOTA, &qfpathname))
return(False) ;
euser_id = geteuid();
seteuid(0);
if (quotactl(qcmd, mnt->mnt_fsname, euser_id, (caddr_t)&D) != 0) {
if ((fd = open(qfpathname, O_RDONLY)) < 0) {
seteuid(euser_id);
return(False);
}
lseek(fd, (long) dqoff(euser_id), L_SET);
switch (read(fd, &D, sizeof(struct dqblk))) {
case 0:/* EOF */
memset((caddr_t)&D, 0, sizeof(struct dqblk));
break;
case sizeof(struct dqblk): /* OK */
break;
default: /* ERROR */
close(fd);
seteuid(euser_id);
return(False);
}
}
seteuid(euser_id);
*bsize=1024;
if (D.dqb_bsoftlimit==0)
return(False);
if ((D.dqb_curblocks>D.dqb_bsoftlimit)||(D.dqb_curinodes>D.dqb_isoftlimit))
{
*dfree = 0;
*dsize = D.dqb_curblocks;
}
else {
*dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
*dsize = D.dqb_bsoftlimit;
}
return (True);
}
#elif defined(CRAY)
#include <sys/quota.h>
#include <mntent.h>
/****************************************************************************
try to get the disk space from disk quotas (CRAY VERSION)
****************************************************************************/
BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize)
{
struct mntent *mnt;
FILE *fd;
struct stat sbuf;
dev_t devno ;
static dev_t devno_cached = 0 ;
static char name[MNTMAXSTR] ;
struct q_request request ;
struct qf_header header ;
static int quota_default = 0 ;
int found ;
if ( stat(path,&sbuf) == -1 )
return(False) ;
devno = sbuf.st_dev ;
if ( devno != devno_cached ) {
devno_cached = devno ;
if ((fd = setmntent(KMTAB)) == NULL)
return(False) ;
found = False ;
while ((mnt = getmntent(fd)) != NULL) {
if ( stat(mnt->mnt_dir,&sbuf) == -1 )
continue ;
if (sbuf.st_dev == devno) {
found = True ;
break ;
}
}
strcpy(name,mnt->mnt_dir) ;
endmntent(fd) ;
if ( ! found )
return(False) ;
}
request.qf_magic = QF_MAGIC ;
request.qf_entry.id = geteuid() ;
if (quotactl(name, Q_GETQUOTA, &request) == -1)
return(False) ;
if ( ! request.user )
return(False) ;
if ( request.qf_entry.user_q.f_quota == QFV_DEFAULT ) {
if ( ! quota_default ) {
if ( quotactl(name, Q_GETHEADER, &header) == -1 )
return(False) ;
else
quota_default = header.user_h.def_fq ;
}
*dfree = quota_default ;
}else if ( request.qf_entry.user_q.f_quota == QFV_PREVENT ) {
*dfree = 0 ;
}else{
*dfree = request.qf_entry.user_q.f_quota ;
}
*dsize = request.qf_entry.user_q.f_use ;
if ( *dfree )
*dfree -= *dsize ;
if ( *dfree < 0 )
*dfree = 0 ;
*bsize = 4096 ; /* Cray blocksize */
return(True) ;
}
#elif defined(SUNOS5) || defined(SUNOS4)
#include <fcntl.h>
#if defined(SUNOS5)
#include <sys/fs/ufs_quota.h>
#include <sys/mnttab.h>
#else /* defined(SUNOS4) */
#include <ufs/quota.h>
#include <mntent.h>
#endif
/****************************************************************************
try to get the disk space from disk quotas (solaris 2 version)
****************************************************************************/
/* Quota code by Peter Urbanec (amiga@cse.unsw.edu.au) */
BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize)
{
uid_t user_id, euser_id;
int ret;
struct dqblk D;
#if defined(SUNOS5)
struct quotctl command;
int file;
struct mnttab mnt;
static char name[MNT_LINE_MAX] ;
#else
struct mntent *mnt;
static char name[MNTMAXSTR] ;
#endif
FILE *fd;
struct stat sbuf;
dev_t devno ;
static dev_t devno_cached = 0 ;
int found ;
if ( stat(path,&sbuf) == -1 )
return(False) ;
devno = sbuf.st_dev ;
DEBUG(5,("disk_quotas: looking for path \"%s\" devno=%o\n", path,devno));
if ( devno != devno_cached ) {
devno_cached = devno ;
#if defined(SUNOS5)
if ((fd = fopen(MNTTAB, "r")) == NULL)
return(False) ;
found = False ;
while (getmntent(fd, &mnt) == 0) {
if ( stat(mnt.mnt_mountp,&sbuf) == -1 )
continue ;
DEBUG(5,("disk_quotas: testing \"%s\" devno=%o\n",
mnt.mnt_mountp,sbuf.st_dev));
if (sbuf.st_dev == devno) {
found = True ;
break ;
}
}
strcpy(name,mnt.mnt_mountp) ;
strcat(name,"/quotas") ;
fclose(fd) ;
#else
if ((fd = setmntent(MOUNTED, "r")) == NULL)
return(False) ;
found = False ;
while ((mnt = getmntent(fd)) != NULL) {
if ( stat(mnt->mnt_dir,&sbuf) == -1 )
continue ;
DEBUG(5,("disk_quotas: testing \"%s\" devno=%o\n",
mnt->mnt_dir,sbuf.st_dev));
if (sbuf.st_dev == devno) {
found = True ;
break ;
}
}
strcpy(name,mnt->mnt_fsname) ;
endmntent(fd) ;
#endif
if ( ! found )
return(False) ;
}
euser_id = geteuid();
user_id = getuid();
setuid(0); /* Solaris seems to want to give info only to super-user */
seteuid(0);
#if defined(SUNOS5)
DEBUG(5,("disk_quotas: looking for quotas file \"%s\"\n", name));
if((file=open(name, O_RDONLY))<0) {
setuid(user_id); /* Restore the original UID status */
seteuid(euser_id);
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
setuid(user_id); /* Restore the original UID status */
seteuid(euser_id);
if (ret < 0) {
DEBUG(2,("disk_quotas ioctl (Solaris) failed\n"));
return(False);
}
/* 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 = 512;
*dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
*dsize = D.dqb_bsoftlimit;
if(*dfree < 0)
{
*dfree = 0;
*dsize = D.dqb_curblocks;
}
DEBUG(5,("disk_quotas for path \"%s\" returning bsize %d, dfree %d, dsize %d\n",
path,*bsize,*dfree,*dsize));
return(True);
}
#else
#include <sys/quota.h>
#include <devnm.h>
/****************************************************************************
try to get the disk space from disk quotas - default version
****************************************************************************/
BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize)
{
uid_t user_id, euser_id;
int r;
char dev_disk[256];
struct dqblk D;
struct stat S;
/* find the block device file */
if ((stat(path, &S)<0) ||
(devnm(S_IFBLK, S.st_dev, dev_disk, 256, 0)<0)) return (False);
euser_id = geteuid();
#ifdef USE_SETRES
/* for HPUX, real uid must be same as euid to execute quotactl for euid */
user_id = getuid();
setresuid(euser_id,-1,-1);
#endif
r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D);
#ifdef USE_SETRES
if (setresuid(user_id,-1,-1))
DEBUG(5,("Unable to reset uid to %d\n", user_id));
#endif
/* Use softlimit to determine disk space, except when it has been exceeded */
*bsize = 1024;
if (r)
{
if (errno == EDQUOT)
{
*dfree =0;
*dsize =D.dqb_curblocks;
return (True);
}
else return(False);
}
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)||(D.dqb_curfiles>D.dqb_fsoftlimit))
{
*dfree = 0;
*dsize = D.dqb_curblocks;
}
else {
*dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
*dsize = D.dqb_bsoftlimit;
}
return (True);
}
#endif
#else
/* this keeps fussy compilers happy */
void quotas_dummy(void) {}
#endif /* QUOTAS */