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"
23 PyOSErrorObject os_error;
24 PyObject *btrfsutilerror;
27 void SetFromBtrfsUtilError(enum btrfs_util_error err)
29 SetFromBtrfsUtilErrorWithPaths(err, NULL, NULL);
32 void SetFromBtrfsUtilErrorWithPath(enum btrfs_util_error err,
33 struct path_arg *path1)
35 SetFromBtrfsUtilErrorWithPaths(err, path1, NULL);
38 void SetFromBtrfsUtilErrorWithPaths(enum btrfs_util_error err,
39 struct path_arg *path1,
40 struct path_arg *path2)
42 PyObject *strobj, *args, *exc;
44 const char *str1 = btrfs_util_strerror(err), *str2 = strerror(i);
46 if (str1 && str2 && strcmp(str1, str2) != 0) {
47 strobj = PyUnicode_FromFormat("%s: %s", str1, str2);
49 strobj = PyUnicode_FromString(str1);
51 strobj = PyUnicode_FromString(str2);
59 args = Py_BuildValue("iOOOOi", i, strobj,
60 path1 ? path1->object : Py_None, Py_None,
61 path2 ? path2->object : Py_None, (int)err);
66 exc = PyObject_CallObject((PyObject *)&BtrfsUtilError_type, args);
71 PyErr_SetObject((PyObject *)&BtrfsUtilError_type, exc);
75 static int BtrfsUtilError_clear(BtrfsUtilError *self)
77 Py_CLEAR(self->btrfsutilerror);
78 return Py_TYPE(self)->tp_base->tp_clear((PyObject *)self);
81 static void BtrfsUtilError_dealloc(BtrfsUtilError *self)
83 PyObject_GC_UnTrack(self);
84 BtrfsUtilError_clear(self);
85 Py_TYPE(self)->tp_free((PyObject *)self);
88 static int BtrfsUtilError_traverse(BtrfsUtilError *self, visitproc visit,
91 Py_VISIT(self->btrfsutilerror);
92 return Py_TYPE(self)->tp_base->tp_traverse((PyObject *)self, visit, arg);
95 static PyObject *BtrfsUtilError_new(PyTypeObject *type, PyObject *args,
99 PyObject *oserror_args = args;
101 if (PyTuple_Check(args) && PyTuple_GET_SIZE(args) == 6) {
102 oserror_args = PyTuple_GetSlice(args, 0, 5);
103 if (oserror_args == NULL)
107 self = (BtrfsUtilError *)type->tp_base->tp_new(type, oserror_args,
109 if (oserror_args != args)
110 Py_DECREF(oserror_args);
114 if (PyTuple_Check(args) && PyTuple_GET_SIZE(args) == 6) {
115 self->btrfsutilerror = PyTuple_GET_ITEM(args, 5);
116 Py_INCREF(self->btrfsutilerror);
119 return (PyObject *)self;
122 static PyObject *BtrfsUtilError_str(BtrfsUtilError *self)
124 #define OR_NONE(x) ((x) ? (x) : Py_None)
125 if (self->btrfsutilerror) {
126 if (self->os_error.filename) {
127 if (self->os_error.filename2) {
128 return PyUnicode_FromFormat("[BtrfsUtilError %S Errno %S] %S: %R -> %R",
129 OR_NONE(self->btrfsutilerror),
130 OR_NONE(self->os_error.myerrno),
131 OR_NONE(self->os_error.strerror),
132 self->os_error.filename,
133 self->os_error.filename2);
135 return PyUnicode_FromFormat("[BtrfsUtilError %S Errno %S] %S: %R",
136 OR_NONE(self->btrfsutilerror),
137 OR_NONE(self->os_error.myerrno),
138 OR_NONE(self->os_error.strerror),
139 self->os_error.filename);
142 if (self->os_error.myerrno && self->os_error.strerror) {
143 return PyUnicode_FromFormat("[BtrfsUtilError %S Errno %S] %S",
144 self->btrfsutilerror,
145 self->os_error.myerrno,
146 self->os_error.strerror);
149 return Py_TYPE(self)->tp_base->tp_str((PyObject *)self);
153 static PyMemberDef BtrfsUtilError_members[] = {
154 {"btrfsutilerror", T_OBJECT,
155 offsetof(BtrfsUtilError, btrfsutilerror), 0,
156 "btrfsutil error code"},
160 #define BtrfsUtilError_DOC \
161 "Btrfs operation error."
163 PyTypeObject BtrfsUtilError_type = {
164 PyVarObject_HEAD_INIT(NULL, 0)
165 "btrfsutil.BtrfsUtilError", /* tp_name */
166 sizeof(BtrfsUtilError), /* tp_basicsize */
168 (destructor)BtrfsUtilError_dealloc, /* tp_dealloc */
170 NULL, /* tp_getattr */
171 NULL, /* tp_setattr */
172 NULL, /* tp_as_async */
174 NULL, /* tp_as_number */
175 NULL, /* tp_as_sequence */
176 NULL, /* tp_as_mapping */
179 (reprfunc)BtrfsUtilError_str, /* tp_str */
180 NULL, /* tp_getattro */
181 NULL, /* tp_setattro */
182 NULL, /* tp_as_buffer */
183 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */
184 BtrfsUtilError_DOC, /* tp_doc */
185 (traverseproc)BtrfsUtilError_traverse, /* tp_traverse */
186 (inquiry)BtrfsUtilError_clear, /* tp_clear */
187 NULL, /* tp_richcompare */
188 0, /* tp_weaklistoffset */
190 NULL, /* tp_iternext */
191 NULL, /* tp_methods */
192 BtrfsUtilError_members, /* tp_members */
193 NULL, /* tp_getset */
196 NULL, /* tp_descr_get */
197 NULL, /* tp_descr_set */
198 offsetof(BtrfsUtilError, os_error.dict), /* tp_dictoffset */
201 BtrfsUtilError_new, /* tp_new */