viernes, 5 de marzo de 2010

stat(), fstat() y reboot()

stat() y fstat()

stat() y fstat() son llamadas al sistema que obtienen la información del i-nodo de un archivo especificado por una cadena y un descriptor de archivo, respectivamente.

Los prototipos de estas llamadas son:

int stat(nombre_archivo, bufer_stat) donde los argumentos están previamente definidos como
char *nombre_archivo;
struct stat *bufer_stat;

y

int fstat(descriptor_archivo, bufer_stat) donde los argumentos están definidos por
int descriptor_archivo;
struct stat *bufer_stat;

stat() y fstat() regresan cero si su ejecución resulta exitosa y -1 si ocurrio un error.
En caso de no haber ocurrido errores, los datos del i-nodo del archivo se encuentran en la estructura de tipo stat (aquí llamada bufer_stat), que contiene los siguientes campos:

struct stat {
dev_t st_dev; /* ID del dispositivo que contiene el archivo */
ino_t st_ino; /* numero de i-nodo */
mode_t st_mode; /* proteccion */
nlink_t st_nlink; /* number de ligas duras */
uid_t st_uid; /* user ID del dueño */
gid_t st_gid; /* group ID del dueño */
dev_t st_rdev; /* ID del dispositivo (si es un archivo especial) */
off_t st_size; /* tamanio total, en bytes */
blksize_t st_blksize; /* Tamaño del bloque para la E/S del sistema de archivos */
blkcnt_t st_blocks; /* numero de bloques de 512B reservados*/
time_t st_atime; /* tiempo del ultimo acceso */
time_t st_mtime; /* tiempo de la ultima modificacion */
time_t st_ctime; /* tiempo del ultimo cambio de status */
};

El formato para la estructura del i-nodo que se regresa esta definida en /usr/include/sys/stat.h, que a su vez usa tipos de datos construidos con typedef del lenguaje C y
definidos dentro del archivo /usr/include/sys/types.h, por lo que ambas bibliotecas deben ser
incluidas (types.h forzosamente antes de stat.h)


EJEMPLO

#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>


int main(int argc, char *argv[])
{
struct stat sb;
if (argc != 2) {
fprintf(stderr, "Usage: %s <pathname>\n", argv[0]);
exit(EXIT_FAILURE);
}
if (stat(argv[1], &sb) == -1) {
perror("stat");
exit(EXIT_SUCCESS);
}
printf("File type: ");
switch (sb.st_mode & S_IFMT) {
case S_IFBLK: printf("block device\n"); break;
case S_IFCHR: printf("character device\n"); break;
case S_IFDIR: printf("directory\n"); break;
case S_IFIFO: printf("FIFO/pipe\n"); break;
case S_IFLNK: printf("symlink\n"); break;
case S_IFREG: printf("regular file\n"); break;
case S_IFSOCK: printf("socket\n"); break;
default: printf("unknown?\n"); break;
}
printf("I-node number: %ld\n", (long) sb.st_ino);
printf("Mode: %lo (octal)\n", (unsigned long) sb.st_mode);
printf("Link count: %ld\n", (long) sb.st_nlink);
printf("Ownership: UID=%ld GID=%ld\n", (long) sb.st_uid, (long)sb.st_gid);
printf("Preferred I/O block size: %ld bytes\n",(long)sb.st_blksize);
printf("File size: %lld bytes\n",(long long) sb.st_size);
printf("Blocks allocated: %lld\n", (long long) sb.st_blocks);
printf("Last status change: %s", ctime(&sb.st_ctime));
printf("Last file access: %s", ctime(&sb.st_atime));
printf("Last file modification: %s", ctime(&sb.st_mtime));
exit(EXIT_SUCCESS);
}


reboot()

La llamada a reboot() reinicia el sistema, o habilita/deshabilita la combinacion de teclas CTR-Alt-Supr (Ctrl-Alt-Delete en inglés) para el reinicio; puede ser cambiado usando loadkeys(1).

