1 /** 2 * @file posix.h 3 * 4 * @section LICENSE 5 * 6 * The MIT License 7 * 8 * @copyright Copyright (c) 2017-2021 TileDB, Inc. 9 * 10 * Permission is hereby granted, free of charge, to any person obtaining a copy 11 * of this software and associated documentation files (the "Software"), to deal 12 * in the Software without restriction, including without limitation the rights 13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 * copies of the Software, and to permit persons to whom the Software is 15 * furnished to do so, subject to the following conditions: 16 * 17 * The above copyright notice and this permission notice shall be included in 18 * all copies or substantial portions of the Software. 19 * 20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 * THE SOFTWARE. 27 * 28 * @section DESCRIPTION 29 * 30 * This file includes declarations of posix filesystem functions. 31 */ 32 33 #ifndef TILEDB_POSIX_FILESYSTEM_H 34 #define TILEDB_POSIX_FILESYSTEM_H 35 36 #ifndef _WIN32 37 38 #include <ftw.h> 39 #include <sys/types.h> 40 41 #include <functional> 42 #include <string> 43 #include <vector> 44 45 #include "tiledb/common/status.h" 46 #include "tiledb/common/thread_pool.h" 47 #include "tiledb/sm/config/config.h" 48 #include "tiledb/sm/filesystem/filelock.h" 49 50 using namespace tiledb::common; 51 52 namespace tiledb { 53 namespace sm { 54 55 /** 56 * This class implements the POSIX filesystem functions. 57 */ 58 class Posix { 59 public: 60 /** Constructor. */ 61 Posix(); 62 63 /** Destructor. */ 64 ~Posix() = default; 65 66 /** 67 * Returns the absolute posix (string) path of the input in the 68 * form "file://<absolute path>" 69 */ 70 static std::string abs_path(const std::string& path); 71 72 /** 73 * Creates a new directory. 74 * 75 * @param dir The name of the directory to be created. 76 * @return Status 77 */ 78 Status create_dir(const std::string& path) const; 79 80 /** 81 * Creates an empty file. 82 * 83 * @param filename The name of the file to be created. 84 * @return Status 85 */ 86 Status touch(const std::string& filename) const; 87 88 /** 89 * Returns the directory where the program is executed. 90 * 91 * @return The directory path where the program is executed. If the program 92 * cannot retrieve the current working directory, the empty string is 93 * returned. 94 */ 95 static std::string current_dir(); 96 97 /** 98 * Removes a given directory recursively. 99 * 100 * @param path The path of the directory to be deleted. 101 * @return Status 102 */ 103 Status remove_dir(const std::string& path) const; 104 105 /** Deletes the file in the input path. */ 106 107 /** 108 * Removes a given path. 109 * 110 * @param path The path of the file / empty directory to be deleted. 111 * @return Status 112 */ 113 Status remove_file(const std::string& path) const; 114 115 /** 116 * Returns the size of the input file. 117 * 118 * @param path The name of the file whose size is to be retrieved. 119 * @param nbytes Pointer to a value 120 * @return Status 121 */ 122 Status file_size(const std::string& path, uint64_t* size) const; 123 124 /** 125 * Lock a given filename and retrieve an open file descriptor handle. 126 * 127 * @param filename The filelock to lock 128 * @param fd A pointer to a file descriptor 129 * @param shared *True* if this is a shared lock, *false* if it is an 130 * exclusive lock. 131 * @return Status 132 */ 133 Status filelock_lock( 134 const std::string& filename, filelock_t* fd, bool shared) const; 135 136 /** 137 * Unlock an opened file descriptor 138 * 139 * @param fd the open file descriptor to unlock 140 * @return Status 141 */ 142 Status filelock_unlock(int fd) const; 143 144 /** 145 * Initialize this instance with the given config. 146 * 147 * @param config Config parameters. 148 * @param vfs_thread_pool ThreadPool from the parent VFS instance. 149 * @return Status 150 */ 151 Status init(const Config& config, ThreadPool* vfs_thread_pool); 152 153 /** 154 * Checks if the input is an existing directory. 155 * 156 * @param dir The directory to be checked. 157 * @return *True* if *dir* is an existing directory, and *False* otherwise. 158 */ 159 bool is_dir(const std::string& path) const; 160 161 /** 162 * Checks if the input is an existing file. 163 * 164 * @param file The file to be checked. 165 * @return *True* if *file* is an existing file, and *false* otherwise. 166 */ 167 bool is_file(const std::string& path) const; 168 169 /** 170 * 171 * Lists files one level deep under a given path. 172 * 173 * @param path The parent path to list sub-paths. 174 * @param paths Pointer to a vector of strings to store the retrieved paths. 175 * @return Status 176 */ 177 Status ls(const std::string& path, std::vector<std::string>* paths) const; 178 179 /** 180 * Move a given filesystem path. 181 * 182 * @param old_path The old path. 183 * @param new_path The new path. 184 * @return Status 185 */ 186 Status move_path(const std::string& old_path, const std::string& new_path); 187 188 /** 189 * Copy a given filesystem file. 190 * 191 * @param old_path The old path. 192 * @param new_path The new path. 193 * @return Status 194 */ 195 Status copy_file(const std::string& old_path, const std::string& new_path); 196 197 /** 198 * Copy a given filesystem directory. 199 * 200 * @param old_path The old path. 201 * @param new_path The new path. 202 * @return Status 203 */ 204 Status copy_dir(const std::string& old_path, const std::string& new_path); 205 206 /** 207 * Reads data from a file into a buffer. 208 * 209 * @param path The name of the file. 210 * @param offset The offset in the file from which the read will start. 211 * @param buffer The buffer into which the data will be written. 212 * @param nbytes The size of the data to be read from the file. 213 * @return Status. 214 */ 215 Status read( 216 const std::string& path, 217 uint64_t offset, 218 void* buffer, 219 uint64_t nbytes) const; 220 221 /** 222 * Syncs a file or directory. 223 * 224 * @param path The name of the file. 225 * @return Status 226 */ 227 Status sync(const std::string& path); 228 229 /** 230 * Writes the input buffer to a file. 231 * 232 * If the file exists than it is created. 233 * If the file does not exist than it is appended to. 234 * 235 * @param path The name of the file. 236 * @param buffer The input buffer. 237 * @param buffer_size The size of the input buffer. 238 * @return Status 239 */ 240 Status write( 241 const std::string& path, const void* buffer, uint64_t buffer_size); 242 243 private: 244 /** Config parameters inherited from parent VFS. */ 245 std::reference_wrapper<const Config> config_; 246 247 /** Default config. */ 248 Config default_config_; 249 250 /** Thread pool from parent VFS instance. */ 251 ThreadPool* vfs_thread_pool_; 252 253 static void adjacent_slashes_dedup(std::string* path); 254 255 static bool both_slashes(char a, char b); 256 257 // Internal logic for 'abs_path()'. 258 static std::string abs_path_internal(const std::string& path); 259 260 /** 261 * It takes as input an **absolute** path, and returns it in its canonicalized 262 * form, after appropriately replacing "./" and "../" in the path. 263 * 264 * @param path The input path passed by reference, which will be modified 265 * by the function to hold the canonicalized absolute path. Note that the 266 * path must be absolute, otherwise the function fails. In case of error 267 * (e.g., if "../" are not properly used in *path*, or if *path* is not 268 * absolute), the function sets the empty string (i.e., "") to *path*. 269 * @return void 270 */ 271 static void purge_dots_from_path(std::string* path); 272 273 /** 274 * Reads all nbytes from the given file descriptor, retrying as necessary. 275 * 276 * @param fd Open file descriptor to read from 277 * @param buffer Buffer to hold read data 278 * @param nbytes Number of bytes to read 279 * @param offset Offset in file to start reading from. 280 * @return Number of bytes actually read (< nbytes on error). 281 */ 282 static uint64_t read_all( 283 int fd, void* buffer, uint64_t nbytes, uint64_t offset); 284 285 static int unlink_cb( 286 const char* fpath, 287 const struct stat* sb, 288 int typeflag, 289 struct FTW* ftwbuf); 290 291 /** 292 * Writes all nbytes to the given file descriptor, retrying as necessary. 293 * 294 * @param fd Open file descriptor to write to 295 * @param file_offset File offset at which to write. 296 * @param buffer Buffer with data to write 297 * @param nbytes Number of bytes to write 298 * @return Number of bytes actually written (< nbytes on error). 299 */ 300 static uint64_t pwrite_all( 301 int fd, uint64_t file_offset, const void* buffer, uint64_t nbytes); 302 303 /** 304 * Write data from the given buffer to the file descriptor, beginning at the 305 * given offset. Multiple threads can safely write to the same open file 306 * descriptor. 307 * 308 * @param fd Open file descriptor to write to 309 * @param file_offset Offset in the file at which to start writing 310 * @param buffer Buffer of data to write 311 * @param buffer_size Number of bytes to write 312 * @return Status 313 */ 314 static Status write_at( 315 int fd, uint64_t file_offset, const void* buffer, uint64_t buffer_size); 316 317 /** 318 * Parse config to get posix permissions for creating new files 319 * @param permissions parsed permissions are set to this parameter 320 * @return Status 321 */ 322 Status get_posix_file_permissions(uint32_t* permissions) const; 323 324 /** 325 * Parse config to get posix permissions for creating new directories 326 * @param permissions parsed permissions are set to this parameter 327 * @return Status 328 */ 329 Status get_posix_directory_permissions(uint32_t* permissions) const; 330 }; 331 332 } // namespace sm 333 } // namespace tiledb 334 335 #endif // !_WIN32 336 337 #endif // TILEDB_POSIX_FILESYSTEM_H 338