464
private static File guessRootByUsableSpace(final File file) {
464
public static enum FileSpaceMethodHelper {
466
// WARNING: File.getFreeSpace also include reserved blocks (eg Linux FileSystems)! Use File.getUsableSpace
468
public long get(File probeFile) {
469
long space = probeFile.getFreeSpace();
471
final File workaroundFile = getWindowsSubstWorkaround(probeFile);
472
if (workaroundFile != null) {
473
space = workaroundFile.getFreeSpace();
482
public long get(File probeFile) {
483
long space = probeFile.getTotalSpace();
485
final File workaroundFile = getWindowsSubstWorkaround(probeFile);
486
if (workaroundFile != null) {
487
space = workaroundFile.getTotalSpace();
497
public long get(File probeFile) {
498
long space = probeFile.getUsableSpace();
500
final File workaroundFile = getWindowsSubstWorkaround(probeFile);
501
if (workaroundFile != null) {
502
space = workaroundFile.getUsableSpace();
510
private static final File getWindowsSubstWorkaround(File probeFile) {
511
if (CrossSystem.isWindows() && (probeFile.getParent() == null || probeFile.isFile())) {
512
// workaround for subst drive
513
final File[] listFiles;
514
if (probeFile.isDirectory()) {
515
listFiles = probeFile.listFiles();
517
final File parentFile = probeFile.getParentFile();
518
listFiles = parentFile != null ? parentFile.listFiles() : null;
520
if (listFiles != null) {
521
for (final File listFile : listFiles) {
522
if (listFile.isDirectory()) {
531
public abstract long get(File file);
534
private static File guessRootBy(final File file, final FileSpaceMethodHelper method) {
465
535
final List<File> bestGuessCandidates = new ArrayList<File>();
466
536
final int maxRetry = 100;
467
537
final int maxRetryTrustThreshold = 30;
468
538
int differentCandidates = 0;
469
539
for (int retry = 1; retry <= maxRetry; retry++) {
470
long lastUsableSpace = -1;
471
541
File lastFile = null;
472
542
File currentFile = file;
473
543
while (currentFile != null) {
474
final long usableSpace = getFileUsableSpace(currentFile);
475
if (usableSpace > 0) {
476
if (lastFile == null || lastUsableSpace == usableSpace) {
544
final long space = method.get(currentFile);
546
if (lastFile == null || lastSpace == space) {
477
547
lastFile = currentFile;
478
lastUsableSpace = usableSpace;
548
618
if (bestRootMatch == null) {
549
619
final String destination = file.getAbsolutePath();
550
620
if (!destination.startsWith("\\")) {
551
final File bestByUsableSpace = guessRootByUsableSpace(file);
621
final File bestByUsableSpace = guessRootBy(file, FileSpaceMethodHelper.TOTAL);
552
622
if (bestByUsableSpace != null) {
553
623
return bestByUsableSpace;
583
653
return bestRootMatch == null ? null : new File(bestRootMatch);
586
private static long getFileUsableSpace(final File probeFile) {
587
long usableSpace = probeFile.getUsableSpace();
588
if (usableSpace == 0 && CrossSystem.isWindows() && (probeFile.getParent() == null || probeFile.isFile())) {
589
// workaround for subst drive
590
final File[] listFiles;
591
if (probeFile.isDirectory()) {
592
listFiles = probeFile.listFiles();
594
final File parentFile = probeFile.getParentFile();
595
listFiles = parentFile != null ? parentFile.listFiles() : null;
597
if (listFiles != null) {
598
for (final File listFile : listFiles) {
599
if (listFile.isDirectory()) {
600
usableSpace = listFile.getUsableSpace();
609
656
public static long getUsableSpace(final File file) {
610
657
final File root = guessRoot(file);
611
// WARNING: File.getFreeSpace also include reserved blocks (eg Linux FileSystems)! Use File.getUsableSpace
612
658
final File probeFile;
613
659
if (root != null) {
614
660
probeFile = root;
616
662
probeFile = file;
618
return getFileUsableSpace(probeFile);
664
return FileSpaceMethodHelper.USABLE.get(probeFile);