LCOV - code coverage report
Current view: top level - envoy/filesystem - filesystem.h (source / functions) Hit Total Coverage
Test: coverage.dat Lines: 10 14 71.4 %
Date: 2024-01-05 06:35:25 Functions: 8 10 80.0 %

          Line data    Source code
       1             : #pragma once
       2             : 
       3             : #include <bitset>
       4             : #include <cstdint>
       5             : #include <memory>
       6             : #include <string>
       7             : 
       8             : #include "envoy/api/io_error.h"
       9             : #include "envoy/common/platform.h"
      10             : #include "envoy/common/pure.h"
      11             : #include "envoy/common/time.h"
      12             : 
      13             : #include "absl/status/statusor.h"
      14             : #include "absl/strings/string_view.h"
      15             : #include "absl/types/optional.h"
      16             : 
      17             : namespace Envoy {
      18             : namespace Filesystem {
      19             : 
      20             : using FlagSet = std::bitset<5>;
      21             : 
      22             : enum class DestinationType { File, Stderr, Stdout, TmpFile };
      23             : 
      24             : enum class FileType { Regular, Directory, Other };
      25             : 
      26             : struct FileInfo {
      27             :   const std::string name_;
      28             :   // the size of the file in bytes, or `nullopt` if the size could not be determined
      29             :   //         (e.g. for directories, or windows symlinks.)
      30             :   const absl::optional<uint64_t> size_;
      31             :   // Note that if the file represented by name_ is a symlink, type_ will be the file type of the
      32             :   // target. For example, if name_ is a symlink to a directory, its file type will be Directory.
      33             :   // A broken symlink on posix will have `FileType::Regular`.
      34             :   const FileType file_type_;
      35             :   const absl::optional<SystemTime> time_created_;
      36             :   const absl::optional<SystemTime> time_last_accessed_;
      37             :   const absl::optional<SystemTime> time_last_modified_;
      38             : };
      39             : 
      40             : /**
      41             :  * Abstraction for a basic file on disk.
      42             :  */
      43             : class File {
      44             : public:
      45         659 :   virtual ~File() = default;
      46             : 
      47             :   enum Operation {
      48             :     // Open a file for reading.
      49             :     Read,
      50             :     // Open a file for writing. The file will be truncated if neither Append nor
      51             :     // KeepExisting is set.
      52             :     Write,
      53             :     // Create the file if it does not already exist
      54             :     Create,
      55             :     // If writing, append to the file rather than writing to the beginning and
      56             :     // truncating after write.
      57             :     Append,
      58             :     // To open for write, without appending, and without truncating, add the
      59             :     // KeepExistingData flag. It is especially important to set this flag if
      60             :     // using pwrite, as the Windows implementation of truncation will interact
      61             :     // poorly with pwrite.
      62             :     KeepExistingData,
      63             :   };
      64             : 
      65             :   /**
      66             :    * Open the file with Flag
      67             :    * The file will be closed when this object is destructed
      68             :    *
      69             :    * @return bool whether the open succeeded
      70             :    */
      71             :   virtual Api::IoCallBoolResult open(FlagSet flags) PURE;
      72             : 
      73             :   /**
      74             :    * Write the buffer to the file. The file must be explicitly opened before writing.
      75             :    *
      76             :    * @return ssize_t number of bytes written, or -1 for failure
      77             :    */
      78             :   virtual Api::IoCallSizeResult write(absl::string_view buffer) PURE;
      79             : 
      80             :   /**
      81             :    * Get additional details about the file. May or may not require a file system operation.
      82             :    *
      83             :    * @return FileInfo the file info.
      84             :    */
      85             :   virtual Api::IoCallResult<FileInfo> info() PURE;
      86             : 
      87             :   /**
      88             :    * Close the file.
      89             :    *
      90             :    * @return bool whether the close succeeded
      91             :    */
      92             :   virtual Api::IoCallBoolResult close() PURE;
      93             : 
      94             :   /**
      95             :    * Read a chunk of data from the file to a buffer. The file must be explicitly opened
      96             :    * before reading.
      97             :    * @param buf The buffer to copy the data into.
      98             :    * @param count The maximum number of bytes to read.
      99             :    * @param offset The offset in the file at which to start reading.
     100             :    * @return ssize_t number of bytes read, or -1 for failure.
     101             :    */
     102             :   virtual Api::IoCallSizeResult pread(void* buf, uint64_t count, uint64_t offset) PURE;
     103             : 
     104             :   /**
     105             :    * Write a chunk of data from a buffer to the file. The file must be explicitly opened
     106             :    * before writing.
     107             :    * @param buf The buffer to read the data from.
     108             :    * @param count The maximum number of bytes to write.
     109             :    * @param offset The offset in the file at which to start writing.
     110             :    * @return ssize_t number of bytes written, or -1 for failure.
     111             :    */
     112             :   virtual Api::IoCallSizeResult pwrite(const void* buf, uint64_t count, uint64_t offset) PURE;
     113             : 
     114             :   /**
     115             :    * @return bool is the file open
     116             :    */
     117             :   virtual bool isOpen() const PURE;
     118             : 
     119             :   /**
     120             :    * @return string the file path
     121             :    */
     122             :   virtual std::string path() const PURE;
     123             : 
     124             :   /**
     125             :    * @return the type of the destination
     126             :    */
     127             :   virtual DestinationType destinationType() const PURE;
     128             : };
     129             : 
     130             : using FilePtr = std::unique_ptr<File>;
     131             : 
     132             : /**
     133             :  * Contains the result of splitting the file name and its parent directory from
     134             :  * a given file path.
     135             :  */
     136             : struct PathSplitResult {
     137             :   absl::string_view directory_;
     138             :   absl::string_view file_;
     139             : };
     140             : 
     141             : /**
     142             :  * Contains the file type and the path.
     143             :  */
     144             : struct FilePathAndType {
     145           0 :   bool operator==(const FilePathAndType& rhs) const {
     146           0 :     return file_type_ == rhs.file_type_ && path_ == rhs.path_;
     147           0 :   }
     148             :   FilePathAndType() = default;
     149             :   FilePathAndType(DestinationType file_type, absl::string_view path)
     150         659 :       : file_type_(file_type), path_(path) {}
     151             :   DestinationType file_type_;
     152             :   std::string path_;
     153             : };
     154             : 
     155             : /**
     156             :  * Abstraction for some basic filesystem operations
     157             :  */
     158             : class Instance {
     159             : public:
     160         150 :   virtual ~Instance() = default;
     161             : 
     162             :   /**
     163             :    *  @param file_info The path and the type of the File
     164             :    *  @return a FilePtr. The file is not opened.
     165             :    */
     166             :   virtual FilePtr createFile(const FilePathAndType& file_info) PURE;
     167             : 
     168             :   /**
     169             :    * @return bool whether a file exists on disk and can be opened for read.
     170             :    */
     171             :   virtual bool fileExists(const std::string& path) PURE;
     172             : 
     173             :   /**
     174             :    * @return FileInfo containing information about the file, or an error status.
     175             :    */
     176             :   virtual Api::IoCallResult<FileInfo> stat(absl::string_view path) PURE;
     177             : 
     178             :   /**
     179             :    * Attempts to create the given path, recursively if necessary.
     180             :    * @return bool true if one or more directories was created and the path exists,
     181             :    *         false if the path already existed, an error status if the path does
     182             :    *         not exist after the call.
     183             :    */
     184             :   virtual Api::IoCallBoolResult createPath(absl::string_view path) PURE;
     185             : 
     186             :   /**
     187             :    * @return bool whether a directory exists on disk and can be opened for read.
     188             :    */
     189             :   virtual bool directoryExists(const std::string& path) PURE;
     190             : 
     191             :   /**
     192             :    * @return ssize_t the size in bytes of the specified file, or -1 if the file size
     193             :    *                 cannot be determined for any reason, including without limitation
     194             :    *                 the non-existence of the file.
     195             :    */
     196             :   virtual ssize_t fileSize(const std::string& path) PURE;
     197             : 
     198             :   /**
     199             :    * @return full file content as a string or an error if the file can not be read.
     200             :    * Be aware, this is not most highly performing file reading method.
     201             :    */
     202             :   virtual absl::StatusOr<std::string> fileReadToEnd(const std::string& path) PURE;
     203             : 
     204             :   /**
     205             :    * @path file path to split
     206             :    * @return PathSplitResult containing the parent directory of the input path and the file name or
     207             :    * an error status.
     208             :    */
     209             :   virtual absl::StatusOr<PathSplitResult> splitPathFromFilename(absl::string_view path) PURE;
     210             : 
     211             :   /**
     212             :    * Determine if the path is on a list of paths Envoy will refuse to access. This
     213             :    * is a basic sanity check for users, denying some clearly bad paths. Paths
     214             :    * may still be problematic (e.g. indirectly leading to /dev/mem) even if this
     215             :    * returns false, it is up to the user to validate that supplied paths are
     216             :    * valid.
     217             :    * @param path some filesystem path.
     218             :    * @return is the path on the deny list?
     219             :    */
     220             :   virtual bool illegalPath(const std::string& path) PURE;
     221             : };
     222             : 
     223             : using InstancePtr = std::unique_ptr<Instance>;
     224             : 
     225             : struct DirectoryEntry {
     226             :   // name_ is the name of the file in the directory, not including the directory path itself
     227             :   // For example, if we have directory a/b containing file c, name_ will be c
     228             :   std::string name_;
     229             : 
     230             :   // Note that if the file represented by name_ is a symlink, type_ will be the file type of the
     231             :   // target. For example, if name_ is a symlink to a directory, its file type will be Directory.
     232             :   FileType type_;
     233             : 
     234             :   // The file size in bytes for regular files. nullopt for FileType::Directory and FileType::Other,
     235             :   // and, on Windows, also nullopt for symlinks, and on Linux nullopt for broken symlinks.
     236             :   absl::optional<uint64_t> size_bytes_;
     237             : 
     238         148 :   bool operator==(const DirectoryEntry& rhs) const {
     239         148 :     return name_ == rhs.name_ && type_ == rhs.type_ && size_bytes_ == rhs.size_bytes_;
     240         148 :   }
     241             : };
     242             : 
     243             : class DirectoryIteratorImpl;
     244             : 
     245             : // Failures during this iteration will be silent; check status() after initialization
     246             : // and after each increment, if error-handling is desired.
     247             : class DirectoryIterator {
     248             : public:
     249          74 :   DirectoryIterator() : entry_({"", FileType::Other, absl::nullopt}) {}
     250          74 :   virtual ~DirectoryIterator() = default;
     251             : 
     252         259 :   const DirectoryEntry& operator*() const { return entry_; }
     253             : 
     254         148 :   bool operator!=(const DirectoryIterator& rhs) const { return !(entry_ == *rhs); }
     255             : 
     256             :   virtual DirectoryIteratorImpl& operator++() PURE;
     257             : 
     258           0 :   const absl::Status& status() const { return status_; }
     259             : 
     260             : protected:
     261             :   DirectoryEntry entry_;
     262             :   absl::Status status_;
     263             : };
     264             : 
     265             : } // namespace Filesystem
     266             : } // namespace Envoy

Generated by: LCOV version 1.15