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, &regs, &regs);
    if (WREGS(regs,flags) & 1)
#else
    intdos(&regs, &regs);
    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(&regs, 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, &regs, &regs);            /* 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 )