Location: PHPKode > scripts > tarX > dump_dir.php
<?php
  class tar_x {
    function parseDirectory($dump_out, $rootPath, $exclude_dirs = array(), $seperator="/", $out_rel_path = ""){
      foreach ($exclude_dirs as $excluded) {
        if (realpath($rootPath) == realpath($excluded))
          return array();
      }
        
      $fileArray=array();
      $handle = opendir($rootPath);
      while( ($file = @readdir($handle))!==false) {
        if($file !='.' && $file !='..'){
          $current_name = $rootPath.$seperator.$file;
          $current_relname = $out_rel_path.$seperator.$file;
          if (is_dir($current_name)){
            $fileArray[$current_relname] = array_merge(stat($current_name), array('is_directory' => true));
            $array = tar_x::parseDirectory($dump_out, $current_name, $exclude_dirs, $seperator, $current_relname);
            $fileArray = array_merge($fileArray, $array);
          } else {
            if ($fp = fopen($current_name, "rb")) {
              while ($temp = fread($fp, 1048576)) {
                fwrite($dump_out, $temp);
              }
              $fileArray[$current_relname] = fstat($fp);
              fclose($fp);
            }
            else
              trigger_error("Could not open file {$current['name']} for reading. It was not added.");
          }
        }
      }
      closedir($handle);
      return $fileArray;
    }
  
    /**
     * Dumps directory contents into two files (*.dmp and *.tree). So that these files may be easily
     * migrated to other place, for example to other web server, and extracted there. It does not
     * use andy compression so it may result in huge output files depending on input directory size.
     *
     * Note: all contents of the parent directory of $out_name file is automatically excluded from the dump! See below.
     *
     * @param $src_dir
     *   path to input directory that shoul be dumped
     *
     * @param $exclude_dirs
     *   paths of directories that should be excluded from the dump.
     *   It must be paths inside $src_dir. If not, they will be ignored.
     *   Also a directory is excluded automatically if
     *     1) it is inside $src_dir
     *     2) and it is a parent directory of $out_name
     *   In that case there is not necessary to specify it in $exclude_dirs.
     *
     * @param $out_name
     *   path to output dump files. It should be a common part of name of these files.
     *   This function will create two separate files located in the same directory
     *   (this directory should have appropriate write permissions)
     *   that will have the same name but end with *.dmp and *.tree extensions.
     *   For example:
     *     If you specify as parameter value /www/home/_mydump/htdocs.tarx
     *     then it will create two files /www/home/_mydump/htdocs.tarx.dmp and
     *     /www/home/_mydump/htdocs.tarx.tree
     */
    function dumpDirectory($src_dir, $exclude_dirs = array(), $out_name) {
      if ($dump_out = fopen($out_name.'.dmp', "wb+")) {
        $files = tar_x::parseDirectory($dump_out, $src_dir, array_merge(array(dirname($out_name)), $exclude_dirs));
        fclose($dump_out);
        if ($dump_tree = fopen($out_name.'.tree', "wb+")) {
          fwrite($dump_tree, serialize($files));
          fclose($dump_tree);
        } else {
          trigger_error("Could not open {$out_name} tree file for writing.");
        }   
      } else {
        trigger_error("Could not open {$out_name} dump file for writing.");
      }
    }
    
    function setAttributes($file_path, $attributes) {
      if (!touch($file_path, $attributes['mtime'], $attributes['atime']))
        trigger_error('cannot change time attributes of '.$file_path);
      $mode = $attributes['mode'] & 0x1ff;
      if (!chmod($file_path, $mode)) 
        trigger_error('cannot change mode '.$mode.' of '.$file_path);
    }
    
    /**
     * Restores directory dump from *.dmp and *.tree files pair. It will overwrite existing files in $out_dir
     * if they conflict with the same files in the dump.
     * Input files pair MUST be previously created by dumpDirectory() function!
     * If you are not sure about the input files, do not use them! because the results are unknown!
     *
     * Under Windows OS it may produce many warnings like 'touch() [function.touch]: Utime failed: Permission denied' (see http://php.net/manual/en/function.touch.php)
     * 
     * @param $in_name
     *   path to the dump files previously created bu dumpDirectory() function.
     *   Note: this path should point to "both" files *.dmp and *.tree but not contain their extensions.
     *   Also the both files must locate in the same directory.
     *   For example:
     *     You have the following files pair:  /www/home/_dump/tmp/mysite.tarx.dmp
     *     and /www/home/_dump/tmp/mysite.tarx.tree.
     *     Then you must specify this path: /www/home/_dump/tmp/mysite.tarx as parameter value
     * 
     * @param $out_dir
     *   path to output directory where to extract the dump. No trailing slash! It must have appropriate write permissions.
     */
    function restoreDirectory($in_name, $out_dir) {
      if ($dump_in = fopen($in_name.'.dmp', "rb")) {
        $files = unserialize(file_get_contents($in_name.'.tree'));
        if (empty($files)) {
          die("Could not read {$in_name} tree file.");
        }
  
        foreach($files as $rel_file => $stat) {
          if (isset($stat['is_directory']) && $stat['is_directory']) {
            mkdir($out_dir.$rel_file);
            tar_x::setAttributes($out_dir.$rel_file, $stat);
          } else {
            if ($current_out_file = fopen($out_dir.$rel_file, "wb")) {
              $bytes_read = 0;
              $file_size = $stat['size'];
              while ($bytes_read < $file_size && $temp = fread($dump_in, min($file_size - $bytes_read, 1048576))) {
                $bytes_read += strlen($temp);
                fwrite($current_out_file, $temp);
              }
              fclose($current_out_file);
              tar_x::setAttributes($out_dir.$rel_file, $stat);
            } else {
              trigger_error("Could not open {$out_name} for writing.");
            }   
          }
        }
        fclose($dump_in);
      } else {
        trigger_error("Could not open {$in_name} dump file for reading.");
      }   
    }
  }
?>
Return current item: tarX