Shaka Player Embedded
file_system_posix.cc
Go to the documentation of this file.
1 // Copyright 2017 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <dirent.h>
16 #include <glog/logging.h>
17 #include <libgen.h>
18 #include <sys/stat.h>
19 #include <unistd.h>
20 
21 #include "src/util/file_system.h"
22 
23 
24 namespace shaka {
25 namespace util {
26 
27 namespace {
28 
29 const char kDirectorySeparator = '/';
30 
31 } // namespace
32 
33 // static
34 std::string FileSystem::PathJoin(const std::string& a, const std::string& b) {
35  if (b.empty())
36  return a;
37  if (a.empty() || b[0] == kDirectorySeparator)
38  return b;
39  if (a[a.size() - 1] == kDirectorySeparator)
40  return a + b;
41  return a + kDirectorySeparator + b;
42 }
43 
44 // static
45 std::string FileSystem::DirName(const std::string& path) {
46  // Create a copy of |path|. Then dirname will edit the string to put a
47  // null char at the last slash. When it returns the argument, the string
48  // constructor will copy the string up to that null char.
49  std::string copy = path;
50  return dirname(&copy[0]);
51 }
52 
53 bool FileSystem::FileExists(const std::string& path) const {
54  // Cannot use fstream for this since it allows opening directories.
55  struct stat info;
56  return stat(path.c_str(), &info) == 0 && S_ISREG(info.st_mode);
57 }
58 
59 bool FileSystem::DirectoryExists(const std::string& path) const {
60  struct stat info;
61  return stat(path.c_str(), &info) == 0 && S_ISDIR(info.st_mode);
62 }
63 
64 bool FileSystem::DeleteFile(const std::string& path) const {
65  return unlink(path.c_str()) == 0;
66 }
67 
68 bool FileSystem::CreateDirectory(const std::string& path) const {
69  std::string::size_type pos = 0;
70  while ((pos = path.find(kDirectorySeparator, pos + 1)) != std::string::npos) {
71  if (mkdir(path.substr(0, pos).c_str(), 0755) != 0 && errno != EEXIST)
72  return false;
73  }
74 
75  return mkdir(path.c_str(), 0755) == 0 || errno == EEXIST;
76 }
77 
78 bool FileSystem::ListFiles(const std::string& path,
79  std::vector<std::string>* files) const {
80  files->clear();
81 
82  DIR* dir;
83  dirent* entry;
84  if ((dir = opendir(path.c_str())) == nullptr) {
85  PLOG(ERROR) << "Unable to open directory '" << path << "'";
86  return false;
87  }
88 
89  while ((entry = readdir(dir)) != nullptr) {
90  if (!strcmp(".", entry->d_name) || !strcmp("..", entry->d_name))
91  continue;
92 
93  const std::string sub_path = PathJoin(path, entry->d_name);
94  struct stat info;
95  CHECK_EQ(0, stat(sub_path.c_str(), &info));
96  if (S_ISREG(info.st_mode))
97  files->push_back(entry->d_name);
98  else if (!S_ISDIR(info.st_mode))
99  LOG(WARNING) << "Unable to process folder entry '" << sub_path << "'";
100  }
101  closedir(dir);
102 
103  return true;
104 }
105 
106 } // namespace util
107 } // namespace shaka
static std::string DirName(const std::string &path)
virtual MUST_USE_RESULT bool DeleteFile(const std::string &path) const
virtual bool FileExists(const std::string &path) const
virtual bool DirectoryExists(const std::string &path) const
static std::string PathJoin(const std::string &a, const std::string &b)
virtual MUST_USE_RESULT bool CreateDirectory(const std::string &path) const
virtual MUST_USE_RESULT bool ListFiles(const std::string &path, std::vector< std::string > *files) const