En la segunda edición de "El Lenguaje de Programación C" de Kernighan y Ritchie se implemento una versión simplificada del comando UNIX ls
(sección 8.6 "Ejemplo - directorios enumerando", p 179.). Para este fin, crean la siguiente interfaz que proporciona un acceso independiente del sistema al nombre y al número de inodo de los archivos almacenados en un directorio.Interfaz K & R para leer directorios: estructura DIR superflua?
#define NAME_MAX 14 /* longest filename component; */
/* system dependent */
typedef struct { /* portable director-entry */
long ino; /* inode number */
char name[NAME_MAX+1]; /* name + '\0' terminator */
} Dirent;
typedef struct { /* minimal DIR: no buffering, etc. */
int fd; /* file descriptor for directory */
Dirent d; /* the directory entry */
} DIR;
DIR *opendir(char *dirname);
Dirent *readdir(DIR *dfd);
void closedir(DIR *dfd);
Luego implementan esta interfaz para los sistemas UNIX versión 7 y System V.
opendir()
básicamente utiliza el sistema llamadaopen()
para abrir un directorio ymalloc()
para asignar espacio para una estructuraDIR
. El descriptor de archivo devuelto poropen()
se almacena entonces en la variablefd
de eseDIR
. No se almacena nada en el componenteDirent
.readdir()
utiliza la llamada al sistemaread()
para obtener la siguiente entrada directorio (dependiente del sistema) de un directorio abierto y copia el modo obtenido el número de inodo y nombre de archivo en unDirent
estructura estática (a cual una se devuelve el puntero). La información solo necesaria porreaddir()
es el descriptor de archivo almacenado en la estructuraDIR
.
Ahora a mi pregunta: ¿Cuál es el punto de tener una estructura DIR
? Si mi comprensión de este programa es correcta, el componente Dirent
de DIR
nunca se utiliza, entonces ¿por qué no reemplazar toda la estructura con un descriptor de archivo y usar directamente open()
y close()
?
Gracias.
Ps: Soy consciente de que en los sistemas UNIX modernos read()
ya no se pueden usar en directorios (he probado este programa en Ubuntu 10.04), pero aún quiero asegurarme de no haber pasado por alto algo importante en este ejemplo.
La portabilidad también fue mi primera suposición, pero después de pensarlo no veo cómo 'DIR' podría contribuir a esto. La única información relevante que puede pasar a 'readdir()' es el descriptor del archivo. Todavía no veo el uso del componente 'Dirent' en' DIR'. Independientemente del sistema, cualquier implementación de 'readdir()' puede tener un 'Dirent' estático al que puede devolver un puntero, por lo que no debería ser un problema de portabilidad. Es cierto que 'dirwalk()' accede al contenido de un 'Dirent', pero este es el estático de' readdir() ', no el contenido en' DIR'. ¿Me falta algo? – qfab
Oye, parece que tienes razón. Supongo que comenzaron definiendo sus estructuras de datos (con un 'Dirent' dentro de' DIR') pero terminaron sin usarlo. Agrupar datos relacionados juntos en estructuras es bueno juju. Un buen ejercicio sería reescribir el código para hacer uso de 'DIR.d' en lugar de hacer que' readdir() 'los llamadores tengan sus propios punteros' Dirent'. – nmichaels
Sí, esta es una explicación plausible. Pero teniendo en cuenta que el libro se publicó hace más de 20 años (segunda edición), es extraño que algo así no se menciona en la [errata] (http://cm.bell-labs.com/cm/cs/cbook/ 2ediffs.html). – qfab