blob: 255307d3e64d06cd0a8aeaa53fa520bba28e528e [file] [log] [blame]
Gilad Arnold11c066f2012-05-10 14:37:25 -07001// Copyright (c) 2012 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 "update_engine/file_descriptor.h"
6
7#include <fcntl.h>
8#include <sys/stat.h>
9#include <sys/types.h>
10
Chris Sosafc661a12013-02-26 14:43:21 -080011#include <base/posix/eintr_wrapper.h>
Gilad Arnold11c066f2012-05-10 14:37:25 -070012
13namespace chromeos_update_engine {
14
15bool EintrSafeFileDescriptor::Open(const char* path, int flags, mode_t mode) {
16 CHECK_EQ(fd_, -1);
17 return ((fd_ = HANDLE_EINTR(open(path, flags, mode))) >= 0);
18}
19
20bool EintrSafeFileDescriptor::Open(const char* path, int flags) {
21 CHECK_EQ(fd_, -1);
22 return ((fd_ = HANDLE_EINTR(open(path, flags))) >= 0);
23}
24
25ssize_t EintrSafeFileDescriptor::Read(void* buf, size_t count) {
26 CHECK_GE(fd_, 0);
27 return HANDLE_EINTR(read(fd_, buf, count));
28}
29
30ssize_t EintrSafeFileDescriptor::Write(const void* buf, size_t count) {
31 CHECK_GE(fd_, 0);
32
33 // Attempt repeated writes, as long as some progress is being made.
34 char* char_buf = const_cast<char*>(reinterpret_cast<const char*>(buf));
35 ssize_t written = 0;
36 while (count > 0) {
37 ssize_t ret = HANDLE_EINTR(write(fd_, char_buf, count));
38
39 // Fail on either an error or no progress.
40 if (ret <= 0)
41 return (written ? written : ret);
42 written += ret;
43 count -= ret;
44 char_buf += ret;
45 }
46 return written;
47}
48
49bool EintrSafeFileDescriptor::Close() {
50 CHECK_GE(fd_, 0);
Gilad Arnold6eccc532012-05-17 15:44:22 -070051 if (HANDLE_EINTR(close(fd_)))
52 return false;
53 Reset();
54 return true;
55}
56
57void EintrSafeFileDescriptor::Reset() {
58 fd_ = -1;
59}
60
61
62ScopedFileDescriptorCloser::~ScopedFileDescriptorCloser() {
63 if (descriptor_ && descriptor_->IsOpen() && !descriptor_->Close()) {
64 const char* err_str = "file closing failed";
65 if (descriptor_->IsSettingErrno()) {
66 PLOG(ERROR) << err_str;
67 } else {
68 LOG(ERROR) << err_str;
69 }
70 // Abandon the current descriptor, forcing it back to a closed state.
71 descriptor_->Reset();
72 }
Gilad Arnold11c066f2012-05-10 14:37:25 -070073}
74
75} // namespace chromeos_update_engine