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
This commit is contained in:
Rahul Frias
2023-04-23 18:47:43 -07:00
parent 5409567ef9
commit 9d1c9ca76a
10 changed files with 183 additions and 38 deletions

View File

@@ -68,6 +68,15 @@ class DeviceFiles {
kIncorrectFileType = kResponseTypeBase + 14, kIncorrectFileType = kResponseTypeBase + 14,
kIncorrectFileVersion = kResponseTypeBase + 15, kIncorrectFileVersion = kResponseTypeBase + 15,
kLicenseNotPresent = kResponseTypeBase + 16, 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 // 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* CertificateStateToString(CertificateState state);
static const char* CertificateTypeToString(CertificateType type); static const char* CertificateTypeToString(CertificateType type);
static const char* ResponseTypeToString(ResponseType type); static const char* ResponseTypeToString(ResponseType type);
static ResponseType ErrnoToResponseType(int errno_value);
// CdmLicenseData represents all of the data that is stored in CDM // CdmLicenseData represents all of the data that is stored in CDM
// license file. License data is uniquely keyed using |key_set_id|. // license file. License data is uniquely keyed using |key_set_id|.

View File

@@ -236,9 +236,21 @@ CdmResponseType CdmSession::RestoreOfflineSession(const CdmKeySetId& key_set_id,
DeviceFiles::ResponseTypeToString(sub_error_code), DeviceFiles::ResponseTypeToString(sub_error_code),
IdToString(key_set_id)); IdToString(key_set_id));
SetErrorDetail(error_detail, sub_error_code); SetErrorDetail(error_detail, sub_error_code);
return sub_error_code == DeviceFiles::kFileNotFound switch (sub_error_code) {
? CdmResponseType(KEYSET_ID_NOT_FOUND_4) case DeviceFiles::kFileNotFound:
: CdmResponseType(GET_LICENSE_ERROR); 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); offline_init_data_ = std::move(license_data.pssh_data);
key_request_ = std::move(license_data.license_request); key_request_ = std::move(license_data.license_request);

View File

