Poesía Binaria

Algoritmos: Probar la existencia de un fichero con open() en C

Estos días a varios de mis alumnos les ha surgido la necesidad de probar la existencia de un archivo haciendo la llamada al sistema open(). Es bastante sencillo, sólo hay que probar si éste se ha podido abrir (como lectura, por ejemplo, para no tocar el fichero en la medida de lo posible).
Una vez se abre el fichero pueden ocurrir varias cosas:

Para contemplar estos casos creamos la función exists(). Incluyo la función y el código de ejemplo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
/**
*************************************************************
* @file exists.c
* @brief Verifica la existencia o no de un fichero
*
* @author Gaspar Fernández <blakeyed@totaki.com>
* https://poesiabinaria.net/algoritmos/
*************************************************************/


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

short exists(char *fname)
{
  int fd=open(fname, O_RDONLY);
  if (fd<0)         /* error */
    return (errno==ENOENT)?-1:-2;
  /* Si no hemos salido ya, cerramos */
  close(fd);
  return 0;
}

int main(int argc, char *argv[])
{
  int abre=exists("archivo");
  switch (abre)
    {
    case 0: printf ("El archivo existe\n"); break;
    case -1: printf ("El archivo no existe\n"); break;
    case -2: printf ("Ocurrió un error al abrir. %d (%s)\n", errno, strerror(errno)); break;

    default: printf ("Nunca veremos este mensaje");
    }

  return EXIT_SUCCESS;
}

Descargar: exists (1Kb)
Para ejecutarlo podemos probar:

$ ./exists
El archivo no existe
$ touch archivo
$ ./exists
El archivo existe
$ chmod -r archivo # Eliminamos permiso de lectura al fichero
$ ./exists
Ocurrió un error al abrir. 13 (Permission denied)

Puede que también seas de los que piensan que si hay algún error al abrir el archivo, da igual, lo marcamos como no existente, de todas formas no podemos hacer nada con él. Así, construimos una función exists() más intuitiva que devuelve 1 cuando existe y 0 cuando no existe o hay error:

1
2
3
4
5
6
7
8
9
short exists(char *fname)
{
  int fd=open(fname, O_RDONLY);
  if (fd<0)         /* error */
    return 0;
  /* Si no hemos salido ya, cerramos */
  close(fd);
  return 1;
}

También podría interesarte....