// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "platform/globals.h"
#if defined(TARGET_OS_ANDROID)

#include "bin/directory.h"

#include <dirent.h>  // NOLINT
#include <errno.h>  // NOLINT
#include <string.h>  // NOLINT
#include <sys/param.h>  // NOLINT
#include <sys/stat.h>  // NOLINT
#include <unistd.h>  // NOLINT

#include "bin/file.h"
#include "bin/platform.h"


namespace dart {
namespace bin {

class PathBuffer {
 public:
  PathBuffer() : length(0) {
    data = new char[PATH_MAX + 1];
  }

  ~PathBuffer() {
    delete[] data;
  }

  char* data;
  int length;

  bool Add(const char* name) {
    int written = snprintf(data + length,
                           PATH_MAX - length,
                           "%s",
                           name);
    data[PATH_MAX] = '\0';
    if (written <= PATH_MAX - length &&
        written >= 0 &&
        static_cast<size_t>(written) == strnlen(name, PATH_MAX + 1)) {
      length += written;
      return true;
    } else {
      errno = ENAMETOOLONG;
      return false;
    }
  }

  void Reset(int new_length) {
    length = new_length;
    data[length] = '\0';
  }
};


// A linked list of symbolic links, with their unique file system identifiers.
// These are scanned to detect loops while doing a recursive directory listing.
struct LinkList {
  dev_t dev;
  ino_t ino;
  LinkList* next;
};


// Forward declarations.
static bool ListRecursively(PathBuffer* path,
                            bool recursive,
                            bool follow_links,
                            LinkList* seen,
                            DirectoryListing* listing);
static bool DeleteRecursively(PathBuffer* path);


static void PostError(DirectoryListing *listing,
                      const char* dir_name) {
  listing->HandleError(dir_name);
}


static bool HandleDir(char* dir_name,
                      PathBuffer* path,
                      bool recursive,
                      bool follow_links,
                      LinkList* seen,
                      DirectoryListing *listing) {
  if (strcmp(dir_name, ".") == 0) return true;
  if (strcmp(dir_name, "..") == 0) return true;
  if (!path->Add(dir_name)) {
    PostError(listing, path->data);
    return false;
  }
  return listing->HandleDirectory(path->data) &&
      (!recursive ||
       ListRecursively(path, recursive, follow_links, seen, listing));
}


static bool HandleFile(char* file_name,
                       PathBuffer* path,
                       DirectoryListing *listing) {
  if (!path->Add(file_name)) {
    PostError(listing, path->data);
    return false;
  }
  return listing->HandleFile(path->data);
}


static bool HandleLink(char* link_name,
                       PathBuffer* path,
                       DirectoryListing *listing) {
  if (!path->Add(link_name)) {
    PostError(listing, path->data);
    return false;
  }
  return listing->HandleLink(path->data);
}


static bool ListRecursively(PathBuffer* path,
                            bool recursive,
                            bool follow_links,
                            LinkList* seen,
                            DirectoryListing *listing) {
  if (!path->Add(File::PathSeparator())) {
    PostError(listing, path->data);
    return false;
  }
  DIR* dir_pointer;
  do {
    dir_pointer = opendir(path->data);
  } while (dir_pointer == NULL && errno == EINTR);
  if (dir_pointer == NULL) {
    PostError(listing, path->data);
    return false;
  }

  // Iterate the directory and post the directories and files to the
  // ports.
  int path_length = path->length;
  int status = 0;
  bool success = true;
  dirent entry;
  dirent* result;
  while ((status = TEMP_FAILURE_RETRY(readdir_r(dir_pointer,
                                                &entry,
                                                &result))) == 0 &&
         result != NULL) {
    switch (entry.d_type) {
      case DT_DIR:
        success = HandleDir(entry.d_name,
                            path,
                            recursive,
                            follow_links,
                            seen,
                            listing) && success;
        break;
      case DT_REG:
        success = HandleFile(entry.d_name,
                             path,
                             listing) && success;
        break;
      case DT_LNK:
        if (!follow_links) {
          success = HandleLink(entry.d_name,
                               path,
                               listing) && success;
          break;
        }
        // Else fall through to next case.
        // Fall through.
      case DT_UNKNOWN: {
        // On some file systems the entry type is not determined by
        // readdir_r. For those and for links we use stat to determine
        // the actual entry type. Notice that stat returns the type of
        // the file pointed to.
        struct stat entry_info;
        if (!path->Add(entry.d_name)) {
          success = false;
          break;
        }
        int stat_success;
        stat_success = TEMP_FAILURE_RETRY(lstat(path->data, &entry_info));
        if (stat_success == -1) {
          success = false;
          PostError(listing, path->data);
          break;
        }
        if (follow_links && S_ISLNK(entry_info.st_mode)) {
          // Check to see if we are in a loop created by a symbolic link.
          LinkList current_link = { entry_info.st_dev,
                                    entry_info.st_ino,
                                    seen };
          LinkList* previous = seen;
          bool looping_link = false;
          while (previous != NULL) {
            if (previous->dev == current_link.dev &&
                previous->ino == current_link.ino) {
              // Report the looping link as a link, rather than following it.
              path->Reset(path_length);
              success = HandleLink(entry.d_name,
                                   path,
                                   listing) && success;
              looping_link = true;
              break;
            }
            previous = previous->next;
          }
          if (looping_link) break;
          stat_success = TEMP_FAILURE_RETRY(stat(path->data, &entry_info));
          if (stat_success == -1) {
            // Report a broken link as a link, even if follow_links is true.
            path->Reset(path_length);
            success = HandleLink(entry.d_name,
                                 path,
                                 listing) && success;
            break;
          }
          if (S_ISDIR(entry_info.st_mode)) {
            // Recurse into the subdirectory with current_link added to the
            // linked list of seen file system links.
            path->Reset(path_length);
            success = HandleDir(entry.d_name,
                                path,
                                recursive,
                                follow_links,
                                &current_link,
                                listing) && success;
            break;
          }
        }
        path->Reset(path_length);
        if (S_ISDIR(entry_info.st_mode)) {
          success = HandleDir(entry.d_name,
                              path,
                              recursive,
                              follow_links,
                              seen,
                              listing) && success;
        } else if (S_ISREG(entry_info.st_mode)) {
          success = HandleFile(entry.d_name,
                               path,
                               listing) && success;
        } else if (S_ISLNK(entry_info.st_mode)) {
          success = HandleLink(entry.d_name,
                               path,
                               listing) && success;
        }
        break;
      }
      default:
        break;
    }
    path->Reset(path_length);
  }

  if (status != 0) {
    errno = status;
    success = false;
    PostError(listing, path->data);
  }

  if (closedir(dir_pointer) == -1) {
    success = false;
    PostError(listing, path->data);
  }

  return success;
}


static bool DeleteFile(char* file_name,
                       PathBuffer* path) {
  return path->Add(file_name) && unlink(path->data) == 0;
}


static bool DeleteDir(char* dir_name,
                      PathBuffer* path) {
  if (strcmp(dir_name, ".") == 0) return true;
  if (strcmp(dir_name, "..") == 0) return true;
  return path->Add(dir_name) && DeleteRecursively(path);
}


static bool DeleteRecursively(PathBuffer* path) {
  // Do not recurse into links for deletion. Instead delete the link.
  // If it's a file, delete it.
  struct stat st;
  if (TEMP_FAILURE_RETRY(lstat(path->data, &st)) == -1) {
    return false;
  } else if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) {
    return (unlink(path->data) == 0);
  }

