blob: b9765a85cbd8f58659ec3da7f83c8aa856e96421 [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:
25 // Interfaces for various udev closers. All of these are merely containers for
26 // a single pointer to some udev handle, which invoke the provided interface's
27 // unref method and nullify the handle upon destruction. It should suffice for
28 // derivative (concrete) interfaces to implement the various unref methods to
29 // fit their needs, making these closers behave as expected.
30 class UdevCloser {
31 public:
32 explicit UdevCloser(UdevInterface* udev_iface, struct udev** udev_p)
33 : udev_iface_(udev_iface), udev_p_(udev_p) {
34 CHECK(udev_iface && udev_p);
35 }
36 virtual ~UdevCloser() {
37 if (*udev_p_) {
38 udev_iface_->Unref(*udev_p_);
39 *udev_p_ = NULL;
40 }
41 }
42 protected:
43 UdevInterface* udev_iface_;
44 struct udev** udev_p_;
45 private:
46 DISALLOW_IMPLICIT_CONSTRUCTORS(UdevCloser);
47 };
48
49 class UdevEnumerateCloser {
50 public:
51 explicit UdevEnumerateCloser(UdevInterface* udev_iface,
52 struct udev_enumerate** udev_enum_p)
53 : udev_iface_(udev_iface), udev_enum_p_(udev_enum_p) {
54 CHECK(udev_iface && udev_enum_p);
55 }
56 virtual ~UdevEnumerateCloser() {
57 if (*udev_enum_p_) {
58 udev_iface_->EnumerateUnref(*udev_enum_p_);
59 *udev_enum_p_ = NULL;
60 }
61 }
62 protected:
63 UdevInterface* udev_iface_;
64 struct udev_enumerate** udev_enum_p_;
65 private:
66 DISALLOW_IMPLICIT_CONSTRUCTORS(UdevEnumerateCloser);
67 };
68
69 class UdevDeviceCloser {
70 public:
71 explicit UdevDeviceCloser(UdevInterface* udev_iface,
72 struct udev_device** udev_dev_p)
73 : udev_iface_(udev_iface), udev_dev_p_(udev_dev_p) {
74 CHECK(udev_iface && udev_dev_p);
75 }
76 virtual ~UdevDeviceCloser() {
77 if (*udev_dev_p_) {
78 udev_iface_->DeviceUnref(*udev_dev_p_);
79 *udev_dev_p_ = NULL;
80 }
81 }
82 protected:
83 UdevInterface* udev_iface_;
84 struct udev_device** udev_dev_p_;
85 private:
86 DISALLOW_IMPLICIT_CONSTRUCTORS(UdevDeviceCloser);
87 };
88
89 virtual UdevCloser* NewUdevCloser(struct udev** udev_p) {
90 return new UdevCloser(this, udev_p);
91 }
92 virtual UdevEnumerateCloser* NewUdevEnumerateCloser(
93 struct udev_enumerate** udev_enum_p) {
94 return new UdevEnumerateCloser(this, udev_enum_p);
95 }
96 virtual UdevDeviceCloser* NewUdevDeviceCloser(
97 struct udev_device** udev_dev_p) {
98 return new UdevDeviceCloser(this, udev_dev_p);
99 }
100
101 // Lists.
102 virtual const char* ListEntryGetName(struct udev_list_entry* list_entry) = 0;
103 virtual udev_list_entry* ListEntryGetNext(
104 struct udev_list_entry* list_entry) = 0;
105
106 // Device methods.
107 virtual struct udev_device* DeviceNewFromSyspath(
108 struct udev* udev,
109 const char* syspath) = 0;
110 virtual const char* DeviceGetPropertyValue(struct udev_device* udev_device,
111 const char* key) = 0;
112 virtual const char* DeviceGetSyspath(
113 struct udev_device* udev_device) = 0;
114 virtual void DeviceUnref(struct udev_device* udev_device) = 0;
115
116 // Enumerate methods.
117 virtual struct udev_enumerate* EnumerateNew(struct udev* udev) = 0;
118 virtual int EnumerateAddMatchSubsystem(struct udev_enumerate* udev_enum,
119 const char* subsystem) = 0;
120 virtual int EnumerateAddMatchSysname(struct udev_enumerate* udev_enum,
121 const char* sysname) = 0;
122 virtual int EnumerateScanDevices(struct udev_enumerate* udev_enum) = 0;
123 virtual struct udev_list_entry* EnumerateGetListEntry(
124 struct udev_enumerate* udev_enum) = 0;
125 virtual void EnumerateUnref(struct udev_enumerate* udev_enum) = 0;
126
127 // Udev instance methods.
128 virtual struct udev* New() = 0;
129 virtual void Unref(struct udev* udev) = 0;
130};
131
132
133// Implementation of libudev interface using concrete udev calls.
134class StandardUdevInterface : public UdevInterface {
135 public:
136 // Concrete udev API wrappers utilizing the standard libudev calls.
137 virtual const char* ListEntryGetName(struct udev_list_entry* list_entry) {
138 return udev_list_entry_get_name(list_entry);
139 }
140 virtual struct udev_list_entry* ListEntryGetNext(
141 struct udev_list_entry* list_entry) {
142 return udev_list_entry_get_next(list_entry);
143 }
144
145 virtual struct udev_device* DeviceNewFromSyspath(struct udev* udev,
146 const char* syspath) {
147 return udev_device_new_from_syspath(udev, syspath);
148 }
149 virtual const char* DeviceGetPropertyValue(struct udev_device* udev_device,
150 const char* key) {
151 return udev_device_get_property_value(udev_device, key);
152 }
153 virtual const char* DeviceGetSyspath(struct udev_device* udev_device) {
154 return udev_device_get_syspath(udev_device);
155 }
156 virtual void DeviceUnref(struct udev_device* udev_device) {
157 return udev_device_unref(udev_device);
158 }
159
160 virtual struct udev_enumerate* EnumerateNew(struct udev* udev) {
161 return udev_enumerate_new(udev);
162 }
163 virtual int EnumerateAddMatchSubsystem(struct udev_enumerate* udev_enum,
164 const char* subsystem) {
165 return udev_enumerate_add_match_subsystem(udev_enum, subsystem);
166 }
167 virtual int EnumerateAddMatchSysname(struct udev_enumerate* udev_enum,
168 const char* sysname) {
169 return udev_enumerate_add_match_sysname(udev_enum, sysname);
170 }
171 virtual int EnumerateScanDevices(struct udev_enumerate* udev_enum) {
172 return udev_enumerate_scan_devices(udev_enum);
173 }
174 virtual struct udev_list_entry* EnumerateGetListEntry(
175 struct udev_enumerate* udev_enum) {
176 return udev_enumerate_get_list_entry(udev_enum);
177 }
178 virtual void EnumerateUnref(struct udev_enumerate* udev_enum) {
179 return udev_enumerate_unref(udev_enum);
180 }
181
182 virtual struct udev* New() {
183 return udev_new();
184 }
185 virtual void Unref(struct udev* udev) {
186 return udev_unref(udev);
187 }
188};
189
190} // namespace chromeos_update_engine
191
192#endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_UDEV_INTERFACE_H__
193