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