7 #include "packager/file/local_file.h"
15 #include "packager/base/files/file_path.h"
16 #include "packager/base/files/file_util.h"
17 #include "packager/base/logging.h"
25 bool DirectoryExists(
const base::FilePath& path,
int* mode) {
27 DWORD fileattr = GetFileAttributes(path.value().c_str());
28 if (fileattr != INVALID_FILE_ATTRIBUTES)
29 return (fileattr & FILE_ATTRIBUTE_DIRECTORY) != 0;
32 if (stat(path.value().c_str(), &info) != 0)
34 if (S_ISDIR(info.st_mode)) {
35 const int FILE_PERMISSION_MASK = S_IRWXU | S_IRWXG | S_IRWXO;
37 *mode = info.st_mode & FILE_PERMISSION_MASK;
46 bool CreateDirectory(
const base::FilePath& full_path) {
47 std::vector<base::FilePath> subpaths;
50 base::FilePath last_path = full_path;
51 subpaths.push_back(full_path);
52 for (base::FilePath path = full_path.DirName();
53 path.value() != last_path.value(); path = path.DirName()) {
54 subpaths.push_back(path);
65 for (
auto i = subpaths.rbegin(); i != subpaths.rend(); ++i) {
66 if (DirectoryExists(*i, &mode)) {
70 if (::CreateDirectory(i->value().c_str(),
nullptr)) {
74 if (mkdir(i->value().c_str(), mode) == 0) {
83 const auto saved_error_code = ::logging::GetLastSystemErrorCode();
84 if (!DirectoryExists(*i,
nullptr)) {
85 LOG(ERROR) <<
"Failed to create directory " << i->value().c_str()
86 <<
" ErrorCode " << saved_error_code;
96 const char kAdditionalFileMode[] =
"b";
99 :
File(file_name), file_mode_(mode), internal_file_(NULL) {
100 if (file_mode_.find(kAdditionalFileMode) == std::string::npos)
101 file_mode_ += kAdditionalFileMode;
106 if (internal_file_) {
107 result = base::CloseFile(internal_file_);
108 internal_file_ = NULL;
115 DCHECK(buffer != NULL);
116 DCHECK(internal_file_ != NULL);
117 size_t bytes_read = fread(buffer,
sizeof(
char), length, internal_file_);
118 VLOG(2) <<
"Read " << length <<
" return " << bytes_read <<
" error "
119 << ferror(internal_file_);
120 if (bytes_read == 0 && ferror(internal_file_) != 0) {
127 DCHECK(buffer != NULL);
128 DCHECK(internal_file_ != NULL);
129 size_t bytes_written = fwrite(buffer,
sizeof(
char), length, internal_file_);
130 VLOG(2) <<
"Write " << length <<
" return " << bytes_written <<
" error "
131 << ferror(internal_file_);
132 if (bytes_written == 0 && ferror(internal_file_) != 0) {
135 return bytes_written;
139 DCHECK(internal_file_ != NULL);
143 LOG(ERROR) <<
"Cannot flush file.";
148 if (!base::GetFileSize(base::FilePath::FromUTF8Unsafe(
file_name()),
150 LOG(ERROR) <<
"Cannot get file size.";
157 DCHECK(internal_file_ != NULL);
158 return ((fflush(internal_file_) == 0) && !ferror(internal_file_));
163 return _fseeki64(internal_file_,
static_cast<__int64
>(position), SEEK_SET) ==
166 return fseeko(internal_file_, position, SEEK_SET) >= 0;
172 __int64 offset = _ftelli64(internal_file_);
174 off_t offset = ftello(internal_file_);
178 *position =
static_cast<uint64_t
>(offset);
182 LocalFile::~LocalFile() {}
185 base::FilePath file_path(base::FilePath::FromUTF8Unsafe(
file_name()));
188 if (file_mode_.find(
"w") != std::string::npos) {
190 if (!shaka::CreateDirectory(file_path.DirName())) {
195 internal_file_ = base::OpenFile(file_path, file_mode_.c_str());
196 return (internal_file_ != NULL);
200 return base::DeleteFile(base::FilePath::FromUTF8Unsafe(
file_name),
false);
Define an abstract file interface.
const std::string & file_name() const
bool Seek(uint64_t position) override
int64_t Read(void *buffer, uint64_t length) override
LocalFile(const char *file_name, const char *mode)
static bool Delete(const char *file_name)
bool Open() override
Internal open. Should not be used directly.
int64_t Write(const void *buffer, uint64_t length) override
bool Tell(uint64_t *position) override
All the methods that are virtual are virtual for mocking.