/ Check-in [f2d2a5df]
Login

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

Overview
Comment:Support UPDATE statements against zipfile virtual tables.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: f2d2a5df4f29b47212fd2411eae6545087b901a270655640c87ceb472e02a24c
User & Date: dan 2018-01-13 19:08:24
Context
2018-01-13
23:28
Fix harmless compiler warnings in zipfile.c. check-in: 8f7a592f user: drh tags: trunk
19:08
Support UPDATE statements against zipfile virtual tables. check-in: f2d2a5df user: dan tags: trunk
14:28
Fully initialize the Mem object for serial-type 10, in case such a serial-type is found in a corrupt database file. check-in: bd70a07d user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to ext/misc/zipfile.c.

   460    460   static u8* zipfileCsrBuffer(ZipfileCsr *pCsr){
   461    461     return ((ZipfileTab*)(pCsr->base.pVtab))->aBuffer;
   462    462   }
   463    463   
   464    464   /*
   465    465   ** Magic numbers used to read CDS records.
   466    466   */
   467         -#define ZIPFILE_CDS_FIXED_SZ  46
   468         -#define ZIPFILE_CDS_NFILE_OFF 28
          467  +#define ZIPFILE_CDS_FIXED_SZ         46
          468  +#define ZIPFILE_CDS_NFILE_OFF        28
   469    469   
   470         -static int zipfileReadCDS(ZipfileCsr *pCsr){
          470  +/*
          471  +** Decode the CDS record in buffer aBuf into (*pCDS). Return SQLITE_ERROR
          472  +** if the record is not well-formed, or SQLITE_OK otherwise.
          473  +*/
          474  +static int zipfileReadCDS(u8 *aBuf, ZipfileCDS *pCDS){
          475  +  u8 *aRead = aBuf;
          476  +  u32 sig = zipfileRead32(aRead);
          477  +  int rc = SQLITE_OK;
          478  +  if( sig!=ZIPFILE_SIGNATURE_CDS ){
          479  +    rc = SQLITE_ERROR;
          480  +  }else{
          481  +    pCDS->iVersionMadeBy = zipfileRead16(aRead);
          482  +    pCDS->iVersionExtract = zipfileRead16(aRead);
          483  +    pCDS->flags = zipfileRead16(aRead);
          484  +    pCDS->iCompression = zipfileRead16(aRead);
          485  +    pCDS->mTime = zipfileRead16(aRead);
          486  +    pCDS->mDate = zipfileRead16(aRead);
          487  +    pCDS->crc32 = zipfileRead32(aRead);
          488  +    pCDS->szCompressed = zipfileRead32(aRead);
          489  +    pCDS->szUncompressed = zipfileRead32(aRead);
          490  +    assert( aRead==&aBuf[ZIPFILE_CDS_NFILE_OFF] );
          491  +    pCDS->nFile = zipfileRead16(aRead);
          492  +    pCDS->nExtra = zipfileRead16(aRead);
          493  +    pCDS->nComment = zipfileRead16(aRead);
          494  +    pCDS->iDiskStart = zipfileRead16(aRead);
          495  +    pCDS->iInternalAttr = zipfileRead16(aRead);
          496  +    pCDS->iExternalAttr = zipfileRead32(aRead);
          497  +    pCDS->iOffset = zipfileRead32(aRead);
          498  +    assert( aRead==&aBuf[ZIPFILE_CDS_FIXED_SZ] );
          499  +  }
          500  +
          501  +  return rc;
          502  +}
          503  +
          504  +/*
          505  +** Read the CDS record for the current entry from disk into pCsr->cds.
          506  +*/
          507  +static int zipfileCsrReadCDS(ZipfileCsr *pCsr){
   471    508     char **pzErr = &pCsr->base.pVtab->zErrMsg;
   472    509     u8 *aRead;
   473    510     int rc = SQLITE_OK;
   474    511   
   475    512     sqlite3_free(pCsr->cds.zFile);
   476    513     pCsr->cds.zFile = 0;
   477    514   
................................................................................
   481    518           pCsr->pFile, aRead, ZIPFILE_CDS_FIXED_SZ, pCsr->iNextOff, pzErr
   482    519       );
   483    520     }else{
   484    521       aRead = pCsr->pCurrent->aCdsEntry;
   485    522     }
   486    523   
   487    524     if( rc==SQLITE_OK ){
   488         -    u32 sig = zipfileRead32(aRead);
   489         -    if( sig!=ZIPFILE_SIGNATURE_CDS ){
          525  +    rc = zipfileReadCDS(aRead, &pCsr->cds);
          526  +    if( rc!=SQLITE_OK ){
   490    527         assert( pCsr->pCurrent==0 );
   491    528         zipfileSetErrmsg(pCsr,"failed to read CDS at offset %lld",pCsr->iNextOff);
   492         -      rc = SQLITE_ERROR;
   493    529       }else{
   494    530         int nRead;
   495         -      pCsr->cds.iVersionMadeBy = zipfileRead16(aRead);
   496         -      pCsr->cds.iVersionExtract = zipfileRead16(aRead);
   497         -      pCsr->cds.flags = zipfileRead16(aRead);
   498         -      pCsr->cds.iCompression = zipfileRead16(aRead);
   499         -      pCsr->cds.mTime = zipfileRead16(aRead);
   500         -      pCsr->cds.mDate = zipfileRead16(aRead);
   501         -      pCsr->cds.crc32 = zipfileRead32(aRead);
   502         -      pCsr->cds.szCompressed = zipfileRead32(aRead);
   503         -      pCsr->cds.szUncompressed = zipfileRead32(aRead);
   504         -      assert( pCsr->pCurrent 
   505         -           || aRead==zipfileCsrBuffer(pCsr)+ZIPFILE_CDS_NFILE_OFF 
   506         -      );
   507         -      pCsr->cds.nFile = zipfileRead16(aRead);
   508         -      pCsr->cds.nExtra = zipfileRead16(aRead);
   509         -      pCsr->cds.nComment = zipfileRead16(aRead);
   510         -      pCsr->cds.iDiskStart = zipfileRead16(aRead);
   511         -      pCsr->cds.iInternalAttr = zipfileRead16(aRead);
   512         -      pCsr->cds.iExternalAttr = zipfileRead32(aRead);
   513         -      pCsr->cds.iOffset = zipfileRead32(aRead);
   514         -      assert( pCsr->pCurrent 
   515         -           || aRead==zipfileCsrBuffer(pCsr)+ZIPFILE_CDS_FIXED_SZ
   516         -      );
   517         -
   518    531         if( pCsr->pCurrent==0 ){
   519    532           nRead = pCsr->cds.nFile + pCsr->cds.nExtra;
   520    533           aRead = zipfileCsrBuffer(pCsr);
   521    534           pCsr->iNextOff += ZIPFILE_CDS_FIXED_SZ;
   522    535           rc = zipfileReadData(pCsr->pFile, aRead, nRead, pCsr->iNextOff, pzErr);
          536  +      }else{
          537  +        aRead = &aRead[ZIPFILE_CDS_FIXED_SZ];
   523    538         }
   524    539   
   525    540         if( rc==SQLITE_OK ){
   526    541           pCsr->cds.zFile = sqlite3_mprintf("%.*s", (int)pCsr->cds.nFile, aRead);
   527    542           pCsr->iNextOff += pCsr->cds.nFile;
   528    543           pCsr->iNextOff += pCsr->cds.nExtra;
   529    544           pCsr->iNextOff += pCsr->cds.nComment;
................................................................................
   566    581   }
   567    582   
   568    583   static FILE *zipfileGetFd(ZipfileCsr *pCsr){
   569    584     if( pCsr->pFile ) return pCsr->pFile;
   570    585     return ((ZipfileTab*)(pCsr->base.pVtab))->pWriteFd;
   571    586   }
   572    587   
   573         -static int zipfileReadLFH(ZipfileCsr *pCsr){
   574         -  FILE *pFile = zipfileGetFd(pCsr);
   575         -  char **pzErr = &pCsr->base.pVtab->zErrMsg;
          588  +static int zipfileReadLFH(
          589  +  FILE *pFd, 
          590  +  i64 iOffset,
          591  +  u8 *aTmp, 
          592  +  ZipfileLFH *pLFH, 
          593  +  char **pzErr
          594  +){
          595  +  u8 *aRead = aTmp;
   576    596     static const int szFix = ZIPFILE_LFH_FIXED_SZ;
   577         -  u8 *aRead = zipfileCsrBuffer(pCsr);
   578    597     int rc;
   579    598   
   580         -  rc = zipfileReadData(pFile, aRead, szFix, pCsr->cds.iOffset, pzErr);
          599  +  rc = zipfileReadData(pFd, aRead, szFix, iOffset, pzErr);
   581    600     if( rc==SQLITE_OK ){
   582    601       u32 sig = zipfileRead32(aRead);
   583    602       if( sig!=ZIPFILE_SIGNATURE_LFH ){
   584         -      zipfileSetErrmsg(pCsr, "failed to read LFH at offset %d", 
   585         -          (int)pCsr->cds.iOffset
   586         -      );
          603  +      *pzErr = sqlite3_mprintf("failed to read LFH at offset %d", (int)iOffset);
   587    604         rc = SQLITE_ERROR;
   588    605       }else{
   589         -      pCsr->lfh.iVersionExtract = zipfileRead16(aRead);
   590         -      pCsr->lfh.flags = zipfileRead16(aRead);
   591         -      pCsr->lfh.iCompression = zipfileRead16(aRead);
   592         -      pCsr->lfh.mTime = zipfileRead16(aRead);
   593         -      pCsr->lfh.mDate = zipfileRead16(aRead);
   594         -      pCsr->lfh.crc32 = zipfileRead32(aRead);
   595         -      pCsr->lfh.szCompressed = zipfileRead32(aRead);
   596         -      pCsr->lfh.szUncompressed = zipfileRead32(aRead);
   597         -      pCsr->lfh.nFile = zipfileRead16(aRead);
   598         -      pCsr->lfh.nExtra = zipfileRead16(aRead);
   599         -      assert( aRead==zipfileCsrBuffer(pCsr)+szFix );
   600         -      pCsr->iDataOff = pCsr->cds.iOffset+szFix+pCsr->lfh.nFile+pCsr->lfh.nExtra;
          606  +      pLFH->iVersionExtract = zipfileRead16(aRead);
          607  +      pLFH->flags = zipfileRead16(aRead);
          608  +      pLFH->iCompression = zipfileRead16(aRead);
          609  +      pLFH->mTime = zipfileRead16(aRead);
          610  +      pLFH->mDate = zipfileRead16(aRead);
          611  +      pLFH->crc32 = zipfileRead32(aRead);
          612  +      pLFH->szCompressed = zipfileRead32(aRead);
          613  +      pLFH->szUncompressed = zipfileRead32(aRead);
          614  +      pLFH->nFile = zipfileRead16(aRead);
          615  +      pLFH->nExtra = zipfileRead16(aRead);
          616  +      assert( aRead==&aTmp[szFix] );
   601    617       }
   602    618     }
          619  +  return rc;
          620  +}
   603    621   
          622  +static int zipfileCsrReadLFH(ZipfileCsr *pCsr){
          623  +  FILE *pFile = zipfileGetFd(pCsr);
          624  +  char **pzErr = &pCsr->base.pVtab->zErrMsg;
          625  +  u8 *aRead = zipfileCsrBuffer(pCsr);
          626  +  int rc = zipfileReadLFH(pFile, pCsr->cds.iOffset, aRead, &pCsr->lfh, pzErr);
          627  +  pCsr->iDataOff =  pCsr->cds.iOffset + ZIPFILE_LFH_FIXED_SZ;
          628  +  pCsr->iDataOff += pCsr->lfh.nFile+pCsr->lfh.nExtra;
   604    629     return rc;
   605    630   }
   606    631   
   607    632   
   608    633   /*
   609    634   ** Advance an ZipfileCsr to its next row of output.
   610    635   */
................................................................................
   625    650       }while( pCsr->pCurrent && pCsr->pCurrent->bDeleted );
   626    651       if( pCsr->pCurrent==0 ){
   627    652         pCsr->bEof = 1;
   628    653       }
   629    654     }
   630    655   
   631    656     if( pCsr->bEof==0 ){
   632         -    rc = zipfileReadCDS(pCsr);
          657  +    rc = zipfileCsrReadCDS(pCsr);
   633    658       if( rc==SQLITE_OK ){
   634         -      rc = zipfileReadLFH(pCsr);
          659  +      rc = zipfileCsrReadLFH(pCsr);
   635    660       }
   636    661     }
   637    662   
   638    663     return rc;
   639    664   }
   640    665   
   641    666   /*
................................................................................
   766    791   static int zipfileColumn(
   767    792     sqlite3_vtab_cursor *cur,   /* The cursor */
   768    793     sqlite3_context *ctx,       /* First argument to sqlite3_result_...() */
   769    794     int i                       /* Which column to return */
   770    795   ){
   771    796     ZipfileCsr *pCsr = (ZipfileCsr*)cur;
   772    797     int rc = SQLITE_OK;
          798  +  if( i>=3 && sqlite3_vtab_nochange(ctx) ){
          799  +    return SQLITE_OK;
          800  +  }
   773    801     switch( i ){
   774    802       case 0:   /* name */
   775    803         sqlite3_result_text(ctx, pCsr->cds.zFile, -1, SQLITE_TRANSIENT);
   776    804         break;
   777    805       case 1:   /* mode */
   778    806         /* TODO: Whether or not the following is correct surely depends on
   779    807         ** the platform on which the archive was created.  */
................................................................................
   985   1013     return SQLITE_OK;
   986   1014   }
   987   1015   
   988   1016   /*
   989   1017   ** Add object pNew to the end of the linked list that begins at
   990   1018   ** ZipfileTab.pFirstEntry and ends with pLastEntry.
   991   1019   */
   992         -static void zipfileAddEntry(ZipfileTab *pTab, ZipfileEntry *pNew){
         1020  +static void zipfileAddEntry(
         1021  +  ZipfileTab *pTab, 
         1022  +  ZipfileEntry *pBefore, 
         1023  +  ZipfileEntry *pNew
         1024  +){
   993   1025     assert( (pTab->pFirstEntry==0)==(pTab->pLastEntry==0) );
   994   1026     assert( pNew->pNext==0 );
   995         -  if( pTab->pFirstEntry==0 ){
   996         -    pTab->pFirstEntry = pTab->pLastEntry = pNew;
         1027  +  if( pBefore==0 ){
         1028  +    if( pTab->pFirstEntry==0 ){
         1029  +      pTab->pFirstEntry = pTab->pLastEntry = pNew;
         1030  +    }else{
         1031  +      assert( pTab->pLastEntry->pNext==0 );
         1032  +      pTab->pLastEntry->pNext = pNew;
         1033  +      pTab->pLastEntry = pNew;
         1034  +    }
   997   1035     }else{
   998         -    assert( pTab->pLastEntry->pNext==0 );
   999         -    pTab->pLastEntry->pNext = pNew;
  1000         -    pTab->pLastEntry = pNew;
         1036  +    ZipfileEntry **pp;
         1037  +    for(pp=&pTab->pFirstEntry; *pp!=pBefore; pp=&((*pp)->pNext));
         1038  +    pNew->pNext = pBefore;
         1039  +    *pp = pNew;
  1001   1040     }
  1002   1041   }
  1003   1042   
  1004   1043   static int zipfileLoadDirectory(ZipfileTab *pTab){
  1005   1044     ZipfileEOCD eocd;
  1006   1045     int rc;
  1007   1046   
................................................................................
  1040   1079           memset(pNew, 0, sizeof(ZipfileEntry));
  1041   1080           pNew->zPath = (char*)&pNew[1];
  1042   1081           memcpy(pNew->zPath, &aRec[ZIPFILE_CDS_FIXED_SZ], nFile);
  1043   1082           pNew->zPath[nFile] = '\0';
  1044   1083           pNew->aCdsEntry = (u8*)&pNew->zPath[nFile+1];
  1045   1084           pNew->nCdsEntry = ZIPFILE_CDS_FIXED_SZ+nFile+nExtra+nComment;
  1046   1085           memcpy(pNew->aCdsEntry, aRec, pNew->nCdsEntry);
  1047         -        zipfileAddEntry(pTab, pNew);
         1086  +        zipfileAddEntry(pTab, 0, pNew);
  1048   1087         }
  1049   1088   
  1050   1089         iOff += ZIPFILE_CDS_FIXED_SZ+nFile+nExtra+nComment;
  1051   1090       }
  1052   1091   
  1053   1092       sqlite3_free(aBuf);
  1054   1093     }else if( rc==SQLITE_EMPTY ){
................................................................................
  1164   1203     u32 defaultMode,                /* Value to use if pVal IS NULL */
  1165   1204     u32 *pMode
  1166   1205   ){
  1167   1206     const char *z = (const char*)sqlite3_value_text(pVal);
  1168   1207     u32 mode = 0;
  1169   1208     if( z==0 ){
  1170   1209       mode = defaultMode;
  1171         -  }else if( z[0]>=0 && z[0]<=9 ){
         1210  +  }else if( z[0]>='0' && z[0]<='9' ){
  1172   1211       mode = (unsigned int)sqlite3_value_int(pVal);
  1173   1212     }else{
  1174   1213       const char zTemplate[11] = "-rwxrwxrwx";
  1175   1214       int i;
  1176   1215       if( strlen(z)!=10 ) goto parse_error;
  1177   1216       switch( z[0] ){
  1178   1217         case '-': mode |= S_IFREG; break;
................................................................................
  1227   1266     int nPath = 0;                  /* strlen(zPath) */
  1228   1267     const u8 *pData = 0;            /* Pointer to buffer containing content */
  1229   1268     int nData = 0;                  /* Size of pData buffer in bytes */
  1230   1269     int iMethod = 0;                /* Compression method for new entry */
  1231   1270     u8 *pFree = 0;                  /* Free this */
  1232   1271     char *zFree = 0;                /* Also free this */
  1233   1272     ZipfileCDS cds;                 /* New Central Directory Structure entry */
  1234         -
         1273  +  ZipfileEntry *pOld = 0;
  1235   1274     int bIsDir = 0;
  1236   1275   
  1237         -  int mNull;
  1238         -
  1239   1276     assert( pTab->zFile );
  1240   1277     assert( pTab->pWriteFd );
  1241   1278   
  1242   1279     if( sqlite3_value_type(apVal[0])!=SQLITE_NULL ){
  1243         -    if( nVal>1 ){
  1244         -      return SQLITE_CONSTRAINT;
  1245         -    }else{
  1246         -      const char *zDelete = (const char*)sqlite3_value_text(apVal[0]);
  1247         -      int nDelete = strlen(zDelete);
  1248         -      ZipfileEntry *p;
  1249         -      for(p=pTab->pFirstEntry; p; p=p->pNext){
  1250         -        if( zipfileComparePath(p->zPath, zDelete, nDelete)==0 ){
  1251         -          p->bDeleted = 1;
  1252         -          break;
         1280  +    const char *zDelete = (const char*)sqlite3_value_text(apVal[0]);
         1281  +    int nDelete = strlen(zDelete);
         1282  +    for(pOld=pTab->pFirstEntry; 1; pOld=pOld->pNext){
         1283  +      if( pOld->bDeleted ) continue;
         1284  +      if( zipfileComparePath(pOld->zPath, zDelete, nDelete)==0 ){
         1285  +        pOld->bDeleted = 1;
         1286  +        break;
         1287  +      }
         1288  +      assert( pOld->pNext );
         1289  +    }
         1290  +    if( nVal==1 ) return SQLITE_OK;
         1291  +  }
         1292  +
         1293  +  if( sqlite3_value_nochange(apVal[5]) && sqlite3_value_nochange(apVal[6])
         1294  +   && sqlite3_value_nochange(apVal[7]) && sqlite3_value_nochange(apVal[8])
         1295  +  ){
         1296  +    /* Reuse the data from the existing entry. */
         1297  +    FILE *pFile = pTab->pWriteFd;
         1298  +    ZipfileCDS cds;
         1299  +    zipfileReadCDS(pOld->aCdsEntry, &cds);
         1300  +
         1301  +    bIsDir = ((cds.iExternalAttr>>16) & S_IFDIR) ? 1 : 0;
         1302  +    sz = cds.szUncompressed;
         1303  +    iMethod = cds.iCompression;
         1304  +    if( sz>0 ){
         1305  +      char **pzErr = &pTab->base.zErrMsg;
         1306  +      ZipfileLFH lfh;
         1307  +      rc = zipfileReadLFH(pFile, cds.iOffset, pTab->aBuffer, &lfh, pzErr);
         1308  +      if( rc==SQLITE_OK ){
         1309  +        nData = lfh.szCompressed;
         1310  +        pData = pFree = sqlite3_malloc(nData);
         1311  +        if( pFree==NULL ){
         1312  +          rc = SQLITE_NOMEM;
         1313  +        }else{
         1314  +          i64 iRead = cds.iOffset + ZIPFILE_LFH_FIXED_SZ + lfh.nFile+lfh.nExtra;
         1315  +          rc = zipfileReadData(pFile, pFree, nData, iRead, pzErr);
  1253   1316           }
  1254   1317         }
  1255         -      return SQLITE_OK;
         1318  +    }
         1319  +  }else{
         1320  +    int mNull;
         1321  +    mNull = (sqlite3_value_type(apVal[5])==SQLITE_NULL ? 0x0 : 0x8)  /* sz */
         1322  +      + (sqlite3_value_type(apVal[6])==SQLITE_NULL ? 0x0 : 0x4)  /* rawdata */
         1323  +      + (sqlite3_value_type(apVal[7])==SQLITE_NULL ? 0x0 : 0x2)  /* data */
         1324  +      + (sqlite3_value_type(apVal[8])==SQLITE_NULL ? 0x0 : 0x1); /* method */
         1325  +    if( mNull==0x00 ){     
         1326  +      /* All four are NULL - this must be a directory */
         1327  +      bIsDir = 1;
  1256   1328       }
  1257         -  }
  1258         -
  1259         -  mNull = (sqlite3_value_type(apVal[5])==SQLITE_NULL ? 0x0 : 0x8)  /* sz */
  1260         -        + (sqlite3_value_type(apVal[6])==SQLITE_NULL ? 0x0 : 0x4)  /* rawdata */
  1261         -        + (sqlite3_value_type(apVal[7])==SQLITE_NULL ? 0x0 : 0x2)  /* data */
  1262         -        + (sqlite3_value_type(apVal[8])==SQLITE_NULL ? 0x0 : 0x1); /* method */
  1263         -  if( mNull==0x00 ){     
  1264         -    /* All four are NULL - this must be a directory */
  1265         -    bIsDir = 1;
  1266         -  }
  1267         -  else if( mNull==0x2 || mNull==0x3 ){
  1268         -    /* Value specified for "data", and possibly "method". This must be
  1269         -    ** a regular file or a symlink. */
  1270         -    const u8 *aIn = sqlite3_value_blob(apVal[7]);
  1271         -    int nIn = sqlite3_value_bytes(apVal[7]);
  1272         -    int bAuto = sqlite3_value_type(apVal[8])==SQLITE_NULL;
  1273         -    
  1274         -    iMethod = sqlite3_value_int(apVal[8]);
  1275         -    sz = nIn;
  1276         -    if( iMethod!=0 && iMethod!=8 ){
  1277         -      rc = SQLITE_CONSTRAINT;
  1278         -    }else if( bAuto || iMethod ){
  1279         -      rc = zipfileDeflate(pTab, aIn, nIn, &pFree, &nData);
  1280         -      if( rc==SQLITE_OK ){
  1281         -        if( iMethod || nData<nIn ){
  1282         -          iMethod = 8;
  1283         -          pData = pFree;
  1284         -        }else{
  1285         -          pData = aIn;
  1286         -          nData = nIn;
         1329  +    else if( mNull==0x2 || mNull==0x3 ){
         1330  +      /* Value specified for "data", and possibly "method". This must be
         1331  +      ** a regular file or a symlink. */
         1332  +      const u8 *aIn = sqlite3_value_blob(apVal[7]);
         1333  +      int nIn = sqlite3_value_bytes(apVal[7]);
         1334  +      int bAuto = sqlite3_value_type(apVal[8])==SQLITE_NULL;
         1335  +
         1336  +      iMethod = sqlite3_value_int(apVal[8]);
         1337  +      sz = nIn;
         1338  +      pData = aIn;
         1339  +      nData = nIn;
         1340  +      if( iMethod!=0 && iMethod!=8 ){
         1341  +        rc = SQLITE_CONSTRAINT;
         1342  +      }else if( bAuto || iMethod ){
         1343  +        int nCmp;
         1344  +        rc = zipfileDeflate(pTab, aIn, nIn, &pFree, &nCmp);
         1345  +        if( rc==SQLITE_OK ){
         1346  +          if( iMethod || nCmp<nIn ){
         1347  +            iMethod = 8;
         1348  +            pData = pFree;
         1349  +            nData = nCmp;
         1350  +          }
  1287   1351           }
  1288   1352         }
  1289   1353       }
  1290         -  }
  1291         -  else if( mNull==0x0D ){
  1292         -    /* Values specified for "sz", "rawdata" and "method". In other words,
  1293         -    ** pre-compressed data is being inserted.  */
  1294         -    pData = sqlite3_value_blob(apVal[6]);
  1295         -    nData = sqlite3_value_bytes(apVal[6]);
  1296         -    sz = sqlite3_value_int(apVal[5]);
  1297         -    iMethod = sqlite3_value_int(apVal[8]);
  1298         -    if( iMethod<0 || iMethod>65535 ){
  1299         -      pTab->base.zErrMsg = sqlite3_mprintf(
  1300         -          "zipfile: invalid compression method: %d", iMethod
  1301         -      );
  1302         -      rc = SQLITE_ERROR;
         1354  +    else if( mNull==0x0D ){
         1355  +      /* Values specified for "sz", "rawdata" and "method". In other words,
         1356  +      ** pre-compressed data is being inserted.  */
         1357  +      pData = sqlite3_value_blob(apVal[6]);
         1358  +      nData = sqlite3_value_bytes(apVal[6]);
         1359  +      sz = sqlite3_value_int(apVal[5]);
         1360  +      iMethod = sqlite3_value_int(apVal[8]);
         1361  +      if( iMethod<0 || iMethod>65535 ){
         1362  +        pTab->base.zErrMsg = sqlite3_mprintf(
         1363  +            "zipfile: invalid compression method: %d", iMethod
         1364  +            );
         1365  +        rc = SQLITE_ERROR;
         1366  +      }
  1303   1367       }
  1304         -  }
  1305         -  else{
  1306         -    rc = SQLITE_CONSTRAINT;
         1368  +    else{
         1369  +      rc = SQLITE_CONSTRAINT;
         1370  +    }
  1307   1371     }
  1308   1372   
  1309   1373     if( rc==SQLITE_OK ){
  1310   1374       rc = zipfileGetMode(pTab, apVal[3], 
  1311   1375           (bIsDir ? (S_IFDIR + 0755) : (S_IFREG + 0644)), &mode
  1312   1376       );
  1313   1377       if( rc==SQLITE_OK && (bIsDir == ((mode & S_IFDIR)==0)) ){
................................................................................
  1340   1404       }
  1341   1405     }
  1342   1406   
  1343   1407     /* Check that we're not inserting a duplicate entry */
  1344   1408     if( rc==SQLITE_OK ){
  1345   1409       ZipfileEntry *p;
  1346   1410       for(p=pTab->pFirstEntry; p; p=p->pNext){
         1411  +      if( p->bDeleted ) continue;
  1347   1412         if( zipfileComparePath(p->zPath, zPath, nPath)==0 ){
  1348   1413           rc = SQLITE_CONSTRAINT;
  1349   1414           break;
  1350   1415         }
  1351   1416       }
  1352   1417     }
  1353   1418   
................................................................................
  1364   1429       cds.szUncompressed = (u32)sz;
  1365   1430       cds.iExternalAttr = (mode<<16);
  1366   1431       cds.iOffset = (u32)pTab->szCurrent;
  1367   1432       pNew = zipfileNewEntry(&cds, zPath, nPath, (u32)mTime);
  1368   1433       if( pNew==0 ){
  1369   1434         rc = SQLITE_NOMEM;
  1370   1435       }else{
  1371         -      zipfileAddEntry(pTab, pNew);
         1436  +      zipfileAddEntry(pTab, pOld, pNew);
  1372   1437       }
  1373   1438     }
  1374   1439   
  1375   1440     /* Append the new header+file to the archive */
  1376   1441     if( rc==SQLITE_OK ){
  1377   1442       rc = zipfileAppendEntry(pTab, &cds, zPath, nPath, pData, nData, (u32)mTime);
  1378   1443     }
  1379   1444   
         1445  +  if( rc!=SQLITE_OK && pOld ){
         1446  +    pOld->bDeleted = 0;
         1447  +  }
  1380   1448     sqlite3_free(pFree);
  1381   1449     sqlite3_free(zFree);
  1382   1450     return rc;
  1383   1451   }
  1384   1452   
  1385   1453   static int zipfileAppendEOCD(ZipfileTab *pTab, ZipfileEOCD *p){
  1386   1454     u8 *aBuf = pTab->aBuffer;

Changes to test/zipfile.test.

    72     72       VALUES('i.txt', '-rw-r--r--', 1000000006, 'zxcvb', 0);
    73     73       SELECT name FROM zz;
    74     74     COMMIT;
    75     75   } {f.txt g.txt h.txt i.txt}
    76     76   do_execsql_test 1.5.2 {
    77     77     SELECT name FROM zz;
    78     78   } {f.txt g.txt h.txt i.txt}
           79  +do_execsql_test 1.5.3 {
           80  +  SELECT data FROM zz WHERE name='i.txt';
           81  +} {zxcvb}
    79     82   
    80     83   do_execsql_test 1.6.0 {
    81     84     DELETE FROM zz WHERE name='g.txt';
    82     85     SELECT name FROM zz;
    83     86   } {f.txt h.txt i.txt}
           87  +
           88  +do_execsql_test 1.6.1 {
           89  +  SELECT name, mode, mtime, data, method FROM zipfile('test.zip');
           90  +} {
           91  +  f.txt 33188 1000000000 abcde 0
           92  +  h.txt 33188 1000000004 aaaaaaaaaabbbbbbbbbb 8
           93  +  i.txt 33188 1000000006 zxcvb 0
           94  +}
           95  +
           96  +do_execsql_test 1.6.2 {
           97  +  UPDATE zz SET mtime=4 WHERE name='i.txt';
           98  +  SELECT name, mode, mtime, data, method FROM zipfile('test.zip');
           99  +} {
          100  +  f.txt 33188 1000000000 abcde 0
          101  +  h.txt 33188 1000000004 aaaaaaaaaabbbbbbbbbb 8
          102  +  i.txt 33188 4 zxcvb 0
          103  +}
          104  +
          105  +do_execsql_test 1.6.3 {
          106  +  UPDATE zz SET mode='-rw-r--r-x' WHERE name='h.txt';
          107  +  SELECT name, mode, mtime, data, method FROM zipfile('test.zip');
          108  +} {
          109  +  f.txt 33188 1000000000 abcde 0
          110  +  h.txt 33189 1000000004 aaaaaaaaaabbbbbbbbbb 8
          111  +  i.txt 33188 4 zxcvb 0
          112  +}
          113  +
          114  +do_execsql_test 1.6.4 {
          115  +  UPDATE zz SET name = 'blue.txt' WHERE name='f.txt';
          116  +  SELECT name, mode, mtime, data, method FROM zipfile('test.zip');
          117  +} {
          118  +  blue.txt 33188 1000000000 abcde 0
          119  +  h.txt 33189 1000000004 aaaaaaaaaabbbbbbbbbb 8
          120  +  i.txt 33188 4 zxcvb 0
          121  +}
          122  +
          123  +do_execsql_test 1.6.5 {
          124  +  UPDATE zz SET data = 'edcba' WHERE name='blue.txt';
          125  +  SELECT name, mode, mtime, data, method FROM zipfile('test.zip');
          126  +} {
          127  +  blue.txt 33188 1000000000 edcba 0
          128  +  h.txt 33189 1000000004 aaaaaaaaaabbbbbbbbbb 8
          129  +  i.txt 33188 4 zxcvb 0
          130  +}
          131  +
          132  +do_execsql_test 1.6.6 {
          133  +  UPDATE zz SET mode=NULL, data = NULL WHERE name='blue.txt';
          134  +  SELECT name, mode, mtime, data, method FROM zipfile('test.zip');
          135  +} {
          136  +  blue.txt/ 16877 1000000000 {} 0
          137  +  h.txt 33189 1000000004 aaaaaaaaaabbbbbbbbbb 8
          138  +  i.txt 33188 4 zxcvb 0
          139  +}
          140  +
          141  +do_catchsql_test 1.6.7 {
          142  +  UPDATE zz SET data=NULL WHERE name='i.txt'
          143  +} {1 {constraint failed}}
          144  +do_execsql_test 1.6.8 {
          145  +  SELECT name, mode, mtime, data, method FROM zipfile('test.zip');
          146  +} {
          147  +  blue.txt/ 16877 1000000000 {} 0
          148  +  h.txt 33189 1000000004 aaaaaaaaaabbbbbbbbbb 8
          149  +  i.txt 33188 4 zxcvb 0
          150  +}
    84    151   
    85    152   #-------------------------------------------------------------------------
    86    153   db close
    87    154   forcedelete test.zip
    88    155   reset_db
    89    156   load_static_extension db zipfile
    90    157   do_execsql_test 2.1 {
................................................................................
   100    167     dirname/ 16877 {}
   101    168     dirname2/ 16877 {}
   102    169     dirname2/file1.txt 33188 abcdefghijklmnop
   103    170   }
   104    171   
   105    172   do_catchsql_test 2.3 {
   106    173     UPDATE zzz SET name = 'dirname3' WHERE name = 'dirname/';
   107         -} {1 {constraint failed}}
          174  +} {0 {}}
   108    175   do_execsql_test 2.4 {
   109    176     SELECT name, mode, data FROM zzz;
   110    177   } {
   111         -  dirname/ 16877 {}
          178  +  dirname3/ 16877 {}
   112    179     dirname2/ 16877 {}
   113    180     dirname2/file1.txt 33188 abcdefghijklmnop
   114    181   }
   115    182   
   116    183   # If on unix, check that the [unzip] utility can unpack our archive.
   117    184   #
   118    185   if {$::tcl_platform(platform)=="unix"} {
   119    186     do_test 2.5.1 {
   120    187       forcedelete dirname
   121         -      forcedelete dirname2
   122         -      set rc [catch { exec unzip test.zip > /dev/null } msg]
   123         -      list $rc $msg
          188  +    forcedelete dirname2
          189  +    set rc [catch { exec unzip test.zip > /dev/null } msg]
          190  +    list $rc $msg
   124    191     } {0 {}}
   125         -  do_test 2.5.2 { file isdir dirname } 1
          192  +  do_test 2.5.2 { file isdir dirname3 } 1
   126    193     do_test 2.5.3 { file isdir dirname2 } 1
   127    194     do_test 2.5.4 { file isdir dirname2/file1.txt } 0
   128    195     do_test 2.5.5 { 
   129    196       set fd [open dirname2/file1.txt]
   130    197       set data [read $fd]
   131    198       close $fd
   132    199       set data