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