stat() es una llamada al sistema Unix que devuelve atributos de archivo sobre un inodo . La semántica de stat() varía según el sistema operativo . Como ejemplo,el comando ls de Unix utiliza esta llamada al sistema para recuperar información sobre archivos que incluye:
stat
apareció en la Versión 1 de Unix . Es una de las pocas llamadas al sistema Unix originales que se deben cambiar, con la adición de permisos de grupo y un tamaño de archivo más grande en la Versión 4 . [1]
El encabezado de la biblioteca C POSIX sys/stat.h , que se encuentra en POSIX y otros sistemas operativos similares a Unix , declara las funciones, así como las funciones relacionadas llamadas y . Las funciones toman un argumento de búfer, que se utiliza para devolver los atributos del archivo. En caso de éxito, las funciones devuelven cero y, en caso de error, se devuelve −1 y errno se establece de forma adecuada.stat()
fstat()
lstat()
struct stat
Las funciones stat()
y lstat()
toman un argumento de nombre de archivo . Si el archivo es un enlace simbólico , stat()
devuelve atributos del destino final del enlace, mientras que lstat()
devuelve atributos del enlace en sí. En su lugar, la fstat()
función toma un argumento descriptor de archivo y devuelve atributos del archivo que identifica.
La familia de funciones se amplió para implementar soporte para archivos de gran tamaño . Funciones denominadas stat64()
y lstat64()
devuelven fstat64()
atributos en una struct stat64
estructura, que representa tamaños de archivos con un tipo de 64 bits, lo que permite que las funciones funcionen en archivos de 2 GiB y más (hasta 8 EiB). Cuando la _FILE_OFFSET_BITS
macro se define en 64, estas funciones de 64 bits están disponibles con los nombres originales.
Las funciones se definen como:
int stat ( const char * nombre de archivo , struct stat * buf ); int lstat ( const char * nombre de archivo , struct stat * buf ); int fstat ( int filedesc , struct stat * buf );
Esta estructura se define en el archivo de encabezado sys/stat.h de la siguiente manera, aunque las implementaciones son libres de definir campos adicionales: [2]
struct stat { modo_t st_mode ; ino_t st_ino ; dev_t st_dev ; dev_t st_rdev ; nlink_t st_nlink ; uid_t st_uid ; gid_t st_gid ; off_t st_size ; estructura especificación de tiempo st_atim ; estructura especificación de tiempo st_mtim ; estructura especificación de tiempo st_ctim ; blksize_t st_blksize ; blkcnt_t st_blocks ; };
POSIX.1 no requiere st_rdev
y st_blocks
miembros st_blksize
; Estos campos se definen como parte de la opción XSI en la Especificación Única de Unix.
En versiones anteriores del estándar POSIX.1, los campos relacionados con el tiempo se definían como st_atime
, st_mtime
y st_ctime
, y eran de tipo time_t
. Desde la versión 2008 del estándar, estos campos pasaron a llamarse st_atim
, st_mtim
y st_ctim
, respectivamente, de tipo struct timespec
, ya que esta estructura proporciona una unidad de tiempo de mayor resolución. Por motivos de compatibilidad, las implementaciones pueden definir los nombres antiguos en términos del tv_sec
miembro de struct timespec
. Por ejemplo, st_atime
se puede definir como st_atim.tv_sec
. [2]
La struct stat
estructura incluye al menos los siguientes miembros:
st_dev
– identificador del dispositivo que contiene el archivost_ino
– número de inodost_mode
– modo de protección ; ver también permisos de Unixst_nlink
– recuento de referencias de enlaces durosst_uid
– identificador de usuario del propietariost_gid
– identificador de grupo del propietariost_rdev
– identificador de dispositivo (si es un archivo especial )st_size
– tamaño total del archivo , en bytesst_atime
– hora del último accesost_mtime
– hora de la última modificaciónst_ctime
– hora del último cambio de estadost_blksize
– tamaño de bloque preferido para E/S del sistema de archivos, que puede depender tanto del sistema como del tipo de sistema de archivos [3]st_blocks
– número de bloques asignados en múltiplos de DEV_BSIZE
(normalmente 512 bytes).El st_mode
campo es un campo de bits . Combina los modos de acceso a archivos y también indica cualquier tipo de archivo especial . Hay muchas macros para trabajar con los diferentes indicadores de modo y tipos de archivos.
La lectura de un archivo cambia su tiempo y finalmente requiere una escritura en el disco, lo que ha sido criticado por ser inconsistente con un sistema de archivos de solo lectura. La caché del sistema de archivos puede reducir significativamente esta actividad a una escritura en disco por vaciado de caché.
El desarrollador del kernel de Linux, Ingo Molnár, criticó públicamente el concepto y el impacto en el rendimiento de atime en 2007, [4] [5] y en 2009, la opción de montaje relatime se convirtió en la predeterminada, lo que aborda esta crítica. [6] El comportamiento detrás de la opción de montaje relatime ofrece rendimiento suficiente para la mayoría de los propósitos y no debería interrumpir ninguna aplicación importante, como se ha discutido extensamente. [7] Inicialmente, relatime solo se actualiza atime si atime < mtime o atime < ctime; que posteriormente se modificó para actualizar horarios que tenían 24 horas o más, para que tmpwatch y el contador de popularidad de Debian (popcon) se comportaran correctamente. [8]
Las versiones actuales del kernel de Linux admiten cuatro opciones de montaje, que se pueden especificar en fstab :
Las versiones actuales de Linux , macOS , Solaris , FreeBSD y NetBSD admiten una opción de montaje noatime en /etc/fstab , lo que hace que el campo atime nunca se actualice. Desactivar la actualización a tiempo interrumpe el cumplimiento de POSIX y algunas aplicaciones, como las notificaciones de " correo nuevo" impulsadas por mbox , [9] y algunas utilidades de vigilancia del uso de archivos, en particular tmpwatch.
La opción noatime en OpenBSD se comporta más como relatime de Linux . [10]
La versión 4.0 de la línea principal del kernel de Linux , que se lanzó el 12 de abril de 2015, introdujo la nueva opción de montaje lazytime . Permite realizar actualizaciones horarias de estilo POSIX en la memoria y descargarlas en el disco junto con algunas operaciones de E/S no relacionadas con el tiempo en el mismo archivo; Las actualizaciones atime también se descargan en el disco cuando se ejecutan algunas de las llamadas al sistema de sincronización , o antes de que el inodo en memoria del archivo sea desalojado del caché del sistema de archivos. Además, es posible configurar durante cuánto tiempo las modificaciones pueden permanecer sin vaciar. De esa manera, lazytime conserva la compatibilidad con POSIX al tiempo que ofrece mejoras de rendimiento. [11] [12]
Es tentador creer que ctime originalmente significaba tiempo de creación; [13] sin embargo, mientras que los primeros Unix tenían tiempos de modificación y creación, este último se cambió para que fuera el tiempo de acceso antes de que existiera una estructura C en la que llamar a cualquier cosa ctime . Los sistemas de archivos conservaron solo el tiempo de acceso ( atime ) y el tiempo de modificación ( mtime ) hasta la sexta edición de Unix. La marca de tiempo ctime se agregó en la reestructuración del sistema de archivos que ocurrió con la Versión 7 de Unix y siempre se ha referido a la hora de cambio de inodo. Se actualiza cada vez que cambian los metadatos del archivo almacenados en el inodo, como los permisos del archivo , la propiedad del archivo y la creación y eliminación de enlaces físicos . POSIX también exige la actualización de ctime (último cambio de estado) con escritura distinta de cero () (modificación de archivo). [14] En algunas implementaciones, ctime se ve afectado al cambiar el nombre de un archivo, a pesar de que los nombres de los archivos no se almacenan en inodos: ambos Unix originales, que implementaron un cambio de nombre haciendo un enlace (actualizando ctime ) y luego desvinculando el nombre anterior (actualizando ctime nuevamente) y el Linux moderno tiende a hacer esto.
A diferencia de atime y mtime , ctime no se puede establecer en un valor arbitrario con utime() , como lo usa la utilidad táctil , por ejemplo. En cambio, cuando se usa utime() , o para cualquier otro cambio en el inodo que no sea una actualización de atime causada por el acceso al archivo, el valor de ctime se establece en la hora actual.
#incluye <stdio.h> #incluye <stdlib.h> #incluye <hora.h> #incluir <sys/types.h> #incluir <pwd.h> #incluir <grp.h> #incluir <sys/stat.h> int principal ( int argc , char * argv []) { estructura estadística sb ; estructura contraseña * pwuser ; grupo de estructuras * grpnam ; if ( argc < 2 ) { fprintf ( stderr , "Uso: %s: archivo... \n " , argv [ 0 ]); salir ( EXIT_FAILURE ); } for ( int i = 1 ; i < argc ; i ++ ) { if ( -1 == stat ( argv [ i ], & sb )) { perror ( "stat()" ); salir ( EXIT_FAILURE ); } if ( NULL == ( pwuser = getpwuid ( sb . st_uid ))) { perror ( "getpwuid()" ); salir ( EXIT_FAILURE ); } if ( NULL == ( grpnam = getgrgid ( sb . st_gid ))) { perror ( "getgrgid()" ); salir ( EXIT_FAILURE ); } printf ( "%s: \n " , argv [ i ]); printf ( " \t inodo: %u \n " , sb . st_ino ); printf ( " \t propietario: %u (%s) \n " , sb . st_uid , pwuser -> pw_name ); printf ( " \t grupo: %u (%s) \n " , sb . st_gid , grpnam -> gr_name ); printf ( " \t permisos: %o \n " , sb . st_mode & ( S_IRWXU | S_IRWXG | S_IRWXO )); printf ( " \t enlaces: %d \n " , sb . st_nlink ); printf ( " \t tamaño: %ld \ n " , sb.st_size ) ; /* puedes usar %lld */ printf ( " \t atime: %s" , ctime ( & sb . st_atim . tv_sec )); printf ( " \t mtime: %s" , ctime ( & sb . st_mtim . tv_sec )); printf ( " \t ctime: %s" , ctime ( & sb . st_ctim . tv_sec )); printf ( " \n " ); }devolver 0 ; }
Una vez completado con éxito, cuando nbyte es mayor que 0, write() marcará para actualizar las marcas de tiempo de la última modificación de datos y del último cambio de estado del archivo.