ALT Linux Team development discussions
 help / color / mirror / Atom feed
* [devel] librpm payload
@ 2005-09-02 20:14 Alexey Tourbin
  2005-09-02 21:00 ` Dmitry V. Levin
  0 siblings, 1 reply; 9+ messages in thread
From: Alexey Tourbin @ 2005-09-02 20:14 UTC (permalink / raw)
  To: devel

[-- Attachment #1: Type: text/plain, Size: 352 bytes --]

Есть ли в librpm API, которое позволяет получить доступ к содержимому
payload без распаковки архива?  То есть мне нужна "прозрачная"
распаковка gzdio и доступ к файлам внутри cpio.  Задача: считать первые
4096 байтов каждого файла (без распаковки).  Скормить считанные байты в
libmagic.  То есть определение типа файлов внутри rpm без распаковки.

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [devel] librpm payload
  2005-09-02 20:14 [devel] librpm payload Alexey Tourbin
@ 2005-09-02 21:00 ` Dmitry V. Levin
  2005-09-05  3:43   ` [devel] " Alexey Tourbin
  0 siblings, 1 reply; 9+ messages in thread
From: Dmitry V. Levin @ 2005-09-02 21:00 UTC (permalink / raw)
  To: ALT Devel discussion list

[-- Attachment #1: Type: text/plain, Size: 781 bytes --]

On Sat, Sep 03, 2005 at 12:14:56AM +0400, Alexey Tourbin wrote:
> Есть ли в librpm API, которое позволяет получить доступ к содержимому
> payload без распаковки архива?  То есть мне нужна "прозрачная"
> распаковка gzdio и доступ к файлам внутри cpio.  Задача: считать первые
> 4096 байтов каждого файла (без распаковки).  Скормить считанные байты в
> libmagic.  То есть определение типа файлов внутри rpm без распаковки.

librpmio может предоставить cpio-архив в виде обычного потока, для
которого, кажется, применимы операции типа fsetpos(3).  Но поскольку этот
cpio-архив на практике запакован, прозрачной распаковки всё равно не
миновать.  Считать первые N байт каждого файла этого cpio-потока librpmio
вряд ли поможет, лучше поискать другие средства.


-- 
ldv

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [devel] Re: librpm payload
  2005-09-02 21:00 ` Dmitry V. Levin
