|
From: <chr...@us...> - 2009-04-30 03:13:39
|
Revision: 5368
http://jnode.svn.sourceforge.net/jnode/?rev=5368&view=rev
Author: chrisboertien
Date: 2009-04-30 03:13:37 +0000 (Thu, 30 Apr 2009)
Log Message:
-----------
Implemented -n/-b/-s/-E flags for cat
Signed-off-by: chrisboertien <chr...@gm...>
Modified Paths:
--------------
trunk/cli/descriptors/org.jnode.command.file.xml
trunk/cli/src/commands/org/jnode/command/file/CatCommand.java
Modified: trunk/cli/descriptors/org.jnode.command.file.xml
===================================================================
--- trunk/cli/descriptors/org.jnode.command.file.xml 2009-04-29 22:41:40 UTC (rev 5367)
+++ trunk/cli/descriptors/org.jnode.command.file.xml 2009-04-30 03:13:37 UTC (rev 5368)
@@ -43,21 +43,28 @@
<alias name="tail" class="org.jnode.command.file.TailCommand"/>
<alias name="touch" class="org.jnode.command.file.TouchCommand"/>
<alias name="wc" class="org.jnode.command.file.WcCommand"/>
- <!-- can't find org.jnode.command.file.WcCommand -->
</extension>
<extension point="org.jnode.shell.syntaxes">
<syntax alias="cat">
<empty description="copy standard input to standard output"/>
+ <sequence description="concatenate files to standard output">
+ <optionSet>
+ <option argLabel="num-nonblank" shortName="b" longName="number-nonblank"/>
+ <option argLabel="num" shortName="n" longName="number"/>
+ <option argLabel="squeeze" shortName="s" longName="sqeeze-blank"/>
+ <option argLabel="show-ends" shortName="E" longName="show-ends"/>
+ </optionSet>
+ <repeat minCount="1">
+ <argument argLabel="file"/>
+ </repeat>
+ </sequence>
<sequence description="fetch and concatenate urls to standard output">
<option argLabel="urls" shortName="u" longName="urls"/>
<repeat minCount="1">
<argument argLabel="url"/>
</repeat>
</sequence>
- <repeat minCount="1" description="concatenate files to standard output">
- <argument argLabel="file"/>
- </repeat>
</syntax>
<syntax alias="cd">
<empty description="change the current directory to the 'user.home' directory"/>
@@ -105,7 +112,7 @@
<argument argLabel="directory" description="directory to start printing sizes recursively"/>
</repeat>
<optionSet>
- <option argLabel="sum" shortName="s" longName="summarize"/>
+ <option argLabel="sum" shortName="s" longName="summarize"/>
<option argLabel="all" shortName="a" longName="all"/>
<option argLabel="human-readable" shortName="h" longName="human-readable"/>
</optionSet>
Modified: trunk/cli/src/commands/org/jnode/command/file/CatCommand.java
===================================================================
--- trunk/cli/src/commands/org/jnode/command/file/CatCommand.java 2009-04-29 22:41:40 UTC (rev 5367)
+++ trunk/cli/src/commands/org/jnode/command/file/CatCommand.java 2009-04-30 03:13:37 UTC (rev 5368)
@@ -20,15 +20,18 @@
package org.jnode.command.file;
+import java.io.BufferedReader;
import java.io.File;
-import java.io.FileInputStream;
import java.io.FileNotFoundException;
+import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
+import java.io.Reader;
import java.net.URL;
+import org.jnode.command.util.IOUtils;
import org.jnode.shell.AbstractCommand;
import org.jnode.shell.syntax.Argument;
import org.jnode.shell.syntax.FileArgument;
@@ -53,115 +56,240 @@
private static final String help_file = "the files to be concatenated";
private static final String help_url = "the urls to be concatenated";
private static final String help_urls = "If set, arguments will be urls";
+ private static final String help_num_nb = "If set, number nonempty output lines";
+ private static final String help_num = "If set, number all output lines";
+ private static final String help_ends = "If set, print a $ at the end of each lines";
+ private static final String help_squeeze = "If set, supress printing of sequential blank lines";
private static final String help_super = "Concatenate the contents of files, urls or standard input";
private static final String err_url = "Cannot fetch %s: %s%n";
- private static final String err_file = "Cannot open %s: %s%n";
+ private static final String err_file = "Cannot open %sn";
private final FileArgument argFile;
+ private final FlagArgument argNumNB;
+ private final FlagArgument argNumAll;
+ private final FlagArgument argEnds;
+ private final FlagArgument argSqueeze;
+
private final URLArgument argUrl;
private final FlagArgument argUrls;
private PrintWriter err;
+ private PrintWriter out;
+ private Reader in;
+ private InputStream stdin;
+ private OutputStream stdout;
+ private File[] files;
+ private String end;
+ private int rc = 0;
+ private boolean squeeze;
+ private boolean numAll;
+ private boolean numNB;
+ private boolean useStreams;
public CatCommand() {
super(help_super);
- argFile = new FileArgument("file", Argument.OPTIONAL | Argument.MULTIPLE | Argument.EXISTING, help_file);
- argUrl = new URLArgument("url", Argument.OPTIONAL | Argument.MULTIPLE | Argument.EXISTING, help_url);
+ int fileFlags = Argument.MULTIPLE | Argument.EXISTING | FileArgument.HYPHEN_IS_SPECIAL;
+ argFile = new FileArgument("file", fileFlags, help_file);
+ argNumNB = new FlagArgument("num-nonblank", 0, help_num_nb);
+ argNumAll = new FlagArgument("num", 0, help_num);
+ argEnds = new FlagArgument("show-ends", 0, help_ends);
+ argSqueeze = new FlagArgument("squeeze", 0, help_squeeze);
+ registerArguments(argFile, argNumNB, argNumAll, argEnds, argSqueeze);
+
+ argUrl = new URLArgument("url", Argument.MULTIPLE | Argument.EXISTING, help_url);
argUrls = new FlagArgument("urls", Argument.OPTIONAL, help_urls);
- registerArguments(argFile, argUrl, argUrls);
+ registerArguments(argUrl, argUrls);
}
-
+
private static final int BUFFER_SIZE = 8192;
-
-
+
public static void main(String[] args) throws Exception {
new CatCommand().execute(args);
}
public void execute() throws IOException {
- this.err = getError().getPrintWriter();
- OutputStream out = getOutput().getOutputStream();
- File[] files = argFile.getValues();
- URL[] urls = argUrl.getValues();
+ in = getInput().getReader();
+ stdin = getInput().getInputStream();
+ out = getOutput().getPrintWriter();
+ stdout = getOutput().getOutputStream();
+ err = getError().getPrintWriter();
- boolean ok = true;
+ parseOptions();
+
+ if (files != null && files.length > 0) {
+ handleFiles();
+ out.flush();
+ exit(rc);
+ }
+
+ // FIXME remove this url code once wget is more complete
+ URL[] urls = argUrl.getValues();
if (urls != null && urls.length > 0) {
+ byte[] buffer = new byte[BUFFER_SIZE];
for (URL url : urls) {
InputStream is = null;
try {
is = url.openStream();
} catch (IOException ex) {
err.format(err_url, url, ex.getLocalizedMessage());
- ok = false;
+ rc = 1;
}
if (is != null) {
try {
- process(is, out);
+ IOUtils.copyStream(is, stdout, buffer);
} finally {
- try {
- is.close();
- } catch (IOException ex) {
- /* ignore */
- }
+ IOUtils.close(is);
}
}
}
- } else if (files != null && files.length > 0) {
- for (File file : files) {
- InputStream is = null;
- try {
- is = openFile(file);
- if (is == null) {
- ok = false;
+ out.flush();
+ exit(rc);
+ }
+
+ // should not reach this
+ throw new IllegalStateException("Nothing to process");
+ }
+
+ private boolean handleFiles() {
+ InputStream in = null;
+ BufferedReader reader = null;
+ byte[] buffer = new byte[BUFFER_SIZE];
+ boolean ok = true;
+
+ for (File file : files) {
+ try {
+ if (useStreams) {
+ if ((in = openFileStream(file)) != null) {
+ IOUtils.copyStream(in, stdout, buffer);
} else {
- process(is, out);
+ rc = 1;
}
- } finally {
- if (is != null) {
- try {
- is.close();
- } catch (IOException ex) {
- /* ignore */
- }
+ } else {
+ if ((reader = openFileReader(file)) != null) {
+ processReader(reader);
+ } else {
+ rc = 1;
}
}
+ } catch (IOException e) {
+ rc = 1;
+ } finally {
+ IOUtils.close(in, reader);
}
- } else {
- process(getInput().getInputStream(), out);
}
- out.flush();
- if (!ok) {
- exit(1);
- }
+
+ return ok;
}
-
+
/**
- * Copy all of stream 'in' to stream 'out'
- * @param in
- * @param out
- * @throws IOException
+ * Process the input through a BufferedReader.
+ *
+ * Instead of doing a straight stream->stream copy, we process line by line
+ * in order to do some per-line editing before we send to stdout.
*/
- private void process(InputStream in, OutputStream out) throws IOException {
- int len;
- final byte[] buf = new byte[BUFFER_SIZE];
- while ((len = in.read(buf)) > 0) {
- out.write(buf, 0, len);
+ private void processReader(BufferedReader reader) throws IOException {
+ String line;
+ boolean haveBlank = false;
+ int lineCount = 0;
+
+ while ((line = reader.readLine()) != null) {
+ if (line.length() == 0) {
+ if (!haveBlank) {
+ haveBlank = true;
+ } else if (squeeze) {
+ continue;
+ }
+ } else {
+ haveBlank = false;
+ }
+
+ if (numAll) {
+ println(line, ++lineCount);
+ } else if (numNB) {
+ println(line, (haveBlank ? -1 : ++lineCount));
+ } else {
+ println(line, 0);
+ }
}
}
/**
- * Attempt to open a file, writing an error message on failure.
+ * Attempt to open a file, writing an error message on failure. If the file
+ * is '-', return stdin.
+ *
* @param fname the filename of the file to be opened
* @return An open stream, or <code>null</code>.
- * @throws FileNotFoundException
*/
- private InputStream openFile(File file) throws FileNotFoundException {
- try {
- return new FileInputStream(file);
- } catch (IOException ex) {
- err.format(err_file, file, ex.getLocalizedMessage());
- return null;
+ private InputStream openFileStream(File file) {
+ InputStream ret = null;
+
+ if (file.getName().equals("-")) {
+ ret = stdin;
+ } else {
+ ret = IOUtils.openInputStream(file, true, BUFFER_SIZE);
+ if (ret == null) {
+ err.format(err_file, file);
+ }
}
+
+ return ret;
}
-
+
+ private BufferedReader openFileReader(File file) {
+ BufferedReader ret = null;
+
+ if (file.getName().equals("-")) {
+ ret = new BufferedReader(in, BUFFER_SIZE);
+ } else {
+ try {
+ ret = new BufferedReader(new FileReader(file), BUFFER_SIZE);
+ } catch (FileNotFoundException e) {
+ err.format(err_file, file);
+ }
+ }
+
+ return ret;
+ }
+
+ private void parseOptions() {
+ files = argFile.getValues();
+
+ if (files == null || files.length == 0) {
+ files = new File[] {new File("-")};
+ }
+
+ useStreams = true;
+
+ if (argNumNB.isSet()) {
+ numNB = true;
+ useStreams = false;
+ } else if (argNumAll.isSet()) {
+ numAll = true;
+ useStreams = false;
+ }
+
+ if (argEnds.isSet()) {
+ end = "$";
+ useStreams = false;
+ } else {
+ end = "";
+ }
+
+ if (argSqueeze.isSet()) {
+ squeeze = true;
+ useStreams = false;
+ }
+ }
+
+ private void println(String s, int line) {
+ if (numNB || numAll) {
+ if (line == -1) {
+ out.format(" %s%s%n", s, end);
+ } else {
+ out.format("%6d %s%s%n", line, s, end);
+ }
+ } else {
+ out.format("%s%s%n", s, end);
+ }
+ }
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <chr...@us...> - 2009-05-01 00:27:44
|
Revision: 5374
http://jnode.svn.sourceforge.net/jnode/?rev=5374&view=rev
Author: chrisboertien
Date: 2009-05-01 00:27:40 +0000 (Fri, 01 May 2009)
Log Message:
-----------
Rewrite of rm/del to better match the POSIX spec
Signed-off-by: chrisboertien <chr...@gm...>
Modified Paths:
--------------
trunk/cli/descriptors/org.jnode.command.file.xml
trunk/cli/src/commands/org/jnode/command/file/DeleteCommand.java
trunk/cli/src/commands/org/jnode/command/util/IOUtils.java
Modified: trunk/cli/descriptors/org.jnode.command.file.xml
===================================================================
--- trunk/cli/descriptors/org.jnode.command.file.xml 2009-04-30 14:11:06 UTC (rev 5373)
+++ trunk/cli/descriptors/org.jnode.command.file.xml 2009-05-01 00:27:40 UTC (rev 5374)
@@ -92,6 +92,7 @@
<option argLabel="force" shortName="f" longName="force" />
<option argLabel="interactive" shortName="i" longName="interactive" />
<option argLabel="verbose" shortName="v" longName="verbose" />
+ <option argLabel="one-fs" longName="one-file-system"/>
</optionSet>
<repeat minCount="1">
<argument argLabel="paths"/>
Modified: trunk/cli/src/commands/org/jnode/command/file/DeleteCommand.java
===================================================================
--- trunk/cli/src/commands/org/jnode/command/file/DeleteCommand.java 2009-04-30 14:11:06 UTC (rev 5373)
+++ trunk/cli/src/commands/org/jnode/command/file/DeleteCommand.java 2009-05-01 00:27:40 UTC (rev 5374)
@@ -27,13 +27,13 @@
import javax.naming.NameNotFoundException;
+import org.jnode.command.util.IOUtils;
import org.jnode.fs.service.FileSystemService;
import org.jnode.naming.InitialNaming;
import org.jnode.shell.AbstractCommand;
import org.jnode.shell.syntax.Argument;
import org.jnode.shell.syntax.FileArgument;
import org.jnode.shell.syntax.FlagArgument;
-
/**
* Delete a file or a empty directory
*
@@ -42,6 +42,8 @@
* @author Levente S\u00e1ntha
* @author Martin Husted Hartvig (hagar at jnode.org)
* @author cr...@jn...
+ * @author chris boertien
+ * @see {@link http://www.opengroup.org/onlinepubs/009695399/utilities/rm.html}
*/
public class DeleteCommand extends AbstractCommand {
@@ -50,30 +52,38 @@
private static final String help_force = "ignore non-existant files, never prompt";
private static final String help_interact = "prompt before every delete";
private static final String help_verbose = "give information on what is happening";
+ private static final String help_onefs = "If recursively deleting, do not recurse into directories that reside" +
+ "on a different file system";
private static final String help_super = "Delete files or directories";
- private static final String fmt_not_exist = "'%s' does not exist%n";
- private static final String fmt_is_dir = "Cannot remove '%s': Is a directory%n";
- private static final String fmt_ask_overwrite = "Remove regular file '%s'?";
- private static final String fmt_ask_descend = "Descend into directory '%s'?";
- private static final String fmt_ask_remove = "Remove directory '%s'?";
+ private static final String str_not_exist = "File or Directory does not exist";
+ private static final String str_is_dir = "Is a directory";
+ private static final String str_is_dot = "Directory is '.' or '..'";
+ private static final String str_is_mount = "Directory is a mount point";
+ private static final String str_not_empty = "Directory is not empty";
+ private static final String fmt_skip = "Skipping '%s' %s%n";
private static final String fmt_removed_file = "Removed '%s'";
private static final String fmt_removed_dir = "Removed directory '%s'";
private static final String fmt_not_removed = "'%s' was not removed";
+ private static final String fmt_ask_remove_file = "Remove regular file '%s'? [yes/no] ";
+ private static final String fmt_ask_descend = "Descend into directory '%s'? [yes/no]";
+ private static final String fmt_ask_remove_dir = "Remove directory '%s'? [yes/no]";
private final FileArgument argPaths;
private final FlagArgument flagRecurse;
private final FlagArgument flagForce;
private final FlagArgument flagInteract;
private final FlagArgument flagVerbose;
+ private final FlagArgument flagOneFS;
private FileSystemService fss;
+ private PrintWriter err;
+ private PrintWriter out;
+ private Reader in;
private boolean recursive;
private boolean force;
private boolean interactive;
private boolean verbose;
- private PrintWriter err;
- private PrintWriter out;
- private Reader in;
+ private boolean onefs;
public DeleteCommand() {
super(help_super);
@@ -82,7 +92,8 @@
flagForce = new FlagArgument("force", Argument.OPTIONAL, help_force);
flagInteract = new FlagArgument("interactive", Argument.OPTIONAL, help_interact);
flagVerbose = new FlagArgument("verbose", Argument.OPTIONAL, help_verbose);
- registerArguments(argPaths, flagRecurse, flagForce, flagInteract, flagVerbose);
+ flagOneFS = new FlagArgument("onefs", 0, help_onefs);
+ registerArguments(argPaths, flagRecurse, flagForce, flagInteract, flagVerbose, flagOneFS);
}
public static void main(String[] args) throws Exception {
@@ -97,6 +108,7 @@
force = flagForce.isSet();
interactive = flagInteract.isSet();
verbose = flagVerbose.isSet();
+ onefs = flagOneFS.isSet();
File[] paths = argPaths.getValues();
err = getError().getPrintWriter();
@@ -113,72 +125,134 @@
}
private boolean deleteFile(File file) {
+ // We have to be careful about how we handle race conditions, especially
+ // considering the depth-first nature of recursive file deletion. If this
+ // method gets called on a file, and the file does not exist, then we assume
+ // some other process has beat us to it. The command line only allows existing
+ // files to be input.
+
+ boolean deleteOk;
+ boolean prompt;
+
if (!file.exists()) {
- if (!force) {
- err.format(fmt_not_exist, file);
- }
- return false;
+ // someone beat us to the delete() call, return gracefully.
+ return skip(str_not_exist, file) || true;
}
- if (file.isDirectory() && !recursive) {
- err.format(fmt_is_dir, file);
- return false;
- }
- if (file.isFile() && interactive && !prompt_yn(String.format(fmt_ask_overwrite, file))) {
- return false;
- }
- boolean deleteOk = true;
-
- // FIXME the following doesn't handle mounted filesystems correctly (I think).
- // Recursive delete should not recurse >>into<< a mounted filesystem, but should
- // give an error message and then refuse to delete the parent directory because
- // it cannot be emptied.
- if (file.isDirectory() && !fss.isMount(file.getAbsolutePath())) {
- if (interactive && !prompt_yn(String.format(fmt_ask_descend, file))) {
- return false;
+ // A note about 'interactive' mode. It is _not_ an error
+ // if stdin is not a tty. It is possible to send responses
+ // via a pipe. This is why we only check for a tty stdin
+ // if interactive was not set.
+ prompt = (!force && (interactive || (!isWriteable(file) && getInput().isTTY())));
+
+ if (file.isDirectory()) {
+ // This is written to match the POSIX behavior in rm Description Section 2
+ if (!recursive) {
+ return skip(str_is_dir, file);
}
+ if (file.getName().equals("..") || file.getName().equals(".")) {
+ return skip(str_is_dot, file);
+ }
+ if (prompt) {
+ if (!prompt(String.format(fmt_ask_descend, file))) {
+ return skip("", file);
+ }
+ }
+ // According to the POSIX spec, there is no provision for recursive deletion
+ // that spans into another file system. The GNU rm utility provides the ability
+ // to stop recursive deleting from entering another file system. If that flag
+ // is not set, then we will continue to delete files within that file system
+ // but the deleting of the directory that is the mount will probably fail because
+ // it is in use.
+ if (!checkMount(file)) {
+ return skip(str_is_mount, file);
+ }
+ deleteOk = true;
for (File f : file.listFiles()) {
- final String name = f.getName();
-
+ String name = f.getName();
if (!name.equals(".") && !name.equals("..")) {
deleteOk &= deleteFile(f);
}
}
- if (deleteOk && interactive && !prompt_yn(String.format(fmt_ask_remove, file))) {
- return false;
+ if (!deleteOk) {
+ return skip(str_not_empty, file);
}
- }
-
- if (deleteOk) {
- // FIXME ... this is going to attempt to delete "directories" that are
- // mounted filesystems. Is this right? What will it do?
- // FIXME ... this does not report the reason that the delete failed.
- // How should we do that?
- if (verbose) {
- if (file.isFile()) out.format(fmt_removed_file, file);
- if (file.isDirectory()) out.format(fmt_removed_dir, file);
+ if (prompt) {
+ if (!prompt(String.format(fmt_ask_remove_dir, file))) {
+ return skip("", file);
+ }
}
- deleteOk = file.delete();
- if (!deleteOk) {
- err.format(fmt_not_removed, file);
+ return rmdir(file);
+ } else {
+ if (prompt) {
+ if (!prompt(String.format(fmt_ask_remove_file, file))) {
+ return skip("", file);
+ }
}
+ return unlink(file);
}
- return deleteOk;
}
- private boolean prompt_yn(String s) {
- int choice;
- for (;;) {
- out.print(s + " [y/n]");
+ private boolean prompt(String s) {
+ return IOUtils.promptYesOrNo(in, out, s);
+ }
+
+ private boolean checkMount(File file) {
+ // This is wrong, as the directory might have been given on the
+ // command line, which means regardless of the value of onefs, we will continue.
+ // The proper way would be to check that this directory resides on the same file
+ // system as the directory given on the command line.
+ if (onefs) {
try {
- choice = in.read();
- } catch (IOException _) {
- choice = 0;
+ if (fss.isMount(file.getCanonicalPath())) {
+ return false;
+ }
+ } catch (IOException e) {
+ return false;
}
- out.println();
- if (choice == 'y' || choice == 'n') break;
}
-
- return choice == 'y';
+ return true;
}
+
+ private boolean isWriteable(File file) {
+ try {
+ return file.canWrite();
+ } catch (SecurityException e) {
+ return false;
+ }
+ }
+
+ private boolean rmdir(File file) {
+ if (!file.delete()) {
+ return error(fmt_not_removed, file);
+ }
+ if (verbose) {
+ out.format(fmt_removed_dir, file);
+ }
+ return true;
+ }
+
+ private boolean unlink(File file) {
+ if (!file.delete()) {
+ return error(fmt_not_removed, file);
+ }
+ if (verbose) {
+ out.format(fmt_removed_file, file);
+ }
+ return true;
+ }
+
+ private boolean skip(String msg, File file) {
+ if (!force) {
+ err.format(fmt_skip, file, msg);
+ }
+ return false;
+ }
+
+ private boolean error(String msg, Object... args) {
+ if (verbose) {
+ err.format(msg, args);
+ }
+ return false;
+ }
}
Modified: trunk/cli/src/commands/org/jnode/command/util/IOUtils.java
===================================================================
--- trunk/cli/src/commands/org/jnode/command/util/IOUtils.java 2009-04-30 14:11:06 UTC (rev 5373)
+++ trunk/cli/src/commands/org/jnode/command/util/IOUtils.java 2009-05-01 00:27:40 UTC (rev 5374)
@@ -462,8 +462,6 @@
input = reader.readLine();
} catch (IOException e) {
return null;
- } finally {
- out.println();
}
return input;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <chr...@us...> - 2009-05-01 07:09:30
|
Revision: 5376
http://jnode.svn.sourceforge.net/jnode/?rev=5376&view=rev
Author: chrisboertien
Date: 2009-05-01 07:09:28 +0000 (Fri, 01 May 2009)
Log Message:
-----------
Improved df impl
Support for -h/-H/-B/-k switches
Signed-off-by: chrisboertien <chr...@gm...>
Modified Paths:
--------------
trunk/cli/descriptors/org.jnode.command.file.xml
trunk/cli/src/commands/org/jnode/command/file/DFCommand.java
Modified: trunk/cli/descriptors/org.jnode.command.file.xml
===================================================================
--- trunk/cli/descriptors/org.jnode.command.file.xml 2009-05-01 06:59:13 UTC (rev 5375)
+++ trunk/cli/descriptors/org.jnode.command.file.xml 2009-05-01 07:09:28 UTC (rev 5376)
@@ -100,8 +100,31 @@
</sequence>
</syntax>
<syntax alias="df">
- <empty description="display disk usage for all filesystems"/>
- <argument argLabel="device" description="display disk usage for the filesystem on a device"/>
+ <sequence description="display disk usage for file systems">
+ <optionSet>
+ <option argLabel="human-read-bin" shortName="h" longName="human-readable"/>
+ <option argLabel="human-read-dec" shortName="H" longName="si"/>
+ <option argLabel="show-all" shortName="a" longName="all"/>
+ <option argLabel="block-size" shortName="B" longName="block-size"/>
+ <option argLabel="block-size-1k" shortName="k"/>
+ <!--
+ <option argLabel="posix" shortName="P" longName="portability"/>
+ <option argLabel="inodes" shortName="i" longName="inodes"/>
+ <option argLabel="local" shortName="l" longName="local"/>
+ <option argLabel="sync" longName="sync"/>
+ <option argLabel="no-sync" longName="no-sync"/>
+ <option argLabel="fs-type" shortName="t" longName="type"/>
+ <option argLabel="print-type" shortName="T" longName="print-type"/>
+ <option argLabel="ex-type" shortName="x" longName="exclude-type"/>
+ -->
+ </optionSet>
+ <optional>
+ <alternatives>
+ <argument argLabel="path"/>
+ <argument argLabel="device"/>
+ </alternatives>
+ </optional>
+ </sequence>
</syntax>
<syntax alias="dir">
<empty description="list the current directory"/>
@@ -231,7 +254,9 @@
<optional eager="true">
<option argLabel="recursive" shortName="r" longName="recursive"/>
</optional>
- <repeat minCount="1"><argument argLabel="paths"/></repeat>
+ <repeat minCount="1">
+ <argument argLabel="paths"/>
+ </repeat>
</sequence>
</syntax>
<syntax alias="mkdir">
@@ -297,5 +322,14 @@
<permission class="java.io.RuntimePermission" name="writeFileDescriptor"/>
<permission class="java.util.PropertyPermission" name="user.dir" actions="read,write"/>
<permission class="java.util.PropertyPermission" name="user.home" actions="read,write"/>
+ <permission class="java.lang.RuntimePermission" name="getenv.*" actions="read"/>
+ <!--
+ <permission class="java.lang.RuntimePermission" name="getenv.POSIXLY_CORRECT" actions="read"/>
+ <permission class="java.lang.RuntimePermission" name="getenv.DF_BLOCK_SIZE" actions="read"/>
+ <permission class="java.lang.RuntimePermission" name="genenv.DU_BLOCK_SIZE" actions="read"/>
+ <permission class="java.lang.RuntimePermission" name="getenv.LS_BLOCK_SIZE" actions="read"/>
+ <permission class="java.lang.RuntimePermission" name="getenv.BLOCK_SIZE" actions="read"/>
+ <permission class="java.lang.RuntimePermission" name="getenv.BLOCKSIZE" actions="read"/>
+ -->
</extension>
</plugin>
Modified: trunk/cli/src/commands/org/jnode/command/file/DFCommand.java
===================================================================
--- trunk/cli/src/commands/org/jnode/command/file/DFCommand.java 2009-05-01 06:59:13 UTC (rev 5375)
+++ trunk/cli/src/commands/org/jnode/command/file/DFCommand.java 2009-05-01 07:09:28 UTC (rev 5376)
@@ -26,6 +26,8 @@
import javax.naming.NameNotFoundException;
+import java.io.File;
+
import org.jnode.driver.Device;
import org.jnode.driver.DeviceManager;
import org.jnode.fs.FileSystem;
@@ -34,6 +36,10 @@
import org.jnode.shell.AbstractCommand;
import org.jnode.shell.syntax.Argument;
import org.jnode.shell.syntax.DeviceArgument;
+import org.jnode.shell.syntax.FileArgument;
+import org.jnode.shell.syntax.FlagArgument;
+import org.jnode.shell.syntax.IntegerArgument;
+import org.jnode.util.NumberUtils;
/**
* The DF command prints disk usage information for devices with filesystems.
@@ -41,13 +47,21 @@
* @author ga...@jn...
* @author cr...@jn...
* @author Levente S\u00e1ntha
+ * @author chris boertien
*/
public class DFCommand extends AbstractCommand {
private static final String help_device = "The device for which disk usage information should be displayed";
+ private static final String help_path = "Display disk usage info for the file system that contains this path";
+ private static final String help_read_dec = "Print output in human readable decimal form (1000)";
+ private static final String help_read_bin = "Print output in human readable binary form (1024)";
+ private static final String help_all = "Show all file systems, even pseudo file systems";
+ private static final String help_block_1k = "Same as -B 1024";
+ private static final String help_block = "Print output with a specified block size";
private static final String help_super = "Print file system usage information";
private static final String str_id = "ID";
private static final String str_size = "Size";
+ private static final String str_blocks = "blocks";
private static final String str_used = "Used";
private static final String str_free = "Free";
private static final String str_mount = "Mount";
@@ -55,44 +69,110 @@
private static final String str_unknown = "unknown";
private static final String err_get_info = "\tError getting disk usage information for %s on %s : %s%n";
+ private static final int OUT_BINARY = 1;
+ private static final int OUT_DECIMAL = 2;
+ private static final int OUT_BLOCKS = 3;
+
+ private static final int DEFAULT_BLOCK_SIZE = 1024;
+
private final DeviceArgument argDevice;
-
+ private final FileArgument argPath;
+ private final FlagArgument argReadDec;
+ private final FlagArgument argReadBin;
+ private final FlagArgument argAll;
+ private final FlagArgument argBlock1k;
+ private final IntegerArgument argBlock;
+
+ private StringBuilder line;
+ private FileSystemService fss;
+ private DeviceManager dm;
+ private Map<String, String> mountPoints;
+ private PrintWriter out;
+ private int outputType;
+ private int blockSize;
+ private boolean all;
+
public DFCommand() {
super(help_super);
- argDevice = new DeviceArgument("device", Argument.OPTIONAL | Argument.EXISTING, help_device);
- registerArguments(argDevice);
+ argDevice = new DeviceArgument("device", Argument.EXISTING, help_device);
+ argPath = new FileArgument("path", Argument.EXISTING, help_path);
+ argReadDec = new FlagArgument("human-read-dec", 0, help_read_dec);
+ argReadBin = new FlagArgument("human-read-bin", 0, help_read_bin);
+ argAll = new FlagArgument("show-all", 0, help_all);
+ argBlock1k = new FlagArgument("block-size-1k", 0, help_block_1k);
+ argBlock = new IntegerArgument("block-size", 0, help_block);
+ registerArguments(argDevice, argPath, argReadDec, argReadBin, argAll, argBlock1k, argBlock);
}
-
- public void execute() throws NameNotFoundException {
- final FileSystemService fss = InitialNaming.lookup(FileSystemService.NAME);
- final Map<String, String> mountPoints = fss.getDeviceMountPoints();
- PrintWriter out = getOutput().getPrintWriter(false);
- format(out, str_id, true);
- format(out, str_size, false);
- format(out, str_used, false);
- format(out, str_free, false);
- out.println(str_mount);
- out.println();
- if (argDevice.isSet()) {
- final Device dev = argDevice.getValue();
- FileSystem<?> fs = fss.getFileSystem(dev);
- if (fs == null) {
- out.println(str_no_fs);
- } else {
- displayInfo(out, dev, fs, mountPoints.get(fs.getDevice().getId()));
- }
+
+ public void execute() throws NameNotFoundException, IOException {
+ parseOptions();
+ fss = InitialNaming.lookup(FileSystemService.NAME);
+ dm = InitialNaming.lookup(DeviceManager.NAME);
+ mountPoints = fss.getDeviceMountPoints();
+ out = getOutput().getPrintWriter(true);
+ line = new StringBuilder();
+
+ Device device = null;
+
+ printHeader();
+
+ if (argPath.isSet()) {
+ device = getDeviceForPath(argPath.getValue());
+ } else if (argDevice.isSet()) {
+ device = argDevice.getValue();
} else {
- final DeviceManager dm = InitialNaming.lookup(DeviceManager.NAME);
for (Device dev : dm.getDevices()) {
FileSystem<?> fs = fss.getFileSystem(dev);
if (fs != null) {
displayInfo(out, dev, fs, mountPoints.get(fs.getDevice().getId()));
}
}
+ out.flush();
+ exit(0);
}
- out.flush();
+ if (device != null) {
+ FileSystem<?> fs = fss.getFileSystem(device);
+ if (fs == null) {
+ out.println(str_no_fs);
+ } else {
+ displayInfo(out, device, fs, mountPoints.get(fs.getDevice().getId()));
+ }
+ out.flush();
+ exit(0);
+ }
}
-
+
+ private Device getDeviceForPath(File file) throws IOException {
+ String path = file.getCanonicalPath();
+ String mp = null;
+ for (String mountPoint : fss.getMountPoints().keySet()) {
+ if (path.startsWith(mountPoint)) {
+ if (mp != null) {
+ if (!mp.startsWith(mountPoint)) {
+ continue;
+ }
+ }
+ mp = mountPoint;
+ }
+ }
+ if (mp == null) {
+ throw new AssertionError("No fs device for " + path);
+ }
+ return fss.getMountPoints().get(mp).getDevice();
+ }
+
+ private void printHeader() {
+ format(out, str_id, true);
+ if (outputType == OUT_BLOCKS) {
+ format(out, String.format("%s-%s", NumberUtils.toBinaryByte(blockSize), str_blocks), false);
+ } else {
+ format(out, str_size, false);
+ }
+ format(out, str_used, false);
+ format(out, str_free, false);
+ out.println(str_mount);
+ }
+
/**
* @param out
* @param dev
@@ -101,27 +181,27 @@
*/
private void displayInfo(PrintWriter out, Device dev, FileSystem<?> fs, String mountPoint) {
try {
-
String str = dev.getId();
+ long total = fs.getTotalSpace();
+ long free = fs.getFreeSpace();
+
format(out, str, true);
-
- final long total = fs.getTotalSpace();
- str = total < 0 ? str_unknown : String.valueOf(total);
+
+ str = total < 0 ? str_unknown : valueOf(total, true);
format(out, str, false);
-
- final long free = fs.getFreeSpace();
- str = total < 0 ? str_unknown : String.valueOf(total - free);
+
+ str = total < 0 ? str_unknown : valueOf(total - free, true);
format(out, str, false);
-
- str = free < 0 ? str_unknown : String.valueOf(free);
+
+ str = free < 0 ? str_unknown : valueOf(free, false);
format(out, str, false);
-
+
out.println(mountPoint);
} catch (IOException ex) {
out.format(err_get_info, mountPoint, dev.getId(), ex.getLocalizedMessage());
}
}
-
+
private void format(PrintWriter out, String str, boolean left) {
int ln;
ln = 15 - str.length();
@@ -138,4 +218,70 @@
}
out.print(' ');
}
+
+ private String valueOf(long size, boolean up) {
+ switch(outputType) {
+ case OUT_DECIMAL :
+ return NumberUtils.toDecimalByte(size, 0);
+ case OUT_BINARY :
+ return NumberUtils.toBinaryByte(size, 0);
+ case OUT_BLOCKS :
+ return toBlock(size, blockSize, up);
+ default :
+ return String.valueOf(size);
+ }
+ }
+
+ private String toBlock(long size, long blockSize, boolean up) {
+ return String.valueOf(size / blockSize + ((up && ((size % blockSize) > 0)) ? 1 : 0));
+ }
+
+ private void parseOptions() {
+ if (argReadDec.isSet()) {
+ outputType = OUT_DECIMAL;
+ } else if (argReadBin.isSet()) {
+ outputType = OUT_BINARY;
+ } else {
+ outputType = OUT_BLOCKS;
+ }
+
+ all = argAll.isSet();
+
+ if (argBlock1k.isSet()) {
+ blockSize = 1024;
+ } else if (argBlock.isSet()) {
+ blockSize = argBlock.getValue();
+ } else {
+ blockSize = getDefaultBlock();
+ }
+ }
+
+ private int getDefaultBlock() {
+ /* Env vars are broken
+ String DF_BLOCK_SIZE = System.getenv("DF_BLOCK_SIZE");
+ String BLOCK_SIZE = System.getenv("BLOCK_SIZE");
+ String BLOCKSIZE = System.getenv("BLOCKSIZE");
+ String POSIXLY_CORRECT = System.getenv("POSIXLY_CORRECT");
+
+ String size = null;
+ if (DF_BLOCK_SIZE != null) {
+ size = DF_BLOCK_SIZE;
+ } else if (BLOCK_SIZE != null) {
+ size = BLOCK_SIZE;
+ } else if (BLOCKSIZE != null) {
+ size = BLOCKSIZE;
+ } else if (POSIXLY_CORRECT != null) {
+ return 512;
+ } else {
+ return DEFAULT_BLOCK_SIZE;
+ }
+
+ try {
+ return Integer.parseInt(size);
+ } catch (NumberFormatException e) {
+ return DEFAULT_BLOCK_SIZE;
+ }
+ */
+ return DEFAULT_BLOCK_SIZE;
+ }
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <chr...@us...> - 2009-05-05 21:20:44
|
Revision: 5427
http://jnode.svn.sourceforge.net/jnode/?rev=5427&view=rev
Author: chrisboertien
Date: 2009-05-05 21:20:25 +0000 (Tue, 05 May 2009)
Log Message:
-----------
New Argument that represents a list of integers and number ranges.
Signed-off-by: chrisboertien <chr...@gm...>
Added Paths:
-----------
trunk/cli/descriptors/org.jnode.command.argument.xml
trunk/cli/src/commands/org/jnode/command/argument/
trunk/cli/src/commands/org/jnode/command/argument/NumberListArgument.java
trunk/cli/src/commands/org/jnode/command/util/NumberRange.java
Added: trunk/cli/descriptors/org.jnode.command.argument.xml
===================================================================
--- trunk/cli/descriptors/org.jnode.command.argument.xml (rev 0)
+++ trunk/cli/descriptors/org.jnode.command.argument.xml 2009-05-05 21:20:25 UTC (rev 5427)
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plugin SYSTEM "jnode.dtd">
+
+<plugin id="org.jnode.command.argument"
+ name="JNode command arguments"
+ version="@VERSION@"
+ provider-name="@PROVIDER@"
+ license-name="lgpl">
+
+ <requires>
+ <import plugin="org.jnode.shell.syntax"/>
+ <import plugin="org.jnode.command.util"/>
+ </requires>
+
+ <runtime>
+ <library name="jnode-cli.jar">
+ <export name="org.jnode.command.argument.*"/>
+ </library>
+ </runtime>
+</plugin>
Added: trunk/cli/src/commands/org/jnode/command/argument/NumberListArgument.java
===================================================================
--- trunk/cli/src/commands/org/jnode/command/argument/NumberListArgument.java (rev 0)
+++ trunk/cli/src/commands/org/jnode/command/argument/NumberListArgument.java 2009-05-05 21:20:25 UTC (rev 5427)
@@ -0,0 +1,193 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2003-2009 JNode.org
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; If not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+package org.jnode.command.argument;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.jnode.command.util.NumberRange;
+import org.jnode.driver.console.CompletionInfo;
+import org.jnode.shell.CommandLine.Token;
+import org.jnode.shell.syntax.CommandSyntaxException;
+import org.jnode.shell.syntax.Argument;
+
+/**
+ * Captures a list of multiple number ranges.
+ *
+ * A number list is represented by a comma delimited list of integers
+ * and ranges. A range is represented by two integers separated by a hyphen.
+ * Either of the integers may be omitted (but not both), to represent a range
+ * that spans from a single point, to the minimum or maximum values of the range.
+ *
+ * In other words, this argument captures the following syntax:
+ * <code>
+ * list ::= range | list,range
+ * range ::= integer | -integer | integer- | integer-integer
+ * <code>
+ * Note that integer is any number in the range 0-Integer.MAX_VALUE, and may be limited
+ * to a smaller range via constructor arguments.
+ *
+ * When a number list has been captured, it may be altered from the form and order
+ * it was found in on the command line. The Command can be certain that the ranges
+ * returned by this argument will have the following properties.
+ *
+ * <ul>
+ * <li>Ranges will never span beyond min/max
+ * <li>Ranges will be in sorted order.
+ * <li>Individual ranges will not overlap, or be sequential. Such ranges will be concatenated
+ * to form a single range. This means that 3-5,4-7 and 3,4,5,6,7 will form the range 3-7.
+ * </ul>
+ *
+ * @author chris boertien
+ */
+public class NumberListArgument extends Argument<NumberRange> {
+
+ private final String listDelim;
+ private final String rangeDelim;
+ private final int min;
+ private final int max;
+
+ public NumberListArgument(String label, int flags, int min, int max, String desc) {
+ super(label, flags | Argument.MULTIPLE, new NumberRange[0], desc);
+ this.rangeDelim = "-";
+ this.listDelim = ",";
+ this.min = min;
+ this.max = max;
+ }
+
+ public NumberListArgument(String label, int flags, String desc) {
+ this(label, flags, Integer.MIN_VALUE + 1, Integer.MAX_VALUE - 1, desc);
+ }
+
+ @Override
+ protected NumberRange doAccept(Token token, int flags) throws CommandSyntaxException {
+ NumberRange[] ranges = parseList(token.text);
+ if (ranges.length == 1) {
+ return ranges[0];
+ }
+
+ Arrays.sort(ranges);
+
+ // concat
+ for (int i = 1; i < ranges.length;) {
+ if (ranges[i - 1].end() >= (ranges[i].start() - 1)) {
+ ranges = concat(ranges, i - 1, i);
+ } else {
+ i++;
+ }
+ }
+ for (int i = 0; i < (ranges.length - 1); i++ ) {
+ values.add(ranges[i]);
+ }
+ return ranges[ranges.length - 1];
+ }
+
+ private NumberRange[] concat(NumberRange[] ranges, int i, int j) {
+ NumberRange[] newRanges = new NumberRange[ranges.length - (j - i)];
+ System.arraycopy(ranges, 0, newRanges, 0, i);
+ if (j < (ranges.length - 1)) {
+ System.arraycopy(ranges, j + 1, newRanges, j, newRanges.length - j);
+ }
+ newRanges[i] = new NumberRange(ranges[i].start(), ranges[j].end(), min - 1, max + 1);
+ return newRanges;
+ }
+
+ private static final boolean debug = false;
+
+ private void error(String s) {
+ if (debug) System.err.println(s);
+ }
+
+ /**
+ * Parse a number list
+ *
+ * list ::= range | list,range
+ */
+ private NumberRange[] parseList(String text) throws CommandSyntaxException {
+ int delimPos = text.indexOf(listDelim);
+ if (delimPos == -1) {
+ return new NumberRange[] { parseRange(text) };
+ } else {
+ String[] rangesText = text.split(listDelim);
+ NumberRange[] ranges = new NumberRange[rangesText.length];
+ for (int i = 0; i < ranges.length; i++) {
+ ranges[i] = parseRange(rangesText[i]);
+ }
+ return ranges;
+ }
+ }
+
+ /**
+ * Parse a number range.
+ *
+ * range ::= integer | -integer | integer- | integer-integer
+ */
+ private NumberRange parseRange(String text) throws CommandSyntaxException {
+ int delimPos = text.indexOf(rangeDelim);
+ int start;
+ int end;
+ if (text.equals(rangeDelim)) {
+ throw new CommandSyntaxException("Invalid number range");
+ }
+ if (delimPos == -1) {
+ // this is ok, as we allow a single integer to represent the range n-n
+ start = end = parseInt(text);
+ } else if (delimPos == 0) {
+ start = min;
+ end = parseInt(text.substring(rangeDelim.length(), text.length()));
+ } else if (delimPos == (text.length() - rangeDelim.length())) {
+ start = parseInt(text.substring(0, delimPos));
+ end = max;
+ } else {
+ start = parseInt(text.substring(0, delimPos));
+ end = parseInt(text.substring(delimPos + rangeDelim.length(), text.length()));
+ }
+ try {
+ return new NumberRange(start, end, min - 1, max + 1);
+ } catch (IllegalArgumentException ex) {
+ throw new CommandSyntaxException("Invalid number range");
+ }
+ }
+
+ private int parseInt(String text) throws CommandSyntaxException {
+ int n;
+ try {
+ n = Integer.parseInt(text);
+ } catch (NumberFormatException ex) {
+ throw new CommandSyntaxException("Invalid number range");
+ }
+ if (n < min || n > max) {
+ throw new CommandSyntaxException("Number out of range");
+ }
+ return n;
+ }
+
+ @Override
+ protected String state() {
+ return "min=" + min + ",max=" + max;
+ }
+
+ @Override
+ protected String argumentKind() {
+ return "number-list";
+ }
+}
Added: trunk/cli/src/commands/org/jnode/command/util/NumberRange.java
===================================================================
--- trunk/cli/src/commands/org/jnode/command/util/NumberRange.java (rev 0)
+++ trunk/cli/src/commands/org/jnode/command/util/NumberRange.java 2009-05-05 21:20:25 UTC (rev 5427)
@@ -0,0 +1,204 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2003-2009 JNode.org
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; If not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+package org.jnode.command.util;
+
+/**
+ * An immutable representation of a sequential number range.
+ *
+ * A number range uses two number of values to denote points of
+ * positive and negative infinity. By default, these values are
+ * Integer.MAX_VALUE and Integer.MIN_VALUE respectively. If start
+ * or end are equal to or beyond the infinity values, then the
+ * range is considered to be infinite in that direction.
+ *
+ * It is worth noting that the Comparable interface is sensitive
+ * to the points of positive and negative infinity. Two number ranges
+ * can have different start and end points and be considered equal if
+ * both ranges are also infinite in that direction.
+ *
+ * @author chris boertien
+ * @see {@link org.jnode.command.argument.NumberRangeArgument}
+ */
+public final class NumberRange implements Comparable<NumberRange> {
+
+ private final int start;
+ private final int end;
+ private final int negativeInfinity;
+ private final int positiveInfinity;
+
+ /**
+ * Creates a number range.
+ *
+ * This number range uses posInf and negInf to denote positive and negative
+ * infinity respectively.
+ *
+ * @param start the start of the range
+ * @param end the end of the range
+ * @param posInf the point of positive infinity
+ * @param negInf the point of negative infinity
+ * @throws IllegalArgumentException if start > end or negInf >= posInf
+ */
+ public NumberRange(int start, int end, int negInf, int posInf) {
+ if (start > end) {
+ throw new IllegalArgumentException("start > end");
+ }
+ if (negInf >= posInf) {
+ throw new IllegalArgumentException("negInf >= posInf");
+ }
+ this.start = start;
+ this.end = end;
+ this.negativeInfinity = negInf;
+ this.positiveInfinity = posInf;
+ }
+
+ /**
+ * Creates a number range.
+ *
+ * This number range uses Integer.MAX_VALUE and Integer.MIN_VALUE to denote
+ * positive and negative infinity respectively.
+ *
+ * @param start the start of the range
+ * @param end the end of the range
+ * @throws IllegalArgumentException if start > end
+ */
+ public NumberRange(int start, int end) {
+ this(start, end, Integer.MIN_VALUE, Integer.MAX_VALUE);
+ }
+
+ /**
+ * Compares this NumberRange to another NumberRange for order.
+ *
+ * NumberRanges are ordered first by their start position, and second
+ * by their end position.
+ *
+ * A NumberRange that is negatively infinite is considered less than one that
+ * is not negatively infinite. Also a NumberRange that is not positively infinite
+ * is considered less than one that is positively infinite.
+ *
+ * @param that the NumberRange to compare this one to
+ * @return -1 if this comes before that, 1 if that comes before this, 0 if they are equal
+ * @see {@link #equals}
+ */
+ public int compareTo(NumberRange that) {
+ if (equals(that)) {
+ return 0;
+ }
+
+ boolean a1 = isStartInfinite();
+ boolean a2 = isEndInfinite();
+ boolean b1 = that.isStartInfinite();
+ boolean b2 = that.isEndInfinite();
+
+ if (a1 ^ b1) {
+ return a1 ? -1 : 1;
+ }
+ if ((a1 && b1) || (start == that.start)) {
+ if (a2 ^ b2) {
+ return a2 ? -1 : 1;
+ }
+ return end - that.end;
+ }
+ return start - that.start;
+ }
+
+ /**
+ * Tests this NumberRange for equivalence to that NumberRange.
+ *
+ * Two NumberRanges are considered equal if:
+ * <ul>
+ * <li>if both are negatively infinite AND both are positively infinite
+ * <li>if both are negatively infinite AND neither are positively infinite AND both have the same end point.
+ * <li>if neither are negatively infinite AND both have the same start point AND both are positvely infinite
+ * <li>if neither are negatively infinite AND both have the same start point AND
+ * neither are positively infinite AND both have the same end point.
+ * </ul>
+ *
+ * @param that the NumberRage to compare with
+ * @return true if both NumberRanges are equal
+ */
+ public boolean equals(NumberRange that) {
+ boolean a1 = isStartInfinite();
+ boolean a2 = isEndInfinite();
+ boolean b1 = that.isStartInfinite();
+ boolean b2 = that.isEndInfinite();
+
+ return ((a1 && b1) || (!(a1 ^ b1) && (start == that.start)))
+ && ((a2 && b2) || (!(a2 ^ b2) && (end == that.end)));
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ if (this == that) {
+ return true;
+ }
+ if (!(that instanceof NumberRange)) {
+ return false;
+ }
+ return equals((NumberRange) that);
+ }
+
+ @Override
+ public String toString() {
+ return start + "-" + end;
+ }
+
+ /**
+ * The starting position of this number range.
+ *
+ * Even if the start value is beyond the negative infinity point
+ * this will still return the value of the start position.
+ *
+ * @return the start
+ */
+ public int start() {
+ return start;
+ }
+
+ /**
+ * The ending position of this number range.
+ *
+ * Even if the end value is beyond the positive infinity point
+ * this will still return the value of the start position.
+ *
+ * @return the end
+ */
+ public int end() {
+ return end;
+ }
+
+ /**
+ * Does this NumberRange represent a range that is positively infinite.
+ *
+ * @return true if the end position is >= positive infinity.
+ */
+ public boolean isEndInfinite() {
+ return end >= positiveInfinity;
+ }
+
+ /**
+ * Does this NumberRange represent a range that is negatively infinite.
+ *
+ * @return true if the start positition is <= negative infinity
+ */
+ public boolean isStartInfinite() {
+ return start <= negativeInfinity;
+ }
+}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <chr...@us...> - 2009-05-05 21:24:13
|
Revision: 5429
http://jnode.svn.sourceforge.net/jnode/?rev=5429&view=rev
Author: chrisboertien
Date: 2009-05-05 21:24:04 +0000 (Tue, 05 May 2009)
Log Message:
-----------
Blackbox tests for cut and the new argument.
Signed-off-by: chrisboertien <chr...@gm...>
Modified Paths:
--------------
trunk/cli/build-tests.xml
trunk/cli/src/test/org/jnode/test/command/all-tests.xml
trunk/cli/src/test/org/jnode/test/command/file/all-file-tests.xml
Added Paths:
-----------
trunk/cli/src/test/org/jnode/test/command/argument/
trunk/cli/src/test/org/jnode/test/command/argument/all-argument-tests.xml
trunk/cli/src/test/org/jnode/test/command/file/cut-command-tests.xml
Modified: trunk/cli/build-tests.xml
===================================================================
--- trunk/cli/build-tests.xml 2009-05-05 21:22:20 UTC (rev 5428)
+++ trunk/cli/build-tests.xml 2009-05-05 21:24:04 UTC (rev 5429)
@@ -5,20 +5,50 @@
<target name="help" description="output target descriptions">
<echo>
The main targets (tests) for this build are as follows:
-all Runs all tests for the 'cli' project
-help Output these messages
+all Runs all tests for the 'cli' project
+all-junit Runs all JUnit tests for the 'cli' project
+blackbox-common Runs all blackbox tests in the 'common' package of the 'cli' project
+blackbox-file Runs all blackbox tests in the 'file' package of the 'cli' project
+all-blackbox Runs all blackbox tests for the 'cli' project
+help Output these messages
</echo>
</target>
- <target name="all">
- <java classpathref="cp-test" classname="org.jnode.test.shell.harness.TestHarness">
+ <target name="all-junit">
+ <junit showoutput="on" printsummary="on" fork="on">
+ <classpath refid="cp-test"/>
+ <test name="org.jnode.test.cli.CLITestSuite"/>
+ </junit>
+ </target>
+
+ <target name="blackbox-common">
+ <java classpathref="cp-test" classname="org.jnode.test.shell.harness.TestHarness">
+ <arg value="-E"/>
+ <arg value="-s"/>
+ <arg value="${root.dir}"/>
+ <arg value="${basedir}/src/test/org/jnode/test/command/common/all-common-tests.xml"/>
+ </java>
+ </target>
+
+ <target name="blackbox-file">
+ <java classpathref="cp-test" classname="org.jnode.test.shell.harness.TestHarness">
+ <arg value="-E"/>
+ <arg value="-s"/>
+ <arg value="${root.dir}"/>
+ <arg value="${basedir}/src/test/org/jnode/test/command/file/all-file-tests.xml"/>
+ </java>
+ </target>
+
+ <target name="all-blackbox">
+ <java classpathref="cp-test" classname="org.jnode.test.shell.harness.TestHarness">
<arg value="-E"/>
<arg value="-s"/>
<arg value="${root.dir}"/>
<arg value="${basedir}/src/test/org/jnode/test/command/all-tests.xml"/>
</java>
</target>
-
+
+ <target name="all" depends="all-junit,all-blackbox"/>
</project>
Modified: trunk/cli/src/test/org/jnode/test/command/all-tests.xml
===================================================================
--- trunk/cli/src/test/org/jnode/test/command/all-tests.xml 2009-05-05 21:22:20 UTC (rev 5428)
+++ trunk/cli/src/test/org/jnode/test/command/all-tests.xml 2009-05-05 21:24:04 UTC (rev 5429)
@@ -1,4 +1,5 @@
<testSet title="All command tests">
+ <include setName="argument/all-argument-tests.xml"/>
<include setName="common/all-common-tests.xml"/>
<include setName="file/all-file-tests.xml"/>
</testSet>
Added: trunk/cli/src/test/org/jnode/test/command/argument/all-argument-tests.xml
===================================================================
--- trunk/cli/src/test/org/jnode/test/command/argument/all-argument-tests.xml (rev 0)
+++ trunk/cli/src/test/org/jnode/test/command/argument/all-argument-tests.xml 2009-05-05 21:24:04 UTC (rev 5429)
@@ -0,0 +1,83 @@
+<testSet title="argument tests">
+ <plugin id="org.jnode.command.file"/>
+ <testSpec title="num-list concat 1" command="cut" runMode="AS_ALIAS" rc="0">
+ <arg>-b</arg>
+ <arg>3,5,7</arg>
+ <input>1234567890
+</input>
+ <output>357
+</output>
+ </testSpec>
+ <testSpec title="num-list concat 2" command="cut" runMode="AS_ALIAS" rc="0">
+ <arg>-b</arg>
+ <arg>-3,7-</arg>
+ <input>1234567890
+</input>
+ <output>1237890
+</output>
+ </testSpec>
+ <testSpec title="num-list concat 3" command="cut" runMode="AS_ALIAS" rc="0">
+ <arg>-b</arg>
+ <arg>3,4-6,7</arg>
+ <input>1234567890
+</input>
+ <output>34567
+</output>
+ </testSpec>
+ <testSpec title="num-list concat 4" command="cut" runMode="AS_ALIAS" rc="0">
+ <arg>-b</arg>
+ <arg>1-2,3,5,6-7,9-10</arg>
+ <input>1234567890
+</input>
+ <output>12356790
+</output>
+ </testSpec>
+ <testSpec title="num-list concat 5" command="cut" runMode="AS_ALIAS" rc="0">
+ <arg>-b</arg>
+ <arg>-3,-2</arg>
+ <input>1234567890
+</input>
+ <output>123
+</output>
+ </testSpec>
+ <testSpec title="num-list concat 6" command="cut" runMode="AS_ALIAS" rc="0">
+ <arg>-b</arg>
+ <arg>9-,5-,7-8,6</arg>
+ <input>1234567890
+</input>
+ <output>567890
+</output>
+ </testSpec>
+ <testSpec title="num-list sort 1" command="cut" runMode="AS_ALIAS" rc="0">
+ <arg>-b</arg>
+ <arg>7,1,5,9,3</arg>
+ <input>1234567890
+</input>
+ <output>13579
+</output>
+ </testSpec>
+ <arg>-b</arg>
+ <testSpec title="num-list sort 2" command="cut" runMode="AS_ALIAS" rc="0">
+ <arg>6-7,5,9-10,2,3,1</arg>
+ <input>1234567890
+</input>
+ <output>12356790
+</output>
+ </testSpec>
+ <testSpec title="num-list sort 3" command="cut" runMode="AS_ALIAS" rc="0">
+ <arg>-b</arg>
+ <arg>7-,-3</arg>
+ <input>1234567890
+</input>
+ <output>1237890
+</output>
+ </testSpec>
+ <testSpec title="num-list sort 4" command="cut" runMode="AS_ALIAS" rc="0">
+ <arg>-b</arg>
+ <arg>5,-4,6-</arg>
+ <input>1234567890
+</input>
+ <output>1234567890
+</output>
+ </testSpec>
+</testSet>
Modified: trunk/cli/src/test/org/jnode/test/command/file/all-file-tests.xml
===================================================================
--- trunk/cli/src/test/org/jnode/test/command/file/all-file-tests.xml 2009-05-05 21:22:20 UTC (rev 5428)
+++ trunk/cli/src/test/org/jnode/test/command/file/all-file-tests.xml 2009-05-05 21:24:04 UTC (rev 5429)
@@ -1,3 +1,4 @@
<testSet title="All file command tests">
<include setName="wc-command-tests.xml"/>
+ <include setName="cut-command-tests.xml"/>
</testSet>
Added: trunk/cli/src/test/org/jnode/test/command/file/cut-command-tests.xml
===================================================================
--- trunk/cli/src/test/org/jnode/test/command/file/cut-command-tests.xml (rev 0)
+++ trunk/cli/src/test/org/jnode/test/command/file/cut-command-tests.xml 2009-05-05 21:24:04 UTC (rev 5429)
@@ -0,0 +1,133 @@
+<testSet title="POSIX cut command tests">
+ <plugin id="org.jnode.command.file"/>
+ <testSpec title="cut byte-range 1" command="cut" runMode="AS_ALIAS" rc="0">
+ <arg>-b</arg>
+ <arg>3-7</arg>
+ <input>1234567890
+</input>
+ <output>34567
+</output>
+ </testSpec>
+ <testSpec title="cut byte-range 2" command="cut" runMode="AS_ALIAS" rc="0">
+ <arg>-b</arg>
+ <arg>-7</arg>
+ <input>1234567890
+</input>
+ <output>1234567
+</output>
+ </testSpec>
+ <testSpec title="cut byte-range 3" command="cut" runMode="AS_ALIAS" rc="0">
+ <arg>-b</arg>
+ <arg>3-</arg>
+ <input>1234567890
+</input>
+ <output>34567890
+</output>
+ </testSpec>
+ <testSpec title="cut char-range 1" command="cut" runMode="AS_ALIAS" rc="0">
+ <arg>-c</arg>
+ <arg>3-7</arg>
+ <input>1234567890
+</input>
+ <output>34567
+</output>
+ </testSpec>
+ <testSpec title="cut char-range 2" command="cut" runMode="AS_ALIAS" rc="0">
+ <arg>-c</arg>
+ <arg>-7</arg>
+ <input>1234567890
+</input>
+ <output>1234567
+</output>
+ </testSpec>
+ <testSpec title="cut char-range 3" command="cut" runMode="AS_ALIAS" rc="0">
+ <arg>-c</arg>
+ <arg>3-</arg>
+ <input>1234567890
+</input>
+ <output>34567890
+</output>
+ </testSpec>
+ <!-- The next 3 tests have <TAB>s in the input/output, make sure an editor does not
+ expand them to spaces! -->
+ <testSpec title="cut field-range default 1" command="cut" runMode="AS_ALIAS" rc="0">
+ <arg>-f</arg>
+ <arg>3-7</arg>
+ <input>1 2 3 4 5 6 7 8 9 0
+</input>
+ <output>3 4 5 6 7
+</output>
+ </testSpec>
+ <testSpec title="cut field-range default 2" command="cut" runMode="AS_ALIAS" rc="0">
+ <arg>-f</arg>
+ <arg>3-</arg>
+ <input>1 2 3 4 5 6 7 8 9 0
+</input>
+ <output>3 4 5 6 7 8 9 0
+</output>
+ </testSpec>
+ <testSpec title="cut field-range default 3" command="cut" runMode="AS_ALIAS" rc="0">
+ <arg>-f</arg>
+ <arg>-7</arg>
+ <input>1 2 3 4 5 6 7 8 9 0
+</input>
+ <output>1 2 3 4 5 6 7
+</output>
+ </testSpec>
+ <testSpec title="cut field-range alt-delim 1" command="cut" runMode="AS_ALIAS" rc="0">
+ <arg>-d</arg>
+ <arg>;</arg>
+ <arg>-f</arg>
+ <arg>3-7</arg>
+ <input>1;2;3;4;5;6;7;8;9;0
+</input>
+ <output>3;4;5;6;7
+</output>
+ </testSpec>
+ <testSpec title="cut field-range alt-delim 2" command="cut" runMode="AS_ALIAS" rc="0">
+ <arg>-d</arg>
+ <arg>;</arg>
+ <arg>-f</arg>
+ <arg>3-</arg>
+ <input>1;2;3;4;5;6;7;8;9;0
+</input>
+ <output>3;4;5;6;7;8;9;0
+</output>
+ </testSpec>
+ <testSpec title="cut field-range alt-delim 3" command="cut" runMode="AS_ALIAS" rc="0">
+ <arg>-d</arg>
+ <arg>;</arg>
+ <arg>-f</arg>
+ <arg>-7</arg>
+ <input>1;2;3;4;5;6;7;8;9;0
+</input>
+ <output>1;2;3;4;5;6;7
+</output>
+ </testSpec>
+ <testSpec title="cut field-range out-delim" command="cut" runMode="AS_ALIAS" rc="0">
+ <arg>-d</arg>
+ <arg>;</arg>
+ <arg>-f</arg>
+ <arg>3-7</arg>
+ <arg>--output-delimiter</arg>
+ <arg>:</arg>
+ <input>1;2;3;4;5;6;7;8;9;0
+</input>
+ <output>3:4:5:6:7
+</output>
+ </testSpec>
+ <testSpec title="cut suppress" command="cut" runMode="AS_ALIAS" rc="0">
+ <arg>-d</arg>
+ <arg>;</arg>
+ <arg>-f</arg>
+ <arg>3-7</arg>
+ <arg>-s</arg>
+ <input>1;2;3;4;5;6;7;8;9;0
+1:2:3:4:5:6:7:8:9:0
+1;2;3;4;5;6;7;8;9;0
+</input>
+ <output>3;4;5;6;7
+3;4;5;6;7
+</output>
+ </testSpec>
+</testSet>
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <chr...@us...> - 2009-05-11 22:52:47
|
Revision: 5480
http://jnode.svn.sourceforge.net/jnode/?rev=5480&view=rev
Author: chrisboertien
Date: 2009-05-11 22:52:39 +0000 (Mon, 11 May 2009)
Log Message:
-----------
Unix 'paste' command + blackbox tests
Signed-off-by: chrisboertien <chr...@gm...>
Modified Paths:
--------------
trunk/cli/descriptors/org.jnode.command.file.xml
trunk/cli/src/commands/org/jnode/command/util/IOUtils.java
trunk/cli/src/test/org/jnode/test/command/argument/all-argument-tests.xml
trunk/cli/src/test/org/jnode/test/command/file/all-file-tests.xml
Added Paths:
-----------
trunk/cli/src/commands/org/jnode/command/file/PasteCommand.java
trunk/cli/src/test/org/jnode/test/command/file/paste-command-tests.xml
Modified: trunk/cli/descriptors/org.jnode.command.file.xml
===================================================================
--- trunk/cli/descriptors/org.jnode.command.file.xml 2009-05-11 20:26:47 UTC (rev 5479)
+++ trunk/cli/descriptors/org.jnode.command.file.xml 2009-05-11 22:52:39 UTC (rev 5480)
@@ -38,8 +38,8 @@
<alias name="hexdump" class="org.jnode.command.file.HexdumpCommand"/>
<alias name="ls" class="org.jnode.command.file.DirCommand"/>
<alias name="md5sum" class="org.jnode.command.file.Md5SumCommand"/>
- <!-- NoSuchAlgorithmException: md5 Message Digest not available -->
<alias name="mkdir" class="org.jnode.command.file.MkdirCommand"/>
+ <alias name="paste" class="org.jnode.command.file.PasteCommand"/>
<alias name="pwd" class="org.jnode.command.file.PwdCommand"/>
<alias name="rm" class="org.jnode.command.file.DeleteCommand"/>
<alias name="tail" class="org.jnode.command.file.TailCommand"/>
@@ -280,6 +280,18 @@
<syntax alias="mkdir">
<argument argLabel="directory" description="create a new directory"/>
</syntax>
+ <syntax alias="paste">
+ <empty />
+ <sequence>
+ <optionSet>
+ <option argLabel="serial" shortName="s" longName="serial"/>
+ <option argLabel="delims" shortName="d" longName="delimiters"/>
+ </optionSet>
+ <repeat>
+ <argument argLabel="files"/>
+ </repeat>
+ </sequence>
+ </syntax>
<syntax alias="pwd">
<empty description="show the pathname for the current directory"/>
</syntax>
Added: trunk/cli/src/commands/org/jnode/command/file/PasteCommand.java
===================================================================
--- trunk/cli/src/commands/org/jnode/command/file/PasteCommand.java (rev 0)
+++ trunk/cli/src/commands/org/jnode/command/file/PasteCommand.java 2009-05-11 22:52:39 UTC (rev 5480)
@@ -0,0 +1,191 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2003-2009 JNode.org
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; If not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+package org.jnode.command.file;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.jnode.command.argument.NumberListArgument;
+import org.jnode.command.util.IOUtils;
+import org.jnode.command.util.NumberRange;
+import org.jnode.shell.AbstractCommand;
+import org.jnode.shell.syntax.Argument;
+import org.jnode.shell.syntax.FileArgument;
+import org.jnode.shell.syntax.FlagArgument;
+import org.jnode.shell.syntax.StringArgument;
+
+/**
+ * Unix 'paste' command
+ *
+ * @author chris boertien
+ */
+public class PasteCommand extends AbstractCommand {
+
+ private static final String help_files = "list of files to be operated on";
+ private static final String help_serial = "if set, paste files one at a time, instead of in parallel";
+ private static final String help_delims = "use the supplied characters as delimiters instead of <TAB>";
+ private static final String help_super = "merge lines of files";
+
+ private final FileArgument argFiles;
+ private final FlagArgument argSerial;
+ private final StringArgument argDelims;
+ private PrintWriter out;
+
+ private List<File> files;
+ private char[] delims;
+ private int delimPos;
+ private int rc = 0;
+ private boolean serial;
+
+ public PasteCommand() {
+ super(help_super);
+ int filesFlags = Argument.MULTIPLE | Argument.EXISTING | FileArgument.HYPHEN_IS_SPECIAL;
+ argFiles = new FileArgument("files", filesFlags, help_files);
+ argSerial = new FlagArgument("serial", 0, help_serial);
+ argDelims = new StringArgument("delims", 0, help_delims);
+ registerArguments(argFiles, argSerial, argDelims);
+ }
+
+ public void execute() {
+ out = getOutput().getPrintWriter();
+ parseOptions();
+ try {
+ if (serial) {
+ pasteSerial();
+ } else {
+ pasteParallel();
+ }
+ } finally {
+ exit(rc);
+ }
+ }
+
+ private void pasteParallel() {
+ List<BufferedReader> readers = new ArrayList<BufferedReader>(files.size());
+ List<String> names = new ArrayList<String>(files.size());
+ List<String> lines = new ArrayList<String>(files.size());
+ try {
+ for (File file : files) {
+ String name = file.getName();
+ int i = names.indexOf(name);
+ if (i != -1) {
+ readers.add(readers.get(i));
+ } else {
+ if (name.equals("-")) {
+ readers.add(IOUtils.openBufferedReader(getInput().getReader()));
+ } else {
+ readers.add(IOUtils.openBufferedReader(file));
+ }
+ }
+ names.add(name);
+ }
+ while (true) {
+ int num = readLines(lines, readers);
+ if (num == 0) break;
+ writeLines(lines, num);
+ lines.clear();
+ }
+ } finally {
+ for (BufferedReader reader : readers) {
+ IOUtils.close(reader);
+ }
+ }
+ }
+
+ private void pasteSerial() {
+ BufferedReader reader = null;
+ for (File file : files) {
+ try {
+ List<String> lines = null;
+ if (file.getName().equals("-")) {
+ reader = IOUtils.openBufferedReader(getInput().getReader());
+ } else {
+ reader = IOUtils.openBufferedReader(file);
+ }
+ if (reader != null) {
+ lines = IOUtils.readLines(reader);
+ if (lines != null) {
+ writeLines(lines, lines.size());
+ }
+ }
+ } finally {
+ IOUtils.close(reader);
+ }
+ }
+ }
+
+ private int readLines(List<String> lines, List<BufferedReader> readers) {
+ int count = 0;
+ String line = null;
+ for (BufferedReader reader : readers) {
+ try {
+ line = reader.readLine();
+ } catch (IOException e) {
+ rc = 1;
+ return 0;
+ }
+ if (line != null) {
+ lines.add(line);
+ count++;
+ }
+ }
+ return count;
+ }
+
+ private void writeLines(List<String> lines, int max) {
+ boolean first = true;
+ for (int i = 0; i < max; i++) {
+ if (!first) {
+ out.write(nextDelim());
+ }
+ first = false;
+ out.write(lines.get(i));
+ }
+ out.println();
+ delimPos = 0;
+ }
+
+ private char nextDelim() {
+ char c = delims[delimPos++];
+ if (delimPos == delims.length) delimPos = 0;
+ return c;
+ }
+
+ private void parseOptions() {
+ if (argFiles.isSet()) {
+ files = Arrays.asList(argFiles.getValues());
+ } else {
+ files = new ArrayList(1);
+ files.add(new File("-"));
+ }
+
+ if (argDelims.isSet()) {
+ delims = argDelims.getValue().toCharArray();
+ } else {
+ delims = new char[]{'\t'};
+ }
+ serial = argSerial.isSet();
+ }
+}
Modified: trunk/cli/src/commands/org/jnode/command/util/IOUtils.java
===================================================================
--- trunk/cli/src/commands/org/jnode/command/util/IOUtils.java 2009-05-11 20:26:47 UTC (rev 5479)
+++ trunk/cli/src/commands/org/jnode/command/util/IOUtils.java 2009-05-11 22:52:39 UTC (rev 5480)
@@ -298,6 +298,30 @@
}
/**
+ * Wraps a {@code Reader} with a {@code BufferedReader}.
+ *
+ * @param reader the reader to wrap
+ * @return a {@code BufferedReader}
+ * @throws NullPointerException if reader is null
+ */
+ public static BufferedReader openBufferedReader(Reader reader) {
+ return openBufferedReader(reader, BUFFER_SIZE);
+ }
+
+ /**
+ * Wraps a {@code Reader} with a {@code BufferedReader}.
+ *
+ * @param reader the reader to wrap
+ * @param bufferSize the size of buffer to use
+ * @return a {@code BufferedReader}
+ * @throws NullPointerException if reader is null
+ */
+ public static BufferedReader openBufferedReader(Reader reader, int bufferSize) {
+ checkNull(reader);
+ return new BufferedReader(reader, bufferSize);
+ }
+
+ /**
* Opens a LineNumberReader on a file.
*
* This method will not throw a FileNotFoundException like the FileReader
Modified: trunk/cli/src/test/org/jnode/test/command/argument/all-argument-tests.xml
===================================================================
--- trunk/cli/src/test/org/jnode/test/command/argument/all-argument-tests.xml 2009-05-11 20:26:47 UTC (rev 5479)
+++ trunk/cli/src/test/org/jnode/test/command/argument/all-argument-tests.xml 2009-05-11 22:52:39 UTC (rev 5480)
@@ -56,8 +56,8 @@
<output>13579
</output>
</testSpec>
+ <testSpec title="num-list sort 2" command="cut" runMode="AS_ALIAS" rc="0">
<arg>-b</arg>
- <testSpec title="num-list sort 2" command="cut" runMode="AS_ALIAS" rc="0">
<arg>6-7,5,9-10,2,3,1</arg>
<input>1234567890
</input>
Modified: trunk/cli/src/test/org/jnode/test/command/file/all-file-tests.xml
===================================================================
--- trunk/cli/src/test/org/jnode/test/command/file/all-file-tests.xml 2009-05-11 20:26:47 UTC (rev 5479)
+++ trunk/cli/src/test/org/jnode/test/command/file/all-file-tests.xml 2009-05-11 22:52:39 UTC (rev 5480)
@@ -1,5 +1,6 @@
<testSet title="All file command tests">
+ <include setName="cut-command-tests.xml"/>
+ <include setName="paste-command-tests.xml"/>
<include setName="wc-command-tests.xml"/>
- <include setName="cut-command-tests.xml"/>
</testSet>
Added: trunk/cli/src/test/org/jnode/test/command/file/paste-command-tests.xml
===================================================================
--- trunk/cli/src/test/org/jnode/test/command/file/paste-command-tests.xml (rev 0)
+++ trunk/cli/src/test/org/jnode/test/command/file/paste-command-tests.xml 2009-05-11 22:52:39 UTC (rev 5480)
@@ -0,0 +1,131 @@
+<testSet title="POSIX paste command tests">
+ <plugin id="org.jnode.command.file"/>
+ <plugin id="org.jnode.shell.bjorne" class="org.jnode.test.shell.bjorne.BjornePseudoPlugin"/>
+ <testSpec title="serial stdin default-delim" command="paste" runMode="AS_ALIAS" rc="0">
+ <arg>-s</arg>
+ <input>1
+2
+3
+4
+</input>
+ <output>1 2 3 4
+</output>
+ </testSpec>
+ <testSpec title="title serial stdin single-delim" command="paste" runMode="AS_ALIAS" rc="0">
+ <arg>-s</arg>
+ <arg>-d</arg>
+ <arg>;</arg>
+ <input>1
+2
+3
+4
+</input>
+ <output>1;2;3;4
+</output>
+ </testSpec>
+ <testSpec title="serial stdin multi-delim 1" command="paste" runMode="AS_ALIAS" rc="0">
+ <arg>-s</arg>
+ <arg>-d</arg>
+ <arg>;:,</arg>
+ <input>1
+2
+3
+4
+</input>
+ <output>1;2:3,4
+</output>
+ </testSpec>
+ <testSpec title="serial stdin multi-delim 2" command="paste" runMode="AS_ALIAS" rc="0">
+ <arg>-s</arg>
+ <arg>-d</arg>
+ <arg>;:</arg>
+ <input>1
+2
+3
+4
+</input>
+ <output>1;2:3;4
+</output>
+ </testSpec>
+ <testSpec title="parallel stdin default-delim" command="paste" runMode="AS_ALIAS" rc="0">
+ <input>1
+2
+3
+4
+</input>
+ <output>1
+2
+3
+4
+</output>
+ </testSpec>
+ <testSpec title="parallel stdin-multi single-delim" command="paste" runMode="AS_ALIAS" rc="0">
+ <arg>-d</arg>
+ <arg>;</arg>
+ <arg>-</arg>
+ <arg>-</arg>
+ <input>1
+2
+3
+4
+</input>
+ <output>1;2
+3;4
+</output>
+ </testSpec>
+ <testSpec title="parallel stdin-multi multi-delim" command="paste" runMode="AS_ALIAS" rc="0">
+ <arg>-d</arg>
+ <arg>;:,</arg>
+ <arg>-</arg>
+ <arg>-</arg>
+ <arg>-</arg>
+ <arg>-</arg>
+ <input>1
+2
+3
+4
+</input>
+ <output>1;2:3,4
+</output>
+ </testSpec>
+ <testSpec title="parallel file-dup sync" command="run" runMode="AS_SCRIPT" rc="0">
+ <script>#!bjorne
+ paste -d ";" @TEMP_DIR@/a @TEMP_DIR@/a
+ </script>
+ <file name="a" input="true">1
+2
+3
+4
+</file>
+ <output>1;2
+3;4
+</output>
+ </testSpec>
+ <testSpec title="parallel file-dup async" command="run" runMode="AS_SCRIPT" rc="0">
+ <script>#!bjorne
+ paste -d ";" @TEMP_DIR@/a @TEMP_DIR@/a @TEMP_DIR@/a
+ </script>
+ <file name="a" input="true">1
+2
+3
+4
+</file>
+ <output>1;2;3
+4
+</output>
+ </testSpec>
+ <testSpec title="parallel file-dup async multi-delim" command="run" runMode="AS_SCRIPT" rc="0">
+ <script>#!bjorne
+ paste -d ";:" @TEMP_DIR@/a @TEMP_DIR@/a @TEMP_DIR@/a
+ </script>
+ <file name="a" input="true">1
+2
+3
+4
+5
+</file>
+ <output>1;2:3
+4;5
+</output>
+ </testSpec>
+</testSet>
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <chr...@us...> - 2009-05-18 22:26:17
|
Revision: 5497
http://jnode.svn.sourceforge.net/jnode/?rev=5497&view=rev
Author: chrisboertien
Date: 2009-05-18 22:26:09 +0000 (Mon, 18 May 2009)
Log Message:
-----------
Checkin of sort command + blackbox tests
Signed-off-by: chrisboertien <chr...@gm...>
Modified Paths:
--------------
trunk/cli/descriptors/org.jnode.command.file.xml
trunk/cli/src/commands/org/jnode/command/util/IOUtils.java
trunk/cli/src/test/org/jnode/test/command/file/all-file-tests.xml
Added Paths:
-----------
trunk/cli/src/commands/org/jnode/command/file/SortCommand.java
trunk/cli/src/test/org/jnode/test/command/file/sort-command-tests.xml
Modified: trunk/cli/descriptors/org.jnode.command.file.xml
===================================================================
--- trunk/cli/descriptors/org.jnode.command.file.xml 2009-05-18 13:15:53 UTC (rev 5496)
+++ trunk/cli/descriptors/org.jnode.command.file.xml 2009-05-18 22:26:09 UTC (rev 5497)
@@ -42,6 +42,7 @@
<alias name="paste" class="org.jnode.command.file.PasteCommand"/>
<alias name="pwd" class="org.jnode.command.file.PwdCommand"/>
<alias name="rm" class="org.jnode.command.file.DeleteCommand"/>
+ <alias name="sort" class="org.jnode.command.file.SortCommand"/>
<alias name="tail" class="org.jnode.command.file.TailCommand"/>
<alias name="touch" class="org.jnode.command.file.TouchCommand"/>
<alias name="wc" class="org.jnode.command.file.WcCommand"/>
@@ -308,6 +309,29 @@
</repeat>
</sequence>
</syntax>
+ <syntax alias="sort">
+ <sequence>
+ <optionSet>
+ <option argLabel="field" shortName="k"/>
+ <option argLabel="output" shortName="o"/>
+ <option argLabel="field-sep" shortName="t"/>
+ <option argLabel="check" shortName="c"/>
+ <option argLabel="merge" shortName="m"/>
+ <option argLabel="unique" shortName="u"/>
+ <option argLabel="reverse" shortName="r"/>
+ <option argLabel="cmp-print" shortName="i"/>
+ <option argLabel="cmp-alpha" shortName="d"/>
+ <option argLabel="cmp-icase" shortName="i"/>
+ <option argLabel="no-blanks" shortName="b"/>
+ <option argLabel="numeric" shortName="n"/>
+ <!-- debugging options -->
+ <option argLabel="sort" longName="sort"/>
+ </optionSet>
+ <repeat>
+ <argument argLabel="files"/>
+ </repeat>
+ </sequence>
+ </syntax>
<syntax alias="tail">
<sequence>
<optionSet label="globals">
Added: trunk/cli/src/commands/org/jnode/command/file/SortCommand.java
===================================================================
--- trunk/cli/src/commands/org/jnode/command/file/SortCommand.java (rev 0)
+++ trunk/cli/src/commands/org/jnode/command/file/SortCommand.java 2009-05-18 22:26:09 UTC (rev 5497)
@@ -0,0 +1,435 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2003-2009 JNode.org
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; If not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+package org.jnode.command.file;
+
+import java.io.File;
+import java.io.PrintWriter;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.LinkedList;
+
+import org.jnode.command.util.IOUtils;
+import org.jnode.shell.AbstractCommand;
+import org.jnode.shell.CommandLine;
+import org.jnode.shell.syntax.Argument;
+import org.jnode.shell.syntax.CommandSyntaxException;
+import org.jnode.shell.syntax.FileArgument;
+import org.jnode.shell.syntax.FlagArgument;
+import org.jnode.shell.syntax.IntegerArgument;
+import org.jnode.shell.syntax.StringArgument;
+import static org.jnode.shell.syntax.Argument.EXISTING;
+import static org.jnode.shell.syntax.Argument.MULTIPLE;
+import static org.jnode.shell.syntax.Argument.NONEXISTENT;
+import static org.jnode.shell.syntax.FileArgument.HYPHEN_IS_SPECIAL;
+
+public class SortCommand extends AbstractCommand {
+
+ private static final boolean DEBUG = true;
+
+ private static final String help_files = "files to sort";
+ private static final String help_output = "send output to this file, instead of stdout";
+ private static final String help_field = "The field or field range to sort on";
+ private static final String help_field_sep = "Use a specific character as the field separator";
+ private static final String help_merge = "Assume the input is sorted and merge only";
+ private static final String help_check = "Instead of sorting, check that the input is sorted.";
+ private static final String help_numeric = "When sorting, sort numerically instead of lexicographically";
+ private static final String help_reverse = "Reverse the sense of ordering";
+ private static final String help_unique = "If sorting, do not insert lines with keys that already exist. If " +
+ "checking, make sure all keys are unique";
+ private static final String help_cmp_print = "For comparisons, ignore non-printing characters";
+ private static final String help_cmp_alpha = "For comparisons, use only blank and alphanumeric characters";
+ private static final String help_cmp_icase = "For comparisons, ignore case of keys when comparing";
+ private static final String help_no_blanks = "Ignore leading blanks when determining that start and end " +
+ "positions of a key";
+ private static final String help_super = "sort/merge files, or check that files are sorted";
+
+ private static class Field {
+ private int field;
+ private int offset;
+ private boolean ignoreBlanks;
+ private boolean sortNumeric;
+ private boolean cmpPrint;
+ private boolean cmpAlpha;
+ private boolean cmpICase;
+ private boolean reverse;
+ }
+
+ private static class FieldRange {
+ private Field start;
+ private Field end;
+ }
+
+ private static class Key {
+ String[] parts;
+ FieldRange[] ranges;
+ }
+
+ private static class Entry {
+ Key key;
+ String value;
+ }
+
+ private static class KeyFieldArgument extends Argument<FieldRange> {
+ private KeyFieldArgument(String label, int flags, String desc) {
+ super(label, flags, new FieldRange[0], desc);
+ }
+
+ @Override
+ protected FieldRange doAccept(CommandLine.Token token, int flags) throws CommandSyntaxException {
+ String text = token.text;
+ FieldRange range = new FieldRange();
+ int i = text.indexOf(",");
+ if (i == -1) {
+ range.start = parseField(text, false);
+ range.end = new Field();
+ range.end.field = -1;
+ range.end.offset = -1;
+ } else {
+ range.start = parseField(text.substring(0, i), false);
+ range.end = parseField(text.substring(i + 1), true);
+ }
+ return range;
+ }
+
+ @Override
+ protected String argumentKind() {
+ return "sort-field";
+ }
+
+ private static Field parseField(String text, boolean end) throws CommandSyntaxException {
+ Field field = new Field();
+ int i = text.length() - 1;
+ LOOP:
+ while (true) {
+ switch (text.charAt(i)) {
+ case 'b':
+ field.ignoreBlanks = true;
+ break;
+ case 'd':
+ field.cmpAlpha = true;
+ break;
+ case 'f':
+ field.cmpICase = true;
+ break;
+ case 'i':
+ field.cmpPrint = true;
+ break;
+ case 'n':
+ field.sortNumeric = true;
+ break;
+ case 'r':
+ field.reverse = true;
+ break;
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case '0':
+ break LOOP;
+ default:
+ throw new CommandSyntaxException("Invalid field: " + text);
+ }
+ i--;
+ }
+ text = text.substring(0, i + 1);
+ i = text.indexOf(".");
+ if (i == 0) {
+ throw new CommandSyntaxException("Field offset cannot be empty");
+ }
+ if (i == (text.length() - 1)) {
+ throw new CommandSyntaxException("Character offset cannot be empty if '.' is given");
+ }
+ try {
+ if (i == -1) {
+ field.field = Integer.parseInt(text) - 1;
+ field.offset = end ? -1 : 0;
+ } else {
+ field.field = Integer.parseInt(text.substring(0, i)) - 1;
+ field.offset = Integer.parseInt(text.substring(i + 1)) - 1;
+ }
+ } catch (NumberFormatException e) {
+ throw new CommandSyntaxException("Invalid number: " + text);
+ }
+ if (field.field < 0) {
+ throw new CommandSyntaxException("Field offset cannot be less than one: " + field.field);
+ }
+ if (field.offset < 0 && !end) {
+ throw new CommandSyntaxException("Start character offset cannot be less than one: " + field.offset);
+ }
+ if (field.offset < -1 && end) {
+ throw new CommandSyntaxException("End character offset cannot be less than zero");
+ }
+ return field;
+ }
+ }
+
+ private class FieldComparator implements Comparator<String> {
+
+ private boolean trim = false;
+
+ @Override
+ public boolean equals(Object o) {
+ return o instanceof FieldComparator;
+ }
+
+ @Override
+ public int compare(String a, String b) {
+ for (FieldRange range : ranges) {
+ trim = range.start.ignoreBlanks;
+ String aKey = getKey(a, range);
+ String bKey = getKey(b, range);
+ int diff = aKey.compareTo(bKey);
+ if (diff != 0) {
+ return diff;
+ }
+ }
+ return 0;
+ }
+
+ // TODO
+ // Refactor this out and calculate the keys before sorting
+ private String getKey(String text, FieldRange range) {
+ Field start = range.start;
+ Field end = range.end;
+ String[] fields = (fieldSep != null) ? splitSep(text, fieldSep) : splitDefault(text);
+ if (start.field >= fields.length) {
+ return "";
+ } else {
+ if (end.field == -1) {
+ end.field = fields.length - 1;
+ }
+ if (start.field == end.field) {
+ int startPos = start.offset;
+ int field = start.field;
+ if ((end.offset == -1) || (end.offset >= fields[field].length())) {
+ return fields[field].substring(startPos);
+ } else {
+ return fields[field].substring(startPos, end.offset + 1);
+ }
+ }
+ StringBuilder capture = new StringBuilder();
+ capture.append(fields[start.field].substring(start.offset));
+ for (int i = start.field + 1; i < end.field; i++) {
+ capture.append(fields[i]);
+ }
+ if ((end.offset == -1) || (end.offset >= fields[end.field].length())) {
+ capture.append(fields[end.field]);
+ } else {
+ capture.append(fields[end.field].substring(0, end.offset + 1));
+ }
+ return capture.toString();
+ }
+ }
+
+ private String[] splitSep(String text, String sep) {
+ List<String> fields = new LinkedList<String>();
+ int mark = 0;
+ int i;
+ while((i = text.indexOf(sep, mark)) != -1) {
+ fields.add(text.substring(mark, i));
+ mark = i + 1;
+ }
+ fields.add(text.substring(mark, text.length()));
+ return fields.toArray(new String[fields.size()]);
+ }
+
+ private String[] splitDefault(String text) {
+ List<String> fields = new LinkedList<String>();
+ boolean haveField = false;
+ int mark = 0;
+ int i;
+ for (i = 0; i < text.length(); i++) {
+ if (isBlank(text.charAt(i))) {
+ if (haveField) {
+ fields.add(text.substring(mark, i));
+ mark = i;
+ haveField = false;
+ } else {
+ if (trim) {
+ mark = i;
+ }
+ }
+ } else {
+ haveField = true;
+ }
+ }
+ if (i > mark) {
+ fields.add(text.substring(mark, i));
+ }
+ return fields.toArray(new String[fields.size()]);
+ }
+
+ private boolean isBlank(char c) {
+ return c == ' ' || c == '\t';
+ }
+ }
+
+ private final FileArgument argFile = new FileArgument("files", MULTIPLE | EXISTING | HYPHEN_IS_SPECIAL, help_files);
+ private final FileArgument argOut = new FileArgument("output", NONEXISTENT, help_output);
+ private final FlagArgument argCheck = new FlagArgument("check", 0, help_check);
+ private final FlagArgument argMerge = new FlagArgument("merge", 0, help_merge);
+ private final FlagArgument argUnique = new FlagArgument("unique", 0, help_unique);
+ private final FlagArgument argNumeric = new FlagArgument("numeric", 0, help_numeric);
+ private final FlagArgument argReverse = new FlagArgument("reverse", 0, help_reverse);
+ private final FlagArgument argCmpPrint = new FlagArgument("cmp-print", 0, help_cmp_print);
+ private final FlagArgument argCmpAlpha = new FlagArgument("cmp-alpha", 0, help_cmp_alpha);
+ private final FlagArgument argCmpICase = new FlagArgument("cmp-icase", 0, help_cmp_icase);
+ private final FlagArgument argNoBlanks = new FlagArgument("no-blanks", 0, help_no_blanks);
+ private final KeyFieldArgument argField = new KeyFieldArgument("field", MULTIPLE, help_field);
+ private final StringArgument argFieldSep = new StringArgument("field-sep", 0, help_field_sep);
+
+ private final IntegerArgument argSort = new IntegerArgument("sort", 0, " ");
+ private static final int SORT_ONE = 1;
+ private static final int SORT_TWO = 2;
+ private static final int SORT_LAST = 1;
+
+ private List<File> files;
+ private File outputFile;
+ private PrintWriter out;
+ private PrintWriter err;
+ private FieldRange[] ranges;
+ private String fieldSep;
+ private int rc;
+ private int sort;
+ private boolean check;
+ private boolean merge;
+ private boolean unique;
+ private boolean reverse;
+ private boolean numeric;
+ private boolean cmpPrint;
+ private boolean cmpAlpha;
+ private boolean cmpICase;
+ private boolean noBlanks;
+
+ public SortCommand() {
+ super(help_super);
+ registerArguments(argFile, argOut, argField, argFieldSep, argMerge, argUnique, argNumeric, argReverse);
+ registerArguments(argCmpPrint, argCmpAlpha, argCmpICase, argNoBlanks, argCheck);
+
+ registerArguments(argSort);
+ }
+
+ public void execute() {
+ err = getError().getPrintWriter();
+ parseOptions();
+
+ try {
+ if (outputFile != null) {
+ out = new PrintWriter(outputFile);
+ } else {
+ out = getOutput().getPrintWriter();
+ }
+ sortOne();
+ } catch (IOException e) {
+ //
+ } finally {
+ //IOUtils.close(true, out);
+ exit(rc);
+ }
+ }
+
+ private void sortOne() {
+ // OPTIMIZE
+ // This is probably effecient enough for most use cases, but alot
+ // can be done to make this run faster, and not do so much buffering.
+ // But it works for now...
+ // Also of note, the -m (merge only) option is basically ignore, as
+ // we're blindly sorting and merging all in one shot with Collections
+ // merge sort. Again, not effecient, but it works.
+ Comparator<String> cmp = new FieldComparator();
+ List<String> allLines = new LinkedList();
+
+ for (File file : files) {
+ List<String> lines;
+ if (file.getName().equals("-")) {
+ lines = IOUtils.readLines(getInput().getReader());
+ } else {
+ lines = IOUtils.readLines(file);
+ }
+ if (lines == null) {
+ error("Problem reading file: " + file.getName());
+ rc = 1;
+ continue;
+ }
+ allLines.addAll(lines);
+ }
+
+ if (argField.isSet()) {
+ Collections.sort(allLines, cmp);
+ } else {
+ Collections.sort(allLines);
+ }
+ for (String line : allLines) {
+ out.println(line);
+ }
+ }
+
+ private void sortTwo() {
+
+ }
+
+ private void parseOptions(){
+ if (argFile.isSet()) {
+ files = Arrays.asList(argFile.getValues());
+ } else {
+ files = new ArrayList<File>(1);
+ files.add(new File("-"));
+ }
+ if (argField.isSet()) {
+ ranges = argField.getValues();
+ }
+ if (argFieldSep.isSet()) {
+ fieldSep = argFieldSep.getValue();
+ }
+ if (argOut.isSet()) {
+ outputFile = argOut.getValue();
+ }
+ check = argCheck.isSet();
+ merge = argMerge.isSet();
+ unique = argUnique.isSet();
+ numeric = argNumeric.isSet();
+ reverse = argReverse.isSet();
+ cmpPrint = argCmpPrint.isSet();
+ cmpAlpha = argCmpAlpha.isSet();
+ cmpICase = argCmpICase.isSet();
+ noBlanks = argNoBlanks.isSet();
+
+ sort = argSort.isSet() ? argSort.getValue() : SORT_LAST;
+ }
+
+ private void error(String s) {
+ err.println(s);
+ }
+
+ private void debug(String s) {
+ if (DEBUG) {
+ error(s);
+ }
+ }
+}
Modified: trunk/cli/src/commands/org/jnode/command/util/IOUtils.java
===================================================================
--- trunk/cli/src/commands/org/jnode/command/util/IOUtils.java 2009-05-18 13:15:53 UTC (rev 5496)
+++ trunk/cli/src/commands/org/jnode/command/util/IOUtils.java 2009-05-18 22:26:09 UTC (rev 5497)
@@ -529,6 +529,18 @@
return input;
}
+ public static List<String> readLines(File file) {
+ BufferedReader reader = openBufferedReader(file);
+ if (reader == null) {
+ return null;
+ }
+ try {
+ return readLines(reader);
+ } finally {
+ close(reader);
+ }
+ }
+
public static List<String> readLines(Reader reader) {
return readLines(new BufferedReader(reader, BUFFER_SIZE), -1);
}
Modified: trunk/cli/src/test/org/jnode/test/command/file/all-file-tests.xml
===================================================================
--- trunk/cli/src/test/org/jnode/test/command/file/all-file-tests.xml 2009-05-18 13:15:53 UTC (rev 5496)
+++ trunk/cli/src/test/org/jnode/test/command/file/all-file-tests.xml 2009-05-18 22:26:09 UTC (rev 5497)
@@ -4,6 +4,7 @@
<include setName="grep-command-tests.xml"/>
<include setName="head-command-tests.xml"/>
<include setName="paste-command-tests.xml"/>
+ <include setName="sort-command-tests.xml"/>
<include setName="tail-command-tests.xml"/>
<include setName="wc-command-tests.xml"/>
</testSet>
Added: trunk/cli/src/test/org/jnode/test/command/file/sort-command-tests.xml
===================================================================
--- trunk/cli/src/test/org/jnode/test/command/file/sort-command-tests.xml (rev 0)
+++ trunk/cli/src/test/org/jnode/test/command/file/sort-command-tests.xml 2009-05-18 22:26:09 UTC (rev 5497)
@@ -0,0 +1,131 @@
+<testSet title="sort command tests">
+ <!--
+ First some tests for the default paramaters
+ -->
+ <testSpec title="whole-line 1" command="sort" runMode="AS_ALIAS" rc="0">
+ <input>d
+c
+b
+a
+</input>
+ <output>a
+b
+c
+d
+</output>
+ </testSpec>
+ <testSpec title="single-field full default-sep" command="sort" runMode="AS_ALIAS" rc="0">
+ <arg>-k</arg>
+ <arg>2,2</arg>
+ <input>1 d
+3 b
+2 c
+4 a
+</input>
+ <output>4 a
+3 b
+2 c
+1 d
+</output>
+ </testSpec>
+
+ <!--
+ The next few tests are aimed at the various combinations of key-field selection
+ -->
+ <testSpec title="single-field full custom-sep" command="sort" runMode="AS_ALIAS" rc="0">
+ <arg>-t</arg>
+ <arg>;</arg>
+ <arg>-k</arg>
+ <arg>2,2</arg>
+ <input>c;j;2
+k;h;4
+i;q;1
+p;f;3
+</input>
+ <output>p;f;3
+k;h;4
+c;j;2
+i;q;1
+</output>
+ </testSpec>
+ <testSpec title="single-field partial custom-sep 1" command="sort" runMode="AS_ALIAS" rc="0">
+ <arg>-t</arg>
+ <arg>;</arg>
+ <arg>-k</arg>
+ <arg>2.2,2.2</arg>
+ <input>k;jc;4
+o;ad;9
+i;la;2
+w;xb;5
+</input>
+ <output>i;la;2
+w;xb;5
+k;jc;4
+o;ad;9
+</output>
+ </testSpec>
+ <testSpec title="single-field partial custom-sep 2" command="sort" runMode="AS_ALIAS" rc="0">
+ <arg>-t</arg>
+ <arg>;</arg>
+ <arg>-k</arg>
+ <arg>1.1,1.2</arg>
+ <input>awq;1
+ajk;4
+aon;2
+alm;3
+</input>
+ <output>ajk;4
+alm;3
+aon;2
+awq;1
+</output>
+ </testSpec>
+ <testSpec title="multi-field full custom-sep 1" command="sort" runMode="AS_ALIAS" rc="0">
+ <arg>-t</arg>
+ <arg>;</arg>
+ <arg>-k</arg>
+ <arg>2,3</arg>
+ <input>3;a;b
+2;b;a
+4;a;a
+1;b;b
+</input>
+ <output>4;a;a
+3;a;b
+2;b;a
+1;b;b
+</output>
+ </testSpec>
+ <testSpec title="multi-field full custom-sep 2" command="sort" runMode="AS_ALIAS" rc="0">
+ <arg>-t</arg>
+ <arg>;</arg>
+ <arg>-k</arg>
+ <arg>2,3</arg>
+ <input>2;;ba
+4;aa;
+1;b;b
+3;a;b
+</input>
+ <output>4;aa;
+3;a;b
+2;;ba
+1;b;b
+</output>
+ </testSpec>
+ <testSpec title="multi-field partial 1" command="sort" runMode="AS_ALIAS" rc="0">
+ <arg>-t</arg>
+ <arg>;</arg>
+ <arg>-k</arg>
+ <arg>2.2,3.2</arg>
+ <input>2;yab;aay
+3;xaa;abx
+4;zaa;aaz
+1;wba;aaw
+</input>
+ <output>4;zaa;aaz
+3;xaa;abx
+2;yab;aay
+1;wba;aaw
+</output>
+ </testSpec>
+</testSet>
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <fd...@us...> - 2009-08-15 09:25:03
|
Revision: 5642
http://jnode.svn.sourceforge.net/jnode/?rev=5642&view=rev
Author: fduminy
Date: 2009-08-15 09:24:53 +0000 (Sat, 15 Aug 2009)
Log Message:
-----------
committed patch from zephyr (http://www.jnode.org/user/9083) for the 'tee' command (http://www.jnode.org/node/3061)
Modified Paths:
--------------
trunk/cli/descriptors/org.jnode.command.file.xml
trunk/cli/src/test/org/jnode/test/command/file/all-file-tests.xml
Added Paths:
-----------
trunk/cli/src/commands/org/jnode/command/file/TeeCommand.java
trunk/cli/src/test/org/jnode/test/command/file/tee-command-tests.xml
Modified: trunk/cli/descriptors/org.jnode.command.file.xml
===================================================================
--- trunk/cli/descriptors/org.jnode.command.file.xml 2009-08-14 16:59:45 UTC (rev 5641)
+++ trunk/cli/descriptors/org.jnode.command.file.xml 2009-08-15 09:24:53 UTC (rev 5642)
@@ -44,6 +44,7 @@
<alias name="rm" class="org.jnode.command.file.DeleteCommand"/>
<alias name="sort" class="org.jnode.command.file.SortCommand"/>
<alias name="tail" class="org.jnode.command.file.TailCommand"/>
+ <alias name="tee" class="org.jnode.command.file.TeeCommand"/>
<alias name="touch" class="org.jnode.command.file.TouchCommand"/>
<alias name="wc" class="org.jnode.command.file.WcCommand"/>
</extension>
@@ -351,6 +352,16 @@
</repeat>
</sequence>
</syntax>
+ <syntax alias="tee">
+ <sequence>
+ <optionSet label="globals">
+ <option argLabel="append" shortName="a" longName="append"/>
+ </optionSet>
+ <repeat>
+ <argument argLabel="files"/>
+ </repeat>
+ </sequence>
+ </syntax>
<syntax alias="touch">
<argument argLabel="file" description="touch the given file"/>
</syntax>
Added: trunk/cli/src/commands/org/jnode/command/file/TeeCommand.java
===================================================================
--- trunk/cli/src/commands/org/jnode/command/file/TeeCommand.java (rev 0)
+++ trunk/cli/src/commands/org/jnode/command/file/TeeCommand.java 2009-08-15 09:24:53 UTC (rev 5642)
@@ -0,0 +1,170 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2003-2009 JNode.org
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; If not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+package org.jnode.command.file;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.jnode.command.util.IOUtils;
+import org.jnode.shell.AbstractCommand;
+import org.jnode.shell.syntax.Argument;
+import org.jnode.shell.syntax.FileArgument;
+import org.jnode.shell.syntax.FlagArgument;
+
+/**
+ * Copy standard input to standard output, making a copy in zero or more files.<br>
+ * Implementation based on:
+ * http://www.opengroup.org/onlinepubs/9699919799/utilities/tee.html.
+ */
+public class TeeCommand extends AbstractCommand {
+
+ /** Help text for the parameter. */
+ private static final String HELP_FILE = "One or more files that will receive the \"tee-d\" output";
+
+ /** Help text for the append switch. */
+ private static final String HELP_APPEND = "Append to the given FILEs, do not overwrite";
+
+ /** Help text for the command. */
+ private static final String HELP_SUPER = "Copy standard input to each FILE, and also to standard outputd";
+
+ /** The file argument. */
+ private final FileArgument argFile;
+
+ /** The append switch. */
+ private final FlagArgument argAppend;
+
+ /** The standard input. */
+ private InputStream stdin;
+
+ /** The standard output. */
+ private OutputStream stdout;
+
+ /** The files that will receive the output. */
+ private File[] files;
+
+ /** The return code of the command. */
+ private int returnCode = 0;
+
+ /** Flag to indicate if the files should be appended. */
+ private boolean appendFiles;
+
+ /**
+ * In the documentation it is stated that a minimum of 13 files must be
+ * supported. Limit the command to only accept a maximum of 13 files to
+ * limit resource usage.
+ */
+ private static final int MAX_NUMBER_OF_FILES = 13;
+
+ /** Buffer used in stream copies. */
+ private static final int BUFFER_SIZE = 8192;
+
+ /**
+ * Default constructor.
+ */
+ public TeeCommand() {
+ super(HELP_SUPER);
+ int fileFlags = Argument.MULTIPLE;
+ argFile = new FileArgument("files", fileFlags, HELP_FILE);
+ argAppend = new FlagArgument("append", 0, HELP_APPEND);
+ registerArguments(argFile, argAppend);
+ }
+
+ /**
+ * Used to run this command independently.
+ *
+ * @param args the arguments passed to the command
+ * @throws Exception if an error occurs
+ */
+ public static void main(String[] args) throws Exception {
+ new TeeCommand().execute(args);
+ }
+
+ @Override
+ public void execute() throws IOException {
+ OutputStream out = null;
+ byte[] buffer = new byte[BUFFER_SIZE];
+
+ stdin = getInput().getInputStream();
+ stdout = getOutput().getOutputStream();
+
+ // Parse the command arguments
+ files = argFile.getValues();
+
+ if (files == null || files.length == 0) {
+ // The command is simply ignored if there are no files
+ // Just copy the input to the output and return
+ IOUtils.copyStream(stdin, stdout, buffer);
+ exit(returnCode);
+ }
+
+ if (argAppend.isSet()) {
+ appendFiles = true;
+ }
+
+ // A maximum of MAX_NUMBER_OF_FILES will be used
+ int numberOfFiles = files.length > MAX_NUMBER_OF_FILES ? MAX_NUMBER_OF_FILES : files.length;
+
+ int successfullOpenFiles = 0;
+
+ // Create an array to hold all output files
+ OutputStream[] outFiles = new OutputStream[numberOfFiles];
+
+ try {
+ // Open all output files
+ for (int i = 0; i < numberOfFiles; i++) {
+ if ((out = IOUtils.openOutputstream(files[i], appendFiles)) != null) {
+ outFiles[successfullOpenFiles++] = out;
+ }
+ }
+
+ int count = 0;
+ do {
+ count = stdin.read(buffer);
+ for (int i = 0; i < successfullOpenFiles; i++) {
+ try {
+ outFiles[i].write(buffer, 0, count);
+ } catch (IOException e) {
+ // Only the return code is updated
+ returnCode++;
+ }
+
+ }
+ stdout.write(buffer, 0, count);
+ } while (!(count < BUFFER_SIZE));
+
+ } finally {
+ // Close all open output files
+ for (int i = 0; i < successfullOpenFiles; i++) {
+ try {
+ outFiles[i].close();
+ } catch (IOException e) {
+ // Nothing to do in this case
+ // Just continue closing the files
+ }
+ }
+ }
+
+ // Returns the code
+ exit(returnCode);
+ }
+}
Modified: trunk/cli/src/test/org/jnode/test/command/file/all-file-tests.xml
===================================================================
--- trunk/cli/src/test/org/jnode/test/command/file/all-file-tests.xml 2009-08-14 16:59:45 UTC (rev 5641)
+++ trunk/cli/src/test/org/jnode/test/command/file/all-file-tests.xml 2009-08-15 09:24:53 UTC (rev 5642)
@@ -6,5 +6,6 @@
<include setName="paste-command-tests.xml"/>
<include setName="sort-command-tests.xml"/>
<include setName="tail-command-tests.xml"/>
+ <include setName="tee-command-tests.xml"/>
<include setName="wc-command-tests.xml"/>
</testSet>
Added: trunk/cli/src/test/org/jnode/test/command/file/tee-command-tests.xml
===================================================================
--- trunk/cli/src/test/org/jnode/test/command/file/tee-command-tests.xml (rev 0)
+++ trunk/cli/src/test/org/jnode/test/command/file/tee-command-tests.xml 2009-08-15 09:24:53 UTC (rev 5642)
@@ -0,0 +1,255 @@
+<testSet title="tee command tests">
+ <plugin id="org.jnode.command.file"/>
+ <plugin id="org.jnode.shell.bjorne" class="org.jnode.test.shell.bjorne.BjornePseudoPlugin"/>
+ <testSpec title="no file" command="tee" runMode="AS_ALIAS" rc="0">
+ <input>1234
+</input>
+ <output>1234
+</output>
+ </testSpec>
+ <testSpec title="single-file" command="run" runMode="AS_SCRIPT" rc="0">
+ <script>#!bjorne
+ echo 1234 | tee @TEMP_DIR@/out
+ </script>
+ <file name="out" input="false">1234
+</file>
+ <output>1234
+</output>
+ </testSpec>
+ <testSpec title="max-files" command="run" runMode="AS_SCRIPT" rc="0">
+ <script>#!bjorne
+ echo 1234 | tee @TEMP_DIR@/out @TEMP_DIR@/out_1 @TEMP_DIR@/out_2 @TEMP_DIR@/out_3 @TEMP_DIR@/out_4 @TEMP_DIR@/out_5 @TEMP_DIR@/out_6 @TEMP_DIR@/out_7 @TEMP_DIR@/out_8 @TEMP_DIR@/out_9 @TEMP_DIR@/out_10 @TEMP_DIR@/out_11 @TEMP_DIR@/out_12
+ </script>
+ <file name="out" input="false">1234
+</file>
+ <file name="out_1" input="false">1234
+</file>
+ <file name="out_2" input="false">1234
+</file>
+ <file name="out_3" input="false">1234
+</file>
+ <file name="out_4" input="false">1234
+</file>
+ <file name="out_5" input="false">1234
+</file>
+ <file name="out_6" input="false">1234
+</file>
+ <file name="out_7" input="false">1234
+</file>
+ <file name="out_8" input="false">1234
+</file>
+ <file name="out_9" input="false">1234
+</file>
+ <file name="out_10" input="false">1234
+</file>
+ <file name="out_11" input="false">1234
+</file>
+ <file name="out_12" input="false">1234
+</file>
+ <output>1234
+</output>
+ </testSpec>
+ <testSpec title="more-then-max-files" command="run" runMode="AS_SCRIPT" rc="0">
+ <script>#!bjorne
+ echo 1234 | tee @TEMP_DIR@/out @TEMP_DIR@/out_1 @TEMP_DIR@/out_2 @TEMP_DIR@/out_3 @TEMP_DIR@/out_4 @TEMP_DIR@/out_5 @TEMP_DIR@/out_6 @TEMP_DIR@/out_7 @TEMP_DIR@/out_8 @TEMP_DIR@/out_9 @TEMP_DIR@/out_10 @TEMP_DIR@/out_11 @TEMP_DIR@/out_12 @TEMP_DIR@/out_13
+ </script>
+ <file name="out" input="false">1234
+</file>
+ <file name="out_1" input="false">1234
+</file>
+ <file name="out_2" input="false">1234
+</file>
+ <file name="out_3" input="false">1234
+</file>
+ <file name="out_4" input="false">1234
+</file>
+ <file name="out_5" input="false">1234
+</file>
+ <file name="out_6" input="false">1234
+</file>
+ <file name="out_7" input="false">1234
+</file>
+ <file name="out_8" input="false">1234
+</file>
+ <file name="out_9" input="false">1234
+</file>
+ <file name="out_10" input="false">1234
+</file>
+ <file name="out_11" input="false">1234
+</file>
+ <file name="out_12" input="false">1234
+</file>
+ <output>1234
+</output>
+ </testSpec>
+
+
+ <testSpec title="append-single-file" command="run" runMode="AS_SCRIPT" rc="0">
+ <script>#!bjorne
+ echo 1234 | tee -a @TEMP_DIR@/out
+ </script>
+ <file name="out" input="true">Already in File out
+</file>
+ <file name="out" input="false">Already in File out
+1234
+</file>
+ <output>1234
+</output>
+ </testSpec>
+ <testSpec title="append-max-files" command="run" runMode="AS_SCRIPT" rc="0">
+ <script>#!bjorne
+ echo 1234 | tee -a @TEMP_DIR@/out @TEMP_DIR@/out_1 @TEMP_DIR@/out_2 @TEMP_DIR@/out_3 @TEMP_DIR@/out_4 @TEMP_DIR@/out_5 @TEMP_DIR@/out_6 @TEMP_DIR@/out_7 @TEMP_DIR@/out_8 @TEMP_DIR@/out_9 @TEMP_DIR@/out_10 @TEMP_DIR@/out_11 @TEMP_DIR@/out_12
+ </script>
+
+ <!-- Exiting files -->
+ <file name="out" input="true">Already in File out
+</file>
+ <file name="out_1" input="true">Already in File out_1
+</file>
+ <file name="out_2" input="true">Already in File out_2
+</file>
+ <file name="out_3" input="true">Already in File out_3
+</file>
+ <file name="out_4" input="true">Already in File out_4
+</file>
+ <file name="out_5" input="true">Already in File out_5
+</file>
+ <file name="out_6" input="true">Already in File out_6
+</file>
+ <file name="out_7" input="true">Already in File out_7
+</file>
+ <file name="out_8" input="true">Already in File out_8
+</file>
+ <file name="out_9" input="true">Already in File out_9
+</file>
+ <file name="out_10" input="true">Already in File out_10
+</file>
+ <file name="out_11" input="true">Already in File out_11
+</file>
+ <file name="out_12" input="true">Already in File out_12
+</file>
+
+ <!-- Output files -->
+ <file name="out" input="false">Already in File out
+1234
+</file>
+ <file name="out_1" input="false">Already in File out_1
+1234
+</file>
+ <file name="out_2" input="false">Already in File out_2
+1234
+</file>
+ <file name="out_3" input="false">Already in File out_3
+1234
+</file>
+ <file name="out_4" input="false">Already in File out_4
+1234
+</file>
+ <file name="out_5" input="false">Already in File out_5
+1234
+</file>
+ <file name="out_6" input="false">Already in File out_6
+1234
+</file>
+ <file name="out_7" input="false">Already in File out_7
+1234
+</file>
+ <file name="out_8" input="false">Already in File out_8
+1234
+</file>
+ <file name="out_9" input="false">Already in File out_9
+1234
+</file>
+ <file name="out_10" input="false">Already in File out_10
+1234
+</file>
+ <file name="out_11" input="false">Already in File out_11
+1234
+</file>
+ <file name="out_12" input="false">Already in File out_12
+1234
+</file>
+ <output>1234
+</output>
+ </testSpec>
+ <testSpec title="append-more-than-max-files" command="run" runMode="AS_SCRIPT" rc="0">
+ <script>#!bjorne
+ echo 1234 | tee -a @TEMP_DIR@/out @TEMP_DIR@/out_1 @TEMP_DIR@/out_2 @TEMP_DIR@/out_3 @TEMP_DIR@/out_4 @TEMP_DIR@/out_5 @TEMP_DIR@/out_6 @TEMP_DIR@/out_7 @TEMP_DIR@/out_8 @TEMP_DIR@/out_9 @TEMP_DIR@/out_10 @TEMP_DIR@/out_11 @TEMP_DIR@/out_12 @TEMP_DIR@/out_13
+ </script>
+
+ <!-- Exiting files -->
+ <file name="out" input="true">Already in File out
+</file>
+ <file name="out_1" input="true">Already in File out_1
+</file>
+ <file name="out_2" input="true">Already in File out_2
+</file>
+ <file name="out_3" input="true">Already in File out_3
+</file>
+ <file name="out_4" input="true">Already in File out_4
+</file>
+ <file name="out_5" input="true">Already in File out_5
+</file>
+ <file name="out_6" input="true">Already in File out_6
+</file>
+ <file name="out_7" input="true">Already in File out_7
+</file>
+ <file name="out_8" input="true">Already in File out_8
+</file>
+ <file name="out_9" input="true">Already in File out_9
+</file>
+ <file name="out_10" input="true">Already in File out_10
+</file>
+ <file name="out_11" input="true">Already in File out_11
+</file>
+ <file name="out_12" input="true">Already in File out_12
+</file>
+ <file name="out_13" input="true">Already in File out_13
+</file>
+
+ <!-- Output files -->
+ <file name="out" input="false">Already in File out
+1234
+</file>
+ <file name="out_1" input="false">Already in File out_1
+1234
+</file>
+ <file name="out_2" input="false">Already in File out_2
+1234
+</file>
+ <file name="out_3" input="false">Already in File out_3
+1234
+</file>
+ <file name="out_4" input="false">Already in File out_4
+1234
+</file>
+ <file name="out_5" input="false">Already in File out_5
+1234
+</file>
+ <file name="out_6" input="false">Already in File out_6
+1234
+</file>
+ <file name="out_7" input="false">Already in File out_7
+1234
+</file>
+ <file name="out_8" input="false">Already in File out_8
+1234
+</file>
+ <file name="out_9" input="false">Already in File out_9
+1234
+</file>
+ <file name="out_10" input="false">Already in File out_10
+1234
+</file>
+ <file name="out_11" input="false">Already in File out_11
+1234
+</file>
+ <file name="out_12" input="false">Already in File out_12
+1234
+</file>
+ <file name="out_13" input="false">Already in File out_13
+</file>
+ <output>1234
+</output>
+ </testSpec>
+</testSet>
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ls...@us...> - 2009-10-20 21:23:10
|
Revision: 5684
http://jnode.svn.sourceforge.net/jnode/?rev=5684&view=rev
Author: lsantha
Date: 2009-10-20 21:23:04 +0000 (Tue, 20 Oct 2009)
Log Message:
-----------
Applied patch by Mark Kokish.
Modified Paths:
--------------
trunk/cli/descriptors/org.jnode.command.file.xml
trunk/cli/src/commands/org/jnode/command/file/DirCommand.java
Modified: trunk/cli/descriptors/org.jnode.command.file.xml
===================================================================
--- trunk/cli/descriptors/org.jnode.command.file.xml 2009-10-15 14:50:26 UTC (rev 5683)
+++ trunk/cli/descriptors/org.jnode.command.file.xml 2009-10-20 21:23:04 UTC (rev 5684)
@@ -262,7 +262,8 @@
<option argLabel="url" shortName="u" longName="url" description="print a hex dump of a URL"/>
</syntax>
<syntax alias="ls">
- <empty description="list the current directory"/>
+ <empty description="with -l, print sizes in human readable format (e.g., 1K 234M 2G)"/>
+ <option argLabel="humanReadable" shortName="h" longName="human-readable"/>
<repeat>
<argument argLabel="path" description="list files or directories"/>
</repeat>
Modified: trunk/cli/src/commands/org/jnode/command/file/DirCommand.java
===================================================================
--- trunk/cli/src/commands/org/jnode/command/file/DirCommand.java 2009-10-15 14:50:26 UTC (rev 5683)
+++ trunk/cli/src/commands/org/jnode/command/file/DirCommand.java 2009-10-20 21:23:04 UTC (rev 5684)
@@ -23,6 +23,7 @@
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
+import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Comparator;
@@ -31,6 +32,7 @@
import org.jnode.shell.AbstractCommand;
import org.jnode.shell.syntax.Argument;
import org.jnode.shell.syntax.FileArgument;
+import org.jnode.shell.syntax.FlagArgument;
/**
* @author epr
@@ -44,15 +46,18 @@
private static final SimpleDateFormat df = new SimpleDateFormat("yyyy.MM.dd HH:mm");
private static final String help_path = "the file or directory to list";
+ private static final String help_humanReadable = "with -l, print sizes in human readable format (e.g., 1K 234M 2G)";
private static final String help_super = "List files or directories";
private static final String fmt_no_path = "No such path: %s%n";
-
+
private final FileArgument argPath;
-
+ private final FlagArgument humanReadableArg;
+
public DirCommand() {
super(help_super);
+ humanReadableArg = new FlagArgument("humanReadable", Argument.OPTIONAL, help_humanReadable);
argPath = new FileArgument("path", Argument.OPTIONAL | Argument.MULTIPLE | Argument.EXISTING, help_path);
- registerArguments(argPath);
+ registerArguments(argPath, humanReadableArg);
}
public static void main(String[] args) throws Exception {
@@ -102,10 +107,9 @@
sb.setLength(0);
lastModified.setTime(f.lastModified());
if (f.isFile()) {
- String ln = String.valueOf(f.length()).concat("B");
+ String ln = formatSize(f.length());
int cnt = LEFT_MARGIN - ln.length();
- for (int j = 0; j < cnt; j++, sb.append(' '))
- ;
+ for (int j = 0; j < cnt; j++) sb.append(' ');
sb.append(ln);
sb.append(" ");
sb.append(df.format(lastModified));
@@ -125,4 +129,16 @@
out.println();
}
}
+
+ private static final String[] units = {"B", "K", "M", "G", "T", "P", "E", "Z", "Y"};
+
+ protected String formatSize(double bytes) {
+ if (humanReadableArg.isSet()) {
+ int index;
+ for (index = 0; bytes >= 1024; index++) bytes = bytes / 1024;
+ DecimalFormat df = new DecimalFormat("###0.0");
+ return df.format(bytes) + units[index];
+ } else
+ return bytes + "B";
+ }
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ls...@us...> - 2009-11-23 17:09:15
|
Revision: 5688
http://jnode.svn.sourceforge.net/jnode/?rev=5688&view=rev
Author: lsantha
Date: 2009-11-23 17:09:02 +0000 (Mon, 23 Nov 2009)
Log Message:
-----------
Extensions to du command. Applied patch by Mario Zsilak.
Modified Paths:
--------------
trunk/cli/descriptors/org.jnode.command.file.xml
trunk/cli/src/commands/org/jnode/command/file/DuCommand.java
Modified: trunk/cli/descriptors/org.jnode.command.file.xml
===================================================================
--- trunk/cli/descriptors/org.jnode.command.file.xml 2009-10-23 08:21:09 UTC (rev 5687)
+++ trunk/cli/descriptors/org.jnode.command.file.xml 2009-11-23 17:09:02 UTC (rev 5688)
@@ -151,14 +151,29 @@
<argument argLabel="path" description="list a file or directory"/>
</syntax>
<syntax alias="du">
- <sequence description="print file sizes">
+ <sequence description="Disk Usage - report the amount of disk space used by the specified directory and for each subdirectory.">
<repeat minCount="0">
<argument argLabel="directory" description="directory to start printing sizes recursively"/>
</repeat>
<optionSet>
- <option argLabel="sum" shortName="s" longName="summarize"/>
- <option argLabel="all" shortName="a" longName="all"/>
- <option argLabel="human-readable" shortName="h" longName="human-readable"/>
+ <option argLabel="all" shortName="a" longName="all"/>
+ <option argLabel="block-size-1" shortName="b" longName="bytes"/>
+ <option argLabel="total" shortName="c" longName="total"/>
+ <option argLabel="derefArgs" shortName="D" longName="dereference-args"/>
+ <option argLabel="human-readable-1024" shortName="h" longName="human-readable"/>
+ <option argLabel="human-readable-1000" shortName="H" longName="si"/>
+ <option argLabel="block-size-1024" shortName="k" longName="kilobytes"/>
+ <option argLabel="count-links" shortName="l" longName="count-links"/>
+ <option argLabel="dereference" shortName="L" longName="dereference"/>
+ <option argLabel="max-depth" shortName="" longName="max-depth"/> <!-- max-depth has no shortname -->
+ <option argLabel="block-size-1024x1024" shortName="m" longName="megabytes"/>
+ <option argLabel="summarize" shortName="s" longName="summarize"/>
+ <option argLabel="separate-dirs" shortName="S" longName="separate-dirs"/>
+ <option argLabel="one-file-system" shortName="x" longName="one-file-system"/> <!-- can't test this currently -->
+ <option argLabel="exclude" shortName="" longName="exclude"/> <!-- exclude has no shortname -->
+ <option argLabel="exclude-from" shortName="X" longName="exclude-from"/>
+ <option argLabel="block-size-custom" shortName="B" longName="block-size"/> <!-- not in man page, but works on unix like systems -->
+ <option argLabel="filesystem-block-size" shortName="" longName="fs-block-size"/> <!-- not in man page, but works on unix like systems -->
</optionSet>
</sequence>
</syntax>
Modified: trunk/cli/src/commands/org/jnode/command/file/DuCommand.java
===================================================================
--- trunk/cli/src/commands/org/jnode/command/file/DuCommand.java 2009-10-23 08:21:09 UTC (rev 5687)
+++ trunk/cli/src/commands/org/jnode/command/file/DuCommand.java 2009-11-23 17:09:02 UTC (rev 5688)
@@ -1,5 +1,5 @@
/*
- * $Id: CdCommand.java 4975 2009-02-02 08:30:52Z lsantha $
+ * $Id: DuCommand.java 4975 2009-02-02 08:30:52Z lsantha $
*
* Copyright (C) 2003-2009 JNode.org
*
@@ -22,175 +22,475 @@
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
-import java.util.Map;
-import java.util.NavigableMap;
-import java.util.TreeMap;
-import java.util.Map.Entry;
+import java.util.Stack;
+import javax.naming.NameNotFoundException;
+
+import org.apache.log4j.Logger;
import org.jnode.command.util.AbstractDirectoryWalker;
+import org.jnode.driver.Device;
+import org.jnode.driver.block.FSBlockDeviceAPI;
+import org.jnode.fs.service.FileSystemService;
+import org.jnode.naming.InitialNaming;
import org.jnode.shell.AbstractCommand;
import org.jnode.shell.syntax.Argument;
import org.jnode.shell.syntax.FileArgument;
import org.jnode.shell.syntax.FlagArgument;
+import org.jnode.shell.syntax.IntegerArgument;
+import org.jnode.shell.syntax.StringArgument;
import org.jnode.util.NumberUtils;
+import org.jnode.vm.VmExit;
-/*
+/**
* @author Alexander Kerner
+ * @author Mario Zsilak
*/
public class DuCommand extends AbstractCommand {
-
- private static final String err_perm = "Permission denied for '%s'%n";
-
- private abstract class Walker extends AbstractDirectoryWalker {
- protected final TreeMap<File, Long> map = new TreeMap<File, Long>();
- protected final boolean humanReadable;
+ private static final String HELP_SUPER =
+ "With no arguments, `du' reports the disk space for the current directory. Normally the disk space is printed in units of 1024 bytes, but this can be overridden";
+ private static final String HELP_DIR = "directory to start printing sizes recursively";
+ private static final String HELP_ALL = "Show counts for all files, not just directories.";
+ private static final String HELP_BLOCK_SIZE_1 =
+ "Print sizes in bytes, overriding the default block size";
+ private static final String HELP_TOTAL =
+ "Print a grand total of all arguments after all arguments have been processed. This can be used to find out the total disk usage of a given set of files or directories.";
+ private static final String HELP_DEREF_ARGS =
+ "Dereference symbolic links that are command line arguments. Does not affect other symbolic links. This is helpful for finding out the disk usage of directories, such as `/usr/tmp', which are often symbolic links.";
+ private static final String HELP_HUMAN_READABLE_1024 =
+ "Append a size letter such as `M' for megabytes to each size. Powers of 1024 are used, not 1000; `M' stands for 1,048,576 bytes. Use the `-H' or `--si' option if you prefer powers of 1000.";
+ private static final String HELP_HUMAN_READABLE_1000 =
+ "Append a size letter such as `M' for megabytes to each size. (SI is the International System of Units, which defines these letters as prefixes.) Powers of 1000 are used, not 1024; `M' stands for 1,000,000 bytes. Use the `-h' or `--human-readable' option if you prefer powers of 1024.";
+ private static final String HELP_BLOCK_SIZE_1024 =
+ "Print sizes in 1024-byte blocks, overriding the default block size";
+ private static final String HELP_COUNT_LINKS =
+ "Count the size of all files, even if they have appeared already (as a hard link).";
+ private static final String HELP_DEREF =
+ "Dereference symbolic links (show the disk space used by the file or directory that the link points to instead of the space used by the link).";
+ private static final String HELP_MAX_DEPTH =
+ "Show the total for each directory (and file if -all) that is at most MAX_DEPTH levels down from the root of the hierarchy. The root is at level 0, so `du --max-depth=0' is equivalent to `du -s'.";
+ private static final String HELP_BLOCK_SIZE_1024x1024 =
+ "Print sizes in megabyte (that is, 1,048,576-byte) blocks.";
+ private static final String HELP_SUM = "Display only a total for each argument.";
+ private static final String HELP_SEPERATE_DIRS =
+ "Report the size of each directory separately, not including the sizes of subdirectories.";
+ private static final String HELP_ONE_FS =
+ "Skip directories that are on different filesystems from the one that the argument being processed is on.";
+ private static final String HELP_EXCLUDE =
+ "When recursing, skip subdirectories or files matching PAT. For example, `du --exclude='*.o'' excludes files whose names end in `.o'.";
+ private static final String HELP_EXCLUDE_FROM =
+ "Like `--exclude', except take the patterns to exclude from FILE, one per line. If FILE is `-', take the patterns from standard input.";
+ private static final String HELP_BLOCK_SIZE_CUSTOM =
+ "Print sizes in the user defined block size, overriding the default block size";
+ private static final String HELP_FS_BLOCK_SIZE =
+ "Overrides the filesystem block size -- use it for testing";
- Walker(boolean humanReadable) {
- this.humanReadable = humanReadable;
+ private final FileArgument argDir =
+ new FileArgument("directory",
+ Argument.OPTIONAL | Argument.MULTIPLE | Argument.EXISTING, HELP_DIR);
+ private final FlagArgument argAll = new FlagArgument("all", Argument.OPTIONAL, HELP_ALL);
+ private final FlagArgument argBlockSize_1 =
+ new FlagArgument("block-size-1", Argument.OPTIONAL, HELP_BLOCK_SIZE_1);
+ private final FlagArgument argTotal = new FlagArgument("total", Argument.OPTIONAL, HELP_TOTAL);
+ private final FlagArgument argDerefArgs =
+ new FlagArgument("derefArgs", Argument.OPTIONAL, HELP_DEREF_ARGS);
+ private final FlagArgument argHumanReadable_1024 =
+ new FlagArgument("human-readable-1024", Argument.OPTIONAL, HELP_HUMAN_READABLE_1024);
+ private final FlagArgument argHumanReadable_1000 =
+ new FlagArgument("human-readable-1000", Argument.OPTIONAL, HELP_HUMAN_READABLE_1000);
+ private final FlagArgument argBlockSize_1024 =
+ new FlagArgument("block-size-1024", Argument.OPTIONAL, HELP_BLOCK_SIZE_1024);
+ private final FlagArgument argCountLinks =
+ new FlagArgument("count-links", Argument.OPTIONAL, HELP_COUNT_LINKS);
+ private final FlagArgument argDereference =
+ new FlagArgument("dereference", Argument.OPTIONAL, HELP_DEREF);
+ private final IntegerArgument argMaxDepth =
+ new IntegerArgument("max-depth", Argument.OPTIONAL, HELP_MAX_DEPTH);
+ private final FlagArgument argBlockSize_1024x1024 =
+ new FlagArgument("block-size-1024x1024", Argument.OPTIONAL, HELP_BLOCK_SIZE_1024x1024);
+ private final FlagArgument argSum = new FlagArgument("summarize", Argument.OPTIONAL, HELP_SUM);
+ private final FlagArgument argSeperateDirs =
+ new FlagArgument("separate-dirs", Argument.OPTIONAL, HELP_SEPERATE_DIRS);
+ private static final FlagArgument argOneFS =
+ new FlagArgument("one-file-system", Argument.OPTIONAL, HELP_ONE_FS);
+ private final StringArgument argExclude =
+ new StringArgument("exclude", Argument.OPTIONAL, HELP_EXCLUDE);
+ private static final StringArgument argExcludeFrom =
+ new StringArgument("exclude-from", Argument.OPTIONAL, HELP_EXCLUDE_FROM);
+ private final IntegerArgument argBlockSize_Custom =
+ new IntegerArgument("block-size-custom", Argument.OPTIONAL, HELP_BLOCK_SIZE_CUSTOM);
+ private final IntegerArgument argFilesystemBlockSize =
+ new IntegerArgument("filesystem-block-size", Argument.OPTIONAL, HELP_FS_BLOCK_SIZE);
+
+ private static final String ERR_PERMISSION = "Permission denied for '%s'%n";
+
+ private static final int DEFAULT_FILESYSTEM_BLOCK_SIZE = 1024;
+ private static final int DEFAULT_DISPLAY_BLOCK_SIZE = 1024;
+
+ private Logger logger = Logger.getLogger(getClass());
+
+ private int fsBlockSize;
+ private int displayBlockSize;
+ private PrintWriter out;
+ private PrintWriter err;
+
+ public static void main(String[] args) throws IOException {
+ new DuCommand().execute();
+ }
+
+ public DuCommand() {
+ super(HELP_SUPER);
+ registerArguments(argDir, argAll, argBlockSize_1, argTotal, argDerefArgs,
+ argHumanReadable_1024, argHumanReadable_1000, argBlockSize_1024, argCountLinks,
+ argDereference, argMaxDepth, argBlockSize_1024x1024, argSum, argSeperateDirs,
+ argOneFS, argExclude, argExcludeFrom, argBlockSize_Custom, argFilesystemBlockSize);
+ }
+
+ public void execute() throws IOException {
+
+ Walker walker = null;
+ File[] startPoints = null;
+
+ out = getOutput().getPrintWriter();
+ err = getError().getPrintWriter();
+
+ if (argAll.isSet() && argSum.isSet()) {
+ err.println("Summarize and show all not possible at the some time!");
+ throw new VmExit(1);
}
- @Override
- public void handleDir(File file) {
- handleAll(file);
+ if (argDerefArgs.isSet()) {
+ logger.warn(argDerefArgs.getLabel() + " is currently not supported");
}
- @Override
- public void handleFile(File file) {
- handleAll(file);
+ if (argOneFS.isSet()) {
+ logger.warn(argOneFS.getLabel() + " is currently not supported");
}
-
- @Override
- protected void handleRestrictedFile(File file) throws IOException {
- err.format(err_perm, file);
+
+ if (argExcludeFrom.isSet()) {
+ logger.warn(argExcludeFrom.getLabel() + " is currently not supported");
}
- private void handleAll(File file) {
- map.put(file, file.length());
+ if (argDereference.isSet()) {
+ logger.warn(argDereference.getLabel() + " is currently not supported");
}
- protected TreeMap<File, Long> summariseIt(TreeMap<File, Long> map) {
- TreeMap<File, Long> result = new TreeMap<File, Long>();
- NavigableMap<File, Long> navMap = map.descendingMap();
- Long tmpSize = 0L;
- while (navMap.size() != 0) {
- Entry<File, Long> e = navMap.pollFirstEntry();
- File key = e.getKey();
- Long value = e.getValue();
- tmpSize += key.length();
+ if (argCountLinks.isSet()) {
+ logger.warn(argCountLinks.getLabel() + " is currently not supported");
+ }
- if (key.isFile()) {
- result.put(key, value);
- } else if (key.isDirectory()) {
- result.put(key, tmpSize);
- } else {
- // ignore unknown file type
- }
+ startPoints = argDir.getValues();
+
+ if (startPoints.length == 0) {
+ startPoints = new File[] {new File(System.getProperty("user.dir"))};
+ }
+
+ if (argFilesystemBlockSize.isSet())
+ fsBlockSize = argFilesystemBlockSize.getValue();
+ else {
+ fsBlockSize = getFsBlockSize(startPoints[0]);
+ }
+
+ if (argBlockSize_Custom.isSet()) {
+ displayBlockSize = argBlockSize_Custom.getValue();
+ } else if (argBlockSize_1024x1024.isSet()) {
+ displayBlockSize = 1024 * 1024;
+ } else if (argBlockSize_1024.isSet()) {
+ displayBlockSize = 1024;
+ } else if (argBlockSize_1.isSet()) {
+ displayBlockSize = 1;
+ } else {
+ displayBlockSize = DEFAULT_DISPLAY_BLOCK_SIZE;
+ }
+
+ if (argSum.isSet() || argTotal.isSet()) {
+
+ long total = 0;
+
+ for (File start : startPoints) {
+ walker = new Walker(argMaxDepth, argExclude);
+ walker.walk(start);
+
+ printSize(start.getAbsolutePath(), walker.getSize());
+ total += walker.getSize();
}
- return result;
+
+ if (argTotal.isSet()) {
+ printSize("Total", total);
+ }
+ } else {
+ new Walker(argMaxDepth, argExclude).walk(startPoints);
}
}
- private class AllWalker extends Walker {
+ private void printFileSize(final File filename, final long size) {
+ if (argAll.isSet()) {
+ out.println(size + "\t" + filename);
+ }
+ }
- AllWalker(boolean humanReadable) {
- super(humanReadable);
+ private void printDirSize(final File filename, final long dirSizeOnly, final long subDirSize) {
+ if (!argSum.isSet()) {
+ if (argSeperateDirs.isSet()) {
+ out.println(sizeToString(dirSizeOnly) + "\t" + filename);
+ } else {
+ out.println(sizeToString(dirSizeOnly + subDirSize) + "\t" + filename);
+ }
}
+ }
- @Override
- protected void lastAction(boolean wasCancelled) {
- Map<File, Long> summarisedMap = summariseIt(map);
- for (Entry<File, Long> e : summarisedMap.entrySet()) {
- if (humanReadable)
- out.println(NumberUtils.toBinaryByte(e.getValue()) + "\t" + e.getKey());
- else
- out.println(e.getValue() + "\t" + e.getKey());
+ private void printSize(final String filename, final long size) {
+ out.println(sizeToString(size) + "\t" + filename);
+ }
+
+ private void log(String message) {
+ // logger.debug(message);
+ }
+
+ /**
+ * should be in NumberUtils I guess
+ *
+ * @param lenght in bytes of the file / directory
+ * @return the number of blocks it uses up depending on the int
+ * displayBlockSize
+ */
+ private long calc(long bytes) {
+
+ double factor = fsBlockSize / displayBlockSize;
+ long ret = -1;
+
+ if (fsBlockSize > displayBlockSize) {
+ if (bytes % displayBlockSize == 0) {
+ ret = bytes / displayBlockSize;
+ } else {
+ ret = (long) ((bytes / (fsBlockSize) + 1) * factor);
}
+ } else {
+ if (bytes % displayBlockSize == 0) {
+ ret = bytes / displayBlockSize;
+ } else {
+ ret = (long) ((bytes / (displayBlockSize) + 1));
+ }
}
+
+ return ret;
}
- private class OnlyDirsWalker extends Walker {
+ private String sizeToString(long size) {
- OnlyDirsWalker(boolean humanReadable) {
- super(humanReadable);
+ String retValue = null;
+
+ if (argHumanReadable_1024.isSet()) {
+ retValue = NumberUtils.toBinaryByte(size);
+ } else if (argHumanReadable_1000.isSet()) {
+ retValue = NumberUtils.toDecimalByte(size);
+ } else {
+ retValue = String.valueOf(size);
}
- @Override
- protected void lastAction(boolean wasCancelled) {
- Map<File, Long> summarisedMap = summariseIt(map);
- for (Entry<File, Long> e : summarisedMap.entrySet()) {
- if (e.getKey().isDirectory()) {
- if (humanReadable)
- out.println(NumberUtils.toBinaryByte(e.getValue()) + "\t" + e.getKey());
- else
- out.println(e.getValue() + "\t" + e.getKey());
+ return retValue;
+ }
+
+ /**
+ * taken from the DfCommand
+ */
+ private int getFsBlockSize(File file) throws IOException {
+
+ int retValue = DEFAULT_FILESYSTEM_BLOCK_SIZE; // default block size
+ FileSystemService fss = null;
+ Device device = null;
+ String path = null;
+ String mp = null;
+
+ try {
+ fss = InitialNaming.lookup(FileSystemService.NAME);
+ path = file.getCanonicalPath();
+ mp = null;
+
+ for (String mountPoint : fss.getMountPoints().keySet()) {
+ if (path.startsWith(mountPoint)) {
+ if (mp != null) {
+ if (!mp.startsWith(mountPoint)) {
+ continue;
+ }
+ }
+ mp = mountPoint;
}
}
+
+ if (mp != null) {
+ device = fss.getMountPoints().get(mp).getDevice();
+
+ if (device instanceof FSBlockDeviceAPI) {
+ retValue = ((FSBlockDeviceAPI) device).getSectorSize();
+
+ } else {
+ logger.warn("No FSBlockDeviceAPI device for device" + device);
+ logger.info("Using default block-size: " + DEFAULT_FILESYSTEM_BLOCK_SIZE);
+ logger.info("override with --fs-block-size");
+ }
+ } else {
+
+ logger.warn("No mount point found for " + path);
+
+ for (String mountPoint : fss.getMountPoints().keySet()) {
+ logger.warn("mountpoints on system: " + mountPoint);
+ }
+
+ logger.info("Using default block-size: " + DEFAULT_FILESYSTEM_BLOCK_SIZE);
+ logger.info("override with --fs-block-size");
+ }
+
+ } catch (NameNotFoundException e) {
+ logger.warn("FileSystemService lookup failed ...", e);
+ logger.info("Using default block-size: " + DEFAULT_FILESYSTEM_BLOCK_SIZE);
+ logger.info("override with --fs-block-size");
}
+
+ return retValue;
}
- private class TotalWalker extends Walker {
+ private class Directory {
+ private Directory parent = null;
+ private File directory = null;
+ private Stack<Directory> subDirs = null;
+ private long size = 0;
- TotalWalker(boolean humanReadable) {
- super(humanReadable);
+ public Directory(Directory parent, File directory) {
+ this.parent = parent;
+ this.directory = directory;
+ subDirs = new Stack<Directory>();
}
- @Override
- protected void lastAction(boolean wasCancelled) {
- TreeMap<File, Long> summarisedMap = summariseIt(map);
- Entry<File, Long> e = summarisedMap.firstEntry();
- if (humanReadable)
- out.println(NumberUtils.toBinaryByte(e.getValue()) + "\t" + e.getKey());
- else
- out.println(e.getValue() + "\t" + e.getKey());
+ public Directory addDirectory(File file) {
+ Directory retValue = null;
+ if (file.getParentFile().equals(directory)) {
+ retValue = new Directory(this, file);
+ subDirs.push(retValue);
+ } else {
+ logger.warn("addDirectory: tried to add " + file + " to " + directory);
+ }
+
+ return retValue;
}
- }
- private PrintWriter out;
- private PrintWriter err;
+ public void addFile(File file) {
+ if (!file.getParentFile().equals(directory)) {
+ logger.warn("addFile: tried to add " + file + " to " + directory);
+ }
- private static final String HELP_TOTAL = "display only a total for each argument";
- private static final String HELP_ALL = "write counts for all files, not just directories";
- private static final String HELP_SUPER = "print file sizes";
- private static final String HELP_DIR = "directory to start printing sizes";
- private static final String HELP_HUMAN_READABLE = "print sizes in human readable format (e.g., 1K 234M 2G)";
+ printFileSize(file, calc(file.length()));
+ size += calc(file.length());
+ }
- private final FlagArgument totalArg;
- private final FlagArgument allArg;
- private final FileArgument dirArg;
- private final FlagArgument humanReadableArg;
+ public Directory getParent() {
- public DuCommand() {
- super(HELP_SUPER);
- totalArg = new FlagArgument("sum", Argument.OPTIONAL, HELP_TOTAL);
- allArg = new FlagArgument("all", Argument.OPTIONAL, HELP_ALL);
- dirArg = new FileArgument("directory", Argument.OPTIONAL | Argument.MULTIPLE, HELP_DIR);
- humanReadableArg = new FlagArgument("human-readable", Argument.OPTIONAL, HELP_HUMAN_READABLE);
- registerArguments(totalArg, allArg, humanReadableArg, dirArg);
- }
+ long dirSize = size + calc(directory.length()); // only the size for
+ // this directory +
+ // files (in other
+ // words: excludes
+ // the size of
+ // subDirs)
+ long subDirSize = 0;
- public static void main(String[] args) throws IOException {
- new DuCommand().execute();
+ while (!subDirs.isEmpty()) {
+ subDirSize += subDirs.pop().getSize();
+ }
+
+ printDirSize(directory, dirSize, subDirSize);
+
+ size = dirSize + subDirSize;
+
+ return parent;
+ }
+
+ public long getSize() {
+ return size;
+ }
+
+ public boolean equals(Object other) {
+ boolean retValue = false;
+
+ if (other instanceof Directory) {
+ retValue = (other != null && ((Directory) other).directory.equals(this.directory));
+ } else if (other instanceof File) {
+ retValue = (other != null && ((File) other).equals(this.directory));
+ }
+
+ return retValue;
+ }
+
+ @Override
+ public String toString() {
+ return directory.toString();
+ }
}
- public void execute() throws IOException {
- out = getOutput().getPrintWriter();
- err = getError().getPrintWriter();
- Walker walker = null;
- if (totalArg.isSet()) {
- walker = new TotalWalker(humanReadableArg.isSet());
- } else if (allArg.isSet()) {
- walker = new AllWalker(humanReadableArg.isSet());
- } else {
- walker = new OnlyDirsWalker(humanReadableArg.isSet());
+ private class Walker extends AbstractDirectoryWalker {
+
+ long totalSize;
+ protected Directory root = null;
+ protected Directory currentDir = null;
+
+ private Walker(IntegerArgument argMaxDepth, StringArgument argExclude) {
+ super();
+
+ if (argMaxDepth.isSet()) {
+ super.setMaxDepth(argMaxDepth.getValue().longValue());
+ }
+
+ if (argExclude.isSet()) {
+ super.addFilter(new RegexPatternFilter(argExclude.getValue(), true));
+ }
}
-
- if (dirArg.isSet()) {
- walker.walk(dirArg.getValues());
- } else {
- walker.walk(new File(System.getProperty("user.dir")));
+
+ public long getSize() {
+ return totalSize;
}
+
+ @Override
+ protected void handleStartingDir(File file) throws IOException {
+ log("starting dir: " + file);
+ root = new Directory(null, file);
+ }
+
+ @Override
+ protected void lastAction(boolean wasCancelled) {
+ root.getParent();
+ totalSize = root.getSize();
+ }
+
+ @Override
+ public void handleDir(File file) {
+ log("handleDir: " + file);
+
+ if (currentDir == null || currentDir.equals(file)) {
+ currentDir = root;
+ return;
+ }
+
+ while (!currentDir.equals(file.getParentFile())) {
+ log("in while");
+ currentDir = currentDir.getParent();
+ }
+
+ currentDir = currentDir.addDirectory(file);
+ }
+
+ @Override
+ public void handleFile(File file) {
+ log("handleFile: " + file);
+
+ while (!currentDir.equals(file.getParentFile())) {
+ currentDir = currentDir.getParent();
+ }
+ currentDir.addFile(file);
+ }
+
+ @Override
+ protected void handleRestrictedFile(File file) throws IOException {
+ err.format(ERR_PERMISSION, file);
+ }
}
}
-
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ls...@us...> - 2009-12-03 21:19:08
|
Revision: 5689
http://jnode.svn.sourceforge.net/jnode/?rev=5689&view=rev
Author: lsantha
Date: 2009-12-03 21:18:57 +0000 (Thu, 03 Dec 2009)
Log Message:
-----------
Fixed NPE. Improved help. Applied patch by Mario Zsilak.
Modified Paths:
--------------
trunk/cli/descriptors/org.jnode.command.file.xml
trunk/cli/src/commands/org/jnode/command/file/DuCommand.java
Modified: trunk/cli/descriptors/org.jnode.command.file.xml
===================================================================
--- trunk/cli/descriptors/org.jnode.command.file.xml 2009-11-23 17:09:02 UTC (rev 5688)
+++ trunk/cli/descriptors/org.jnode.command.file.xml 2009-12-03 21:18:57 UTC (rev 5689)
@@ -173,10 +173,10 @@
<option argLabel="exclude" shortName="" longName="exclude"/> <!-- exclude has no shortname -->
<option argLabel="exclude-from" shortName="X" longName="exclude-from"/>
<option argLabel="block-size-custom" shortName="B" longName="block-size"/> <!-- not in man page, but works on unix like systems -->
- <option argLabel="filesystem-block-size" shortName="" longName="fs-block-size"/> <!-- not in man page, but works on unix like systems -->
+ <option argLabel="filesystem-block-size" shortName="" longName="fs-block-size"/> <!-- testing -->
</optionSet>
</sequence>
- </syntax>
+ </syntax>
<syntax alias="find">
<sequence description="find files or directories">
<repeat minCount="0">
Modified: trunk/cli/src/commands/org/jnode/command/file/DuCommand.java
===================================================================
--- trunk/cli/src/commands/org/jnode/command/file/DuCommand.java 2009-11-23 17:09:02 UTC (rev 5688)
+++ trunk/cli/src/commands/org/jnode/command/file/DuCommand.java 2009-12-03 21:18:57 UTC (rev 5689)
@@ -56,7 +56,7 @@
private static final String HELP_TOTAL =
"Print a grand total of all arguments after all arguments have been processed. This can be used to find out the total disk usage of a given set of files or directories.";
private static final String HELP_DEREF_ARGS =
- "Dereference symbolic links that are command line arguments. Does not affect other symbolic links. This is helpful for finding out the disk usage of directories, such as `/usr/tmp', which are often symbolic links.";
+ "Dereference symbolic links that are command line arguments. Does not affect other symbolic links. This is helpful for finding out the disk usage of directories, such as `/usr/tmp', which are often symbolic links. (not implemented";
private static final String HELP_HUMAN_READABLE_1024 =
"Append a size letter such as `M' for megabytes to each size. Powers of 1024 are used, not 1000; `M' stands for 1,048,576 bytes. Use the `-H' or `--si' option if you prefer powers of 1000.";
private static final String HELP_HUMAN_READABLE_1000 =
@@ -64,22 +64,22 @@
private static final String HELP_BLOCK_SIZE_1024 =
"Print sizes in 1024-byte blocks, overriding the default block size";
private static final String HELP_COUNT_LINKS =
- "Count the size of all files, even if they have appeared already (as a hard link).";
+ "Count the size of all files, even if they have appeared already (as a hard link). (not implemented";
private static final String HELP_DEREF =
- "Dereference symbolic links (show the disk space used by the file or directory that the link points to instead of the space used by the link).";
+ "Dereference symbolic links (show the disk space used by the file or directory that the link points to instead of the space used by the link). (not implemented";
private static final String HELP_MAX_DEPTH =
- "Show the total for each directory (and file if -all) that is at most MAX_DEPTH levels down from the root of the hierarchy. The root is at level 0, so `du --max-depth=0' is equivalent to `du -s'.";
+ "Show the total for each directory (and file if -all) that is at most MAX_DEPTH levels down from the root of the hierarchy. The root is at level 0, so `du --max-depth=0' is equivalent to `du -s'. (not tested)";
private static final String HELP_BLOCK_SIZE_1024x1024 =
"Print sizes in megabyte (that is, 1,048,576-byte) blocks.";
private static final String HELP_SUM = "Display only a total for each argument.";
private static final String HELP_SEPERATE_DIRS =
"Report the size of each directory separately, not including the sizes of subdirectories.";
private static final String HELP_ONE_FS =
- "Skip directories that are on different filesystems from the one that the argument being processed is on.";
+ "Skip directories that are on different filesystems from the one that the argument being processed is on. (not implemented)";
private static final String HELP_EXCLUDE =
- "When recursing, skip subdirectories or files matching PAT. For example, `du --exclude='*.o'' excludes files whose names end in `.o'.";
+ "When recursing, skip subdirectories or files matching PAT. For example, `du --exclude='*.o'' excludes files whose names end in `.o'. (not tested)";
private static final String HELP_EXCLUDE_FROM =
- "Like `--exclude', except take the patterns to exclude from FILE, one per line. If FILE is `-', take the patterns from standard input.";
+ "Like `--exclude', except take the patterns to exclude from FILE, one per line. If FILE is `-', take the patterns from standard input. (not implemented)";
private static final String HELP_BLOCK_SIZE_CUSTOM =
"Print sizes in the user defined block size, overriding the default block size";
private static final String HELP_FS_BLOCK_SIZE =
@@ -225,7 +225,7 @@
private void printFileSize(final File filename, final long size) {
if (argAll.isSet()) {
- out.println(size + "\t" + filename);
+ out.println(sizeToString(size) + "\t" + filename);
}
}
@@ -325,7 +325,7 @@
retValue = ((FSBlockDeviceAPI) device).getSectorSize();
} else {
- logger.warn("No FSBlockDeviceAPI device for device" + device);
+ logger.warn("No FSBlockDeviceAPI device for device: " + device);
logger.info("Using default block-size: " + DEFAULT_FILESYSTEM_BLOCK_SIZE);
logger.info("override with --fs-block-size");
}
@@ -386,12 +386,9 @@
public Directory getParent() {
- long dirSize = size + calc(directory.length()); // only the size for
- // this directory +
- // files (in other
- // words: excludes
- // the size of
- // subDirs)
+ long dirSize = size + calc(directory.length());
+ // only the size for this directory + files
+ // (in other words: excludes the size of subDirs)
long subDirSize = 0;
while (!subDirs.isEmpty()) {
@@ -408,6 +405,11 @@
public long getSize() {
return size;
}
+
+ @Override
+ public int hashCode() {
+ return directory.hashCode();
+ }
public boolean equals(Object other) {
boolean retValue = false;
@@ -450,18 +452,28 @@
}
@Override
+ /**
+ * Set the "root" Directory to the Starting Dir
+ */
protected void handleStartingDir(File file) throws IOException {
log("starting dir: " + file);
root = new Directory(null, file);
}
@Override
+ /**
+ * Calculate the "root" directory and reset the "current" directory .. we are done for now
+ */
protected void lastAction(boolean wasCancelled) {
root.getParent();
+ currentDir = null;
totalSize = root.getSize();
}
@Override
+ /**
+ * add the currently handled directory/file to the correct position in the hierarchy
+ */
public void handleDir(File file) {
log("handleDir: " + file);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ls...@us...> - 2011-08-07 08:53:47
|
Revision: 5844
http://jnode.svn.sourceforge.net/jnode/?rev=5844&view=rev
Author: lsantha
Date: 2011-08-07 08:53:41 +0000 (Sun, 07 Aug 2011)
Log Message:
-----------
Added default mode to 'thread' command to show a flat thread list sorted by id.
Modified Paths:
--------------
trunk/cli/descriptors/org.jnode.command.system.xml
trunk/cli/src/commands/org/jnode/command/system/ThreadCommand.java
Modified: trunk/cli/descriptors/org.jnode.command.system.xml
===================================================================
--- trunk/cli/descriptors/org.jnode.command.system.xml 2011-08-04 12:57:47 UTC (rev 5843)
+++ trunk/cli/descriptors/org.jnode.command.system.xml 2011-08-07 08:53:41 UTC (rev 5844)
@@ -288,6 +288,9 @@
<optional description="Display all extant JNode Threads">
<option argLabel="groupDump" shortName="g" longName="groupDump"/>
</optional>
+ <optional description="Display all threads in thread groups">
+ <option argLabel="verbose" shortName="v"/>
+ </optional>
<argument argLabel="threadName" description="Display the named Thread"/>
</syntax>
<syntax alias="vminfo">
Modified: trunk/cli/src/commands/org/jnode/command/system/ThreadCommand.java
===================================================================
--- trunk/cli/src/commands/org/jnode/command/system/ThreadCommand.java 2011-08-04 12:57:47 UTC (rev 5843)
+++ trunk/cli/src/commands/org/jnode/command/system/ThreadCommand.java 2011-08-07 08:53:41 UTC (rev 5844)
@@ -24,6 +24,8 @@
import java.security.AccessController;
import java.security.PrivilegedAction;
+import java.util.Comparator;
+import java.util.TreeSet;
import org.jnode.shell.AbstractCommand;
import org.jnode.shell.syntax.Argument;
import org.jnode.shell.syntax.FlagArgument;
@@ -36,11 +38,13 @@
* @author Ewout Prangsma (ep...@us...)
* @author Martin Husted Hartvig (ha...@jn...)
* @author cr...@jn...
+ * @author Levente S\u00e1ntha
*/
public class ThreadCommand extends AbstractCommand {
private static final String help_name = "the name of a specific thread to be printed";
- private static final String help_group = "if set, output a ThreadGroup dump";
+ private static final String help_group = "output a ThreadGroup dump";
+ private static final String help_verbose = "show all threads in thread groups";
private static final String help_super = "View info about all threads, or a specific thread";
private static final String SEPARATOR = ", ";
@@ -50,12 +54,14 @@
private final ThreadNameArgument argName;
private final FlagArgument argDump;
+ private final FlagArgument argVerbose;
public ThreadCommand() {
super(help_super);
argName = new ThreadNameArgument("threadName", Argument.OPTIONAL, help_name);
argDump = new FlagArgument("groupDump", Argument.OPTIONAL, help_group);
- registerArguments(argName, argDump);
+ argVerbose = new FlagArgument("verbose", Argument.OPTIONAL, help_verbose);
+ registerArguments(argName, argVerbose, argDump);
}
public static void main(String[] args) throws Exception {
@@ -82,11 +88,57 @@
// standard API.
grp.list();
} else {
- // Show the threads in the ThreadGroup tree.
- showThreads(grp, getOutput().getPrintWriter(), threadName);
+ if(!argVerbose.isSet() && !argName.isSet()) {
+ showDefaultInfo(grp);
+ } else {
+ // Show the threads in the ThreadGroup tree.
+ showThreads(grp, getOutput().getPrintWriter(), threadName);
+ }
}
}
+ private void showDefaultInfo(ThreadGroup grp) {
+ TreeSet<Thread> threadSet = new TreeSet<Thread>(new Comparator<Thread>() {
+ @Override
+ public int compare(Thread t1, Thread t2) {
+ return Long.valueOf(t1.getId()).compareTo(t2.getId());
+ }
+ });
+ findThreads(grp, threadSet);
+
+ PrintWriter out = getOutput().getPrintWriter();
+ for(final Thread thread : threadSet) {
+ VmThread vmThread = AccessController.doPrivileged(new PrivilegedAction<VmThread>() {
+ public VmThread run() {
+ return ThreadHelper.getVmThread(thread);
+ }
+ });
+ out.println(" " + thread.getId() + SEPARATOR + thread.getName() + SEPARATOR + thread.getPriority() +
+ SEPARATOR + vmThread.getThreadStateName());
+ }
+ }
+
+ private void findThreads(ThreadGroup grp, TreeSet<Thread> threadSet) {
+ final int max = grp.activeCount() * 2;
+ final Thread[] ts = new Thread[max];
+ grp.enumerate(ts);
+ for (int i = 0; i < max; i++) {
+ final Thread t = ts[i];
+ if (t != null) {
+ threadSet.add(t);
+ }
+ }
+ final int gmax = grp.activeGroupCount() * 2;
+ final ThreadGroup[] tgs = new ThreadGroup[gmax];
+ grp.enumerate(tgs);
+ for (int i = 0; i < gmax; i++) {
+ final ThreadGroup tg = tgs[i];
+ if (tg != null) {
+ findThreads(tg, threadSet);
+ }
+ }
+ }
+
/**
* Traverse the ThreadGroups threads and its child ThreadGroups printing
* information for each thread found. If 'threadName' is non-null, only
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ls...@us...> - 2011-08-17 19:41:34
|
Revision: 5851
http://jnode.svn.sourceforge.net/jnode/?rev=5851&view=rev
Author: lsantha
Date: 2011-08-17 19:41:28 +0000 (Wed, 17 Aug 2011)
Log Message:
-----------
Added shell command: cmp.
Modified Paths:
--------------
trunk/cli/descriptors/org.jnode.command.file.xml
Added Paths:
-----------
trunk/cli/src/commands/org/jnode/command/file/CmpCommand.java
Modified: trunk/cli/descriptors/org.jnode.command.file.xml
===================================================================
--- trunk/cli/descriptors/org.jnode.command.file.xml 2011-08-16 21:16:00 UTC (rev 5850)
+++ trunk/cli/descriptors/org.jnode.command.file.xml 2011-08-17 19:41:28 UTC (rev 5851)
@@ -26,6 +26,7 @@
<extension point="org.jnode.shell.aliases">
<alias name="cat" class="org.jnode.command.file.CatCommand"/>
<alias name="cd" class="org.jnode.command.file.CdCommand" internal="yes"/>
+ <alias name="cmp" class="org.jnode.command.file.CmpCommand"/>
<alias name="cp" class="org.jnode.command.file.CpCommand"/>
<alias name="cut" class="org.jnode.command.file.CutCommand"/>
<alias name="del" class="org.jnode.command.file.DeleteCommand"/>
@@ -74,6 +75,12 @@
<empty description="change the current directory to the 'user.home' directory"/>
<argument argLabel="directory" description="change the current directory to 'directory'"/>
</syntax>
+ <syntax alias="cmp">
+ <sequence description="compare two files">
+ <argument argLabel="file1"/>
+ <argument argLabel="file2"/>
+ </sequence>
+ </syntax>
<syntax alias="cp">
<sequence description="copy files or directories">
<optionSet>
Added: trunk/cli/src/commands/org/jnode/command/file/CmpCommand.java
===================================================================
--- trunk/cli/src/commands/org/jnode/command/file/CmpCommand.java (rev 0)
+++ trunk/cli/src/commands/org/jnode/command/file/CmpCommand.java 2011-08-17 19:41:28 UTC (rev 5851)
@@ -0,0 +1,123 @@
+package org.jnode.command.file;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import org.jnode.shell.AbstractCommand;
+import org.jnode.shell.syntax.Argument;
+import org.jnode.shell.syntax.FileArgument;
+
+/**
+ * Compare two files and report the first difference.
+ *
+ * @author Levente S\u00e1ntha
+ */
+public class CmpCommand extends AbstractCommand {
+
+ private static final int BUFFER_SIZE = 64 * 1024;
+
+ private static final String HELP_SUPER = "Compare two files";
+ private static final String HELP_FILE = "a file to compare";
+ private static final String ERR_FILE_INVALID = "%s is not a file%n";
+ private static final String MSG_DIFFER = "%s %s differ: byte %d, line %d%n";
+ private static final String MSG_EOF = "cmp: EOF on %s%n";
+
+ private final FileArgument file1Arg;
+ private final FileArgument file2Arg;
+
+ public CmpCommand() {
+ super(HELP_SUPER);
+
+ file1Arg = new FileArgument("file1", Argument.MANDATORY | Argument.EXISTING, HELP_FILE);
+ file2Arg = new FileArgument("file2", Argument.MANDATORY | Argument.EXISTING, HELP_FILE);
+
+ registerArguments(file1Arg, file2Arg);
+ }
+
+ public static void main(String[] args) throws Exception {
+ new CmpCommand().execute(args);
+ }
+
+ @Override
+ public void execute() throws IOException {
+
+ File file1 = file1Arg.getValue();
+ File file2 = file2Arg.getValue();
+
+ PrintWriter err = getError().getPrintWriter();
+
+ if (!file1.isFile()) {
+ err.format(ERR_FILE_INVALID, file1);
+ exit(1);
+ }
+
+ if (!file2.isFile()) {
+ err.format(ERR_FILE_INVALID, file2);
+ exit(1);
+ }
+
+ BufferedInputStream bis1 = null;
+ BufferedInputStream bis2 = null;
+
+ try {
+ bis1 = new BufferedInputStream(new FileInputStream(file1), BUFFER_SIZE);
+ bis2 = new BufferedInputStream(new FileInputStream(file2), BUFFER_SIZE);
+
+ long bc = 1;
+ long lc = 1;
+
+ while (true) {
+ int b1 = bis1.read();
+ int b2 = bis2.read();
+
+ if (b1 == -1 && b2 == -1)
+ //done
+ break;
+
+ if (b1 == -1) {
+ PrintWriter out = getOutput().getPrintWriter();
+ out.format(MSG_EOF, file1.toString());
+ exit(1);
+ return;
+ }
+
+ if (b2 == -1) {
+ PrintWriter out = getOutput().getPrintWriter();
+ out.format(MSG_EOF, file2.toString());
+ exit(1);
+ return;
+ }
+
+ if (b1 != b2) {
+ PrintWriter out = getOutput().getPrintWriter();
+ out.format(MSG_DIFFER, file1.toString(), file2.toString(), bc, lc);
+ exit(1);
+ return;
+ }
+
+ bc++;
+
+ if (b1 == (byte) '\n')
+ lc++;
+ }
+ } finally {
+ if (bis1 != null) {
+ try {
+ bis1.close();
+ } catch (IOException x) {
+ //ignore
+ }
+ }
+
+ if (bis2 != null) {
+ try {
+ bis2.close();
+ } catch (IOException x) {
+ //ignore
+ }
+ }
+ }
+ }
+}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ls...@us...> - 2013-02-13 20:12:40
|
Revision: 5947
http://jnode.svn.sourceforge.net/jnode/?rev=5947&view=rev
Author: lsantha
Date: 2013-02-13 20:12:29 +0000 (Wed, 13 Feb 2013)
Log Message:
-----------
Applied patch by Sebastian Ritter, implementing the uname command.
Modified Paths:
--------------
trunk/cli/descriptors/org.jnode.command.system.xml
Added Paths:
-----------
trunk/cli/src/commands/org/jnode/command/system/UnameCommand.java
Modified: trunk/cli/descriptors/org.jnode.command.system.xml
===================================================================
--- trunk/cli/descriptors/org.jnode.command.system.xml 2013-01-25 11:33:00 UTC (rev 5946)
+++ trunk/cli/descriptors/org.jnode.command.system.xml 2013-02-13 20:12:29 UTC (rev 5947)
@@ -15,13 +15,13 @@
<import plugin="org.jnode.shell.syntax"/>
<import plugin="org.jnode.util"/>
</requires>
-
+
<runtime>
<library name="jnode-cli.jar">
<export name="org.jnode.command.system.*"/>
</library>
</runtime>
-
+
<extension point="org.jnode.shell.aliases">
<alias name="alias" class="org.jnode.command.system.AliasCommand"/>
<alias name="bindkeys" class="org.jnode.command.system.BindKeysCommand"/>
@@ -50,9 +50,10 @@
<alias name="syntax" class="org.jnode.command.system.SyntaxCommand"/>
<alias name="terminate" class="org.jnode.command.system.TerminateCommand"/>
<alias name="thread" class="org.jnode.command.system.ThreadCommand"/>
+ <alias name="uname" class="org.jnode.command.system.UnameCommand"/>
<alias name="vminfo" class="org.jnode.command.system.VmInfoCommand"/>
</extension>
-
+
<extension point="org.jnode.shell.syntaxes">
<syntax alias="alias">
<empty description="List all aliases"/>
@@ -222,7 +223,7 @@
<option argLabel="minTotalSize" longName="minTotalSize"/>
<option argLabel="className" longName="className"/>
</optionSet>
- </syntax>
+ </syntax>
<syntax alias="page">
<empty description="Filter standard input a page (screen) at a time"/>
<argument argLabel="file" description="Output the file a page (screen) at a time"/>
@@ -294,13 +295,25 @@
</optional>
<argument argLabel="threadName" description="Display the named Thread"/>
</syntax>
+ <syntax alias="uname" description="Print operating system informations.">
+ <empty description="Print the hardware type on witch system is running; same like argument -m"/>
+ <optionSet>
+ <option argLabel="a" shortName="a"/>
+ <option argLabel="m" shortName="m"/>
+ <option argLabel="n" shortName="n"/>
+ <option argLabel="r" shortName="r"/>
+ <option argLabel="s" shortName="s"/>
+ <option argLabel="v" shortName="v"/>
+ </optionSet>
+ </syntax>
+
<syntax alias="vminfo">
<optional description="dump IRQ handler information">
<option argLabel="reset" longName="reset"/>
</optional>
</syntax>
</extension>
-
+
<extension point="org.jnode.security.permissions">
<permission class="java.util.PropertyPermission" name="*" actions="read,write"/>
<permission class="java.lang.RuntimePermission" name="getProtectionDomain"/>
@@ -317,5 +330,5 @@
<permission class="org.jnode.permission.JNodePermission" name="getVmClass"/>
<permission class="java.lang.reflect.ReflectPermission" name="suppressAccessChecks"/>
</extension>
-
+
</plugin>
Added: trunk/cli/src/commands/org/jnode/command/system/UnameCommand.java
===================================================================
--- trunk/cli/src/commands/org/jnode/command/system/UnameCommand.java (rev 0)
+++ trunk/cli/src/commands/org/jnode/command/system/UnameCommand.java 2013-02-13 20:12:29 UTC (rev 5947)
@@ -0,0 +1,145 @@
+/**
+ * Copyright (C) 2013 JNode.org
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; If not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+package org.jnode.command.system;
+
+import gnu.java.security.action.GetPropertiesAction;
+
+import java.security.AccessController;
+import java.util.Properties;
+
+import org.jnode.shell.AbstractCommand;
+import org.jnode.shell.syntax.Argument;
+import org.jnode.shell.syntax.FlagArgument;
+
+/**
+ * <code>uname</code> command prints informations about the operation system.
+ * With <code>a</code> argument the return syntax of uname posix is:
+ * <pre>sysname<SPACE>nodename<SPACE>release<SPACE>version<SPACE>machine<NL></pre>
+ * For example:
+ *
+ * <table border='1'>
+ * <tr><th rowspan='2'>Argument</th><th colspan='3'>Output</th></tr>
+ * <tr><th>JNode</th><th>MacOS 10.8.2</th><th>OpenSUSE 12</th></tr>
+ * <tr><td>m</td><td>${os.arch}</td><td>x86_64</td><td>i686</td></tr>
+ * <tr><td>n</td><td>${os.name}</td><td>my_mac</td><td>suse12</td></tr>
+ * <tr><td>r</td><td>${os.version}</td><td>12.2.0</td><td>3.1.0-1.2-default</td></tr>
+ * <tr><td>s</td><td>${os.name}</td><td>Darwin</td><td>Linux</td></tr>
+ * <tr><td>v</td><td>${os.name} ${os.version}</td><td>Darwin Kernel Version 12.2.0: Sat Aug 25 00:48:52 PDT 2012; root:xnu-2050.18.24~1/RELEASE_X86_64</td><td>#1 SMP Thu Nov 3 14:45:45 UTC 2011 (187dde0)</td></tr>
+ * </table>
+ * @author bastie
+ *
+ */
+public final class UnameCommand extends AbstractCommand {
+
+ /**
+ * Command description
+ */
+ private static final String HELP_UNAME = "Print operating system informations.";
+ /**
+ * Description of <code>a</code> argument.
+ */
+ private static final String HELP_ALL = "Same as all params [mnrsv] using.";
+ /**
+ * Description of <code>m</code> argument.
+ */
+ private static final String HELP_M = "Print the hardware type on witch system is running.";
+ /**
+ * Description of <code>n</code> argument.
+ */
+ private static final String HELP_N = "Print the name of network implementation.";
+ /**
+ * Description of <code>r</code> argument.
+ */
+ private static final String HELP_R = "Print the current release level of os implementation.";
+ /**
+ * Description of <code>s</code> argument.
+ */
+ private static final String HELP_S = "Print the name of implementation.";
+ /**
+ * Description of <code>v</code> argument.
+ */
+ private static final String HELP_V = "Print the current version level of release level of os implementation.";
+
+ /**
+ * Flag for argument 'a'.
+ */
+ private final FlagArgument allArg;
+ /**
+ * Flag for argument 'm'.
+ */
+ private final FlagArgument hardwareMaschineArg;
+ /**
+ * Flag for argument 'n'.
+ */
+ private final FlagArgument networkImplNameArg;
+ /**
+ * Flag for argument 'r'.
+ */
+ private final FlagArgument releaseLevelArg;
+ /**
+ * Flag for argument 's'.
+ */
+ private final FlagArgument implNameArg;
+ /**
+ * Flag for argument 'v'.
+ */
+ private final FlagArgument versionArg;
+
+
+ /**
+ * Construct new uname command implementation with "amnrsv" arguments.
+ */
+ public UnameCommand() {
+ super (HELP_UNAME);
+ allArg = new FlagArgument("a", Argument.OPTIONAL | Argument.SINGLE, HELP_ALL);
+ hardwareMaschineArg = new FlagArgument("m", Argument.OPTIONAL | Argument.SINGLE, HELP_M);
+ networkImplNameArg = new FlagArgument("n", Argument.OPTIONAL | Argument.SINGLE, HELP_N);
+ releaseLevelArg = new FlagArgument("r", Argument.OPTIONAL | Argument.SINGLE, HELP_R);
+ implNameArg = new FlagArgument("s", Argument.OPTIONAL | Argument.SINGLE, HELP_S);
+ versionArg = new FlagArgument("v", Argument.OPTIONAL | Argument.SINGLE, HELP_V);
+ registerArguments(allArg, hardwareMaschineArg, networkImplNameArg,releaseLevelArg, implNameArg, versionArg);
+ }
+
+ @Override
+ public void execute() throws Exception {
+ Properties ps = AccessController.doPrivileged(new GetPropertiesAction());
+
+ String sysname = allArg.isSet() || hardwareMaschineArg.isSet() ? ps.getProperty("os.arch") : "";
+ final String nodename = allArg.isSet() || networkImplNameArg.isSet() ? ps.getProperty("os.name"): "";
+ final String release = allArg.isSet() || releaseLevelArg.isSet() ? ps.getProperty("os.version") :"";
+ final String version = allArg.isSet() || implNameArg.isSet() ? ps.getProperty("os.name") : "";
+ final String machine = allArg.isSet() || versionArg.isSet() ? ps.getProperty("os.name")
+ + " "
+ + ps.getProperty("os.version"): "";
+ // If no argument specific, set the default
+ if (!allArg.isSet() &&
+ !hardwareMaschineArg.isSet() &&
+ !networkImplNameArg.isSet() &&
+ !releaseLevelArg.isSet() &&
+ !implNameArg.isSet() &&
+ !versionArg.isSet()) {
+ sysname = ps.getProperty("os.arch");// ps.getProperty("os.arch");
+ }
+
+ // Description for more than one arguments contains:
+ // "separated by one or more <blank>s."
+ final String result = String.format("%s %s %s %s %s", sysname, nodename, release, version, machine).trim() +'\n';
+
+ getOutput().getPrintWriter().write(result);
+ }
+}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ls...@us...> - 2013-02-23 16:41:20
|
Revision: 5977
http://jnode.svn.sourceforge.net/jnode/?rev=5977&view=rev
Author: lsantha
Date: 2013-02-23 16:41:08 +0000 (Sat, 23 Feb 2013)
Log Message:
-----------
Updated headers.
Modified Paths:
--------------
trunk/cli/build-tests.xml
trunk/cli/build.xml
trunk/cli/descriptors/org.apache.tools.archive.xml
trunk/cli/descriptors/org.jnode.command.archive.xml
trunk/cli/descriptors/org.jnode.command.argument.xml
trunk/cli/descriptors/org.jnode.command.common.xml
trunk/cli/descriptors/org.jnode.command.dev.ant.xml
trunk/cli/descriptors/org.jnode.command.dev.xml
trunk/cli/descriptors/org.jnode.command.file.xml
trunk/cli/descriptors/org.jnode.command.net.xml
trunk/cli/descriptors/org.jnode.command.system.xml
trunk/cli/descriptors/org.jnode.command.util.xml
Modified: trunk/cli/build-tests.xml
===================================================================
--- trunk/cli/build-tests.xml 2013-02-23 16:39:45 UTC (rev 5976)
+++ trunk/cli/build-tests.xml 2013-02-23 16:41:08 UTC (rev 5977)
@@ -1,3 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ $Id$
+
+ Copyright (C) 2003-2013 JNode.org
+
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ This library 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 Lesser General Public
+ License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library; If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+-->
<project name="JNode-CLI-Tests" default="all" basedir=".">
<import file="${basedir}/../all/build.xml"/>
Modified: trunk/cli/build.xml
===================================================================
--- trunk/cli/build.xml 2013-02-23 16:39:45 UTC (rev 5976)
+++ trunk/cli/build.xml 2013-02-23 16:41:08 UTC (rev 5977)
@@ -1,3 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ $Id$
+
+ Copyright (C) 2003-2013 JNode.org
+
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ This library 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 Lesser General Public
+ License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library; If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+-->
<project name="JNode-CoreUtils" default="all" basedir=".">
<typedef file="${basedir}/../all/lib/jnode.xml"/>
Modified: trunk/cli/descriptors/org.apache.tools.archive.xml
===================================================================
--- trunk/cli/descriptors/org.apache.tools.archive.xml 2013-02-23 16:39:45 UTC (rev 5976)
+++ trunk/cli/descriptors/org.apache.tools.archive.xml 2013-02-23 16:41:08 UTC (rev 5977)
@@ -1,4 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ $Id$
+
+ Copyright (C) 2003-2013 JNode.org
+
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ This library 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 Lesser General Public
+ License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library; If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+-->
<!DOCTYPE plugin SYSTEM "jnode.dtd">
<plugin id="org.apache.tools.archive"
Modified: trunk/cli/descriptors/org.jnode.command.archive.xml
===================================================================
--- trunk/cli/descriptors/org.jnode.command.archive.xml 2013-02-23 16:39:45 UTC (rev 5976)
+++ trunk/cli/descriptors/org.jnode.command.archive.xml 2013-02-23 16:41:08 UTC (rev 5977)
@@ -1,4 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ $Id$
+
+ Copyright (C) 2003-2013 JNode.org
+
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ This library 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 Lesser General Public
+ License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library; If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+-->
<!DOCTYPE plugin SYSTEM "jnode.dtd">
<plugin id="org.jnode.command.archive"
Modified: trunk/cli/descriptors/org.jnode.command.argument.xml
===================================================================
--- trunk/cli/descriptors/org.jnode.command.argument.xml 2013-02-23 16:39:45 UTC (rev 5976)
+++ trunk/cli/descriptors/org.jnode.command.argument.xml 2013-02-23 16:41:08 UTC (rev 5977)
@@ -1,4 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ $Id$
+
+ Copyright (C) 2003-2013 JNode.org
+
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ This library 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 Lesser General Public
+ License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library; If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+-->
<!DOCTYPE plugin SYSTEM "jnode.dtd">
<plugin id="org.jnode.command.argument"
Modified: trunk/cli/descriptors/org.jnode.command.common.xml
===================================================================
--- trunk/cli/descriptors/org.jnode.command.common.xml 2013-02-23 16:39:45 UTC (rev 5976)
+++ trunk/cli/descriptors/org.jnode.command.common.xml 2013-02-23 16:41:08 UTC (rev 5977)
@@ -1,4 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ $Id$
+
+ Copyright (C) 2003-2013 JNode.org
+
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ This library 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 Lesser General Public
+ License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library; If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+-->
<!DOCTYPE plugin SYSTEM "jnode.dtd">
<plugin id="org.jnode.command.common"
Modified: trunk/cli/descriptors/org.jnode.command.dev.ant.xml
===================================================================
--- trunk/cli/descriptors/org.jnode.command.dev.ant.xml 2013-02-23 16:39:45 UTC (rev 5976)
+++ trunk/cli/descriptors/org.jnode.command.dev.ant.xml 2013-02-23 16:41:08 UTC (rev 5977)
@@ -1,4 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ $Id$
+
+ Copyright (C) 2003-2013 JNode.org
+
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ This library 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 Lesser General Public
+ License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library; If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+-->
<!DOCTYPE plugin SYSTEM "jnode.dtd">
<plugin id="org.jnode.command.dev.ant"
Modified: trunk/cli/descriptors/org.jnode.command.dev.xml
===================================================================
--- trunk/cli/descriptors/org.jnode.command.dev.xml 2013-02-23 16:39:45 UTC (rev 5976)
+++ trunk/cli/descriptors/org.jnode.command.dev.xml 2013-02-23 16:41:08 UTC (rev 5977)
@@ -1,4 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ $Id$
+
+ Copyright (C) 2003-2013 JNode.org
+
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ This library 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 Lesser General Public
+ License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library; If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+-->
<!DOCTYPE plugin SYSTEM "jnode.dtd">
<plugin id="org.jnode.command.dev"
Modified: trunk/cli/descriptors/org.jnode.command.file.xml
===================================================================
--- trunk/cli/descriptors/org.jnode.command.file.xml 2013-02-23 16:39:45 UTC (rev 5976)
+++ trunk/cli/descriptors/org.jnode.command.file.xml 2013-02-23 16:41:08 UTC (rev 5977)
@@ -1,4 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ $Id$
+
+ Copyright (C) 2003-2013 JNode.org
+
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ This library 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 Lesser General Public
+ License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library; If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+-->
<!DOCTYPE plugin SYSTEM "jnode.dtd">
<plugin id="org.jnode.command.file"
Modified: trunk/cli/descriptors/org.jnode.command.net.xml
===================================================================
--- trunk/cli/descriptors/org.jnode.command.net.xml 2013-02-23 16:39:45 UTC (rev 5976)
+++ trunk/cli/descriptors/org.jnode.command.net.xml 2013-02-23 16:41:08 UTC (rev 5977)
@@ -1,4 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ $Id$
+
+ Copyright (C) 2003-2013 JNode.org
+
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ This library 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 Lesser General Public
+ License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library; If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+-->
<!DOCTYPE plugin SYSTEM "jnode.dtd">
<plugin id="org.jnode.command.net"
Modified: trunk/cli/descriptors/org.jnode.command.system.xml
===================================================================
--- trunk/cli/descriptors/org.jnode.command.system.xml 2013-02-23 16:39:45 UTC (rev 5976)
+++ trunk/cli/descriptors/org.jnode.command.system.xml 2013-02-23 16:41:08 UTC (rev 5977)
@@ -1,4 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ $Id$
+
+ Copyright (C) 2003-2013 JNode.org
+
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ This library 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 Lesser General Public
+ License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library; If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+-->
<!DOCTYPE plugin SYSTEM "jnode.dtd">
<plugin id="org.jnode.command.system"
Modified: trunk/cli/descriptors/org.jnode.command.util.xml
===================================================================
--- trunk/cli/descriptors/org.jnode.command.util.xml 2013-02-23 16:39:45 UTC (rev 5976)
+++ trunk/cli/descriptors/org.jnode.command.util.xml 2013-02-23 16:41:08 UTC (rev 5977)
@@ -1,4 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ $Id$
+
+ Copyright (C) 2003-2013 JNode.org
+
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ This library 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 Lesser General Public
+ License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library; If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+-->
<!DOCTYPE plugin SYSTEM "jnode.dtd">
<plugin id="org.jnode.command.util"
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|