www.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1993/02/03/10:58:00

Date: Wed, 3 Feb 93 10:17:10 EST
From: engdahl AT brutus DOT aa DOT ab DOT com (Jon Engdahl)
To: rcharif AT math DOT utexas DOT edu
Subject: Re: Porting GCC 2.3.3
Cc: djgpp AT sun DOT soe DOT clarkson DOT edu

> The idea is to intercept the "creat" and "open" calls either in the
> library or in go32 so that they generate unique file names for the
> TMPDIR. There will be need to keep a corespondance table between the
> long file names and the generated ones (Actually the idea could be
> expanded to handle long file names in a sort of database, but that's
> another story).

I have thought about the same thing myself, but haven't got around to trying
it. What I would like to see is a DOS TSR that would do this function for all
programs.

The following is a program called zmangle, which is a hacked up version
of DJ's djtarx. What it does that is new is automatically mangle long
filenames to fit into the 8.3 format. Someone might find it useful as a
start in making filenames fit. I first wrote it as a means to unpack
the BSD distribution from ftp.uu.net on my PC. The BSD sources there
have most files compressed, and the whole thing was tarred due to using
the automatic tar on their fancy ftp server.

Jonathan Engdahl, Sr. Project Engineer  | engdahl AT aa DOT ab DOT com   313-998-2450
Allen-Bradley Co.                       | A Rockwell International Company
555 Briarwood Circle,                   | Industrial Communication Network
Ann Arbor, Michigan, 48108, USA         | system design, software, ASICs



------------------------------zmangle.c - cut here -------------
/*

ZMANGLE.C

Derived from djtarx by DJ Delorie.

Filename mangling and uncompression added 1992
by Jonathan Engdahl (engdahl AT aa DOT ab DOT com)

If DJ has no conflicting claims, this falls under the GNU copyleft.

Usage:

	zmangle <filename>

Does basically the same thing as

	tar xvf <filename>

except it does a pretty good job of making up filenames for things that
don't fit within DOS's limitations.

If any files in the tar file are compressed, they are uncompressed so
we can get rid of the .Z off the end of the filename, and therefore
have a better chance of making the filename fit.

It still may have problems with variant TAR formats, filenames with leading
dots, and sometimes with creating new directory structures.

I compile this under BCC 3.1.

There are plenty of guesses and hacks used here as a substitute for DOS
and/or UNIX expertise - I didn't take the time to look everything up,
such as the tar format or the DOS file naming rules. Use at your own
risk.

*/



#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <io.h>
#include <dir.h>
#include <ctype.h>

FILE *change_file;



/*------------------------------------------------------------------------*/

typedef struct CHANGE {
  struct CHANGE *next;
  char *old;
  char *new;
} CHANGE;

#define chFILE 0
#define chDIR 1
#define chSKIP 2


CHANGE *change_root = 0;


char freq[]="eaioutsrclnpmfdkgbh_xvyw-qzj0123456789"; /* order of frequency of occurrance in BSD sources file names (except vowels first) */

#define WACCESS (O_WRONLY|O_BINARY|O_CREAT|O_EXCL)
#define RACCESS (O_RDONLY|O_BINARY)
#define MODE (S_IWRITE|S_IREAD)

