blob: 972273a95658953e76c1a5133457a4590d528e07 [file] [log] [blame]
Alex Deymo03f1deb2015-10-13 02:15:31 -07001// Copyright 2015 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "file.h"
6
7#include <errno.h>
8#include <fcntl.h>
9#include <string.h>
10#include <sys/ioctl.h>
11#include <sys/stat.h>
12#include <sys/types.h>
13#include <unistd.h>
14
15// TEMP_FAILURE_RETRY is defined by some versions of <unistd.h>.
16#ifndef TEMP_FAILURE_RETRY
17#include <utils/Compat.h>
18#endif
19
20#include <algorithm>
21
22namespace bsdiff {
23
24std::unique_ptr<File> File::FOpen(const char* pathname, int flags) {
25 int fd = TEMP_FAILURE_RETRY(open(pathname, flags));
26 if (fd < 0)
27 return std::unique_ptr<File>();
28 return std::unique_ptr<File>(new File(fd));
29}
30
31File::~File() {
32 Close();
33}
34
35bool File::Read(void* buf, size_t count, size_t* bytes_read) {
36 if (fd_ < 0) {
37 errno = EBADF;
38 return false;
39 }
40 ssize_t rc = TEMP_FAILURE_RETRY(read(fd_, buf, count));
41 if (rc == -1)
42 return false;
43 *bytes_read = static_cast<size_t>(rc);
44 return true;
45}
46
47bool File::Write(const void* buf, size_t count, size_t* bytes_written) {
48 if (fd_ < 0) {
49 errno = EBADF;
50 return false;
51 }
52 ssize_t rc = TEMP_FAILURE_RETRY(write(fd_, buf, count));
53 if (rc == -1)
54 return false;
55 *bytes_written = static_cast<size_t>(rc);
56 return true;
57}
58
59bool File::Seek(off_t pos) {
60 if (fd_ < 0) {
61 errno = EBADF;
62 return false;
63 }
64 // fseek() uses a long value for the offset which could be smaller than off_t.
65 if (pos > std::numeric_limits<long>::max()) {
66 errno = EOVERFLOW;
67 return false;
68 }
69 off_t newpos = lseek(fd_, pos, SEEK_SET) == pos;
70 if (newpos < 0)
71 return false;
72 if (newpos != pos) {
73 errno = EINVAL;
74 return false;
75 }
76 return true;
77}
78
79bool File::Close() {
80 if (fd_ < 0) {
81 errno = EBADF;
82 return false;
83 }
84 bool success = close(fd_) == 0;
85 if (!success && errno == EINTR)
86 success = true;
87 fd_ = -1;
88 return success;
89}
90
91File::File(int fd)
92 : fd_(fd) {}
93
94} // namespace bsdiff