]> git.ipfire.org Git - people/stevee/pakfire.git/blob - src/_pakfire/file.c
ca0d32d7ffdb76fa59df36283b76ce1c70edc6d0
[people/stevee/pakfire.git] / src / _pakfire / file.c
1 /*#############################################################################
2 # #
3 # Pakfire - The IPFire package management system #
4 # Copyright (C) 2022 Pakfire development team #
5 # #
6 # This program is free software: you can redistribute it and/or modify #
7 # it under the terms of the GNU 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. #
10 # #
11 # This program 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 General Public License for more details. #
15 # #
16 # You should have received a copy of the GNU General Public License #
17 # along with this program. If not, see <http://www.gnu.org/licenses/>. #
18 # #
19 #############################################################################*/
20
21 #include <Python.h>
22 #include <datetime.h>
23
24 #include <pakfire/digest.h>
25 #include <pakfire/file.h>
26
27 #include "file.h"
28 #include "pakfire.h"
29 #include "util.h"
30
31 PyObject* new_file(struct pakfire_file* file) {
32 PyTypeObject* type = &FileType;
33
34 FileObject* self = (FileObject *)type->tp_alloc(type, 0);
35 if (self) {
36 if (file)
37 self->file = pakfire_file_ref(file);
38 else
39 self->file = NULL;
40 }
41
42 return (PyObject *)self;
43 }
44
45 static PyObject* File_new(PyTypeObject* type, PyObject* args, PyObject* kwds) {
46 return new_file(NULL);
47 }
48
49 static void File_dealloc(FileObject* self) {
50 if (self->file)
51 pakfire_file_unref(self->file);
52
53 Py_TYPE(self)->tp_free((PyObject *)self);
54 }
55
56 static int File_init(FileObject* self, PyObject* args, PyObject* kwds) {
57 PakfireObject* pakfire = NULL;
58
59 if (!PyArg_ParseTuple(args, "O!", &PakfireType, &pakfire))
60 return -1;
61
62 // Create a new File object
63 int r = pakfire_file_create(&self->file, pakfire->pakfire);
64 if (r)
65 return -1;
66
67 return 0;
68 }
69
70 static PyObject* File_repr(FileObject* self) {
71 const char* path = pakfire_file_get_path(self->file);
72
73 return PyUnicode_FromFormat("<_pakfire.Problem %s>", path);
74 }
75
76 static PyObject* File_get_path(FileObject* self) {
77 const char* path = pakfire_file_get_path(self->file);
78
79 return PyUnicode_FromString(path);
80 }
81
82 static int File_set_path(FileObject* self, PyObject* value) {
83 const char* path = PyUnicode_AsUTF8(value);
84 if (!path)
85 return -1;
86
87 pakfire_file_set_path(self->file, path);
88 return 0;
89 }
90
91 static PyObject* File_get_size(FileObject* self) {
92 const size_t size = pakfire_file_get_size(self->file);
93
94 return PyLong_FromSize_t(size);
95 }
96
97 static int File_set_size(FileObject* self, PyObject* value) {
98 long size = PyLong_AsLong(value);
99 if (size < 0)
100 return -1;
101
102 pakfire_file_set_size(self->file, size);
103 return 0;
104 }
105
106 static PyObject* File_get_type(FileObject* self) {
107 int type = pakfire_file_get_type(self->file);
108
109 return PyLong_FromLong(type);
110 }
111
112 static PyObject* File_get_uname(FileObject* self) {
113 const char* uname = pakfire_file_get_uname(self->file);
114
115 return PyUnicode_FromString(uname);
116 }
117
118 static int File_set_uname(FileObject* self, PyObject* value) {
119 const char* uname = PyUnicode_AsUTF8(value);
120 if (!uname)
121 return -1;
122
123 pakfire_file_set_uname(self->file, uname);
124 return 0;
125 }
126
127 static PyObject* File_get_gname(FileObject* self) {
128 const char* gname = pakfire_file_get_gname(self->file);
129
130 return PyUnicode_FromString(gname);
131 }
132
133 static int File_set_gname(FileObject* self, PyObject* value) {
134 const char* gname = PyUnicode_AsUTF8(value);
135 if (!gname)
136 return -1;
137
138 pakfire_file_set_gname(self->file, gname);
139 return 0;
140 }
141
142 static PyObject* File_get_mode(FileObject* self) {
143 const mode_t mode = pakfire_file_get_mode(self->file);
144
145 return PyLong_FromLong(mode);
146 }
147
148 static int File_set_mode(FileObject* self, PyObject* value) {
149 const mode_t mode = PyLong_AsLong(value);
150
151 pakfire_file_set_mode(self->file, mode);
152 return 0;
153 }
154
155 static time_t PyDateTime_AsTime_t(PyObject* value) {
156 if (!PyDateTime_Check(value))
157 return -1;
158
159 PyDateTime_IMPORT;
160
161 // Convert from datetime to struct tm
162 struct tm tm = {
163 .tm_year = PyDateTime_GET_YEAR(value) - 1900,
164 .tm_mon = PyDateTime_GET_MONTH(value) - 1,
165 .tm_mday = PyDateTime_GET_DAY(value),
166 .tm_hour = PyDateTime_DATE_GET_HOUR(value),
167 .tm_min = PyDateTime_DATE_GET_MINUTE(value),
168 .tm_sec = PyDateTime_DATE_GET_SECOND(value),
169 .tm_isdst = 0,
170 };
171
172 // Convert into time_t
173 const time_t t = mktime(&tm);
174 if (t < 0) {
175 PyErr_SetFromErrno(PyExc_OSError);
176 return -1;
177 }
178
179 return t;
180 }
181
182 static PyObject* File_get_ctime(FileObject* self) {
183 const time_t t = pakfire_file_get_ctime(self->file);
184
185 return PyDateTime_FromTime_t(&t);
186 }
187
188 static int File_set_ctime(FileObject* self, PyObject* value) {
189 const time_t t = PyDateTime_AsTime_t(value);
190 if (t < 0)
191 return -1;
192
193 pakfire_file_set_ctime(self->file, t);
194 return 0;
195 }
196
197 static PyObject* File_get_mtime(FileObject* self) {
198 const time_t t = pakfire_file_get_mtime(self->file);
199
200 return PyDateTime_FromTime_t(&t);
201 }
202
203 static int File_set_mtime(FileObject* self, PyObject* value) {
204 const time_t t = PyDateTime_AsTime_t(value);
205 if (t < 0)
206 return -1;
207
208 pakfire_file_set_mtime(self->file, t);
209 return 0;
210 }
211
212 static PyObject* File_digest(FileObject* self, PyObject* args) {
213 const char* name = NULL;
214
215 if (!PyArg_ParseTuple(args, "s", &name))
216 return NULL;
217
218 // Fetch the type
219 const enum pakfire_digest_types type = pakfire_digest_get_by_name(name);
220
221 // Raise ValueError if we could not find the type
222 if (!type) {
223 PyErr_Format(PyExc_ValueError, "Unknown digest type: %s", name);
224 return NULL;
225 }
226
227 size_t length = 0;
228
229 // Fetch the digest
230 const unsigned char* digest = pakfire_file_get_digest(self->file, type, &length);
231 if (!digest)
232 Py_RETURN_NONE;
233
234 return PyBytes_FromStringAndSize((const char*)digest, length);
235 }
236
237 static PyObject* File_get_mimetype(FileObject* self) {
238 const char* mimetype = pakfire_file_get_mimetype(self->file);
239
240 return PyUnicode_FromString(mimetype);
241 }
242
243 static int File_set_mimetype(FileObject* self, PyObject* value) {
244 int r;
245
246 // Read the MIME type
247 const char* mimetype = PyUnicode_AsUTF8(value);
248 if (!mimetype)
249 return -1;
250
251 // Set the value
252 r = pakfire_file_set_mimetype(self->file, mimetype);
253 if (r) {
254 PyErr_SetFromErrno(PyExc_OSError);
255 return -1;
256 }
257
258 return 0;
259 }
260
261 static PyObject* File_get_capabilities(FileObject* self) {
262 PyObject* result = NULL;
263 char* caps = NULL;
264
265 // No capabilities
266 if (!pakfire_file_has_caps(self->file))
267 Py_RETURN_NONE;
268
269 // Fetch capabilities
270 caps = pakfire_file_get_caps(self->file);
271 if (!caps) {
272 PyErr_SetFromErrno(PyExc_OSError);
273 goto ERROR;
274 }
275
276 // Convert to Python string object
277 result = PyUnicode_FromString(caps);
278
279 ERROR:
280 if (caps)
281 free(caps);
282
283 return result;
284 }
285
286 static struct PyMethodDef File_methods[] = {
287 {
288 "digest",
289 (PyCFunction)File_digest,
290 METH_VARARGS,
291 NULL,
292 },
293 { NULL },
294 };
295
296 static struct PyGetSetDef File_getsetters[] = {
297 {
298 "capabilities",
299 (getter)File_get_capabilities,
300 NULL,
301 NULL,
302 NULL,
303 },
304 {
305 "ctime",
306 (getter)File_get_ctime,
307 (setter)File_set_ctime,
308 NULL,
309 NULL,
310 },
311 {
312 "gname",
313 (getter)File_get_gname,
314 (setter)File_set_gname,
315 NULL,
316 NULL,
317 },
318 {
319 "mimetype",
320 (getter)File_get_mimetype,
321 (setter)File_set_mimetype,
322 NULL,
323 NULL,
324 },
325 {
326 "mode",
327 (getter)File_get_mode,
328 (setter)File_set_mode,
329 NULL,
330 NULL,
331 },
332 {
333 "mtime",
334 (getter)File_get_mtime,
335 (setter)File_set_mtime,
336 NULL,
337 NULL,
338 },
339 {
340 "path",
341 (getter)File_get_path,
342 (setter)File_set_path,
343 NULL,
344 NULL,
345 },
346 {
347 "size",
348 (getter)File_get_size,
349 (setter)File_set_size,
350 NULL,
351 NULL,
352 },
353 {
354 "type",
355 (getter)File_get_type,
356 NULL,
357 NULL,
358 NULL,
359 },
360 {
361 "uname",
362 (getter)File_get_uname,
363 (setter)File_set_uname,
364 NULL,
365 NULL,
366 },
367 { NULL },
368 };
369
370 PyTypeObject FileType = {
371 PyVarObject_HEAD_INIT(NULL, 0)
372 tp_name: "_pakfire.File",
373 tp_basicsize: sizeof(FileObject),
374 tp_flags: Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
375 tp_new: File_new,
376 tp_dealloc: (destructor)File_dealloc,
377 tp_init: (initproc)File_init,
378 tp_doc: "File object",
379 tp_methods: File_methods,
380 tp_getset: File_getsetters,
381 tp_repr: (reprfunc)File_repr,
382 tp_str: (reprfunc)File_get_path,
383 };