// Copyright 2014 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.devtools.build.lib.vfs.inmemoryfs;

import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.google.devtools.build.lib.clock.Clock;
import com.google.devtools.build.lib.clock.JavaClock;
import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
import com.google.devtools.build.lib.util.OS;
import com.google.devtools.build.lib.vfs.FileAccessException;
import com.google.devtools.build.lib.vfs.FileStatus;
import com.google.devtools.build.lib.vfs.FileSystem;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.io.ByteArrayInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Stack;
import javax.annotation.Nullable;

/**
 * This class provides a complete in-memory file system.
 *
 * <p>Naming convention: we use "path" for all {@link Path} variables, since these represent *names*
 * and we use "node" or "inode" for InMemoryContentInfo variables, since these correspond to inodes
 * in the UNIX file system.
 *
 * <p>The code is structured to be as similar to the implementation of UNIX "namei" as is reasonably
 * possibly. This provides a firm reference point for many concepts and makes compatibility easier
 * to achieve.
 */
@ThreadSafe
public class InMemoryFileSystem extends FileSystem {

  private final PathFragment scopeRoot;
  private final Clock clock;

  // The root inode (a directory).
  private final InMemoryDirectoryInfo rootInode;

  // Maximum number of traversals before ELOOP is thrown.
  private static final int MAX_TRAVERSALS = 256;

  /**
   * Creates a new InMemoryFileSystem with scope checking disabled (all paths are considered to be
   * within scope) and a default clock.
   */
  public InMemoryFileSystem() {
    this(new JavaClock());
  }

  /**
   * Creates a new InMemoryFileSystem with scope checking disabled (all
   * paths are considered to be within scope).
   */
  public InMemoryFileSystem(Clock clock) {
    this(clock, (PathFragment) null);
  }

  /**
   * Creates a new InMemoryFileSystem with scope checking disabled (all paths are considered to be
   * within scope).
   */
  public InMemoryFileSystem(Clock clock, HashFunction hashFunction) {
    super(hashFunction);
    this.clock = clock;
    this.rootInode = newRootInode(clock);
    this.scopeRoot = null;
  }

  /**
   * Creates a new InMemoryFileSystem with scope checking bound to scopeRoot, i.e. any path that's
   * not below scopeRoot is considered to be out of scope.
   */
  public InMemoryFileSystem(Clock clock, PathFragment scopeRoot) {
    this.scopeRoot = scopeRoot;
    this.clock = clock;
    this.rootInode = newRootInode(clock);
  }

  private static InMemoryDirectoryInfo newRootInode(Clock clock) {
    InMemoryDirectoryInfo rootInode = new InMemoryDirectoryInfo(clock);
    rootInode.addChild(".", rootInode);
    rootInode.addChild("..", rootInode);
    return rootInode;
  }

  /**
   * Returns true if the given path is within this file system's scope, false otherwise.
   *
   * @param parentDepth the number of segments in the path's parent directory (only meaningful for
   *     paths that begin with ".."). The parent directory itself is assumed to be in scope.
   * @param normalizedPath input path, expected to be normalized such that all ".." and "." segments
   *     are removed (with the exception of a possible prefix sequence of contiguous ".." segments)
   */
  private boolean inScope(int parentDepth, PathFragment normalizedPath) {
    if (scopeRoot == null) {
      return true;
    } else if (normalizedPath.isAbsolute()) {
      return normalizedPath.startsWith(scopeRoot);
    } else {
      // Efficiency note: we're not accounting for "/scope/root/../root" paths here, i.e. paths
      // that appear to go out of scope but ultimately stay within scope. This may result in
      // unnecessary re-delegation back into the same FS. we're choosing to forgo that
      // optimization under the assumption that such scenarios are rare and unimportant to
      // overall performance. We can always enhance this if needed.
      return parentDepth - leadingParentReferences(normalizedPath) >= scopeRoot.segmentCount();
    }
  }

