Commit Diff


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