// Copyright 2019 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 static com.google.common.base.MoreObjects.firstNonNull;
import static com.google.devtools.build.lib.collect.CollectionUtils.isNullOrEmpty;

import com.google.common.base.Preconditions;
import com.google.common.collect.Iterators;
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.AbstractFileSystemWithCustomStat;
import com.google.devtools.build.lib.vfs.DigestHashFunction;
import com.google.devtools.build.lib.vfs.FileAccessException;
import com.google.devtools.build.lib.vfs.FileStatus;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.errorprone.annotations.CheckReturnValue;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.SeekableByteChannel;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
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 AbstractFileSystemWithCustomStat {

  protected 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 {@code InMemoryFileSystem} with default clock and given hash function.
   *
   * @param hashFunction the function to use for calculating digests.
   */
  public InMemoryFileSystem(DigestHashFunction hashFunction) {
    this(new JavaClock(), hashFunction);
  }

  /** Creates a new {@code InMemoryFileSystem} with the given clock and hash function. */
  public InMemoryFileSystem(Clock clock, DigestHashFunction hashFunction) {
    super(hashFunction);
    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;
  }

  /** The errors that {@link InMemoryFileSystem} might issue for different sorts of IO failures. */
  protected enum Errno implements InodeOrErrno {
    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;

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

    @Nullable
    @Override
    public InMemoryContentInfo inode() {
      return null;
    }

    @Override
    public Errno error() {
      return this;
    }

    @Override
    public boolean isError() {
      return true;
    }

    @Override
    public InMemoryContentInfo inodeOrThrow(PathFragment path) throws IOException {
      throw exception(path);
    }

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

    /**
     * Throws a new {@link IOException} for this error. The exception message contains {@code path},
     * and is consistent with the messages returned by {@link
     * com.google.devtools.build.lib.vfs.FileSystemUtils}.
     */
    public IOException exception(PathFragment path) throws IOException {
      String m = path + " (" + message + ")";
      switch (this) {
        case EACCES:
          throw new FileAccessException(m);
        case ENOENT:
          throw new FileNotFoundException(m);
        default:
          throw new IOException(m);
      }
    }
  }

  /**
   * {@inheritDoc}
   *
   * <p>If <code>/proc/mounts</code> does not exist return {@code "inmemoryfs"}.
   */
  @Override
  public String getFileSystemType(PathFragment path) {
    return exists(path.getRelative("/proc/mounts")) ? 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 static void unlink(InMemoryDirectoryInfo dir, String child, PathFragment errorPath)
      throws IOException {
    if (!dir.isWritable()) {
      throw Errno.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.
   */
  @CheckReturnValue
  private static Errno insert(
      InMemoryDirectoryInfo dir, String child, InMemoryContentInfo childInode) {
    if (!dir.isWritable()) {
      return Errno.EACCES;
    }
    dir.addChild(child, childInode);
    return null;
  }

  private static void insert(
      InMemoryDirectoryInfo dir,
      String child,
      InMemoryContentInfo childInode,
      PathFragment errorPath)
      throws IOException {
    Errno error = insert(dir, child, childInode);
    if (error != null) {
      throw error.exception(errorPath);
    }
  }

  /**
   * Given an existing directory 'dir', looks up 'name' within it and returns its inode. May fail
   * with ENOTDIR, EACCES, ENOENT. Error messages will be reported against file 'path'.
   */
  private static InodeOrErrno directoryLookupErrno(InMemoryContentInfo dir, String name) {
    if (!dir.isDirectory()) {
      return Errno.ENOTDIR;
    }
    if (!dir.isExecutable()) {
      return Errno.EACCES;
    }
    return firstNonNull(dir.asDirectory().getChild(name), Errno.ENOENT);
  }

  protected FileInfo newFile(Clock clock, PathFragment path) {
    return new InMemoryFileInfo(clock);
  }

  /** How to handle {@link Errno#ENOENT} during {@link #pathWalkErrno}. */
  private enum OnEnoent {
    /** Halt the walk with {@link Errno#ENOENT}. */
    HALT,
    /**
     * Create a file node if at the last segment of the walk, otherwise halt with {@link
     * Errno#ENOENT}.
     */
    CREATE_FILE,
    /** Create a directory node. */
    CREATE_DIRECTORY_AND_PARENTS
  }

  /**
   * 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>ENOENT along the walk is handled according to the given {@link OnEnoent}.
   *
   * <p>May fail with ENOTDIR, ENOENT, EACCES, ELOOP.
   */
  private synchronized InodeOrErrno pathWalkErrno(PathFragment path, OnEnoent behavior) {
    Iterator<String> it = path.segments().iterator();

    // Prepend the Windows drive if there is one.
    if (path.getDriveStrLength() > 1) {
      it = Iterators.concat(Iterators.singletonIterator(path.getDriveStr()), it);
    }

    InMemoryContentInfo inode = rootInode;
    int traversals = 0;

    // Stack of symlink targets. Lazily initialized because we probably won't see any.
    Deque<String> symlinks = null;

    while (it.hasNext() || !isNullOrEmpty(symlinks)) {
      traversals++;

      String name = !isNullOrEmpty(symlinks) ? symlinks.pop() : it.next();

      InodeOrErrno childOrError = directoryLookupErrno(inode, name);

      InMemoryContentInfo child;
      if (!childOrError.isError()) {
        child = childOrError.inode();
      } else if (childOrError.error() == Errno.ENOENT && behavior != OnEnoent.HALT) {
        InMemoryDirectoryInfo parent = inode.asDirectory();
        Errno error;
        if (behavior == OnEnoent.CREATE_DIRECTORY_AND_PARENTS) {
          // ENOENT anywhere with Create.DIRECTORY_AND_PARENTS => create a new directory.
          InMemoryDirectoryInfo newDir = new InMemoryDirectoryInfo(clock);
          error = insertChildDirectory(parent, newDir, name);
          child = newDir;
        } else if (!it.hasNext() && isNullOrEmpty(symlinks)) {
          // ENOENT on last segment with Create.FILE => create a new file.
          child = newFile(clock, path);
          error = insert(parent, name, child);
        } else {
          return childOrError;
        }
        if (error != null) {
          return error;
        }
      } else {
        return childOrError;
      }

      if (!child.isSymbolicLink()) {
        inode = child;
      } else {
        PathFragment linkTarget = ((InMemoryLinkInfo) child).getNormalizedLinkContent();
        if (linkTarget.isAbsolute()) {
          inode = rootInode;
        }
        if (traversals > MAX_TRAVERSALS) {
          return Errno.ELOOP;
        }

        List<String> segments = linkTarget.splitToListOfSegments(); // May include ".." segments.
        if (symlinks == null) {
          symlinks = new ArrayDeque<>(segments);
        } else {
          for (int ii = segments.size() - 1; ii >= 0; --ii) {
            symlinks.push(segments.get(ii));
          }
        }
        // Push Windows drive if there is one.
        if (linkTarget.getDriveStrLength() > 1) {
          symlinks.push(linkTarget.getDriveStr());
        }
      }
    }
    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 InodeOrErrno getDirectoryErrno(PathFragment path) {
    InodeOrErrno dirInfoOrError = pathWalkErrno(path, OnEnoent.HALT);
    if (dirInfoOrError.isError()) {
      return dirInfoOrError;
    }
    return dirInfoOrError.inode().isDirectory() ? dirInfoOrError : Errno.ENOTDIR;
  }

  /**
   * 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(PathFragment path) throws IOException {
    return getDirectoryErrno(path).inodeOrThrow(path).asDirectory();
  }

  /** Helper method for stat and inodeStat: return the path's (no symlink-followed) stat. */
  private synchronized InodeOrErrno noFollowStatErrno(PathFragment path) {
    InodeOrErrno dirInfoOrError = getDirectoryErrno(path.getParentDirectory());
    if (dirInfoOrError.isError()) {
      return dirInfoOrError;
    }
    return directoryLookupErrno(dirInfoOrError.inode(), baseNameOrWindowsDrive(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(PathFragment path, boolean followSymlinks) throws IOException {
    return inodeStatErrno(path, followSymlinks).inodeOrThrow(path);
  }

  @Override
  @Nullable
  public FileStatus statIfFound(PathFragment path, boolean followSymlinks) throws IOException {
    InodeOrErrno inodeOrErrno = inodeStatErrno(path, followSymlinks);
    if (!inodeOrErrno.isError()) {
      return inodeOrErrno.inode();
    }
    Errno errorCode = inodeOrErrno.error();
    if (errorCode == Errno.ENOENT || errorCode == Errno.ENOTDIR) {
      return null;
    }
    throw errorCode.exception(path);
  }

  @Override
  @Nullable
  protected FileStatus statNullable(PathFragment path, boolean followSymlinks) {
    return inodeStatErrno(path, followSymlinks).inode();
  }

  /** Version of stat that returns an InodeOrErrno of the input path. */
  @CheckReturnValue
  protected InodeOrErrno inodeStatErrno(PathFragment path, boolean followSymlinks) {
    if (followSymlinks) {
      return pathWalkErrno(path, OnEnoent.HALT);
    }
    return isRootDirectory(path) ? rootInode : noFollowStatErrno(path);
  }

  private InMemoryContentInfo inodeStat(PathFragment path, boolean followSymlinks)
      throws IOException {
    return inodeStatErrno(path, followSymlinks).inodeOrThrow(path);
  }

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

  /**
   * This is a helper routing for {@link #resolveSymbolicLinks(PathFragment)}, i.e. the "user-mode"
   * routing for canonicalizing 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(PathFragment path) throws IOException {
    // Beware, this seemingly simple code belies the complex specification of
    // FileSystem.resolveOneLink().
    InMemoryContentInfo status = inodeStat(path, false);
    return status.isSymbolicLink() ? ((InMemoryLinkInfo) status).getLinkContent() : null;
  }

  @Override
  protected boolean exists(PathFragment path, boolean followSymlinks) {
    return statNullable(path, followSymlinks) != null;
  }

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

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

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

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

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

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

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

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

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

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

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

    PathFragment parentDir = path.getParentDirectory();
    String name = baseNameOrWindowsDrive(path);
    Errno error;
    synchronized (this) {
      InMemoryDirectoryInfo parent = getDirectory(parentDir);
      InMemoryContentInfo child = parent.getChild(name);
      if (child != null) { // already exists
        if (!child.isDirectory()) {
          throw Errno.EEXIST.exception(path);
        }
        return false;
      }
      error = insertChildDirectory(parent, new InMemoryDirectoryInfo(clock), name);
    }
    if (error != null) {
      throw error.exception(path);
    }
    return true;
  }

  @Nullable
  private static Errno insertChildDirectory(
      InMemoryDirectoryInfo parent, InMemoryDirectoryInfo newDir, String name) {
    newDir.addChild(".", newDir);
    newDir.addChild("..", parent);
    return insert(parent, name, newDir);
  }

  @Override
  public void createDirectoryAndParents(PathFragment path) throws IOException {
    InMemoryContentInfo result =
        pathWalkErrno(path, OnEnoent.CREATE_DIRECTORY_AND_PARENTS).inodeOrThrow(path);
    if (!result.isDirectory()) {
      throw new IOException("Not a directory: " + path);
    }
  }

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

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

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

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

  @Override
  protected synchronized Collection<String> getDirectoryEntries(PathFragment path)
      throws IOException {
    InMemoryDirectoryInfo dirInfo = getDirectory(path);
    if (!dirInfo.isReadable()) {
      throw Errno.EACCES.exception(path);
    }

    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
  protected boolean delete(PathFragment path) throws IOException {
    if (isRootDirectory(path)) {
      throw Errno.EBUSY.exception(path);
    }

    synchronized (this) {
      if (!exists(path, /*followSymlinks=*/ false)) {
        return false;
      }
      InMemoryDirectoryInfo parent = getDirectory(path.getParentDirectory());
      InMemoryContentInfo child = parent.getChild(baseNameOrWindowsDrive(path));
      if (child.isDirectory() && child.getSize() > 2) {
        throw Errno.ENOTEMPTY.exception(path);
      }
      unlink(parent, baseNameOrWindowsDrive(path), path);
      return true;
    }
  }

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

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

  @Override
  protected synchronized InputStream getInputStream(PathFragment path) throws IOException {
    return statFile(path).getInputStream();
  }

  @Override
  protected synchronized ReadableByteChannel createReadableByteChannel(PathFragment path)
      throws IOException {
    return statFile(path).createReadableByteChannel();
  }

  @Override
  protected synchronized SeekableByteChannel createReadWriteByteChannel(PathFragment path) {
    // It's feasible to implement, but so far it is not needed.
    throw new UnsupportedOperationException("Not implemented");
  }

  @Override
  protected synchronized byte[] getFastDigest(PathFragment path) throws IOException {
    return statFile(path).getFastDigest();
  }

  private FileInfo statFile(PathFragment path) throws IOException {
    InMemoryContentInfo status = inodeStat(path, /*followSymlinks=*/ true);
    if (status.isDirectory()) {
      throw Errno.EISDIR.exception(path);
    }
    if (!status.isReadable()) {
      throw Errno.EACCES.exception(path);
    }
    Preconditions.checkState(status instanceof FileInfo, status);
    return (FileInfo) status;
  }

  @Override
  @Nullable
  public synchronized byte[] getxattr(PathFragment path, String name, boolean followSymlinks)
      throws IOException {
    InMemoryContentInfo status = inodeStat(path, followSymlinks);
    if (status.isDirectory()) {
      throw Errno.EISDIR.exception(path);
    }
    if (!isReadable(path)) {
      throw Errno.EACCES.exception(path);
    }
    if (!followSymlinks && status.isSymbolicLink()) {
      return null; // xattr on symlinks not supported.
    }
    Preconditions.checkState(status instanceof FileInfo, status);
    return ((FileInfo) status).getxattr(name);
  }

  /** Creates a new file at the given path and returns its inode. */
  protected InMemoryContentInfo getOrCreateWritableInode(PathFragment 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 = pathWalkErrno(path, OnEnoent.CREATE_FILE).inodeOrThrow(path);
    if (child.isDirectory()) {
      throw Errno.EISDIR.exception(path);
    }
    if (!child.isWritable()) {
      throw Errno.EACCES.exception(path);
    }
    return child;
  }

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

  @Override
  public void renameTo(PathFragment sourcePath, PathFragment targetPath) throws IOException {
    if (isRootDirectory(sourcePath)) {
      throw Errno.EACCES.exception(sourcePath);
    }
    if (isRootDirectory(targetPath)) {
      throw Errno.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 Errno.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 + " (" + Errno.EISDIR + ")");
            }
            if (targetInode.getSize() > 2) {
              throw Errno.ENOTEMPTY.exception(targetPath);
            }
          } else if (sourceInode.isDirectory()) {
            throw new IOException(sourcePath + " -> " + targetPath + " (" + Errno.ENOTDIR + ")");
          }
          unlink(targetParent, baseNameOrWindowsDrive(targetPath), targetPath);
        }
        insert(targetParent, baseNameOrWindowsDrive(targetPath), sourceInode, targetPath);
      } catch (IOException e) {
        insert(
            sourceParent,
            baseNameOrWindowsDrive(sourcePath),
            sourceInode,
            sourcePath); // restore source
        throw e;
      }
    }
  }

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

    // Same check used when creating a symbolic link
    if (isRootDirectory(originalPath)) {
      throw Errno.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 Errno.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 static boolean isRootDirectory(@Nullable PathFragment 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(PathFragment path) {
    String name = path.getBaseName();
    return !name.isEmpty() ? name : path.getDriveStr();
  }

  /** Represents either an {@link Errno} or an {@link InMemoryContentInfo}. */
  protected interface InodeOrErrno {

    @Nullable
    InMemoryContentInfo inode();

    @Nullable
    Errno error();

    boolean isError();

    /**
     * Returns the underlying {@link InMemoryContentInfo} unless this {@link #isError}, in which
     * case {@link IOException} is thrown, using the given path to construct an error message.
     */
    InMemoryContentInfo inodeOrThrow(PathFragment path) throws IOException;
  }
}
