// 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.unix;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.flogger.GoogleLogger;
import com.google.devtools.build.lib.jni.JniLoader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.logging.LogManager;

/**
 * Utility methods for access to UNIX filesystem calls not exposed by the Java
 * SDK. Exception messages are selected to be consistent with those generated
 * by the java.io package where appropriate--see package javadoc for details.
 */
public final class NativePosixFiles {
  private NativePosixFiles() {}

  static {
    if (!java.nio.charset.Charset.defaultCharset().name().equals("ISO-8859-1")) {
      // Defer the Logger call, so we don't deadlock if this is called from Logger
      // initialization code.
      new Thread(
              () -> {
                // wait (if necessary) until the logging system is initialized
                synchronized (LogManager.getLogManager()) {
                }
                @SuppressWarnings("FloggerRequiredModifiers")
                GoogleLogger logger = GoogleLogger.forEnclosingClass();
                logger.atFine().log(
                    "WARNING: Default character set is not latin1; java.io.File and"
                        + " com.google.devtools.build.lib.unix.FilesystemUtils will represent"
                        + " some filenames differently.");
              })
          .start();
    }
    JniLoader.loadJni();
    initJNIClasses();
  }

  /**
   * Native wrapper around Linux readlink(2) call.
   *
   * @param path the file of interest
   * @return the pathname to which the symbolic link 'path' links
   * @throws IOException iff the readlink() call failed
   */
  public static native String readlink(String path) throws IOException;

  /**
   * Native wrapper around POSIX chmod(2) syscall: Changes the file access
   * permissions of 'path' to 'mode'.
   *
   * @param path the file of interest
   * @param mode the POSIX type and permission mode bits to set
   * @throws IOException iff the chmod() call failed.
   */
  public static native void chmod(String path, int mode) throws IOException;

  /**
   * Native wrapper around POSIX symlink(2) syscall.
   *
   * @param oldpath the file to link to
   * @param newpath the new path for the link
   * @throws IOException iff the symlink() syscall failed.
   */
  public static native void symlink(String oldpath, String newpath)
      throws IOException;

  /**
   * Native wrapper around POSIX link(2) syscall.
   *
   * @param oldpath the file to link to
   * @param newpath the new path for the link
   * @throws IOException iff the link() syscall failed.
   */
  public static native void link(String oldpath, String newpath) throws IOException;

  /**
   * Native wrapper around POSIX stat(2) syscall.
   *
   * @param path the file to stat.
   * @return a FileStatus instance containing the metadata.
   * @throws IOException if the stat() syscall failed.
   */
  public static native FileStatus stat(String path) throws IOException;

  /**
   * Native wrapper around POSIX lstat(2) syscall.
   *
   * @param path the file to lstat.
   * @return a FileStatus instance containing the metadata.
   * @throws IOException if the lstat() syscall failed.
   */
  public static native FileStatus lstat(String path) throws IOException;

  /**
   * Native wrapper around POSIX stat(2) syscall.
   *
   * @param path the file to stat.
   * @return an ErrnoFileStatus instance containing the metadata.
   *   If there was an error, the return value's hasError() method
   *   will return true, and all stat information is undefined.
   */
  public static native ErrnoFileStatus errnoStat(String path);

  /**
   * Native wrapper around POSIX lstat(2) syscall.
   *
   * @param path the file to lstat.
   * @return an ErrnoFileStatus instance containing the metadata.
   *   If there was an error, the return value's hasError() method
   *   will return true, and all stat information is undefined.
   */
  public static native ErrnoFileStatus errnoLstat(String path);

  /**
   * Native wrapper around POSIX utime(2) syscall.
   *
   * Note: negative file times are interpreted as unsigned time_t.
   *
   * @param path the file whose times to change.
   * @param now if true, ignore actime/modtime parameters and use current time.
   * @param modtime the file modification time in seconds since the UNIX epoch.
   * @throws IOException if the utime() syscall failed.
   */
  public static native void utime(String path, boolean now, int modtime) throws IOException;

  /**
   * Native wrapper around POSIX mkdir(2) syscall.
   *
   * Caveat: errno==EEXIST is mapped to the return value "false", not
   * IOException.  It requires an additional stat() to determine if mkdir
   * failed because the directory already exists.
   *
   * @param path the directory to create.
   * @param mode the mode with which to create the directory.
   * @return true if the directory was successfully created; false if the
   *   system call returned EEXIST because some kind of a file (not necessarily
   *   a directory) already exists.
   * @throws IOException if the mkdir() syscall failed for any other reason.
   */
  public static native boolean mkdir(String path, int mode)
      throws IOException;

  /**
   * Makes sure a writable directory exists at a given path. Returns whether a new directory was
   * created.
   *
   * <p>Unlike {@link #mkdir}, it fails if a file/symlink at a given path already exists. If a
   * directory is already present, it will make sure it is writable and return false.
   */
  public static native boolean mkdirWritable(String path);

  /**
   * Implements (effectively) mkdir -p.
   *
   * @param path the directory to recursively create.
   * @param mode the mode with which to create the directories.
   * @throws IOException if the directory creation failed for any reason.
   */
  public static native void mkdirs(String path, int mode) throws IOException;

  /**
   * Native wrapper around POSIX opendir(2)/readdir(3)/closedir(3) syscall.
   *
   * @param path the directory to read.
   * @return the list of directory entries in the order they were returned by the system, excluding
   *     "." and "..".
   * @throws IOException if the call to opendir failed for any reason.
   */
  public static String[] readdir(String path) throws IOException {
    return readdir(path, ReadTypes.NONE).names;
  }

