/ Check-in [0702fb56]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Remove the time() dependency from the zipfile extension. Use SQLite VFS methods instead.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 0702fb5611c7cf0154c5490eeada66afc733731dff0fe030375bae6a72123a17
User & Date: dan 2018-02-02 16:20:41
Context
2018-02-02
16:28
Remove the "include <io.h>" win32 dependency from the zipfile extension. check-in: cb3feb3b user: dan tags: trunk
16:20
Remove the time() dependency from the zipfile extension. Use SQLite VFS methods instead. check-in: 0702fb56 user: dan tags: trunk
2018-02-01
20:42
Add a few more zipfile tests. No changes to code. check-in: 3f621545 user: dan tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to ext/misc/zipfile.c.

    26     26   */
    27     27   #include "sqlite3ext.h"
    28     28   SQLITE_EXTENSION_INIT1
    29     29   #include <stdio.h>
    30     30   #include <string.h>
    31     31   #include <assert.h>
    32     32   
    33         -#include <sys/types.h>
    34         -#include <sys/stat.h>
    35         -#include <fcntl.h>
    36         -#if !defined(_WIN32) && !defined(WIN32)
    37         -#  include <unistd.h>
    38         -#  include <dirent.h>
    39         -#  include <utime.h>
    40         -#else
           33  +#if defined(_WIN32) || defined(WIN32)
    41     34   #  include <io.h>
    42     35   #endif
    43         -#include <time.h>
    44         -#include <errno.h>
    45     36   
    46     37   #include <zlib.h>
    47     38   
    48     39   #ifndef SQLITE_OMIT_VIRTUALTABLE
    49     40   
    50     41   #ifndef SQLITE_AMALGAMATION
    51     42   
................................................................................
    64     55   #else
    65     56   # define ALWAYS(X)      (X)
    66     57   # define NEVER(X)       (X)
    67     58   #endif
    68     59   
    69     60   #endif   /* SQLITE_AMALGAMATION */
    70     61   
           62  +/*
           63  +** Definitions for mode bitmasks S_IFDIR, S_IFREG and S_IFLNK.
           64  +**
           65  +** In some ways it would be better to obtain these values from system 
           66  +** header files. But, the dependency is undesirable and (a) these
           67  +** have been stable for decades, (b) the values are part of POSIX and
           68  +** are also made explicit in [man stat], and (c) are part of the 
           69  +** file format for zip archives.
           70  +*/
           71  +#ifndef S_IFDIR
           72  +# define S_IFDIR 0040000
           73  +#endif
           74  +#ifndef S_IFREG
           75  +# define S_IFREG 0100000
           76  +#endif
           77  +#ifndef S_IFLNK
           78  +# define S_IFLNK 0120000
           79  +#endif
           80  +
    71     81   static const char ZIPFILE_SCHEMA[] = 
    72     82     "CREATE TABLE y("
    73     83       "name PRIMARY KEY,"  /* 0: Name of file in zip archive */
    74     84       "mode,"              /* 1: POSIX mode for file */
    75     85       "mtime,"             /* 2: Last modification time (secs since 1970)*/
    76     86       "sz,"                /* 3: Size of object */
    77     87       "rawdata,"           /* 4: Raw data */
