Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

rpmunpac w/LFN support for DJGPP and WATCOM

32 views
Skip to first unread message

Rod Pemberton

unread,
Oct 5, 2005, 5:24:54 PM10/5/05
to

The following version of rpmunpac has been modified for LFN support and
compiles for DJGPP v3.41 (and hopefully current versions) and OW1.3. My
changes are "contributed to the Public Domain."

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

0 new messages