| 1 | n/a | |
|---|
| 2 | n/a | /* fcntl module */ |
|---|
| 3 | n/a | |
|---|
| 4 | n/a | #define PY_SSIZE_T_CLEAN |
|---|
| 5 | n/a | |
|---|
| 6 | n/a | #include "Python.h" |
|---|
| 7 | n/a | |
|---|
| 8 | n/a | #ifdef HAVE_SYS_FILE_H |
|---|
| 9 | n/a | #include <sys/file.h> |
|---|
| 10 | n/a | #endif |
|---|
| 11 | n/a | |
|---|
| 12 | n/a | #include <sys/ioctl.h> |
|---|
| 13 | n/a | #include <fcntl.h> |
|---|
| 14 | n/a | #ifdef HAVE_STROPTS_H |
|---|
| 15 | n/a | #include <stropts.h> |
|---|
| 16 | n/a | #endif |
|---|
| 17 | n/a | |
|---|
| 18 | n/a | /*[clinic input] |
|---|
| 19 | n/a | module fcntl |
|---|
| 20 | n/a | [clinic start generated code]*/ |
|---|
| 21 | n/a | /*[clinic end generated code: output=da39a3ee5e6b4b0d input=124b58387c158179]*/ |
|---|
| 22 | n/a | |
|---|
| 23 | n/a | static int |
|---|
| 24 | n/a | conv_descriptor(PyObject *object, int *target) |
|---|
| 25 | n/a | { |
|---|
| 26 | n/a | int fd = PyObject_AsFileDescriptor(object); |
|---|
| 27 | n/a | |
|---|
| 28 | n/a | if (fd < 0) |
|---|
| 29 | n/a | return 0; |
|---|
| 30 | n/a | *target = fd; |
|---|
| 31 | n/a | return 1; |
|---|
| 32 | n/a | } |
|---|
| 33 | n/a | |
|---|
| 34 | n/a | /* Must come after conv_descriptor definition. */ |
|---|
| 35 | n/a | #include "clinic/fcntlmodule.c.h" |
|---|
| 36 | n/a | |
|---|
| 37 | n/a | /*[clinic input] |
|---|
| 38 | n/a | fcntl.fcntl |
|---|
| 39 | n/a | |
|---|
| 40 | n/a | fd: object(type='int', converter='conv_descriptor') |
|---|
| 41 | n/a | cmd as code: int |
|---|
| 42 | n/a | arg: object(c_default='NULL') = 0 |
|---|
| 43 | n/a | / |
|---|
| 44 | n/a | |
|---|
| 45 | n/a | Perform the operation `cmd` on file descriptor fd. |
|---|
| 46 | n/a | |
|---|
| 47 | n/a | The values used for `cmd` are operating system dependent, and are available |
|---|
| 48 | n/a | as constants in the fcntl module, using the same names as used in |
|---|
| 49 | n/a | the relevant C header files. The argument arg is optional, and |
|---|
| 50 | n/a | defaults to 0; it may be an int or a string. If arg is given as a string, |
|---|
| 51 | n/a | the return value of fcntl is a string of that length, containing the |
|---|
| 52 | n/a | resulting value put in the arg buffer by the operating system. The length |
|---|
| 53 | n/a | of the arg string is not allowed to exceed 1024 bytes. If the arg given |
|---|
| 54 | n/a | is an integer or if none is specified, the result value is an integer |
|---|
| 55 | n/a | corresponding to the return value of the fcntl call in the C code. |
|---|
| 56 | n/a | [clinic start generated code]*/ |
|---|
| 57 | n/a | |
|---|
| 58 | n/a | static PyObject * |
|---|
| 59 | n/a | fcntl_fcntl_impl(PyObject *module, int fd, int code, PyObject *arg) |
|---|
| 60 | n/a | /*[clinic end generated code: output=888fc93b51c295bd input=8cefbe59b29efbe2]*/ |
|---|
| 61 | n/a | { |
|---|
| 62 | n/a | unsigned int int_arg = 0; |
|---|
| 63 | n/a | int ret; |
|---|
| 64 | n/a | char *str; |
|---|
| 65 | n/a | Py_ssize_t len; |
|---|
| 66 | n/a | char buf[1024]; |
|---|
| 67 | n/a | |
|---|
| 68 | n/a | if (arg != NULL) { |
|---|
| 69 | n/a | int parse_result; |
|---|
| 70 | n/a | |
|---|
| 71 | n/a | if (PyArg_Parse(arg, "s#", &str, &len)) { |
|---|
| 72 | n/a | if ((size_t)len > sizeof buf) { |
|---|
| 73 | n/a | PyErr_SetString(PyExc_ValueError, |
|---|
| 74 | n/a | "fcntl string arg too long"); |
|---|
| 75 | n/a | return NULL; |
|---|
| 76 | n/a | } |
|---|
| 77 | n/a | memcpy(buf, str, len); |
|---|
| 78 | n/a | Py_BEGIN_ALLOW_THREADS |
|---|
| 79 | n/a | ret = fcntl(fd, code, buf); |
|---|
| 80 | n/a | Py_END_ALLOW_THREADS |
|---|
| 81 | n/a | if (ret < 0) { |
|---|
| 82 | n/a | PyErr_SetFromErrno(PyExc_IOError); |
|---|
| 83 | n/a | return NULL; |
|---|
| 84 | n/a | } |
|---|
| 85 | n/a | return PyBytes_FromStringAndSize(buf, len); |
|---|
| 86 | n/a | } |
|---|
| 87 | n/a | |
|---|
| 88 | n/a | PyErr_Clear(); |
|---|
| 89 | n/a | parse_result = PyArg_Parse(arg, |
|---|
| 90 | n/a | "I;fcntl requires a file or file descriptor," |
|---|
| 91 | n/a | " an integer and optionally a third integer or a string", |
|---|
| 92 | n/a | &int_arg); |
|---|
| 93 | n/a | if (!parse_result) { |
|---|
| 94 | n/a | return NULL; |
|---|
| 95 | n/a | } |
|---|
| 96 | n/a | } |
|---|
| 97 | n/a | |
|---|
| 98 | n/a | Py_BEGIN_ALLOW_THREADS |
|---|
| 99 | n/a | ret = fcntl(fd, code, (int)int_arg); |
|---|
| 100 | n/a | Py_END_ALLOW_THREADS |
|---|
| 101 | n/a | if (ret < 0) { |
|---|
| 102 | n/a | PyErr_SetFromErrno(PyExc_IOError); |
|---|
| 103 | n/a | return NULL; |
|---|
| 104 | n/a | } |
|---|
| 105 | n/a | return PyLong_FromLong((long)ret); |
|---|
| 106 | n/a | } |
|---|
| 107 | n/a | |
|---|
| 108 | n/a | |
|---|
| 109 | n/a | /*[clinic input] |
|---|
| 110 | n/a | fcntl.ioctl |
|---|
| 111 | n/a | |
|---|
| 112 | n/a | fd: object(type='int', converter='conv_descriptor') |
|---|
| 113 | n/a | request as code: unsigned_int(bitwise=True) |
|---|
| 114 | n/a | arg as ob_arg: object(c_default='NULL') = 0 |
|---|
| 115 | n/a | mutate_flag as mutate_arg: bool = True |
|---|
| 116 | n/a | / |
|---|
| 117 | n/a | |
|---|
| 118 | n/a | Perform the operation `request` on file descriptor `fd`. |
|---|
| 119 | n/a | |
|---|
| 120 | n/a | The values used for `request` are operating system dependent, and are available |
|---|
| 121 | n/a | as constants in the fcntl or termios library modules, using the same names as |
|---|
| 122 | n/a | used in the relevant C header files. |
|---|
| 123 | n/a | |
|---|
| 124 | n/a | The argument `arg` is optional, and defaults to 0; it may be an int or a |
|---|
| 125 | n/a | buffer containing character data (most likely a string or an array). |
|---|
| 126 | n/a | |
|---|
| 127 | n/a | If the argument is a mutable buffer (such as an array) and if the |
|---|
| 128 | n/a | mutate_flag argument (which is only allowed in this case) is true then the |
|---|
| 129 | n/a | buffer is (in effect) passed to the operating system and changes made by |
|---|
| 130 | n/a | the OS will be reflected in the contents of the buffer after the call has |
|---|
| 131 | n/a | returned. The return value is the integer returned by the ioctl system |
|---|
| 132 | n/a | call. |
|---|
| 133 | n/a | |
|---|
| 134 | n/a | If the argument is a mutable buffer and the mutable_flag argument is false, |
|---|
| 135 | n/a | the behavior is as if a string had been passed. |
|---|
| 136 | n/a | |
|---|
| 137 | n/a | If the argument is an immutable buffer (most likely a string) then a copy |
|---|
| 138 | n/a | of the buffer is passed to the operating system and the return value is a |
|---|
| 139 | n/a | string of the same length containing whatever the operating system put in |
|---|
| 140 | n/a | the buffer. The length of the arg buffer in this case is not allowed to |
|---|
| 141 | n/a | exceed 1024 bytes. |
|---|
| 142 | n/a | |
|---|
| 143 | n/a | If the arg given is an integer or if none is specified, the result value is |
|---|
| 144 | n/a | an integer corresponding to the return value of the ioctl call in the C |
|---|
| 145 | n/a | code. |
|---|
| 146 | n/a | [clinic start generated code]*/ |
|---|
| 147 | n/a | |
|---|
| 148 | n/a | static PyObject * |
|---|
| 149 | n/a | fcntl_ioctl_impl(PyObject *module, int fd, unsigned int code, |
|---|
| 150 | n/a | PyObject *ob_arg, int mutate_arg) |
|---|
| 151 | n/a | /*[clinic end generated code: output=7f7f5840c65991be input=ede70c433cccbbb2]*/ |
|---|
| 152 | n/a | { |
|---|
| 153 | n/a | #define IOCTL_BUFSZ 1024 |
|---|
| 154 | n/a | /* We use the unsigned non-checked 'I' format for the 'code' parameter |
|---|
| 155 | n/a | because the system expects it to be a 32bit bit field value |
|---|
| 156 | n/a | regardless of it being passed as an int or unsigned long on |
|---|
| 157 | n/a | various platforms. See the termios.TIOCSWINSZ constant across |
|---|
| 158 | n/a | platforms for an example of this. |
|---|
| 159 | n/a | |
|---|
| 160 | n/a | If any of the 64bit platforms ever decide to use more than 32bits |
|---|
| 161 | n/a | in their unsigned long ioctl codes this will break and need |
|---|
| 162 | n/a | special casing based on the platform being built on. |
|---|
| 163 | n/a | */ |
|---|
| 164 | n/a | int arg = 0; |
|---|
| 165 | n/a | int ret; |
|---|
| 166 | n/a | Py_buffer pstr; |
|---|
| 167 | n/a | char *str; |
|---|
| 168 | n/a | Py_ssize_t len; |
|---|
| 169 | n/a | char buf[IOCTL_BUFSZ+1]; /* argument plus NUL byte */ |
|---|
| 170 | n/a | |
|---|
| 171 | n/a | if (ob_arg != NULL) { |
|---|
| 172 | n/a | if (PyArg_Parse(ob_arg, "w*:ioctl", &pstr)) { |
|---|
| 173 | n/a | char *arg; |
|---|
| 174 | n/a | str = pstr.buf; |
|---|
| 175 | n/a | len = pstr.len; |
|---|
| 176 | n/a | |
|---|
| 177 | n/a | if (mutate_arg) { |
|---|
| 178 | n/a | if (len <= IOCTL_BUFSZ) { |
|---|
| 179 | n/a | memcpy(buf, str, len); |
|---|
| 180 | n/a | buf[len] = '\0'; |
|---|
| 181 | n/a | arg = buf; |
|---|
| 182 | n/a | } |
|---|
| 183 | n/a | else { |
|---|
| 184 | n/a | arg = str; |
|---|
| 185 | n/a | } |
|---|
| 186 | n/a | } |
|---|
| 187 | n/a | else { |
|---|
| 188 | n/a | if (len > IOCTL_BUFSZ) { |
|---|
| 189 | n/a | PyBuffer_Release(&pstr); |
|---|
| 190 | n/a | PyErr_SetString(PyExc_ValueError, |
|---|
| 191 | n/a | "ioctl string arg too long"); |
|---|
| 192 | n/a | return NULL; |
|---|
| 193 | n/a | } |
|---|
| 194 | n/a | else { |
|---|
| 195 | n/a | memcpy(buf, str, len); |
|---|
| 196 | n/a | buf[len] = '\0'; |
|---|
| 197 | n/a | arg = buf; |
|---|
| 198 | n/a | } |
|---|
| 199 | n/a | } |
|---|
| 200 | n/a | if (buf == arg) { |
|---|
| 201 | n/a | Py_BEGIN_ALLOW_THREADS /* think array.resize() */ |
|---|
| 202 | n/a | ret = ioctl(fd, code, arg); |
|---|
| 203 | n/a | Py_END_ALLOW_THREADS |
|---|
| 204 | n/a | } |
|---|
| 205 | n/a | else { |
|---|
| 206 | n/a | ret = ioctl(fd, code, arg); |
|---|
| 207 | n/a | } |
|---|
| 208 | n/a | if (mutate_arg && (len <= IOCTL_BUFSZ)) { |
|---|
| 209 | n/a | memcpy(str, buf, len); |
|---|
| 210 | n/a | } |
|---|
| 211 | n/a | PyBuffer_Release(&pstr); /* No further access to str below this point */ |
|---|
| 212 | n/a | if (ret < 0) { |
|---|
| 213 | n/a | PyErr_SetFromErrno(PyExc_IOError); |
|---|
| 214 | n/a | return NULL; |
|---|
| 215 | n/a | } |
|---|
| 216 | n/a | if (mutate_arg) { |
|---|
| 217 | n/a | return PyLong_FromLong(ret); |
|---|
| 218 | n/a | } |
|---|
| 219 | n/a | else { |
|---|
| 220 | n/a | return PyBytes_FromStringAndSize(buf, len); |
|---|
| 221 | n/a | } |
|---|
| 222 | n/a | } |
|---|
| 223 | n/a | |
|---|
| 224 | n/a | PyErr_Clear(); |
|---|
| 225 | n/a | if (PyArg_Parse(ob_arg, "s*:ioctl", &pstr)) { |
|---|
| 226 | n/a | str = pstr.buf; |
|---|
| 227 | n/a | len = pstr.len; |
|---|
| 228 | n/a | if (len > IOCTL_BUFSZ) { |
|---|
| 229 | n/a | PyBuffer_Release(&pstr); |
|---|
| 230 | n/a | PyErr_SetString(PyExc_ValueError, |
|---|
| 231 | n/a | "ioctl string arg too long"); |
|---|
| 232 | n/a | return NULL; |
|---|
| 233 | n/a | } |
|---|
| 234 | n/a | memcpy(buf, str, len); |
|---|
| 235 | n/a | buf[len] = '\0'; |
|---|
| 236 | n/a | Py_BEGIN_ALLOW_THREADS |
|---|
| 237 | n/a | ret = ioctl(fd, code, buf); |
|---|
| 238 | n/a | Py_END_ALLOW_THREADS |
|---|
| 239 | n/a | if (ret < 0) { |
|---|
| 240 | n/a | PyBuffer_Release(&pstr); |
|---|
| 241 | n/a | PyErr_SetFromErrno(PyExc_IOError); |
|---|
| 242 | n/a | return NULL; |
|---|
| 243 | n/a | } |
|---|
| 244 | n/a | PyBuffer_Release(&pstr); |
|---|
| 245 | n/a | return PyBytes_FromStringAndSize(buf, len); |
|---|
| 246 | n/a | } |
|---|
| 247 | n/a | |
|---|
| 248 | n/a | PyErr_Clear(); |
|---|
| 249 | n/a | if (!PyArg_Parse(ob_arg, |
|---|
| 250 | n/a | "i;ioctl requires a file or file descriptor," |
|---|
| 251 | n/a | " an integer and optionally an integer or buffer argument", |
|---|
| 252 | n/a | &arg)) { |
|---|
| 253 | n/a | return NULL; |
|---|
| 254 | n/a | } |
|---|
| 255 | n/a | // Fall-through to outside the 'if' statement. |
|---|
| 256 | n/a | } |
|---|
| 257 | n/a | Py_BEGIN_ALLOW_THREADS |
|---|
| 258 | n/a | ret = ioctl(fd, code, arg); |
|---|
| 259 | n/a | Py_END_ALLOW_THREADS |
|---|
| 260 | n/a | if (ret < 0) { |
|---|
| 261 | n/a | PyErr_SetFromErrno(PyExc_IOError); |
|---|
| 262 | n/a | return NULL; |
|---|
| 263 | n/a | } |
|---|
| 264 | n/a | return PyLong_FromLong((long)ret); |
|---|
| 265 | n/a | #undef IOCTL_BUFSZ |
|---|
| 266 | n/a | } |
|---|
| 267 | n/a | |
|---|
| 268 | n/a | /*[clinic input] |
|---|
| 269 | n/a | fcntl.flock |
|---|
| 270 | n/a | |
|---|
| 271 | n/a | fd: object(type='int', converter='conv_descriptor') |
|---|
| 272 | n/a | operation as code: int |
|---|
| 273 | n/a | / |
|---|
| 274 | n/a | |
|---|
| 275 | n/a | Perform the lock operation `operation` on file descriptor `fd`. |
|---|
| 276 | n/a | |
|---|
| 277 | n/a | See the Unix manual page for flock(2) for details (On some systems, this |
|---|
| 278 | n/a | function is emulated using fcntl()). |
|---|
| 279 | n/a | [clinic start generated code]*/ |
|---|
| 280 | n/a | |
|---|
| 281 | n/a | static PyObject * |
|---|
| 282 | n/a | fcntl_flock_impl(PyObject *module, int fd, int code) |
|---|
| 283 | n/a | /*[clinic end generated code: output=84059e2b37d2fc64 input=b70a0a41ca22a8a0]*/ |
|---|
| 284 | n/a | { |
|---|
| 285 | n/a | int ret; |
|---|
| 286 | n/a | |
|---|
| 287 | n/a | #ifdef HAVE_FLOCK |
|---|
| 288 | n/a | Py_BEGIN_ALLOW_THREADS |
|---|
| 289 | n/a | ret = flock(fd, code); |
|---|
| 290 | n/a | Py_END_ALLOW_THREADS |
|---|
| 291 | n/a | #else |
|---|
| 292 | n/a | |
|---|
| 293 | n/a | #ifndef LOCK_SH |
|---|
| 294 | n/a | #define LOCK_SH 1 /* shared lock */ |
|---|
| 295 | n/a | #define LOCK_EX 2 /* exclusive lock */ |
|---|
| 296 | n/a | #define LOCK_NB 4 /* don't block when locking */ |
|---|
| 297 | n/a | #define LOCK_UN 8 /* unlock */ |
|---|
| 298 | n/a | #endif |
|---|
| 299 | n/a | { |
|---|
| 300 | n/a | struct flock l; |
|---|
| 301 | n/a | if (code == LOCK_UN) |
|---|
| 302 | n/a | l.l_type = F_UNLCK; |
|---|
| 303 | n/a | else if (code & LOCK_SH) |
|---|
| 304 | n/a | l.l_type = F_RDLCK; |
|---|
| 305 | n/a | else if (code & LOCK_EX) |
|---|
| 306 | n/a | l.l_type = F_WRLCK; |
|---|
| 307 | n/a | else { |
|---|
| 308 | n/a | PyErr_SetString(PyExc_ValueError, |
|---|
| 309 | n/a | "unrecognized flock argument"); |
|---|
| 310 | n/a | return NULL; |
|---|
| 311 | n/a | } |
|---|
| 312 | n/a | l.l_whence = l.l_start = l.l_len = 0; |
|---|
| 313 | n/a | Py_BEGIN_ALLOW_THREADS |
|---|
| 314 | n/a | ret = fcntl(fd, (code & LOCK_NB) ? F_SETLK : F_SETLKW, &l); |
|---|
| 315 | n/a | Py_END_ALLOW_THREADS |
|---|
| 316 | n/a | } |
|---|
| 317 | n/a | #endif /* HAVE_FLOCK */ |
|---|
| 318 | n/a | if (ret < 0) { |
|---|
| 319 | n/a | PyErr_SetFromErrno(PyExc_IOError); |
|---|
| 320 | n/a | return NULL; |
|---|
| 321 | n/a | } |
|---|
| 322 | n/a | Py_RETURN_NONE; |
|---|
| 323 | n/a | } |
|---|
| 324 | n/a | |
|---|
| 325 | n/a | |
|---|
| 326 | n/a | /*[clinic input] |
|---|
| 327 | n/a | fcntl.lockf |
|---|
| 328 | n/a | |
|---|
| 329 | n/a | fd: object(type='int', converter='conv_descriptor') |
|---|
| 330 | n/a | cmd as code: int |
|---|
| 331 | n/a | len as lenobj: object(c_default='NULL') = 0 |
|---|
| 332 | n/a | start as startobj: object(c_default='NULL') = 0 |
|---|
| 333 | n/a | whence: int = 0 |
|---|
| 334 | n/a | / |
|---|
| 335 | n/a | |
|---|
| 336 | n/a | A wrapper around the fcntl() locking calls. |
|---|
| 337 | n/a | |
|---|
| 338 | n/a | `fd` is the file descriptor of the file to lock or unlock, and operation is one |
|---|
| 339 | n/a | of the following values: |
|---|
| 340 | n/a | |
|---|
| 341 | n/a | LOCK_UN - unlock |
|---|
| 342 | n/a | LOCK_SH - acquire a shared lock |
|---|
| 343 | n/a | LOCK_EX - acquire an exclusive lock |
|---|
| 344 | n/a | |
|---|
| 345 | n/a | When operation is LOCK_SH or LOCK_EX, it can also be bitwise ORed with |
|---|
| 346 | n/a | LOCK_NB to avoid blocking on lock acquisition. If LOCK_NB is used and the |
|---|
| 347 | n/a | lock cannot be acquired, an OSError will be raised and the exception will |
|---|
| 348 | n/a | have an errno attribute set to EACCES or EAGAIN (depending on the operating |
|---|
| 349 | n/a | system -- for portability, check for either value). |
|---|
| 350 | n/a | |
|---|
| 351 | n/a | `len` is the number of bytes to lock, with the default meaning to lock to |
|---|
| 352 | n/a | EOF. `start` is the byte offset, relative to `whence`, to that the lock |
|---|
| 353 | n/a | starts. `whence` is as with fileobj.seek(), specifically: |
|---|
| 354 | n/a | |
|---|
| 355 | n/a | 0 - relative to the start of the file (SEEK_SET) |
|---|
| 356 | n/a | 1 - relative to the current buffer position (SEEK_CUR) |
|---|
| 357 | n/a | 2 - relative to the end of the file (SEEK_END) |
|---|
| 358 | n/a | [clinic start generated code]*/ |
|---|
| 359 | n/a | |
|---|
| 360 | n/a | static PyObject * |
|---|
| 361 | n/a | fcntl_lockf_impl(PyObject *module, int fd, int code, PyObject *lenobj, |
|---|
| 362 | n/a | PyObject *startobj, int whence) |
|---|
| 363 | n/a | /*[clinic end generated code: output=4985e7a172e7461a input=3a5dc01b04371f1a]*/ |
|---|
| 364 | n/a | { |
|---|
| 365 | n/a | int ret; |
|---|
| 366 | n/a | |
|---|
| 367 | n/a | #ifndef LOCK_SH |
|---|
| 368 | n/a | #define LOCK_SH 1 /* shared lock */ |
|---|
| 369 | n/a | #define LOCK_EX 2 /* exclusive lock */ |
|---|
| 370 | n/a | #define LOCK_NB 4 /* don't block when locking */ |
|---|
| 371 | n/a | #define LOCK_UN 8 /* unlock */ |
|---|
| 372 | n/a | #endif /* LOCK_SH */ |
|---|
| 373 | n/a | { |
|---|
| 374 | n/a | struct flock l; |
|---|
| 375 | n/a | if (code == LOCK_UN) |
|---|
| 376 | n/a | l.l_type = F_UNLCK; |
|---|
| 377 | n/a | else if (code & LOCK_SH) |
|---|
| 378 | n/a | l.l_type = F_RDLCK; |
|---|
| 379 | n/a | else if (code & LOCK_EX) |
|---|
| 380 | n/a | l.l_type = F_WRLCK; |
|---|
| 381 | n/a | else { |
|---|
| 382 | n/a | PyErr_SetString(PyExc_ValueError, |
|---|
| 383 | n/a | "unrecognized lockf argument"); |
|---|
| 384 | n/a | return NULL; |
|---|
| 385 | n/a | } |
|---|
| 386 | n/a | l.l_start = l.l_len = 0; |
|---|
| 387 | n/a | if (startobj != NULL) { |
|---|
| 388 | n/a | #if !defined(HAVE_LARGEFILE_SUPPORT) |
|---|
| 389 | n/a | l.l_start = PyLong_AsLong(startobj); |
|---|
| 390 | n/a | #else |
|---|
| 391 | n/a | l.l_start = PyLong_Check(startobj) ? |
|---|
| 392 | n/a | PyLong_AsLongLong(startobj) : |
|---|
| 393 | n/a | PyLong_AsLong(startobj); |
|---|
| 394 | n/a | #endif |
|---|
| 395 | n/a | if (PyErr_Occurred()) |
|---|
| 396 | n/a | return NULL; |
|---|
| 397 | n/a | } |
|---|
| 398 | n/a | if (lenobj != NULL) { |
|---|
| 399 | n/a | #if !defined(HAVE_LARGEFILE_SUPPORT) |
|---|
| 400 | n/a | l.l_len = PyLong_AsLong(lenobj); |
|---|
| 401 | n/a | #else |
|---|
| 402 | n/a | l.l_len = PyLong_Check(lenobj) ? |
|---|
| 403 | n/a | PyLong_AsLongLong(lenobj) : |
|---|
| 404 | n/a | PyLong_AsLong(lenobj); |
|---|
| 405 | n/a | #endif |
|---|
| 406 | n/a | if (PyErr_Occurred()) |
|---|
| 407 | n/a | return NULL; |
|---|
| 408 | n/a | } |
|---|
| 409 | n/a | l.l_whence = whence; |
|---|
| 410 | n/a | Py_BEGIN_ALLOW_THREADS |
|---|
| 411 | n/a | ret = fcntl(fd, (code & LOCK_NB) ? F_SETLK : F_SETLKW, &l); |
|---|
| 412 | n/a | Py_END_ALLOW_THREADS |
|---|
| 413 | n/a | } |
|---|
| 414 | n/a | if (ret < 0) { |
|---|
| 415 | n/a | PyErr_SetFromErrno(PyExc_IOError); |
|---|
| 416 | n/a | return NULL; |
|---|
| 417 | n/a | } |
|---|
| 418 | n/a | Py_RETURN_NONE; |
|---|
| 419 | n/a | } |
|---|
| 420 | n/a | |
|---|
| 421 | n/a | /* List of functions */ |
|---|
| 422 | n/a | |
|---|
| 423 | n/a | static PyMethodDef fcntl_methods[] = { |
|---|
| 424 | n/a | FCNTL_FCNTL_METHODDEF |
|---|
| 425 | n/a | FCNTL_IOCTL_METHODDEF |
|---|
| 426 | n/a | FCNTL_FLOCK_METHODDEF |
|---|
| 427 | n/a | FCNTL_LOCKF_METHODDEF |
|---|
| 428 | n/a | {NULL, NULL} /* sentinel */ |
|---|
| 429 | n/a | }; |
|---|
| 430 | n/a | |
|---|
| 431 | n/a | |
|---|
| 432 | n/a | PyDoc_STRVAR(module_doc, |
|---|
| 433 | n/a | "This module performs file control and I/O control on file \n\ |
|---|
| 434 | n/a | descriptors. It is an interface to the fcntl() and ioctl() Unix\n\ |
|---|
| 435 | n/a | routines. File descriptors can be obtained with the fileno() method of\n\ |
|---|
| 436 | n/a | a file or socket object."); |
|---|
| 437 | n/a | |
|---|
| 438 | n/a | /* Module initialisation */ |
|---|
| 439 | n/a | |
|---|
| 440 | n/a | |
|---|
| 441 | n/a | static int |
|---|
| 442 | n/a | all_ins(PyObject* m) |
|---|
| 443 | n/a | { |
|---|
| 444 | n/a | if (PyModule_AddIntMacro(m, LOCK_SH)) return -1; |
|---|
| 445 | n/a | if (PyModule_AddIntMacro(m, LOCK_EX)) return -1; |
|---|
| 446 | n/a | if (PyModule_AddIntMacro(m, LOCK_NB)) return -1; |
|---|
| 447 | n/a | if (PyModule_AddIntMacro(m, LOCK_UN)) return -1; |
|---|
| 448 | n/a | /* GNU extensions, as of glibc 2.2.4 */ |
|---|
| 449 | n/a | #ifdef LOCK_MAND |
|---|
| 450 | n/a | if (PyModule_AddIntMacro(m, LOCK_MAND)) return -1; |
|---|
| 451 | n/a | #endif |
|---|
| 452 | n/a | #ifdef LOCK_READ |
|---|
| 453 | n/a | if (PyModule_AddIntMacro(m, LOCK_READ)) return -1; |
|---|
| 454 | n/a | #endif |
|---|
| 455 | n/a | #ifdef LOCK_WRITE |
|---|
| 456 | n/a | if (PyModule_AddIntMacro(m, LOCK_WRITE)) return -1; |
|---|
| 457 | n/a | #endif |
|---|
| 458 | n/a | #ifdef LOCK_RW |
|---|
| 459 | n/a | if (PyModule_AddIntMacro(m, LOCK_RW)) return -1; |
|---|
| 460 | n/a | #endif |
|---|
| 461 | n/a | |
|---|
| 462 | n/a | #ifdef F_DUPFD |
|---|
| 463 | n/a | if (PyModule_AddIntMacro(m, F_DUPFD)) return -1; |
|---|
| 464 | n/a | #endif |
|---|
| 465 | n/a | #ifdef F_DUPFD_CLOEXEC |
|---|
| 466 | n/a | if (PyModule_AddIntMacro(m, F_DUPFD_CLOEXEC)) return -1; |
|---|
| 467 | n/a | #endif |
|---|
| 468 | n/a | #ifdef F_GETFD |
|---|
| 469 | n/a | if (PyModule_AddIntMacro(m, F_GETFD)) return -1; |
|---|
| 470 | n/a | #endif |
|---|
| 471 | n/a | #ifdef F_SETFD |
|---|
| 472 | n/a | if (PyModule_AddIntMacro(m, F_SETFD)) return -1; |
|---|
| 473 | n/a | #endif |
|---|
| 474 | n/a | #ifdef F_GETFL |
|---|
| 475 | n/a | if (PyModule_AddIntMacro(m, F_GETFL)) return -1; |
|---|
| 476 | n/a | #endif |
|---|
| 477 | n/a | #ifdef F_SETFL |
|---|
| 478 | n/a | if (PyModule_AddIntMacro(m, F_SETFL)) return -1; |
|---|
| 479 | n/a | #endif |
|---|
| 480 | n/a | #ifdef F_GETLK |
|---|
| 481 | n/a | if (PyModule_AddIntMacro(m, F_GETLK)) return -1; |
|---|
| 482 | n/a | #endif |
|---|
| 483 | n/a | #ifdef F_SETLK |
|---|
| 484 | n/a | if (PyModule_AddIntMacro(m, F_SETLK)) return -1; |
|---|
| 485 | n/a | #endif |
|---|
| 486 | n/a | #ifdef F_SETLKW |
|---|
| 487 | n/a | if (PyModule_AddIntMacro(m, F_SETLKW)) return -1; |
|---|
| 488 | n/a | #endif |
|---|
| 489 | n/a | #ifdef F_GETOWN |
|---|
| 490 | n/a | if (PyModule_AddIntMacro(m, F_GETOWN)) return -1; |
|---|
| 491 | n/a | #endif |
|---|
| 492 | n/a | #ifdef F_SETOWN |
|---|
| 493 | n/a | if (PyModule_AddIntMacro(m, F_SETOWN)) return -1; |
|---|
| 494 | n/a | #endif |
|---|
| 495 | n/a | #ifdef F_GETSIG |
|---|
| 496 | n/a | if (PyModule_AddIntMacro(m, F_GETSIG)) return -1; |
|---|
| 497 | n/a | #endif |
|---|
| 498 | n/a | #ifdef F_SETSIG |
|---|
| 499 | n/a | if (PyModule_AddIntMacro(m, F_SETSIG)) return -1; |
|---|
| 500 | n/a | #endif |
|---|
| 501 | n/a | #ifdef F_RDLCK |
|---|
| 502 | n/a | if (PyModule_AddIntMacro(m, F_RDLCK)) return -1; |
|---|
| 503 | n/a | #endif |
|---|
| 504 | n/a | #ifdef F_WRLCK |
|---|
| 505 | n/a | if (PyModule_AddIntMacro(m, F_WRLCK)) return -1; |
|---|
| 506 | n/a | #endif |
|---|
| 507 | n/a | #ifdef F_UNLCK |
|---|
| 508 | n/a | if (PyModule_AddIntMacro(m, F_UNLCK)) return -1; |
|---|
| 509 | n/a | #endif |
|---|
| 510 | n/a | /* LFS constants */ |
|---|
| 511 | n/a | #ifdef F_GETLK64 |
|---|
| 512 | n/a | if (PyModule_AddIntMacro(m, F_GETLK64)) return -1; |
|---|
| 513 | n/a | #endif |
|---|
| 514 | n/a | #ifdef F_SETLK64 |
|---|
| 515 | n/a | if (PyModule_AddIntMacro(m, F_SETLK64)) return -1; |
|---|
| 516 | n/a | #endif |
|---|
| 517 | n/a | #ifdef F_SETLKW64 |
|---|
| 518 | n/a | if (PyModule_AddIntMacro(m, F_SETLKW64)) return -1; |
|---|
| 519 | n/a | #endif |
|---|
| 520 | n/a | /* GNU extensions, as of glibc 2.2.4. */ |
|---|
| 521 | n/a | #ifdef FASYNC |
|---|
| 522 | n/a | if (PyModule_AddIntMacro(m, FASYNC)) return -1; |
|---|
| 523 | n/a | #endif |
|---|
| 524 | n/a | #ifdef F_SETLEASE |
|---|
| 525 | n/a | if (PyModule_AddIntMacro(m, F_SETLEASE)) return -1; |
|---|
| 526 | n/a | #endif |
|---|
| 527 | n/a | #ifdef F_GETLEASE |
|---|
| 528 | n/a | if (PyModule_AddIntMacro(m, F_GETLEASE)) return -1; |
|---|
| 529 | n/a | #endif |
|---|
| 530 | n/a | #ifdef F_NOTIFY |
|---|
| 531 | n/a | if (PyModule_AddIntMacro(m, F_NOTIFY)) return -1; |
|---|
| 532 | n/a | #endif |
|---|
| 533 | n/a | /* Old BSD flock(). */ |
|---|
| 534 | n/a | #ifdef F_EXLCK |
|---|
| 535 | n/a | if (PyModule_AddIntMacro(m, F_EXLCK)) return -1; |
|---|
| 536 | n/a | #endif |
|---|
| 537 | n/a | #ifdef F_SHLCK |
|---|
| 538 | n/a | if (PyModule_AddIntMacro(m, F_SHLCK)) return -1; |
|---|
| 539 | n/a | #endif |
|---|
| 540 | n/a | |
|---|
| 541 | n/a | /* OS X specifics */ |
|---|
| 542 | n/a | #ifdef F_FULLFSYNC |
|---|
| 543 | n/a | if (PyModule_AddIntMacro(m, F_FULLFSYNC)) return -1; |
|---|
| 544 | n/a | #endif |
|---|
| 545 | n/a | #ifdef F_NOCACHE |
|---|
| 546 | n/a | if (PyModule_AddIntMacro(m, F_NOCACHE)) return -1; |
|---|
| 547 | n/a | #endif |
|---|
| 548 | n/a | |
|---|
| 549 | n/a | /* For F_{GET|SET}FL */ |
|---|
| 550 | n/a | #ifdef FD_CLOEXEC |
|---|
| 551 | n/a | if (PyModule_AddIntMacro(m, FD_CLOEXEC)) return -1; |
|---|
| 552 | n/a | #endif |
|---|
| 553 | n/a | |
|---|
| 554 | n/a | /* For F_NOTIFY */ |
|---|
| 555 | n/a | #ifdef DN_ACCESS |
|---|
| 556 | n/a | if (PyModule_AddIntMacro(m, DN_ACCESS)) return -1; |
|---|
| 557 | n/a | #endif |
|---|
| 558 | n/a | #ifdef DN_MODIFY |
|---|
| 559 | n/a | if (PyModule_AddIntMacro(m, DN_MODIFY)) return -1; |
|---|
| 560 | n/a | #endif |
|---|
| 561 | n/a | #ifdef DN_CREATE |
|---|
| 562 | n/a | if (PyModule_AddIntMacro(m, DN_CREATE)) return -1; |
|---|
| 563 | n/a | #endif |
|---|
| 564 | n/a | #ifdef DN_DELETE |
|---|
| 565 | n/a | if (PyModule_AddIntMacro(m, DN_DELETE)) return -1; |
|---|
| 566 | n/a | #endif |
|---|
| 567 | n/a | #ifdef DN_RENAME |
|---|
| 568 | n/a | if (PyModule_AddIntMacro(m, DN_RENAME)) return -1; |
|---|
| 569 | n/a | #endif |
|---|
| 570 | n/a | #ifdef DN_ATTRIB |
|---|
| 571 | n/a | if (PyModule_AddIntMacro(m, DN_ATTRIB)) return -1; |
|---|
| 572 | n/a | #endif |
|---|
| 573 | n/a | #ifdef DN_MULTISHOT |
|---|
| 574 | n/a | if (PyModule_AddIntMacro(m, DN_MULTISHOT)) return -1; |
|---|
| 575 | n/a | #endif |
|---|
| 576 | n/a | |
|---|
| 577 | n/a | #ifdef HAVE_STROPTS_H |
|---|
| 578 | n/a | /* Unix 98 guarantees that these are in stropts.h. */ |
|---|
| 579 | n/a | if (PyModule_AddIntMacro(m, I_PUSH)) return -1; |
|---|
| 580 | n/a | if (PyModule_AddIntMacro(m, I_POP)) return -1; |
|---|
| 581 | n/a | if (PyModule_AddIntMacro(m, I_LOOK)) return -1; |
|---|
| 582 | n/a | if (PyModule_AddIntMacro(m, I_FLUSH)) return -1; |
|---|
| 583 | n/a | if (PyModule_AddIntMacro(m, I_FLUSHBAND)) return -1; |
|---|
| 584 | n/a | if (PyModule_AddIntMacro(m, I_SETSIG)) return -1; |
|---|
| 585 | n/a | if (PyModule_AddIntMacro(m, I_GETSIG)) return -1; |
|---|
| 586 | n/a | if (PyModule_AddIntMacro(m, I_FIND)) return -1; |
|---|
| 587 | n/a | if (PyModule_AddIntMacro(m, I_PEEK)) return -1; |
|---|
| 588 | n/a | if (PyModule_AddIntMacro(m, I_SRDOPT)) return -1; |
|---|
| 589 | n/a | if (PyModule_AddIntMacro(m, I_GRDOPT)) return -1; |
|---|
| 590 | n/a | if (PyModule_AddIntMacro(m, I_NREAD)) return -1; |
|---|
| 591 | n/a | if (PyModule_AddIntMacro(m, I_FDINSERT)) return -1; |
|---|
| 592 | n/a | if (PyModule_AddIntMacro(m, I_STR)) return -1; |
|---|
| 593 | n/a | if (PyModule_AddIntMacro(m, I_SWROPT)) return -1; |
|---|
| 594 | n/a | #ifdef I_GWROPT |
|---|
| 595 | n/a | /* despite the comment above, old-ish glibcs miss a couple... */ |
|---|
| 596 | n/a | if (PyModule_AddIntMacro(m, I_GWROPT)) return -1; |
|---|
| 597 | n/a | #endif |
|---|
| 598 | n/a | if (PyModule_AddIntMacro(m, I_SENDFD)) return -1; |
|---|
| 599 | n/a | if (PyModule_AddIntMacro(m, I_RECVFD)) return -1; |
|---|
| 600 | n/a | if (PyModule_AddIntMacro(m, I_LIST)) return -1; |
|---|
| 601 | n/a | if (PyModule_AddIntMacro(m, I_ATMARK)) return -1; |
|---|
| 602 | n/a | if (PyModule_AddIntMacro(m, I_CKBAND)) return -1; |
|---|
| 603 | n/a | if (PyModule_AddIntMacro(m, I_GETBAND)) return -1; |
|---|
| 604 | n/a | if (PyModule_AddIntMacro(m, I_CANPUT)) return -1; |
|---|
| 605 | n/a | if (PyModule_AddIntMacro(m, I_SETCLTIME)) return -1; |
|---|
| 606 | n/a | #ifdef I_GETCLTIME |
|---|
| 607 | n/a | if (PyModule_AddIntMacro(m, I_GETCLTIME)) return -1; |
|---|
| 608 | n/a | #endif |
|---|
| 609 | n/a | if (PyModule_AddIntMacro(m, I_LINK)) return -1; |
|---|
| 610 | n/a | if (PyModule_AddIntMacro(m, I_UNLINK)) return -1; |
|---|
| 611 | n/a | if (PyModule_AddIntMacro(m, I_PLINK)) return -1; |
|---|
| 612 | n/a | if (PyModule_AddIntMacro(m, I_PUNLINK)) return -1; |
|---|
| 613 | n/a | #endif |
|---|
| 614 | n/a | |
|---|
| 615 | n/a | return 0; |
|---|
| 616 | n/a | } |
|---|
| 617 | n/a | |
|---|
| 618 | n/a | |
|---|
| 619 | n/a | static struct PyModuleDef fcntlmodule = { |
|---|
| 620 | n/a | PyModuleDef_HEAD_INIT, |
|---|
| 621 | n/a | "fcntl", |
|---|
| 622 | n/a | module_doc, |
|---|
| 623 | n/a | -1, |
|---|
| 624 | n/a | fcntl_methods, |
|---|
| 625 | n/a | NULL, |
|---|
| 626 | n/a | NULL, |
|---|
| 627 | n/a | NULL, |
|---|
| 628 | n/a | NULL |
|---|
| 629 | n/a | }; |
|---|
| 630 | n/a | |
|---|
| 631 | n/a | PyMODINIT_FUNC |
|---|
| 632 | n/a | PyInit_fcntl(void) |
|---|
| 633 | n/a | { |
|---|
| 634 | n/a | PyObject *m; |
|---|
| 635 | n/a | |
|---|
| 636 | n/a | /* Create the module and add the functions and documentation */ |
|---|
| 637 | n/a | m = PyModule_Create(&fcntlmodule); |
|---|
| 638 | n/a | if (m == NULL) |
|---|
| 639 | n/a | return NULL; |
|---|
| 640 | n/a | |
|---|
| 641 | n/a | /* Add some symbolic constants to the module */ |
|---|
| 642 | n/a | if (all_ins(m) < 0) |
|---|
| 643 | n/a | return NULL; |
|---|
| 644 | n/a | |
|---|
| 645 | n/a | return m; |
|---|
| 646 | n/a | } |
|---|