text: #include "mkpath.h"
  
  #include <errno.h>
  #ifdef HAVE_UNISTD_H
  #include <unistd.h>
  #endif /* HAVE_UNISTD_H */
  #include <string.h>
  #include <sys/stat.h>    /* Fix up for Windows - inc mode_t */
  
  #include <sys/types.h>
  #include <dirent.h>
  #include <stdio.h>
  #include <unistd.h>
  
  #if !defined(JM_MALLOC)
  #include <malloc.h>
  #endif
  
  typedef struct stat Stat;
  
  static int do_mkdir(const char *path, mode_t mode)
  {
      Stat st;
      int status = 0;
  
      if (stat(path, &st) != 0)
      {
          /* Directory does not exist. EEXIST for race condition */
  #ifdef _WIN32      
          if (mkdir(path) != 0 && errno != EEXIST)
  #else
          if (mkdir(path, mode) != 0 && errno != EEXIST)
  #endif
              status = -1;
      }
      else if (!S_ISDIR(st.st_mode))
      {
          errno = ENOTDIR;
          status = -1;
      }
  
      return(status);
  }
  
  /**
  ** mkpath - ensure all directories in path exist
  ** Algorithm takes the pessimistic view and works top-down to ensure
  ** each directory in path exists, rather than optimistically creating
  ** the last element and working backwards.
  */
  int mkpath(const char *path, mode_t mode)
  {
      char *pp;
      char *sp;
      int status;
      char *copypath = (char*)malloc(strlen(path));
      strcpy(copypath, path);
  
      status = 0;
      pp = copypath;
      while (status == 0 && (sp = strchr(pp, '/')) != 0)
      {
          if (sp != pp)
          {
              /* Neither root nor double slash in path */
              *sp = '\0';
              status = do_mkdir(copypath, mode);
              *sp = '/';
          }
          pp = sp + 1;
      }
      if (status == 0)
          status = do_mkdir(path, mode);
      free(copypath);
      return (status);
  }
  
  int rmpath(const char *path)
  {
     DIR *d = opendir(path);
     size_t path_len = strlen(path);
     int r = -1;
  
     if (d)
     {
        struct dirent *p;
  
        r = 0;
  
        while (!r && (p=readdir(d)))
        {
            int r2 = -1;
            char *buf;
            size_t len;
  
            /* Skip the names "." and ".." as we don't want to recurse on them. */
            if (!strcmp(p->d_name, ".") || !strcmp(p->d_name, ".."))
            {
               continue;
            }
  
            len = path_len + strlen(p->d_name) + 2; 
            buf = (char*)malloc(len);
  
            if (buf)
            {
               struct stat statbuf;
  
               snprintf(buf, len, "%s/%s", path, p->d_name);
  
               if (!stat(buf, &statbuf))
               {
                  if (S_ISDIR(statbuf.st_mode))
                  {
                     r2 = rmpath(buf);
                  }
                  else
                  {
                     r2 = unlink(buf);
                  }
               }
  
               free(buf);
            }
  
            r = r2;
        }
  
        closedir(d);
     }
  
     if (!r)
     {
        r = rmdir(path);
     }
  
     return r;
  }
  