]> git.sur5r.net Git - bacula/bacula/commitdiff
baculum: Add restore hardlinks support in api
authorMarcin Haba <marcin.haba@bacula.pl>
Mon, 27 Nov 2017 20:03:11 +0000 (21:03 +0100)
committerKern Sibbald <kern@sibbald.com>
Sat, 9 Dec 2017 11:00:46 +0000 (12:00 +0100)
gui/baculum/protected/API/Pages/API/BVFSRestore.php
gui/baculum/protected/Common/Class/Errors.php
gui/baculum/protected/Common/Class/Miscellaneous.php

index 73eaa66e78e8910ab5d6030f855ab77b085a0ce9..f94c1d0b9538deb49add698b7bdb853a415cbb25 100644 (file)
  */
  
 class BVFSRestore extends BaculumAPIServer {
+
        public function create($params) {
+               $misc = $this->getModule('misc');
                $jobids = property_exists($params, 'jobids') ? $params->jobids : null;
                $fileids = property_exists($params, 'fileid') ? $params->fileid : null;
                $dirids = property_exists($params, 'dirid') ? $params->dirid : null;
+               $findexes = property_exists($params, 'findex') ? $params->findex : null;
                $path = property_exists($params, 'path') ? $params->path : null;
 
-               $is_valid = true;
-               if (!is_null($jobids)) {
-                       $jobidsList = explode(',', $jobids);
-                       if(is_array($jobidsList)) {
-                               for($i = 0; $i < count($jobidsList); $i++) {
-                                       $job = $this->getModule('job')->getJobById($jobidsList[$i]);
-                                       if(is_null($job)) {
-                                               $is_valid = false;
-                                               break;
-                                       }
-                               }
-                       } else {
-                               $is_valid = false;
-                       }
-               } else {
-                       $is_valid = false;
+               if (!is_null($jobids) && !$misc->isValidIdsList($jobids)) {
+                       $this->output = BVFSError::MSG_ERROR_INVALID_JOBID_LIST;
+                       $this->error = BVFSError::ERROR_INVALID_JOBID_LIST;
+                       return;
+               }
+               if (!is_null($fileids) && !$misc->isValidIdsList($fileids)) {
+                       $this->output = BVFSError::MSG_ERROR_INVALID_FILEID_LIST;
+                       $this->error = BVFSError::ERROR_INVALID_FILEID_LIST;
+                       return;
+               }
+               if (!is_null($dirids) && !$misc->isValidIdsList($dirids)) {
+                       $this->output = BVFSError::MSG_ERROR_INVALID_DIRID_LIST;
+                       $this->error = BVFSError::ERROR_INVALID_DIRID_LIST;
+                       return;
+               }
+               if (!is_null($findexes) && !$misc->isValidIdsList($findexes)) {
+                       $this->output = BVFSError::MSG_ERROR_INVALID_FILEINDEX_LIST;
+                       $this->error = BVFSError::ERROR_INVALID_FILEINDEX_LIST;
+                       return;
                }
 
-               if($is_valid === true) {
-                       if(!is_null($path)) {
-                               $cmd = array('.bvfs_restore', 'jobid="' .  $jobids . '"', 'path="' . $path . '"');
-                               if(!is_null($fileids)) {
-                                       array_push($cmd, 'fileid="' . $fileids . '"');
-                               }
-                               if(!is_null($dirids)) {
-                                       array_push($cmd, 'dirid="' . $dirids . '"');
-                               }
+               if (!is_null($path) && !$misc->isValidBvfsPath($path)) {
+                       $this->output = BVFSError::MSG_ERROR_INVALID_RPATH;
+                       $this->error = BVFSError::ERROR_INVALID_RPATH;
+                       return;
+               }
 
-                               $result = $this->getModule('bconsole')->bconsoleCommand($this->director, $cmd, $this->user);
-                               $this->output = $result->output;
-                               $this->error = $result->exitcode;
-                       } else {
-                               $this->output = BVFSError::MSG_ERROR_INVALID_RPATH;
-                               $this->error = BVFSError::ERROR_INVALID_RPATH;
-                       }
-               } else {
-                       $this->output = BVFSError::MSG_ERROR_JOB_DOES_NOT_EXISTS;
-                       $this->error = BVFSError::ERROR_JOB_DOES_NOT_EXISTS;
+               $cmd = array('.bvfs_restore', 'jobid="' .  $jobids . '"', 'path="' . $path . '"');
+               if (is_string($fileids)) {
+                       array_push($cmd, 'fileid="' . $fileids . '"');
+               }
+               if (is_string($dirids)) {
+                       array_push($cmd, 'dirid="' . $dirids . '"');
                }
+               if (is_string($findexes)) {
+                       array_push($cmd, 'hardlink="' . $findexes . '"');
+               }
+
+               $result = $this->getModule('bconsole')->bconsoleCommand($this->director, $cmd, $this->user);
+               $this->output = $result->output;
+               $this->error = $result->exitcode;
        }
 }
 ?>
index 8a308d5fb3decc868c16e4184750187529249ac0..b0b7304f7c362000356c173d1ea36f0bcc4c3fe2 100644 (file)
@@ -111,13 +111,19 @@ class FileSetError extends GenericError {
 }
 
 class BVFSError extends GenericError {
-       const ERROR_JOB_DOES_NOT_EXISTS = 70;
+       const ERROR_INVALID_JOBID_LIST = 70;
        const ERROR_INVALID_RPATH = 71;
        const ERROR_INVALID_RESTORE_PATH = 72;
+       const ERROR_INVALID_FILEID_LIST = 73;
+       const ERROR_INVALID_FILEINDEX_LIST = 74;
+       const ERROR_INVALID_DIRID_LIST = 75;
 
-       const MSG_ERROR_JOB_DOES_NOT_EXISTS = 'Job with inputted jobid does not exist.';
+       const MSG_ERROR_INVALID_JOBID_LIST = 'Invalid jobid list.';
        const MSG_ERROR_INVALID_RPATH = 'Inputted path for restore is invalid. Proper format is b2[0-9]+.';
        const MSG_ERROR_INVALID_RESTORE_PATH = 'Inputted BVFS path param is invalid.';
+       const MSG_ERROR_INVALID_FILEID_LIST = 'Invalid fileid list.';
+       const MSG_ERROR_INVALID_FILEINDEX_LIST = 'Invalid file index list.';
+       const MSG_ERROR_INVALID_DIRID_LIST = 'Invalid dirid list.';
 }
 
 class JSONToolsError extends GenericError {
index 833f23352e89da414788e818b1ee068cf956c353..0d9871bc1525ce97fba24c147cd18bfcb76095f1 100644 (file)
@@ -47,7 +47,7 @@ class Miscellaneous extends TModule {
                'd' => 'DiskToCatalog'
        );
 
-       private $jobStates =  array(
+       public $jobStates =  array(
                'C' => array('value' => 'Created', 'description' =>'Created but not yet running'),
                'R' => array('value' => 'Running', 'description' => 'Running'),
                'B' => array('value' => 'Blocked', 'description' => 'Blocked'),
@@ -90,6 +90,14 @@ class Miscellaneous extends TModule {
                'bcons' => array('full_name' => 'Console', 'main_resource' => 'Director')
        );
 
+       private $replace_opts = array(
+               'always',
+               'ifnewer',
+               'ifolder',
+               'never'
+       );
+
+
        /**
         * Getting the licence from file.
         * 
@@ -166,6 +174,9 @@ class Miscellaneous extends TModule {
                return $statesByType;
        }
 
+       /*
+        * @TODO: Move it to separate validation module.
+        */
        public function isValidJobLevel($jobLevel) {
                return array_key_exists($jobLevel, $this->getJobLevels());
        }
@@ -174,6 +185,22 @@ class Miscellaneous extends TModule {
                return (preg_match('/^[\w:\.\-\s]{1,127}$/', $name) === 1);
        }
 
+       public function isValidPath($path) {
+               return (preg_match('/^[\p{L}\p{N}\p{Z}\[\]\(\)\-\+\/\\\:\.#~_,{}!]{1,1000}$/', $path) === 1);
+       }
+
+       public function isValidReplace($replace) {
+               return in_array($replace, $this->replace_opts);
+       }
+
+       public function isValidIdsList($list) {
+               return (preg_match('/^[\d,]+$/', $list) === 1);
+       }
+
+       public function isValidBvfsPath($path) {
+               return (preg_match('/^b2\d+$/', $path) === 1);
+       }
+
        /**
         * Writing INI-style configuration file.
         * 
@@ -257,13 +284,51 @@ class Miscellaneous extends TModule {
                $base64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
                $lstat = trim($lstat);
                $lstat_fields = explode(' ', $lstat);
-
-               if(count($lstat_fields) !== 16) {
-                       die('Błąd! Niepoprawna ilość pól wartości LStat. Proszę upewnić się, że podany ciąg znaków jest poprawną wartością LStat');
+               $lstat_len = count($lstat_fields);
+               if ($lstat_len < 16) {
+                       // not known or empty lstat value
+                       return;
+               } elseif ($lstat_len > 16) {
+                       // cut off unknown fields
+                       array_splice($lstat_fields, 16);
                }
 
-               list($dev, $inode, $mode, $nlink, $uid, $gid, $rdev, $size, $blocksize, $blocks, $atime, $mtime, $ctime, $linkfi, $flags, $data) = $lstat_fields;
-               $encoded_values = array('dev' => $dev, 'inode' => $inode, 'mode' => $mode, 'nlink' => $nlink, 'uid' => $uid, 'gid' => $gid, 'rdev' => $rdev, 'size' => $size, 'blocksize' => $blocksize, 'blocks' => $blocks, 'atime' => $atime, 'mtime' => $mtime, 'ctime' => $ctime, 'linkfi' => $linkfi, 'flags' => $flags, 'data' => $data);
+               list(
+                       $dev,
+                       $inode,
+                       $mode,
+                       $nlink,
+                       $uid,
+                       $gid,
+                       $rdev,
+                       $size,
+                       $blocksize,
+                       $blocks,
+                       $atime,
+                       $mtime,
+                       $ctime,
+                       $linkfi,
+                       $flags,
+                       $data
+               ) = $lstat_fields;
+               $encoded_values = array(
+                       'dev' => $dev,
+                       'inode' => $inode,
+                       'mode' => $mode,
+                       'nlink' => $nlink,
+                       'uid' => $uid,
+                       'gid' => $gid,
+                       'rdev' => $rdev,
+                       'size' => $size,
+                       'blocksize' => $blocksize,
+                       'blocks' => $blocks,
+                       'atime' => $atime,
+                       'mtime' => $mtime,
+                       'ctime' => $ctime,
+                       'linkfi' => $linkfi,
+                       'flags' => $flags,
+                       'data' => $data
+               );
 
                $ret = array();
                foreach($encoded_values as $key => $val) {
@@ -294,12 +359,28 @@ class Miscellaneous extends TModule {
                                } elseif($match['name'] != '..') {
                                        $match['name'] .= '/';
                                }
-                               $elements[] = array('pathid' => $match['pathid'], 'filenameid' => $match['filenameid'], 'fileid' => $match['fileid'], 'jobid' => $match['jobid'], 'lstat' => $match['lstat'], 'name' => $match['name'], 'type' => 'dir');
+                               $elements[] = array(
+                                       'pathid' => $match['pathid'],
+                                       'filenameid' => $match['filenameid'],
+                                       'fileid' => $match['fileid'],
+                                       'jobid' => $match['jobid'],
+                                       'lstat' => $this->decode_bacula_lstat($match['lstat']),
+                                       'name' => $match['name'],
+                                       'type' => 'dir'
+                               );
                        } elseif(preg_match('/^(?P<pathid>\d+)\t(?P<filenameid>\d+)\t(?P<fileid>\d+)\t(?P<jobid>\d+)\t(?P<lstat>[a-zA-z0-9\+\/\ ]+)\t(?P<name>[^\/]+)$/', $list[$i], $match) == 1) {
                                if($match['name'] == '.') {
                                        continue;
                                }
-                               $elements[] = array('pathid' => $match['pathid'], 'filenameid' => $match['filenameid'], 'fileid' => $match['fileid'], 'jobid' => $match['jobid'], 'lstat' => $match['lstat'], 'name' => $match['name'], 'type' => 'file'); 
+                               $elements[] = array(
+                                       'pathid' => $match['pathid'],
+                                       'filenameid' => $match['filenameid'],
+                                       'fileid' => $match['fileid'],
+                                       'jobid' => $match['jobid'],
+                                       'lstat' => $this->decode_bacula_lstat($match['lstat']),
+                                       'name' => $match['name'],
+                                       'type' => 'file'
+                               );
                        }
                }
                usort($elements, 'sortFilesListByName');
@@ -310,7 +391,18 @@ class Miscellaneous extends TModule {
                $elements = array();
                for($i = 0; $i < count($list); $i++) {
                        if(preg_match('/^(?P<pathid>\d+)\t(?P<filenameid>\d+)\t(?P<fileid>\d+)\t(?P<jobid>\d+)\t(?P<lstat>[a-zA-Z0-9\+\/\ ]+)\t(?P<md5>.+)\t(?P<volname>.+)\t(?P<inchanger>\d+)$/', $list[$i], $match) == 1) {
-                               $elements[$match['fileid']] = array('name' => $filename, 'pathid' => $match['pathid'], 'filenameid' => $match['filenameid'], 'fileid' => $match['fileid'], 'jobid' => $match['jobid'], 'lstat' => $this->decode_bacula_lstat($match['lstat']), 'md5' => $match['md5'], 'volname' => $match['volname'], 'inchanger' => $match['inchanger'], 'type' => 'file');
+                               $elements[$match['fileid']] = array(
+                                       'name' => $filename,
+                                       'pathid' => $match['pathid'],
+                                       'filenameid' => $match['filenameid'],
+                                       'fileid' => $match['fileid'],
+                                       'jobid' => $match['jobid'],
+                                       'lstat' => $this->decode_bacula_lstat($match['lstat']),
+                                       'md5' => $match['md5'],
+                                       'volname' => $match['volname'],
+                                       'inchanger' => $match['inchanger'],
+                                       'type' => 'file'
+                               );
                        }
                }
                return $elements;