📄 msdos.c
字号:
gets used in extracting all members from every zipfile specified on the
command line. Note that under OS/2 and MS-DOS, if a candidate extract-to
directory specification includes a drive letter (leading "x:"), it is
treated just as if it had a trailing '/'--that is, one directory level
will be created if the path doesn't exist, unless this is otherwise pro-
hibited (e.g., freshening).
---------------------------------------------------------------------------*/
#if (!defined(SFX) || defined(SFX_EXDIR))
if (FUNCTION == ROOT) {
Trace((stderr, "initializing root path to [%s]\n", pathcomp));
if (pathcomp == (char *)NULL) {
rootlen = 0;
return 0;
}
if ((rootlen = strlen(pathcomp)) > 0) {
int had_trailing_pathsep=FALSE, has_drive=FALSE, xtra=2;
if (isalpha(pathcomp[0]) && pathcomp[1] == ':')
has_drive = TRUE; /* drive designator */
if (pathcomp[rootlen-1] == '/') {
pathcomp[--rootlen] = '\0';
had_trailing_pathsep = TRUE;
}
if (has_drive && (rootlen == 2)) {
if (!had_trailing_pathsep) /* i.e., original wasn't "x:/" */
xtra = 3; /* room for '.' + '/' + 0 at end of "x:" */
} else if (rootlen > 0) { /* need not check "x:." and "x:/" */
#ifdef MSC
/* MSC 6.00 bug: stat(non-existent-dir) == 0 [exists!] */
if (_dos_getfileattr(pathcomp, &attrs) ||
SSTAT(pathcomp, &statbuf) || !S_ISDIR(statbuf.st_mode))
#else
if (SSTAT(pathcomp, &statbuf) || !S_ISDIR(statbuf.st_mode))
#endif
{
/* path does not exist */
if (!create_dirs /* || iswild(pathcomp) */
#ifdef OLD_EXDIR
|| (!has_drive && !had_trailing_pathsep)
#endif
) {
rootlen = 0;
return 2; /* treat as stored file */
}
/* GRR: scan for wildcard characters? OS-dependent... if find any, return 2:
* treat as stored file(s) */
/* create directory (could add loop here to scan pathcomp
* and create more than one level, but really necessary?) */
if (MKDIR(pathcomp, 0777) == -1) {
FPRINTF(stderr, LoadFarString(CantCreateExtractDir),
pathcomp);
fflush(stderr);
rootlen = 0; /* path didn't exist, tried to create, */
return 3; /* failed: file exists, or need 2+ levels */
}
}
}
if ((rootpath = (char *)malloc(rootlen+xtra)) == (char *)NULL) {
rootlen = 0;
return 10;
}
strcpy(rootpath, pathcomp);
if (xtra == 3) /* had just "x:", make "x:." */
rootpath[rootlen++] = '.';
rootpath[rootlen++] = '/';
rootpath[rootlen] = '\0';
}
Trace((stderr, "rootpath now = [%s]\n", rootpath));
return 0;
}
#endif /* !SFX || SFX_EXDIR */
/*---------------------------------------------------------------------------
END: free rootpath, immediately prior to program exit.
---------------------------------------------------------------------------*/
if (FUNCTION == END) {
Trace((stderr, "freeing rootpath\n"));
if (rootlen > 0)
free(rootpath);
return 0;
}
return 99; /* should never reach */
} /* end function checkdir() */
/***********************/
/* Function isfloppy() */
/***********************/
static int isfloppy(nDrive) /* more precisely, is it removable? */
int nDrive;
{
union REGS regs;
regs.h.ah = 0x44;
regs.h.al = 0x08;
regs.h.bl = (uch)nDrive;
#ifdef __EMX__
_int86(0x21, ®s, ®s);
if (regs.x.flags & 1)
#else
intdos(®s, ®s);
if (regs.x.cflag) /* error: do default a/b check instead */
#endif
{
Trace((stderr,
"error in DOS function 0x44 (AX = 0x%04x): guessing instead...\n",
regs.x.ax));
return (nDrive == 1 || nDrive == 2)? TRUE : FALSE;
} else
return regs.x.ax? FALSE : TRUE;
}
#if (!defined(__GO32__) && !defined(__EMX__))
typedef struct dosfcb {
uch flag; /* ff to indicate extended FCB */
char res[5]; /* reserved */
uch vattr; /* attribute */
uch drive; /* drive (1=A, 2=B, ...) */
uch vn[11]; /* file or volume name */
char dmmy[5];
uch nn[11]; /* holds new name if renaming (else reserved) */
char dmmy2[9];
} dos_fcb;
/**************************/
/* Function volumelabel() */
/**************************/
static int volumelabel(newlabel)
char *newlabel;
{
#ifdef DEBUG
char *p;
#endif
int len = strlen(newlabel);
dos_fcb fcb, dta, far *pfcb=&fcb, far *pdta=&dta;
struct SREGS sregs;
union REGS regs;
/*---------------------------------------------------------------------------
Label the diskette specified by nLabelDrive using FCB calls. (Old ver-
sions of MS-DOS and OS/2 DOS boxes can't use DOS function 3Ch to create
labels.) Must use far pointers for MSC FP_* macros to work; must pad
FCB filenames with spaces; and cannot include dot in 8th position. May
or may not need to zero out FCBs before using; do so just in case.
---------------------------------------------------------------------------*/
memset((char *)&dta, 0, sizeof(dos_fcb));
memset((char *)&fcb, 0, sizeof(dos_fcb));
#ifdef DEBUG
for (p = (char *)&dta; (p - (char *)&dta) < sizeof(dos_fcb); ++p)
if (*p)
fprintf(stderr, "error: dta[%d] = %x\n", (p - (char *)&dta), *p);
for (p = (char *)&fcb; (p - (char *)&fcb) < sizeof(dos_fcb); ++p)
if (*p)
fprintf(stderr, "error: fcb[%d] = %x\n", (p - (char *)&fcb), *p);
printf("testing pointer macros:\n");
segread(&sregs);
printf("cs = %x, ds = %x, es = %x, ss = %x\n", sregs.cs, sregs.ds, sregs.es,
sregs.ss);
#endif /* DEBUG */
#if 0
#ifdef __TURBOC__
bdosptr(0x1a, dta, DO_NOT_CARE);
#else
(intdosx method below)
#endif
#endif /* 0 */
/* set the disk transfer address for subsequent FCB calls */
sregs.ds = FP_SEG(pdta);
regs.x.dx = FP_OFF(pdta);
Trace((stderr, "segment:offset of pdta = %x:%x\n", sregs.ds, regs.x.dx));
Trace((stderr, "&dta = %lx, pdta = %lx\n", (ulg)&dta, (ulg)pdta));
regs.h.ah = 0x1a;
intdosx(®s, ®s, &sregs);
/* fill in the FCB */
sregs.ds = FP_SEG(pfcb);
regs.x.dx = FP_OFF(pfcb);
pfcb->flag = 0xff; /* extended FCB */
pfcb->vattr = 0x08; /* attribute: disk volume label */
pfcb->drive = (uch)nLabelDrive;
#ifdef DEBUG
Trace((stderr, "segment:offset of pfcb = %x:%x\n", sregs.ds, regs.x.dx));
Trace((stderr, "&fcb = %lx, pfcb = %lx\n", (ulg)&fcb, (ulg)pfcb));
Trace((stderr, "(2nd check: labelling drive %c:)\n", pfcb->drive-1+'A'));
if (pfcb->flag != fcb.flag)
fprintf(stderr, "error: pfcb->flag = %d, fcb.flag = %d\n",
pfcb->flag, fcb.flag);
if (pfcb->drive != fcb.drive)
fprintf(stderr, "error: pfcb->drive = %d, fcb.drive = %d\n",
pfcb->drive, fcb.drive);
if (pfcb->vattr != fcb.vattr)
fprintf(stderr, "error: pfcb->vattr = %d, fcb.vattr = %d\n",
pfcb->vattr, fcb.vattr);
#endif /* DEBUG */
/* check for existing label */
Trace((stderr, "searching for existing label via FCBs\n"));
regs.h.ah = 0x11; /* FCB find first */
#if 0 /* THIS STRNCPY FAILS (MSC bug?): */
strncpy(pfcb->vn, "???????????", 11); /* i.e., "*.*" */
Trace((stderr, "pfcb->vn = %lx\n", (ulg)pfcb->vn));
Trace((stderr, "flag = %x, drive = %d, vattr = %x, vn = %s = %s.\n",
fcb.flag, fcb.drive, fcb.vattr, fcb.vn, pfcb->vn));
#endif
strncpy((char *)fcb.vn, "???????????", 11); /* i.e., "*.*" */
Trace((stderr, "fcb.vn = %lx\n", (ulg)fcb.vn));
Trace((stderr, "regs.h.ah = %x, regs.x.dx = %04x, sregs.ds = %04x\n",
regs.h.ah, regs.x.dx, sregs.ds));
Trace((stderr, "flag = %x, drive = %d, vattr = %x, vn = %s = %s.\n",
fcb.flag, fcb.drive, fcb.vattr, fcb.vn, pfcb->vn));
intdosx(®s, ®s, &sregs);
/*---------------------------------------------------------------------------
If not previously labelled, write a new label. Otherwise just rename,
since MS-DOS 2.x has a bug which damages the FAT when the old label is
deleted.
---------------------------------------------------------------------------*/
if (regs.h.al) {
Trace((stderr, "no label found\n\n"));
regs.h.ah = 0x16; /* FCB create file */
strncpy((char *)fcb.vn, newlabel, len);
if (len < 11) /* fill with spaces */
strncpy((char *)(fcb.vn+len), " ", 11-len);
Trace((stderr, "fcb.vn = %lx pfcb->vn = %lx\n", (ulg)fcb.vn,
(ulg)pfcb->vn));
Trace((stderr, "flag = %x, drive = %d, vattr = %x\n", fcb.flag,
fcb.drive, fcb.vattr));
Trace((stderr, "vn = %s = %s.\n", fcb.vn, pfcb->vn));
intdosx(®s, ®s, &sregs);
regs.h.ah = 0x10; /* FCB close file */
if (regs.h.al) {
Trace((stderr, "unable to write volume name (AL = %x)\n",
regs.h.al));
intdosx(®s, ®s, &sregs);
return 1;
} else {
intdosx(®s, ®s, &sregs);
Trace((stderr, "new volume label [%s] written\n", newlabel));
return 0;
}
} else {
Trace((stderr, "found old label [%s]\n\n", dta.vn)); /* not term. */
regs.h.ah = 0x17; /* FCB rename */
strncpy((char *)fcb.vn, (char *)dta.vn, 11);
strncpy((char *)fcb.nn, newlabel, len);
if (len < 11) /* fill with spaces */
strncpy((char *)(fcb.nn+len), " ", 11-len);
Trace((stderr, "fcb.vn = %lx pfcb->vn = %lx\n", (ulg)fcb.vn,
(ulg)pfcb->vn));
Trace((stderr, "fcb.nn = %lx pfcb->nn = %lx\n", (ulg)fcb.nn,
(ulg)pfcb->nn));
Trace((stderr, "flag = %x, drive = %d, vattr = %x\n", fcb.flag,
fcb.drive, fcb.vattr));
Trace((stderr, "vn = %s = %s.\n", fcb.vn, pfcb->vn));
Trace((stderr, "nn = %s = %s.\n", fcb.nn, pfcb->nn));
intdosx(®s, ®s, &sregs);
if (regs.h.al) {
Trace((stderr, "Unable to change volume name (AL = %x)\n",
regs.h.al));
return 1;
} else {
Trace((stderr, "volume label changed to [%s]\n", newlabel));
return 0;
}
}
} /* end function volumelabel() */
#endif /* !__GO32__ && !__EMX__ */
/****************************/
/* Function close_outfile() */
/****************************/
void close_outfile()
/*
* MS-DOS VERSION
*
* Set the output file date/time stamp according to information from the
* zipfile directory record for this member, then close the file and set
* its permissions (archive, hidden, read-only, system). Aside from closing
* the file, this routine is optional (but most compilers support it).
*/
{
#ifdef __TURBOC__
union {
struct ftime ft; /* system file time record */
struct {
ush ztime; /* date and time words */
ush zdate; /* .. same format as in .ZIP file */
} zt;
} td;
#endif
/*---------------------------------------------------------------------------
Copy and/or convert time and date variables, if necessary; then set the
file time/date. WEIRD BORLAND "BUG": if output is buffered, and if run
under at least some versions of DOS (e.g., 6.0), and if files are smaller
than DOS physical block size (i.e., 512 bytes) (?), then files MAY NOT
get timestamped correctly--apparently setftime() occurs before any data
are written to the file, and when file is closed and buffers are flushed,
timestamp is overwritten with current time. Even with a 32K buffer, this
does not seem to occur with larger files. UnZip output is now unbuffered,
but if it were not, could still avoid problem by adding "fflush(outfile)"
just before setftime() call. Weird, huh?
---------------------------------------------------------------------------*/
#ifdef __TURBOC__
td.zt.ztime = lrec.last_mod_file_time;
td.zt.zdate = lrec.last_mod_file_date;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -