/*****************************************************************************
 *  Backup Copy                                                              *
 *  Programmed by: Kevin Lindsay                                             *
 *  Copyright (c) 1998 NetNation Communications Inc                          *
 * ***************************************************************************/ 

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

#include "statmalloc.h"

#ifdef BSD
#endif

/* Amount to increase buffer size by in each try. */
#define PATH_INCR 32


/* Globals */

int dirpos = 1;
ino_t root_inode = 0;
dev_t root_dev = 0;
int counter=0;

/* Return the current directory, newly allocated, arbitrarily long.
 *    Return NULL and set errno on error. */

char *
MYgetcwd ()
{
   char *cwd;
   char *ret;
   unsigned path_max;
   
   errno = 0;
   path_max = (unsigned) MYPATH_MAX;
   path_max += 2;     /* The getcwd docs say to do this. */
   
   cwd = (char *)statmalloc(path_max);
   
   errno = 0;
   while ((ret = getcwd (cwd, path_max)) == NULL && errno == ERANGE)   {
      path_max += PATH_INCR;
      cwd = (char *)realloc(cwd, path_max);
      errno = 0;
   }
   
   if (ret == NULL){
      int save_errno = errno;
      freemalloc(cwd);
      errno = save_errno;            
      return NULL;
   }
   
   return cwd;
} 

/* Unlink all files in current directory. If a non empty Dir is found, return dirname */
char *
unlink_dir(char *dirname)
{
   DIR *dir_contents;
   struct dirent *filename = NULL;
   int check = 0;
   
   counter = 0;
   
   if ((dir_contents = opendir(".")) == NULL) {
      fprintf(stderr,"%s: %s\n",dirname,strerror(errno));
      return(NULL);
   }
   
   if ((filename = readdir(dir_contents)) == NULL) {
      return(NULL);
   }
   
   seekdir(dir_contents,telldir(dir_contents)+1);
   
   while (readdir(dir_contents) != NULL) {
      counter=1;
      check = 1;
      //      if (VERBOSE)
      //          printf("rmfile: %s/%s\n",MYgetcwd(),filename->d_name);
      
      if (unlink(filename->d_name) == -1) {      
         if (errno == EISDIR || errno == EPERM) {
            if (rmdir(filename->d_name) == -1) {
               if (errno == ENOTEMPTY) {
                  closedir(dir_contents);
                  dirpos++;                  
                  return(filename->d_name);
               } else {
                  closedir(dir_contents);                  
                  fprintf(stderr,"%s/%s: %s",dirname,filename->d_name,strerror(errno));
                  return(NULL);
               }
            }
         } else {
            closedir(dir_contents);            
            fprintf(stderr,"%s/%s: %s",dirname,filename->d_name,strerror(errno));
            return(NULL);
         }
      }
      
      seekdir(dir_contents,telldir(dir_contents));
   }
   
   
   if (!check) return(NULL);
   
   closedir(dir_contents);
   
   dirpos--;
   return ("..");
}

/* Recursively Remove a Directory */

int
rmrec(char *dirname)
{
   char *tempname;
   struct stat root_fs;
   char *rootdir = NULL;
   char *MYcwd=NULL;
   
   tempname = (char *)statmalloc(strlen(dirname)+1);
   tempname[0] = '\0';
   strcat(tempname,dirname);
   
   if (chdir(dirname) != 0) {
      dirname = NULL;
   }
   if (dirname != NULL && chdir("..") != 0) {
      dirname = NULL;
   }
   else {
      lstat(".",&root_fs);   
      root_inode = root_fs.st_ino;
      root_dev = root_fs.st_dev;
      MYcwd = MYgetcwd();
      rootdir = (char *)statmalloc(strlen(MYcwd)+1);
      rootdir[0] = '\0';
      strcat(rootdir,MYcwd);
   }
   
   if (dirname != NULL && chdir(dirname) != 0) {
      dirname = NULL;
   }
   
   while (dirname != NULL) {
      
      dirname = unlink_dir(dirname);
      
      if (chdir(dirname) != 0)      
          dirname = NULL;
      
      freemalloc(MYcwd);
      MYcwd = MYgetcwd();
      
      if (strcmp(rootdir,MYcwd) == 0)
          dirname = NULL;
      
      if (dirname != NULL && strcmp(dirname,"..") == 0) {
         lstat(".",&root_fs);
         if (root_inode == root_fs.st_ino && root_dev == root_fs.st_dev)
             dirname = NULL;
      }
      
   }
   
   if (counter == 0)
       chdir("..");
   
   rmdir(tempname);
   freemalloc(rootdir);
   freemalloc(tempname);
   freemalloc(MYcwd);
   
   return(0);
}


syntax highlighted by Code2HTML, v. 0.9.1