Example #1
0
/* Loop though files in a package and perform full file property checking. */
int check_pkg_full(alpm_pkg_t *pkg)
{
	const char *root, *pkgname;
	size_t errors = 0;
	size_t rootlen;
	char filepath[PATH_MAX];
	struct archive *mtree;
	struct archive_entry *entry = NULL;
	size_t file_count = 0;
	const alpm_list_t *lp;

	root = alpm_option_get_root(config->handle);
	rootlen = strlen(root);
	if(rootlen + 1 > PATH_MAX) {
		/* we are in trouble here */
		pm_printf(ALPM_LOG_ERROR, _("path too long: %s%s\n"), root, "");
		return 1;
	}
	strcpy(filepath, root);

	pkgname = alpm_pkg_get_name(pkg);
	mtree = alpm_pkg_mtree_open(pkg);
	if(mtree == NULL) {
		/* TODO: check error to confirm failure due to no mtree file */
		if(!config->quiet) {
			printf(_("%s: no mtree file\n"), pkgname);
		}
		return 0;
	}

	while(alpm_pkg_mtree_next(pkg, mtree, &entry) == ARCHIVE_OK) {
		struct stat st;
		const char *path = archive_entry_pathname(entry);
		mode_t type;
		size_t file_errors = 0;
		int backup = 0;

		/* strip leading "./" from path entries */
		if(path[0] == '.' && path[1] == '/') {
			path += 2;
		}

		if(strcmp(path, ".INSTALL") == 0) {
			char filename[PATH_MAX];
			snprintf(filename, PATH_MAX, "%slocal/%s-%s/install",
					alpm_option_get_dbpath(config->handle) + 1,
					pkgname, alpm_pkg_get_version(pkg));
			archive_entry_set_pathname(entry, filename);
			path = archive_entry_pathname(entry);
		} else if(strcmp(path, ".CHANGELOG") == 0) {
			char filename[PATH_MAX];
			snprintf(filename, PATH_MAX, "%slocal/%s-%s/changelog",
					alpm_option_get_dbpath(config->handle) + 1,
					pkgname, alpm_pkg_get_version(pkg));
			archive_entry_set_pathname(entry, filename);
			path = archive_entry_pathname(entry);
		} else if(*path == '.') {
			continue;
		}

		file_count++;

		if(rootlen + 1 + strlen(path) > PATH_MAX) {
			pm_printf(ALPM_LOG_WARNING, _("path too long: %s%s\n"), root, path);
			continue;
		}
		strcpy(filepath + rootlen, path);

		if(check_file_exists(pkgname, filepath, &st) == 1) {
			errors++;
			continue;
		}

		type = archive_entry_filetype(entry);

		if(type != AE_IFDIR && type != AE_IFREG && type != AE_IFLNK) {
			pm_printf(ALPM_LOG_WARNING, _("file type not recognized: %s%s\n"), root, path);
			continue;
		}

		if(check_file_type(pkgname, filepath, &st, entry) == 1) {
			errors++;
			continue;
		}

		file_errors += check_file_permissions(pkgname, filepath, &st, entry);

		if(type == AE_IFLNK) {
			file_errors += check_file_link(pkgname, filepath, &st, entry);
		}

		/* the following checks are expected to fail if a backup file has been
		   modified */
		for(lp = alpm_pkg_get_backup(pkg); lp; lp = lp->next) {
			alpm_backup_t *bl = lp->data;

			if(strcmp(path, bl->name) == 0) {
				backup = 1;
				break;
			}
		}

		if(type != AE_IFDIR) {
			/* file or symbolic link */
			file_errors += check_file_time(pkgname, filepath, &st, entry, backup);
		}

		if(type == AE_IFREG) {
			/* TODO: these are expected to be changed with backup files */
			file_errors += check_file_size(pkgname, filepath, &st, entry, backup);
			/* file_errors += check_file_md5sum(pkgname, filepath, &st, entry, backup); */
		}

		if(config->quiet && file_errors) {
			printf("%s %s\n", pkgname, filepath);
		}

		errors += (file_errors != 0 ? 1 : 0);
	}

	alpm_pkg_mtree_close(pkg, mtree);

	if(!config->quiet) {
		printf(_n("%s: %jd total file, ", "%s: %jd total files, ",
					(unsigned long)file_count), pkgname, (intmax_t)file_count);
		printf(_n("%jd altered file\n", "%jd altered files\n",
					(unsigned long)errors), (intmax_t)errors);
	}

	return (errors != 0 ? 1 : 0);
}
Example #2
0
/* check filesystem against extra mtree data if available,
 * NOT guaranteed to catch db/filesystem discrepencies */
