2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
17 #ifndef incl_HPHP_FILE_H_
18 #define incl_HPHP_FILE_H_
20 #include "hphp/runtime/base/execution-context.h"
21 #include "hphp/runtime/base/req-list.h"
22 #include "hphp/runtime/base/request-event-handler.h"
23 #include "hphp/runtime/base/req-ptr.h"
24 #include "hphp/runtime/base/type-array.h"
25 #include "hphp/runtime/base/type-resource.h"
26 #include "hphp/runtime/base/type-string.h"
27 #include "hphp/runtime/base/type-variant.h"
29 #include "hphp/util/rds-local.h"
34 ///////////////////////////////////////////////////////////////////////////////
38 extern RDS_LOCAL(int, s_pcloseRet
);
40 // This structure holds the request allocated data members of File. The
41 // purpose of the class is to allow File (and subclasses) to be managed by
42 // the request heap while also allowing their underlying OS handles to be
43 // persisted beyond the lifetime of a request.
45 // The FileData is stored in a shared_ptr and managed by new/delete, so it is
46 // safe to store in an object whose lifetime is longer than a request.
47 // A File (or subclass) can be reconstructed using a shared_ptr to a FileData.
48 // Note that subclasses of File that need to be persisted must subclass
49 // FileData to add any persistent data members, e.g. see Socket.
50 // Classes in the FileData hierarchy may not contain request-allocated data.
52 static const int DEFAULT_CHUNK_SIZE
;
55 explicit FileData(bool nonblocking
);
56 virtual bool closeImpl();
60 bool valid() const { return m_fd
>= 0;}
61 bool isClosed() const { return m_closed
; }
62 void setIsClosed(bool closed
) { m_closed
= closed
; }
63 void setFd(int fd
) { m_fd
= fd
; }
64 int getFd() { return m_fd
; }
68 friend struct PhpStreamWrapper
;
69 int m_fd
{-1}; // file descriptor
70 bool m_isLocal
{false}; // is this on the local disk?
71 bool m_closed
{false}; // whether close() was called
72 const bool m_nonblocking
{true};
74 // fields useful for both reads and writes
76 int64_t m_position
{0}; // the current cursor position
78 // fields only useful for buffered reads
79 int64_t m_writepos
{0}; // where we have read from lower level
80 int64_t m_readpos
{0}; // where we have given to upper level
85 char *m_buffer
{nullptr};
86 int64_t m_bufferSize
{0};
87 int64_t m_chunkSize
{DEFAULT_CHUNK_SIZE
};
91 * This is PHP's "stream", base class of plain file, gzipped file, directory
92 * and sockets. We are not going to structure directories this way at all,
93 * but we will have PlainFile, ZipFile and Socket derive from this base class,
94 * so they can share some minimal functionalities.
96 struct File
: SweepableResourceData
{
97 static String
TranslatePath(const String
& filename
);
98 // Same as TranslatePath except doesn't make paths absolute
99 static String
TranslatePathKeepRelative(const char* fn
, uint32_t len
);
100 static String
TranslatePathKeepRelative(const String
& filename
) {
101 return TranslatePathKeepRelative(filename
.c_str(), filename
.size());
103 static String
TranslatePathKeepRelative(const std::string
& filename
) {
104 return TranslatePathKeepRelative(filename
.c_str(), filename
.size());
106 // Same as TranslatePath except checks the file cache on miss
107 static String
TranslatePathWithFileCache(const String
& filename
);
108 static String
TranslateCommand(const String
& cmd
);
109 static req::ptr
<File
> Open(
110 const String
& filename
, const String
& mode
,
111 int options
= 0, const req::ptr
<StreamContext
>& context
= nullptr);
113 static bool IsVirtualDirectory(const String
& filename
);
114 static bool IsVirtualFile(const String
& filename
);
115 static bool IsPlainFilePath(const String
& filename
) {
116 return filename
.find("://") == String::npos
;
119 static const int USE_INCLUDE_PATH
;
121 explicit File(bool nonblocking
= true,
122 const String
& wrapper_type
= null_string
,
123 const String
& stream_type
= empty_string_ref
);
126 static StaticString
& classnameof() {
127 static StaticString
result("File");
130 static StaticString s_resource_name
;
132 // overriding ResourceData
133 const String
& o_getClassNameHook() const override
{ return classnameof(); }
134 const String
& o_getResourceName() const override
;
135 bool isInvalid() const override
{ return m_data
->m_closed
; }
137 virtual int fd() const { return m_data
->m_fd
;}
138 bool valid() const { return m_data
&& m_data
->m_fd
>= 0; }
139 std::string
getName() const { return m_data
->m_name
;}
141 virtual bool setBlocking(bool mode
);
142 virtual bool setTimeout(uint64_t usecs
);
145 * How to open this type of file.
147 virtual bool open(const String
& filename
, const String
& mode
) = 0;
149 virtual bool close() = 0;
150 virtual bool isClosed() const { return !m_data
|| m_data
->m_closed
; }
153 * - read() when fetching data to return to PHP
154 * - readImpl() when you want raw unbuffered data; for example, if you use
155 * the Socket class to implement a network-based extension, use readImpl
156 * to avoid the internal buffer, and so on
160 * Read one chunk of input. Returns a null string on failure or eof.
162 virtual int64_t readImpl(char *buffer
, int64_t length
) = 0;
164 virtual String
read(int64_t length
);
165 virtual String
read();
168 * - write() in response to a PHP code that is documented as writing to a
170 * - writeImpl() if you want C-like behavior, instead of PHP-like behavior;
171 * for example, if you write a network-based extension using Socket
175 * Write one chunk of output. Returns bytes written.
177 virtual int64_t writeImpl(const char *buffer
, int64_t length
) = 0;
178 virtual int64_t write(const String
& str
, int64_t length
= 0);
182 * Optional virtual functions to implement.
184 virtual bool seekable() { return false;}
185 virtual bool seek(int64_t offset
, int whence
= SEEK_SET
);
186 virtual int64_t tell();
188 virtual bool rewind();
189 virtual bool flush();
190 virtual bool truncate(int64_t size
);
191 virtual bool lock(int operation
);
192 virtual bool lock(int operation
, bool &wouldblock
);
193 virtual bool stat(struct stat
*sb
);
195 virtual Object
await(uint16_t events
, double timeout
);
197 virtual Array
getMetaData();
198 virtual Variant
getWrapperMetaData() { return Variant(); }
199 String
getWrapperType() const;
200 String
getStreamType() const { return String
{m_streamType
}; }
201 const req::ptr
<StreamContext
>& getStreamContext() { return m_streamContext
; }
202 void setStreamContext(const req::ptr
<StreamContext
>& context
) {
203 m_streamContext
= context
;
205 int64_t bufferedLen() { return m_data
->m_writepos
- m_data
->m_readpos
; }
207 std::string
getMode() { return m_data
->m_mode
; }
210 * Read one line a time. Returns a null string on failure or eof.
212 String
readLine(int64_t maxlen
= 0);
215 * Read one record a time. Returns a false on failure or eof.
217 Variant
readRecord(const String
& delimiter
, int64_t maxlen
= 0);
220 * Read entire file and print it out.
225 * Write to file with specified format and arguments.
227 int64_t printf(const String
& format
, const Array
& args
);
230 * Get the Chunk Size.
232 int64_t getChunkSize() const;
235 * Set the Chunk Size.
237 void setChunkSize(int64_t chunk_size
);
240 * Write one line of csv record.
242 int64_t writeCSV(const Array
& fields
, char delimiter
= ',',
243 char enclosure
= '"', char escape_char
= '\\');
246 * Read one line of csv record.
248 Array
readCSV(int64_t length
= 0, char delimiter
= ',', char enclosure
= '"',
249 char escape
= '\\', const String
* initial
= nullptr);
252 * Return the last error we know about
254 String
getLastError();
256 bool isLocal() const { return m_data
->m_isLocal
; }
258 std::shared_ptr
<FileData
> getData() const { return m_data
; }
262 void sweep() override
;
264 void setIsLocal(bool isLocal
) { m_data
->m_isLocal
= isLocal
; }
265 void setIsClosed(bool closed
) { m_data
->m_closed
= closed
; }
267 bool getEof() const { return m_data
->m_eof
; }
268 void setEof(bool eof
) { m_data
->m_eof
= eof
; }
270 int64_t getPosition() const { return m_data
->m_position
; }
271 void setPosition(int64_t pos
) { m_data
->m_position
= pos
; }
273 int64_t getWritePosition() const { return m_data
->m_writepos
; }
274 void setWritePosition(int64_t wpos
) { m_data
->m_writepos
= wpos
; }
276 int64_t getReadPosition() const { return m_data
->m_readpos
; }
277 void setReadPosition(int64_t rpos
) { m_data
->m_readpos
= rpos
; }
279 int getFd() const { return m_data
->m_fd
; }
280 void setFd(int fd
) { m_data
->m_fd
= fd
; }
282 void setName(std::string name
) { m_data
->m_name
= name
; }
284 void setStreamType(const StaticString
& streamType
) {
285 m_streamType
= streamType
.get();
288 FileData
* getFileData() { return m_data
.get(); }
289 const FileData
* getFileData() const { return m_data
.get(); }
292 explicit File(std::shared_ptr
<FileData
> data
,
293 const String
& wrapper_type
= null_string
,
294 const String
& stream_type
= empty_string_ref
);
297 std::shared_ptr
<FileData
> m_data
;
298 StringData
* m_wrapperType
;
299 StringData
* m_streamType
;
300 req::ptr
<StreamContext
> m_streamContext
;
303 ///////////////////////////////////////////////////////////////////////////////
306 #endif // incl_HPHP_FILE_H_