summaryrefslogtreecommitdiff
path: root/pkgtools
diff options
context:
space:
mode:
authortron <tron@pkgsrc.org>2004-02-18 21:29:37 +0000
committertron <tron@pkgsrc.org>2004-02-18 21:29:37 +0000
commitba25819afd30b4a25bc4084830087738121cb444 (patch)
tree8b9dab66e95a9794a0a2e7c7ea25e7444b6d3369 /pkgtools
parent227648818b04ae03a6b948844424a0d8ff3fbaf5 (diff)
downloadpkgsrc-ba25819afd30b4a25bc4084830087738121cb444.tar.gz
Update "rpm2pkg" package to version 2.0. Changes since version 1.3:
- added support for RPM archive compress with bzip2 as used by e.g. SuSE Linux 8.2. - (hopefully) made portable - rewrote ugly code for handling "-s" command line option - converted source to KNF
Diffstat (limited to 'pkgtools')
-rw-r--r--pkgtools/rpm2pkg/Makefile21
-rw-r--r--pkgtools/rpm2pkg/files/rpm2pkg.c1460
2 files changed, 834 insertions, 647 deletions
diff --git a/pkgtools/rpm2pkg/Makefile b/pkgtools/rpm2pkg/Makefile
index b9c3731cdf4..6293c9350b9 100644
--- a/pkgtools/rpm2pkg/Makefile
+++ b/pkgtools/rpm2pkg/Makefile
@@ -1,13 +1,12 @@
-# $NetBSD: Makefile,v 1.21 2004/02/08 04:03:15 jlam Exp $
+# $NetBSD: Makefile,v 1.22 2004/02/18 21:29:37 tron Exp $
-DISTNAME= rpm2pkg-1.3
-PKGREVISION= 1
+DISTNAME= rpm2pkg-2.0
CATEGORIES= pkgtools
MASTER_SITES= # empty
DISTFILES= # empty
MAINTAINER= tron@NetBSD.org
-HOMEPAGE= ftp://ftp.NetBSD.org/pub/NetBSD/packages/pkgsrc/Packages.txt
+HOMEPAGE= http://www.netbsd.org/Documentation/pkgsrc/
COMMENT= Convert RPM archives to NetBSD packages
CONFLICTS+= suse-base<=6.4
@@ -16,17 +15,25 @@ WRKSRC= ${WRKDIR}
USE_BUILDLINK2= YES
NO_CHECKSUM= YES
-CFLAGS+= ${BUILDLINK_CPPFLAGS.rpm}
-LIBS= -lrpm -lintl -lz
+CPPFLAGS+= ${BUILDLINK_CPPFLAGS.bzip2} ${BUILDLINK_CPPFLAGS.rpm} \
+ ${BUILDLINK_CPPFLAGS.zlib}
+LIBS= -lrpm -lintl -lz -lbz2
+
+.include "../../mk/bsd.prefs.mk"
+
+.if (${CC} == gcc)
+CFLAGS+= -Wall
+.endif
do-build:
- ${CC} ${CFLAGS} ${LDFLAGS} -o ${WRKSRC}/rpm2pkg \
+ ${CC} ${CFLAGS} ${CPPFLAGS} ${LDFLAGS} -o ${WRKSRC}/rpm2pkg \
${FILESDIR}/rpm2pkg.c ${LIBS}
do-install:
${INSTALL_PROGRAM} ${WRKSRC}/rpm2pkg ${PREFIX}/sbin
${INSTALL_MAN} ${FILESDIR}/rpm2pkg.8 ${PREFIX}/man/man8
+.include "../../archivers/bzip2/buildlink2.mk"
.include "../../devel/zlib/buildlink2.mk"
.include "../../misc/rpm/buildlink2.mk"
diff --git a/pkgtools/rpm2pkg/files/rpm2pkg.c b/pkgtools/rpm2pkg/files/rpm2pkg.c
index 6fead0ac2a3..b7ee246de18 100644
--- a/pkgtools/rpm2pkg/files/rpm2pkg.c
+++ b/pkgtools/rpm2pkg/files/rpm2pkg.c
@@ -1,8 +1,36 @@
-/*
-
- $NetBSD: rpm2pkg.c,v 1.3 2002/12/09 15:16:27 tron Exp $
-
-*/
+/* $NetBSD: rpm2pkg.c,v 1.4 2004/02/18 21:29:37 tron Exp $ */
+
+/*-
+ * Copyright (c) 2004 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.
+ * 3. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * 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 <sys/types.h>
#include <sys/stat.h>
@@ -14,10 +42,27 @@
#include <string.h>
#include <unistd.h>
-#include <cpio.h>
+#include <bzlib.h>
#include <rpmlib.h>
#include <zlib.h>
+#define C_IRUSR 0000400
+#define C_IWUSR 0000200
+#define C_IXUSR 0000100
+#define C_IRGRP 0000040
+#define C_IWGRP 0000020
+#define C_IXGRP 0000010
+#define C_IROTH 0000004
+#define C_IWOTH 0000002
+#define C_IXOTH 0000001
+#define C_ISUID 0004000
+#define C_ISGID 0002000
+#define C_ISVTX 0001000
+#define C_ISDIR 0040000
+#define C_ISREG 0100000
+#define C_ISCHR 0020000
+#define C_ISLNK 0120000
+
char CPIOMagic[] = {'0','7','0','7','0','1'};
#define CPIO_END_MARKER "TRAILER!!!"
@@ -31,726 +76,861 @@ char CPIOMagic[] = {'0','7','0','7','0','1'};
#define CP_IFMT 0170000
-#define TRUE 1
-#define FALSE 0
-
-#define GZREAD(s,b,l) (gzread((s),(b),(l))==l)
-
-extern char *__progname;
-
-struct ModeMap
- {
- long mm_CPIOMode;
- mode_t mm_SysMode;
- };
-struct ModeMap ModeMapTab[] =
- {
- {C_IRUSR,S_IRUSR},
- {C_IWUSR,S_IWUSR},
- {C_IXUSR,S_IXUSR},
- {C_IRGRP,S_IRGRP},
- {C_IWGRP,S_IWGRP},
- {C_IXGRP,S_IXGRP},
- {C_IROTH,S_IROTH},
- {C_IWOTH,S_IWOTH},
- {C_IXOTH,S_IXOTH},
- {C_ISUID,S_ISUID},
- {C_ISGID,S_ISGID},
- {C_ISVTX,S_ISVTX},
- {0,0}
- };
+#define TRUE 1
+#define FALSE 0
+
+typedef struct ModeMapStruct {
+ unsigned long mm_CPIOMode;
+ mode_t mm_SysMode;
+} ModeMap;
+
+ModeMap ModeMapTab[] = {
+ {C_IRUSR, S_IRUSR},
+ {C_IWUSR, S_IWUSR},
+ {C_IXUSR, S_IXUSR},
+ {C_IRGRP, S_IRGRP},
+ {C_IWGRP, S_IWGRP},
+ {C_IXGRP, S_IXGRP},
+ {C_IROTH, S_IROTH},
+ {C_IWOTH, S_IWOTH},
+ {C_IXOTH, S_IXOTH},
+ {C_ISUID, S_ISUID},
+ {C_ISGID, S_ISGID},
+ {C_ISVTX, S_ISVTX},
+ {0, 0}
+};
typedef struct PListEntryStruct PListEntry;
-struct PListEntryStruct
- {
- PListEntry *pe_Childs[2];
- int pe_DirEmpty;
- mode_t pe_DirMode;
- long pe_INode;
- char *pe_Link;
- char pe_Name[1];
- };
-
-#define pe_Left pe_Childs[0]
-#define pe_Right pe_Childs[1]
+struct PListEntryStruct {
+ PListEntry *pe_Childs[2];
+ int pe_DirEmpty;
+ mode_t pe_DirMode;
+ 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 *);
-#define PLIST_ORDER_FORWARD 0
-#define PLIST_ORDER_BACKWARD 1
-
-PListEntry *InsertPListEntry(PListEntry **Tree,char *Name)
+#define PLIST_ORDER_FORWARD 0
+#define PLIST_ORDER_BACKWARD 1
-{
- PListEntry *Node;
-
- while ((Node=*Tree)!=NULL)
- Tree=&((strcmp(Name,Node->pe_Name)<0)?Node->pe_Left:Node->pe_Right);
+#define INVERT_PLIST_ORDER(o) (1 - (o))
- if ((Node=malloc(sizeof(PListEntry)+strlen(Name)))==NULL)
- {
- perror(__progname);
- exit(EXIT_FAILURE);
- }
+typedef struct FileHandleStruct {
+ FILE *fh_File;
+ BZFILE *fh_BZFile;
+ gzFile *fh_GZFile;
+ off_t fh_Pos;
+} FileHandle;
- Node->pe_Left=NULL;
- Node->pe_Right=NULL;
- Node->pe_DirEmpty=FALSE;
- Node->pe_INode=0;
- Node->pe_Link=NULL;
- (void)strcpy(Node->pe_Name,Name);
+static int
+InitBuffer(void **Buffer,int *BufferSize)
+{
+ if (*Buffer == NULL) {
+ *BufferSize = sysconf(_SC_PAGESIZE) * 256;
+ if ((*Buffer = malloc(*BufferSize)) == NULL)
+ return FALSE;
+ }
+ return TRUE;
+}
- return *Tree=Node;
+static void
+Close(FileHandle *fh)
+{
+ if (fh->fh_BZFile != NULL) {
+ int bzerror;
+
+ (void)BZ2_bzReadClose(&bzerror, fh->fh_BZFile);
+ (void)fclose(fh->fh_File);
+ } else {
+ (void)gzclose(fh->fh_GZFile);
+ }
+ free(fh);
}
-PListEntry *FindPListEntry(PListEntry *Tree,char *Name)
+static FileHandle *
+Open(int fd)
+{
+ off_t offset;
+ char Magic[3];
+ FileHandle *fh;
+
+ if ((offset = lseek(fd, 0, SEEK_CUR)) < 0)
+ return NULL;
+ if (read(fd, Magic, sizeof (Magic)) != sizeof (Magic))
+ return NULL;
+ if (lseek(fd, offset, SEEK_SET) != offset)
+ return NULL;
+
+ if ((fh = calloc(1, sizeof (FileHandle))) == NULL)
+ return NULL;
+
+ if ((Magic[0] == 'B') && (Magic[1] == 'Z') && (Magic[2] == 'h')) {
+ int bzerror;
+
+ if ((fd = dup(fd)) < 0) {
+ free(fh);
+ return NULL;
+ }
+ if ((fh->fh_File = fdopen(fd, "rb")) == NULL) {
+ perror("fdopen");
+ (void)close(fd);
+ free(fh);
+ return NULL;
+ }
+ if ((fh->fh_BZFile = BZ2_bzReadOpen(&bzerror, fh->fh_File, 0,
+ 0, NULL, 0)) == NULL) {
+ (void)fclose(fh->fh_File);
+ free(fh);
+ return (NULL);
+ }
+ } else {
+ if ((fh->fh_GZFile = gzdopen(fd, "r")) == NULL) {
+ free(fh);
+ return (NULL);
+ }
+ }
+
+ return (fh);
+}
+static int
+Read(FileHandle *fh, void *buffer, int length)
{
- while (Tree!=NULL)
- {
- int Result;
+ int bzerror, bytes;
- if ((Result=strcmp(Name,Tree->pe_Name))==0) break;
- Tree=(Result<0)?Tree->pe_Left:Tree->pe_Right;
- }
+ bytes = (fh->fh_BZFile != NULL) ?
+ BZ2_bzRead(&bzerror, fh->fh_BZFile, buffer, length) :
+ gzread(fh->fh_GZFile, buffer, length);
+ if (bytes > 0)
+ fh->fh_Pos += bytes;
- return Tree;
+ return (bytes == length);
}
-void PListEntryFile(PListEntry *Node,FILE *Out)
+static int
+SkipAndAlign(FileHandle *fh, off_t Skip)
{
- (void)fputs(Node->pe_Name,Out);
- (void)fputc('\n',Out);
+ off_t NewPos;
+
+ NewPos = (fh->fh_Pos + Skip + 3) & ~3;
+ if (fh->fh_Pos == NewPos)
+ return TRUE;
+
+ if (fh->fh_GZFile != NULL) {
+ if (gzseek(fh->fh_GZFile, NewPos, SEEK_SET) == NewPos) {
+ fh->fh_Pos = NewPos;
+ return TRUE;
+ }
+ return FALSE;
+ } else {
+ static void *Buffer = NULL;
+ static int BufferSize = 0;
+
+ if (!InitBuffer(&Buffer, &BufferSize))
+ return FALSE;
+
+ while (fh->fh_Pos < NewPos) {
+ off_t Length;
+ int Chunk;
+
+ Length = NewPos - fh->fh_Pos;
+ Chunk = (Length > BufferSize) ? BufferSize : Length;
+ if (!Read(fh, Buffer, Chunk))
+ return FALSE;
+ }
+ }
+
+ return TRUE;
}
-void PListEntryLink(PListEntry *Node,FILE *Out)
+static PListEntry *
+InsertPListEntry(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;
+}
+
+static PListEntry *
+FindPListEntry(PListEntry *Tree, char *Name)
{
- (void)fprintf(Out,"@exec ln -fs %s %%D/%s\n",Node->pe_Link,Node->pe_Name);
- (void)fprintf(Out,"@unexec rm -f %%D/%s\n",Node->pe_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;
}
-void PListEntryMakeDir(PListEntry *Node,FILE *Out)
+static void
+PListEntryFile(PListEntry *Node, FILE *Out)
{
- if (Node->pe_DirEmpty)
- (void)fprintf(Out,
- "@exec mkdir -m %o -p %%D/%s\n",
- Node->pe_DirMode,
- Node->pe_Name);
+ (void)fputs(Node->pe_Name, Out);
+ (void)fputc('\n', Out);
}
-void PListEntryRemoveDir(PListEntry *Node,FILE *Out)
+static void
+PListEntryLink(PListEntry *Node, FILE *Out)
{
- (void)fprintf(Out,"@dirrm %s\n",Node->pe_Name);
+ (void)fprintf(Out, "@exec ln -fs %s %%D/%s\n@unexec rm -f %%D/%s\n",
+ Node->pe_Link, Node->pe_Name, Node->pe_Name);
}
-void ProcessPList(PListEntry *Tree,PListEntryFunc Func,int Order,FILE *Out)
+static void
+PListEntryMakeDir(PListEntry *Node, FILE *Out)
{
- while (Tree!=NULL)
- {
- if (Tree->pe_Childs[Order]!=NULL)
- ProcessPList(Tree->pe_Childs[Order],Func,Order,Out);
- Func(Tree,Out);
- Tree=Tree->pe_Childs[1-Order];
- }
+ if (Node->pe_DirEmpty) {
+ (void)fprintf(Out, "@exec mkdir -m %o -p %%D/%s\n",
+ Node->pe_DirMode, Node->pe_Name);
+ }
}
-char **ArrayAdd(char **Array,char *String)
+static void
+PListEntryRemoveDir(PListEntry *Node, FILE *Out)
{
- int Old;
-
- Old=0;
- if (Array!=NULL) while (Array[Old]!=NULL) Old++;
- if ((Array=realloc(Array,sizeof(char *)*(Old+2)))==NULL) return NULL;
+ (void)fprintf(Out, "@dirrm %s\n", Node->pe_Name);
+}
- Array[Old++]=String;
- Array[Old]=NULL;
+static void
+ProcessPList(PListEntry *Tree, PListEntryFunc Func, int Order, FILE *Out)
- return Array;
+{
+ while (Tree != NULL) {
+ if (Tree->pe_Childs[Order] != NULL)
+ ProcessPList(Tree->pe_Childs[Order], Func, Order, Out);
+ Func(Tree, Out);
+ Tree = Tree->pe_Childs[INVERT_PLIST_ORDER(Order)];
+ }
}
-void Usage(void)
+static char **
+ArrayAdd(char **Array, char *String)
{
- (void)fprintf(stderr,
- "Usage: %s [-d directory] [-f packlist] [[-i ignorepath] ...]\n"
- " [-p prefix] [-s strippath] rpmfile [...]\n",
- __progname);
- exit(EXIT_FAILURE);
+ int Old;
+
+ Old = 0;
+ if (Array != NULL) {
+ while (Array[Old] != NULL)
+ Old ++;
+ }
+ if ((Array = realloc(Array, sizeof (char *) * (Old + 2))) == NULL) {
+ perror("realloc");
+ exit(EXIT_FAILURE);
+ }
+
+ Array[Old++] = String;
+ Array[Old] = NULL;
+
+ return Array;
}
-int SkipAndAlign(gzFile In,long Skip)
+static void
+Usage(char *Progname)
+{
+ (void)fprintf(stderr,
+ "Usage: %s [-d directory] [-f packlist] [[-i ignorepath] ...]\n"
+ " [-p prefix] [-s stripcount] rpmfile [...]\n",
+ Progname);
+ exit(EXIT_FAILURE);
+}
+static char *
+GetData(FileHandle *In, unsigned long Length)
{
- z_off_t Pos,NewPos;
+ char *Ptr;
- if ((Pos=gztell(In))<0) return FALSE;
+ if ((Ptr = malloc(Length + 1)) != NULL) {
+ if (Read(In, Ptr, Length) && SkipAndAlign(In, 0)) {
+ Ptr[Length] = '\0';
+ return Ptr;
+ }
+ free(Ptr);
+ }
- NewPos=(Pos+Skip+3)&(~3);
- return ((Pos==NewPos)||(gzseek(In,NewPos,SEEK_SET)==NewPos));
+ return NULL;
}
-char *GetData(gzFile In,long Length)
-
+static int
+GetCPIOHeader(FileHandle *In, unsigned long *Fields, char **Name)
{
- char *Ptr;
-
- if ((Ptr=malloc(Length+1))!=NULL)
- {
- if (GZREAD(In,Ptr,Length)&&SkipAndAlign(In,0))
- {
- Ptr[Length]='\0';
- return Ptr;
- }
- free(Ptr);
- }
-
- return NULL;
+ char Buffer[CPIO_NUM_HEADERS*CPIO_FIELD_LENGTH], *Ptr;
+ int Index;
+ unsigned long Value;
+
+ *Name = NULL;
+
+ if (!Read(In, Buffer, sizeof (CPIOMagic)))
+ return FALSE;
+ if (memcmp(Buffer, CPIOMagic, sizeof (CPIOMagic)) != 0)
+ return FALSE;
+
+ if (!Read(In, Buffer, sizeof (Buffer)))
+ return FALSE;
+
+ Ptr = Buffer;
+ Index = sizeof (Buffer);
+ Value = 0;
+ while (Index-- > 0) {
+ Value <<= 4;
+ if ((*Ptr >= '0') && (*Ptr <= '9')) {
+ Value += (unsigned long)(*Ptr++-'0');
+ } else if ((*Ptr >= 'A') && (*Ptr <= 'F')) {
+ Value += (unsigned long)(*Ptr++-'A') + 10;
+ } else if ((*Ptr >= 'a') && (*Ptr <= 'f')) {
+ Value += (unsigned long)(*Ptr++-'a') + 10;
+ } else {
+ return FALSE;
+ }
+
+ if ((Index % CPIO_FIELD_LENGTH) == 0) {
+ *Fields++ = Value;
+ Value = 0;
+ }
+ }
+
+ Value = Fields[CPIO_HDR_NAMESIZE - CPIO_NUM_HEADERS];
+ if ((*Name = GetData(In, Value)) == NULL)
+ return FALSE;
+ return ((*Name)[Value -1 ] == '\0');
}
-int GetCPIOHeader(gzFile In,long *Fields,char **Name)
-
+static mode_t
+ConvertMode(unsigned long CPIOMode)
{
- char Buffer[CPIO_NUM_HEADERS*CPIO_FIELD_LENGTH];
- char *Ptr;
- int Index;
- long Value;
-
- *Name=NULL;
-
- if (!GZREAD(In,Buffer,sizeof(CPIOMagic))) return FALSE;
- if (memcmp(Buffer,CPIOMagic,sizeof(CPIOMagic))!=0) return FALSE;
-
- if (gzread(In,Buffer,sizeof(Buffer))!=sizeof(Buffer)) return FALSE;
- Ptr=Buffer;
- Index=sizeof(Buffer);
- Value=0;
- while (Index-->0)
- {
- Value<<=4;
- if ((*Ptr>='0')&&(*Ptr<='9')) Value+=(long)(*Ptr++-'0');
- else
- if ((*Ptr>='A')&&(*Ptr<='F')) Value+=(long)(*Ptr++-'A')+10;
- else
- if ((*Ptr>='a')&&(*Ptr<='f')) Value+=(long)(*Ptr++-'a')+10;
- else return FALSE;
-
- if ((Index%CPIO_FIELD_LENGTH)==0)
- {
- *Fields++=Value;
- Value=0;
- }
- }
-
- Value=Fields[CPIO_HDR_NAMESIZE-CPIO_NUM_HEADERS];
- if ((*Name=GetData(In,Value))==NULL) return FALSE;
- return ((*Name)[Value-1]=='\0');
+ mode_t Mode;
+ ModeMap *Ptr;
+
+ Mode = 0;
+ Ptr = ModeMapTab;
+ while (Ptr->mm_CPIOMode != 0) {
+ if ((CPIOMode & Ptr->mm_CPIOMode) != 0)
+ Mode |= Ptr->mm_SysMode;
+ Ptr++;
+ }
+
+ return Mode;
}
-mode_t ConvertMode(long CPIOMode)
-
+static int
+MakeTargetDir(char *Name, PListEntry **Dirs, int MarkNonEmpty)
{
- mode_t Mode;
- int Index;
-
- Mode=0;
- Index=0;
- while (ModeMapTab[Index].mm_CPIOMode!=0)
- {
- if ((CPIOMode&ModeMapTab[Index].mm_CPIOMode)!=0)
- Mode|=ModeMapTab[Index].mm_SysMode;
- Index++;
- }
-
- return Mode;
+ char *Basename;
+ PListEntry *Dir;
+ struct stat Stat;
+ int Result;
+
+ if ((Basename = strrchr(Name, '/')) == NULL)
+ return TRUE;
+
+ *Basename = '\0';
+ if ((Dir = FindPListEntry(*Dirs, Name)) != NULL) {
+ *Basename = '/';
+ Dir->pe_DirEmpty = !MarkNonEmpty;
+ return TRUE;
+ }
+
+ if (!MakeTargetDir(Name, Dirs, TRUE)) {
+ *Basename = '/';
+ return FALSE;
+ }
+
+ if (stat(Name, &Stat) == 0) {
+ Result = S_ISDIR(Stat.st_mode);
+ } else if (errno != ENOENT) {
+ Result = FALSE;
+ } else if ((Result = (mkdir(Name, S_IRWXU|S_IRWXG|S_IRWXO) == 0))) {
+ InsertPListEntry(Dirs, Name)->pe_DirMode =
+ S_IRWXU|S_IRWXG|S_IRWXO;
+ }
+
+ *Basename = '/';
+ return Result;
}
-int MakeTargetDir(char *Name,PListEntry **Dirs,int MarkNonEmpty)
-
+static char
+*StrCat(char *Prefix, char *Suffix)
{
- char *Basename;
- PListEntry *Dir;
- struct stat Stat;
- int Result;
-
- if ((Basename=strrchr(Name,'/'))==NULL) return TRUE;
-
- *Basename='\0';
- if ((Dir=FindPListEntry(*Dirs,Name))!=NULL)
- {
- *Basename='/';
- Dir->pe_DirEmpty=!MarkNonEmpty;
- return TRUE;
- }
-
- if (!MakeTargetDir(Name,Dirs,TRUE))
- {
- *Basename='/';
- return FALSE;
- }
-
- if (stat(Name,&Stat)==0) Result=S_ISDIR(Stat.st_mode);
- else
- if (errno!=ENOENT) Result=FALSE;
- else
- if ((Result=(mkdir(Name,S_IRWXU|S_IRWXG|S_IRWXO)==0)))
- InsertPListEntry(Dirs,Name)->pe_DirMode=S_IRWXU|S_IRWXG|S_IRWXO;
-
- *Basename='/';
- return Result;
-}
+ int Length;
+ char *Str;
-char *StrCat(char *Prefix,char *Suffix)
+ Length = strlen(Prefix);
+ if ((Str = malloc(Length + strlen(Suffix) + 1)) == NULL) {
+ perror("malloc");
+ exit(EXIT_FAILURE);
+ }
-{
- int Length;
- char *Str;
-
- Length=strlen(Prefix);
- if ((Str=malloc(Length+strlen(Suffix)+1))!=NULL)
- {
- (void)memcpy(Str,Prefix,Length);
- (void)strcpy(&Str[Length],Suffix);
- }
- return Str;
-}
+ (void)memcpy(Str, Prefix, Length);
+ (void)strcpy(&Str[Length], Suffix);
-int MakeDir(char *Name,mode_t Mode,int *OldDir)
+ return Str;
+}
+static int
+MakeDir(char *Name, mode_t Mode, int *OldDir)
{
- struct stat Stat;
+ struct stat Stat;
- *OldDir=FALSE;
- if (mkdir(Name,Mode)==0) return TRUE;
+ *OldDir = FALSE;
+ if (mkdir(Name, Mode) == 0)
+ return TRUE;
- if ((errno!=EEXIST)||
- (lstat(Name,&Stat)<0)||
- !S_ISDIR(Stat.st_mode)) return FALSE;
+ if ((errno != EEXIST) || (lstat(Name, &Stat) < 0) ||
+ !S_ISDIR(Stat.st_mode)) {
+ return FALSE;
+ }
- *OldDir=TRUE;
- return TRUE;
+ *OldDir = TRUE;
+ return TRUE;
}
-int MakeSymLink(char *Link,char *Name)
-
+static int
+MakeSymLink(char *Link, char *Name)
{
- struct stat Stat;
+ struct stat Stat;
- if (symlink(Link,Name)==0) return TRUE;
+ if (symlink(Link, Name) == 0) return TRUE;
- if ((errno!=EEXIST)||
- (lstat(Name,&Stat)<0)||
- !S_ISLNK(Stat.st_mode)) return FALSE;
+ if ((errno != EEXIST) || (lstat(Name, &Stat) < 0) ||
+ !S_ISLNK(Stat.st_mode)) {
+ return FALSE;
+ }
- return ((unlink(Name)==0)&&(symlink(Link,Name)==0));
+ return ((unlink(Name) == 0) && (symlink(Link, Name) == 0));
}
-int WriteFile(gzFile In,char *Name,mode_t Mode,long Length,char *Link)
-
+static int
+WriteFile(FileHandle *In, char *Name, mode_t Mode, unsigned long Length,
+ char *Link)
{
- int Out;
- struct stat Stat;
- static void *Buffer=NULL;
- static long BufferSize=0;
-
- if (lstat(Name,&Stat)==0)
- if (!S_ISREG(Stat.st_mode)||(unlink(Name)<0)) return FALSE;
-
- if (Buffer==NULL)
- {
- BufferSize=sysconf(_SC_PAGESIZE)*256;
- if ((Buffer=malloc(BufferSize))==NULL) return FALSE;
- }
-
- if (Link!=NULL)
- {
- if (link(Link,Name)<0) return FALSE;
- Out=open(Name,O_WRONLY,Mode);
- }
- else Out=open(Name,O_WRONLY|O_CREAT,Mode);
- if (Out<0) return FALSE;
-
- while (Length>0)
- {
- long Chunk;
-
- Chunk=(Length>BufferSize)?BufferSize:Length;
- if (!GZREAD(In,Buffer,Chunk)) break;
- if (write(Out,Buffer,Chunk)!=Chunk) break;
- Length-=Chunk;
- }
-
- if ((close(Out)==0)&&(Length==0)) return SkipAndAlign(In,0);
-
- (void)unlink(Name);
- return FALSE;
+ int Out;
+ struct stat Stat;
+ static void *Buffer = NULL;
+ static int BufferSize = 0;
+
+ if ((lstat(Name, &Stat) == 0) &&
+ (!S_ISREG(Stat.st_mode) || (unlink(Name) < 0))) {
+ return FALSE;
+ }
+
+ if (!InitBuffer(&Buffer, &BufferSize))
+ return FALSE;
+
+ if (Link != NULL) {
+ if (link(Link, Name) < 0)
+ return FALSE;
+ Out = open(Name, O_WRONLY, Mode);
+ } else {
+ Out = open(Name, O_WRONLY|O_CREAT, Mode);
+ }
+ if (Out < 0)
+ return FALSE;
+
+ while (Length > 0) {
+ int Chunk;
+
+ Chunk = (Length > BufferSize) ? BufferSize : Length;
+ if (!Read(In, Buffer, Chunk) ||
+ (write(Out, Buffer, Chunk) != Chunk))
+ break;
+ Length -= Chunk;
+ }
+
+ if ((close(Out) == 0) && (Length == 0))
+ return SkipAndAlign(In, 0);
+
+ (void)unlink(Name);
+ return FALSE;
}
-void CheckSymLinks(PListEntry **Links,PListEntry **Files,PListEntry **Dirs)
+static void
+CheckSymLinks(PListEntry **Links, PListEntry **Files, PListEntry **Dirs)
+{
+ PListEntry *Link;
+
+ while ((Link = *Links) != NULL) {
+ struct stat Stat;
+ PListEntry *Ptr;
+ char *Basename;
+
+ if (Link->pe_Left != NULL)
+ CheckSymLinks(&Link->pe_Left, Files, Dirs);
+
+ if ((stat(Link->pe_Name, &Stat) < 0) ||
+ !S_ISREG(Stat.st_mode)) {
+ Links = &Link->pe_Right;
+ continue;
+ }
+
+ (void)InsertPListEntry(Files, Link->pe_Name);
+ if ((Basename = strrchr(Link->pe_Name, '/')) != NULL) {
+ *Basename = '\0';
+ if ((Ptr = FindPListEntry(*Dirs,
+ Link->pe_Name)) != NULL)
+ Ptr->pe_DirEmpty = FALSE;
+ }
+
+ if (Link->pe_Right == NULL) {
+ *Links = Link->pe_Left;
+ free(Link);
+ break;
+ }
+
+ *Links = Link->pe_Right;
+ Ptr = Link->pe_Left;
+ free(Link);
+
+ if (Ptr == NULL)
+ continue;
+
+ Link = *Links;
+ while (Link->pe_Left != NULL)
+ Link = Link->pe_Left;
+ Link->pe_Left = Ptr;
+ }
+}
+static int
+CheckPrefix(char *Prefix, char *Name)
{
- PListEntry *Link;
- struct stat Stat;
-
- while ((Link=*Links)!=NULL)
- {
- PListEntry *Ptr;
- char *Basename;
-
- if (Link->pe_Left!=NULL)
- CheckSymLinks(&Link->pe_Left,Files,Dirs);
-
- if ((stat(Link->pe_Name,&Stat)<0)||!S_ISREG(Stat.st_mode))
- {
- Links=&Link->pe_Right;
- continue;
- }
-
- (void)InsertPListEntry(Files,Link->pe_Name);
- if ((Basename=strrchr(Link->pe_Name,'/'))!=NULL)
- {
- *Basename='\0';
- if ((Ptr=FindPListEntry(*Dirs,Link->pe_Name))!=NULL)
- Ptr->pe_DirEmpty=FALSE;
- }
-
- if (Link->pe_Right==NULL)
- {
- *Links=Link->pe_Left;
- free(Link);
- break;
- }
-
- *Links=Link->pe_Right;
- Ptr=Link->pe_Left;
- free(Link);
-
- if (Ptr==NULL) continue;
-
- Link=*Links;
- while (Link->pe_Left!=NULL) Link=Link->pe_Left;
- Link->pe_Left=Ptr;
- }
+ int Length;
+
+ Length = strlen(Prefix);
+ return ((strncmp(Prefix, Name, Length) == 0) &&
+ ((Name[Length] == '\0') || (Name[Length] == '/')));
}
-int main(int argc,char **argv)
+static char *
+StripPrefix(char *Name, int Count)
+{
+ char *NewName;
+
+ if (Count <= 0)
+ return Name;
+
+ NewName = Name;
+ while (Count-- > 0) {
+ NewName = strchr(NewName, '/');
+ if (NewName == NULL)
+ return NULL;
+ NewName++;
+ }
+ (void)memmove(Name, NewName, strlen(NewName) + 1);
+
+ return Name;
+}
+int
+main(int argc, char **argv)
{
- FILE *PList;
- char **Ignore,*Prefix;
- int Opt,Index,FD,IsSource,PathIndex,StripPath;
- PListEntry *Files,*Links,*Dirs;
- Header Hdr;
- gzFile In;
-
- PList=NULL;
- Ignore=NULL;
- Prefix=NULL;
- StripPath = 0;
- while ((Opt=getopt(argc,argv,"s:d:f:i:p:"))!=-1)
- switch (Opt)
- {
- case 's':
- StripPath=atoi(optarg);
- if (StripPath == 0) {
- fprintf(stderr,"Warning: -s argument to %s should be a positive integer, ignoring supplied argument\n",argv[Index]);
- }
- break;
- case 'f':
- if (PList!=NULL) (void)fclose(PList);
- if ((PList=fopen(optarg,"a"))==NULL)
- {
- perror(optarg);
- return EXIT_FAILURE;
- }
- break;
- case 'i':
- if ((Ignore=ArrayAdd(Ignore,optarg))==NULL)
- {
- perror(__progname);
- exit(EXIT_FAILURE);
- }
- break;
- case 'd':
- if (chdir(optarg))
- {
- perror(optarg);
- return EXIT_FAILURE;
- }
- break;
- case 'p':
- Prefix=optarg;
- break;
- default:
- Usage();
- }
-
- if (Prefix!=NULL)
- {
- int Length;
-
- Length=strlen(Prefix);
- if (Length==0) Prefix=NULL;
- else
- if ((Prefix[Length-1]!='/')&&((Prefix=StrCat(Prefix,"/"))==NULL))
- {
- perror(__progname);
- exit(EXIT_FAILURE);
- }
- }
-
- argc-=optind;
- argv+=optind;
- if (argc==0) Usage();
-
- Files=NULL;
- Links=NULL;
- Dirs=NULL;
- for (Index=0; Index<argc; Index++)
- {
- PListEntry *Last;
-
- if ((FD=open(argv[Index],O_RDONLY,0))<0)
- {
- perror(argv[Index]);
- return EXIT_FAILURE;
- }
-
- switch (rpmReadPackageHeader(FD,&Hdr,&IsSource,NULL,NULL))
- {
- case 0:
- break;
- case 1:
- (void)fprintf(stderr,"%s: file is not an RPM package.\n",argv[Index]);
- return EXIT_FAILURE;
- default:
- (void)fprintf(stderr,"%s: error reading header.\n",argv[Index]);
- return EXIT_FAILURE;
- }
-
- if ((In=gzdopen(FD,"r"))==NULL)
- {
- (void)fprintf(stderr,"%s: cannot read cpio data.\n",argv[Index]);
- return EXIT_FAILURE;
- }
-
- Last=NULL;
- for (;;)
- {
- long Fields[CPIO_NUM_HEADERS];
- char *Name;
- char *NewName;
- char *TmpName;
- mode_t Mode;
- long Length;
-
- if (!GetCPIOHeader(In,Fields,&Name))
- {
- (void)fprintf(stderr,"%s: error in cpio header.\n",argv[Index]);
- return EXIT_FAILURE;
- }
- if (strcmp(Name,CPIO_END_MARKER)==0)
- {
- free(Name);
- break;
- }
- if (*Name=='\0') Fields[CPIO_HDR_MODE]=0;
-
- if (Ignore!=NULL)
- {
- char **Ptr;
-
- Ptr=Ignore;
- while (*Ptr!=NULL)
- {
- int Length;
-
- Length=strlen(*Ptr);
- if ((strncmp(*Ptr,Name,Length)==0)&&
- ((Name[Length]=='\0')||(Name[Length]=='/'))) break;
- else Ptr++;
- }
- if (*Ptr!=NULL) Fields[CPIO_HDR_MODE]=0;
- }
-
- for (PathIndex=1; PathIndex<=StripPath; PathIndex++) {
- NewName=Name;
- do {
- NewName++;
- if (NewName[0]=='\0') {
- fprintf(stderr,"%s: Leading path to strip too big (-s %d)\n",
- argv[Index], StripPath);
- return EXIT_FAILURE;
- }
- } while (NewName[0]!='/');
- NewName++; /* We ended up with a leading /, and this must disapear */
- TmpName=malloc(strlen(NewName));
- if (TmpName==NULL)
- {
- perror(__progname);
- exit(EXIT_FAILURE);
- }
- strcpy(TmpName, NewName);
- free(Name);
- Name=TmpName;
- }
-
- if (Prefix!=NULL)
- {
- char *Fullname;
-
- if ((Fullname=StrCat(Prefix,Name))==NULL)
- {
- perror(__progname);
- exit(EXIT_FAILURE);
- }
- free(Name);
- Name=Fullname;
- }
-
- Mode=ConvertMode(Fields[CPIO_HDR_MODE]);
- Length=Fields[CPIO_HDR_FILESIZE];
- switch (Fields[CPIO_HDR_MODE]&CP_IFMT)
- {
- case C_ISDIR:
- {
- PListEntry *Dir;
- int OldDir;
-
- if (Length!=0)
- {
- (void)fprintf(stderr,"%s: error in cpio file.\n",argv[Index]);
- return EXIT_FAILURE;
- }
- if (!MakeTargetDir(Name,&Dirs,TRUE))
- {
- (void)fprintf(stderr,
- "%s: can't create parent directories for \"%s\".\n",
- argv[Index],
- Name);
- return EXIT_FAILURE;
- }
-
- if (!MakeDir(Name,Mode,&OldDir))
- {
- (void)fprintf(stderr,
- "%s: can't create directory \"%s\".\n",
- argv[Index],
- Name);
- return EXIT_FAILURE;
- }
-
- if (!OldDir)
- {
- Dir=InsertPListEntry(&Dirs,Name);
- Dir->pe_DirEmpty=TRUE;
- Dir->pe_DirMode=Mode;
- }
- break;
- }
- case C_ISLNK:
- {
- char *Link;
- struct stat Stat;
-
- if ((Link=GetData(In,Length))==NULL)
- {
- (void)fprintf(stderr,"%s: error in cpio file.\n",argv[Index]);
- return EXIT_FAILURE;
- }
-
- if (!MakeTargetDir(Name,&Dirs,FALSE))
- {
- (void)fprintf(stderr,
- "%s: can't create parent directories for \"%s\".\n",
- argv[Index],
- Name);
- return EXIT_FAILURE;
- }
-
- if (*Link=='/')
- {
- char *Ptr;
-
- (void)strcpy(Link,Link+1);
- Ptr=Name;
- if (Prefix!=NULL) Ptr+=strlen(Prefix);
- while ((Ptr=strchr(Ptr,'/'))!=NULL)
- {
- char *NewLink;
-
- if ((NewLink=StrCat("../",Link))==NULL)
- {
- perror(__progname);
- return EXIT_FAILURE;
- }
- free(Link);
- Link=NewLink;
-
- Ptr++;
- }
- }
- if (!MakeSymLink(Link,Name))
- {
- (void)fprintf(stderr,
- "%s: can't create symbolic link \"%s\".\n",
- argv[Index],
- Name);
- return EXIT_FAILURE;
- }
-
- InsertPListEntry(&Links,Name)->pe_Link=Link;
- break;
- }
- case C_ISREG:
- if (!MakeTargetDir(Name,&Dirs,TRUE))
- {
- (void)fprintf(stderr,
- "%s: can't create parent directories for \"%s\".\n",
- argv[Index],
- Name);
- return EXIT_FAILURE;
- }
-
- if ((Last!=NULL)&&(Last->pe_INode!=Fields[CPIO_HDR_INODE]))
- Last=NULL;
-
- if (!WriteFile(In,Name,Mode,Length,(Last!=NULL)?Last->pe_Name:NULL))
- {
- (void)fprintf(stderr,
- "%s: can't write file \"%s\".\n",
- argv[Index],
- Name);
- return EXIT_FAILURE;
- }
-
- Last=InsertPListEntry(&Files,Name);
- Last->pe_INode=Fields[CPIO_HDR_INODE];
- break;
- default:
- if ((Length>0)&&(gzseek(In,(Length+3)&(~3),SEEK_CUR)<0)) break;
- }
-
- free(Name);
- }
-
- (void)gzclose(In);
- (void)close(FD);
- }
-
- if (PList!=NULL)
- {
- ProcessPList(Files,PListEntryFile,PLIST_ORDER_FORWARD,PList);
- ProcessPList(Dirs,PListEntryMakeDir,PLIST_ORDER_FORWARD,PList);
- ProcessPList(Links,PListEntryLink,PLIST_ORDER_FORWARD,PList);
- ProcessPList(Dirs,PListEntryRemoveDir,PLIST_ORDER_BACKWARD,PList);
- (void)fclose(PList);
- }
-
- return EXIT_SUCCESS;
+ char *Progname;
+ FILE *PListFile;
+ char **Ignore, *Prefix;
+ int Opt, Index, FD, IsSource, StripCount;
+ PListEntry *Files, *Links, *Dirs;
+ Header Hdr;
+ FileHandle *In;
+
+ Progname = strrchr(argv[0], '/');
+ if (Progname == NULL)
+ Progname = argv[0];
+ else
+ Progname ++;
+
+ PListFile = NULL;
+ Ignore = NULL;
+ Prefix = NULL;
+ StripCount = 0;
+ while ((Opt = getopt(argc, argv, "s:d:f:i:p:")) != -1) {
+ switch (Opt) {
+ case 's':
+ StripCount = atoi(optarg);
+ if (StripCount <= 0) {
+ (void)fprintf(stderr,
+ "%s: -s argument \"%s\" "
+ "must be a positive integer.\n",
+ Progname, optarg);
+ return EXIT_FAILURE;
+ }
+ break;
+ case 'f':
+ if (PListFile != NULL)
+ (void)fclose(PListFile);
+ if ((PListFile = fopen(optarg, "a")) == NULL) {
+ perror(optarg);
+ return EXIT_FAILURE;
+ }
+ break;
+ case 'i':
+ Ignore = ArrayAdd(Ignore, optarg);
+ break;
+ case 'd':
+ if (chdir(optarg)) {
+ perror(optarg);
+ return EXIT_FAILURE;
+ }
+ break;
+ case 'p':
+ if (strlen(optarg) > 0)
+ Prefix = optarg;
+ break;
+ default:
+ Usage(Progname);
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+ if (argc == 0)
+ Usage(Progname);
+
+ if ((Prefix != NULL) && (Prefix[strlen(Prefix) - 1] != '/'))
+ Prefix = StrCat(Prefix, "/");
+
+ Files = NULL;
+ Links = NULL;
+ Dirs = NULL;
+ for (Index = 0; Index < argc ; Index++) {
+ PListEntry *Last;
+
+ if ((FD = open(argv[Index], O_RDONLY, 0)) < 0) {
+ perror(argv[Index]);
+ return EXIT_FAILURE;
+ }
+
+ switch (rpmReadPackageHeader(FD, &Hdr, &IsSource, NULL,
+ NULL)) {
+ case 0:
+ break;
+ case 1:
+ (void)fprintf(stderr,
+ "%s: file is not an RPM package.\n", argv[Index]);
+ return EXIT_FAILURE;
+ default:
+ (void)fprintf(stderr, "%s: error reading header.\n",
+ argv[Index]);
+ return EXIT_FAILURE;
+ }
+
+ if ((In = Open(FD)) == NULL) {
+ (void)fprintf(stderr,
+ "%s: cannot read cpio data.\n", argv[Index]);
+ return EXIT_FAILURE;
+ }
+
+ Last = NULL;
+ for (;;) {
+ unsigned long Fields[CPIO_NUM_HEADERS];
+ char *Name;
+ mode_t Mode;
+ unsigned long Length;
+
+ if (!GetCPIOHeader(In, Fields, &Name)) {
+ (void)fprintf(stderr,
+ "%s: error in cpio header.\n",
+ argv[Index]);
+ return EXIT_FAILURE;
+ }
+ if (strcmp(Name, CPIO_END_MARKER) == 0) {
+ free(Name);
+ break;
+ }
+ if (*Name == '\0')
+ Fields[CPIO_HDR_MODE] = 0;
+
+ if (Ignore != NULL) {
+ char **Ptr;
+
+ Ptr = Ignore;
+ while (*Ptr != NULL) {
+ if (CheckPrefix(*Ptr, Name)) {
+ Fields[CPIO_HDR_MODE] = 0;
+ break;
+ }
+ Ptr++;
+ }
+ }
+
+ if ((Name = StripPrefix(Name, StripCount)) == NULL) {
+ (void)fprintf(stderr,
+ "%s: Leading path to strip too "
+ "big (-s %d)\n",
+ argv[Index], StripCount);
+ return EXIT_FAILURE;
+ }
+
+ if (Prefix != NULL) {
+ char *Fullname;
+
+ Fullname = StrCat(Prefix, Name);
+ free(Name);
+ Name = Fullname;
+ }
+
+ Mode = ConvertMode(Fields[CPIO_HDR_MODE]);
+ Length = Fields[CPIO_HDR_FILESIZE];
+ switch (Fields[CPIO_HDR_MODE] & CP_IFMT) {
+ case C_ISDIR: {
+ PListEntry *Dir;
+ int OldDir;
+
+ if (Length != 0) {
+ (void)fprintf(stderr,
+ "%s: error in cpio file.\n",
+ argv[Index]);
+ return EXIT_FAILURE;
+ }
+
+ if (!MakeTargetDir(Name, &Dirs, TRUE)) {
+ (void)fprintf(stderr,
+ "%s: can't create parent "
+ "directories for \"%s\".\n",
+ argv[Index], Name);
+ return EXIT_FAILURE;
+ }
+
+ if (!MakeDir(Name, Mode, &OldDir)) {
+ (void)fprintf(stderr,
+ "%s: can't create directory "
+ "\"%s\".\n", argv[Index], Name);
+ return EXIT_FAILURE;
+ }
+
+ if (!OldDir) {
+ Dir = InsertPListEntry(&Dirs, Name);
+ Dir->pe_DirEmpty = TRUE;
+ Dir->pe_DirMode = Mode;
+ }
+ break;
+ }
+ case C_ISLNK: {
+ char *Link;
+
+ if ((Link = GetData(In, Length)) == NULL) {
+ (void)fprintf(stderr,
+ "%s: error in cpio file.\n",
+ argv[Index]);
+ return EXIT_FAILURE;
+ }
+
+ if (!MakeTargetDir(Name, &Dirs, TRUE)) {
+ (void)fprintf(stderr,
+ "%s: can't create parent "
+ "directories for \"%s\".\n",
+ argv[Index], Name);
+ return EXIT_FAILURE;
+ }
+
+ if (*Link == '/') {
+ char *Ptr;
+
+ (void)memmove(Link, Link + 1,
+ strlen(Link + 1) + 1);
+ Ptr = Name;
+ if (Prefix != NULL)
+ Ptr += strlen(Prefix);
+
+ while ((Ptr = strchr(Ptr, '/'))
+ != NULL) {
+ char *NewLink;
+
+ NewLink = StrCat("../", Link);
+ free(Link);
+ Link = NewLink;
+ Ptr++;
+ }
+ }
+
+ if (!MakeSymLink(Link, Name)) {
+ (void)fprintf(stderr,
+ "%s: can't create symbolic link "
+ "\"%s\".\n", argv[Index], Name);
+ return EXIT_FAILURE;
+ }
+
+ InsertPListEntry(&Links, Name)->pe_Link = Link;
+ break;
+ }
+ case C_ISREG:
+ if (!MakeTargetDir(Name, &Dirs, TRUE)) {
+ (void)fprintf(stderr,
+ "%s: can't create parent "
+ "directories for \"%s\".\n",
+ argv[Index], Name);
+ return EXIT_FAILURE;
+ }
+
+
+ if ((Last != NULL) && (Last->pe_INode !=
+ Fields[CPIO_HDR_INODE])) {
+ Last = NULL;
+ }
+
+ if (!WriteFile(In, Name, Mode, Length,
+ (Last != NULL)? Last->pe_Name : NULL)) {
+ (void)fprintf(stderr,
+ "%s: can't write file \"%s\".\n",
+ argv[Index],
+ Name);
+ return EXIT_FAILURE;
+ }
+
+ Last = InsertPListEntry(&Files, Name);
+ Last->pe_INode = Fields[CPIO_HDR_INODE];
+ break;
+ default:
+ if ((Length > 0) &&
+ !SkipAndAlign(In, Length)) {
+ (void)fprintf(stderr,
+ "%s: error in cpio file.\n",
+ argv[Index]);
+ return EXIT_FAILURE;
+ }
+
+ }
+
+ free(Name);
+ }
+
+ Close(In);
+ (void)close(FD);
+ }
+
+ if (PListFile != NULL) {
+ ProcessPList(Files, PListEntryFile, PLIST_ORDER_FORWARD,
+ PListFile);
+ ProcessPList(Dirs, PListEntryMakeDir, PLIST_ORDER_FORWARD,
+ PListFile);
+ ProcessPList(Links, PListEntryLink, PLIST_ORDER_FORWARD,
+ PListFile);
+ ProcessPList(Dirs, PListEntryRemoveDir, PLIST_ORDER_BACKWARD,
+ PListFile);
+ (void)fclose(PListFile);
+ }
+
+ return EXIT_SUCCESS;
}