Archive-Unzip-Burst
view release on metacpan or search on metacpan
unzip-6.0/msdos/msdos.c view on Meta::CPAN
/*
Copyright (c) 1990-2008 Info-ZIP. All rights reserved.
See the accompanying file LICENSE, version 2000-Apr-09 or later
(the contents of which are also included in unzip.h) for terms of use.
If, for some reason, all these files are missing, the Info-ZIP license
also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html
*/
/*---------------------------------------------------------------------------
msdos.c
MSDOS-specific routines for use with Info-ZIP's UnZip 5.3 and later.
Contains: Opendir() (from zip)
Readdir() (from zip)
do_wild()
mapattr()
mapname()
maskDOSdevice()
map2fat()
checkdir()
isfloppy()
z_dos_chmod()
volumelabel() (non-djgpp, non-emx)
close_outfile()
stamp_file() (TIMESTAMP only)
prepare_ISO_OEM_translat()
dateformat()
version()
zcalloc() (16-bit, only)
zcfree() (16-bit, only)
_dos_getcountryinfo() (djgpp 1.x, emx)
[_dos_getftime() (djgpp 1.x, emx) to be added]
_dos_setftime() (djgpp 1.x, emx)
_dos_setfileattr() (djgpp 1.x, emx)
_dos_getdrive() (djgpp 1.x, emx)
_dos_creat() (djgpp 1.x, emx)
_dos_close() (djgpp 1.x, emx)
volumelabel() (djgpp, emx)
_dos_getcountryinfo() (djgpp 2.x)
_is_executable() (djgpp 2.x)
__crt0_glob_function() (djgpp 2.x)
__crt0_load_environment_file() (djgpp 2.x)
dos_getcodepage() (all, ASM system call)
screensize() (emx, Watcom 32-bit)
int86x_realmode() (Watcom 32-bit)
stat_bandaid() (Watcom)
---------------------------------------------------------------------------*/
#define UNZIP_INTERNAL
#include "unzip.h"
/* fUnZip does not need anything from here except the zcalloc() & zcfree()
* function pair (when Deflate64 support is enabled in 16-bit environment).
*/
#ifndef FUNZIP
static void maskDOSdevice(__GPRO__ char *pathcomp, char *last_dot);
#ifdef MAYBE_PLAIN_FAT
static void map2fat OF((char *pathcomp, char *last_dot));
#endif
static int isfloppy OF((int nDrive));
static int z_dos_chmod OF((__GPRO__ ZCONST char *fname, int attributes));
static int volumelabel OF((ZCONST char *newlabel));
#if (!defined(SFX) && !defined(WINDLL))
static int is_running_on_windows OF((void));
#endif
static int getdoscodepage OF((void));
static int created_dir; /* used by mapname(), checkdir() */
static int renamed_fullpath; /* ditto */
static unsigned nLabelDrive; /* ditto, plus volumelabel() */
/*****************************/
/* Strings used in msdos.c */
/*****************************/
#ifndef SFX
static ZCONST char Far CantAllocateWildcard[] =
"warning: cannot allocate wildcard buffers\n";
#endif
static ZCONST char Far WarnDirTraversSkip[] =
"warning: skipped \"../\" path component(s) in %s\n";
static ZCONST char Far Creating[] = " creating: %s\n";
static ZCONST char Far ConversionFailed[] =
"mapname: conversion of %s failed\n";
static ZCONST char Far Labelling[] = "labelling %c: %-22s\n";
static ZCONST char Far ErrSetVolLabel[] =
"mapname: error setting volume label\n";
static ZCONST char Far PathTooLong[] = "checkdir error: path too long: %s\n";
static ZCONST char Far CantCreateDir[] = "checkdir error: cannot create %s\n\
unable to process %s.\n";
static ZCONST char Far DirIsntDirectory[] =
"checkdir error: %s exists but is not directory\n\
unable to process %s.\n";
static ZCONST char Far PathTooLongTrunc[] =
"checkdir warning: path too long; truncating\n %s\n\
-> %s\n";
#if (!defined(SFX) || defined(SFX_EXDIR))
static ZCONST char Far CantCreateExtractDir[] =
"checkdir: cannot create extraction directory: %s\n";
#endif
static ZCONST char Far AttribsMayBeWrong[] =
"\nwarning: file attributes may not be correct\n";
#if (!defined(SFX) && !defined(WINDLL))
static ZCONST char Far WarnUsedOnWindows[] =
"\n%s warning: You are using the MSDOS version on Windows.\n"
"Please try the native Windows version before reporting any problems.\n";
#endif
/****************************/
/* Macros used in msdos.c */
/****************************/
#ifdef WATCOMC_386
# define WREGS(v,r) (v.w.r)
# define int86x int386x
static int int86x_realmode(int inter_no, union REGS *in,
union REGS *out, struct SREGS *seg);
unzip-6.0/msdos/msdos.c view on Meta::CPAN
case '?':
*pp++ = '_';
break;
case ';': /* start of VMS version? */
lastsemi = pp;
#ifdef MAYBE_PLAIN_FAT
# ifdef USE_LFN
if (use_lfn)
*pp++ = ';'; /* keep for now; remove VMS ";##" later */
# endif
#else
*pp++ = ';'; /* keep for now; remove VMS ";##" later */
#endif
break;
#ifdef MAYBE_PLAIN_FAT
case ' ': /* change spaces to underscores */
# ifdef USE_LFN
if (!use_lfn && uO.sflag) /* only if requested and NO lfn! */
# else
if (uO.sflag) /* only if requested */
# endif
*pp++ = '_';
else
*pp++ = (char)workch;
break;
#endif /* MAYBE_PLAIN_FAT */
default:
/* allow ASCII 255 and European characters in filenames: */
if (isprint(workch) || workch >= 127)
*pp++ = (char)workch;
} /* end switch */
} /* end while loop */
/* Show warning when stripping insecure "parent dir" path components */
if (killed_ddot && QCOND2) {
Info(slide, 0, ((char *)slide, LoadFarString(WarnDirTraversSkip),
FnFilter1(G.filename)));
if (!(error & ~MPN_MASK))
error = (error & MPN_MASK) | PK_WARN;
}
/*---------------------------------------------------------------------------
Report if directory was created (and no file to create: filename ended
in '/'), check name to be sure it exists, and combine path and name be-
fore exiting.
---------------------------------------------------------------------------*/
if (G.filename[strlen(G.filename) - 1] == '/') {
checkdir(__G__ G.filename, GETPATH);
if (created_dir) {
if (QCOND2) {
Info(slide, 0, ((char *)slide, LoadFarString(Creating),
FnFilter1(G.filename)));
}
/* set file attributes: */
z_dos_chmod(__G__ G.filename, G.pInfo->file_attr);
/* set dir time (note trailing '/') */
return (error & ~MPN_MASK) | MPN_CREATED_DIR;
} else if (IS_OVERWRT_ALL) {
/* overwrite attributes of existing directory on user's request */
/* set file attributes: */
z_dos_chmod(__G__ G.filename, G.pInfo->file_attr);
}
/* dir existed already; don't look for data to extract */
return (error & ~MPN_MASK) | MPN_INF_SKIP;
}
*pp = '\0'; /* done with pathcomp: terminate it */
/* if not saving them, remove VMS version numbers (appended ";###") */
if (!uO.V_flag && lastsemi) {
#ifndef MAYBE_PLAIN_FAT
pp = lastsemi + 1;
#else
# ifdef USE_LFN
if (use_lfn)
pp = lastsemi + 1;
else
pp = lastsemi; /* semi-colon was omitted: expect all #'s */
# else
pp = lastsemi; /* semi-colon was omitted: expect all #'s */
# endif
#endif
while (isdigit((uch)(*pp)))
++pp;
if (*pp == '\0') /* only digits between ';' and end: nuke */
*lastsemi = '\0';
}
#ifdef MAYBE_PLAIN_FAT
maskDOSdevice(__G__ pathcomp, last_dot);
#else
maskDOSdevice(__G__ pathcomp, NULL);
#endif
if (G.pInfo->vollabel) {
if (strlen(pathcomp) > 11)
pathcomp[11] = '\0';
} else {
#ifdef MAYBE_PLAIN_FAT
# ifdef USE_LFN
if (!use_lfn)
map2fat(pathcomp, last_dot); /* 8.3 truncation (in place) */
# else
map2fat(pathcomp, last_dot); /* 8.3 truncation (in place) */
# endif
#endif
}
if (*pathcomp == '\0') {
Info(slide, 1, ((char *)slide, LoadFarString(ConversionFailed),
FnFilter1(G.filename)));
return (error & ~MPN_MASK) | MPN_ERR_SKIP;
}
checkdir(__G__ pathcomp, APPEND_NAME); /* returns 1 if truncated: care? */
checkdir(__G__ G.filename, GETPATH);
if (G.pInfo->vollabel) { /* set the volume label now */
if (QCOND2)
Info(slide, 0, ((char *)slide, LoadFarString(Labelling),
(nLabelDrive + 'a' - 1),
unzip-6.0/msdos/msdos.c view on Meta::CPAN
Trace((stderr, "rootpath now = [%s]\n", FnFilter1(rootpath)));
}
return MPN_OK;
}
#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);
rootlen = 0;
}
return MPN_OK;
}
return MPN_INVALID; /* 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 (WREGS(regs,flags) & 1)
#else
intdos(®s, ®s);
if (WREGS(regs,cflag)) /* error: do default a/b check instead */
#endif
{
Trace((stderr,
"error in DOS function 0x44 (AX = 0x%04x): guessing instead...\n",
(unsigned int)(WREGS(regs,ax))));
return (nDrive == 1 || nDrive == 2)? TRUE : FALSE;
} else
return WREGS(regs,ax)? FALSE : TRUE;
}
/**************************/
/* Function z_dos_chmod() */
/**************************/
static int z_dos_chmod(__G__ fname, attributes)
__GDEF
ZCONST char *fname;
int attributes;
{
char *name;
unsigned fnamelength;
int errv;
/* set file attributes:
The DOS `chmod' system call requires to mask out the
directory and volume_label attribute bits.
And, a trailing '/' has to be removed from the directory name,
the DOS `chmod' system call does not accept it. */
fnamelength = strlen(fname);
if (fnamelength > 1 && fname[fnamelength-1] == '/' &&
fname[fnamelength-2] != ':' &&
(name = (char *)malloc(fnamelength)) != (char *)NULL) {
strncpy(name, fname, fnamelength-1);
name[fnamelength-1] = '\0';
} else {
name = (char *)fname;
fnamelength = 0;
}
#if defined(__TURBOC__) || (defined(__DJGPP__) && (__DJGPP__ >= 2))
# if (defined(__BORLANDC__) && (__BORLANDC__ >= 0x0452))
# define Chmod _rtl_chmod
# else
# define Chmod _chmod
# endif
errv = (Chmod(name, 1, attributes & (~FSUBDIR & ~FVOLID)) !=
(attributes & (~FSUBDIR & ~FVOLID)));
# undef Chmod
#else /* !(__TURBOC__ || (__DJGPP__ && __DJGPP__ >= 2)) */
errv = (_dos_setfileattr(name, attributes & (~FSUBDIR & ~FVOLID)) != 0);
#endif /* ?(__TURBOC__ || (__DJGPP__ && __DJGPP__ >= 2)) */
if (errv)
Info(slide, 1, ((char *)slide, LoadFarString(AttribsMayBeWrong)));
if (fnamelength > 0)
free(name);
return errv;
} /* end function z_dos_chmod() */
#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)
ZCONST char *newlabel;
{
#ifdef DEBUG
char *p;
#endif
int len = strlen(newlabel);
int fcbseg, dtaseg, fcboff, dtaoff, retv;
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.
---------------------------------------------------------------------------*/
#ifdef WATCOMC_386
int truseg;
memset(&sregs, 0, sizeof(sregs));
memset(®s, 0, sizeof(regs));
/* PMODE/W does not support extended versions of any dos FCB functions, */
/* so we have to use brute force, allocating real mode memory for them. */
regs.w.ax = 0x0100;
regs.w.bx = (2 * sizeof(dos_fcb) + 15) >> 4; /* size in paragraphs */
int386(0x31, ®s, ®s); /* DPMI allocate DOS memory */
if (regs.w.cflag)
return DF_MDY; /* no memory, return default */
truseg = regs.w.dx; /* protected mode selector */
dtaseg = regs.w.ax; /* real mode paragraph */
fcboff = 0;
dtaoff = sizeof(dos_fcb);
#ifdef XXX__MK_FP_IS_BROKEN
/* XXX This code may not be trustworthy in general, though it is */
unzip-6.0/msdos/msdos.c view on Meta::CPAN
G.tz_is_valid &&
#endif
(ef_scan_for_izux(G.extra_field, G.lrec.extra_field_length, 0,
G.lrec.last_mod_dos_datetime, &z_utime, NULL)
& EB_UT_FL_MTIME))
{
TTrace((stderr, "close_outfile: Unix e.f. modif. time = %ld\n",
z_utime.mtime));
/* round up (down if "up" overflows) to even seconds */
if (z_utime.mtime & 1)
z_utime.mtime = (z_utime.mtime + 1 > z_utime.mtime) ?
z_utime.mtime + 1 : z_utime.mtime - 1;
TIMET_TO_NATIVE(z_utime.mtime) /* NOP unless MSC 7 or Macintosh */
t = localtime(&(z_utime.mtime));
} else
t = (struct tm *)NULL;
if (t != (struct tm *)NULL) {
if (t->tm_year < 80) {
dos_dt.z_dtf.zt_se = 0;
dos_dt.z_dtf.zt_mi = 0;
dos_dt.z_dtf.zt_hr = 0;
dos_dt.z_dtf.zd_dy = 1;
dos_dt.z_dtf.zd_mo = 1;
dos_dt.z_dtf.zd_yr = 0;
} else {
dos_dt.z_dtf.zt_se = t->tm_sec >> 1;
dos_dt.z_dtf.zt_mi = t->tm_min;
dos_dt.z_dtf.zt_hr = t->tm_hour;
dos_dt.z_dtf.zd_dy = t->tm_mday;
dos_dt.z_dtf.zd_mo = t->tm_mon + 1;
dos_dt.z_dtf.zd_yr = t->tm_year - 80;
}
} else {
dos_dt.z_dostime = G.lrec.last_mod_dos_datetime;
}
# ifdef __TURBOC__
setftime(fileno(G.outfile), &dos_dt.ft);
# else
_dos_setftime(fileno(G.outfile), dos_dt.zft.zdate, dos_dt.zft.ztime);
# endif
#else /* !USE_EF_UT_TIME */
# ifdef __TURBOC__
setftime(fileno(G.outfile),
(struct ftime *)(&(G.lrec.last_mod_dos_datetime)));
# else
_dos_setftime(fileno(G.outfile),
(ush)(G.lrec.last_mod_dos_datetime >> 16),
(ush)(G.lrec.last_mod_dos_datetime));
# endif
#endif /* ?USE_EF_UT_TIME */
}
/*---------------------------------------------------------------------------
And finally we can close the file...at least everybody agrees on how to
do *this*. I think... Also change the mode according to the stored file
attributes, since we didn't do that when we opened the dude.
---------------------------------------------------------------------------*/
fclose(G.outfile);
z_dos_chmod(__G__ G.filename, G.pInfo->file_attr);
} /* end function close_outfile() */
#ifdef TIMESTAMP
/*************************/
/* Function stamp_file() */
/*************************/
int stamp_file(fname, modtime)
ZCONST char *fname;
time_t modtime;
{
dos_fdatetime dos_dt;
time_t t_even;
struct tm *t;
int fd; /* file handle */
/* round up (down if "up" overflows) to even seconds */
t_even = ((modtime + 1 > modtime) ? modtime + 1 : modtime) & (~1);
TIMET_TO_NATIVE(t_even) /* NOP unless MSC 7.0 or Macintosh */
t = localtime(&t_even);
if (t == (struct tm *)NULL)
return -1; /* time conversion error */
if (t->tm_year < 80) {
dos_dt.z_dtf.zt_se = 0;
dos_dt.z_dtf.zt_mi = 0;
dos_dt.z_dtf.zt_hr = 0;
dos_dt.z_dtf.zd_dy = 1;
dos_dt.z_dtf.zd_mo = 1;
dos_dt.z_dtf.zd_yr = 0;
} else {
dos_dt.z_dtf.zt_se = t->tm_sec >> 1;
dos_dt.z_dtf.zt_mi = t->tm_min;
dos_dt.z_dtf.zt_hr = t->tm_hour;
dos_dt.z_dtf.zd_dy = t->tm_mday;
dos_dt.z_dtf.zd_mo = t->tm_mon + 1;
dos_dt.z_dtf.zd_yr = t->tm_year - 80;
}
if (((fd = open((char *)fname, 0)) == -1) ||
# ifdef __TURBOC__
(setftime(fd, &dos_dt.ft)))
# else
(_dos_setftime(fd, dos_dt.zft.zdate, dos_dt.zft.ztime)))
# endif
{
if (fd != -1)
close(fd);
return -1;
}
close(fd);
return 0;
} /* end function stamp_file() */
#endif /* TIMESTAMP */
( run in 1.898 second using v1.01-cache-2.11-cpan-98e64b0badf )