1998-07-29 07:08:05 +04:00
/*
Unix SMB / Netbios implementation .
Version 1.9 .
functions to calculate the free disk space
Copyright ( C ) Andrew Tridgell 1998
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 0213 9 , USA .
*/
# include "includes.h"
extern int DEBUGLEVEL ;
/****************************************************************************
normalise for DOS usage
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
static void disk_norm ( BOOL small_query , SMB_BIG_UINT * bsize , SMB_BIG_UINT * dfree , SMB_BIG_UINT * dsize )
1998-07-29 07:08:05 +04:00
{
/* check if the disk is beyond the max disk size */
1998-09-18 03:06:57 +04:00
SMB_BIG_UINT maxdisksize = lp_maxdisksize ( ) ;
1998-07-29 07:08:05 +04:00
if ( maxdisksize ) {
/* convert to blocks - and don't overflow */
maxdisksize = ( ( maxdisksize * 1024 ) / ( * bsize ) ) * 1024 ;
if ( * dsize > maxdisksize ) * dsize = maxdisksize ;
if ( * dfree > maxdisksize ) * dfree = maxdisksize - 1 ;
/* the -1 should stop applications getting div by 0
errors */
}
1999-12-13 16:27:58 +03:00
1998-07-29 07:08:05 +04:00
while ( * dfree > WORDMAX | | * dsize > WORDMAX | | * bsize < 512 ) {
* dfree / = 2 ;
* dsize / = 2 ;
* bsize * = 2 ;
1999-12-13 16:27:58 +03:00
if ( small_query ) {
/*
* Force max to fit in 16 bit fields .
*/
if ( * bsize > ( WORDMAX * 512 ) ) {
* bsize = ( WORDMAX * 512 ) ;
if ( * dsize > WORDMAX )
* dsize = WORDMAX ;
if ( * dfree > WORDMAX )
* dfree = WORDMAX ;
break ;
}
1998-07-29 07:08:05 +04:00
}
}
}
/****************************************************************************
return number of 1 K blocks available on a path and total number
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
static SMB_BIG_UINT disk_free ( char * path , BOOL small_query ,
SMB_BIG_UINT * bsize , SMB_BIG_UINT * dfree , SMB_BIG_UINT * dsize )
1998-07-29 07:08:05 +04:00
{
int dfree_retval ;
1998-11-06 21:40:51 +03:00
SMB_BIG_UINT dfree_q = 0 ;
SMB_BIG_UINT bsize_q = 0 ;
SMB_BIG_UINT dsize_q = 0 ;
2000-01-06 04:41:27 +03:00
char * dfree_command ;
1998-07-29 07:08:05 +04:00
( * dfree ) = ( * dsize ) = 0 ;
( * bsize ) = 512 ;
2000-01-06 04:41:27 +03:00
/*
* If external disk calculation specified , use it .
*/
dfree_command = lp_dfree_command ( ) ;
if ( dfree_command & & * dfree_command ) {
char * p ;
2000-04-16 15:00:21 +04:00
char * * lines ;
pstring syscmd ;
2000-01-06 04:41:27 +03:00
2000-04-16 15:00:21 +04:00
slprintf ( syscmd , sizeof ( syscmd ) , " %s %s " , dfree_command , path ) ;
DEBUG ( 3 , ( " disk_free: Running command %s \n " , syscmd ) ) ;
2000-02-15 22:36:47 +03:00
2000-12-07 22:26:04 +03:00
lines = file_lines_pload ( syscmd , NULL , True ) ;
2000-04-16 15:00:21 +04:00
if ( lines ) {
char * line = lines [ 0 ] ;
2000-01-06 04:41:27 +03:00
DEBUG ( 3 , ( " Read input from dfree, \" %s \" \n " , line ) ) ;
* dsize = ( SMB_BIG_UINT ) strtoul ( line , & p , 10 ) ;
while ( p & & * p & isspace ( * p ) )
p + + ;
if ( p & & * p )
* dfree = ( SMB_BIG_UINT ) strtoul ( p , & p , 10 ) ;
while ( p & & * p & isspace ( * p ) )
p + + ;
if ( p & & * p )
* bsize = ( SMB_BIG_UINT ) strtoul ( p , NULL , 10 ) ;
else
* bsize = 1024 ;
2000-04-16 15:00:21 +04:00
file_lines_free ( lines ) ;
2000-01-06 04:41:27 +03:00
DEBUG ( 3 , ( " Parsed output of dfree, dsize=%u, dfree=%u, bsize=%u \n " ,
( unsigned int ) * dsize , ( unsigned int ) * dfree , ( unsigned int ) * bsize ) ) ;
if ( ! * dsize )
* dsize = 2048 ;
if ( ! * dfree )
* dfree = 1024 ;
} else {
2000-02-15 22:36:47 +03:00
DEBUG ( 0 , ( " disk_free: sys_popen() failed for command %s. Error was : %s \n " ,
2000-04-16 15:00:21 +04:00
syscmd , strerror ( errno ) ) ) ;
2000-04-19 12:23:13 +04:00
sys_fsusage ( path , dfree , dsize ) ;
2000-01-06 04:41:27 +03:00
}
} else
2000-04-19 12:23:13 +04:00
sys_fsusage ( path , dfree , dsize ) ;
1998-07-29 07:08:05 +04:00
1998-11-06 21:40:51 +03:00
if ( disk_quotas ( path , & bsize_q , & dfree_q , & dsize_q ) ) {
( * bsize ) = bsize_q ;
( * dfree ) = MIN ( * dfree , dfree_q ) ;
( * dsize ) = MIN ( * dsize , dsize_q ) ;
}
/* FIXME : Any reason for this assumption ? */
1998-07-29 07:08:05 +04:00
if ( * bsize < 256 ) {
1998-11-09 06:45:49 +03:00
DEBUG ( 5 , ( " disk_free:Warning: bsize == %d < 256 . Changing to assumed correct bsize = 512 \n " , ( int ) * bsize ) ) ;
1998-07-29 07:08:05 +04:00
* bsize = 512 ;
}
if ( ( * dsize ) < 1 ) {
static int done ;
if ( ! done ) {
DEBUG ( 0 , ( " WARNING: dfree is broken on this system \n " ) ) ;
done = 1 ;
}
* dsize = 20 * 1024 * 1024 / ( * bsize ) ;
* dfree = MAX ( 1 , * dfree ) ;
}
1999-12-13 16:27:58 +03:00
disk_norm ( small_query , bsize , dfree , dsize ) ;
1998-07-29 07:08:05 +04:00
if ( ( * bsize ) < 1024 ) {
dfree_retval = ( * dfree ) / ( 1024 / ( * bsize ) ) ;
} else {
dfree_retval = ( ( * bsize ) / 1024 ) * ( * dfree ) ;
}
return ( dfree_retval ) ;
}
/****************************************************************************
wrap it to get filenames right
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
SMB_BIG_UINT sys_disk_free ( char * path , BOOL small_query ,
SMB_BIG_UINT * bsize , SMB_BIG_UINT * dfree , SMB_BIG_UINT * dsize )
1998-07-29 07:08:05 +04:00
{
1999-12-13 16:27:58 +03:00
return ( disk_free ( dos_to_unix ( path , False ) , small_query , bsize , dfree , dsize ) ) ;
1998-07-29 07:08:05 +04:00
}