Funciones opendir, readdir y closedir en C

La función opendir se usa para abrir un directorio. Su prototipo es:

DIR *opendir(const char *nombre);

El único parámetro que recibe es el nombre del directorio que se quiere abrir. Devuelve un puntero al flujo de directorio (DIR) o NULL en caso de error. Este puntero se colocará en la primera entrada del directorio.

La función readdir sirve para leer las entradas del directorio abierto con opendir. Su prototipo es:

struct dirent *readdir(DIR *dir);

Recibe como parámetro el puntero al flujo de directorio (DIR) que se obtuvo con opendir y devuelve un puntero a una estructura dirent o NULL en caso de error o fin del directorio. Esta estructura dirent representa la siguiente entrada de directorio al que apunte dir.

La función closedir cierra el flujo de directorio que se obtuvo con opendir. Su prototipo es:

int closedir(DIR *dir);

Recibe como parámetro el puntero al flujo de directorio (DIR) y devuelve 0 en caso de éxito y -1 en caso de error.

Y nada mejor que un ejemplo para entenderlo:

#include <sys/types.h>
#include <dirent.h>
#include <stdlib.h>
#include <stdio.h>

int main (int argc, char *argv[]){

 /* Variables */
 DIR *dirp;
 struct dirent *direntp;

 /* Comprobamos los argumentos */
 if (argc != 2){
 printf("Uso: %s directorio\n", argv[0]);
 exit(1);
 }

 /* Abrimos el directorio */
 dirp = opendir(argv[1]);
 if (dirp == NULL){
 printf("Error: No se puede abrir el directorio\n");
 exit(2);
 }

 /* Leemos las entradas del directorio */
 printf("i-nodo\toffset\t\tlong\tnombre\n");
 while ((direntp = readdir(dirp)) != NULL) {
 printf("%d\t%d\t%d\t%s\n", direntp->d_ino, direntp->d_off, direntp->d_reclen, direntp->d_name);
 }

 /* Cerramos el directorio */
 closedir(dirp);
}

Funciones open/close y read/write en C

Las funciones open y close se usan para abrir abrir y cerrar ficheros, respectivamente. Sus prototipos son los siguientes:

int open(const char *camino, int flags);
int open(const char *camino, int flags, mode_t modo);
int close(int fd);

La función open devuelve un número entero que identifica a un descriptor de fichero o -1 en caso de error, y tiene como parámetros un puntero a la ruta del fichero que queramos abrir y unas banderas (flags) que indican la forma de apertura: sólo lectura (O_RDONLY), sólo escritura (O_WRONLY), lectura/escritura (O_RDWR) u otros (O_CREAT, O_EXCL, O_NOCTTY, O_TRUNC, O_APPEND, O_NONBLOCK u O_NDELAY, O_SYNC, O_NOFOLLOW, O_DIRECTORY, O_DIRECT, O_ASYNC y O_LARGEFILE). Se puede leer más información sobre las banderas en el manual de open.

En la función open podemos especificar un tercer parámentro, el modo, que se usa para especificar los permisos en caso de que se esté creando el archivo. Dichos permisos o modos pueden ser S_IRWXU (el usuario puede leer, escribir y ejecutar (rwx)), S_IRUSR (el usuario puede leer (r)), S_IWUSR (el usuario puede escribir (w)), S_IXUSR (el usuario puede ejecutar (x)), S_IRWXG, S_IRGRP, S_IWGRP, S_IXGRP, S_IRWXO, S_IROTH, S_IWOTH y S_IXOTH.

La función close cierra el descriptor de fichero que le pasemos como parámetro. Devuelve 0 en caso de éxito y -1 en caso de error.

Las funciones read y write se usan para leer y escribir en un descriptor de fichero que previamente hayamos abierto. Sus prototipos son los siguientes:

ssize_t read(int fd, void *buf, size_t nbytes);
ssize_t write(int fd, const void *buf, size_t num);

Como véis, ambas funciones son iguales y los parámetros que reciben son el descriptor de fichero que devolvía la función open, un puntero a un buffer de memoria y un tamaño que indica el número de bytes del buffer que queramos leer o escribir. Ambas funciones devuelven el número de bytes leídos o escritos, o -1 en caso de error.

Aquí os muestro un ejemplo de cómo se pueden usar estas cuatro funciones para copiar un fichero en otro. Este programa recibe dos parámetros que son el archivo origen y el archivo destino. El archivo origen lo abre en modo sólo lectura (O_RDONLY), mientras que el archivo destino lo abre en modo sólo escritura, creándose en caso de que no exista y truncándolo (O_WRONLY|O_CREAT|O_TRUNC). Luego se usa un bucle para leer del descriptor fd1 (origen), guardarlos en un buffer de memoria y escribirlos en el descriptor fd2 (destino). Finalmente cerrará ambos archivos.

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

int main(int argc, char *argv[]){

  /* Variables */
  int fd1,fd2;
  char buffer[1024];
  int numbytes;

  /* Comprobamos que se pasan dos argumentos */
  if (argc != 3){
    printf("Uso: %s origen destino\n", argv[0]);
    exit(1);
  }

  /* Abrimos los dos archivos */
  fd1 = open(argv[1], O_RDONLY);
  fd2 = open(argv[2], O_WRONLY|O_CREAT|O_TRUNC, 0700);

  /* Bucle de lectura/escritura */
  while ((numbytes = read(fd1, &buffer, sizeof(char))) > 0){
    write(fd2, &buffer, numbytes);
  }

  /* Cierre de archivos */
  close(fd1);
  close(fd2);
}

Parámetros de un programa con argc y *argv[]

Para manejar los parámetros de un programa en C es necesario usar los argumentos argc y *argv[]. El primero es un entero que indica el número de parámetros recibidos y el segundo es un array de punteros a carácter que apuntan a cada uno de los parámetros.

#include

int main(int argc, char *argv[]){
printf(“El número de parámetros es %i\n”, argc);
int i;
for (i=0; i < argc; i++) { printf("Parámetro %d: %s\n", i, argv[i]); } } [/sourcecode] La salida de dicho programa sería éste: [sourcecode language='bash'] $ ./parametros mi primer ejemplo con parámetros El número de parámetros es 6 Parámetro 0: ./parametros Parámetro 1: mi Parámetro 2: primer Parámetro 3: ejemplo Parámetro 4: con Parámetro 5: parámetros [/sourcecode]