  /**
   * Given a path that's normalized (no ".." or "." segments), except for a possible prefix sequence
   * of contiguous ".." segments, returns the size of that prefix sequence.
   *
   * <p>Example allowed inputs: "/absolute/path", "relative/path", "../../relative/path". Example
   * disallowed inputs: "/absolute/path/../path2", "relative/../path", "../relative/../p".
   */
  private int leadingParentReferences(PathFragment normalizedPath) {
    int leadingParentReferences = 0;
    for (int i = 0;
        i < normalizedPath.segmentCount() && normalizedPath.getSegment(i).equals("..");
        i++) {
      leadingParentReferences++;
    }
    return leadingParentReferences;
  }

  /**
   * The errors that {@link InMemoryFileSystem} might issue for different sorts of IO failures.
   */
  public enum Error {
    ENOENT("No such file or directory"),
    EACCES("Permission denied"),
    ENOTDIR("Not a directory"),
    EEXIST("File exists"),
    EBUSY("Device or resource busy"),
    ENOTEMPTY("Directory not empty"),
    EISDIR("Is a directory"),
    ELOOP("Too many levels of symbolic links");

    private final String message;

    Error(String message) {
      this.message = message;
    }

    @Override
    public String toString() {
      return message;
    }

    /** Implemented by exceptions that contain the extra info of which Error caused them. */
    private interface WithError {
      Error getError();
    }

    /**
     * The exceptions below extend their parent classes in order to additionally store the error
     * that caused them. However, they must impersonate their parents to any outside callers,
     * including in their toString() method, which prints the class name followed by the exception
     * method. This method returns the same value as the toString() method of a {@link Throwable}'s
     * parent would, so that the child class can have the same toString() value.
     */
    private static String parentThrowableToString(Throwable obj) {
      String s = obj.getClass().getSuperclass().getName();
      String message = obj.getLocalizedMessage();
      return (message != null) ? (s + ": " + message) : s;
    }

    private static class IOExceptionWithError extends IOException implements WithError {
      private final Error errorCode;

      private IOExceptionWithError(String message, Error errorCode) {
        super(message);
        this.errorCode = errorCode;
      }

      @Override
      public Error getError() {
        return errorCode;
      }

      @Override
      public String toString() {
        return parentThrowableToString(this);
      }
    }


    private static class FileNotFoundExceptionWithError
        extends FileNotFoundException implements WithError {
      private final Error errorCode;

      private FileNotFoundExceptionWithError(String message, Error errorCode) {
        super(message);
        this.errorCode = errorCode;
      }

      @Override
      public Error getError() {
        return errorCode;
      }

      @Override
      public String toString() {
        return parentThrowableToString(this);
      }
    }


    private static class FileAccessExceptionWithError
        extends FileAccessException implements WithError {
      private final Error errorCode;

      private FileAccessExceptionWithError(String message, Error errorCode) {
        super(message);
        this.errorCode = errorCode;
      }

      @Override
      public Error getError() {
        return errorCode;
      }

      @Override
      public String toString() {
        return parentThrowableToString(this);
      }
    }

    /**
     * Returns a new IOException for the error. The exception message
     * contains 'path', and is consistent with the messages returned by
     * c.g.common.unix.FilesystemUtils.
     */
    public IOException exception(Path path) throws IOException {
      String m = path + " (" + message + ")";
      if (this == EACCES) {
        throw new FileAccessExceptionWithError(m, this);
      } else if (this == ENOENT) {
        throw new FileNotFoundExceptionWithError(m, this);
      } else {
        throw new IOExceptionWithError(m, this);
      }
    }
  }

  /**
   * {@inheritDoc}
   *
   * <p>If <code>/proc/mounts</code> does not exist return {@code "inmemoryfs"}.
   */
  @Override
  public String getFileSystemType(Path path) {
    return path.getRelative("/proc/mounts").exists() ? super.getFileSystemType(path) : "inmemoryfs";
  }

  /****************************************************************************
   * "Kernel" primitives: basic directory lookup primitives, in topological
   * order.
   */