@ 2005-09-05  3:43   ` Alexey Tourbin
  2005-09-05  9:09     ` Sergey Vlasov
  2005-09-11 17:06     ` Alexey Tourbin
  0 siblings, 2 replies; 9+ messages in thread
From: Alexey Tourbin @ 2005-09-05  3:43 UTC (permalink / raw)
  To: ALT Devel discussion list


[-- Attachment #1.1: Type: text/plain, Size: 688 bytes --]

On Sat, Sep 03, 2005 at 01:00:07AM +0400, Dmitry V. Levin wrote:
> librpmio может предоставить cpio-архив в виде обычного потока, для
> которого, кажется, применимы операции типа fsetpos(3).  Но поскольку этот
> cpio-архив на практике запакован, прозрачной распаковки всё равно не
> миновать.  Считать первые N байт каждого файла этого cpio-потока librpmio
> вряд ли поможет, лучше поискать другие средства.

Как читать поток cpio, я разобрался.  Теперь дальше, как парсить cpio?
У него какой-то хитрый padding (см. TODO).  Как libmagic подключить --
вроде ясно, magic_buffer().

Что-то такое есть в rpm-4_0-4.0.4/lib/{cpio,fsm}.{c,h}, но им
воспользоваться очень проблемно.

[-- Attachment #1.2: rpmfile.c --]
[-- Type: text/plain, Size: 2349 bytes --]

// gcc -Wall -I/usr/include/rpm rpmfile.c -lrpm -o rpmfile
#include <error.h>
#include <stdlib.h>
#include <string.h>
#include <rpmlib.h>

struct cpio_header
{
	char magic[6];
	char inode[8];
	char mode[8];
	char uid[8];
	char gid[8];
	char nlink[8];
	char mtime[8];
	char filesize[8];
	char dev_major[8];
	char dev_minor[8];
	char rdev_major[8];
	char rdev_minor[8];
	char namesize[8];
	char checksum[8];
};

int num8(char *s)
{
	char c = s[8];
	s[8] = 0;
	int n = strtoul(s, NULL, 16);
	s[8] = c;
	return n;
}

FD_t open_payload(const char *fname)
{
	FD_t fd = Fopen(fname, "r.ufdio");
	if (Ferror(fd))
		error(1, 0, "%s: %s", fname, Fstrerror(fd));
	
	Header h; int isSource;
	if (rpmReadPackageHeader(fd, &h, &isSource, NULL, NULL))
		error(1, 0, "%s: %s", fname, "bad RPM header");
	
	char *method;
	if (headerGetEntry(h, RPMTAG_PAYLOADCOMPRESSOR, NULL, (void **) &method, NULL))
		method = "gzip";
	
	char *type = "r";
	if (strcmp(method, "gzip") == 0)
		type = "r.gzdio";
	if (strcmp(method, "bzip2") == 0)
		type = "r.bzdio";

	FD_t zfd = Fdopen(fd, type);
	if (Ferror(zfd))
		error(1, 0, "%s: %s", fname, Fstrerror(zfd));
	if (fd != zfd)
		Fclose(fd);

	return zfd;
}

void rpmfile(const char *fname)
{
	FD_t fd = open_payload(fname);
	
	while (1) {
		size_t n;
		struct cpio_header h;
		n = Fread(&h, sizeof(h), 1, fd);
		if (n != 1)
			error(1, 0, "%s: %s", fname, "bad cpio header");
		if (strncmp(h.magic, "070701", 6))
			error(1, 0, "%s: %s", fname, "bad cpio magic");

		char path[PATH_MAX];
		int len = num8(h.namesize);
		n = Fread(path, len, 1, fd);
		if (n != 1)
			error(1, 0, "%s: %s", fname, "bad cpio namesize");
		if (strcmp(path, "TRAILER!!!") == 0)
			break;

		char buf[4096];
		int size = num8(h.filesize);
		int toread = (size > sizeof(buf)) ? sizeof(buf) : size;
		int toseek = size - toread;
		n = 1;
		if (toread)
			n = Fread(buf, toread, 1, fd);
		if (toseek)
			n += Fseek(fd, toseek, SEEK_CUR);
		if (n != 1)
			error(1, 0, "%s: %s", fname, "bad cpio filesize");
			
		int mode = num8(h.mode);
		printf("%s\t%s\t0%o\n", fname, path, mode);
		
		/* TODO: zero padded? how do I seek ? */
		break;
	}
	Fclose(fd);
}

int main(int argc, char *argv[])
{
	while (--argc > 0)
		rpmfile(*++argv);
	return 0;
}

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [devel] Re: librpm payload
  2005-09-05  3:43   ` [devel] " Alexey Tourbin
@ 2005-09-05  9:09     ` Sergey Vlasov
  2005-09-11 17:06     ` Alexey Tourbin
  1 sibling, 0 replies; 9+ messages in thread
From: Sergey Vlasov @ 2005-09-05  9:09 UTC (permalink / raw)
  To: ALT Devel discussion list

[-- Attachment #1: Type: text/plain, Size: 1203 bytes --]

On Mon, Sep 05, 2005 at 07:43:57AM +0400, Alexey Tourbin wrote:
> On Sat, Sep 03, 2005 at 01:00:07AM +0400, Dmitry V. Levin wrote:
> > librpmio может предоставить cpio-архив в виде обычного потока, для
> > которого, кажется, применимы операции типа fsetpos(3).  Но поскольку этот
> > cpio-архив на практике запакован, прозрачной распаковки всё равно не
> > миновать.  Считать первые N байт каждого файла этого cpio-потока librpmio
> > вряд ли поможет, лучше поискать другие средства.
> 
> Как читать поток cpio, я разобрался.  Теперь дальше, как парсить cpio?

Его даже ядро читать умеет (в initramfs) ;)

> У него какой-то хитрый padding (см. TODO).  Как libmagic подключить --
> вроде ясно, magic_buffer().

#define N_ALIGN(len) ((((len) + 1) & ~3) + 2)
...
	parse_header(collected);
	/* тут this_header уже продвинут за struct cpio_header */
	next_header = this_header + N_ALIGN(name_len) + body_len;
	next_header = (next_header + 3) & ~3;

Правда, после SkipIt (пропуск до позиции next_header) там есть ещё
Reset:

static int __init do_reset(void)
{
	while(count && *victim == '\0')
		eat(1);
	if (count && (this_header & 3))
		error("broken padding");
	return 1;
}

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [devel] Re: librpm payload
  2005-09-05  3:43   ` [devel] " Alexey Tourbin
  2005-09-05  9:09     ` Sergey Vlasov