Para libc4 y libc5 la función de biblioteca y la llamada al sistema son idénticas, y desde la versión 2.1.30 del kernel existen nombres simbólicos LINUX_REBOOT_* para las constantes y un cuarto argumento para la llamada:

#include <unistd.h>
#include <linux/reboot.h>

int reboot (int magico, int otro_magico, int flag, void *arg);

En los sistemas que usan glibc se han asignado nombres simbólicos RB_* a algunas de las contantes involucradas y la función de biblioteca es un envoltorio de 1 argumento de la llamada al sistema de 3 argumentos:

#include <unistd.h>
#include <sys/reboot.h>
int reboot (int flag);

La llamada reboot() manda error (EINVAL) a menos que magico sea igual a LINUX_REBOOT_MAGIC1 (esto es, 0xfee1dead) y otro_magico sea igual a LINUX_REBOOT_MAGIC2 (o sea, 672274793).

Sin embargo, también se permiten como valores de otro_magico:

  • LINUX_REBOOT_MAGIC2A (esto es, 85072278) desde la versión 2.1.17
  • LINUX_REBOOT_MAGIC2B (es decir, 369367448) desde la versión 2.1.97
  • LINUX_REBOOT_MAGIC2C (that is, 537993216)desde la versión 2.5.71

El argumento flag puede tener los siguientes valores:

  • LINUX_REBOOT_CMD_RESTART: (RB_AUTOBOOT, 0x1234567). Se muestra el mensaje "Restarting system." y se realiza inmediatamente un reinicio por defecto. Si no se precede por una llamada a sync(2) se perderán datos.

  • LINUX_REBOOT_CMD_HALT: (RB_HALT_SYSTEM, 0xcdef0123; desde la versión 1.1.76). Se muestra el mensaje"System halted." y se detiene el sistema. El control se cede al monitor en ROM, si existe alguno. Si no se precede por una llamada a sync(2) se perderán datos.

  • LINUX_REBOOT_CMD_POWER_OFF: (0x4321fedc; desde la versión 2.1.30). Se muestra el mensaje "Power down.", se detiene el sistema y se apaga el sistema, si es posible. Si no se precede por una llamada a sync(2) se perderán datos.

  • LINUX_REBOOT_CMD_RESTART2: (0xa1b2c3d4; desde la versión 2.1.30). Se muestra el mensaje "Restarting system with command '%s'" y se realiza inmediatamente un reinicio (usando la cadena de orden dada en arg). Si no se precede por una llamada a sync(2) se perderán datos.

  • LINUX_REBOOT_CMD_CAD_ON: (RB_ENABLE_CAD, 0x89abcdef). Se habilita la combinación de teclas Ctrl+Alt+Supr. Esto significa el tecleo de esta combinación producirá inmediatamente la acción asociada a LINUX_REBOOT_CMD_RESTART.

  • LINUX_REBOOT_CMD_CAD_OFF: (RB_DISABLE_CAD, 0). Se inhabilita la combinación de teclas CAS. Esto significa al presionar Ctr+Alt+Supr producirá el envío de la señal SIGINT a init (el proceso 1), y como consecuencia de esto este proceso puede decidir una acción apropiada (quizás,matar todos los procesos, llamar a sync y reiniciar).


Para valores de flag que detienen o reinicial el sitema, reboot() nunca regresa, en otros casos
se devuelve 0 en caso de éxito. En caso de error, se devuelve -1 y se pone un valor apropiado en errno.

NOTAS:

1) reboot requiere permisos de root (superusuario) para poderse ejecutar.
2) reboot es específico de Linux y no deberí­a emplearse en programas que pretendan ser portables
3) Los resultados de reboot varían dependiendo de la arquitectura.
4) En un sistema basado en glibc, los parámetros magico y otro_magico no existen. Sólo existe el parámetro flag.

Referencias

-manpages (man 2 stat, man 2 reboot)
- http://www.di.uevora.pt/~lmr/syscalls.html

2 comentarios: