X-Git-Url: https://git.decadent.org.uk/gitweb/?a=blobdiff_plain;f=daklib%2Fgpg.py;h=828bf64906278f86db0aa13547b91356c0ba6568;hb=dbd3ceac44904f678181a189f34dc75c56178953;hp=5c396ec24a4a7274818b3e0f7acb71db734d78e0;hpb=9952acaae7cd7758ef320acfe194168a22829ab8;p=dak.git diff --git a/daklib/gpg.py b/daklib/gpg.py index 5c396ec2..828bf649 100644 --- a/daklib/gpg.py +++ b/daklib/gpg.py @@ -19,11 +19,12 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +import apt_pkg +import datetime import errno import fcntl import os import select -import sys try: _MAXFD = os.sysconf("SC_OPEN_MAX") @@ -69,7 +70,7 @@ class SignedFile(object): def __init__(self, data, keyrings, require_signature=True, gpg="/usr/bin/gpg"): """ @param data: string containing the message - @param keyrings: seqeuence of keyrings + @param keyrings: sequence of keyrings @param require_signature: if True (the default), will raise an exception if no valid signature was found @param gpg: location of the gpg binary """ @@ -86,32 +87,39 @@ class SignedFile(object): with _Pipe() as stdin: with _Pipe() as contents: with _Pipe() as status: + with _Pipe() as stderr: pid = os.fork() if pid == 0: - self._exec_gpg(stdin.r, contents.w, sys.stderr.fileno(), status.w) + self._exec_gpg(stdin.r, contents.w, stderr.w, status.w) else: stdin.close_r() contents.close_w() + stderr.close_w() status.close_w() - read = self._do_io([contents.r, status.r], {stdin.w: data}) + read = self._do_io([contents.r, stderr.r, status.r], {stdin.w: data}) stdin.w = None # was closed by _do_io (pid_, exit_code, usage_) = os.wait4(pid, 0) self.contents = read[contents.r] self.status = read[status.r] + self.stderr = read[stderr.r] if self.status == "": - raise GpgException("No status output from GPG. (GPG exited with status code %s)" % exit_code) + raise GpgException("No status output from GPG. (GPG exited with status code %s)\n%s" % (exit_code, self.stderr)) for line in self.status.splitlines(): self._parse_status(line) if require_signature and not self.valid: - raise GpgException("No valid signature found. (GPG exited with status code %s)" % exit_code) + raise GpgException("No valid signature found. (GPG exited with status code %s)\n%s" % (exit_code, self.stderr)) def _do_io(self, read, write): + for fd in write.keys(): + old = fcntl.fcntl(fd, fcntl.F_GETFL) + fcntl.fcntl(fd, fcntl.F_SETFL, old | os.O_NONBLOCK) + read_lines = dict( (fd, []) for fd in read ) write_pos = dict( (fd, 0) for fd in write ) @@ -135,6 +143,17 @@ class SignedFile(object): return dict( (fd, "".join(read_lines[fd])) for fd in read_lines.keys() ) + def _parse_date(self, value): + """parse date string in YYYY-MM-DD format + + @rtype: L{datetime.datetime} + @returns: datetime objects for 0:00 on the given day + """ + year, month, day = value.split('-') + date = datetime.date(int(year), int(month), int(day)) + time = datetime.time(0, 0) + return datetime.datetime.combine(date, time) + def _parse_status(self, line): fields = line.split() if fields[0] != "[GNUPG:]": @@ -147,6 +166,7 @@ class SignedFile(object): self.valid = True self.fingerprint = fields[2] self.primary_fingerprint = fields[11] + self.signature_timestamp = self._parse_date(fields[3]) if fields[1] == "BADARMOR": raise GpgException("Bad armor.") @@ -182,6 +202,9 @@ class SignedFile(object): os.execvp(self.gpg, args) finally: - sys.exit(1) + os._exit(1) + + def contents_sha1(self): + return apt_pkg.sha1sum(self.contents) # vim: set sw=4 et: