Initial commit

Add sources, setup.py and .gitignore

Build/Install:

	python setup.py build
	python setup.py install
master
Jose M. Guisado Gomez 2022-04-06 11:31:30 +02:00
commit ca92f15e2a
7 changed files with 796 additions and 0 deletions

153
.gitignore vendored 100644
View File

@ -0,0 +1,153 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/#use-with-ide
.pdm.toml
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/

237
context.c 100644
View File

@ -0,0 +1,237 @@
#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_parts(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},
{"parts", (getter)Context_get_parts, 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);
}

59
fdisk.c 100644
View File

@ -0,0 +1,59 @@
#include <dirent.h>
#include "fdisk.h"
PyObject *PyObjectResultStr(const char *s)
{
PyObject *result;
if (!s)
/* TODO: maybe lie about it and return "":
* which would allow for
* fs = libmount.Fs()
* fs.comment += "comment"
return Py_BuildValue("s", ""); */
Py_RETURN_NONE;
result = Py_BuildValue("s", s);
if (!result)
PyErr_SetString(PyExc_RuntimeError, CONSTRUCT_ERR);
return result;
}
static PyMethodDef FdiskMethods[] = {
{NULL, NULL, 0, NULL} /* Sentinel */
};
static struct PyModuleDef fdiskmodule = {
PyModuleDef_HEAD_INIT,
"fdisk", /* name of module */
NULL, /* module documentation, may be NULL */
-1, /* size of per-interpreter state of the module,
or -1 if the module keeps state in global variables. */
FdiskMethods
};
PyMODINIT_FUNC
PyInit_fdisk(void)
{
PyObject *m = PyModule_Create(&fdiskmodule);
PyModule_AddIntConstant(m, "FDISK_SIZEUNIT_BYTES", FDISK_SIZEUNIT_BYTES);
PyModule_AddIntConstant(m, "FDISK_SIZEUNIT_HUMAN", FDISK_SIZEUNIT_HUMAN);
PyModule_AddIntConstant(m, "FDISK_FIELD_DEVICE", FDISK_FIELD_DEVICE);
PyModule_AddIntConstant(m, "FDISK_FIELD_SIZE", FDISK_FIELD_SIZE);
PyModule_AddIntConstant(m, "FDISK_FIELD_TYPE", FDISK_FIELD_TYPE);
PyModule_AddIntConstant(m, "FDISK_FIELD_TYPEID", FDISK_FIELD_TYPEID);
PyModule_AddIntConstant(m, "FDISK_FIELD_FSTYPE", FDISK_FIELD_FSTYPE);
PyModule_AddIntConstant(m, "FDISK_DISKLABEL_DOS", FDISK_DISKLABEL_DOS);
PyModule_AddIntConstant(m, "FDISK_DISKLABEL_GPT", FDISK_DISKLABEL_GPT);
PyModule_AddIntConstant(m, "FDISK_ITER_FORWARD", FDISK_ITER_FORWARD);
PyModule_AddIntConstant(m, "FDISK_ITER_BACKWARD", FDISK_ITER_BACKWARD);
Context_AddModuleObject(m);
Label_AddModuleObject(m);
return m;
}

40
fdisk.h 100644
View File

@ -0,0 +1,40 @@
#ifndef UTIL_LINUX_PYLIBFDISK_H
#define UTIL_LINUX_PYLIBFDISK_H
#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include <structmember.h>
#include <libfdisk/libfdisk.h>
#define CONSTRUCT_ERR "Error during object construction"
#define ARG_ERR "Invalid number or type of arguments"
typedef struct {
PyObject_HEAD
struct fdisk_context *cxt;
struct fdisk_label *lb;
struct fdisk_table *tb;
} ContextObject;
typedef struct {
PyObject_HEAD
struct fdisk_label *lb;
} LabelObject;
typedef struct {
PyObject_HEAD
struct fdisk_partition *pa;
} PartitionObject;
extern PyTypeObject ContextType;
extern PyTypeObject PartitionType;
extern void Context_AddModuleObject(PyObject *mod);
extern void Label_AddModuleObject(PyObject *mod);
extern PyObject *PyObjectResultStr(const char *s);
extern PyObject *PyObjectResultLabel(struct fdisk_label *lb);
extern PyObject *PyObjectResultPartition(struct fdisk_partition *pa);
#endif

