summaryrefslogtreecommitdiff
path: root/diskman
diff options
context:
space:
mode:
Diffstat (limited to 'diskman')
-rw-r--r--diskman/CMakeLists.txt22
-rw-r--r--diskman/disk.cc67
-rw-r--r--diskman/disk.hh96
-rw-r--r--diskman/diskman.cc81
-rw-r--r--diskman/diskman.hh44
-rw-r--r--diskman/lvmhelp.cc0
-rw-r--r--diskman/lvmhelp.hh0
-rw-r--r--diskman/partition.cc0
-rw-r--r--diskman/partition.hh0
9 files changed, 310 insertions, 0 deletions
diff --git a/diskman/CMakeLists.txt b/diskman/CMakeLists.txt
new file mode 100644
index 0000000..ea0c5fe
--- /dev/null
+++ b/diskman/CMakeLists.txt
@@ -0,0 +1,22 @@
+pkg_check_modules(FDISK REQUIRED fdisk)
+find_package(Boost REQUIRED)
+
+set(DISKMAN_SOURCE
+ diskman.cc
+ disk.cc
+ lvmhelp.cc
+ partition.cc
+)
+
+set(DISKMAN_INCLUDE
+ diskman.hh
+ disk.hh
+ partition.hh
+)
+
+include_directories(${Boost_INCLUDE_DIRS})
+add_library(diskman ${DISKMAN_SOURCE})
+target_link_libraries(diskman ${FDISK_LIBRARIES} ${LIBUDEV_LIBRARIES})
+
+install(TARGETS diskman DESTINATION lib)
+install(FILES ${DISKMAN_INCLUDE} DESTINATION include/diskman)
diff --git a/diskman/disk.cc b/diskman/disk.cc
new file mode 100644
index 0000000..ddb357f
--- /dev/null
+++ b/diskman/disk.cc
@@ -0,0 +1,67 @@
+/*
+ * disk.cc - Implementation of the Disk class
+ * diskman, the Disk Manipulation library for
+ * Project Horizon
+ *
+ * Copyright (c) 2020 Adélie Linux and contributors. All rights reserved.
+ * This code is licensed under the AGPL 3.0 license, as noted in the
+ * LICENSE-code file in the root directory of this repository.
+ *
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+#include "disk.hh"
+
+#include <cstring>
+#include <libudev.h>
+
+namespace Horizon {
+namespace DiskMan {
+
+/*! The full serial number of the disk */
+std::string _full_serial;
+
+#define SAFE_SET(ivar, udev_call) \
+ value = udev_call;\
+ if(value != nullptr) {\
+ ivar = std::string(value);\
+ }
+
+Disk::Disk(void *creation, bool partition) {
+ struct udev_device *device = static_cast<struct udev_device *>(creation);
+ const char *value;
+
+ SAFE_SET(_name, udev_device_get_sysname(device));
+ SAFE_SET(_model, udev_device_get_property_value(device, "ID_MODEL"));
+ SAFE_SET(_node, udev_device_get_devnode(device));
+ SAFE_SET(_devpath, udev_device_get_devpath(device));
+
+ value = udev_device_get_property_value(device, "ID_PART_TABLE_TYPE");
+ if(value == nullptr) {
+ _has_label = false;
+ _label = Unknown;
+ } else {
+ _has_label = true;
+ if(::strcmp(value, "apm") == 0) {
+ _label = APM;
+ } else if(::strcmp(value, "dos") == 0) {
+ _label = MBR;
+ } else if(::strcmp(value, "gpt") == 0) {
+ _label = GPT;
+ } else {
+ _label = Unknown;
+ }
+ }
+
+ value = udev_device_get_property_value(device, "ID_FS_TYPE");
+ if(value == nullptr) {
+ _has_fs = false;
+ } else {
+ _has_fs = true;
+ _fs_type = std::string(value);
+ SAFE_SET(_fs_label, udev_device_get_property_value(device, "ID_FS_LABEL"));
+ }
+}
+
+}
+}
diff --git a/diskman/disk.hh b/diskman/disk.hh
new file mode 100644
index 0000000..dcb9793
--- /dev/null
+++ b/diskman/disk.hh
@@ -0,0 +1,96 @@
+/*
+ * disk.hh - Public definition of the Disk class
+ * diskman, the Disk Manipulation library for
+ * Project Horizon
+ *
+ * Copyright (c) 2020 Adélie Linux and contributors. All rights reserved.
+ * This code is licensed under the AGPL 3.0 license, as noted in the
+ * LICENSE-code file in the root directory of this repository.
+ *
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+#ifndef DISKMAN__DISK_HH
+#define DISKMAN__DISK_HH
+
+#include <memory>
+#include <string>
+
+namespace Horizon {
+namespace DiskMan {
+
+/*! Represents a fixed disk device. */
+class Disk {
+public:
+ /*! Potential disk label types */
+ enum Label {
+ /*! GUID Partition Table, common on x86 and POWER */
+ GPT,
+ /*! Master Boot Record, common on x86 and ARM */
+ MBR,
+ /*! Apple Partition Map, common on POWER */
+ APM,
+ /*! Unknown disk label type */
+ Unknown
+ };
+
+ /*! Retrieve the disk's name. For instance, "sda" or "nvme0n1". */
+ const std::string name() const { return this->_name; }
+ /*! Retrieve the disk's model. This is specified by the vendor. */
+ const std::string model() const { return this->_model; }
+ /*! Retrieve the disk's serial number. This may be equivalent to
+ * the model name, if the vendor did not specify a serial number. */
+ const std::string serial() const { return this->_full_serial; }
+ /*! Retrieve the device node for this disk. For instance, "/dev/sda". */
+ const std::string node() const { return this->_node; }
+ /*! Retrieve the system device path for this disk. */
+ const std::string dev_path() const { return this->_devpath; }
+
+ /*! Determine if this disk has a disk label attached. */
+ bool has_label() const { return this->_has_label; }
+ /*! Retrieve the type of disk label in use on this disk.
+ * Only valid if has_label() is true. */
+ enum Label label() const { return this->_label; }
+
+ /*! Determine if this disk has a file system written to it.
+ * If this method returns true, the file system is directly written to
+ * the disk; it is not a partition inside a disklabel. */
+ bool has_fs() const { return this->_has_fs; }
+ /*! Retrieve the type of file system written on this disk.
+ * Only valid if has_fs() is true. */
+ const std::string fs_type() const { return this->_fs_type; }
+ /*! Retrieve the label of the file system written on this disk.
+ * Only valid if has_fs() is true. */
+ const std::string fs_label() const { return this->_fs_label; }
+private:
+ /*! The name of the disk ("sda") */
+ std::string _name;
+ /*! The model name of the disk ("WDC WDBNCE2500PNC") */
+ std::string _model;
+ /*! The full serial number of the disk */
+ std::string _full_serial;
+ /*! The device node of the disk ("/dev/sda") */
+ std::string _node;
+ /*! The device path of the disk ("/sys/devices/...") */
+ std::string _devpath;
+
+ /*! Whether this disk has a disklabel */
+ bool _has_label;
+ /*! The type of disk label used, if +has_label+ is true */
+ enum Label _label;
+
+ /*! Whether this disk has a direct filesystem (non-labelled) */
+ bool _has_fs;
+ /*! The type of file system in use, if +has_fs+ is true */
+ std::string _fs_type;
+ /*! The label of the file system, if +has_fs+ is true */
+ std::string _fs_label;
+
+ Disk(void *creation, bool partition);
+ friend class DiskMan;
+};
+
+}
+}
+
+#endif /* !DISKMAN__DISK_HH */
diff --git a/diskman/diskman.cc b/diskman/diskman.cc
new file mode 100644
index 0000000..32a2c40
--- /dev/null
+++ b/diskman/diskman.cc
@@ -0,0 +1,81 @@
+/*
+ * diskman.cc - Common routines for the DiskMan library
+ * diskman, the Disk Manipulation library for
+ * Project Horizon
+ *
+ * Copyright (c) 2020 Adélie Linux and contributors. All rights reserved.
+ * This code is licensed under the AGPL 3.0 license, as noted in the
+ * LICENSE-code file in the root directory of this repository.
+ *
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+#include "diskman.hh"
+
+#include <iostream>
+#include <libudev.h>
+
+namespace Horizon {
+namespace DiskMan {
+
+struct DiskMan::impl {
+ struct udev *udev;
+
+ impl() {
+ udev = udev_new();
+ }
+ ~impl() {
+ udev_unref(udev);
+ }
+ impl(const impl &other) {
+ this->udev = udev_ref(other.udev);
+ }
+};
+
+DiskMan::DiskMan() : pImpl {std::make_unique<impl>()} {
+}
+
+DiskMan::~DiskMan() = default;
+
+std::vector<Disk> DiskMan::find_disks(bool include_part, bool include_vg,
+ bool include_lvm) {
+ struct udev_enumerate *disk_enum = udev_enumerate_new(pImpl->udev);
+ struct udev_list_entry *first, *item;
+ struct udev_device *device = nullptr;
+ std::vector<Disk> disks;
+
+ if(disk_enum == nullptr) {
+ std::cerr << "Couldn't connect to udev" << std::endl;
+ return {};
+ }
+ udev_enumerate_add_match_subsystem(disk_enum, "block");
+ udev_enumerate_add_match_property(disk_enum, "DEVTYPE", "disk");
+ udev_enumerate_scan_devices(disk_enum);
+ first = udev_enumerate_get_list_entry(disk_enum);
+ if(first == NULL) {
+ std::cerr << "No block devices found" << std::endl;
+ return {};
+ }
+
+ udev_list_entry_foreach(item, first) {
+ const char *path = udev_list_entry_get_name(item);
+ if(device != NULL) udev_device_unref(device);
+ device = udev_device_new_from_syspath(pImpl->udev, path);
+ std::string name(udev_device_get_sysname(device));
+ if(name.compare(0, 4, "loop") == 0
+ || name.compare(0, 3, "ram") == 0) {
+ /* Don't include loop or ram devices */
+ continue;
+ }
+ if(!include_lvm && name.compare(0, 3, "dm-") == 0) {
+ /* Skip LVM volumes if requested. */
+ continue;
+ }
+ disks.push_back(Disk(device, include_part));
+ }
+
+ return disks;
+}
+
+}
+}
diff --git a/diskman/diskman.hh b/diskman/diskman.hh
new file mode 100644
index 0000000..ba9d4be
--- /dev/null
+++ b/diskman/diskman.hh
@@ -0,0 +1,44 @@
+/*
+ * diskman.hh - Public interface for the DiskMan library
+ * diskman, the Disk Manipulation library for
+ * Project Horizon
+ *
+ * Copyright (c) 2020 Adélie Linux and contributors. All rights reserved.
+ * This code is licensed under the AGPL 3.0 license, as noted in the
+ * LICENSE-code file in the root directory of this repository.
+ *
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+#ifndef DISKMAN__DISKMAN_HH
+#define DISKMAN__DISKMAN_HH
+
+#include <memory>
+#include <vector>
+
+#include "disk.hh"
+
+namespace Horizon {
+namespace DiskMan {
+
+class DiskMan {
+ struct impl;
+ std::unique_ptr<impl> pImpl;
+public:
+ DiskMan();
+ ~DiskMan();
+
+ /*! Find all available disks on this system.
+ * @param include_part Include partitions with disks.
+ * @param include_vg Include LVM volume groups as disks.
+ * @param include_lvm Include LVM volumes as disks.
+ */
+ std::vector<Disk> find_disks(bool include_part = true,
+ bool include_vg = true,
+ bool include_lvm = false);
+};
+
+}
+}
+
+#endif /* !DISKMAN__DISKMAN_HH */
diff --git a/diskman/lvmhelp.cc b/diskman/lvmhelp.cc
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/diskman/lvmhelp.cc
diff --git a/diskman/lvmhelp.hh b/diskman/lvmhelp.hh
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/diskman/lvmhelp.hh
diff --git a/diskman/partition.cc b/diskman/partition.cc
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/diskman/partition.cc
diff --git a/diskman/partition.hh b/diskman/partition.hh
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/diskman/partition.hh