// 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.
   */
  @Nullable
  @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.
   */
  @Nullable
  @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 == Path.NOW_SENTINEL_TIME ? 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, boolean internal) 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;
  }
}
