stat() es una llamada al sistema Unix que devuelve atributos de archivo sobre un inodo . La semántica de stat() varía entre sistemas operativos . Como ejemplo,el comando Unix ls 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 cambiaron, con la incorporación de permisos de grupo y un mayor tamaño de archivo 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 puntero a 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 se configura errno de forma adecuada.stat()
fstat()
lstat()
struct stat
Las funciones stat()
and lstat()
toman un argumento de nombre de archivo . Si el archivo es un enlace simbólico , stat()
devuelve los atributos del destino final del enlace, mientras que lstat()
devuelve los atributos del enlace en sí. La fstat()
función toma un argumento de descriptor de archivo en su lugar y devuelve los atributos del archivo que identifica.
La familia de funciones se amplió para implementar la compatibilidad con archivos de gran tamaño . Las funciones denominadas stat64()
y devuelven atributos en una estructura que representa tamaños lstat64()
de archivos con un tipo de 64 bits, lo que permite que las funciones funcionen en archivos de 2 GiB y más grandes (hasta 8 EiB). Cuando la macro se define en 64, estas funciones de 64 bits están disponibles con los nombres originales.fstat64()
struct stat64
_FILE_OFFSET_BITS
Las funciones se definen como:
int stat ( const char * nombre_archivo , struct stat * buf ); int lstat ( const char * nombre_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]
estructura stat { modo_t modo_est ; 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 tamaño_est ; estructura timespec st_atim ; estructura timespec st_mtim ; estructura timespec st_ctim ; blksize_t st_blksize ; blkcnt_t st_blocks ; };
POSIX.1 no requiere miembros st_rdev
, st_blocks
y 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 del tipo time_t
. Desde la versión 2008 del estándar, estos campos fueron renombrados a st_atim
, st_mtim
y st_ctim
, respectivamente, del 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 Unixst_nlink
– recuento de referencias de enlaces durosst_uid
– identificador de usuario del propietariost_gid
– identificador de grupo del propietariost_rdev
– identificador del 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 la 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 de ejecución y, en última instancia, requiere una escritura en el disco, lo que ha sido criticado por ser incompatible con un sistema de archivos de solo lectura. La memoria caché del sistema de archivos puede reducir significativamente esta actividad a una escritura en el disco por cada vaciado de la memoria 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 había convertido en la predeterminada, lo que aborda esta crítica. [6] El comportamiento detrás de la opción de montaje relatime ofrece un rendimiento suficiente para la mayoría de los propósitos y no debería dañar ninguna aplicación significativa, como se ha discutido ampliamente. [7] Inicialmente, relatime solo actualizaba atime si atime < mtime o atime < ctime; eso se modificó posteriormente para actualizar atimes 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 , que hace que el campo atime nunca se actualice. Desactivar la actualización de atime interrumpe la compatibilidad con POSIX y algunas aplicaciones, como las notificaciones de " correo nuevo " controladas por mbox , [9] y algunas utilidades de control 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 que las actualizaciones de atime de estilo POSIX se realicen en la memoria y se descarguen en el disco junto con algunas operaciones de E/S no relacionadas con el tiempo en el mismo archivo; las actualizaciones de atime también se descargan en el disco cuando se ejecutan algunas de las llamadas del sistema de sincronización , o antes de que el inodo en memoria del archivo se expulse de la memoria caché del sistema de archivos. Además, es posible configurar durante cuánto tiempo las modificaciones de atime pueden permanecer sin descargarse. 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, el último fue cambiado a tiempo de acceso antes de que hubiera alguna estructura de C en la que llamar a algo 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 al tiempo 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 duros . POSIX también exige la actualización de ctime (último cambio de estado) con write() distinto de cero (modificación del archivo). [14] En algunas implementaciones, ctime se ve afectado al cambiar el nombre de un archivo, a pesar de que los nombres de archivo no se almacenan en inodos: tanto el Unix original, que implementaba un cambio de nombre haciendo un enlace (actualizando ctime ) y luego desvinculando el nombre antiguo (actualizando ctime nuevamente) y el Linux moderno tienden a hacer esto.
A diferencia de atime y mtime , ctime no se puede configurar con un valor arbitrario con utime() , como lo utiliza la utilidad touch , por ejemplo. En cambio, cuando se utiliza 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 configura con la hora actual.
#include <stdio.h> #include <stdlib.h> #include <time.h> #include <sys/types.h> #include <pwd.h> #include <grp.h> #include <sys/stat.h> int principal ( int argc , char * argv []) { estructura stat sb ; estructura passwd * pwuser ; estructura grupo * grpnam ; if ( argc < 2 ) { fprintf ( stderr , "Uso: %s: archivo ... \n " , argv [ 0 ]); exit ( EXIT_FAILURE ); } para ( int i = 1 ; i < argc ; i ++ ) { si ( -1 == stat ( argv [ i ], & sb )) { perror ( "stat()" ); salir ( EXIT_FAILURE ); } si ( NULL == ( pwuser = getpwuid ( sb . st_uid ))) { perror ( "getpwuid()" ); salir ( EXIT_FAILURE ); } si ( 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 ); /* puede 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 " ); }devuelve 0 ; }
Una vez completado con éxito, donde 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