diff --git a/CHANGELOG.md b/CHANGELOG.md index 72c1f03b728dacf579db90ae1066915c19a0e169..6b5b9e743704b5095c3b50401a2e325a56ed862e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,8 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - Tests to cover proxy and (malleability) ([!222](https://storage.bsc.es/gitlab/hpc/gekkofs/-/merge_requests/222)) - New fd generation method ([!225](https://storage.bsc.es/gitlab/hpc/gekkofs/-/merge_requests/202)) - Use LIBGKFS_PROTECT_FD=1 to enable the original method of assignation and protection. + - Lock system (server level) ([!233](https://storage.bsc.es/gitlab/hpc/gekkofs/-/merge_requests/233)) + - Use PROTECT_FILES_GENERATOR=1 and PROTECT_FILES_CONSUMER=1 to enable. Generator, creates transparent .lockgekko files that blocks the open (for some seconds) of any consumer. Multiple opens / closes for generator are managed. ### Changed - Tests check ret for -1 instead of 10000 fd ([!320](https://storage.bsc.es/gitlab/hpc/gekkofs/-/merge_requests/320)) diff --git a/README.md b/README.md index 03d89091e93a4bf11404a8396edcc15a5be65c44..ee5eab21c44fdaa787b4ad601be96bc70c60419b 100644 --- a/README.md +++ b/README.md @@ -589,6 +589,11 @@ until the file is closed. The cache does not impact the consistency of the file When the user creates a fd, this is protected from normal fds with a recolocation. This theoretically protects the fd from being closed from outside. However a new fd assignation system has been developed and is activated by default. - `LIBGKFS_PROTECT_FD=1` - Enable the original method of assignation and protection. +##### Lightweight File-Locking (server side) +Using two environment variables +- `LIBGKFS_PROTECT_FILES_GENERATOR=1` enables the application as generator, so a open will create (and increase) a file .lockgekko and close will remove it (or decrease its value). The behaviour only uses metadata at server side. +- `LIBGKFS_PROTECT_FILES_CONSUMER=1` enables the application as consumer, so a open will wait until the .lockgekko dissapears. The wait is limited to ~40 seconds. + ### Daemon #### Logging - `GKFS_DAEMON_LOG_PATH` - Path to the log file of the daemon. diff --git a/include/client/env.hpp b/include/client/env.hpp index ec400aba492e8eb4b1e6e32bb35a6be8fe570cd5..5140d8f1110ab8a82288415f059c47b34c7f2cc7 100644 --- a/include/client/env.hpp +++ b/include/client/env.hpp @@ -69,6 +69,10 @@ static constexpr auto METRICS_IP_PORT = ADD_PREFIX("METRICS_IP_PORT"); #endif static constexpr auto PROTECT_FD = ADD_PREFIX("PROTECT_FD"); +static constexpr auto PROTECT_FILES_GENERATOR = + ADD_PREFIX("PROTECT_FILES_GENERATOR"); +static constexpr auto PROTECT_FILES_CONSUMER = + ADD_PREFIX("PROTECT_FILES_CONSUMER"); static constexpr auto NUM_REPL = ADD_PREFIX("NUM_REPL"); static constexpr auto PROXY_PID_FILE = ADD_PREFIX("PROXY_PID_FILE"); namespace cache { diff --git a/include/client/preload_context.hpp b/include/client/preload_context.hpp index 9f4b388758e0b26ab46abd7a05e2a36e9ba4a435..6d4877184e76d4ca5a08775524787e91f8f92133 100644 --- a/include/client/preload_context.hpp +++ b/include/client/preload_context.hpp @@ -140,6 +140,9 @@ private: int replicas_; bool protect_fds_{false}; + bool protect_files_generator_{false}; + bool protect_files_consumer_{false}; + std::shared_ptr write_metrics_; std::shared_ptr read_metrics_; @@ -322,6 +325,19 @@ public: void protect_fds(bool protect); + bool + protect_files_generator() const; + + void + protect_files_generator(bool protect); + + bool + protect_files_consumer() const; + + void + protect_files_consumer(bool protect); + + const std::shared_ptr write_metrics(); diff --git a/src/client/gkfs_functions.cpp b/src/client/gkfs_functions.cpp index 293e20c7f49ebb686166334aafa87aaecb6858bd..414d5d8f803a89b3691c27d7315cd640d23b7bc9 100644 --- a/src/client/gkfs_functions.cpp +++ b/src/client/gkfs_functions.cpp @@ -48,6 +48,8 @@ #include #include #include +#include +#include #include #ifdef GKFS_ENABLE_CLIENT_METRICS @@ -116,6 +118,65 @@ check_parent_dir(const std::string& path) { namespace gkfs::syscall { +/** + * @brief generate_lock_file + * @param path + * @param increase + * + * Creates, if it does not exist, a lock file, path+".lockgekko", empty + * If increase is true, increase the size of the file +1 + * if increase is false, decrease the size of the file -1 + * If size == 0, delete the file + * Using calls : forward_create, forward_stat, forward_remove, forward_decr_size + * and forward_update_metadentry_size Proxy not supported + */ +void +generate_lock_file(const std::string& path, bool increase) { + auto lock_path = path + ".lockgekko"; + if(increase) { + auto md = gkfs::utils::get_metadata(lock_path); + if(!md) { + gkfs::rpc::forward_create(lock_path, 0777 | S_IFREG, 0); + } + gkfs::rpc::forward_update_metadentry_size(lock_path, 1, 0, false, 0); + } else { + auto md = gkfs::utils::get_metadata(lock_path); + if(md) { + if(md.value().size() == 1) { + LOG(DEBUG, "Deleting Lock file {}", lock_path); + gkfs::rpc::forward_remove(lock_path, false, 0); + } else { + gkfs::rpc::forward_decr_size(lock_path, md.value().size() - 1, + 0); + } + } + } +} + +/** + * @brief generate_lock_file + * @param path + * + * Test if the lock file exists, if it exists, wait 0.5 second and check again + * (max 80 times) Using calls : forward_stat + */ +void +test_lock_file(const std::string& path) { + auto lock_path = path + ".lockgekko"; + auto md = gkfs::utils::get_metadata(lock_path); + if(md) { + LOG(DEBUG, "Lock file exists {} --> {}", lock_path, md->size()); + for(int i = 0; i < 80; i++) { + if(!md) { + break; + } + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + md = gkfs::utils::get_metadata(lock_path); + } + } +} + + /** * gkfs wrapper for open() system calls * errno may be set @@ -168,9 +229,14 @@ gkfs_open(const std::string& path, mode_t mode, int flags) { return -1; } } else { - // file was successfully created. Add to filemap - return CTX->file_map()->add( + auto fd = CTX->file_map()->add( std::make_shared(path, flags)); + // CREATE_MODE + if(CTX->protect_files_generator()) { + generate_lock_file(path, true); + } + // file was successfully created. Add to filemap + return fd; } } else { auto md_ = gkfs::utils::get_metadata(path); @@ -228,7 +294,7 @@ gkfs_open(const std::string& path, mode_t mode, int flags) { return -1; } } - + // RENAMED OR SYMLINK NOT PROTECTED return CTX->file_map()->add( std::make_shared(new_path, flags)); } @@ -248,9 +314,19 @@ gkfs_open(const std::string& path, mode_t mode, int flags) { return -1; } } - - return CTX->file_map()->add( + // NORMAL OPEN + auto fd = CTX->file_map()->add( std::make_shared(path, flags)); + + + if(CTX->protect_files_consumer()) { + test_lock_file(path); + } + + if(CTX->protect_files_generator()) { + generate_lock_file(path, true); + } + return fd; } /** @@ -1498,6 +1574,14 @@ gkfs_getdents(unsigned int fd, struct linux_dirent* dirp, unsigned int count) { while(pos < open_dir->size()) { // get dentry fir current position auto de = open_dir->getdent(pos); + if(CTX->protect_files_consumer() or CTX->protect_files_generator()) { + // if de.name ends with lockgekko jump to the next file + if(de.name().size() >= 10 && + de.name().substr(de.name().size() - 10) == ".lockgekko") { + pos++; + continue; + } + } /* * Calculate the total dentry size within the kernel struct * `linux_dirent` depending on the file name size. The size is then @@ -1567,6 +1651,14 @@ gkfs_getdents64(unsigned int fd, struct linux_dirent64* dirp, struct linux_dirent64* current_dirp = nullptr; while(pos < open_dir->size()) { auto de = open_dir->getdent(pos); + if(CTX->protect_files_consumer() or CTX->protect_files_generator()) { + // if de.name ends with lockgekko jump to the next file + if(de.name().size() >= 10 && + de.name().substr(de.name().size() - 10) == ".lockgekko") { + pos++; + continue; + } + } /* * Calculate the total dentry size within the kernel struct * `linux_dirent` depending on the file name size. The size is then @@ -1662,6 +1754,11 @@ gkfs_close(unsigned int fd) { CTX->file_map()->get(fd)->path()); } } + + if(CTX->protect_files_generator()) { + auto path = CTX->file_map()->get(fd)->path(); + generate_lock_file(path, false); + } // No call to the daemon is required CTX->file_map()->remove(fd); return 0; @@ -1791,6 +1888,13 @@ gkfs_get_file_list(const std::string& path) { while(pos < open_dir->size()) { auto de = open_dir->getdent(pos++); + if(CTX->protect_files_consumer() or CTX->protect_files_generator()) { + // if de.name ends with lockgekko jump to the next file + if(de.name().size() >= 10 && + de.name().substr(de.name().size() - 10) == ".lockgekko") { + continue; + } + } file_list.push_back(de.name()); } return file_list; diff --git a/src/client/gkfs_libc.cpp b/src/client/gkfs_libc.cpp index 0edc0e7a47209807a46b1a66d761b1bfe4a4275e..68862c9d2d8b51a18f73ad778749cdf9fda5b1f9 100644 --- a/src/client/gkfs_libc.cpp +++ b/src/client/gkfs_libc.cpp @@ -68,7 +68,6 @@ std::atomic initializing{false}; // Define a debug macro, can be easily disabled #define GKFS_TRACE -// #define PATH_SHORTCUT #ifdef GKFS_DEBUG_BUILD #ifdef GKFS_TRACE @@ -106,7 +105,6 @@ initializeGekko() { void log_arguments(const char* symbol) { DEBUG_INFO("[BYPASS] {}", symbol); - // printf("[BYPASS] %s\n",symbol); } // Variadic case: 1+ arguments @@ -117,7 +115,6 @@ log_arguments(const char* symbol, Args&&... args) { ss << "[BYPASS] Calling " << symbol << " with arguments: "; ((ss << "[" << typeid(Args).name() << "] " << args << " "), ...); DEBUG_INFO("{}", ss.str()); - // printf("%s\n",ss.str().c_str()); } // Variadic case: 1+ arguments @@ -128,7 +125,6 @@ log_argumentsx(const char* symbol, Args&&... args) { ss << "[BYPASS-ERROR] Calling " << symbol << " with arguments: "; ((ss << "[" << typeid(Args).name() << "] " << args << " "), ...); DEBUG_INFO("{}", ss.str()); - // printf("%s\n",ss.str().c_str()); } /** @@ -219,8 +215,6 @@ DLSYM_WRAPPER(int, openat, (int fd, const char* path, int flags, mode_t mode), (fd, path, flags, mode), "openat") DLSYM_WRAPPER(int, open64, (const char* path, int flags, mode_t mode), (path, flags, mode), "open64") -// DLSYM_WRAPPER(int, __open_2, (char* path, int flags), (path, flags), -// "__open") DLSYM_WRAPPER(int, close, (int fd), (fd), "close") DLSYM_WRAPPER(int, close_range, (unsigned int low, unsigned int high, int flags), @@ -383,7 +377,7 @@ DLSYM_WRAPPER(int, chmod, (char* path, mode_t mode), (path, mode), "chmod") DLSYM_WRAPPER(int, fchmod, (int fd, mode_t mode), (fd, mode), "fchmod") DLSYM_WRAPPER(int, chown, (char* path, uid_t owner, gid_t group), (path, owner, group), "chown") -// DLSYM_WRAPPER(int, fcntl, (int fd, int cmd, ...), (fd, cmd, ...), "fcntl") + static int (*real_fcntl)(int fd, int cmd, ...) = nullptr; DLSYM_WRAPPER(int, access, (const char* path, int mode), (path, mode), "access") @@ -559,16 +553,7 @@ enum class PathStatus { External, Internal, Error }; PathStatus resolve_gkfs_path(int dirfd, const char* path, std::string& resolved, int flags = 0, bool resolve_last_link = true) { -// if path does not start with CTX->mountdir() just return external -#ifdef PATH_SHORTCUT - auto res = std::mismatch(CTX->mountdir().begin(), CTX->mountdir().end(), - std::string(path).begin()); - - if(res.first != CTX->mountdir().end() and dirfd == AT_FDCWD) { - return PathStatus::External; - } -#endif const auto status = CTX->relativize_fd_path(dirfd, path, resolved, flags, resolve_last_link); @@ -814,7 +799,7 @@ creat(const char* path, mode_t mode) { int ftruncate(int fd, off_t length) { initializeGekko(); - if(is_gkfs_fd(fd)) { + if(CTX->interception_enabled() && is_gkfs_fd(fd)) { std::string path_str = CTX->file_map()->get(fd)->path(); DEBUG_INFO("[GKFS] {}", path_str); return gkfs::syscall::gkfs_truncate(path_str, length); @@ -1027,7 +1012,7 @@ __lxstat64(int ver, const char* path, struct stat64* buf) { int __fxstat(int ver, int fd, struct stat* buf) { initializeGekko(); - if(is_gkfs_fd(fd)) { + if(CTX->interception_enabled() && is_gkfs_fd(fd)) { DEBUG_INFO("[GKFS] {}", CTX->file_map()->get(fd)->path()); return gkfs::syscall::gkfs_stat(CTX->file_map()->get(fd)->path(), buf, true, true); @@ -1046,7 +1031,7 @@ __fxstatat(int ver, int dfd, const char* path, struct stat* buf, int flags) { int __fxstat64(int ver, int fd, struct stat64* buf) { initializeGekko(); - if(is_gkfs_fd(fd)) { + if(CTX->interception_enabled() && is_gkfs_fd(fd)) { struct stat st; DEBUG_INFO("[GKFS] {}", CTX->file_map()->get(fd)->path()); int res = gkfs::syscall::gkfs_stat(CTX->file_map()->get(fd)->path(), @@ -1061,7 +1046,7 @@ __fxstat64(int ver, int fd, struct stat64* buf) { int fstat64(int fd, struct stat64* buf) { initializeGekko(); - if(is_gkfs_fd(fd)) { + if(CTX->interception_enabled() && is_gkfs_fd(fd)) { struct stat st; DEBUG_INFO("[GKFS] {}", CTX->file_map()->get(fd)->path()); int res = gkfs::syscall::gkfs_stat(CTX->file_map()->get(fd)->path(), @@ -1076,7 +1061,7 @@ fstat64(int fd, struct stat64* buf) { int fstat(int fd, struct stat* buf) { initializeGekko(); - if(is_gkfs_fd(fd)) { + if(CTX->interception_enabled() && is_gkfs_fd(fd)) { DEBUG_INFO("[GKFS] {}", CTX->file_map()->get(fd)->path()); // The fd could be a renamed file, thus when doing gkfs_stat we will get @@ -1280,17 +1265,18 @@ dup(int fd) { int dup2(int fd, int fd2) { initializeGekko(); - if(is_gkfs_fd(fd) && is_gkfs_fd(fd2)) { - DEBUG_INFO("[GKFS] DUP2 G{} --> G{}", fd, fd2); - return gkfs::syscall::gkfs_dup2(fd, fd2); - } else if(is_gkfs_fd(fd2)) { - DEBUG_INFO("[GKFS-NON] DUP2 {} --> G{}", fd, fd2); - return gkfs::syscall::gkfs_dup(fd); - } else if(is_gkfs_fd(fd)) { - DEBUG_INFO("[GKFS-NON] DUP2 G{} --> {}", fd, fd2); - return gkfs::syscall::gkfs_dup2(fd, fd2); + if(CTX->interception_enabled()) { + if(is_gkfs_fd(fd) && is_gkfs_fd(fd2)) { + DEBUG_INFO("[GKFS] DUP2 G{} --> G{}", fd, fd2); + return gkfs::syscall::gkfs_dup2(fd, fd2); + } else if(is_gkfs_fd(fd2)) { + DEBUG_INFO("[GKFS-NON] DUP2 {} --> G{}", fd, fd2); + return gkfs::syscall::gkfs_dup(fd); + } else if(is_gkfs_fd(fd)) { + DEBUG_INFO("[GKFS-NON] DUP2 G{} --> {}", fd, fd2); + return gkfs::syscall::gkfs_dup2(fd, fd2); + } } - // GKFS_OPERATION(dup2, fd, fd2); GKFS_FALLBACK(dup2, fd, fd2); } @@ -1380,7 +1366,7 @@ fcntl(int fd, int cmd, ...) // TODO va_end(myargs); // is from gekkofs? - if(is_gkfs_fd(fd)) { + if(CTX->interception_enabled() && is_gkfs_fd(fd)) { int ret = -1; switch(cmd) { @@ -2011,7 +1997,7 @@ fflush(FILE* stream) { void* mmap(void* addr, size_t length, int prot, int flags, int fd, off_t offset) { initializeGekko(); - if(is_gkfs_fd(fd)) { + if(CTX->interception_enabled() && is_gkfs_fd(fd)) { DEBUG_INFO("[GKFS] {}", CTX->file_map()->get(fd)->path()); // create a malloc of length void* ptr = malloc(length); @@ -2078,7 +2064,7 @@ munmap(void* addr, size_t length) { int fchown(int fd, uid_t owner, gid_t group) { initializeGekko(); - if(is_gkfs_fd(fd)) { + if(CTX->interception_enabled() && is_gkfs_fd(fd)) { DEBUG_INFO("[GKFS] {}", CTX->file_map()->get(fd)->path()); return 0; } @@ -2089,7 +2075,7 @@ fchown(int fd, uid_t owner, gid_t group) { int fchmod(int fd, mode_t mode) { initializeGekko(); - if(is_gkfs_fd(fd)) { + if(CTX->interception_enabled() && is_gkfs_fd(fd)) { DEBUG_INFO("[GKFS] {}", CTX->file_map()->get(fd)->path()); return 0; } @@ -2100,7 +2086,7 @@ fchmod(int fd, mode_t mode) { int futimes(int fd, const struct timeval tv[2]) { initializeGekko(); - if(is_gkfs_fd(fd)) { + if(CTX->interception_enabled() && is_gkfs_fd(fd)) { DEBUG_INFO("[GKFS] {}", CTX->file_map()->get(fd)->path()); return 0; } @@ -2139,7 +2125,7 @@ listxattr(const char* path, char* list, size_t size) { ssize_t flistxattr(int fd, char* list, size_t size) { initializeGekko(); - if(is_gkfs_fd(fd)) { + if(CTX->interception_enabled() && is_gkfs_fd(fd)) { DEBUG_INFO("[GKFS] {}", CTX->file_map()->get(fd)->path()); return 0; } diff --git a/src/client/hooks.cpp b/src/client/hooks.cpp index cc539532de2b7428909b7d6d486711ded69d991c..be909276191faed882f6adb925fac679eccfbbbe 100644 --- a/src/client/hooks.cpp +++ b/src/client/hooks.cpp @@ -722,7 +722,8 @@ hook_chdir(const char* path) { // path falls in our namespace auto md = gkfs::utils::get_metadata(rel_path); if(!md) { - LOG(ERROR, "{}() path {} / {} errno {}", __func__, path, rel_path, errno); + LOG(ERROR, "{}() path {} / {} errno {}", __func__, path, rel_path, + errno); return -errno; } @@ -929,7 +930,6 @@ hook_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg) { return gsl::narrow_cast( syscall_no_intercept_wrapper(SYS_fcntl, fd, cmd, arg)); - case F_SETLK: LOG(ERROR, "{}() F_SETLK on fd (on underlying fd) {}", __func__, fd); diff --git a/src/client/preload.cpp b/src/client/preload.cpp index b46f252c62c870062aeb6c8053ffc997e7761ffb..98589c8c0de2876d611756221b16040556b31f46 100644 --- a/src/client/preload.cpp +++ b/src/client/preload.cpp @@ -239,6 +239,16 @@ init_environment() { "Failed to connect to hosts: "s + e.what()); } + LOG(INFO, "Lock-Files : Generator = {} / Consumer = {}", + (bool) gkfs::env::get_var(gkfs::env::PROTECT_FILES_GENERATOR, 0), + (bool) gkfs::env::get_var(gkfs::env::PROTECT_FILES_CONSUMER, 0)); + + CTX->protect_files_generator( + gkfs::env::get_var(gkfs::env::PROTECT_FILES_GENERATOR, 0)); + + CTX->protect_files_consumer( + gkfs::env::get_var(gkfs::env::PROTECT_FILES_CONSUMER, 0)); + /* Setup distributor */ auto forwarding_map_file = gkfs::env::get_var( gkfs::env::FORWARDING_MAP_FILE, gkfs::config::forwarding_file_path); diff --git a/src/client/preload_context.cpp b/src/client/preload_context.cpp index 51bfbc4c505dfbeb269500bd08c7015e5bf9bdb7..fe98304c32544bb065a4636c9345d6e8b9a50077 100644 --- a/src/client/preload_context.cpp +++ b/src/client/preload_context.cpp @@ -660,6 +660,28 @@ PreloadContext::get_replicas() { return replicas_; } + +bool +PreloadContext::protect_files_generator() const { + return protect_files_generator_; +} + +void +PreloadContext::protect_files_generator(bool protect) { + protect_files_generator_ = protect; +} + +bool +PreloadContext::protect_files_consumer() const { + return protect_files_consumer_; +} + +void +PreloadContext::protect_files_consumer(bool protect) { + protect_files_consumer_ = protect; +} + + const std::shared_ptr PreloadContext::write_metrics() { return write_metrics_; diff --git a/src/common/statistics/stats.cpp b/src/common/statistics/stats.cpp index 668c6b09a23053f33a16ede3a24d9db2d834d8b4..aa4d063e088b2a8ce2698637015f9df4f8bdf1ac 100644 --- a/src/common/statistics/stats.cpp +++ b/src/common/statistics/stats.cpp @@ -163,9 +163,10 @@ Stats::output_map(std::ofstream& output) { } auto chunkMap = - [](std::string caption, - map>>& order, + [](const std::string& caption, + const map>>& + order, std::ofstream& output) { output << caption << std::endl; for(auto k : order) { diff --git a/src/daemon/daemon.cpp b/src/daemon/daemon.cpp index 4b8728f92d09304e687e4de197459183ff5e27bb..25b970b586e62bbc29d13f86fb032ae66c2714fc 100644 --- a/src/daemon/daemon.cpp +++ b/src/daemon/daemon.cpp @@ -588,7 +588,7 @@ agios_initialize() { agios_exit(); - throw; + std::terminate(); } } #endif @@ -889,10 +889,9 @@ parse_input(const cli_options& opts, const CLI::App& desc) { metadir_path.native()); } else { // use rootdir as metadata dir - auto metadir = opts.rootdir; - if(GKFS_DATA->enable_forwarding()) { + auto metadir = opts.rootdir; // As we store normally he metadata to the pfs, we need to put each // daemon in a separate directory. auto metadir_path = diff --git a/src/proxy/util.cpp b/src/proxy/util.cpp index f1542949a0f3fd8da7a2597915bf7f75c82871bb..e85bd8e73d141ecc3fb35040f280b98b34672cd6 100644 --- a/src/proxy/util.cpp +++ b/src/proxy/util.cpp @@ -215,8 +215,8 @@ connect_to_hosts(const vector>& hosts) { ret = margo_addr_lookup(PROXY_DATA->client_rpc_mid(), uri.c_str(), &svr_addr); if(ret != HG_SUCCESS) { - // still not working after 5 tries. - if(i == 4) { + // still not working after 4 tries. + if(i == 3) { auto err_msg = fmt::format("{}() Unable to lookup address '{}'", __func__, uri); diff --git a/test/symlink_test.cpp b/test/symlink_test.cpp index 6f90f1676da5ef6a695e4de23a8cd45cefc50c65..6e7dd35cd803b4d26d476e5f1b1967bc896994ab 100644 --- a/test/symlink_test.cpp +++ b/test/symlink_test.cpp @@ -57,7 +57,7 @@ main(int argc, char* argv[]) { const std::string link_ext = dir_ext + "/tmp/link"; char buffIn[] = "oops."; - char* buffOut = new char[strlen(buffIn) + 1]; + char buffOut[strlen(buffIn) + 1]; struct stat st; int ret; @@ -170,7 +170,7 @@ main(int argc, char* argv[]) { // Check readlink - char* target_path = new char[target_int.size() + 1]; + char target_path[target_int.size() + 1]; ret = readlink(link_int.c_str(), target_path, target_int.size() + 1); if(ret <= 0) { std::cerr << "ERROR: Failed to retrieve link path: " << strerror(errno) diff --git a/test/wr_test.cpp b/test/wr_test.cpp index 802e48ca611767f7fa352add0ac6f28ea387e12d..b712f33b7de7a909f2555504b996aaa603defe8f 100644 --- a/test/wr_test.cpp +++ b/test/wr_test.cpp @@ -61,7 +61,7 @@ main(int argc, char* argv[]) { string mountdir = "/tmp/mountdir"; string p = mountdir + "/file"; char buffIn[] = "oops."; - char* buffOut = new char[strlen(buffIn) + 1 + 20]; + char buffOut[strlen(buffIn) + 1 + 20]; int fd; int ret; struct stat st;