Wed Jan 12 00:26:33 2011 UTC ()
Update "rpm2pkg" package to version 3.2.0. Changes since 3.1.8:
- Major overhaul of the source code to make maintenance and support
  for new compression formats easier.
- Use "liblzma" instead of "xzcat" for dealing with LZMA compressed RPMs.


(tron)
diff -r1.55 -r1.56 pkgsrc/pkgtools/rpm2pkg/Makefile
diff -r1.1 -r1.2 pkgsrc/pkgtools/rpm2pkg/PLIST
diff -r0 -r1.1 pkgsrc/pkgtools/rpm2pkg/files/Makefile
diff -r0 -r1.1 pkgsrc/pkgtools/rpm2pkg/files/fileio-bzlib.c
diff -r0 -r1.1 pkgsrc/pkgtools/rpm2pkg/files/fileio-lzma.c
diff -r0 -r1.1 pkgsrc/pkgtools/rpm2pkg/files/fileio-plain.c
diff -r0 -r1.1 pkgsrc/pkgtools/rpm2pkg/files/fileio-zlib.c
diff -r0 -r1.1 pkgsrc/pkgtools/rpm2pkg/files/fileio.c
diff -r0 -r1.1 pkgsrc/pkgtools/rpm2pkg/files/fileio.h
diff -r0 -r1.1 pkgsrc/pkgtools/rpm2pkg/files/package-list.c
diff -r0 -r1.1 pkgsrc/pkgtools/rpm2pkg/files/package-list.h
diff -r0 -r1.1 pkgsrc/pkgtools/rpm2pkg/files/parse-rpm.c
diff -r0 -r1.1 pkgsrc/pkgtools/rpm2pkg/files/parse-rpm.h
diff -r1.5 -r1.6 pkgsrc/pkgtools/rpm2pkg/files/rpm2pkg.8
diff -r1.19 -r1.20 pkgsrc/pkgtools/rpm2pkg/files/rpm2pkg.c

cvs diff -r1.55 -r1.56 pkgsrc/pkgtools/rpm2pkg/Makefile (expand / switch to unified diff)

--- pkgsrc/pkgtools/rpm2pkg/Makefile 2010/12/30 00:39:15 1.55
+++ pkgsrc/pkgtools/rpm2pkg/Makefile 2011/01/12 00:26:33 1.56
@@ -1,47 +1,34 @@ @@ -1,47 +1,34 @@
1# $NetBSD: Makefile,v 1.55 2010/12/30 00:39:15 tron Exp $ 1# $NetBSD: Makefile,v 1.56 2011/01/12 00:26:33 tron Exp $
2 2
3DISTNAME= rpm2pkg-3.1.8 3DISTNAME= rpm2pkg-3.2.0
4CATEGORIES= pkgtools 4CATEGORIES= pkgtools
5MASTER_SITES= # empty 5MASTER_SITES= # empty
6DISTFILES= # empty 6DISTFILES= # empty
7NO_CHECKSUM= yes 7NO_CHECKSUM= yes
8 8
9OWNER= tron@NetBSD.org 9OWNER= tron@NetBSD.org
10HOMEPAGE= http://www.NetBSD.org/docs/pkgsrc/ 10HOMEPAGE= http://www.pkgsrc.org/
11COMMENT= Convert RPM archives to NetBSD packages 11COMMENT= Convert RPM archives to NetBSD packages
12LICENSE= modified-bsd 12LICENSE= modified-bsd
13 13
14CONFLICTS+= suse-base<=6.4 14CONFLICTS+= suse-base<=6.4
15 15
16PKG_DESTDIR_SUPPORT= user-destdir 16PKG_DESTDIR_SUPPORT= user-destdir
17 17
18USE_LANGUAGES= c99 18MANCOMPRESSED_IF_MANZ= yes
19USE_TOOLS+= xzcat:run 19USE_BSD_MAKEFILE= yes
20WRKSRC= ${WRKDIR} 20USE_LANGUAGES= c99
21 21
22CPPFLAGS+= ${BUILDLINK_CPPFLAGS.bzip2} \ 22MAKE_ENV+= FILESDIR=${FILESDIR:Q}
23 ${BUILDLINK_CPPFLAGS.zlib} -DXZCAT=\"${TOOLS_PATH.xzcat:Q}\" 23MAKE_FILE= ${FILESDIR}/Makefile
24LIBS+= -lz -lbz2 24WRKSRC= ${WRKDIR}
25 25
26.include "../../mk/compiler.mk" 26.include "../../mk/compiler.mk"
27 27
28.if !empty(CC_VERSION:Mgcc-*) 28INSTALLATION_DIRS= ${PKGMANDIR}/man8 ${PKGMANDIR}/cat8 sbin
29CFLAGS+= -Wall -Wshadow -Wsign-compare -Wunused-value 
30.endif 
31 
32CFLAGS+= -g 
33 
34INSTALLATION_DIRS= ${PKGMANDIR}/man8 sbin 
35 
36do-build: 
37 cd ${WRKSRC}; ${CC} ${CFLAGS} ${CPPFLAGS} ${LDFLAGS} -o rpm2pkg \ 
38 ${FILESDIR}/rpm2pkg.c ${LIBS} 
39 
40do-install: 
41 ${INSTALL_PROGRAM} ${WRKSRC}/rpm2pkg ${DESTDIR}${PREFIX}/sbin 
42 ${INSTALL_MAN} ${FILESDIR}/rpm2pkg.8 ${DESTDIR}${PREFIX}/${PKGMANDIR}/man8 
43 29
44.include "../../archivers/bzip2/buildlink3.mk" 30.include "../../archivers/bzip2/buildlink3.mk"
 31.include "../../archivers/xz/buildlink3.mk"
45.include "../../devel/zlib/buildlink3.mk" 32.include "../../devel/zlib/buildlink3.mk"
46 33
47.include "../../mk/bsd.pkg.mk" 34.include "../../mk/bsd.pkg.mk"

cvs diff -r1.1 -r1.2 pkgsrc/pkgtools/rpm2pkg/PLIST (expand / switch to unified diff)

--- pkgsrc/pkgtools/rpm2pkg/PLIST 2001/10/31 21:19:10 1.1
+++ pkgsrc/pkgtools/rpm2pkg/PLIST 2011/01/12 00:26:33 1.2
@@ -1,3 +1,4 @@ @@ -1,3 +1,4 @@
1@comment $NetBSD: PLIST,v 1.1 2001/10/31 21:19:10 zuntum Exp $ 1@comment $NetBSD: PLIST,v 1.2 2011/01/12 00:26:33 tron Exp $
2sbin/rpm2pkg 2sbin/rpm2pkg
 3man/cat8/rpm2pkg.0
3man/man8/rpm2pkg.8 4man/man8/rpm2pkg.8

File Added: pkgsrc/pkgtools/rpm2pkg/files/Makefile
#	$NetBSD: Makefile,v 1.1 2011/01/12 00:26:33 tron Exp $

PROG=		rpm2pkg
SRCS=		fileio.c package-list.c parse-rpm.c rpm2pkg.c
SRCS+=		fileio-bzlib.c fileio-lzma.c fileio-plain.c fileio-zlib.c
MAN=		rpm2pkg.8

BINDIR=		${PREFIX}/sbin
LDADD=		-lbz2 -llzma -lz
WARNS=		4

#CFLAGS+=	-g
#LDFLAGS+=	-g

.PATH: ${FILESDIR}

.include <bsd.prog.mk>

File Added: pkgsrc/pkgtools/rpm2pkg/files/fileio-bzlib.c
/*-
 * Copyright (c) 2011 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Matthias Scheler.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#define	FILEIO_INTERNAL	/**/

#include "fileio.h"

#include <bzlib.h>
#include <stdio.h>
#include <stdlib.h>

typedef struct {
	FILE	*id_File;
	int	id_bzerror;
	BZFILE	*id_BZFile;
} InstData;

static void
BZLibCloseFunc(FileHandle *fh)
{
	InstData *id;

	id = fh->fh_InstData;

	if (id->id_BZFile != NULL)
                (void)BZ2_bzReadClose(&id->id_bzerror, id->id_BZFile);

	if (id->id_File != NULL)
		(void)fclose(id->id_File);
}

static ssize_t
BZLibReadFunc(FileHandle *fh, void *buffer, size_t bytes)
{
	InstData *id;
	int rbytes;

	id = fh->fh_InstData;
	
	rbytes = BZ2_bzRead(&id->id_bzerror, id->id_BZFile, buffer, bytes);
	switch (id->id_bzerror) {
	case BZ_OK:
	case BZ_STREAM_END:
		return rbytes;

	default:
		return -1;
	}
}

FileHandle *
FileHandleBZLib(int *fd_p)
{
	FileHandle *fh;
	InstData *id;

	fh = FileHandleCreate(BZLibCloseFunc, BZLibReadFunc, sizeof(*id));
	if (fh == NULL)
		return NULL;
	id = fh->fh_InstData;

	if ((id->id_File = fdopen(*fd_p, "rb")) == NULL) {
		FileHandleClose(fh);
		return NULL;
	}
	*fd_p = -1;

	if ((id->id_BZFile = BZ2_bzReadOpen(&id->id_bzerror, id->id_File, 0, 0,
	    NULL, 0)) == NULL) {
		FileHandleClose(fh);
		return NULL;
	}

	return fh;
}

File Added: pkgsrc/pkgtools/rpm2pkg/files/fileio-lzma.c
/*-
 * Copyright (c) 2011 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Matthias Scheler.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#define	FILEIO_INTERNAL	/**/

#include "fileio.h"

#include <inttypes.h>
#include <lzma.h>

typedef struct {
	lzma_stream	id_Stream;
	int		id_FD;
	size_t		id_Chunk;
	uint8_t		id_Buffer[1 << 16];
} InstData;

static void
LZMACloseFunc(FileHandle *fh)
{
	InstData *id;

	id = fh->fh_InstData;
	if (id != NULL) {
		lzma_end(&id->id_Stream);

		if (id->id_FD >= 0)
			(void)close(id->id_FD);

		fh->fh_InstData = NULL;
	}
}

