David Ghandehari | 9e5b587 | 2016-07-28 09:50:04 -0700 | [diff] [blame] | 1 | // Copyright 2015 Google Inc. All Rights Reserved. |
| 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 | // http://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 | // File system Input/Output |
| 16 | |
| 17 | #ifndef STARBOARD_FILE_H_ |
| 18 | #define STARBOARD_FILE_H_ |
| 19 | |
| 20 | #include "starboard/export.h" |
David Ghandehari | 8c5039b | 2016-08-17 19:39:30 -0700 | [diff] [blame] | 21 | #include "starboard/log.h" |
David Ghandehari | 9e5b587 | 2016-07-28 09:50:04 -0700 | [diff] [blame] | 22 | #include "starboard/time.h" |
| 23 | #include "starboard/types.h" |
| 24 | |
| 25 | #ifdef __cplusplus |
| 26 | extern "C" { |
| 27 | #endif |
| 28 | |
| 29 | // Private structure representing an open file. |
| 30 | typedef struct SbFilePrivate SbFilePrivate; |
| 31 | |
| 32 | // A handle to an open file. |
| 33 | typedef SbFilePrivate* SbFile; |
| 34 | |
| 35 | // kSbFile(Open|Create)(Only|Always|Truncated) are mutually exclusive. You |
| 36 | // should specify exactly one of the five (possibly combining with other flags) |
| 37 | // when opening or creating a file. |
| 38 | typedef enum SbFileFlags { |
| 39 | kSbFileOpenOnly = 1 << 0, // Opens a file, only if it exists. |
| 40 | kSbFileCreateOnly = 1 << 1, // Creates a new file, only if it |
| 41 | // does not already exist. |
| 42 | kSbFileOpenAlways = 1 << 2, // May create a new file. |
| 43 | kSbFileCreateAlways = 1 << 3, // May overwrite an old file. |
| 44 | kSbFileOpenTruncated = 1 << 4, // Opens a file and truncates it |
| 45 | // to zero, only if it exists. |
| 46 | kSbFileRead = 1 << 5, |
| 47 | kSbFileWrite = 1 << 6, |
| 48 | kSbFileAsync = 1 << 7, // May allow asynchronous I/O on some |
| 49 | // platforms, meaning that calls to |
| 50 | // Read or Write will only return the |
| 51 | // data that is readily available. |
| 52 | } SbFileFlags; |
| 53 | |
| 54 | // kSbFileErrorAccessDenied is returned when a call fails because of a |
| 55 | // filesystem restriction. kSbFileErrorSecurity is returned when a security |
| 56 | // policy doesn't allow the operation to be executed. |
| 57 | typedef enum SbFileError { |
| 58 | kSbFileOk = 0, |
| 59 | kSbFileErrorFailed = -1, |
| 60 | kSbFileErrorInUse = -2, |
| 61 | kSbFileErrorExists = -3, |
| 62 | kSbFileErrorNotFound = -4, |
| 63 | kSbFileErrorAccessDenied = -5, |
| 64 | kSbFileErrorTooManyOpened = -6, |
| 65 | kSbFileErrorNoMemory = -7, |
| 66 | kSbFileErrorNoSpace = -8, |
| 67 | kSbFileErrorNotADirectory = -9, |
| 68 | kSbFileErrorInvalidOperation = -10, |
| 69 | kSbFileErrorSecurity = -11, |
| 70 | kSbFileErrorAbort = -12, |
| 71 | kSbFileErrorNotAFile = -13, |
| 72 | kSbFileErrorNotEmpty = -14, |
| 73 | kSbFileErrorInvalidUrl = -15, |
| 74 | // Put new entries here and increment kSbFileErrorMax. |
| 75 | kSbFileErrorMax = -16, |
| 76 | } SbFileError; |
| 77 | |
| 78 | // This explicit mapping matches both FILE_ on Windows and SEEK_ on Linux. |
| 79 | typedef enum SbFileWhence { |
| 80 | kSbFileFromBegin = 0, |
| 81 | kSbFileFromCurrent = 1, |
| 82 | kSbFileFromEnd = 2, |
| 83 | } SbFileWhence; |
| 84 | |
| 85 | // Used to hold information about a file. |
| 86 | typedef struct SbFileInfo { |
| 87 | // The size of the file in bytes. Undefined when is_directory is true. |
| 88 | int64_t size; |
| 89 | |
| 90 | // Whether the file corresponds to a directory. |
| 91 | bool is_directory; |
| 92 | |
| 93 | // Whether the file corresponds to a symbolic link. |
| 94 | bool is_symbolic_link; |
| 95 | |
| 96 | // The last modified time of a file. |
| 97 | SbTime last_modified; |
| 98 | |
| 99 | // The last accessed time of a file. |
| 100 | SbTime last_accessed; |
| 101 | |
| 102 | // The creation time of a file. |
| 103 | SbTime creation_time; |
| 104 | } SbFileInfo; |
| 105 | |
| 106 | // Well-defined value for an invalid file handle. |
| 107 | #define kSbFileInvalid (SbFile) NULL |
| 108 | |
| 109 | // Returns whether the given file handle is valid. |
| 110 | static SB_C_INLINE bool SbFileIsValid(SbFile file) { |
| 111 | return file != kSbFileInvalid; |
| 112 | } |
| 113 | |
| 114 | // Opens the file at |path|, which must be absolute, creating it if specified by |
| 115 | // |flags|. |out_created|, if provided, will be set to true if a new file was |
| 116 | // created (or an old one truncated to zero length to simulate a new file, which |
| 117 | // can happen with kSbFileCreateAlways), and false otherwise. |out_error| can |
| 118 | // be NULL. If creation failed, it will return kSbFileInvalid. The read/write |
| 119 | // position is at the beginning of the file. |
| 120 | SB_EXPORT SbFile SbFileOpen(const char* path, |
| 121 | int flags, |
| 122 | bool* out_created, |
| 123 | SbFileError* out_error); |
| 124 | |
| 125 | // Closes |file|. Returns whether the close was successful. |
| 126 | SB_EXPORT bool SbFileClose(SbFile file); |
| 127 | |
| 128 | // Changes current read/write position in |file| to |offset| relative to the |
| 129 | // origin defined by |whence|. Returns the resultant current read/write position |
| 130 | // in the file (relative to the start) or -1 in case of error. May not support |
| 131 | // seeking past the end of the file on some platforms. |
| 132 | SB_EXPORT int64_t SbFileSeek(SbFile file, SbFileWhence whence, int64_t offset); |
| 133 | |
| 134 | // Reads |size| bytes (or until EOF is reached) from |file| into |data|, |
| 135 | // starting at the file's current position. Returns the number of bytes read, or |
| 136 | // -1 on error. Note that this function does NOT make a best effort to read all |
| 137 | // data on all platforms, it just reads however many bytes are quickly |
| 138 | // available. Can be run in a loop to make it a best-effort read. |
| 139 | SB_EXPORT int SbFileRead(SbFile file, char* data, int size); |
| 140 | |
| 141 | // Writes the given buffer into |file| at the file's current position, |
| 142 | // overwritting any data that was previously there. Returns the number of bytes |
| 143 | // written, or -1 on error. Note that this function does NOT make a best effort |
| 144 | // to write all data, it writes however many bytes can be written quickly. It |
| 145 | // should be run in a loop to ensure all data is written. |
| 146 | SB_EXPORT int SbFileWrite(SbFile file, const char* data, int size); |
| 147 | |
| 148 | // Truncates the given |file| to the given |length|. If length is greater than |
| 149 | // the current size of the file, the file is extended with zeros. Negative |
| 150 | // |length| will do nothing and return false. |
| 151 | SB_EXPORT bool SbFileTruncate(SbFile file, int64_t length); |
| 152 | |
| 153 | // Flushes the write buffer to |file|. Data written via SbFileWrite isn't |
| 154 | // necessarily comitted right away until the file is flushed or closed. |
| 155 | SB_EXPORT bool SbFileFlush(SbFile file); |
| 156 | |
| 157 | // Places some information about |file|, an open SbFile, in |out_info|. Returns |
| 158 | // |true| if successful. If unsuccessful, |out_info| is untouched. |
| 159 | SB_EXPORT bool SbFileGetInfo(SbFile file, SbFileInfo* out_info); |
| 160 | |
| 161 | // Places information about the file or directory at |path|, which must be |
| 162 | // absolute, into |out_info|. Returns |true| if successful. If unsuccessful, |
| 163 | // |out_info| is untouched. |
| 164 | SB_EXPORT bool SbFileGetPathInfo(const char* path, SbFileInfo* out_info); |
| 165 | |
| 166 | // Deletes the regular file, symlink, or empty directory at |path|, which must |
| 167 | // be absolute. Used mainly to clean up after unit tests. May fail on some |
| 168 | // platforms if the file in question is being held open. |
| 169 | SB_EXPORT bool SbFileDelete(const char* path); |
| 170 | |
| 171 | // Returns whether a file or directory exists at |path|, which must be absolute. |
| 172 | SB_EXPORT bool SbFileExists(const char* path); |
| 173 | |
| 174 | // Returns whether SbFileOpen() with the given |flags| is allowed for |path|, |
| 175 | // which must be absolute. |
| 176 | SB_EXPORT bool SbFileCanOpen(const char* path, int flags); |
| 177 | |
| 178 | // Converts an ISO fopen() mode string into flags that can be equivalently |
| 179 | // passed into SbFileOpen(). |
| 180 | SB_EXPORT int SbFileModeStringToFlags(const char* mode); |
| 181 | #ifdef __cplusplus |
| 182 | } // extern "C" |
| 183 | #endif |
| 184 | |
David Ghandehari | 8c5039b | 2016-08-17 19:39:30 -0700 | [diff] [blame] | 185 | #ifdef __cplusplus |
| 186 | namespace starboard { |
| 187 | |
| 188 | // A class that opens an SbFile in its constructor and closes it in its |
| 189 | // destructor, so the file is open for the lifetime of the object. Member |
| 190 | // functions call the corresponding SbFile function. |
| 191 | class ScopedFile { |
| 192 | public: |
| 193 | ScopedFile(const char* path, |
| 194 | int flags, |
| 195 | bool* out_created, |
| 196 | SbFileError* out_error) |
| 197 | : file_(kSbFileInvalid) { |
| 198 | file_ = SbFileOpen(path, flags, out_created, out_error); |
| 199 | } |
| 200 | |
| 201 | ScopedFile(const char* path, int flags, bool* out_created) |
| 202 | : file_(kSbFileInvalid) { |
| 203 | file_ = SbFileOpen(path, flags, out_created, NULL); |
| 204 | } |
| 205 | |
| 206 | ScopedFile(const char* path, int flags) : file_(kSbFileInvalid) { |
| 207 | file_ = SbFileOpen(path, flags, NULL, NULL); |
| 208 | } |
| 209 | |
| 210 | ~ScopedFile() { SbFileClose(file_); } |
| 211 | |
| 212 | SbFile file() const { return file_; } |
| 213 | |
| 214 | bool IsValid() const { return SbFileIsValid(file_); } |
| 215 | |
| 216 | int64_t Seek(SbFileWhence whence, int64_t offset) const { |
| 217 | return SbFileSeek(file_, whence, offset); |
| 218 | } |
| 219 | |
| 220 | int Read(char* data, int size) const { return SbFileRead(file_, data, size); } |
| 221 | |
| 222 | int Write(const char* data, int size) const { |
| 223 | return SbFileWrite(file_, data, size); |
| 224 | } |
| 225 | |
| 226 | bool Truncate(int64_t length) const { return SbFileTruncate(file_, length); } |
| 227 | |
| 228 | bool Flush() const { return SbFileFlush(file_); } |
| 229 | |
| 230 | bool GetInfo(SbFileInfo* out_info) const { |
| 231 | return SbFileGetInfo(file_, out_info); |
| 232 | } |
| 233 | |
| 234 | private: |
| 235 | SbFile file_; |
| 236 | }; |
| 237 | |
| 238 | } // namespace starboard |
| 239 | #endif // ifdef __cplusplus |
| 240 | |
David Ghandehari | 9e5b587 | 2016-07-28 09:50:04 -0700 | [diff] [blame] | 241 | #endif // STARBOARD_FILE_H_ |