]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Fix missing header comments and other code issues in zipfile.c.
authordan <dan@noemail.net>
Sat, 27 Jan 2018 18:55:18 +0000 (18:55 +0000)
committerdan <dan@noemail.net>
Sat, 27 Jan 2018 18:55:18 +0000 (18:55 +0000)
FossilOrigin-Name: 6ea8ba312c38365d3e28cfb2a367d729dd2751d1d853843eea0e18126777a320

ext/misc/zipfile.c
manifest
manifest.uuid

index 4e59675c1d9e8e487d30197e3620bce1f416b265..efc25927d472d8dd7c3e03e5cf7ae2511fc7fef4 100644 (file)
@@ -93,6 +93,9 @@ static const char ZIPFILE_SCHEMA[] =
 **
 ** ZIPFILE_SIGNATURE_LFH:
 **   First 4 bytes of a valid LFH record.
+**
+** ZIPFILE_SIGNATURE_EOCD
+**   First 4 bytes of a valid EOCD record.
 */
 #define ZIPFILE_EXTRA_TIMESTAMP   0x5455
 #define ZIPFILE_NEWENTRY_MADEBY   ((3<<8) + 30)
@@ -101,24 +104,14 @@ static const char ZIPFILE_SCHEMA[] =
 #define ZIPFILE_SIGNATURE_CDS     0x02014b50
 #define ZIPFILE_SIGNATURE_LFH     0x04034b50
 #define ZIPFILE_SIGNATURE_EOCD    0x06054b50
-#define ZIPFILE_LFH_FIXED_SZ      30
-
-#define ZIPFILE_EOCD_FIXED_SZ     22
 
 /*
-** Set the error message contained in context ctx to the results of
-** vprintf(zFmt, ...).
+** The sizes of the fixed-size part of each of the three main data 
+** structures in a zip archive.
 */
-static void zipfileCtxErrorMsg(sqlite3_context *ctx, const char *zFmt, ...){
-  char *zMsg = 0;
-  va_list ap;
-  va_start(ap, zFmt);
-  zMsg = sqlite3_vmprintf(zFmt, ap);
-  sqlite3_result_error(ctx, zMsg, -1);
-  sqlite3_free(zMsg);
-  va_end(ap);
-}
-
+#define ZIPFILE_LFH_FIXED_SZ      30
+#define ZIPFILE_EOCD_FIXED_SZ     22
+#define ZIPFILE_CDS_FIXED_SZ      46
 
 /*
 *** 4.3.16  End of central directory record:
@@ -227,13 +220,13 @@ struct ZipfileEntry {
   ZipfileCDS cds;            /* Parsed CDS record */
   u32 mUnixTime;             /* Modification time, in UNIX format */
   u8 *aExtra;                /* cds.nExtra+cds.nComment bytes of extra data */
