home *** CD-ROM | disk | FTP | other *** search
- #ifdef MULTIFILE
- #define NAME "xadUnFileM"
- #else
- #define NAME "xadUnFile"
- #endif
- #define DISTRIBUTION "(Freeware) "
- #define REVISION "7"
-
- /* Programmheader
-
- Name: xadUnFile
- Author: SDI
- Distribution: Freeware
- Description: dearchives file archives
- Compileropts: -
- Linkeropts: -gsi -l amiga
-
- 1.0 13.09.98 : first version
- 1.1 18.11.98 : added FILE parameter and directory creation
- 1.2 03.02.99 : added corrupt message
- 1.3 07.02.99 : added missing "group crunched" handling
- 1.4 16.03.99 : errors no longer abort decrunching
- 1.5 21.06.99 : added support for multiple input files and renaming
- 1.6 04.07.99 : bug fix
- 1.7 18.07.99 : added SHOWPROT, reduced status prints, added QUIT,
- splitted in xadUnFile and xadUnFileM
- */
-
- #include <proto/xadmaster.h>
- #include <proto/exec.h>
- #include <proto/dos.h>
- #include <exec/memory.h>
- #include <dos/dosasl.h>
- #include <utility/hooks.h>
- #include "SDI_defines.h"
- #include "SDI_compiler.h"
- #define SDI_TO_ANSI
- #include "SDI_ASM_STD_protos.h"
-
- struct xadMasterBase * xadMasterBase = 0;
- struct DosLibrary * DOSBase = 0;
- struct ExecBase * SysBase = 0;
-
- #define MINPRINTSIZE 51200 /* 50KB */
-
- #ifdef MULTIFILE
- #define PARAM "FROM/A/M,DEST=DESTDIR/K,PASSWORD/K,FILE/K,NE=NOEXTERN/S,"\
- "INFO=LIST/S,OW=OVERWRITE/S,NOTREE/S,ASKMAKEDIR/S," \
- "NOCOMMENT/S,NOPROT/S,NODATE/S,NOABS/S,SHOWPROT/S,QUIET/S"
- #else
- #define PARAM "FROM/A,DEST=DESTDIR,PASSWORD/K,FILE/M,NE=NOEXTERN/S,"\
- "INFO=LIST/S,OW=OVERWRITE/S,NOTREE/S,ASKMAKEDIR/S," \
- "NOCOMMENT/S,NOPROT/S,NODATE/S,NOABS/S,SHOWPROT/S,QUIET/S"
- #endif
-
- #ifdef MULTIFILE
- #define OPTIONS \
- "FROM The input archive file(s) (no patterns allowed)\n" \
- "DESTDIR The destination directory, not needed with INFO\n" \
- "PASSWORD A password for encrypted archives\n" \
- "FILE Filename (with patterns) to be extracted\n" \
- "NOEXTERN Turns off usage of external clients\n" \
- "INFO Shows archive information without extracting\n" \
- "OVERWRITE Files are overwritten without asking\n" \
- "NOTREE Files are extracted without subdirectories\n" \
- "ASKMAKEDIR You get asked before a directory is created\n" \
- "NOCOMMENT No filenote comments are extracted or displayed\n" \
- "NOPROT Protection information gets not extracted\n" \
- "NODATE Creation date information gets not extracted\n" \
- "NOABS Do not extract absolute path name parts\n" \
- "SHOWPROT Show protection information with LIST\n" \
- "QUIET Turns of progress report and user interaction!\n"
- #else
- #define OPTIONS \
- "FROM The input archive file (no patterns allowed)\n" \
- "DESTDIR The destination directory, not needed with INFO\n" \
- "PASSWORD A password for encrypted archives\n" \
- "FILE Filename(s) (with patterns) to be extracted\n" \
- "NOEXTERN Turns off usage of external clients\n" \
- "INFO Shows archive information without extracting\n" \
- "OVERWRITE Files are overwritten without asking\n" \
- "NOTREE Files are extracted without subdirectories\n" \
- "ASKMAKEDIR You get asked before a directory is created\n" \
- "NOCOMMENT No filenote comments are extracted or displayed\n" \
- "NOPROT Protection information gets not extracted\n" \
- "NODATE Creation date information gets not extracted\n" \
- "NOABS Do not extract absolute path name parts\n" \
- "SHOWPROT Show protection information with LIST\n" \
- "QUIET Turns of progress report and user interaction!\n"
- #endif
-
- struct xHookArgs {
- STRPTR name;
- ULONG flags;
- ULONG finish;
- ULONG lastprint;
- };
-
- #ifdef MULTIFILE
- struct Args {
- STRPTR * from;
- STRPTR destdir;
- STRPTR password;
- STRPTR file;
- ULONG noextern;
- ULONG info;
- ULONG overwrite;
- ULONG notree;
- ULONG askmakedir;
- ULONG nocomment;
- ULONG noprot;
- ULONG nodate;
- ULONG noabs;
- ULONG showprot;
- ULONG quiet;
- };
- #else
- struct Args {
- STRPTR from;
- STRPTR destdir;
- STRPTR password;
- STRPTR * file;
- ULONG noextern;
- ULONG info;
- ULONG overwrite;
- ULONG notree;
- ULONG askmakedir;
- ULONG nocomment;
- ULONG noprot;
- ULONG nodate;
- ULONG noabs;
- ULONG showprot;
- ULONG quiet;
- };
-
- LONG CheckName(STRPTR *pat, STRPTR name);
- #endif
-
- ASM(ULONG) progrhook(REG(a0, struct Hook *),
- REG(a1, struct xadProgressInfo *));
-
- void ShowProt(ULONG i);
-
- ULONG start(void)
- {
- ULONG ret = RETURN_FAIL;
- struct DosLibrary *dosbase;
-
- SysBase = (*((struct ExecBase **) 4));
- { /* test for WB and reply startup-message */
- struct Process *task;
- if(!(task = (struct Process *) FindTask(0))->pr_CLI)
- {
- WaitPort(&task->pr_MsgPort);
- Forbid();
- ReplyMsg(GetMsg(&task->pr_MsgPort));
- return RETURN_FAIL;
- }
- }
-
- if((dosbase = (struct DosLibrary *) OpenLibrary("dos.library", 37)))
- {
- LONG err = 0;
- struct xadMasterBase *xadmasterbase;
-
- DOSBase = dosbase;
- if((xadmasterbase = (struct xadMasterBase *)
- OpenLibrary("xadmaster.library", 1)))
- {
- struct Args args;
- struct RDArgs *rda;
-
- memset(&args, 0, sizeof(struct Args));
- xadMasterBase = xadmasterbase;
-
- if((rda = (struct RDArgs *) AllocDosObject(DOS_RDARGS, 0)))
- {
- rda->RDA_ExtHelp = OPTIONS;
-
- if(ReadArgs(PARAM, (LONG *) &args, rda))
- {
- if(args.destdir || args.info)
- {
- struct xadArchiveInfo *ai;
-
- if((ai = (struct xadArchiveInfo *)
- xadAllocObjectA(XADOBJ_ARCHIVEINFO, 0)))
- {
- #ifdef MULTIFILE
- if(*(args.from+1))
- {
- struct xadSplitFile *sf = 0, *sf2, *sf0 = 0;
- while(*args.from && !err)
- {
- if((sf2 = xadAllocObjectA(XADOBJ_SPLITFILE, 0)))
- {
- if(sf)
- {
- sf->xsf_Next = sf2; sf = sf2;
- }
- else
- sf0 = sf = sf2;
- sf->xsf_Type = XAD_INFILENAME;
- sf->xsf_Data = (ULONG) *(args.from++);
- }
- else
- err = XADERR_NOMEMORY;
- }
- if(!err)
- err = xadGetInfo(ai, XAD_INSPLITTED, sf0, XAD_NOEXTERN,
- args.noextern, args.password ? XAD_PASSWORD : TAG_IGNORE,
- args.password, TAG_DONE);
- while(sf0)
- {
- sf2 = sf0; sf0 = sf0->xsf_Next;
- xadFreeObjectA(sf2, 0);
- }
- }
- else
- err = xadGetInfo(ai, XAD_INFILENAME, *args.from,
- XAD_NOEXTERN, args.noextern, args.password ? XAD_PASSWORD :
- TAG_IGNORE, args.password, TAG_DONE);
- #else
- err = xadGetInfo(ai, XAD_INFILENAME, args.from,
- XAD_NOEXTERN, args.noextern, args.password ? XAD_PASSWORD :
- TAG_IGNORE, args.password, TAG_DONE);
- #endif
-
- if(!err)
- {
- if(ai->xai_Flags & XADAIF_FILECORRUPT)
- Printf("!!! The archive file has some corrupt data. !!!\n");
- if(args.info)
- {
- struct xadFileInfo *xfi;
- ULONG grsize = 0;
- Printf("ArchiverName: %s\n"
- "Size CrndSize Ratio Date Time %sName\n",
- ai->xai_Client->xc_ArchiverName, args.showprot ? "Protection " : "");
-
- xfi = ai->xai_FileInfo;
- while(xfi && !CTRL_C)
- {
- if(!(xfi->xfi_Flags & XADFIF_GROUPED))
- grsize = 0;
- if(xfi->xfi_Flags & XADFIF_DIRECTORY)
- {
- Printf(" <dir> <dir> %02ld.%02ld.%04ld %02ld:%02ld:%02ld ",
- xfi->xfi_Date.xd_Day, xfi->xfi_Date.xd_Month,
- xfi->xfi_Date.xd_Year, xfi->xfi_Date.xd_Hour,
- xfi->xfi_Date.xd_Minute, xfi->xfi_Date.xd_Second);
- if(args.showprot)
- ShowProt(xfi->xfi_Protection);
- Printf("%s\n", args.notree ? FilePart(xfi->xfi_FileName) :
- xfi->xfi_FileName);
- }
- else if(xfi->xfi_Flags & XADFIF_GROUPED)
- {
- Printf("%8ld merged n/a %02ld.%02ld.%04ld %02ld:%02ld:%02ld ",
- xfi->xfi_Size, xfi->xfi_Date.xd_Day, xfi->xfi_Date.xd_Month,
- xfi->xfi_Date.xd_Year, xfi->xfi_Date.xd_Hour,
- xfi->xfi_Date.xd_Minute, xfi->xfi_Date.xd_Second);
- if(args.showprot)
- ShowProt(xfi->xfi_Protection);
- Printf("%s\n", args.notree ? FilePart(xfi->xfi_FileName) :
- xfi->xfi_FileName);
- grsize += xfi->xfi_Size;
- if(xfi->xfi_Flags & XADFIF_ENDOFGROUP)
- {
- ULONG i = 0, j = 0;
-
- if(xfi->xfi_GroupCrSize < grsize)
- {
- i = ((grsize - xfi->xfi_GroupCrSize)*1000)/grsize;
- j = i % 10;
- i /= 10;
- }
- Printf("%8ld %8ld %2ld.%1ld%%\n", grsize, xfi->xfi_GroupCrSize,
- i, j);
- grsize = 0;
- }
- }
- else
- {
- ULONG i = 0, j = 0;
-
- if(xfi->xfi_CrunchSize < xfi->xfi_Size)
- {
- i = ((xfi->xfi_Size - xfi->xfi_CrunchSize)*1000)/xfi->xfi_Size;
- j = i % 10;
- i /= 10;
- }
-
- Printf("%8ld %8ld %2ld.%1ld%% %02ld.%02ld.%04ld %02ld:%02ld:%02ld ",
- xfi->xfi_Size, xfi->xfi_CrunchSize, i, j,
- xfi->xfi_Date.xd_Day, xfi->xfi_Date.xd_Month,
- xfi->xfi_Date.xd_Year, xfi->xfi_Date.xd_Hour,
- xfi->xfi_Date.xd_Minute, xfi->xfi_Date.xd_Second);
- if(args.showprot)
- ShowProt(xfi->xfi_Protection);
- Printf("%s\n", args.notree ? FilePart(xfi->xfi_FileName) :
- xfi->xfi_FileName);
- }
- if(xfi->xfi_Comment && !args.nocomment)
- Printf(": %s\n", xfi->xfi_Comment);
- #ifdef DEBUG
- if(xfi->xfi_Flags)
- {
- Printf("Flags: ");
- if(xfi->xfi_Flags & XADFIF_CRYPTED)
- Printf("XADFIF_CRYPTED ");
- if(xfi->xfi_Flags & XADFIF_DIRECTORY)
- Printf("XADFIF_DIRECTORY ");
- if(xfi->xfi_Flags & XADFIF_LINK)
- Printf("XADFIF_LINK ");
- if(xfi->xfi_Flags & XADFIF_INFOTEXT)
- Printf("XADFIF_INFOTEXT ");
- if(xfi->xfi_Flags & XADFIF_GROUPED)
- Printf("XADFIF_GROUPED ");
- if(xfi->xfi_Flags & XADFIF_ENDOFGROUP)
- Printf("XADFIF_ENDOFGROUP ");
- if(xfi->xfi_Flags & XADFIF_NODATE)
- Printf("XADFIF_NODATE ");
- Printf("\n");
- }
- #endif
- if(xfi->xfi_Flags & XADFIF_CRYPTED)
- Printf("The entry is encrypted\n");
- xfi = xfi->xfi_Next;
- }
- ret = 0;
- }
- else
- {
- struct Hook prhook;
- struct xadFileInfo *fi;
- UBYTE filename[256];
- #ifdef MULTIFILE
- UBYTE parsebuf[1024];
- #endif
- struct xHookArgs xh;
-
- ret = 0;
- xh.name = filename;
- xh.flags = xh.finish = xh.lastprint = 0;
-
- /* Note! The hook may change the filename!!! */
-
- memset(&prhook, 0, sizeof(struct Hook));
- prhook.h_Entry = (ULONG (*)()) progrhook;
- prhook.h_Data = &xh;
- fi = ai->xai_FileInfo;
-
- #ifdef MULTIFILE
- if(!args.file || ParsePatternNoCase(args.file, parsebuf, 1024) >= 0)
- #endif
- {
- while(fi && !CTRL_C && !xh.finish)
- {
- #ifdef MULTIFILE
- if(!args.file || MatchPatternNoCase(parsebuf, args.notree ?
- FilePart(fi->xfi_FileName) : fi->xfi_FileName))
- #else
- if(!args.file || CheckName(args.file, args.notree ?
- FilePart(fi->xfi_FileName) : fi->xfi_FileName))
- #endif
- {
- CopyMem(args.destdir, filename, strlen(args.destdir)+1);
- if(args.notree)
- AddPart(filename, FilePart(fi->xfi_FileName), 256);
- else if(!args.noabs)
- AddPart(filename, fi->xfi_FileName, 256);
- else
- {
- STRPTR fname = filename, f;
-
- if(*args.destdir)
- {
- fname += strlen(args.destdir)-1;
- if(*fname != ':' && *fname != '/')
- *(++fname) = '/';
- ++fname;
- }
- for(f = fi->xfi_FileName; *f; ++f)
- *(fname++) = *f == ':' ? '/' : *f;
- *fname = 0;
- }
- if(fi->xfi_Flags & XADFIF_DIRECTORY)
- {
- if(!args.notree)
- {
- BPTR a;
- LONG err = 0, i = 0;
- UBYTE r;
- while(filename[i] && !err)
- {
- for(;filename[i] && filename[i] != '/'; ++i)
- ;
- r = filename[i];
- filename[i] = 0;
- if((a = Lock(filename, SHARED_LOCK)))
- UnLock(a);
- else if((a = CreateDir(filename)))
- UnLock(a);
- else
- err = 1;
- filename[i++] = r;
- }
- if(!args.quiet)
- {
- if(err)
- Printf("failed to create directory '%s'\n",
- fi->xfi_FileName);
- else
- Printf("Created directory : %s\n", filename);
- }
- }
- }
- else if(fi->xfi_Flags & XADFIF_LINK)
- {
- if(!args.quiet)
- Printf("Skipped Link\n");
- }
- else
- {
- struct DateStamp d;
-
- if(!xadFileUnArc(ai, XAD_OUTFILENAME, filename,
- XAD_ENTRYNUMBER, fi->xfi_EntryNumber, XAD_MAKEDIRECTORY,
- !args.askmakedir, XAD_OVERWRITE, args.overwrite,
- args.quiet ? TAG_IGNORE : XAD_PROGRESSHOOK, &prhook, TAG_DONE))
- {
- if(!args.nodate && !(fi->xfi_Flags & XADFIF_NODATE)
- && !xadConvertDates(XAD_DATEXADDATE, &fi->xfi_Date,
- XAD_GETDATEDATESTAMP, &d, TAG_DONE))
- SetFileDate(filename, &d);
- if(!args.noprot)
- SetProtection(filename, fi->xfi_Protection);
- if(fi->xfi_Comment && !args.nocomment)
- SetComment(filename, fi->xfi_Comment);
- /* SetOwner ??? */
- }
- }
- }
- fi = fi->xfi_Next;
- }
- }
- }
- xadFreeInfo(ai);
- } /* xadGetInfo */
-
- xadFreeObjectA(ai, 0);
- } /* xadAllocObject */
- }
- else
- SetIoErr(ERROR_REQUIRED_ARG_MISSING);
-
- FreeArgs(rda);
- } /* ReadArgs */
- FreeDosObject(DOS_RDARGS, rda);
- } /* AllocDosObject */
-
- if(CTRL_C)
- SetIoErr(ERROR_BREAK);
-
- if(!args.quiet)
- {
- if(err)
- Printf("An error occured: %s\n", xadGetErrorText(err));
- else if(ret)
- PrintFault(IoErr(), 0);
- }
-
- CloseLibrary((struct Library *) xadmasterbase);
- } /* OpenLibrary xadmaster */
- else
- Printf("Could not open xadmaster.library\n");
- CloseLibrary((struct Library *) dosbase);
- } /* OpenLibrary dos */
- return ret;
- }
-
- /* Because of SAS-err, this cannot be SAVEDS */
- ASM(ULONG) progrhook(REG(a0, struct Hook *hook),
- REG(a1, struct xadProgressInfo *pi))
- {
- ULONG ret = 0;
- STRPTR name = ((struct xHookArgs *) (hook->h_Data))->name;
-
- switch(pi->xpi_Mode)
- {
- case XADPMODE_ASK:
- ret |= ((struct xHookArgs *) (hook->h_Data))->flags;
- if((pi->xpi_Status & XADPIF_OVERWRITE) && !(ret & XADPIF_OVERWRITE))
- {
- LONG r;
-
- Printf("File '%s' already exists, overwrite? (Y|A|S|\033[1mN\033[0m|Q|R): ",
- pi->xpi_FileName);
- Flush(Output());
- SetMode(Input(), TRUE);
- r = FGetC(Input());
- SetMode(Input(), FALSE);
- switch(r)
- {
- case 'a': case 'A':
- ((struct xHookArgs *) (hook->h_Data))->flags |= XADPIF_OVERWRITE;
- case 'y': case 'Y': ret |= XADPIF_OVERWRITE; break;
- case 's': case 'S': ret |= XADPIF_SKIP; break;
- case 'q': case 'Q': ((struct xHookArgs *) (hook->h_Data))->finish = 1; break;
- case 'r': case 'R':
- Printf("\r\033[KEnter new (full) name for '%s':", pi->xpi_FileName);
- Flush(Output());
- FGets(Input(), name, 255); /* 1 byte less to correct bug before V39 */
- r = strlen(name);
- if(name[r-1] == '\n') /* skip return character */
- name[--r] = 0;
- Printf("\033[1F\033[K"); /* go up one line and clear it */
- if(pi->xpi_NewName = xadAllocVec(++r, MEMF_PUBLIC))
- {
- while(r--)
- pi->xpi_NewName[r] = name[r];
- ret |= XADPIF_RENAME;
- }
- else
- Printf("No memory to store new name\n");
- }
- }
- if((pi->xpi_Status & XADPIF_MAKEDIRECTORY) &&
- !(ret & XADPIF_MAKEDIRECTORY))
- {
- Printf("Directory of file '%s' does not exist, create? (Y|A|S|\033[1mN\033[0m|Q): ",
- name);
- Flush(Output());
- SetMode(Input(), TRUE);
- switch(FGetC(Input()))
- {
- case 'a': case 'A':
- ((struct xHookArgs *) (hook->h_Data))->flags |= XADPIF_MAKEDIRECTORY;
- case 'y': case 'Y': ret |= XADPIF_MAKEDIRECTORY; break;
- case 's': case 'S': ret |= XADPIF_SKIP; break;
- case 'q': case 'Q': ((struct xHookArgs *) (hook->h_Data))->finish = 1;
- }
- SetMode(Input(), FALSE);
- }
- break;
- case XADPMODE_PROGRESS:
- if(pi->xpi_CurrentSize - ((struct xHookArgs *) (hook->h_Data))->lastprint >= MINPRINTSIZE)
- {
- Printf("\r\033[KWrote %8ld of %8ld bytes: %s",
- pi->xpi_CurrentSize, pi->xpi_FileInfo->xfi_Size, name);
- Flush(Output());
- ((struct xHookArgs *) (hook->h_Data))->lastprint = pi->xpi_CurrentSize;
- }
- break;
- case XADPMODE_END: Printf("\r\033[KWrote %8ld bytes: %s\n",
- pi->xpi_CurrentSize, name);
- break;
- case XADPMODE_ERROR: Printf("\r\033[K%s: %s\n", name,
- xadGetErrorText(pi->xpi_Error));
- break;
- }
-
- if(!CTRL_C) /* clear ok flag */
- ret |= XADPIF_OK;
-
- return ret;
- }
-
- void ShowProt(ULONG i)
- {
- LONG j;
- UBYTE buf[18];
-
- for(j = 0; j < 16; ++j)
- buf[j] = '-';
- buf[j++] = ' ';
- buf[j] = 0;
-
- if(i & FIBF_OTR_READ) buf[0] = 'r';
- if(i & FIBF_OTR_WRITE) buf[1] = 'w';
- if(i & FIBF_OTR_EXECUTE) buf[2] = 'e';
- if(i & FIBF_OTR_DELETE) buf[3] = 'd';
- if(i & FIBF_GRP_READ) buf[4] = 'r';
- if(i & FIBF_GRP_WRITE) buf[5] = 'w';
- if(i & FIBF_GRP_EXECUTE) buf[6] = 'e';
- if(i & FIBF_GRP_DELETE) buf[7] = 'd';
- if(i & (1<<7)) buf[8] = 'h';
- if(i & FIBF_SCRIPT) buf[9] = 's';
- if(i & FIBF_PURE) buf[10] = 'p';
- if(i & FIBF_ARCHIVE) buf[11] = 'a';
- if(!(i & FIBF_READ)) buf[12] = 'r';
- if(!(i & FIBF_WRITE)) buf[13] = 'w';
- if(!(i & FIBF_EXECUTE)) buf[14] = 'e';
- if(!(i & FIBF_DELETE)) buf[15] = 'd';
- Printf(buf);
- }
-
- #ifndef MULTIFILE
- /* would be better to store the pattern parse stuff and do it only once,
- but so it is a lot easier */
- LONG CheckName(STRPTR *pat, STRPTR name)
- {
- UBYTE buf[500];
- while(*pat)
- {
- if(ParsePatternNoCase(*(pat++), buf, 500) >= 0)
- {
- if(MatchPatternNoCase(buf, name))
- return 1;
- } /* A scan failure means no recognition, should be an error print here */
- }
- return 0;
- }
- #endif
-