LCOV - code coverage report
Current view: top level - lib/util - fsusage.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 9 14 64.3 %
Date: 2024-04-21 15:09:00 Functions: 2 2 100.0 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             :    functions to calculate the free disk space
       4             :    Copyright (C) Andrew Tridgell 1998-2000
       5             :    
       6             :    This program is free software; you can redistribute it and/or modify
       7             :    it under the terms of the GNU General Public License as published by
       8             :    the Free Software Foundation; either version 3 of the License, or
       9             :    (at your option) any later version.
      10             :    
      11             :    This program is distributed in the hope that it will be useful,
      12             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU General Public License for more details.
      15             :    
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             : */
      19             : 
      20             : #include "replace.h"
      21             : #include "lib/util/samba_util.h"
      22             : #include "system/filesys.h"
      23             :  
      24             : /**
      25             :  * @file
      26             :  * @brief Utility functions for getting the amount of free disk space
      27             :  */
      28             : 
      29             : /* Return the number of TOSIZE-byte blocks used by
      30             :    BLOCKS FROMSIZE-byte blocks, rounding away from zero.
      31             : */
      32        3292 : static uint64_t adjust_blocks(uint64_t blocks, uint64_t fromsize, uint64_t tosize)
      33             : {
      34        3292 :         if (fromsize == tosize) { /* e.g., from 512 to 512 */
      35           0 :                 return blocks;
      36        3292 :         } else if (fromsize > tosize) { /* e.g., from 2048 to 512 */
      37        3292 :                 return blocks * (fromsize / tosize);
      38             :         } else { /* e.g., from 256 to 512 */
      39             :                 /* Protect against broken filesystems... */
      40           0 :                 if (fromsize == 0) {
      41           0 :                         fromsize = tosize;
      42             :                 }
      43           0 :                 return (blocks + 1) / (tosize / fromsize);
      44             :         }
      45             : }
      46             : 
      47             : /**
      48             :  * Retrieve amount of free disk space.
      49             :  * this does all of the system specific guff to get the free disk space.
      50             :  * It is derived from code in the GNU fileutils package, but has been
      51             :  * considerably mangled for use here 
      52             :  *
      53             :  * results are returned in *dfree and *dsize, in 512 byte units
      54             : */
      55        1646 : _PUBLIC_ int sys_fsusage(const char *path, uint64_t *dfree, uint64_t *dsize)
      56             : {
      57             : #ifdef STAT_STATFS3_OSF1
      58             : #define CONVERT_BLOCKS(B) adjust_blocks ((uint64_t)(B), (uint64_t)fsd.f_fsize, (uint64_t)512)
      59             :         struct statfs fsd;
      60             : 
      61             :         if (statfs (path, &fsd, sizeof (struct statfs)) != 0)
      62             :                 return -1;
      63             : #endif /* STAT_STATFS3_OSF1 */
      64             :         
      65             : #ifdef STAT_STATFS2_FS_DATA     /* Ultrix */
      66             : #define CONVERT_BLOCKS(B) adjust_blocks ((uint64_t)(B), (uint64_t)1024, (uint64_t)512)  
      67             :         struct fs_data fsd;
      68             :         
      69             :         if (statfs (path, &fsd) != 1)
      70             :                 return -1;
      71             :         
      72             :         (*dsize) = CONVERT_BLOCKS (fsd.fd_req.btot);
      73             :         (*dfree) = CONVERT_BLOCKS (fsd.fd_req.bfreen);
      74             : #endif /* STAT_STATFS2_FS_DATA */
      75             :         
      76             : #ifdef STAT_STATFS2_BSIZE       /* 4.3BSD, SunOS 4, HP-UX, AIX */
      77             : #define CONVERT_BLOCKS(B) adjust_blocks ((uint64_t)(B), (uint64_t)fsd.f_bsize, (uint64_t)512)
      78             :         struct statfs fsd;
      79             :         
      80             :         if (statfs (path, &fsd) < 0)
      81             :                 return -1;
      82             :         
      83             : #ifdef STATFS_TRUNCATES_BLOCK_COUNTS
      84             :         /* In SunOS 4.1.2, 4.1.3, and 4.1.3_U1, the block counts in the
      85             :            struct statfs are truncated to 2GB.  These conditions detect that
      86             :            truncation, presumably without botching the 4.1.1 case, in which
      87             :            the values are not truncated.  The correct counts are stored in
      88             :            undocumented spare fields.  */
      89             :         if (fsd.f_blocks == 0x1fffff && fsd.f_spare[0] > 0) {
      90             :                 fsd.f_blocks = fsd.f_spare[0];
      91             :                 fsd.f_bfree = fsd.f_spare[1];
      92             :                 fsd.f_bavail = fsd.f_spare[2];
      93             :         }
      94             : #endif /* STATFS_TRUNCATES_BLOCK_COUNTS */
      95             : #endif /* STAT_STATFS2_BSIZE */
      96             :         
      97             : 
      98             : #ifdef STAT_STATFS2_FSIZE       /* 4.4BSD */
      99             : #define CONVERT_BLOCKS(B) adjust_blocks ((uint64_t)(B), (uint64_t)fsd.f_fsize, (uint64_t)512)
     100             :         
     101             :         struct statfs fsd;
     102             :         
     103             :         if (statfs (path, &fsd) < 0)
     104             :                 return -1;
     105             : #endif /* STAT_STATFS2_FSIZE */
     106             :         
     107             : #ifdef STAT_STATFS4             /* SVR3, Dynix, Irix, AIX */
     108             : # if _AIX || defined(_CRAY)
     109             : #  define CONVERT_BLOCKS(B) adjust_blocks ((uint64_t)(B), (uint64_t)fsd.f_bsize, (uint64_t)512)
     110             : #  ifdef _CRAY
     111             : #   define f_bavail f_bfree
     112             : #  endif
     113             : # else
     114             : #  define CONVERT_BLOCKS(B) ((uint64_t)B)
     115             : #  ifndef _SEQUENT_             /* _SEQUENT_ is DYNIX/ptx */
     116             : #   ifndef DOLPHIN              /* DOLPHIN 3.8.alfa/7.18 has f_bavail */
     117             : #    define f_bavail f_bfree
     118             : #   endif
     119             : #  endif
     120             : # endif
     121             :         
     122             :         struct statfs fsd;
     123             : 
     124             :         if (statfs (path, &fsd, sizeof fsd, 0) < 0)
     125             :                 return -1;
     126             :         /* Empirically, the block counts on most SVR3 and SVR3-derived
     127             :            systems seem to always be in terms of 512-byte blocks,
     128             :            no matter what value f_bsize has.  */
     129             : 
     130             : #endif /* STAT_STATFS4 */
     131             : 
     132             : #if defined(STAT_STATVFS)               /* SVR4 */
     133             : #ifdef HAVE_FRSIZE
     134             : # define CONVERT_BLOCKS(B) \
     135             :         adjust_blocks ((uint64_t)(B), fsd.f_frsize ? (uint64_t)fsd.f_frsize : (uint64_t)fsd.f_bsize, (uint64_t)512)
     136             : #else
     137             : # define CONVERT_BLOCKS(B) \
     138             :         adjust_blocks ((uint64_t)(B), (uint64_t)fsd.f_bsize, (uint64_t)512)
     139             : #endif
     140             : 
     141           0 :         struct statvfs fsd;
     142        1646 :         if (statvfs(path, &fsd) < 0) return -1;
     143             : 
     144             :         /* f_frsize isn't guaranteed to be supported.  */
     145             : 
     146             : #endif /* STAT_STATVFS */
     147             : 
     148             : #ifndef CONVERT_BLOCKS
     149             :         /* we don't have any dfree code! */
     150             :         return -1;
     151             : #else
     152             : #if !defined(STAT_STATFS2_FS_DATA)
     153             :         /* !Ultrix */
     154        1646 :         (*dsize) = CONVERT_BLOCKS (fsd.f_blocks);
     155        1646 :         (*dfree) = CONVERT_BLOCKS (fsd.f_bavail);
     156             : #endif /* not STAT_STATFS2_FS_DATA */
     157             : #endif
     158             : 
     159        1646 :         return 0;
     160             : }

Generated by: LCOV version 1.14