]> err.no Git - pwstore/commitdiff
Figure out if we can access files
authorPeter Palfrader <peter@palfrader.org>
Thu, 18 Sep 2008 16:40:48 +0000 (18:40 +0200)
committerPeter Palfrader <peter@palfrader.org>
Thu, 18 Sep 2008 16:40:48 +0000 (18:40 +0200)
pws

diff --git a/pws b/pws
index 8cbdf42c114f7a6cefb67d72963ac40e9ac89b84..df83dd0b4b4059501310fb27cb2a19ebb1ecf761 100755 (executable)
--- a/pws
+++ b/pws
@@ -1,9 +1,101 @@
 #!/usr/bin/ruby
 
 require 'optparse'
+require 'thread'
+
+Thread.abort_on_exception = true
+
+GNUPG = "/usr/bin/gpg"
 
 $program_name = File.basename($0, '.*')
 
+
+class GnuPG
+  def GnuPG.readwrite3(intxt, infd, stdoutfd, stderrfd, statusfd)
+    outtxt, stderrtxt, statustxt = ''
+    thread_in = Thread.new {
+      infd.print intxt
+      infd.close
+    }
+    thread_out = Thread.new {
+      outtxt = stdoutfd.read
+      stdoutfd.close
+    }
+    thread_err = Thread.new {
+      errtxt = stderrfd.read
+      stderrfd.close
+    }
+    thread_status = Thread.new {
+      statustxt = statusfd.read
+      statusfd.close
+    } if (statusfd)
+
+    thread_in.join
+    thread_out.join
+    thread_err.join
+    thread_status.join if thread_status
+
+    return outtxt, stderrtxt, statustxt
+  end
+
+  def GnuPG.gpgcall(intxt, args)
+    inR, inW = IO.pipe
+    outR, outW = IO.pipe
+    errR, errW = IO.pipe
+    statR, statW = IO.pipe
+
+    pid = Kernel.fork do
+      inW.close
+      outR.close
+      errR.close
+      statR.close
+      STDIN.reopen(inR)
+      STDOUT.reopen(outW)
+      STDERR.reopen(errW)
+      exec(GNUPG, "--status-fd=#{statW.fileno}",  *args)
+      raise ("Calling gnupg failed")
+    end
+    inR.close
+    outW.close
+    errW.close
+    statW.close
+    (outtxt, stderrtxt, statustxt) = readwrite3(intxt, inW, outR, errR, statR);
+    Process.wait pid
+    return outtxt, stderrtxt, statustxt
+  end
+
+  def GnuPG.list_readers(filename)
+    content = File.read(filename)
+    (outtxt, stderrtxt, statustxt) = gpgcall(content, %w{--with-colons --no-default-keyring --secret-keyring=/dev/null --keyring=/dev/null})
+    readers = []
+    statustxt.split("\n").each do |line|
+      m = /^\[GNUPG:\] ENC_TO ([0-9A-F]+)/.match line
+      next unless m
+      readers.push m[1]
+    end
+    return readers
+  end
+
+  def initialize()
+    (outtxt, stderrtxt, statustxt) = GnuPG.gpgcall('', %w{--fast-list-mode --with-colons --list-secret-keys})
+    @my_keys = []
+    outtxt.split("\n").each do |line|
+      parts = line.split(':')
+      if (parts[0] == "ssb" or parts[0] == "sec")
+        @my_keys.push parts[4]
+      end
+    end
+  end
+
+  def can_read(filename)
+    readers = GnuPG.list_readers(filename)
+    @my_keys.each do |k|
+      return true if readers.include?(k)
+    end
+    return false
+  end
+end
+
 class Ls
   def help(parser, code=0, io=STDOUT)
     io.puts "Usage: #{$program_name} ls [<directory> ...]"
@@ -15,6 +107,8 @@ class Ls
   end
 
   def ls_dir(d)
+    g = GnuPG.new
+
     begin
       dir = Dir.open(d)
     rescue Exception => e
@@ -26,13 +120,19 @@ class Ls
       next if (filename =~ /^\./) and not @all
       stat = File::Stat.new(filename)
       if stat.symlink?
-        puts "(sym)    #{filename}"
+        puts "(sym)      #{filename}"
       elsif stat.directory?
-        puts "(dir)    #{filename}"
+        puts "(dir)      #{filename}"
       elsif !stat.file?
-        puts "(other)  #{filename}"
+        puts "(other)    #{filename}"
       else
-        puts "(file)   #{filename}"
+        readable = g.can_read(filename)
+        if readable
+          puts "(ok)       #{filename}"
+        else
+          puts "(locked)   #{filename}"
+        end
+        #puts "(file)   #{filename}"
       end
     end
   end