Shaka Packager SDK
local_file.cc
1 // Copyright 2014 Google Inc. All rights reserved.
2 //
3 // Use of this source code is governed by a BSD-style
4 // license that can be found in the LICENSE file or at
5 // https://developers.google.com/open-source/licenses/bsd
6 
7 #include "packager/file/local_file.h"
8 
9 #include <stdio.h>
10 #if defined(OS_WIN)
11 #include <windows.h>
12 #endif // defined(OS_WIN)
13 #include "packager/base/files/file_util.h"
14 #include "packager/base/logging.h"
15 
16 namespace shaka {
17 
18 // Always open files in binary mode.
19 const char kAdditionalFileMode[] = "b";
20 
21 LocalFile::LocalFile(const char* file_name, const char* mode)
22  : File(file_name), file_mode_(mode), internal_file_(NULL) {
23  if (file_mode_.find(kAdditionalFileMode) == std::string::npos)
24  file_mode_ += kAdditionalFileMode;
25 }
26 
28  bool result = true;
29  if (internal_file_) {
30  result = base::CloseFile(internal_file_);
31  internal_file_ = NULL;
32  }
33  delete this;
34  return result;
35 }
36 
37 int64_t LocalFile::Read(void* buffer, uint64_t length) {
38  DCHECK(buffer != NULL);
39  DCHECK(internal_file_ != NULL);
40  size_t bytes_read = fread(buffer, sizeof(char), length, internal_file_);
41  VLOG(2) << "Read " << length << " return " << bytes_read << " error "
42  << ferror(internal_file_);
43  if (bytes_read == 0 && ferror(internal_file_) != 0) {
44  return -1;
45  }
46  return bytes_read;
47 }
48 
49 int64_t LocalFile::Write(const void* buffer, uint64_t length) {
50  DCHECK(buffer != NULL);
51  DCHECK(internal_file_ != NULL);
52  size_t bytes_written = fwrite(buffer, sizeof(char), length, internal_file_);
53  VLOG(2) << "Write " << length << " return " << bytes_written << " error "
54  << ferror(internal_file_);
55  if (bytes_written == 0 && ferror(internal_file_) != 0) {
56  return -1;
57  }
58  return bytes_written;
59 }
60 
61 int64_t LocalFile::Size() {
62  DCHECK(internal_file_ != NULL);
63 
64  // Flush any buffered data, so we get the true file size.
65  if (!Flush()) {
66  LOG(ERROR) << "Cannot flush file.";
67  return -1;
68  }
69 
70  int64_t file_size;
71  if (!base::GetFileSize(base::FilePath::FromUTF8Unsafe(file_name()),
72  &file_size)) {
73  LOG(ERROR) << "Cannot get file size.";
74  return -1;
75  }
76  return file_size;
77 }
78 
80  DCHECK(internal_file_ != NULL);
81  return ((fflush(internal_file_) == 0) && !ferror(internal_file_));
82 }
83 
84 bool LocalFile::Seek(uint64_t position) {
85 #if defined(OS_WIN)
86  return _fseeki64(internal_file_, static_cast<__int64>(position), SEEK_SET) ==
87  0;
88 #else
89  return fseeko(internal_file_, position, SEEK_SET) >= 0;
90 #endif // !defined(OS_WIN)
91 }
92 
93 bool LocalFile::Tell(uint64_t* position) {
94 #if defined(OS_WIN)
95  __int64 offset = _ftelli64(internal_file_);
96 #else
97  off_t offset = ftello(internal_file_);
98 #endif // !defined(OS_WIN)
99  if (offset < 0)
100  return false;
101  *position = static_cast<uint64_t>(offset);
102  return true;
103 }
104 
105 LocalFile::~LocalFile() {}
106 
108  base::FilePath file_path(base::FilePath::FromUTF8Unsafe(file_name()));
109 
110  // Create upper level directories for write mode.
111  if (file_mode_.find("w") != std::string::npos) {
112  base::File::Error error;
113  // The function returns success if the directories already exist.
114  if (!base::CreateDirectoryAndGetError(file_path.DirName(), &error)) {
115  LOG(ERROR) << "Failed to create directories for file '"
116  << file_path.AsUTF8Unsafe()
117  << "'. Error: " << base::File::ErrorToString(error);
118  return false;
119  }
120  }
121 
122  internal_file_ = base::OpenFile(file_path, file_mode_.c_str());
123  return (internal_file_ != NULL);
124 }
125 
126 bool LocalFile::Delete(const char* file_name) {
127  return base::DeleteFile(base::FilePath::FromUTF8Unsafe(file_name), false);
128 }
129 
130 } // namespace shaka
bool Close() override
Definition: local_file.cc:27
bool Seek(uint64_t position) override
Definition: local_file.cc:84
bool Flush() override
Definition: local_file.cc:79
Define an abstract file interface.
Definition: file.h:26
const std::string & file_name() const
Definition: file.h:94
All the methods that are virtual are virtual for mocking.
int64_t Size() override
Definition: local_file.cc:61
static bool Delete(const char *file_name)
Definition: local_file.cc:126
int64_t Read(void *buffer, uint64_t length) override
Definition: local_file.cc:37
bool Open() override
Internal open. Should not be used directly.
Definition: local_file.cc:107
int64_t Write(const void *buffer, uint64_t length) override
Definition: local_file.cc:49
bool Tell(uint64_t *position) override
Definition: local_file.cc:93
LocalFile(const char *file_name, const char *mode)
Definition: local_file.cc:21