  /**
   * Unlinks the entry 'child' from its existing parent directory 'dir'. Dual to
   * insert. This succeeds even if 'child' names a non-empty directory; we need
   * that for renameTo. 'child' must be a member of its parent directory,
   * however. Fails if the directory was read-only.
   */
  private void unlink(InMemoryDirectoryInfo dir, String child, Path errorPath)
      throws IOException {
    if (!dir.isWritable()) { throw Error.EACCES.exception(errorPath); }
    dir.removeChild(child);
  }

  /**
   * Inserts inode 'childInode' into the existing directory 'dir' under the
   * specified 'name'.  Dual to unlink.  Fails if the directory was read-only.
   */
  private void insert(InMemoryDirectoryInfo dir, String child,
                      InMemoryContentInfo childInode, Path errorPath)
      throws IOException {
    if (!dir.isWritable()) { throw Error.EACCES.exception(errorPath); }
    dir.addChild(child, childInode);
  }

  /**
   * Given an existing directory 'dir', looks up 'name' within it and returns
   * its inode. Assumes the file exists, unless 'create', in which case it will
   * try to create it. May fail with ENOTDIR, EACCES, ENOENT. Error messages
   * will be reported against file 'path'.
   */
  private InMemoryContentInfo directoryLookup(InMemoryContentInfo dir,
                                              String name,
                                              boolean create,
                                              Path path) throws IOException {
    if (!dir.isDirectory()) { throw Error.ENOTDIR.exception(path); }
    InMemoryDirectoryInfo imdi = (InMemoryDirectoryInfo) dir;
    if (!imdi.isExecutable()) { throw Error.EACCES.exception(path); }
    InMemoryContentInfo child = imdi.getChild(name);
    if (child == null) {
      if (!create)  {
        throw Error.ENOENT.exception(path);
      } else {
        child = new InMemoryFileInfo(clock);
        insert(imdi, name, child, path);
      }
    }
    return child;
  }

  /**
   * Low-level path-to-inode lookup routine. Analogous to path_walk() in many UNIX kernels. Given
   * 'path', walks the directory tree from the root, resolving all symbolic links, and returns the
   * designated inode.
   *
   * <p>If 'create' is false, the inode must exist; otherwise, it will be created and added to its
   * parent directory, which must exist.
   *
   * <p>Iff the given path escapes this file system's scope, a Error.ENOENT exception is thrown.
   *
   * <p>May fail with ENOTDIR, ENOENT, EACCES, ELOOP.
   */
  private synchronized InMemoryContentInfo pathWalk(Path path, boolean create) throws IOException {
    // Implementation note: This is where we check for out-of-scope symlinks and
    // trigger re-delegation to another file system accordingly. This code handles
    // both absolute and relative symlinks. Some assumptions we make: First, only
    // symlink targets as read from getNormalizedLinkContent() can escape our scope.
    // This is because Path objects are all canonicalized (see {@link Path#getRelative},
    // etc.) and symlink target segments that get added to the stack are in-scope by
    // definition. Second, symlink targets with relative segments must have the form
    // [".."]*[standard segment]+, i.e. only the ".." non-standard segment is allowed
    // and it may only appear as part of a contiguous prefix sequence.

    Stack<String> stack = new Stack<>();
    for (Path p = path; !isRootDirectory(p); p = p.getParentDirectory()) {
      String name = baseNameOrWindowsDrive(p);
      stack.push(name);
    }

    InMemoryContentInfo inode = rootInode;
    int parentDepth = -1;
    int traversals = 0;

    while (!stack.isEmpty()) {
      traversals++;

      String name = stack.pop();
      parentDepth += name.equals("..") ? -1 : 1;

      // ENOENT on last segment with 'create' => create a new file.
      InMemoryContentInfo child = directoryLookup(inode, name, create && stack.isEmpty(), path);
      if (child.isSymbolicLink()) {
        PathFragment linkTarget = ((InMemoryLinkInfo) child).getNormalizedLinkContent();
        if (!inScope(parentDepth, linkTarget)) {
          throw Error.ENOENT.exception(path);
        }
        if (linkTarget.isAbsolute()) {
          inode = rootInode;
          parentDepth = -1;
        }
        if (traversals > MAX_TRAVERSALS) {
          throw Error.ELOOP.exception(path);
        }
        List<String> segments = linkTarget.getSegments();
        for (int ii = segments.size() - 1; ii >= 0; --ii) {
          stack.push(segments.get(ii)); // Note this may include ".." segments.
        }
        // Push Windows drive if there is one
        if (linkTarget.isAbsolute()) {
          String driveStr = linkTarget.getDriveStr();
          if (driveStr.length() > 1) {
            stack.push(driveStr);
          }
        }
      } else {
        inode = child;
      }
    }
    return inode;
  }

