blob: d1ecc1189030a8731e7c934deb9145832fb2d0f9 [file] [log] [blame]
David Ghandehari9e5b5872016-07-28 09:50:04 -07001// 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 Ghandehari8c5039b2016-08-17 19:39:30 -070021#include "starboard/log.h"
David Ghandehari9e5b5872016-07-28 09:50:04 -070022#include "starboard/time.h"
23#include "starboard/types.h"
24
25#ifdef __cplusplus
26extern "C" {
27#endif
28
29// Private structure representing an open file.
30typedef struct SbFilePrivate SbFilePrivate;
31
32// A handle to an open file.
33typedef 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.
38typedef 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.
57typedef 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.
79typedef enum SbFileWhence {
80 kSbFileFromBegin = 0,
81 kSbFileFromCurrent = 1,
82 kSbFileFromEnd = 2,
83} SbFileWhence;
84
85// Used to hold information about a file.
86typedef 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.
110static 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.
120SB_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.
126SB_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.
132SB_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.
139SB_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.
146SB_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.
151SB_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.
155SB_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.
159SB_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.
164SB_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.
169SB_EXPORT bool SbFileDelete(const char* path);
170
171// Returns whether a file or directory exists at |path|, which must be absolute.
172SB_EXPORT bool SbFileExists(const char* path);
173
174// Returns whether SbFileOpen() with the given |flags| is allowed for |path|,
175// which must be absolute.
176SB_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().
180SB_EXPORT int SbFileModeStringToFlags(const char* mode);
181#ifdef __cplusplus
182} // extern "C"
183#endif
184
David Ghandehari8c5039b2016-08-17 19:39:30 -0700185#ifdef __cplusplus
186namespace 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.
191class 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 Ghandehari9e5b5872016-07-28 09:50:04 -0700241#endif // STARBOARD_FILE_H_