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

パーミッションをチェックする確実な方法は、文字通りファイルモードをチェックすることです。ディレクトリ権限の場合、「読み取り可能」と「書き込み可能」の意味は驚くべきものかもしれません。

  • 読み取り-ディレクトリの内容を一覧表示できます
  • 書き込み-ディレクトリからファイルを作成、名前変更、削除し、基本的に目次を変更できます(実行も必要です)
  • 実行-ディレクトリ内のファイルのプロパティにアクセス(読み取りと書き込みの両方)および変更できます

したがって、実行ビットのみが設定されたディレクトリがある場合でも、内部のファイルの読み取りと書き込みを行うことができます。実行ビットをオフにすることで、ファイルへのアクセスを無効にすることができます。含まれているファイルに関する限り、ディレクトリのアクセス許可から最も理解できるのは次のとおりです。

  • --xまたはr-x:既存のファイルの読み取りと書き込みが可能
  • -wxまたはrwx:既存のファイルの読み取りと書き込み、ファイルの作成、名前の変更、削除が可能
  • それ以外の場合:ファイルにまったくアクセスできません

ファイルが読み取り可能であるが書き込み可能ではない(またはその逆)かどうかを判断するには、ファイル自体のアクセス許可を確認する必要があります。ディレクトリは、ファイルが一般的にアクセスできるかどうかだけを教えてくれます。

stat() またはaccess()(BЈовићのコメントを参照)を使用して、ファイルまたはディレクトリのアクセス許可を確認できます。すでにboostを使用しているので、stat()をラップするだけのboost :: filesystem :: status()を使用することもできます。

于 2012-09-24T13:59:00.023 に答える
2

移植性と正確性を確保するために、ファイル/ディレクトリの読み取り/書き込み可能性をテストする唯一の方法は、ファイル/ディレクトリからの読み取り/書き込みです。アクセス許可モデルは非常に複雑で、移植性がない (ACL など) 場合があるため、親ディレクトリのアクセス許可を単純に確認することはできません。また、チェックとその後の書き込みは、アクセス権がチェックと書き込みの間で変更される可能性があるため、競合状態になります。

代わりに、アプリケーションのスクラッチ フォルダーをユーザーに選択させる場合など、書き込みが成功する可能性が高い場合は、ファイルの書き込みを試してから、後で削除してください。これにより、ユーザーの選択時にディレクトリが書き込み可能であったことがわかります。

堅牢であるためには、ファイルシステム操作が失敗することを常に想定し、失敗した場合にクラッシュではなく論理的な何かが発生するように設計してください。特に、パーミッション エラーがどこにあるかをユーザーが把握できるようにシステムを設計してください。パーミッションを間違って設定する方法は無数にあるため、役に立つエラー メッセージは大いに役に立ちます。

于 2015-09-15T03:28:55.860 に答える