static ssize_t
LZMAReadFunc(FileHandle *fh, void *buffer, size_t bytes)
{
	InstData *id;
	lzma_stream *stream;
	ssize_t rbytes;
	lzma_ret ret;

	id = fh->fh_InstData;
	if (id == NULL)
		return 0;

	stream = &id->id_Stream;
	if (stream->avail_in == 0 && id->id_FD >= 0) {
		rbytes = read(id->id_FD, id->id_Buffer, id->id_Chunk);
		if (rbytes < 0) {
			LZMACloseFunc(fh);
			return rbytes;
		}

		if (rbytes > 0) {
			stream->next_in = id->id_Buffer;
			stream->avail_in = rbytes;

			id->id_Chunk = sizeof(id->id_Buffer);
		} else {
			(void)close(id->id_FD);
			id->id_FD = -1;
		}
	}

	stream->next_out = buffer;
	stream->avail_out = bytes;
	ret = lzma_code(stream,
	    (stream->avail_in > 0) ? LZMA_RUN : LZMA_FINISH);

	rbytes = (ret == LZMA_OK || ret == LZMA_STREAM_END) ?
	    (ssize_t)(bytes - stream->avail_out) : -1;

	if (ret != LZMA_OK)
		LZMACloseFunc(fh);

	return rbytes;
}

FileHandle *
FileHandleLZMA(int *fd_p)
{
	FileHandle *fh;
	InstData *id;
	off_t offset;

	fh = FileHandleCreate(LZMACloseFunc, LZMAReadFunc, sizeof(*id));
	if (fh == NULL)
		return NULL;
	id = fh->fh_InstData;

	if (lzma_auto_decoder(&id->id_Stream, 1U << 30,
	    LZMA_CONCATENATED) != LZMA_OK) {
		fh->fh_InstData = NULL;
		FileHandleClose(fh);
		return NULL;
	}
	id->id_FD = *fd_p;
	*fd_p = -1;

	id->id_Chunk = sizeof(id->id_Buffer);
	offset = lseek(id->id_FD, 0, SEEK_CUR);
	if (offset != -1) {
		id->id_Chunk = sizeof(id->id_Buffer) -
		    (size_t)offset % sizeof(id->id_Buffer);
	}

	return fh;
}

File Added: pkgsrc/pkgtools/rpm2pkg/files/fileio-plain.c
/*-
 * Copyright (c) 2011 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Matthias Scheler.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#define	FILEIO_INTERNAL	/**/

#include "fileio.h"

#include <stdlib.h>

static void
PlainCloseFunc(FileHandle *fh)
{
	int *fd_p = fh->fh_InstData;

	if (*fd_p >= 0)
		(void)close(*fd_p);
}

static ssize_t
PlainReadFunc(FileHandle *fh, void *buffer, size_t bytes)
{
	int *fd_p = fh->fh_InstData;
	
	return read(*fd_p, buffer, bytes);
}

FileHandle *
FileHandlePlain(int *fd_p)
{
	FileHandle  *fh;

	fh = FileHandleCreate(PlainCloseFunc, PlainReadFunc, sizeof(int));
	if (fh != NULL) {
		int *new_fd_p = fh->fh_InstData;

		*new_fd_p = *fd_p;
		*fd_p = -1;
	}

	return fh;
}

File Added: pkgsrc/pkgtools/rpm2pkg/files/fileio-zlib.c
/*-
 * Copyright (c) 2011 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Matthias Scheler.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#define	FILEIO_INTERNAL	/**/

#include "fileio.h"

#include <zlib.h>

static void
ZLibCloseFunc(FileHandle *fh)
{
	gzFile *mygzfile = fh->fh_InstData;
	if (mygzfile != NULL)
		(void)gzclose(mygzfile);
}

static ssize_t
ZLibReadFunc(FileHandle *fh, void *buffer, size_t bytes)
{
	gzFile *mygzfile = fh->fh_InstData;
	return gzread(mygzfile, buffer, bytes);
}

FileHandle *
FileHandleZLib(int *fd_p)
{
	FileHandle  *fh;

	fh = FileHandleCreate(ZLibCloseFunc, ZLibReadFunc, 0);
	if (fh != NULL) {
		fh->fh_InstData = gzdopen(*fd_p, "r");
		if (fh->fh_InstData != NULL) {
			*fd_p = -1;
		} else {
			FileHandleClose(fh);
			fh = NULL;
		}
	}

	return fh;
}

File Added: pkgsrc/pkgtools/rpm2pkg/files/fileio.c
/*-
 * Copyright (c) 2011 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Matthias Scheler.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#define	FILEIO_INTERNAL	/**/

#include "fileio.h"

#include <stdlib.h>

FileHandle *
FileHandleCreate(FileHandleCloseFunc close_func, FileHandleReadFunc read_func,
    size_t inst_size)
{
	FileHandle *fh;

	if ((fh = calloc(1, sizeof(*fh) + inst_size)) == NULL)
		return NULL;

	fh->fh_CloseFunc = close_func;
	fh->fh_ReadFunc = read_func;

	if (inst_size > 0)
		fh->fh_InstData = &fh[1];

	return fh;
}

void
FileHandleClose(FileHandle *fh)
{
	fh->fh_CloseFunc(fh);
	free(fh);
}

bool
FileHandleRead(FileHandle *fh, void *buffer, size_t bytes)
{
	char *ptr;

	ptr = buffer;
	while (bytes > 0) {
		ssize_t rbytes;

		rbytes = fh->fh_ReadFunc(fh, ptr, bytes);
		if (rbytes <= 0)
			break;

		ptr += rbytes;
		bytes -= rbytes;

		fh->fh_Pos += rbytes;
	}

	return (bytes == 0);
}

off_t
FileHandleGetPos(const FileHandle *fh)
{
	return fh->fh_Pos;
}

File Added: pkgsrc/pkgtools/rpm2pkg/files/fileio.h
/*-
 * Copyright (c) 2011 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Matthias Scheler.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef FILEIO_H
#define FILEIO_H

#include <stdbool.h>
#include <unistd.h>

typedef struct FileHandleStruct FileHandle;

extern void	FileHandleClose(FileHandle *);
extern bool	FileHandleRead(FileHandle *, void *, size_t);
extern off_t	FileHandleGetPos(const FileHandle *fh);

extern FileHandle *FileHandleBZLib(int *);
extern FileHandle *FileHandleLZMA(int *);
extern FileHandle *FileHandlePlain(int *);
extern FileHandle *FileHandleZLib(int *);

#ifdef	FILEIO_INTERNAL

typedef void	(*FileHandleCloseFunc)(struct FileHandleStruct *);
typedef ssize_t	(*FileHandleReadFunc)(struct FileHandleStruct *, void *,size_t);

struct FileHandleStruct {
	FileHandleCloseFunc	fh_CloseFunc;
	FileHandleReadFunc	fh_ReadFunc;

	void			*fh_InstData;

	off_t			fh_Pos;
};

extern FileHandle *FileHandleCreate(FileHandleCloseFunc, FileHandleReadFunc,
    size_t);

#endif /* FILEIO_INTERNAL */

#endif /* !FILEIO_H */

File Added: pkgsrc/pkgtools/rpm2pkg/files/package-list.c
/*	$NetBSD: package-list.c,v 1.1 2011/01/12 00:26:33 tron Exp $	*/

/*-
 * Copyright (c) 2001-2011 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Matthias Scheler.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "package-list.h"

#include <stdlib.h>
#include <strings.h>

PListEntry *
PListInsert(PListEntry **Tree,char *Name)
{
	PListEntry *Node;

	while ((Node = *Tree) != NULL) {
		Tree = (strcmp(Name, Node->pe_Name) <0) ?
		    &Node->pe_Left : &Node->pe_Right;
	}

	if ((Node = calloc(1, sizeof (PListEntry) + strlen(Name))) == NULL) {
		perror("calloc");
		exit(EXIT_FAILURE);
	}

	(void)strcpy(Node->pe_Name, Name);

	return *Tree = Node;
}

PListEntry *
PListFind(PListEntry *Tree, char *Name)
{
	while (Tree != NULL) {
		int Result;

		if ((Result = strcmp(Name, Tree->pe_Name)) == 0) break;
		Tree = (Result < 0) ? Tree->pe_Left : Tree->pe_Right;
	}

	return Tree;
}

static void
PListWalk(PListEntry *Tree, PListEntryFunc Func, FILE *Out)
{
	while (Tree != NULL) {
		if (Tree->pe_Childs[0] != NULL)
			PListWalk(Tree->pe_Childs[0], Func, Out);
		Func(Tree, Out);
		Tree = Tree->pe_Childs[1];
	}
}

static void
PListEntryFile(PListEntry *node, FILE *out)
{
	(void)fprintf(out, "%s\n", node->pe_Name);
}

static void
PListEntryMakeDir(PListEntry *node, FILE *out)
{
	if (node->pe_DirEmpty)
		(void)fprintf(out, "@pkgdir %s\n", node->pe_Name);
}

void
PListWrite(PListEntry *files, PListEntry *dirs, FILE *out)
{
	PListWalk(files, PListEntryFile, out);
	PListWalk(dirs, PListEntryMakeDir, out);
}

File Added: pkgsrc/pkgtools/rpm2pkg/files/package-list.h
/*	$NetBSD: package-list.h,v 1.1 2011/01/12 00:26:33 tron Exp $	*/

/*-
 * Copyright (c) 2011 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Matthias Scheler.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef PACKAGE_LIST_H
#define PACKAGE_LIST_H

#include <stdio.h>

typedef struct PListEntryStruct PListEntry;
struct PListEntryStruct {
	PListEntry	*pe_Childs[2];
	int		pe_DirEmpty;
	unsigned long	pe_INode;
	char		*pe_Link;
	char		pe_Name[1];
};

#define	pe_Left		pe_Childs[0]
#define	pe_Right	pe_Childs[1]

typedef void PListEntryFunc(PListEntry *, FILE *);

extern PListEntry	*PListInsert(PListEntry **, char *);
extern PListEntry	*PListFind(PListEntry *, char *);
extern void		PListWrite(PListEntry *, PListEntry *, FILE *);

#endif /* !PACKAGE_LIST_H */

File Added: pkgsrc/pkgtools/rpm2pkg/files/parse-rpm.c
/*	$NetBSD: parse-rpm.c,v 1.1 2011/01/12 00:26:33 tron Exp $	*/

/*-
 * Copyright (c) 2001-2011 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Matthias Scheler.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "parse-rpm.h"

#include <sys/types.h>
#include <arpa/inet.h>

#include <inttypes.h>
#include <string.h>

/*
 * The following definitions are based on the documentation of the
 * RPM format which can be found here:
 *
 * http://www.rpm.org/max-rpm/s1-rpm-file-format-rpm-file-format.html
 */