  /**
   * Given 'path', returns the existing directory inode it designates,
   * following symbolic links.
   *
   * <p>May fail with ENOTDIR, or any exception from pathWalk.
   */
  private InMemoryDirectoryInfo getDirectory(Path path) throws IOException {
    InMemoryContentInfo dirInfo = pathWalk(path, false);
    if (!dirInfo.isDirectory()) {
      throw Error.ENOTDIR.exception(path);
    } else {
      return (InMemoryDirectoryInfo) dirInfo;
    }
  }

  /**
   * Helper method for stat, scopeLimitedStat: lock the internal state and return the
   * path's (no symlink-followed) stat if the path's parent directory is within scope,
   * else return an "out of scope" reference to the path's parent directory (which will
   * presumably be re-delegated to another FS).
   */
  private synchronized InMemoryContentInfo getNoFollowStatOrOutOfScopeParent(Path path)
      throws IOException  {
    InMemoryDirectoryInfo dirInfo = getDirectory(path.getParentDirectory());
    return directoryLookup(dirInfo, baseNameOrWindowsDrive(path), /*create=*/ false, path);
  }

  /**
   * Given 'path', returns the existing inode it designates, optionally
   * following symbolic links.  Analogous to UNIX stat(2)/lstat(2), except that
   * it returns a mutable inode we can modify directly.
   */
  @Override
  public FileStatus stat(Path path, boolean followSymlinks) throws IOException {
    if (followSymlinks) {
      return scopeLimitedStat(path, true);
    } else {
      if (isRootDirectory(path)) {
        return rootInode;
      } else {
        return getNoFollowStatOrOutOfScopeParent(path);
      }
    }
  }

  @Override
  @Nullable
  public FileStatus statIfFound(Path path, boolean followSymlinks) throws IOException {
    try {
      return stat(path, followSymlinks);
    } catch (IOException e) {
      if (e instanceof Error.WithError) {
        Error errorCode = ((Error.WithError) e).getError();
        if  (errorCode == Error.ENOENT || errorCode == Error.ENOTDIR) {
          return null;
        }
      }
      throw e;
    }
  }

  /**
   * Version of stat that returns an inode if the input path stays entirely within this file
   * system's scope, otherwise throws.
   */
  private InMemoryContentInfo scopeLimitedStat(Path path, boolean followSymlinks)
      throws IOException {
    if (followSymlinks) {
      return pathWalk(path, false);
    } else {
      if (isRootDirectory(path)) {
        return rootInode;
      } else {
        return getNoFollowStatOrOutOfScopeParent(path);
      }
    }
  }

  /****************************************************************************
   *  FileSystem methods
   */

  /**
   * This is a helper routing for {@link #resolveSymbolicLinks(Path)}, i.e.
   * the "user-mode" routing for canonicalising paths. It is analogous to the
   * code in glibc's realpath(3).
   *
   * <p>Just like realpath, resolveSymbolicLinks requires a quadratic number of
   * directory lookups: n path segments are statted, and each stat requires a
   * linear amount of work in the "kernel" routine.
   */
  @Override
  protected PathFragment resolveOneLink(Path path) throws IOException {
    // Beware, this seemingly simple code belies the complex specification of
    // FileSystem.resolveOneLink().
    InMemoryContentInfo status = scopeLimitedStat(path, false);
    return status.isSymbolicLink() ? ((InMemoryLinkInfo) status).getLinkContent() : null;
  }

