views:

194

answers:

3

I have a C program that, at one point in the program has this:

system("rm -rf foo");

Where foo is a directory. I decided that, rather than calling system, it would be better to do the recursive delete right in the code. I assumed a piece of code to do this would be easy to find. Silly me. Anyway, I ended up writing this:

#include <stdio.h>
#include <sys/stat.h>
#include <dirent.h>
#include <libgen.h>

int recursiveDelete(char* dirname) {

  DIR *dp;
  struct dirent *ep;

  char abs_filename[FILENAME_MAX];

  dp = opendir (dirname);
  if (dp != NULL)
    {
      while (ep = readdir (dp)) {
        struct stat stFileInfo;

        snprintf(abs_filename, FILENAME_MAX, "%s/%s", dirname, ep->d_name);

        if (lstat(abs_filename, &stFileInfo) < 0)
          perror ( abs_filename );

        if(S_ISDIR(stFileInfo.st_mode)) {
          if(strcmp(ep->d_name, ".") && 
             strcmp(ep->d_name, "..")) {
            printf("%s directory\n",abs_filename);
            recursiveDelete(abs_filename);
          }
        } else {
          printf("%s file\n",abs_filename);
                  remove(abs_filename);
        }
          }
      (void) closedir (dp);
        }
  else
    perror ("Couldn't open the directory");


  remove(dirname);
  return 0;

}

This seems to work, but I'm too scared to actually use it in production. I'm sure I've done something wrong. Does anyone know of a C library to do recursive delete I've missed, or can someone point out any mistakes I've made?

Thanks.

+1  A: 

kudos for being scared to death, that's a healthy attitude to have in a case like this.

I have no library to suggest in which case you have two options:

1) 'run' this code exhaustively
  a) not on a machine; on paper, with pencil. take an existing directory tree, list all the elements and run the program through each step, verify that it works
  b) compile the code but replace all of the deletion calls with a line that does a printf - verify that it does what it should do
  c) re-insert the deletion calls and run

2) use your original method (call system())

KevinDTimm
+3  A: 

POSIX has a function called ftw(3) (file tree walk) that

walks through the directory tree that is located under the directory dirpath, and calls fn() once for each entry in the tree.

ninjalj
Yup. POSIX to the rescue. It's probably safer, faster, and catches little errors you won't always get during normal operation of a manual traverse.
Matt Joiner
There's also the new FTW function - [nftw](http://www.opengroup.org/onlinepubs/9699919799/functions/nftw.html) with a slightly different interface.
Jonathan Leffler
`nftw` is what you're after - see [this answer to the same question](http://stackoverflow.com/questions/3184445/how-to-clear-directory-contents-in-c-on-linux-basically-i-want-to-do-rm-rf/3184915#3184915).
caf
A: 

You should not be scared to run the code, it looks fine from my glance. But, if you are not sure just fire up a virtual machine and test it there.

in70x
I didn't say i was scared to run it, I said I was scared to put it into production. I ran it on some safely isolated test directories and it "seems" to work. The worry is that some future use will have, say, a symbolic link '~', which function will follow, and bye bye important data. I didn't think of symbolic links when I wrote the above code. Although, it turns out that it works correctly.