1996-05-05 15:25:33 +04:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
1996-05-05 15:25:33 +04:00
support for quotas
1998-01-22 16:27:43 +03:00
Copyright ( C ) Andrew Tridgell 1992 - 1998
1996-05-05 15:25:33 +04:00
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
2007-07-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
1996-05-05 15:25:33 +04:00
( 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
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
1996-05-05 15:25:33 +04:00
*/
1996-05-31 19:13:29 +04:00
/*
* 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"
2011-03-22 18:57:01 +03:00
# include "smbd/smbd.h"
2011-06-14 10:27:34 +04:00
# include "system/filesys.h"
1996-05-05 15:25:33 +04:00
2004-01-15 11:49:30 +03:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_QUOTA
2003-05-12 05:20:17 +04:00
# ifndef HAVE_SYS_QUOTAS
2003-05-14 18:38:11 +04:00
/* just a quick hack because sysquotas.h is included before linux/quota.h */
# ifdef QUOTABLOCK_SIZE
# undef QUOTABLOCK_SIZE
# endif
2003-05-12 05:20:17 +04:00
# ifdef WITH_QUOTAS
2000-03-13 20:38:13 +03:00
# if defined(VXFS_QUOTA)
/*
* In addition to their native filesystems , some systems have Veritas VxFS .
* Declare here , define at end : reduces likely " include " interaction problems .
* David Lee < T . D . Lee @ durham . ac . uk >
*/
2008-10-14 03:59:36 +04:00
bool disk_quotas_vxfs ( const char * name , char * path , uint64_t * bsize , uint64_t * dfree , uint64_t * dsize ) ;
2000-03-13 20:38:13 +03:00
# endif /* VXFS_QUOTA */
1996-05-05 15:25:33 +04:00
# ifdef LINUX
1996-05-31 19:13:29 +04:00
1997-06-11 05:03:06 +04:00
# include <sys/types.h>
2004-01-05 22:36:02 +03:00
# include <mntent.h>
2001-09-22 02:06:03 +04:00
/*
* This shouldn ' t be neccessary - it should be / usr / include / sys / quota . h
2004-01-05 22:36:02 +03:00
* So we include all the files has * should * be in the system into a large ,
* grungy samba_linux_quoatas . h Sometimes I * hate * Linux : - ) . JRA .
2001-09-22 02:06:03 +04:00
*/
2004-01-05 22:36:02 +03:00
# include "samba_linux_quota.h"
2001-09-22 02:06:03 +04:00
typedef struct _LINUX_SMB_DISK_QUOTA {
2008-10-14 03:59:36 +04:00
uint64_t bsize ;
uint64_t hardlimit ; /* In bsize units. */
uint64_t softlimit ; /* In bsize units. */
uint64_t curblocks ; /* In bsize units. */
uint64_t ihardlimit ; /* inode hard limit. */
uint64_t isoftlimit ; /* inode soft limit. */
uint64_t curinodes ; /* Current used inodes. */
2001-09-22 02:06:03 +04:00
} LINUX_SMB_DISK_QUOTA ;
2007-07-10 05:15:57 +04:00
2010-08-06 13:58:46 +04:00
/*
* nfs quota support
* ( essentially taken from FreeBSD / SUNOS5 section )
*/
# include <rpc/rpc.h>
# include <rpc/types.h>
# include <rpcsvc/rquota.h>
# ifdef HAVE_RPC_NETTYPE_H
# include <rpc/nettype.h>
# endif
# include <rpc/xdr.h>
static int my_xdr_getquota_args ( XDR * xdrsp , struct getquota_args * args )
{
if ( ! xdr_string ( xdrsp , & args - > gqa_pathp , RQ_PATHLEN ) )
return ( 0 ) ;
if ( ! xdr_int ( xdrsp , & args - > gqa_uid ) )
return ( 0 ) ;
return ( 1 ) ;
}
static int my_xdr_getquota_rslt ( XDR * xdrsp , struct getquota_rslt * gqr )
{
int quotastat ;
if ( ! xdr_int ( xdrsp , & quotastat ) ) {
DEBUG ( 6 , ( " nfs_quotas: Status bad or zero \n " ) ) ;
return 0 ;
}
gqr - > status = quotastat ;
if ( ! xdr_int ( xdrsp , & gqr - > getquota_rslt_u . gqr_rquota . rq_bsize ) ) {
DEBUG ( 6 , ( " nfs_quotas: Block size bad or zero \n " ) ) ;
return 0 ;
}
if ( ! xdr_bool ( xdrsp , & gqr - > getquota_rslt_u . gqr_rquota . rq_active ) ) {
DEBUG ( 6 , ( " nfs_quotas: Active bad or zero \n " ) ) ;
return 0 ;
}
if ( ! xdr_int ( xdrsp , ( int * ) & gqr - > getquota_rslt_u . gqr_rquota . rq_bhardlimit ) ) {
DEBUG ( 6 , ( " nfs_quotas: Hardlimit bad or zero \n " ) ) ;
return 0 ;
}
if ( ! xdr_int ( xdrsp , ( int * ) & gqr - > getquota_rslt_u . gqr_rquota . rq_bsoftlimit ) ) {
DEBUG ( 6 , ( " nfs_quotas: Softlimit bad or zero \n " ) ) ;
return 0 ;
}
if ( ! xdr_int ( xdrsp , ( int * ) & gqr - > getquota_rslt_u . gqr_rquota . rq_curblocks ) ) {
DEBUG ( 6 , ( " nfs_quotas: Currentblocks bad or zero \n " ) ) ;
return 0 ;
}
return 1 ;
}
static bool nfs_quotas ( char * nfspath , uid_t euser_id , uint64_t * bsize ,
uint64_t * dfree , uint64_t * dsize )
{
uid_t uid = euser_id ;
LINUX_SMB_DISK_QUOTA D ;
char * mnttype = nfspath ;
CLIENT * clnt ;
struct getquota_rslt gqr ;
struct getquota_args args ;
char * cutstr , * pathname , * host , * testpath ;
int len ;
static struct timeval timeout = { 2 , 0 } ;
enum clnt_stat clnt_stat ;
bool ret = True ;
* bsize = * dfree = * dsize = ( uint64_t ) 0 ;
len = strcspn ( mnttype , " : " ) ;
pathname = strstr ( mnttype , " : " ) ;
cutstr = ( char * ) SMB_MALLOC ( len + 1 ) ;
if ( ! cutstr )
return False ;
memset ( cutstr , ' \0 ' , len + 1 ) ;
host = strncat ( cutstr , mnttype , sizeof ( char ) * len ) ;
DEBUG ( 5 , ( " nfs_quotas: looking for mount on \" %s \" \n " , cutstr ) ) ;
DEBUG ( 5 , ( " nfs_quotas: of path \" %s \" \n " , mnttype ) ) ;
testpath = strchr_m ( mnttype , ' : ' ) ;
args . gqa_pathp = testpath + 1 ;
args . gqa_uid = uid ;
DEBUG ( 5 , ( " nfs_quotas: Asking for host \" %s \" rpcprog \" %i \" rpcvers "
" \" %i \" network \" %s \" \n " , host , RQUOTAPROG , RQUOTAVERS ,
" udp " ) ) ;
if ( ( clnt = clnt_create ( host , RQUOTAPROG , RQUOTAVERS , " udp " ) ) = = NULL ) {
ret = False ;
goto out ;
}
clnt - > cl_auth = authunix_create_default ( ) ;
DEBUG ( 9 , ( " nfs_quotas: auth_success \n " ) ) ;
clnt_stat = clnt_call ( clnt ,
RQUOTAPROC_GETQUOTA ,
( const xdrproc_t ) my_xdr_getquota_args ,
( caddr_t ) & args ,
( const xdrproc_t ) my_xdr_getquota_rslt ,
( caddr_t ) & gqr , timeout ) ;
if ( clnt_stat ! = RPC_SUCCESS ) {
DEBUG ( 9 , ( " nfs_quotas: clnt_call fail \n " ) ) ;
ret = False ;
goto out ;
}
/*
* gqr . status returns 0 if the rpc call fails , 1 if quotas exist , 2 if there is
* no quota set , and 3 if no permission to get the quota . If 0 or 3 return
* something sensible .
*/
switch ( gqr . status ) {
case 0 :
DEBUG ( 9 , ( " nfs_quotas: Remote Quotas Failed! Error \" %i \" \n " ,
gqr . status ) ) ;
ret = False ;
goto out ;
case 1 :
DEBUG ( 9 , ( " nfs_quotas: Good quota data \n " ) ) ;
D . softlimit = gqr . getquota_rslt_u . gqr_rquota . rq_bsoftlimit ;
D . hardlimit = gqr . getquota_rslt_u . gqr_rquota . rq_bhardlimit ;
D . curblocks = gqr . getquota_rslt_u . gqr_rquota . rq_curblocks ;
break ;
case 2 :
case 3 :
D . softlimit = 1 ;
D . curblocks = 1 ;
DEBUG ( 9 , ( " nfs_quotas: Remote Quotas returned \" %i \" \n " ,
gqr . status ) ) ;
break ;
default :
DEBUG ( 9 , ( " nfs_quotas: Remote Quotas Questionable! "
" Error \" %i \" \n " , gqr . status ) ) ;
break ;
}
DEBUG ( 10 , ( " nfs_quotas: Let`s look at D a bit closer... "
" status \" %i \" bsize \" %i \" active? \" %i \" bhard "
" \" %i \" bsoft \" %i \" curb \" %i \" \n " ,
gqr . status ,
gqr . getquota_rslt_u . gqr_rquota . rq_bsize ,
gqr . getquota_rslt_u . gqr_rquota . rq_active ,
gqr . getquota_rslt_u . gqr_rquota . rq_bhardlimit ,
gqr . getquota_rslt_u . gqr_rquota . rq_bsoftlimit ,
gqr . getquota_rslt_u . gqr_rquota . rq_curblocks ) ) ;
if ( D . softlimit = = 0 )
D . softlimit = D . hardlimit ;
if ( D . softlimit = = 0 )
return False ;
* bsize = gqr . getquota_rslt_u . gqr_rquota . rq_bsize ;
* dsize = D . softlimit ;
if ( D . curblocks = = 1 )
* bsize = DEV_BSIZE ;
if ( D . curblocks > D . softlimit ) {
* dfree = 0 ;
* dsize = D . curblocks ;
} else
* dfree = D . softlimit - D . curblocks ;
out :
if ( clnt ) {
if ( clnt - > cl_auth )
auth_destroy ( clnt - > cl_auth ) ;
clnt_destroy ( clnt ) ;
}
DEBUG ( 5 , ( " nfs_quotas: For path \" %s \" returning "
" bsize %.0f, dfree %.0f, dsize %.0f \n " ,
args . gqa_pathp , ( double ) * bsize , ( double ) * dfree ,
( double ) * dsize ) ) ;
SAFE_FREE ( cutstr ) ;
DEBUG ( 10 , ( " nfs_quotas: End of nfs_quotas \n " ) ) ;
return ret ;
}
/* end of nfs quota section */
2007-07-10 05:15:57 +04:00
# ifdef HAVE_LINUX_DQBLK_XFS_H
# include <linux/dqblk_xfs.h>
2001-12-01 00:50:02 +03:00
/****************************************************************************
Abstract out the XFS Quota Manager quota get call .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-01-05 22:36:02 +03:00
static int get_smb_linux_xfs_quota ( char * path , uid_t euser_id , gid_t egrp_id , LINUX_SMB_DISK_QUOTA * dp )
2001-12-01 00:50:02 +03:00
{
2003-11-19 05:19:34 +03:00
struct fs_disk_quota D ;
2004-01-05 22:36:02 +03:00
int ret ;
2003-11-19 05:19:34 +03:00
ZERO_STRUCT ( D ) ;
2004-01-15 11:49:30 +03:00
ret = quotactl ( QCMD ( Q_XGETQUOTA , USRQUOTA ) , path , euser_id , ( caddr_t ) & D ) ;
2003-11-19 05:19:34 +03:00
2004-01-05 22:36:02 +03:00
if ( ret )
2004-01-15 11:49:30 +03:00
ret = quotactl ( QCMD ( Q_XGETQUOTA , GRPQUOTA ) , path , egrp_id , ( caddr_t ) & D ) ;
2004-01-05 22:36:02 +03:00
if ( ret )
return ret ;
2003-11-19 05:19:34 +03:00
2008-10-14 03:59:36 +04:00
dp - > bsize = ( uint64_t ) 512 ;
dp - > softlimit = ( uint64_t ) D . d_blk_softlimit ;
dp - > hardlimit = ( uint64_t ) D . d_blk_hardlimit ;
dp - > ihardlimit = ( uint64_t ) D . d_ino_hardlimit ;
dp - > isoftlimit = ( uint64_t ) D . d_ino_softlimit ;
dp - > curinodes = ( uint64_t ) D . d_icount ;
dp - > curblocks = ( uint64_t ) D . d_bcount ;
2004-01-05 22:36:02 +03:00
2003-11-19 05:19:34 +03:00
return ret ;
2001-12-01 00:50:02 +03:00
}
2007-07-10 05:15:57 +04:00
# else
static int get_smb_linux_xfs_quota ( char * path , uid_t euser_id , gid_t egrp_id , LINUX_SMB_DISK_QUOTA * dp )
{
DEBUG ( 0 , ( " XFS quota support not available \n " ) ) ;
errno = ENOSYS ;
return - 1 ;
}
# endif
2001-12-01 00:50:02 +03:00
2001-09-22 02:06:03 +04:00
/****************************************************************************
Abstract out the old and new Linux quota get calls .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-01-05 22:36:02 +03:00
static int get_smb_linux_v1_quota ( char * path , uid_t euser_id , gid_t egrp_id , LINUX_SMB_DISK_QUOTA * dp )
2001-09-22 02:06:03 +04:00
{
2004-01-05 22:36:02 +03:00
struct v1_kern_dqblk D ;
int ret ;
2001-09-22 02:06:03 +04:00
ZERO_STRUCT ( D ) ;
2004-01-05 22:36:02 +03:00
ret = quotactl ( QCMD ( Q_V1_GETQUOTA , USRQUOTA ) , path , euser_id , ( caddr_t ) & D ) ;
if ( ret & & errno ! = EDQUOT )
ret = quotactl ( QCMD ( Q_V1_GETQUOTA , GRPQUOTA ) , path , egrp_id , ( caddr_t ) & D ) ;
if ( ret & & errno ! = EDQUOT )
return ret ;
2008-10-14 03:59:36 +04:00
dp - > bsize = ( uint64_t ) QUOTABLOCK_SIZE ;
dp - > softlimit = ( uint64_t ) D . dqb_bsoftlimit ;
dp - > hardlimit = ( uint64_t ) D . dqb_bhardlimit ;
dp - > ihardlimit = ( uint64_t ) D . dqb_ihardlimit ;
dp - > isoftlimit = ( uint64_t ) D . dqb_isoftlimit ;
dp - > curinodes = ( uint64_t ) D . dqb_curinodes ;
dp - > curblocks = ( uint64_t ) D . dqb_curblocks ;
2004-01-05 22:36:02 +03:00
return ret ;
}
static int get_smb_linux_v2_quota ( char * path , uid_t euser_id , gid_t egrp_id , LINUX_SMB_DISK_QUOTA * dp )
{
struct v2_kern_dqblk D ;
int ret ;
2001-09-22 02:06:03 +04:00
ZERO_STRUCT ( D ) ;
2004-01-05 22:36:02 +03:00
ret = quotactl ( QCMD ( Q_V2_GETQUOTA , USRQUOTA ) , path , euser_id , ( caddr_t ) & D ) ;
if ( ret & & errno ! = EDQUOT )
ret = quotactl ( QCMD ( Q_V2_GETQUOTA , GRPQUOTA ) , path , egrp_id , ( caddr_t ) & D ) ;
if ( ret & & errno ! = EDQUOT )
return ret ;
2008-10-14 03:59:36 +04:00
dp - > bsize = ( uint64_t ) QUOTABLOCK_SIZE ;
dp - > softlimit = ( uint64_t ) D . dqb_bsoftlimit ;
dp - > hardlimit = ( uint64_t ) D . dqb_bhardlimit ;
dp - > ihardlimit = ( uint64_t ) D . dqb_ihardlimit ;
dp - > isoftlimit = ( uint64_t ) D . dqb_isoftlimit ;
dp - > curinodes = ( uint64_t ) D . dqb_curinodes ;
dp - > curblocks = ( ( uint64_t ) D . dqb_curspace ) / dp - > bsize ;
2004-01-05 22:36:02 +03:00
return ret ;
}
/****************************************************************************
Brand - new generic quota interface .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int get_smb_linux_gen_quota ( char * path , uid_t euser_id , gid_t egrp_id , LINUX_SMB_DISK_QUOTA * dp )
{
struct if_dqblk D ;
int ret ;
ZERO_STRUCT ( D ) ;
2001-09-22 02:06:03 +04:00
2003-11-19 05:19:34 +03:00
ret = quotactl ( QCMD ( Q_GETQUOTA , USRQUOTA ) , path , euser_id , ( caddr_t ) & D ) ;
2004-01-05 22:36:02 +03:00
if ( ret & & errno ! = EDQUOT )
ret = quotactl ( QCMD ( Q_GETQUOTA , GRPQUOTA ) , path , egrp_id , ( caddr_t ) & D ) ;
2001-09-22 02:06:03 +04:00
2004-01-05 22:36:02 +03:00
if ( ret & & errno ! = EDQUOT )
return ret ;
2008-10-14 03:59:36 +04:00
dp - > bsize = ( uint64_t ) QUOTABLOCK_SIZE ;
dp - > softlimit = ( uint64_t ) D . dqb_bsoftlimit ;
dp - > hardlimit = ( uint64_t ) D . dqb_bhardlimit ;
dp - > ihardlimit = ( uint64_t ) D . dqb_ihardlimit ;
dp - > isoftlimit = ( uint64_t ) D . dqb_isoftlimit ;
dp - > curinodes = ( uint64_t ) D . dqb_curinodes ;
dp - > curblocks = ( ( uint64_t ) D . dqb_curspace ) / dp - > bsize ;
2001-09-22 02:06:03 +04:00
2003-11-19 05:19:34 +03:00
return ret ;
2001-09-22 02:06:03 +04:00
}
1996-05-31 19:13:29 +04:00
1996-05-05 15:25:33 +04:00
/****************************************************************************
2004-01-05 22:36:02 +03:00
Try to get the disk space from disk quotas ( LINUX version ) .
1996-05-05 15:25:33 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1997-06-11 05:03:06 +04:00
2008-10-14 03:59:36 +04:00
bool disk_quotas ( const char * path , uint64_t * bsize , uint64_t * dfree , uint64_t * dsize )
1996-05-05 15:25:33 +04:00
{
2001-09-22 02:06:03 +04:00
int r ;
SMB_STRUCT_STAT S ;
FILE * fp ;
LINUX_SMB_DISK_QUOTA D ;
struct mntent * mnt ;
SMB_DEV_T devno ;
int found ;
uid_t euser_id ;
2004-01-05 22:36:02 +03:00
gid_t egrp_id ;
2001-09-22 02:06:03 +04:00
2005-12-25 13:41:34 +03:00
ZERO_STRUCT ( D ) ;
2001-09-22 02:06:03 +04:00
euser_id = geteuid ( ) ;
2004-01-05 22:36:02 +03:00
egrp_id = getegid ( ) ;
2001-09-22 02:06:03 +04:00
/* find the block device file */
2007-11-13 23:51:31 +03:00
2009-11-27 14:57:43 +03:00
if ( sys_stat ( path , & S , false ) = = - 1 )
2001-09-22 02:06:03 +04:00
return ( False ) ;
1996-05-05 15:25:33 +04:00
2009-06-29 18:26:42 +04:00
devno = S . st_ex_dev ;
2007-11-13 23:51:31 +03:00
2005-12-05 19:51:19 +03:00
if ( ( fp = setmntent ( MOUNTED , " r " ) ) = = NULL )
return ( False ) ;
2001-09-22 02:06:03 +04:00
found = False ;
2007-11-13 23:51:31 +03:00
2001-09-22 02:06:03 +04:00
while ( ( mnt = getmntent ( fp ) ) ) {
2009-11-27 14:57:43 +03:00
if ( sys_stat ( mnt - > mnt_dir , & S , false ) = = - 1 )
2001-09-22 02:06:03 +04:00
continue ;
2009-06-29 18:26:42 +04:00
if ( S . st_ex_dev = = devno ) {
2001-09-22 02:06:03 +04:00
found = True ;
break ;
}
}
endmntent ( fp ) ;
2007-11-13 23:51:31 +03:00
2001-09-22 02:06:03 +04:00
if ( ! found )
return ( False ) ;
2007-04-06 03:56:10 +04:00
become_root ( ) ;
2004-01-05 22:36:02 +03:00
2010-08-06 13:58:46 +04:00
if ( strcmp ( mnt - > mnt_type , " nfs " ) = = 0 ) {
bool retval ;
retval = nfs_quotas ( mnt - > mnt_fsname , euser_id , bsize , dfree , dsize ) ;
unbecome_root ( ) ;
return retval ;
}
2004-01-05 22:36:02 +03:00
if ( strcmp ( mnt - > mnt_type , " xfs " ) = = 0 ) {
r = get_smb_linux_xfs_quota ( mnt - > mnt_fsname , euser_id , egrp_id , & D ) ;
} else {
r = get_smb_linux_gen_quota ( mnt - > mnt_fsname , euser_id , egrp_id , & D ) ;
if ( r = = - 1 & & errno ! = EDQUOT ) {
r = get_smb_linux_v2_quota ( mnt - > mnt_fsname , euser_id , egrp_id , & D ) ;
if ( r = = - 1 & & errno ! = EDQUOT )
r = get_smb_linux_v1_quota ( mnt - > mnt_fsname , euser_id , egrp_id , & D ) ;
}
}
2007-04-06 03:56:10 +04:00
unbecome_root ( ) ;
2001-09-22 02:06:03 +04:00
/* Use softlimit to determine disk space, except when it has been exceeded */
* bsize = D . bsize ;
if ( r = = - 1 ) {
if ( errno = = EDQUOT ) {
* dfree = 0 ;
* dsize = D . curblocks ;
return ( True ) ;
} else {
return ( False ) ;
}
}
/* Use softlimit to determine disk space, except when it has been exceeded */
if (
( D . softlimit & & D . curblocks > = D . softlimit ) | |
( D . hardlimit & & D . curblocks > = D . hardlimit ) | |
( D . isoftlimit & & D . curinodes > = D . isoftlimit ) | |
( D . ihardlimit & & D . curinodes > = D . ihardlimit )
) {
* dfree = 0 ;
* dsize = D . curblocks ;
} else if ( D . softlimit = = 0 & & D . hardlimit = = 0 ) {
return ( False ) ;
} else {
if ( D . softlimit = = 0 )
D . softlimit = D . hardlimit ;
* dfree = D . softlimit - D . curblocks ;
* dsize = D . softlimit ;
}
return ( True ) ;
1996-05-05 15:25:33 +04:00
}
# elif defined(CRAY)
1996-05-31 19:13:29 +04:00
# include <sys/quota.h>
# include <mntent.h>
1996-05-05 15:25:33 +04:00
/****************************************************************************
try to get the disk space from disk quotas ( CRAY VERSION )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-11-06 21:40:51 +03:00
2008-10-14 03:59:36 +04:00
bool disk_quotas ( const char * path , uint64_t * bsize , uint64_t * dfree , uint64_t * dsize )
1996-05-05 15:25:33 +04:00
{
2007-11-13 23:51:31 +03:00
struct mntent * mnt ;
FILE * fd ;
SMB_STRUCT_STAT sbuf ;
SMB_DEV_T devno ;
struct q_request request ;
struct qf_header header ;
int quota_default = 0 ;
bool found = false ;
2009-11-27 14:57:43 +03:00
if ( sys_stat ( path , & sbuf , false ) = = - 1 ) {
2007-11-13 23:51:31 +03:00
return false ;
}
2009-06-29 18:26:42 +04:00
devno = sbuf . st_ex_dev ;
2007-11-13 23:51:31 +03:00
if ( ( fd = setmntent ( KMTAB ) ) = = NULL ) {
return false ;
}
while ( ( mnt = getmntent ( fd ) ) ! = NULL ) {
2009-12-12 18:58:31 +03:00
if ( sys_stat ( mnt - > mnt_dir , & sbuf , false ) = = - 1 ) {
2007-11-13 23:51:31 +03:00
continue ;
}
2009-06-29 18:26:42 +04:00
if ( sbuf . st_ex_dev = = devno ) {
2007-11-13 23:51:31 +03:00
found = frue ;
break ;
}
}
name = talloc_strdup ( talloc_tos ( ) , mnt - > mnt_dir ) ;
endmntent ( fd ) ;
if ( ! found ) {
return false ;
}
if ( ! name ) {
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 < * dsize ) {
* dfree = 0 ;
} else {
* dfree - = * dsize ;
}
* bsize = 4096 ; /* Cray blocksize */
return true ;
1996-05-05 15:25:33 +04:00
}
1996-06-08 08:33:37 +04:00
# elif defined(SUNOS5) || defined(SUNOS4)
1996-05-05 15:25:33 +04:00
# include <fcntl.h>
1998-11-06 21:40:51 +03:00
# include <sys/param.h>
1996-06-08 08:33:37 +04:00
# if defined(SUNOS5)
1996-05-05 15:25:33 +04:00
# include <sys/fs/ufs_quota.h>
1996-06-08 08:33:37 +04:00
# include <sys/mnttab.h>
2001-02-28 00:46:01 +03:00
# include <sys/mntent.h>
1996-06-08 08:33:37 +04:00
# else /* defined(SUNOS4) */
# include <ufs/quota.h>
# include <mntent.h>
# endif
1996-05-05 15:25:33 +04:00
2001-04-01 23:00:43 +04:00
# if defined(SUNOS5)
/****************************************************************************
Allows querying of remote hosts for quotas on NFS mounted shares .
Supports normal NFS and AMD mounts .
Alan Romeril < a . romeril @ ic . ac . uk > July 2 K .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include <rpc/rpc.h>
# include <rpc/types.h>
# include <rpcsvc/rquota.h>
# include <rpc/nettype.h>
# include <rpc/xdr.h>
2005-10-11 18:46:40 +04:00
static int my_xdr_getquota_args ( XDR * xdrsp , struct getquota_args * args )
2001-04-01 23:00:43 +04:00
{
if ( ! xdr_string ( xdrsp , & args - > gqa_pathp , RQ_PATHLEN ) )
return ( 0 ) ;
if ( ! xdr_int ( xdrsp , & args - > gqa_uid ) )
return ( 0 ) ;
return ( 1 ) ;
}
2005-10-11 18:46:40 +04:00
static int my_xdr_getquota_rslt ( XDR * xdrsp , struct getquota_rslt * gqr )
2001-04-01 23:00:43 +04:00
{
2009-01-08 12:43:10 +03:00
int quotastat ;
2001-04-01 23:00:43 +04:00
if ( ! xdr_int ( xdrsp , & quotastat ) ) {
DEBUG ( 6 , ( " nfs_quotas: Status bad or zero \n " ) ) ;
return 0 ;
}
2009-01-08 12:43:10 +03:00
gqr - > status = quotastat ;
2001-04-06 00:46:15 +04:00
if ( ! xdr_int ( xdrsp , & gqr - > getquota_rslt_u . gqr_rquota . rq_bsize ) ) {
2001-04-01 23:00:43 +04:00
DEBUG ( 6 , ( " nfs_quotas: Block size bad or zero \n " ) ) ;
return 0 ;
}
if ( ! xdr_bool ( xdrsp , & gqr - > getquota_rslt_u . gqr_rquota . rq_active ) ) {
DEBUG ( 6 , ( " nfs_quotas: Active bad or zero \n " ) ) ;
return 0 ;
}
2001-04-06 00:46:15 +04:00
if ( ! xdr_int ( xdrsp , & gqr - > getquota_rslt_u . gqr_rquota . rq_bhardlimit ) ) {
2001-04-01 23:00:43 +04:00
DEBUG ( 6 , ( " nfs_quotas: Hardlimit bad or zero \n " ) ) ;
return 0 ;
}
2001-04-06 00:46:15 +04:00
if ( ! xdr_int ( xdrsp , & gqr - > getquota_rslt_u . gqr_rquota . rq_bsoftlimit ) ) {
2001-04-01 23:00:43 +04:00
DEBUG ( 6 , ( " nfs_quotas: Softlimit bad or zero \n " ) ) ;
return 0 ;
}
2001-04-06 00:46:15 +04:00
if ( ! xdr_int ( xdrsp , & gqr - > getquota_rslt_u . gqr_rquota . rq_curblocks ) ) {
2001-04-01 23:00:43 +04:00
DEBUG ( 6 , ( " nfs_quotas: Currentblocks bad or zero \n " ) ) ;
return 0 ;
}
return ( 1 ) ;
}
2007-11-13 23:51:31 +03:00
/* Restricted to SUNOS5 for the moment, I haven`t access to others to test. */
2008-10-14 03:59:36 +04:00
static bool nfs_quotas ( char * nfspath , uid_t euser_id , uint64_t * bsize , uint64_t * dfree , uint64_t * dsize )
2001-04-01 23:00:43 +04:00
{
uid_t uid = euser_id ;
struct dqblk D ;
char * mnttype = nfspath ;
CLIENT * clnt ;
struct getquota_rslt gqr ;
struct getquota_args args ;
char * cutstr , * pathname , * host , * testpath ;
int len ;
static struct timeval timeout = { 2 , 0 } ;
enum clnt_stat clnt_stat ;
2007-10-19 04:40:25 +04:00
bool ret = True ;
2001-04-27 23:56:15 +04:00
2008-10-14 03:59:36 +04:00
* bsize = * dfree = * dsize = ( uint64_t ) 0 ;
2001-04-01 23:00:43 +04:00
len = strcspn ( mnttype , " : " ) ;
pathname = strstr ( mnttype , " : " ) ;
2004-12-21 04:04:11 +03:00
cutstr = ( char * ) SMB_MALLOC ( len + 1 ) ;
2001-04-01 23:00:43 +04:00
if ( ! cutstr )
return False ;
2003-03-11 21:10:27 +03:00
memset ( cutstr , ' \0 ' , len + 1 ) ;
2001-04-01 23:00:43 +04:00
host = strncat ( cutstr , mnttype , sizeof ( char ) * len ) ;
DEBUG ( 5 , ( " nfs_quotas: looking for mount on \" %s \" \n " , cutstr ) ) ;
DEBUG ( 5 , ( " nfs_quotas: of path \" %s \" \n " , mnttype ) ) ;
2001-07-04 11:36:09 +04:00
testpath = strchr_m ( mnttype , ' : ' ) ;
2001-04-01 23:00:43 +04:00
args . gqa_pathp = testpath + 1 ;
args . gqa_uid = uid ;
DEBUG ( 5 , ( " nfs_quotas: Asking for host \" %s \" rpcprog \" %i \" rpcvers \" %i \" network \" %s \" \n " , host , RQUOTAPROG , RQUOTAVERS , " udp " ) ) ;
2001-04-27 23:56:15 +04:00
if ( ( clnt = clnt_create ( host , RQUOTAPROG , RQUOTAVERS , " udp " ) ) = = NULL ) {
ret = False ;
goto out ;
}
clnt - > cl_auth = authunix_create_default ( ) ;
DEBUG ( 9 , ( " nfs_quotas: auth_success \n " ) ) ;
2001-04-01 23:00:43 +04:00
2005-10-11 18:46:40 +04:00
clnt_stat = clnt_call ( clnt , RQUOTAPROC_GETQUOTA , my_xdr_getquota_args , ( caddr_t ) & args , my_xdr_getquota_rslt , ( caddr_t ) & gqr , timeout ) ;
2001-04-01 23:00:43 +04:00
2001-04-27 23:56:15 +04:00
if ( clnt_stat ! = RPC_SUCCESS ) {
DEBUG ( 9 , ( " nfs_quotas: clnt_call fail \n " ) ) ;
ret = False ;
goto out ;
}
2001-04-01 23:00:43 +04:00
2007-11-13 23:51:31 +03:00
/*
2009-01-08 12:43:10 +03:00
* gqr . status returns 0 if the rpc call fails , 1 if quotas exist , 2 if there is
2001-04-01 23:00:43 +04:00
* no quota set , and 3 if no permission to get the quota . If 0 or 3 return
* something sensible .
2007-11-13 23:51:31 +03:00
*/
2001-04-01 23:00:43 +04:00
2009-01-08 12:43:10 +03:00
switch ( gqr . status ) {
2001-04-27 23:56:15 +04:00
case 0 :
2009-01-08 12:43:10 +03:00
DEBUG ( 9 , ( " nfs_quotas: Remote Quotas Failed! Error \" %i \" \n " , gqr . status ) ) ;
2001-04-27 23:56:15 +04:00
ret = False ;
goto out ;
case 1 :
2001-04-01 23:00:43 +04:00
DEBUG ( 9 , ( " nfs_quotas: Good quota data \n " ) ) ;
D . dqb_bsoftlimit = gqr . getquota_rslt_u . gqr_rquota . rq_bsoftlimit ;
D . dqb_bhardlimit = gqr . getquota_rslt_u . gqr_rquota . rq_bhardlimit ;
D . dqb_curblocks = gqr . getquota_rslt_u . gqr_rquota . rq_curblocks ;
2001-04-27 23:56:15 +04:00
break ;
2001-04-01 23:00:43 +04:00
2001-04-27 23:56:15 +04:00
case 2 :
case 3 :
2001-04-01 23:00:43 +04:00
D . dqb_bsoftlimit = 1 ;
D . dqb_curblocks = 1 ;
2009-01-08 12:43:10 +03:00
DEBUG ( 9 , ( " nfs_quotas: Remote Quotas returned \" %i \" \n " , gqr . status ) ) ;
2001-04-27 23:56:15 +04:00
break ;
2001-04-01 23:00:43 +04:00
2001-04-27 23:56:15 +04:00
default :
2009-01-08 12:43:10 +03:00
DEBUG ( 9 , ( " nfs_quotas: Remote Quotas Questionable! Error \" %i \" \n " , gqr . status ) ) ;
2001-04-27 23:56:15 +04:00
break ;
}
2001-04-01 23:00:43 +04:00
DEBUG ( 10 , ( " nfs_quotas: Let`s look at D a bit closer... status \" %i \" bsize \" %i \" active? \" %i \" bhard \" %i \" bsoft \" %i \" curb \" %i \" \n " ,
2009-01-08 12:43:10 +03:00
gqr . status ,
2001-04-01 23:00:43 +04:00
gqr . getquota_rslt_u . gqr_rquota . rq_bsize ,
gqr . getquota_rslt_u . gqr_rquota . rq_active ,
gqr . getquota_rslt_u . gqr_rquota . rq_bhardlimit ,
gqr . getquota_rslt_u . gqr_rquota . rq_bsoftlimit ,
gqr . getquota_rslt_u . gqr_rquota . rq_curblocks ) ) ;
* bsize = gqr . getquota_rslt_u . gqr_rquota . rq_bsize ;
* dsize = D . dqb_bsoftlimit ;
2008-09-16 05:21:02 +04:00
if ( D . dqb_curblocks = = 1 )
2001-04-01 23:00:43 +04:00
* bsize = 512 ;
if ( D . dqb_curblocks > D . dqb_bsoftlimit ) {
* dfree = 0 ;
* dsize = D . dqb_curblocks ;
} else
* dfree = D . dqb_bsoftlimit - D . dqb_curblocks ;
2001-04-27 23:56:15 +04:00
out :
if ( clnt ) {
if ( clnt - > cl_auth )
auth_destroy ( clnt - > cl_auth ) ;
clnt_destroy ( clnt ) ;
}
2001-04-01 23:00:43 +04:00
DEBUG ( 5 , ( " nfs_quotas: For path \" %s \" returning bsize %.0f, dfree %.0f, dsize %.0f \n " , args . gqa_pathp , ( double ) * bsize , ( double ) * dfree , ( double ) * dsize ) ) ;
2001-09-17 15:25:41 +04:00
SAFE_FREE ( cutstr ) ;
2001-04-01 23:00:43 +04:00
DEBUG ( 10 , ( " nfs_quotas: End of nfs_quotas \n " ) ) ;
2001-04-27 23:56:15 +04:00
return ret ;
2001-04-01 23:00:43 +04:00
}
# endif
1996-05-05 15:25:33 +04:00
/****************************************************************************
1998-11-06 21:40:51 +03:00
try to get the disk space from disk quotas ( SunOS & Solaris2 version )
1998-11-09 23:33:37 +03:00
Quota code by Peter Urbanec ( amiga @ cse . unsw . edu . au ) .
1998-11-06 21:40:51 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-11-13 23:51:31 +03:00
bool disk_quotas ( const char * path ,
2008-10-14 03:59:36 +04:00
uint64_t * bsize ,
uint64_t * dfree ,
uint64_t * dsize )
1996-05-05 15:25:33 +04:00
{
2001-04-01 23:00:43 +04:00
uid_t euser_id ;
int ret ;
struct dqblk D ;
1996-06-08 08:33:37 +04:00
# if defined(SUNOS5)
2001-04-01 23:00:43 +04:00
struct quotctl command ;
int file ;
2007-11-13 23:51:31 +03:00
struct mnttab mnt ;
1998-11-06 21:40:51 +03:00
# else /* SunOS4 */
2001-04-01 23:00:43 +04:00
struct mntent * mnt ;
1996-06-08 08:33:37 +04:00
# endif
2007-11-13 23:51:31 +03:00
char * name = NULL ;
2001-04-01 23:00:43 +04:00
FILE * fd ;
SMB_STRUCT_STAT sbuf ;
2007-11-13 23:51:31 +03:00
SMB_DEV_T devno ;
bool found = false ;
1999-12-13 16:27:58 +03:00
2001-04-01 23:00:43 +04:00
euser_id = geteuid ( ) ;
2007-11-13 23:51:31 +03:00
2009-12-12 18:58:31 +03:00
if ( sys_stat ( path , & sbuf , false ) = = - 1 ) {
2007-11-13 23:51:31 +03:00
return false ;
}
2009-06-29 18:26:42 +04:00
devno = sbuf . st_ex_dev ;
2006-10-13 09:22:36 +04:00
DEBUG ( 5 , ( " disk_quotas: looking for path \" %s \" devno=%x \n " ,
path , ( unsigned int ) devno ) ) ;
1996-06-08 08:33:37 +04:00
# if defined(SUNOS5)
2007-11-13 23:51:31 +03:00
if ( ( fd = sys_fopen ( MNTTAB , " r " ) ) = = NULL ) {
return false ;
}
while ( getmntent ( fd , & mnt ) = = 0 ) {
2009-11-27 14:57:43 +03:00
if ( sys_stat ( mnt . mnt_mountp , & sbuf , false ) = = - 1 ) {
2007-11-13 23:51:31 +03:00
continue ;
2001-04-01 23:00:43 +04:00
}
2007-11-13 23:51:31 +03:00
DEBUG ( 5 , ( " disk_quotas: testing \" %s \" devno=%x \n " ,
mnt . mnt_mountp , ( unsigned int ) devno ) ) ;
/* quotas are only on vxfs, UFS or NFS */
2009-06-29 18:26:42 +04:00
if ( ( sbuf . st_ex_dev = = devno ) & & (
2007-11-13 23:51:31 +03:00
strcmp ( mnt . mnt_fstype , MNTTYPE_UFS ) = = 0 | |
strcmp ( mnt . mnt_fstype , " nfs " ) = = 0 | |
strcmp ( mnt . mnt_fstype , " vxfs " ) = = 0 ) ) {
found = true ;
name = talloc_asprintf ( talloc_tos ( ) ,
" %s/quotas " ,
mnt . mnt_mountp ) ;
2001-04-01 23:00:43 +04:00
break ;
}
}
1996-05-05 15:25:33 +04:00
2007-11-13 23:51:31 +03:00
fclose ( fd ) ;
# else /* SunOS4 */
if ( ( fd = setmntent ( MOUNTED , " r " ) ) = = NULL ) {
return false ;
}
while ( ( mnt = getmntent ( fd ) ) ! = NULL ) {
2009-11-27 14:57:43 +03:00
if ( sys_stat ( mnt - > mnt_dir , & sbuf , false ) = = - 1 ) {
2007-11-13 23:51:31 +03:00
continue ;
}
DEBUG ( 5 , ( " disk_quotas: testing \" %s \" devno=%x \n " ,
mnt - > mnt_dir ,
2009-06-29 18:26:42 +04:00
( unsigned int ) sbuf . st_ex_dev ) ) ;
if ( sbuf . st_ex_dev = = devno ) {
2007-11-13 23:51:31 +03:00
found = true ;
name = talloc_strdup ( talloc_tos ( ) ,
mnt - > mnt_fsname ) ;
break ;
}
}
2001-02-28 00:46:01 +03:00
2007-11-13 23:51:31 +03:00
endmntent ( fd ) ;
# endif
if ( ! found ) {
return false ;
}
if ( ! name ) {
return false ;
}
2007-04-06 03:56:10 +04:00
become_root ( ) ;
1996-05-31 19:13:29 +04:00
1996-06-08 08:33:37 +04:00
# if defined(SUNOS5)
2007-11-13 23:51:31 +03:00
if ( strcmp ( mnt . mnt_fstype , " nfs " ) = = 0 ) {
2007-10-19 04:40:25 +04:00
bool retval ;
2007-11-13 23:51:31 +03:00
DEBUG ( 5 , ( " disk_quotas: looking for mountpath (NFS) \" %s \" \n " ,
mnt . mnt_special ) ) ;
retval = nfs_quotas ( mnt . mnt_special ,
euser_id , bsize , dfree , dsize ) ;
2007-04-10 19:41:23 +04:00
unbecome_root ( ) ;
2001-04-01 23:00:43 +04:00
return retval ;
}
DEBUG ( 5 , ( " disk_quotas: looking for quotas file \" %s \" \n " , name ) ) ;
2012-03-28 05:48:00 +04:00
if ( ( file = open ( name , O_RDONLY , 0 ) ) < 0 ) {
2007-04-06 03:56:10 +04:00
unbecome_root ( ) ;
2007-11-13 23:51:31 +03:00
return false ;
2001-04-01 23:00:43 +04:00
}
command . op = Q_GETQUOTA ;
command . uid = euser_id ;
command . addr = ( caddr_t ) & D ;
ret = ioctl ( file , Q_QUOTACTL , & command ) ;
close ( file ) ;
1996-06-08 08:33:37 +04:00
# else
2001-04-01 23:00:43 +04:00
DEBUG ( 5 , ( " disk_quotas: trying quotactl on device \" %s \" \n " , name ) ) ;
ret = quotactl ( Q_GETQUOTA , name , euser_id , & D ) ;
1996-06-08 08:33:37 +04:00
# endif
1996-05-05 15:25:33 +04:00
2007-04-06 03:56:10 +04:00
unbecome_root ( ) ;
1996-05-05 15:25:33 +04:00
2001-04-01 23:00:43 +04:00
if ( ret < 0 ) {
2007-11-13 23:51:31 +03:00
DEBUG ( 5 , ( " disk_quotas ioctl (Solaris) failed. Error = %s \n " ,
strerror ( errno ) ) ) ;
2000-03-13 20:38:13 +03:00
# if defined(SUNOS5) && defined(VXFS_QUOTA)
2001-04-01 23:00:43 +04:00
/* 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 " ) ) {
2007-10-19 04:40:25 +04:00
bool retval ;
2007-11-13 23:51:31 +03:00
retval = disk_quotas_vxfs ( name , path ,
bsize , dfree , dsize ) ;
return retval ;
2001-04-01 23:00:43 +04:00
}
2000-03-13 20:38:13 +03:00
# else
2007-11-13 23:51:31 +03:00
return false ;
2000-03-13 20:38:13 +03:00
# endif
2001-04-01 23:00:43 +04:00
}
1996-05-31 19:13:29 +04:00
2001-04-01 23:00:43 +04:00
/* If softlimit is zero, set it equal to hardlimit.
*/
2007-11-13 23:51:31 +03:00
if ( D . dqb_bsoftlimit = = 0 ) {
2001-04-01 23:00:43 +04:00
D . dqb_bsoftlimit = D . dqb_bhardlimit ;
2007-11-13 23:51:31 +03:00
}
2001-04-01 23:00:43 +04:00
2007-11-13 23:51:31 +03:00
/* 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 : - )
2001-04-01 23:00:43 +04:00
*/
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 ;
2007-11-13 23:51:31 +03:00
} else {
2001-04-01 23:00:43 +04:00
* dfree = D . dqb_bsoftlimit - D . dqb_curblocks ;
2007-11-13 23:51:31 +03:00
}
DEBUG ( 5 , ( " disk_quotas for path \" %s \" returning "
" bsize %.0f, dfree %.0f, dsize %.0f \n " ,
2001-04-01 23:00:43 +04:00
path , ( double ) * bsize , ( double ) * dfree , ( double ) * dsize ) ) ;
1996-05-05 15:25:33 +04:00
2007-11-13 23:51:31 +03:00
return true ;
1996-05-05 15:25:33 +04:00
}
1997-08-19 23:22:26 +04:00
# elif defined(OSF1)
# include <ufs/quota.h>
/****************************************************************************
1998-11-13 05:07:07 +03:00
try to get the disk space from disk quotas - OSF1 version
1997-08-19 23:22:26 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-11-06 21:40:51 +03:00
2008-10-14 03:59:36 +04:00
bool disk_quotas ( const char * path , uint64_t * bsize , uint64_t * dfree , uint64_t * dsize )
1997-08-19 23:22:26 +04:00
{
1997-09-23 23:19:06 +04:00
int r , save_errno ;
1997-08-19 23:22:26 +04:00
struct dqblk D ;
1998-09-02 00:11:54 +04:00
SMB_STRUCT_STAT S ;
1999-12-13 16:27:58 +03:00
uid_t euser_id ;
1997-08-19 23:22:26 +04:00
1999-12-13 16:27:58 +03:00
/*
* This code presumes that OSF1 will only
* give out quota info when the real uid
* matches the effective uid . JRA .
*/
1997-08-19 23:22:26 +04:00
euser_id = geteuid ( ) ;
1999-12-13 16:27:58 +03:00
save_re_uid ( ) ;
if ( set_re_uid ( ) ! = 0 ) return False ;
1997-08-19 23:22:26 +04:00
r = quotactl ( path , QCMD ( Q_GETQUOTA , USRQUOTA ) , euser_id , ( char * ) & D ) ;
1999-12-13 16:27:58 +03:00
if ( r ) {
1997-09-23 23:19:06 +04:00
save_errno = errno ;
1999-12-13 16:27:58 +03:00
}
1997-09-23 23:19:06 +04:00
1999-12-13 16:27:58 +03:00
restore_re_uid ( ) ;
1997-08-19 23:22:26 +04:00
* bsize = DEV_BSIZE ;
if ( r )
1997-09-23 23:19:06 +04:00
{
2000-12-04 20:16:44 +03:00
if ( save_errno = = EDQUOT ) /* disk quota exceeded */
1997-09-23 23:19:06 +04:00
{
* dfree = 0 ;
* dsize = D . dqb_curblocks ;
return ( True ) ;
}
else
return ( False ) ;
}
1997-08-19 23:22:26 +04:00
2000-04-11 01:02:45 +04:00
/* If softlimit is zero, set it equal to hardlimit.
*/
if ( D . dqb_bsoftlimit = = 0 )
D . dqb_bsoftlimit = D . dqb_bhardlimit ;
1997-08-19 23:22:26 +04:00
/* Use softlimit to determine disk space, except when it has been exceeded */
if ( D . dqb_bsoftlimit = = 0 )
return ( False ) ;
if ( ( D . dqb_curblocks > D . dqb_bsoftlimit ) ) {
* dfree = 0 ;
* dsize = D . dqb_curblocks ;
} else {
* dfree = D . dqb_bsoftlimit - D . dqb_curblocks ;
* dsize = D . dqb_bsoftlimit ;
}
return ( True ) ;
}
1997-10-09 00:34:13 +04:00
1999-12-13 16:27:58 +03:00
# elif defined (IRIX6)
1997-10-09 00:34:13 +04:00
/****************************************************************************
try to get the disk space from disk quotas ( IRIX 6.2 version )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include <sys/quota.h>
# include <mntent.h>
2008-10-14 03:59:36 +04:00
bool disk_quotas ( const char * path , uint64_t * bsize , uint64_t * dfree , uint64_t * dsize )
1997-10-09 00:34:13 +04:00
{
uid_t euser_id ;
int r ;
struct dqblk D ;
struct fs_disk_quota F ;
1998-09-02 00:11:54 +04:00
SMB_STRUCT_STAT S ;
1997-10-09 00:34:13 +04:00
FILE * fp ;
struct mntent * mnt ;
1998-09-03 22:40:31 +04:00
SMB_DEV_T devno ;
1997-10-09 00:34:13 +04:00
int found ;
/* find the block device file */
2009-11-27 14:57:43 +03:00
if ( sys_stat ( path , & S , false ) = = - 1 ) {
1997-10-09 00:34:13 +04:00
return ( False ) ;
}
2009-06-29 18:26:42 +04:00
devno = S . st_ex_dev ;
1997-10-09 00:34:13 +04:00
fp = setmntent ( MOUNTED , " r " ) ;
found = False ;
while ( ( mnt = getmntent ( fp ) ) ) {
2009-11-27 14:57:43 +03:00
if ( sys_stat ( mnt - > mnt_dir , & S , false ) = = - 1 )
1997-10-09 00:34:13 +04:00
continue ;
2009-06-29 18:26:42 +04:00
if ( S . st_ex_dev = = devno ) {
1997-10-09 00:34:13 +04:00
found = True ;
break ;
}
}
endmntent ( fp ) ;
if ( ! found ) {
return ( False ) ;
}
euser_id = geteuid ( ) ;
2007-04-06 03:56:10 +04:00
become_root ( ) ;
1997-10-09 00:34:13 +04:00
/* Use softlimit to determine disk space, except when it has been exceeded */
* bsize = 512 ;
if ( 0 = = strcmp ( mnt - > mnt_type , " efs " ) )
{
r = quotactl ( Q_GETQUOTA , mnt - > mnt_fsname , euser_id , ( caddr_t ) & D ) ;
2007-04-06 03:56:10 +04:00
unbecome_root ( ) ;
1997-11-17 22:16:38 +03:00
1997-10-09 00:34:13 +04:00
if ( r = = - 1 )
return ( False ) ;
/* Use softlimit to determine disk space, except when it has been exceeded */
if (
( D . dqb_bsoftlimit & & D . dqb_curblocks > = D . dqb_bsoftlimit ) | |
( D . dqb_bhardlimit & & D . dqb_curblocks > = D . dqb_bhardlimit ) | |
( D . dqb_fsoftlimit & & D . dqb_curfiles > = D . dqb_fsoftlimit ) | |
( D . dqb_fhardlimit & & D . dqb_curfiles > = D . dqb_fhardlimit )
)
{
* dfree = 0 ;
* dsize = D . dqb_curblocks ;
}
else if ( D . dqb_bsoftlimit = = 0 & & D . dqb_bhardlimit = = 0 )
{
return ( False ) ;
}
else
{
* dfree = D . dqb_bsoftlimit - D . dqb_curblocks ;
* dsize = D . dqb_bsoftlimit ;
}
}
else if ( 0 = = strcmp ( mnt - > mnt_type , " xfs " ) )
{
r = quotactl ( Q_XGETQUOTA , mnt - > mnt_fsname , euser_id , ( caddr_t ) & F ) ;
2007-04-06 03:56:10 +04:00
unbecome_root ( ) ;
1997-11-17 22:16:38 +03:00
1997-10-09 00:34:13 +04:00
if ( r = = - 1 )
2005-03-22 20:31:23 +03:00
{
DEBUG ( 5 , ( " quotactl for uid=%u: %s " , euser_id , strerror ( errno ) ) ) ;
1997-10-09 00:34:13 +04:00
return ( False ) ;
2005-03-22 20:31:23 +03:00
}
1997-10-09 00:34:13 +04:00
2005-03-22 20:31:23 +03:00
/* No quota for this user. */
if ( F . d_blk_softlimit = = 0 & & F . d_blk_hardlimit = = 0 )
{
return ( False ) ;
}
1997-10-09 00:34:13 +04:00
/* Use softlimit to determine disk space, except when it has been exceeded */
if (
( F . d_blk_softlimit & & F . d_bcount > = F . d_blk_softlimit ) | |
( F . d_blk_hardlimit & & F . d_bcount > = F . d_blk_hardlimit ) | |
( F . d_ino_softlimit & & F . d_icount > = F . d_ino_softlimit ) | |
( F . d_ino_hardlimit & & F . d_icount > = F . d_ino_hardlimit )
)
{
* dfree = 0 ;
1998-11-06 21:40:51 +03:00
* dsize = F . d_bcount ;
1997-10-09 00:34:13 +04:00
}
else
{
1998-11-06 21:40:51 +03:00
* dfree = ( F . d_blk_softlimit - F . d_bcount ) ;
2005-03-22 20:31:23 +03:00
* dsize = F . d_blk_softlimit ? F . d_blk_softlimit : F . d_blk_hardlimit ;
1997-10-09 00:34:13 +04:00
}
}
else
1997-11-17 22:16:38 +03:00
{
2007-04-06 03:56:10 +04:00
unbecome_root ( ) ;
1999-12-13 16:27:58 +03:00
return ( False ) ;
1997-11-17 22:16:38 +03:00
}
1997-10-09 00:34:13 +04:00
return ( True ) ;
}
1996-05-05 15:25:33 +04:00
# else
2005-05-10 19:42:32 +04:00
# if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
1996-12-10 20:58:11 +03:00
# include <ufs/ufs/quota.h>
1997-10-09 00:34:13 +04:00
# include <machine/param.h>
1997-07-08 20:54:44 +04:00
# elif AIX
/* AIX quota patch from Ole Holm Nielsen <ohnielse@fysik.dtu.dk> */
# include <jfs/quota.h>
/* AIX 4.X: Rename members of the dqblk structure (ohnielse@fysik.dtu.dk) */
# define dqb_curfiles dqb_curinodes
# define dqb_fhardlimit dqb_ihardlimit
# define dqb_fsoftlimit dqb_isoftlimit
2007-04-03 21:10:52 +04:00
# ifdef _AIXVERSION_530
# include <sys/statfs.h>
# include <sys/vmount.h>
# endif /* AIX 5.3 */
2005-05-10 19:42:32 +04:00
# else /* !__FreeBSD__ && !AIX && !__OpenBSD__ && !__DragonFly__ */
1996-05-31 19:13:29 +04:00
# include <sys/quota.h>
# include <devnm.h>
1996-12-10 20:58:11 +03:00
# endif
1996-05-31 19:13:29 +04:00
2005-05-10 19:42:32 +04:00
# if defined(__FreeBSD__) || defined(__DragonFly__)
2004-07-04 03:53:36 +04:00
# include <rpc/rpc.h>
# include <rpc/types.h>
# include <rpcsvc/rquota.h>
2005-02-01 21:14:15 +03:00
# ifdef HAVE_RPC_NETTYPE_H
2004-07-04 03:53:36 +04:00
# include <rpc/nettype.h>
2005-02-01 21:14:15 +03:00
# endif
2004-07-04 03:53:36 +04:00
# include <rpc/xdr.h>
static int my_xdr_getquota_args ( XDR * xdrsp , struct getquota_args * args )
{
if ( ! xdr_string ( xdrsp , & args - > gqa_pathp , RQ_PATHLEN ) )
return ( 0 ) ;
if ( ! xdr_int ( xdrsp , & args - > gqa_uid ) )
return ( 0 ) ;
return ( 1 ) ;
}
static int my_xdr_getquota_rslt ( XDR * xdrsp , struct getquota_rslt * gqr )
{
2009-01-08 12:43:10 +03:00
int quotastat ;
2004-07-04 03:53:36 +04:00
if ( ! xdr_int ( xdrsp , & quotastat ) ) {
DEBUG ( 6 , ( " nfs_quotas: Status bad or zero \n " ) ) ;
return 0 ;
}
2009-01-08 12:43:10 +03:00
gqr - > status = quotastat ;
2004-07-04 03:53:36 +04:00
if ( ! xdr_int ( xdrsp , & gqr - > getquota_rslt_u . gqr_rquota . rq_bsize ) ) {
DEBUG ( 6 , ( " nfs_quotas: Block size bad or zero \n " ) ) ;
return 0 ;
}
if ( ! xdr_bool ( xdrsp , & gqr - > getquota_rslt_u . gqr_rquota . rq_active ) ) {
DEBUG ( 6 , ( " nfs_quotas: Active bad or zero \n " ) ) ;
return 0 ;
}
if ( ! xdr_int ( xdrsp , & gqr - > getquota_rslt_u . gqr_rquota . rq_bhardlimit ) ) {
DEBUG ( 6 , ( " nfs_quotas: Hardlimit bad or zero \n " ) ) ;
return 0 ;
}
if ( ! xdr_int ( xdrsp , & gqr - > getquota_rslt_u . gqr_rquota . rq_bsoftlimit ) ) {
DEBUG ( 6 , ( " nfs_quotas: Softlimit bad or zero \n " ) ) ;
return 0 ;
}
if ( ! xdr_int ( xdrsp , & gqr - > getquota_rslt_u . gqr_rquota . rq_curblocks ) ) {
DEBUG ( 6 , ( " nfs_quotas: Currentblocks bad or zero \n " ) ) ;
return 0 ;
}
return ( 1 ) ;
}
/* Works on FreeBSD, too. :-) */
2008-10-14 03:59:36 +04:00
static bool nfs_quotas ( char * nfspath , uid_t euser_id , uint64_t * bsize , uint64_t * dfree , uint64_t * dsize )
2004-07-04 03:53:36 +04:00
{
uid_t uid = euser_id ;
struct dqblk D ;
char * mnttype = nfspath ;
CLIENT * clnt ;
struct getquota_rslt gqr ;
struct getquota_args args ;
char * cutstr , * pathname , * host , * testpath ;
int len ;
static struct timeval timeout = { 2 , 0 } ;
enum clnt_stat clnt_stat ;
2007-10-19 04:40:25 +04:00
bool ret = True ;
2004-07-04 03:53:36 +04:00
2008-10-14 03:59:36 +04:00
* bsize = * dfree = * dsize = ( uint64_t ) 0 ;
2004-07-04 03:53:36 +04:00
len = strcspn ( mnttype , " : " ) ;
pathname = strstr ( mnttype , " : " ) ;
2004-12-21 04:04:11 +03:00
cutstr = ( char * ) SMB_MALLOC ( len + 1 ) ;
2004-07-04 03:53:36 +04:00
if ( ! cutstr )
return False ;
memset ( cutstr , ' \0 ' , len + 1 ) ;
host = strncat ( cutstr , mnttype , sizeof ( char ) * len ) ;
DEBUG ( 5 , ( " nfs_quotas: looking for mount on \" %s \" \n " , cutstr ) ) ;
DEBUG ( 5 , ( " nfs_quotas: of path \" %s \" \n " , mnttype ) ) ;
testpath = strchr_m ( mnttype , ' : ' ) ;
args . gqa_pathp = testpath + 1 ;
args . gqa_uid = uid ;
DEBUG ( 5 , ( " nfs_quotas: Asking for host \" %s \" rpcprog \" %i \" rpcvers \" %i \" network \" %s \" \n " , host , RQUOTAPROG , RQUOTAVERS , " udp " ) ) ;
if ( ( clnt = clnt_create ( host , RQUOTAPROG , RQUOTAVERS , " udp " ) ) = = NULL ) {
ret = False ;
goto out ;
}
clnt - > cl_auth = authunix_create_default ( ) ;
DEBUG ( 9 , ( " nfs_quotas: auth_success \n " ) ) ;
clnt_stat = clnt_call ( clnt , RQUOTAPROC_GETQUOTA , ( const xdrproc_t ) my_xdr_getquota_args , ( caddr_t ) & args , ( const xdrproc_t ) my_xdr_getquota_rslt , ( caddr_t ) & gqr , timeout ) ;
if ( clnt_stat ! = RPC_SUCCESS ) {
DEBUG ( 9 , ( " nfs_quotas: clnt_call fail \n " ) ) ;
ret = False ;
goto out ;
}
/*
2009-01-08 12:43:10 +03:00
* gqr - > status returns 0 if the rpc call fails , 1 if quotas exist , 2 if there is
2004-07-04 03:53:36 +04:00
* no quota set , and 3 if no permission to get the quota . If 0 or 3 return
* something sensible .
*/
2009-01-08 12:43:10 +03:00
switch ( gqr . status ) {
2004-07-04 03:53:36 +04:00
case 0 :
2009-01-08 12:43:10 +03:00
DEBUG ( 9 , ( " nfs_quotas: Remote Quotas Failed! Error \" %i \" \n " , gqr . status ) ) ;
2004-07-04 03:53:36 +04:00
ret = False ;
goto out ;
case 1 :
DEBUG ( 9 , ( " nfs_quotas: Good quota data \n " ) ) ;
D . dqb_bsoftlimit = gqr . getquota_rslt_u . gqr_rquota . rq_bsoftlimit ;
D . dqb_bhardlimit = gqr . getquota_rslt_u . gqr_rquota . rq_bhardlimit ;
D . dqb_curblocks = gqr . getquota_rslt_u . gqr_rquota . rq_curblocks ;
break ;
case 2 :
case 3 :
D . dqb_bsoftlimit = 1 ;
D . dqb_curblocks = 1 ;
2009-01-08 12:43:10 +03:00
DEBUG ( 9 , ( " nfs_quotas: Remote Quotas returned \" %i \" \n " , gqr . status ) ) ;
2004-07-04 03:53:36 +04:00
break ;
default :
2009-01-08 12:43:10 +03:00
DEBUG ( 9 , ( " nfs_quotas: Remote Quotas Questionable! Error \" %i \" \n " , gqr . status ) ) ;
2004-07-04 03:53:36 +04:00
break ;
}
DEBUG ( 10 , ( " nfs_quotas: Let`s look at D a bit closer... status \" %i \" bsize \" %i \" active? \" %i \" bhard \" %i \" bsoft \" %i \" curb \" %i \" \n " ,
2009-01-08 12:43:10 +03:00
gqr . status ,
2004-07-04 03:53:36 +04:00
gqr . getquota_rslt_u . gqr_rquota . rq_bsize ,
gqr . getquota_rslt_u . gqr_rquota . rq_active ,
gqr . getquota_rslt_u . gqr_rquota . rq_bhardlimit ,
gqr . getquota_rslt_u . gqr_rquota . rq_bsoftlimit ,
gqr . getquota_rslt_u . gqr_rquota . rq_curblocks ) ) ;
if ( D . dqb_bsoftlimit = = 0 )
D . dqb_bsoftlimit = D . dqb_bhardlimit ;
if ( D . dqb_bsoftlimit = = 0 )
return False ;
* bsize = gqr . getquota_rslt_u . gqr_rquota . rq_bsize ;
* dsize = D . dqb_bsoftlimit ;
2008-09-16 05:21:02 +04:00
if ( D . dqb_curblocks = = 1 )
2004-07-04 03:53:36 +04:00
* bsize = DEV_BSIZE ;
if ( D . dqb_curblocks > D . dqb_bsoftlimit ) {
* dfree = 0 ;
* dsize = D . dqb_curblocks ;
} else
* dfree = D . dqb_bsoftlimit - D . dqb_curblocks ;
out :
if ( clnt ) {
if ( clnt - > cl_auth )
auth_destroy ( clnt - > cl_auth ) ;
clnt_destroy ( clnt ) ;
}
DEBUG ( 5 , ( " nfs_quotas: For path \" %s \" returning bsize %.0f, dfree %.0f, dsize %.0f \n " , args . gqa_pathp , ( double ) * bsize , ( double ) * dfree , ( double ) * dsize ) ) ;
SAFE_FREE ( cutstr ) ;
DEBUG ( 10 , ( " nfs_quotas: End of nfs_quotas \n " ) ) ;
return ret ;
}
# endif
1996-05-05 15:25:33 +04:00
/****************************************************************************
try to get the disk space from disk quotas - default version
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-11-06 21:40:51 +03:00
2008-10-14 03:59:36 +04:00
bool disk_quotas ( const char * path , uint64_t * bsize , uint64_t * dfree , uint64_t * dsize )
1996-05-05 15:25:33 +04:00
{
int r ;
struct dqblk D ;
1999-12-13 16:27:58 +03:00
uid_t euser_id ;
2005-05-10 19:42:32 +04:00
# if !defined(__FreeBSD__) && !defined(AIX) && !defined(__OpenBSD__) && !defined(__DragonFly__)
1997-07-02 05:19:41 +04:00
char dev_disk [ 256 ] ;
1998-09-02 00:11:54 +04:00
SMB_STRUCT_STAT S ;
2003-01-28 05:15:11 +03:00
1996-05-05 15:25:33 +04:00
/* find the block device file */
2003-01-28 05:15:11 +03:00
# 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 .
*/
2009-11-27 14:57:43 +03:00
if ( ( sys_stat ( path , & S , false ) < 0 )
2009-11-27 14:42:39 +03:00
| | ( devnm ( S_IFBLK , S . st_ex_dev , dev_disk , 256 , 1 ) < 0 ) )
2003-01-28 05:15:11 +03:00
# else
2009-11-27 14:57:43 +03:00
if ( ( sys_stat ( path , & S , false ) < 0 )
2009-11-27 14:42:39 +03:00
| | ( devnm ( S_IFBLK , S . st_ex_dev , dev_disk , 256 , 0 ) < 0 ) )
2003-05-01 15:02:54 +04:00
return ( False ) ;
2004-01-05 22:36:02 +03:00
# endif /* ifdef HPUX */
2003-01-28 05:15:11 +03:00
2005-05-10 19:42:32 +04:00
# endif /* !defined(__FreeBSD__) && !defined(AIX) && !defined(__OpenBSD__) && !defined(__DragonFly__) */
1996-05-05 15:25:33 +04:00
euser_id = geteuid ( ) ;
1998-07-29 07:08:05 +04:00
# ifdef HPUX
1999-12-13 16:27:58 +03:00
/* 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 ( ) ;
1998-07-29 07:08:05 +04:00
# else
2005-05-10 19:42:32 +04:00
# if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
1997-10-09 00:34:13 +04:00
{
/* FreeBSD patches from Marty Moll <martym@arbor.edu> */
gid_t egrp_id ;
2005-05-10 19:42:32 +04:00
# if defined(__FreeBSD__) || defined(__DragonFly__)
2004-07-04 03:53:36 +04:00
SMB_DEV_T devno ;
struct statfs * mnts ;
SMB_STRUCT_STAT st ;
int mntsize , i ;
2009-11-27 14:57:43 +03:00
if ( sys_stat ( path , & st , false ) < 0 )
2004-07-04 03:53:36 +04:00
return False ;
2009-06-29 18:26:42 +04:00
devno = st . st_ex_dev ;
2004-07-04 03:53:36 +04:00
mntsize = getmntinfo ( & mnts , MNT_NOWAIT ) ;
if ( mntsize < = 0 )
return False ;
for ( i = 0 ; i < mntsize ; i + + ) {
2009-11-27 14:57:43 +03:00
if ( sys_stat ( mnts [ i ] . f_mntonname , & st , false ) < 0 )
2004-07-04 03:53:36 +04:00
return False ;
2009-06-29 18:26:42 +04:00
if ( st . st_ex_dev = = devno )
2004-07-04 03:53:36 +04:00
break ;
}
if ( i = = mntsize )
return False ;
# endif
2007-04-06 03:56:10 +04:00
become_root ( ) ;
1999-12-13 16:27:58 +03:00
2005-05-10 19:42:32 +04:00
# if defined(__FreeBSD__) || defined(__DragonFly__)
2004-07-04 03:53:36 +04:00
if ( strcmp ( mnts [ i ] . f_fstypename , " nfs " ) = = 0 ) {
2007-10-19 04:40:25 +04:00
bool retval ;
2004-07-04 03:53:36 +04:00
retval = nfs_quotas ( mnts [ i ] . f_mntfromname , euser_id , bsize , dfree , dsize ) ;
2007-04-06 03:56:10 +04:00
unbecome_root ( ) ;
2004-07-04 03:53:36 +04:00
return retval ;
}
# endif
1997-10-09 00:34:13 +04:00
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 . */
1999-12-13 16:27:58 +03:00
if ( r ) {
r = quotactl ( path , QCMD ( Q_GETQUOTA , GRPQUOTA ) , egrp_id , ( char * ) & D ) ;
}
2007-04-06 03:56:10 +04:00
unbecome_root ( ) ;
1997-10-09 00:34:13 +04:00
}
1997-07-08 20:54:44 +04:00
# elif defined(AIX)
/* AIX has both USER and GROUP quotas:
Get the USER quota ( ohnielse @ fysik . dtu . dk ) */
2007-04-03 21:10:52 +04:00
# ifdef _AIXVERSION_530
{
struct statfs statbuf ;
quota64_t user_quota ;
if ( statfs ( path , & statbuf ) ! = 0 )
return False ;
if ( statbuf . f_vfstype = = MNT_J2 )
{
/* For some reason we need to be root for jfs2 */
2007-04-06 03:56:10 +04:00
become_root ( ) ;
2007-04-03 21:10:52 +04:00
r = quotactl ( path , QCMD ( Q_J2GETQUOTA , USRQUOTA ) , euser_id , ( char * ) & user_quota ) ;
2007-04-06 03:56:10 +04:00
unbecome_root ( ) ;
2007-04-03 21:10:52 +04:00
/* Copy results to old struct to let the following code work as before */
D . dqb_curblocks = user_quota . bused ;
D . dqb_bsoftlimit = user_quota . bsoft ;
D . dqb_bhardlimit = user_quota . bhard ;
2007-09-25 01:43:54 +04:00
D . dqb_curfiles = user_quota . iused ;
D . dqb_fsoftlimit = user_quota . isoft ;
D . dqb_fhardlimit = user_quota . ihard ;
2007-04-03 21:10:52 +04:00
}
else if ( statbuf . f_vfstype = = MNT_JFS )
{
# endif /* AIX 5.3 */
2004-03-16 22:06:03 +03:00
save_re_uid ( ) ;
if ( set_re_uid ( ) ! = 0 )
return False ;
1997-07-08 20:54:44 +04:00
r = quotactl ( path , QCMD ( Q_GETQUOTA , USRQUOTA ) , euser_id , ( char * ) & D ) ;
2004-03-16 22:06:03 +03:00
restore_re_uid ( ) ;
2007-04-03 21:10:52 +04:00
# ifdef _AIXVERSION_530
}
else
r = 1 ; /* Fail for other FS-types */
}
# endif /* AIX 5.3 */
2005-05-10 19:42:32 +04:00
# else /* !__FreeBSD__ && !AIX && !__OpenBSD__ && !__DragonFly__ */
1996-12-10 20:58:11 +03:00
r = quotactl ( Q_GETQUOTA , dev_disk , euser_id , & D ) ;
2005-05-10 19:42:32 +04:00
# endif /* !__FreeBSD__ && !AIX && !__OpenBSD__ && !__DragonFly__ */
1999-12-13 16:27:58 +03:00
# endif /* HPUX */
1996-12-10 20:58:11 +03:00
1996-05-05 15:25:33 +04:00
/* Use softlimit to determine disk space, except when it has been exceeded */
2005-05-10 19:42:32 +04:00
# if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
1997-10-09 00:34:13 +04:00
* bsize = DEV_BSIZE ;
2005-05-10 19:42:32 +04:00
# else /* !__FreeBSD__ && !__OpenBSD__ && !__DragonFly__ */
1996-05-05 15:25:33 +04:00
* bsize = 1024 ;
2005-05-10 19:42:32 +04:00
# endif /*!__FreeBSD__ && !__OpenBSD__ && !__DragonFly__ */
1997-10-09 00:34:13 +04:00
1996-05-05 15:25:33 +04:00
if ( r )
{
if ( errno = = EDQUOT )
{
* dfree = 0 ;
* dsize = D . dqb_curblocks ;
return ( True ) ;
}
else return ( False ) ;
}
2000-04-11 01:02:45 +04:00
/* If softlimit is zero, set it equal to hardlimit.
*/
if ( D . dqb_bsoftlimit = = 0 )
D . dqb_bsoftlimit = D . dqb_bhardlimit ;
1996-06-08 08:33:37 +04:00
if ( D . dqb_bsoftlimit = = 0 )
return ( False ) ;
1996-05-05 15:25:33 +04:00
/* Use softlimit to determine disk space, except when it has been exceeded */
1996-12-10 20:58:11 +03:00
if ( ( D . dqb_curblocks > D . dqb_bsoftlimit )
2005-05-10 19:42:32 +04:00
# if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__DragonFly__)
1997-07-18 00:11:58 +04:00
| | ( ( D . dqb_curfiles > D . dqb_fsoftlimit ) & & ( D . dqb_fsoftlimit ! = 0 ) )
1996-12-10 20:58:11 +03:00
# endif
) {
1996-05-05 15:25:33 +04:00
* dfree = 0 ;
* dsize = D . dqb_curblocks ;
}
else {
* dfree = D . dqb_bsoftlimit - D . dqb_curblocks ;
* dsize = D . dqb_bsoftlimit ;
}
return ( True ) ;
}
# endif
2000-03-13 20:38:13 +03:00
# if defined(VXFS_QUOTA)
/****************************************************************************
Try to get the disk space from Veritas disk quotas .
David Lee < T . D . Lee @ durham . ac . uk > August 1999.
Background assumptions :
Potentially under many Operating Systems . Initially Solaris 2.
My guess is that Veritas is largely , though not entirely ,
independent of OS . So I have separated it out .
There may be some details . For example , OS - specific " include " files .
It is understood that HPUX 10 somehow gets Veritas quotas without
any special effort ; if so , this routine need not be compiled in .
Dirk De Wachter < Dirk . DeWachter @ rug . ac . be >
Warning :
It is understood that Veritas do not publicly support this ioctl interface .
Rather their preference would be for the user ( us ) to call the native
OS and then for the OS itself to call through to the VxFS filesystem .
Presumably HPUX 10 , see above , does this .
Hints for porting :
Add your OS to " IFLIST " below .
Get it to compile successfully :
Almost certainly " include " s require attention : see SUNOS5 .
In the main code above , arrange for it to be called : see SUNOS5 .
Test !
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* "IFLIST"
* This " if " is a list of ports :
* if defined ( OS1 ) | | defined ( OS2 ) | | . . .
*/
# if defined(SUNOS5)
# if defined(SUNOS5)
# include <sys/fs/vx_solaris.h>
# endif
# include <sys/fs/vx_machdep.h>
# include <sys/fs/vx_layout.h>
# include <sys/fs/vx_quota.h>
# include <sys/fs/vx_aioctl.h>
# include <sys/fs/vx_ioctl.h>
2008-10-14 03:59:36 +04:00
bool disk_quotas_vxfs ( const char * name , char * path , uint64_t * bsize , uint64_t * dfree , uint64_t * dsize )
2000-03-13 20:38:13 +03:00
{
uid_t user_id , euser_id ;
int ret ;
struct vx_dqblk D ;
struct vx_quotctl quotabuf ;
struct vx_genioctl genbuf ;
2007-11-13 23:51:31 +03:00
char * qfname ;
2000-03-13 20:38:13 +03:00
int file ;
/*
* " name " may or may not include a trailing " /quotas " .
* Arranging consistency of calling here in " quotas.c " may not be easy and
* it might be easier to examine and adjust it here .
* Fortunately , VxFS seems not to mind at present .
*/
2007-11-13 23:51:31 +03:00
qfname = talloc_strdup ( talloc_tos ( ) , name ) ;
if ( ! qfname ) {
return false ;
}
2000-03-13 20:38:13 +03:00
/* pstrcat(qfname, "/quotas") ; */ /* possibly examine and adjust "name" */
euser_id = geteuid ( ) ;
set_effective_uid ( 0 ) ;
DEBUG ( 5 , ( " disk_quotas: looking for VxFS quotas file \" %s \" \n " , qfname ) ) ;
2012-03-28 05:48:00 +04:00
if ( ( file = open ( qfname , O_RDONLY , 0 ) ) < 0 ) {
2000-03-13 20:38:13 +03:00
set_effective_uid ( euser_id ) ;
return ( False ) ;
}
genbuf . ioc_cmd = VX_QUOTACTL ;
genbuf . ioc_up = ( void * ) & quotabuf ;
quotabuf . cmd = VX_GETQUOTA ;
quotabuf . uid = euser_id ;
quotabuf . addr = ( caddr_t ) & D ;
ret = ioctl ( file , VX_ADMIN_IOCTL , & genbuf ) ;
close ( file ) ;
set_effective_uid ( euser_id ) ;
if ( ret < 0 ) {
DEBUG ( 5 , ( " disk_quotas ioctl (VxFS) failed. Error = %s \n " , strerror ( errno ) ) ) ;
return ( False ) ;
}
2000-04-11 01:02:45 +04:00
/* If softlimit is zero, set it equal to hardlimit.
*/
if ( D . dqb_bsoftlimit = = 0 )
D . dqb_bsoftlimit = D . dqb_bhardlimit ;
2000-03-13 20:38:13 +03:00
/* 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 : - )
*/
DEBUG ( 5 , ( " disk_quotas for path \" %s \" block c/s/h %ld/%ld/%ld; file c/s/h %ld/%ld/%ld \n " ,
path , D . dqb_curblocks , D . dqb_bsoftlimit , D . dqb_bhardlimit ,
D . dqb_curfiles , D . dqb_fsoftlimit , D . dqb_fhardlimit ) ) ;
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 ) ;
}
# endif /* SUNOS5 || ... */
# endif /* VXFS_QUOTA */
2003-05-12 05:20:17 +04:00
# else /* WITH_QUOTAS */
2008-10-14 03:59:36 +04:00
bool disk_quotas ( const char * path , uint64_t * bsize , uint64_t * dfree , uint64_t * dsize )
2003-05-12 05:20:17 +04:00
{
2007-11-13 23:51:31 +03:00
( * bsize ) = 512 ; /* This value should be ignored */
2003-05-12 05:20:17 +04:00
2007-11-13 23:51:31 +03:00
/* And just to be sure we set some values that hopefully */
/* will be larger that any possible real-world value */
2008-10-14 03:59:36 +04:00
( * dfree ) = ( uint64_t ) - 1 ;
( * dsize ) = ( uint64_t ) - 1 ;
2003-05-12 05:20:17 +04:00
2007-11-13 23:51:31 +03:00
/* As we have select not to use quotas, allways fail */
return false ;
2003-05-12 05:20:17 +04:00
}
# endif /* WITH_QUOTAS */
# else /* HAVE_SYS_QUOTAS */
2007-11-13 23:51:31 +03:00
/* wrapper to the new sys_quota interface
2003-05-12 05:20:17 +04:00
this file should be removed later
*/
2008-10-14 03:59:36 +04:00
bool disk_quotas ( const char * path , uint64_t * bsize , uint64_t * dfree , uint64_t * dsize )
2003-05-12 05:20:17 +04:00
{
int r ;
SMB_DISK_QUOTA D ;
unid_t id ;
id . uid = geteuid ( ) ;
2004-01-15 11:49:30 +03:00
ZERO_STRUCT ( D ) ;
2003-05-12 05:20:17 +04:00
r = sys_get_quota ( path , SMB_USER_QUOTA_TYPE , id , & D ) ;
/* Use softlimit to determine disk space, except when it has been exceeded */
* bsize = D . bsize ;
if ( r = = - 1 ) {
if ( errno = = EDQUOT ) {
* dfree = 0 ;
* dsize = D . curblocks ;
return ( True ) ;
} else {
goto try_group_quota ;
}
}
/* Use softlimit to determine disk space, except when it has been exceeded */
if (
( D . softlimit & & D . curblocks > = D . softlimit ) | |
( D . hardlimit & & D . curblocks > = D . hardlimit ) | |
( D . isoftlimit & & D . curinodes > = D . isoftlimit ) | |
( D . ihardlimit & & D . curinodes > = D . ihardlimit )
) {
* dfree = 0 ;
* dsize = D . curblocks ;
} else if ( D . softlimit = = 0 & & D . hardlimit = = 0 ) {
goto try_group_quota ;
} else {
if ( D . softlimit = = 0 )
D . softlimit = D . hardlimit ;
* dfree = D . softlimit - D . curblocks ;
* dsize = D . softlimit ;
}
return True ;
try_group_quota :
id . gid = getegid ( ) ;
2004-01-15 11:49:30 +03:00
ZERO_STRUCT ( D ) ;
2003-05-12 05:20:17 +04:00
r = sys_get_quota ( path , SMB_GROUP_QUOTA_TYPE , id , & D ) ;
/* Use softlimit to determine disk space, except when it has been exceeded */
* bsize = D . bsize ;
if ( r = = - 1 ) {
if ( errno = = EDQUOT ) {
* dfree = 0 ;
* dsize = D . curblocks ;
return ( True ) ;
} else {
return False ;
}
}
/* Use softlimit to determine disk space, except when it has been exceeded */
if (
( D . softlimit & & D . curblocks > = D . softlimit ) | |
( D . hardlimit & & D . curblocks > = D . hardlimit ) | |
( D . isoftlimit & & D . curinodes > = D . isoftlimit ) | |
( D . ihardlimit & & D . curinodes > = D . ihardlimit )
) {
* dfree = 0 ;
* dsize = D . curblocks ;
} else if ( D . softlimit = = 0 & & D . hardlimit = = 0 ) {
return False ;
} else {
if ( D . softlimit = = 0 )
D . softlimit = D . hardlimit ;
* dfree = D . softlimit - D . curblocks ;
* dsize = D . softlimit ;
}
return ( True ) ;
}
# endif /* HAVE_SYS_QUOTAS */