6

我编写了一个函数来测试文件夹的可读性/可写性。

对于单元测试,我需要生成不同的案例:

  • 包含可读写文件的文件夹
  • 具有可读文件的文件夹(不可写)
  • 一个不可写且不可读的文件夹。

到目前为止,这是我来到的函数的代码:

void FileUtils::checkPath(std::string path, bool &readable, bool &writable)
{
   namespace bf = boost::filesystem;
   std::string filePath = path + "/test.txt";

   // remove a possibly existing test file
   remove(filePath.c_str());

   // check that the path exists
   if(!bf::is_directory(path))
   {
      readable = writable = false;
      return;
   }

   // try to write in the location
   std::ofstream outfile (filePath.c_str());
   outfile << "I can write!" << std::endl;
   outfile.close();

   if(!outfile.fail() && !outfile.bad())
   {
      writable = true;
   }

   // look for a file to read
   std::ifstream::pos_type size;
   char * memblock;
   for (bf::recursive_directory_iterator it(path); it != bf::recursive_directory_iterator(); ++it)
   {
      if (!is_directory(*it))
      {
         std::string sFilePath = it->path().string();
         std::ifstream file(sFilePath.c_str(), std::ios::in|std::ios::binary|std::ios::ate);
         if (file.is_open())
         {
           size = file.tellg();
           if(size > 0)
           {
              memblock = new char [1];
              file.seekg (0, std::ios::beg);
              file.read (memblock, 1);
              file.close();
              delete[] memblock;
              if(!file.fail() && !file.bad())
              {
                 readable = true;
              }
              break;
           }
         }
         else
         {
            // there is a non readable file in the folder
            // readable = false;
            break;
         }
      }
   }

   // delete the test file
   remove(filePath.c_str());
}

现在进行测试(通过 Google 测试完成):

TEST_F(FileUtilsTest, shouldCheckPath)
{
   // given an existing folder
   namespace fs = boost::filesystem;
   fs::create_directory("/tmp/to_be_deleted");

   bool readable = false, writable = false;

   FileUtils::checkPath("/tmp/to_be_deleted",readable, writable);

   fs::boost::filesystem::remove_all("/tmp/to_be_deleted");

   EXPECT_TRUE(readable && writable);
}

当我走得更远时,我会为其他情况添加更多内容。

现在游戏开放以提出更好的解决方案:-)

4

2 回答 2

5

检查权限的万无一失的方法是逐字检查文件模式。在目录权限的情况下,“可读”和“可写”的含义可能令人惊讶:

  • 读取 - 允许您列出目录的内容
  • 写入 - 允许您从目录中创建、重命名、删除文件,本质上是修改内容列表(也需要执行)
  • 执行 - 允许您访问(读取和写入)和更改目录中文件的属性

所以如果你有一个只设置了执行位的目录,你仍然可以读写里面的文件。通过关闭执行位,您可以禁用对文件的访问。就包含的文件而言,您可以从目录权限中找出最多的是:

  • --xr-x:可以读取和写入现有文件
  • -wxrwx:可以读取和写入现有文件,可以创建、重命名和删除文件
  • 否则:您根本无法访问这些文件

要确定文件是否可读但不可写(反之亦然),您需要检查文件本身的权限。该目录只能告诉您文件是否可以正常访问。

您可以使用stat() access()(请参阅 BЈовић 的评论)来找出文件或目录的权限。由于您已经在使用 boost,您还可以使用boost::filesystem::status(),它只是包装了 stat()。

于 2012-09-24T13:59:00.023 回答
2

为了可移植和正确,测试文件/目录的可读性/可写性的唯一方法是对其进行读/写。权限模型可能非常复杂且不可移植(例如 ACL),因此您不能简单地检查父目录的权限。此外,检查,然后尝试写入是一种竞争条件,因为权限可能会在检查和写入之间发生变化。

相反,如果您想要的是写入成功的可能性很高,例如,如果您让用户为您的应用程序选择一个临时文件夹,则只需尝试写入一个文件,然后将其删除。这让您知道在用户选择时目录是可写的。

为了保持稳健,始终假设文件系统操作将失败并进行设计,以便当它们失败时,会发生一些合乎逻辑的事情而不是崩溃。特别是,设计一个系统,以便用户可以找出权限错误的位置——因为权限设置错误的方式有很多种,有用的错误消息会大有帮助。

于 2015-09-15T03:28:55.860 回答