147
label.c 100644
View File

@ -0,0 +1,147 @@
#include "fdisk.h"
static PyMemberDef Label_members[] = {
{ NULL }
};
static void Label_dealloc(LabelObject *self)
{
Py_TYPE(self)->tp_free((PyObject *) self);
}
static PyObject *Label_new(PyTypeObject *type,
PyObject *args __attribute__((unused)),
PyObject *kwds __attribute__((unused)))
{
LabelObject *self = (LabelObject*) type->tp_alloc(type, 0);
if (self) {
self->lb = NULL;
}
return (PyObject *)self;
}
#define Label_HELP "Label(context=None)"
static int Label_init(LabelObject *self, PyObject *args, PyObject *kwds)
{
ContextObject *cxt = NULL;
struct fdisk_label *lb;
char *kwlist[] = {
"context",
NULL
};
if (!PyArg_ParseTupleAndKeywords(args,
kwds, "|O!", kwlist,
&ContextType, &cxt)) {
PyErr_SetString(PyExc_TypeError, "Error");
return -1;
}
if (cxt && (lb = fdisk_get_label(cxt->cxt, NULL))) {
self->lb = lb;
}
return 0;
}
static PyMethodDef Label_methods[] = {
{NULL}
};
static PyObject *Label_get_type(LabelObject *self)
{
return PyLong_FromLong(fdisk_label_get_type(self->lb));
}
static PyObject *Label_get_name(LabelObject *self)
{
return PyObjectResultStr(fdisk_label_get_name(self->lb));
}
static PyGetSetDef Label_getseters[] = {
{"type", (getter)Label_get_type, NULL, "label type", NULL},
{"name", (getter)Label_get_name, NULL, "label name", NULL},
{NULL}
};
static PyObject *Label_repr(LabelObject *self)
{
return PyUnicode_FromFormat("<libfdisk.Label object at %p, name=%s>",
self, fdisk_label_get_name(self->lb));
}
PyTypeObject LabelType = {
PyVarObject_HEAD_INIT(NULL, 0)
"libfdisk.Label", /*tp_name*/
sizeof(LabelObject), /*tp_basicsize*/
0, /*tp_itemsize*/
(destructor)Label_dealloc, /*tp_dealloc*/
0, /*tp_print*/
NULL, /*tp_getattr*/
NULL, /*tp_setattr*/
NULL, /*tp_compare*/
(reprfunc) Label_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*/
Label_HELP, /* tp_doc */
NULL, /* tp_traverse */
NULL, /* tp_clear */
NULL, /* tp_richcompare */
0, /* tp_weaklistoffset */
NULL, /* tp_iter */
NULL, /* tp_iternext */
Label_methods, /* tp_methods */
Label_members, /* tp_members */
Label_getseters, /* tp_getset */
NULL, /* tp_base */
NULL, /* tp_dict */
NULL, /* tp_descr_get */
NULL, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)Label_init, /* tp_init */
NULL, /* tp_alloc */
Label_new, /* tp_new */
};
PyObject *PyObjectResultLabel(struct fdisk_label *lb)
{
LabelObject *result;
if (!lb) {
PyErr_SetString(PyExc_AssertionError, "lb assert failed");
return NULL;
}
result = PyObject_New(LabelObject, &LabelType);
if (!result) {
PyErr_SetString(PyExc_MemoryError, "Couldn't allocate Label object");
return NULL;
}
/* Py_INCREF(result); */
result->lb = lb;
return (PyObject *) result;
}
void Label_AddModuleObject(PyObject *mod)
{
if (PyType_Ready(&LabelType) < 0)
return;
Py_INCREF(&LabelType);
PyModule_AddObject(mod, "Label", (PyObject *)&LabelType);
}

150
partition.c 100644
View File

