diff options
| -rw-r--r-- | debian/byteback/DEBIAN/control | 26 | ||||
| -rw-r--r-- | debian/byteback/DEBIAN/md5sums | 9 | ||||
| -rwxr-xr-x | debian/byteback/usr/sbin/byteback | 65 | ||||
| -rwxr-xr-x | debian/byteback/usr/sbin/byteback-backup | 216 | ||||
| -rwxr-xr-x | debian/byteback/usr/sbin/byteback-receive | 54 | ||||
| -rwxr-xr-x | debian/byteback/usr/sbin/byteback-setup-client | 54 | ||||
| -rwxr-xr-x | debian/byteback/usr/sbin/byteback-setup-client-receive | 42 | ||||
| -rwxr-xr-x | debian/byteback/usr/sbin/byteback-snapshot | 234 | ||||
| -rw-r--r-- | debian/byteback/usr/share/doc/byteback/README.md.gz | bin | 3193 -> 0 bytes | |||
| -rw-r--r-- | debian/byteback/usr/share/doc/byteback/changelog.Debian.gz | bin | 203 -> 0 bytes | |||
| -rw-r--r-- | debian/byteback/usr/share/doc/byteback/copyright | 29 | 
11 files changed, 0 insertions, 729 deletions
diff --git a/debian/byteback/DEBIAN/control b/debian/byteback/DEBIAN/control deleted file mode 100644 index ee20a2e..0000000 --- a/debian/byteback/DEBIAN/control +++ /dev/null @@ -1,26 +0,0 @@ -Package: byteback -Version: 0.2.0-1 -Architecture: all -Maintainer: Patrick J Cherry <patrick@bytemark.co.uk> -Installed-Size: 48 -Depends: ruby | ruby-interpreter, rsync, openssh-client -Recommends: ruby-trollop | libtrollop-ruby -Section: ruby -Priority: optional -Homepage: https://projects.bytemark.co.uk/projects/byteback -Description: Maintenance-free client & server backup scripts for Linux -  byteback encapsulates Bytemark's "best practice" for maintenance-free backups -  with easy client and server setup. -  . -  "Maintenance-free" means that we'd rather make full use of a fixed amount of -  disc space.  Management of disc space must be completely automatic, so the -  process never grinds to a halt for reasons that could be automatically -  resolved.  Failed backups can be restarted in case of network problems. -  . -  We use the standard OpenSSH on the server for encrypted transport & access -  control, btrfs for simple snapshots and rsync for efficient data transfer -  across the network. -  . -  Backups should require as little configuration as possible to be safe - just -  the server address should be enough. -Ruby-Versions: ruby1.9.1 ruby2.0 diff --git a/debian/byteback/DEBIAN/md5sums b/debian/byteback/DEBIAN/md5sums deleted file mode 100644 index e9641f9..0000000 --- a/debian/byteback/DEBIAN/md5sums +++ /dev/null @@ -1,9 +0,0 @@ -6f600d576b18b93e3bf43afd043f156e  usr/sbin/byteback -21a8bb0fb9fecf44bbf58e9bbceda2b7  usr/sbin/byteback-backup -cee04f5b5f344d8ecb6ae0af488c5e0d  usr/sbin/byteback-receive -7a7899e4bc3c0ba13280b8cd6eca827c  usr/sbin/byteback-setup-client -cc78a3fd9b662e3db1e7fa801c4011dd  usr/sbin/byteback-setup-client-receive -54a8cd3305209c36446b63707e68d070  usr/sbin/byteback-snapshot -538e288de3c0b5fdddcfb65840017482  usr/share/doc/byteback/README.md.gz -09620c298fa07a984827d0bac4dd9cc3  usr/share/doc/byteback/changelog.Debian.gz -4e261bda29e8364ad551d709a97162a0  usr/share/doc/byteback/copyright diff --git a/debian/byteback/usr/sbin/byteback b/debian/byteback/usr/sbin/byteback deleted file mode 100755 index 7418006..0000000 --- a/debian/byteback/usr/sbin/byteback +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/ruby -# -# byteback backup script prototype -# -# (c) Bytemark Hosting 2013 -# -#  -VERSION='prototype' - -HOSTNAME=`hostname -f` - -mode = ARGV.shift -case mode -when 'backup' - -    @destination_host = HOSTNAME.split(".")[2..-1].join(".") - -	system *<<-CMD.split(/\s+/) - -rsync  - -  --rsync-path  -    rsync --fake-super -  --rsh  -    ssh -i /etc/bytebackup/bytebackup.key -  --delete -  --one-file-system -  --archive -  --exclude -    /swap.file - -  / - -  #{@destination_ssh} - -	CMD -when 'backup-receive' - -else -	print <<-SYNTAX -byteback v#{VERSION}, a focused backup tool - -Usage: byteback <mode> - -Modes: -    server-setup -    client-setup -    backup -    backup-receive - -Type 'bytebackup help <mode>' for more information on a mode, or -see the man page. -	SYNTAX -	exit 1 -end - -require 'trollop' -opts = Trollop::options do -	opt :mode, "Program mode to run",  -		:default => :backup, -		:required, -		:type => String - -	opt  -:end
\ No newline at end of file diff --git a/debian/byteback/usr/sbin/byteback-backup b/debian/byteback/usr/sbin/byteback-backup deleted file mode 100755 index 22fe0fb..0000000 --- a/debian/byteback/usr/sbin/byteback-backup +++ /dev/null @@ -1,216 +0,0 @@ -#!/usr/bin/ruby -# -# Back up this system to a byteback-enabled server (just some command line -# tools and SSH setup).  We aim to make sure this backups are easy, complete -# and safe for most types of hosting customer. -# -# See 'man byteback' for more information. - -require 'getoptlong' -require 'resolv' - - -def error(message) -  STDERR.print "*** #{message}\n" -  exit 1 -end - -def verbose(message) -  print "#{message}\n" -end - -def help -  puts <<EOF -#{$0}: Back up this system to a byteback-enabled server - -Options: -   --destination, -d <s>:   Backup destination (i.e. user@host:/path) -       --source, -s  <s>:   Source paths (defaults: / and /boot) -       --exclude, -x <s>:   Exclude paths (defaults: /swap.file, /var/backups/localhost, /var/cache) -           --verbose, -v:   Show rsync command and progress -  --retry-number, -r <n>:   Number of retries on error (default: 3) -   --retry-delay, -e <n>:   Wait number of seconds between retries (default: 1800) -       --ssh-key, -k <s>:   SSH key for connection (default: /etc/byteback/key) -              --help, -h:   Show this message -EOF -  exit 0 -end - - -opts = GetoptLong.new( -  [ '--help',       '-h', GetoptLong::NO_ARGUMENT ], -  [ '--verbose',    '-v', GetoptLong::NO_ARGUMENT ], -  [ '--source',     '-s', GetoptLong::REQUIRED_ARGUMENT ], -  [ '--destination',   '-d', GetoptLong::REQUIRED_ARGUMENT ], -  [ '--retry-number',  '-r', GetoptLong::REQUIRED_ARGUMENT ], -  [ '--retry-delay',   '-e', GetoptLong::REQUIRED_ARGUMENT ], -  [ '--ssh-key'       ,'-k', GetoptLong::REQUIRED_ARGUMENT ] -) - -@ssh_key = nil -@destination = nil -@retry_number = 3 -@retry_delay = 1800 -@sources = nil -@excludes = nil - -# Read the default destination -if File.exists?("/etc/byteback/destination") -  @destination = File.read("/etc/byteback/destination").chomp -end - -# Set the default SSH key -if File.exists?("/etc/byteback/key") -  @ssh_key = "/etc/byteback/key" -end - -# Read in the default sources -if File.exists?("/etc/byteback/sources") -  @sources = File.readlines("/etc/byteback/sources").map{|m| m.chomp} -end - -# Read in the default excludes -if File.exists?("/etc/byteback/excludes") -  @excludes = File.readlines("/etc/byteback/excludes").map{|m| m.chomp} -end - -begin -  opts.each do |opt,arg| -    case opt -    when '--help' -      help = true -    when '--verbose' -      $VERBOSE = true -    when "--source" -      @sources ||= [] -      @sources << arg -    when "--exclude" -      @excludes ||= [] -      @excludes << arg -    when "--destination" -      @destination = arg -    when "--retry-number" -      @retry_number = arg.to_i -    when "--retry-delay" -      @retry_delay = arg.to_i -    when "--ssh-key" -      @ssh_key = arg -    end -  end -rescue => err -  # any errors, show the help -  warn err.to_s -  help = true -end - - -# -# Check our destination -# -if @destination =~ /^(?:(.+)@)?([^@:]+):(.+)?$/ -  @destination_user, @destination_host, @destination_path = [$1, $2, $3] -else -  error("Destination must be a remote path, e.g. ssh@host.com:/store/backups") -end - -# -# Validate & normalise source directories -# -@sources = ["/"] if @sources.nil? - -error("No sources specified") if @sources.empty? - -@sources = @sources.map do |s| -  s = s.gsub(/\/+/,"/") -  error("Can't read directory #{s}") unless File.readable?(s) -  s -end - -# -# Validate and normalise excludes -# -if @excludes.nil? -  @excludes = ["/swap.file", "/var/backups/localhost"] -  @excludes << "/var/cache/apt/archives" if  File.directory?("/var/cache/apt/archives") -end - -@excludes = @excludes.map do |e| -  e.gsub(/\/+/,"/") -end - -error("Must suply --destination or put it into /etc/bytebackup/destination") unless @destination - -# -# Test ssh connection is good before we start -# -error("Could not read ssh key #{@ssh_key}") unless File.readable?(@ssh_key) - -def ssh(*ssh_args) -  args = ["ssh", -    "-o", "BatchMode=yes", -    "-x", "-a", -    "-i", @ssh_key, -    "-l", @destination_user, -    @destination_host -  ] + -  ssh_args. -  map { |a| a ? a : "" } - -  print args.map { |a| / /.match(a) ? "\"#{a}\"" : a }.join(" ")+"\n" if $VERBOSE - -  system(*args) -end - -error("Could not connect to #{@destination}") unless -  ssh("byteback-receive", "--ping", ($VERBOSE ? "--verbose" : "" )) - -# -# Call rsync to copy certain sources, returns exit status (see man rsync) -# -def rsync(*sources) -  # Default options include --inplace because we only care about consistency -  # at the end of the job, and rsync will do more work for big files without -  # it. -  # -  args = %w(rsync --archive --numeric-ids --delete --inplace --delete --one-file-system --relative) -  args += [ "--rsync-path", "rsync --fake-super"] -  args += [ "--rsh", "ssh -o BatchMode=yes -x -a -i #{@ssh_key} -l #{@destination_user}"] -  args << "--verbose" if $VERBOSE -  args += @excludes.map { |x| ["--exclude", x] }.flatten -  args += sources -  args << @destination - -  print args.map { |a| / /.match(a) ? "\"#{a}\"" : a }.join(" ")+"\n" if $VERBOSE - -  system(*args) - -  return $?.exitstatus -end - -RSYNC_EXIT_STATUSES_TO_RETRY_ON = [10,11,20,21,22,23,24,30] - -# Run the file copy, retrying if necessary -# -loop do -  status = rsync(*@sources) - -  if status === 0 -    break -  elsif RSYNC_EXIT_STATUSES_TO_RETRY_ON.include?(status) -    if @retry_number > 0 -      @retry_number -= 1 -      sleep @retry_delay -      redo -    else -      error("Maximum number of rsync retries reached") -    end -  else -    error("Fatal rsync error occurred (#{status})") -  end -end - -# Mark the backup as done on the other end -# -error("Backup could not be marked complete") unless -  ssh("sudo", "byteback-snapshot", "--snapshot", ($VERBOSE ? "--verbose" : "")) - diff --git a/debian/byteback/usr/sbin/byteback-receive b/debian/byteback/usr/sbin/byteback-receive deleted file mode 100755 index 05e6a7c..0000000 --- a/debian/byteback/usr/sbin/byteback-receive +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/ruby -# -# Program to receive backups and run rsync in receive mode.  Must check that -# user as authorised by SSH is allowed to access particular directory. - -#STDERR.print ARGV.inspect + "\n" - -require 'trollop' - -def error(message) -	STDERR.print "*** #{message}\n" -	exit 1 -end - -#STDERR.print "ARGV=#{ARGV.inspect}\nSSH_ORIGINAL_COMMAND=#{ENV['SSH_ORIGINAL_COMMAND']}\n" - -if ENV['SSH_ORIGINAL_COMMAND'] -	ARGV.concat(ENV['SSH_ORIGINAL_COMMAND'].split(" ")) -end - -#STDERR.print "after ARGV=#{ARGV.inspect}\n" - -byteback_host = ENV['BYTEBACK_HOST'] -error("BYTEBACK_HOST environment not set") unless byteback_host - -byteback_root = ENV['HOME'] + "/" + ENV["BYTEBACK_HOST"] -error("#{byteback_root} does not exist") unless File.directory?(byteback_root) - -# force destination to be where we expect -# -if ARGV[0] == 'rsync' -	ARGV[-1] = "#{byteback_root}/current" -	exec(*ARGV) -elsif ARGV[0] == 'byteback-snapshot' || (ARGV[0] == 'sudo' && ARGV[1] == 'byteback-snapshot') -	ARGV.concat(["--root", "#{byteback_root}"]) -	exec(*ARGV) -end - -opts = Trollop::options do -	opt :verbose, "Print diagnostics" -	opt :ping, "Check connection parameters and exit" -	opt :complete, "Mark current backup as complete" -end - -error("Please only choose one mode") if opts[:ping] && opts[:complete] -if opts[:complete] -	system("byteback-snapshot", byteback_root) -elsif opts[:ping] -	exit 0 -else -	STDERR.print "byteback-receive failed\n" -	exit 9 -end - diff --git a/debian/byteback/usr/sbin/byteback-setup-client b/debian/byteback/usr/sbin/byteback-setup-client deleted file mode 100755 index ddb6672..0000000 --- a/debian/byteback/usr/sbin/byteback-setup-client +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/ruby -# -# Run on a client machine to set up backups for the first time - -require 'fileutils' -require 'trollop' - -def error(message) -	STDERR.print "*** #{message}\n" -	exit 1 -end - -def verbose(message) -	print "#{message}\n" -end - -opts = Trollop::options do - -	opt :hostname, "Set host name for backups", -	  :type => :string - -	opt :destination, "Backup destination (i.e. user@host:/path)",  -	  :type => :string - -end - -@destination = opts[:destination] -@hostname = opts[:hostname] - -_dummy, @destination_user, @destination_host, colon, @destination_path =  -  /^(.*)?(?:@)([^:]+)(:)(.*)?$/.match(@destination).to_a - -error("Must be a remote path") unless colon -if !@hostname -	@hostname = `hostname -f` -	print "No hostname set, using #{@hostname}" -end - -error "This host already appears set up - you need to delete /etc/byteback if not" if -  File.readable?("/etc/byteback/key") - -FileUtils.mkdir_p("/etc/byteback") - -error "Couldn't generate SSH key" unless  -  system("ssh-keygen -q -t rsa -C \"byteback client key\" -N \"\" -f /etc/byteback/key") - -key_pub = File.read("/etc/byteback/key.pub") - -error "Setup didn't work" unless -  system("ssh -i /etc/byteback/key -l #{@destination_user} #{@destination_host} byteback-setup-client-receive #{@hostname} #{key_pub}") - -File.open("/etc/byteback/destination", "w") { |f| f.print @destination } - -print "Setup worked!  To take your first backup run: byteback-backup --verbose\n" diff --git a/debian/byteback/usr/sbin/byteback-setup-client-receive b/debian/byteback/usr/sbin/byteback-setup-client-receive deleted file mode 100755 index 35a3b65..0000000 --- a/debian/byteback/usr/sbin/byteback-setup-client-receive +++ /dev/null @@ -1,42 +0,0 @@ -#!/usr/bin/ruby -# -# Called by byteback-setup-client to set up a new byteback-setup-client - -require 'fileutils' - -def error(message) -	STDERR.print "*** #{message}\n" -	exit 1 -end - -@hostname = ARGV.shift -@pubkey = ARGV.join(" ") - -error("You must call this from byteback-setup-client on remote host") unless -  @hostname &&  -  /^ssh/.match(@pubkey) && -  ENV['SSH_CONNECTION'] - -@client_ip = ENV['SSH_CONNECTION'].split(" ").first - -Dir.chdir(ENV['HOME']) # don't know why we wouldn't be here - -Dir.mkdir(@hostname) - -error("Couldn't create btrfs subvolume (needs sudo)") unless  -	system("sudo btrfs subvolume create #{@hostname}/current") - -FileUtils.mkdir_p(".ssh") - -error("This key already exists in .ssh/authorized_keys on server") if -	File.exists?(".ssh/authorized_keys") && -	File.read(".ssh/authorized_keys").match(@pubkey.split(/\s+/)[1]) - -File.open(".ssh/authorized_keys", "a+") do |fh| -	fh.print <<-LINE.gsub(/\n/,"") -command="byteback-receive", -from="#{@client_ip}", -environment="BYTEBACK_HOST=#{@hostname}" - #{@pubkey} -	LINE -end diff --git a/debian/byteback/usr/sbin/byteback-snapshot b/debian/byteback/usr/sbin/byteback-snapshot deleted file mode 100755 index 0e5a362..0000000 --- a/debian/byteback/usr/sbin/byteback-snapshot +++ /dev/null @@ -1,234 +0,0 @@ -#!/usr/bin/ruby -# -# Program to create a snapshot and/or rotate a directory of backup snapshots  -# using btrfs subvolume commands. - -require 'trollop' -require 'time' - -def error(message) -	STDERR.print "*** #{message}\n" -	exit 1 -end - -def verbose(message) -	print "#{Time.now}: #{message}\n" if @verbose -end - -# Icky way to find out free disc space on our mount -# -class DiskFree -	def initialize(mount) -		@mount = mount -	end - -	def total -		all[2] -	end - -	def used -		all[3] -	end - -	def available -		all[4] -	end - -	def fraction_used -		disk_device, disk_fs, disk_total, disk_used, disk_available, *rest = all -		disk_used.to_f / disk_available -	end - -	protected - -	def all -		disk_device, disk_fs, disk_total, disk_used, disk_available, *rest =  -			df. -			split("\n")[1]. -			split(/\s+/). -			map { |i| /^[0-9]+$/.match(i) ? i.to_i : i } -	end - -	def df -		`/bin/df -T -P -B1 #{@mount}` -	end -end - -# Represent a directory full of backups where "current"  is a subvolume -# which is snapshotted to frozen backup directories called e.g.  -# "yyyy-mm-ddThh:mm+zzzz". -# -class BackupDirectory -	attr_reader :dir - -	def initialize(dir) -		@dir = Dir.new(dir) -		current -	end - -	# Return total amount of free space in backup directory (bytes) -	# -	def free -		df = DiskFree.new(@dir.path) -		df.total - df.used -	end - -	# Return an array of Times representing the current list of  -	# snapshots. -	# -	def snapshot_times -		@dir.entries.map do |entry| -			begin -				Time.parse(entry) -			rescue ArgumentError => error -				nil -			end -		end. -		compact. -		sort -	end - -	# What order to remove snapshots in to regain disk space? -	# -	# Order backups by their closeness to defined backup times, which are -	# listed in a set order (i.e. today's backup is more important than yesterday's). -	# -	BACKUP_IMPORTANCE = [0, 1, 2, 3, 7, 14, 21, 28, 56, 112] -	def snapshot_times_by_importance -		now = Time.now -		snapshot_times_unsorted = snapshot_times -		snapshot_times_sorted = [] -		while !snapshot_times_unsorted.empty? -			BACKUP_IMPORTANCE.each do |days| -				target_time = now + (days*86400) -				closest = snapshot_times_unsorted.inject(nil) do |best, time| -					if best.nil? || (time-target_time).abs < (best-target_time).abs -						time -					else -						best -					end -				end -				break unless closest -				snapshot_times_sorted << snapshot_times_unsorted.delete(closest) -			end -		end -		snapshot_times_sorted -	end - -	# Returns the size of the given snapshot (runs du, may be slow) -	# -	# Would much prefer to take advantage of this feature: -	#   http://dustymabe.com/2013/09/22/btrfs-how-big-are-my-snapshots/ -	# but it's not currently in Debian/wheezy. -	# -	def snapshot_size(time=snapshot_times.latest) -		`du -s -b #{snapshot_path(time)}`.to_i -	end - -	def average_snapshot_size(number=10) -		snapshot_times.sort[0..number].inject(0) { |time, total| snapshot_size(time) } / number -	end - -	# Create a new snapshot of 'current' -	# -	def new_snapshot! -		system_no_error("btrfs subvolume snapshot -r #{current.path} #{snapshot_path}") -	end - -	def delete_snapshot!(time) -		system_no_error("btrfs subvolume delete #{snapshot_path(time)}") -	end - -	def current -		Dir.new("#{dir.path}/current") -	end - -	def snapshot_path(time=Time.now) -		"#{dir.path}/#{time.strftime("%Y-%m-%dT%H:%M%z")}" -	end - -	protected - -	def system_no_error(*args) -		raise RuntimeError.new("Command failed: "+args.join(" ")) unless -		  system(*args) -	end -end - -opts = Trollop::options do - -    opt :root, "Backups directory (must be a btrfs subvolume)", -    	:type => :string - -    opt :snapshot, "Take a new snapshot" - -    opt :prune, "Prune old backups", -    	:type => :string - -    opt :list, "List backups (by 'age' or 'importance')", -    	:type => :string - -    opt :verbose, "Print diagnostics" - -end - -@root = opts[:root] -@verbose = opts[:verbose] -@do_snapshot = opts[:snapshot] -@do_list = opts[:list] -@do_prune = opts[:prune] - -error("Must specify snapshot, prune or list") unless @do_snapshot || @do_prune || @do_list - -error("--root not readable") unless File.directory?(@root) - -@backups = BackupDirectory.new(@root) - -def get_snapshots_by(method) -	if method == 'importance' -		@backups.snapshot_times_by_importance.reverse # least important first -	elsif method == 'age' -		@backups.snapshot_times -	else -		raise ArgumentError.new("Unknown snapshot sort method #{method}") -	end -end - -if @do_snapshot -	last_snapshot_time = @backups.snapshot_times.last -	error("Last snapshot was less than six hours ago") unless  -		!last_snapshot_time ||  -		Time.now - @backups.snapshot_times.last >= 6*60*60 # FIXME: make configurable - -	verbose "Making new snapshot" -	@backups.new_snapshot!  -end - -if @do_list -	list = get_snapshots_by(@do_list) -	print "Backups in #{@root} by #{@do_list}:\n" -	list.each_with_index do |time, index| -		print "#{sprintf('% 3d',index)}: #{time}\n" -	end -end - -if @do_prune -	verbose "Counting last 10 backups" -	target_free_space = 1.5 * @backups.average_snapshot_size(10) -	verbose "Want to ensure we have #{target_free_space}" - -	if @backups.free >= target_free_space -		verbose "(we have #{@backups.free} so no action needed)" -	else -		list = get_snapshots_by(@do_prune) - -		while @backups.free < target_free_space && !list.empty? -			to_delete = list.pop -			verbose "Deleting #{to_delete}" -			@backups.delete_snapshot!(to_delete) -			verbose "Leaves us with #{@backups.free}" -		end -	end -end - -verbose "Finished" diff --git a/debian/byteback/usr/share/doc/byteback/README.md.gz b/debian/byteback/usr/share/doc/byteback/README.md.gz Binary files differdeleted file mode 100644 index 6d5e92a..0000000 --- a/debian/byteback/usr/share/doc/byteback/README.md.gz +++ /dev/null diff --git a/debian/byteback/usr/share/doc/byteback/changelog.Debian.gz b/debian/byteback/usr/share/doc/byteback/changelog.Debian.gz Binary files differdeleted file mode 100644 index 0fa0c0d..0000000 --- a/debian/byteback/usr/share/doc/byteback/changelog.Debian.gz +++ /dev/null diff --git a/debian/byteback/usr/share/doc/byteback/copyright b/debian/byteback/usr/share/doc/byteback/copyright deleted file mode 100644 index daf38ac..0000000 --- a/debian/byteback/usr/share/doc/byteback/copyright +++ /dev/null @@ -1,29 +0,0 @@ -Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ -Upstream-Name: byteback -Source: <https://projects.bytemark.co.uk/projects/byteback> - -Files: * -Copyright: 2013-2014 Bytemark Computer Consulting Ltd -License: GPL-2+ - -License: GPL-2+ - This program is free software; you can redistribute it - and/or modify it under the terms of the GNU General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later - version. - . - This program is distributed in the hope that it will be - useful, but WITHOUT ANY WARRANTY; without even the implied - warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - PURPOSE.  See the GNU General Public License for more - details. - . - You should have received a copy of the GNU General Public - License along with this package; if not, write to the Free - Software Foundation, Inc., 51 Franklin St, Fifth Floor, - Boston, MA  02110-1301 USA - . - On Debian systems, the full text of the GNU General Public - License version 2 can be found in the file - `/usr/share/common-licenses/GPL-2'.  | 
