tags:

views:

107

answers:

2
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>

static char *dup_str(const char *s)
{
    size_t n = strlen(s) + 1;
    char *t = (char*) malloc(n);
    if (t)
    {
        memcpy(t, s, n);
    }
    return t;
 }

 static char **get_all_files(const char *path)
 {
    DIR *dir;
    struct dirent *dp;
    char **files;
    size_t alloc, used;
    if (!(dir = opendir(path)))
    {
        goto error;
    }
    used = 0;
    alloc = 10;
    if (!(files = (char**) malloc(alloc * sizeof *files)))
    {
        goto error_close;
    }

    while ((dp = readdir(dir)))
    {
        if (used + 1 >= alloc)
        {
            size_t new_thing = alloc / 2 * 3;
            char **tmp = (char**) realloc(files, new_thing * sizeof *files);
            if (!tmp)
            {
                goto error_free;
            }
            files = tmp;
            alloc = new_thing;
        }
        if (!(files[used] = dup_str(dp->d_name))) 
        {
            goto error_free;
        }
        ++used;
    }
    files[used] = NULL;
    closedir(dir);
    return files;
error_free:
    while (used--) 
    {
        free(files[used]);
    }
    free(files);
error_close:
    closedir(dir);
error:
    return NULL;
}

int main(int argc, char **argv)
{
    char **files;
    size_t i;

    if (argc != 2)
    {
        fprintf(stderr, "Usage: %s DIRECTORY\n", argv[0]);
         return EXIT_FAILURE;
    }
    files = get_all_files(argv[1]);

    if (!files) 
    {
        fprintf(stderr, "%s: %s: something went wrong\n", argv[0], argv[1]);
        return EXIT_FAILURE;
    }

    for (i = 0; files[i]; ++i) 
    { 
        FILE *fp;
        if((fp = fopen(files[i],"r"))==NULL)
        {
            printf("error cannot open file\n");
            exit(1);
        }
        fclose(fp);
    }
    for (i = 0; files[i]; ++i) 
    {
        free(files[i]);
    }
    free(files);
    return EXIT_SUCCESS;
}

I am just getting "error cannot open file".

+4  A: 

If I invoke your program passing it /tmp as the argument.

files = get_all_files(argv[1]);

will return all the files in /tmp but when you do:

for (i = 0; files[i]; ++i) { 
  FILE *fp;
  if((fp = fopen(files[i],"r"))==NULL)

you are trying to open those files from the present working directory. But they are present in the directory you passed as argument making your fopens fail.

To fix this

  • you prefix the dir name to the file to be opened. or
  • You can change your pwd using chdir and then do the fopens.
codaddict
yep. thanks for the pointer
Also there is a library function named `strdup`: http://linux.die.net/man/3/strdup which does exactly what your `dup_str` function is doing.
codaddict
It would also help you troubleshoot any future errors if you. (1) print out the name of the file you couldn't open, and (2) print out the reason for the error (e.g. with sterrror())
David Gelhar
strdup() is non-standard though.
Nyan
+1  A: 

A couple problems, I think:

  1. readdir() returns subdirectories in the path, even entries like "." and "..".
  2. you try to open the files returned, but in whatever the current directory might be - you need to concatenate the path to the filename you're opening.
Michael Burr