static int check_file_properties(alpm_pkg_t *pkg)
{
	char path[PATH_MAX], *rel;
	int ret = 0;
	size_t space;
	struct archive *mtree = alpm_pkg_mtree_open(pkg);
	struct archive_entry *entry;

	if(!mtree) {
		pu_ui_warn("%s: mtree data not available (%s)",
				alpm_pkg_get_name(pkg), strerror(errno));
		return require_mtree;
	}

	strncpy(path, alpm_option_get_root(handle), PATH_MAX);
	rel = path + strlen(path);
	space = PATH_MAX - (rel - path);

	while(alpm_pkg_mtree_next(pkg, mtree, &entry) == ARCHIVE_OK) {
		const char *ppath = archive_entry_pathname(entry);
		const char *fpath;
		struct stat buf;

		if(strncmp("./", ppath, 2) == 0) { ppath += 2; }

		if(strcmp(ppath, ".INSTALL") == 0) {
			if((fpath = get_db_path(pkg, "install")) == NULL) {
				continue;
			}
		} else if(strcmp(ppath, ".CHANGELOG") == 0) {
			if((fpath = get_db_path(pkg, "changelog")) == NULL) {
				continue;
			}
		} else if(ppath[0] == '.') {
			continue;
		} else if(skip_noextract && match_noextract(handle, ppath)) {
			continue;
		} else {
			strncpy(rel, ppath, space);
			fpath = path;
		}

		if(lstat(fpath, &buf) != 0) {
			if(errno == ENOENT) {
				eprintf("%s: '%s' missing file\n", alpm_pkg_get_name(pkg), fpath);
			} else {
				pu_ui_warn("%s: '%s' read error (%s)",
						alpm_pkg_get_name(pkg), fpath, strerror(errno));
			}
			ret = 1;
			continue;
		}

		if(cmp_type(pkg, fpath, entry, &buf) != 0) { ret = 1; }

		if(skip_noupgrade && match_noupgrade(handle, ppath)) { continue; }

		if(cmp_mode(pkg, fpath, entry, &buf) != 0) { ret = 1; }
		if(cmp_uid(pkg, fpath, entry, &buf) != 0) { ret = 1; }
		if(cmp_gid(pkg, fpath, entry, &buf) != 0) { ret = 1; }

		if(skip_backups && match_backup(pkg, ppath)) {
			continue;
		}

		if(S_ISLNK(buf.st_mode) && S_ISLNK(archive_entry_mode(entry))) {
			if(cmp_target(pkg, fpath, entry) != 0) { ret = 1; }
		}
		if(!S_ISDIR(buf.st_mode)) {
			if(cmp_mtime(pkg, fpath, entry, &buf) != 0) { ret = 1; }
			if(!S_ISLNK(buf.st_mode)) {
				/* always fails for directories and symlinks */
				if(cmp_size(pkg, fpath, entry, &buf) != 0) { ret = 1; }
			}
		}
	}
	alpm_pkg_mtree_close(pkg, mtree);

	if(!quiet && !ret) {
		eprintf("%s: all files match mtree\n", alpm_pkg_get_name(pkg));
	}

	return ret;
}