SkOSFile_posix.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. /*
  2. * Copyright 2013 Google Inc.
  3. *
  4. * Use of this source code is governed by a BSD-style license that can be
  5. * found in the LICENSE file.
  6. */
  7. #include "include/core/SkString.h"
  8. #include "include/core/SkTypes.h"
  9. #include "include/private/SkTFitsIn.h"
  10. #include "include/private/SkTemplates.h"
  11. #include "src/core/SkOSFile.h"
  12. #include <dirent.h>
  13. #include <new>
  14. #include <stdio.h>
  15. #include <string.h>
  16. #include <sys/mman.h>
  17. #include <sys/stat.h>
  18. #include <sys/types.h>
  19. #include <unistd.h>
  20. #ifdef SK_BUILD_FOR_IOS
  21. #include "src/ports/SkOSFile_ios.h"
  22. #endif
  23. bool sk_exists(const char *path, SkFILE_Flags flags) {
  24. int mode = F_OK;
  25. if (flags & kRead_SkFILE_Flag) {
  26. mode |= R_OK;
  27. }
  28. if (flags & kWrite_SkFILE_Flag) {
  29. mode |= W_OK;
  30. }
  31. #ifdef SK_BUILD_FOR_IOS
  32. // if the default path fails, check the bundle (but only if read-only)
  33. if (0 == access(path, mode)) {
  34. return true;
  35. } else {
  36. return (kRead_SkFILE_Flag == flags && ios_get_path_in_bundle(path, nullptr));
  37. }
  38. #else
  39. return (0 == access(path, mode));
  40. #endif
  41. }
  42. typedef struct {
  43. dev_t dev;
  44. ino_t ino;
  45. } SkFILEID;
  46. static bool sk_ino(FILE* a, SkFILEID* id) {
  47. int fd = fileno(a);
  48. if (fd < 0) {
  49. return 0;
  50. }
  51. struct stat status;
  52. if (0 != fstat(fd, &status)) {
  53. return 0;
  54. }
  55. id->dev = status.st_dev;
  56. id->ino = status.st_ino;
  57. return true;
  58. }
  59. bool sk_fidentical(FILE* a, FILE* b) {
  60. SkFILEID aID, bID;
  61. return sk_ino(a, &aID) && sk_ino(b, &bID)
  62. && aID.ino == bID.ino
  63. && aID.dev == bID.dev;
  64. }
  65. void sk_fmunmap(const void* addr, size_t length) {
  66. munmap(const_cast<void*>(addr), length);
  67. }
  68. void* sk_fdmmap(int fd, size_t* size) {
  69. struct stat status;
  70. if (0 != fstat(fd, &status)) {
  71. return nullptr;
  72. }
  73. if (!S_ISREG(status.st_mode)) {
  74. return nullptr;
  75. }
  76. if (!SkTFitsIn<size_t>(status.st_size)) {
  77. return nullptr;
  78. }
  79. size_t fileSize = static_cast<size_t>(status.st_size);
  80. void* addr = mmap(nullptr, fileSize, PROT_READ, MAP_PRIVATE, fd, 0);
  81. if (MAP_FAILED == addr) {
  82. return nullptr;
  83. }
  84. *size = fileSize;
  85. return addr;
  86. }
  87. int sk_fileno(FILE* f) {
  88. return fileno(f);
  89. }
  90. void* sk_fmmap(FILE* f, size_t* size) {
  91. int fd = sk_fileno(f);
  92. if (fd < 0) {
  93. return nullptr;
  94. }
  95. return sk_fdmmap(fd, size);
  96. }
  97. size_t sk_qread(FILE* file, void* buffer, size_t count, size_t offset) {
  98. int fd = sk_fileno(file);
  99. if (fd < 0) {
  100. return SIZE_MAX;
  101. }
  102. ssize_t bytesRead = pread(fd, buffer, count, offset);
  103. if (bytesRead < 0) {
  104. return SIZE_MAX;
  105. }
  106. return bytesRead;
  107. }
  108. ////////////////////////////////////////////////////////////////////////////
  109. struct SkOSFileIterData {
  110. SkOSFileIterData() : fDIR(nullptr) { }
  111. DIR* fDIR;
  112. SkString fPath, fSuffix;
  113. };
  114. static_assert(sizeof(SkOSFileIterData) <= SkOSFile::Iter::kStorageSize, "not_enough_space");
  115. SkOSFile::Iter::Iter() { new (fSelf.get()) SkOSFileIterData; }
  116. SkOSFile::Iter::Iter(const char path[], const char suffix[]) {
  117. new (fSelf.get()) SkOSFileIterData;
  118. this->reset(path, suffix);
  119. }
  120. SkOSFile::Iter::~Iter() {
  121. SkOSFileIterData& self = *static_cast<SkOSFileIterData*>(fSelf.get());
  122. if (self.fDIR) {
  123. ::closedir(self.fDIR);
  124. }
  125. self.~SkOSFileIterData();
  126. }
  127. void SkOSFile::Iter::reset(const char path[], const char suffix[]) {
  128. SkOSFileIterData& self = *static_cast<SkOSFileIterData*>(fSelf.get());
  129. if (self.fDIR) {
  130. ::closedir(self.fDIR);
  131. self.fDIR = nullptr;
  132. }
  133. self.fPath.set(path);
  134. if (path) {
  135. self.fDIR = ::opendir(path);
  136. #ifdef SK_BUILD_FOR_IOS
  137. // check bundle for directory
  138. if (!self.fDIR && ios_get_path_in_bundle(path, &self.fPath)) {
  139. self.fDIR = ::opendir(self.fPath.c_str());
  140. }
  141. #endif
  142. self.fSuffix.set(suffix);
  143. } else {
  144. self.fSuffix.reset();
  145. }
  146. }
  147. // returns true if suffix is empty, or if str ends with suffix
  148. static bool issuffixfor(const SkString& suffix, const char str[]) {
  149. size_t suffixLen = suffix.size();
  150. size_t strLen = strlen(str);
  151. return strLen >= suffixLen &&
  152. memcmp(suffix.c_str(), str + strLen - suffixLen, suffixLen) == 0;
  153. }
  154. bool SkOSFile::Iter::next(SkString* name, bool getDir) {
  155. SkOSFileIterData& self = *static_cast<SkOSFileIterData*>(fSelf.get());
  156. if (self.fDIR) {
  157. dirent* entry;
  158. while ((entry = ::readdir(self.fDIR)) != nullptr) {
  159. struct stat s;
  160. SkString str(self.fPath);
  161. if (!str.endsWith("/") && !str.endsWith("\\")) {
  162. str.append("/");
  163. }
  164. str.append(entry->d_name);
  165. if (0 == stat(str.c_str(), &s)) {
  166. if (getDir) {
  167. if (s.st_mode & S_IFDIR) {
  168. break;
  169. }
  170. } else {
  171. if (!(s.st_mode & S_IFDIR) && issuffixfor(self.fSuffix, entry->d_name)) {
  172. break;
  173. }
  174. }
  175. }
  176. }
  177. if (entry) { // we broke out with a file
  178. if (name) {
  179. name->set(entry->d_name);
  180. }
  181. return true;
  182. }
  183. }
  184. return false;
  185. }