  if (!path->Add(File::PathSeparator())) return false;

  // Not a link. Attempt to open as a directory and recurse into the
  // directory.
  DIR* dir_pointer;
  do {
    dir_pointer = opendir(path->data);
  } while (dir_pointer == NULL && errno == EINTR);

  if (dir_pointer == NULL) {
    return false;
  }

  // Iterate the directory and delete all files and directories.
  int path_length = path->length;
  int read = 0;
  bool success = true;
  dirent entry;
  dirent* result;
  while ((read = TEMP_FAILURE_RETRY(readdir_r(dir_pointer,
                                              &entry,
                                              &result))) == 0 &&
         result != NULL &&
         success) {
    switch (entry.d_type) {
      case DT_DIR:
        success = success && DeleteDir(entry.d_name, path);
        break;
      case DT_REG:
      case DT_LNK:
        // Treat all links as files. This will delete the link which
        // is what we want no matter if the link target is a file or a
        // directory.
        success = success && DeleteFile(entry.d_name, path);
        break;
      case DT_UNKNOWN: {
        // On some file systems the entry type is not determined by
        // readdir_r. For those we use lstat to determine the entry
        // type.
        struct stat entry_info;
        if (!path->Add(entry.d_name)) {
          success = false;
          break;
        }
        int lstat_success = TEMP_FAILURE_RETRY(lstat(path->data, &entry_info));
        if (lstat_success == -1) {
          success = false;
          break;
        }
        path->Reset(path_length);
        if (S_ISDIR(entry_info.st_mode)) {
          success = success && DeleteDir(entry.d_name, path);
        } else if (S_ISREG(entry_info.st_mode) || S_ISLNK(entry_info.st_mode)) {
          // Treat links as files. This will delete the link which is
          // what we want no matter if the link target is a file or a
          // directory.
          success = success && DeleteFile(entry.d_name, path);
        }
        break;
      }
      default:
        break;
    }
    path->Reset(path_length);
  }

