250 lines
6.4 KiB
C
250 lines
6.4 KiB
C
/*
|
|
* (C) 2022 Soleta Consulting S.L. <info@soleta.eu>
|
|
*
|
|
* 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 <jguisado@soleta.eu>
|
|
*/
|
|
|
|
|
|
#include "fdisk.h"
|
|
|
|
static PyMemberDef Context_members[] = {
|
|
{ NULL }
|
|
};
|
|
|
|
|
|
static void Context_dealloc(ContextObject *self)
|
|
{
|
|
if (!self->cxt) /* if init fails */
|
|
return;
|
|
|
|
fdisk_unref_context(self->cxt);
|
|
Py_TYPE(self)->tp_free((PyObject *) self);
|
|
}
|
|
|
|
static PyObject *Context_new(PyTypeObject *type,
|
|
PyObject *args __attribute__((unused)),
|
|
PyObject *kwds __attribute__((unused)))
|
|
{
|
|
ContextObject *self = (ContextObject*) type->tp_alloc(type, 0);
|
|
|
|
if (self) {
|
|
self->cxt = NULL;
|
|
self->lb = NULL;
|
|
self->tb = NULL;
|
|
}
|
|
|
|
return (PyObject *)self;
|
|
}
|
|
|
|
#define Context_HELP "Context(device=None, details=None)"
|
|
static int Context_init(ContextObject *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
char *device = NULL;
|
|
int details, rc = 0;
|
|
char *kwlist[] = {
|
|
"device", "details",
|
|
NULL
|
|
};
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args,
|
|
kwds, "|sp", kwlist,
|
|
&device, &details)) {
|
|
PyErr_SetString(PyExc_TypeError, ARG_ERR);
|
|
return -1;
|
|
}
|
|
|
|
if (self->cxt)
|
|
fdisk_unref_context(self->cxt);
|
|
|
|
self->cxt = fdisk_new_context();
|
|
if (!self->cxt) {
|
|
PyErr_SetString(PyExc_MemoryError, "Couldn't allocate context");
|
|
return -1;
|
|
}
|
|
|
|
/* XXX: always readonly */
|
|
if (device && (rc = fdisk_assign_device(self->cxt, device, 1)))
|
|
return -1;
|
|
if (details && (rc = fdisk_enable_details(self->cxt, details)))
|
|
return -1;
|
|
|
|
fdisk_get_partitions(self->cxt, &self->tb);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
#define Context_assign_device_HELP "assign_device(device)\n\n" \
|
|
"Open the device, discovery topology, geometry, detect disklabel " \
|
|
"and switch the current label driver to reflect the probing result. "
|
|
static PyObject *Context_assign_device(ContextObject *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
char *fname;
|
|
|
|
if (!PyArg_ParseTuple(args, "s", &fname)) {
|
|
PyErr_SetString(PyExc_TypeError, ARG_ERR);
|
|
return NULL;
|
|
}
|
|
|
|
/* Assert self->cxt */
|
|
|
|
/* XXX: readonly */
|
|
fdisk_assign_device(self->cxt, fname, 1);
|
|
|
|
self->lb = fdisk_get_label(self->cxt, NULL);
|
|
fdisk_get_partitions(self->cxt, &self->tb);
|
|
|
|
/* XXX: check rc*/
|
|
Py_INCREF(Py_None);
|
|
return Py_None;
|
|
}
|
|
#define Context_partition_to_string_HELP "partition_to_string(pa, field)\n\n" \
|
|
"Retrieve partition field using fdisk_partition_to_string." \
|
|
"Field constants are available as FDISK_LABEL_*"
|
|
static PyObject *Context_partition_to_string(ContextObject *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
struct fdisk_partition *pa;
|
|
enum fdisk_fieldtype field;
|
|
PartitionObject *part;
|
|
PyObject *ret;
|
|
char *data;
|
|
|
|
if (!PyArg_ParseTuple(args, "O!i", &PartitionType, &part, &field)) {
|
|
PyErr_SetString(PyExc_TypeError, ARG_ERR);
|
|
return NULL;
|
|
}
|
|
|
|
pa = part->pa;
|
|
|
|
fdisk_partition_to_string(pa, self->cxt, field, &data);
|
|
ret = Py_BuildValue("s", data);
|
|
free(data);
|
|
|
|
return ret;
|
|
}
|
|
static PyMethodDef Context_methods[] = {
|
|
{"assign_device", (PyCFunction)Context_assign_device, METH_VARARGS, Context_assign_device_HELP},
|
|
{"partition_to_string", (PyCFunction)Context_partition_to_string, METH_VARARGS, Context_partition_to_string_HELP},
|
|
{NULL}
|
|
};
|
|
|
|
|
|
static PyObject *Context_get_nsectors(ContextObject *self)
|
|
{
|
|
return PyLong_FromUnsignedLong(fdisk_get_nsectors(self->cxt));
|
|
}
|
|
static PyObject *Context_get_sector_size(ContextObject *self)
|
|
{
|
|
return PyLong_FromUnsignedLong(fdisk_get_sector_size(self->cxt));
|
|
}
|
|
static PyObject *Context_get_devname(ContextObject *self)
|
|
{
|
|
return PyObjectResultStr(fdisk_get_devname(self->cxt));
|
|
}
|
|
static PyObject *Context_get_label(ContextObject *self)
|
|
{
|
|
struct fdisk_context *cxt = self->cxt;
|
|
|
|
if (fdisk_has_label(cxt)) {
|
|
return PyObjectResultLabel(fdisk_get_label(cxt, NULL));
|
|
} else {
|
|
Py_RETURN_NONE;
|
|
}
|
|
}
|
|
static PyObject *Context_get_nparts(ContextObject *self)
|
|
{
|
|
return PyLong_FromLong(fdisk_table_get_nents(self->tb));
|
|
}
|
|
static PyObject *Context_get_partitions(ContextObject *self)
|
|
{
|
|
PyObject *p, *list = PyList_New(0); /* XXX: null if failed*/
|
|
struct fdisk_partition *pa;
|
|
struct fdisk_iter *itr;
|
|
struct fdisk_table *tb;
|
|
/* char *data; */
|
|
|
|
tb = self->tb;
|
|
itr = fdisk_new_iter(FDISK_ITER_FORWARD);
|
|
|
|
while(fdisk_table_next_partition(tb, itr, &pa) == 0) {
|
|
/* const char *name = fdisk_partition_get_name(pa);*/
|
|
p = PyObjectResultPartition(pa);
|
|
PyList_Append(list, p);
|
|
/*free(data);*/
|
|
}
|
|
|
|
fdisk_free_iter(itr);
|
|
|
|
return list;
|
|
}
|
|
static PyGetSetDef Context_getseters[] = {
|
|
{"nsectors", (getter)Context_get_nsectors, NULL, "context number of sectors", NULL},
|
|
{"sector_size", (getter)Context_get_sector_size, NULL, "context sector size", NULL},
|
|
{"devname", (getter)Context_get_devname, NULL, "context devname", NULL},
|
|
{"label", (getter)Context_get_label, NULL, "context label type", NULL},
|
|
{"nparts", (getter)Context_get_nparts, NULL, "context label number of existing partitions", NULL},
|
|
{"partitions", (getter)Context_get_partitions, NULL, "context partitions", NULL},
|
|
{NULL}
|
|
};
|
|
|
|
static PyObject *Context_repr(ContextObject *self)
|
|
{
|
|
return PyUnicode_FromFormat("<libfdisk.Context object at %p, details=%s>",
|
|
self, fdisk_is_details(self->cxt) ? "True" : "False");
|
|
}
|
|
|
|
PyTypeObject ContextType = {
|
|
PyVarObject_HEAD_INIT(NULL, 0)
|
|
"libfdisk.Context", /*tp_name*/
|
|
sizeof(ContextObject), /*tp_basicsize*/
|
|
0, /*tp_itemsize*/
|
|
(destructor)Context_dealloc, /*tp_dealloc*/
|
|
0, /*tp_print*/
|
|
NULL, /*tp_getattr*/
|
|
NULL, /*tp_setattr*/
|
|
NULL, /*tp_compare*/
|
|
(reprfunc) Context_repr,
|
|
NULL, /*tp_as_number*/
|
|
NULL, /*tp_as_sequence*/
|
|
NULL, /*tp_as_mapping*/
|
|
NULL, /*tp_hash */
|
|
NULL, /*tp_call*/
|
|
NULL, /*tp_str*/
|
|
NULL, /*tp_getattro*/
|
|
NULL, /*tp_setattro*/
|
|
NULL, /*tp_as_buffer*/
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
|
|
Context_HELP, /* tp_doc */
|
|
NULL, /* tp_traverse */
|
|
NULL, /* tp_clear */
|
|
NULL, /* tp_richcompare */
|
|
0, /* tp_weaklistoffset */
|
|
NULL, /* tp_iter */
|
|
NULL, /* tp_iternext */
|
|
Context_methods, /* tp_methods */
|
|
Context_members, /* tp_members */
|
|
Context_getseters, /* tp_getset */
|
|
NULL, /* tp_base */
|
|
NULL, /* tp_dict */
|
|
NULL, /* tp_descr_get */
|
|
NULL, /* tp_descr_set */
|
|
0, /* tp_dictoffset */
|
|
(initproc)Context_init, /* tp_init */
|
|
NULL, /* tp_alloc */
|
|
Context_new, /* tp_new */
|
|
};
|
|
|
|
void Context_AddModuleObject(PyObject *mod)
|
|
{
|
|
if (PyType_Ready(&ContextType) < 0)
|
|
return;
|
|
|
|
Py_INCREF(&ContextType);
|
|
PyModule_AddObject(mod, "Context", (PyObject *)&ContextType);
|
|
}
|