/* Lead of an RPM archive. */
typedef struct RPMLead_s {
	uint8_t		magic[4];
	uint8_t		major, minor;
	int16_t		type;
	int16_t		archnum;
	int8_t		name[66];
	int16_t		osnum;
	uint16_t	signature_type;
	int8_t		reserved[16];
} RPMLead;

static const uint8_t RPMLeadMagic[] = { 0xed, 0xab, 0xee, 0xdb };

/* Header section of an RPM archive. */
typedef struct RPMHeader_s {
	uint8_t		magic[3];
	uint8_t		version;
	uint8_t		reserved[4];
	uint32_t	indexSize;
	uint32_t	dataSize;
} RPMHeader;

static const uint8_t RPMHeaderMagic[] = { 0x8e, 0xad, 0xe8 };

/* Magic bytes for "bzip2" and "gzip" compressed files. */
static const unsigned char BZipMagic[] = { 'B', 'Z', 'h' };
static const unsigned char GZipMagic[] = { 0x1f, 0x8b, 0x08 };

/* Magic bytes for a cpio(1) archive. */
static const unsigned char CPIOMagic[] = {'0','7','0','7','0','1'};

/* Check whether we got an RPM file and find the data section. */
bool
IsRPMFile(int fd)
{
	RPMLead		rpmLead;
	bool		padding;
	RPMHeader	rpmHeader;

	/* Check for RPM lead. */
	if (read(fd, &rpmLead, sizeof(RPMLead)) != sizeof(RPMLead))
		return false;

	if (memcmp(rpmLead.magic, RPMLeadMagic, sizeof(RPMLeadMagic)) != 0)
		return false;

	/* We don't support very old RPMs. */
	if (rpmLead.major < 3)
		return false;

	/*
	 * The RPM file format has a horrible requirement for extra padding
	 * depending on what type of signature is used.
	 */
	padding = htons(rpmLead.signature_type) == 5;

	/* Skip over RPM header(s). */
	while (read(fd, &rpmHeader, sizeof(RPMHeader)) == sizeof(RPMHeader)) {
		uint32_t	indexSize, dataSize;
		off_t		offset;

		/* Did we find another header? */		
		if (memcmp(rpmHeader.magic, RPMHeaderMagic,
		    sizeof(RPMHeaderMagic)) != 0) {
			/* Nope, seek backwards and return. */
			return (lseek(fd, -(off_t)sizeof(RPMHeader),
			    SEEK_CUR) != -1);
		}

		/* Find out how large the header is ... */
		indexSize = htonl(rpmHeader.indexSize);
		dataSize = htonl(rpmHeader.dataSize);

		/* .. and skip over it. */
		offset = indexSize * 4 * sizeof(uint32_t) + dataSize;
		if (padding) {
			offset = ((offset + 7) / 8) * 8;
			padding = false;
		}
		if (lseek(fd, offset, SEEK_CUR) == -1)
			return false;
	}

	return false;
}

FileHandle *
OpenRPM(int *fd_p)
{
	unsigned char buffer[8];
	FileHandle *fh;

	/*
	 * Read enough bytes to identify the compression and seek back to
	 * the beginning of the data section.
	 */
	if (read(*fd_p, buffer, sizeof(buffer)) != sizeof(buffer) ||
	    lseek(*fd_p, -(off_t)sizeof(buffer), SEEK_CUR) == -1) {
		return NULL;
	}

	/* Determine the compression method. */
	if (memcmp(buffer, CPIOMagic, sizeof(CPIOMagic)) == 0) {
		/* uncompressed data */
		fh = FileHandlePlain(fd_p);		
	} else if (memcmp(buffer, BZipMagic, sizeof(BZipMagic)) == 0) {
		/* bzip2 archive */
		fh = FileHandleBZLib(fd_p);
	} else if (memcmp(buffer, GZipMagic, sizeof(GZipMagic)) == 0) {
		/* gzip archive */
		fh = FileHandleZLib(fd_p);
	} else {
		/* lzma ... hopefully */
		fh = FileHandleLZMA(fd_p);
	}

	return fh;
}

File Added: pkgsrc/pkgtools/rpm2pkg/files/parse-rpm.h
/*-
 * Copyright (c) 2011 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Matthias Scheler.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef PARSE_RPM_H
#define PARSE_RPM_H

#include "fileio.h"

extern bool		IsRPMFile(int);
extern FileHandle	*OpenRPM(int *);

#endif /* !PARSE_RPM_H */

cvs diff -r1.5 -r1.6 pkgsrc/pkgtools/rpm2pkg/files/rpm2pkg.8 (expand / switch to unified diff)

--- pkgsrc/pkgtools/rpm2pkg/files/rpm2pkg.8 2001/12/03 19:03:23 1.5
+++ pkgsrc/pkgtools/rpm2pkg/files/rpm2pkg.8 2011/01/12 00:26:33 1.6
@@ -1,36 +1,28 @@ @@ -1,36 +1,28 @@
1.\" $NetBSD: rpm2pkg.8,v 1.5 2001/12/03 19:03:23 wiz Exp $ 
2.\" 1.\"
3.\" Copyright (c) 2001 The NetBSD Foundation, Inc. 2.\" Copyright (c) 2001, 2011 The NetBSD Foundation, Inc.
4.\" All rights reserved. 3.\" All rights reserved.
5.\" 4.\"
6.\" This code is derived from software contributed to The NetBSD Foundation 5.\" This code is derived from software contributed to The NetBSD Foundation
7.\" by Emmanuel Dreyfus. 6.\" by Emmanuel Dreyfus.
8.\" 7.\"
9.\" Redistribution and use in source and binary forms, with or without 8.\" Redistribution and use in source and binary forms, with or without
10.\" modification, are permitted provided that the following conditions 9.\" modification, are permitted provided that the following conditions
11.\" are met: 10.\" are met:
12.\" 1. Redistributions of source code must retain the above copyright 11.\" 1. Redistributions of source code must retain the above copyright
13.\" notice, this list of conditions and the following disclaimer. 12.\" notice, this list of conditions and the following disclaimer.
14.\" 2. Redistributions in binary form must reproduce the above copyright 13.\" 2. Redistributions in binary form must reproduce the above copyright
15.\" notice, this list of conditions and the following disclaimer in the 14.\" notice, this list of conditions and the following disclaimer in the
16.\" documentation and/or other materials provided with the distribution. 15.\" documentation and/or other materials provided with the distribution.
17.\" 3. All advertising materials mentioning features or use of this software 
18.\" must display the following acknowledgement: 
19.\" This product includes software developed by the NetBSD 
20.\" Foundation, Inc. and its contributors. 
21.\" 4. Neither the name of The NetBSD Foundation nor the names of its 
22.\" contributors may be used to endorse or promote products derived 
23.\" from this software without specific prior written permission. 
24.\" 16.\"
25.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
26.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
29.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35.\" POSSIBILITY OF SUCH DAMAGE. 27.\" POSSIBILITY OF SUCH DAMAGE.
36.\" 28.\"
@@ -140,22 +132,18 @@ file in @@ -140,22 +132,18 @@ file in
140while striping the leading directory of files path in 132while striping the leading directory of files path in
141.Ar bar.rpm . 133.Ar bar.rpm .
142This is useful for dealing with RPM archives that contains files like 134This is useful for dealing with RPM archives that contains files like
143.Pa usr/bin/foo , 135.Pa usr/bin/foo ,
144which you would like to go in 136which you would like to go in
145.Pa /usr/pkg/bin . 137.Pa /usr/pkg/bin .
146.Sh COMPATIBILITY 138.Sh COMPATIBILITY
147.Nm 139.Nm
148should work with any regular RPM file. 140should work with any regular RPM file.
149.Sh SEE ALSO 141.Sh SEE ALSO
150.Xr cpio 1 , 142.Xr cpio 1 ,
151.Xr rpm 8 , 143.Xr rpm 8 ,
152.Xr rpm2cpio 8 144.Xr rpm2cpio 8
153.br 
154.Em Dq Documentation on the NetBSD Package System , 
155.An Hubert Feyrer Aq hubert.feyrer@informatik.fh-regensburg.de , 
156.An Alistair Crooks Aq agc@pkgsrc.org 
157.Sh AUTHORS 145.Sh AUTHORS
158.An Matthias Scheler Aq tron@netbsd.org 146.An Matthias Scheler Aq tron@netbsd.org
159.br 147.br
160This man page was written by 148This man page was written by
161.An Emmanuel Dreyfus Aq manu@netbsd.org 149.An Emmanuel Dreyfus Aq manu@netbsd.org

cvs diff -r1.19 -r1.20 pkgsrc/pkgtools/rpm2pkg/files/rpm2pkg.c (expand / switch to unified diff)