@ -0,0 +1,150 @@
#include "fdisk.h"
static PyMemberDef Partition_members[] = {
{ NULL }
};
static void Partition_dealloc(PartitionObject *self)
{
if (self->pa)
fdisk_unref_partition(self->pa);
Py_TYPE(self)->tp_free((PyObject *) self);
}
static PyObject *Partition_new(PyTypeObject *type,
PyObject *args __attribute__((unused)),
PyObject *kwds __attribute__((unused)))
{
PartitionObject *self = (PartitionObject*) type->tp_alloc(type, 0);
if (self)
self->pa = NULL;
return (PyObject *)self;
}
#define Partition_HELP "Partition()"
static int Partition_init(PartitionObject *self, PyObject *args, PyObject *kwds)
{
/*
char *kwlist[] = {
"context",
NULL
};
if (!PyArg_ParseTupleAndKeywords(args,
kwds, "|O!", kwlist,
&ContextType, &cxt)) {
PyErr_SetString(PyExc_TypeError, "Error");
return -1;
}
*/
self->pa = fdisk_new_partition();
return 0;
}
static PyMethodDef Partition_methods[] = {
{NULL}
};
static PyObject *Partition_get_partno(PartitionObject *self)
{
if (fdisk_partition_has_partno(self->pa)) {
return PyLong_FromSize_t(fdisk_partition_get_partno(self->pa));
}
// Py_RETURN_NONE;
return Py_BuildValue("%d", -1);
}
static PyObject *Partition_get_size(PartitionObject *self)
{
if (fdisk_partition_has_size(self->pa)) {
return PyLong_FromUnsignedLongLong(fdisk_partition_get_size(self->pa));
}
Py_RETURN_NONE;
}
static PyGetSetDef Partition_getseters[] = {
{"partno", (getter)Partition_get_partno, NULL, "partition number", NULL},
{"size", (getter)Partition_get_size, NULL, "number of sectors", NULL},
{NULL}
};
static PyObject *Partition_repr(PartitionObject *self)
{
return PyUnicode_FromFormat("<libfdisk.Partition object at %p>",
self);
}
PyTypeObject PartitionType = {
PyVarObject_HEAD_INIT(NULL, 0)
"libfdisk.Partition", /*tp_name*/
sizeof(PartitionObject), /*tp_basicsize*/
0, /*tp_itemsize*/
(destructor)Partition_dealloc, /*tp_dealloc*/
0, /*tp_print*/
NULL, /*tp_getattr*/
NULL, /*tp_setattr*/
NULL, /*tp_compare*/
(reprfunc) Partition_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*/
Partition_HELP, /* tp_doc */
NULL, /* tp_traverse */
NULL, /* tp_clear */
NULL, /* tp_richcompare */
0, /* tp_weaklistoffset */
NULL, /* tp_iter */
NULL, /* tp_iternext */
Partition_methods, /* tp_methods */
Partition_members, /* tp_members */
Partition_getseters, /* tp_getset */
NULL, /* tp_base */
NULL, /* tp_dict */
NULL, /* tp_descr_get */
NULL, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)Partition_init, /* tp_init */
NULL, /* tp_alloc */
Partition_new, /* tp_new */
};
PyObject *PyObjectResultPartition(struct fdisk_partition *pa)
{
PartitionObject *result;
if (!pa) {
PyErr_SetString(PyExc_AssertionError, "pa assert failed");
return NULL;
}
result = PyObject_New(PartitionObject, &PartitionType);
if (!result) {
PyErr_SetString(PyExc_MemoryError, "Couldn't allocate Partition object");
return NULL;
}
result->pa = pa;
return (PyObject *) result;
}
void Partition_AddModuleObject(PyObject *mod)
{
if (PyType_Ready(&PartitionType) < 0)
return;
Py_INCREF(&PartitionType);
PyModule_AddObject(mod, "Partition", (PyObject *)&PartitionType);
}

10
setup.py 100644
View File

@ -0,0 +1,10 @@
from setuptools import setup, Extension
libfdisk = Extension('fdisk',
libraries = ['fdisk'],
sources = ['fdisk.c', 'context.c', 'label.c', 'partition.c'])
setup (name = 'libfdisk',
version = '1.0',
description = 'Python bindings for libfdisk',
ext_modules = [libfdisk])