Skip to content

Commit dcb61e5

Browse files
author
Stephen Colebourne
committed
Add FileSystemUtils to allow access to information about the filing system
bug 32982, from Frank W. Zammetti git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/io/trunk@154561 13f79535-47bb-0310-9956-ffa450edef68
1 parent 4a92373 commit dcb61e5

3 files changed

Lines changed: 296 additions & 0 deletions

File tree

project.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,9 @@
171171
<contributor>
172172
<name>Masato Tezuka</name>
173173
</contributor>
174+
<contributor>
175+
<name>Frank W. Zammetti</name>
176+
</contributor>
174177
</contributors>
175178

176179
<dependencies>
Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
/*
2+
* Copyright 2005 The Apache Software Foundation.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.apache.commons.io;
17+
18+
import java.io.BufferedReader;
19+
import java.io.IOException;
20+
import java.io.InputStreamReader;
21+
import java.util.StringTokenizer;
22+
23+
/**
24+
* General File System utilities.
25+
* <p>
26+
* This class provides static utility methods for general file system
27+
* functions.
28+
*
29+
* @author Frank W. Zammetti
30+
* @author Stephen Colebourne
31+
* @version $Id$
32+
*/
33+
public final class FileSystemUtils {
34+
35+
private static final int INIT_PROBLEM = -1;
36+
private static final int OTHER = 0;
37+
private static final int WINDOWS = 1;
38+
private static final int UNIX = 2;
39+
40+
private static final int OS;
41+
static {
42+
int os = OTHER;
43+
try {
44+
String osName = System.getProperty("os.name");
45+
if (osName == null) {
46+
throw new IOException("os.name not found");
47+
}
48+
osName = osName.toLowerCase();
49+
// match
50+
if (osName.indexOf("windows") != -1) {
51+
os = WINDOWS;
52+
} else if (osName.indexOf("linux") != -1 ||
53+
osName.indexOf("sun os") != -1 ||
54+
osName.indexOf("sunos") != -1 ||
55+
osName.indexOf("solaris") != -1 ||
56+
osName.indexOf("mpe/ix") != -1 ||
57+
osName.indexOf("hp-ux") != -1 ||
58+
osName.indexOf("aix") != -1 ||
59+
osName.indexOf("freebsd") != -1 ||
60+
osName.indexOf("irix") != -1 ||
61+
osName.indexOf("digital unix") != -1 ||
62+
osName.indexOf("unix") != -1 ||
63+
osName.indexOf("mac os x") != -1) {
64+
os = UNIX;
65+
} else {
66+
os = OTHER;
67+
}
68+
69+
} catch (Exception ex) {
70+
os = INIT_PROBLEM;
71+
}
72+
OS = os;
73+
}
74+
75+
/**
76+
* Instances should NOT be constructed in standard programming.
77+
*/
78+
public FileSystemUtils() {
79+
}
80+
81+
//-----------------------------------------------------------------------
82+
/**
83+
* Returns the free space on a drive or volume in a cross-platform manner.
84+
* Note that some OS's are NOT currently supported, including OS/390.
85+
* <pre>
86+
* FileSystemUtils.getFreeSpace("C:"); // Windows
87+
* FileSystemUtils.getFreeSpace("/volume"); // *nix
88+
* </pre>
89+
* The free space is calculated via the command line.
90+
* It uses 'dir /-c' on Windows and 'df' on Unix.
91+
*
92+
* @param path the path to get free space for
93+
* @return the amount of free drive space on the drive or volume
94+
* @throws IllegalArgumentException if the path is invalid
95+
* @throws IllegalStateException if an error occurred in initialisation
96+
* @throws IOException if an error occurs when finding the free space
97+
*/
98+
public static long getFreeSpace(String path) throws IOException {
99+
if (path == null || path.length() == 0) {
100+
throw new IllegalArgumentException("Path must not be empty");
101+
}
102+
switch (OS) {
103+
case WINDOWS:
104+
return getFreeSpaceWindows(path);
105+
case UNIX:
106+
return getFreeSpaceUnix(path);
107+
case OTHER:
108+
throw new IllegalStateException("Unsupported operating system");
109+
default:
110+
throw new IllegalStateException("Exception caught when determining operating system");
111+
}
112+
}
113+
114+
/**
115+
* Find free space on the Windows platform using the 'dir' command.
116+
*
117+
* @param path the path to get free space for, including the colon
118+
* @return the amount of free drive space on the drive
119+
* @throws IOException if an error occurs
120+
*/
121+
private static long getFreeSpaceWindows(String path) throws IOException {
122+
// build and run the 'dir' command
123+
String line = null;
124+
String[] cmdAttrbs = new String[3];
125+
cmdAttrbs[0] = "cmd.exe";
126+
cmdAttrbs[1] = "/C";
127+
cmdAttrbs[2] = "dir /-c " + path;
128+
Process proc = Runtime.getRuntime().exec(cmdAttrbs);
129+
130+
// read the output until we find the line with 'bytes free'
131+
long bytes = -1;
132+
BufferedReader in = null;
133+
try {
134+
in = new BufferedReader(new InputStreamReader(proc.getInputStream()));
135+
line = in.readLine();
136+
while (line != null) {
137+
line = line.toLowerCase();
138+
int bfl = line.indexOf("bytes free");
139+
if (bfl != -1) {
140+
// found "bytes free"
141+
// chop off everything AFTER the actual byte count
142+
line = line.substring(0, bfl);
143+
line = line.trim();
144+
// find the LAST space in the string, should be right before the
145+
// byte count
146+
int lsl = line.lastIndexOf(' ');
147+
// now get rid of everything BEFORE that space, and line will
148+
// then contain just the byte count
149+
line = line.substring(lsl + 1);
150+
bytes = Long.parseLong(line);
151+
}
152+
line = in.readLine();
153+
}
154+
} finally {
155+
IOUtils.closeQuietly(in);
156+
}
157+
158+
if (bytes == -1) {
159+
throw new IOException(
160+
"Command line 'dir' did not find text 'bytes free' in response for path '" +
161+
path + "'- check path is of the form 'C:'");
162+
}
163+
return bytes;
164+
}
165+
166+
/**
167+
* Find free space on the Nix platform using the 'df' command.
168+
*
169+
* @param path the path to get free space for
170+
* @return the amount of free drive space on the volume
171+
* @throws IOException if an error occurs
172+
*/
173+
private static long getFreeSpaceUnix(String path) throws IOException {
174+
// build and run the 'dir' command
175+
String[] cmdAttrbs = new String[3];
176+
cmdAttrbs[0] = "cmd.exe";
177+
cmdAttrbs[1] = "/C";
178+
cmdAttrbs[2] = "df " + path;
179+
Process proc = Runtime.getRuntime().exec(cmdAttrbs);
180+
181+
// read the output from the command until we come to the second line
182+
long bytes = -1;
183+
BufferedReader in = null;
184+
try {
185+
in = new BufferedReader(new InputStreamReader(proc.getInputStream()));
186+
String line1 = in.readLine(); // header line (ignore it)
187+
String line2 = in.readLine(); // the line we're interested in
188+
if (line2 == null) {
189+
// unknown problem, throw exception
190+
throw new IOException(
191+
"Command line 'df' did not return info as expected for path '" +
192+
path + "'- response on first line was '" + line1 + '"');
193+
}
194+
line2 = line2.trim();
195+
196+
// Now, we tokenize the string. The fourth element is what we want.
197+
StringTokenizer tok = new StringTokenizer(line2, " ");
198+
if (tok.countTokens() < 4) {
199+
throw new IOException(
200+
"Command line 'df' did not return data as expected for path '" +
201+
path + "'- check path is valid");
202+
}
203+
tok.nextToken(); // Ignore Filesystem
204+
tok.nextToken(); // Ignore 1K-blocks
205+
tok.nextToken(); // Ignore Used
206+
String freeSpace = tok.nextToken();
207+
bytes = Long.parseLong(freeSpace);
208+
209+
} finally {
210+
IOUtils.closeQuietly(in);
211+
}
212+
213+
if (bytes == -1) {
214+
throw new IOException(
215+
"Command line 'df' did not find free space in response for path '" +
216+
path + "'- check path is valid");
217+
}
218+
return bytes;
219+
}
220+
221+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*
2+
* Copyright 2005 The Apache Software Foundation.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.apache.commons.io;
17+
18+
import java.io.IOException;
19+
import java.util.StringTokenizer;
20+
21+
/**
22+
* This is used to test FileSystemUtils for correctness.
23+
*
24+
* @author Stephen Colebourne
25+
* @version $Id$
26+
*/
27+
public class FileSystemUtilsChecker {
28+
29+
public static void main(String[] args) {
30+
try {
31+
outputFreeSpaceCDrive();
32+
outputFreeSpaceUnix();
33+
} catch (Throwable th) {
34+
th.printStackTrace();
35+
}
36+
}
37+
38+
private static void outputFreeSpaceCDrive() throws IOException {
39+
System.out.println(FileSystemUtils.getFreeSpace("C:"));
40+
}
41+
42+
private static void outputFreeSpaceUnix() throws Exception {
43+
// copied from FileSystemUtils, with some genuine UNIX data
44+
// as I run a Windows box
45+
String path = "/usr";
46+
long bytes = -1;
47+
48+
String line1 = "Filesystem 1K-blocks Used Avail Capacity Mounted on";
49+
String line2 = "/dev/da0s1g 8064542 2930306 4489074 39% /usr";
50+
if (line2 == null) {
51+
// unknown problem, throw exception
52+
throw new IOException(
53+
"Command line 'df' did not return info as expected for path '" +
54+
path + "'- response on first line was '" + line1 + '"');
55+
}
56+
line2 = line2.trim();
57+
58+
// Now, we tokenize the string. The fourth element is what we want.
59+
StringTokenizer tok = new StringTokenizer(line2, " ");
60+
if (tok.countTokens() < 4) {
61+
throw new IOException(
62+
"Command line 'df' did not return data as expected for path '" +
63+
path + "'- check path is valid");
64+
}
65+
tok.nextToken(); // Ignore Filesystem
66+
tok.nextToken(); // Ignore 1K-blocks
67+
tok.nextToken(); // Ignore Used
68+
String freeSpace = tok.nextToken();
69+
bytes = Long.parseLong(freeSpace);
70+
System.out.println("" + bytes);
71+
}
72+
}

0 commit comments

Comments
 (0)