1*1a96fba6SXin Li // Copyright 2015 The Chromium OS Authors. All rights reserved.
2*1a96fba6SXin Li // Use of this source code is governed by a BSD-style license that can be
3*1a96fba6SXin Li // found in the LICENSE file.
4*1a96fba6SXin Li
5*1a96fba6SXin Li #include <brillo/streams/file_stream.h>
6*1a96fba6SXin Li
7*1a96fba6SXin Li #include <fcntl.h>
8*1a96fba6SXin Li #include <sys/stat.h>
9*1a96fba6SXin Li #include <unistd.h>
10*1a96fba6SXin Li
11*1a96fba6SXin Li #include <algorithm>
12*1a96fba6SXin Li #include <utility>
13*1a96fba6SXin Li
14*1a96fba6SXin Li #include <base/bind.h>
15*1a96fba6SXin Li #include <base/files/file_descriptor_watcher_posix.h>
16*1a96fba6SXin Li #include <base/files/file_util.h>
17*1a96fba6SXin Li #include <base/posix/eintr_wrapper.h>
18*1a96fba6SXin Li #include <brillo/errors/error_codes.h>
19*1a96fba6SXin Li #include <brillo/message_loops/message_loop.h>
20*1a96fba6SXin Li #include <brillo/streams/stream_errors.h>
21*1a96fba6SXin Li #include <brillo/streams/stream_utils.h>
22*1a96fba6SXin Li
23*1a96fba6SXin Li namespace brillo {
24*1a96fba6SXin Li
25*1a96fba6SXin Li // FileDescriptor is a helper class that serves two purposes:
26*1a96fba6SXin Li // 1. It wraps low-level system APIs (as FileDescriptorInterface) to allow
27*1a96fba6SXin Li // mocking calls to them in tests.
28*1a96fba6SXin Li // 2. It provides file descriptor watching services using FileDescriptorWatcher
29*1a96fba6SXin Li // and MessageLoopForIO::Watcher interface.
30*1a96fba6SXin Li // The real FileStream uses this class to perform actual file I/O on the
31*1a96fba6SXin Li // contained file descriptor.
32*1a96fba6SXin Li class FileDescriptor : public FileStream::FileDescriptorInterface {
33*1a96fba6SXin Li public:
FileDescriptor(int fd,bool own)34*1a96fba6SXin Li FileDescriptor(int fd, bool own) : fd_{fd}, own_{own} {}
~FileDescriptor()35*1a96fba6SXin Li ~FileDescriptor() override {
36*1a96fba6SXin Li if (IsOpen()) {
37*1a96fba6SXin Li Close();
38*1a96fba6SXin Li }
39*1a96fba6SXin Li }
40*1a96fba6SXin Li
41*1a96fba6SXin Li // Overrides for FileStream::FileDescriptorInterface methods.
IsOpen() const42*1a96fba6SXin Li bool IsOpen() const override { return fd_ >= 0; }
43*1a96fba6SXin Li
Read(void * buf,size_t nbyte)44*1a96fba6SXin Li ssize_t Read(void* buf, size_t nbyte) override {
45*1a96fba6SXin Li return HANDLE_EINTR(read(fd_, buf, nbyte));
46*1a96fba6SXin Li }
47*1a96fba6SXin Li
Write(const void * buf,size_t nbyte)48*1a96fba6SXin Li ssize_t Write(const void* buf, size_t nbyte) override {
49*1a96fba6SXin Li return HANDLE_EINTR(write(fd_, buf, nbyte));
50*1a96fba6SXin Li }
51*1a96fba6SXin Li
Seek(off64_t offset,int whence)52*1a96fba6SXin Li off64_t Seek(off64_t offset, int whence) override {
53*1a96fba6SXin Li return lseek64(fd_, offset, whence);
54*1a96fba6SXin Li }
55*1a96fba6SXin Li
GetFileMode() const56*1a96fba6SXin Li mode_t GetFileMode() const override {
57*1a96fba6SXin Li struct stat file_stat;
58*1a96fba6SXin Li if (fstat(fd_, &file_stat) < 0)
59*1a96fba6SXin Li return 0;
60*1a96fba6SXin Li return file_stat.st_mode;
61*1a96fba6SXin Li }
62*1a96fba6SXin Li
GetSize() const63*1a96fba6SXin Li uint64_t GetSize() const override {
64*1a96fba6SXin Li struct stat file_stat;
65*1a96fba6SXin Li if (fstat(fd_, &file_stat) < 0)
66*1a96fba6SXin Li return 0;
67*1a96fba6SXin Li return file_stat.st_size;
68*1a96fba6SXin Li }
69*1a96fba6SXin Li
Truncate(off64_t length) const70*1a96fba6SXin Li int Truncate(off64_t length) const override {
71*1a96fba6SXin Li return HANDLE_EINTR(ftruncate(fd_, length));
72*1a96fba6SXin Li }
73*1a96fba6SXin Li
Close()74*1a96fba6SXin Li int Close() override {
75*1a96fba6SXin Li int fd = -1;
76*1a96fba6SXin Li // The stream may or may not own the file descriptor stored in |fd_|.
77*1a96fba6SXin Li // Despite that, we will need to set |fd_| to -1 when Close() finished.
78*1a96fba6SXin Li // So, here we set it to -1 first and if we own the old descriptor, close
79*1a96fba6SXin Li // it before exiting.
80*1a96fba6SXin Li std::swap(fd, fd_);
81*1a96fba6SXin Li CancelPendingAsyncOperations();
82*1a96fba6SXin Li return own_ ? IGNORE_EINTR(close(fd)) : 0;
83*1a96fba6SXin Li }
84*1a96fba6SXin Li
WaitForData(Stream::AccessMode mode,const DataCallback & data_callback,ErrorPtr * error)85*1a96fba6SXin Li bool WaitForData(Stream::AccessMode mode,
86*1a96fba6SXin Li const DataCallback& data_callback,
87*1a96fba6SXin Li ErrorPtr* error) override {
88*1a96fba6SXin Li if (stream_utils::IsReadAccessMode(mode)) {
89*1a96fba6SXin Li CHECK(read_data_callback_.is_null());
90*1a96fba6SXin Li read_watcher_ = base::FileDescriptorWatcher::WatchReadable(
91*1a96fba6SXin Li fd_,
92*1a96fba6SXin Li base::BindRepeating(&FileDescriptor::OnReadable,
93*1a96fba6SXin Li base::Unretained(this)));
94*1a96fba6SXin Li if (!read_watcher_) {
95*1a96fba6SXin Li Error::AddTo(error, FROM_HERE, errors::stream::kDomain,
96*1a96fba6SXin Li errors::stream::kInvalidParameter,
97*1a96fba6SXin Li "File descriptor doesn't support watching for reading.");
98*1a96fba6SXin Li return false;
99*1a96fba6SXin Li }
100*1a96fba6SXin Li read_data_callback_ = data_callback;
101*1a96fba6SXin Li }
102*1a96fba6SXin Li if (stream_utils::IsWriteAccessMode(mode)) {
103*1a96fba6SXin Li CHECK(write_data_callback_.is_null());
104*1a96fba6SXin Li write_watcher_ = base::FileDescriptorWatcher::WatchWritable(
105*1a96fba6SXin Li fd_,
106*1a96fba6SXin Li base::BindRepeating(&FileDescriptor::OnWritable,
107*1a96fba6SXin Li base::Unretained(this)));
108*1a96fba6SXin Li if (!write_watcher_) {
109*1a96fba6SXin Li Error::AddTo(error, FROM_HERE, errors::stream::kDomain,
110*1a96fba6SXin Li errors::stream::kInvalidParameter,
111*1a96fba6SXin Li "File descriptor doesn't support watching for writing.");
112*1a96fba6SXin Li return false;
113*1a96fba6SXin Li }
114*1a96fba6SXin Li write_data_callback_ = data_callback;
115*1a96fba6SXin Li }
116*1a96fba6SXin Li return true;
117*1a96fba6SXin Li }
118*1a96fba6SXin Li
WaitForDataBlocking(Stream::AccessMode in_mode,base::TimeDelta timeout,Stream::AccessMode * out_mode)119*1a96fba6SXin Li int WaitForDataBlocking(Stream::AccessMode in_mode,
120*1a96fba6SXin Li base::TimeDelta timeout,
121*1a96fba6SXin Li Stream::AccessMode* out_mode) override {
122*1a96fba6SXin Li fd_set read_fds;
123*1a96fba6SXin Li fd_set write_fds;
124*1a96fba6SXin Li fd_set error_fds;
125*1a96fba6SXin Li
126*1a96fba6SXin Li FD_ZERO(&read_fds);
127*1a96fba6SXin Li FD_ZERO(&write_fds);
128*1a96fba6SXin Li FD_ZERO(&error_fds);
129*1a96fba6SXin Li
130*1a96fba6SXin Li if (stream_utils::IsReadAccessMode(in_mode))
131*1a96fba6SXin Li FD_SET(fd_, &read_fds);
132*1a96fba6SXin Li
133*1a96fba6SXin Li if (stream_utils::IsWriteAccessMode(in_mode))
134*1a96fba6SXin Li FD_SET(fd_, &write_fds);
135*1a96fba6SXin Li
136*1a96fba6SXin Li FD_SET(fd_, &error_fds);
137*1a96fba6SXin Li timeval timeout_val = {};
138*1a96fba6SXin Li if (!timeout.is_max()) {
139*1a96fba6SXin Li const timespec ts = timeout.ToTimeSpec();
140*1a96fba6SXin Li TIMESPEC_TO_TIMEVAL(&timeout_val, &ts);
141*1a96fba6SXin Li }
142*1a96fba6SXin Li int res = HANDLE_EINTR(select(fd_ + 1, &read_fds, &write_fds, &error_fds,
143*1a96fba6SXin Li timeout.is_max() ? nullptr : &timeout_val));
144*1a96fba6SXin Li if (res > 0 && out_mode) {
145*1a96fba6SXin Li *out_mode = stream_utils::MakeAccessMode(FD_ISSET(fd_, &read_fds),
146*1a96fba6SXin Li FD_ISSET(fd_, &write_fds));
147*1a96fba6SXin Li }
148*1a96fba6SXin Li return res;
149*1a96fba6SXin Li }
150*1a96fba6SXin Li
CancelPendingAsyncOperations()151*1a96fba6SXin Li void CancelPendingAsyncOperations() override {
152*1a96fba6SXin Li read_data_callback_.Reset();
153*1a96fba6SXin Li read_watcher_ = nullptr;
154*1a96fba6SXin Li write_data_callback_.Reset();
155*1a96fba6SXin Li write_watcher_ = nullptr;
156*1a96fba6SXin Li }
157*1a96fba6SXin Li
158*1a96fba6SXin Li // Called from the brillo::MessageLoop when the file descriptor is available
159*1a96fba6SXin Li // for reading.
OnReadable()160*1a96fba6SXin Li void OnReadable() {
161*1a96fba6SXin Li CHECK(!read_data_callback_.is_null());
162*1a96fba6SXin Li
163*1a96fba6SXin Li read_watcher_ = nullptr;
164*1a96fba6SXin Li DataCallback cb = std::move(read_data_callback_);
165*1a96fba6SXin Li cb.Run(Stream::AccessMode::READ);
166*1a96fba6SXin Li }
167*1a96fba6SXin Li
OnWritable()168*1a96fba6SXin Li void OnWritable() {
169*1a96fba6SXin Li CHECK(!write_data_callback_.is_null());
170*1a96fba6SXin Li
171*1a96fba6SXin Li write_watcher_ = nullptr;
172*1a96fba6SXin Li DataCallback cb = std::move(write_data_callback_);
173*1a96fba6SXin Li cb.Run(Stream::AccessMode::WRITE);
174*1a96fba6SXin Li }
175*1a96fba6SXin Li
176*1a96fba6SXin Li private:
177*1a96fba6SXin Li // The actual file descriptor we are working with. Will contain -1 if the
178*1a96fba6SXin Li // file stream has been closed.
179*1a96fba6SXin Li int fd_;
180*1a96fba6SXin Li
181*1a96fba6SXin Li // |own_| is set to true if the file stream owns the file descriptor |fd_| and
182*1a96fba6SXin Li // must close it when the stream is closed. This will be false for file
183*1a96fba6SXin Li // descriptors that shouldn't be closed (e.g. stdin, stdout, stderr).
184*1a96fba6SXin Li bool own_;
185*1a96fba6SXin Li
186*1a96fba6SXin Li // Stream callbacks to be called when read and/or write operations can be
187*1a96fba6SXin Li // performed on the file descriptor without blocking.
188*1a96fba6SXin Li DataCallback read_data_callback_;
189*1a96fba6SXin Li DataCallback write_data_callback_;
190*1a96fba6SXin Li
191*1a96fba6SXin Li // Monitoring read/write operations on the file descriptor.
192*1a96fba6SXin Li std::unique_ptr<base::FileDescriptorWatcher::Controller> read_watcher_;
193*1a96fba6SXin Li std::unique_ptr<base::FileDescriptorWatcher::Controller> write_watcher_;
194*1a96fba6SXin Li
195*1a96fba6SXin Li DISALLOW_COPY_AND_ASSIGN(FileDescriptor);
196*1a96fba6SXin Li };
197*1a96fba6SXin Li
Open(const base::FilePath & path,AccessMode mode,Disposition disposition,ErrorPtr * error)198*1a96fba6SXin Li StreamPtr FileStream::Open(const base::FilePath& path,
199*1a96fba6SXin Li AccessMode mode,
200*1a96fba6SXin Li Disposition disposition,
201*1a96fba6SXin Li ErrorPtr* error) {
202*1a96fba6SXin Li StreamPtr stream;
203*1a96fba6SXin Li int open_flags = O_CLOEXEC;
204*1a96fba6SXin Li switch (mode) {
205*1a96fba6SXin Li case AccessMode::READ:
206*1a96fba6SXin Li open_flags |= O_RDONLY;
207*1a96fba6SXin Li break;
208*1a96fba6SXin Li case AccessMode::WRITE:
209*1a96fba6SXin Li open_flags |= O_WRONLY;
210*1a96fba6SXin Li break;
211*1a96fba6SXin Li case AccessMode::READ_WRITE:
212*1a96fba6SXin Li open_flags |= O_RDWR;
213*1a96fba6SXin Li break;
214*1a96fba6SXin Li }
215*1a96fba6SXin Li
216*1a96fba6SXin Li switch (disposition) {
217*1a96fba6SXin Li case Disposition::OPEN_EXISTING:
218*1a96fba6SXin Li // Nothing else to do.
219*1a96fba6SXin Li break;
220*1a96fba6SXin Li case Disposition::CREATE_ALWAYS:
221*1a96fba6SXin Li open_flags |= O_CREAT | O_TRUNC;
222*1a96fba6SXin Li break;
223*1a96fba6SXin Li case Disposition::CREATE_NEW_ONLY:
224*1a96fba6SXin Li open_flags |= O_CREAT | O_EXCL;
225*1a96fba6SXin Li break;
226*1a96fba6SXin Li case Disposition::TRUNCATE_EXISTING:
227*1a96fba6SXin Li open_flags |= O_TRUNC;
228*1a96fba6SXin Li break;
229*1a96fba6SXin Li }
230*1a96fba6SXin Li
231*1a96fba6SXin Li mode_t creation_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
232*1a96fba6SXin Li int fd = HANDLE_EINTR(open(path.value().c_str(), open_flags, creation_mode));
233*1a96fba6SXin Li if (fd < 0) {
234*1a96fba6SXin Li brillo::errors::system::AddSystemError(error, FROM_HERE, errno);
235*1a96fba6SXin Li return stream;
236*1a96fba6SXin Li }
237*1a96fba6SXin Li if (HANDLE_EINTR(fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK)) < 0) {
238*1a96fba6SXin Li brillo::errors::system::AddSystemError(error, FROM_HERE, errno);
239*1a96fba6SXin Li IGNORE_EINTR(close(fd));
240*1a96fba6SXin Li return stream;
241*1a96fba6SXin Li }
242*1a96fba6SXin Li
243*1a96fba6SXin Li std::unique_ptr<FileDescriptorInterface> fd_interface{
244*1a96fba6SXin Li new FileDescriptor{fd, true}};
245*1a96fba6SXin Li
246*1a96fba6SXin Li stream.reset(new FileStream{std::move(fd_interface), mode});
247*1a96fba6SXin Li return stream;
248*1a96fba6SXin Li }
249*1a96fba6SXin Li
CreateTemporary(ErrorPtr * error)250*1a96fba6SXin Li StreamPtr FileStream::CreateTemporary(ErrorPtr* error) {
251*1a96fba6SXin Li StreamPtr stream;
252*1a96fba6SXin Li base::FilePath path;
253*1a96fba6SXin Li // The "proper" solution would be here to add O_TMPFILE flag to |open_flags|
254*1a96fba6SXin Li // below and pass just the temp directory path to open(), so the actual file
255*1a96fba6SXin Li // name isn't even needed. However this is supported only as of Linux kernel
256*1a96fba6SXin Li // 3.11 and not all our configurations have that. So, for now just create
257*1a96fba6SXin Li // a temp file first and then open it.
258*1a96fba6SXin Li if (!base::CreateTemporaryFile(&path)) {
259*1a96fba6SXin Li brillo::errors::system::AddSystemError(error, FROM_HERE, errno);
260*1a96fba6SXin Li return stream;
261*1a96fba6SXin Li }
262*1a96fba6SXin Li int open_flags = O_CLOEXEC | O_RDWR | O_CREAT | O_TRUNC;
263*1a96fba6SXin Li mode_t creation_mode = S_IRUSR | S_IWUSR;
264*1a96fba6SXin Li int fd = HANDLE_EINTR(open(path.value().c_str(), open_flags, creation_mode));
265*1a96fba6SXin Li if (fd < 0) {
266*1a96fba6SXin Li brillo::errors::system::AddSystemError(error, FROM_HERE, errno);
267*1a96fba6SXin Li return stream;
268*1a96fba6SXin Li }
269*1a96fba6SXin Li unlink(path.value().c_str());
270*1a96fba6SXin Li
271*1a96fba6SXin Li stream = FromFileDescriptor(fd, true, error);
272*1a96fba6SXin Li if (!stream)
273*1a96fba6SXin Li IGNORE_EINTR(close(fd));
274*1a96fba6SXin Li return stream;
275*1a96fba6SXin Li }
276*1a96fba6SXin Li
FromFileDescriptor(int file_descriptor,bool own_descriptor,ErrorPtr * error)277*1a96fba6SXin Li StreamPtr FileStream::FromFileDescriptor(int file_descriptor,
278*1a96fba6SXin Li bool own_descriptor,
279*1a96fba6SXin Li ErrorPtr* error) {
280*1a96fba6SXin Li StreamPtr stream;
281*1a96fba6SXin Li if (file_descriptor < 0 || file_descriptor >= FD_SETSIZE) {
282*1a96fba6SXin Li Error::AddTo(error, FROM_HERE, errors::stream::kDomain,
283*1a96fba6SXin Li errors::stream::kInvalidParameter,
284*1a96fba6SXin Li "Invalid file descriptor value");
285*1a96fba6SXin Li return stream;
286*1a96fba6SXin Li }
287*1a96fba6SXin Li
288*1a96fba6SXin Li int fd_flags = HANDLE_EINTR(fcntl(file_descriptor, F_GETFL));
289*1a96fba6SXin Li if (fd_flags < 0) {
290*1a96fba6SXin Li brillo::errors::system::AddSystemError(error, FROM_HERE, errno);
291*1a96fba6SXin Li return stream;
292*1a96fba6SXin Li }
293*1a96fba6SXin Li int file_access_mode = (fd_flags & O_ACCMODE);
294*1a96fba6SXin Li AccessMode access_mode = AccessMode::READ_WRITE;
295*1a96fba6SXin Li if (file_access_mode == O_RDONLY)
296*1a96fba6SXin Li access_mode = AccessMode::READ;
297*1a96fba6SXin Li else if (file_access_mode == O_WRONLY)
298*1a96fba6SXin Li access_mode = AccessMode::WRITE;
299*1a96fba6SXin Li
300*1a96fba6SXin Li // Make sure the file descriptor is set to perform non-blocking operations
301*1a96fba6SXin Li // if not enabled already.
302*1a96fba6SXin Li if ((fd_flags & O_NONBLOCK) == 0) {
303*1a96fba6SXin Li fd_flags |= O_NONBLOCK;
304*1a96fba6SXin Li if (HANDLE_EINTR(fcntl(file_descriptor, F_SETFL, fd_flags)) < 0) {
305*1a96fba6SXin Li brillo::errors::system::AddSystemError(error, FROM_HERE, errno);
306*1a96fba6SXin Li return stream;
307*1a96fba6SXin Li }
308*1a96fba6SXin Li }
309*1a96fba6SXin Li
310*1a96fba6SXin Li std::unique_ptr<FileDescriptorInterface> fd_interface{
311*1a96fba6SXin Li new FileDescriptor{file_descriptor, own_descriptor}};
312*1a96fba6SXin Li
313*1a96fba6SXin Li stream.reset(new FileStream{std::move(fd_interface), access_mode});
314*1a96fba6SXin Li return stream;
315*1a96fba6SXin Li }
316*1a96fba6SXin Li
FileStream(std::unique_ptr<FileDescriptorInterface> fd_interface,AccessMode mode)317*1a96fba6SXin Li FileStream::FileStream(std::unique_ptr<FileDescriptorInterface> fd_interface,
318*1a96fba6SXin Li AccessMode mode)
319*1a96fba6SXin Li : fd_interface_(std::move(fd_interface)),
320*1a96fba6SXin Li access_mode_(mode) {
321*1a96fba6SXin Li switch (fd_interface_->GetFileMode() & S_IFMT) {
322*1a96fba6SXin Li case S_IFCHR: // Character device
323*1a96fba6SXin Li case S_IFSOCK: // Socket
324*1a96fba6SXin Li case S_IFIFO: // FIFO/pipe
325*1a96fba6SXin Li // We know that these devices are not seekable and stream size is unknown.
326*1a96fba6SXin Li seekable_ = false;
327*1a96fba6SXin Li can_get_size_ = false;
328*1a96fba6SXin Li break;
329*1a96fba6SXin Li
330*1a96fba6SXin Li case S_IFBLK: // Block device
331*1a96fba6SXin Li case S_IFDIR: // Directory
332*1a96fba6SXin Li case S_IFREG: // Normal file
333*1a96fba6SXin Li case S_IFLNK: // Symbolic link
334*1a96fba6SXin Li default:
335*1a96fba6SXin Li // The above devices support seek. Also, if not sure/in doubt, err on the
336*1a96fba6SXin Li // side of "allowable".
337*1a96fba6SXin Li seekable_ = true;
338*1a96fba6SXin Li can_get_size_ = true;
339*1a96fba6SXin Li break;
340*1a96fba6SXin Li }
341*1a96fba6SXin Li }
342*1a96fba6SXin Li
IsOpen() const343*1a96fba6SXin Li bool FileStream::IsOpen() const {
344*1a96fba6SXin Li return fd_interface_->IsOpen();
345*1a96fba6SXin Li }
346*1a96fba6SXin Li
CanRead() const347*1a96fba6SXin Li bool FileStream::CanRead() const {
348*1a96fba6SXin Li return IsOpen() && stream_utils::IsReadAccessMode(access_mode_);
349*1a96fba6SXin Li }
350*1a96fba6SXin Li
CanWrite() const351*1a96fba6SXin Li bool FileStream::CanWrite() const {
352*1a96fba6SXin Li return IsOpen() && stream_utils::IsWriteAccessMode(access_mode_);
353*1a96fba6SXin Li }
354*1a96fba6SXin Li
CanSeek() const355*1a96fba6SXin Li bool FileStream::CanSeek() const {
356*1a96fba6SXin Li return IsOpen() && seekable_;
357*1a96fba6SXin Li }
358*1a96fba6SXin Li
CanGetSize() const359*1a96fba6SXin Li bool FileStream::CanGetSize() const {
360*1a96fba6SXin Li return IsOpen() && can_get_size_;
361*1a96fba6SXin Li }
362*1a96fba6SXin Li
GetSize() const363*1a96fba6SXin Li uint64_t FileStream::GetSize() const {
364*1a96fba6SXin Li return IsOpen() ? fd_interface_->GetSize() : 0;
365*1a96fba6SXin Li }
366*1a96fba6SXin Li
SetSizeBlocking(uint64_t size,ErrorPtr * error)367*1a96fba6SXin Li bool FileStream::SetSizeBlocking(uint64_t size, ErrorPtr* error) {
368*1a96fba6SXin Li if (!IsOpen())
369*1a96fba6SXin Li return stream_utils::ErrorStreamClosed(FROM_HERE, error);
370*1a96fba6SXin Li
371*1a96fba6SXin Li if (!stream_utils::CheckInt64Overflow(FROM_HERE, size, 0, error))
372*1a96fba6SXin Li return false;
373*1a96fba6SXin Li
374*1a96fba6SXin Li if (fd_interface_->Truncate(size) >= 0)
375*1a96fba6SXin Li return true;
376*1a96fba6SXin Li
377*1a96fba6SXin Li errors::system::AddSystemError(error, FROM_HERE, errno);
378*1a96fba6SXin Li return false;
379*1a96fba6SXin Li }
380*1a96fba6SXin Li
GetRemainingSize() const381*1a96fba6SXin Li uint64_t FileStream::GetRemainingSize() const {
382*1a96fba6SXin Li if (!CanGetSize())
383*1a96fba6SXin Li return 0;
384*1a96fba6SXin Li uint64_t pos = GetPosition();
385*1a96fba6SXin Li uint64_t size = GetSize();
386*1a96fba6SXin Li return (pos < size) ? (size - pos) : 0;
387*1a96fba6SXin Li }
388*1a96fba6SXin Li
GetPosition() const389*1a96fba6SXin Li uint64_t FileStream::GetPosition() const {
390*1a96fba6SXin Li if (!CanSeek())
391*1a96fba6SXin Li return 0;
392*1a96fba6SXin Li
393*1a96fba6SXin Li off64_t pos = fd_interface_->Seek(0, SEEK_CUR);
394*1a96fba6SXin Li const off64_t min_pos = 0;
395*1a96fba6SXin Li return std::max(min_pos, pos);
396*1a96fba6SXin Li }
397*1a96fba6SXin Li
Seek(int64_t offset,Whence whence,uint64_t * new_position,ErrorPtr * error)398*1a96fba6SXin Li bool FileStream::Seek(int64_t offset,
399*1a96fba6SXin Li Whence whence,
400*1a96fba6SXin Li uint64_t* new_position,
401*1a96fba6SXin Li ErrorPtr* error) {
402*1a96fba6SXin Li if (!IsOpen())
403*1a96fba6SXin Li return stream_utils::ErrorStreamClosed(FROM_HERE, error);
404*1a96fba6SXin Li
405*1a96fba6SXin Li int raw_whence = 0;
406*1a96fba6SXin Li switch (whence) {
407*1a96fba6SXin Li case Whence::FROM_BEGIN:
408*1a96fba6SXin Li raw_whence = SEEK_SET;
409*1a96fba6SXin Li break;
410*1a96fba6SXin Li case Whence::FROM_CURRENT:
411*1a96fba6SXin Li raw_whence = SEEK_CUR;
412*1a96fba6SXin Li break;
413*1a96fba6SXin Li case Whence::FROM_END:
414*1a96fba6SXin Li raw_whence = SEEK_END;
415*1a96fba6SXin Li break;
416*1a96fba6SXin Li default:
417*1a96fba6SXin Li Error::AddTo(error, FROM_HERE, errors::stream::kDomain,
418*1a96fba6SXin Li errors::stream::kInvalidParameter, "Invalid whence");
419*1a96fba6SXin Li return false;
420*1a96fba6SXin Li }
421*1a96fba6SXin Li off64_t pos = fd_interface_->Seek(offset, raw_whence);
422*1a96fba6SXin Li if (pos < 0) {
423*1a96fba6SXin Li errors::system::AddSystemError(error, FROM_HERE, errno);
424*1a96fba6SXin Li return false;
425*1a96fba6SXin Li }
426*1a96fba6SXin Li
427*1a96fba6SXin Li if (new_position)
428*1a96fba6SXin Li *new_position = static_cast<uint64_t>(pos);
429*1a96fba6SXin Li return true;
430*1a96fba6SXin Li }
431*1a96fba6SXin Li
ReadNonBlocking(void * buffer,size_t size_to_read,size_t * size_read,bool * end_of_stream,ErrorPtr * error)432*1a96fba6SXin Li bool FileStream::ReadNonBlocking(void* buffer,
433*1a96fba6SXin Li size_t size_to_read,
434*1a96fba6SXin Li size_t* size_read,
435*1a96fba6SXin Li bool* end_of_stream,
436*1a96fba6SXin Li ErrorPtr* error) {
437*1a96fba6SXin Li if (!IsOpen())
438*1a96fba6SXin Li return stream_utils::ErrorStreamClosed(FROM_HERE, error);
439*1a96fba6SXin Li
440*1a96fba6SXin Li ssize_t read = fd_interface_->Read(buffer, size_to_read);
441*1a96fba6SXin Li if (read < 0) {
442*1a96fba6SXin Li // If read() fails, check if this is due to no data being currently
443*1a96fba6SXin Li // available and we do non-blocking I/O.
444*1a96fba6SXin Li if (errno == EWOULDBLOCK || errno == EAGAIN) {
445*1a96fba6SXin Li if (end_of_stream)
446*1a96fba6SXin Li *end_of_stream = false;
447*1a96fba6SXin Li *size_read = 0;
448*1a96fba6SXin Li return true;
449*1a96fba6SXin Li }
450*1a96fba6SXin Li // Otherwise a real problem occurred.
451*1a96fba6SXin Li errors::system::AddSystemError(error, FROM_HERE, errno);
452*1a96fba6SXin Li return false;
453*1a96fba6SXin Li }
454*1a96fba6SXin Li if (end_of_stream)
455*1a96fba6SXin Li *end_of_stream = (read == 0 && size_to_read != 0);
456*1a96fba6SXin Li *size_read = read;
457*1a96fba6SXin Li return true;
458*1a96fba6SXin Li }
459*1a96fba6SXin Li
WriteNonBlocking(const void * buffer,size_t size_to_write,size_t * size_written,ErrorPtr * error)460*1a96fba6SXin Li bool FileStream::WriteNonBlocking(const void* buffer,
461*1a96fba6SXin Li size_t size_to_write,
462*1a96fba6SXin Li size_t* size_written,
463*1a96fba6SXin Li ErrorPtr* error) {
464*1a96fba6SXin Li if (!IsOpen())
465*1a96fba6SXin Li return stream_utils::ErrorStreamClosed(FROM_HERE, error);
466*1a96fba6SXin Li
467*1a96fba6SXin Li ssize_t written = fd_interface_->Write(buffer, size_to_write);
468*1a96fba6SXin Li if (written < 0) {
469*1a96fba6SXin Li // If write() fails, check if this is due to the fact that no data
470*1a96fba6SXin Li // can be presently written and we do non-blocking I/O.
471*1a96fba6SXin Li if (errno == EWOULDBLOCK || errno == EAGAIN) {
472*1a96fba6SXin Li *size_written = 0;
473*1a96fba6SXin Li return true;
474*1a96fba6SXin Li }
475*1a96fba6SXin Li // Otherwise a real problem occurred.
476*1a96fba6SXin Li errors::system::AddSystemError(error, FROM_HERE, errno);
477*1a96fba6SXin Li return false;
478*1a96fba6SXin Li }
479*1a96fba6SXin Li *size_written = written;
480*1a96fba6SXin Li return true;
481*1a96fba6SXin Li }
482*1a96fba6SXin Li
FlushBlocking(ErrorPtr * error)483*1a96fba6SXin Li bool FileStream::FlushBlocking(ErrorPtr* error) {
484*1a96fba6SXin Li if (!IsOpen())
485*1a96fba6SXin Li return stream_utils::ErrorStreamClosed(FROM_HERE, error);
486*1a96fba6SXin Li
487*1a96fba6SXin Li // File descriptors don't have an internal buffer to flush.
488*1a96fba6SXin Li return true;
489*1a96fba6SXin Li }
490*1a96fba6SXin Li
CloseBlocking(ErrorPtr * error)491*1a96fba6SXin Li bool FileStream::CloseBlocking(ErrorPtr* error) {
492*1a96fba6SXin Li if (!IsOpen())
493*1a96fba6SXin Li return true;
494*1a96fba6SXin Li
495*1a96fba6SXin Li if (fd_interface_->Close() < 0) {
496*1a96fba6SXin Li errors::system::AddSystemError(error, FROM_HERE, errno);
497*1a96fba6SXin Li return false;
498*1a96fba6SXin Li }
499*1a96fba6SXin Li
500*1a96fba6SXin Li return true;
501*1a96fba6SXin Li }
502*1a96fba6SXin Li
WaitForData(AccessMode mode,const base::Callback<void (AccessMode)> & callback,ErrorPtr * error)503*1a96fba6SXin Li bool FileStream::WaitForData(
504*1a96fba6SXin Li AccessMode mode,
505*1a96fba6SXin Li const base::Callback<void(AccessMode)>& callback,
506*1a96fba6SXin Li ErrorPtr* error) {
507*1a96fba6SXin Li if (!IsOpen())
508*1a96fba6SXin Li return stream_utils::ErrorStreamClosed(FROM_HERE, error);
509*1a96fba6SXin Li
510*1a96fba6SXin Li return fd_interface_->WaitForData(mode, callback, error);
511*1a96fba6SXin Li }
512*1a96fba6SXin Li
WaitForDataBlocking(AccessMode in_mode,base::TimeDelta timeout,AccessMode * out_mode,ErrorPtr * error)513*1a96fba6SXin Li bool FileStream::WaitForDataBlocking(AccessMode in_mode,
514*1a96fba6SXin Li base::TimeDelta timeout,
515*1a96fba6SXin Li AccessMode* out_mode,
516*1a96fba6SXin Li ErrorPtr* error) {
517*1a96fba6SXin Li if (!IsOpen())
518*1a96fba6SXin Li return stream_utils::ErrorStreamClosed(FROM_HERE, error);
519*1a96fba6SXin Li
520*1a96fba6SXin Li int ret = fd_interface_->WaitForDataBlocking(in_mode, timeout, out_mode);
521*1a96fba6SXin Li if (ret < 0) {
522*1a96fba6SXin Li errors::system::AddSystemError(error, FROM_HERE, errno);
523*1a96fba6SXin Li return false;
524*1a96fba6SXin Li }
525*1a96fba6SXin Li if (ret == 0)
526*1a96fba6SXin Li return stream_utils::ErrorOperationTimeout(FROM_HERE, error);
527*1a96fba6SXin Li
528*1a96fba6SXin Li return true;
529*1a96fba6SXin Li }
530*1a96fba6SXin Li
CancelPendingAsyncOperations()531*1a96fba6SXin Li void FileStream::CancelPendingAsyncOperations() {
532*1a96fba6SXin Li if (IsOpen()) {
533*1a96fba6SXin Li fd_interface_->CancelPendingAsyncOperations();
534*1a96fba6SXin Li }
535*1a96fba6SXin Li Stream::CancelPendingAsyncOperations();
536*1a96fba6SXin Li }
537*1a96fba6SXin Li
538*1a96fba6SXin Li } // namespace brillo
539