|
11 | 11 | #include <fcntl.h> // fcntl() |
12 | 12 | #include <string.h> // memcpy() |
13 | 13 | #include <sys/ioctl.h> // ioctl() |
| 14 | + |
| 15 | +#ifdef F_PREALLOCATE |
| 16 | +#ifdef HAVE_SYS_TYPES_H |
| 17 | +#include <sys/types.h> |
| 18 | +#endif |
| 19 | +#include <stddef.h> /* for offsetof */ |
| 20 | +#endif |
14 | 21 | #ifdef HAVE_SYS_FILE_H |
15 | 22 | # include <sys/file.h> // flock() |
16 | 23 | #endif |
@@ -502,6 +509,119 @@ fcntl_lockf_impl(PyObject *module, int fd, int code, PyObject *lenobj, |
502 | 509 | Py_RETURN_NONE; |
503 | 510 | } |
504 | 511 |
|
| 512 | +#ifdef F_PREALLOCATE |
| 513 | + |
| 514 | +typedef struct { |
| 515 | + PyObject_HEAD |
| 516 | + struct fstore fstore; |
| 517 | +} fstoreObject; |
| 518 | + |
| 519 | +static int |
| 520 | +fstore_init(fstoreObject *self, PyObject *args, PyObject *kwds) |
| 521 | +{ |
| 522 | + static char *kwlist[] = { |
| 523 | + "flags", "posmode", "offset", "length", NULL |
| 524 | + }; |
| 525 | + int flags = 0; |
| 526 | + int posmode = 0; |
| 527 | + off_t offset = 0; |
| 528 | + off_t length = 0; |
| 529 | + |
| 530 | + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|iiLL", kwlist, |
| 531 | + &flags, &posmode, &offset, &length)) { |
| 532 | + return -1; |
| 533 | + } |
| 534 | + |
| 535 | + memset(&self->fstore, 0, sizeof(struct fstore)); |
| 536 | + self->fstore.fst_flags = flags; |
| 537 | + self->fstore.fst_posmode = posmode; |
| 538 | + self->fstore.fst_offset = offset; |
| 539 | + self->fstore.fst_length = length; |
| 540 | + |
| 541 | + return 0; |
| 542 | +} |
| 543 | + |
| 544 | +static Py_ssize_t |
| 545 | +fstore_getbuffer(fstoreObject *self, Py_buffer *view, int flags) |
| 546 | +{ |
| 547 | + return PyBuffer_FillInfo(view, (PyObject *)self, (void *)&self->fstore, |
| 548 | + sizeof(struct fstore), 1, flags); |
| 549 | +} |
| 550 | + |
| 551 | +static PyObject * |
| 552 | +fstore_frombytes(PyTypeObject *type, PyObject *args, PyObject *kwds) |
| 553 | +{ |
| 554 | + static char *kwlist[] = {"data", NULL}; |
| 555 | + PyObject *data_obj; |
| 556 | + Py_buffer view; |
| 557 | + fstoreObject *self; |
| 558 | + |
| 559 | + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &data_obj)) { |
| 560 | + return NULL; |
| 561 | + } |
| 562 | + |
| 563 | + if (PyObject_GetBuffer(data_obj, &view, PyBUF_SIMPLE) < 0) { |
| 564 | + return NULL; |
| 565 | + } |
| 566 | + |
| 567 | + if (view.len != sizeof(struct fstore)) { |
| 568 | + PyBuffer_Release(&view); |
| 569 | + PyErr_Format(PyExc_ValueError, |
| 570 | + "data must be exactly %zu bytes, got %zd bytes", |
| 571 | + sizeof(struct fstore), view.len); |
| 572 | + return NULL; |
| 573 | + } |
| 574 | + |
| 575 | + self = (fstoreObject *)PyType_GenericNew(type, NULL, NULL); |
| 576 | + if (self == NULL) { |
| 577 | + PyBuffer_Release(&view); |
| 578 | + return NULL; |
| 579 | + } |
| 580 | + |
| 581 | + memcpy(&self->fstore, view.buf, sizeof(struct fstore)); |
| 582 | + PyBuffer_Release(&view); |
| 583 | + |
| 584 | + return (PyObject *)self; |
| 585 | +} |
| 586 | + |
| 587 | +static PyMethodDef fstore_methods[] = { |
| 588 | + {"frombytes", (PyCFunction)fstore_frombytes, METH_VARARGS | METH_KEYWORDS | METH_CLASS, |
| 589 | + "Create an fstore instance from bytes data."}, |
| 590 | + {NULL, NULL} |
| 591 | +}; |
| 592 | + |
| 593 | +static PyMemberDef fstore_members[] = { |
| 594 | + {"flags", Py_T_INT, offsetof(fstoreObject, fstore.fst_flags), 0, |
| 595 | + "Allocation flags"}, |
| 596 | + {"posmode", Py_T_INT, offsetof(fstoreObject, fstore.fst_posmode), 0, |
| 597 | + "Position mode"}, |
| 598 | + {"offset", Py_T_LONGLONG, offsetof(fstoreObject, fstore.fst_offset), 0, |
| 599 | + "File offset"}, |
| 600 | + {"length", Py_T_LONGLONG, offsetof(fstoreObject, fstore.fst_length), 0, |
| 601 | + "Length to allocate"}, |
| 602 | + {"bytesalloc", Py_T_LONGLONG, offsetof(fstoreObject, fstore.fst_bytesalloc), Py_READONLY, |
| 603 | + "Number of bytes actually allocated"}, |
| 604 | + {NULL}, |
| 605 | +}; |
| 606 | + |
| 607 | +static PyType_Slot fstore_slots[] = { |
| 608 | + {Py_tp_init, (initproc)fstore_init}, |
| 609 | + {Py_tp_members, fstore_members}, |
| 610 | + {Py_tp_methods, fstore_methods}, |
| 611 | + {Py_tp_doc, "fstore structure for F_PREALLOCATE"}, |
| 612 | + {Py_bf_getbuffer, (getbufferproc)fstore_getbuffer}, |
| 613 | + {0, NULL}, |
| 614 | +}; |
| 615 | + |
| 616 | +static PyType_Spec fstore_spec = { |
| 617 | + .name = "fcntl.fstore", |
| 618 | + .basicsize = sizeof(fstoreObject), |
| 619 | + .flags = Py_TPFLAGS_DEFAULT, |
| 620 | + .slots = fstore_slots, |
| 621 | +}; |
| 622 | + |
| 623 | +#endif /* F_PREALLOCATE */ |
| 624 | + |
505 | 625 | /* List of functions */ |
506 | 626 |
|
507 | 627 | static PyMethodDef fcntl_methods[] = { |
@@ -687,6 +807,24 @@ all_ins(PyObject* m) |
687 | 807 | #ifdef F_NOCACHE |
688 | 808 | if (PyModule_AddIntMacro(m, F_NOCACHE)) return -1; |
689 | 809 | #endif |
| 810 | +#ifdef F_PREALLOCATE |
| 811 | + if (PyModule_AddIntMacro(m, F_PREALLOCATE)) return -1; |
| 812 | +#endif |
| 813 | +#ifdef F_ALLOCATECONTIG |
| 814 | + if (PyModule_AddIntMacro(m, F_ALLOCATECONTIG)) return -1; |
| 815 | +#endif |
| 816 | +#ifdef F_ALLOCATEALL |
| 817 | + if (PyModule_AddIntMacro(m, F_ALLOCATEALL)) return -1; |
| 818 | +#endif |
| 819 | +#ifdef F_ALLOCATEPERSIST |
| 820 | + if (PyModule_AddIntMacro(m, F_ALLOCATEPERSIST)) return -1; |
| 821 | +#endif |
| 822 | +#ifdef F_PEOFPOSMODE |
| 823 | + if (PyModule_AddIntMacro(m, F_PEOFPOSMODE)) return -1; |
| 824 | +#endif |
| 825 | +#ifdef F_VOLPOSMODE |
| 826 | + if (PyModule_AddIntMacro(m, F_VOLPOSMODE)) return -1; |
| 827 | +#endif |
690 | 828 |
|
691 | 829 | /* FreeBSD specifics */ |
692 | 830 | #ifdef F_DUP2FD |
@@ -808,6 +946,18 @@ fcntl_exec(PyObject *module) |
808 | 946 | if (all_ins(module) < 0) { |
809 | 947 | return -1; |
810 | 948 | } |
| 949 | + |
| 950 | +#ifdef F_PREALLOCATE |
| 951 | + PyObject *fstore_type = PyType_FromSpec(&fstore_spec); |
| 952 | + if (fstore_type == NULL) { |
| 953 | + return -1; |
| 954 | + } |
| 955 | + if (PyModule_AddObject(module, "fstore", fstore_type) < 0) { |
| 956 | + Py_DECREF(fstore_type); |
| 957 | + return -1; |
| 958 | + } |
| 959 | +#endif |
| 960 | + |
811 | 961 | return 0; |
812 | 962 | } |
813 | 963 |
|
|
0 commit comments