int mangle(char *fname, int type)
	{
	CHANGE *ch;
	char new[200];
	char user[100];
	char *pos,*p;
	int len,i;
	char *nm;
	int file=0;

	for(p=fname;*p;p++)*p = tolower(*p);
	strcpy(new,fname);

	/* check for directory changes on record */
	for (ch=change_root; ch; ch = ch->next)
		{
		if(strncmp(fname,ch->old,strlen(ch->old)) == 0)
			{
			/* substitute the changed directory  name */
			if(strcmp(fname,ch->old)==0)return(file);
			sprintf(new, "%s%s", ch->new, fname+strlen(ch->old));
			break;
			}
		}

	nm=strrchr(new,'/');
	nm=nm?nm+1:&new[0];
	len = strlen(nm);

	/* on the first try, fix obvious illegalities */

	/* change conflicts with DOS I/O names */
	if     (strncmp(&nm[0],"com1.",5)==0)nm[1]='$';
	else if(strncmp(&nm[0],"com2.",5)==0)nm[1]='$';
	else if(strncmp(&nm[0],"com3.",5)==0)nm[1]='$';
	else if(strncmp(&nm[0],"com4.",5)==0)nm[1]='$';
	else if(strncmp(&nm[0],"lpt1.",5)==0)nm[1]='$';
	else if(strncmp(&nm[0],"lpt2.",5)==0)nm[1]='$';
	else if(strncmp(&nm[0],"lpt3.",5)==0)nm[1]='$';
	else if(strncmp(&nm[0],"con.",4)==0)nm[1]='$';
	else if(strncmp(&nm[0],"aux.",4)==0)nm[1]='$';
	else if(strncmp(&nm[0],"prn.",4)==0)nm[1]='$';
	else if(strncmp(&nm[0],"nul.",4)==0)nm[1]='$';

	/* zap illegal characters */
	for(p=&nm[len];--p>=&nm[0];)
		{
		if(*p=='+')*p='p';
		else if(*p==':')*p='$';
		else if(*p==',')*p='^';
		else if(*p=='=')*p='#';
		}

	/* zap extra periods */
	for(p=&nm[len];--p>=&nm[0];)
		if(*p=='.')
			for(;--p>&nm[0];)
				if(*p=='.')*p='^';


	if(type==chFILE && (file=open(new,WACCESS,MODE))<0
	|| type==chDIR  && mkdir(new))
		{
		/* collapse ".Z" to "z" */
		if(strcmp(&nm[len-2],".z")==0)strcpy(&nm[len-2],"z");

		if(type==chFILE && (file=open(new,WACCESS,MODE))<0
		|| type==chDIR  && mkdir(new))
			{

			/* mangle the extension */

			/*  zap letters,
			    starting with vowels and most common consonants,
			    until it fits.
			*/

			i=0;
			pos = strrchr(nm,'.');
			if(pos)
				{
				pos++;
				while(strlen(pos)>3)
					{
					if(freq[i]==0)goto giveup;
					p=&nm[strlen(nm)];
					while(--p>=pos && strlen(pos)>3)
						if(*p==freq[i])strcpy(p,p+1);
					i++;
					}
				}
			if(type==chFILE && (file=open(new,WACCESS,MODE))<0
			|| type==chDIR  && mkdir(new))
				{

				/* getting nervous, try fixing the name */

				i=0;
				while(pos = strrchr(nm,'.'),
				      pos = pos?pos:&nm[strlen(nm)],
				      pos-&nm[0]>8)
					{
					if(freq[i]==0)goto giveup;
					p=pos;
					while(--p>=&nm[0] && pos-&nm[0]>8)
						if(*p==freq[i])
							{
							strcpy(p,p+1);
							pos--;
							}
					i++;
					}
				if(type==chFILE && (file=open(new,WACCESS,MODE))<0
				|| type==chDIR  && mkdir(new))
					{
					/* mangle to a 7 character name */
					/* and tack a random character on the end */

					i=0;
					while(pos = strrchr(nm,'.'),
					      pos = pos?pos:&nm[strlen(nm)],
					      pos-&nm[0]>7)
						{
						if(freq[i]==0)goto giveup;
						p=pos;
						while(--p>=&nm[0] && pos-&nm[0]>7)
							if(*p==freq[i])
								{
								strcpy(p,p+1);
								pos--;
								}
						i++;
						}
					for(i=0;i<26;)
						{
						pos[-1] = 'a'+i;
						if(type==chFILE && (file=open(new,WACCESS,MODE))<0
						|| type==chDIR  && mkdir(new))
							{
							i++;
							}
						else break;
						}
					if(i>=26)
						{
giveup:
						/* ask the luser for a new name */
						do
							{
							printf("old name: %s\nnew name: ", fname);
							gets(user);

							if(user[0]=='!')
								{
								if(user[1])system(&user[1]);
								else system("command");
								}
							else
								{
								pos = strrchr(new, '/');
								if (pos && (strchr(user, '/') == 0))strcpy(pos+1,user);
								else strcpy(new,user);
								if(!(type==chFILE && (file=open(new,WACCESS,MODE))<0
								|| type==chDIR  && mkdir(new)))break;
								}
							}
						while(new[0]=='!');
						}
					}
				}
			}
		}


	if(strcmp(fname,new)==0 && type !=chDIR)return(file);

	if(strcmp(fname,new))fprintf(change_file, "%s -> %s\n", fname, new);

	if(type!=chDIR)return(file);

	ch = (CHANGE *)malloc(sizeof(CHANGE));
	if(!ch)
		{
		printf("cannot malloc!\n");
		exit(-1);
		}
	ch->next = change_root;
	change_root = ch;
	ch->old = strdup(fname);
	ch->new = strdup(new);
	strcpy(fname,new);

	return(file);
	}