--- pkgsrc/pkgtools/rpm2pkg/files/rpm2pkg.c 2010/12/22 09:36:35 1.19
+++ pkgsrc/pkgtools/rpm2pkg/files/rpm2pkg.c 2011/01/12 00:26:33 1.20
@@ -1,17 +1,17 @@ @@ -1,17 +1,17 @@
1/* $NetBSD: rpm2pkg.c,v 1.19 2010/12/22 09:36:35 tron Exp $ */ 1/* $NetBSD: rpm2pkg.c,v 1.20 2011/01/12 00:26:33 tron Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2001-2010 The NetBSD Foundation, Inc. 4 * Copyright (c) 2001-2011 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Matthias Scheler. 8 * by Matthias Scheler.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
@@ -21,97 +21,58 @@ @@ -21,97 +21,58 @@
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32#include <sys/types.h> 32#include <sys/types.h>
33#include <sys/stat.h> 33#include <sys/stat.h>
34#include <sys/wait.h> 
35 
36#include <arpa/inet.h> 
37 34
 35#include <ctype.h>
38#include <errno.h> 36#include <errno.h>
39#include <fcntl.h> 37#include <fcntl.h>
40#include <inttypes.h> 
41#include <signal.h> 
42#include <stdbool.h> 38#include <stdbool.h>
43#include <stdio.h> 39#include <stdio.h>
44#include <stdlib.h> 40#include <stdlib.h>
45#include <string.h> 41#include <string.h>
46#include <unistd.h> 42#include <unistd.h>
47 43
48#include <bzlib.h> 44#include "fileio.h"
49#include <zlib.h> 45#include "package-list.h"
50 46#include "parse-rpm.h"
51/* 
52 * The following definitions are based on the documentation of the 
53 * RPM format which can be found here: 
54 * 
55 * http://www.rpm.org/max-rpm/s1-rpm-file-format-rpm-file-format.html 
56 */ 
57 
58/* Lead of an RPM archive. */ 
59typedef struct RPMLead_s { 
60 uint8_t magic[4]; 
61 uint8_t major, minor; 
62 int16_t type; 
63 int16_t archnum; 
64 int8_t name[66]; 
65 int16_t osnum; 
66 uint16_t signature_type; 
67 int8_t reserved[16]; 
68} RPMLead; 
69 
70static const uint8_t RPMLeadMagic[] = { 0xed, 0xab, 0xee, 0xdb }; 
71 
72/* Header section of an RPM archive. */ 
73typedef struct RPMHeader_s { 
74 uint8_t magic[3]; 
75 uint8_t version; 
76 uint8_t reserved[4]; 
77 uint32_t indexSize; 
78 uint32_t dataSize; 
79} RPMHeader; 
80 
81static const uint8_t RPMHeaderMagic[] = { 0x8e, 0xad, 0xe8 }; 
82 
83/* Magic bytes for "bzip2" and "gzip" compressed files. */ 
84static const unsigned char BZipMagic[] = { 'B', 'Z', 'h' }; 
85static const unsigned char GZipMagic[] = { 0x1f, 0x8b, 0x08 }; 
86 47
87/* Structure of a cpio(1) archive. */ 48/* Structure of a cpio(1) archive. */
88#define C_IRUSR 0000400 49#define C_IRUSR 0000400
89#define C_IWUSR 0000200 50#define C_IWUSR 0000200
90#define C_IXUSR 0000100 51#define C_IXUSR 0000100
91#define C_IRGRP 0000040 52#define C_IRGRP 0000040
92#define C_IWGRP 0000020 53#define C_IWGRP 0000020
93#define C_IXGRP 0000010 54#define C_IXGRP 0000010
94#define C_IROTH 0000004 55#define C_IROTH 0000004
95#define C_IWOTH 0000002 56#define C_IWOTH 0000002
96#define C_IXOTH 0000001 57#define C_IXOTH 0000001
97#define C_ISUID 0004000 58#define C_ISUID 0004000
98#define C_ISGID 0002000 59#define C_ISGID 0002000
99#define C_ISVTX 0001000 60#define C_ISVTX 0001000
100#define C_ISDIR 0040000 61#define C_ISDIR 0040000
101#define C_ISREG 0100000 62#define C_ISREG 0100000
102#define C_ISCHR 0020000 63#define C_ISCHR 0020000
103#define C_ISLNK 0120000 64#define C_ISLNK 0120000
104  65
105static const unsigned char CPIOMagic[] = {'0','7','0','7','0','1'}; 66static const unsigned char CPIOMagic[] = {'0','7','0','7','0','1'};
106 67
107#define CPIO_END_MARKER "TRAILER!!!" 68#define CPIO_END_MARKER "TRAILER!!!"
108#define CPIO_FIELD_LENGTH 8 69#define CPIO_FIELD_LENGTH 8
109 70
110#define CPIO_HDR_INODE 0 71#define CPIO_HDR_INODE 0
111#define CPIO_HDR_MODE 1 72#define CPIO_HDR_MODE 1
112#define CPIO_HDR_FILESIZE 6 73#define CPIO_HDR_FILESIZE 6
113#define CPIO_HDR_NAMESIZE 11 74#define CPIO_HDR_NAMESIZE 11
114#define CPIO_NUM_HEADERS 13 75#define CPIO_NUM_HEADERS 13
115 76
116#define CP_IFMT 0170000 77#define CP_IFMT 0170000
117 78
@@ -126,974 +87,618 @@ ModeMap ModeMapTab[] = { @@ -126,974 +87,618 @@ ModeMap ModeMapTab[] = {
126 {C_IXUSR, S_IXUSR}, 87 {C_IXUSR, S_IXUSR},
127 {C_IRGRP, S_IRGRP}, 88 {C_IRGRP, S_IRGRP},
128 {C_IWGRP, S_IWGRP}, 89 {C_IWGRP, S_IWGRP},
129 {C_IXGRP, S_IXGRP}, 90 {C_IXGRP, S_IXGRP},
130 {C_IROTH, S_IROTH}, 91 {C_IROTH, S_IROTH},
131 {C_IWOTH, S_IWOTH}, 92 {C_IWOTH, S_IWOTH},
132 {C_IXOTH, S_IXOTH}, 93 {C_IXOTH, S_IXOTH},
133 {C_ISUID, S_ISUID}, 94 {C_ISUID, S_ISUID},
134 {C_ISGID, S_ISGID}, 95 {C_ISGID, S_ISGID},
135 {C_ISVTX, S_ISVTX}, 96 {C_ISVTX, S_ISVTX},
136 {0, 0} 97 {0, 0}
137}; 98};
138 99
139typedef struct PListEntryStruct PListEntry; 
140struct PListEntryStruct { 
141 PListEntry *pe_Childs[2]; 
142 int pe_DirEmpty; 
143 unsigned long pe_INode; 
144 char *pe_Link; 
145 char pe_Name[1]; 
146}; 
147 
148#define pe_Left pe_Childs[0] 
149#define pe_Right pe_Childs[1] 
150 
151typedef void PListEntryFunc(PListEntry *,FILE *); 
152 
153typedef struct FileHandleStruct { 
154 FILE *fh_File; 
155 BZFILE *fh_BZFile; 
156 gzFile *fh_GZFile; 
157 off_t fh_Pos; 
158 int fh_FD; 
159 pid_t fh_Child; 
160} FileHandle; 
161 
162static bool 
163InitBuffer(void **Buffer, size_t *BufferSizePtr) 
164{ 
165 if (*Buffer == NULL) { 
166 size_t BufferSize; 
167 
168 BufferSize = sysconf(_SC_PAGESIZE) * 256; 
169 while ((*Buffer = malloc(BufferSize)) == NULL) { 
170 BufferSize >>= 1; 
171 if (BufferSize == 0) 
172 return false; 
173 } 
174 *BufferSizePtr = BufferSize; 
175 } 
176 return true; 
177} 
178 
179static void 
180Close(FileHandle *fh) 
181{ 
182 if (fh->fh_BZFile != NULL) { 
183 int bzerror; 
184 
185 (void)BZ2_bzReadClose(&bzerror, fh->fh_BZFile); 
186 (void)fclose(fh->fh_File); 
187 } 
188 
189 if (fh->fh_GZFile != NULL) { 
190 (void)gzclose(fh->fh_GZFile); 
191 } 
192 
193 if (fh->fh_FD >= 0) { 
194 (void)close(fh->fh_FD); 
195 } 
196 
197 if (fh->fh_Child != -1) { 
198 if (waitpid(fh->fh_Child, NULL, WNOHANG) != fh->fh_Child) { 
199 (void)kill(fh->fh_Child, SIGTERM); 
200 (void)waitpid(fh->fh_Child, NULL, 0); 
201 } 
202 } 
203 
204 free(fh); 
205} 
206 
207/* Check whether we got an RPM file and find the data section. */ 
208static bool 
209IsRPMFile(int fd) 
210{ 
211 RPMLead rpmLead; 
212 bool padding; 
213 RPMHeader rpmHeader; 
214 
215 /* Check for RPM lead. */ 
216 if (read(fd, &rpmLead, sizeof(RPMLead)) != sizeof(RPMLead)) 
217 return false; 
218 
219 if (memcmp(rpmLead.magic, RPMLeadMagic, sizeof(RPMLeadMagic)) != 0) 
220 return false; 
221 
222 /* We don't support very old RPMs. */ 
223 if (rpmLead.major < 3) 
224 return false; 
225 
226 /* 
227 * The RPM file format has a horrible requirement for extra padding 
228 * depending on what type of signature is used. 
229 */ 
230 padding = htons(rpmLead.signature_type) == 5; 
231 
232 /* Skip over RPM header(s). */ 
233 while (read(fd, &rpmHeader, sizeof(RPMHeader)) == sizeof(RPMHeader)) { 
234 uint32_t indexSize, dataSize; 
235 off_t offset; 
236 
237 /* Did we find another header? */  
238 if (memcmp(rpmHeader.magic, RPMHeaderMagic, 
239 sizeof(RPMHeaderMagic)) != 0) { 
240 /* Nope, seek backwards and return. */ 
241 return (lseek(fd, -(off_t)sizeof(RPMHeader), 
242 SEEK_CUR) != -1); 
243 } 
244 
245 /* Find out how large the header is ... */ 
246 indexSize = htonl(rpmHeader.indexSize); 
247 dataSize = htonl(rpmHeader.dataSize); 
248 
249 /* .. and skip over it. */ 
250 offset = indexSize * 4 * sizeof(uint32_t) + dataSize; 
251 if (padding) { 
252 offset = ((offset + 7) / 8) * 8; 
253 padding = false; 
254 } 
255 if (lseek(fd, offset, SEEK_CUR) == -1) 
256 return false; 
257 } 
258 
259 return false; 
260} 
261 
262static FileHandle * 
263Open(int fd) 
264{ 
265 unsigned char buffer[8]; 
266 FileHandle *fh; 
267 
268 /* 
269 * Read enough bytes to identify the compression and seek back to 
270 * the beginning of the data section. 
271 */ 
272 if (read(fd, buffer, sizeof(buffer)) != sizeof(buffer) || 
273 lseek(fd, -(off_t)sizeof(buffer), SEEK_CUR) == -1) { 
274 return NULL; 
275 } 
276 
277 if ((fh = calloc(1, sizeof (FileHandle))) == NULL) 
278 return NULL; 
279 
280 fh->fh_FD = -1; 
281 fh->fh_Child = -1; 
282 
283 /* Determine the compression method. */ 
284 if (memcmp(buffer, CPIOMagic, sizeof(CPIOMagic)) == 0) { 
285 /* uncompressed data */ 
286 if ((fh->fh_FD = dup(fd)) < 0) { 
287 free(fh); 
288 return NULL; 
289 } 
290 } else if (memcmp(buffer, BZipMagic, sizeof(BZipMagic)) == 0) { 
291 /* bzip2 archive */ 
292 int bzerror; 
293 
294 if ((fd = dup(fd)) < 0) { 
295 free(fh); 
296 return NULL; 
297 } 
298 if ((fh->fh_File = fdopen(fd, "rb")) == NULL) { 
299 (void)close(fd); 
300 free(fh); 
301 return NULL; 
302 } 
303 if ((fh->fh_BZFile = BZ2_bzReadOpen(&bzerror, fh->fh_File, 0, 
304 0, NULL, 0)) == NULL) { 
305 (void)fclose(fh->fh_File); 
306 free(fh); 
307 return (NULL); 
308 } 
309 } else if (memcmp(buffer, GZipMagic, sizeof(GZipMagic)) == 0) { 
310 /* gzip archive */ 
311 if ((fh->fh_GZFile = gzdopen(fd, "r")) == NULL) { 
312 free(fh); 
313 return (NULL); 
314 } 
315 } else { 
316 /* lzma ... hopefully */ 
317#ifdef XZCAT 
318 int pfds[2]; 
319 char *path, *argv[3]; 
320 pid_t pid; 
321 
322 if (pipe(pfds) != 0) { 
323 free(fh); 
324 return (NULL); 
325 } 
326 
327 path = XZCAT; 
328 argv[0] = strrchr(path, '/'); 
329 if (argv[0] == NULL) 
330 argv[0] = path; 
331 argv[1] = NULL; 
332 
333 pid = vfork(); 
334 switch (pid) { 
335 case -1: 
336 (void)close(pfds[0]); 
337 (void)close(pfds[1]); 
338 free(fh); 
339 return NULL; 
340 
341 case 0: 
342 if (dup2(fd, STDIN_FILENO) == -1 || 
343 dup2(pfds[1], STDOUT_FILENO) == -1) { 
344 _exit(EXIT_FAILURE); 
345 } 
346 (void)close(fd); 
347 (void)close(pfds[0]); 
348 (void)close(pfds[1]); 
349 
350 (void)execvp(path, argv); 
351 _exit(EXIT_FAILURE); 
352  
353 default: 
354 (void)close(pfds[1]); 
355 if (waitpid(pid, NULL, WNOHANG) == pid) { 
356 (void)close(pfds[0]); 
357 free(fh); 
358 return NULL; 
359 } 
360 fh->fh_FD = pfds[0]; 
361 fh->fh_Child = pid; 
362 }  
363#else 
364 free(fh); 
365 fh = NULL; 
366#endif 
367 } 
368 
369 return (fh); 
370} 
371 
372static bool 
373Read(FileHandle *fh, void *buffer, size_t length) 
374{ 
375 ssize_t bytes; 
376 
377 if (fh->fh_BZFile != NULL) { 
378 int bzerror; 
379 bytes = BZ2_bzRead(&bzerror, fh->fh_BZFile, buffer, length); 
380 } else if (fh->fh_GZFile != NULL) { 
381 bytes = gzread(fh->fh_GZFile, buffer, length); 
382 } else if (fh->fh_FD >= 0) { 
383 uint8_t *ptr; 
384 
385 bytes = 0; 
386 ptr = buffer; 
387 while (bytes < (ssize_t)length) { 
388 ssize_t chunk = read(fh->fh_FD, ptr, length - bytes); 
389 if (chunk < 0) { 
390 bytes = -1; 
391 break; 
392 } else if (chunk == 0) { 
393 break; 
394 } 
395 
396 ptr += chunk; 
397 bytes += chunk; 
398 } 
399 } else { 
400 bytes = -1; 
401 } 
402 
403 if (bytes > 0) 
404 fh->fh_Pos += bytes; 
405 
406 return (bytes == (ssize_t)length); 
407} 
408 
409static bool 100static bool
410SkipAndAlign(FileHandle *fh, off_t Skip) 101SkipAndAlign(FileHandle *fh, off_t skip)
411 
412{ 102{
413 off_t NewPos; 103 off_t old_pos, new_pos;
 104 char buffer[1 << 16];
414 105
415 NewPos = (fh->fh_Pos + Skip + 3) & ~3; 106 old_pos = FileHandleGetPos(fh);
416 if (fh->fh_Pos == NewPos) 107 new_pos = (old_pos + skip + 3) & ~3;
 108 if (old_pos == new_pos)
417 return true; 109 return true;
418 110
419 if (fh->fh_GZFile != NULL) { 111 while (old_pos < new_pos) {
420 if (gzseek(fh->fh_GZFile, NewPos, SEEK_SET) == NewPos) { 112 off_t length;
421 fh->fh_Pos = NewPos; 113 size_t chunk;
422 return true; 114
423 } 115 length = new_pos - old_pos;
424 return false; 116 chunk = (length > (off_t)sizeof(buffer)) ?
425 } else { 117 (off_t)sizeof(buffer) : length;
426 static void *Buffer = NULL; 118 if (!FileHandleRead(fh, buffer, chunk))
427 static size_t BufferSize = 0; 
428 
429 if (!InitBuffer(&Buffer, &BufferSize)) 
430 return false; 119 return false;
431 120
432 while (fh->fh_Pos < NewPos) { 121 old_pos = FileHandleGetPos(fh);
433 off_t Length; 
434 int Chunk; 
435 
436 Length = NewPos - fh->fh_Pos; 
437 Chunk = (Length > (off_t)BufferSize) ? 
438 (off_t)BufferSize : Length; 
439 if (!Read(fh, Buffer, Chunk)) 
440 return false; 
441 } 
442 } 122 }
443 123
444 return true; 124 return true;
445} 125}
446 126
447static PListEntry * 
448InsertPListEntry(PListEntry **Tree,char *Name) 
449{ 
450 PListEntry *Node; 
451 
452 while ((Node = *Tree) != NULL) { 
453 Tree = (strcmp(Name, Node->pe_Name) <0) ? 
454 &Node->pe_Left : &Node->pe_Right; 
455 } 
456 
457 if ((Node = calloc(1, sizeof (PListEntry) + strlen(Name))) == NULL) { 
458 perror("calloc"); 
459 exit(EXIT_FAILURE); 
460 } 
461 
462 (void)strcpy(Node->pe_Name, Name); 
463 
464 return *Tree = Node; 
465} 
466 
467static PListEntry * 
468FindPListEntry(PListEntry *Tree, char *Name) 
469{ 
470 while (Tree != NULL) { 
471 int Result; 
472 
473 if ((Result = strcmp(Name, Tree->pe_Name)) == 0) break; 
474 Tree = (Result < 0) ? Tree->pe_Left : Tree->pe_Right; 
475 } 
476 
477 return Tree; 
478} 
479 
480static void 
481PListEntryFile(PListEntry *Node, FILE *Out) 
482 
483{ 
484 (void)fputs(Node->pe_Name, Out); 
485 (void)fputc('\n', Out); 
486} 
487 
488static char * 127static char *
489StrCat(char *Prefix, char *Suffix) 128StrCat(const char *prefix, const char *suffix)
490{ 129{
491 int Length; 130 size_t prefix_length;
492 char *Str; 131 char *str;
493 132
494 Length = strlen(Prefix); 133 prefix_length = strlen(prefix);
495 if ((Str = malloc(Length + strlen(Suffix) + 1)) == NULL) { 134 if ((str = malloc(prefix_length + strlen(suffix) + 1)) == NULL) {
496 perror("malloc"); 135 perror("malloc");
497 exit(EXIT_FAILURE); 136 exit(EXIT_FAILURE);
498 } 137 }
499 138
500 (void)memcpy(Str, Prefix, Length); 139 (void)memcpy(str, prefix, prefix_length);
501 (void)strcpy(&Str[Length], Suffix); 140 (void)strcpy(&str[prefix_length], suffix);
502 141
503 return Str; 142 return str;
504} 
505 
506 
507static void 
508PListEntryMakeDir(PListEntry *Node, FILE *Out) 
509 
510{ 
511 if (Node->pe_DirEmpty) { 
512 (void)fprintf(Out, "@pkgdir %s\n", Node->pe_Name); 
513 } 
514} 
515 
516static void 
517ProcessPList(PListEntry *Tree, PListEntryFunc Func, FILE *Out) 
518 
519{ 
520 while (Tree != NULL) { 
521 if (Tree->pe_Childs[0] != NULL) 
522 ProcessPList(Tree->pe_Childs[0], Func, Out); 
523 Func(Tree, Out); 
524 Tree = Tree->pe_Childs[1]; 
525 } 
526} 143}
527 144
528static char ** 145static char **
529ArrayAdd(char **Array, char *String) 146ArrayAdd(char **array, char *string)
530 
531{ 147{
532 int Old; 148 size_t old;
533 149
534 Old = 0; 150 old = 0;
535 if (Array != NULL) { 151 if (array != NULL) {
536 while (Array[Old] != NULL) 152 while (array[old] != NULL)
537 Old ++; 153 old++;
538 } 154 }
539 if ((Array = realloc(Array, sizeof (char *) * (Old + 2))) == NULL) { 155
 156 if ((array = realloc(array, sizeof(char *) * (old + 2))) == NULL) {
540 perror("realloc"); 157 perror("realloc");
541 exit(EXIT_FAILURE); 158 exit(EXIT_FAILURE);
542 } 159 }
543 160
544 Array[Old++] = String; 161 array[old++] = string;
545 Array[Old] = NULL; 162 array[old] = NULL;
546 163
547 return Array; 164 return array;
548} 165}
549 166
550static void 167static void
551Usage(char *Progname) 168Usage(char *Progname)
552{ 169{
553 (void)fprintf(stderr,  170 (void)fprintf(stderr,
554 "Usage: %s [-d directory] [-f packlist] [[-i ignorepath] ...]\n" 171 "Usage: %s [-d directory] [-f packlist] [[-i ignorepath] ...]\n"
555 " [-p prefix] [-s stripcount] rpmfile [...]\n",  172 " [-p prefix] [-s stripcount] rpmfile [...]\n",
556 Progname); 173 Progname);
557 exit(EXIT_FAILURE); 174 exit(EXIT_FAILURE);
558} 175}
559 176
560static char * 177static char *
561GetData(FileHandle *In, unsigned long Length) 178GetData(FileHandle *In, unsigned long Length)
562{ 179{
563 char *Ptr; 180 char *Ptr;
564 181
565 if ((Ptr = malloc(Length + 1)) != NULL) { 182 if ((Ptr = malloc(Length + 1)) != NULL) {
566 if (Read(In, Ptr, Length) && SkipAndAlign(In, 0)) { 183 if (FileHandleRead(In, Ptr, Length) && SkipAndAlign(In, 0)) {
567 Ptr[Length] = '\0'; 184 Ptr[Length] = '\0';
568 return Ptr; 185 return Ptr;
569 } 186 }
570 free(Ptr); 187 free(Ptr);
571 } 188 }
572 189
573 return NULL; 190 return NULL;
574} 191}
575 192
576static bool 193static bool
577GetCPIOHeader(FileHandle *In, unsigned long *Fields, char **Name) 194GetCPIOHeader(FileHandle *in, unsigned long *fields, char **name)
578{ 195{
579 char Buffer[CPIO_NUM_HEADERS * CPIO_FIELD_LENGTH], *Ptr; 196 char buffer[CPIO_NUM_HEADERS][CPIO_FIELD_LENGTH];
580 int Index; 197 char header[CPIO_FIELD_LENGTH + 1];
581 unsigned long Value; 198 size_t i, j;
 199 unsigned long namelen;
582 200
583 *Name = NULL; 201 *name = NULL;
584 202
585 if (!Read(In, Buffer, sizeof (CPIOMagic))) 203 if (!FileHandleRead(in, buffer, sizeof(CPIOMagic)))
586 return false; 204 return false;
587 if (memcmp(Buffer, CPIOMagic, sizeof (CPIOMagic)) != 0) 205 if (memcmp(buffer, CPIOMagic, sizeof(CPIOMagic)) != 0)
588 return false; 206 return false;
589 207
590 if (!Read(In, Buffer, sizeof (Buffer))) 208 if (!FileHandleRead(in, buffer, sizeof(buffer)))
591 return false; 209 return false;
592 210
593 Ptr = Buffer; 211 header[CPIO_FIELD_LENGTH] = '\0';
594 Index = sizeof (Buffer); 212 for (i = 0; i < CPIO_NUM_HEADERS; i++) {
595 Value = 0; 213 for (j = 0; j < CPIO_FIELD_LENGTH; j++) {
596 while (Index-- > 0) { 214 if (!isxdigit((unsigned char)buffer[i][j]))
597 Value <<= 4; 215 return false;
598 if ((*Ptr >= '0') && (*Ptr <= '9')) { 216 header[j] = buffer[i][j];
599 Value += (unsigned long)(*Ptr++-'0'); 
600 } else if ((*Ptr >= 'A') && (*Ptr <= 'F')) { 
601 Value += (unsigned long)(*Ptr++-'A') + 10; 
602 } else if ((*Ptr >= 'a') && (*Ptr <= 'f')) { 
603 Value += (unsigned long)(*Ptr++-'a') + 10; 
604 } else { 
605 return false; 
606 } 
607  
608 if ((Index % CPIO_FIELD_LENGTH) == 0) { 
609 *Fields++ = Value; 
610 Value = 0; 
611 } 217 }
612 } 
613 218
614 Value = Fields[CPIO_HDR_NAMESIZE - CPIO_NUM_HEADERS]; 219 fields[i] = strtoul(header, NULL, 16);
615 if ((*Name = GetData(In, Value)) == NULL) 220 }
 221
 222 namelen = fields[CPIO_HDR_NAMESIZE];
 223 if ((*name = GetData(in, namelen)) == NULL)
616 return false; 224 return false;
617 return ((*Name)[Value -1 ] == '\0'); 225 return ((*name)[namelen - 1] == '\0');
618} 226}
619 227
620static mode_t 228static mode_t
621ConvertMode(unsigned long CPIOMode) 229ConvertMode(unsigned long cpio_mode)
622{ 230{
623 mode_t Mode; 231 mode_t mode;
624 ModeMap *Ptr; 232 ModeMap *ptr;
625 233
626 Mode = 0; 234 for (ptr = ModeMapTab, mode = 0; ptr->mm_CPIOMode != 0; ptr++) {
627 Ptr = ModeMapTab; 235 if (cpio_mode & ptr->mm_CPIOMode)
628 while (Ptr->mm_CPIOMode != 0) { 236 mode |= ptr->mm_SysMode;
629 if ((CPIOMode & Ptr->mm_CPIOMode) != 0) 
630 Mode |= Ptr->mm_SysMode; 
631 Ptr++; 
632 } 237 }
633 238
634 return Mode; 239 return mode;
635} 240}
636 241
637static bool 242static bool
638MakeTargetDir(char *Name, PListEntry **Dirs) 243MakeTargetDir(char *Name, PListEntry **Dirs)
639{ 244{
640 char *Basename; 245 char *Basename;
641 PListEntry *Dir; 246 PListEntry *Dir;
642 struct stat Stat; 247 struct stat Stat;
643 int Result; 248 int Result;
644 249
645 if ((Basename = strrchr(Name, '/')) == NULL) 250 if ((Basename = strrchr(Name, '/')) == NULL)
646 return true; 251 return true;
647 252
648 *Basename = '\0'; 253 *Basename = '\0';
649 if ((Dir = FindPListEntry(*Dirs, Name)) != NULL) { 254 if ((Dir = PListFind(*Dirs, Name)) != NULL) {
650 *Basename = '/'; 255 *Basename = '/';
651 Dir->pe_DirEmpty = false; 256 Dir->pe_DirEmpty = false;
652 return true; 257 return true;
653 } 258 }
654 259
655 if (!MakeTargetDir(Name, Dirs)) { 260 if (!MakeTargetDir(Name, Dirs)) {
656 *Basename = '/'; 261 *Basename = '/';
657 return false; 262 return false;
658 } 263 }
659 264
660 if (stat(Name, &Stat) == 0) { 265 if (stat(Name, &Stat) == 0) {
661 Result = S_ISDIR(Stat.st_mode); 266 Result = S_ISDIR(Stat.st_mode);
662 } else if (errno != ENOENT) { 267 } else if (errno != ENOENT) {
663 Result = false; 268 Result = false;
664 } else if ((Result = (mkdir(Name, S_IRWXU|S_IRWXG|S_IRWXO) == 0))) { 269 } else if ((Result = (mkdir(Name, S_IRWXU|S_IRWXG|S_IRWXO) == 0))) {
665 (void)InsertPListEntry(Dirs, Name); 270 (void)PListInsert(Dirs, Name);
666 } 271 }
667 272
668 *Basename = '/'; 273 *Basename = '/';
669 return Result; 274 return Result;
670} 275}
671 276
672static bool 277static bool
673MakeDir(char *Name, mode_t Mode, int *OldDir) 278MakeDir(char *name, mode_t mode, bool *old_dir)
674{ 279{
675 struct stat Stat; 280 struct stat sb;
676 281
677 *OldDir = false; 282 *old_dir = false;
678 if (mkdir(Name, Mode) == 0) 283 if (mkdir(name, mode) == 0)
679 return true; 284 return true;
680 285
681 if ((errno != EEXIST) || (lstat(Name, &Stat) < 0) ||  286 if (errno != EEXIST || lstat(name, &sb) < 0 || !S_ISDIR(sb.st_mode))
682 !S_ISDIR(Stat.st_mode)) { 
683 return false; 287 return false;
684 } 
685 288
686 *OldDir = true; 289 *old_dir = true;
687 return true; 290 return true;
688} 291}
689 292
690static bool 293static bool
691MakeSymLink(char *Link, char *Name) 294MakeSymLink(char *Link, char *Name)
692{ 295{
693 struct stat Stat; 296 struct stat Stat;
694 297
695 if (symlink(Link, Name) == 0) return true; 298 if (symlink(Link, Name) == 0) return true;
696 299
697 if ((errno != EEXIST) || (lstat(Name, &Stat) < 0) ||  300 if ((errno != EEXIST) || (lstat(Name, &Stat) < 0) ||
698 !S_ISLNK(Stat.st_mode)) { 301 !S_ISLNK(Stat.st_mode)) {
699 return false; 302 return false;
700 } 303 }
701 304
702 return ((unlink(Name) == 0) && (symlink(Link, Name) == 0)); 305 return ((unlink(Name) == 0) && (symlink(Link, Name) == 0));
703} 306}
704 307
705static bool 308static bool
706WriteFile(FileHandle *In, char *Name, mode_t Mode, unsigned long Length, 309WriteFile(FileHandle *in, char *name, mode_t mode, unsigned long length,
707 char *Link) 310 const char *link_target)
708{ 311{
709 int Out; 312 int outfd;
710 struct stat Stat; 313 struct stat sb;
711 static void *Buffer = NULL; 314 char buffer[1 << 16];
712 static size_t BufferSize = 0; 
713 315
714 if ((lstat(Name, &Stat) == 0) && 316 if ((lstat(name, &sb) == 0) &&
715 (!S_ISREG(Stat.st_mode) || (unlink(Name) < 0))) { 317 (!S_ISREG(sb.st_mode) || (unlink(name) < 0))) {
716 return false; 318 return false;
717 } 319 }
718 320
719 if (!InitBuffer(&Buffer, &BufferSize)) 321 if (link_target != NULL) {
720 return false; 322 if (link(link_target, name) < 0)
721 
722 if (Link != NULL) { 
723 if (link(Link, Name) < 0) 
724 return false; 323 return false;
725 Out = open(Name, O_WRONLY, Mode); 324 outfd = open(name, O_WRONLY, mode);
726 } else { 325 } else {
727 Out = open(Name, O_WRONLY|O_CREAT, Mode); 326 outfd = open(name, O_WRONLY|O_CREAT, mode);
728 } 327 }
729 if (Out < 0) 328 if (outfd < 0)
730 return false; 329 return false;
731 330
732 while (Length > 0) { 331 while (length > 0) {
733 int Chunk; 332 ssize_t chunk;
734 333
735 Chunk = (Length > BufferSize) ? BufferSize : Length; 334 chunk = (length > sizeof(buffer)) ? sizeof(buffer) : length;
736 if (!Read(In, Buffer, Chunk) || 335 if (!FileHandleRead(in, buffer, chunk) ||
737 (write(Out, Buffer, Chunk) != Chunk)) 336 write(outfd, buffer, chunk) != chunk)
738 break; 337 break;
739 Length -= Chunk; 338 length -= chunk;
740 } 339 }
741 340
742 if ((close(Out) == 0) && (Length == 0)) 341 if (close(outfd) == 0 && length == 0)
743 return SkipAndAlign(In, 0); 342 return SkipAndAlign(in, 0);
744 343
745 (void)unlink(Name); 344 (void)unlink(name);
746 return false; 345 return false;
747} 346}
748 347
749static void 348static void
750CheckSymLinks(PListEntry **Links, PListEntry **Files, PListEntry **Dirs) 349CheckSymLinks(PListEntry **Links, PListEntry **Files, PListEntry **Dirs)
751{ 350{
752 PListEntry *Link; 351 PListEntry *Link;
753 352
754 while ((Link = *Links) != NULL) { 353 while ((Link = *Links) != NULL) {
755 struct stat Stat; 354 struct stat Stat;
756 PListEntry *Ptr; 355 PListEntry *Ptr;
757 char *Basename; 356 char *Basename;
758 357
759 if (Link->pe_Left != NULL) 358 if (Link->pe_Left != NULL)
760 CheckSymLinks(&Link->pe_Left, Files, Dirs); 359 CheckSymLinks(&Link->pe_Left, Files, Dirs);
761 360
762 if ((stat(Link->pe_Name, &Stat) < 0) || 361 if ((stat(Link->pe_Name, &Stat) < 0) ||
763 !S_ISREG(Stat.st_mode)) { 362 !S_ISREG(Stat.st_mode)) {
764 Links = &Link->pe_Right; 363 Links = &Link->pe_Right;
765 continue; 364 continue;
766 } 365 }
767 366
768 (void)InsertPListEntry(Files, Link->pe_Name); 367 (void)PListInsert(Files, Link->pe_Name);
769 if ((Basename = strrchr(Link->pe_Name, '/')) != NULL) { 368 if ((Basename = strrchr(Link->pe_Name, '/')) != NULL) {
770 *Basename = '\0'; 369 *Basename = '\0';
771 if ((Ptr = FindPListEntry(*Dirs, 370 if ((Ptr = PListFind(*Dirs, Link->pe_Name)) != NULL)
772 Link->pe_Name)) != NULL) 
773 Ptr->pe_DirEmpty = false; 371 Ptr->pe_DirEmpty = false;
774 } 372 }
775 373
776 if (Link->pe_Right == NULL) { 374 if (Link->pe_Right == NULL) {
777 *Links = Link->pe_Left; 375 *Links = Link->pe_Left;
778 free(Link); 376 free(Link);
779 break; 377 break;
780 } 378 }
781 379
782 *Links = Link->pe_Right; 380 *Links = Link->pe_Right;
783 Ptr = Link->pe_Left; 381 Ptr = Link->pe_Left;
784 free(Link); 382 free(Link);
785 383
786 if (Ptr == NULL) 384 if (Ptr == NULL)
787 continue; 385 continue;
788 386
789 Link = *Links; 387 Link = *Links;
790 while (Link->pe_Left != NULL) 388 while (Link->pe_Left != NULL)
791 Link = Link->pe_Left; 389 Link = Link->pe_Left;
792 Link->pe_Left = Ptr; 390 Link->pe_Left = Ptr;
793 } 391 }
794} 392}
795 393
796static bool 394static bool
797CheckPrefix(char *Prefix, char *Name) 395CheckPrefix(const char *prefix, char *name)
798{ 396{
799 int Length; 397 size_t length;
800 398
801 Length = strlen(Prefix); 399 length = strlen(prefix);
802 return ((strncmp(Prefix, Name, Length) == 0) &&  400 return ((strncmp(prefix, name, length) == 0) &&
803 ((Name[Length] == '\0') || (Name[Length] == '/'))); 401 ((name[length] == '\0') || (name[length] == '/')));
804} 402}
805 403
806static char * 404static bool
807StripPrefix(char *Name, int Count) 405StripPrefix(char *name, int stripcount)
808{ 406{
809 char *NewName; 407 char *new_name;
810 408
811 if (Count <= 0) 409 if (stripcount <= 0)
812 return Name; 410 return true;
813 411
814 NewName = Name; 412 new_name = name;
815 while (Count-- > 0) { 413 while (stripcount-- > 0) {
816 NewName = strchr(NewName, '/'); 414 new_name = strchr(new_name, '/');
817 if (NewName == NULL) 415 if (new_name == NULL)
818 return NULL; 416 return false;
819 NewName++; 417 new_name++;
820 } 418 }
821 (void)memmove(Name, NewName, strlen(NewName) + 1); 419 (void)memmove(name, new_name, strlen(new_name) + 1);
822 420
823 return Name; 421 return true;
824} 422}
825 423
826int 424static void
827main(int argc, char **argv) 425ProcessRPM(const char *filename, PListEntry **files, PListEntry **dirs,
 426 char **ignore, const char *prefix, int stripcount)
