blob: 74749c6f07a8a9bc5943b85026cab044b04f80a9 [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#ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_FILE_DESCRIPTOR_H__
6#define CHROMEOS_PLATFORM_UPDATE_ENGINE_FILE_DESCRIPTOR_H__
7
8#include <errno.h>
9#include <sys/types.h>
10
11#include "base/logging.h"
12
13#include "update_engine/utils.h"
14
15// Abstraction for managing opening, reading, writing and closing of file
16// descriptors. This includes an abstract class and one standard implementation
17// based on POSIX system calls.
18//
19// TODO(garnold) this class is modeled after (and augments the functionality of)
20// the FileWriter class; ultimately, the latter should be replaced by the former
21// throughout the codebase. A few deviations from the original FileWriter:
22//
23// * Providing two flavors of Open()
24//
25// * A FileDescriptor is reusable and can be used to read/write multiple files
26// as long as open/close preconditions are respected.
27//
28// * Write() returns the number of bytes written: this appears to be more useful
29// for clients, who may wish to retry or otherwise do something useful with
30// the remaining data that was not written.
31
32namespace chromeos_update_engine {
33
34// An abstract class defining the file descriptor API.
35class FileDescriptor {
36 public:
37 FileDescriptor() {}
38 virtual ~FileDescriptor() {}
39
40 // Opens a file descriptor. The descriptor must be in the closed state prior
41 // to this call. Returns true on success, false otherwise. Specific
42 // implementations may set errno accordingly.
43 virtual bool Open(const char* path, int flags, mode_t mode) = 0;
44 virtual bool Open(const char* path, int flags) = 0;
45
46 // Reads from a file descriptor up to a given count. The descriptor must be
47 // open prior to this call. Returns the number of bytes read, or -1 on error.
48 // Specific implementations may set errno accordingly.
49 virtual ssize_t Read(void* buf, size_t count) = 0;
50
51 // Writes to a file descriptor. The descriptor must be open prior to this
52 // call. Returns the number of bytes written, or -1 if an error occurred and
53 // no bytes were written. Specific implementations may set errno accordingly.
54 virtual ssize_t Write(const void* buf, size_t count) = 0;
55
56 // Wrapper around close. The descriptor must be open prior to this call.
57 // Returns true on success, false otherwise. Specific implementations may set
58 // errno accordingly.
59 virtual bool Close() = 0;
60
61 // Indicates whether or not an implementation sets meaningful errno.
62 virtual bool IsSettingErrno() = 0;
63
64 private:
65 DISALLOW_COPY_AND_ASSIGN(FileDescriptor);
66};
67
68// A simple EINTR-immune wrapper implementation around standard system calls.
69class EintrSafeFileDescriptor : public FileDescriptor {
70 public:
71 EintrSafeFileDescriptor() : fd_(-1) {}
72 virtual ~EintrSafeFileDescriptor() {};
73
74 // Interface methods.
75 virtual bool Open(const char* path, int flags, mode_t mode);
76 virtual bool Open(const char* path, int flags);
77 virtual ssize_t Read(void* buf, size_t count);
78 virtual ssize_t Write(const void* buf, size_t count);
79 virtual bool Close();
80 virtual bool IsSettingErrno() {
81 return true;
82 }
83
84 private:
85 int fd_;
86};
87
88// A scoped closer for a FileDescriptor object.
89class ScopedFileDescriptorCloser {
90 public:
91 explicit ScopedFileDescriptorCloser(FileDescriptor* descriptor)
92 : descriptor_(descriptor) {}
93 ~ScopedFileDescriptorCloser() {
94 if (descriptor_ && !descriptor_->Close())
95 LOG(ERROR) << "FileDescriptor::Close failed: "
96 << (descriptor_->IsSettingErrno() ?
97 utils::ErrnoNumberAsString(errno) :
98 "(no error code)");
99 }
100 private:
101 FileDescriptor* descriptor_;
102
103 DISALLOW_COPY_AND_ASSIGN(ScopedFileDescriptorCloser);
104};
105
106} // namespace chromeos_update_engine
107
108#endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_FILE_DESCRIPTOR_H__