-  i64 iDataOff;
+  i64 iDataOff;              /* Offset to data in file (if aData==0) */
   u8 *aData;                 /* cds.szCompressed bytes of compressed data */
   ZipfileEntry *pNext;       /* Next element in in-memory CDS */
 };
 
 /* 
-** Cursor type for recursively iterating through a directory structure.
+** Cursor type for zipfile tables.
 */
 typedef struct ZipfileCsr ZipfileCsr;
 struct ZipfileCsr {
@@ -247,23 +240,11 @@ struct ZipfileCsr {
   i64 iNextOff;              /* Offset of next record in central directory */
   ZipfileEOCD eocd;          /* Parse of central directory record */
 
-  ZipfileEntry *pFreeEntry;
-
+  ZipfileEntry *pFreeEntry;  /* Free this list when cursor is closed or reset */
   ZipfileEntry *pCurrent;    /* Current entry */
   ZipfileCsr *pCsrNext;      /* Next cursor on same virtual table */
 };
 
-/*
-** Possible values for ZipfileCsr.eType. Set in zipfileFilter().
-*/
-#define ZIPFILE_CSR_LIST 1        /* Cursor reads from ZipfileTab.pFirstEntry */
-#define ZIPFILE_CSR_FILE 2        /* Cursor reads from file on disk */
-
-/*
-** Values for ZipfileCsr.flags.
-*/
-#define ZIPFILE_NOOP_NEXT   0x0002     /* Next xNext() is a no-op */
-
 typedef struct ZipfileTab ZipfileTab;
 struct ZipfileTab {
   sqlite3_vtab base;         /* Base class - must be first */
@@ -281,6 +262,24 @@ struct ZipfileTab {
   i64 szOrig;                /* Size of archive at start of transaction */
 };
 
+/*
+** Set the error message contained in context ctx to the results of
+** vprintf(zFmt, ...).
+*/
+static void zipfileCtxErrorMsg(sqlite3_context *ctx, const char *zFmt, ...){
+  char *zMsg = 0;
+  va_list ap;
+  va_start(ap, zFmt);
+  zMsg = sqlite3_vmprintf(zFmt, ap);
+  sqlite3_result_error(ctx, zMsg, -1);
+  sqlite3_free(zMsg);
+  va_end(ap);
+}
+
+/*
+** If string zIn is quoted, dequote it in place. Otherwise, if the string
+** is not quoted, do nothing.
+*/
 static void zipfileDequote(char *zIn){
   char q = zIn[0];
   if( q=='"' || q=='\'' || q=='`' || q=='[' ){
@@ -340,6 +339,9 @@ static int zipfileConnect(
   return rc;
 }
 
+/*
+** Free the ZipfileEntry structure indicated by the only argument.
+*/
 static void zipfileEntryFree(ZipfileEntry *p){
   if( p ){
     sqlite3_free(p->cds.zFile);
@@ -347,6 +349,10 @@ static void zipfileEntryFree(ZipfileEntry *p){
   }
 }
 
+/*
+** Release resources that should be freed at the end of a write 
+** transaction.
+*/
 static void zipfileCleanupTransaction(ZipfileTab *pTab){
   ZipfileEntry *pEntry;
   ZipfileEntry *pNext;
@@ -446,6 +452,16 @@ static void zipfileSetErrmsg(ZipfileCsr *pCsr, const char *zFmt, ...){
   va_end(ap);
 }
 
+/*
+** Read nRead bytes of data from offset iOff of file pFile into buffer
+** aRead[]. Return SQLITE_OK if successful, or an SQLite error code
+** otherwise. 
+**
+** If an error does occur, output variable (*pzErrmsg) may be set to point
+** to an English language error message. It is the responsibility of the
+** caller to eventually free this buffer using
+** sqlite3_free().
+*/
 static int zipfileReadData(
   FILE *pFile,                    /* Read from this file */
   u8 *aRead,                      /* Read into this buffer */
@@ -479,9 +495,16 @@ static int zipfileAppendData(
   return SQLITE_OK;
 }
 
+/*
+** Read and return a 16-bit little-endian unsigned integer from buffer aBuf.
+*/
 static u16 zipfileGetU16(const u8 *aBuf){
   return (aBuf[1] << 8) + aBuf[0];
 }
+
+/*
+** Read and return a 32-bit little-endian unsigned integer from buffer aBuf.
+*/
 static u32 zipfileGetU32(const u8 *aBuf){
   return ((u32)(aBuf[3]) << 24)
        + ((u32)(aBuf[2]) << 16)
@@ -489,10 +512,17 @@ static u32 zipfileGetU32(const u8 *aBuf){
        + ((u32)(aBuf[0]) <<  0);
 }
 
+/*
+** Write a 16-bit little endiate integer into buffer aBuf.
+*/
 static void zipfilePutU16(u8 *aBuf, u16 val){
   aBuf[0] = val & 0xFF;
   aBuf[1] = (val>>8) & 0xFF;
 }
+
+/*
+** Write a 32-bit little endiate integer into buffer aBuf.
+*/
 static void zipfilePutU32(u8 *aBuf, u32 val){
   aBuf[0] = val & 0xFF;
   aBuf[1] = (val>>8) & 0xFF;
@@ -509,7 +539,6 @@ static void zipfilePutU32(u8 *aBuf, u32 val){
 /*
 ** Magic numbers used to read CDS records.
 */
-#define ZIPFILE_CDS_FIXED_SZ         46
 #define ZIPFILE_CDS_NFILE_OFF        28
 #define ZIPFILE_CDS_SZCOMPRESSED_OFF 20
 
@@ -548,6 +577,44 @@ static int zipfileReadCDS(u8 *aBuf, ZipfileCDS *pCDS){
 }
 
 /*
+** Decode the LFH record in buffer aBuf into (*pLFH). Return SQLITE_ERROR
+** if the record is not well-formed, or SQLITE_OK otherwise.
+*/
+static int zipfileReadLFH(
+  u8 *aBuffer,
+  ZipfileLFH *pLFH
+){
+  u8 *aRead = aBuffer;
+  int rc = SQLITE_OK;
+
+  u32 sig = zipfileRead32(aRead);
+  if( sig!=ZIPFILE_SIGNATURE_LFH ){
+    rc = SQLITE_ERROR;
+  }else{
+    pLFH->iVersionExtract = zipfileRead16(aRead);
+    pLFH->flags = zipfileRead16(aRead);
+    pLFH->iCompression = zipfileRead16(aRead);
+    pLFH->mTime = zipfileRead16(aRead);
+    pLFH->mDate = zipfileRead16(aRead);
+    pLFH->crc32 = zipfileRead32(aRead);
+    pLFH->szCompressed = zipfileRead32(aRead);
+    pLFH->szUncompressed = zipfileRead32(aRead);
+    pLFH->nFile = zipfileRead16(aRead);
+    pLFH->nExtra = zipfileRead16(aRead);
+  }
+  return rc;
+}
+
+
+/*
+** Buffer aExtra (size nExtra bytes) contains zip archive "extra" fields.
+** Scan through this buffer to find an "extra-timestamp" field. If one
+** exists, extract the 32-bit modification-timestamp from it and store
+** the value in output parameter *pmTime.
+**
+** Zero is returned if no extra-timestamp record could be found (and so
+** *pmTime is left unchanged), or non-zero otherwise.
+**
 ** The general format of an extra field is:
 **
 **   Header ID    2 bytes
@@ -580,6 +647,10 @@ static int zipfileScanExtra(u8 *aExtra, int nExtra, u32 *pmTime){
 }
 
 /*
+** Convert the standard MS-DOS timestamp stored in the mTime and mDate
+** fields of the CDS structure passed as the only argument to a 32-bit
+** UNIX seconds-since-the-epoch timestamp. Return the result.
+**
 ** "Standard" MS-DOS time format:
 **
 **   File modification time:
@@ -590,6 +661,8 @@ static int zipfileScanExtra(u8 *aExtra, int nExtra, u32 *pmTime){
 **     Bits 00-04: day
 **     Bits 05-08: month (1-12)
 **     Bits 09-15: years from 1980 
+**
+** https://msdn.microsoft.com/en-us/library/9kkf9tah.aspx
 */
 static time_t zipfileMtime(ZipfileCDS *pCDS){
   struct tm t;
@@ -605,42 +678,50 @@ static time_t zipfileMtime(ZipfileCDS *pCDS){
   return mktime(&t);
 }
 
-static int zipfileReadLFH(
-  u8 *aBuffer,
-  ZipfileLFH *pLFH
-){
-  u8 *aRead = aBuffer;
-  int rc = SQLITE_OK;
+/*
+** The opposite of zipfileMtime(). This function populates the mTime and
+** mDate fields of the CDS structure passed as the first argument according
+** to the UNIX timestamp value passed as the second.
+*/
+static void zipfileMtimeToDos(ZipfileCDS *pCds, u32 mUnixTime){
+  time_t t = (time_t)mUnixTime;
+  struct tm res;
 
-  u32 sig = zipfileRead32(aRead);
-  if( sig!=ZIPFILE_SIGNATURE_LFH ){
-    rc = SQLITE_ERROR;
-  }else{
-    pLFH->iVersionExtract = zipfileRead16(aRead);
-    pLFH->flags = zipfileRead16(aRead);
-    pLFH->iCompression = zipfileRead16(aRead);
-    pLFH->mTime = zipfileRead16(aRead);
-    pLFH->mDate = zipfileRead16(aRead);
-    pLFH->crc32 = zipfileRead32(aRead);
-    pLFH->szCompressed = zipfileRead32(aRead);
-    pLFH->szUncompressed = zipfileRead32(aRead);
-    pLFH->nFile = zipfileRead16(aRead);
-    pLFH->nExtra = zipfileRead16(aRead);
-  }
-  return rc;
+#if !defined(_WIN32) && !defined(WIN32)
+  localtime_r(&t, &res);
+#else
+  memcpy(&res, localtime(&t), sizeof(struct tm));
+#endif
+
+  pCds->mTime = (u16)(
+    (res.tm_sec / 2) + 
+    (res.tm_min << 5) +
+    (res.tm_hour << 11));
+
+  pCds->mDate = (u16)(
+    (res.tm_mday-1) +
+    ((res.tm_mon+1) << 5) +
+    ((res.tm_year-80) << 9));
 }
 
 /*
-** Read a Zip archive CDS header from offset iOff of file pFile. Return
-** SQLITE_OK if successful, or an SQLite error code otherwise.
+** If aBlob is not NULL, then it is a pointer to a buffer (nBlob bytes in
+** size) containing an entire zip archive image. Or, if aBlob is NULL,
+** then pFile is a file-handle open on a zip file. In either case, this
+** function creates a ZipfileEntry object based on the zip archive entry
+** for which the CDS record is at offset iOff.
+**
+** If successful, SQLITE_OK is returned and (*ppEntry) set to point to
+** the new object. Otherwise, an SQLite error code is returned and the
+** final value of (*ppEntry) undefined.
 */
 static int zipfileGetEntry(
   ZipfileTab *pTab,               /* Store any error message here */
   const u8 *aBlob,                /* Pointer to in-memory file image */
   int nBlob,                      /* Size of aBlob[] in bytes */
   FILE *pFile,                    /* If aBlob==0, read from this file */
-  i64 iOff,
-  ZipfileEntry **ppEntry
+  i64 iOff,                       /* Offset of CDS record */
+  ZipfileEntry **ppEntry          /* OUT: Pointer to new object */
 ){
   u8 *aRead;
   char **pzErr = &pTab->base.zErrMsg;
@@ -729,12 +810,6 @@ static int zipfileGetEntry(
   return rc;
 }
 
-static FILE *zipfileGetFd(ZipfileCsr *pCsr){
-  if( pCsr->pFile ) return pCsr->pFile;
-  return ((ZipfileTab*)(pCsr->base.pVtab))->pWriteFd;
-}
-
-
 /*
 ** Advance an ZipfileCsr to its next row of output.
 */
@@ -771,27 +846,17 @@ static int zipfileNext(sqlite3_vtab_cursor *cur){
   return rc;
 }
 
-static void zipfileMtimeToDos(ZipfileCDS *pCds, u32 mTime){
-  time_t t = (time_t)mTime;
-  struct tm res;
-
-#if !defined(_WIN32) && !defined(WIN32)
-  localtime_r(&t, &res);
-#else
-  memcpy(&res, localtime(&t), sizeof(struct tm));
-#endif
-
-  pCds->mTime = (u16)(
-    (res.tm_sec / 2) + 
-    (res.tm_min << 5) +
-    (res.tm_hour << 11));
-
-  pCds->mDate = (u16)(
-    (res.tm_mday-1) +
-    ((res.tm_mon+1) << 5) +
-    ((res.tm_year-80) << 9));
+static void zipfileFree(void *p) { 
+  sqlite3_free(p); 
 }
 
+/*
+** Buffer aIn (size nIn bytes) contains compressed data. Uncompressed, the
+** size is nOut bytes. This function uncompresses the data and sets the
+** return value in context pCtx to the result (a blob).
+**
+** If an error occurs, an error code is left in pCtx instead.
+*/
 static void zipfileInflate(
   sqlite3_context *pCtx,          /* Store error here, if any */
   const u8 *aIn,                  /* Compressed data */
@@ -819,7 +884,8 @@ static void zipfileInflate(
       if( err!=Z_STREAM_END ){
         zipfileCtxErrorMsg(pCtx, "inflate() failed (%d)", err);
       }else{
-        sqlite3_result_blob(pCtx, aRes, nOut, SQLITE_TRANSIENT);
+        sqlite3_result_blob(pCtx, aRes, nOut, zipfileFree);
+        aRes = 0;
       }
     }
     sqlite3_free(aRes);
@@ -827,6 +893,18 @@ static void zipfileInflate(
   }
 }
 
+/*
+** Buffer aIn (size nIn bytes) contains uncompressed data. This function
+** compresses it and sets (*ppOut) to point to a buffer containing the
+** compressed data. The caller is responsible for eventually calling
+** sqlite3_free() to release buffer (*ppOut). Before returning, (*pnOut) 
+** is set to the size of buffer (*ppOut) in bytes.
+**
+** If no error occurs, SQLITE_OK is returned. Otherwise, an SQLite error
+** code is returned and an error message left in virtual-table handle
+** pTab. The values of (*ppOut) and (*pnOut) are left unchanged in this
+** case.
+*/
 static int zipfileDeflate(
   ZipfileTab *pTab,               /* Set error message here */
   const u8 *aIn, int nIn,         /* Input */
@@ -913,12 +991,13 @@ static int zipfileColumn(
             if( aBuf==0 ){
               rc = SQLITE_NOMEM;
             }else{
-              FILE *pFile = zipfileGetFd(pCsr);
-              if( rc==SQLITE_OK ){
-                rc = zipfileReadData(pFile, aBuf, sz, pCsr->pCurrent->iDataOff,
-                    &pCsr->base.pVtab->zErrMsg
-                );
+              FILE *pFile = pCsr->pFile;
+              if( pFile==0 ){
+                pFile = ((ZipfileTab*)(pCsr->base.pVtab))->pWriteFd;
               }
+              rc = zipfileReadData(pFile, aBuf, sz, pCsr->pCurrent->iDataOff,
+                  &pCsr->base.pVtab->zErrMsg
+              );
             }
           }
           if( rc==SQLITE_OK ){
@@ -953,16 +1032,7 @@ static int zipfileColumn(
 }
 
 /*
-** Return the rowid for the current row.
-*/
-static int zipfileRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
-  assert( 0 );
-  return SQLITE_OK;
-}
-
-/*
-** Return TRUE if the cursor has been moved off of the last
-** row of output.
+** Return TRUE if the cursor is at EOF.
 */
 static int zipfileEof(sqlite3_vtab_cursor *cur){
   ZipfileCsr *pCsr = (ZipfileCsr*)cur;
@@ -970,6 +1040,14 @@ static int zipfileEof(sqlite3_vtab_cursor *cur){
 }
 
 /*
+** If aBlob is not NULL, then it points to a buffer nBlob bytes in size
+** containing an entire zip archive image. Or, if aBlob is NULL, then pFile
+** is guaranteed to be a file-handle open on a zip file.
+**
+** This function attempts to locate the EOCD record within the zip archive
+** and populate *pEOCD with the results of decoding it. SQLITE_OK is
+** returned if successful. Otherwise, an SQLite error code is returned and
+** an English language error message may be left in virtual-table pTab.
 */
 static int zipfileReadEOCD(
   ZipfileTab *pTab,               /* Return errors here */
@@ -1030,8 +1108,10 @@ static int zipfileReadEOCD(
 }
 
 /*
-** Add object pNew to the end of the linked list that begins at
-** ZipfileTab.pFirstEntry and ends with pLastEntry.
+** Add object pNew to the linked list that begins at ZipfileTab.pFirstEntry 
+** and ends with pLastEntry. If argument pBefore is NULL, then pNew is added
+** to the end of the list. Otherwise, it is added to the list immediately
+** before pBefore (which is guaranteed to be a part of said list).
 */
 static void zipfileAddEntry(
   ZipfileTab *pTab, 
@@ -1647,8 +1727,6 @@ static void zipfileFunctionCds(
   }
 }
 
-static void zipfileFree(void *p) { sqlite3_free(p); }
-
 static void zipfileFunctionBlob(
   sqlite3_context *context,
   int argc,
@@ -1758,7 +1836,7 @@ static int zipfileRegister(sqlite3 *db){
     zipfileNext,               /* xNext - advance a cursor */
     zipfileEof,                /* xEof - check for end of scan */
     zipfileColumn,             /* xColumn - read data */
-    zipfileRowid,              /* xRowid - read data */
+    0,                         /* xRowid - read data */
     zipfileUpdate,             /* xUpdate */
     zipfileBegin,              /* xBegin */
     0,                         /* xSync */
index 96a7ea5fe4253014af73c84a48c4f5a7ebe58fcc..e699a399acb3b56215eaf3eeb046f57b16b19e8e 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C If\sa\szipfile\svirtual\stable\sis\screated\swith\sno\sargument\s-\s"CREATE\sVIRTUAL\sTABLE\nzzz\sUSING\szipfile()"\s-\saccumulate\sdata\sin\smemory.\sSupport\s"SELECT\nzipfile_blob(z)\sFROM\szzz\sLIMIT\s1"\sto\sretrieve\sa\szip\sarchive\simage.
-D 2018-01-27T16:29:59.042
+C Fix\smissing\sheader\scomments\sand\sother\scode\sissues\sin\szipfile.c.
+D 2018-01-27T18:55:18.394
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F Makefile.in 7a3f714b4fcf793108042b7b0a5c720b0b310ec84314d61ba7f3f49f27e550ea
@@ -304,7 +304,7 @@ F ext/misc/vfsstat.c bf10ef0bc51e1ad6756629e1edb142f7a8db1178
 F ext/misc/vtablog.c 31d0d8f4406795679dcd3a67917c213d3a2a5fb3ea5de35f6e773491ed7e13c9
 F ext/misc/vtshim.c 1976e6dd68dd0d64508c91a6dfab8e75f8aaf6cd
 F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212
-F ext/misc/zipfile.c df57128d9ad2a1e60097d7971e787b582fb66ce0926577cb6f5978f7af210b8c
+F ext/misc/zipfile.c 398f53469ed90076dd5d69494eb7f1bd01a42d402fc5dbe92374178887244805
 F ext/rbu/rbu.c ea7d1b7eb44c123a2a619332e19fe5313500705c4a58aaa1887905c0d83ffc2e
 F ext/rbu/rbu1.test 43836fac8c7179a358eaf38a8a1ef3d6e6285842
 F ext/rbu/rbu10.test 1846519a438697f45e9dcb246908af81b551c29e1078d0304fae83f1fed7e9ee
@@ -1702,7 +1702,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 19f5c1400054df10688ab448e7e23afef97cab4a7c7a3e411f7527509b515dd8
-R 8b2b96d9b8d1e07c4df7e0d2971e5e57
+P e63185edfe0c316aa60c1fa085d032425ecc7db54536dfa5a977772eaf3c240e
+R 347b5f95fee3abc6c3f7640c1a70a4d4
 U dan
-Z e468bfc5bd8b08bb5b9404b26ad000bc
+Z faf05f7eafa9394c044e435efe4a986b
index a8aca2c7e58dd66d058ad31f422aaf53f54a32b5..7c9ca14be30fba9c3b870ec90e7ec4920cf4d881 100644 (file)
@@ -1 +1 @@
-e63185edfe0c316aa60c1fa085d032425ecc7db54536dfa5a977772eaf3c240e
\ No newline at end of file
+6ea8ba312c38365d3e28cfb2a367d729dd2751d1d853843eea0e18126777a320
\ No newline at end of file