@ 2005-09-11 17:06     ` Alexey Tourbin
  2005-09-11 22:14       ` Dmitry V. Levin
  1 sibling, 1 reply; 9+ messages in thread
From: Alexey Tourbin @ 2005-09-11 17:06 UTC (permalink / raw)
  To: ALT Devel discussion list


[-- Attachment #1.1: Type: text/plain, Size: 1814 bytes --]

On Mon, Sep 05, 2005 at 07:43:57AM +0400, Alexey Tourbin wrote:
> Как читать поток cpio, я разобрался.  Теперь дальше, как парсить cpio?
> У него какой-то хитрый padding (см. TODO).  Как libmagic подключить --
> вроде ясно, magic_buffer().
> 
> Что-то такое есть в rpm-4_0-4.0.4/lib/{cpio,fsm}.{c,h}, но им
> воспользоваться очень проблемно.

Нет, задолбало на Си писать.  Это контрпродуктивно.  Можно что-нибудь
сделать, а можно сидеть и пейсать на Си.  Ну его в баню.

Написал на шелле, с кешированием для каталогов.  Для робота это важно --
очень долго (с распаковкой всех rpm'ов) только один раз будет работать.

$ ./rpmfile -h
Usage:
    rpmfile [-h] [*FILE*...] [*DIR*...]

$ ./rpmfile ~/build/repo/i586/RPMS.hasher/qa-robot-0.2-alt1.noarch.rpm
/usr/bin/bugs	100755	Bourne shell script text executable
/usr/bin/csv2tab	100755	perl script text executable
...
$ ./rpmfile ~/build/repo/i586/RPMS.hasher |sort -t$'\t' -k1,1 -u
libsqlite3	/usr/lib/libsqlite3.so.0	120777	symbolic link to `libsqlite3.so.0.8.6'
libsqlite3-devel	/usr/include/sqlite3.h	100644	ASCII C program text
...
$

То есть если "дампить" каталог, то впереди добавляется ещё подно поле --
имя пакета.  Правильнее было бы добавлять не имя пакета, а собственно
имя файла, но мне сейчас нужнее имя пакета.

А кеширование работает так:

$ rm -rf ~/tmp/tmp
$ mkdir -p ~/tmp/tmp
$ time workdir=~/tmp/tmp ./rpmfile ~/build/repo/i586/RPMS.hasher >/dev/null
workdir=~/tmp/tmp ./rpmfile ~/build/repo/i586/RPMS.hasher > /dev/null  16,70s user 4,81s system 95% cpu 22,606 total
$ time workdir=~/tmp/tmp ./rpmfile ~/build/repo/i586/RPMS.hasher >/dev/null
workdir=~/tmp/tmp ./rpmfile ~/build/repo/i586/RPMS.hasher > /dev/null  1,46s user 0,22s system 99% cpu 1,685 total
$

Трюк с paste(1) -- по моему, красиво. :)

[-- Attachment #1.2: rpmfile --]
[-- Type: text/plain, Size: 1734 bytes --]

#!/bin/sh -ef
export LC_ALL=C

dump_file()
{
	rpm -qp --qf '[%{FILENAMES}\t%{FILEMODES:octal}\n]' "$@" >files
	if [ -d d ]; then chmod -Rf u+rwX d; rm -rf d; fi
	rpm2cpio "$@" |(mkdir d; cd d; cpio -idmu --quiet)
	awk -F'\t' '{printf"d/%s\0",$1}' files |xargs -r0 file -b >types
	paste files types
}

dump_dir()
{
	local d="$1"; shift
	packages "$d" >packages
	sort -t$'\t' -o packages -u -k1,1 packages
	mkdir -p c
	while IFS=$'\t' read p v f _; do
		b="${f%%.rpm}"
		[ -f c/"$b" ] || dump_file "$d/$f" >c/"$b"
		awk -v p="$p" '{print p"\t"$0}' c/"$b"
	done <packages
}

while getopts h opt; do
	case "$opt" in
		h) pod2usage --exit=0 "$0"; exit 0 ;;
		*) pod2usage --exit=2 "$0"; exit 2 ;;
	esac
done
shift "$((OPTIND-1))"

if [ -z "$workdir" ]; then
	atexit() { rc=$?; trap - EXIT; rm -rf "$workdir"; exit $rc; }
	workdir="$(mktemp -d -t "${0##*/}.XXXXXXXX")"
	trap atexit EXIT HUP INT QUIT PIPE TERM
	export workdir
fi

if [ -z "$*" ]; then
	: ${sisyphus:=/raid/ALT/Sisyphus}
	set -- "$sisyphus"/files/i586/RPMS
fi

for arg; do
	arg="$(readlink -ev "${arg:?}")"
	cd "${workdir:?}"
	if [ -f "$arg" ]; then
		dump_file "$arg"
	else
		dump_dir "$arg"
	fi
	cd -
done

: <<'__EOF__'

=head1	NAME

rpmfile - list file modes and types in RPM packages

=head1	SYNOPSIS

B<rpmfile> [B<-h>] [I<FILE>...] [I<DIR>...]

=head1	AUTHOR

Written by Alexey Tourbin <at@altlinux.org>.

=head1	COPYING

Copyright (c) 2005 Alexey Tourbin, ALT Linux Team.

This is free software; you can redistribute it and/or modify it under the terms
of the GNU General Public License as published by the Free Software Foundation;
either version 2 of the License, or (at your option) any later version.

=head1	SEE ALSO

rpm(8),
rpm2cpio(8),
file(1)

=cut

__EOF__

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [devel] Re: librpm payload
  2005-09-11 17:06     ` Alexey Tourbin
@ 2005-09-11 22:14       ` Dmitry V. Levin
  2005-09-12  3:48         ` Alexey Tourbin
  0 siblings, 1 reply; 9+ messages in thread
From: Dmitry V. Levin @ 2005-09-11 22:14 UTC (permalink / raw)
  To: ALT Devel discussion list

[-- Attachment #1: Type: text/plain, Size: 801 bytes --]

On Sun, Sep 11, 2005 at 09:06:44PM +0400, Alexey Tourbin wrote:
> On Mon, Sep 05, 2005 at 07:43:57AM +0400, Alexey Tourbin wrote:
> > Как читать поток cpio, я разобрался.  Теперь дальше, как парсить cpio?
> > У него какой-то хитрый padding (см. TODO).  Как libmagic подключить --
> > вроде ясно, magic_buffer().
> > 
> > Что-то такое есть в rpm-4_0-4.0.4/lib/{cpio,fsm}.{c,h}, но им
> > воспользоваться очень проблемно.
> 
> Нет, задолбало на Си писать.  Это контрпродуктивно.  Можно что-нибудь
> сделать, а можно сидеть и пейсать на Си.  Ну его в баню.
> 
> Написал на шелле, с кешированием для каталогов.  Для робота это важно --
> очень долго (с распаковкой всех rpm'ов) только один раз будет работать.

Да, красиво, мне понравилось.  Запакуй куда-нибудь, пожалуйста.


-- 
ldv

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [devel] Re: librpm payload
  2005-09-11 22:14       ` Dmitry V. Levin
@ 2005-09-12  3:48         ` Alexey Tourbin
  2005-09-12 10:28           ` Dmitry V. Levin
  0 siblings, 1 reply; 9+ messages in thread
From: Alexey Tourbin @ 2005-09-12  3:48 UTC (permalink / raw)
  To: ALT Devel discussion list

[-- Attachment #1: Type: text/plain, Size: 809 bytes --]

On Mon, Sep 12, 2005 at 02:14:10AM +0400, Dmitry V. Levin wrote:
> > Написал на шелле, с кешированием для каталогов.  Для робота это важно --
> > очень долго (с распаковкой всех rpm'ов) только один раз будет работать.
> 
> Да, красиво, мне понравилось.  Запакуй куда-нибудь, пожалуйста.

Посмотрел, что он мне тут ночью сделал.  Есть грабли с %ghost файлами,
с неправильными правами доступа на каталог (когда в каталог "не пускают")
и с девайсами.  Похоже, придется использовать fakeroot.

Запакую в qa-robot-0.3.  Он же использует /usr/bin/packages.

	local d="$1"; shift
	packages "$d" >packages
	sort -t$'\t' -o packages -u -k1,1 packages
	while IFS=$'\t' read p v f _; do

Если в каталоге $d есть дупы, то будут из одноименных пакетов будет
обработан только один, с наибольшей версией.

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [devel] Re: librpm payload
  2005-09-12  3:48         ` Alexey Tourbin
@ 2005-09-12 10:28           ` Dmitry V. Levin
  2005-09-13  8:51             ` [devel] rpmfile Alexey Tourbin
  0 siblings, 1 reply; 9+ messages in thread
From: Dmitry V. Levin @ 2005-09-12 10:28 UTC (permalink / raw)
  To: ALT Devel discussion list

[-- Attachment #1: Type: text/plain, Size: 565 bytes --]

On Mon, Sep 12, 2005 at 07:48:30AM +0400, Alexey Tourbin wrote:
> Посмотрел, что он мне тут ночью сделал.  Есть грабли с %ghost файлами,
> с неправильными правами доступа на каталог (когда в каталог "не пускают")
> и с девайсами.  Похоже, придется использовать fakeroot.

Когда в каталг не пускают, можно использовать chmod.

[...]
> Если в каталоге $d есть дупы, то будут из одноименных пакетов будет
> обработан только один, с наибольшей версией.

Это не всегда удобно.  Может, лучше по дереву на бинарный пакет, чтобы
не пересекались?


-- 
ldv

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [devel] rpmfile
  2005-09-12 10:28           ` Dmitry V. Levin
@ 2005-09-13  8:51             ` Alexey Tourbin
  0 siblings, 0 replies; 9+ messages in thread
From: Alexey Tourbin @ 2005-09-13  8:51 UTC (permalink / raw)
  To: ALT Devel discussion list

[-- Attachment #1: Type: text/plain, Size: 1829 bytes --]

On Mon, Sep 12, 2005 at 02:28:57PM +0400, Dmitry V. Levin wrote:
> > Посмотрел, что он мне тут ночью сделал.  Есть грабли с %ghost файлами,
> > с неправильными правами доступа на каталог (когда в каталог "не пускают")
> > и с девайсами.  Похоже, придется использовать fakeroot.
> Когда в каталг не пускают, можно использовать chmod.

chmod проще всего сделать рекурсивно, но тогда может частично измениться
описание файла, т.к. при чмоде "слетает" suid/sgid.  С fakeroot пока
получается лучше всего.

at@solemn ~/.cmdcache 4 $ grep -r setuid rpmfile
rpmfile/i327820s28180m1099489621:/usr/sbin/suexec       104711  setuid ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.18, dynamically linked (uses shared libs), stripped
rpmfile/i275202s28073547m1084879330:/usr/lib/erlang/erts-5.3/src/setuid_socket_wrap.c   100644  ASCII C program text
rpmfile/i328102s346373m1094052150:/usr/sbin/exim-mysql  104711  setuid ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.18, dynamically linked (uses shared libs), stripped
rpmfile/i327778s499335m1093862089:/usr/lib/amanda/dumper        104710  setuid ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.18, dynamically linked (uses shared libs), stripped
rpmfile/i327778s499335m1093862089:/usr/lib/amanda/planner       104710  setuid ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.18, dynamically linked (uses shared libs), stripped
rpmfile/i327778s499335m1093862089:/usr/sbin/amcheck     104710  setuid ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.18, dynamically linked (uses shared libs), stripped
^C
at@solemn ~/.cmdcache 4 $

> Это не всегда удобно.  Может, лучше по дереву на бинарный пакет, чтобы
> не пересекались?

Ok.

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2005-09-13  8:51 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-09-02 20:14 [devel] librpm payload Alexey Tourbin
2005-09-02 21:00 ` Dmitry V. Levin
2005-09-05  3:43   ` [devel] " Alexey Tourbin
2005-09-05  9:09     ` Sergey Vlasov
2005-09-11 17:06     ` Alexey Tourbin
2005-09-11 22:14       ` Dmitry V. Levin
2005-09-12  3:48         ` Alexey Tourbin
2005-09-12 10:28           ` Dmitry V. Levin
2005-09-13  8:51             ` [devel] rpmfile Alexey Tourbin

ALT Linux Team development discussions

This inbox may be cloned and mirrored by anyone:

	git clone --mirror http://lore.altlinux.org/devel/0 devel/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 devel devel/ http://lore.altlinux.org/devel \
		devel@altlinux.org devel@altlinux.ru devel@lists.altlinux.org devel@lists.altlinux.ru devel@linux.iplabs.ru mandrake-russian@linuxteam.iplabs.ru sisyphus@linuxteam.iplabs.ru
	public-inbox-index devel

Example config snippet for mirrors.
Newsgroup available over NNTP:
	nntp://lore.altlinux.org/org.altlinux.lists.devel


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git