/ Check-in [6ea8ba31]
Login

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

Overview
Comment:Fix missing header comments and other code issues in zipfile.c.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256:6ea8ba312c38365d3e28cfb2a367d729dd2751d1d853843eea0e18126777a320
User & Date: dan 2018-01-27 18:55:18
Context
2018-01-29
16:22
Ensure the "unique-not-null" flag is set for automatic indexes on columns declared with "col UNIQUE NOT NULL" (where the NOT NULL comes after the UNIQUE). check-in: 8767f7b8 user: dan tags: trunk
2018-01-27
18:55
Fix missing header comments and other code issues in zipfile.c. check-in: 6ea8ba31 user: dan tags: trunk
16:29
If a zipfile virtual table is created with no argument - "CREATE VIRTUAL TABLE zzz USING zipfile()" - accumulate data in memory. Support "SELECT zipfile_blob(z) FROM zzz LIMIT 1" to retrieve a zip archive image. check-in: e63185ed user: dan tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to ext/misc/zipfile.c.

    89     89   **   11 means "utf-8 filename and comment".
    90     90   **
    91     91   ** ZIPFILE_SIGNATURE_CDS:
    92     92   **   First 4 bytes of a valid CDS record.
    93     93   **
    94     94   ** ZIPFILE_SIGNATURE_LFH:
    95     95   **   First 4 bytes of a valid LFH record.
           96  +**
           97  +** ZIPFILE_SIGNATURE_EOCD
           98  +**   First 4 bytes of a valid EOCD record.
    96     99   */
    97    100   #define ZIPFILE_EXTRA_TIMESTAMP   0x5455
    98    101   #define ZIPFILE_NEWENTRY_MADEBY   ((3<<8) + 30)
    99    102   #define ZIPFILE_NEWENTRY_REQUIRED 20
   100    103   #define ZIPFILE_NEWENTRY_FLAGS    0x800
   101    104   #define ZIPFILE_SIGNATURE_CDS     0x02014b50
   102    105   #define ZIPFILE_SIGNATURE_LFH     0x04034b50
   103    106   #define ZIPFILE_SIGNATURE_EOCD    0x06054b50
          107  +
          108  +/*
          109  +** The sizes of the fixed-size part of each of the three main data 
          110  +** structures in a zip archive.
          111  +*/
   104    112   #define ZIPFILE_LFH_FIXED_SZ      30
   105         -
   106    113   #define ZIPFILE_EOCD_FIXED_SZ     22
   107         -
   108         -/*
   109         -** Set the error message contained in context ctx to the results of
   110         -** vprintf(zFmt, ...).
   111         -*/
   112         -static void zipfileCtxErrorMsg(sqlite3_context *ctx, const char *zFmt, ...){
   113         -  char *zMsg = 0;
   114         -  va_list ap;
   115         -  va_start(ap, zFmt);
   116         -  zMsg = sqlite3_vmprintf(zFmt, ap);
   117         -  sqlite3_result_error(ctx, zMsg, -1);
   118         -  sqlite3_free(zMsg);
   119         -  va_end(ap);
   120         -}
   121         -
          114  +#define ZIPFILE_CDS_FIXED_SZ      46
   122    115   
   123    116   /*
   124    117   *** 4.3.16  End of central directory record:
   125    118   ***
   126    119   ***   end of central dir signature    4 bytes  (0x06054b50)
   127    120   ***   number of this disk             2 bytes
   128    121   ***   number of the disk with the
................................................................................
   223    216   };
   224    217   
   225    218   typedef struct ZipfileEntry ZipfileEntry;
   226    219   struct ZipfileEntry {
   227    220     ZipfileCDS cds;            /* Parsed CDS record */
   228    221     u32 mUnixTime;             /* Modification time, in UNIX format */
   229    222     u8 *aExtra;                /* cds.nExtra+cds.nComment bytes of extra data */
   230         -  i64 iDataOff;
          223  +  i64 iDataOff;              /* Offset to data in file (if aData==0) */
   231    224     u8 *aData;                 /* cds.szCompressed bytes of compressed data */
   232    225     ZipfileEntry *pNext;       /* Next element in in-memory CDS */
   233    226   };
   234    227   
   235    228   /* 
   236         -** Cursor type for recursively iterating through a directory structure.
          229  +** Cursor type for zipfile tables.
   237    230   */
   238    231   typedef struct ZipfileCsr ZipfileCsr;
   239    232   struct ZipfileCsr {
   240    233     sqlite3_vtab_cursor base;  /* Base class - must be first */
   241    234     i64 iId;                   /* Cursor ID */
   242    235     u8 bEof;                   /* True when at EOF */
   243    236     u8 bNoop;                  /* If next xNext() call is no-op */
   244    237   
   245    238     /* Used outside of write transactions */
   246    239     FILE *pFile;               /* Zip file */
   247    240     i64 iNextOff;              /* Offset of next record in central directory */
   248    241     ZipfileEOCD eocd;          /* Parse of central directory record */
   249    242   
   250         -  ZipfileEntry *pFreeEntry;
   251         -
          243  +  ZipfileEntry *pFreeEntry;  /* Free this list when cursor is closed or reset */
   252    244     ZipfileEntry *pCurrent;    /* Current entry */
   253    245     ZipfileCsr *pCsrNext;      /* Next cursor on same virtual table */
   254    246   };
   255    247   
   256         -/*
   257         -** Possible values for ZipfileCsr.eType. Set in zipfileFilter().
   258         -*/
   259         -#define ZIPFILE_CSR_LIST 1        /* Cursor reads from ZipfileTab.pFirstEntry */
   260         -#define ZIPFILE_CSR_FILE 2        /* Cursor reads from file on disk */
   261         -
   262         -/*
   263         -** Values for ZipfileCsr.flags.
   264         -*/
   265         -#define ZIPFILE_NOOP_NEXT   0x0002     /* Next xNext() is a no-op */
   266         -
   267    248   typedef struct ZipfileTab ZipfileTab;
   268    249   struct ZipfileTab {
   269    250     sqlite3_vtab base;         /* Base class - must be first */
   270    251     char *zFile;               /* Zip file this table accesses (may be NULL) */
   271    252     u8 *aBuffer;               /* Temporary buffer used for various tasks */
   272    253   
   273    254     ZipfileCsr *pCsrList;      /* List of cursors */
................................................................................
   277    258     ZipfileEntry *pFirstEntry; /* Linked list of all files (if pWriteFd!=0) */
   278    259     ZipfileEntry *pLastEntry;  /* Last element in pFirstEntry list */
   279    260     FILE *pWriteFd;            /* File handle open on zip archive */
   280    261     i64 szCurrent;             /* Current size of zip archive */
   281    262     i64 szOrig;                /* Size of archive at start of transaction */
   282    263   };
   283    264   
          265  +/*
          266  +** Set the error message contained in context ctx to the results of
          267  +** vprintf(zFmt, ...).
          268  +*/
          269  +static void zipfileCtxErrorMsg(sqlite3_context *ctx, const char *zFmt, ...){
          270  +  char *zMsg = 0;
          271  +  va_list ap;
          272  +  va_start(ap, zFmt);
          273  +  zMsg = sqlite3_vmprintf(zFmt, ap);
          274  +  sqlite3_result_error(ctx, zMsg, -1);
          275  +  sqlite3_free(zMsg);
          276  +  va_end(ap);
          277  +}
          278  +
          279  +/*
          280  +** If string zIn is quoted, dequote it in place. Otherwise, if the string
          281  +** is not quoted, do nothing.
          282  +*/
   284    283   static void zipfileDequote(char *zIn){
   285    284     char q = zIn[0];
   286    285     if( q=='"' || q=='\'' || q=='`' || q=='[' ){
   287    286       char c;
   288    287       int iIn = 1;
   289    288       int iOut = 0;
   290    289       if( q=='[' ) q = ']';
................................................................................
   336    335         zipfileDequote(pNew->zFile);
   337    336       }
   338    337     }
   339    338     *ppVtab = (sqlite3_vtab*)pNew;
   340    339     return rc;
   341    340   }
   342    341   
          342  +/*
          343  +** Free the ZipfileEntry structure indicated by the only argument.
          344  +*/
   343    345   static void zipfileEntryFree(ZipfileEntry *p){
   344    346     if( p ){
   345    347       sqlite3_free(p->cds.zFile);
   346    348       sqlite3_free(p);
   347    349     }
   348    350   }
   349    351   
          352  +/*
          353  +** Release resources that should be freed at the end of a write 
          354  +** transaction.
          355  +*/
   350    356   static void zipfileCleanupTransaction(ZipfileTab *pTab){
   351    357     ZipfileEntry *pEntry;
   352    358     ZipfileEntry *pNext;
   353    359   
   354    360     if( pTab->pWriteFd ){
   355    361       fclose(pTab->pWriteFd);
   356    362       pTab->pWriteFd = 0;
................................................................................
   442    448   static void zipfileSetErrmsg(ZipfileCsr *pCsr, const char *zFmt, ...){
   443    449     va_list ap;
   444    450     va_start(ap, zFmt);
   445    451     pCsr->base.pVtab->zErrMsg = sqlite3_vmprintf(zFmt, ap);
   446    452     va_end(ap);
   447    453   }
   448    454   
          455  +/*
          456  +** Read nRead bytes of data from offset iOff of file pFile into buffer
          457  +** aRead[]. Return SQLITE_OK if successful, or an SQLite error code
          458  +** otherwise. 
          459  +**
          460  +** If an error does occur, output variable (*pzErrmsg) may be set to point
          461  +** to an English language error message. It is the responsibility of the
          462  +** caller to eventually free this buffer using
          463  +** sqlite3_free().
          464  +*/
   449    465   static int zipfileReadData(
   450    466     FILE *pFile,                    /* Read from this file */
   451    467     u8 *aRead,                      /* Read into this buffer */
   452    468     int nRead,                      /* Number of bytes to read */
   453    469     i64 iOff,                       /* Offset to read from */
   454    470     char **pzErrmsg                 /* OUT: Error message (from sqlite3_malloc) */
   455    471   ){
................................................................................
   475    491       pTab->base.zErrMsg = sqlite3_mprintf("error in fwrite()");
   476    492       return SQLITE_ERROR;
   477    493     }
   478    494     pTab->szCurrent += nWrite;
   479    495     return SQLITE_OK;
   480    496   }
   481    497   
          498  +/*
          499  +** Read and return a 16-bit little-endian unsigned integer from buffer aBuf.
          500  +*/
   482    501   static u16 zipfileGetU16(const u8 *aBuf){
   483    502     return (aBuf[1] << 8) + aBuf[0];
   484    503   }
          504  +
          505  +/*
          506  +** Read and return a 32-bit little-endian unsigned integer from buffer aBuf.
          507  +*/
   485    508   static u32 zipfileGetU32(const u8 *aBuf){
   486    509     return ((u32)(aBuf[3]) << 24)
   487    510          + ((u32)(aBuf[2]) << 16)
   488    511          + ((u32)(aBuf[1]) <<  8)
   489    512          + ((u32)(aBuf[0]) <<  0);
   490    513   }
   491    514   
          515  +/*
          516  +** Write a 16-bit little endiate integer into buffer aBuf.
          517  +*/
   492    518   static void zipfilePutU16(u8 *aBuf, u16 val){
   493    519     aBuf[0] = val & 0xFF;
   494    520     aBuf[1] = (val>>8) & 0xFF;
   495    521   }
          522  +
          523  +/*
          524  +** Write a 32-bit little endiate integer into buffer aBuf.
          525  +*/
   496    526   static void zipfilePutU32(u8 *aBuf, u32 val){
   497    527     aBuf[0] = val & 0xFF;
   498    528     aBuf[1] = (val>>8) & 0xFF;
   499    529     aBuf[2] = (val>>16) & 0xFF;
   500    530     aBuf[3] = (val>>24) & 0xFF;
   501    531   }
   502    532   
................................................................................
   505    535   
   506    536   #define zipfileWrite32(aBuf,val) { zipfilePutU32(aBuf,val); aBuf+=4; }
   507    537   #define zipfileWrite16(aBuf,val) { zipfilePutU16(aBuf,val); aBuf+=2; }
   508    538   
   509    539   /*
   510    540   ** Magic numbers used to read CDS records.
   511    541   */
   512         -#define ZIPFILE_CDS_FIXED_SZ         46
   513    542   #define ZIPFILE_CDS_NFILE_OFF        28
   514    543   #define ZIPFILE_CDS_SZCOMPRESSED_OFF 20
   515    544   
   516    545   /*
   517    546   ** Decode the CDS record in buffer aBuf into (*pCDS). Return SQLITE_ERROR
   518    547   ** if the record is not well-formed, or SQLITE_OK otherwise.
   519    548   */
................................................................................
   544    573       assert( aRead==&aBuf[ZIPFILE_CDS_FIXED_SZ] );
   545    574     }
   546    575   
   547    576     return rc;
   548    577   }
   549    578   
   550    579   /*
          580  +** Decode the LFH record in buffer aBuf into (*pLFH). Return SQLITE_ERROR
          581  +** if the record is not well-formed, or SQLITE_OK otherwise.
          582  +*/
          583  +static int zipfileReadLFH(
          584  +  u8 *aBuffer,
          585  +  ZipfileLFH *pLFH
          586  +){
          587  +  u8 *aRead = aBuffer;
          588  +  int rc = SQLITE_OK;
          589  +
          590  +  u32 sig = zipfileRead32(aRead);
          591  +  if( sig!=ZIPFILE_SIGNATURE_LFH ){
          592  +    rc = SQLITE_ERROR;
          593  +  }else{
          594  +    pLFH->iVersionExtract = zipfileRead16(aRead);
          595  +    pLFH->flags = zipfileRead16(aRead);
          596  +    pLFH->iCompression = zipfileRead16(aRead);
          597  +    pLFH->mTime = zipfileRead16(aRead);
          598  +    pLFH->mDate = zipfileRead16(aRead);
          599  +    pLFH->crc32 = zipfileRead32(aRead);
          600  +    pLFH->szCompressed = zipfileRead32(aRead);
          601  +    pLFH->szUncompressed = zipfileRead32(aRead);
          602  +    pLFH->nFile = zipfileRead16(aRead);
          603  +    pLFH->nExtra = zipfileRead16(aRead);
          604  +  }
          605  +  return rc;
          606  +}
          607  +
          608  +
          609  +/*
          610  +** Buffer aExtra (size nExtra bytes) contains zip archive "extra" fields.
          611  +** Scan through this buffer to find an "extra-timestamp" field. If one
          612  +** exists, extract the 32-bit modification-timestamp from it and store
          613  +** the value in output parameter *pmTime.
          614  +**
          615  +** Zero is returned if no extra-timestamp record could be found (and so
          616  +** *pmTime is left unchanged), or non-zero otherwise.
          617  +**
   551    618   ** The general format of an extra field is:
   552    619   **
   553    620   **   Header ID    2 bytes
   554    621   **   Data Size    2 bytes
   555    622   **   Data         N bytes
   556    623   */
   557    624   static int zipfileScanExtra(u8 *aExtra, int nExtra, u32 *pmTime){
................................................................................
   576    643   
   577    644       p += nByte;
   578    645     }
   579    646     return ret;
   580    647   }
   581    648   
   582    649   /*
          650  +** Convert the standard MS-DOS timestamp stored in the mTime and mDate
          651  +** fields of the CDS structure passed as the only argument to a 32-bit
          652  +** UNIX seconds-since-the-epoch timestamp. Return the result.
          653  +**
   583    654   ** "Standard" MS-DOS time format:
   584    655   **
   585    656   **   File modification time:
   586    657   **     Bits 00-04: seconds divided by 2
   587    658   **     Bits 05-10: minute
   588    659   **     Bits 11-15: hour
   589    660   **   File modification date:
   590    661   **     Bits 00-04: day
   591    662   **     Bits 05-08: month (1-12)
   592    663   **     Bits 09-15: years from 1980 
          664  +**
          665  +** https://msdn.microsoft.com/en-us/library/9kkf9tah.aspx
   593    666   */
   594    667   static time_t zipfileMtime(ZipfileCDS *pCDS){
   595    668     struct tm t;
   596    669     memset(&t, 0, sizeof(t));
   597    670     t.tm_sec = (pCDS->mTime & 0x1F)*2;
   598    671     t.tm_min = (pCDS->mTime >> 5) & 0x2F;
   599    672     t.tm_hour = (pCDS->mTime >> 11) & 0x1F;
................................................................................
   601    674     t.tm_mday = (pCDS->mDate & 0x1F);
   602    675     t.tm_mon = ((pCDS->mDate >> 5) & 0x0F) - 1;
   603    676     t.tm_year = 80 + ((pCDS->mDate >> 9) & 0x7F);
   604    677   
   605    678     return mktime(&t);
   606    679   }
   607    680   
   608         -static int zipfileReadLFH(
   609         -  u8 *aBuffer,
   610         -  ZipfileLFH *pLFH
   611         -){
   612         -  u8 *aRead = aBuffer;
   613         -  int rc = SQLITE_OK;
   614         -
   615         -  u32 sig = zipfileRead32(aRead);
   616         -  if( sig!=ZIPFILE_SIGNATURE_LFH ){
   617         -    rc = SQLITE_ERROR;
   618         -  }else{
   619         -    pLFH->iVersionExtract = zipfileRead16(aRead);
   620         -    pLFH->flags = zipfileRead16(aRead);
   621         -    pLFH->iCompression = zipfileRead16(aRead);
   622         -    pLFH->mTime = zipfileRead16(aRead);
   623         -    pLFH->mDate = zipfileRead16(aRead);
   624         -    pLFH->crc32 = zipfileRead32(aRead);
   625         -    pLFH->szCompressed = zipfileRead32(aRead);
   626         -    pLFH->szUncompressed = zipfileRead32(aRead);
   627         -    pLFH->nFile = zipfileRead16(aRead);
   628         -    pLFH->nExtra = zipfileRead16(aRead);
   629         -  }
   630         -  return rc;
   631         -}
   632         -
   633         -/*
   634         -** Read a Zip archive CDS header from offset iOff of file pFile. Return
   635         -** SQLITE_OK if successful, or an SQLite error code otherwise.
          681  +/*
          682  +** The opposite of zipfileMtime(). This function populates the mTime and
          683  +** mDate fields of the CDS structure passed as the first argument according
          684  +** to the UNIX timestamp value passed as the second.
          685  +*/
          686  +static void zipfileMtimeToDos(ZipfileCDS *pCds, u32 mUnixTime){
          687  +  time_t t = (time_t)mUnixTime;
          688  +  struct tm res;
          689  +
          690  +#if !defined(_WIN32) && !defined(WIN32)
          691  +  localtime_r(&t, &res);
          692  +#else
          693  +  memcpy(&res, localtime(&t), sizeof(struct tm));
          694  +#endif
          695  +
          696  +  pCds->mTime = (u16)(
          697  +    (res.tm_sec / 2) + 
          698  +    (res.tm_min << 5) +
          699  +    (res.tm_hour << 11));
          700  +
          701  +  pCds->mDate = (u16)(
          702  +    (res.tm_mday-1) +
          703  +    ((res.tm_mon+1) << 5) +
          704  +    ((res.tm_year-80) << 9));
          705  +}
          706  +
          707  +/*
          708  +** If aBlob is not NULL, then it is a pointer to a buffer (nBlob bytes in
          709  +** size) containing an entire zip archive image. Or, if aBlob is NULL,
          710  +** then pFile is a file-handle open on a zip file. In either case, this
          711  +** function creates a ZipfileEntry object based on the zip archive entry
          712  +** for which the CDS record is at offset iOff.
          713  +**
          714  +** If successful, SQLITE_OK is returned and (*ppEntry) set to point to
          715  +** the new object. Otherwise, an SQLite error code is returned and the
          716  +** final value of (*ppEntry) undefined.
   636    717   */
   637    718   static int zipfileGetEntry(
   638    719     ZipfileTab *pTab,               /* Store any error message here */
   639    720     const u8 *aBlob,                /* Pointer to in-memory file image */
   640    721     int nBlob,                      /* Size of aBlob[] in bytes */
   641    722     FILE *pFile,                    /* If aBlob==0, read from this file */
   642         -  i64 iOff,
   643         -  ZipfileEntry **ppEntry
          723  +  i64 iOff,                       /* Offset of CDS record */
          724  +  ZipfileEntry **ppEntry          /* OUT: Pointer to new object */
   644    725   ){
   645    726     u8 *aRead;
   646    727     char **pzErr = &pTab->base.zErrMsg;
   647    728     int rc = SQLITE_OK;
   648    729   
   649    730     if( aBlob==0 ){
   650    731       aRead = pTab->aBuffer;
................................................................................
   724    805       }else{
   725    806         *ppEntry = pNew;
   726    807       }
   727    808     }
   728    809   
   729    810     return rc;
   730    811   }
   731         -
   732         -static FILE *zipfileGetFd(ZipfileCsr *pCsr){
   733         -  if( pCsr->pFile ) return pCsr->pFile;
   734         -  return ((ZipfileTab*)(pCsr->base.pVtab))->pWriteFd;
   735         -}
   736         -
   737    812   
   738    813   /*
   739    814   ** Advance an ZipfileCsr to its next row of output.
   740    815   */
   741    816   static int zipfileNext(sqlite3_vtab_cursor *cur){
   742    817     ZipfileCsr *pCsr = (ZipfileCsr*)cur;
   743    818     int rc = SQLITE_OK;
................................................................................
   767    842       }
   768    843     }
   769    844   
   770    845     pCsr->bNoop = 0;
   771    846     return rc;
   772    847   }
   773    848   
   774         -static void zipfileMtimeToDos(ZipfileCDS *pCds, u32 mTime){
   775         -  time_t t = (time_t)mTime;
   776         -  struct tm res;
   777         -
   778         -#if !defined(_WIN32) && !defined(WIN32)
   779         -  localtime_r(&t, &res);
   780         -#else
   781         -  memcpy(&res, localtime(&t), sizeof(struct tm));
   782         -#endif
   783         -
   784         -  pCds->mTime = (u16)(
   785         -    (res.tm_sec / 2) + 
   786         -    (res.tm_min << 5) +
   787         -    (res.tm_hour << 11));
   788         -
   789         -  pCds->mDate = (u16)(
   790         -    (res.tm_mday-1) +
   791         -    ((res.tm_mon+1) << 5) +
   792         -    ((res.tm_year-80) << 9));
          849  +static void zipfileFree(void *p) { 
          850  +  sqlite3_free(p); 
   793    851   }
   794    852   
          853  +/*
          854  +** Buffer aIn (size nIn bytes) contains compressed data. Uncompressed, the
          855  +** size is nOut bytes. This function uncompresses the data and sets the
          856  +** return value in context pCtx to the result (a blob).
          857  +**
          858  +** If an error occurs, an error code is left in pCtx instead.
          859  +*/
   795    860   static void zipfileInflate(
   796    861     sqlite3_context *pCtx,          /* Store error here, if any */
   797    862     const u8 *aIn,                  /* Compressed data */
   798    863     int nIn,                        /* Size of buffer aIn[] in bytes */
   799    864     int nOut                        /* Expected output size */
   800    865   ){
   801    866     u8 *aRes = sqlite3_malloc(nOut);
................................................................................
   815    880       if( err!=Z_OK ){
   816    881         zipfileCtxErrorMsg(pCtx, "inflateInit2() failed (%d)", err);
   817    882       }else{
   818    883         err = inflate(&str, Z_NO_FLUSH);
   819    884         if( err!=Z_STREAM_END ){
   820    885           zipfileCtxErrorMsg(pCtx, "inflate() failed (%d)", err);
   821    886         }else{
   822         -        sqlite3_result_blob(pCtx, aRes, nOut, SQLITE_TRANSIENT);
          887  +        sqlite3_result_blob(pCtx, aRes, nOut, zipfileFree);
          888  +        aRes = 0;
   823    889         }
   824    890       }
   825    891       sqlite3_free(aRes);
   826    892       inflateEnd(&str);
   827    893     }
   828    894   }
   829    895   
          896  +/*
          897  +** Buffer aIn (size nIn bytes) contains uncompressed data. This function
          898  +** compresses it and sets (*ppOut) to point to a buffer containing the
          899  +** compressed data. The caller is responsible for eventually calling
          900  +** sqlite3_free() to release buffer (*ppOut). Before returning, (*pnOut) 
          901  +** is set to the size of buffer (*ppOut) in bytes.
          902  +**
          903  +** If no error occurs, SQLITE_OK is returned. Otherwise, an SQLite error
          904  +** code is returned and an error message left in virtual-table handle
          905  +** pTab. The values of (*ppOut) and (*pnOut) are left unchanged in this
          906  +** case.
          907  +*/
   830    908   static int zipfileDeflate(
   831    909     ZipfileTab *pTab,               /* Set error message here */
   832    910     const u8 *aIn, int nIn,         /* Input */
   833    911     u8 **ppOut, int *pnOut          /* Output */
   834    912   ){
   835    913     int nAlloc = (int)compressBound(nIn);
   836    914     u8 *aOut;
................................................................................
   909    987             if( pCsr->pCurrent->aData ){
   910    988               aBuf = pCsr->pCurrent->aData;
   911    989             }else{
   912    990               aBuf = aFree = sqlite3_malloc(sz);
   913    991               if( aBuf==0 ){
   914    992                 rc = SQLITE_NOMEM;
   915    993               }else{
   916         -              FILE *pFile = zipfileGetFd(pCsr);
   917         -              if( rc==SQLITE_OK ){
   918         -                rc = zipfileReadData(pFile, aBuf, sz, pCsr->pCurrent->iDataOff,
   919         -                    &pCsr->base.pVtab->zErrMsg
   920         -                );
          994  +              FILE *pFile = pCsr->pFile;
          995  +              if( pFile==0 ){
          996  +                pFile = ((ZipfileTab*)(pCsr->base.pVtab))->pWriteFd;
   921    997                 }
          998  +              rc = zipfileReadData(pFile, aBuf, sz, pCsr->pCurrent->iDataOff,
          999  +                  &pCsr->base.pVtab->zErrMsg
         1000  +              );
   922   1001               }
   923   1002             }
   924   1003             if( rc==SQLITE_OK ){
   925   1004               if( i==5 && pCDS->iCompression ){
   926   1005                 zipfileInflate(ctx, aBuf, sz, szFinal);
   927   1006               }else{
   928   1007                 sqlite3_result_blob(ctx, aBuf, sz, SQLITE_TRANSIENT);
................................................................................
   949   1028         break;
   950   1029     }
   951   1030   
   952   1031     return rc;
   953   1032   }
   954   1033   
   955   1034   /*
   956         -** Return the rowid for the current row.
   957         -*/
   958         -static int zipfileRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
   959         -  assert( 0 );
   960         -  return SQLITE_OK;
   961         -}
   962         -
   963         -/*
   964         -** Return TRUE if the cursor has been moved off of the last
   965         -** row of output.
         1035  +** Return TRUE if the cursor is at EOF.
   966   1036   */
   967   1037   static int zipfileEof(sqlite3_vtab_cursor *cur){
   968   1038     ZipfileCsr *pCsr = (ZipfileCsr*)cur;
   969   1039     return pCsr->bEof;
   970   1040   }
   971   1041   
   972   1042   /*
         1043  +** If aBlob is not NULL, then it points to a buffer nBlob bytes in size
         1044  +** containing an entire zip archive image. Or, if aBlob is NULL, then pFile
         1045  +** is guaranteed to be a file-handle open on a zip file.
         1046  +**
         1047  +** This function attempts to locate the EOCD record within the zip archive
         1048  +** and populate *pEOCD with the results of decoding it. SQLITE_OK is
         1049  +** returned if successful. Otherwise, an SQLite error code is returned and
         1050  +** an English language error message may be left in virtual-table pTab.
   973   1051   */
   974   1052   static int zipfileReadEOCD(
   975   1053     ZipfileTab *pTab,               /* Return errors here */
   976   1054     const u8 *aBlob,                /* Pointer to in-memory file image */
   977   1055     int nBlob,                      /* Size of aBlob[] in bytes */
   978   1056     FILE *pFile,                    /* Read from this file if aBlob==0 */
   979   1057     ZipfileEOCD *pEOCD              /* Object to populate */
................................................................................
  1026   1104       pEOCD->iOffset = zipfileRead32(aRead);
  1027   1105     }
  1028   1106   
  1029   1107     return SQLITE_OK;
  1030   1108   }
  1031   1109   
  1032   1110   /*
  1033         -** Add object pNew to the end of the linked list that begins at
  1034         -** ZipfileTab.pFirstEntry and ends with pLastEntry.
         1111  +** Add object pNew to the linked list that begins at ZipfileTab.pFirstEntry 
         1112  +** and ends with pLastEntry. If argument pBefore is NULL, then pNew is added
         1113  +** to the end of the list. Otherwise, it is added to the list immediately
         1114  +** before pBefore (which is guaranteed to be a part of said list).
  1035   1115   */
  1036   1116   static void zipfileAddEntry(
  1037   1117     ZipfileTab *pTab, 
  1038   1118     ZipfileEntry *pBefore, 
  1039   1119     ZipfileEntry *pNew
  1040   1120   ){
  1041   1121     assert( (pTab->pFirstEntry==0)==(pTab->pLastEntry==0) );
................................................................................
  1643   1723       }else{
  1644   1724         sqlite3_result_text(context, zRes, -1, SQLITE_TRANSIENT);
  1645   1725         sqlite3_free(zRes);
  1646   1726       }
  1647   1727     }
  1648   1728   }
  1649   1729   
  1650         -static void zipfileFree(void *p) { sqlite3_free(p); }
  1651         -
  1652   1730   static void zipfileFunctionBlob(
  1653   1731     sqlite3_context *context,
  1654   1732     int argc,
  1655   1733     sqlite3_value **argv
  1656   1734   ){
  1657   1735     ZipfileCsr *pCsr;
  1658   1736     ZipfileTab *pTab = (ZipfileTab*)sqlite3_user_data(context);
................................................................................
  1754   1832       zipfileDisconnect,         /* xDestroy */
  1755   1833       zipfileOpen,               /* xOpen - open a cursor */
  1756   1834       zipfileClose,              /* xClose - close a cursor */
  1757   1835       zipfileFilter,             /* xFilter - configure scan constraints */
  1758   1836       zipfileNext,               /* xNext - advance a cursor */
  1759   1837       zipfileEof,                /* xEof - check for end of scan */
  1760   1838       zipfileColumn,             /* xColumn - read data */
  1761         -    zipfileRowid,              /* xRowid - read data */
         1839  +    0,                         /* xRowid - read data */
  1762   1840       zipfileUpdate,             /* xUpdate */
  1763   1841       zipfileBegin,              /* xBegin */
  1764   1842       0,                         /* xSync */
  1765   1843       zipfileCommit,             /* xCommit */
  1766   1844       zipfileRollback,           /* xRollback */
  1767   1845       zipfileFindFunction,       /* xFindMethod */
  1768   1846       0,                         /* xRename */