From 58616d99e473fe2da611dea9f2510a22c2bdafd3 Mon Sep 17 00:00:00 2001 From: lotus Date: Sun, 1 Nov 2009 08:54:16 +0000 Subject: [PATCH] patch for yacy disk usage detection on lvm host by Michael S. git-svn-id: https://svn.berlios.de/svnroot/repos/yacy/trunk@6442 6c8d7289-2bf4-0310-a012-ef5d649a1542 --- source/net/yacy/kelondro/util/DiskSpace.java | 803 ++++++++++--------- 1 file changed, 402 insertions(+), 401 deletions(-) diff --git a/source/net/yacy/kelondro/util/DiskSpace.java b/source/net/yacy/kelondro/util/DiskSpace.java index 54130b9fd..0fb4aa450 100644 --- a/source/net/yacy/kelondro/util/DiskSpace.java +++ b/source/net/yacy/kelondro/util/DiskSpace.java @@ -1,401 +1,402 @@ -// diskUsage.java -// ----------------------- -// part of YaCy -// (C) by Detlef Reichl; detlef!reichl()gmx!org -// Pforzheim, Germany, 2008 -// -// [MC] made many changes to remove side-effect-based routines towards a more functional programming style -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -// The HashMap contains the following values: -// -// key = the device name e.g. /dev/hda1, on windows the drive e.g. c: -// value[0] = the total space of the volume, on windows not used -// value[1] = the free space of the volume - -package net.yacy.kelondro.util; - -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; - - -import net.yacy.kelondro.logging.Log; - - -public class DiskSpace { - - private static Log log = new Log("DISK USAGE"); - - private static final List allVolumes = new ArrayList(); - private static final List allMountPoints = new ArrayList(); - private static final List usedVolumes = new ArrayList(); - - private static final List yacyUsedVolumes = new ArrayList(); - private static final List yacyUsedMountPoints = new ArrayList(); - - private static int usedOS = -1; - private static String usageError = null; - private static String windowsCommand = null; - - - // Unix-like - private static final int AIX = 0; // IBM - private static final int BS2000 = 1; // Fujitsu Siemens (oficial BS2000/OSD) - //private static final int BSD = 2; // all kind of BSD - private static final int HAIKU = 3; // like BeOS; does not have a JRE til now, but they are working on it - //private static final int HP_UX = 4; // Hewlett-Packard - private static final int TRU64 = 5; // Hewlett-Packard - //private static final int IRIX = 6; // sgi - //private static final int LINUX = 7; // all kind of linux - //private static final int MAC_OS_X = 8; // Apple - private static final int MINIX = 9; // don't know if there even is a JRE for minix... - //private static final int SOLARIS = 10; // SUN - //private static final int SUNOS = 11; // The latest SunOS version is from 1990 but the Solaris java refferer remains SunOS - private static final int UNICOS = 12; // cray - - private static final int UNIX_END = UNICOS; - - // Windows dos based - //private static final int WINDOWS_95 = 13; - //private static final int WINDOWS_98 = 14; - //private static final int WINDOWS_ME = 15; - - // Windows WinNT based - //private static final int WINDOWS_NT = 16; - //private static final int WINDOWS_2000 = 17; - //private static final int WINDOWS_XP = 18; - //private static final int WINDOWS_SERVER = 19; - //private static final int WINDOWS_VISTA = 20; - //private static final int WINDOWS_7 = 21; - - // don't change order of names! - // (look above) - private static final String[] OSname = { - "aix", "bs2000", "bsd", "haiku", "hp-ux", "tru64", "irix", "linux", "mac os x", "minix", - "solaris", "sunos", "unicos", - "windows 95", "windows 98", "windows me", - "windows nt", "windows 2000", "windows xp", "windows server", "windows vista", "windows 7"}; - - ////////////////// - // public API // - ////////////////// - - public static void init(final ArrayList pathsToCheck) { - if (usedOS >= 0) return; // prevent double initialization - usedOS = getOS(); - if (usedOS == -1) { - return; - } - usageError = null; - - if (usedOS <= UNIX_END) { - // some kind of *nix - dfUnixGetVolumes(); - for (int i = 0; i < allMountPoints.size(); i++) - usedVolumes.add(false); - checkVolumesInUseUnix ("DATA"); - checkMappedSubDirs(pathsToCheck); - - for (int i = 0; i < allVolumes.size(); i++){ - if (usedVolumes.get(i) == true) { - yacyUsedVolumes.add(allVolumes.get (i)); - yacyUsedMountPoints.add(allMountPoints.get (i)); - } - } - } else { - // all Windows versions - initWindowsCommandVersion(); - checkStartVolume(); - checkMappedSubDirs(pathsToCheck); - } - if (yacyUsedVolumes.size() < 1) - usageError = "found no volumes"; - } - - public static HashMap getDiskUsage () { - if (usageError != null) return null; - - if (usedOS <= UNIX_END) - return dfUnix(); - else - return dfWindows(); - } - - public static boolean isUsable() { - return usageError == null; - } - - public static int getNumUsedVolumes () { - return yacyUsedVolumes.size(); - } - - public static String getErrorMessage() { - return usageError; - } - - //////////// - // Unix // - //////////// - - private static HashMap dfUnix() { - final HashMap diskUsages = new HashMap(); - try { - final List lines = dfUnixExec(); - nextLine: for (final String line: lines){ - if (line.charAt(0) != '/') continue; - final String[] tokens = line.split(" +", 6); - if (tokens.length < 6) continue; - for (int i = 0; i < yacyUsedVolumes.size(); i++){ - if (yacyUsedVolumes.get(i).equals(tokens[0])) { - final long[] vals = new long[2]; - try { vals[0] = Long.valueOf(tokens[1]); } catch (final NumberFormatException e) { continue nextLine; } - try { vals[1] = Long.valueOf(tokens[3]); } catch (final NumberFormatException e) { continue nextLine; } - vals[0] *= 1024; - vals[1] *= 1024; - diskUsages.put(yacyUsedMountPoints.get(i), vals); - } - } - } - return diskUsages; - } catch (final IOException e) { - usageError = "dfUnix: " + e.getMessage(); - return diskUsages; - } - } - - private static void dfUnixGetVolumes() { - try { - final List lines = dfUnixExec(); - - nextLine: for (final String line: lines){ - if (line.charAt(0) != '/') continue; - final String[] tokens = line.split(" +", 6); - if (tokens.length < 6) continue; - for (int i = 0; i < allMountPoints.size(); i++) { - if (tokens[5].trim().compareTo(allMountPoints.get(i)) > 0) { - allMountPoints.add(i, tokens[5].trim()); - allVolumes.add(i, tokens[0]); - continue nextLine; - } - } - allMountPoints.add(allMountPoints.size(), tokens[5]); - allVolumes.add(allVolumes.size(), tokens[0]); - } - } catch (final IOException e) { - usageError = "error during dfUnixGetVolumes: " + e.getMessage(); - } - } - - private static List dfUnixExec() throws IOException { - - // -k set blocksize to 1024 - // confirmed with tests: - // Linux - // verified with man pages or other docs: - // AIX, BS2000, *BSD, HP-UX, IRIX, minix, Mac OS X, Solaris, Tru64, UNICOS - - // -l list local filesystems only - // confirmed with tests: - // Linux - // verified with man pages or other docs: - // AIX, BS2000, *BSD, HP-UX, IRIX, minix, Mac OS X, Solaris, UNICOS - - // please report all successes or fails for non-confirmed systems to - // detlef!reichl()gmx!org. Thanks! - - final List processArgs = new ArrayList(); - processArgs.add("df"); - processArgs.add("-k"); - // Some systems need the additional -P parameter to return the data in Posix format. - // Without it the mount point will be in the 7th and not in the 6th column - if (usedOS == AIX || usedOS == BS2000 || usedOS == MINIX || usedOS == UNICOS) - processArgs.add("-P"); - // Tru64 does not know the -l parameter - // For haiku i didn't found online docs at all; so better exclude it - if (usedOS != TRU64 && usedOS != HAIKU) - processArgs.add("-l"); - - final List lines = ConsoleInterface.getConsoleOutput(processArgs, log); - return lines; - } - - private static void checkVolumesInUseUnix (final String path) { - final File file = new File(path); - final File[] fileList = file.listFiles(); - if (fileList == null) { - // the file is not a directory - return; - } - String base; - String dir; - - for (final File element : fileList) { - if (element.isDirectory()) { - try { - dir = element.getCanonicalPath(); - } catch (final IOException e) { - usageError = "checkVolumesInUseUnix(1): " + e.getMessage(); - break; - } - if (dir.endsWith ("HTCACHE") - || dir.endsWith ("HTDOCS") - || dir.endsWith ("LOCALE") - || dir.endsWith ("RANKING") - || dir.endsWith ("RELEASE") - || dir.endsWith ("collection.0028.commons")) { - checkPathUsageUnix (dir); - } else if (dir != null) { - checkVolumesInUseUnix (dir); - } else { - log.logSevere("directory is null: " + element); - } - } else { - try { - base = element.getCanonicalPath(); - } catch (final IOException e) { - usageError = "checkVolumesInUseUnix(2): " + e.getMessage(); - break; - } - checkPathUsageUnix (base); - } - } - } - - /////////////// - // Windows // - /////////////// - - private static void initWindowsCommandVersion () { - windowsCommand = null; - final String os = System.getProperty("os.name").toLowerCase(); - final String[] oses = {"windows 95", "windows 98", "windows me"}; - - for (final String element : oses) { - if (os.indexOf(element) >= 0){ - windowsCommand = "command.com"; - break; - } - } - if (windowsCommand == null) - windowsCommand = "cmd.exe"; - } - - private static void checkStartVolume() { - final File file = new File("DATA"); - - String path = null; - try { path = file.getCanonicalPath(); } catch (final IOException e) { - usageError = "Cant get DATA directory"; - return; - } - if (path.length() < 6) - return; - yacyUsedVolumes.add(path); - } - - private static HashMap dfWindows() { - final HashMap diskUsages = new HashMap(); - for (int i = 0; i < yacyUsedVolumes.size(); i++){ - final List processArgs = new ArrayList(); - processArgs.add(windowsCommand); - processArgs.add("/c"); - processArgs.add("dir"); - processArgs.add("\"" + yacyUsedVolumes.get(i) + "\""); - - try { - final List lines = ConsoleInterface.getConsoleOutput(processArgs, log); - - String line = ""; - for (int l = lines.size() - 1; l >= 0; l--) { - line = lines.get(l).trim(); - if (line.length() > 0) break; - } - if (line.length() == 0) { - usageError = "unable to get free size of volume " + yacyUsedVolumes.get(i); - return diskUsages; - } - - final String[] tokens = line.trim().split(" ++"); - final long[] vals = new long[2]; - vals[0] = -1; - try { vals[1] = Long.valueOf(tokens[2].replaceAll("[.,]", "")); } catch (final NumberFormatException e) {continue;} - diskUsages.put (yacyUsedVolumes.get(i), vals); - } catch (final IOException e) { - usageError = "dfWindows: " + e.getMessage(); - return diskUsages; - } - - } - return diskUsages; - } - - ///////////// - // common // - ///////////// - - private static int getOS() { - final String os = System.getProperty("os.name").toLowerCase(); - for (int i = 0; i < OSname.length; i++) - { - if (os.indexOf(OSname[i]) >= 0) - return i; - } - usageError = "unknown operating system (" + System.getProperty("os.name") + ")"; - return -1; - } - - private static void checkMappedSubDirs (final ArrayList pathsToCheck) { - for (final String path : pathsToCheck) { - if (usedOS <= UNIX_END) - checkPathUsageUnix (path); - else - checkPathUsageWindows (path); - } - } - - private static void checkPathUsageUnix (final String path) { - for (int i = 0; i < allMountPoints.size(); i++){ - if (path.startsWith (allMountPoints.get(i))) { - usedVolumes.set(i, true); - return; - } - } - } - - private static void checkPathUsageWindows(final String path) { - // we would need to ask every path by "dir" as asking the root is not hardlink-proof: - // yacyUsedVolumes.add(path); - return; - /* - int index = -1; - final String sub = path.substring(0, 1); // ?? nur ein character? - try { - index = yacyUsedVolumes.indexOf(sub); - } catch (final IndexOutOfBoundsException e) { - usageError = "internal error while checking used windows volumes"; - return; - } - if (index < 0) - yacyUsedVolumes.add(sub); - */ - } - -} - +// diskUsage.java +// ----------------------- +// part of YaCy +// (C) by Detlef Reichl; detlef!reichl()gmx!org +// Pforzheim, Germany, 2008 +// +// [MC] made many changes to remove side-effect-based routines towards a more functional programming style +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +// The HashMap contains the following values: +// +// key = the device name e.g. /dev/hda1, on windows the drive e.g. c: +// value[0] = the total space of the volume, on windows not used +// value[1] = the free space of the volume + +package net.yacy.kelondro.util; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + + +import net.yacy.kelondro.logging.Log; + + +public class DiskSpace { + + private static Log log = new Log("DISK USAGE"); + + private static final List allVolumes = new ArrayList(); + private static final List allMountPoints = new ArrayList(); + private static final List usedVolumes = new ArrayList(); + + private static final List yacyUsedVolumes = new ArrayList(); + private static final List yacyUsedMountPoints = new ArrayList(); + + private static int usedOS = -1; + private static String usageError = null; + private static String windowsCommand = null; + + + // Unix-like + private static final int AIX = 0; // IBM + private static final int BS2000 = 1; // Fujitsu Siemens (oficial BS2000/OSD) + //private static final int BSD = 2; // all kind of BSD + private static final int HAIKU = 3; // like BeOS; does not have a JRE til now, but they are working on it + //private static final int HP_UX = 4; // Hewlett-Packard + private static final int TRU64 = 5; // Hewlett-Packard + //private static final int IRIX = 6; // sgi + private static final int LINUX = 7; // all kind of linux + //private static final int MAC_OS_X = 8; // Apple + private static final int MINIX = 9; // don't know if there even is a JRE for minix... + //private static final int SOLARIS = 10; // SUN + //private static final int SUNOS = 11; // The latest SunOS version is from 1990 but the Solaris java refferer remains SunOS + private static final int UNICOS = 12; // cray + + private static final int UNIX_END = UNICOS; + + // Windows dos based + //private static final int WINDOWS_95 = 13; + //private static final int WINDOWS_98 = 14; + //private static final int WINDOWS_ME = 15; + + // Windows WinNT based + //private static final int WINDOWS_NT = 16; + //private static final int WINDOWS_2000 = 17; + //private static final int WINDOWS_XP = 18; + //private static final int WINDOWS_SERVER = 19; + //private static final int WINDOWS_VISTA = 20; + //private static final int WINDOWS_7 = 21; + + // don't change order of names! + // (look above) + private static final String[] OSname = { + "aix", "bs2000", "bsd", "haiku", "hp-ux", "tru64", "irix", "linux", "mac os x", "minix", + "solaris", "sunos", "unicos", + "windows 95", "windows 98", "windows me", + "windows nt", "windows 2000", "windows xp", "windows server", "windows vista", "windows 7"}; + + ////////////////// + // public API // + ////////////////// + + public static void init(final ArrayList pathsToCheck) { + if (usedOS >= 0) return; // prevent double initialization + usedOS = getOS(); + if (usedOS == -1) { + return; + } + usageError = null; + + if (usedOS <= UNIX_END) { + // some kind of *nix + dfUnixGetVolumes(); + for (int i = 0; i < allMountPoints.size(); i++) + usedVolumes.add(false); + checkVolumesInUseUnix ("DATA"); + checkMappedSubDirs(pathsToCheck); + + for (int i = 0; i < allVolumes.size(); i++){ + if (usedVolumes.get(i) == true) { + yacyUsedVolumes.add(allVolumes.get (i)); + yacyUsedMountPoints.add(allMountPoints.get (i)); + } + } + } else { + // all Windows versions + initWindowsCommandVersion(); + checkStartVolume(); + checkMappedSubDirs(pathsToCheck); + } + if (yacyUsedVolumes.size() < 1) + usageError = "found no volumes"; + } + + public static HashMap getDiskUsage () { + if (usageError != null) return null; + + if (usedOS <= UNIX_END) + return dfUnix(); + else + return dfWindows(); + } + + public static boolean isUsable() { + return usageError == null; + } + + public static int getNumUsedVolumes () { + return yacyUsedVolumes.size(); + } + + public static String getErrorMessage() { + return usageError; + } + + //////////// + // Unix // + //////////// + + private static HashMap dfUnix() { + final HashMap diskUsages = new HashMap(); + try { + final List lines = dfUnixExec(); + nextLine: for (final String line: lines){ + if (line.charAt(0) != '/') continue; + final String[] tokens = line.split(" +", 6); + if (tokens.length < 6) continue; + for (int i = 0; i < yacyUsedVolumes.size(); i++){ + if (yacyUsedVolumes.get(i).equals(tokens[0])) { + final long[] vals = new long[2]; + try { vals[0] = Long.valueOf(tokens[1]); } catch (final NumberFormatException e) { continue nextLine; } + try { vals[1] = Long.valueOf(tokens[3]); } catch (final NumberFormatException e) { continue nextLine; } + vals[0] *= 1024; + vals[1] *= 1024; + diskUsages.put(yacyUsedMountPoints.get(i), vals); + } + } + } + return diskUsages; + } catch (final IOException e) { + usageError = "dfUnix: " + e.getMessage(); + return diskUsages; + } + } + + private static void dfUnixGetVolumes() { + try { + final List lines = dfUnixExec(); + + nextLine: for (final String line: lines){ + if (line.charAt(0) != '/') continue; + final String[] tokens = line.split(" +", 6); + if (tokens.length < 6) continue; + for (int i = 0; i < allMountPoints.size(); i++) { + if (tokens[5].trim().compareTo(allMountPoints.get(i)) > 0) { + allMountPoints.add(i, tokens[5].trim()); + allVolumes.add(i, tokens[0]); + continue nextLine; + } + } + allMountPoints.add(allMountPoints.size(), tokens[5]); + allVolumes.add(allVolumes.size(), tokens[0]); + } + } catch (final IOException e) { + usageError = "error during dfUnixGetVolumes: " + e.getMessage(); + } + } + + private static List dfUnixExec() throws IOException { + + // -k set blocksize to 1024 + // confirmed with tests: + // Linux + // verified with man pages or other docs: + // AIX, BS2000, *BSD, HP-UX, IRIX, minix, Mac OS X, Solaris, Tru64, UNICOS + + // -l list local filesystems only + // confirmed with tests: + // Linux + // verified with man pages or other docs: + // AIX, BS2000, *BSD, HP-UX, IRIX, minix, Mac OS X, Solaris, UNICOS + + // please report all successes or fails for non-confirmed systems to + // detlef!reichl()gmx!org. Thanks! + + final List processArgs = new ArrayList(); + processArgs.add("df"); + processArgs.add("-k"); + // Some systems need the additional -P parameter to return the data in Posix format. + // Without it the mount point will be in the 7th and not in the 6th column + // On Linux, -P is used to have everything on one line, for lvm or based setup + if (usedOS == AIX || usedOS == BS2000 || usedOS == MINIX || usedOS == UNICOS || usedOS == LINUX) + processArgs.add("-P"); + // Tru64 does not know the -l parameter + // For haiku i didn't found online docs at all; so better exclude it + if (usedOS != TRU64 && usedOS != HAIKU) + processArgs.add("-l"); + + final List lines = ConsoleInterface.getConsoleOutput(processArgs, log); + return lines; + } + + private static void checkVolumesInUseUnix (final String path) { + final File file = new File(path); + final File[] fileList = file.listFiles(); + if (fileList == null) { + // the file is not a directory + return; + } + String base; + String dir; + + for (final File element : fileList) { + if (element.isDirectory()) { + try { + dir = element.getCanonicalPath(); + } catch (final IOException e) { + usageError = "checkVolumesInUseUnix(1): " + e.getMessage(); + break; + } + if (dir.endsWith ("HTCACHE") + || dir.endsWith ("HTDOCS") + || dir.endsWith ("LOCALE") + || dir.endsWith ("RANKING") + || dir.endsWith ("RELEASE") + || dir.endsWith ("collection.0028.commons")) { + checkPathUsageUnix (dir); + } else if (dir != null) { + checkVolumesInUseUnix (dir); + } else { + log.logSevere("directory is null: " + element); + } + } else { + try { + base = element.getCanonicalPath(); + } catch (final IOException e) { + usageError = "checkVolumesInUseUnix(2): " + e.getMessage(); + break; + } + checkPathUsageUnix (base); + } + } + } + + /////////////// + // Windows // + /////////////// + + private static void initWindowsCommandVersion () { + windowsCommand = null; + final String os = System.getProperty("os.name").toLowerCase(); + final String[] oses = {"windows 95", "windows 98", "windows me"}; + + for (final String element : oses) { + if (os.indexOf(element) >= 0){ + windowsCommand = "command.com"; + break; + } + } + if (windowsCommand == null) + windowsCommand = "cmd.exe"; + } + + private static void checkStartVolume() { + final File file = new File("DATA"); + + String path = null; + try { path = file.getCanonicalPath(); } catch (final IOException e) { + usageError = "Cant get DATA directory"; + return; + } + if (path.length() < 6) + return; + yacyUsedVolumes.add(path); + } + + private static HashMap dfWindows() { + final HashMap diskUsages = new HashMap(); + for (int i = 0; i < yacyUsedVolumes.size(); i++){ + final List processArgs = new ArrayList(); + processArgs.add(windowsCommand); + processArgs.add("/c"); + processArgs.add("dir"); + processArgs.add("\"" + yacyUsedVolumes.get(i) + "\""); + + try { + final List lines = ConsoleInterface.getConsoleOutput(processArgs, log); + + String line = ""; + for (int l = lines.size() - 1; l >= 0; l--) { + line = lines.get(l).trim(); + if (line.length() > 0) break; + } + if (line.length() == 0) { + usageError = "unable to get free size of volume " + yacyUsedVolumes.get(i); + return diskUsages; + } + + final String[] tokens = line.trim().split(" ++"); + final long[] vals = new long[2]; + vals[0] = -1; + try { vals[1] = Long.valueOf(tokens[2].replaceAll("[.,]", "")); } catch (final NumberFormatException e) {continue;} + diskUsages.put (yacyUsedVolumes.get(i), vals); + } catch (final IOException e) { + usageError = "dfWindows: " + e.getMessage(); + return diskUsages; + } + + } + return diskUsages; + } + + ///////////// + // common // + ///////////// + + private static int getOS() { + final String os = System.getProperty("os.name").toLowerCase(); + for (int i = 0; i < OSname.length; i++) + { + if (os.indexOf(OSname[i]) >= 0) + return i; + } + usageError = "unknown operating system (" + System.getProperty("os.name") + ")"; + return -1; + } + + private static void checkMappedSubDirs (final ArrayList pathsToCheck) { + for (final String path : pathsToCheck) { + if (usedOS <= UNIX_END) + checkPathUsageUnix (path); + else + checkPathUsageWindows (path); + } + } + + private static void checkPathUsageUnix (final String path) { + for (int i = 0; i < allMountPoints.size(); i++){ + if (path.startsWith (allMountPoints.get(i))) { + usedVolumes.set(i, true); + return; + } + } + } + + private static void checkPathUsageWindows(final String path) { + // we would need to ask every path by "dir" as asking the root is not hardlink-proof: + // yacyUsedVolumes.add(path); + return; + /* + int index = -1; + final String sub = path.substring(0, 1); // ?? nur ein character? + try { + index = yacyUsedVolumes.indexOf(sub); + } catch (final IndexOutOfBoundsException e) { + usageError = "internal error while checking used windows volumes"; + return; + } + if (index < 0) + yacyUsedVolumes.add(sub); + */ + } + +} +