Esempio n. 1
0
def VerifyUpdate(directory):
    """
    Verify the update in the directory is valid -- the manifest
    is sane, any signature is valid, the package files necessary to
    update are present, and have a valid checksum.  Returns either
    a file object if it's valid (the file object is locked), None
    if it doesn't exist, or it raises an exception -- one of
    UpdateIncompleteCacheException or UpdateInvalidCacheException --
    if necessary.
    """
    import fcntl

    # First thing we do is get the systen configuration and
    # systen manifest
    conf = Configuration.Configuration()
    mani = conf.SystemManifest()

    # Next, let's see if the directory exists.
    if not os.path.exists(directory):
        return None
    # Open up the manifest file.  Assuming it exists.
    try:
        mani_file = open(directory + "/MANIFEST", "r+")
    except:
        # Doesn't exist.  Or we can't get to it, which would be weird.
        return None
    # Let's try getting an exclusive lock on the manifest
    try:
        fcntl.lockf(mani_file, fcntl.LOCK_EX | fcntl.LOCK_NB, 0, 0)
    except:
        # Well, if we can't acquire the lock, someone else has it.
        # Throw an incomplete exception
        raise UpdateBusyCacheException("Cache directory %s is being modified" %
                                       directory)
    cached_mani = Manifest.Manifest()
    try:
        cached_mani.LoadFile(mani_file)
    except Exception as e:
        # If we got an exception, it's invalid.
        log.error("Could not load cached manifest file: %s" % str(e))
        raise UpdateInvalidCacheException

    # First easy thing to do:  look for the SEQUENCE file.
    try:
        cached_sequence = open(directory + "/SEQUENCE", "r").read().rstrip()
    except (IOError, Exception) as e:
        log.error("Could not sequence file in cache directory %s: %s" %
                  (directory, str(e)))
        raise UpdateIncompleteCacheException(
            "Cache directory %s does not have a sequence file" % directory)

    # Now let's see if the sequence matches us.
    if cached_sequence != mani.Sequence():
        log.error("Cached sequence, %s, does not match system sequence, %s" %
                  (cached_sequence, mani.Sequence()))
        raise UpdateInvalidCacheException(
            "Cached sequence does not match system sequence")

    # Next thing to do is go through the manifest, and decide which package files we need.
    diffs = Manifest.CompareManifests(mani, cached_mani)
    # This gives us an array to examine.
    for (pkg, op, old) in diffs:
        if op == "delete":
            # Deleted package, so we don't need to do any verification here
            continue
        if op == "install":
            # New package, being installed, so we need the full package
            cur_vers = None
        if op == "upgrade":
            # Package being updated, so we can look for the delta package.
            cur_vers = old.Version()
        new_vers = pkg.Version()
        # This is slightly redundant -- if cur_vers is None, it'll check
        # the same filename twice.
        if not os.path.exists(directory + "/" + pkg.FileName())  and \
           not os.path.exists(directory + "/" + pkg.FileName(cur_vers)):
            # Neither exists, so incoplete
            log.error("Cache %s  directory missing files for package %s" %
                      (directory, pkg.Name()))
            raise UpdateIncompleteCacheException(
                "Cache directory %s missing files for package %s" %
                (directory, pkg.Name()))
        # Okay, at least one of them exists.
        # Let's try the full file first
        try:
            with open(directory + "/" + pkg.FileName()) as f:
                if pkg.Checksum():
                    cksum = Configuration.ChecksumFile(f)
                    if cksum == pkg.Checksum():
                        continue
                else:
                    continue
        except:
            pass

        if cur_vers is None:
            e = "Cache directory %s missing files for package %s" % (
                directory, pkg.Name())
            log.error(e)
            raise UpdateIncompleteCacheException(e)

        # Now we try the delta file
        # To do that, we need to find the right dictionary in the pkg
        upd_cksum = None
        found = False
        for update_dict in pkg.Updates():
            if update_dict[Package.VERSION_KEY] == cur_vers:
                if Package.CHECKSUM_KEY in update_dict:
                    upd_cksum = update_dict[Package.CHECKSUM_KEY]
                    try:
                        with open(directory + "/" +
                                  pkg.FileName(cur_vers)) as f:
                            cksum = Configuration.ChecksumFile(f)
                            if upd_cksum == cksum:
                                found = True
                                break
                    except:
                        pass
                else:
                    found = True
                    break
        if found is False:
            # If we got here, we are missing this file
            log_msg = "Cache directory %s is missing package %s" % (directory,
                                                                    pkg.Name())
            log.error(log_msg)
            raise UpdateIncompleteCacheException(log_msg)
    # And if we got here, then we have found all of the packages, the manifest is fine,
    # and the sequence tag is correct.
    mani_file.seek(0)
    return mani_file
Esempio n. 2
0
        with open(notesfile, "r") as f:
            for line in f:
                notes.append(line)
        mani.SetNotes(notes)

    if package_dir is not None:
        conf.SetPackageDir(package_dir)

    for P in pkgs:
        if os.path.exists(P):
            # Let's get the manifest from it
            pkgfile = open(P, "rb")
            pkg_json = PF.GetManifest(file=pkgfile)
            name = pkg_json[PF.kPkgNameKey]
            version = pkg_json[PF.kPkgVersionKey]
            hash = Configuration.ChecksumFile(pkgfile)
            size = os.lstat(P).st_size
            try:
                services = pkg_json[PF.kPkgServicesKey]
            except:
                print("%s is not in pkg_json" % PF.kPkgServicesKey,
                      file=sys.stderr)
                services = None
            try:
                rr = pkg_json[PF.kPkgRebootKey]
            except:
                rr = None

            pkg = Package.Package({
                Package.NAME_KEY: name,
                Package.VERSION_KEY: version,