Author: suresh
Date: Wed Apr 21 07:18:56 2010
New Revision: 936178
URL: http://svn.apache.org/viewvc?rev=936178&view=rev
Log:
HDFS-1088. Prevent renaming symbolic link to its target. Contribute by Eli
Collins.
Modified:
hadoop/hdfs/trunk/CHANGES.txt
hadoop/hdfs/trunk/src/java/org/apache/hadoop/fs/Hdfs.java
hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/server/namenode/FSDirectory.java
hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/server/namenode/FSImage.java
hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/server/namenode/INode.java
Modified: hadoop/hdfs/trunk/CHANGES.txt
URL:
http://svn.apache.org/viewvc/hadoop/hdfs/trunk/CHANGES.txt?rev=936178&r1=936177&r2=936178&view=diff
==============================================================================
--- hadoop/hdfs/trunk/CHANGES.txt (original)
+++ hadoop/hdfs/trunk/CHANGES.txt Wed Apr 21 07:18:56 2010
@@ -267,6 +267,9 @@ Trunk (unreleased changes)
HDFS-1014. Error in reading delegation tokens from edit logs.
(Jitendra Nath Pandey via jhoman)
+ HDFS-1088. Prevent renaming a symbolik link to its target.
+ (Eli Collins via suresh)
+
Release 0.21.0 - Unreleased
INCOMPATIBLE CHANGES
Modified: hadoop/hdfs/trunk/src/java/org/apache/hadoop/fs/Hdfs.java
URL:
http://svn.apache.org/viewvc/hadoop/hdfs/trunk/src/java/org/apache/hadoop/fs/Hdfs.java?rev=936178&r1=936177&r2=936178&view=diff
==============================================================================
--- hadoop/hdfs/trunk/src/java/org/apache/hadoop/fs/Hdfs.java (original)
+++ hadoop/hdfs/trunk/src/java/org/apache/hadoop/fs/Hdfs.java Wed Apr 21
07:18:56 2010
@@ -93,7 +93,7 @@ public class Hdfs extends AbstractFileSy
@Override
protected BlockLocation[] getFileBlockLocations(Path p, long start, long len)
throws IOException, UnresolvedLinkException {
- return dfs.getBlockLocations(p.toString(), start, len);
+ return dfs.getBlockLocations(getUriPath(p), start, len);
}
@Override
Modified:
hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/server/namenode/FSDirectory.java
URL:
http://svn.apache.org/viewvc/hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/server/namenode/FSDirectory.java?rev=936178&r1=936177&r2=936178&view=diff
==============================================================================
---
hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/server/namenode/FSDirectory.java
(original)
+++
hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/server/namenode/FSDirectory.java
Wed Apr 21 07:18:56 2010
@@ -383,7 +383,8 @@ class FSDirectory implements Closeable {
*/
@Deprecated
boolean renameTo(String src, String dst)
- throws QuotaExceededException, UnresolvedLinkException {
+ throws QuotaExceededException, UnresolvedLinkException,
+ FileAlreadyExistsException {
if (NameNode.stateChangeLog.isDebugEnabled()) {
NameNode.stateChangeLog.debug("DIR* FSDirectory.renameTo: "
+src+" to "+dst);
@@ -420,16 +421,19 @@ class FSDirectory implements Closeable {
* @param dst destination path
* @return true if rename succeeds; false otherwise
* @throws QuotaExceededException if the operation violates any quota limit
+ * @throws FileAlreadyExistsException if the src is a symlink that points to
dst
* @deprecated See {...@link #renameTo(String, String)}
*/
@Deprecated
boolean unprotectedRenameTo(String src, String dst, long timestamp)
- throws QuotaExceededException, UnresolvedLinkException {
+ throws QuotaExceededException, UnresolvedLinkException,
+ FileAlreadyExistsException {
synchronized (rootDir) {
INode[] srcInodes = rootDir.getExistingPathINodes(src, false);
-
+ INode srcInode = srcInodes[srcInodes.length-1];
+
// check the validation of the source
- if (srcInodes[srcInodes.length-1] == null) {
+ if (srcInode == null) {
NameNode.stateChangeLog.warn("DIR* FSDirectory.unprotectedRenameTo: "
+ "failed to rename " + src + " to " + dst
+ " because source does not exist");
@@ -448,6 +452,12 @@ class FSDirectory implements Closeable {
if (dst.equals(src)) {
return true;
}
+ if (srcInode.isLink() &&
+ dst.equals(((INodeSymlink)srcInode).getLinkValue())) {
+ throw new FileAlreadyExistsException(
+ "Cannot rename symlink "+src+" to its target "+dst);
+ }
+
// dst cannot be directory or a file under src
if (dst.startsWith(src) &&
dst.charAt(src.length()) == Path.SEPARATOR_CHAR) {
@@ -529,6 +539,8 @@ class FSDirectory implements Closeable {
* @param timestamp modification time
* @param options Rename options
* @throws IOException if the operation violates any quota limit
+ * @throws FileAlreadyExistsException if src equals dst or the src is a
+ * symlink that points to dst.
* @return true if rename overwrites {...@code dst}
*/
boolean unprotectedRenameTo(String src, String dst, long timestamp,
@@ -560,9 +572,15 @@ class FSDirectory implements Closeable {
throw new IOException(error);
}
- // validate of the destination
+ // validate the destination
if (dst.equals(src)) {
- return false;
+ throw new FileAlreadyExistsException(
+ "The source "+src+" and destination "+dst+" are the same");
+ }
+ if (srcInode.isLink() &&
+ dst.equals(((INodeSymlink)srcInode).getLinkValue())) {
+ throw new FileAlreadyExistsException(
+ "Cannot rename symlink "+src+" to its target "+dst);
}
// dst cannot be a directory or a file under src
if (dst.startsWith(src) &&
Modified:
hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/server/namenode/FSImage.java
URL:
http://svn.apache.org/viewvc/hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/server/namenode/FSImage.java?rev=936178&r1=936177&r2=936178&view=diff
==============================================================================
---
hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/server/namenode/FSImage.java
(original)
+++
hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/server/namenode/FSImage.java
Wed Apr 21 07:18:56 2010
@@ -889,6 +889,14 @@ public class FSImage extends Storage {
* Choose latest image from one of the directories,
* load it and merge with the edits from that directory.
*
+ * Saving and loading fsimage should never trigger symlink resolution.
+ * The paths that are persisted do not have *intermediate* symlinks
+ * because intermediate symlinks are resolved at the time files,
+ * directories, and symlinks are created. All paths accessed while
+ * loading or saving fsimage should therefore only see symlinks as
+ * the final path component, and the functions called below do not
+ * resolve symlinks that are the final path component.
+ *
* @return whether the image should be saved
* @throws IOException
*/
Modified:
hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/server/namenode/INode.java
URL:
http://svn.apache.org/viewvc/hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/server/namenode/INode.java?rev=936178&r1=936177&r2=936178&view=diff
==============================================================================
---
hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/server/namenode/INode.java
(original)
+++
hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/server/namenode/INode.java
Wed Apr 21 07:18:56 2010
@@ -348,13 +348,14 @@ abstract class INode implements Comparab
}
/**
- * Breaks file path into names.
+ * Splits an absolute path into an array of path components.
* @param path
- * @return array of names
+ * @throws AssertionError if the given path is invalid.
+ * @return array of path components.
*/
static String[] getPathNames(String path) {
if (path == null || !path.startsWith(Path.SEPARATOR)) {
- return null;
+ throw new AssertionError("Absolute path required");
}
return path.split(Path.SEPARATOR);
}