From 9d1c9ca76ae6790226812819912d6a1c1ca49ce4 Mon Sep 17 00:00:00 2001 From: Rahul Frias Date: Sun, 23 Apr 2023 18:47:43 -0700 Subject: [PATCH] Add error details when offline license is not found [ Merge of http://go/wvgerrit/171310 ] Offline license not found errors are identified by CdmResponseEnum 347 (KEYSET_ID_NOT_FOUND_4). No addition file system information is shared. Checks for file existance use the stat command. The stat call can return error codes from errno.h when the command fails. These are now converted into sub error codes and returned along with the offline license file not found error. This also includes a change to log stat errors other than ENOENT (no such file or directory) as a warning rather than verbose. Bug: 276225520 Test: file_store_unittest, file_utils_unittest, GtsMediaTestCases Change-Id: Ic09d036549582cd65783b49fa96ffefc4bf562c7 --- .../cdm/core/include/device_files.h | 10 +++ libwvdrmengine/cdm/core/src/cdm_session.cpp | 18 +++- libwvdrmengine/cdm/core/src/device_files.cpp | 53 ++++++++++- .../cdm/core/test/device_files_unittest.cpp | 89 ++++++++++++------- libwvdrmengine/cdm/util/include/file_store.h | 1 + libwvdrmengine/cdm/util/include/file_utils.h | 1 + libwvdrmengine/cdm/util/src/file_store.cpp | 5 ++ libwvdrmengine/cdm/util/src/file_utils.cpp | 13 ++- .../cdm/util/test/file_store_unittest.cpp | 8 ++ .../cdm/util/test/file_utils_unittest.cpp | 23 +++++ 10 files changed, 183 insertions(+), 38 deletions(-) diff --git a/libwvdrmengine/cdm/core/include/device_files.h b/libwvdrmengine/cdm/core/include/device_files.h index 6f4ddd62..de2e81f7 100644 --- a/libwvdrmengine/cdm/core/include/device_files.h +++ b/libwvdrmengine/cdm/core/include/device_files.h @@ -68,6 +68,15 @@ class DeviceFiles { kIncorrectFileType = kResponseTypeBase + 14, kIncorrectFileVersion = kResponseTypeBase + 15, kLicenseNotPresent = kResponseTypeBase + 16, + kFileNotFoundEAcces = kResponseTypeBase + 17, + kFileNotFoundEFault = kResponseTypeBase + 18, + kFileNotFoundELoop = kResponseTypeBase + 19, + kFileNotFoundENameTooLong = kResponseTypeBase + 20, + kFileNotFoundENoEnt = kResponseTypeBase + 21, + kFileNotFoundENoMem = kResponseTypeBase + 22, + kFileNotFoundENotDir = kResponseTypeBase + 23, + kFileNotFoundEOverflow = kResponseTypeBase + 24, + kFileNotFoundOther = kResponseTypeBase + 25, }; // Converts the different enum types to a human readable C-string for @@ -75,6 +84,7 @@ class DeviceFiles { static const char* CertificateStateToString(CertificateState state); static const char* CertificateTypeToString(CertificateType type); static const char* ResponseTypeToString(ResponseType type); + static ResponseType ErrnoToResponseType(int errno_value); // CdmLicenseData represents all of the data that is stored in CDM // license file. License data is uniquely keyed using |key_set_id|. diff --git a/libwvdrmengine/cdm/core/src/cdm_session.cpp b/libwvdrmengine/cdm/core/src/cdm_session.cpp index 81a8e1ed..90024c50 100644 --- a/libwvdrmengine/cdm/core/src/cdm_session.cpp +++ b/libwvdrmengine/cdm/core/src/cdm_session.cpp @@ -236,9 +236,21 @@ CdmResponseType CdmSession::RestoreOfflineSession(const CdmKeySetId& key_set_id, DeviceFiles::ResponseTypeToString(sub_error_code), IdToString(key_set_id)); SetErrorDetail(error_detail, sub_error_code); - return sub_error_code == DeviceFiles::kFileNotFound - ? CdmResponseType(KEYSET_ID_NOT_FOUND_4) - : CdmResponseType(GET_LICENSE_ERROR); + switch (sub_error_code) { + case DeviceFiles::kFileNotFound: + case DeviceFiles::kFileNotFoundEAcces: + case DeviceFiles::kFileNotFoundEFault: + case DeviceFiles::kFileNotFoundELoop: + case DeviceFiles::kFileNotFoundENameTooLong: + case DeviceFiles::kFileNotFoundENoEnt: + case DeviceFiles::kFileNotFoundENoMem: + case DeviceFiles::kFileNotFoundENotDir: + case DeviceFiles::kFileNotFoundEOverflow: + case DeviceFiles::kFileNotFoundOther: + return (CdmResponseType(KEYSET_ID_NOT_FOUND_4)); + default: + return (CdmResponseType(GET_LICENSE_ERROR)); + } } offline_init_data_ = std::move(license_data.pssh_data); key_request_ = std::move(license_data.license_request); diff --git a/libwvdrmengine/cdm/core/src/device_files.cpp b/libwvdrmengine/cdm/core/src/device_files.cpp index 6a727794..4bbb786e 100644 --- a/libwvdrmengine/cdm/core/src/device_files.cpp +++ b/libwvdrmengine/cdm/core/src/device_files.cpp @@ -358,12 +358,56 @@ const char* DeviceFiles::ResponseTypeToString(ResponseType type) { return "IncorrectFileVersion"; case kLicenseNotPresent: return "LicenseNotFound"; + case kFileNotFoundEAcces: + return "FileNotFound_EAcces"; + case kFileNotFoundEFault: + return "FileNotFound_EFault"; + case kFileNotFoundELoop: + return "FileNotFound_ELoop"; + case kFileNotFoundENameTooLong: + return "FileNotFound_ENameTooLong"; + case kFileNotFoundENoEnt: + return "FileNotFound_ENoEnt"; + case kFileNotFoundENoMem: + return "FileNotFound_ENoMem"; + case kFileNotFoundENotDir: + return "FileNotFound_ENotDir"; + case kFileNotFoundEOverflow: + return "FileNotFound_EOverflow"; + case kFileNotFoundOther: + return "FileNotFound_Other"; case kResponseTypeBase: // Not a valid value. break; } return UnknownEnumValueToString(static_cast(type)); } +// static +DeviceFiles::ResponseType DeviceFiles::ErrnoToResponseType(int errno_value) { + switch (errno_value) { + case 0: + return kNoError; + case EACCES: + return kFileNotFoundEAcces; + case EFAULT: + return kFileNotFoundEFault; + case ELOOP: + return kFileNotFoundELoop; + case ENAMETOOLONG: + return kFileNotFoundENameTooLong; + case ENOENT: + return kFileNotFoundENoEnt; + case ENOMEM: + return kFileNotFoundENoMem; + case ENOTDIR: + return kFileNotFoundENotDir; + case EOVERFLOW: + return kFileNotFoundEOverflow; + default: + return kFileNotFoundOther; + } +} + // static std::set DeviceFiles::reserved_license_ids_; std::mutex DeviceFiles::reserved_license_ids_mutex_; @@ -1999,9 +2043,12 @@ DeviceFiles::ResponseType DeviceFiles::RetrieveHashedFile( path += name; - if (!file_system_->Exists(path)) { - LOGW("File does not exist: path = %s", path.c_str()); - return kFileNotFound; + int errno_value = 0; + if (!file_system_->Exists(path, &errno_value)) { + const ResponseType result = ErrnoToResponseType(errno_value); + LOGW("File does not exist: path = %s, error = %s", path.c_str(), + ResponseTypeToString(result)); + return result; } const ssize_t file_size = file_system_->FileSize(path); diff --git a/libwvdrmengine/cdm/core/test/device_files_unittest.cpp b/libwvdrmengine/cdm/core/test/device_files_unittest.cpp index dbc82358..47cbc8c6 100644 --- a/libwvdrmengine/cdm/core/test/device_files_unittest.cpp +++ b/libwvdrmengine/cdm/core/test/device_files_unittest.cpp @@ -4432,6 +4432,7 @@ class MockFileSystem : public wvutil::FileSystem { MOCK_METHOD(std::unique_ptr, Open, (const std::string&, int flags), (override)); MOCK_METHOD(bool, Exists, (const std::string&), (override)); + MOCK_METHOD(bool, Exists, (const std::string&, int*), (override)); MOCK_METHOD(bool, Remove, (const std::string&), (override)); MOCK_METHOD(ssize_t, FileSize, (const std::string&), (override)); MOCK_METHOD(bool, List, (const std::string&, std::vector*), @@ -4640,6 +4641,9 @@ TEST_F(DeviceFilesTest, RetrieveAtscCertificate) { // Call to Open will return a unique_ptr, freeing this object. MockFile* file = new MockFile(); + EXPECT_CALL(file_system, Exists(StrEq(device_certificate_path), NotNull())) + .Times(AtLeast(1)) + .WillRepeatedly(Return(true)); EXPECT_CALL(file_system, Exists(StrEq(device_certificate_path))) .Times(AtLeast(1)) .WillRepeatedly(Return(true)); @@ -4908,6 +4912,9 @@ TEST_F(DeviceFilesTest, RetrieveDefaultCertificateNeverExpires) { EXPECT_CALL(file_system, Exists(StrEq(device_certificate_path))) .Times(AtLeast(1)) .WillRepeatedly(Return(true)); + EXPECT_CALL(file_system, Exists(StrEq(device_certificate_path), NotNull())) + .Times(AtLeast(1)) + .WillRepeatedly(Return(true)); EXPECT_CALL(file_system, FileSize(StrEq(device_certificate_path))) .WillOnce(Return(data.size())); EXPECT_CALL(file_system, Open(StrEq(device_certificate_path), _)) @@ -4955,6 +4962,9 @@ TEST_P(RetrieveDefaultCertificateTest, ErrorScenarios) { EXPECT_CALL(file_system, Exists(StrEq(device_certificate_path))) .Times(AtLeast(1)) .WillRepeatedly(Return(true)); + EXPECT_CALL(file_system, Exists(StrEq(device_certificate_path), NotNull())) + .Times(AtLeast(1)) + .WillRepeatedly(Return(true)); EXPECT_CALL(file_system, FileSize(StrEq(device_certificate_path))) .WillOnce(Return(data.size())); EXPECT_CALL(file_system, Open(StrEq(device_certificate_path), _)) @@ -5009,6 +5019,10 @@ TEST_F(DeviceFilesTest, RetrieveCertificateWithoutKeyType) { EXPECT_CALL(file_system, Exists(StrEq(device_legacy_certificate_path))) .Times(AtLeast(1)) .WillRepeatedly(Return(true)); + EXPECT_CALL(file_system, + Exists(StrEq(device_legacy_certificate_path), NotNull())) + .Times(AtLeast(1)) + .WillRepeatedly(Return(true)); EXPECT_CALL(file_system, Exists(StrEq(device_default_certificate_path))) .Times(AtLeast(1)) .WillRepeatedly(Return(false)); @@ -5311,7 +5325,7 @@ TEST_F(DeviceFilesTest, RetrieveLicenses) { // Call to Open will return a unique_ptr, freeing this object. MockFile* file = new MockFile(); - EXPECT_CALL(file_system, Exists(StrEq(license_path))) + EXPECT_CALL(file_system, Exists(StrEq(license_path), NotNull())) .WillOnce(Return(true)); EXPECT_CALL(file_system, FileSize(StrEq(license_path))) .WillOnce(Return(size)); @@ -5383,7 +5397,8 @@ TEST_F(DeviceFilesTest, AppParametersBackwardCompatibility) { // Call to Open will return a unique_ptr, freeing this object. MockFile* file = new MockFile(); - EXPECT_CALL(file_system, Exists(StrEq(license_path))).WillOnce(Return(true)); + EXPECT_CALL(file_system, Exists(StrEq(license_path), NotNull())) + .WillOnce(Return(true)); EXPECT_CALL(file_system, FileSize(StrEq(license_path))) .WillOnce(Return(size)); EXPECT_CALL(file_system, Open(StrEq(license_path), _)) @@ -5474,10 +5489,9 @@ TEST_F(DeviceFilesTest, DeleteLicense) { // Call to Open will return a unique_ptr, freeing this object. MockFile* file = new MockFile(); - EXPECT_CALL(file_system, Exists(StrEq(license_path))) - .Times(2) - .WillOnce(Return(true)) - .WillOnce(Return(false)); + EXPECT_CALL(file_system, Exists(StrEq(license_path))).WillOnce(Return(false)); + EXPECT_CALL(file_system, Exists(StrEq(license_path), NotNull())) + .WillOnce(Return(true)); EXPECT_CALL(file_system, FileSize(StrEq(license_path))) .WillOnce(Return(size)); EXPECT_CALL(file_system, Open(StrEq(license_path), _)) @@ -5579,10 +5593,12 @@ TEST_F(DeviceFilesTest, OkpInfo_FileDoesNotExist) { MockFileSystem file_system; DeviceFiles device_files(&file_system); EXPECT_TRUE(device_files.Init(kSecurityLevelL1)); + int errno_value = ENOENT; const std::string kOkpInfoPath = device_base_path_ + DeviceFiles::GetOkpInfoFileName(); - EXPECT_CALL(file_system, Exists(kOkpInfoPath)).WillOnce(Return(false)); + EXPECT_CALL(file_system, Exists(StrEq(kOkpInfoPath), NotNull())) + .WillRepeatedly(DoAll(SetArgPointee<1>(errno_value), (Return(false)))); okp::SystemFallbackInfo info; EXPECT_FALSE(device_files.RetrieveOkpInfo(&info)); @@ -5641,7 +5657,8 @@ TEST_F(DeviceFilesTest, OkpInfo_StoreAndRetrieve) { // Set retrieve expectations. file = new MockFile(); - EXPECT_CALL(file_system, Exists(kOkpInfoPath)).WillOnce(Return(true)); + EXPECT_CALL(file_system, Exists(StrEq(kOkpInfoPath), NotNull())) + .WillOnce(Return(true)); EXPECT_CALL(file_system, FileSize(kOkpInfoPath)) .WillOnce(Return(serialized.size())); EXPECT_CALL(file_system, Open(kOkpInfoPath, _)) @@ -5676,6 +5693,7 @@ TEST_P(DeviceFilesDeleteMultipleUsageInfoTest, DeleteAllButOne) { file_path += kUsageInfoFileName; EXPECT_CALL(file_system, Exists(_)).WillRepeatedly(Return(true)); + EXPECT_CALL(file_system, Exists(_, NotNull())).WillOnce(Return(true)); EXPECT_CALL(file_system, FileSize(file_path)) .WillOnce(Return(kHashedUsageInfoFileWithThreeKeySetIds.size())); @@ -5733,6 +5751,7 @@ TEST_F(DeviceFilesDeleteMultipleUsageInfoTest, DeleteAllKeySetIds) { // File read expectations. MockFile* file_in = new MockFile(); EXPECT_CALL(file_system, Exists(_)).WillRepeatedly(Return(true)); + EXPECT_CALL(file_system, Exists(_, NotNull())).WillRepeatedly(Return(true)); EXPECT_CALL(file_system, FileSize(file_path)) .WillOnce(Return(kHashedUsageInfoFileWithThreeKeySetIds.size())); EXPECT_CALL(file_system, Open(file_path, wvutil::FileSystem::kReadOnly)) @@ -5763,6 +5782,7 @@ TEST_F(DeviceFilesDeleteMultipleUsageInfoTest, DeleteNone) { file_path += kUsageInfoFileName; EXPECT_CALL(file_system, Exists(_)).WillRepeatedly(Return(true)); + EXPECT_CALL(file_system, Exists(_, NotNull())).WillRepeatedly(Return(true)); // Call, not providing any key set IDs. Should return true without any // action, assuming the file exists. @@ -5803,6 +5823,7 @@ TEST_F(DeviceFilesDeleteMultipleUsageInfoTest, DeleteOne) { file_path += kUsageInfoFileName; EXPECT_CALL(file_system, Exists(_)).WillRepeatedly(Return(true)); + EXPECT_CALL(file_system, Exists(_, NotNull())).WillRepeatedly(Return(true)); EXPECT_CALL(file_system, FileSize(file_path)) .WillOnce(Return(kHashedUsageInfoFileWithTwoKeySetIds.size())); @@ -5857,6 +5878,7 @@ TEST_F(DeviceFilesDeleteMultipleUsageInfoTest, BadFile) { // File is missing hash. MockFile* file_in = new MockFile(); EXPECT_CALL(file_system, Exists(_)).WillRepeatedly(Return(true)); + EXPECT_CALL(file_system, Exists(_, NotNull())).WillRepeatedly(Return(true)); EXPECT_CALL(file_system, FileSize(file_path)) .WillOnce(Return(kHashlessUsageInfoFile.size())); EXPECT_CALL(file_system, Open(file_path, wvutil::FileSystem::kReadOnly)) @@ -5903,9 +5925,9 @@ TEST_F(DeviceFilesUsageInfoTest, ListUsageIds) { if (index >= 0) { // Call to Open will return a unique_ptr, freeing this object. MockFile* file = new MockFile(); - EXPECT_CALL(file_system, Exists(StrEq(path))) - .Times(2) - .WillRepeatedly(Return(true)); + EXPECT_CALL(file_system, Exists(StrEq(path))).WillOnce(Return(true)); + EXPECT_CALL(file_system, Exists(StrEq(path), NotNull())) + .WillOnce(Return(true)); EXPECT_CALL(file_system, FileSize(StrEq(path))) .Times(2) .WillRepeatedly(Return(file_data.size())); @@ -6038,9 +6060,9 @@ TEST_P(DeviceFilesUsageInfoTest, Retrieve) { if (index >= 0) { // Call to Open will return a unique_ptr, freeing this object. MockFile* file = new MockFile(); - EXPECT_CALL(file_system, Exists(StrEq(path))) - .Times(2) - .WillRepeatedly(Return(true)); + EXPECT_CALL(file_system, Exists(StrEq(path))).WillOnce(Return(true)); + EXPECT_CALL(file_system, Exists(StrEq(path), NotNull())) + .WillOnce(Return(true)); EXPECT_CALL(file_system, FileSize(StrEq(path))) .Times(2) .WillRepeatedly(Return(file_data.size())); @@ -6101,9 +6123,9 @@ TEST_P(DeviceFilesUsageInfoTest, ListKeySetIds) { if (index >= 0) { // Call to Open will return a unique_ptr, freeing this object. MockFile* file = new MockFile(); - EXPECT_CALL(file_system, Exists(StrEq(path))) - .Times(2) - .WillRepeatedly(Return(true)); + EXPECT_CALL(file_system, Exists(StrEq(path))).WillOnce(Return(true)); + EXPECT_CALL(file_system, Exists(StrEq(path), NotNull())) + .WillOnce(Return(true)); EXPECT_CALL(file_system, FileSize(StrEq(path))) .Times(2) .WillRepeatedly(Return(file_data.size())); @@ -6153,9 +6175,9 @@ TEST_P(DeviceFilesUsageInfoTest, ListProviderSessionTokenIds) { if (index >= 0) { // Call to Open will return a unique_ptr, freeing this object. MockFile* file = new MockFile(); - EXPECT_CALL(file_system, Exists(StrEq(path))) - .Times(2) - .WillRepeatedly(Return(true)); + EXPECT_CALL(file_system, Exists(StrEq(path))).WillOnce(Return(true)); + EXPECT_CALL(file_system, Exists(StrEq(path), NotNull())) + .WillOnce(Return(true)); EXPECT_CALL(file_system, FileSize(StrEq(path))) .Times(2) .WillRepeatedly(Return(file_data.size())); @@ -6215,7 +6237,8 @@ TEST_P(DeviceFilesUsageInfoTest, RetrieveByProviderSessionToken) { kUsageInfoTestData[index < 0 ? 0 : index] .usage_data.provider_session_token; - EXPECT_CALL(file_system, Exists(StrEq(path))).WillOnce(Return(true)); + EXPECT_CALL(file_system, Exists(StrEq(path), NotNull())) + .WillOnce(Return(true)); EXPECT_CALL(file_system, FileSize(StrEq(path))) .WillOnce(Return(file_data.size())); EXPECT_CALL(file_system, Open(StrEq(path), _)) @@ -6299,9 +6322,9 @@ TEST_P(DeviceFilesUsageInfoTest, UpdateUsageInfo) { (index < 0) ? kEmptyUsageInfoFileData : kUsageInfoTestData[max_index_by_app_id].file_data; - EXPECT_CALL(file_system, Exists(StrEq(path))) - .Times(2) - .WillRepeatedly(Return(true)); + EXPECT_CALL(file_system, Exists(StrEq(path))).WillOnce(Return(true)); + EXPECT_CALL(file_system, Exists(StrEq(path), NotNull())) + .WillOnce(Return(true)); EXPECT_CALL(file_system, FileSize(StrEq(path))) .WillOnce(Return(file_data.size())); EXPECT_CALL(*file, Read(NotNull(), Eq(file_data.size()))) @@ -6344,7 +6367,8 @@ TEST_P(DeviceFilesHlsAttributesTest, Read) { std::string path = device_base_path_ + param->key_set_id + DeviceFiles::GetHlsAttributesFileNameExtension(); - EXPECT_CALL(file_system, Exists(StrEq(path))).WillRepeatedly(Return(true)); + EXPECT_CALL(file_system, Exists(StrEq(path), NotNull())) + .WillOnce(Return(true)); EXPECT_CALL(file_system, FileSize(StrEq(path))) .WillRepeatedly(Return(param->file_data.size())); EXPECT_CALL(file_system, Open(StrEq(path), _)) @@ -6452,7 +6476,8 @@ TEST_P(DeviceFilesUsageTableTest, Read) { std::string path = device_base_path_ + DeviceFiles::GetUsageTableFileName(); const std::string& file_data = kUsageTableInfoTestData[index].file_data; - EXPECT_CALL(file_system, Exists(StrEq(path))).WillRepeatedly(Return(true)); + EXPECT_CALL(file_system, Exists(StrEq(path), NotNull())) + .WillOnce(Return(true)); EXPECT_CALL(file_system, FileSize(StrEq(path))) .WillRepeatedly(Return(file_data.size())); EXPECT_CALL(file_system, Open(StrEq(path), _)) @@ -6505,7 +6530,8 @@ TEST_F(DeviceFilesUsageTableTest, ReadWithoutLruData) { const std::string path = device_base_path_ + DeviceFiles::GetUsageTableFileName(); MockFileSystem file_system; - EXPECT_CALL(file_system, Exists(StrEq(path))).WillRepeatedly(Return(true)); + EXPECT_CALL(file_system, Exists(StrEq(path), NotNull())) + .WillRepeatedly(Return(true)); EXPECT_CALL(file_system, FileSize(StrEq(path))) .WillRepeatedly(Return(kUsageTableWithoutLruData.size())); EXPECT_CALL(file_system, Open(StrEq(path), _)) @@ -6619,7 +6645,7 @@ TEST_F(DeviceFilesTest, RetrieveOemCertificateSuccess) { device_base_path_ + wvutil::kOemCertificateFileName; // Call to Open will return a unique_ptr, freeing this object. MockFile* read_file = new MockFile(); - EXPECT_CALL(file_system, Exists(StrEq(device_certificate_path))) + EXPECT_CALL(file_system, Exists(StrEq(device_certificate_path), NotNull())) .Times(AtLeast(1)) .WillRepeatedly(Return(true)); EXPECT_CALL(file_system, FileSize(StrEq(device_certificate_path))) @@ -6650,7 +6676,7 @@ TEST_F(DeviceFilesTest, RetrieveOemCertificateRandomCertFail) { std::string ramdom_cert = "random_cert"; // Call to Open will return a unique_ptr, freeing this object. MockFile* read_file = new MockFile(); - EXPECT_CALL(file_system, Exists(StrEq(device_certificate_path))) + EXPECT_CALL(file_system, Exists(StrEq(device_certificate_path), NotNull())) .Times(AtLeast(1)) .WillRepeatedly(Return(true)); EXPECT_CALL(file_system, FileSize(StrEq(device_certificate_path))) @@ -6676,9 +6702,10 @@ TEST_F(DeviceFilesTest, RetrieveOemCertificateNotFoundFail) { MockFileSystem file_system; const std::string device_certificate_path = device_base_path_ + wvutil::kOemCertificateFileName; - EXPECT_CALL(file_system, Exists(StrEq(device_certificate_path))) + int errno_value = ENOENT; + EXPECT_CALL(file_system, Exists(StrEq(device_certificate_path), NotNull())) .Times(AtLeast(1)) - .WillRepeatedly(Return(false)); + .WillRepeatedly(DoAll(SetArgPointee<1>(errno_value), (Return(false)))); DeviceFiles device_files(&file_system); EXPECT_TRUE(device_files.Init(kSecurityLevelL1)); diff --git a/libwvdrmengine/cdm/util/include/file_store.h b/libwvdrmengine/cdm/util/include/file_store.h index 6bb1773c..9563b5eb 100644 --- a/libwvdrmengine/cdm/util/include/file_store.h +++ b/libwvdrmengine/cdm/util/include/file_store.h @@ -58,6 +58,7 @@ class FileSystem { virtual std::unique_ptr Open(const std::string& file_path, int flags); virtual bool Exists(const std::string& file_path); + virtual bool Exists(const std::string& file_path, int* errno_value); virtual bool Remove(const std::string& file_path); virtual ssize_t FileSize(const std::string& file_path); diff --git a/libwvdrmengine/cdm/util/include/file_utils.h b/libwvdrmengine/cdm/util/include/file_utils.h index 4a61efac..1f75f973 100644 --- a/libwvdrmengine/cdm/util/include/file_utils.h +++ b/libwvdrmengine/cdm/util/include/file_utils.h @@ -16,6 +16,7 @@ bool IsCurrentOrParentDirectory(const char* dir); class FileUtils { public: static bool Exists(const std::string& src); + static bool Exists(const std::string& src, int* errno_value); // The caller may only specifying a single wildcard static bool Remove(const std::string& src); static bool Copy(const std::string& src, const std::string& dest); diff --git a/libwvdrmengine/cdm/util/src/file_store.cpp b/libwvdrmengine/cdm/util/src/file_store.cpp index ca11cdfb..63f3b716 100644 --- a/libwvdrmengine/cdm/util/src/file_store.cpp +++ b/libwvdrmengine/cdm/util/src/file_store.cpp @@ -497,6 +497,11 @@ std::unique_ptr FileSystem::Open(const std::string& file_name, return std::unique_ptr(new AndroidFile(fd, flags, file_path)); } +bool FileSystem::Exists(const std::string& path, int* errno_value) { + return FileUtils::Exists(GetFileNameForIdentifier(path, identifier_), + errno_value); +} + bool FileSystem::Exists(const std::string& path) { return FileUtils::Exists(GetFileNameForIdentifier(path, identifier_)); } diff --git a/libwvdrmengine/cdm/util/src/file_utils.cpp b/libwvdrmengine/cdm/util/src/file_utils.cpp index 07892cac..56c3106c 100644 --- a/libwvdrmengine/cdm/util/src/file_utils.cpp +++ b/libwvdrmengine/cdm/util/src/file_utils.cpp @@ -25,11 +25,22 @@ bool IsCurrentOrParentDirectory(const char* dir) { } bool FileUtils::Exists(const std::string& path) { + return Exists(path, nullptr); +} + +bool FileUtils::Exists(const std::string& path, int* errno_value) { struct stat buf; + int error = 0; int res = stat(path.c_str(), &buf) == 0; if (!res) { - LOGV("File::Exists: stat failed: %d, %s", errno, strerror(errno)); + error = errno; + if (error == ENOENT) { + LOGI("stat failed: ENOENT"); + } else { + LOGE("stat failed: %d, %s", error, strerror(error)); + } } + if (errno_value != nullptr) *errno_value = error; return res; } diff --git a/libwvdrmengine/cdm/util/test/file_store_unittest.cpp b/libwvdrmengine/cdm/util/test/file_store_unittest.cpp index 340a6214..a62bfc03 100644 --- a/libwvdrmengine/cdm/util/test/file_store_unittest.cpp +++ b/libwvdrmengine/cdm/util/test/file_store_unittest.cpp @@ -39,9 +39,17 @@ class FileTest : public testing::Test { }; TEST_F(FileTest, FileExists) { + int errno_value = -1; EXPECT_TRUE(file_system_.Exists(wvcdm::test_vectors::kExistentFile)); + EXPECT_TRUE( + file_system_.Exists(wvcdm::test_vectors::kExistentFile, &errno_value)); + EXPECT_EQ(0, errno_value); EXPECT_TRUE(file_system_.Exists(wvcdm::test_vectors::kExistentDir)); + EXPECT_FALSE(file_system_.Exists(wvcdm::test_vectors::kNonExistentFile)); + EXPECT_FALSE( + file_system_.Exists(wvcdm::test_vectors::kNonExistentFile, &errno_value)); + EXPECT_EQ(ENOENT, errno_value); EXPECT_FALSE(file_system_.Exists(wvcdm::test_vectors::kNonExistentDir)); } diff --git a/libwvdrmengine/cdm/util/test/file_utils_unittest.cpp b/libwvdrmengine/cdm/util/test/file_utils_unittest.cpp index 8c3feb47..6ab86610 100644 --- a/libwvdrmengine/cdm/util/test/file_utils_unittest.cpp +++ b/libwvdrmengine/cdm/util/test/file_utils_unittest.cpp @@ -98,6 +98,29 @@ TEST_F(FileUtilsTest, IsRegularFile) { EXPECT_FALSE(FileUtils::IsRegularFile(wvcdm::test_vectors::kTestDir)); } +TEST_F(FileUtilsTest, FileExists) { + std::string path = wvcdm::test_vectors::kTestDir + kTestFileName; + std::string path2 = wvcdm::test_vectors::kTestDir + kTestFileName2; + file_system_.Remove(path); + file_system_.Remove(path2); + + std::unique_ptr file = file_system_.Open(path, FileSystem::kCreate); + EXPECT_TRUE(file); + + EXPECT_TRUE(file_system_.Exists(path)); + int errno_value = -1; + EXPECT_TRUE(file_system_.Exists(path, &errno_value)); + EXPECT_EQ(0, errno_value); + EXPECT_TRUE(file_system_.Exists(wvcdm::test_vectors::kTestDir)); + EXPECT_TRUE(file_system_.Exists(path, nullptr)); + + EXPECT_FALSE(file_system_.Exists(path2)); + EXPECT_FALSE(file_system_.Exists(path2, &errno_value)); + EXPECT_EQ(ENOENT, errno_value); + EXPECT_TRUE(file_system_.Exists(wvcdm::test_vectors::kTestDir)); + EXPECT_FALSE(file_system_.Exists(path2, nullptr)); +} + TEST_F(FileUtilsTest, CopyFile) { std::string path = wvcdm::test_vectors::kTestDir + kTestFileName; file_system_.Remove(path);