home *** CD-ROM | disk | FTP | other *** search
- /*************************************************
- LHarc version 1.13b (c)Yoshi, 1988-89.
- main module : 1989/ 5/14
-
- HTAB = 4
- *************************************************/
-
- #include <stdio.h>
- #include <io.h>
- #include <ctype.h>
- #include <string.h>
- #include <dir.h>
- #include <dos.h>
- #include <alloc.h>
- #include <fcntl.h>
- #include <process.h>
- #include <stdlib.h>
- #include <errno.h>
-
- #define UNKNOWNERR 0
- #define INVCMDERR 1
- #define MANYPATERR 2
- #define NOARCNMERR 3
- #define NOFNERR 4
- #define NOARCERR 5
- #define RENAMEERR 6
- #define MKTMPERR 7
- #define DUPFNERR 8
- #define TOOMANYERR 9
- #define TOOLONGERR 10
- #define NOFILEERR 11
- #define MKFILEERR 12
- #define RDERR 13
- #define WTERR 14
- #define MEMOVRERR 15
- #define INVSWERR 16
- #define CTRLBRK 17
- #define NOMATCHERR 18
- #define COPYERR 19
- #define NOTLZH 20
- #define OVERWT 21
- #define MKDIR 22
- #define MKDIRERR 23
- #define CRCERR 24
- #define RDONLY 25
-
- #define MAXBLK 64
-
- #define MAX_PAT 64
- #define FAULT 0
- #define SUCCS ~FAULT
- #define getch() (bdos(0x08, 0, 0) & 0xff)
-
- typedef unsigned char uchar;
- typedef unsigned int uint;
- typedef unsigned long ulong;
-
- FILE *file1, *file2, *file3, *infile, *outfile;
- int cmd; /* command */
- int cmdupdate; /* Not zero, when updating archive */
- int errorlevel = 0; /* return value */
- long textsize; /* file size before compression */
- long codesize; /* file size after compression */
- long arcpos0; /* position pointer for archive */
- uchar *basedir; /* base directory (home-directory) */
- uchar *wdir = ""; /* work directory */
- uchar workdir[MAXPATH]; /* work directory */
- uchar *infname; /* input file name (for error message) */
- uchar *outfname; /* output file name (for error message)*/
- int attr; /* file attributes for search files */
- int Nfile; /* number of files which was found */
- int fblft, fbsize; /* for buffers handling file names */
- uint seg; /* beginning segment of file name buffers */
- uchar far *fbuf, huge *fbnxt; /* pointer to file name buffers */
- uchar arcname[MAXPATH]; /* archive name */
- uchar pathname[MAXPATH]; /* work for file name (extracting) */
- uchar filename[MAXPATH]; /* work for file name (for file in archive) */
- int patno; /* No. of path names in command line */
- uchar patfile[MAX_PAT][12]; /* file name in command line */
- uchar *patpath[MAX_PAT]; /* directory name in command line */
- int patcnt[MAX_PAT]; /* counts which this name matched */
- uchar patnul[] = "*.*"; /* default path name */
- uchar backup1[MAXPATH], backup2[MAXPATH];
- /* temporary file names */
- uchar flg_r = 0, flg_p = 0, flg_x = 0, flg_m = 0;
- uchar flg_a = 0, flg_c = 0, flg_v = 0, flg_w = 0;
- uchar flg_n = 0, flg_t = 0;
- /* switches */
- uchar copying = 0; /* turn on when copying temporary file */
- uchar crcflg = 0; /* force copyfile() to calculate CRC*/
- uchar tstflg = 0; /* turn on in 't' command */
- uchar swchar; /* switch character */
- uchar *pager = "less"; /* utility used in 'p /v' mode */
- uint crc; /* calculated CRC code */
- uchar *keyword = ""; /* key word for auto-execution */
-
- struct filebuf { /* work for file name buffer */
- void far *next;
- uchar fpos; /* position of file name */
- uchar cpos; /* position of effective path name */
- uchar dir[MAXDIR]; /* full path name */
- } fb0, fb1;
-
- extern char *errmes[]; /* array of pointers to error messages */
- extern uchar use[]; /* usage */
- extern uchar buf2[], buf3[]; /* I/O buffers */
-
- /* routines for handling Japanese strings */
- extern uchar *j_strupr(uchar *p);
- extern int j_strcmp(char *p, char *q);
- extern uchar *j_strchr(char *p, uint c);
- extern uchar *j_strrchr(char *p, uint c);
-
- extern int getfattr(uchar *fn); /* get file attributes */
- extern void setfattr(uchar *fn, int attr);/* set file attributes */
- extern uchar getswchar(void); /* get switch character */
- extern void slash2yen(uchar *p); /* convert '/' to '\' */
-
- extern char M_NOMATCHERR[];
- extern char M_COPYERR[];
- extern char M_NOTLZH[];
- extern char M_OVERWT[];
- extern char M_MKDIR[];
- extern char M_MKDIRERR[];
- extern char M_CRCERR[];
- extern char M_RDONLY[];
-
- union stamp { /* time stamp */
- struct ftime s;
- ulong u;
- };
-
- union stamp arcstamp = {0L}; /* time stamp for archive */
-
- struct LzHead { /* file header */
- uchar HeadSiz, HeadChk, HeadID[5];
- ulong PacSiz, OrgSiz;
- union stamp Ftime;
- uint Attr;
- uchar Fname[MAXPATH];
- } Hdr1, Hdr2;
-
- struct exeHead { /* EXE header for SFX */
- uint exeID, byte, page, reloc;
- uint hdrsize, minalloc, maxalloc, initSS;
- uint initSP, chksum, initIP, initCS;
- uint reloctab, overlay, dummy1, dummy2;
- } ExeHdr = {
- 'MZ', 0, 0, 0, 2, 0, 0xffff, 0xfff0,
- 0x100, 0, 0x100, 0xfff0, 0x1e, 0, 0, 0
- };
-
- /*******************************
- display helps
- *******************************/
- void usage(void)
- {
- fputs(use, stdout);
- exit(0);
- }
-
- /*******************************
- display a message
- *******************************/
-
- void message(uchar *p, uchar *q)
- {
- printf("%s", p);
- if (q) {
- printf(" : '%s'", q);
- }
- printf("\n");
- }
-
- /*******************************
- process for an error
- *******************************/
- void error(int errcode, uchar *p)
- {
- if (copying) { /* error during copying temporary? */
- fprintf(stderr, "\n%s\n", M_COPYERR);
- fclose(file1);
- unlink(arcname); /* erase incomplete archive */
- file1 = NULL;
- }
- fprintf(stderr, "\n%s", errmes[errcode]);
- if (p) {
- fprintf(stderr, " : '%s'", p);
- }
- fprintf(stderr, "\n");
- if (file3) {
- fclose(file3);
- if (!cmdupdate) /* during extracting */
- unlink(pathname); /* delete the file */
- }
- if (file1) {
- fclose(file1);
- if (cmdupdate) /* during updating */
- rename(backup1, arcname); /* recover old archive */
- }
- if (file2) {
- fclose(file2);
- if (!copying) { /* if not copying */
- unlink(backup2); /* delete temporary */
- }
- }
- if (copying)
- exit(3);
- else
- exit(2);
- }
-
- /*******************************
- handle user break
- *******************************/
- int userbreak(void)
- {
- error(CTRLBRK, NULL);
- }
-
- /*******************************
- fopen with detecting error
- *******************************/
- FILE *e_fopen(uchar *fname, uchar *mode, int errID)
- {
- FILE *f;
-
- if ((f = fopen(fname, mode)) == NULL) {
- if (errno == EACCES)
- error(RDONLY, fname);
- error(errID, fname);
- }
- return f;
- }
-
- /*******************************
- rename with detecting error
- *******************************/
- void e_rename(uchar *old, uchar *new)
- {
- if (rename(old, new))
- error(RENAMEERR, old);
- }
-
- /*******************************
- ask 'Y' or 'N'
- *******************************/
- uint getyn(void)
- {
- uint yn;
-
- do {
- yn = toupper(getch());
- } while (yn != 'Y' && yn != 'N');
- fprintf(stderr, "%c\n", yn);
- return yn;
- }
-
- /*******************************
- file name -> internal format
- *******************************/
- void extfn(uchar *p, uchar *pb)
- {
- int i;
- uchar * q;
-
- if ((q = j_strrchr(p, '\\')) != NULL ||
- (q = j_strchr(p, ':')) != NULL)
- p = q + 1;
- q = p;
- for (i = 8; i > 0; i--, pb++) {
- switch (*p) {
- case '*':
- *pb = '?';
- break;
- case '.':
- case '\0':
- *pb = ' ';
- break;
- default:
- *pb = *p++;
- }
- }
- while (+(*p != '\0' && *p++ != '.'));
- for (i = 3; i > 0; i--, pb++) {
- switch (*p) {
- case '*':
- *pb = '?';
- break;
- case '\0':
- *pb = ' ';
- break;
- default:
- *pb = *p++;
- }
- }
- *q = *pb = '\0';
- }
-
- /*******************************
- internal format -> file name
- *******************************/
- void packfn(uchar *p, uchar *q)
- {
- int i;
-
- for (i = 8; i > 0; i--) {
- if (*q != ' ')
- *p++ = *q;
- q++;
- }
- *p++ = '.';
- for (i = 3; i > 0; i--) {
- if (*q != ' ')
- *p++ = *q;
- q++;
- }
- if (p[-1] == '.')
- p--;
- *p = '\0';
- }
-
- /*******************************
- get back to parent directory
- *******************************/
- uchar *backpath(uchar *p)
- {
- uchar *q;
-
- if ((q = j_strrchr(p, '\\')) == NULL &&
- (q = j_strchr(p, ':')) == NULL) {
- *p = '\0';
- q = p;
- } else {
- *++q = '\0';
- }
- return q;
- }
-
- /***********************************
- whether path name was used or not
- ***********************************/
- void tstpat(void)
- {
- int i, cnt;
- uchar path[MAXPATH];
-
- cnt = 0;
- for (i = 0; i < patno; i++)
- cnt += patcnt[i];
- if (cnt == 0) /* no file matched */
- error(NOFILEERR, NULL);
- for (i = 0; i < patno; i++) {
- if (patcnt[i] == 0) { /* if any path name was not used */
- packfn(stpcpy(path, patpath[i]), patfile[i]);
- fprintf(stderr, "%s : '%s'\n", M_NOMATCHERR, path);
- errorlevel = 1; /* display warning */
- }
- }
- }
-
- /*******************************
- make a file header
- *******************************/
- void sethdr(uchar *fn, uint attr, struct LzHead *h)
- {
- uint l;
-
- memset(h, 0, sizeof(struct LzHead));
- l = strlen(fn); /* length of file name */
- h -> Fname[0] = l;
- memcpy(h -> Fname + 1, fn, l);
- l += 20 + 2; /* size of header */
- h -> HeadSiz = l;
- fseek(file3, 0L, SEEK_END);
- h -> OrgSiz = textsize = ftell(file3); /* original size of a file */
- h -> PacSiz = codesize = 0;
- rewind(file3);
- getftime(fileno(file3), &(h -> Ftime.s)); /* get time stamp */
- h -> Attr = attr; /* file attributes */
- memcpy(h -> HeadID, "-lh1-", 5); /* at first, select the method -lh1- */
- }
-
- /*******************************
- write a file header
- *******************************/
- void wthdr(struct LzHead *h)
- {
- arcpos0 = ftell(file2); /* memorize this position */
- if (fwrite(h, h -> HeadSiz + 2, 1, file2) == 0)
- error(WTERR, backup2);
- }
-
- /*******************************
- calculate check-sum of header
- *******************************/
- uchar mksum(struct LzHead *h)
- {
- uchar *p, *q;
- uchar i;
-
- p = (uchar *)h + 2;
- q = p + h -> HeadSiz;
- for (i = 0; p < q; p++)
- i += *p;
- return i;
- }
-
- /*******************************
- remake file header & write
- *******************************/
- void remkhdr(struct LzHead *h)
- {
- int flg;
- long arcpos1;
-
- flg = 0;
- h -> PacSiz = codesize; /* packed size of a file */
- *(uint *)(h -> Fname + *(h -> Fname) + 1) = crc;
- if (h -> OrgSiz <= codesize) { /* if packed size >= original size */
- flg = 1; /* select method "simple copy" */
- memcpy(h -> HeadID, "-lh0-", 5);
- h -> PacSiz = h -> OrgSiz;
- }
- h -> HeadChk = mksum(h); /* header sum */
- arcpos1 = ftell(file2); /* memorize this position */
- fseek(file2, arcpos0, SEEK_SET); /* seek to header */
- fwrite(h, h -> HeadSiz + 2, 1, file2); /* rewrite header */
- if (flg) {
- rewind(file3);
- copyfile(file3, file2, h -> OrgSiz); /* do simple copy */
- } else {
- fseek(file2, arcpos1, SEEK_SET); /* return to the end */
- }
- }
-
- /*******************************
- get a file header
- *******************************/
- uchar *gethdr(FILE *arc, struct LzHead *h)
- {
- uchar *q, i;
-
- if ((h -> HeadSiz = getc(arc)) <= 0 ||
- h -> HeadSiz > sizeof(struct LzHead) - 3 ||
- fread(&(h -> HeadChk), h -> HeadSiz + 1, 1, arc) == 0)
- { /* read file header */
- return NULL;
- }
- if (mksum(h) != h -> HeadChk) /* if sum is wrong */
- return NULL;
- i = *(h -> Fname);
- strncpy(filename, h -> Fname + 1, i);
- *(filename + i) = '\0';
- if ((q = j_strrchr(filename, '\\')) == NULL &&
- (q = j_strchr(filename, ':')) == NULL)
- q = filename;
- else
- q++;
- return q; /* return the portion of file name */
- }
-
- /*******************************
- test match of file name
- *******************************/
- int matchpat(uchar *p)
- {
- uchar buf[12], name[MAXPATH];
- int i, j, retcode;
-
- retcode = FAULT;
- strcpy(name, p);
- extfn(name, buf);
- for (i = 0; i < patno; i++) {
- if (flg_p || *patpath[i]) { /* should compare full path ? */
- if (j_strcmp(name, patpath[i]))
- continue;
- }
- for (j = 0; j < 11; j++) { /* compare file name */
- if (patfile[i][j] != buf[j] && patfile[i][j] != '?')
- break;
- }
- if (j == 11) { /* if matched */
- patcnt[i]++;
- retcode = SUCCS;
- }
- }
- return retcode;
- }
-
- /*******************************
- ratio * 1000
- *******************************/
- uint ratio(ulong a, ulong b)
- {
- int i;
-
- if (!b) return 0; /* if diviser == 0 */
- for (i = 0; i < 3 && a < 0x19999999; i++) {
- a *= 10; /* while not overflow */
- } /* upto 1000 times */
- for (; i < 3; i++) { /* the case of overflow */
- b /= 10;
- }
- a += b / 2; /* for round up */
- return (a / b); /* return (a * 1000 / b) */
- }
-
- /*******************************
- compare names
- *******************************/
- int cmpname(uchar *f0, uchar *f1, uchar *p0, uchar *p1)
- {
- int c;
-
- c = j_strcmp(f0, f1); /* compare only file names */
- if (c == 0) {
- c = strlen(p0) - strlen(p1); /* compare lengths of path names */
- if (c == 0) {
- c = j_strcmp(p0, p1); /* compare path names */
- }
- }
- return c;
- }
-
- /*******************************
- regist file names
- *******************************/
- void regfile(uchar *p, uchar *q, uchar *f)
- /*
- p: full path name including base directory
- q: directory name to be registed
- f: file name
- */
- {
- uchar path[MAXPATH];
- struct filebuf far *f0;
- struct filebuf far *f1;
- uchar *s;
- int c, size;
-
- if (strstr(f, "LHARC.)1(") || strstr(f, "LHARC.)2("))
- return; /* temporary file ? */
- stpcpy(stpcpy(path, q), f);
- stpcpy(s = stpcpy(fb1.dir, p), f);
- fb1.fpos = s - (uchar *)&fb1;
- fb1.cpos = flg_x ? (q - p) + (fb1.dir - (uchar *)&fb1) : fb1.fpos;
- if (fbuf == NULL) { /* for first entry */
- if (allocmem(fbsize = 0x100, &seg) != -1)
- error(MEMOVRERR, NULL);
- fbuf = (uchar far *)fbnxt = MK_FP(seg, 0);
- fblft = 0x1000 - 4;
- *(long far *)fbuf = 0;
- fbnxt += 4;
- }
- f0 = (struct filebuf far *)fbuf;
- do { /* search position in which should be inserted*/
- f1 = f0;
- if ((f0 = f0 -> next) == NULL)
- break;
- fb0 = *f0;
- c = cmpname((uchar *)&fb0 + fb0.fpos, (uchar *)&fb1 + fb1.fpos,
- (uchar *)&fb0 + fb0.cpos, (uchar *)&fb1 + fb1.cpos);
- } while (c < 0);
-
- if (f0 && c == 0 && j_strcmp(fb0.dir, fb1.dir)) {
- error(DUPFNERR, (uchar *)&fb1 + fb1.cpos);
- } /* same registing names of different files */
-
- if (f0 == NULL || c) { /* do regist */
- size = strlen(fb1.dir) +
- (fb1.dir - (uchar *)&fb1) + 1;
- if (fblft < sizeof(struct filebuf)) { /* if buffer is short */
- if (setblock(seg, fbsize += 0x100) != -1)
- error(TOOMANYERR, NULL);
- fblft += 0x1000;
- }
- fb1.next = f0;
- f0 = (struct filebuf far *)fbnxt;
- f1 -> next = f0;
- *f0 = fb1;
- fblft -= size;
- fbnxt += size;
- }
- }
-
- /*******************************
- recursive collection of files
- *******************************/
- int travel(uchar *p, uchar *q, uchar *f)
- {
- struct ffblk ffb;
- static uchar buf[12];
- uchar *r, *s;
- int done, cnt, j;
-
- cnt = 0;
- if (flg_r == 1 || j_strrchr(q, '\\') == q + strlen(q) - 1) {
- stpcpy(s = q + strlen(q), "*.*");
- }
- done = findfirst(p, &ffb, attr); /* search the first file */
- s = backpath(q);
- while (! done) {
- if (ffb.ff_attrib & 0x10) { /* if this is a sub-directory */
- if (ffb.ff_name[0] != '.') {
- r = stpcpy(stpcpy(s, ffb.ff_name), "\\");
- if (r - p > MAXPATH)
- error(TOOLONGERR, p);
- cnt += travel(p, q, f); /* search recursively */
- *s = '\0';
- }
- } else /* if this is a file */
- if (flg_r == 2) { /* in /r2 mode */
- cnt++;
- regfile(p, q, ffb.ff_name); /* regist name */
- } else { /* in /r+ mode */
- stpcpy(s, ffb.ff_name);
- extfn(s, buf);
- for (j = 0; j < 11; j++) { /* test file names */
- if (f[j] != buf[j] && f[j] != '?')
- break;
- }
- if (j == 11) {
- cnt++;
- regfile(p, q, ffb.ff_name); /* if match, regist */
- }
- }
- done = findnext(&ffb);
- }
- return cnt; /* number of registed files */
- }
-
- /**********************************
- non-recursive collection of files
- **********************************/
- int findfile(uchar *p, uchar *q)
- {
- struct ffblk ffb;
- int done, cnt;
-
- cnt = 0;
- done = findfirst(p, &ffb, attr);
- backpath(p);
- while (! done) {
- cnt++;
- regfile(p, q, ffb.ff_name);
- done = findnext(&ffb);
- }
- return cnt;
- }
-
- /*******************************
- make file lists to append
- *******************************/
- void mklist(void)
- {
- uchar path[MAXPATH], *p, *q, *r;
- int i, cnt;
-
- Nfile = 0;
- if (flg_a) { /* set attributes for search */
- attr = 0x07;
- } else {
- attr = 0;
- }
- if (flg_r) {
- attr |= 0x10;
- }
- for (i = 0; i < patno; i++) {
- p = patpath[i];
- q = path;
- if (*p && p[1] == ':') { /* if path name includes drive */
- q = stpcpy(path, p); /* ignore base directory */
- r = path + 2; /* don't regist drive name */
- } else {
- q = stpcpy(r = stpcpy(path, basedir), p);
- }
- if (flg_r == 1) { /* /r+ mode */
- cnt = travel(path, r, patfile[i]);
- } else if (flg_r > 1) { /* /r2 mode */
- packfn(q, patfile[i]);
- cnt = travel(path, r, NULL);
- } else { /* /r- mode */
- packfn(q, patfile[i]);
- cnt = findfile(path, r);
- }
- Nfile += patcnt[i] = cnt;
- }
- }
-
- /*******************************
- make file header
- *******************************/
- uchar *mkhdr(struct filebuf far *f, struct LzHead *h)
- {
- int attr;
-
- fb0 = *f;
- attr = getfattr(fb0.dir);
- file3 = e_fopen(fb0.dir, "rb", RDERR);
- sethdr((uchar *)&fb0 + fb0.cpos, attr, h);
- return (uchar *)&fb0 + fb0.fpos; /* position of file name */
- }
-
- uint blkcnt;
- uint curcnt;
- uint nxtcnt;
- uint namcnt;
-
- /*******************************
- calculate and display
- for indicator
- *******************************/
- void blkdisp(long l, char *s) {
- uint i;
-
- if (flg_n == 0) {
- fprintf(stderr, "\n %s : ", s);
- blkcnt = (l + 4095) / 4096;
- i = (blkcnt > MAXBLK) ? MAXBLK : blkcnt;
- while (i-- > 0) {
- putc('.', stderr);
- }
- fprintf(stderr, "\r %s : ", s);
- curcnt = nxtcnt = 0;
- } else {
- curcnt = 0;
- nxtcnt = -1;
- }
- }
-
- /*******************************
- let cursor back after
- displaying indicator
- *******************************/
- void curback(void)
- {
- if (flg_n == 0) {
- fprintf(stderr, "\r ");
- }
- }
-
- /*******************************
- freeze a file
- *******************************/
- void freeze(uchar *p)
- {
- if (arcstamp.u < Hdr2.Ftime.u)
- arcstamp.u = Hdr2.Ftime.u;
- printf("%s ", p);
- blkdisp(Hdr2.OrgSiz, "Freezing ");
- wthdr(&Hdr2);
- setvbuf(file3, buf3, _IOFBF, 4096);
- infile = file3;
- outfile = file2;
- infname = p;
- crc = 0;
- Encode();
- remkhdr(&Hdr2);
- curback();
- printf("Frozen(%3d%%)\n", ratio(Hdr2.PacSiz, Hdr2.OrgSiz) / 10);
- }
-
- /*******************************
- Copy a file from
- old archive
- *******************************/
- void copyold()
- {
- if (arcstamp.u < Hdr1.Ftime.u)
- arcstamp.u = Hdr1.Ftime.u;
- wthdr(&Hdr1); /* copy from old archive */
- copyfile(file1, file2, Hdr1.PacSiz);
- }
-
- /*******************************
- execute one of a, u, m
- commands
- *******************************/
- int execappend(void)
- {
- struct filebuf far *f0;
- uchar *p, *q;
- int c, d;
- int cnt = 0;
-
- q = file1 ? gethdr(file1, &Hdr1) : NULL; /* read header from old arc */
- if ((f0 = ((struct filebuf far *)fbuf) -> next) != NULL) {
- p = mkhdr(f0, &Hdr2); /* make header from the file list */
- }
- while (1) {
- if (f0 == NULL) {
- d = 1;
- if (q == NULL)
- break;
- } else if (q == NULL) {
- d = -1;
- } else {
- d = cmpname(p, q, (uchar *)&fb0 + fb0.cpos, filename);
- }
- c = d;
- if (c == 0) {
- if (flg_c || Hdr1.Ftime.u < Hdr2.Ftime.u) {
- c = -1;
- } else {
- c = 1;
- }
- }
- if (c < 0) { /* freeze a new file */
- if (d == 0) {
- fseek(file1, Hdr1.PacSiz, SEEK_CUR);
- q = gethdr(file1, &Hdr1); /* skip a file in old */
- } /* archive */
- freeze(fb0.dir);
- fclose(file3);
- cnt++;
- if ((f0 = fb0.next) != NULL) { /* make header of the next */
- p = mkhdr(f0, &Hdr2); /* file in file list */
- }
- } else { /* copy a file from old archive */
- if (d == 0) {
- fclose(file3);
- if ((f0 = fb0.next) != NULL) { /* make header of the next */
- p = mkhdr(f0, &Hdr2); /* file in file list */
- }
- }
- copyold();
- q = gethdr(file1, &Hdr1); /* get the next header */
- } /* in old archive */
- }
- return cnt;
- }
-
- /*******************************
- delete files after
- execution of updating
- in 'm' command
- *******************************/
- void delfile(void)
- {
- struct filebuf far *f0;
- struct filebuf fb0;
-
- f0 = (struct filebuf far *)fbuf;
- while ((f0 = f0 -> next) != NULL) {
- fb0 = *f0;
- unlink(fb0.dir);
- };
- }
-
- /*******************************
- open an old archive
- *******************************/
- void openarc1(void)
- {
- uchar *p, *q;
-
- file1 = e_fopen(infname = arcname, "rb", NOARCERR);
- q = buf2 - 5 + fread(buf2, 1, 2048, file1);
- for (p = buf2; p < q; p++) {
- if (p[0] == '-' && p[1] == 'l' && p[4] == '-') break;
- }
- if (p >= q) {
- error(NOFILEERR, arcname);
- }
- fseek(file1, (long)(p - buf2 - 2), SEEK_SET);
- }
-
- /*******************************
- open an archive in rd/wt
- for testing read-only
- *******************************/
- void openrwarc1(void)
- {
- file1 = e_fopen(arcname, "r+b", NOARCERR);
- }
-
- /*******************************
- close an old archive
- & rename to temporary
- *******************************/
- void openbackup1(void)
- {
- fclose(file1);
- stpcpy(backpath(strcpy(backup1, arcname)), "lharc.)1(");
- e_rename(arcname, backup1);
- file1 = fopen(infname = backup1, "rb");
- }
-
- /*******************************
- open a temporary file
- for a new archive
- *******************************/
- void openbackup2(void)
- {
- if (flg_w) {
- stpcpy(stpcpy(backup2, workdir), "lharc.)2(");
- } else {
- strcat(backpath(strcpy(backup2, arcname)), "lharc.)2(");
- }
- file2 = e_fopen(outfname = backup2, "w+b", MKTMPERR);
- setvbuf(file2, buf2, _IOFBF, 4096);
- }
-
- /*******************************
- set time & close an archive
- *******************************/
- void stclosearc(FILE *f)
- {
- if (flg_t) {
- fflush(f);
- setftime(fileno(f), &arcstamp.s);
- }
- fclose(f);
- }
-
- /*******************************
- end-of-job process
- in making new archive
- *******************************/
- void endofupdate(int cnt)
- {
- stclosearc(file1);
- tstpat();
- if (cnt) { /* if any files are manipulated */
- if (file1)
- if (unlink(backup1)) /* delete an old archive */
- printf("debug : Failed in deleting '%s'.", backup1);
- if ((arcpos0 = ftell(file2)) != 0) {
- if (putc(0, file2) == EOF)
- error(WTERR, backup2);
- if (flg_w) { /* if work directory is assigned */
- rewind(file2);
- infname = backup2;
- copying = 1; /* copy temporary to new archive */
- file1 = e_fopen(outfname = arcname, "wb", MKFILEERR);
- printf("Copying Temp to Archive ...");
- copyfile(file2, file1, arcpos0 + 1);
- printf("\n");
- copying = 0;
- stclosearc(file1);
- fclose(file2);
- unlink(backup2);
- } else {
- stclosearc(file2); /* else rename temporary to archive */
- rename(backup2, arcname);
- }
- } else {
- fclose(file2);
- unlink(backup2);
- }
- } else { /* if no change was made in archive */
- fclose(file2);
- unlink(backup2);
- rename(backup1, arcname); /* restore the old archive */
- }
- }
-
- /*******************************
- a, u, m command
- *******************************/
- void append(void)
- {
- int cnt;
-
- file1 = fopen(arcname, "r+b");
- if (file1) {
- openbackup1(); /* if archive presents, rename to temp */
- } else {
- if (errno == EACCES)
- error(RDONLY, arcname); /* read-only error */
- }
- mklist(); /* make a file list */
- if (Nfile == 0) {
- error(NOFILEERR, NULL);
- }
- if (file1) {
- message("Updating archive", arcname);
- } else {
- message("Creating archive", arcname);
- }
- openbackup2(); /* open temporary for new archive */
- cnt = execappend(); /* execute updating archive */
- endofupdate(cnt); /* end-of-job process */
- if (cmd == 'M')
- delfile(); /* if 'm' command, delete files */
- freemem(seg);
- }
-
- /*******************************
- f command
- *******************************/
- void freshen(void)
- {
- uchar path[MAXPATH];
- int c;
- int cnt = 0;
-
- openrwarc1(); /* open an archive */
- message("Freshening archive", arcname);
- openbackup1(); /* rename the archive to temp. */
- openbackup2(); /* open temp. for a new archive */
- while (gethdr(file1, &Hdr1)) {
- c = 0;
- if (matchpat(filename)) {
- stpcpy(stpcpy(path, basedir), filename);
- if ((file3 = fopen(path, "rb")) != NULL) {
- sethdr(filename, getfattr(path), &Hdr2);
- if (flg_c || Hdr1.Ftime.u < Hdr2.Ftime.u) {
- c = 1; /* found the file to be updated */
- }
- }
- }
- if (c) {
- freeze(path); /* do updating */
- cnt++;
- fseek(file1, Hdr1.PacSiz, SEEK_CUR);
- } else {
- copyold();
- }
- fclose(file3);
- }
- endofupdate(cnt); /* end-of-job process */
- }
-
- /*******************************
- test the file which
- should be melted
- *******************************/
- int tstdir(uchar *name)
- {
- uchar path[MAXPATH], *p, yn;
- struct ffblk ffb;
-
- p = name;
- if (*p && p[1] == ':') /* skip a drive name */
- p += 2;
- if (*p == '\\') /* skip a root mark('\') */
- p++;
- yn = flg_m ? 'Y' : 'N';
- while ((p = j_strchr(p, '\\')) != NULL) { /* skip to next '\' */
- memcpy(path, name, p - name);
- path[p - name] = '\0';
- if (findfirst(path, &ffb, 0x1f)) { /* Is there this directory? */
- if (yn == 'N') {
- fprintf(stderr, "'%s' : %s", name, M_MKDIR);
- yn = getyn();
- }
- if (yn == 'N') {
- return FAULT;
- } else {
- if (mkdir(path)) { /* make directory */
- error(MKDIRERR, path);
- }
- }
- } else {
- if ((ffb.ff_attrib & 0x10) == 0) {
- error(MKDIRERR, path); /* if the name isn't directory */
- }
- }
- p++;
- }
- if (! findfirst(name, &ffb, 0x1f)) { /* if a file has the same name */
- if (ffb.ff_attrib & 0x01 && ffb.ff_attrib != Hdr1.Attr) {
- /* if the file is read-only, */
- /* attributes must match */
- fprintf(stderr, "'%s' %s\n", M_RDONLY);
- return FAULT;
- }
- yn = 'Y';
- if (flg_c == 0) {
- if (((ulong)ffb.ff_fdate << 16) + (ulong)ffb.ff_ftime
- < Hdr1.Ftime.u) { /* compare time stamps */
- yn = 'Y';
- } else {
- printf("Skipped : '%s' : New or same file exists.\n", name);
- yn = 'N';
- }
- }
- if (yn == 'Y' && flg_m == 0) {
- fprintf(stderr, "'%s' : %s", name, M_OVERWT);
- yn = getyn(); /* may overwrite? */
- }
- if (yn == 'N') {
- return FAULT;
- }
- setfattr(name, 0x20); /* reset attributes */
- }
- return SUCCS;
- }
-
- /*******************************
- read header-ID (method)
- *******************************/
- int tstID(uchar *h)
- {
- int m;
- static uchar IDpat[4][6] =
- {"-lz4-", "-lz5-", "-lh0-", "-lh1-"};
-
- m = 3;
- while (m >= 0 && memcmp(h, IDpat[m], 5)) {
- m--;
- }
- return m;
- }
-
- /*******************************
- e, x, p, t command
- *******************************/
- int extract(void)
- {
- uchar *p, *q;
- int m;
- int cnt = 0;
-
- openarc1(); /* open an archive */
- setvbuf(file1, buf2, _IOFBF, 4096);
- message("Extract from", arcname);
- if (flg_v == 1)
- fprintf(file3, "Extract from '%s'\n", arcname);
- while ((p = gethdr(file1, &Hdr1)) != NULL) {
- if (matchpat(filename)) {
- arcpos0 = ftell(file1) + Hdr1.PacSiz;
- if (cmd == 'E') { /* if extract command, */
- if (flg_x) { /* get the destination path name */
- p = stpcpy(pathname, basedir);
- if (filename[0] == '\\') {
- p = pathname;
- if (*p && p[1] == ':') {
- p += 2;
- }
- }
- stpcpy(p, filename);
- } else {
- stpcpy(stpcpy(pathname, basedir), p);
- }
- }
- if (cmd != 'E' || tstdir(pathname)) {
- if ((m = tstID(Hdr1.HeadID)) < 0) {
- printf("Skipped : '%s' : Unknown method\n", pathname);
- } else if (cmd == 'T' && Hdr1.HeadSiz - Hdr1.Fname[0] != 22) {
- printf("Skipped : '%s' : CRC not supported\n", filename);
- } else {
- cnt++;
- p = "Melting ";
- q = "Melted ";
- switch (cmd) {
- case 'E':
- printf("%s ", pathname);
- file3 = fopen(outfname = pathname, "wb");
- break;
- case 'T':
- printf("%s ", filename);
- file3 = fopen("nul", "wb");
- p = "Testing ";
- q = "Tested ";
- break;
- case 'P':
- if (flg_v != 2)
- fprintf(file3, "<<< %s >>>\n", filename);
- if (flg_v)
- printf("%s ", filename);
- fflush(file3);
- setmode(fileno(file3), O_BINARY);
- break;
- }
- if ((ioctl(fileno(file3), 0) & 0x82) == 0x82) {
- flg_n = 1; /* Console output ? */
- } else {
- setvbuf(file3, buf3, _IOFBF, 4096);
- }
- blkdisp(Hdr1.OrgSiz, p);
- outfile = file3;
- infile = file1;
- textsize = Hdr1.OrgSiz;
- crc = 0;
- if (m == 3) {
- Decode(); /* extract LHarc's file */
- } else if (m == 1) {
- DecodeOld(); /* extract LArc's file */
- } else {
- crcflg = 1;
- copyfile(infile, outfile, Hdr1.OrgSiz);
- crcflg = 0; /* only stored file */
- }
- if (fflush(file3)) {
- error(WTERR, outfname);
- }
- if (cmd == 'E') {
- setftime(fileno(file3), &Hdr1.Ftime.s);
- fclose(file3);
- setfattr(pathname, Hdr1.Attr);
- file3 = NULL;
- } else if (cmd == 'T') {
- fclose(file3);
- } else {
- setmode(fileno(file3), O_TEXT);
- if (flg_v != 2)
- fprintf(file3, "\n");
- }
- curback();
- if (Hdr1.HeadSiz - Hdr1.Fname[0] == 22 &&
- *(uint *)(&Hdr1.Fname[1] + Hdr1.Fname[0]) != crc) {
- errorlevel = 1; /* test CRC */
- printf("CRC err\n");
- } else if (cmd != 'P' || flg_v != 0) {
- printf("%s\n", q);
- }
- }
- }
- fseek(file1, arcpos0, SEEK_SET); /* move pointer to next file */
- } else {
- fseek(file1, Hdr1.PacSiz, SEEK_CUR);
- }
- }
- fclose(file1);
- file1 = NULL;
- return cnt;
- }
-
- /*******************************
- d command
- *******************************/
- void delete(void)
- {
- int cnt = 0;
-
- openrwarc1(); /* open archive */
- if (patno == 0) {
- error(NOFNERR, NULL);
- }
- message("Updating archive", arcname);
- openbackup1(); /* rename to temporary name */
- openbackup2(); /* open another temporary file */
- while (gethdr(file1, &Hdr1)) {
- if (matchpat(filename)) {
- message("Deleting", filename);
- cnt++;
- fseek(file1, Hdr1.PacSiz, SEEK_CUR); /* skip file */
- } else {
- copyold();
- }
- }
- endofupdate(cnt); /* end-of-job process */
- }
-
- /*******************************
- s command
- *******************************/
- void self(void)
- {
- uchar *p, /* *q,*/ buf[12], yn;
- int flg, i;
- long l, m, n;
- void sfx(void), sfx2(void);
-
- openarc1(); /* open archive */
- message("Making Sfx from archive", arcname);
- stpcpy(stpcpy(backup2, workdir), "lharc.)2(");
- file2 = e_fopen(outfname = backup2, "w+b", MKTMPERR);
- /* open temporary */
- while (gethdr(file1, &Hdr1)) {
- flg = 0;
- if (matchpat(filename)) {
- printf("Extracting '%s' ", filename);
- if (tstID(Hdr1.HeadID) < 2) {
- printf("(not supported) skipped.");
- } else {
- if (flg_x == 0 && (p = j_strrchr(filename, '\\')) != NULL) {
- p++; /* delete directory part */
- Hdr1.Fname[0] = strlen(p);
- i = p - filename;
- Hdr1.HeadSiz -= i;
- memcpy(Hdr1.Fname + 1, Hdr1.Fname + 1 + i,
- Hdr1.Fname[0] + 2);
- Hdr1.HeadChk = mksum(&Hdr1); /* recalculate sum */
- }
- wthdr(&Hdr1);
- copyfile(file1, file2, Hdr1.PacSiz);
- flg = 1;
- }
- printf("\n");
- }
- if (flg == 0) {
- fseek(file1, Hdr1.PacSiz, SEEK_CUR);
- }
- }
- fclose(file1);
- if (putc(0, file2) == EOF) /* end-mark of archive */
- error(WTERR, backup2);
- if ((l = ftell(file2)) <= 1) {
- goto self9;
- }
- if (flg_x == 0) {
- m = (uchar*)sfx2 - (uchar*)sfx; /* size of sfx routine */
- } else {
- m = (uchar*)usage - (uchar*)sfx2;
- }
- n = l + m; /* total size of sfx file */
- rewind(file2);
- infname = backup2;
- extfn(arcname, buf); /* make the name of sfx */
- p = stpcpy(pathname, basedir);
- strcpy(&buf[8], "COM");
- if (flg_x || n > 0xfe80ul) {
- strcpy(&buf[8], "EXE");
- }
- packfn(p, buf);
- if ((getfattr(pathname) & 0x8000) == 0) { /* if the same name exists */
- fprintf(stderr, "'%s' : %s", pathname, M_OVERWT);
- yn = getyn(); /* may overwrite */
- if (yn == 'N') {
- goto self9;
- }
- }
- file3 = e_fopen(outfname = pathname, "wb", MKFILEERR);
- if (buf[8] == 'E') { /* if .EXE */
- if (flg_x) {
- n = m;
- }
- n += 0x20;
- ExeHdr.page = (n + 511) / 512;
- ExeHdr.byte = n % 512;
- ExeHdr.minalloc = (flg_x ? 0x66c0 : 0x2560) / 0x10;
- if (fwrite(&ExeHdr, 0x20, 1, file3) == 0)
- error(WTERR, pathname);
- }
- movedata(_CS, (flg_x ? (unsigned)sfx2 : (unsigned)sfx),
- _DS, (unsigned)buf2, m);
- if (flg_x) {
- memcpy(buf2 + 0x34, p, strlen(p)); /* large ver. */
- } else {
- *((uint *)buf2 + 1) = (l + m + 0x10f) / 0x10; /* small ver. */
- }
- if (fwrite(buf2, m, 1, file3) == 0) /* write sfx routine */
- error(WTERR, pathname);
- if (flg_x) {
- if (fwrite(keyword, strlen(keyword) + 1, 1, file3) == 0)
- error(WTERR, pathname);
- }
- copyfile(file2, file3, l); /* write an archive */
- printf("\nCreated : '%s'\n", pathname);
- fclose(file3);
- self9:
- fclose(file2);
- unlink(backup2);
- }
-
- /*******************************
- l, v command
- *******************************/
- void list(void)
- {
- uint rt;
- uchar buf[79], *p;
- static uchar attr[7] = "ohs--a";
- int i, j, k, Fno;
- ulong Osize, Psize;
-
- Fno = Osize = Psize = 0;
- openarc1(); /* open archive */
- printf("Listing of archive : '%s'\n\n", arcname);
- printf(" Name Original Packed Ratio"
- " Date Time Attr Type CRC\n");
- printf("-------------- -------- -------- ------"
- " -------- -------- ---- ----- ----\n");
- while ((p = gethdr(file1, &Hdr1)) != NULL) {
- if (matchpat(filename)) {
- rt = ratio(Hdr1.PacSiz, Hdr1.OrgSiz);
- sprintf(buf, " %10lu%10lu %3d.%1d%% "
- "%2d-%02d-%02d %2d:%02d:%02d ---w %04X\n",
- Hdr1.OrgSiz, Hdr1.PacSiz, rt / 10, rt % 10,
- (Hdr1.Ftime.s.ft_year + 80) % 100, Hdr1.Ftime.s.ft_month,
- Hdr1.Ftime.s.ft_day, Hdr1.Ftime.s.ft_hour,
- Hdr1.Ftime.s.ft_min, Hdr1.Ftime.s.ft_tsec * 2,
- *(uint *)(&Hdr1.Fname[1] + Hdr1.Fname[0]));
- memcpy(&buf[65], Hdr1.HeadID, 5);
- for (i = 0, j = 1; i < 6; i++, j <<= 1) { /* attributes */
- if (Hdr1.Attr & j) {
- k = attr[i];
- if (i <= 2) {
- buf[63 - i] = k;
- } else {
- buf[60] = k;
- }
- }
- }
- if (Hdr1.HeadSiz - Hdr1.Fname[0] != 22) {
- memset(&buf[71], '*', 4); /* if no CRC suppoted */
- }
- if (flg_x) {
- printf("%s\n", filename); /* display in 2 lines */
- } else {
- if (p != filename) { /* display in one line */
- *buf = '+';
- }
- memcpy(&buf[2], p, strlen(p));
- }
- printf(buf);
- Fno ++;
- Osize += Hdr1.OrgSiz;
- Psize += Hdr1.PacSiz;
- }
- if (fseek(file1, Hdr1.PacSiz, 1))
- break;
- }
- if (Fno) {
- printf("-------------- -------- -------- ------"
- " -------- --------\n");
- rt = ratio(Psize, Osize);
- getftime(fileno(file1), &arcstamp.s);
- printf(" %3d files %10lu%10lu %3d.%1d%% "
- "%2d-%02d-%02d %2d:%02d:%02d\n",
- Fno, Osize, Psize, rt / 10, rt % 10,
- (arcstamp.s.ft_year + 80) % 100, arcstamp.s.ft_month,
- arcstamp.s.ft_day, arcstamp.s.ft_hour,
- arcstamp.s.ft_min, arcstamp.s.ft_tsec * 2);
- } else {
- printf(" no file\n");
- }
- fclose(file1);
- }
-
- /*******************************
- get switches
- *******************************/
- void getsw(uchar *p)
- {
- static uchar flg[] = "rpxmacntvw";
- static uchar *flgpos[] = {&flg_r, &flg_p, &flg_x, &flg_m,
- &flg_a, &flg_c, &flg_n, &flg_t,
- &flg_v, &flg_w};
- int i;
- uchar s;
- uchar *q;
-
- while ((s = *p++) != 0) {
- q = j_strchr(flg, s); /* search switch */
- if (q) {
- i = q - flg;
- if (*p == '+') {
- *flgpos[i] = 1;
- p++;
- } else if (*p == '-') {
- *flgpos[i] = 0;
- p++;
- } else if (*p == '2') {
- *flgpos[i] = 2;
- p++;
- } else if (s == 'v' && *p) {
- if (flg_v == 0) /* process of '/vSTRING' */
- flg_v = 1;
- pager = p;
- p = "";
- } else if (s == 'w' && *p) {
- flg_w = 1; /* process of '/wSTRING' */
- wdir = p;
- p = "";
- } else {
- if (*flgpos[i]) { /* flip-flop */
- *flgpos[i] = 0;
- } else {
- *flgpos[i] = 1;
- }
- }
- if (s == 'r' && flg_r > 0) {
- flg_x = 1;
- }
- } else if (s == 'k') {
- keyword = p;
- p = "";
- } else {
- if (s == '?') usage();
- error(INVSWERR, NULL);
- }
- }
- }
-
- /*******************************
- execute command
- *******************************/
- void executecmd()
- {
- int handle;
- int cnt;
-
- switch (cmd) {
- case 'A':
- flg_c++;
- case 'U':
- case 'M':
- append();
- break;
- case 'F':
- freshen();
- break;
- case 'P':
- if (flg_v == 0) {
- file3 = stdout;
- goto common;
- }
- stpcpy(stpcpy(pathname, workdir), "LHARC.TMP"); /* view files */
- file3 = e_fopen(outfname = pathname, "w", MKTMPERR);
- cnt = extract();
- fclose(file3);
- if (cnt) /* if any files extracted */
- stpcpy(stpcpy(stpcpy(buf2, pager), " "), pathname);
- execute(buf2); /* execute by INT 0x2e */
- #if 0
- spawnlp(P_WAIT, pager, pager, pathname, NULL);
- #endif
- unlink(pathname);
- break;
- case 'T':
- tstflg = 1;
- goto common;
- case 'X':
- case 'E':
- cmd = 'E';
- common:
- flg_v = 0;
- extract();
- break;
- case 'V':
- flg_x++;
- case 'L':
- list();
- break;
- case 'D':
- delete();
- break;
- case 'S':
- self();
- break;
- }
- fputc('\n', stderr);
- }
-
- int cbrk;
-
- void recovercbrk(void) {
- setcbrk(cbrk);
- }
-
- /*******************************
- main routine
- *******************************/
- int main(int argc, uchar *argv[])
- {
- uchar *p, *q, *env, *env9;
- int i, yn;
- extern char title[];
- struct ffblk ffb;
-
- ctrlbrk(userbreak); /* set vector for '^C' */
- cbrk = getcbrk();
- setcbrk(1);
- atexit(recovercbrk);
- fputs(title, stderr); /* output title */
- putchar('\n');
- mkcrc(); /* make CRC table */
- swchar = getswchar(); /* get the setting of switch char */
- argc--;
- argv++;
- if (argc-- == 0)
- usage(); /* if no parameter given */
- p = (argv++)[0];
- cmd = toupper(*p);
- if (strlen(p) - 1 || j_strchr("EXTDLVAUMFPS", cmd) == 0) {
- cmd = 'L'; /* if no command, assume 'L' command */
- argc++;
- argv--;
- }
- cmdupdate = (int)j_strchr("AUMFD", cmd); /* command updating archive? */
- if ((env = getenv("TMP")) != NULL) { /* get 'TMP' from environment */
- wdir = env;
- flg_w = 1;
- }
- if ((env = getenv("LHARC")) != NULL) { /* get 'LHARC' from environment */
- for (p = env; *p != '\0'; p++) {
- if (*p == ' ' || *p == '\x08')
- *p = '\0';
- }
- env9 = p;
- p = env;
- while (p < env9) {
- while (*p == '\0') p++;
- if (*p == swchar || *p == '-') p++;
- getsw(p);
- while (*p) p++;
- }
- }
- patno = -1;
- basedir = NULL;
- while (argc--) {
- p = (argv++)[0];
- if (*p == swchar || *p == '-') {
- getsw(++p);
- } else {
- slash2yen(j_strupr(p)); /* convert '/' to '\' */
- if (patno < 0) { /* get archive name */
- strcpy(arcname, p);
- if ((p = j_strrchr(arcname, '\\')) == NULL) {
- p = arcname; /* pointer of the part of file name */
- }
- if ((q = j_strchr(p, '.')) == NULL) {
- strcat(arcname, ".LZH"); /* if no extension */
- } else if (j_strcmp(".LZH", q) && flg_m == 0 && cmdupdate) {
- fprintf(stderr, M_NOTLZH, arcname);
- yn = getyn(); /* if the extension is not '.LZH' */
- if (yn == 'N') {
- exit(1);
- }
- }
- patno++;
- } else {
- if (patno == 0 && basedir == NULL &&
- (j_strrchr(p, '\\') == p + strlen(p) - 1 ||
- p[strlen(p) - 1] == ':')) {
- basedir = p; /* get base (or home) directory */
- } else if (patno >= MAX_PAT) {
- message("File table overflow. ignore", p);
- } else {
- patpath[patno] = p;
- extfn(p, patfile[patno]);
- patno++; /* regist path names */
- }
- }
- }
- }
- if (patno < 0) {
- error(NOARCNMERR, NULL);
- }
- if (patno == 0 && cmd != 'D') { /* if no name given */
- extfn(patpath[0] = patnul, patfile[0]); /* '*.*' is assumed */
- patno++;
- }
- p = stpcpy(workdir, wdir) - 1;
- if (*workdir != '\0' && j_strrchr(workdir, '\\') != p && *p != ':') {
- strcat(workdir, "\\"); /* concatenate '\' after the work dir. */
- }
- if (cmdupdate) {
- if (j_strchr(arcname, '*') || j_strchr(arcname, '?')) {
- error(NOARCERR, arcname);
- } /* when updating archive, wild cards can't used */
- executecmd();
- } else {
- if (findfirst(arcname, &ffb, 0x07)) {
- error(NOARCERR, arcname);
- }
- do {
- strcpy(backpath(arcname), ffb.ff_name);
- executecmd();
- } while (!findnext(&ffb));
- if (cmd != 'L' && cmd != 'V')
- tstpat(); /* whether all given names were used? */
- }
- return errorlevel;
- }