commit aedb452477c60551dc13c223da74f0878488caeb from: Aleksey Ryndin date: Tue Feb 13 17:02:12 2024 UTC WiP: split open_file and open_directory commit - e3d510f54dd27b2a9674e8fbe051d69969d48a90 commit + aedb452477c60551dc13c223da74f0878488caeb blob - ee8dc1b8becc3072574095085fcf2f5d3654d66d blob + 49612ff96d3235a80905edc5971fcfb2421069b8 --- tests/test_open_file.cc +++ tests/test_open_file.cc @@ -25,31 +25,45 @@ TEST_START(test_open_file) const UniqueFd dir{open(ss.str().c_str(), O_RDONLY | O_DIRECTORY)}; IS_TRUE_ERRNO(dir, "Open directory " << ss.str().c_str()); + struct stat sb1{}; + IS_TRUE_ERRNO(fstat(dir.get(), &sb1) != -1, "Stat file " << ss.str().c_str()) std::string file_name; { - OpenedFile opened_file; + UniqueFd opened_fd; file_name = ""; - IS_TRUE(opened_file.open(dir.get(), file_name) == OpenedFile::NOT_FOUND); + IS_TRUE(open_file::open(dir.get(), file_name, opened_fd) == open_file::OPENED_DIRECTORY); + + struct stat sb2{}; + IS_TRUE_ERRNO(fstat(opened_fd.get(), &sb2) != -1, "Stat file " << ss.str().c_str()); + IS_TRUE((sb1.st_dev == sb2.st_dev) && (sb1.st_ino == sb2.st_ino)); } { - OpenedFile opened_file; + UniqueFd opened_fd; + file_name = "/"; + IS_TRUE(open_file::open(dir.get(), file_name, opened_fd) == open_file::OPENED_DIRECTORY); + + struct stat sb2{}; + IS_TRUE_ERRNO(fstat(opened_fd.get(), &sb2) != -1, "Stat file " << ss.str().c_str()); + IS_TRUE((sb1.st_dev == sb2.st_dev) && (sb1.st_ino == sb2.st_ino)); + } + { + UniqueFd opened_fd; file_name = "non-existent-file"; - IS_TRUE(opened_file.open(dir.get(), file_name) == OpenedFile::NOT_FOUND); + IS_TRUE(open_file::open(dir.get(), file_name, opened_fd) == open_file::NOT_FOUND); } { - OpenedFile opened_file; + UniqueFd opened_fd; file_name = "non-existent-dir/file"; - IS_TRUE(opened_file.open(dir.get(), file_name) == OpenedFile::NOT_FOUND); + IS_TRUE(open_file::open(dir.get(), file_name, opened_fd) == open_file::NOT_FOUND); } const UniqueFd index_gmi{openat(dir.get(), "index.gmi", O_RDONLY | O_CREAT | O_EXCL, S_IRWXU)}; IS_TRUE_ERRNO(index_gmi, "Create file " << ss.str().c_str() << "/index.gmi"); - struct stat sb1{}; IS_TRUE_ERRNO(fstat(index_gmi.get(), &sb1) != -1, "Stat file " << ss.str().c_str() << "/index.gmi"); - +/* { OpenedFile opened_file; file_name = ""; @@ -129,7 +143,8 @@ TEST_START(test_open_file) IS_TRUE_ERRNO(unlinkat(subdir.get(), "EPERM.gmi", 0) != -1, "Remove file " << ss.str().c_str() << "/subdir/EPERM.gmi"); IS_TRUE_ERRNO(unlinkat(subdir.get(), "index.gmi", 0) != -1, "Remove file " << ss.str().c_str() << "/subdir/index.gmi"); IS_TRUE_ERRNO(unlinkat(dir.get(), "subdir", AT_REMOVEDIR) != -1, "Remove directory " << ss.str().c_str() << "/subdir"); - IS_TRUE_ERRNO(unlinkat(dir.get(), "index.gmi", 0) != -1, "Remove file " << ss.str().c_str() << "/index.gmi"); +*/ + IS_TRUE_ERRNO(unlinkat(dir.get(), "index.gmi", 0) != -1, "Remove file " << ss.str().c_str() << "/index.gmi"); IS_TRUE_ERRNO(rmdir(ss.str().c_str()) != -1, "Remove directory " << ss.str().c_str()); TEST_END() } // namespace vostok blob - 3c2916fd4db1cae0ce47ab970207e3dac0fdeb62 blob + 6b9722c01a9c7d891f6f144c06294b9746b0f490 --- vostok/open_file.cc +++ vostok/open_file.cc @@ -10,46 +10,89 @@ namespace vostok { +namespace open_file +{ -const std::string OpenedFile::s_index_gmi{"index.gmi"}; +static +const char *get_pathname(const std::string &path) +{ + if (path.empty() || (path.size() == 1 && path[0] == '/')) + return "."; + assert(path[0] != '/'); + return path.c_str(); +} -OpenedFile::Result -OpenedFile::open( +Result open( /* in */ int directory_fd, - /* in/out */ std::string &request_path + /* in */ const std::string &path, + /* out */ UniqueFd &opened_fd // filled if OPENED or OPENED_DIRECTORY ) { - if (request_path.empty()) + opened_fd.reset(openat(directory_fd, get_pathname(path), O_RDONLY)); + if (!opened_fd) { - m_path = &s_index_gmi; + const auto error_code = errno; + error::occurred( + [&path] + { + error::g_log << "Open file \"" << path << "\""; + }, + error::Print{error_code} + ); + return (error_code == ENOENT) ? NOT_FOUND : OPENING_ERROR; } - else + struct stat sb{}; + if (fstat(opened_fd.get(), &sb) == -1) { - m_owner.swap(request_path); - m_path = &m_owner; + error::occurred( + [&path] + { + error::g_log << "Stat file \"" << path << "\""; + }, + error::Print{} + ); + return OPENING_ERROR; } - - m_fd.reset(openat(directory_fd, m_path->c_str(), O_RDONLY)); - if (!m_fd) + return S_ISDIR(sb.st_mode) ? OPENED_DIRECTORY : OPENED; +} + + +} // namespace open_file + + +namespace open_directory +{ + + +const std::string g_index_gmi{"index.gmi"}; + + +Result open( + /* in */ int directory_fd, + /* out */ UniqueFd &opened_fd +) +{ + opened_fd.reset(openat(directory_fd, g_index_gmi.c_str(), O_RDONLY)); + if (!opened_fd) { const auto error_code = errno; error::occurred( - [this] + [] { - error::g_log << "Open file \"" << *this->m_path << "\""; + error::g_log << "Open file \"" << g_index_gmi << "\""; }, error::Print{error_code} ); return (error_code == ENOENT) ? NOT_FOUND : OPENING_ERROR; } struct stat sb{}; - if (fstat(m_fd.get(), &sb) == -1) + if (fstat(opened_fd.get(), &sb) == -1) { error::occurred( - [this] + [] { - error::g_log << "Stat file \"" << *this->m_path << "\""; + error::g_log << "Stat file \"" << g_index_gmi << "\""; }, error::Print{} ); @@ -57,24 +100,14 @@ OpenedFile::open( } if (S_ISDIR(sb.st_mode)) { - const UniqueFd new_parent{m_fd.release()}; - m_path = &s_index_gmi; - m_fd.reset(openat(new_parent.get(), m_path->c_str(), O_RDONLY)); - if (!m_fd) - { - const auto error_code = errno; - error::occurred( - [this] - { - error::g_log << "Re-open file " << this->m_path->c_str(); - }, - error::Print{error_code} - ); - return (error_code == ENOENT) ? NOT_FOUND : OPENING_ERROR; - } + opened_fd.reset(); + return NOT_FOUND; } return OPENED; } +} // namespace open_directory + + } // namespace vostok blob - 543937f216bb3e053c9f15abfb8ff9a848595c18 blob + 1b9e6dcf59466e29a5c2269d3c64da36ed8f34c2 --- vostok/open_file.h +++ vostok/open_file.h @@ -9,36 +9,49 @@ namespace vostok { -class OpenedFile +namespace open_file { -public: - /** Gettters: call after method open(...) has returned OPENED */ - int get_fd() const { return m_fd.get(); } - const std::string &get_path() const{ assert(m_path); return *m_path; } - /** Open file */ - enum Result - { - OPENED, +enum Result +{ + OPENED, + OPENED_DIRECTORY, - NOT_FOUND, - OPENING_ERROR, - }; + NOT_FOUND, + OPENING_ERROR, +}; - Result - open( - /* in */ int directory_fd, - /* in/out */ std::string &request_path // move ownership - ); +Result open( + /* in */ int directory_fd, + /* in */ const std::string &path, + /* out */ UniqueFd &opened_fd // filled if OPENED or OPENED_DIRECTORY +); -private: - UniqueFd m_fd; - const std::string *m_path{nullptr}; - - std::string m_owner; - static const std::string s_index_gmi; + +} // namespace open_file + + +namespace open_directory +{ + + +enum Result +{ + OPENED, + + NOT_FOUND, + OPENING_ERROR, }; +Result open( + /* in */ int directory_fd, + /* out */ UniqueFd &opened_fd +); +extern const std::string g_index_gmi; + + +} // namespace open_directory + } // namespace vostok