From 5eba6d4d65fb5a633f7d0c67a308410a97b6a3ad Mon Sep 17 00:00:00 2001 From: "Jose M. Guisado" Date: Wed, 14 Dec 2022 17:24:11 +0100 Subject: parttype: add parttype class and functions Parttype is a container for partition types in libfdisk. In python-libfdisk, the only way to create parttype instances is using the corresponding label-specific function: get_parttype_from_{code,string} This function wraps libfdisk's label_get_parttype_from_code (lookup DOS label parttype by hex code) and label_get_parttype_from_string (lookup GPT parttype by type uuid) For example, to get the parttype instance of 'EFI System' partition type of a GPT label, with type uuid 'c12a7328-f81f-11d2-ba4b-00a0c93ec93b': >>> import fdisk >>> cxt = fdisk.Context('./disk.bin', readonly=False) >>> cxt.create_disklabel('gpt') >>> efitype = cxt.label.get_parttype_from_string("c12a7328-f81f-11d2-ba4b-00a0c93ec93b") >>> efitype See: https://cdn.kernel.org/pub/linux/utils/util-linux/v2.34/libfdisk-docs/libfdisk-Partition-types.html https://cdn.kernel.org/pub/linux/utils/util-linux/v2.34/libfdisk-docs/libfdisk-Label.html#fdisk-label-get-parttype-from-code https://cdn.kernel.org/pub/linux/utils/util-linux/v2.34/libfdisk-docs/libfdisk-Label.html#fdisk-label-get-parttype-from-string --- fdisk.c | 1 + fdisk.h | 8 ++++++ label.c | 41 ++++++++++++++++++++++++++++++ parttype.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ setup.py | 3 ++- 5 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 parttype.c diff --git a/fdisk.c b/fdisk.c index c44b2f1..909d95c 100644 --- a/fdisk.c +++ b/fdisk.c @@ -66,6 +66,7 @@ PyInit_fdisk(void) Context_AddModuleObject(m); Label_AddModuleObject(m); Partition_AddModuleObject(m); + PartType_AddModuleObject(m); return m; diff --git a/fdisk.h b/fdisk.h index 496b6f7..39b4c95 100644 --- a/fdisk.h +++ b/fdisk.h @@ -39,15 +39,23 @@ typedef struct { struct fdisk_partition *pa; } PartitionObject; +typedef struct { + PyObject_HEAD + struct fdisk_parttype *type; +} PartTypeObject; + extern PyTypeObject ContextType; extern PyTypeObject PartitionType; +extern PyTypeObject PartTypeType; extern void Context_AddModuleObject(PyObject *mod); extern void Label_AddModuleObject(PyObject *mod); extern void Partition_AddModuleObject(PyObject *mod); +extern void PartType_AddModuleObject(PyObject *mod); extern PyObject *PyObjectResultStr(const char *s); extern PyObject *PyObjectResultLabel(struct fdisk_label *lb); extern PyObject *PyObjectResultPartition(struct fdisk_partition *pa); +extern PyObject *PyObjectResultPartType(struct fdisk_parttype *t); #endif diff --git a/label.c b/label.c index 626ca5f..a4bd265 100644 --- a/label.c +++ b/label.c @@ -60,8 +60,49 @@ static int Label_init(LabelObject *self, PyObject *args, PyObject *kwds) return 0; } +#define Label_get_parttype_from_code_HELP "get_parttype_from_code(code)\n\n" \ + "Search for partition type in label-specific table." +static PyObject *Label_get_parttype_from_code(LabelObject *self, PyObject *args, PyObject *kwds) +{ + struct fdisk_parttype *ptype; + unsigned int ptype_code; + + if (!PyArg_ParseTuple(args, "I", &ptype_code)) { + PyErr_SetString(PyExc_TypeError, ARG_ERR); + return NULL; + } + ptype = fdisk_label_get_parttype_from_code(self->lb, ptype_code); + if (!ptype) { + PyErr_Format(PyExc_RuntimeError, "No match for parttype with code: %d", ptype_code); + return NULL; + } + + return PyObjectResultPartType(ptype); +} +#define Label_get_parttype_from_string_HELP "get_parttype_from_string(uuid)\n\n" \ + "Search by string for partition type in label-specific table." +static PyObject *Label_get_parttype_from_string(LabelObject *self, PyObject *args, PyObject *kwds) +{ + struct fdisk_parttype *ptype = NULL; + char *str; + + if (!PyArg_ParseTuple(args, "s", &str)) { + PyErr_SetString(PyExc_TypeError, ARG_ERR); + return NULL; + } + + ptype = fdisk_label_get_parttype_from_string(self->lb, str); + if (!ptype) { + PyErr_Format(PyExc_RuntimeError, "No match for parttype with string: %s", str); + return NULL; + } + + return PyObjectResultPartType(ptype); +} static PyMethodDef Label_methods[] = { + {"get_parttype_from_code", (PyCFunction)Label_get_parttype_from_code, METH_VARARGS, Label_get_parttype_from_code_HELP}, + {"get_parttype_from_string", (PyCFunction)Label_get_parttype_from_string, METH_VARARGS, Label_get_parttype_from_string_HELP}, {NULL} }; diff --git a/parttype.c b/parttype.c new file mode 100644 index 0000000..e3c6238 --- /dev/null +++ b/parttype.c @@ -0,0 +1,86 @@ +/* + * (C) 2022 Soleta Consulting S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Author: Jose M. Guisado + */ + +#include "fdisk.h" + +static PyMemberDef PartType_members[] = { + { NULL } +}; + +static void PartType_dealloc(PartTypeObject *self) +{ + Py_TYPE(self)->tp_free((PyObject *) self); +} + +static PyMethodDef PartType_methods[] = { + {NULL} +}; + +static PyObject *PartType_get_name(PartTypeObject *self) +{ + return PyObjectResultStr(fdisk_parttype_get_name(self->type)); +} +static PyObject *PartType_get_code(PartTypeObject *self) +{ + return PyLong_FromUnsignedLong(fdisk_parttype_get_code(self->type)); +} +static PyGetSetDef PartType_getseters[] = { + {"name", (getter)PartType_get_name, NULL, "parttype human readable name", NULL}, + {"code", (getter)PartType_get_code, NULL, "parttype DOS code", NULL}, + {NULL} +}; + +static PyObject *PartType_repr(PartTypeObject *self) +{ + return PyUnicode_FromFormat("", + self, fdisk_parttype_get_name(self->type)); +} + +PyTypeObject PartTypeType = { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = "libfdisk.PartType", + .tp_basicsize = sizeof(PartTypeObject), + .tp_dealloc = (destructor)PartType_dealloc, + .tp_repr = (reprfunc) PartType_repr, + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + /* TODO: .tp_doc = PartType_HELP, */ + .tp_methods = PartType_methods, + .tp_members = PartType_members, + .tp_getset = PartType_getseters, +}; + +PyObject *PyObjectResultPartType(struct fdisk_parttype *t) +{ + PartTypeObject *result; + + if (!t) { + PyErr_SetString(PyExc_AssertionError, "lb assert failed"); + return NULL; + } + + result = PyObject_New(PartTypeObject, &PartTypeType); + if (!result) { + PyErr_SetString(PyExc_MemoryError, "Couldn't allocate PartType object"); + return NULL; + } + + result->type = t; + return (PyObject *) result; +} + +void PartType_AddModuleObject(PyObject *mod) +{ + if (PyType_Ready(&PartTypeType) < 0) + return; + + Py_INCREF(&PartTypeType); + PyModule_AddObject(mod, "PartType", (PyObject *)&PartTypeType); +} diff --git a/setup.py b/setup.py index aed3664..d360edf 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,8 @@ from setuptools import setup, Extension libfdisk = Extension('fdisk', libraries = ['fdisk'], - sources = ['fdisk.c', 'context.c', 'label.c', 'partition.c']) + sources = ['fdisk.c', 'context.c', 'label.c', + 'partition.c', 'parttype.c']) setup (name = 'libfdisk', version = '1.0', -- cgit v1.2.3-18-g5258