/*------------------------------------------------------------------------*/

typedef struct {
  char name[100];
  char operm[8];
  char ouid[8];
  char ogid[8];
  char osize[11];
  char otime[12];
  char ocsum[8];
  char flags[1];
  char linkflag;
  char filler[355];
} TARREC;

char buf[512];

void tarread(char *fname)
  {
  TARREC header;
  int f, r,w;
  long perm, uid, gid, size, time;
  int dsize;
  int len;
  int skipflag=0;

  f = open(fname, O_RDONLY|O_BINARY);

  while (1)
    {
    if (read(f, &header, 512) < sizeof(header))
      break;
    if (header.name[0] == 0)
      break;
    sscanf(header.operm, "%lo", &perm);
    sscanf(header.ouid, "%lo", &uid);
    sscanf(header.ogid, "%lo", &gid);
    sscanf(header.osize, "%lo", &size);
    sscanf(header.otime, "%lo", &time);
    printf("%6lo %02x %12ld %s", perm, header.flags[0], size, header.name);
    if (header.name[strlen(header.name)-1] == '/')
	{
	printf("\n");
	header.name[strlen(header.name)-1] = 0;
	mangle(header.name, chDIR);
	}
    else if(header.linkflag && header.linkflag!=0x30)
	{
	printf(" --> %s\n",header.filler);
	}
    else
	{
	char *b;
	char *e;
	char dirbuf[128];

/*	if(header.linkflag)printf("<%02x>",header.linkflag);*/
	printf("\n");
	len=strlen(header.name);

	/* make sure that all the directories exist */

	b=header.name;
	while((e=strchr(b,'/'))!=NULL)
		{
		strncpy(dirbuf,header.name,e-header.name);
		dirbuf[e-header.name]=0;
		mangle(dirbuf, chDIR);
		b = e+1;
		}

	w = mangle(header.name,chFILE);

	if(w<0)
		{
		perror("opening extract file - skipping");
		skipflag=1;
		}

	while (size)
	  {
	  if (size < 512)
	    dsize = size;
	  else
	    dsize = 512;
	  read(f, buf, 512);
	  if (!skipflag && write(w, buf, dsize) < dsize)
	    {
	    perror("writing extract file");
	    skipflag=1;
	    }
	  size -= dsize;
	  }
	close(w);
	}
    }
  close(f);
  }



/*	how to skip a file ->	lseek(f, (size+511) & ~511, 1); */


int main(int argc, char **argv)
{
  int i;
  change_file = fopen("tarchange.lst", "w");
  for (i=1; i < argc; i++)tarread(argv[i]);
  fclose(change_file);
  return(0);
}


- Raw text -


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