  if ((read != 0) ||
      (closedir(dir_pointer) == -1) ||
      (remove(path->data) == -1)) {
    return false;
  }
  return success;
}


bool Directory::List(const char* dir_name,
                     bool recursive,
                     bool follow_links,
                     DirectoryListing *listing) {
  PathBuffer path;
  if (!path.Add(dir_name)) {
    PostError(listing, dir_name);
    return false;
  }
  return ListRecursively(&path, recursive, follow_links, NULL, listing);
}


Directory::ExistsResult Directory::Exists(const char* dir_name) {
  struct stat entry_info;
  int success = TEMP_FAILURE_RETRY(stat(dir_name, &entry_info));
  if (success == 0) {
    if (S_ISDIR(entry_info.st_mode)) {
      return EXISTS;
    } else {
      return DOES_NOT_EXIST;
    }
  } else {
    if (errno == EACCES ||
        errno == EBADF ||
        errno == EFAULT ||
        errno == ENOMEM ||
        errno == EOVERFLOW) {
      // Search permissions denied for one of the directories in the
      // path or a low level error occured. We do not know if the
      // directory exists.
      return UNKNOWN;
    }
    ASSERT(errno == ELOOP ||
           errno == ENAMETOOLONG ||
           errno == ENOENT ||
           errno == ENOTDIR);
    return DOES_NOT_EXIST;
  }
}


char* Directory::Current() {
  // Android's getcwd adheres closely to the POSIX standard. It won't
  // allocate memory. We need to make our own copy.

  char buffer[PATH_MAX];
  if (NULL == getcwd(buffer, PATH_MAX)) {
    return NULL;
  }

  return strdup(buffer);
}


bool Directory::SetCurrent(const char* path) {
  int result = TEMP_FAILURE_RETRY(chdir(path));
  return result == 0;
}


bool Directory::Create(const char* dir_name) {
  // Create the directory with the permissions specified by the
  // process umask.
  int result = TEMP_FAILURE_RETRY(mkdir(dir_name, 0777));
  // If the directory already exists, treat it as a success.
  if (result == -1 && errno == EEXIST) {
    return (Exists(dir_name) == EXISTS);
  }
  return (result == 0);
}


// Android doesn't currently provide mkdtemp.  Once Android provied mkdtemp,
// remove this function in favor of calling mkdtemp directly.
static char* MakeTempDirectory(char* path_template) {
  if (mktemp(path_template) == NULL) {
    return NULL;
  }
  if (mkdir(path_template, 0700) != 0) {
    return NULL;
  }
  return path_template;
}


char* Directory::CreateTemp(const char* const_template) {
  // Returns a new, unused directory name, modifying the contents of
  // dir_template.  Creates the directory with the permissions specified
  // by the process umask.
  // The return value must be freed by the caller.
  PathBuffer path;
  path.Add(const_template);
  if (path.length == 0) {
    // Android does not have a /tmp directory. A partial substitute,
    // suitable for bring-up work and tests, is to create a tmp
    // directory in /data/local/tmp.
    //
    // TODO(4413): In the long run, when running in an application we should
    // probably use android.content.Context.getCacheDir().
    #define ANDROID_TEMP_DIR "/data/local/tmp"
    struct stat st;
    if (stat(ANDROID_TEMP_DIR, &st) != 0) {
      mkdir(ANDROID_TEMP_DIR, 0777);
    }
    path.Add(ANDROID_TEMP_DIR "/temp_dir1_");
  } else if ((path.data)[path.length - 1] == '/') {
    path.Add("temp_dir_");
  }
  if (!path.Add("XXXXXX")) {
    // Pattern has overflowed.
    return NULL;
  }
  char* result;
  do {
    result = MakeTempDirectory(path.data);
  } while (result == NULL && errno == EINTR);
  if (result == NULL) {
    return NULL;
  }
  int length = strnlen(path.data, PATH_MAX);
  result = static_cast<char*>(malloc(length + 1));
  strncpy(result, path.data, length);
  result[length] = '\0';
  return result;
}


bool Directory::Delete(const char* dir_name, bool recursive) {
  if (!recursive) {
    if (File::GetType(dir_name, false) == File::kIsLink &&
        File::GetType(dir_name, true) == File::kIsDirectory) {
      return (TEMP_FAILURE_RETRY(unlink(dir_name)) == 0);
    }
    return (TEMP_FAILURE_RETRY(rmdir(dir_name)) == 0);
  } else {
    PathBuffer path;
    if (!path.Add(dir_name)) {
      return false;
    }
    return DeleteRecursively(&path);
  }
}


bool Directory::Rename(const char* path, const char* new_path) {
  ExistsResult exists = Exists(path);
  if (exists != EXISTS) return false;
  return (TEMP_FAILURE_RETRY(rename(path, new_path)) == 0);
}

}  // namespace bin
}  // namespace dart

#endif  // defined(TARGET_OS_ANDROID)
