"fcntl" --- Las llamadas a sistema "fcntl" y "ioctl"
****************************************************

======================================================================

Este módulo realiza control de archivos y control de E/S en
descriptores de ficheros. Es una interfaz para las rutinas de Unix
"fcntl()" y "ioctl()". Para una completa descripción de estas
llamadas, ver las páginas del manual de Unix *fcntl(2)* y *ioctl(2)*.

Todas las funciones de este módulo toman un descriptor de fichero *fd*
como su primer argumento.  Puede ser un descriptor de fichero entero,
como el retornado por "sys.stdin.fileno()", o un objeto "io.IOBase",
como *sys.stdin`*, que proporciona un "fileno()" que retornan un
descriptor de fichero original.

Distinto en la versión 3.3: Las operaciones en este módulo solían
lanzar un "IOError" donde ahora lanzan un "OSError".

Distinto en la versión 3.8: El módulo *fcntl* ahora contiene las
constantes "F_ADD_SEALS", "F_GET_SEALS", y "F_SEAL_*" para sellar los
descriptores de fichero "os.memfd_create()".

Distinto en la versión 3.9: On macOS, the fcntl module exposes the
"F_GETPATH" constant, which obtains the path of a file from a file
descriptor. On Linux(>=3.15), the fcntl module exposes the
"F_OFD_GETLK", "F_OFD_SETLK" and "F_OFD_SETLKW" constants, which are
used when working with open file description locks.

Distinto en la versión 3.10: En Linux >= 2.6.11, el módulo fcntl
expone las constantes "F_GETPIPE_SZ" y "F_SETPIPE_SZ", las cuales
permiten chequear y modificar el tamaño de un *pipe*, respectivamente.

El módulo define las siguientes funciones:

fcntl.fcntl(fd, cmd, arg=0)

   Realice la operación *cmd* en el descriptor de fichero *fd* (los
   objetos de fichero que proporcionan un método "fileno()" también
   son aceptados). Los valores utilizados para *cmd* dependen del
   sistema operativo y están disponibles como constantes en el módulo
   "fcntl", utilizando los mismos nombres que se utilizan en los
   archivos de cabecera C relevantes. El argumento *arg* puede ser un
   valor entero o un objeto "bytes". Con un valor entero, el valor
   retorno de esta función es el valor entero retornado por la llamada
   en C "fcntl()" . Cuando el argumento son bytes representa una
   estructura binaria, e.g. creada por "struct.pack()". Los datos
   binarios se copian en un búfer cuya dirección se pasa a la llamada
   en C :"fcntl()". El valor de retorno después de una llamada
   correcta es el contenido del búfer, convertido en un objeto
   "bytes". La longitud del objeto retornado será la misma que la
   longitud del argumento *arg*. Esta longitud está limitada a 1024
   bytes. Si la información retornada en el búfer por el sistema
   operativo es mayor que 1024 bytes, lo más probable es que se
   produzca una violación de segmento o a una corrupción de datos más
   sutil.

   Si se produce un error en "fcntl()", se lanza un "OSError".

   Lanza un auditing event "fcntl.fcntl" con argumentos "fd", "cmd",
   "arg".

fcntl.ioctl(fd, request, arg=0, mutate_flag=True)

   Esta función es idéntica a la función "fcntl()", excepto por el
   manejo de los argumentos que es aún más complicado.

   El parámetro *request* se encuentra limitado a valores que encajen
   en 32-bits. Se pueden encontrar constantes adicionales de interés
   para usar como argumento *request* en el módulo "termios", con los
   mismos nombres que se usan en los archivos de cabecera C
   relevantes.

   El parámetro *arg* puede ser un entero, un objeto que admita una
   interfaz de búfer de solo lectura (como "bytes") o un objeto que
   admita una interfaz de búfer de lectura-escritura (como: clase
   "bytearray").

   En todos los casos excepto en el último, el comportamiento es el de
   la función "fcntl()".

   Si se pasa un búfer mutable, el comportamiento estará determinado
   por el valor del parámetro *mutate_flag*.

   Si es falso, la mutabilidad del búfer se ignorará y el
   comportamiento será como el de un búfer de solo lectura, excepto
   por el límite de 1024 bytes mencionado arriba, que será evitado --
   siempre que el búfer que pase sea al menos tan largo como el
   sistema operativo quiera colocar allí, las cosas deberían
   funcionar.

   Si *mutate_flag* es verdadero (valor predeterminado), entonces el
   búfer se pasa (en efecto) a la llamada al sistema subyacente
   "ioctl()", el código de retorno de éste último se retorna al Python
   que llama, y el nuevo contenido del búfer refleja la acción de
   "ioctl()". Esto es una ligera simplificación, porque si el búfer
   proporcionado tiene menos de 1024 bytes de longitud, primero se
   copia en un búfer estático de 1024 bytes de longitud que luego se
   pasa a "ioctl()" y se copia de nuevo en el búfer proporcionado.

   Si "ioctl()" falla, se lanza la excepción "OSError".

   Un ejemplo:

      >>> import array, fcntl, struct, termios, os
      >>> os.getpgrp()
      13341
      >>> struct.unpack('h', fcntl.ioctl(0, termios.TIOCGPGRP, "  "))[0]
      13341
      >>> buf = array.array('h', [0])
      >>> fcntl.ioctl(0, termios.TIOCGPGRP, buf, 1)
      0
      >>> buf
      array('h', [13341])

   Lanza un evento auditing event "fcntl.ioctl" con argumentos "fd",
   "request", "arg".

fcntl.flock(fd, operation)

   Realiza la operación de bloqueo *operation* sobre el descriptor de
   fichero *fd* (los objetos de fichero que proporcionan un método
   "fileno()" también son aceptados). Ver el manual de Unix *flock(2)*
   para más detalles. (En algunos sistemas, esta función es emulada
   usando "fcntl()".)

   Si "flock()" falla, una excepción "OSError" se lanza.

   Lanza un auditing event "fcntl.flock" con argumentos "fd",
   "operation".

fcntl.lockf(fd, cmd, len=0, start=0, whence=0)

   Esto es esencialmente un "wrapper" de las llamadas de bloqueo
   "fcntl()" . * fd * es el descriptor de fichero (los objetos de
   fichero que proporcionan un método "fileno()" también se aceptan)
   del archivo para bloquear o desbloquear, y *cmd* es uno de los
   siguientes valores:

   * "LOCK_UN" -- desbloquear

   * "LOCK_SH" -- adquirir un bloqueo compartido

   * "LOCK_EX" -- adquirir un bloqueo exclusivo

   Cuando *cmd* es "LOCK_SH" o "LOCK_EX", también se puede usar OR bit
   a bit con "LOCK_NB" para evitar el bloqueo en la adquisición de
   bloqueos. Si se usa "LOCK_NB" y no se puede adquirir el bloqueo, se
   lanzará un "LOCK_NB" y la excepción tendrá un atributo *errno*
   establecido a "EACCES" o "EAGAIN" (según el sistema operativo; para
   la portabilidad, compruebe ambos valores). En al menos algunos
   sistemas, "LOCK_EX" solo se puede usar si el descriptor de fichero
   se refiere a un archivo abierto para escritura.

   *len* es el número de bytes a bloquear, *start* es el byte de
   "offset" en el cual comienza el bloqueo, relativo a *whence*, y
   *whence* es como con "io.IOBase.seek()", específicamente:

   * "0" -- relativo al comienzo del archivo ("os.SEEK_SET")

   * "1" -- relativa a la posición actual del búfer ("os.SEEK_CUR")

   * "2" -- relativo al final del archivo ("os.SEEK_END")

   El valor por defecto de*start* es 0, lo que significa que comienza
   al inicio del archivo. El valor por defecto para *len* es 0 lo que
   significa bloquear hasta el final del archivo. El valor por defecto
   para *whence* también es 0.

   Lanza un auditing event "fcntl.lockf" con argumentos "fd", "cmd",
   "len", "start", "whence".

Ejemplos (todos en un sistema compatible con SVR4):

   import struct, fcntl, os

   f = open(...)
   rv = fcntl.fcntl(f, fcntl.F_SETFL, os.O_NDELAY)

   lockdata = struct.pack('hhllhh', fcntl.F_WRLCK, 0, 0, 0, 0, 0)
   rv = fcntl.fcntl(f, fcntl.F_SETLKW, lockdata)

Tenga en cuenta que en el primer ejemplo, la variable de valor de
retorno *rv* contendrá un valor entero; en el segundo ejemplo
contendrá un objeto "bytes". El diseño de la estructura para la
variable *lockdata* depende del sistema --- por lo tanto, usar la
llamada "flock()" puede ser mejor.

Ver también:

  Módulo  "os"
     Si los flags de bloqueo "O_SHLOCK" y "O_EXLOCK" están presentes
     en el módulo "os" (sólo en BSD), la función "os.open()"
     proporciona una alternativa a las funciones "lockf()" y
     "flock()".
