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
2016-03-13 09:18:47 +03:00
# if defined(SUNOS5) /* Solaris */
1996-05-05 15:25:33 +04:00
# include <fcntl.h>
1998-11-06 21:40:51 +03:00
# include <sys/param.h>
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>
2001-04-01 23:00:43 +04:00
/****************************************************************************
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_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 ) ;
}
2012-09-11 03:00:50 +04:00
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 ) ;
}
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
/*
2015-10-20 08:53:23 +03:00
* gqr . status returns 1 if quotas exist , 2 if there is
* no quota set , and 3 if no permission to get the quota .
* If 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 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 :
2015-10-20 08:53:23 +03:00
DEBUG ( 9 , ( " nfs_quotas: Unknown Remote Quota Status \" %i \" \n " ,
gqr . status ) ) ;
ret = false ;
goto out ;
2001-04-27 23:56:15 +04:00
}
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 ;
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
}
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
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-01-14 01:09:36 +03:00
bool disk_quotas ( connection_struct * conn , struct smb_filename * fname ,
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 ;
struct quotctl command ;
int file ;
2007-11-13 23:51:31 +03:00
struct mnttab mnt ;
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 ;
2016-01-14 01:09:36 +03:00
const char * path = fname - > base_name ;
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
2016-01-14 01:09:36 +03:00
devno = fname - > st . 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 ) ) ;
2012-03-28 05:51:17 +04:00
if ( ( fd = fopen ( MNTTAB , " r " ) ) = = NULL ) {
2007-11-13 23:51:31 +03:00
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 ) ;
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
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-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
2007-11-13 23:51:31 +03:00
return false ;
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
2016-03-13 09:18:47 +03:00
# else /* not Solaris */
1996-05-05 15:25:33 +04:00
2012-09-02 19:51:59 +04:00
# if AIX
1997-07-08 20:54:44 +04:00
/* 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 */
2012-09-03 07:16:38 +04:00
# else /* !AIX */
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
2004-07-04 03:53:36 +04:00
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
2016-01-14 01:09:36 +03:00
bool disk_quotas ( connection_struct * conn , struct smb_filename * fname ,
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 ;
2016-01-14 01:09:36 +03:00
const char * path = fname - > base_name ;
2012-09-03 07:16:38 +04:00
# if !defined(AIX)
1997-07-02 05:19:41 +04:00
char dev_disk [ 256 ] ;
2016-01-14 01:09:36 +03:00
SMB_STRUCT_STAT S = fname - > st ;
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
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 ) ;
2003-01-28 05:15:11 +03:00
2012-09-03 07:16:38 +04:00
# endif /* !defined(AIX) */
1996-05-05 15:25:33 +04:00
euser_id = geteuid ( ) ;
2012-09-02 19:51:59 +04:00
# if defined(AIX)
1997-07-08 20:54:44 +04:00
/* 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 */
2012-09-03 07:16:38 +04:00
# else /* !AIX */
1996-12-10 20:58:11 +03:00
r = quotactl ( Q_GETQUOTA , dev_disk , euser_id , & D ) ;
2012-09-03 07:16:38 +04:00
# endif /* !AIX */
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 */
* bsize = 1024 ;
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 )
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
) {
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 ) ;
}
2016-03-13 09:18:47 +03:00
# endif /* Solaris */
2003-05-12 05:20:17 +04:00
# else /* WITH_QUOTAS */
2016-01-14 01:09:36 +03:00
bool disk_quotas ( connection_struct * conn , struct smb_filename * fname ,
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
*/
2016-01-14 01:09:36 +03:00
bool disk_quotas ( connection_struct * conn , struct smb_filename * fname ,
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 ;
2016-04-27 23:22:25 +03:00
/*
* First of all , check whether user quota is
* enforced . If the call fails , assume it is
* not enforced .
*/
ZERO_STRUCT ( D ) ;
id . uid = - 1 ;
2017-06-01 21:45:25 +03:00
r = SMB_VFS_GET_QUOTA ( conn , fname , SMB_USER_FS_QUOTA_TYPE ,
2016-01-14 01:09:36 +03:00
id , & D ) ;
2016-04-27 23:22:25 +03:00
if ( r = = - 1 & & errno ! = ENOSYS ) {
goto try_group_quota ;
}
if ( r = = 0 & & ( D . qflags & QUOTAS_DENY_DISK ) = = 0 ) {
goto try_group_quota ;
}
2004-01-15 11:49:30 +03:00
ZERO_STRUCT ( D ) ;
2016-04-27 23:22:25 +03:00
id . uid = geteuid ( ) ;
2016-08-11 23:37:42 +03:00
/* if new files created under this folder get this
* folder ' s UID , then available space is governed by
* the quota of the folder ' s UID , not the creating user .
*/
if ( lp_inherit_owner ( SNUM ( conn ) ) ! = INHERIT_OWNER_NO & &
id . uid ! = fname - > st . st_ex_uid & & id . uid ! = sec_initial_uid ( ) ) {
int save_errno ;
id . uid = fname - > st . st_ex_uid ;
become_root ( ) ;
2017-06-01 21:45:25 +03:00
r = SMB_VFS_GET_QUOTA ( conn , fname ,
2016-08-11 23:37:42 +03:00
SMB_USER_QUOTA_TYPE , id , & D ) ;
save_errno = errno ;
unbecome_root ( ) ;
errno = save_errno ;
} else {
2017-06-01 21:45:25 +03:00
r = SMB_VFS_GET_QUOTA ( conn , fname ,
2016-08-11 23:37:42 +03:00
SMB_USER_QUOTA_TYPE , id , & D ) ;
}
2003-05-12 05:20:17 +04:00
if ( r = = - 1 ) {
2016-05-27 22:15:46 +03:00
goto try_group_quota ;
2003-05-12 05:20:17 +04:00
}
2016-05-27 22:15:46 +03:00
* bsize = D . bsize ;
2003-05-12 05:20:17 +04:00
/* 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 {
2016-01-21 22:09:12 +03:00
if ( D . softlimit = = 0 ) {
2003-05-12 05:20:17 +04:00
D . softlimit = D . hardlimit ;
2016-01-21 22:09:12 +03:00
}
2003-05-12 05:20:17 +04:00
* dfree = D . softlimit - D . curblocks ;
* dsize = D . softlimit ;
}
return True ;
try_group_quota :
2016-04-27 23:22:25 +03:00
/*
* First of all , check whether group quota is
* enforced . If the call fails , assume it is
* not enforced .
*/
ZERO_STRUCT ( D ) ;
id . gid = - 1 ;
2017-06-01 21:45:25 +03:00
r = SMB_VFS_GET_QUOTA ( conn , fname , SMB_GROUP_FS_QUOTA_TYPE ,
2016-01-14 01:09:36 +03:00
id , & D ) ;
2016-04-27 23:22:25 +03:00
if ( r = = - 1 & & errno ! = ENOSYS ) {
return false ;
}
if ( r = = 0 & & ( D . qflags & QUOTAS_DENY_DISK ) = = 0 ) {
return false ;
}
2003-05-12 05:20:17 +04:00
id . gid = getegid ( ) ;
2004-01-15 11:49:30 +03:00
ZERO_STRUCT ( D ) ;
2017-06-01 21:45:25 +03:00
r = SMB_VFS_GET_QUOTA ( conn , fname , SMB_GROUP_QUOTA_TYPE , id ,
2016-01-14 01:09:36 +03:00
& D ) ;
2003-05-12 05:20:17 +04:00
if ( r = = - 1 ) {
2016-05-27 22:15:46 +03:00
return False ;
2003-05-12 05:20:17 +04:00
}
2016-05-27 22:15:46 +03:00
* bsize = D . bsize ;
2003-05-12 05:20:17 +04:00
/* 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 {
2016-01-21 22:09:12 +03:00
if ( D . softlimit = = 0 ) {
2003-05-12 05:20:17 +04:00
D . softlimit = D . hardlimit ;
2016-01-21 22:09:12 +03:00
}
2003-05-12 05:20:17 +04:00
* dfree = D . softlimit - D . curblocks ;
* dsize = D . softlimit ;
}
return ( True ) ;
}
# endif /* HAVE_SYS_QUOTAS */