  /**
   * Native wrapper around POSIX opendir(2)/readdir(3)/closedir(3) syscall.
   *
   * @param path the directory to read.
   * @param readTypes How the types of individual entries should be returned. If {@code NONE}, the
   *     "types" field in the result will be null.
   * @return a Dirents object, containing "names", the list of directory entries (excluding "." and
   *     "..") in the order they were returned by the system, and "types", an array of entry types
   *     (file, directory, etc) corresponding positionally to "names".
   * @throws IOException if the call to opendir failed for any reason.
   */
  public static Dirents readdir(String path, ReadTypes readTypes) throws IOException {
    // Passing enums to native code is possible, but onerous; we use a char instead.
    return readdir(path, readTypes.getCode());
  }

  private static native Dirents readdir(String path, char typeCode) throws IOException;

  /**
   * An enum for specifying now the types of the individual entries returned by
   * {@link #readdir(String, ReadTypes)} is to be returned.
   */
  public enum ReadTypes {
    NONE('n'),      // Do not read types
    NOFOLLOW('d'),  // Do not follow symlinks
    FOLLOW('f');    // Follow symlinks; never returns "SYMLINK" and returns "UNKNOWN" when dangling

    private final char code;

    private ReadTypes(char code) {
      this.code = code;
    }

    private char getCode() {
      return code;
    }
  }

  /**
   * A compound return type for readdir(), analogous to struct dirent[] in C. A low memory profile
   * is critical for this class, as instances are expected to be kept around for caching for
   * potentially a long time.
   */
  public static final class Dirents {

  /**
   * The type of the directory entry.
   */
  public enum Type {
    FILE,
    DIRECTORY,
    SYMLINK,
    UNKNOWN;

    private static Type forChar(char c) {
      if (c == 'f') {
        return Type.FILE;
      } else if (c == 'd') {
        return Type.DIRECTORY;
      } else if (c == 's') {
        return Type.SYMLINK;
      } else {
        return Type.UNKNOWN;
      }
    }
  }

    /** The names of the entries in a directory. */
    private final String[] names;
    /**
     * An optional (nullable) array of entry types, corresponding positionally
     * to the "names" field.  The types are:
     *   'd': a subdirectory
     *   'f': a regular file
     *   's': a symlink (only returned with {@code NOFOLLOW})
     *   '?': anything else
     * Note that unlike libc, this implementation of readdir() follows
     * symlinks when determining these types.
     *
     * <p>This is intentionally a byte array rather than a array of enums to save memory.
     */
    private final byte[] types;

    /** called from JNI */
    public Dirents(String[] names, byte[] types) {
      this.names = names;
      this.types = types;
    }

    public int size() {
      return names.length;
    }

    public boolean hasTypes() {
      return types != null;
    }

    public String getName(int i) {
      return names[i];
    }

    public Type getType(int i) {
      return Type.forChar((char) types[i]);
    }
  }

  /**
   * Native wrapper around POSIX rename(2) syscall.
   *
   * @param oldpath the source location.
   * @param newpath the destination location.
   * @throws IOException if the rename failed for any reason.
   */
  public static native void rename(String oldpath, String newpath)
      throws IOException;

  /**
   * Native wrapper around POSIX remove(3) C library call.
   *
   * @param path the file or directory to remove.
   * @return true iff the file was actually deleted by this call.
   * @throws IOException if the remove failed, but the file was present prior to the call.
   */
  public static native boolean remove(String path) throws IOException;

  /**
   * Native wrapper around POSIX mkfifo(3) C library call.
   *
   * @param path the name of the pipe to create.
   * @param mode the mode with which to create the pipe.
   * @throws IOException if the mkfifo failed.
   */
  @VisibleForTesting
  public static native void mkfifo(String path, int mode) throws IOException;

  /********************************************************************
   *                                                                  *
   *                  Linux extended file attributes                  *
   *                                                                  *
   ********************************************************************/

  /**
   * Native wrapper around Linux getxattr(2) syscall.
   *
   * @param path the file whose extended attribute is to be returned.
   * @param name the name of the extended attribute key.
   * @return the value of the extended attribute associated with 'path', if
   *   any, or null if no such attribute is defined (ENODATA).
   * @throws IOException if the call failed for any other reason.
   */
  public static native byte[] getxattr(String path, String name)
      throws IOException;

  /**
   * Native wrapper around Linux lgetxattr(2) syscall.  (Like getxattr, but
   * does not follow symbolic links.)
   *
   * @param path the file whose extended attribute is to be returned.
   * @param name the name of the extended attribute key.
   * @return the value of the extended attribute associated with 'path', if
   *   any, or null if no such attribute is defined (ENODATA).
   * @throws IOException if the call failed for any other reason.
   */
  public static native byte[] lgetxattr(String path, String name)
      throws IOException;

  /**
   * Deletes all directory trees recursively beneath the given path, which is expected to be a
   * directory. Does not remove the top directory.
   *
   * @param dir the directory hierarchy to remove
   * @throws IOException if the hierarchy cannot be removed successfully or if the given path is not
   *     a directory
   */
  public static native void deleteTreesBelow(String dir) throws IOException;

  /**
   * Open a file descriptor for writing.
   *
   * <p>This is a low level API. The caller is responsible for calling {@link close} on the returned
   * file descriptor.
   *
   * @param path file to open
   * @param append whether to open is append mode
   */
  public static native int openWrite(String path, boolean append) throws FileNotFoundException;

  /** Write a segment of data to a file descriptor. */
  public static native int write(int fd, byte[] data, int off, int len) throws IOException;

  /**
   * Close a file descriptor. Additionally, accept and ignore an object; this can be used to keep a
   * reference alive.
   */
  public static native int close(int fd, Object ignored) throws IOException;

  private static native void initJNIClasses();
}
