|
@@ -437,7 +437,6 @@ public class RawLocalFileSystem extends FileSystem {
|
|
|
public void setWorkingDirectory(Path newDir) {
|
|
|
workingDir = makeAbsolute(newDir);
|
|
|
checkPath(workingDir);
|
|
|
-
|
|
|
}
|
|
|
|
|
|
@Override
|
|
@@ -641,4 +640,109 @@ public class RawLocalFileSystem extends FileSystem {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ @Override
|
|
|
+ public boolean supportsSymlinks() {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void createSymlink(Path target, Path link, boolean createParent)
|
|
|
+ throws IOException {
|
|
|
+ final String targetScheme = target.toUri().getScheme();
|
|
|
+ if (targetScheme != null && !"file".equals(targetScheme)) {
|
|
|
+ throw new IOException("Unable to create symlink to non-local file "+
|
|
|
+ "system: "+target.toString());
|
|
|
+ }
|
|
|
+ if (createParent) {
|
|
|
+ mkdirs(link.getParent());
|
|
|
+ }
|
|
|
+ // NB: Use createSymbolicLink in java.nio.file.Path once available
|
|
|
+ try {
|
|
|
+ Shell.execCommand(Shell.getSymlinkCommand(
|
|
|
+ Path.getPathWithoutSchemeAndAuthority(target).toString(),
|
|
|
+ Path.getPathWithoutSchemeAndAuthority(makeAbsolute(link)).toString()));
|
|
|
+ } catch (IOException x) {
|
|
|
+ throw new IOException("Unable to create symlink: "+x.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Returns the target of the given symlink. Returns the empty string if
|
|
|
+ * the given path does not refer to a symlink or there is an error
|
|
|
+ * accessing the symlink.
|
|
|
+ */
|
|
|
+ private String readLink(Path p) {
|
|
|
+ /* NB: Use readSymbolicLink in java.nio.file.Path once available. Could
|
|
|
+ * use getCanonicalPath in File to get the target of the symlink but that
|
|
|
+ * does not indicate if the given path refers to a symlink.
|
|
|
+ */
|
|
|
+ try {
|
|
|
+ final String path = p.toUri().getPath();
|
|
|
+ return Shell.execCommand(Shell.READ_LINK_COMMAND, path).trim();
|
|
|
+ } catch (IOException x) {
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Return a FileStatus representing the given path. If the path refers
|
|
|
+ * to a symlink return a FileStatus representing the link rather than
|
|
|
+ * the object the link refers to.
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public FileStatus getFileLinkStatus(final Path f) throws IOException {
|
|
|
+ FileStatus fi = getFileLinkStatusInternal(f);
|
|
|
+ // getFileLinkStatus is supposed to return a symlink with a
|
|
|
+ // qualified path
|
|
|
+ if (fi.isSymlink()) {
|
|
|
+ Path targetQual = FSLinkResolver.qualifySymlinkTarget(this.getUri(),
|
|
|
+ fi.getPath(), fi.getSymlink());
|
|
|
+ fi.setSymlink(targetQual);
|
|
|
+ }
|
|
|
+ return fi;
|
|
|
+ }
|
|
|
+
|
|
|
+ private FileStatus getFileLinkStatusInternal(final Path f) throws IOException {
|
|
|
+ String target = readLink(f);
|
|
|
+
|
|
|
+ try {
|
|
|
+ FileStatus fs = getFileStatus(f);
|
|
|
+ // If f refers to a regular file or directory
|
|
|
+ if (target.isEmpty()) {
|
|
|
+ return fs;
|
|
|
+ }
|
|
|
+ // Otherwise f refers to a symlink
|
|
|
+ return new FileStatus(fs.getLen(),
|
|
|
+ false,
|
|
|
+ fs.getReplication(),
|
|
|
+ fs.getBlockSize(),
|
|
|
+ fs.getModificationTime(),
|
|
|
+ fs.getAccessTime(),
|
|
|
+ fs.getPermission(),
|
|
|
+ fs.getOwner(),
|
|
|
+ fs.getGroup(),
|
|
|
+ new Path(target),
|
|
|
+ f);
|
|
|
+ } catch (FileNotFoundException e) {
|
|
|
+ /* The exists method in the File class returns false for dangling
|
|
|
+ * links so we can get a FileNotFoundException for links that exist.
|
|
|
+ * It's also possible that we raced with a delete of the link. Use
|
|
|
+ * the readBasicFileAttributes method in java.nio.file.attributes
|
|
|
+ * when available.
|
|
|
+ */
|
|
|
+ if (!target.isEmpty()) {
|
|
|
+ return new FileStatus(0, false, 0, 0, 0, 0, FsPermission.getDefault(),
|
|
|
+ "", "", new Path(target), f);
|
|
|
+ }
|
|
|
+ // f refers to a file or directory that does not exist
|
|
|
+ throw e;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Path getLinkTarget(Path f) throws IOException {
|
|
|
+ FileStatus fi = getFileLinkStatusInternal(f);
|
|
|
+ // return an unqualified symlink target
|
|
|
+ return fi.getSymlink();
|
|
|
+ }
|
|
|
}
|