2003-08-13 05:53:07 +04:00
/*
Unix SMB / CIFS implementation .
functions to calculate the free disk space
Copyright ( C ) Andrew Tridgell 1998 - 2000
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-10 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2003-08-13 05:53:07 +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 06:07:03 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2003-08-13 05:53:07 +04:00
*/
2022-06-25 12:07:44 +03:00
# include "replace.h"
# include "lib/util/samba_util.h"
2004-11-02 03:24:21 +03:00
# include "system/filesys.h"
2008-10-14 04:16:27 +04:00
2006-02-28 16:12:39 +03:00
/**
* @ file
* @ brief Utility functions for getting the amount of free disk space
*/
2003-08-13 05:53:07 +04:00
/* Return the number of TOSIZE-byte blocks used by
BLOCKS FROMSIZE - byte blocks , rounding away from zero .
*/
2004-05-25 17:57:39 +04:00
static uint64_t adjust_blocks ( uint64_t blocks , uint64_t fromsize , uint64_t tosize )
2003-08-13 05:53:07 +04:00
{
2008-10-14 04:16:27 +04:00
if ( fromsize = = tosize ) { /* e.g., from 512 to 512 */
2003-08-13 05:53:07 +04:00
return blocks ;
2008-10-14 04:16:27 +04:00
} else if ( fromsize > tosize ) { /* e.g., from 2048 to 512 */
2003-08-13 05:53:07 +04:00
return blocks * ( fromsize / tosize ) ;
2008-10-14 04:16:27 +04:00
} else { /* e.g., from 256 to 512 */
/* Protect against broken filesystems... */
if ( fromsize = = 0 ) {
fromsize = tosize ;
}
2003-08-13 05:53:07 +04:00
return ( blocks + 1 ) / ( tosize / fromsize ) ;
2008-10-14 04:16:27 +04:00
}
2003-08-13 05:53:07 +04:00
}
2006-02-28 16:12:39 +03:00
/**
* Retrieve amount of free disk space .
* this does all of the system specific guff to get the free disk space .
* It is derived from code in the GNU fileutils package , but has been
* considerably mangled for use here
*
* results are returned in * dfree and * dsize , in 512 byte units
2003-08-13 05:53:07 +04:00
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ int sys_fsusage ( const char * path , uint64_t * dfree , uint64_t * dsize )
2003-08-13 05:53:07 +04:00
{
# ifdef STAT_STATFS3_OSF1
2004-05-25 17:57:39 +04:00
# define CONVERT_BLOCKS(B) adjust_blocks ((uint64_t)(B), (uint64_t)fsd.f_fsize, (uint64_t)512)
2003-08-13 05:53:07 +04:00
struct statfs fsd ;
if ( statfs ( path , & fsd , sizeof ( struct statfs ) ) ! = 0 )
return - 1 ;
# endif /* STAT_STATFS3_OSF1 */
# ifdef STAT_STATFS2_FS_DATA /* Ultrix */
2004-05-25 17:57:39 +04:00
# define CONVERT_BLOCKS(B) adjust_blocks ((uint64_t)(B), (uint64_t)1024, (uint64_t)512)
2003-08-13 05:53:07 +04:00
struct fs_data fsd ;
if ( statfs ( path , & fsd ) ! = 1 )
return - 1 ;
( * dsize ) = CONVERT_BLOCKS ( fsd . fd_req . btot ) ;
( * dfree ) = CONVERT_BLOCKS ( fsd . fd_req . bfreen ) ;
# endif /* STAT_STATFS2_FS_DATA */
# ifdef STAT_STATFS2_BSIZE /* 4.3BSD, SunOS 4, HP-UX, AIX */
2004-05-25 17:57:39 +04:00
# define CONVERT_BLOCKS(B) adjust_blocks ((uint64_t)(B), (uint64_t)fsd.f_bsize, (uint64_t)512)
2003-08-13 05:53:07 +04:00
struct statfs fsd ;
if ( statfs ( path , & fsd ) < 0 )
return - 1 ;
# ifdef STATFS_TRUNCATES_BLOCK_COUNTS
/* In SunOS 4.1.2, 4.1.3, and 4.1.3_U1, the block counts in the
struct statfs are truncated to 2 GB . These conditions detect that
truncation , presumably without botching the 4.1 .1 case , in which
the values are not truncated . The correct counts are stored in
undocumented spare fields . */
if ( fsd . f_blocks = = 0x1fffff & & fsd . f_spare [ 0 ] > 0 ) {
fsd . f_blocks = fsd . f_spare [ 0 ] ;
fsd . f_bfree = fsd . f_spare [ 1 ] ;
fsd . f_bavail = fsd . f_spare [ 2 ] ;
}
# endif /* STATFS_TRUNCATES_BLOCK_COUNTS */
# endif /* STAT_STATFS2_BSIZE */
# ifdef STAT_STATFS2_FSIZE /* 4.4BSD */
2004-05-25 17:57:39 +04:00
# define CONVERT_BLOCKS(B) adjust_blocks ((uint64_t)(B), (uint64_t)fsd.f_fsize, (uint64_t)512)
2003-08-13 05:53:07 +04:00
struct statfs fsd ;
if ( statfs ( path , & fsd ) < 0 )
return - 1 ;
# endif /* STAT_STATFS2_FSIZE */
# ifdef STAT_STATFS4 /* SVR3, Dynix, Irix, AIX */
# if _AIX || defined(_CRAY)
2004-05-25 17:57:39 +04:00
# define CONVERT_BLOCKS(B) adjust_blocks ((uint64_t)(B), (uint64_t)fsd.f_bsize, (uint64_t)512)
2003-08-13 05:53:07 +04:00
# ifdef _CRAY
# define f_bavail f_bfree
# endif
# else
2004-05-25 17:57:39 +04:00
# define CONVERT_BLOCKS(B) ((uint64_t)B)
2003-08-13 05:53:07 +04:00
# ifndef _SEQUENT_ /* _SEQUENT_ is DYNIX/ptx */
# ifndef DOLPHIN /* DOLPHIN 3.8.alfa/7.18 has f_bavail */
# define f_bavail f_bfree
# endif
# endif
# endif
struct statfs fsd ;
if ( statfs ( path , & fsd , sizeof fsd , 0 ) < 0 )
return - 1 ;
/* Empirically, the block counts on most SVR3 and SVR3-derived
systems seem to always be in terms of 512 - byte blocks ,
no matter what value f_bsize has . */
# endif /* STAT_STATFS4 */
2012-03-28 02:49:48 +04:00
# if defined(STAT_STATVFS) /* SVR4 */
2008-10-13 22:50:27 +04:00
# ifdef HAVE_FRSIZE
2003-08-13 05:53:07 +04:00
# define CONVERT_BLOCKS(B) \
2004-05-25 17:57:39 +04:00
adjust_blocks ( ( uint64_t ) ( B ) , fsd . f_frsize ? ( uint64_t ) fsd . f_frsize : ( uint64_t ) fsd . f_bsize , ( uint64_t ) 512 )
2008-10-13 22:50:27 +04:00
# else
# define CONVERT_BLOCKS(B) \
adjust_blocks ( ( uint64_t ) ( B ) , ( uint64_t ) fsd . f_bsize , ( uint64_t ) 512 )
# endif
2003-08-13 05:53:07 +04:00
struct statvfs fsd ;
if ( statvfs ( path , & fsd ) < 0 ) return - 1 ;
/* f_frsize isn't guaranteed to be supported. */
# endif /* STAT_STATVFS */
# ifndef CONVERT_BLOCKS
/* we don't have any dfree code! */
return - 1 ;
# else
# if !defined(STAT_STATFS2_FS_DATA)
/* !Ultrix */
( * dsize ) = CONVERT_BLOCKS ( fsd . f_blocks ) ;
( * dfree ) = CONVERT_BLOCKS ( fsd . f_bavail ) ;
# endif /* not STAT_STATFS2_FS_DATA */
# endif
return 0 ;
}