/* pristines.c: * * vim:smartindent ts=8:sts=2:sta:et:ai:shiftwidth=2 **************************************************************** * Copyright (C) 2003 Tom Lord * * See the file "COPYING" for further information about * the copyright and warranty status of this work. */ #include "hackerlab/bugs/panic.h" #include "hackerlab/bugs/exception.h" #include "hackerlab/char/char-class.h" #include "hackerlab/char/str.h" #include "hackerlab/fs/file-names.h" #include "hackerlab/vu/safe.h" #include "libfsutils/dir-listing.h" #include "libfsutils/ensure-dir.h" #include "libfsutils/tmp-files.h" #include "libfsutils/rmrf.h" #include "libfsutils/copy-file.h" #include "libarch/invent.h" #include "libarch/build-revision.h" #include "libarch/inode-sig.h" #include "libarch/namespace.h" #include "libarch/pristines.h" #include "libarch/project-tree.h" static t_uchar * arch_pristine_loc (t_uchar * archive, t_uchar * revision); void arch_make_pristine (arch_project_tree_t * tree, t_uchar * archive, t_uchar * revision) { rel_table inventory = 0; t_uchar * tmp_pristine = 0; t_uchar * version = arch_parse_package_name (arch_ret_package_version, 0, revision); t_uchar * fqversion = arch_fully_qualify (archive, version); arch_patch_id * patch_id = arch_patch_id_new_archive (archive, revision); lim_free (0, version); inventory = arch_source_inventory (tree, 1, 0, 0); tmp_pristine = talloc_tmp_file_name (talloc_context, tree->root, ",,pristine"); rmrf_file (tmp_pristine); safe_mkdir (tmp_pristine, 0777); copy_file_list (tmp_pristine, tree->root, inventory); arch_set_tree_version (tmp_pristine, patch_id); arch_install_pristine (tree, archive, revision, tmp_pristine); rel_free_table (inventory); talloc_free (tmp_pristine); lim_free (0, fqversion); talloc_free (patch_id); } void arch_add_pristine (int chatter_fd, arch_project_tree_t * tree, struct arch_archive * arch, t_uchar * archive, t_uchar * revision) { t_uchar * tmp_path = 0; tmp_path = talloc_tmp_file_name (talloc_context, tree->root, ",,new-pristine"); safe_mkdir (tmp_path, 0777); arch_build_revision (tmp_path, arch, archive, revision, tree); arch_install_pristine (tree, archive, revision, tmp_path); talloc_free (tmp_path); } t_uchar * arch_pristine_loc (t_uchar * archive, t_uchar * revision) { t_uchar * category = 0; t_uchar * branch = 0; t_uchar * version = 0; t_uchar * answer = 0; invariant (arch_valid_package_name (revision, arch_no_archive, arch_req_patch_level, 0)); invariant (arch_valid_archive_name (archive)); category = arch_parse_package_name (arch_ret_category, 0, revision); branch = arch_parse_package_name (arch_ret_package, 0, revision); version = arch_parse_package_name (arch_ret_package_version, 0, revision); answer = str_alloc_cat_many (0, "{arch}/++pristine-trees/", "unlocked", "/", category, "/", branch, "/", version, "/", archive, "/", revision, str_end); lim_free (0, category); lim_free (0, branch); lim_free (0, version); return answer; } void arch_install_pristine (arch_project_tree_t * tree, t_uchar * archive, t_uchar * revision, t_uchar * source) { t_uchar * loc = 0; t_uchar * path = 0; arch_project_tree_t * source_tree; arch_patch_id * patch_id = arch_patch_id_new_archive (archive, revision); source_tree = arch_project_tree_new (talloc_context, source); arch_snap_inode_sig (source_tree, patch_id); loc = arch_pristine_loc (archive, revision); path = file_name_in_vicinity (0, tree->root, loc); ensure_directory_exists (path); rmrf_file (path); safe_rename (source, path); arch_project_tree_delete (source_tree); lim_free (0, loc); lim_free (0, path); talloc_free (patch_id); } rel_table arch_pristines (t_uchar * tree_root, t_uchar * archive_limit, t_uchar * limit) { int here_fd; int errn; struct stat statb; t_uchar * category = 0; t_uchar * branch = 0; t_uchar * version = 0; t_uchar * revision = 0; t_uchar * unlocked_in_this_tree_path = 0; rel_table answer = 0; int x; here_fd = safe_open (".", O_RDONLY, 0); if (archive_limit) invariant (arch_valid_archive_name (archive_limit)); if (limit) { invariant (arch_valid_package_name (limit, arch_no_archive, arch_req_category, 1)); category = arch_parse_package_name (arch_ret_category, 0, limit); if (arch_valid_package_name (limit, arch_no_archive, arch_req_package, 1)) { branch = arch_parse_package_name (arch_ret_package, 0, limit); if (arch_valid_package_name (limit, arch_no_archive, arch_req_version, 1)) { version = arch_parse_package_name (arch_ret_package_version, 0, limit); if (arch_valid_package_name (limit, arch_no_archive, arch_req_patch_level, 0)) { revision = limit; } } } } unlocked_in_this_tree_path = file_name_in_vicinity (0, tree_root, "{arch}/++pristine-trees/unlocked"); for (x=0; x!=1; x=1) { if (vu_chdir (&errn, unlocked_in_this_tree_path)) continue; { rel_table maybe_categories = 0; int c; if (category) { rel_add_records (&maybe_categories, rel_make_record (category, 0), 0); } else { maybe_categories = directory_files ("."); } for (c = 0; c < rel_n_records (maybe_categories); ++c) { if (arch_valid_package_name (maybe_categories[c][0], arch_no_archive, arch_req_category, 0) && (!vu_lstat (&errn, maybe_categories[c][0], &statb) && S_ISDIR (statb.st_mode))) { rel_table maybe_branches = 0; int b; safe_chdir (maybe_categories[c][0]); if (branch) { rel_add_records (&maybe_branches, rel_make_record (branch, 0), 0); } else { maybe_branches = directory_files ("."); } for (b = 0; b < rel_n_records (maybe_branches); ++b) { if (arch_valid_package_name (maybe_branches[b][0], arch_no_archive, arch_req_package, 0) && (!vu_lstat (&errn, maybe_branches[b][0], &statb) && S_ISDIR (statb.st_mode))) { rel_table maybe_versions = 0; int v; safe_chdir (maybe_branches[b][0]); if (version) { rel_add_records (&maybe_versions, rel_make_record (version, 0), 0); } else { maybe_versions = directory_files ("."); } for (v = 0; v < rel_n_records (maybe_versions); ++v) { if (arch_valid_package_name (maybe_versions[v][0], arch_no_archive, arch_req_version, 0) && (!vu_lstat (&errn, maybe_versions[v][0], &statb) && S_ISDIR (statb.st_mode))) { rel_table maybe_archives = 0; int a; safe_chdir (maybe_versions[v][0]); if (archive_limit) { rel_add_records (&maybe_archives, rel_make_record (archive_limit, 0), 0); } else { maybe_archives = directory_files ("."); } for (a = 0; a < rel_n_records (maybe_archives); ++a) { if (arch_valid_archive_name (maybe_archives[a][0]) && (!vu_lstat (&errn, maybe_archives[a][0], &statb) && S_ISDIR (statb.st_mode))) { rel_table maybe_revisions = 0; int r; safe_chdir (maybe_archives[a][0]); if (revision) { rel_add_records (&maybe_revisions, rel_make_record (revision, 0), 0); } else { maybe_revisions = directory_files ("."); } for (r = 0; r < rel_n_records (maybe_revisions); ++r) { if (arch_valid_package_name (maybe_revisions[r][0], arch_no_archive, arch_req_patch_level, 0) && (!vu_lstat (&errn, maybe_revisions[r][0], &statb) && S_ISDIR (statb.st_mode))) { t_uchar * fqr = 0; fqr = arch_fully_qualify (maybe_archives[a][0], maybe_revisions[r][0]); rel_add_records (&answer, rel_make_record (fqr, 0), 0); lim_free (0, fqr); } } safe_chdir (".."); rel_free_table (maybe_revisions); } } safe_chdir (".."); rel_free_table (maybe_archives); } } safe_chdir (".."); rel_free_table (maybe_versions); } } safe_chdir (".."); rel_free_table (maybe_branches); } } safe_fchdir (here_fd); rel_free_table (maybe_categories); } } arch_sort_table_by_name_field (0, answer, 0); safe_close (here_fd); lim_free (0, category); lim_free (0, branch); lim_free (0, version); lim_free (0, revision); lim_free (0, unlocked_in_this_tree_path); return answer; } arch_project_tree_t * arch_find_pristine (arch_project_tree_t * tree, arch_patch_id * revision, enum arch_pristine_search_scope scope) { const t_uchar * unlocked_pristine_stem = "{arch}/++pristine-trees/unlocked"; t_uchar * category = 0; t_uchar * branch = 0; t_uchar * unlocked_relpath = 0; t_uchar * unlocked_in_this_tree_path = 0; arch_project_tree_t * answer = NULL; invariant (arch_valid_package_name (arch_patch_id_patch_id (revision), arch_req_archive, arch_req_patch_level, 0)); category = arch_parse_package_name (arch_ret_category, 0, arch_patch_id_patch_id (revision)); branch = arch_parse_package_name (arch_ret_package, 0, arch_patch_id_patch_id (revision)); unlocked_relpath = str_alloc_cat_many (0, unlocked_pristine_stem, "/", category, "/", branch, "/", arch_patch_id_version (revision), "/", arch_patch_id_patch_id (revision), str_end); unlocked_in_this_tree_path = file_name_in_vicinity (0, tree->root, unlocked_relpath); if ((scope == arch_tree_pristine_search) && !safe_access (unlocked_in_this_tree_path, F_OK)) { answer = arch_project_tree_new_exact (talloc_context, unlocked_in_this_tree_path); } else { t_uchar * tree_root_dir = 0; rel_table sibling_files = 0; rel_table sibling_paths = 0; int x; if (scope == arch_cache_dir_pristine_search) tree_root_dir = str_save (0, tree->root); else { tree_root_dir = file_name_directory_file (0, tree->root); if (!tree_root_dir) tree_root_dir = str_save (0, "."); } sibling_files = directory_files (tree_root_dir); if (scope != arch_tree_pristine_search) { for (x = 0; x < rel_n_records (sibling_files); ++x) { if (char_is_alnum (sibling_files[x][0][0])) { int ign; struct stat stat_buf; t_uchar * path = 0; path = file_name_in_vicinity (0, tree_root_dir, sibling_files[x][0]); if (!vu_lstat (&ign, path, &stat_buf) && S_ISDIR (stat_buf.st_mode)) { rel_add_records (&sibling_paths, rel_make_record (path, 0), 0); } lim_free (0, path); } } for (x = 0; !answer && (x < rel_n_records (sibling_paths)); ++x) { t_uchar * unlocked_sibling_path = 0; int errno = 0; unlocked_sibling_path = file_name_in_vicinity (0, sibling_paths[x][0], unlocked_relpath); if (!vu_access (&errno, unlocked_sibling_path, F_OK)) { answer = arch_project_tree_new_exact (talloc_context, unlocked_sibling_path); } lim_free (0, unlocked_sibling_path); } } lim_free (0, tree_root_dir); rel_free_table (sibling_files); rel_free_table (sibling_paths); } lim_free (0, category); lim_free (0, branch); lim_free (0, unlocked_relpath); lim_free (0, unlocked_in_this_tree_path); if (answer) { if (!arch_valid_inode_sig (answer, arch_patch_id_archive (revision), arch_patch_id_revision (revision))) { safe_printfmt (2, "corrupt pristine (failed inode signature validation)\n revision: %s\n directory %s\n. Removing this pristine.\n", arch_patch_id_patch_id (revision), answer->root); rmrf_file (answer->root); arch_project_tree_delete (answer); answer = NULL; } } return answer; } /* tag: Tom Lord Wed May 21 18:53:22 2003 (pristines.c) */