  @Override
  protected boolean isDirectory(Path path, boolean followSymlinks) {
    try {
      return stat(path, followSymlinks).isDirectory();
    } catch (IOException e) {
      return false;
    }
  }

  @Override
  protected boolean isFile(Path path, boolean followSymlinks) {
    try {
      return stat(path, followSymlinks).isFile();
    } catch (IOException e) {
      return false;
    }
  }

  @Override
  protected boolean isSpecialFile(Path path, boolean followSymlinks) {
    try {
      return stat(path, followSymlinks).isSpecialFile();
    } catch (IOException e) {
      return false;
    }
  }

  @Override
  protected boolean isSymbolicLink(Path path) {
    try {
      return stat(path, false).isSymbolicLink();
    } catch (IOException e) {
      return false;
    }
  }

  @Override
  protected boolean exists(Path path, boolean followSymlinks) {
    try {
      stat(path, followSymlinks);
      return true;
    } catch (IOException e) {
      return false;
    }
  }

  @Override
  protected boolean isReadable(Path path) throws IOException {
    InMemoryContentInfo status = scopeLimitedStat(path, true);
    return status.isReadable();
  }

  @Override
  protected void setReadable(Path path, boolean readable) throws IOException {
    synchronized (this) {
      InMemoryContentInfo status = scopeLimitedStat(path, true);
      status.setReadable(readable);
    }
  }

  @Override
  protected boolean isWritable(Path path) throws IOException {
    InMemoryContentInfo status = scopeLimitedStat(path, true);
    return status.isWritable();
  }

  @Override
  public void setWritable(Path path, boolean writable) throws IOException {
    InMemoryContentInfo status;
    synchronized (this) {
      status = scopeLimitedStat(path, true);
      status.setWritable(writable);
    }
  }

  @Override
  protected boolean isExecutable(Path path) throws IOException {
    InMemoryContentInfo status = scopeLimitedStat(path, true);
    return status.isExecutable();
  }

  @Override
  protected void setExecutable(Path path, boolean executable)
      throws IOException {
    synchronized (this) {
      InMemoryContentInfo status = scopeLimitedStat(path, true);
      status.setExecutable(executable);
    }
  }

  @Override
  public boolean supportsModifications(Path path) {
    return true;
  }

  @Override
  public boolean supportsSymbolicLinksNatively(Path path) {
    return true;
  }

  @Override
  public boolean supportsHardLinksNatively(Path path) {
    return true;
  }

  @Override
  public boolean isFilePathCaseSensitive() {
    return OS.getCurrent() != OS.WINDOWS;
  }

  @Override
  public boolean createDirectory(Path path) throws IOException {
    if (isRootDirectory(path)) {
      throw Error.EACCES.exception(path);
    }

    InMemoryDirectoryInfo parent;
    synchronized (this) {
      parent = getDirectory(path.getParentDirectory());
      InMemoryContentInfo child = parent.getChild(baseNameOrWindowsDrive(path));
      if (child != null) { // already exists
        if (child.isDirectory()) {
          return false;
        } else {
          throw Error.EEXIST.exception(path);
        }
      }

      InMemoryDirectoryInfo newDir = new InMemoryDirectoryInfo(clock);
      newDir.addChild(".", newDir);
      newDir.addChild("..", parent);
      insert(parent, baseNameOrWindowsDrive(path), newDir, path);

      return true;
    }
  }

  @Override
  public synchronized void createDirectoryAndParents(Path path) throws IOException {
    List<Path> subdirs = new ArrayList<>();
    for (; !isRootDirectory(path); path = path.getParentDirectory()) {
      if (path.isDirectory()) {
        break;
      } else if (path.exists()) {
        throw new IOException("Not a directory: " + path);
      }
      subdirs.add(path);
    }
    for (Path subdir : Lists.reverse(subdirs)) {
      subdir.createDirectory();
    }
  }

