#!/usr/bin/ruby # encoding: UTF-8 # # Program to receive backups and run rsync in receive mode. Must check that # user as authorised by SSH is allowed to access particular directory. $LOAD_PATH << '/usr/lib/byteback' require 'trollop' require 'byteback' require 'byteback/restore' include Byteback::Log if ENV['SSH_ORIGINAL_COMMAND'] ARGV.concat(ENV['SSH_ORIGINAL_COMMAND'].split(' ')) end byteback_host = ENV['BYTEBACK_HOST'] fatal('BYTEBACK_HOST environment not set') unless byteback_host byteback_root = ENV['HOME'] + '/' + ENV['BYTEBACK_HOST'] fatal("#{byteback_root} does not exist") unless File.directory?(byteback_root) # # Calling byteback-restore really needs rsync to restore the files. # if ARGV[0] == 'byteback-restore' # # Ignore the first arg # ARGV.shift args = ['rsync'] snapshot = nil verbose = false all = false # # Mangle the arguments, and pull out any that are not-rsync compatible. # while (arg = ARGV.shift) case arg when '.' break when /^-([^-]*v[^-]*|-verbose)$/ verbose = true args << arg when '--snapshot' snapshot = ARGV.shift when '--all' all = true else args << arg end end # Always exclude the current directory, because it can change the # ownership at the restorers end. args << '--exclude=.' # # Search for certain files # DANGER the args might be too long if lots of files are returned. # paths = Byteback::Restore.decode_args(ARGV) restore = Byteback::Restore.new(byteback_root) restore.snapshot = snapshot if snapshot restore.find(paths, all: all) Dir.chdir(byteback_host) args << '.' restore.results.each do |r| args << File.join('.', r.snapshot, r.path) end if restore.results.empty? STDERR.puts '** Sorry. There were no files matching:' STDERR.puts '--> ' + paths.join("\n--> ") exit 1 end STDERR.puts 'Restoring:' STDERR.puts restore.list STDERR.puts(args.join(' ')) if verbose exec(*args) elsif ARGV[0] == 'rsync' ARGV[-1] = "#{byteback_root}/current" exec(*ARGV) elsif ARGV[0] == 'byteback-snapshot' ARGV.concat(['--root', byteback_root.to_s]) exec(*ARGV) elsif ARGV[0] == 'restore' puts '** Your byteback package needs to be updated. Please update and try again.' exit(1) end opts = Trollop.options do opt :ping, 'Check connection parameters and exit' opt :complete, 'Mark current backup as complete' opt :list, 'Show backed up files matching the given pattern' opt :all, 'Show all stored versions of a file' opt :snapshot, 'Show backed up files in a certain snapshot.', default: '*' opt :verbose, 'Print diagnostics' end # # Make sure we don't get crazy option combinations. # n_modes = opts.keys.inject(0) do |s, m| [:ping, :complete, :list].include?(m) ? s += 1 : s end error('Please only choose one mode') unless n_modes == 1 if opts[:complete] system('byteback-snapshot', '--root', byteback_root) elsif opts[:list] args = Byteback::Restore.decode_args(ARGV[1..-1]) restore = Byteback::Restore.new(byteback_root) restore.snapshot = opts[:snapshot] restore.find(args, all: opts[:all], verbose: opts[:verbose]) if restore.results.empty? puts '** Sorry. There were no files matching:' puts '--> ' + args.join("\n--> ") else puts restore.list end exit(0) elsif opts[:ping] exit 0 else STDERR.print "byteback-receive failed\n" exit 9 end