blob: 4b8fc17c19450baba50b74a148cd4ab4bbd466dc [file] [log] [blame]
Gilad Arnold4d740eb2012-05-15 08:48:13 -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_UDEV_INTERFACE_H__
6#define CHROMEOS_PLATFORM_UPDATE_ENGINE_UDEV_INTERFACE_H__
7
8#include <libudev.h>
9
10#include "update_engine/utils.h"
11
12// An interface for libudev calls, allowing to easily mock it.
13
14namespace chromeos_update_engine {
15
16// An interface for libudev methods that are being used in update engine.
17//
18// TODO(garnold) As is, this is a pretty lame indirection layer that otherwise
19// does not provide any better abstraction than the existing libudev API. Done
20// properly, we should replace it with encapsulated udev, enumerate and device
21// objects, and hide initialization, reference handling and iterators in ways
22// more appropriate to an object-oriented setting...
23class UdevInterface {
24 public:
Gilad Arnoldbf7919b2013-01-08 13:07:37 -080025 virtual ~UdevInterface() {}
26
Gilad Arnold4d740eb2012-05-15 08:48:13 -070027 // Interfaces for various udev closers. All of these are merely containers for
28 // a single pointer to some udev handle, which invoke the provided interface's
29 // unref method and nullify the handle upon destruction. It should suffice for
30 // derivative (concrete) interfaces to implement the various unref methods to
31 // fit their needs, making these closers behave as expected.
32 class UdevCloser {
33 public:
34 explicit UdevCloser(UdevInterface* udev_iface, struct udev** udev_p)
35 : udev_iface_(udev_iface), udev_p_(udev_p) {
36 CHECK(udev_iface && udev_p);
37 }
38 virtual ~UdevCloser() {
39 if (*udev_p_) {
40 udev_iface_->Unref(*udev_p_);
41 *udev_p_ = NULL;
42 }
43 }
44 protected:
45 UdevInterface* udev_iface_;
46 struct udev** udev_p_;
47 private:
48 DISALLOW_IMPLICIT_CONSTRUCTORS(UdevCloser);
49 };
50
51 class UdevEnumerateCloser {
52 public:
53 explicit UdevEnumerateCloser(UdevInterface* udev_iface,
54 struct udev_enumerate** udev_enum_p)
55 : udev_iface_(udev_iface), udev_enum_p_(udev_enum_p) {
56 CHECK(udev_iface && udev_enum_p);
57 }
58 virtual ~UdevEnumerateCloser() {
59 if (*udev_enum_p_) {
60 udev_iface_->EnumerateUnref(*udev_enum_p_);
61 *udev_enum_p_ = NULL;
62 }
63 }
64 protected:
65 UdevInterface* udev_iface_;
66 struct udev_enumerate** udev_enum_p_;
67 private:
68 DISALLOW_IMPLICIT_CONSTRUCTORS(UdevEnumerateCloser);
69 };
70
71 class UdevDeviceCloser {
72 public:
73 explicit UdevDeviceCloser(UdevInterface* udev_iface,
74 struct udev_device** udev_dev_p)
75 : udev_iface_(udev_iface), udev_dev_p_(udev_dev_p) {
76 CHECK(udev_iface && udev_dev_p);
77 }
78 virtual ~UdevDeviceCloser() {
79 if (*udev_dev_p_) {
80 udev_iface_->DeviceUnref(*udev_dev_p_);
81 *udev_dev_p_ = NULL;
82 }
83 }
84 protected:
85 UdevInterface* udev_iface_;
86 struct udev_device** udev_dev_p_;
87 private:
88 DISALLOW_IMPLICIT_CONSTRUCTORS(UdevDeviceCloser);
89 };
90
91 virtual UdevCloser* NewUdevCloser(struct udev** udev_p) {
92 return new UdevCloser(this, udev_p);
93 }
94 virtual UdevEnumerateCloser* NewUdevEnumerateCloser(
95 struct udev_enumerate** udev_enum_p) {
96 return new UdevEnumerateCloser(this, udev_enum_p);
97 }
98 virtual UdevDeviceCloser* NewUdevDeviceCloser(
99 struct udev_device** udev_dev_p) {
100 return new UdevDeviceCloser(this, udev_dev_p);
101 }
102
103 // Lists.
104 virtual const char* ListEntryGetName(struct udev_list_entry* list_entry) = 0;
105 virtual udev_list_entry* ListEntryGetNext(
106 struct udev_list_entry* list_entry) = 0;
107
108 // Device methods.
109 virtual struct udev_device* DeviceNewFromSyspath(
110 struct udev* udev,
111 const char* syspath) = 0;
112 virtual const char* DeviceGetPropertyValue(struct udev_device* udev_device,
113 const char* key) = 0;
114 virtual const char* DeviceGetSyspath(
115 struct udev_device* udev_device) = 0;
116 virtual void DeviceUnref(struct udev_device* udev_device) = 0;
117
118 // Enumerate methods.
119 virtual struct udev_enumerate* EnumerateNew(struct udev* udev) = 0;
120 virtual int EnumerateAddMatchSubsystem(struct udev_enumerate* udev_enum,
121 const char* subsystem) = 0;
122 virtual int EnumerateAddMatchSysname(struct udev_enumerate* udev_enum,
123 const char* sysname) = 0;
124 virtual int EnumerateScanDevices(struct udev_enumerate* udev_enum) = 0;
125 virtual struct udev_list_entry* EnumerateGetListEntry(
126 struct udev_enumerate* udev_enum) = 0;
127 virtual void EnumerateUnref(struct udev_enumerate* udev_enum) = 0;
128
129 // Udev instance methods.
130 virtual struct udev* New() = 0;
131 virtual void Unref(struct udev* udev) = 0;
132};
133
134
135// Implementation of libudev interface using concrete udev calls.
136class StandardUdevInterface : public UdevInterface {
137 public:
Gilad Arnoldbf7919b2013-01-08 13:07:37 -0800138 virtual ~StandardUdevInterface() {}
139
Gilad Arnold4d740eb2012-05-15 08:48:13 -0700140 // Concrete udev API wrappers utilizing the standard libudev calls.
141 virtual const char* ListEntryGetName(struct udev_list_entry* list_entry) {
142 return udev_list_entry_get_name(list_entry);
143 }
144 virtual struct udev_list_entry* ListEntryGetNext(
145 struct udev_list_entry* list_entry) {
146 return udev_list_entry_get_next(list_entry);
147 }
148
149 virtual struct udev_device* DeviceNewFromSyspath(struct udev* udev,
150 const char* syspath) {
151 return udev_device_new_from_syspath(udev, syspath);
152 }
153 virtual const char* DeviceGetPropertyValue(struct udev_device* udev_device,
154 const char* key) {
155 return udev_device_get_property_value(udev_device, key);
156 }
157 virtual const char* DeviceGetSyspath(struct udev_device* udev_device) {
158 return udev_device_get_syspath(udev_device);
159 }
160 virtual void DeviceUnref(struct udev_device* udev_device) {
161 return udev_device_unref(udev_device);
162 }
163
164 virtual struct udev_enumerate* EnumerateNew(struct udev* udev) {
165 return udev_enumerate_new(udev);
166 }
167 virtual int EnumerateAddMatchSubsystem(struct udev_enumerate* udev_enum,
168 const char* subsystem) {
169 return udev_enumerate_add_match_subsystem(udev_enum, subsystem);
170 }
171 virtual int EnumerateAddMatchSysname(struct udev_enumerate* udev_enum,
172 const char* sysname) {
173 return udev_enumerate_add_match_sysname(udev_enum, sysname);
174 }
175 virtual int EnumerateScanDevices(struct udev_enumerate* udev_enum) {
176 return udev_enumerate_scan_devices(udev_enum);
177 }
178 virtual struct udev_list_entry* EnumerateGetListEntry(
179 struct udev_enumerate* udev_enum) {
180 return udev_enumerate_get_list_entry(udev_enum);
181 }
182 virtual void EnumerateUnref(struct udev_enumerate* udev_enum) {
183 return udev_enumerate_unref(udev_enum);
184 }
185
186 virtual struct udev* New() {
187 return udev_new();
188 }
189 virtual void Unref(struct udev* udev) {
190 return udev_unref(udev);
191 }
192};
193
194} // namespace chromeos_update_engine
195
196#endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_UDEV_INTERFACE_H__
197