Rod Pemberton
PS. Could someone, perhaps FreeDOSFan on www.mysoftware.cjg.net or maybe
Delorie, save the code somewhere publicly accessible? This would be
appreciated.
PPS. I tried sending this with post.newsfeeds.com and it never made it. Is
there a
reliable newserver that has free post access to comp.os.msdos.djgpp? Read
access
is available everywhere, but posting seems to be unavailable...
PPPS. I tried dj...@delorie.com but it blocks private pc's...
This is being sent from www.cyberjustice.org. Let's hope it works.
/*
* rpmunpack.c - Utility program to unpack an RPM archive
*
* Gero Kuhlmann <ge...@gkminix.han.de> 1998
*
* This program is public domain software; you can do whatever you like
* with this source, including modifying and redistributing it.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
*/
/*
* DJGPP LFN code and all WATCOM code
* contributed to the Public Domain by
* Rod Pemberton 2003-2005
*
* DJGPP gcc -o rpmunpac.exe rpmunpac.c
* WATCOM wcl/l=dos rpmunpac.c
* or wcl386/l=dos4g rpmunpac.c
*
* USAGE:
* doslfn
* rpmunpac file.rpm
* gzip -d file.gz
* cpio -iudv < file.cpio
* djtar -xvf file.tar (djtar has lfn support, DJGPP's GNU tar
doesn't)
*
* (doslfn from Henrik Haftmann)
* ( http://www.tu-chemnitz.de/~heha/hs_freeware/doslfn.zip )
* (dos cpio, gzip, djtar from DJ Delorie)
* ( http://www.delorie.com )
*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <dos.h>
#ifdef __DJGPP__
#include <dpmi.h>
#include <go32.h>
#include <crt0.h>
#include <dir.h>
__dpmi_regs r;
char ** __crt0_glob_function(char *arg) { return (char **)0; }
void __crt0_load_environment_file(char *app_name) {}
#define MX_PTH MAXPATH
#endif
#ifdef __WATCOMC__
#include <i86.h>
union REGS r;
struct SREGS s;
struct {
unsigned long EDI,ESI,EBP,rsvd,EBX,EDX,ECX,EAX;
unsigned short flags,ES,DS,FS,GS,IP,CS,SP,SS;
} RMI;
#define MX_PTH _MAX_PATH
/* tb used to setup transfer buffer below 1st megabyte (DJGPP __tb) */
/* DOS can only access the first 1Mb of memory */
/* tb used to save return information from DOS calls */
void *tb;
unsigned short sel; /* sel needed to free allocated memory, don't use */
#endif
/*
* Some general definitions
*/
#define BUFSIZE 512
#define RPM_MAGIC "\xED\xAB\xEE\xDB"
#define GZ_MAGIC_1 '\x1F'
#define GZ_MAGIC_2 '\x8B'
#define OFFS 261
/*
* Global variables
*/
static char buffer[BUFSIZE],short_name[9],long_name[65];
static char *progname;
FILE *infile, *outfile;
unsigned char sfnt[256];
#ifdef __WATCOMC__
/* setup tb - transfer buffer for dos calls in memory below 1Mb */
void free_dos_mem(void)
{
#ifdef __386__
r.w.ax=0x0101; /* free dos memory */
r.w.dx=sel;
int386(0x31,&r,&r);
#else
free (tb);
#endif
}
void get_dos_mem(void)
{
#ifdef __386__
r.w.ax=0x0100; /* allocate dos memory, no __tb in Watcom */
r.w.bx=0x400; /* 04000h (16384 bytes) in paragraphs (16 bytes) */
int386(0x31,&r,&r);
sel = r.w.dx;
tb = (void *)(r.w.ax<<4);
#else
tb = malloc (16384);
if (tb==NULL)
{
printf("RM malloc failed.\n");
exit(1);
}
#endif
}
#endif
void lfn_7156(char *opath, char *npath)
{
#ifdef __DJGPP__
dosmemput(opath, MX_PTH, __tb);
dosmemput(npath, MX_PTH, __tb+OFFS);
r.x.ax = 0x7156;
r.x.ds = __tb>>4;
r.x.dx = 0;
r.x.es = (__tb+OFFS)>>4;
r.x.di = (__tb+OFFS)&0x0F;
r.x.flags |= 1;
__dpmi_int(0x21, &r);
#endif
#ifdef __WATCOMC__
#ifdef __386__
memcpy(tb,opath,MX_PTH);
memcpy((char *)tb+OFFS,npath,MX_PTH);
RMI.EAX = 0x7156;
RMI.DS = (unsigned long)tb>>4;
RMI.EDX = 0;
RMI.ES = ((unsigned long)tb+OFFS)>>4;
RMI.EDI = ((unsigned long)tb+OFFS)&0x0F;
RMI.flags = INTR_CF; /* set carry */
r.w.ax=0x0300; /* simulate real mode interrupt */
r.h.bl=0x21;
r.h.bh=0;
r.w.cx=0;
s.es=FP_SEG(&RMI);
r.x.edi=FP_OFF(&RMI);
int386x(0x31,&r,&r,&s);
#else
movedata(FP_SEG(opath), FP_OFF(opath), FP_SEG(tb), FP_OFF(tb),
MX_PTH);
movedata(FP_SEG(npath), FP_OFF(npath), FP_SEG((char *)tb+OFFS),
FP_OFF((char *)tb+OFFS), MX_PTH);
r.w.ax = 0x7156;
s.ds = FP_SEG(tb);
r.w.dx = FP_OFF(tb);
s.es = FP_SEG((char *)tb+OFFS);
r.w.di = FP_OFF((char *)tb+OFFS);
r.w.cflag = INTR_CF;
int86x(0x21,&r,&r,&s);
#endif
#endif
}
#define COE 0x0011 /* create, open if exists */
#define CFE 0x0010 /* create, fail if exists */
#define CTE 0x0012 /* create, truncate if exists */
#define OFN 0x0001 /* open, fail if does not exist */
#define TFN 0x0002; /* truncate, fail if does not exist */
int lfn_716C(char *mpath, unsigned *fhandle)
{
#ifdef __DJGPP__
dosmemput( mpath, MX_PTH,__tb);
r.x.ax = 0x716c;
r.x.bx = 0x0002;
r.x.cx = 0;
r.x.dx = OFN;
r.x.ds = __tb>>4;
r.x.si = 0;
r.x.di = 0;
r.x.flags |= 1;
__dpmi_int(0x21, &r);
*fhandle = r.x.ax;
return(r.x.flags&0x01);
#endif
#ifdef __WATCOMC__
#ifdef __386__
memcpy(tb,mpath,MX_PTH);
RMI.EAX = 0x716c;
RMI.EBX = 0x0002;
RMI.ECX = 0;
RMI.EDX = OFN;
RMI.DS = (unsigned long)tb>>4;
RMI.ESI = (unsigned long)tb&0x0F;
RMI.EDI = 0;
RMI.flags = INTR_CF; /* set carry */
r.w.ax=0x0300; /* simulate real mode interrupt */
r.h.bl=0x21;
r.h.bh=0;
r.w.cx=0;
s.es=FP_SEG(&RMI);
r.x.edi=FP_OFF(&RMI);
int386x(0x31,&r,&r,&s);
*fhandle = RMI.EAX;
return(RMI.flags&INTR_CF);
#else
movedata(FP_SEG(mpath), FP_OFF(mpath), FP_SEG(tb), FP_OFF(tb),
MX_PTH);
r.w.ax = 0x716c;
r.w.bx = 0x0002;
r.w.cx = 0;
r.w.dx = OFN;
s.ds = FP_SEG(tb);
r.w.si = FP_OFF(tb);
r.w.di = 0;
r.w.cflag = INTR_CF;
int86x(0x21,&r,&r,&s);
*fhandle = r.w.ax;
return(r.w.cflag);
#endif
#endif
}
void lfn_3E(unsigned fhandle)
{
#ifdef __DJGPP__
r.h.ah = 0x3E;
r.x.bx = fhandle;
r.x.flags |= 1;
__dpmi_int(0x21, &r);
#endif
#ifdef __WATCOMC__
#ifdef __386__
RMI.EAX = 0x3E00;
RMI.EBX = fhandle;
RMI.flags = INTR_CF;
r.w.ax=0x0300; /* simulate real mode interrupt */
r.h.bl=0x21;
r.h.bh=0;
r.w.cx=0;
s.es=FP_SEG(&RMI);
r.x.edi=FP_OFF(&RMI);
int386x(0x31,&r,&r,&s);
#else
r.h.ah = 0x3E;
r.w.bx = fhandle;
r.w.cflag = INTR_CF;
int86(0x21,&r,&r);
#endif
#endif
}
/*
* Read a specified number of bytes from input file
*/
static void myread(int num)
{
int err;
if ((err = fread(( char *) &buffer, sizeof( char), num, infile)) != num) {
if (err < 0)
perror(progname);
else
fprintf(stderr, "unexpected end of input file\n");
exit(1);
}
}
/*
* Main program
*/
int main(int argc, char **argv)
{
int len, status = 0;
unsigned int i;
#ifdef __WATCOMC__
unsigned int fh=0;
atexit(free_dos_mem);
get_dos_mem();
#endif
/* Get our own program name */
if ((progname = strrchr(argv[0], '/')) == NULL)
progname = argv[0];
else
progname++;
/* Check for command line parameters */
if (argc != 2) {
fprintf(stderr, "usage: %s [RPM file]\n", argv[0]);
exit(1);
}
/* Open input file */
if ((infile = fopen(argv[1],"rb"))==NULL) {
perror(progname);
exit(1);
}
/* Read magic ID and output filename */
myread(4);
if (strncmp(buffer, RPM_MAGIC, 4)) {
fprintf(stderr, "input file is not in RPM format\n");
exit(1);
}
myread(6); /* Skip flags */
myread(64);
buffer[64] = '\0';
/* MS-DOS filename 8.3 A-Z a-z 0-9 _^$~!#%&-{}@`\'() */
for (i=0;i<256;i++) { /* setup SFN translation table */
sfnt[i]=i;
if (!isalnum(i) && strchr("_^$~!#%&-{}@`\'()\0",i)==NULL)
sfnt[i]='_';
}
short_name[4] = '\0';
strcpy(long_name,buffer);
for (i=0;i<4;i++) {
short_name[i] = sfnt[(int)buffer[i]];
}
strcat(short_name, ".gz");
/* Open output file */
strcat(long_name, ".cpio.gz");
printf ("%s\n%s\n",short_name,long_name);
if ((outfile = fopen(short_name,"wb"))==NULL) {
perror(progname);
exit(1);
}
/*
* Now search for the GZIP signature. This is rather awkward, but I don't
* know any other way how to find out the exact starting position of the
* archive within the input file. There are a couple of data structures
* and texts (obviously descriptions, installation shell scripts etc.)
* coming before the archive, but even they start at different offsets
* with different RPM files. However, it looks like the GZIP signature
* never appears before offset 0x200, so we skip these first couple of
* bytes to make the signature scan a little more reliable.
*/
myread(0x200 - 74);
while (status < 2) {
myread(1);
if ((status == 0) && (buffer[0] == GZ_MAGIC_1))
status++;
else if ((status == 1) && (buffer[0] == GZ_MAGIC_2))
status++;
else
status = 0;
}
buffer[0] = GZ_MAGIC_1;
buffer[1] = GZ_MAGIC_2;
if (fwrite(( char *) &buffer, sizeof( char), 2, outfile) < 0) {
perror(progname);
exit(1);
}
/* Now simply copy the GZIP archive into the output file */
while ((len = fread(( char *) &buffer, sizeof( char), BUFSIZE, infile)) >
0) {
if (fwrite(( char *) &buffer, sizeof( char), len, outfile) < 0) {
perror(progname);
exit(1);
}
}
if (len < 0) {
perror(progname);
exit(1);
}
fclose(infile);
fclose(outfile);
#ifdef __WATCOMC__
if (lfn_716C(short_name, &fh)==0) /* force LFN driver cache update */
lfn_3E(fh); /* close file, if it opened */
#endif
lfn_7156(short_name, long_name); /* LFN rename */
return(0);
}
--
Posted via: http://www.cyberjustice.org