2 * Copyright (C) 2018 Facebook
4 * This file is part of libbtrfsutil.
6 * libbtrfsutil is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * libbtrfsutil is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with libbtrfsutil. If not, see <http://www.gnu.org/licenses/>.
20 #include "btrfsutilpy.h"
22 PyObject *is_subvolume(PyObject *self, PyObject *args, PyObject *kwds)
24 static char *keywords[] = {"path", NULL};
25 struct path_arg path = {.allow_fd = true};
26 enum btrfs_util_error err;
28 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&:is_subvolume",
29 keywords, &path_converter, &path))
33 err = btrfs_util_is_subvolume(path.path);
35 err = btrfs_util_is_subvolume_fd(path.fd);
36 if (err == BTRFS_UTIL_OK) {
39 } else if (err == BTRFS_UTIL_ERROR_NOT_BTRFS ||
40 err == BTRFS_UTIL_ERROR_NOT_SUBVOLUME) {
44 SetFromBtrfsUtilErrorWithPath(err, &path);
50 PyObject *subvolume_id(PyObject *self, PyObject *args, PyObject *kwds)
52 static char *keywords[] = {"path", NULL};
53 struct path_arg path = {.allow_fd = true};
54 enum btrfs_util_error err;
57 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&:subvolume_id",
58 keywords, &path_converter, &path))
62 err = btrfs_util_subvolume_id(path.path, &id);
64 err = btrfs_util_subvolume_id_fd(path.fd, &id);
66 SetFromBtrfsUtilErrorWithPath(err, &path);
72 return PyLong_FromUnsignedLongLong(id);
75 PyObject *subvolume_path(PyObject *self, PyObject *args, PyObject *kwds)
77 static char *keywords[] = {"path", "id", NULL};
78 struct path_arg path = {.allow_fd = true};
79 enum btrfs_util_error err;
84 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&|K:subvolume_path",
85 keywords, &path_converter, &path, &id))
89 err = btrfs_util_subvolume_path(path.path, id, &subvol_path);
91 err = btrfs_util_subvolume_path_fd(path.fd, id, &subvol_path);
93 SetFromBtrfsUtilErrorWithPath(err, &path);
100 ret = PyUnicode_DecodeFSDefault(subvol_path);
105 static PyObject *subvolume_info_to_object(const struct btrfs_util_subvolume_info *subvol)
109 ret = PyStructSequence_New(&SubvolumeInfo_type);
113 #define SET_UINT64(i, field) \
114 tmp = PyLong_FromUnsignedLongLong(subvol->field); \
119 PyStructSequence_SET_ITEM(ret, i, tmp);
121 #define SET_UUID(i, field) \
122 tmp = PyBytes_FromStringAndSize((char *)subvol->field, 16); \
127 PyStructSequence_SET_ITEM(ret, i, tmp);
129 #define SET_TIME(i, field) \
130 tmp = PyFloat_FromDouble(subvol->field.tv_sec + \
131 subvol->field.tv_nsec / 1000000000); \
136 PyStructSequence_SET_ITEM(ret, i, tmp);
139 SET_UINT64(1, parent_id);
140 SET_UINT64(2, dir_id);
141 SET_UINT64(3, flags);
143 SET_UUID(5, parent_uuid);
144 SET_UUID(6, received_uuid);
145 SET_UINT64(7, generation);
146 SET_UINT64(8, ctransid);
147 SET_UINT64(9, otransid);
148 SET_UINT64(10, stransid);
149 SET_UINT64(11, rtransid);
162 PyObject *subvolume_info(PyObject *self, PyObject *args, PyObject *kwds)
164 static char *keywords[] = {"path", "id", NULL};
165 struct path_arg path = {.allow_fd = true};
166 struct btrfs_util_subvolume_info subvol;
167 enum btrfs_util_error err;
170 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&|K:subvolume_info",
171 keywords, &path_converter, &path, &id))
175 err = btrfs_util_subvolume_info(path.path, id, &subvol);
177 err = btrfs_util_subvolume_info_fd(path.fd, id, &subvol);
179 SetFromBtrfsUtilErrorWithPath(err, &path);
186 return subvolume_info_to_object(&subvol);
189 static PyStructSequence_Field SubvolumeInfo_fields[] = {
190 {"id", "int ID of this subvolume"},
191 {"parent_id", "int ID of the subvolume containing this subvolume"},
192 {"dir_id", "int inode number of the directory containing this subvolume"},
193 {"flags", "int root item flags"},
194 {"uuid", "bytes UUID of this subvolume"},
195 {"parent_uuid", "bytes UUID of the subvolume this is a snapshot of"},
196 {"received_uuid", "bytes UUID of the subvolume this was received from"},
197 {"generation", "int transaction ID of the subvolume root"},
198 {"ctransid", "int transaction ID when an inode was last changed"},
199 {"otransid", "int transaction ID when this subvolume was created"},
200 {"stransid", "int transaction ID of the sent subvolume this subvolume was received from"},
201 {"rtransid", "int transaction ID when this subvolume was received"},
202 {"ctime", "float time when an inode was last changed"},
203 {"otime", "float time when this subvolume was created"},
204 {"stime", "float time, usually zero"},
205 {"rtime", "float time when this subvolume was received"},
209 PyStructSequence_Desc SubvolumeInfo_desc = {
210 "btrfsutil.SubvolumeInfo",
211 "Information about a Btrfs subvolume.",
212 SubvolumeInfo_fields,
216 PyTypeObject SubvolumeInfo_type;
218 PyObject *get_subvolume_read_only(PyObject *self, PyObject *args, PyObject *kwds)
220 static char *keywords[] = {"path", NULL};
221 struct path_arg path = {.allow_fd = true};
222 enum btrfs_util_error err;
225 if (!PyArg_ParseTupleAndKeywords(args, kwds,
226 "O&:get_subvolume_read_only",
227 keywords, &path_converter, &path))
231 err = btrfs_util_get_subvolume_read_only(path.path, &read_only);
233 err = btrfs_util_get_subvolume_read_only_fd(path.fd,
237 SetFromBtrfsUtilErrorWithPath(err, &path);
243 return PyBool_FromLong(read_only);
246 PyObject *set_subvolume_read_only(PyObject *self, PyObject *args, PyObject *kwds)
248 static char *keywords[] = {"path", "read_only", NULL};
249 struct path_arg path = {.allow_fd = true};
250 enum btrfs_util_error err;
253 if (!PyArg_ParseTupleAndKeywords(args, kwds,
254 "O&|p:set_subvolume_read_only",
255 keywords, &path_converter, &path,
260 err = btrfs_util_set_subvolume_read_only(path.path, read_only);
262 err = btrfs_util_set_subvolume_read_only_fd(path.fd, read_only);
264 SetFromBtrfsUtilErrorWithPath(err, &path);
273 PyObject *create_subvolume(PyObject *self, PyObject *args, PyObject *kwds)
275 static char *keywords[] = {"path", "async", "qgroup_inherit", NULL};
276 struct path_arg path = {.allow_fd = false};
277 enum btrfs_util_error err;
279 QgroupInherit *inherit = NULL;
282 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&|pO!:create_subvolume",
283 keywords, &path_converter, &path,
284 &async, &QgroupInherit_type, &inherit))
287 err = btrfs_util_create_subvolume(path.path, 0, async ? &transid : NULL,
288 inherit ? inherit->inherit : NULL);
290 SetFromBtrfsUtilErrorWithPath(err, &path);
297 return PyLong_FromUnsignedLongLong(transid);