/* 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)
*/
syntax highlighted by Code2HTML, v. 0.9.1