#pragma region CPL License /* Nuclex Native Framework Copyright (C) 2002-2021 Nuclex Development Labs This library is free software; you can redistribute it and/or modify it under the terms of the IBM Common Public License as published by the IBM Corporation; either version 1.0 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the IBM Common Public License for more details. You should have received a copy of the IBM Common Public License along with this library */ #pragma endregion // CPL License #ifndef NUCLEX_STORAGE_FILESYSTEM_LINUX_LINUXFILEAPI_H #define NUCLEX_STORAGE_FILESYSTEM_LINUX_LINUXFILEAPI_H #include "Nuclex/Storage/Config.h" #if defined(NUCLEX_STORAGE_LINUX) #include // std::string #include // std::uint8_t and std::size_t #include // ::fstat() and permission flags #include // struct ::dirent namespace Nuclex { namespace Storage { namespace FileSystem { namespace Linux { // ------------------------------------------------------------------------------------------- // /// Wraps the Linux file system API /// /// /// This is just a small helper class that reduces the amount of boilerplate code /// required when calling the file system API functions, such as checking /// result codes over and over again. /// /// /// It is not intended to hide operating system details or make this API platform /// neutral (the File and Container classes do that), so depending on the amount /// of noise required by the file system APIs, only some methods will be wrapped here. /// /// class LinuxFileApi { /// Creates the specified directory /// Path to the directory that will be created public: static void MakeDirectory(const std::string &path); /// Creates all directories down to the specified path /// Directory that will be created recursively public: static void MakeDirectoryRecursively(const std::string &directory); /// Deletes a directory and everything in it /// Path of the directory that will be deleted public: static void RemoveDirectory(const std::string &path); /// Deletes a file /// Path of the file that will be deleted public: static void RemoveFile(const std::string &path); /// Returns the current working directory of the process /// The process' current working directory public: static std::string GetCurrentWorkingDirectory(); /// Retrieves the protection mode of the file in the specified path /// Path of the file whose protection mode will be retrieved /// The protection mode of the specified file public: static ::mode_t StatMode(const std::string &path); /// Retrieves the status of the file in the specified path /// Path of the file whose status will be retrieved /// Receives the file status on successfull execution /// True if the file exists and was queried, false if it doesn't exsit /// /// If any error other than the file not existing occurs, an exception is thrown. /// public: static bool Stat(const std::string &path, struct ::stat &fileStatus); /// Attempts to opens the specified file for shared reading /// Path of the file that will be opened /// /// Receives the file descriptor (numeric handle) of the opened file on success /// /// /// True if the file was opened, false if any error occurred and the contents /// of the parameter should not be used. /// /// /// Use this if you need to read files that may be missing or that you may not be /// permitted to read and where you wish to fall back to something else in that case. /// public: static bool TryOpenFileForReading(const std::string &path, int &fileDescriptor); /// Opens the specified file for shared reading /// Path of the file that will be opened /// The descriptor (numeric handle) of the opened file public: static int OpenFileForReading(const std::string &path); /// Creates or opens the specified file for exclusive writing /// Path of the file that will be opened /// The descriptor (numeric handle) of the opened file public: static int OpenFileForWriting(const std::string &path); /// Moves the file cursor for the specified file /// File whose file cursor will be moved /// Location the file cursor will be moved to /// The actual location the file cursor public: static std::uint64_t Seek(int fileDescriptor, std::uint64_t location); /// Determines the file status of a file by its handle /// Handle of the file whose status will be determined /// Receives the file status public: static void Stat(int fileDescriptor, struct ::stat &fileStatus); /// Reads data from the specified file /// Handle of the file from which data will be read /// Buffer into which the data will be put /// Number of bytes that will be read from the file /// The number of bytes that were actually read public: static std::size_t Read( int fileDescriptor, std::uint8_t *buffer, std::size_t count ); /// Reads data from the specified file /// Handle of the file from which data will be read /// Offset in the file from which data is read /// Buffer into which the data will be put /// Number of bytes that will be read from the file /// The number of bytes that were actually read public: static std::size_t PositionalRead( int fileDescriptor, std::uint64_t offset, std::uint8_t *buffer, std::size_t count ); /// Writes data into the specified file /// Handle of the file into which data will be written /// Buffer containing the data that will be written /// Number of bytes that will be written into the file /// The number of bytes that were actually written public: static std::size_t Write( int fileDescriptor, const std::uint8_t *buffer, std::size_t count ); /// Writes data into the specified file /// Handle of the file into which data will be written /// Offset in the file at which data is written /// Buffer containing the data that will be written /// Number of bytes that will be written into the file /// The number of bytes that were actually written public: static std::size_t PositionalWrite( int fileDescriptor, std::uint64_t offset, const std::uint8_t *buffer, std::size_t count ); /// Closes the specified file /// Handle of the file that will be closed /// /// Whether to throw an exception if the file cannot be closed /// public: static void Close(int fileDescriptor, bool throwOnError = true); /// Opens a directory for enumeration /// Path of the directory that will be opened /// The opened directory public: static DIR *OpenDirectory(const std::string &path); /// Reads the next directory entry from a directory /// Directory from which the next entry will be read /// /// The next directory entry or NULL if the last directory entry has been reached /// public: static struct ::dirent *ReadDirectory(::DIR *directory); /// Closes a directory that was opened for enumeration /// Directory that will be closed /// /// Whether to throw an exception if the directory cannot be closed /// public: static void CloseDirectory(::DIR *directory, bool throwOnError = true); /// Reads the target file or directory pointed to by a symlink /// Path to the symlink whose target will be read /// The path to which the symlink is pointing public: static std::string ReadLink(const std::string &path); /// Resolves a path, following symlinks, to its ultimate target /// Path that will be resolved to its ultimate target /// The ultimate target of the specified path public: static std::string RealPath(const std::string &path); }; // ------------------------------------------------------------------------------------------- // /// Closes a directory handle upon destruction class DirectoryScope { /// Initializes the directory handle closer /// Directory handle that will be closed public: DirectoryScope(::DIR *directoryHandle) : directoryHandle(directoryHandle) {} /// Closes the directory handle public: ~DirectoryScope() { const bool throwOnError = false; LinuxFileApi::CloseDirectory(this->directoryHandle, throwOnError); } /// Directory handle that will be closed upon destruction private: ::DIR *directoryHandle; }; // ------------------------------------------------------------------------------------------- // /// Closes a file upon destruction class FileScope { /// Initializes the file closer /// File that will be closed public: FileScope(int fileDescriptor) : fileDescriptor(fileDescriptor) {} /// Closes the file public: ~FileScope() { const bool throwOnError = false; LinuxFileApi::Close(this->fileDescriptor, throwOnError); } /// File that will be closed upon destruction private: int fileDescriptor; }; // ------------------------------------------------------------------------------------------- // }}}} // namespace Nuclex::Storage::FileSystem::Linux #endif // defined(NUCLEX_STORAGE_LINUX) #endif // NUCLEX_STORAGE_FILESYSTEM_LINUX_LINUXFILEAPI_H