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 : }
|