@@ -358,12 +358,56 @@ const char* DeviceFiles::ResponseTypeToString(ResponseType type) {
return "IncorrectFileVersion"; return "IncorrectFileVersion";
case kLicenseNotPresent: case kLicenseNotPresent:
return "LicenseNotFound"; 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. case kResponseTypeBase: // Not a valid value.
break; break;
} }
return UnknownEnumValueToString(static_cast<int>(type)); return UnknownEnumValueToString(static_cast<int>(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 // static
std::set<std::string> DeviceFiles::reserved_license_ids_; std::set<std::string> DeviceFiles::reserved_license_ids_;
std::mutex DeviceFiles::reserved_license_ids_mutex_; std::mutex DeviceFiles::reserved_license_ids_mutex_;
@@ -1999,9 +2043,12 @@ DeviceFiles::ResponseType DeviceFiles::RetrieveHashedFile(
path += name; path += name;
if (!file_system_->Exists(path)) { int errno_value = 0;
LOGW("File does not exist: path = %s", path.c_str()); if (!file_system_->Exists(path, &errno_value)) {
return kFileNotFound; 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); const ssize_t file_size = file_system_->FileSize(path);

View File

@@ -4432,6 +4432,7 @@ class MockFileSystem : public wvutil::FileSystem {
MOCK_METHOD(std::unique_ptr<File>, Open, (const std::string&, int flags), MOCK_METHOD(std::unique_ptr<File>, Open, (const std::string&, int flags),
(override)); (override));
MOCK_METHOD(bool, Exists, (const std::string&), (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(bool, Remove, (const std::string&), (override));
MOCK_METHOD(ssize_t, FileSize, (const std::string&), (override)); MOCK_METHOD(ssize_t, FileSize, (const std::string&), (override));
MOCK_METHOD(bool, List, (const std::string&, std::vector<std::string>*), MOCK_METHOD(bool, List, (const std::string&, std::vector<std::string>*),
@@ -4640,6 +4641,9 @@ TEST_F(DeviceFilesTest, RetrieveAtscCertificate) {
// Call to Open will return a unique_ptr, freeing this object. // Call to Open will return a unique_ptr, freeing this object.
MockFile* file = new MockFile(); 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))) EXPECT_CALL(file_system, Exists(StrEq(device_certificate_path)))
.Times(AtLeast(1)) .Times(AtLeast(1))
.WillRepeatedly(Return(true)); .WillRepeatedly(Return(true));
@@ -4908,6 +4912,9 @@ TEST_F(DeviceFilesTest, RetrieveDefaultCertificateNeverExpires) {
EXPECT_CALL(file_system, Exists(StrEq(device_certificate_path))) EXPECT_CALL(file_system, Exists(StrEq(device_certificate_path)))
.Times(AtLeast(1)) .Times(AtLeast(1))
.WillRepeatedly(Return(true)); .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))) EXPECT_CALL(file_system, FileSize(StrEq(device_certificate_path)))
.WillOnce(Return(data.size())); .WillOnce(Return(data.size()));
EXPECT_CALL(file_system, Open(StrEq(device_certificate_path), _)) 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))) EXPECT_CALL(file_system, Exists(StrEq(device_certificate_path)))
.Times(AtLeast(1)) .Times(AtLeast(1))
.WillRepeatedly(Return(true)); .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))) EXPECT_CALL(file_system, FileSize(StrEq(device_certificate_path)))
.WillOnce(Return(data.size())); .WillOnce(Return(data.size()));
EXPECT_CALL(file_system, Open(StrEq(device_certificate_path), _)) 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))) EXPECT_CALL(file_system, Exists(StrEq(device_legacy_certificate_path)))
.Times(AtLeast(1)) .Times(AtLeast(1))
.WillRepeatedly(Return(true)); .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))) EXPECT_CALL(file_system, Exists(StrEq(device_default_certificate_path)))
.Times(AtLeast(1)) .Times(AtLeast(1))
.WillRepeatedly(Return(false)); .WillRepeatedly(Return(false));
@@ -5311,7 +5325,7 @@ TEST_F(DeviceFilesTest, RetrieveLicenses) {
// Call to Open will return a unique_ptr, freeing this object. // Call to Open will return a unique_ptr, freeing this object.
MockFile* file = new MockFile(); MockFile* file = new MockFile();
EXPECT_CALL(file_system, Exists(StrEq(license_path))) EXPECT_CALL(file_system, Exists(StrEq(license_path), NotNull()))
.WillOnce(Return(true)); .WillOnce(Return(true));
EXPECT_CALL(file_system, FileSize(StrEq(license_path))) EXPECT_CALL(file_system, FileSize(StrEq(license_path)))
.WillOnce(Return(size)); .WillOnce(Return(size));
@@ -5383,7 +5397,8 @@ TEST_F(DeviceFilesTest, AppParametersBackwardCompatibility) {
// Call to Open will return a unique_ptr, freeing this object. // Call to Open will return a unique_ptr, freeing this object.
MockFile* file = new MockFile(); 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))) EXPECT_CALL(file_system, FileSize(StrEq(license_path)))
.WillOnce(Return(size)); .WillOnce(Return(size));
EXPECT_CALL(file_system, Open(StrEq(license_path), _)) 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. // Call to Open will return a unique_ptr, freeing this object.
MockFile* file = new MockFile(); MockFile* file = new MockFile();
EXPECT_CALL(file_system, Exists(StrEq(license_path))) EXPECT_CALL(file_system, Exists(StrEq(license_path))).WillOnce(Return(false));
.Times(2) EXPECT_CALL(file_system, Exists(StrEq(license_path), NotNull()))
.WillOnce(Return(true)) .WillOnce(Return(true));
.WillOnce(Return(false));
EXPECT_CALL(file_system, FileSize(StrEq(license_path))) EXPECT_CALL(file_system, FileSize(StrEq(license_path)))
.WillOnce(Return(size)); .WillOnce(Return(size));
EXPECT_CALL(file_system, Open(StrEq(license_path), _)) EXPECT_CALL(file_system, Open(StrEq(license_path), _))
@@ -5579,10 +5593,12 @@ TEST_F(DeviceFilesTest, OkpInfo_FileDoesNotExist) {
MockFileSystem file_system; MockFileSystem file_system;
DeviceFiles device_files(&file_system); DeviceFiles device_files(&file_system);
EXPECT_TRUE(device_files.Init(kSecurityLevelL1)); EXPECT_TRUE(device_files.Init(kSecurityLevelL1));
int errno_value = ENOENT;
const std::string kOkpInfoPath = const std::string kOkpInfoPath =
device_base_path_ + DeviceFiles::GetOkpInfoFileName(); 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; okp::SystemFallbackInfo info;
EXPECT_FALSE(device_files.RetrieveOkpInfo(&info)); EXPECT_FALSE(device_files.RetrieveOkpInfo(&info));
@@ -5641,7 +5657,8 @@ TEST_F(DeviceFilesTest, OkpInfo_StoreAndRetrieve) {
// Set retrieve expectations. // Set retrieve expectations.
file = new MockFile(); 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)) EXPECT_CALL(file_system, FileSize(kOkpInfoPath))
.WillOnce(Return(serialized.size())); .WillOnce(Return(serialized.size()));
EXPECT_CALL(file_system, Open(kOkpInfoPath, _)) EXPECT_CALL(file_system, Open(kOkpInfoPath, _))
@@ -5676,6 +5693,7 @@ TEST_P(DeviceFilesDeleteMultipleUsageInfoTest, DeleteAllButOne) {
file_path += kUsageInfoFileName; file_path += kUsageInfoFileName;
EXPECT_CALL(file_system, Exists(_)).WillRepeatedly(Return(true)); EXPECT_CALL(file_system, Exists(_)).WillRepeatedly(Return(true));
EXPECT_CALL(file_system, Exists(_, NotNull())).WillOnce(Return(true));
EXPECT_CALL(file_system, FileSize(file_path)) EXPECT_CALL(file_system, FileSize(file_path))
.WillOnce(Return(kHashedUsageInfoFileWithThreeKeySetIds.size())); .WillOnce(Return(kHashedUsageInfoFileWithThreeKeySetIds.size()));
@@ -5733,6 +5751,7 @@ TEST_F(DeviceFilesDeleteMultipleUsageInfoTest, DeleteAllKeySetIds) {
// File read expectations. // File read expectations.
MockFile* file_in = new MockFile(); MockFile* file_in = new MockFile();
EXPECT_CALL(file_system, Exists(_)).WillRepeatedly(Return(true)); EXPECT_CALL(file_system, Exists(_)).WillRepeatedly(Return(true));
EXPECT_CALL(file_system, Exists(_, NotNull())).WillRepeatedly(Return(true));
EXPECT_CALL(file_system, FileSize(file_path)) EXPECT_CALL(file_system, FileSize(file_path))
.WillOnce(Return(kHashedUsageInfoFileWithThreeKeySetIds.size())); .WillOnce(Return(kHashedUsageInfoFileWithThreeKeySetIds.size()));
EXPECT_CALL(file_system, Open(file_path, wvutil::FileSystem::kReadOnly)) EXPECT_CALL(file_system, Open(file_path, wvutil::FileSystem::kReadOnly))
@@ -5763,6 +5782,7 @@ TEST_F(DeviceFilesDeleteMultipleUsageInfoTest, DeleteNone) {
file_path += kUsageInfoFileName; file_path += kUsageInfoFileName;
EXPECT_CALL(file_system, Exists(_)).WillRepeatedly(Return(true)); 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 // Call, not providing any key set IDs. Should return true without any
// action, assuming the file exists. // action, assuming the file exists.
@@ -5803,6 +5823,7 @@ TEST_F(DeviceFilesDeleteMultipleUsageInfoTest, DeleteOne) {
file_path += kUsageInfoFileName; file_path += kUsageInfoFileName;
EXPECT_CALL(file_system, Exists(_)).WillRepeatedly(Return(true)); EXPECT_CALL(file_system, Exists(_)).WillRepeatedly(Return(true));
EXPECT_CALL(file_system, Exists(_, NotNull())).WillRepeatedly(Return(true));
EXPECT_CALL(file_system, FileSize(file_path)) EXPECT_CALL(file_system, FileSize(file_path))
.WillOnce(Return(kHashedUsageInfoFileWithTwoKeySetIds.size())); .WillOnce(Return(kHashedUsageInfoFileWithTwoKeySetIds.size()));
@@ -5857,6 +5878,7 @@ TEST_F(DeviceFilesDeleteMultipleUsageInfoTest, BadFile) {
// File is missing hash. // File is missing hash.
MockFile* file_in = new MockFile(); MockFile* file_in = new MockFile();
EXPECT_CALL(file_system, Exists(_)).WillRepeatedly(Return(true)); EXPECT_CALL(file_system, Exists(_)).WillRepeatedly(Return(true));
EXPECT_CALL(file_system, Exists(_, NotNull())).WillRepeatedly(Return(true));
EXPECT_CALL(file_system, FileSize(file_path)) EXPECT_CALL(file_system, FileSize(file_path))
.WillOnce(Return(kHashlessUsageInfoFile.size())); .WillOnce(Return(kHashlessUsageInfoFile.size()));
EXPECT_CALL(file_system, Open(file_path, wvutil::FileSystem::kReadOnly)) EXPECT_CALL(file_system, Open(file_path, wvutil::FileSystem::kReadOnly))
@@ -5903,9 +5925,9 @@ TEST_F(DeviceFilesUsageInfoTest, ListUsageIds) {
if (index >= 0) { if (index >= 0) {
// Call to Open will return a unique_ptr, freeing this object. // Call to Open will return a unique_ptr, freeing this object.
MockFile* file = new MockFile(); MockFile* file = new MockFile();
EXPECT_CALL(file_system, Exists(StrEq(path))) EXPECT_CALL(file_system, Exists(StrEq(path))).WillOnce(Return(true));
.Times(2) EXPECT_CALL(file_system, Exists(StrEq(path), NotNull()))
.WillRepeatedly(Return(true)); .WillOnce(Return(true));
EXPECT_CALL(file_system, FileSize(StrEq(path))) EXPECT_CALL(file_system, FileSize(StrEq(path)))
.Times(2) .Times(2)
.WillRepeatedly(Return(file_data.size())); .WillRepeatedly(Return(file_data.size()));
@@ -6038,9 +6060,9 @@ TEST_P(DeviceFilesUsageInfoTest, Retrieve) {
if (index >= 0) { if (index >= 0) {
// Call to Open will return a unique_ptr, freeing this object. // Call to Open will return a unique_ptr, freeing this object.
MockFile* file = new MockFile(); MockFile* file = new MockFile();
EXPECT_CALL(file_system, Exists(StrEq(path))) EXPECT_CALL(file_system, Exists(StrEq(path))).WillOnce(Return(true));
.Times(2) EXPECT_CALL(file_system, Exists(StrEq(path), NotNull()))
.WillRepeatedly(Return(true)); .WillOnce(Return(true));
EXPECT_CALL(file_system, FileSize(StrEq(path))) EXPECT_CALL(file_system, FileSize(StrEq(path)))
.Times(2) .Times(2)
.WillRepeatedly(Return(file_data.size())); .WillRepeatedly(Return(file_data.size()));
@@ -6101,9 +6123,9 @@ TEST_P(DeviceFilesUsageInfoTest, ListKeySetIds) {
if (index >= 0) { if (index >= 0) {
// Call to Open will return a unique_ptr, freeing this object. // Call to Open will return a unique_ptr, freeing this object.
MockFile* file = new MockFile(); MockFile* file = new MockFile();
EXPECT_CALL(file_system, Exists(StrEq(path))) EXPECT_CALL(file_system, Exists(StrEq(path))).WillOnce(Return(true));
.Times(2) EXPECT_CALL(file_system, Exists(StrEq(path), NotNull()))
.WillRepeatedly(Return(true)); .WillOnce(Return(true));
EXPECT_CALL(file_system, FileSize(StrEq(path))) EXPECT_CALL(file_system, FileSize(StrEq(path)))
.Times(2) .Times(2)
.WillRepeatedly(Return(file_data.size())); .WillRepeatedly(Return(file_data.size()));
@@ -6153,9 +6175,9 @@ TEST_P(DeviceFilesUsageInfoTest, ListProviderSessionTokenIds) {
if (index >= 0) { if (index >= 0) {
// Call to Open will return a unique_ptr, freeing this object. // Call to Open will return a unique_ptr, freeing this object.
MockFile* file = new MockFile(); MockFile* file = new MockFile();
EXPECT_CALL(file_system, Exists(StrEq(path))) EXPECT_CALL(file_system, Exists(StrEq(path))).WillOnce(Return(true));
.Times(2) EXPECT_CALL(file_system, Exists(StrEq(path), NotNull()))
.WillRepeatedly(Return(true)); .WillOnce(Return(true));
EXPECT_CALL(file_system, FileSize(StrEq(path))) EXPECT_CALL(file_system, FileSize(StrEq(path)))
.Times(2) .Times(2)
.WillRepeatedly(Return(file_data.size())); .WillRepeatedly(Return(file_data.size()));
@@ -6215,7 +6237,8 @@ TEST_P(DeviceFilesUsageInfoTest, RetrieveByProviderSessionToken) {
kUsageInfoTestData[index < 0 ? 0 : index] kUsageInfoTestData[index < 0 ? 0 : index]
.usage_data.provider_session_token; .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))) EXPECT_CALL(file_system, FileSize(StrEq(path)))
.WillOnce(Return(file_data.size())); .WillOnce(Return(file_data.size()));
EXPECT_CALL(file_system, Open(StrEq(path), _)) EXPECT_CALL(file_system, Open(StrEq(path), _))
@@ -6299,9 +6322,9 @@ TEST_P(DeviceFilesUsageInfoTest, UpdateUsageInfo) {
(index < 0) ? kEmptyUsageInfoFileData (index < 0) ? kEmptyUsageInfoFileData
: kUsageInfoTestData[max_index_by_app_id].file_data; : kUsageInfoTestData[max_index_by_app_id].file_data;
EXPECT_CALL(file_system, Exists(StrEq(path))) EXPECT_CALL(file_system, Exists(StrEq(path))).WillOnce(Return(true));
.Times(2) EXPECT_CALL(file_system, Exists(StrEq(path), NotNull()))
.WillRepeatedly(Return(true)); .WillOnce(Return(true));
EXPECT_CALL(file_system, FileSize(StrEq(path))) EXPECT_CALL(file_system, FileSize(StrEq(path)))
.WillOnce(Return(file_data.size())); .WillOnce(Return(file_data.size()));
EXPECT_CALL(*file, Read(NotNull(), Eq(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 + std::string path = device_base_path_ + param->key_set_id +
DeviceFiles::GetHlsAttributesFileNameExtension(); 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))) EXPECT_CALL(file_system, FileSize(StrEq(path)))
.WillRepeatedly(Return(param->file_data.size())); .WillRepeatedly(Return(param->file_data.size()));
EXPECT_CALL(file_system, Open(StrEq(path), _)) EXPECT_CALL(file_system, Open(StrEq(path), _))
@@ -6452,7 +6476,8 @@ TEST_P(DeviceFilesUsageTableTest, Read) {
std::string path = device_base_path_ + DeviceFiles::GetUsageTableFileName(); std::string path = device_base_path_ + DeviceFiles::GetUsageTableFileName();
const std::string& file_data = kUsageTableInfoTestData[index].file_data; 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))) EXPECT_CALL(file_system, FileSize(StrEq(path)))
.WillRepeatedly(Return(file_data.size())); .WillRepeatedly(Return(file_data.size()));
EXPECT_CALL(file_system, Open(StrEq(path), _)) EXPECT_CALL(file_system, Open(StrEq(path), _))
@@ -6505,7 +6530,8 @@ TEST_F(DeviceFilesUsageTableTest, ReadWithoutLruData) {
const std::string path = const std::string path =
device_base_path_ + DeviceFiles::GetUsageTableFileName(); device_base_path_ + DeviceFiles::GetUsageTableFileName();
MockFileSystem file_system; 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))) EXPECT_CALL(file_system, FileSize(StrEq(path)))
.WillRepeatedly(Return(kUsageTableWithoutLruData.size())); .WillRepeatedly(Return(kUsageTableWithoutLruData.size()));
EXPECT_CALL(file_system, Open(StrEq(path), _)) EXPECT_CALL(file_system, Open(StrEq(path), _))
@@ -6619,7 +6645,7 @@ TEST_F(DeviceFilesTest, RetrieveOemCertificateSuccess) {
device_base_path_ + wvutil::kOemCertificateFileName; device_base_path_ + wvutil::kOemCertificateFileName;
// Call to Open will return a unique_ptr, freeing this object. // Call to Open will return a unique_ptr, freeing this object.
MockFile* read_file = new MockFile(); 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)) .Times(AtLeast(1))
.WillRepeatedly(Return(true)); .WillRepeatedly(Return(true));
EXPECT_CALL(file_system, FileSize(StrEq(device_certificate_path))) EXPECT_CALL(file_system, FileSize(StrEq(device_certificate_path)))
@@ -6650,7 +6676,7 @@ TEST_F(DeviceFilesTest, RetrieveOemCertificateRandomCertFail) {
std::string ramdom_cert = "random_cert"; std::string ramdom_cert = "random_cert";
// Call to Open will return a unique_ptr, freeing this object. // Call to Open will return a unique_ptr, freeing this object.
MockFile* read_file = new MockFile(); 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)) .Times(AtLeast(1))
.WillRepeatedly(Return(true)); .WillRepeatedly(Return(true));
EXPECT_CALL(file_system, FileSize(StrEq(device_certificate_path))) EXPECT_CALL(file_system, FileSize(StrEq(device_certificate_path)))
@@ -6676,9 +6702,10 @@ TEST_F(DeviceFilesTest, RetrieveOemCertificateNotFoundFail) {
MockFileSystem file_system; MockFileSystem file_system;
const std::string device_certificate_path = const std::string device_certificate_path =
device_base_path_ + wvutil::kOemCertificateFileName; 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)) .Times(AtLeast(1))
.WillRepeatedly(Return(false)); .WillRepeatedly(DoAll(SetArgPointee<1>(errno_value), (Return(false))));
DeviceFiles device_files(&file_system); DeviceFiles device_files(&file_system);
EXPECT_TRUE(device_files.Init(kSecurityLevelL1)); EXPECT_TRUE(device_files.Init(kSecurityLevelL1));

View File

@@ -58,6 +58,7 @@ class FileSystem {
virtual std::unique_ptr<File> Open(const std::string& file_path, int flags); virtual std::unique_ptr<File> Open(const std::string& file_path, int flags);
virtual bool Exists(const std::string& file_path); 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 bool Remove(const std::string& file_path);
virtual ssize_t FileSize(const std::string& file_path); virtual ssize_t FileSize(const std::string& file_path);

View File

@@ -16,6 +16,7 @@ bool IsCurrentOrParentDirectory(const char* dir);
class FileUtils { class FileUtils {
public: public:
static bool Exists(const std::string& src); 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 // The caller may only specifying a single wildcard
static bool Remove(const std::string& src); static bool Remove(const std::string& src);
static bool Copy(const std::string& src, const std::string& dest); static bool Copy(const std::string& src, const std::string& dest);

View File

@@ -497,6 +497,11 @@ std::unique_ptr<File> FileSystem::Open(const std::string& file_name,
return std::unique_ptr<File>(new AndroidFile(fd, flags, file_path)); return std::unique_ptr<File>(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) { bool FileSystem::Exists(const std::string& path) {
return FileUtils::Exists(GetFileNameForIdentifier(path, identifier_)); return FileUtils::Exists(GetFileNameForIdentifier(path, identifier_));
} }

View File

@@ -25,11 +25,22 @@ bool IsCurrentOrParentDirectory(const char* dir) {
} }
bool FileUtils::Exists(const std::string& path) { bool FileUtils::Exists(const std::string& path) {
return Exists(path, nullptr);
}
bool FileUtils::Exists(const std::string& path, int* errno_value) {
struct stat buf; struct stat buf;
int error = 0;
int res = stat(path.c_str(), &buf) == 0; int res = stat(path.c_str(), &buf) == 0;
if (!res) { 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; return res;
} }

View File

@@ -39,9 +39,17 @@ class FileTest : public testing::Test {
}; };
TEST_F(FileTest, FileExists) { 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));
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_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));
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)); EXPECT_FALSE(file_system_.Exists(wvcdm::test_vectors::kNonExistentDir));
} }

View File

@@ -98,6 +98,29 @@ TEST_F(FileUtilsTest, IsRegularFile) {
EXPECT_FALSE(FileUtils::IsRegularFile(wvcdm::test_vectors::kTestDir)); 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 = 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) { TEST_F(FileUtilsTest, CopyFile) {
std::string path = wvcdm::test_vectors::kTestDir + kTestFileName; std::string path = wvcdm::test_vectors::kTestDir + kTestFileName;
file_system_.Remove(path); file_system_.Remove(path);