Python fcntl Library
Python provides various functions and commands for using and working with the files in codes. For working with these files we need to define file descriptors. A file descriptor is a number that uniquely identifies an open file in a computer's operating system. It describes a data resource, and how that resource may be accessed.
When a process makes a successful request to open a file, the kernel returns a file descriptor which points to an entry in the kernel's global file table. The file table entry contains information such as the inode of the file, byte offset, and the access restrictions for that data stream (read-only, write-only, etc.).
File Descriptors are the integer such as returned by the 'sys.stdin.fileno()' or an io.IOBase object such as sys.stdin itself, which provides a fileno() that returns a genuine file descriptor.
This Python module performs file control and I/O control on file descriptors. It is an interface to the fcntl() and ioctl() Unix routines. All the functions used in this module take a file descriptor 'fd' as their first argument to know which file they need to handle in the code.
Two of the functions in this module are:
1. fcntl.fcntl(fd, cmd, arg=0):
This is a function defined in the fcntl library in python. It takes three arguments. The first argument is the file descriptor of the file with which we need to work. The second argument contained the command 'cmd' which we want to perform on the file. The third argument is the arg which takes either the integer value or a bytes object. When arg is given an integer value, the return of this function is an integer value of C fcntl() call. And when the arg is bytes, it represent a binary structure , e.g. created by the struct.pack(). The binary data is copied to a buffer whose address is passed to the C fcntl() call. The return value after a successful call is the contents of the buffer, converted to a bytes object. The length of the returned object will be the same as the length of the arg argument and is limited to 1024 bytes, else if the information returned in the buffer by the operating system exceeds 1024 bytes, it is most likely to result in a segmentation violation or a more subtle data corruption.
So basically this function is used to perform the operation 'cmd' on the file using the file descriptor 'fd'.
If the fcntl() fails, an OSError is raised.
2. fcntl.ioctl(fd, request, arg=0, mutate_flag=True):
This function is similar to the fcntl() function, except that the argument handling is even more complicated.
The request parameter is limited to 32-bits values. Additional constants of interest for use as the request argument can be found in the termios module, under the same names as used in the relevant C header files.
The parameter 'arg' can be one of an integer, an object supporting the read-only buffer interface (like bytes) or an object supporting the read-write buffer interface (like byte array).
If a mutable buffer is passed, then the behavior is determined by the value of the mutate_flag parameter.
If the mutable_flag is false, the buffer’s mutability is ignored and behavior is as for a read-only buffer, except that the 1024 byte limit mentioned above is avoided – so long as the buffer you pass is at least as long as what the operating system wants to put there, things should work.
If mutate_flag is true (which it is by default), then the buffer is (in effect) passed to the underlying ioctl() system call, the latter’s return code is passed back to the calling Python, and the buffer’s new contents reflect the action of the ioctl(). This is a slight simplification, because if the supplied buffer is less than 1024 bytes long it is first copied into a static buffer 1024 bytes long which is then passed to ioctl() and copied back into the supplied buffer.
If the ioctl() fails, an OSError exception is raised.