diff options
Diffstat (limited to 'libbtrfsutil/python')
-rw-r--r-- | libbtrfsutil/python/btrfsutilpy.h | 3 | ||||
-rw-r--r-- | libbtrfsutil/python/module.c | 30 | ||||
-rw-r--r-- | libbtrfsutil/python/qgroup.c | 17 | ||||
-rw-r--r-- | libbtrfsutil/python/subvolume.c | 30 | ||||
-rw-r--r-- | libbtrfsutil/python/tests/test_subvolume.py | 8 |
5 files changed, 73 insertions, 15 deletions
diff --git a/libbtrfsutil/python/btrfsutilpy.h b/libbtrfsutil/python/btrfsutilpy.h index 0ee6afa7..af3a6edf 100644 --- a/libbtrfsutil/python/btrfsutilpy.h +++ b/libbtrfsutil/python/btrfsutilpy.h @@ -54,6 +54,8 @@ struct path_arg { int path_converter(PyObject *o, void *p); void path_cleanup(struct path_arg *path); +PyObject *list_from_uint64_array(const uint64_t *arr, size_t n); + void SetFromBtrfsUtilError(enum btrfs_util_error err); void SetFromBtrfsUtilErrorWithPath(enum btrfs_util_error err, struct path_arg *path); @@ -75,6 +77,7 @@ PyObject *set_default_subvolume(PyObject *self, PyObject *args, PyObject *kwds); PyObject *create_subvolume(PyObject *self, PyObject *args, PyObject *kwds); PyObject *create_snapshot(PyObject *self, PyObject *args, PyObject *kwds); PyObject *delete_subvolume(PyObject *self, PyObject *args, PyObject *kwds); +PyObject *deleted_subvolumes(PyObject *self, PyObject *args, PyObject *kwds); void add_module_constants(PyObject *m); diff --git a/libbtrfsutil/python/module.c b/libbtrfsutil/python/module.c index fe25f4b7..2dbdc7be 100644 --- a/libbtrfsutil/python/module.c +++ b/libbtrfsutil/python/module.c @@ -125,6 +125,29 @@ err: return 0; } +PyObject *list_from_uint64_array(const uint64_t *arr, size_t n) +{ + PyObject *ret; + size_t i; + + ret = PyList_New(n); + if (!ret) + return NULL; + + for (i = 0; i < n; i++) { + PyObject *tmp; + + tmp = PyLong_FromUnsignedLongLong(arr[i]); + if (!tmp) { + Py_DECREF(ret); + return NULL; + } + PyList_SET_ITEM(ret, i, tmp); + } + + return ret; +} + void path_cleanup(struct path_arg *path) { Py_CLEAR(path->object); @@ -235,6 +258,13 @@ static PyMethodDef btrfsutil_methods[] = { "path -- string, bytes, or path-like object\n" "recursive -- if the given subvolume has child subvolumes, delete\n" "them instead of failing"}, + {"deleted_subvolumes", (PyCFunction)deleted_subvolumes, + METH_VARARGS | METH_KEYWORDS, + "deleted_subvolumes(path)\n\n" + "Get the list of subvolume IDs which have been deleted but not yet\n" + "cleaned up\n\n" + "Arguments:\n" + "path -- string, bytes, path-like object, or open file descriptor"}, {}, }; diff --git a/libbtrfsutil/python/qgroup.c b/libbtrfsutil/python/qgroup.c index 69716d92..44ac5ebc 100644 --- a/libbtrfsutil/python/qgroup.c +++ b/libbtrfsutil/python/qgroup.c @@ -55,25 +55,12 @@ static PyObject *QgroupInherit_getattro(QgroupInherit *self, PyObject *nameobj) } if (strcmp(name, "groups") == 0) { - PyObject *ret, *tmp; const uint64_t *arr; - size_t n, i; + size_t n; btrfs_util_qgroup_inherit_get_groups(self->inherit, &arr, &n); - ret = PyList_New(n); - if (!ret) - return NULL; - - for (i = 0; i < n; i++) { - tmp = PyLong_FromUnsignedLongLong(arr[i]); - if (!tmp) { - Py_DECREF(ret); - return NULL; - } - PyList_SET_ITEM(ret, i, tmp); - } - return ret; + return list_from_uint64_array(arr, n); } else { return PyObject_GenericGetAttr((PyObject *)self, nameobj); } diff --git a/libbtrfsutil/python/subvolume.c b/libbtrfsutil/python/subvolume.c index eb3f6e27..069e606b 100644 --- a/libbtrfsutil/python/subvolume.c +++ b/libbtrfsutil/python/subvolume.c @@ -425,6 +425,36 @@ PyObject *delete_subvolume(PyObject *self, PyObject *args, PyObject *kwds) Py_RETURN_NONE; } +PyObject *deleted_subvolumes(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *keywords[] = {"path", NULL}; + struct path_arg path = {.allow_fd = true}; + PyObject *ret; + uint64_t *ids; + size_t n; + enum btrfs_util_error err; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&:deleted_subvolumes", + keywords, &path_converter, &path)) + return NULL; + + if (path.path) + err = btrfs_util_deleted_subvolumes(path.path, &ids, &n); + else + err = btrfs_util_deleted_subvolumes_fd(path.fd, &ids, &n); + if (err) { + SetFromBtrfsUtilErrorWithPath(err, &path); + path_cleanup(&path); + return NULL; + } + + path_cleanup(&path); + + ret = list_from_uint64_array(ids, n); + free(ids); + return ret; +} + typedef struct { PyObject_HEAD struct btrfs_util_subvolume_iterator *iter; diff --git a/libbtrfsutil/python/tests/test_subvolume.py b/libbtrfsutil/python/tests/test_subvolume.py index 08083abe..a46d4a34 100644 --- a/libbtrfsutil/python/tests/test_subvolume.py +++ b/libbtrfsutil/python/tests/test_subvolume.py @@ -318,6 +318,14 @@ class TestSubvolume(BtrfsTestCase): btrfsutil.delete_subvolume(subvol + '5', recursive=True) self.assertFalse(os.path.exists(subvol + '5')) + def test_deleted_subvolumes(self): + subvol = os.path.join(self.mountpoint, 'subvol') + btrfsutil.create_subvolume(subvol + '1') + btrfsutil.delete_subvolume(subvol + '1') + for arg in self.path_or_fd(self.mountpoint): + with self.subTest(type=type(arg)): + self.assertEqual(btrfsutil.deleted_subvolumes(arg), [256]) + def test_subvolume_iterator(self): pwd = os.getcwd() try: |