4 ** The author disclaims copyright to this source code. In place of
5 ** a legal notice, here is a blessing:
7 ** May you do good and not evil.
8 ** May you find forgiveness for yourself and forgive others.
9 ** May you share freely, never taking more than you give.
11 ******************************************************************************
13 ** This file implements a virtual table for reading and writing ZIP archive
18 ** SELECT name, sz, datetime(mtime,'unixepoch') FROM zipfile($filename);
20 ** Current limitations:
22 ** * No support for encryption
23 ** * No support for ZIP archives spanning multiple files
24 ** * No support for zip64 extensions
25 ** * Only the "inflate/deflate" (zlib) compression method is supported
27 #include "sqlite3ext.h"
28 SQLITE_EXTENSION_INIT1
36 #ifndef SQLITE_OMIT_VIRTUALTABLE
38 #ifndef SQLITE_AMALGAMATION
42 # define UINT32_TYPE uint32_t
44 # define UINT32_TYPE unsigned int
49 # define UINT16_TYPE uint16_t
51 # define UINT16_TYPE unsigned short int
54 typedef sqlite3_int64 i64
;
55 typedef unsigned char u8
;
56 typedef UINT32_TYPE u32
; /* 4-byte unsigned integer */
57 typedef UINT16_TYPE u16
; /* 2-byte unsigned integer */
58 #define MIN(a,b) ((a)<(b) ? (a) : (b))
60 #if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST)
61 # define SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS 1
63 #if defined(SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS)
64 # define ALWAYS(X) (1)
66 #elif !defined(NDEBUG)
67 # define ALWAYS(X) ((X)?1:(assert(0),0))
68 # define NEVER(X) ((X)?(assert(0),1):0)
70 # define ALWAYS(X) (X)
74 #endif /* SQLITE_AMALGAMATION */
77 ** Definitions for mode bitmasks S_IFDIR, S_IFREG and S_IFLNK.
79 ** In some ways it would be better to obtain these values from system
80 ** header files. But, the dependency is undesirable and (a) these
81 ** have been stable for decades, (b) the values are part of POSIX and
82 ** are also made explicit in [man stat], and (c) are part of the
83 ** file format for zip archives.
86 # define S_IFDIR 0040000
89 # define S_IFREG 0100000
92 # define S_IFLNK 0120000
95 static const char ZIPFILE_SCHEMA
[] =
97 "name PRIMARY KEY," /* 0: Name of file in zip archive */
98 "mode," /* 1: POSIX mode for file */
99 "mtime," /* 2: Last modification time (secs since 1970)*/
100 "sz," /* 3: Size of object */
101 "rawdata," /* 4: Raw data */
102 "data," /* 5: Uncompressed data */
103 "method," /* 6: Compression method (integer) */
104 "z HIDDEN" /* 7: Name of zip file */
107 #define ZIPFILE_F_COLUMN_IDX 7 /* Index of column "file" in the above */
108 #define ZIPFILE_BUFFER_SIZE (64*1024)
112 ** Magic numbers used to read and write zip files.
114 ** ZIPFILE_NEWENTRY_MADEBY:
115 ** Use this value for the "version-made-by" field in new zip file
116 ** entries. The upper byte indicates "unix", and the lower byte
117 ** indicates that the zip file matches pkzip specification 3.0.
118 ** This is what info-zip seems to do.
120 ** ZIPFILE_NEWENTRY_REQUIRED:
121 ** Value for "version-required-to-extract" field of new entries.
122 ** Version 2.0 is required to support folders and deflate compression.
124 ** ZIPFILE_NEWENTRY_FLAGS:
125 ** Value for "general-purpose-bit-flags" field of new entries. Bit
126 ** 11 means "utf-8 filename and comment".
128 ** ZIPFILE_SIGNATURE_CDS:
129 ** First 4 bytes of a valid CDS record.
131 ** ZIPFILE_SIGNATURE_LFH:
132 ** First 4 bytes of a valid LFH record.
134 ** ZIPFILE_SIGNATURE_EOCD
135 ** First 4 bytes of a valid EOCD record.
137 #define ZIPFILE_EXTRA_TIMESTAMP 0x5455
138 #define ZIPFILE_NEWENTRY_MADEBY ((3<<8) + 30)
139 #define ZIPFILE_NEWENTRY_REQUIRED 20
140 #define ZIPFILE_NEWENTRY_FLAGS 0x800
141 #define ZIPFILE_SIGNATURE_CDS 0x02014b50
142 #define ZIPFILE_SIGNATURE_LFH 0x04034b50
143 #define ZIPFILE_SIGNATURE_EOCD 0x06054b50
146 ** The sizes of the fixed-size part of each of the three main data
147 ** structures in a zip archive.
149 #define ZIPFILE_LFH_FIXED_SZ 30
150 #define ZIPFILE_EOCD_FIXED_SZ 22
151 #define ZIPFILE_CDS_FIXED_SZ 46
154 *** 4.3.16 End of central directory record:
156 *** end of central dir signature 4 bytes (0x06054b50)
157 *** number of this disk 2 bytes
158 *** number of the disk with the
159 *** start of the central directory 2 bytes
160 *** total number of entries in the
161 *** central directory on this disk 2 bytes
162 *** total number of entries in
163 *** the central directory 2 bytes
164 *** size of the central directory 4 bytes
165 *** offset of start of central
166 *** directory with respect to
167 *** the starting disk number 4 bytes
168 *** .ZIP file comment length 2 bytes
169 *** .ZIP file comment (variable size)
171 typedef struct ZipfileEOCD ZipfileEOCD
;
182 *** 4.3.12 Central directory structure:
186 *** central file header signature 4 bytes (0x02014b50)
187 *** version made by 2 bytes
188 *** version needed to extract 2 bytes
189 *** general purpose bit flag 2 bytes
190 *** compression method 2 bytes
191 *** last mod file time 2 bytes
192 *** last mod file date 2 bytes
194 *** compressed size 4 bytes
195 *** uncompressed size 4 bytes
196 *** file name length 2 bytes
197 *** extra field length 2 bytes
198 *** file comment length 2 bytes
199 *** disk number start 2 bytes
200 *** internal file attributes 2 bytes
201 *** external file attributes 4 bytes
202 *** relative offset of local header 4 bytes
204 typedef struct ZipfileCDS ZipfileCDS
;
222 char *zFile
; /* Filename (sqlite3_malloc()) */
226 *** 4.3.7 Local file header:
228 *** local file header signature 4 bytes (0x04034b50)
229 *** version needed to extract 2 bytes
230 *** general purpose bit flag 2 bytes
231 *** compression method 2 bytes
232 *** last mod file time 2 bytes
233 *** last mod file date 2 bytes
235 *** compressed size 4 bytes
236 *** uncompressed size 4 bytes
237 *** file name length 2 bytes
238 *** extra field length 2 bytes
241 typedef struct ZipfileLFH ZipfileLFH
;
255 typedef struct ZipfileEntry ZipfileEntry
;
256 struct ZipfileEntry
{
257 ZipfileCDS cds
; /* Parsed CDS record */
258 u32 mUnixTime
; /* Modification time, in UNIX format */
259 u8
*aExtra
; /* cds.nExtra+cds.nComment bytes of extra data */
260 i64 iDataOff
; /* Offset to data in file (if aData==0) */
261 u8
*aData
; /* cds.szCompressed bytes of compressed data */
262 ZipfileEntry
*pNext
; /* Next element in in-memory CDS */
266 ** Cursor type for zipfile tables.
268 typedef struct ZipfileCsr ZipfileCsr
;
270 sqlite3_vtab_cursor base
; /* Base class - must be first */
271 i64 iId
; /* Cursor ID */
272 u8 bEof
; /* True when at EOF */
273 u8 bNoop
; /* If next xNext() call is no-op */
275 /* Used outside of write transactions */
276 FILE *pFile
; /* Zip file */
277 i64 iNextOff
; /* Offset of next record in central directory */
278 ZipfileEOCD eocd
; /* Parse of central directory record */
280 ZipfileEntry
*pFreeEntry
; /* Free this list when cursor is closed or reset */
281 ZipfileEntry
*pCurrent
; /* Current entry */
282 ZipfileCsr
*pCsrNext
; /* Next cursor on same virtual table */
285 typedef struct ZipfileTab ZipfileTab
;
287 sqlite3_vtab base
; /* Base class - must be first */
288 char *zFile
; /* Zip file this table accesses (may be NULL) */
289 sqlite3
*db
; /* Host database connection */
290 u8
*aBuffer
; /* Temporary buffer used for various tasks */
292 ZipfileCsr
*pCsrList
; /* List of cursors */
295 /* The following are used by write transactions only */
296 ZipfileEntry
*pFirstEntry
; /* Linked list of all files (if pWriteFd!=0) */
297 ZipfileEntry
*pLastEntry
; /* Last element in pFirstEntry list */
298 FILE *pWriteFd
; /* File handle open on zip archive */
299 i64 szCurrent
; /* Current size of zip archive */
300 i64 szOrig
; /* Size of archive at start of transaction */
304 ** Set the error message contained in context ctx to the results of
305 ** vprintf(zFmt, ...).
307 static void zipfileCtxErrorMsg(sqlite3_context
*ctx
, const char *zFmt
, ...){
311 zMsg
= sqlite3_vmprintf(zFmt
, ap
);
312 sqlite3_result_error(ctx
, zMsg
, -1);
318 ** If string zIn is quoted, dequote it in place. Otherwise, if the string
319 ** is not quoted, do nothing.
321 static void zipfileDequote(char *zIn
){
323 if( q
=='"' || q
=='\'' || q
=='`' || q
=='[' ){
326 if( q
=='[' ) q
= ']';
327 while( ALWAYS(zIn
[iIn
]) ){
329 if( c
==q
&& zIn
[iIn
++]!=q
) break;
337 ** Construct a new ZipfileTab virtual table object.
339 ** argv[0] -> module name ("zipfile")
340 ** argv[1] -> database name
341 ** argv[2] -> table name
342 ** argv[...] -> "column name" and other module argument fields.
344 static int zipfileConnect(
347 int argc
, const char *const*argv
,
348 sqlite3_vtab
**ppVtab
,
351 int nByte
= sizeof(ZipfileTab
) + ZIPFILE_BUFFER_SIZE
;
353 const char *zFile
= 0;
354 ZipfileTab
*pNew
= 0;
358 /* If the table name is not "zipfile", require that the argument be
359 ** specified. This stops zipfile tables from being created as:
361 ** CREATE VIRTUAL TABLE zzz USING zipfile();
363 ** It does not prevent:
365 ** CREATE VIRTUAL TABLE zipfile USING zipfile();
367 assert( 0==sqlite3_stricmp(argv
[0], "zipfile") );
368 if( (0!=sqlite3_stricmp(argv
[2], "zipfile") && argc
<4) || argc
>4 ){
369 *pzErr
= sqlite3_mprintf("zipfile constructor requires one argument");
375 nFile
= (int)strlen(zFile
)+1;
378 rc
= sqlite3_declare_vtab(db
, ZIPFILE_SCHEMA
);
380 pNew
= (ZipfileTab
*)sqlite3_malloc64((sqlite3_int64
)nByte
+nFile
);
381 if( pNew
==0 ) return SQLITE_NOMEM
;
382 memset(pNew
, 0, nByte
+nFile
);
384 pNew
->aBuffer
= (u8
*)&pNew
[1];
386 pNew
->zFile
= (char*)&pNew
->aBuffer
[ZIPFILE_BUFFER_SIZE
];
387 memcpy(pNew
->zFile
, zFile
, nFile
);
388 zipfileDequote(pNew
->zFile
);
391 sqlite3_vtab_config(db
, SQLITE_VTAB_DIRECTONLY
);
392 *ppVtab
= (sqlite3_vtab
*)pNew
;
397 ** Free the ZipfileEntry structure indicated by the only argument.
399 static void zipfileEntryFree(ZipfileEntry
*p
){
401 sqlite3_free(p
->cds
.zFile
);
407 ** Release resources that should be freed at the end of a write
410 static void zipfileCleanupTransaction(ZipfileTab
*pTab
){
411 ZipfileEntry
*pEntry
;
414 if( pTab
->pWriteFd
){
415 fclose(pTab
->pWriteFd
);
418 for(pEntry
=pTab
->pFirstEntry
; pEntry
; pEntry
=pNext
){
419 pNext
= pEntry
->pNext
;
420 zipfileEntryFree(pEntry
);
422 pTab
->pFirstEntry
= 0;
423 pTab
->pLastEntry
= 0;
429 ** This method is the destructor for zipfile vtab objects.
431 static int zipfileDisconnect(sqlite3_vtab
*pVtab
){
432 zipfileCleanupTransaction((ZipfileTab
*)pVtab
);
438 ** Constructor for a new ZipfileCsr object.
440 static int zipfileOpen(sqlite3_vtab
*p
, sqlite3_vtab_cursor
**ppCsr
){
441 ZipfileTab
*pTab
= (ZipfileTab
*)p
;
443 pCsr
= sqlite3_malloc(sizeof(*pCsr
));
444 *ppCsr
= (sqlite3_vtab_cursor
*)pCsr
;
448 memset(pCsr
, 0, sizeof(*pCsr
));
449 pCsr
->iId
= ++pTab
->iNextCsrid
;
450 pCsr
->pCsrNext
= pTab
->pCsrList
;
451 pTab
->pCsrList
= pCsr
;
456 ** Reset a cursor back to the state it was in when first returned
459 static void zipfileResetCursor(ZipfileCsr
*pCsr
){
467 zipfileEntryFree(pCsr
->pCurrent
);
471 for(p
=pCsr
->pFreeEntry
; p
; p
=pNext
){
478 ** Destructor for an ZipfileCsr.
480 static int zipfileClose(sqlite3_vtab_cursor
*cur
){
481 ZipfileCsr
*pCsr
= (ZipfileCsr
*)cur
;
482 ZipfileTab
*pTab
= (ZipfileTab
*)(pCsr
->base
.pVtab
);
484 zipfileResetCursor(pCsr
);
486 /* Remove this cursor from the ZipfileTab.pCsrList list. */
487 for(pp
=&pTab
->pCsrList
; *pp
!=pCsr
; pp
=&((*pp
)->pCsrNext
));
488 *pp
= pCsr
->pCsrNext
;
495 ** Set the error message for the virtual table associated with cursor
496 ** pCsr to the results of vprintf(zFmt, ...).
498 static void zipfileTableErr(ZipfileTab
*pTab
, const char *zFmt
, ...){
501 sqlite3_free(pTab
->base
.zErrMsg
);
502 pTab
->base
.zErrMsg
= sqlite3_vmprintf(zFmt
, ap
);
505 static void zipfileCursorErr(ZipfileCsr
*pCsr
, const char *zFmt
, ...){
508 sqlite3_free(pCsr
->base
.pVtab
->zErrMsg
);
509 pCsr
->base
.pVtab
->zErrMsg
= sqlite3_vmprintf(zFmt
, ap
);
514 ** Read nRead bytes of data from offset iOff of file pFile into buffer
515 ** aRead[]. Return SQLITE_OK if successful, or an SQLite error code
518 ** If an error does occur, output variable (*pzErrmsg) may be set to point
519 ** to an English language error message. It is the responsibility of the
520 ** caller to eventually free this buffer using
523 static int zipfileReadData(
524 FILE *pFile
, /* Read from this file */
525 u8
*aRead
, /* Read into this buffer */
526 int nRead
, /* Number of bytes to read */
527 i64 iOff
, /* Offset to read from */
528 char **pzErrmsg
/* OUT: Error message (from sqlite3_malloc) */
531 fseek(pFile
, (long)iOff
, SEEK_SET
);
532 n
= fread(aRead
, 1, nRead
, pFile
);
534 *pzErrmsg
= sqlite3_mprintf("error in fread()");
540 static int zipfileAppendData(
547 fseek(pTab
->pWriteFd
, (long)pTab
->szCurrent
, SEEK_SET
);
548 n
= fwrite(aWrite
, 1, nWrite
, pTab
->pWriteFd
);
549 if( (int)n
!=nWrite
){
550 pTab
->base
.zErrMsg
= sqlite3_mprintf("error in fwrite()");
553 pTab
->szCurrent
+= nWrite
;
559 ** Read and return a 16-bit little-endian unsigned integer from buffer aBuf.
561 static u16
zipfileGetU16(const u8
*aBuf
){
562 return (aBuf
[1] << 8) + aBuf
[0];
566 ** Read and return a 32-bit little-endian unsigned integer from buffer aBuf.
568 static u32
zipfileGetU32(const u8
*aBuf
){
569 if( aBuf
==0 ) return 0;
570 return ((u32
)(aBuf
[3]) << 24)
571 + ((u32
)(aBuf
[2]) << 16)
572 + ((u32
)(aBuf
[1]) << 8)
573 + ((u32
)(aBuf
[0]) << 0);
577 ** Write a 16-bit little endiate integer into buffer aBuf.
579 static void zipfilePutU16(u8
*aBuf
, u16 val
){
580 aBuf
[0] = val
& 0xFF;
581 aBuf
[1] = (val
>>8) & 0xFF;
585 ** Write a 32-bit little endiate integer into buffer aBuf.
587 static void zipfilePutU32(u8
*aBuf
, u32 val
){
588 aBuf
[0] = val
& 0xFF;
589 aBuf
[1] = (val
>>8) & 0xFF;
590 aBuf
[2] = (val
>>16) & 0xFF;
591 aBuf
[3] = (val
>>24) & 0xFF;
594 #define zipfileRead32(aBuf) ( aBuf+=4, zipfileGetU32(aBuf-4) )
595 #define zipfileRead16(aBuf) ( aBuf+=2, zipfileGetU16(aBuf-2) )
597 #define zipfileWrite32(aBuf,val) { zipfilePutU32(aBuf,val); aBuf+=4; }
598 #define zipfileWrite16(aBuf,val) { zipfilePutU16(aBuf,val); aBuf+=2; }
601 ** Magic numbers used to read CDS records.
603 #define ZIPFILE_CDS_NFILE_OFF 28
604 #define ZIPFILE_CDS_SZCOMPRESSED_OFF 20
607 ** Decode the CDS record in buffer aBuf into (*pCDS). Return SQLITE_ERROR
608 ** if the record is not well-formed, or SQLITE_OK otherwise.
610 static int zipfileReadCDS(u8
*aBuf
, ZipfileCDS
*pCDS
){
612 u32 sig
= zipfileRead32(aRead
);
614 if( sig
!=ZIPFILE_SIGNATURE_CDS
){
617 pCDS
->iVersionMadeBy
= zipfileRead16(aRead
);
618 pCDS
->iVersionExtract
= zipfileRead16(aRead
);
619 pCDS
->flags
= zipfileRead16(aRead
);
620 pCDS
->iCompression
= zipfileRead16(aRead
);
621 pCDS
->mTime
= zipfileRead16(aRead
);
622 pCDS
->mDate
= zipfileRead16(aRead
);
623 pCDS
->crc32
= zipfileRead32(aRead
);
624 pCDS
->szCompressed
= zipfileRead32(aRead
);
625 pCDS
->szUncompressed
= zipfileRead32(aRead
);
626 assert( aRead
==&aBuf
[ZIPFILE_CDS_NFILE_OFF
] );
627 pCDS
->nFile
= zipfileRead16(aRead
);
628 pCDS
->nExtra
= zipfileRead16(aRead
);
629 pCDS
->nComment
= zipfileRead16(aRead
);
630 pCDS
->iDiskStart
= zipfileRead16(aRead
);
631 pCDS
->iInternalAttr
= zipfileRead16(aRead
);
632 pCDS
->iExternalAttr
= zipfileRead32(aRead
);
633 pCDS
->iOffset
= zipfileRead32(aRead
);
634 assert( aRead
==&aBuf
[ZIPFILE_CDS_FIXED_SZ
] );
641 ** Decode the LFH record in buffer aBuf into (*pLFH). Return SQLITE_ERROR
642 ** if the record is not well-formed, or SQLITE_OK otherwise.
644 static int zipfileReadLFH(
651 u32 sig
= zipfileRead32(aRead
);
652 if( sig
!=ZIPFILE_SIGNATURE_LFH
){
655 pLFH
->iVersionExtract
= zipfileRead16(aRead
);
656 pLFH
->flags
= zipfileRead16(aRead
);
657 pLFH
->iCompression
= zipfileRead16(aRead
);
658 pLFH
->mTime
= zipfileRead16(aRead
);
659 pLFH
->mDate
= zipfileRead16(aRead
);
660 pLFH
->crc32
= zipfileRead32(aRead
);
661 pLFH
->szCompressed
= zipfileRead32(aRead
);
662 pLFH
->szUncompressed
= zipfileRead32(aRead
);
663 pLFH
->nFile
= zipfileRead16(aRead
);
664 pLFH
->nExtra
= zipfileRead16(aRead
);
671 ** Buffer aExtra (size nExtra bytes) contains zip archive "extra" fields.
672 ** Scan through this buffer to find an "extra-timestamp" field. If one
673 ** exists, extract the 32-bit modification-timestamp from it and store
674 ** the value in output parameter *pmTime.
676 ** Zero is returned if no extra-timestamp record could be found (and so
677 ** *pmTime is left unchanged), or non-zero otherwise.
679 ** The general format of an extra field is:
685 static int zipfileScanExtra(u8
*aExtra
, int nExtra
, u32
*pmTime
){
688 u8
*pEnd
= &aExtra
[nExtra
];
691 u16 id
= zipfileRead16(p
);
692 u16 nByte
= zipfileRead16(p
);
695 case ZIPFILE_EXTRA_TIMESTAMP
: {
697 if( b
& 0x01 ){ /* 0x01 -> modtime is present */
698 *pmTime
= zipfileGetU32(&p
[1]);
711 ** Convert the standard MS-DOS timestamp stored in the mTime and mDate
712 ** fields of the CDS structure passed as the only argument to a 32-bit
713 ** UNIX seconds-since-the-epoch timestamp. Return the result.
715 ** "Standard" MS-DOS time format:
717 ** File modification time:
718 ** Bits 00-04: seconds divided by 2
719 ** Bits 05-10: minute
721 ** File modification date:
723 ** Bits 05-08: month (1-12)
724 ** Bits 09-15: years from 1980
726 ** https://msdn.microsoft.com/en-us/library/9kkf9tah.aspx
728 static u32
zipfileMtime(ZipfileCDS
*pCDS
){
729 int Y
,M
,D
,X1
,X2
,A
,B
,sec
,min
,hr
;
731 Y
= (1980 + ((pCDS
->mDate
>> 9) & 0x7F));
732 M
= ((pCDS
->mDate
>> 5) & 0x0F);
733 D
= (pCDS
->mDate
& 0x1F);
734 sec
= (pCDS
->mTime
& 0x1F)*2;
735 min
= (pCDS
->mTime
>> 5) & 0x3F;
736 hr
= (pCDS
->mTime
>> 11) & 0x1F;
741 X1
= 36525*(Y
+4716)/100;
742 X2
= 306001*(M
+1)/10000;
745 JDsec
= (i64
)((X1
+ X2
+ D
+ B
- 1524.5)*86400) + hr
*3600 + min
*60 + sec
;
746 return (u32
)(JDsec
- (i64
)24405875*(i64
)8640);
750 ** The opposite of zipfileMtime(). This function populates the mTime and
751 ** mDate fields of the CDS structure passed as the first argument according
752 ** to the UNIX timestamp value passed as the second.
754 static void zipfileMtimeToDos(ZipfileCDS
*pCds
, u32 mUnixTime
){
755 /* Convert unix timestamp to JD (2440588 is noon on 1/1/1970) */
756 i64 JD
= (i64
)2440588 + mUnixTime
/ (24*60*60);
762 A
= (int)((JD
- 1867216.25)/36524.25);
763 A
= (int)(JD
+ 1 + A
- (A
/4));
765 C
= (int)((B
- 122.1)/365.25);
766 D
= (36525*(C
&32767))/100;
767 E
= (int)((B
-D
)/30.6001);
769 day
= B
- D
- (int)(30.6001*E
);
770 mon
= (E
<14 ? E
-1 : E
-13);
771 yr
= mon
>2 ? C
-4716 : C
-4715;
773 hr
= (mUnixTime
% (24*60*60)) / (60*60);
774 min
= (mUnixTime
% (60*60)) / 60;
775 sec
= (mUnixTime
% 60);
778 pCds
->mDate
= (u16
)(day
+ (mon
<< 5) + ((yr
-1980) << 9));
779 pCds
->mTime
= (u16
)(sec
/2 + (min
<<5) + (hr
<<11));
781 pCds
->mDate
= pCds
->mTime
= 0;
784 assert( mUnixTime
<315507600
785 || mUnixTime
==zipfileMtime(pCds
)
786 || ((mUnixTime
% 2) && mUnixTime
-1==zipfileMtime(pCds
))
787 /* || (mUnixTime % 2) */
792 ** If aBlob is not NULL, then it is a pointer to a buffer (nBlob bytes in
793 ** size) containing an entire zip archive image. Or, if aBlob is NULL,
794 ** then pFile is a file-handle open on a zip file. In either case, this
795 ** function creates a ZipfileEntry object based on the zip archive entry
796 ** for which the CDS record is at offset iOff.
798 ** If successful, SQLITE_OK is returned and (*ppEntry) set to point to
799 ** the new object. Otherwise, an SQLite error code is returned and the
800 ** final value of (*ppEntry) undefined.
802 static int zipfileGetEntry(
803 ZipfileTab
*pTab
, /* Store any error message here */
804 const u8
*aBlob
, /* Pointer to in-memory file image */
805 int nBlob
, /* Size of aBlob[] in bytes */
806 FILE *pFile
, /* If aBlob==0, read from this file */
807 i64 iOff
, /* Offset of CDS record */
808 ZipfileEntry
**ppEntry
/* OUT: Pointer to new object */
811 char **pzErr
= &pTab
->base
.zErrMsg
;
816 aRead
= pTab
->aBuffer
;
817 rc
= zipfileReadData(pFile
, aRead
, ZIPFILE_CDS_FIXED_SZ
, iOff
, pzErr
);
819 aRead
= (u8
*)&aBlob
[iOff
];
823 sqlite3_int64 nAlloc
;
826 int nFile
= zipfileGetU16(&aRead
[ZIPFILE_CDS_NFILE_OFF
]);
827 int nExtra
= zipfileGetU16(&aRead
[ZIPFILE_CDS_NFILE_OFF
+2]);
828 nExtra
+= zipfileGetU16(&aRead
[ZIPFILE_CDS_NFILE_OFF
+4]);
830 nAlloc
= sizeof(ZipfileEntry
) + nExtra
;
832 nAlloc
+= zipfileGetU32(&aRead
[ZIPFILE_CDS_SZCOMPRESSED_OFF
]);
835 pNew
= (ZipfileEntry
*)sqlite3_malloc64(nAlloc
);
839 memset(pNew
, 0, sizeof(ZipfileEntry
));
840 rc
= zipfileReadCDS(aRead
, &pNew
->cds
);
842 *pzErr
= sqlite3_mprintf("failed to read CDS at offset %lld", iOff
);
843 }else if( aBlob
==0 ){
844 rc
= zipfileReadData(
845 pFile
, aRead
, nExtra
+nFile
, iOff
+ZIPFILE_CDS_FIXED_SZ
, pzErr
848 aRead
= (u8
*)&aBlob
[iOff
+ ZIPFILE_CDS_FIXED_SZ
];
853 u32
*pt
= &pNew
->mUnixTime
;
854 pNew
->cds
.zFile
= sqlite3_mprintf("%.*s", nFile
, aRead
);
855 pNew
->aExtra
= (u8
*)&pNew
[1];
856 memcpy(pNew
->aExtra
, &aRead
[nFile
], nExtra
);
857 if( pNew
->cds
.zFile
==0 ){
859 }else if( 0==zipfileScanExtra(&aRead
[nFile
], pNew
->cds
.nExtra
, pt
) ){
860 pNew
->mUnixTime
= zipfileMtime(&pNew
->cds
);
865 static const int szFix
= ZIPFILE_LFH_FIXED_SZ
;
868 rc
= zipfileReadData(pFile
, aRead
, szFix
, pNew
->cds
.iOffset
, pzErr
);
870 aRead
= (u8
*)&aBlob
[pNew
->cds
.iOffset
];
873 if( rc
==SQLITE_OK
) rc
= zipfileReadLFH(aRead
, &lfh
);
875 pNew
->iDataOff
= pNew
->cds
.iOffset
+ ZIPFILE_LFH_FIXED_SZ
;
876 pNew
->iDataOff
+= lfh
.nFile
+ lfh
.nExtra
;
877 if( aBlob
&& pNew
->cds
.szCompressed
){
878 pNew
->aData
= &pNew
->aExtra
[nExtra
];
879 memcpy(pNew
->aData
, &aBlob
[pNew
->iDataOff
], pNew
->cds
.szCompressed
);
882 *pzErr
= sqlite3_mprintf("failed to read LFH at offset %d",
883 (int)pNew
->cds
.iOffset
889 zipfileEntryFree(pNew
);
899 ** Advance an ZipfileCsr to its next row of output.
901 static int zipfileNext(sqlite3_vtab_cursor
*cur
){
902 ZipfileCsr
*pCsr
= (ZipfileCsr
*)cur
;
906 i64 iEof
= pCsr
->eocd
.iOffset
+ pCsr
->eocd
.nSize
;
907 zipfileEntryFree(pCsr
->pCurrent
);
909 if( pCsr
->iNextOff
>=iEof
){
913 ZipfileTab
*pTab
= (ZipfileTab
*)(cur
->pVtab
);
914 rc
= zipfileGetEntry(pTab
, 0, 0, pCsr
->pFile
, pCsr
->iNextOff
, &p
);
916 pCsr
->iNextOff
+= ZIPFILE_CDS_FIXED_SZ
;
917 pCsr
->iNextOff
+= (int)p
->cds
.nExtra
+ p
->cds
.nFile
+ p
->cds
.nComment
;
923 pCsr
->pCurrent
= pCsr
->pCurrent
->pNext
;
925 if( pCsr
->pCurrent
==0 ){
934 static void zipfileFree(void *p
) {
939 ** Buffer aIn (size nIn bytes) contains compressed data. Uncompressed, the
940 ** size is nOut bytes. This function uncompresses the data and sets the
941 ** return value in context pCtx to the result (a blob).
943 ** If an error occurs, an error code is left in pCtx instead.
945 static void zipfileInflate(
946 sqlite3_context
*pCtx
, /* Store result here */
947 const u8
*aIn
, /* Compressed data */
948 int nIn
, /* Size of buffer aIn[] in bytes */
949 int nOut
/* Expected output size */
951 u8
*aRes
= sqlite3_malloc(nOut
);
953 sqlite3_result_error_nomem(pCtx
);
957 memset(&str
, 0, sizeof(str
));
959 str
.next_in
= (Byte
*)aIn
;
961 str
.next_out
= (Byte
*)aRes
;
962 str
.avail_out
= nOut
;
964 err
= inflateInit2(&str
, -15);
966 zipfileCtxErrorMsg(pCtx
, "inflateInit2() failed (%d)", err
);
968 err
= inflate(&str
, Z_NO_FLUSH
);
969 if( err
!=Z_STREAM_END
){
970 zipfileCtxErrorMsg(pCtx
, "inflate() failed (%d)", err
);
972 sqlite3_result_blob(pCtx
, aRes
, nOut
, zipfileFree
);
982 ** Buffer aIn (size nIn bytes) contains uncompressed data. This function
983 ** compresses it and sets (*ppOut) to point to a buffer containing the
984 ** compressed data. The caller is responsible for eventually calling
985 ** sqlite3_free() to release buffer (*ppOut). Before returning, (*pnOut)
986 ** is set to the size of buffer (*ppOut) in bytes.
988 ** If no error occurs, SQLITE_OK is returned. Otherwise, an SQLite error
989 ** code is returned and an error message left in virtual-table handle
990 ** pTab. The values of (*ppOut) and (*pnOut) are left unchanged in this
993 static int zipfileDeflate(
994 const u8
*aIn
, int nIn
, /* Input */
995 u8
**ppOut
, int *pnOut
, /* Output */
996 char **pzErr
/* OUT: Error message */
999 sqlite3_int64 nAlloc
;
1003 memset(&str
, 0, sizeof(str
));
1004 str
.next_in
= (Bytef
*)aIn
;
1006 deflateInit2(&str
, 9, Z_DEFLATED
, -15, 8, Z_DEFAULT_STRATEGY
);
1008 nAlloc
= deflateBound(&str
, nIn
);
1009 aOut
= (u8
*)sqlite3_malloc64(nAlloc
);
1014 str
.next_out
= aOut
;
1015 str
.avail_out
= nAlloc
;
1016 res
= deflate(&str
, Z_FINISH
);
1017 if( res
==Z_STREAM_END
){
1019 *pnOut
= (int)str
.total_out
;
1022 *pzErr
= sqlite3_mprintf("zipfile: deflate() error");
1033 ** Return values of columns for the row at which the series_cursor
1034 ** is currently pointing.
1036 static int zipfileColumn(
1037 sqlite3_vtab_cursor
*cur
, /* The cursor */
1038 sqlite3_context
*ctx
, /* First argument to sqlite3_result_...() */
1039 int i
/* Which column to return */
1041 ZipfileCsr
*pCsr
= (ZipfileCsr
*)cur
;
1042 ZipfileCDS
*pCDS
= &pCsr
->pCurrent
->cds
;
1046 sqlite3_result_text(ctx
, pCDS
->zFile
, -1, SQLITE_TRANSIENT
);
1049 /* TODO: Whether or not the following is correct surely depends on
1050 ** the platform on which the archive was created. */
1051 sqlite3_result_int(ctx
, pCDS
->iExternalAttr
>> 16);
1053 case 2: { /* mtime */
1054 sqlite3_result_int64(ctx
, pCsr
->pCurrent
->mUnixTime
);
1058 if( sqlite3_vtab_nochange(ctx
)==0 ){
1059 sqlite3_result_int64(ctx
, pCDS
->szUncompressed
);
1063 case 4: /* rawdata */
1064 if( sqlite3_vtab_nochange(ctx
) ) break;
1065 case 5: { /* data */
1066 if( i
==4 || pCDS
->iCompression
==0 || pCDS
->iCompression
==8 ){
1067 int sz
= pCDS
->szCompressed
;
1068 int szFinal
= pCDS
->szUncompressed
;
1072 if( pCsr
->pCurrent
->aData
){
1073 aBuf
= pCsr
->pCurrent
->aData
;
1075 aBuf
= aFree
= sqlite3_malloc64(sz
);
1079 FILE *pFile
= pCsr
->pFile
;
1081 pFile
= ((ZipfileTab
*)(pCsr
->base
.pVtab
))->pWriteFd
;
1083 rc
= zipfileReadData(pFile
, aBuf
, sz
, pCsr
->pCurrent
->iDataOff
,
1084 &pCsr
->base
.pVtab
->zErrMsg
1088 if( rc
==SQLITE_OK
){
1089 if( i
==5 && pCDS
->iCompression
){
1090 zipfileInflate(ctx
, aBuf
, sz
, szFinal
);
1092 sqlite3_result_blob(ctx
, aBuf
, sz
, SQLITE_TRANSIENT
);
1095 sqlite3_free(aFree
);
1097 /* Figure out if this is a directory or a zero-sized file. Consider
1098 ** it to be a directory either if the mode suggests so, or if
1099 ** the final character in the name is '/'. */
1100 u32 mode
= pCDS
->iExternalAttr
>> 16;
1101 if( !(mode
& S_IFDIR
)
1103 && pCDS
->zFile
[pCDS
->nFile
-1]!='/'
1105 sqlite3_result_blob(ctx
, "", 0, SQLITE_STATIC
);
1111 case 6: /* method */
1112 sqlite3_result_int(ctx
, pCDS
->iCompression
);
1116 sqlite3_result_int64(ctx
, pCsr
->iId
);
1124 ** Return TRUE if the cursor is at EOF.
1126 static int zipfileEof(sqlite3_vtab_cursor
*cur
){
1127 ZipfileCsr
*pCsr
= (ZipfileCsr
*)cur
;
1132 ** If aBlob is not NULL, then it points to a buffer nBlob bytes in size
1133 ** containing an entire zip archive image. Or, if aBlob is NULL, then pFile
1134 ** is guaranteed to be a file-handle open on a zip file.
1136 ** This function attempts to locate the EOCD record within the zip archive
1137 ** and populate *pEOCD with the results of decoding it. SQLITE_OK is
1138 ** returned if successful. Otherwise, an SQLite error code is returned and
1139 ** an English language error message may be left in virtual-table pTab.
1141 static int zipfileReadEOCD(
1142 ZipfileTab
*pTab
, /* Return errors here */
1143 const u8
*aBlob
, /* Pointer to in-memory file image */
1144 int nBlob
, /* Size of aBlob[] in bytes */
1145 FILE *pFile
, /* Read from this file if aBlob==0 */
1146 ZipfileEOCD
*pEOCD
/* Object to populate */
1148 u8
*aRead
= pTab
->aBuffer
; /* Temporary buffer */
1149 int nRead
; /* Bytes to read from file */
1152 memset(pEOCD
, 0, sizeof(ZipfileEOCD
));
1154 i64 iOff
; /* Offset to read from */
1155 i64 szFile
; /* Total size of file in bytes */
1156 fseek(pFile
, 0, SEEK_END
);
1157 szFile
= (i64
)ftell(pFile
);
1161 nRead
= (int)(MIN(szFile
, ZIPFILE_BUFFER_SIZE
));
1162 iOff
= szFile
- nRead
;
1163 rc
= zipfileReadData(pFile
, aRead
, nRead
, iOff
, &pTab
->base
.zErrMsg
);
1165 nRead
= (int)(MIN(nBlob
, ZIPFILE_BUFFER_SIZE
));
1166 aRead
= (u8
*)&aBlob
[nBlob
-nRead
];
1169 if( rc
==SQLITE_OK
){
1172 /* Scan backwards looking for the signature bytes */
1173 for(i
=nRead
-20; i
>=0; i
--){
1174 if( aRead
[i
]==0x50 && aRead
[i
+1]==0x4b
1175 && aRead
[i
+2]==0x05 && aRead
[i
+3]==0x06
1181 pTab
->base
.zErrMsg
= sqlite3_mprintf(
1182 "cannot find end of central directory record"
1184 return SQLITE_ERROR
;
1188 pEOCD
->iDisk
= zipfileRead16(aRead
);
1189 pEOCD
->iFirstDisk
= zipfileRead16(aRead
);
1190 pEOCD
->nEntry
= zipfileRead16(aRead
);
1191 pEOCD
->nEntryTotal
= zipfileRead16(aRead
);
1192 pEOCD
->nSize
= zipfileRead32(aRead
);
1193 pEOCD
->iOffset
= zipfileRead32(aRead
);
1200 ** Add object pNew to the linked list that begins at ZipfileTab.pFirstEntry
1201 ** and ends with pLastEntry. If argument pBefore is NULL, then pNew is added
1202 ** to the end of the list. Otherwise, it is added to the list immediately
1203 ** before pBefore (which is guaranteed to be a part of said list).
1205 static void zipfileAddEntry(
1207 ZipfileEntry
*pBefore
,
1210 assert( (pTab
->pFirstEntry
==0)==(pTab
->pLastEntry
==0) );
1211 assert( pNew
->pNext
==0 );
1213 if( pTab
->pFirstEntry
==0 ){
1214 pTab
->pFirstEntry
= pTab
->pLastEntry
= pNew
;
1216 assert( pTab
->pLastEntry
->pNext
==0 );
1217 pTab
->pLastEntry
->pNext
= pNew
;
1218 pTab
->pLastEntry
= pNew
;
1222 for(pp
=&pTab
->pFirstEntry
; *pp
!=pBefore
; pp
=&((*pp
)->pNext
));
1223 pNew
->pNext
= pBefore
;
1228 static int zipfileLoadDirectory(ZipfileTab
*pTab
, const u8
*aBlob
, int nBlob
){
1234 rc
= zipfileReadEOCD(pTab
, aBlob
, nBlob
, pTab
->pWriteFd
, &eocd
);
1235 iOff
= eocd
.iOffset
;
1236 for(i
=0; rc
==SQLITE_OK
&& i
<eocd
.nEntry
; i
++){
1237 ZipfileEntry
*pNew
= 0;
1238 rc
= zipfileGetEntry(pTab
, aBlob
, nBlob
, pTab
->pWriteFd
, iOff
, &pNew
);
1240 if( rc
==SQLITE_OK
){
1241 zipfileAddEntry(pTab
, 0, pNew
);
1242 iOff
+= ZIPFILE_CDS_FIXED_SZ
;
1243 iOff
+= (int)pNew
->cds
.nExtra
+ pNew
->cds
.nFile
+ pNew
->cds
.nComment
;
1250 ** xFilter callback.
1252 static int zipfileFilter(
1253 sqlite3_vtab_cursor
*cur
,
1254 int idxNum
, const char *idxStr
,
1255 int argc
, sqlite3_value
**argv
1257 ZipfileTab
*pTab
= (ZipfileTab
*)cur
->pVtab
;
1258 ZipfileCsr
*pCsr
= (ZipfileCsr
*)cur
;
1259 const char *zFile
= 0; /* Zip file to scan */
1260 int rc
= SQLITE_OK
; /* Return Code */
1261 int bInMemory
= 0; /* True for an in-memory zipfile */
1266 zipfileResetCursor(pCsr
);
1269 zFile
= pTab
->zFile
;
1270 }else if( idxNum
==0 ){
1271 zipfileCursorErr(pCsr
, "zipfile() function requires an argument");
1272 return SQLITE_ERROR
;
1273 }else if( sqlite3_value_type(argv
[0])==SQLITE_BLOB
){
1274 static const u8 aEmptyBlob
= 0;
1275 const u8
*aBlob
= (const u8
*)sqlite3_value_blob(argv
[0]);
1276 int nBlob
= sqlite3_value_bytes(argv
[0]);
1277 assert( pTab
->pFirstEntry
==0 );
1279 aBlob
= &aEmptyBlob
;
1282 rc
= zipfileLoadDirectory(pTab
, aBlob
, nBlob
);
1283 pCsr
->pFreeEntry
= pTab
->pFirstEntry
;
1284 pTab
->pFirstEntry
= pTab
->pLastEntry
= 0;
1285 if( rc
!=SQLITE_OK
) return rc
;
1288 zFile
= (const char*)sqlite3_value_text(argv
[0]);
1291 if( 0==pTab
->pWriteFd
&& 0==bInMemory
){
1292 pCsr
->pFile
= zFile
? fopen(zFile
, "rb") : 0;
1293 if( pCsr
->pFile
==0 ){
1294 zipfileCursorErr(pCsr
, "cannot open file: %s", zFile
);
1297 rc
= zipfileReadEOCD(pTab
, 0, 0, pCsr
->pFile
, &pCsr
->eocd
);
1298 if( rc
==SQLITE_OK
){
1299 if( pCsr
->eocd
.nEntry
==0 ){
1302 pCsr
->iNextOff
= pCsr
->eocd
.iOffset
;
1303 rc
= zipfileNext(cur
);
1309 pCsr
->pCurrent
= pCsr
->pFreeEntry
? pCsr
->pFreeEntry
: pTab
->pFirstEntry
;
1310 rc
= zipfileNext(cur
);
1317 ** xBestIndex callback.
1319 static int zipfileBestIndex(
1321 sqlite3_index_info
*pIdxInfo
1328 for(i
=0; i
<pIdxInfo
->nConstraint
; i
++){
1329 const struct sqlite3_index_constraint
*pCons
= &pIdxInfo
->aConstraint
[i
];
1330 if( pCons
->iColumn
!=ZIPFILE_F_COLUMN_IDX
) continue;
1331 if( pCons
->usable
==0 ){
1333 }else if( pCons
->op
==SQLITE_INDEX_CONSTRAINT_EQ
){
1337 pIdxInfo
->estimatedCost
= 1000.0;
1339 pIdxInfo
->aConstraintUsage
[idx
].argvIndex
= 1;
1340 pIdxInfo
->aConstraintUsage
[idx
].omit
= 1;
1341 pIdxInfo
->idxNum
= 1;
1342 }else if( unusable
){
1343 return SQLITE_CONSTRAINT
;
1348 static ZipfileEntry
*zipfileNewEntry(const char *zPath
){
1350 pNew
= sqlite3_malloc(sizeof(ZipfileEntry
));
1352 memset(pNew
, 0, sizeof(ZipfileEntry
));
1353 pNew
->cds
.zFile
= sqlite3_mprintf("%s", zPath
);
1354 if( pNew
->cds
.zFile
==0 ){
1362 static int zipfileSerializeLFH(ZipfileEntry
*pEntry
, u8
*aBuf
){
1363 ZipfileCDS
*pCds
= &pEntry
->cds
;
1368 /* Write the LFH itself */
1369 zipfileWrite32(a
, ZIPFILE_SIGNATURE_LFH
);
1370 zipfileWrite16(a
, pCds
->iVersionExtract
);
1371 zipfileWrite16(a
, pCds
->flags
);
1372 zipfileWrite16(a
, pCds
->iCompression
);
1373 zipfileWrite16(a
, pCds
->mTime
);
1374 zipfileWrite16(a
, pCds
->mDate
);
1375 zipfileWrite32(a
, pCds
->crc32
);
1376 zipfileWrite32(a
, pCds
->szCompressed
);
1377 zipfileWrite32(a
, pCds
->szUncompressed
);
1378 zipfileWrite16(a
, (u16
)pCds
->nFile
);
1379 zipfileWrite16(a
, pCds
->nExtra
);
1380 assert( a
==&aBuf
[ZIPFILE_LFH_FIXED_SZ
] );
1382 /* Add the file name */
1383 memcpy(a
, pCds
->zFile
, (int)pCds
->nFile
);
1384 a
+= (int)pCds
->nFile
;
1386 /* The "extra" data */
1387 zipfileWrite16(a
, ZIPFILE_EXTRA_TIMESTAMP
);
1388 zipfileWrite16(a
, 5);
1390 zipfileWrite32(a
, pEntry
->mUnixTime
);
1395 static int zipfileAppendEntry(
1397 ZipfileEntry
*pEntry
,
1401 u8
*aBuf
= pTab
->aBuffer
;
1405 nBuf
= zipfileSerializeLFH(pEntry
, aBuf
);
1406 rc
= zipfileAppendData(pTab
, aBuf
, nBuf
);
1407 if( rc
==SQLITE_OK
){
1408 pEntry
->iDataOff
= pTab
->szCurrent
;
1409 rc
= zipfileAppendData(pTab
, pData
, nData
);
1415 static int zipfileGetMode(
1416 sqlite3_value
*pVal
,
1417 int bIsDir
, /* If true, default to directory */
1418 u32
*pMode
, /* OUT: Mode value */
1419 char **pzErr
/* OUT: Error message */
1421 const char *z
= (const char*)sqlite3_value_text(pVal
);
1424 mode
= (bIsDir
? (S_IFDIR
+ 0755) : (S_IFREG
+ 0644));
1425 }else if( z
[0]>='0' && z
[0]<='9' ){
1426 mode
= (unsigned int)sqlite3_value_int(pVal
);
1428 const char zTemplate
[11] = "-rwxrwxrwx";
1430 if( strlen(z
)!=10 ) goto parse_error
;
1432 case '-': mode
|= S_IFREG
; break;
1433 case 'd': mode
|= S_IFDIR
; break;
1434 case 'l': mode
|= S_IFLNK
; break;
1435 default: goto parse_error
;
1437 for(i
=1; i
<10; i
++){
1438 if( z
[i
]==zTemplate
[i
] ) mode
|= 1 << (9-i
);
1439 else if( z
[i
]!='-' ) goto parse_error
;
1442 if( ((mode
& S_IFDIR
)==0)==bIsDir
){
1443 /* The "mode" attribute is a directory, but data has been specified.
1444 ** Or vice-versa - no data but "mode" is a file or symlink. */
1445 *pzErr
= sqlite3_mprintf("zipfile: mode does not match data");
1446 return SQLITE_CONSTRAINT
;
1452 *pzErr
= sqlite3_mprintf("zipfile: parse error in mode: %s", z
);
1453 return SQLITE_ERROR
;
1457 ** Both (const char*) arguments point to nul-terminated strings. Argument
1458 ** nB is the value of strlen(zB). This function returns 0 if the strings are
1459 ** identical, ignoring any trailing '/' character in either path. */
1460 static int zipfileComparePath(const char *zA
, const char *zB
, int nB
){
1461 int nA
= (int)strlen(zA
);
1462 if( nA
>0 && zA
[nA
-1]=='/' ) nA
--;
1463 if( nB
>0 && zB
[nB
-1]=='/' ) nB
--;
1464 if( nA
==nB
&& memcmp(zA
, zB
, nA
)==0 ) return 0;
1468 static int zipfileBegin(sqlite3_vtab
*pVtab
){
1469 ZipfileTab
*pTab
= (ZipfileTab
*)pVtab
;
1472 assert( pTab
->pWriteFd
==0 );
1473 if( pTab
->zFile
==0 || pTab
->zFile
[0]==0 ){
1474 pTab
->base
.zErrMsg
= sqlite3_mprintf("zipfile: missing filename");
1475 return SQLITE_ERROR
;
1478 /* Open a write fd on the file. Also load the entire central directory
1479 ** structure into memory. During the transaction any new file data is
1480 ** appended to the archive file, but the central directory is accumulated
1481 ** in main-memory until the transaction is committed. */
1482 pTab
->pWriteFd
= fopen(pTab
->zFile
, "ab+");
1483 if( pTab
->pWriteFd
==0 ){
1484 pTab
->base
.zErrMsg
= sqlite3_mprintf(
1485 "zipfile: failed to open file %s for writing", pTab
->zFile
1489 fseek(pTab
->pWriteFd
, 0, SEEK_END
);
1490 pTab
->szCurrent
= pTab
->szOrig
= (i64
)ftell(pTab
->pWriteFd
);
1491 rc
= zipfileLoadDirectory(pTab
, 0, 0);
1494 if( rc
!=SQLITE_OK
){
1495 zipfileCleanupTransaction(pTab
);
1502 ** Return the current time as a 32-bit timestamp in UNIX epoch format (like
1505 static u32
zipfileTime(void){
1506 sqlite3_vfs
*pVfs
= sqlite3_vfs_find(0);
1508 if( pVfs
==0 ) return 0;
1509 if( pVfs
->iVersion
>=2 && pVfs
->xCurrentTimeInt64
){
1511 pVfs
->xCurrentTimeInt64(pVfs
, &ms
);
1512 ret
= (u32
)((ms
/1000) - ((i64
)24405875 * 8640));
1515 pVfs
->xCurrentTime(pVfs
, &day
);
1516 ret
= (u32
)((day
- 2440587.5) * 86400);
1522 ** Return a 32-bit timestamp in UNIX epoch format.
1524 ** If the value passed as the only argument is either NULL or an SQL NULL,
1525 ** return the current time. Otherwise, return the value stored in (*pVal)
1526 ** cast to a 32-bit unsigned integer.
1528 static u32
zipfileGetTime(sqlite3_value
*pVal
){
1529 if( pVal
==0 || sqlite3_value_type(pVal
)==SQLITE_NULL
){
1530 return zipfileTime();
1532 return (u32
)sqlite3_value_int64(pVal
);
1536 ** Unless it is NULL, entry pOld is currently part of the pTab->pFirstEntry
1537 ** linked list. Remove it from the list and free the object.
1539 static void zipfileRemoveEntryFromList(ZipfileTab
*pTab
, ZipfileEntry
*pOld
){
1541 if( pTab
->pFirstEntry
==pOld
){
1542 pTab
->pFirstEntry
= pOld
->pNext
;
1543 if( pTab
->pLastEntry
==pOld
) pTab
->pLastEntry
= 0;
1546 for(p
=pTab
->pFirstEntry
; p
; p
=p
->pNext
){
1547 if( p
->pNext
==pOld
){
1548 p
->pNext
= pOld
->pNext
;
1549 if( pTab
->pLastEntry
==pOld
) pTab
->pLastEntry
= p
;
1554 zipfileEntryFree(pOld
);
1561 static int zipfileUpdate(
1562 sqlite3_vtab
*pVtab
,
1564 sqlite3_value
**apVal
,
1565 sqlite_int64
*pRowid
1567 ZipfileTab
*pTab
= (ZipfileTab
*)pVtab
;
1568 int rc
= SQLITE_OK
; /* Return Code */
1569 ZipfileEntry
*pNew
= 0; /* New in-memory CDS entry */
1571 u32 mode
= 0; /* Mode for new entry */
1572 u32 mTime
= 0; /* Modification time for new entry */
1573 i64 sz
= 0; /* Uncompressed size */
1574 const char *zPath
= 0; /* Path for new entry */
1575 int nPath
= 0; /* strlen(zPath) */
1576 const u8
*pData
= 0; /* Pointer to buffer containing content */
1577 int nData
= 0; /* Size of pData buffer in bytes */
1578 int iMethod
= 0; /* Compression method for new entry */
1579 u8
*pFree
= 0; /* Free this */
1580 char *zFree
= 0; /* Also free this */
1581 ZipfileEntry
*pOld
= 0;
1582 ZipfileEntry
*pOld2
= 0;
1583 int bUpdate
= 0; /* True for an update that modifies "name" */
1589 if( pTab
->pWriteFd
==0 ){
1590 rc
= zipfileBegin(pVtab
);
1591 if( rc
!=SQLITE_OK
) return rc
;
1594 /* If this is a DELETE or UPDATE, find the archive entry to delete. */
1595 if( sqlite3_value_type(apVal
[0])!=SQLITE_NULL
){
1596 const char *zDelete
= (const char*)sqlite3_value_text(apVal
[0]);
1597 int nDelete
= (int)strlen(zDelete
);
1599 const char *zUpdate
= (const char*)sqlite3_value_text(apVal
[1]);
1600 if( zUpdate
&& zipfileComparePath(zUpdate
, zDelete
, nDelete
)!=0 ){
1604 for(pOld
=pTab
->pFirstEntry
; 1; pOld
=pOld
->pNext
){
1605 if( zipfileComparePath(pOld
->cds
.zFile
, zDelete
, nDelete
)==0 ){
1608 assert( pOld
->pNext
);
1613 /* Check that "sz" and "rawdata" are both NULL: */
1614 if( sqlite3_value_type(apVal
[5])!=SQLITE_NULL
){
1615 zipfileTableErr(pTab
, "sz must be NULL");
1616 rc
= SQLITE_CONSTRAINT
;
1618 if( sqlite3_value_type(apVal
[6])!=SQLITE_NULL
){
1619 zipfileTableErr(pTab
, "rawdata must be NULL");
1620 rc
= SQLITE_CONSTRAINT
;
1623 if( rc
==SQLITE_OK
){
1624 if( sqlite3_value_type(apVal
[7])==SQLITE_NULL
){
1625 /* data=NULL. A directory */
1628 /* Value specified for "data", and possibly "method". This must be
1629 ** a regular file or a symlink. */
1630 const u8
*aIn
= sqlite3_value_blob(apVal
[7]);
1631 int nIn
= sqlite3_value_bytes(apVal
[7]);
1632 int bAuto
= sqlite3_value_type(apVal
[8])==SQLITE_NULL
;
1634 iMethod
= sqlite3_value_int(apVal
[8]);
1638 if( iMethod
!=0 && iMethod
!=8 ){
1639 zipfileTableErr(pTab
, "unknown compression method: %d", iMethod
);
1640 rc
= SQLITE_CONSTRAINT
;
1642 if( bAuto
|| iMethod
){
1644 rc
= zipfileDeflate(aIn
, nIn
, &pFree
, &nCmp
, &pTab
->base
.zErrMsg
);
1645 if( rc
==SQLITE_OK
){
1646 if( iMethod
|| nCmp
<nIn
){
1653 iCrc32
= crc32(0, aIn
, nIn
);
1658 if( rc
==SQLITE_OK
){
1659 rc
= zipfileGetMode(apVal
[3], bIsDir
, &mode
, &pTab
->base
.zErrMsg
);
1662 if( rc
==SQLITE_OK
){
1663 zPath
= (const char*)sqlite3_value_text(apVal
[2]);
1664 if( zPath
==0 ) zPath
= "";
1665 nPath
= (int)strlen(zPath
);
1666 mTime
= zipfileGetTime(apVal
[4]);
1669 if( rc
==SQLITE_OK
&& bIsDir
){
1670 /* For a directory, check that the last character in the path is a
1671 ** '/'. This appears to be required for compatibility with info-zip
1672 ** (the unzip command on unix). It does not create directories
1674 if( nPath
<=0 || zPath
[nPath
-1]!='/' ){
1675 zFree
= sqlite3_mprintf("%s/", zPath
);
1676 zPath
= (const char*)zFree
;
1681 nPath
= (int)strlen(zPath
);
1686 /* Check that we're not inserting a duplicate entry -OR- updating an
1687 ** entry with a path, thereby making it into a duplicate. */
1688 if( (pOld
==0 || bUpdate
) && rc
==SQLITE_OK
){
1690 for(p
=pTab
->pFirstEntry
; p
; p
=p
->pNext
){
1691 if( zipfileComparePath(p
->cds
.zFile
, zPath
, nPath
)==0 ){
1692 switch( sqlite3_vtab_on_conflict(pTab
->db
) ){
1693 case SQLITE_IGNORE
: {
1694 goto zipfile_update_done
;
1696 case SQLITE_REPLACE
: {
1701 zipfileTableErr(pTab
, "duplicate name: \"%s\"", zPath
);
1702 rc
= SQLITE_CONSTRAINT
;
1711 if( rc
==SQLITE_OK
){
1712 /* Create the new CDS record. */
1713 pNew
= zipfileNewEntry(zPath
);
1717 pNew
->cds
.iVersionMadeBy
= ZIPFILE_NEWENTRY_MADEBY
;
1718 pNew
->cds
.iVersionExtract
= ZIPFILE_NEWENTRY_REQUIRED
;
1719 pNew
->cds
.flags
= ZIPFILE_NEWENTRY_FLAGS
;
1720 pNew
->cds
.iCompression
= (u16
)iMethod
;
1721 zipfileMtimeToDos(&pNew
->cds
, mTime
);
1722 pNew
->cds
.crc32
= iCrc32
;
1723 pNew
->cds
.szCompressed
= nData
;
1724 pNew
->cds
.szUncompressed
= (u32
)sz
;
1725 pNew
->cds
.iExternalAttr
= (mode
<<16);
1726 pNew
->cds
.iOffset
= (u32
)pTab
->szCurrent
;
1727 pNew
->cds
.nFile
= (u16
)nPath
;
1728 pNew
->mUnixTime
= (u32
)mTime
;
1729 rc
= zipfileAppendEntry(pTab
, pNew
, pData
, nData
);
1730 zipfileAddEntry(pTab
, pOld
, pNew
);
1735 if( rc
==SQLITE_OK
&& (pOld
|| pOld2
) ){
1737 for(pCsr
=pTab
->pCsrList
; pCsr
; pCsr
=pCsr
->pCsrNext
){
1738 if( pCsr
->pCurrent
&& (pCsr
->pCurrent
==pOld
|| pCsr
->pCurrent
==pOld2
) ){
1739 pCsr
->pCurrent
= pCsr
->pCurrent
->pNext
;
1744 zipfileRemoveEntryFromList(pTab
, pOld
);
1745 zipfileRemoveEntryFromList(pTab
, pOld2
);
1748 zipfile_update_done
:
1749 sqlite3_free(pFree
);
1750 sqlite3_free(zFree
);
1754 static int zipfileSerializeEOCD(ZipfileEOCD
*p
, u8
*aBuf
){
1756 zipfileWrite32(a
, ZIPFILE_SIGNATURE_EOCD
);
1757 zipfileWrite16(a
, p
->iDisk
);
1758 zipfileWrite16(a
, p
->iFirstDisk
);
1759 zipfileWrite16(a
, p
->nEntry
);
1760 zipfileWrite16(a
, p
->nEntryTotal
);
1761 zipfileWrite32(a
, p
->nSize
);
1762 zipfileWrite32(a
, p
->iOffset
);
1763 zipfileWrite16(a
, 0); /* Size of trailing comment in bytes*/
1768 static int zipfileAppendEOCD(ZipfileTab
*pTab
, ZipfileEOCD
*p
){
1769 int nBuf
= zipfileSerializeEOCD(p
, pTab
->aBuffer
);
1770 assert( nBuf
==ZIPFILE_EOCD_FIXED_SZ
);
1771 return zipfileAppendData(pTab
, pTab
->aBuffer
, nBuf
);
1775 ** Serialize the CDS structure into buffer aBuf[]. Return the number
1776 ** of bytes written.
1778 static int zipfileSerializeCDS(ZipfileEntry
*pEntry
, u8
*aBuf
){
1780 ZipfileCDS
*pCDS
= &pEntry
->cds
;
1782 if( pEntry
->aExtra
==0 ){
1786 zipfileWrite32(a
, ZIPFILE_SIGNATURE_CDS
);
1787 zipfileWrite16(a
, pCDS
->iVersionMadeBy
);
1788 zipfileWrite16(a
, pCDS
->iVersionExtract
);
1789 zipfileWrite16(a
, pCDS
->flags
);
1790 zipfileWrite16(a
, pCDS
->iCompression
);
1791 zipfileWrite16(a
, pCDS
->mTime
);
1792 zipfileWrite16(a
, pCDS
->mDate
);
1793 zipfileWrite32(a
, pCDS
->crc32
);
1794 zipfileWrite32(a
, pCDS
->szCompressed
);
1795 zipfileWrite32(a
, pCDS
->szUncompressed
);
1796 assert( a
==&aBuf
[ZIPFILE_CDS_NFILE_OFF
] );
1797 zipfileWrite16(a
, pCDS
->nFile
);
1798 zipfileWrite16(a
, pCDS
->nExtra
);
1799 zipfileWrite16(a
, pCDS
->nComment
);
1800 zipfileWrite16(a
, pCDS
->iDiskStart
);
1801 zipfileWrite16(a
, pCDS
->iInternalAttr
);
1802 zipfileWrite32(a
, pCDS
->iExternalAttr
);
1803 zipfileWrite32(a
, pCDS
->iOffset
);
1805 memcpy(a
, pCDS
->zFile
, pCDS
->nFile
);
1808 if( pEntry
->aExtra
){
1809 int n
= (int)pCDS
->nExtra
+ (int)pCDS
->nComment
;
1810 memcpy(a
, pEntry
->aExtra
, n
);
1813 assert( pCDS
->nExtra
==9 );
1814 zipfileWrite16(a
, ZIPFILE_EXTRA_TIMESTAMP
);
1815 zipfileWrite16(a
, 5);
1817 zipfileWrite32(a
, pEntry
->mUnixTime
);
1823 static int zipfileCommit(sqlite3_vtab
*pVtab
){
1824 ZipfileTab
*pTab
= (ZipfileTab
*)pVtab
;
1826 if( pTab
->pWriteFd
){
1827 i64 iOffset
= pTab
->szCurrent
;
1832 /* Write out all entries */
1833 for(p
=pTab
->pFirstEntry
; rc
==SQLITE_OK
&& p
; p
=p
->pNext
){
1834 int n
= zipfileSerializeCDS(p
, pTab
->aBuffer
);
1835 rc
= zipfileAppendData(pTab
, pTab
->aBuffer
, n
);
1839 /* Write out the EOCD record */
1841 eocd
.iFirstDisk
= 0;
1842 eocd
.nEntry
= (u16
)nEntry
;
1843 eocd
.nEntryTotal
= (u16
)nEntry
;
1844 eocd
.nSize
= (u32
)(pTab
->szCurrent
- iOffset
);
1845 eocd
.iOffset
= (u32
)iOffset
;
1846 rc
= zipfileAppendEOCD(pTab
, &eocd
);
1848 zipfileCleanupTransaction(pTab
);
1853 static int zipfileRollback(sqlite3_vtab
*pVtab
){
1854 return zipfileCommit(pVtab
);
1857 static ZipfileCsr
*zipfileFindCursor(ZipfileTab
*pTab
, i64 iId
){
1859 for(pCsr
=pTab
->pCsrList
; pCsr
; pCsr
=pCsr
->pCsrNext
){
1860 if( iId
==pCsr
->iId
) break;
1865 static void zipfileFunctionCds(
1866 sqlite3_context
*context
,
1868 sqlite3_value
**argv
1871 ZipfileTab
*pTab
= (ZipfileTab
*)sqlite3_user_data(context
);
1874 pCsr
= zipfileFindCursor(pTab
, sqlite3_value_int64(argv
[0]));
1876 ZipfileCDS
*p
= &pCsr
->pCurrent
->cds
;
1877 char *zRes
= sqlite3_mprintf("{"
1878 "\"version-made-by\" : %u, "
1879 "\"version-to-extract\" : %u, "
1881 "\"compression\" : %u, "
1885 "\"compressed-size\" : %u, "
1886 "\"uncompressed-size\" : %u, "
1887 "\"file-name-length\" : %u, "
1888 "\"extra-field-length\" : %u, "
1889 "\"file-comment-length\" : %u, "
1890 "\"disk-number-start\" : %u, "
1891 "\"internal-attr\" : %u, "
1892 "\"external-attr\" : %u, "
1893 "\"offset\" : %u }",
1894 (u32
)p
->iVersionMadeBy
, (u32
)p
->iVersionExtract
,
1895 (u32
)p
->flags
, (u32
)p
->iCompression
,
1896 (u32
)p
->mTime
, (u32
)p
->mDate
,
1897 (u32
)p
->crc32
, (u32
)p
->szCompressed
,
1898 (u32
)p
->szUncompressed
, (u32
)p
->nFile
,
1899 (u32
)p
->nExtra
, (u32
)p
->nComment
,
1900 (u32
)p
->iDiskStart
, (u32
)p
->iInternalAttr
,
1901 (u32
)p
->iExternalAttr
, (u32
)p
->iOffset
1905 sqlite3_result_error_nomem(context
);
1907 sqlite3_result_text(context
, zRes
, -1, SQLITE_TRANSIENT
);
1914 ** xFindFunction method.
1916 static int zipfileFindFunction(
1917 sqlite3_vtab
*pVtab
, /* Virtual table handle */
1918 int nArg
, /* Number of SQL function arguments */
1919 const char *zName
, /* Name of SQL function */
1920 void (**pxFunc
)(sqlite3_context
*,int,sqlite3_value
**), /* OUT: Result */
1921 void **ppArg
/* OUT: User data for *pxFunc */
1924 if( sqlite3_stricmp("zipfile_cds", zName
)==0 ){
1925 *pxFunc
= zipfileFunctionCds
;
1926 *ppArg
= (void*)pVtab
;
1932 typedef struct ZipfileBuffer ZipfileBuffer
;
1933 struct ZipfileBuffer
{
1934 u8
*a
; /* Pointer to buffer */
1935 int n
; /* Size of buffer in bytes */
1936 int nAlloc
; /* Byte allocated at a[] */
1939 typedef struct ZipfileCtx ZipfileCtx
;
1946 static int zipfileBufferGrow(ZipfileBuffer
*pBuf
, int nByte
){
1947 if( pBuf
->n
+nByte
>pBuf
->nAlloc
){
1949 sqlite3_int64 nNew
= pBuf
->n
? pBuf
->n
*2 : 512;
1950 int nReq
= pBuf
->n
+ nByte
;
1952 while( nNew
<nReq
) nNew
= nNew
*2;
1953 aNew
= sqlite3_realloc64(pBuf
->a
, nNew
);
1954 if( aNew
==0 ) return SQLITE_NOMEM
;
1956 pBuf
->nAlloc
= (int)nNew
;
1962 ** xStep() callback for the zipfile() aggregate. This can be called in
1963 ** any of the following ways:
1965 ** SELECT zipfile(name,data) ...
1966 ** SELECT zipfile(name,mode,mtime,data) ...
1967 ** SELECT zipfile(name,mode,mtime,data,method) ...
1969 static void zipfileStep(sqlite3_context
*pCtx
, int nVal
, sqlite3_value
**apVal
){
1970 ZipfileCtx
*p
; /* Aggregate function context */
1971 ZipfileEntry e
; /* New entry to add to zip archive */
1973 sqlite3_value
*pName
= 0;
1974 sqlite3_value
*pMode
= 0;
1975 sqlite3_value
*pMtime
= 0;
1976 sqlite3_value
*pData
= 0;
1977 sqlite3_value
*pMethod
= 0;
1984 int iMethod
= -1; /* Compression method to use (0 or 8) */
1986 const u8
*aData
= 0; /* Possibly compressed data for new entry */
1987 int nData
= 0; /* Size of aData[] in bytes */
1988 int szUncompressed
= 0; /* Size of data before compression */
1989 u8
*aFree
= 0; /* Free this before returning */
1990 u32 iCrc32
= 0; /* crc32 of uncompressed data */
1992 char *zName
= 0; /* Path (name) of new entry */
1993 int nName
= 0; /* Size of zName in bytes */
1994 char *zFree
= 0; /* Free this before returning */
1997 memset(&e
, 0, sizeof(e
));
1998 p
= (ZipfileCtx
*)sqlite3_aggregate_context(pCtx
, sizeof(ZipfileCtx
));
2001 /* Martial the arguments into stack variables */
2002 if( nVal
!=2 && nVal
!=4 && nVal
!=5 ){
2003 zErr
= sqlite3_mprintf("wrong number of arguments to function zipfile()");
2005 goto zipfile_step_out
;
2019 /* Check that the 'name' parameter looks ok. */
2020 zName
= (char*)sqlite3_value_text(pName
);
2021 nName
= sqlite3_value_bytes(pName
);
2023 zErr
= sqlite3_mprintf("first argument to zipfile() must be non-NULL");
2025 goto zipfile_step_out
;
2028 /* Inspect the 'method' parameter. This must be either 0 (store), 8 (use
2029 ** deflate compression) or NULL (choose automatically). */
2030 if( pMethod
&& SQLITE_NULL
!=sqlite3_value_type(pMethod
) ){
2031 iMethod
= (int)sqlite3_value_int64(pMethod
);
2032 if( iMethod
!=0 && iMethod
!=8 ){
2033 zErr
= sqlite3_mprintf("illegal method value: %d", iMethod
);
2035 goto zipfile_step_out
;
2039 /* Now inspect the data. If this is NULL, then the new entry must be a
2040 ** directory. Otherwise, figure out whether or not the data should
2041 ** be deflated or simply stored in the zip archive. */
2042 if( sqlite3_value_type(pData
)==SQLITE_NULL
){
2046 aData
= sqlite3_value_blob(pData
);
2047 szUncompressed
= nData
= sqlite3_value_bytes(pData
);
2048 iCrc32
= crc32(0, aData
, nData
);
2049 if( iMethod
<0 || iMethod
==8 ){
2051 rc
= zipfileDeflate(aData
, nData
, &aFree
, &nOut
, &zErr
);
2052 if( rc
!=SQLITE_OK
){
2053 goto zipfile_step_out
;
2055 if( iMethod
==8 || nOut
<nData
){
2065 /* Decode the "mode" argument. */
2066 rc
= zipfileGetMode(pMode
, bIsDir
, &mode
, &zErr
);
2067 if( rc
) goto zipfile_step_out
;
2069 /* Decode the "mtime" argument. */
2070 e
.mUnixTime
= zipfileGetTime(pMtime
);
2072 /* If this is a directory entry, ensure that there is exactly one '/'
2073 ** at the end of the path. Or, if this is not a directory and the path
2074 ** ends in '/' it is an error. */
2076 if( nName
>0 && zName
[nName
-1]=='/' ){
2077 zErr
= sqlite3_mprintf("non-directory name must not end with /");
2079 goto zipfile_step_out
;
2082 if( nName
==0 || zName
[nName
-1]!='/' ){
2083 zName
= zFree
= sqlite3_mprintf("%s/", zName
);
2086 goto zipfile_step_out
;
2088 nName
= (int)strlen(zName
);
2090 while( nName
>1 && zName
[nName
-2]=='/' ) nName
--;
2094 /* Assemble the ZipfileEntry object for the new zip archive entry */
2095 e
.cds
.iVersionMadeBy
= ZIPFILE_NEWENTRY_MADEBY
;
2096 e
.cds
.iVersionExtract
= ZIPFILE_NEWENTRY_REQUIRED
;
2097 e
.cds
.flags
= ZIPFILE_NEWENTRY_FLAGS
;
2098 e
.cds
.iCompression
= (u16
)iMethod
;
2099 zipfileMtimeToDos(&e
.cds
, (u32
)e
.mUnixTime
);
2100 e
.cds
.crc32
= iCrc32
;
2101 e
.cds
.szCompressed
= nData
;
2102 e
.cds
.szUncompressed
= szUncompressed
;
2103 e
.cds
.iExternalAttr
= (mode
<<16);
2104 e
.cds
.iOffset
= p
->body
.n
;
2105 e
.cds
.nFile
= (u16
)nName
;
2106 e
.cds
.zFile
= zName
;
2108 /* Append the LFH to the body of the new archive */
2109 nByte
= ZIPFILE_LFH_FIXED_SZ
+ e
.cds
.nFile
+ 9;
2110 if( (rc
= zipfileBufferGrow(&p
->body
, nByte
)) ) goto zipfile_step_out
;
2111 p
->body
.n
+= zipfileSerializeLFH(&e
, &p
->body
.a
[p
->body
.n
]);
2113 /* Append the data to the body of the new archive */
2115 if( (rc
= zipfileBufferGrow(&p
->body
, nData
)) ) goto zipfile_step_out
;
2116 memcpy(&p
->body
.a
[p
->body
.n
], aData
, nData
);
2120 /* Append the CDS record to the directory of the new archive */
2121 nByte
= ZIPFILE_CDS_FIXED_SZ
+ e
.cds
.nFile
+ 9;
2122 if( (rc
= zipfileBufferGrow(&p
->cds
, nByte
)) ) goto zipfile_step_out
;
2123 p
->cds
.n
+= zipfileSerializeCDS(&e
, &p
->cds
.a
[p
->cds
.n
]);
2125 /* Increment the count of entries in the archive */
2129 sqlite3_free(aFree
);
2130 sqlite3_free(zFree
);
2133 sqlite3_result_error(pCtx
, zErr
, -1);
2135 sqlite3_result_error_code(pCtx
, rc
);
2142 ** xFinalize() callback for zipfile aggregate function.
2144 static void zipfileFinal(sqlite3_context
*pCtx
){
2150 p
= (ZipfileCtx
*)sqlite3_aggregate_context(pCtx
, sizeof(ZipfileCtx
));
2153 memset(&eocd
, 0, sizeof(eocd
));
2154 eocd
.nEntry
= (u16
)p
->nEntry
;
2155 eocd
.nEntryTotal
= (u16
)p
->nEntry
;
2156 eocd
.nSize
= p
->cds
.n
;
2157 eocd
.iOffset
= p
->body
.n
;
2159 nZip
= p
->body
.n
+ p
->cds
.n
+ ZIPFILE_EOCD_FIXED_SZ
;
2160 aZip
= (u8
*)sqlite3_malloc64(nZip
);
2162 sqlite3_result_error_nomem(pCtx
);
2164 memcpy(aZip
, p
->body
.a
, p
->body
.n
);
2165 memcpy(&aZip
[p
->body
.n
], p
->cds
.a
, p
->cds
.n
);
2166 zipfileSerializeEOCD(&eocd
, &aZip
[p
->body
.n
+ p
->cds
.n
]);
2167 sqlite3_result_blob(pCtx
, aZip
, (int)nZip
, zipfileFree
);
2171 sqlite3_free(p
->body
.a
);
2172 sqlite3_free(p
->cds
.a
);
2177 ** Register the "zipfile" virtual table.
2179 static int zipfileRegister(sqlite3
*db
){
2180 static sqlite3_module zipfileModule
= {
2182 zipfileConnect
, /* xCreate */
2183 zipfileConnect
, /* xConnect */
2184 zipfileBestIndex
, /* xBestIndex */
2185 zipfileDisconnect
, /* xDisconnect */
2186 zipfileDisconnect
, /* xDestroy */
2187 zipfileOpen
, /* xOpen - open a cursor */
2188 zipfileClose
, /* xClose - close a cursor */
2189 zipfileFilter
, /* xFilter - configure scan constraints */
2190 zipfileNext
, /* xNext - advance a cursor */
2191 zipfileEof
, /* xEof - check for end of scan */
2192 zipfileColumn
, /* xColumn - read data */
2193 0, /* xRowid - read data */
2194 zipfileUpdate
, /* xUpdate */
2195 zipfileBegin
, /* xBegin */
2197 zipfileCommit
, /* xCommit */
2198 zipfileRollback
, /* xRollback */
2199 zipfileFindFunction
, /* xFindMethod */
2204 0, /* xShadowName */
2208 int rc
= sqlite3_create_module(db
, "zipfile" , &zipfileModule
, 0);
2209 if( rc
==SQLITE_OK
) rc
= sqlite3_overload_function(db
, "zipfile_cds", -1);
2210 if( rc
==SQLITE_OK
){
2211 rc
= sqlite3_create_function(db
, "zipfile", -1, SQLITE_UTF8
, 0, 0,
2212 zipfileStep
, zipfileFinal
2215 assert( sizeof(i64
)==8 );
2216 assert( sizeof(u32
)==4 );
2217 assert( sizeof(u16
)==2 );
2218 assert( sizeof(u8
)==1 );
2221 #else /* SQLITE_OMIT_VIRTUALTABLE */
2222 # define zipfileRegister(x) SQLITE_OK
2226 __declspec(dllexport
)
2228 int sqlite3_zipfile_init(
2231 const sqlite3_api_routines
*pApi
2233 SQLITE_EXTENSION_INIT2(pApi
);
2234 (void)pzErrMsg
; /* Unused parameter */
2235 return zipfileRegister(db
);