@@ -145,7 +145,7 @@ public FileSystemUtils() {
145145 */
146146 @ Deprecated
147147 public static long freeSpace (String path ) throws IOException {
148- return INSTANCE .freeSpaceOS (path , OS , false );
148+ return INSTANCE .freeSpaceOS (path , OS , false , - 1 );
149149 }
150150
151151 //-----------------------------------------------------------------------
@@ -174,7 +174,36 @@ public static long freeSpace(String path) throws IOException {
174174 * @since Commons IO 1.2, enhanced OS support in 1.3
175175 */
176176 public static long freeSpaceKb (String path ) throws IOException {
177- return INSTANCE .freeSpaceOS (path , OS , true );
177+ return freeSpaceKb (path , -1 );
178+ }
179+ /**
180+ * Returns the free space on a drive or volume in kilobytes by invoking
181+ * the command line.
182+ * <pre>
183+ * FileSystemUtils.freeSpaceKb("C:"); // Windows
184+ * FileSystemUtils.freeSpaceKb("/volume"); // *nix
185+ * </pre>
186+ * The free space is calculated via the command line.
187+ * It uses 'dir /-c' on Windows, 'df -kP' on AIX/HP-UX and 'df -k' on other Unix.
188+ * <p>
189+ * In order to work, you must be running Windows, or have a implementation of
190+ * Unix df that supports GNU format when passed -k (or -kP). If you are going
191+ * to rely on this code, please check that it works on your OS by running
192+ * some simple tests to compare the command line with the output from this class.
193+ * If your operating system isn't supported, please raise a JIRA call detailing
194+ * the exact result from df -k and as much other detail as possible, thanks.
195+ *
196+ * @param path the path to get free space for, not null, not empty on Unix
197+ * @param timeout The timout amount in milliseconds or no timeout if the value
198+ * is zero or less
199+ * @return the amount of free drive space on the drive or volume in kilobytes
200+ * @throws IllegalArgumentException if the path is invalid
201+ * @throws IllegalStateException if an error occurred in initialisation
202+ * @throws IOException if an error occurs when finding the free space
203+ * @since Commons IO 2.0
204+ */
205+ public static long freeSpaceKb (String path , long timeout ) throws IOException {
206+ return INSTANCE .freeSpaceOS (path , OS , true , timeout );
178207 }
179208
180209 /**
@@ -189,7 +218,25 @@ public static long freeSpaceKb(String path) throws IOException {
189218 * @throws IOException if an error occurs when finding the free space
190219 */
191220 public static long freeSpaceKb () throws IOException {
192- return freeSpaceKb (new File ("." ).getAbsolutePath ());
221+ return freeSpaceKb (-1 );
222+ }
223+
224+ /**
225+ * Returns the disk size of the volume which holds the working directory.
226+ * <p>
227+ * Identical to:
228+ * <pre>
229+ * freeSpaceKb(new File(".").getAbsolutePath())
230+ * </pre>
231+ * @param timeout The timout amount in milliseconds or no timeout if the value
232+ * is zero or less
233+ * @return the amount of free drive space on the drive or volume in kilobytes
234+ * @throws IllegalStateException if an error occurred in initialisation
235+ * @throws IOException if an error occurs when finding the free space
236+ * @since Commons IO 2.0
237+ */
238+ public static long freeSpaceKb (long timeout ) throws IOException {
239+ return freeSpaceKb (new File ("." ).getAbsolutePath (), timeout );
193240 }
194241
195242 //-----------------------------------------------------------------------
@@ -206,22 +253,24 @@ public static long freeSpaceKb() throws IOException {
206253 * @param path the path to get free space for, not null, not empty on Unix
207254 * @param os the operating system code
208255 * @param kb whether to normalize to kilobytes
256+ * @param timeout The timout amount in milliseconds or no timeout if the value
257+ * is zero or less
209258 * @return the amount of free drive space on the drive or volume
210259 * @throws IllegalArgumentException if the path is invalid
211260 * @throws IllegalStateException if an error occurred in initialisation
212261 * @throws IOException if an error occurs when finding the free space
213262 */
214- long freeSpaceOS (String path , int os , boolean kb ) throws IOException {
263+ long freeSpaceOS (String path , int os , boolean kb , long timeout ) throws IOException {
215264 if (path == null ) {
216265 throw new IllegalArgumentException ("Path must not be empty" );
217266 }
218267 switch (os ) {
219268 case WINDOWS :
220- return (kb ? freeSpaceWindows (path ) / 1024 : freeSpaceWindows (path ));
269+ return (kb ? freeSpaceWindows (path , timeout ) / 1024 : freeSpaceWindows (path , timeout ));
221270 case UNIX :
222- return freeSpaceUnix (path , kb , false );
271+ return freeSpaceUnix (path , kb , false , timeout );
223272 case POSIX_UNIX :
224- return freeSpaceUnix (path , kb , true );
273+ return freeSpaceUnix (path , kb , true , timeout );
225274 case OTHER :
226275 throw new IllegalStateException ("Unsupported operating system" );
227276 default :
@@ -235,10 +284,12 @@ long freeSpaceOS(String path, int os, boolean kb) throws IOException {
235284 * Find free space on the Windows platform using the 'dir' command.
236285 *
237286 * @param path the path to get free space for, including the colon
287+ * @param timeout The timout amount in milliseconds or no timeout if the value
288+ * is zero or less
238289 * @return the amount of free drive space on the drive
239290 * @throws IOException if an error occurs
240291 */
241- long freeSpaceWindows (String path ) throws IOException {
292+ long freeSpaceWindows (String path , long timeout ) throws IOException {
242293 path = FilenameUtils .normalize (path );
243294 if (path .length () > 2 && path .charAt (1 ) == ':' ) {
244295 path = path .substring (0 , 2 ); // seems to make it work
@@ -248,7 +299,7 @@ long freeSpaceWindows(String path) throws IOException {
248299 String [] cmdAttribs = new String [] {"cmd.exe" , "/C" , "dir /-c " + path };
249300
250301 // read in the output of the command to an ArrayList
251- List <String > lines = performCommand (cmdAttribs , Integer .MAX_VALUE );
302+ List <String > lines = performCommand (cmdAttribs , Integer .MAX_VALUE , timeout );
252303
253304 // now iterate over the lines we just read and find the LAST
254305 // non-empty line (the free space bytes should be in the last element
@@ -325,10 +376,12 @@ long parseDir(String line, String path) throws IOException {
325376 * @param path the path to get free space for
326377 * @param kb whether to normalize to kilobytes
327378 * @param posix whether to use the posix standard format flag
379+ * @param timeout The timout amount in milliseconds or no timeout if the value
380+ * is zero or less
328381 * @return the amount of free drive space on the volume
329382 * @throws IOException if an error occurs
330383 */
331- long freeSpaceUnix (String path , boolean kb , boolean posix ) throws IOException {
384+ long freeSpaceUnix (String path , boolean kb , boolean posix , long timeout ) throws IOException {
332385 if (path .length () == 0 ) {
333386 throw new IllegalArgumentException ("Path must not be empty" );
334387 }
@@ -345,7 +398,7 @@ long freeSpaceUnix(String path, boolean kb, boolean posix) throws IOException {
345398 (flags .length () > 1 ? new String [] {DF , flags , path } : new String [] {DF , path });
346399
347400 // perform the command, asking for up to 3 lines (header, interesting, overflow)
348- List <String > lines = performCommand (cmdAttribs , 3 );
401+ List <String > lines = performCommand (cmdAttribs , 3 , timeout );
349402 if (lines .size () < 2 ) {
350403 // unknown problem, throw exception
351404 throw new IOException (
@@ -407,10 +460,12 @@ long parseBytes(String freeSpace, String path) throws IOException {
407460 *
408461 * @param cmdAttribs the command line parameters
409462 * @param max The maximum limit for the lines returned
463+ * @param timeout The timout amount in milliseconds or no timeout if the value
464+ * is zero or less
410465 * @return the parsed data
411466 * @throws IOException if an error occurs
412467 */
413- List <String > performCommand (String [] cmdAttribs , int max ) throws IOException {
468+ List <String > performCommand (String [] cmdAttribs , int max , long timeout ) throws IOException {
414469 // this method does what it can to avoid the 'Too many open files' error
415470 // based on trial and error and these links:
416471 // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4784692
@@ -426,6 +481,9 @@ List<String> performCommand(String[] cmdAttribs, int max) throws IOException {
426481 InputStream err = null ;
427482 BufferedReader inr = null ;
428483 try {
484+
485+ Thread monitor = ThreadMonitor .start (timeout );
486+
429487 proc = openProcess (cmdAttribs );
430488 in = proc .getInputStream ();
431489 out = proc .getOutputStream ();
@@ -439,6 +497,9 @@ List<String> performCommand(String[] cmdAttribs, int max) throws IOException {
439497 }
440498
441499 proc .waitFor ();
500+
501+ ThreadMonitor .stop (monitor );
502+
442503 if (proc .exitValue () != 0 ) {
443504 // os command problem, throw exception
444505 throw new IOException (
0 commit comments