828{ 427{
829 char *Progname; 428 int fd;
830 FILE *PListFile; 429 FileHandle *in;
831 char **Ignore, *Prefix; 430 PListEntry *last;
832 int Opt, Index, FD, StripCount; 
833 PListEntry *Files, *Dirs; 
834 FileHandle *In; 
835 
836 Progname = strrchr(argv[0], '/'); 
837 if (Progname == NULL) 
838 Progname = argv[0]; 
839 else 
840 Progname ++; 
841 431
842 PListFile = NULL; 432 if ((fd = open(filename, O_RDONLY, 0)) < 0) {
843 Ignore = NULL; 433 perror(filename);
844 Prefix = NULL; 434 exit(EXIT_FAILURE);
845 StripCount = 0; 435 }
846 while ((Opt = getopt(argc, argv, "s:d:f:i:p:")) != -1) { 436
847 switch (Opt) { 437 if (!IsRPMFile(fd)) {
848 case 's': 438 (void)fprintf(stderr, "%s: file is not an RPM package.\n",
849 StripCount = atoi(optarg); 439 filename);
850 if (StripCount <= 0) { 440 exit(EXIT_FAILURE);
851 (void)fprintf(stderr, 441 }
852 "%s: -s argument \"%s\" " 442
853 "must be a positive integer.\n", 443 if ((in = OpenRPM(&fd)) == NULL) {
854 Progname, optarg); 444 (void)fprintf(stderr, "%s: cannot get RPM data.\n", filename);
855 return EXIT_FAILURE; 445 exit(EXIT_FAILURE);
856 } 446 }
857 break; 447 if (fd >= 0) {
858 case 'f': 448 (void)close(fd);
859 if (PListFile != NULL) 449 fd = -1;
860 (void)fclose(PListFile); 450 }
861 if ((PListFile = fopen(optarg, "a")) == NULL) { 451
862 perror(optarg); 452 last = NULL;
863 return EXIT_FAILURE; 453 for (;;) {
864 } 454 unsigned long fields[CPIO_NUM_HEADERS];
865 break; 455 char *name;
866 case 'i': 456 mode_t mode;
867 Ignore = ArrayAdd(Ignore, optarg); 457 unsigned long length;
868 break; 458
869 case 'd': 459 if (!GetCPIOHeader(in, fields, &name)) {
870 if (chdir(optarg)) { 460 (void)fprintf(stderr,
871 perror(optarg); 461 "%s: error in cpio header.\n",
872 return EXIT_FAILURE; 462 filename);
873 } 463 exit(EXIT_FAILURE);
874 break; 464 }
875 case 'p': 465 if (strcmp(name, CPIO_END_MARKER) == 0) {
876 if (strlen(optarg) > 0) 466 free(name);
877 Prefix = optarg; 
878 break; 467 break;
879 default: 
880 Usage(Progname); 
881 } 468 }
882 } 469 if (*name == '\0')
 470 fields[CPIO_HDR_MODE] = 0;
 471
 472 if (ignore != NULL) {
 473 char **ptr;
883 474
884 argc -= optind; 475 for (ptr = ignore; *ptr != NULL; ptr++) {
885 argv += optind; 476 if (CheckPrefix(*ptr, name)) {
886 if (argc == 0) 477 fields[CPIO_HDR_MODE] = 0;
887 Usage(Progname); 478 break;
888 479 }
889 if ((Prefix != NULL) && (Prefix[strlen(Prefix) - 1] != '/')) 480 }
890 Prefix = StrCat(Prefix, "/"); 
891 
892 Files = NULL; 
893 Dirs = NULL; 
894 for (Index = 0; Index < argc ; Index++) { 
895 PListEntry *Last; 
896 
897 if ((FD = open(argv[Index], O_RDONLY, 0)) < 0) { 
898 perror(argv[Index]); 
899 return EXIT_FAILURE; 
900 } 481 }
901 482
902 if (!IsRPMFile(FD)) { 483 if (fields[CPIO_HDR_MODE] != 0 &&
 484 !StripPrefix(name, stripcount)) {
903 (void)fprintf(stderr, 485 (void)fprintf(stderr,
904 "%s: file is not an RPM package.\n", argv[Index]); 486 "%s: Leading path to strip too "
905 return EXIT_FAILURE; 487 "big (-s %d)\n",
 488 filename, stripcount);
 489 exit(EXIT_FAILURE);
906 } 490 }
907 491
908 if ((In = Open(FD)) == NULL) { 492 if (prefix != NULL) {
909 (void)fprintf(stderr, 493 char *fullname;
910 "%s: cannot get RPM data.\n", argv[Index]); 494
911 return EXIT_FAILURE; 495 fullname = StrCat(prefix, name);
 496 free(name);
 497 name = fullname;
912 } 498 }
913 499
914 Last = NULL; 500 mode = ConvertMode(fields[CPIO_HDR_MODE]);
915 for (;;) { 501 length = fields[CPIO_HDR_FILESIZE];
916 unsigned long Fields[CPIO_NUM_HEADERS]; 502 switch (fields[CPIO_HDR_MODE] & CP_IFMT) {
917 char *Name; 503 case C_ISDIR: {
918 mode_t Mode; 504 PListEntry *dir;
919 unsigned long Length; 505 bool old_dir;
920 506
921 if (!GetCPIOHeader(In, Fields, &Name)) { 507 if (length != 0) {
922 (void)fprintf(stderr, 508 (void)fprintf(stderr,
923 "%s: error in cpio header.\n", 509 "%s: error in cpio file.\n",
924 argv[Index]); 510 filename);
925 return EXIT_FAILURE; 511 exit(EXIT_FAILURE);
926 } 512 }
927 if (strcmp(Name, CPIO_END_MARKER) == 0) { 513
928 free(Name); 514 if (!MakeTargetDir(name, dirs)) {
929 break; 515 (void)fprintf(stderr,
 516 "%s: can't create parent "
 517 "directories for \"%s\".\n",
 518 filename, name);
 519 exit(EXIT_FAILURE);
930 } 520 }
931 if (*Name == '\0') 
932 Fields[CPIO_HDR_MODE] = 0; 
933 521
934 if (Ignore != NULL) { 522 if (!MakeDir(name, mode, &old_dir)) {
935 char **Ptr; 523 (void)fprintf(stderr,
 524 "%s: can't create directory "
 525 "\"%s\".\n", filename, name);
 526 exit(EXIT_FAILURE);
 527 }
936 528
937 Ptr = Ignore; 529 if (!old_dir) {
938 while (*Ptr != NULL) { 530 dir = PListInsert(dirs, name);
939 if (CheckPrefix(*Ptr, Name)) { 531 dir->pe_DirEmpty = true;
940 Fields[CPIO_HDR_MODE] = 0; 
941 break; 
942 } 
943 Ptr++; 
944 } 
945 } 532 }
 533 break;
 534 }
 535 case C_ISLNK: {
 536 char *link_target;
946 537
947 if (Fields[CPIO_HDR_MODE] != 0 && 538 if ((link_target = GetData(in, length)) == NULL) {
948 (Name = StripPrefix(Name, StripCount)) == NULL) { 
949 (void)fprintf(stderr, 539 (void)fprintf(stderr,
950 "%s: Leading path to strip too " 540 "%s: error in cpio file.\n",
951 "big (-s %d)\n",  541 filename);
952 argv[Index], StripCount); 542 exit(EXIT_FAILURE);
953 return EXIT_FAILURE; 
954 } 543 }
955 544
956 if (Prefix != NULL) { 545 if (!MakeTargetDir(name, dirs)) {
957 char *Fullname; 546 (void)fprintf(stderr,
958 547 "%s: can't create parent "
959 Fullname = StrCat(Prefix, Name); 548 "directories for \"%s\".\n",
960 free(Name); 549 filename, name);
961 Name = Fullname; 550 exit(EXIT_FAILURE);
962 } 551 }
963 552
964 Mode = ConvertMode(Fields[CPIO_HDR_MODE]); 553 if (*link_target == '/') {
965 Length = Fields[CPIO_HDR_FILESIZE]; 554 char *ptr;
966 switch (Fields[CPIO_HDR_MODE] & CP_IFMT) { 
967 case C_ISDIR: { 
968 PListEntry *Dir; 
969 int OldDir; 
970 
971 if (Length != 0) { 
972 (void)fprintf(stderr, 
973 "%s: error in cpio file.\n", 
974 argv[Index]); 
975 return EXIT_FAILURE; 
976 } 
977 555
978 if (!MakeTargetDir(Name, &Dirs)) { 556 (void)memmove(link_target, link_target + 1,
979 (void)fprintf(stderr,  557 strlen(link_target));
980 "%s: can't create parent " 558 ptr = name;
981 "directories for \"%s\".\n",  559 if (prefix != NULL)
982 argv[Index], Name); 560 ptr += strlen(prefix);
983 return EXIT_FAILURE; 
984 } 
985 561
986 if (!MakeDir(Name, Mode, &OldDir)) { 562 while ((ptr = strchr(ptr, '/')) != NULL) {
987 (void)fprintf(stderr,  563 char *new_link_target;
988 "%s: can't create directory " 
989 "\"%s\".\n", argv[Index], Name); 
990 return EXIT_FAILURE; 
991 } 
992 564
993 if (!OldDir) { 565 new_link_target = StrCat("../",
994 Dir = InsertPListEntry(&Dirs, Name); 566 link_target);
995 Dir->pe_DirEmpty = true; 567 free(link_target);
 568 link_target = new_link_target;
 569 ptr++;
996 } 570 }
997 break; 
998 } 571 }
999 case C_ISLNK: { 
1000 char *Link; 
1001 572
1002 if ((Link = GetData(In, Length)) == NULL) { 573 if (!MakeSymLink(link_target, name)) {
1003 (void)fprintf(stderr, 574 (void)fprintf(stderr,
1004 "%s: error in cpio file.\n", 575 "%s: can't create symbolic link "
1005 argv[Index]); 576 "\"%s\".\n", filename, name);
1006 return EXIT_FAILURE; 577 exit(EXIT_FAILURE);
1007 } 578 }
1008 579
1009 if (!MakeTargetDir(Name, &Dirs)) { 580 PListInsert(files, name)->pe_Link = link_target;
1010 (void)fprintf(stderr,  581 break;
1011 "%s: can't create parent " 582 }
1012 "directories for \"%s\".\n",  583 case C_ISREG:
1013 argv[Index], Name); 584 if (!MakeTargetDir(name, dirs)) {
1014 return EXIT_FAILURE; 585 (void)fprintf(stderr,
1015 } 586 "%s: can't create parent "
 587 "directories for \"%s\".\n",
 588 filename, name);
 589 exit(EXIT_FAILURE);
 590 }
1016 591
1017 if (*Link == '/') { 
1018 char *Ptr; 
1019 592
1020 (void)memmove(Link, Link + 1, 593 if ((last != NULL) && (last->pe_INode !=
1021 strlen(Link + 1) + 1); 594 fields[CPIO_HDR_INODE])) {
1022 Ptr = Name; 595 last = NULL;
1023 if (Prefix != NULL) 596 }
1024 Ptr += strlen(Prefix); 
1025 
1026 while ((Ptr = strchr(Ptr, '/')) 
1027 != NULL) { 
1028 char *NewLink; 
1029 
1030 NewLink = StrCat("../", Link); 
1031 free(Link); 
1032 Link = NewLink; 
1033 Ptr++; 
1034 } 
1035 } 
1036 597
1037 if (!MakeSymLink(Link, Name)) { 598 if (!WriteFile(in, name, mode, length,
1038 (void)fprintf(stderr,  599 (last != NULL)? last->pe_Name : NULL)) {
1039 "%s: can't create symbolic link " 600 (void)fprintf(stderr,
1040 "\"%s\".\n", argv[Index], Name); 601 "%s: can't write file \"%s\".\n",
1041 return EXIT_FAILURE; 602 filename, name);
1042 } 603 exit(EXIT_FAILURE);
 604 }
1043 605
1044 InsertPListEntry(&Files, Name)->pe_Link = Link; 606 last = PListInsert(files, name);
1045 break; 607 last->pe_INode = fields[CPIO_HDR_INODE];
 608 break;
 609 default:
 610 if (length > 0 && !SkipAndAlign(in, length)) {
 611 (void)fprintf(stderr,
 612 "%s: error in cpio file.\n",
 613 filename);
 614 exit(EXIT_FAILURE);
1046 } 615 }
1047 case C_ISREG: 616
1048 if (!MakeTargetDir(Name, &Dirs)) { 617 }
1049 (void)fprintf(stderr,  
1050 "%s: can't create parent " 
1051 "directories for \"%s\".\n",  
1052 argv[Index], Name); 
1053 return EXIT_FAILURE; 
1054 } 
1055 618
 619 free(name);
 620 }
1056 621
1057 if ((Last != NULL) && (Last->pe_INode !=  622 FileHandleClose(in);
1058 Fields[CPIO_HDR_INODE])) { 623}
1059 Last = NULL; 
1060 } 
1061 624
1062 if (!WriteFile(In, Name, Mode, Length, 625int
1063 (Last != NULL)? Last->pe_Name : NULL)) { 626main(int argc, char **argv)
1064 (void)fprintf(stderr,  627{
1065 "%s: can't write file \"%s\".\n",  628 char *progname;
1066 argv[Index],  629 FILE *plist_file;
1067 Name); 630 char **ignore, *prefix;
1068 return EXIT_FAILURE; 631 int opt, stripcount, i;
1069 } 632 PListEntry *files, *dirs;
 633
 634 progname = strrchr(argv[0], '/');
 635 if (progname == NULL)
 636 progname = argv[0];
 637 else
 638 progname++;
1070 639
1071 Last = InsertPListEntry(&Files, Name); 640 plist_file = NULL;
1072 Last->pe_INode = Fields[CPIO_HDR_INODE]; 641 ignore = NULL;
1073 break; 642 prefix = NULL;
1074 default: 643 stripcount = 0;
1075 if ((Length > 0) && 644 while ((opt = getopt(argc, argv, "d:f:i:p:s:")) != -1) {
1076 !SkipAndAlign(In, Length)) { 645 switch (opt) {
1077 (void)fprintf(stderr, 646 case 'd':
1078 "%s: error in cpio file.\n", 647 if (chdir(optarg)) {
1079 argv[Index]); 648 perror(optarg);
1080 return EXIT_FAILURE; 649 return EXIT_FAILURE;
1081 } 
1082  
1083 } 650 }
 651 break;
1084 652
1085 free(Name); 653 case 'f':
1086 } 654 if (plist_file != NULL)
 655 (void)fclose(plist_file);
 656 if ((plist_file = fopen(optarg, "a")) == NULL) {
 657 perror(optarg);
 658 return EXIT_FAILURE;
 659 }
 660 break;
 661
 662 case 'i':
 663 ignore = ArrayAdd(ignore, optarg);
 664 break;
1087 665
1088 Close(In); 666 case 'p':
1089 (void)close(FD); 667 if (strlen(optarg) > 0)
 668 prefix = optarg;
 669 break;
 670
 671 case 's':
 672 stripcount = atoi(optarg);
 673 if (stripcount <= 0) {
 674 (void)fprintf(stderr,
 675 "%s: -s argument \"%s\" "
 676 "must be a positive integer.\n",
 677 progname, optarg);
 678 return EXIT_FAILURE;
 679 }
 680 break;
 681
 682 default:
 683 Usage(progname);
 684 }
1090 } 685 }
1091 686
1092 if (PListFile != NULL) { 687 if (argc == optind)
1093 ProcessPList(Files, PListEntryFile, PListFile); 688 Usage(progname);
1094 ProcessPList(Dirs, PListEntryMakeDir, PListFile); 689
1095 (void)fclose(PListFile); 690 if (prefix != NULL && prefix[strlen(prefix) - 1] != '/')
 691 prefix = StrCat(prefix, "/");
 692
 693 files = NULL;
 694 dirs = NULL;
 695 for (i = optind; i < argc ; i++)
 696 ProcessRPM(argv[i], &files, &dirs, ignore, prefix, stripcount);
 697
 698 if (plist_file != NULL) {
 699 PListWrite(files, dirs, plist_file);
 700 (void)fclose(plist_file);
1096 } 701 }
1097 702
1098 return EXIT_SUCCESS; 703 return EXIT_SUCCESS;
1099} 704}