from yum.plugins import TYPE_CORE from os import walk, path, fstat requires_api_version = '2.3' plugin_type = (TYPE_CORE,) VERBOSE_DEBUGLEVEL = 3 def _stat_ino_fp(fp): """ Get the inode number from file descriptor """ return fstat(fp.fileno()).st_ino def get_file_list(rpmpath): """ Enumerate all files in a directory """ for root, _, files in walk(rpmpath): for f in files: yield path.join(root, f) def for_each_file(files, cb, m='rb'): """ Open each file with mode specified in `m` and invoke `cb` on each of the file objects """ if not files or not cb: return [] ret = [] for f in files: with open(f, m) as fp: ret.append(cb(fp)) return ret def do_detect_copy_up(files): """ Open the files first R/O, then R/W and count unique inode numbers """ num_files = len(files) lower = for_each_file(files, _stat_ino_fp, 'rb') upper = for_each_file(files, _stat_ino_fp, 'ab') diff = set(lower + upper) return len(diff) - num_files def init_hook(conduit): rpmdb_path = conduit._base.rpmdb._rpmdbpath try: files = list(get_file_list(rpmdb_path)) copied_num = do_detect_copy_up(files) conduit.info(VERBOSE_DEBUGLEVEL, "ovl: Copying up (%i) files from OverlayFS lower layer" % copied_num) except Exception as e: conduit.error(1, "ovl: Error while doing RPMdb copy-up:\n%s" % e)