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
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,