blob: 4b8fc17c19450baba50b74a148cd4ab4bbd466dc [file] [log] [blame]
// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_UDEV_INTERFACE_H__
#define CHROMEOS_PLATFORM_UPDATE_ENGINE_UDEV_INTERFACE_H__
#include <libudev.h>
#include "update_engine/utils.h"
// An interface for libudev calls, allowing to easily mock it.
namespace chromeos_update_engine {
// An interface for libudev methods that are being used in update engine.
//
// TODO(garnold) As is, this is a pretty lame indirection layer that otherwise
// does not provide any better abstraction than the existing libudev API. Done
// properly, we should replace it with encapsulated udev, enumerate and device
// objects, and hide initialization, reference handling and iterators in ways
// more appropriate to an object-oriented setting...
class UdevInterface {
public:
virtual ~UdevInterface() {}
// Interfaces for various udev closers. All of these are merely containers for
// a single pointer to some udev handle, which invoke the provided interface's
// unref method and nullify the handle upon destruction. It should suffice for
// derivative (concrete) interfaces to implement the various unref methods to
// fit their needs, making these closers behave as expected.
class UdevCloser {
public:
explicit UdevCloser(UdevInterface* udev_iface, struct udev** udev_p)
: udev_iface_(udev_iface), udev_p_(udev_p) {
CHECK(udev_iface && udev_p);
}
virtual ~UdevCloser() {
if (*udev_p_) {
udev_iface_->Unref(*udev_p_);
*udev_p_ = NULL;
}
}
protected:
UdevInterface* udev_iface_;
struct udev** udev_p_;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(UdevCloser);
};
class UdevEnumerateCloser {
public:
explicit UdevEnumerateCloser(UdevInterface* udev_iface,
struct udev_enumerate** udev_enum_p)
: udev_iface_(udev_iface), udev_enum_p_(udev_enum_p) {
CHECK(udev_iface && udev_enum_p);
}
virtual ~UdevEnumerateCloser() {
if (*udev_enum_p_) {
udev_iface_->EnumerateUnref(*udev_enum_p_);
*udev_enum_p_ = NULL;
}
}
protected:
UdevInterface* udev_iface_;
struct udev_enumerate** udev_enum_p_;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(UdevEnumerateCloser);
};
class UdevDeviceCloser {
public:
explicit UdevDeviceCloser(UdevInterface* udev_iface,
struct udev_device** udev_dev_p)
: udev_iface_(udev_iface), udev_dev_p_(udev_dev_p) {
CHECK(udev_iface && udev_dev_p);
}
virtual ~UdevDeviceCloser() {
if (*udev_dev_p_) {
udev_iface_->DeviceUnref(*udev_dev_p_);
*udev_dev_p_ = NULL;
}
}
protected:
UdevInterface* udev_iface_;
struct udev_device** udev_dev_p_;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(UdevDeviceCloser);
};
virtual UdevCloser* NewUdevCloser(struct udev** udev_p) {
return new UdevCloser(this, udev_p);
}
virtual UdevEnumerateCloser* NewUdevEnumerateCloser(
struct udev_enumerate** udev_enum_p) {
return new UdevEnumerateCloser(this, udev_enum_p);
}
virtual UdevDeviceCloser* NewUdevDeviceCloser(
struct udev_device** udev_dev_p) {
return new UdevDeviceCloser(this, udev_dev_p);
}
// Lists.
virtual const char* ListEntryGetName(struct udev_list_entry* list_entry) = 0;
virtual udev_list_entry* ListEntryGetNext(
struct udev_list_entry* list_entry) = 0;
// Device methods.
virtual struct udev_device* DeviceNewFromSyspath(
struct udev* udev,
const char* syspath) = 0;
virtual const char* DeviceGetPropertyValue(struct udev_device* udev_device,
const char* key) = 0;
virtual const char* DeviceGetSyspath(
struct udev_device* udev_device) = 0;
virtual void DeviceUnref(struct udev_device* udev_device) = 0;
// Enumerate methods.
virtual struct udev_enumerate* EnumerateNew(struct udev* udev) = 0;
virtual int EnumerateAddMatchSubsystem(struct udev_enumerate* udev_enum,
const char* subsystem) = 0;
virtual int EnumerateAddMatchSysname(struct udev_enumerate* udev_enum,
const char* sysname) = 0;
virtual int EnumerateScanDevices(struct udev_enumerate* udev_enum) = 0;
virtual struct udev_list_entry* EnumerateGetListEntry(
struct udev_enumerate* udev_enum) = 0;
virtual void EnumerateUnref(struct udev_enumerate* udev_enum) = 0;
// Udev instance methods.
virtual struct udev* New() = 0;
virtual void Unref(struct udev* udev) = 0;
};
// Implementation of libudev interface using concrete udev calls.
class StandardUdevInterface : public UdevInterface {
public:
virtual ~StandardUdevInterface() {}
// Concrete udev API wrappers utilizing the standard libudev calls.
virtual const char* ListEntryGetName(struct udev_list_entry* list_entry) {
return udev_list_entry_get_name(list_entry);
}
virtual struct udev_list_entry* ListEntryGetNext(
struct udev_list_entry* list_entry) {
return udev_list_entry_get_next(list_entry);
}
virtual struct udev_device* DeviceNewFromSyspath(struct udev* udev,
const char* syspath) {
return udev_device_new_from_syspath(udev, syspath);
}
virtual const char* DeviceGetPropertyValue(struct udev_device* udev_device,
const char* key) {
return udev_device_get_property_value(udev_device, key);
}
virtual const char* DeviceGetSyspath(struct udev_device* udev_device) {
return udev_device_get_syspath(udev_device);
}
virtual void DeviceUnref(struct udev_device* udev_device) {
return udev_device_unref(udev_device);
}
virtual struct udev_enumerate* EnumerateNew(struct udev* udev) {
return udev_enumerate_new(udev);
}
virtual int EnumerateAddMatchSubsystem(struct udev_enumerate* udev_enum,
const char* subsystem) {
return udev_enumerate_add_match_subsystem(udev_enum, subsystem);
}
virtual int EnumerateAddMatchSysname(struct udev_enumerate* udev_enum,
const char* sysname) {
return udev_enumerate_add_match_sysname(udev_enum, sysname);
}
virtual int EnumerateScanDevices(struct udev_enumerate* udev_enum) {
return udev_enumerate_scan_devices(udev_enum);
}
virtual struct udev_list_entry* EnumerateGetListEntry(
struct udev_enumerate* udev_enum) {
return udev_enumerate_get_list_entry(udev_enum);
}
virtual void EnumerateUnref(struct udev_enumerate* udev_enum) {
return udev_enumerate_unref(udev_enum);
}
virtual struct udev* New() {
return udev_new();
}
virtual void Unref(struct udev* udev) {
return udev_unref(udev);
}
};
} // namespace chromeos_update_engine
#endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_UDEV_INTERFACE_H__