/// <exception cref="System.IO.IOException"/> public override void CreateSymlink(Path target, Path link, bool createParent) { if (!FileSystem.AreSymlinksEnabled()) { throw new NotSupportedException("Symlinks not supported"); } 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 int result = FileUtil.SymLink(target.ToString(), MakeAbsolute(link).ToString()); if (result != 0) { throw new IOException("Error " + result + " creating symlink " + link + " to " + target); } }
/// <summary> /// Attempt calling overridden /// <see cref="FileSystemLinkResolver{T}.DoCall(Path)"/> /// method with /// specified /// <see cref="FileSystem"/> /// and /// <see cref="Path"/> /// . If the call fails with an /// UnresolvedLinkException, it will try to resolve the path and retry the call /// by calling /// <see cref="FileSystemLinkResolver{T}.Next(FileSystem, Path)"/> /// . /// </summary> /// <param name="filesys">FileSystem with which to try call</param> /// <param name="path">Path with which to try call</param> /// <returns>Generic type determined by implementation</returns> /// <exception cref="System.IO.IOException"/> public virtual T Resolve(FileSystem filesys, Path path) { int count = 0; T @in = null; Path p = path; // Assumes path belongs to this FileSystem. // Callers validate this by passing paths through FileSystem#checkPath FileSystem fs = filesys; for (bool isLink = true; isLink;) { try { @in = DoCall(p); isLink = false; } catch (UnresolvedLinkException e) { if (!filesys.resolveSymlinks) { throw new IOException("Path " + path + " contains a symlink" + " and symlink resolution is disabled (" + CommonConfigurationKeys.FsClientResolveRemoteSymlinksKey + ").", e); } if (!FileSystem.AreSymlinksEnabled()) { throw new IOException("Symlink resolution is disabled in" + " this version of Hadoop." ); } if (count++ > FsConstants.MaxPathLinks) { throw new IOException("Possible cyclic loop while " + "following symbolic link " + path); } // Resolve the first unresolved path component p = FSLinkResolver.QualifySymlinkTarget(fs.GetUri(), p, filesys.ResolveLink(p)); fs = FileSystem.GetFSofPath(p, filesys.GetConf()); // Have to call next if it's a new FS if (!fs.Equals(filesys)) { return(Next(fs, p)); } } } // Else, we keep resolving with this filesystem // Successful call, path was fully resolved return(@in); }
/// <summary> /// Performs the operation specified by the next function, calling it /// repeatedly until all symlinks in the given path are resolved. /// </summary> /// <param name="fc">FileContext used to access file systems.</param> /// <param name="path">The path to resolve symlinks on.</param> /// <returns>Generic type determined by the implementation of next.</returns> /// <exception cref="System.IO.IOException"/> public virtual T Resolve(FileContext fc, Path path) { int count = 0; T @in = null; Path p = path; // NB: More than one AbstractFileSystem can match a scheme, eg // "file" resolves to LocalFs but could have come by RawLocalFs. AbstractFileSystem fs = fc.GetFSofPath(p); // Loop until all symlinks are resolved or the limit is reached for (bool isLink = true; isLink;) { try { @in = Next(fs, p); isLink = false; } catch (UnresolvedLinkException e) { if (!fc.resolveSymlinks) { throw new IOException("Path " + path + " contains a symlink" + " and symlink resolution is disabled (" + CommonConfigurationKeys.FsClientResolveRemoteSymlinksKey + ").", e); } if (!FileSystem.AreSymlinksEnabled()) { throw new IOException("Symlink resolution is disabled in" + " this version of Hadoop." ); } if (count++ > FsConstants.MaxPathLinks) { throw new IOException("Possible cyclic loop while " + "following symbolic link " + path); } // Resolve the first unresolved path component p = QualifySymlinkTarget(fs.GetUri(), p, fs.GetLinkTarget(p)); fs = fc.GetFSofPath(p); } } return(@in); }