  @Override
  protected void createSymbolicLink(Path path, PathFragment targetFragment)
      throws IOException {
    if (isRootDirectory(path)) {
      throw Error.EACCES.exception(path);
    }

    synchronized (this) {
      InMemoryDirectoryInfo parent = getDirectory(path.getParentDirectory());
      if (parent.getChild(baseNameOrWindowsDrive(path)) != null) {
        throw Error.EEXIST.exception(path);
      }
      insert(
          parent, baseNameOrWindowsDrive(path), new InMemoryLinkInfo(clock, targetFragment), path);
    }
  }

  @Override
  protected PathFragment readSymbolicLink(Path path) throws IOException {
    InMemoryContentInfo status = scopeLimitedStat(path, false);
    if (status.isSymbolicLink()) {
      Preconditions.checkState(status instanceof InMemoryLinkInfo);
      return ((InMemoryLinkInfo) status).getLinkContent();
    } else {
        throw new NotASymlinkException(path);
    }
  }

  @Override
  protected long getFileSize(Path path, boolean followSymlinks)
      throws IOException {
    return stat(path, followSymlinks).getSize();
  }

  @Override
  protected Collection<String> getDirectoryEntries(Path path) throws IOException {
    synchronized (this) {
      InMemoryDirectoryInfo dirInfo = getDirectory(path);
      FileStatus status = stat(path, false);
      Preconditions.checkState(status instanceof InMemoryContentInfo);
      if (!((InMemoryContentInfo) status).isReadable()) {
        throw new IOException("Directory is not readable");
      }

      Collection<String> allChildren = dirInfo.getAllChildren();
      List<String> result = new ArrayList<>(allChildren.size());
      for (String child : allChildren) {
        if (!(child.equals(".") || child.equals(".."))) {
          result.add(child);
        }
      }
      return result;
    }
  }

  @Override
  public boolean delete(Path path) throws IOException {
    if (isRootDirectory(path)) {
      throw Error.EBUSY.exception(path);
    }
    if (!exists(path, false)) { return false; }

    synchronized (this) {
      InMemoryDirectoryInfo parent = getDirectory(path.getParentDirectory());
      InMemoryContentInfo child = parent.getChild(baseNameOrWindowsDrive(path));
      if (child.isDirectory() && child.getSize() > 2) {
        throw Error.ENOTEMPTY.exception(path);
      }
      unlink(parent, baseNameOrWindowsDrive(path), path);
      return true;
    }
  }

  @Override
  protected long getLastModifiedTime(Path path, boolean followSymlinks)
      throws IOException {
    return stat(path, followSymlinks).getLastModifiedTime();
  }

  @Override
  public void setLastModifiedTime(Path path, long newTime) throws IOException {
    synchronized (this) {
      InMemoryContentInfo status = scopeLimitedStat(path, true);
      status.setLastModifiedTime(newTime == -1L ? clock.currentTimeMillis() : newTime);
    }
  }

  @Override
  protected InputStream getInputStream(Path path) throws IOException {
    synchronized (this) {
      InMemoryContentInfo status = scopeLimitedStat(path, true);
      if (status.isDirectory()) {
        throw Error.EISDIR.exception(path);
      }
      if (!path.isReadable()) {
        throw Error.EACCES.exception(path);
      }
      Preconditions.checkState(status instanceof FileInfo);
      return new ByteArrayInputStream(((FileInfo) status).readContent());
    }
  }

  /** Creates a new file at the given path and returns its inode. */
  private InMemoryContentInfo getOrCreateWritableInode(Path path) throws IOException {
    // open(WR_ONLY) of a dangling link writes through the link.  That means
    // that the usual path lookup operations have to behave differently when
    // resolving a path with the intent to create it: instead of failing with
    // ENOENT they have to return an open file.  This is exactly how UNIX
    // kernels do it, which is what we're trying to emulate.
    InMemoryContentInfo child = pathWalk(path, /*create=*/true);
    Preconditions.checkNotNull(child);
    if (child.isDirectory()) {
      throw Error.EISDIR.exception(path);
    } else { // existing or newly-created file
      if (!child.isWritable()) { throw Error.EACCES.exception(path); }
      return child;
    }
  }

