home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Boston 2
/
boston-2.iso
/
DOS
/
HILFEN
/
SYSTEM
/
MSH
/
ZIPLS.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-12-01
|
4KB
|
135 lines
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <alloc.h>
#include <dos.h>
#include <mem.h>
#include <io.h>
#include <fcntl.h>
/* this file is what allows MSH to work inside zip archives.
It is given as an example so you may write your own directory-reader
for other types of archives (you will get complimentary copies
of all our products if you are the first person to send me back
such a reader for one of the common types which are not yet supported
by MSH). If you define another lister, just add it in the list of
panel_listers in primitiv.c
*/
static int ZipHandle;
#include "msh.h"
/* service routines: ReadZip and baseptr */
static int ReadZip(long offset,int fromwhere,void *ReadBuf,int ReadSize)
{ if((lseek(ZipHandle,offset,fromwhere)<0) ||
(_read(ZipHandle,ReadBuf,ReadSize)!=ReadSize))
{(*efns)(WARNING_,"Invalid Zip format");return -1;}
else return 0;
}
char *baseptr(char *name)
{char *s;
for(s=name;*name;name++)if(*name=='\\' || *name=='/' || *name==':')s=name+1;
return s;
}
/* the following function 'addlist' from msh.lib does the main job: you call
it once for each name found in the archive. If the name given matches
the pattern given, addlist returns a pointer to a structure that you then
have to fill */
struct dlst{refobj fname;
unsigned long size;
unsigned long time;
unsigned read:1;
unsigned system:1;
unsigned hidden:1;
unsigned isdir:1;
unsigned selected:1;
unsigned selected_shown:1;
}*addlist(char *name,char *pattern);
void zip_ls(char *Zipname)
{/* Format information for ZIP files (produced by PKWARE's PKZIP.EXE) */
/* Structure of the central directory record */
struct CENTRAL_RECORD
{ long Signature;
int VersionMadeBy;
int VersionNeeded;
int BitFlag;
int CompressionMethod;
long FileTime;
long CRC32;
long CompressedSize;
long UnCompressedSize;
int FileNameLength;
int ExtraFieldLength;
int CommentFieldLength;
int DiskStartNumber;
int InternalAttributes;
long ExternalAttributes;
long LocalHeaderOffset;
}*ZipCR, *pCR;
#define CENTRALDIRSIG 0x02014b50L
struct END_CENTRAL_RECORD
{ long Signature;
int DiskNumber;
int DiskWithCD;
int DiskCD;
int CDEntries;
long CDSize;
long CDOffset;
int ZipCommentLength;
}*ECR;
#define ENDCENTRALSIG 0x06054b50L
#define sizeofECR sizeof(struct END_CENTRAL_RECORD)
int i, nbentries, ZipCmtLngth, dnlen;
char Buffer[sizeofECR], *Pathname=strstr(Zipname,".zip")+5, dn[_MAX_PATH];
Pathname[-1]=0;
if((ZipHandle=_open(Zipname,O_RDONLY|O_BINARY))==-1)
{(*efns)(WARNING_|FILE_,"Cannot open %s",Zipname);goto end2;}
if(ReadZip(-(long)sizeofECR,SEEK_END,Buffer,sizeofECR))goto end;
while(1)
{ for(i=0;i<sizeofECR-sizeof(long);i++)
if(*(long *)(Buffer+i)==ENDCENTRALSIG)goto found;
if(ReadZip(3-2*(long)sizeofECR,SEEK_CUR,Buffer,sizeofECR))goto end;
}
found:
if(ReadZip(i-(long)sizeof(int),SEEK_CUR,&ZipCmtLngth,sizeof(int)))goto end;
testalloc(ECR=malloc(sizeofECR+ZipCmtLngth));
if(ReadZip(-(long)sizeofECR,SEEK_CUR,ECR,sizeofECR+ZipCmtLngth))
{ free(ECR);goto end;}
/* Allocate 1 more byte to avoid malloc(0)==NULL (fuck you, ANSI commitee!!) */
testalloc(ZipCR=malloc((int)ECR->CDSize+1));
if(ReadZip(ECR->CDOffset,SEEK_SET,(char *)ZipCR,(int)ECR->CDSize))
{ free(ZipCR);free(ECR);goto end;}
else nbentries=ECR->CDEntries;
free(ECR);
addlist("..",NULL);
dnlen=baseptr(Pathname)-Pathname;
strncpy(dn,Pathname,dnlen);dn[dnlen]=0;strupr(dn);
for(i=0,pCR=ZipCR;i<nbentries;i++,pCR++)
{ char *name=(char *)(pCR+1), *s;
name[pCR->FileNameLength]=0;strupr(name);
for(s=name;*s;s++)if(*s=='/')*s='\\';
if(strstr(name,dn)==name)
{ char *pattern=NULL;struct dlst *d;name+=strlen(dn);
if((s=strpbrk(name,"\\/"))==NULL)pattern=Pathname+strlen(dn);
else { *s=0;name=baseptr(name);}
if((d=addlist(name,pattern))&& pattern)
{ d->time=pCR->FileTime;
d->size=pCR->UnCompressedSize;
}
}
(char *)pCR+=pCR->CommentFieldLength+pCR->FileNameLength+
pCR->ExtraFieldLength;
}
free(ZipCR);
end: close(ZipHandle);
end2: Pathname[-1]='\\';
}