text: /*
   * The MIT License (MIT)
   *
   * Copyright (c) 2015 Microsoft Corporation
   *
   * -=- Robust Distributed System Nucleus (rDSN) -=-
   *
   * Permission is hereby granted, free of charge, to any person obtaining a copy
   * of this software and associated documentation files (the "Software"), to deal
   * in the Software without restriction, including without limitation the rights
   * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   * copies of the Software, and to permit persons to whom the Software is
   * furnished to do so, subject to the following conditions:
   *
   * The above copyright notice and this permission notice shall be included in
   * all copies or substantial portions of the Software.
   *
   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   * THE SOFTWARE.
   */
  
  // Copyright (c) 2017-present, Xiaomi, Inc.  All rights reserved.
  // This source code is licensed under the Apache License Version 2.0, which
  // can be found in the LICENSE file in the root directory of this source tree.
  
  #pragma once
  
  #include <string>
  #include <dsn/utility/error_code.h>
  
  #ifndef _XOPEN_SOURCE
  #define _XOPEN_SOURCE 500
  #endif
  
  #include <ftw.h>
  
  #ifndef FTW_CONTINUE
  #define FTW_CONTINUE 0
  #endif
  
  #ifndef FTW_STOP
  #define FTW_STOP 1
  #endif
  
  #ifndef FTW_SKIP_SUBTREE
  #define FTW_SKIP_SUBTREE 2
  #endif
  
  #ifndef FTW_SKIP_SIBLINGS
  #define FTW_SKIP_SIBLINGS 3
  #endif
  
  namespace dsn {
  namespace utils {
  namespace filesystem {
  
  int get_normalized_path(const std::string &path, std::string &npath);
  
  bool get_absolute_path(const std::string &path1, std::string &path2);
  
  std::string remove_file_name(const std::string &path);
  
  std::string get_file_name(const std::string &path);
  
  std::string path_combine(const std::string &path1, const std::string &path2);
  
  typedef std::function<int(const char *, int, struct FTW *)> ftw_handler;
  bool file_tree_walk(const std::string &dirpath, ftw_handler handler, bool recursive = true);
  
  bool path_exists(const std::string &path);
  
  bool directory_exists(const std::string &path);
  
  bool file_exists(const std::string &path);
  
  bool get_subfiles(const std::string &path, std::vector<std::string> &sub_list, bool recursive);
  
  bool get_subdirectories(const std::string &path,
                          std::vector<std::string> &sub_list,
                          bool recursive);
  
  bool get_subpaths(const std::string &path, std::vector<std::string> &sub_list, bool recursive);
  
  // Returns true if no error.
  bool remove_path(const std::string &path);
  
  // this will always remove target path if exist
  bool rename_path(const std::string &path1, const std::string &path2);
  
  bool file_size(const std::string &path, int64_t &sz);
  
  bool create_directory(const std::string &path);
  
  bool create_file(const std::string &path);
  
  bool get_current_directory(std::string &path);
  
  bool last_write_time(const std::string &path, time_t &tm);
  
  error_code get_process_image_path(int pid, std::string &path);
  
  inline error_code get_current_process_image_path(std::string &path)
  {
      auto err = dsn::utils::filesystem::get_process_image_path(-1, path);
      assert(err == ERR_OK);
      return err;
  }
  
  struct disk_space_info
  {
      // all values are byte counts
      uint64_t capacity;
      uint64_t available;
  };
  bool get_disk_space_info(const std::string &path, disk_space_info &info);
  
  bool link_file(const std::string &src, const std::string &target);
  
  error_code md5sum(const std::string &file_path, /*out*/ std::string &result);
  
  // return value:
  //  - <A, B>:
  //          A is represent whether operation encounter some local error
  //          B is represent wheter the directory is empty, true means empty, otherwise false
  std::pair<error_code, bool> is_directory_empty(const std::string &dirname);
  
  error_code read_file(const std::string &fname, /*out*/ std::string &buf);
  
  // compare file metadata calculated by fname with expected md5 and file_size
  bool verify_file(const std::string &fname,
                   const std::string &expected_md5,
                   const int64_t &expected_fsize);
  
  } // namespace filesystem
  } // namespace utils
  } // namespace dsn
  