................................................................................
  1442   1452   
  1443   1453     if( rc!=SQLITE_OK ){
  1444   1454       zipfileCleanupTransaction(pTab);
  1445   1455     }
  1446   1456   
  1447   1457     return rc;
  1448   1458   }
         1459  +
         1460  +/*
         1461  +** Return the current time as a 32-bit timestamp in UNIX epoch format (like
         1462  +** time(2)).
         1463  +*/
         1464  +static u32 zipfileTime(void){
         1465  +  sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
         1466  +  u32 ret;
         1467  +  if( pVfs->iVersion>=2 && pVfs->xCurrentTimeInt64 ){
         1468  +    i64 ms;
         1469  +    pVfs->xCurrentTimeInt64(pVfs, &ms);
         1470  +    ret = (u32)((ms/1000) - ((i64)24405875 * 8640));
         1471  +  }else{
         1472  +    double day;
         1473  +    pVfs->xCurrentTime(pVfs, &day);
         1474  +    ret = (u32)((day - 2440587.5) * 86400);
         1475  +  }
         1476  +  return ret;
         1477  +}
         1478  +
         1479  +/*
         1480  +** Return a 32-bit timestamp in UNIX epoch format.
         1481  +**
         1482  +** If the value passed as the only argument is either NULL or an SQL NULL,
         1483  +** return the current time. Otherwise, return the value stored in (*pVal)
         1484  +** cast to a 32-bit unsigned integer.
         1485  +*/
         1486  +static u32 zipfileGetTime(sqlite3_value *pVal){
         1487  +  if( pVal==0 || sqlite3_value_type(pVal)==SQLITE_NULL ){
         1488  +    return zipfileTime();
         1489  +  }
         1490  +  return (u32)sqlite3_value_int64(pVal);
         1491  +}
  1449   1492   
  1450   1493   /*
  1451   1494   ** xUpdate method.
  1452   1495   */
  1453   1496   static int zipfileUpdate(
  1454   1497     sqlite3_vtab *pVtab, 
  1455   1498     int nVal, 
................................................................................
  1457   1500     sqlite_int64 *pRowid
  1458   1501   ){
  1459   1502     ZipfileTab *pTab = (ZipfileTab*)pVtab;
  1460   1503     int rc = SQLITE_OK;             /* Return Code */
  1461   1504     ZipfileEntry *pNew = 0;         /* New in-memory CDS entry */
  1462   1505   
  1463   1506     u32 mode = 0;                   /* Mode for new entry */
  1464         -  i64 mTime = 0;                  /* Modification time for new entry */
         1507  +  u32 mTime = 0;                  /* Modification time for new entry */
  1465   1508     i64 sz = 0;                     /* Uncompressed size */
  1466   1509     const char *zPath = 0;          /* Path for new entry */
  1467   1510     int nPath = 0;                  /* strlen(zPath) */
  1468   1511     const u8 *pData = 0;            /* Pointer to buffer containing content */
  1469   1512     int nData = 0;                  /* Size of pData buffer in bytes */
  1470   1513     int iMethod = 0;                /* Compression method for new entry */
  1471   1514     u8 *pFree = 0;                  /* Free this */
................................................................................
  1536   1579       if( rc==SQLITE_OK ){
  1537   1580         rc = zipfileGetMode(apVal[3], bIsDir, &mode, &pTab->base.zErrMsg);
  1538   1581       }
  1539   1582   
  1540   1583       if( rc==SQLITE_OK ){
  1541   1584         zPath = (const char*)sqlite3_value_text(apVal[2]);
  1542   1585         nPath = (int)strlen(zPath);
  1543         -      if( sqlite3_value_type(apVal[4])==SQLITE_NULL ){
  1544         -        mTime = (sqlite3_int64)time(0);
  1545         -      }else{
  1546         -        mTime = sqlite3_value_int64(apVal[4]);
  1547         -      }
         1586  +      mTime = zipfileGetTime(apVal[4]);
  1548   1587       }
  1549   1588   
  1550   1589       if( rc==SQLITE_OK && bIsDir ){
  1551   1590         /* For a directory, check that the last character in the path is a
  1552   1591         ** '/'. This appears to be required for compatibility with info-zip
  1553   1592         ** (the unzip command on unix). It does not create directories
  1554   1593         ** otherwise.  */
................................................................................
  1577   1616         if( pNew==0 ){
  1578   1617           rc = SQLITE_NOMEM;
  1579   1618         }else{
  1580   1619           pNew->cds.iVersionMadeBy = ZIPFILE_NEWENTRY_MADEBY;
  1581   1620           pNew->cds.iVersionExtract = ZIPFILE_NEWENTRY_REQUIRED;
  1582   1621           pNew->cds.flags = ZIPFILE_NEWENTRY_FLAGS;
  1583   1622           pNew->cds.iCompression = (u16)iMethod;
  1584         -        zipfileMtimeToDos(&pNew->cds, (u32)mTime);
         1623  +        zipfileMtimeToDos(&pNew->cds, mTime);
  1585   1624           pNew->cds.crc32 = iCrc32;
  1586   1625           pNew->cds.szCompressed = nData;
  1587   1626           pNew->cds.szUncompressed = (u32)sz;
  1588   1627           pNew->cds.iExternalAttr = (mode<<16);
  1589   1628           pNew->cds.iOffset = (u32)pTab->szCurrent;
  1590   1629           pNew->cds.nFile = nPath;
  1591   1630           pNew->mUnixTime = (u32)mTime;
................................................................................
  1925   1964     }
  1926   1965   
  1927   1966     /* Decode the "mode" argument. */
  1928   1967     rc = zipfileGetMode(pMode, bIsDir, &mode, &zErr);
  1929   1968     if( rc ) goto zipfile_step_out;
  1930   1969   
  1931   1970     /* Decode the "mtime" argument. */
  1932         -  if( pMtime==0 || sqlite3_value_type(pMtime)==SQLITE_NULL ){
  1933         -    e.mUnixTime = (u32)time(0);
  1934         -  }else{
  1935         -    e.mUnixTime = (u32)sqlite3_value_int64(pMtime);
  1936         -  }
         1971  +  e.mUnixTime = zipfileGetTime(pMtime);
  1937   1972   
  1938   1973     /* If this is a directory entry, ensure that there is exactly one '/'
  1939   1974     ** at the end of the path. Or, if this is not a directory and the path
  1940   1975     ** ends in '/' it is an error. */
  1941   1976     if( bIsDir==0 ){
  1942   1977       if( zName[nName-1]=='/' ){
  1943   1978         zErr = sqlite3_mprintf("non-directory name must not end with /");