  @Override
  protected OutputStream getOutputStream(Path path, boolean append)
      throws IOException {
    synchronized (this) {
      InMemoryContentInfo status = getOrCreateWritableInode(path);
      return ((FileInfo) status).getOutputStream(append);
    }
  }

  @Override
  public void renameTo(Path sourcePath, Path targetPath)
      throws IOException {
    if (isRootDirectory(sourcePath)) {
      throw Error.EACCES.exception(sourcePath);
    }
    if (isRootDirectory(targetPath)) {
      throw Error.EACCES.exception(targetPath);
    }
    synchronized (this) {
      InMemoryDirectoryInfo sourceParent = getDirectory(sourcePath.getParentDirectory());
      InMemoryDirectoryInfo targetParent = getDirectory(targetPath.getParentDirectory());

      InMemoryContentInfo sourceInode = sourceParent.getChild(baseNameOrWindowsDrive(sourcePath));
      if (sourceInode == null) {
        throw Error.ENOENT.exception(sourcePath);
      }
      InMemoryContentInfo targetInode = targetParent.getChild(baseNameOrWindowsDrive(targetPath));

      unlink(sourceParent, baseNameOrWindowsDrive(sourcePath), sourcePath);
      try {
        // TODO(bazel-team): (2009) test with symbolic links.

        // Precondition checks:
        if (targetInode != null) { // already exists
          if (targetInode.isDirectory()) {
            if (!sourceInode.isDirectory()) {
              throw new IOException(sourcePath + " -> " + targetPath + " (" + Error.EISDIR + ")");
            }
            if (targetInode.getSize() > 2) {
              throw Error.ENOTEMPTY.exception(targetPath);
            }
          } else if (sourceInode.isDirectory()) {
            throw new IOException(sourcePath + " -> " + targetPath + " (" + Error.ENOTDIR + ")");
          }
          unlink(targetParent, baseNameOrWindowsDrive(targetPath), targetPath);
        }
        sourceInode.movedTo(targetPath);
        insert(targetParent, baseNameOrWindowsDrive(targetPath), sourceInode, targetPath);
        return;

      } catch (IOException e) {
        sourceInode.movedTo(sourcePath);
        insert(
            sourceParent,
            baseNameOrWindowsDrive(sourcePath),
            sourceInode,
            sourcePath); // restore source
        throw e;
      }
    }
  }

  @Override
  protected void createFSDependentHardLink(Path linkPath, Path originalPath)
      throws IOException {

    // Same check used when creating a symbolic link
    if (isRootDirectory(originalPath)) {
      throw Error.EACCES.exception(originalPath);
    }

    synchronized (this) {
      InMemoryDirectoryInfo linkParent = getDirectory(linkPath.getParentDirectory());
      // Same check used when creating a symbolic link
      if (linkParent.getChild(baseNameOrWindowsDrive(linkPath)) != null) {
        throw Error.EEXIST.exception(linkPath);
      }
      insert(
          linkParent,
          baseNameOrWindowsDrive(linkPath),
          getDirectory(originalPath.getParentDirectory())
              .getChild(baseNameOrWindowsDrive(originalPath)),
          linkPath);
    }
  }

  /**
   * On Unix the root directory is "/". On Windows there isn't one, so we reach null from
   * getParentDirectory.
   */
  private boolean isRootDirectory(@Nullable Path path) {
    return path == null || path.getPathString().equals("/");
  }

  /**
   * Returns either the base name of the path, or the drive (if referring to a Windows drive).
   *
   * <p>This allows the file system to treat windows drives much like directories.
   */
  private static String baseNameOrWindowsDrive(Path path) {
    String name = path.getBaseName();
    return !name.isEmpty() ? name : path.getDriveStr();
  }
}
