delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/2005/10/05/17:31:06

X-Authentication-Warning: delorie.com: mail set sender to djgpp-bounces using -f
From: Rod Pemberton <donthave AT noreply DOT bit>
Newsgroups: comp.os.msdos.djgpp
Subject: rpmunpac w/LFN support for DJGPP and WATCOM
Date: Wed, 5 Oct 2005 21:24:54 +0000 (UTC)
Organization: cyberjustice.org
Lines: 409
Message-ID: <di1gb5$udv$1@sadr.dfn.de>
NNTP-Posting-Host: 66.28.207.11
Mime-Version: 1.0
X-Trace: sadr.dfn.de 1128547494 31167 66.28.207.11 (5 Oct 2005 21:24:54 GMT)
X-Complaints-To: usenet AT sadr DOT dfn DOT de
NNTP-Posting-Date: Wed, 5 Oct 2005 21:24:54 +0000 (UTC)
X-User-Real-E-Mail: nobody AT no DOT where DOT com
User-Agent: http://www.cyberjustice.org
To: djgpp AT delorie DOT com
DJ-Gateway: from newsgroup comp.os.msdos.djgpp
Reply-To: djgpp AT delorie DOT com

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 djgpp AT delorie DOT 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 <gero AT gkminix DOT han DOT 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

- Raw text -


  webmaster     delorie software   privacy  
  Copyright 2019   by DJ Delorie     Updated Jul 2019