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);