Build the rsync command as an argument list
The rsync command was built as a string and split with shlex.split, so paths containing quotes broke it, and the key file path in the -e command was split on spaces. Pass each path as its own argument, and quote the key file and user name inside the -e command, which rsync splits itself.
This commit is contained in:
@@ -552,24 +552,27 @@ class Backup:
|
|||||||
|
|
||||||
logger.info('Copying files. This may take a long time...')
|
logger.info('Copying files. This may take a long time...')
|
||||||
|
|
||||||
if self._last_backup == '':
|
# Build the argument list directly, so paths with spaces or quotes are passed unchanged
|
||||||
rsync = f'/usr/bin/rsync {self.options} --exclude-from={self._exclude_path} ' +\
|
args = ['/usr/bin/rsync', *self.options.split()]
|
||||||
f'--files-from={self._inputs_path} / "{self._server}{self._output_dir}"'
|
|
||||||
else:
|
|
||||||
rsync = f'/usr/bin/rsync {self.options} --link-dest="{self._last_backup}" --exclude-from=' +\
|
|
||||||
f'{self._exclude_path} --files-from={self._inputs_path} / "{self._server}{self._output_dir}"'
|
|
||||||
|
|
||||||
|
if self._last_backup != '':
|
||||||
|
args.append(f'--link-dest={self._last_backup}')
|
||||||
|
|
||||||
|
args.extend([f'--exclude-from={self._exclude_path}', f'--files-from={self._inputs_path}',
|
||||||
|
'/', f'{self._server}{self._output_dir}'])
|
||||||
|
|
||||||
|
# rsync splits the -e command itself, so quote the parts that may contain spaces
|
||||||
if self.ssh_keyfile is not None:
|
if self.ssh_keyfile is not None:
|
||||||
rsync = f'{rsync} -e \'ssh -i {self.ssh_keyfile} -o StrictHostKeyChecking=accept-new\''
|
ssh = f'ssh -i {shlex.quote(self.ssh_keyfile)} -o StrictHostKeyChecking=accept-new'
|
||||||
elif self._password_auth and which('sshpass'):
|
elif self._password_auth and which('sshpass'):
|
||||||
rsync = f'{rsync} -e \'sshpass -e ssh -l {self.ssh_user} -o StrictHostKeyChecking=accept-new\''
|
ssh = f'sshpass -e ssh -l {shlex.quote(self.ssh_user)} -o StrictHostKeyChecking=accept-new'
|
||||||
else:
|
else:
|
||||||
rsync = f'{rsync} -e \'ssh -o StrictHostKeyChecking=accept-new\''
|
ssh = 'ssh -o StrictHostKeyChecking=accept-new'
|
||||||
|
|
||||||
|
args.extend(['-e', ssh])
|
||||||
|
|
||||||
if self._remote and self.remote_sudo:
|
if self._remote and self.remote_sudo:
|
||||||
rsync = f'{rsync} --rsync-path="sudo rsync"'
|
args.append('--rsync-path=sudo rsync')
|
||||||
|
|
||||||
args = shlex.split(rsync)
|
|
||||||
|
|
||||||
with Popen(args, stdin=PIPE, stdout=PIPE, stderr=STDOUT, shell=False) as p:
|
with Popen(args, stdin=PIPE, stdout=PIPE, stderr=STDOUT, shell=False) as p:
|
||||||
output: Union[bytes, List[str]]
|
output: Union[bytes, List[str]]
|
||||||
|
|||||||
Reference in New Issue
Block a user