#!/usr/bin/env ruby require 'socket' require 'mountycreds' require 'digest/md5' begin # require 'openssl' rescue LoadError end class Updater attr_reader :sock def initialize @mat = mountycreds.first @sock = TCPSocket.open($syncsrv, $syncsrvport) if defined? OpenSSL @sock.write 1.chr @sock = OpenSSL::SSL::SSLSocket.new(@sock, OpenSSL::SSL::SSLContext.new) @sock.sync = true puts 'SSL_connect' if $DEBUG @sock.connect else @sock.write 0.chr puts 'cleartext' if $DEBUG end @sock.puts @mat end def get(name, delafter = false) puts "get #{name.inspect}" if $DEBUG @sock.puts "get #{name}" len = @sock.gets.to_i File.open(name, 'wb') { |fd| while len > 0 and not (chunk = @sock.read([len, 2**14].min)).empty? fd.write chunk len -= chunk.size end } delafter ? del(name) : puts('ok') end def del(name) puts "del #{name.inspect}" if $DEBUG @sock.puts "del #{name}" len = @sock.gets.to_i puts @sock.read(len) end def list puts "list" if $DEBUG @sock.puts "list" len = @sock.gets.to_i @sock.read(len).to_a.map { |f| f.chomp } end def put(name) len = File.size(name) @sock.puts "put #{name}", len bs = 256*1024 File.open(name, 'rb') { |fd| while fd.pos < len fpos = fd.pos buf = fd.read bs puts "checking md5 at #{fpos}" if $DEBUG if @sock.gets.chomp != Digest::MD5.hexdigest(buf) puts "sending block at #{fpos}" if $DEBUG @sock.puts fpos @sock.write buf end end @sock.puts fd.pos } puts "sent #{name}, wait confirm" if $DEBUG puts @sock.read(@sock.gets.to_i) end def yell(name) buf = File.read(name) @sock.puts "yell#{name}", buf.length @sock.write buf len = @sock.gets.to_i puts @sock.read(len) end end if __FILE__ == $0 u = Updater.new curmeth = nil ARGV.each { |a| case a when 'list': puts "list:", u.list when 'put', 'get', 'del', 'yell': curmeth = a when 'update' u.list.each { |fn| print "get #{fn.inspect}: " u.get fn, true } else print "#{curmeth} #{a.inspect}: " u.send(curmeth, a) end } u.sock.shutdown rescue nil u.sock.close end