Skip to content

Commit

Permalink
repo2solv: no longer use "find" to find rpms
Browse files Browse the repository at this point in the history
This commit implements the file tree work needed
for the "plaindir" format. Like with the "find" command,
we do not follow symlinks to directories in recursive
mode.
  • Loading branch information
mlschroe committed Jul 8, 2024
1 parent 1602dc2 commit 5c3047a
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 94 deletions.
1 change: 0 additions & 1 deletion package/libsolv.spec.in
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,6 @@ Group: System/Management
Conflicts: satsolver-tools-obsolete
Obsoletes: satsolver-tools < 0.18
Provides: satsolver-tools = 0.18
Requires: findutils
Requires: libsolv-tools-base = %{version}

%description tools
Expand Down
168 changes: 75 additions & 93 deletions tools/repo2solv.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,111 +119,93 @@ autodetect_repotype(Pool *pool, const char *dir)

#ifdef ENABLE_RPMPKG

static int
plaindir_entry_cmp(const struct dirent **a, const struct dirent **b)
{
return strcmp((*a)->d_name, (*b)->d_name);
}

int
read_plaindir_repo(Repo *repo, const char *dir)
{
Pool *pool = repo->pool;
Repodata *data;
int c;
FILE *fp;
int wstatus;
int fds[2];
pid_t pid;
char *buf = 0;
char *buf_end = 0;
char *bp = 0;
char *rpm;
Queue todo;
Stringpool ss;
struct dirent **namelist;
int nents, i;
Id p, id;
size_t namel, dirl = strlen(dir);
int res = 0;
Id p;
int isfirst = 1;

/* run find command */
if (pipe(fds))
{
perror("pipe");
exit(1);
}
while ((pid = fork()) == (pid_t)-1)
{
if (errno != EAGAIN)
{
perror("fork");
exit(1);
}
sleep(3);
}
if (pid == 0)
{
if (chdir(dir))
{
perror(dir);
_exit(1);
}
close(fds[0]);
if (fds[1] != 1)
{
if (dup2(fds[1], 1) == -1)
{
perror("dup2");
_exit(1);
}
close(fds[1]);
}
if (recursive)
execl("/usr/bin/find", "/usr/bin/find", ".", "-name", ".", "-o", "-name", ".*", "-prune", "-o", "-name", "*.delta.rpm", "-o", "-name", "*.patch.rpm", "-o", "-name", "*.rpm", "-a", "-type", "f", "-print0", (char *)0);
else
execl("/usr/bin/find", "/usr/bin/find", ".", "-maxdepth", "1", "-name", ".", "-o", "-name", ".*", "-prune", "-o", "-name", "*.delta.rpm", "-o", "-name", "*.patch.rpm", "-o", "-name", "*.rpm", "-a", "-type", "f", "-print0", (char *)0);
perror("/usr/bin/find");
_exit(1);
}
close(fds[1]);
if ((fp = fdopen(fds[0], "r")) == 0)
{
perror("fdopen");
exit(1);
}
data = repo_add_repodata(repo, 0);
bp = buf;
while ((c = getc(fp)) != EOF)
{
if (bp == buf_end)
{
size_t len = bp - buf;
buf = solv_realloc(buf, len + 4096);
bp = buf + len;
buf_end = bp + 4096;
queue_init(&todo);
stringpool_init_empty(&ss);
queue_push(&todo, stringpool_str2id(&ss, dir, 1));
while (todo.count) {
id = queue_shift(&todo);
nents = scandir(stringpool_id2str(&ss, id), &namelist, NULL, plaindir_entry_cmp);
if (nents == -1) {
perror(stringpool_id2str(&ss, id));
if (isfirst)
res = 1; /* return error if we cannot read the passed dir */
continue;
}
isfirst = 0;
for (i = 0; i < nents; i++) {
struct stat stb;
char *path;
const char *name = namelist[i]->d_name;
int isrpm = 0;

if (!*name)
continue;
if (*name == '.' && (!name[1] || (name[1] == '.' && !name[2])))
continue;
namel = strlen(name);
if (namel > 4 && !strcmp(name + namel - 4, ".rpm")) {
isrpm = 1;
if (namel >= 10 && (!strcmp(name + namel - 10, ".patch.rpm") || !strcmp(name + namel - 10, ".delta.rpm")))
isrpm = 0;
}
if (!isrpm && !recursive)
continue;
path = pool_tmpjoin(pool, stringpool_id2str(&ss, id), "/", name);
if (lstat(path, &stb)) {
perror(path);
continue;
}
if (S_ISLNK(stb.st_mode)) {
if (stat(path, &stb)) {
perror(path);
continue;
}
*bp++ = c;
if (c)
if (S_ISDIR(stb.st_mode))
continue; /* ignore symlinks to directories */
}
if (S_ISDIR(stb.st_mode)) {
if (recursive)
queue_push(&todo, stringpool_str2id(&ss, path, 1));
continue;
}
if (!S_ISREG(stb.st_mode))
continue;
if (!isrpm)
continue;
bp = buf;
rpm = solv_dupjoin(dir, "/", bp[0] == '.' && bp[1] == '/' ? bp + 2 : bp);
if ((p = repo_add_rpm(repo, rpm, REPO_REUSE_REPODATA|REPO_NO_INTERNALIZE|REPO_NO_LOCATION|(filtered_filelist ? RPM_ADD_FILTERED_FILELIST : 0))) == 0)
if ((p = repo_add_rpm(repo, path, REPO_REUSE_REPODATA|REPO_NO_INTERNALIZE|REPO_NO_LOCATION|(filtered_filelist ? RPM_ADD_FILTERED_FILELIST : 0))) == 0)
{
fprintf(stderr, "%s: %s\n", rpm, pool_errstr(pool));
#if 0
res = 1;
#endif
fprintf(stderr, "%s: %s\n", path, pool_errstr(pool));
continue;
}
else
repodata_set_location(data, p, 0, 0, bp[0] == '.' && bp[1] == '/' ? bp + 2 : bp);
solv_free(rpm);
}
solv_free(buf);
fclose(fp);
while (waitpid(pid, &wstatus, 0) == -1)
{
if (errno == EINTR)
continue;
perror("waitpid");
exit(1);
}
if (wstatus)
{
fprintf(stderr, "find: exit status %d\n", (wstatus >> 8) | (wstatus & 255) << 8);
#if 0
res = 1;
#endif
}
repodata_set_location(data, p, 0, 0, path + dirl + 1);
}
for (i = 0; i < nents; i++)
free(namelist[i]);
free(namelist);
}
queue_free(&todo);
stringpool_free(&ss);
repo_internalize(repo);
return res;
}
Expand Down

0 comments on commit 5c3047a

Please sign in to comment.