zipfile.c
Go to the documentation of this file.
1
18#ifdef linux
19#define _GNU_SOURCE
20#endif
21
22#ifdef STANDALONE
23#include <sqlite3.h>
24#else
25#include <sqlite3ext.h>
26static SQLITE_EXTENSION_INIT1
27#endif
28
29#if defined(_WIN32) || defined(_WIN64)
30#include <windows.h>
31#else
32#include <sys/mman.h>
33#include <fcntl.h>
34#include <unistd.h>
35#include <errno.h>
36#endif
37
38#include <stdio.h>
39#include <stdlib.h>
40#include <string.h>
41#include <limits.h>
42
43#include <zlib.h>
44
45#undef snprintf
46
47#define ZIP_SIG_LEN 4
48
49#define ZIP_LOCAL_HEADER_SIG 0x04034b50
50#define ZIP_LOCAL_HEADER_FLAGS 6
51#define ZIP_LOCAL_PATHLEN_OFFS 26
52#define ZIP_LOCAL_EXTRA_OFFS 28
53#define ZIP_LOCAL_HEADER_LEN 30
54
55#define ZIP_CENTRAL_HEADER_SIG 0x02014b50
56#define ZIP_CENTRAL_HEADER_FLAGS 8
57#define ZIP_CENTRAL_HEADER_LEN 46
58#define ZIP_CENTRAL_COMPMETH_OFFS 10
59#define ZIP_CENTRAL_MTIME_OFFS 12
60#define ZIP_CENTRAL_MDATE_OFFS 14
61#define ZIP_CENTRAL_CRC32_OFFS 16
62#define ZIP_CENTRAL_COMPLEN_OFFS 20
63#define ZIP_CENTRAL_UNCOMPLEN_OFFS 24
64#define ZIP_CENTRAL_PATHLEN_OFFS 28
65#define ZIP_CENTRAL_EXTRALEN_OFFS 30
66#define ZIP_CENTRAL_COMMENTLEN_OFFS 32
67#define ZIP_CENTRAL_LOCALHDR_OFFS 42
68
69#define ZIP_CENTRAL_END_SIG 0x06054b50
70#define ZIP_CENTRAL_END_LEN 22
71#define ZIP_CENTRAL_ENTS_OFFS 8
72#define ZIP_CENTRAL_DIRSIZE_OFFS 12
73#define ZIP_CENTRAL_DIRSTART_OFFS 16
74
75#define ZIP_COMPMETH_STORED 0
76#define ZIP_COMPMETH_DEFLATED 8
77
78#define zip_read_int(p) \
79 ((p)[0] | ((p)[1] << 8) | ((p)[2] << 16) | ((p)[3] << 24))
80#define zip_read_short(p) \
81 ((p)[0] | ((p)[1] << 8))
82
89typedef struct zip_file {
90 off_t length;
91 unsigned char *data;
92#if defined(_WIN32) || defined(_WIN64)
93 HANDLE h;
94 HANDLE mh;
95#endif
98 unsigned char *entries[1];
100
107typedef struct zip_vtab {
108 sqlite3_vtab vtab;
109 sqlite3 *db;
111 int sorted;
112 char tblname[1];
114
121typedef struct {
122 sqlite3_vtab_cursor cursor;
123 int pos;
126 int *matches;
127} zip_cursor;
128
129#ifdef SQLITE_OPEN_URI
130
137typedef struct mem_blk {
138#define MEM_MAGIC "MVFS"
139 char magic[4];
140 int opened;
141#if defined(_WIN32) || defined(_WIN64)
142 HANDLE mh;
143#else
144 long psize;
145#ifdef linux
146 sqlite3_mutex *mutex;
147 int lcnt;
148#endif
149#endif
150 unsigned long size;
151 unsigned long length;
152 unsigned char *data;
153} mem_blk;
154
161typedef struct mem_file {
162 sqlite3_file base;
163#ifdef linux
164 int lock;
165#endif
166 mem_blk *mb;
167} mem_file;
168
169/*
170 * Private VFS name
171 */
172
173static char mem_vfs_name[64];
174
175#endif /* SQLITE_OPEN_URI */
176
183static zip_file *
184zip_open(const char *filename)
185{
186#if defined(_WIN32) || defined(_WIN64)
187 HANDLE h, mh = INVALID_HANDLE_VALUE;
188 DWORD length;
189 unsigned char *data = 0;
190#else
191 int fd;
192 off_t length;
193 unsigned char *data = MAP_FAILED;
194#endif
195 int nentries, baseoffs = 0, i;
196 zip_file *zip = 0;
197 unsigned char *p, *q;
198
199 if (!filename) {
200 return 0;
201 }
202#if defined(_WIN32) || defined(_WIN64)
203 h = CreateFile(filename, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0);
204 if (h == INVALID_HANDLE_VALUE) {
205 goto error;
206 }
207 length = GetFileSize(h, 0);
208 if ((length == INVALID_FILE_SIZE) || (length < ZIP_CENTRAL_END_LEN)) {
209 goto error;
210 }
211 mh = CreateFileMapping(h, 0, PAGE_READONLY, 0, length, 0);
212 if (mh == INVALID_HANDLE_VALUE) {
213 goto error;
214 }
215 data = MapViewOfFile(mh, FILE_MAP_READ, 0, 0, length);
216 if (!data) {
217 goto error;
218 }
219#else
220 fd = open(filename, O_RDONLY);
221 if (fd < 0) {
222 goto error;
223 }
224 length = lseek(fd, 0, SEEK_END);
225 if ((length == -1) || (length < ZIP_CENTRAL_END_LEN)) {
226 goto error;
227 }
228 data = (unsigned char *) mmap(0, length, PROT_READ,
229 MAP_FILE | MAP_PRIVATE, fd, 0);
230 if (data == MAP_FAILED) {
231 goto error;
232 }
233 close(fd);
234 fd = -1;
235#endif
236 p = data + length - ZIP_CENTRAL_END_LEN;
237 while (p >= data) {
238 if (*p == (ZIP_CENTRAL_END_SIG & 0xFF)) {
240 break;
241 }
242 p -= ZIP_SIG_LEN;
243 } else {
244 --p;
245 }
246 }
247 if (p < data) {
248 goto error;
249 }
251 if (nentries == 0) {
252 goto error;
253 }
256 if (p < data || p > data + length || q < data || q > data + length) {
257 goto error;
258 }
259 baseoffs = p - q;
260 q = p;
261 for (i = 0; i < nentries; i++) {
262 int pathlen, comlen, extra;
263
264 if ((q + ZIP_CENTRAL_HEADER_LEN) > (data + length)) {
265 goto error;
266 }
268 goto error;
269 }
273 q += pathlen + comlen + extra + ZIP_CENTRAL_HEADER_LEN;
274 }
275 zip = sqlite3_malloc(sizeof (zip_file) +
276 nentries * sizeof (unsigned char *));
277 if (!zip) {
278 goto error;
279 }
280#if defined(_WIN32) || defined(_WIN64)
281 zip->h = zip->mh = INVALID_HANDLE_VALUE;
282#endif
283 zip->length = length;
284 zip->data = data;
285 zip->baseoffs = baseoffs;
286 zip->nentries = nentries;
287 q = p;
288 for (i = 0; i < nentries; i++) {
289 int pathlen, comlen, extra;
290
291 if ((q + ZIP_CENTRAL_HEADER_LEN) > (data + length)) {
292 goto error;
293 }
295 goto error;
296 }
297 zip->entries[i] = q;
301 q += pathlen + comlen + extra + ZIP_CENTRAL_HEADER_LEN;
302 }
303 zip->entries[i] = 0;
304#if defined(_WIN32) || defined(_WIN64)
305 zip->h = h;
306 zip->mh = mh;
307#endif
308 return zip;
309error:
310 if (zip) {
311 sqlite3_free(zip);
312 }
313#if defined(_WIN32) || defined(_WIN64)
314 if (data) {
315 UnmapViewOfFile(data);
316 }
317 if (mh != INVALID_HANDLE_VALUE) {
318 CloseHandle(mh);
319 }
320 if (h != INVALID_HANDLE_VALUE) {
321 CloseHandle(h);
322 }
323#else
324 if (data != MAP_FAILED) {
325 munmap(data, length);
326 }
327 if (fd >= 0) {
328 close(fd);
329 }
330#endif
331 return 0;
332}
333
339static void
341{
342 if (zip) {
343#if defined(_WIN32) || defined(_WIN64)
344 if (zip->data) {
345 UnmapViewOfFile(zip->data);
346 }
347 if (zip->mh != INVALID_HANDLE_VALUE) {
348 CloseHandle(zip->mh);
349 }
350 if (zip->h != INVALID_HANDLE_VALUE) {
351 CloseHandle(zip->h);
352 }
353#else
354 if (zip->data) {
355 munmap(zip->data, zip->length);
356 }
357#endif
358 zip->length = 0;
359 zip->data = 0;
360 zip->nentries = 0;
361 sqlite3_free(zip);
362 }
363}
364
371static char *
372unquote(char const *in)
373{
374 char c, *ret;
375 int i;
376
377 ret = sqlite3_malloc(strlen(in) + 1);
378 if (ret) {
379 c = in[0];
380 if ((c == '"') || (c == '\'')) {
381 i = strlen(in + 1);
382 if ((i > 0) && (in[i] == c)) {
383 strcpy(ret, in + 1);
384 ret[i - 1] = '\0';
385 return ret;
386 }
387 }
388 strcpy(ret, in);
389 }
390 return ret;
391}
392
411static int
412zip_vtab_connect(sqlite3* db, void *aux, int argc, const char * const *argv,
413 sqlite3_vtab **vtabp, char **errp)
414{
415 zip_file *zip = 0;
416 int rc = SQLITE_ERROR;
417 char *filename;
418 zip_vtab *vtab;
419
420 if (argc < 4) {
421 *errp = sqlite3_mprintf("input file name missing");
422 return SQLITE_ERROR;
423 }
424 filename = unquote(argv[3]);
425 if (filename) {
426 zip = zip_open(filename);
427 sqlite3_free(filename);
428 }
429 if (!zip) {
430 *errp = sqlite3_mprintf("unable to open input file");
431 return rc;
432 }
433 vtab = sqlite3_malloc(sizeof(zip_vtab) + 6 +
434 strlen(argv[1]) + strlen(argv[2]));
435 if (!vtab) {
436 zip_close(zip);
437 *errp = sqlite3_mprintf("out of memory");
438 return rc;
439 }
440 memset(vtab, 0, sizeof (*vtab));
441 strcpy(vtab->tblname, "\"");
442 strcat(vtab->tblname, argv[1]);
443 strcat(vtab->tblname, "\".\"");
444 strcat(vtab->tblname, argv[2]);
445 strcat(vtab->tblname, "\"");
446 vtab->db = db;
447 vtab->zip = zip;
448 rc = sqlite3_declare_vtab(db, "CREATE TABLE x(path, comp, mtime, "
449 "crc32, length, data, clength, cdata, isdir)");
450 if (rc != SQLITE_OK) {
451 zip_close(zip);
452 sqlite3_free(vtab);
453 *errp = sqlite3_mprintf("table definition failed (error %d)", rc);
454 return rc;
455 }
456 *vtabp = &vtab->vtab;
457 *errp = 0;
458 return SQLITE_OK;
459}
460
472static int
473zip_vtab_create(sqlite3* db, void *aux, int argc,
474 const char *const *argv,
475 sqlite3_vtab **vtabp, char **errp)
476{
477 return zip_vtab_connect(db, aux, argc, argv, vtabp, errp);
478}
479
486static int
487zip_vtab_disconnect(sqlite3_vtab *vtab)
488{
489 zip_vtab *tab = (zip_vtab *) vtab;
490
491 zip_close(tab->zip);
492 sqlite3_free(tab);
493 return SQLITE_OK;
494}
495
502static int
503zip_vtab_destroy(sqlite3_vtab *vtab)
504{
505 return zip_vtab_disconnect(vtab);
506}
507
515static int
516zip_vtab_bestindex(sqlite3_vtab *vtab, sqlite3_index_info *info)
517{
518 zip_vtab *tab = (zip_vtab *) vtab;
519 int i;
520
521 info->idxNum = 0;
522 if (tab->sorted == 0) {
523 char *sql = 0;
524 unsigned char **entries = 0;
525 sqlite3_stmt *stmt = 0;
526 int rc, count, i;
527 size_t tmp;
528
529 /* perform sorting on 0th column (path, string) */
530 tab->sorted = -1;
531 entries = sqlite3_malloc(tab->zip->nentries * sizeof (entries));
532 sql = sqlite3_mprintf("SELECT rowid FROM %s ORDER BY path",
533 tab->tblname);
534 if (sql && entries) {
535 rc = sqlite3_prepare_v2(tab->db, sql, -1, &stmt, 0);
536 if ((rc == SQLITE_OK) && stmt) {
537 count = 0;
538 while (1) {
539 rc = sqlite3_step(stmt);
540 if (rc != SQLITE_ROW) {
541 break;
542 }
543 tmp = sqlite3_column_int(stmt, 0);
544 entries[count++] = (unsigned char *) tmp;
545 }
546 if ((rc == SQLITE_DONE) && (count == tab->zip->nentries)) {
547 for (i = 0; i < count; i++) {
548 tmp = (size_t) entries[i];
549 tmp = (size_t) tab->zip->entries[tmp];
550 entries[i] = (unsigned char *) tmp;
551 }
552 memcpy(tab->zip->entries, entries, i * sizeof (entries));
553 tab->sorted = 1;
554 }
555 }
556 }
557 if (stmt) {
558 sqlite3_finalize(stmt);
559 }
560 if (sql) {
561 sqlite3_free(sql);
562 }
563 if (entries) {
564 sqlite3_free(entries);
565 }
566 }
567 /* no optimization while table is being sorted or is unsorted */
568 if (tab->sorted != 1) {
569 return SQLITE_OK;
570 }
571 /* support EQ or simple MATCH constraint on 0th column (path) */
572 for (i = 0; i < info->nConstraint; i++) {
573 if (info->aConstraint[i].usable &&
574 (info->aConstraint[i].iColumn == 0)) {
575 if (info->aConstraint[i].op == SQLITE_INDEX_CONSTRAINT_EQ) {
576 info->idxNum = 1;
577 info->aConstraintUsage[i].argvIndex = 1;
578 info->aConstraintUsage[i].omit = 1;
579 info->estimatedCost = 1.0;
580 break;
581 } else if (info->aConstraint[i].op ==
582 SQLITE_INDEX_CONSTRAINT_MATCH) {
583 info->idxNum = 2;
584 info->aConstraintUsage[i].argvIndex = 1;
585 info->aConstraintUsage[i].omit = 1;
586 info->estimatedCost = 2.0;
587 break;
588 }
589 }
590 }
591 /* ORDER BY is ascending on 0th column (path) when table is sorted */
592 if (info->nOrderBy > 0) {
593 if ((info->aOrderBy[0].iColumn == 0) && !info->aOrderBy[0].desc) {
594 info->orderByConsumed = 1;
595 }
596 }
597 return SQLITE_OK;
598}
599
607static int
608zip_vtab_open(sqlite3_vtab *vtab, sqlite3_vtab_cursor **cursorp)
609{
610 zip_cursor *cur = sqlite3_malloc(sizeof(*cur));
611
612 if (!cur) {
613 return SQLITE_ERROR;
614 }
615 cur->cursor.pVtab = vtab;
616 cur->pos = -1;
617 cur->usematches = 0;
618 cur->nmatches = 0;
619 cur->matches = 0;
620 *cursorp = &cur->cursor;
621 return SQLITE_OK;
622}
623
630static int
631zip_vtab_close(sqlite3_vtab_cursor *cursor)
632{
633 zip_cursor *cur = (zip_cursor *) cursor;
634
635 if (cur->matches) {
636 sqlite3_free(cur->matches);
637 }
638 sqlite3_free(cur);
639 return SQLITE_OK;
640}
641
648static int
649zip_vtab_next(sqlite3_vtab_cursor *cursor)
650{
651 zip_cursor *cur = (zip_cursor *) cursor;
652
653 if (cur->nmatches >= 0) {
654 cur->pos++;
655 }
656 return SQLITE_OK;
657}
658
669static int
670zip_vtab_filter(sqlite3_vtab_cursor *cursor, int idxNum,
671 const char *idxStr, int argc, sqlite3_value **argv)
672{
673 zip_cursor *cur = (zip_cursor *) cursor;
674 zip_vtab *tab = (zip_vtab *) cur->cursor.pVtab;
675
676 if (cur->matches) {
677 sqlite3_free(cur->matches);
678 cur->matches = 0;
679 }
680 cur->usematches = 0;
681 cur->nmatches = 0;
682 /* if EQ or MATCH constraint is active, add match array to cursor */
683 if (idxNum && (argc > 0)) {
684 int i, k, d, found, leneq, len;
685 unsigned char *eq;
686
687 eq = (unsigned char *) sqlite3_value_text(argv[0]);
688 if (!eq) {
689 cur->nmatches = -1;
690 goto done;
691 }
692 if (idxNum > 1) {
693 unsigned char *p = (unsigned char *) strrchr((char *) eq, '*');
694
695 if (!p || (p[1] != '\0')) {
696 return SQLITE_ERROR;
697 }
698 leneq = p - eq;
699 } else {
700 leneq = sqlite3_value_bytes(argv[0]);
701 if (leneq == 0) {
702 cur->nmatches = -1;
703 goto done;
704 }
705 }
706 cur->matches = sqlite3_malloc(tab->zip->nentries * sizeof (int));
707 if (!cur->matches) {
708 return SQLITE_NOMEM;
709 }
710 cur->usematches = 1;
711 memset(cur->matches, 0, tab->zip->nentries * sizeof (int));
712 for (k = found = 0; k < tab->zip->nentries; k++) {
713 len = zip_read_short(tab->zip->entries[k] +
715 if (idxNum > 1) {
716 if (len < leneq) {
717 continue;
718 }
719 } else if (len != leneq) {
720 if (found) {
721 break;
722 }
723 continue;
724 }
725 d = memcmp(tab->zip->entries[k] + ZIP_CENTRAL_HEADER_LEN,
726 eq, leneq);
727 if (d == 0) {
728 found++;
729 cur->matches[k] = 1;
730 } else if (d > 0) {
731 break;
732 }
733 }
734 for (i = k = 0; i < tab->zip->nentries; i++) {
735 if (cur->matches[i]) {
736 cur->matches[k++] = i;
737 }
738 }
739 cur->nmatches = k;
740 }
741done:
742 cur->pos = -1;
743 return zip_vtab_next(cursor);
744}
745
752static int
753zip_vtab_eof(sqlite3_vtab_cursor *cursor)
754{
755 zip_cursor *cur = (zip_cursor *) cursor;
756 zip_vtab *tab = (zip_vtab *) cur->cursor.pVtab;
757
758 if (cur->nmatches < 0) {
759 return 1;
760 }
761 if (cur->usematches) {
762 return cur->pos >= cur->nmatches;
763 }
764 return cur->pos >= tab->zip->nentries;
765}
766
775static int
776zip_vtab_column(sqlite3_vtab_cursor *cursor, sqlite3_context *ctx, int n)
777{
778 zip_cursor *cur = (zip_cursor *) cursor;
779 zip_vtab *tab = (zip_vtab *) cur->cursor.pVtab;
780 unsigned char *data = 0;
781 unsigned char *dest = 0;
782 int length;
783
784 if (cur->usematches) {
785 int pos;
786
787 if ((cur->pos < 0) || (cur->pos >= cur->nmatches)) {
788 sqlite3_result_error(ctx, "out of bounds", -1);
789 return SQLITE_ERROR;
790 }
791 pos = cur->matches[cur->pos];
792 data = tab->zip->entries[pos];
793 } else {
794 if ((cur->pos < 0) || (cur->pos >= tab->zip->nentries)) {
795 sqlite3_result_error(ctx, "out of bounds", -1);
796 return SQLITE_ERROR;
797 }
798 data = tab->zip->entries[cur->pos];
799 }
800 switch (n) {
801 case 0: /* "path": pathname */
804 sqlite3_result_text(ctx, (char *) data, length, SQLITE_TRANSIENT);
805 return SQLITE_OK;
806 case 1: /* "comp": compression method */
808 sqlite3_result_int(ctx, length);
809 return SQLITE_OK;
810 case 2: /* "mtime": modification time/date */
811 {
812 int time = zip_read_short(data + ZIP_CENTRAL_MTIME_OFFS);
813 int date = zip_read_short(data + ZIP_CENTRAL_MDATE_OFFS);
814 char mtbuf[64];
815
816 sprintf(mtbuf, "%04d-%02d-%02d %02d:%02d:%02d",
817 (date >> 9) + 1980, (date >> 5) & 0xf, date & 0x1f,
818 time >> 11, (time >> 5) & 0x3f, (time & 0x1f) << 1);
819 sqlite3_result_text(ctx, mtbuf, -1, SQLITE_TRANSIENT);
820 return SQLITE_OK;
821 }
822 case 3: /* "crc32": CRC32 of uncompress data */
823 length = zip_read_int(data + ZIP_CENTRAL_CRC32_OFFS);
824 sqlite3_result_int(ctx, length);
825 return SQLITE_OK;
826 case 4: /* "length": uncompress length of data */
828 sqlite3_result_int(ctx, length);
829 return SQLITE_OK;
830 case 5: /* "data": uncompressed data */
831 {
832 int clength, offs, extra, pathlen, cmeth;
833
834 offs = tab->zip->baseoffs +
836 if ((offs + ZIP_LOCAL_HEADER_LEN) > tab->zip->length) {
837 goto donull;
838 }
839 extra = zip_read_short(tab->zip->data + offs +
841 pathlen = zip_read_short(tab->zip->data + offs +
844 clength = zip_read_int(data + ZIP_CENTRAL_COMPLEN_OFFS);
846 offs += ZIP_LOCAL_HEADER_LEN + pathlen + extra;
847 if ((offs + clength) > tab->zip->length) {
848 goto donull;
849 }
850 data = tab->zip->data + offs;
851 if (cmeth == ZIP_COMPMETH_STORED) {
852 sqlite3_result_blob(ctx, data, clength, SQLITE_TRANSIENT);
853 return SQLITE_OK;
854 } else if (cmeth == ZIP_COMPMETH_DEFLATED) {
855 z_stream stream;
856 int err;
857
858 stream.zalloc = Z_NULL;
859 stream.zfree = Z_NULL;
860 stream.next_in = data;
861 stream.avail_in = clength;
862 stream.next_out = dest = sqlite3_malloc(length);
863 stream.avail_out = length;
864 stream.opaque = 0;
865 if (!dest) {
866 goto donull;
867 }
868 if (inflateInit2(&stream, -15) != Z_OK) {
869 goto donull;
870 }
871 err = inflate(&stream, Z_SYNC_FLUSH);
872 inflateEnd(&stream);
873 if ((err == Z_STREAM_END) ||
874 ((err == Z_OK) && (stream.avail_in == 0))) {
875 sqlite3_result_blob(ctx, dest, length, sqlite3_free);
876 return SQLITE_OK;
877 }
878 }
879 donull:
880 if (dest) {
881 sqlite3_free(dest);
882 }
883 sqlite3_result_null(ctx);
884 return SQLITE_OK;
885 }
886 case 6: /* "clength": compressed length */
887 length = zip_read_int(data + ZIP_CENTRAL_COMPLEN_OFFS);
888 sqlite3_result_int(ctx, length);
889 return SQLITE_OK;
890 case 7: /* "cdata": raw data */
891 {
892 int clength, offs, extra, pathlen;
893
894 offs = tab->zip->baseoffs +
896 if ((offs + ZIP_LOCAL_HEADER_LEN) > tab->zip->length) {
897 goto donull;
898 }
899 extra = zip_read_short(tab->zip->data + offs +
901 pathlen = zip_read_short(tab->zip->data + offs +
904 clength = zip_read_int(data + ZIP_CENTRAL_COMPLEN_OFFS);
905 offs += ZIP_LOCAL_HEADER_LEN + pathlen + extra;
906 if ((offs + clength) > tab->zip->length) {
907 goto donull;
908 }
909 data = tab->zip->data + offs;
910 sqlite3_result_blob(ctx, data, clength, SQLITE_TRANSIENT);
911 return SQLITE_OK;
912 }
913 case 8: /* "isdir": directory indicator */
916 sqlite3_result_int(ctx, (length > 0 && data[length - 1] == '/'));
917 return SQLITE_OK;
918 }
919 sqlite3_result_error(ctx, "invalid column number", -1);
920 return SQLITE_ERROR;
921}
922
930static int
931zip_vtab_rowid(sqlite3_vtab_cursor *cursor, sqlite_int64 *rowidp)
932{
933 zip_cursor *cur = (zip_cursor *) cursor;
934
935 if (cur->nmatches < 0) {
936 *rowidp = -1;
937 } else if ((cur->pos >= 0) && (cur->usematches > 0)) {
938 if (cur->pos < cur->nmatches) {
939 *rowidp = cur->matches[cur->pos];
940 } else {
941 *rowidp = -1;
942 }
943 } else {
944 *rowidp = cur->pos;
945 }
946 return SQLITE_OK;
947}
948
956static void
957zip_vtab_matchfunc(sqlite3_context *ctx, int argc, sqlite3_value **argv)
958{
959 int ret = 0;
960
961 if (argc == 2) {
962 unsigned char *q = (unsigned char *) sqlite3_value_text(argv[0]);
963 unsigned char *p = (unsigned char *) sqlite3_value_text(argv[1]);
964
965 if (p && q) {
966 unsigned char *eq = (unsigned char *) strrchr((char *) q, '*');
967 int lenq, lenp;
968
969 if (eq && (eq[1] == '\0')) {
970 lenq = eq - q;
971 if (lenq) {
972 lenp = strlen((char *) p);
973 if ((lenp >= lenq) && !memcmp(p, q, lenq)) {
974 ret = 1;
975 }
976 }
977 }
978 }
979 }
980 sqlite3_result_int(ctx, ret);
981}
982
993static int
994zip_vtab_findfunc(sqlite3_vtab *vtab, int narg, const char *name,
995 void (**pfunc)(sqlite3_context *, int, sqlite3_value **),
996 void **parg)
997{
998 if ((narg == 2) && !strcmp(name, "match")) {
999 *pfunc = zip_vtab_matchfunc;
1000 *parg = 0;
1001 return 1;
1002 }
1003 return 0;
1004}
1005
1006#if (SQLITE_VERSION_NUMBER > 3004000)
1007
1014static int
1015zip_vtab_rename(sqlite3_vtab *vtab, const char *newname)
1016{
1017 return SQLITE_OK;
1018}
1019
1020#endif
1021
1026static const sqlite3_module zip_vtab_mod = {
1027 1, /* iVersion */
1028 zip_vtab_create, /* xCreate */
1029 zip_vtab_connect, /* xConnect */
1030 zip_vtab_bestindex, /* xBestIndex */
1031 zip_vtab_disconnect, /* xDisconnect */
1032 zip_vtab_destroy, /* xDestroy */
1033 zip_vtab_open, /* xOpen */
1034 zip_vtab_close, /* xClose */
1035 zip_vtab_filter, /* xFilter */
1036 zip_vtab_next, /* xNext */
1037 zip_vtab_eof, /* xEof */
1038 zip_vtab_column, /* xColumn */
1039 zip_vtab_rowid, /* xRowid */
1040 0, /* xUpdate */
1041 0, /* xBegin */
1042 0, /* xSync */
1043 0, /* xCommit */
1044 0, /* xRollback */
1045 zip_vtab_findfunc, /* xFindFunction */
1046#if (SQLITE_VERSION_NUMBER > 3004000)
1047 zip_vtab_rename, /* xRename */
1048#endif
1049};
1050
1058static void
1059zip_crc32_func(sqlite3_context *ctx, int argc, sqlite3_value **argv)
1060{
1061 int crc, length;
1062 unsigned char *data;
1063
1064 if (argc != 1) {
1065 sqlite3_result_error(ctx, "need one argument", -1);
1066 }
1067 data = (unsigned char *) sqlite3_value_blob(argv[0]);
1068 length = sqlite3_value_bytes(argv[0]);
1069 crc = crc32(0, 0, 0);
1070 if (data && (length > 0)) {
1071 crc = crc32(crc, data, length);
1072 }
1073 sqlite3_result_int(ctx, crc);
1074}
1075
1083static void
1084zip_inflate_func(sqlite3_context *ctx, int argc, sqlite3_value **argv)
1085{
1086 int err, length, dlength, avail;
1087 unsigned char *data, *dest, *newdest;
1088 z_stream stream;
1089
1090 if (argc != 1) {
1091 sqlite3_result_error(ctx, "need one argument", -1);
1092 return;
1093 }
1094 data = (unsigned char *) sqlite3_value_blob(argv[0]);
1095 length = sqlite3_value_bytes(argv[0]);
1096 stream.zalloc = Z_NULL;
1097 stream.zfree = Z_NULL;
1098 stream.next_in = data;
1099 stream.avail_in = length;
1100 avail = length;
1101 stream.next_out = dest = sqlite3_malloc(avail);
1102 stream.avail_out = avail;
1103 stream.opaque = 0;
1104 if (!dest) {
1105 goto oom;
1106 }
1107 if (inflateInit2(&stream, -15) != Z_OK) {
1108 goto nomem;
1109 }
1110 dlength = 0;
1111 while (1) {
1112 err = inflate(&stream, Z_SYNC_FLUSH);
1113 if ((err == Z_STREAM_END) ||
1114 ((err == Z_OK) && (stream.avail_in == 0))) {
1115 dlength += length - stream.avail_out;
1116 newdest = sqlite3_realloc(dest, dlength);
1117 inflateEnd(&stream);
1118 if (!newdest) {
1119nomem:
1120 if (dest) {
1121 sqlite3_free(dest);
1122 }
1123oom:
1124 sqlite3_result_error_nomem(ctx);
1125 return;
1126 }
1127 sqlite3_result_blob(ctx, newdest, dlength, sqlite3_free);
1128 return;
1129 }
1130 if ((err == Z_BUF_ERROR) || (err == Z_OK)) {
1131 newdest = sqlite3_realloc(dest, avail + length);
1132 dlength += length - stream.avail_out;
1133 if (!newdest) {
1134 inflateEnd(&stream);
1135 goto nomem;
1136 }
1137 avail += length;
1138 stream.next_out = newdest + (stream.next_out - dest);
1139 dest = newdest;
1140 stream.avail_out += length;
1141 } else {
1142 inflateEnd(&stream);
1143 sqlite3_free(dest);
1144 sqlite3_result_error(ctx, "inflate error", -1);
1145 return;
1146 }
1147 }
1148}
1149
1157static void
1158zip_deflate_func(sqlite3_context *ctx, int argc, sqlite3_value **argv)
1159{
1160 int err, level = 9;
1161 unsigned long avail, length;
1162 unsigned char *data, *dest = 0;
1163 z_stream stream;
1164
1165 if ((argc < 1) || (argc > 2)) {
1166 sqlite3_result_error(ctx, "need one or two arguments", -1);
1167 return;
1168 }
1169 if (argc > 1) {
1170 level = sqlite3_value_int(argv[1]);
1171 }
1172 data = (unsigned char *) sqlite3_value_blob(argv[0]);
1173 length = sqlite3_value_bytes(argv[0]);
1174 stream.zalloc = Z_NULL;
1175 stream.zfree = Z_NULL;
1176 stream.next_in = data;
1177 stream.avail_in = length;
1178 stream.next_out = 0;
1179 stream.avail_out = 0;
1180 stream.opaque = 0;
1181 if (deflateInit2(&stream, level, Z_DEFLATED, -15, 8,
1182 Z_DEFAULT_STRATEGY) != Z_OK) {
1183 goto deflerr;
1184 }
1185 avail = deflateBound(&stream, length);
1186 if (avail == 0) {
1187 sqlite3_result_null(ctx);
1188 return;
1189 }
1190 stream.next_out = dest = sqlite3_malloc(avail);
1191 stream.avail_out = avail;
1192 if (!dest) {
1193 sqlite3_result_error_nomem(ctx);
1194 return;
1195 }
1196 err = deflate(&stream, Z_FINISH);
1197 if (err != Z_STREAM_END) {
1198 deflateEnd(&stream);
1199deflerr:
1200 if (dest) {
1201 sqlite3_free(dest);
1202 }
1203 sqlite3_result_error(ctx, "deflate error", -1);
1204 return;
1205 }
1206 length = stream.total_out;
1207 err = deflateEnd(&stream);
1208 if (err != Z_OK) {
1209 goto deflerr;
1210 }
1211 sqlite3_result_blob(ctx, dest, length, sqlite3_free);
1212}
1213
1221static void
1222zip_compress_func(sqlite3_context *ctx, int argc, sqlite3_value **argv)
1223{
1224 int err, level = 9;
1225 unsigned long length, dlength;
1226 unsigned char *data, *dest;
1227
1228 if ((argc < 1) || (argc > 2)) {
1229 sqlite3_result_error(ctx, "need one or two arguments", -1);
1230 return;
1231 }
1232 if (argc > 1) {
1233 level = sqlite3_value_int(argv[1]);
1234 }
1235 data = (unsigned char *) sqlite3_value_blob(argv[0]);
1236 length = sqlite3_value_bytes(argv[0]);
1237 dlength = compressBound(length);
1238 dest = sqlite3_malloc(dlength);
1239 if (!dest) {
1240 sqlite3_result_error_nomem(ctx);
1241 return;
1242 }
1243 err = compress2(dest, &dlength, data, length, level);
1244 if (err == Z_OK) {
1245 sqlite3_result_blob(ctx, dest, dlength, sqlite3_free);
1246 return;
1247 }
1248 if (err == Z_MEM_ERROR) {
1249 sqlite3_result_error(ctx, "memory error", -1);
1250 } else if (err == Z_BUF_ERROR) {
1251 sqlite3_result_error(ctx, "buffer error", -1);
1252 } else {
1253 sqlite3_result_error(ctx, "compress error", -1);
1254 }
1255 sqlite3_free(dest);
1256}
1257
1258#ifdef SQLITE_OPEN_URI
1259
1267static mem_blk *
1268mem_createmb(const unsigned char *data, unsigned long length)
1269{
1270 mem_blk *mb;
1271#if defined(_WIN32) || defined(_WIN64)
1272 HANDLE mh;
1273#else
1274 long psize;
1275#endif
1276 unsigned long size;
1277
1278#if defined(_WIN32) || defined(_WIN64)
1279 size = sizeof (mem_blk) + length;
1280 mh = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE,
1281 0, size, 0);
1282 if (mh == INVALID_HANDLE_VALUE) {
1283 return 0;
1284 }
1285 mb = (mem_blk *) MapViewOfFile(mh, FILE_MAP_ALL_ACCESS, 0, 0, length);
1286 if (!mb) {
1287 return 0;
1288 }
1289#else
1290 psize = sysconf(_SC_PAGESIZE);
1291#ifdef linux
1292 mb = (mem_blk *) sqlite3_malloc(sizeof (mem_blk));
1293 if (!mb) {
1294 return 0;
1295 }
1296 size = length + 1;
1297 mb->data = (unsigned char *) mmap(0, size, PROT_READ | PROT_WRITE,
1298 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
1299 if (mb->data == MAP_FAILED) {
1300 sqlite3_free(mb);
1301 return 0;
1302 }
1303#else
1304 size = sizeof (mem_blk) + psize + length + 1;
1305 mb = (mem_blk *) mmap(0, size, PROT_READ | PROT_WRITE,
1306 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
1307 if (mb == MAP_FAILED) {
1308 return 0;
1309 }
1310#endif
1311#endif
1312 if (mb) {
1313 memcpy(mb->magic, MEM_MAGIC, 4);
1314 mb->opened = 1;
1315 mb->size = size;
1316 mb->length = length;
1317#if defined(_WIN32) || defined(_WIN64)
1318 mb->mh = mh;
1319 mb->data = (unsigned char *) (mb + 1);
1320 memcpy(mb->data, data, length);
1321#else
1322 mb->psize = psize;
1323#ifdef linux
1324 mb->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
1325 sqlite3_mutex_enter(mb->mutex);
1326 mb->lcnt = 0;
1327 memcpy(mb->data, data, length);
1328#else
1329 if (psize >= sizeof (mem_blk)) {
1330 mb->data = (unsigned char *) mb + psize;
1331 memcpy(mb->data, data, length);
1332#ifndef linux
1333 mprotect(mb->data, length, PROT_READ);
1334#endif
1335 } else {
1336 mb->data = (unsigned char *) (mb + 1);
1337 memcpy(mb->data, data, length);
1338 }
1339#endif
1340#endif
1341 }
1342 return mb;
1343}
1344
1350static void
1351mem_destroymb(mem_blk *mb)
1352{
1353#if defined(_WIN32) || defined(_WIN64)
1354 HANDLE mh;
1355#endif
1356
1357 if (mb) {
1358 memset(mb->magic, 0, 4);
1359#if defined(_WIN32) || defined(_WIN64)
1360 mh = mb->mh;
1361 UnmapViewOfFile(mb);
1362 CloseHandle(mh);
1363#else
1364#ifdef linux
1365 munmap(mb->data, mb->size);
1366 sqlite3_mutex_leave(mb->mutex);
1367 sqlite3_mutex_free(mb->mutex);
1368 sqlite3_free(mb);
1369#else
1370 munmap(mb, mb->size);
1371#endif
1372#endif
1373 }
1374}
1375
1382static int
1383mem_close(sqlite3_file *file)
1384{
1385 mem_file *mf = (mem_file *) file;
1386 mem_blk *mb = mf->mb;
1387
1388 if (mb) {
1389#ifdef linux
1390 sqlite3_mutex_enter(mb->mutex);
1391 if (mf->lock > 0) {
1392 mb->lcnt = 0;
1393 }
1394#endif
1395 mb->opened--;
1396 if (mb->opened <= 0) {
1397 mem_destroymb(mb);
1398 }
1399#ifdef linux
1400 else {
1401 sqlite3_mutex_leave(mb->mutex);
1402 }
1403#endif
1404 mf->mb = 0;
1405 }
1406 return SQLITE_OK;
1407}
1408
1418static int
1419mem_read(sqlite3_file *file, void *buf, int len, sqlite_int64 offs)
1420{
1421 mem_file *mf = (mem_file *) file;
1422 mem_blk *mb = mf->mb;
1423 int rc = SQLITE_IOERR_READ;
1424
1425#ifdef linux
1426 if (mb) {
1427 sqlite3_mutex_enter(mb->mutex);
1428 }
1429#endif
1430 if (mb && (offs <= mb->length)) {
1431 rc = SQLITE_OK;
1432 if (offs + len > mb->length) {
1433 rc = SQLITE_IOERR_SHORT_READ;
1434 len = mb->length - offs;
1435 }
1436 memcpy(buf, mb->data + offs, len);
1437 }
1438#ifdef linux
1439 if (mb) {
1440 sqlite3_mutex_leave(mb->mutex);
1441 }
1442#endif
1443 return rc;
1444}
1445
1453static int
1454#ifdef linux
1455mem_truncate_unlocked(sqlite3_file *file, sqlite_int64 offs)
1456#else
1457mem_truncate(sqlite3_file *file, sqlite_int64 offs)
1458#endif
1459{
1460#ifdef linux
1461 mem_file *mf = (mem_file *) file;
1462 mem_blk *mb = mf->mb;
1463 unsigned char *p;
1464 long psize = mb->psize;
1465 unsigned long length = offs;
1466 unsigned long size;
1467
1468 size = length + 1;
1469 if ((psize > 0) && (size / psize == mb->size / psize)) {
1470 p = mb->data;
1471 } else {
1472 p = mremap(mb->data, mb->size, size, MREMAP_MAYMOVE);
1473 }
1474 if (p == MAP_FAILED) {
1475 return SQLITE_IOERR_TRUNCATE;
1476 }
1477 mb->size = size;
1478 mb->length = length;
1479 mb->data = p;
1480 return SQLITE_OK;
1481#else
1482 return SQLITE_IOERR_TRUNCATE;
1483#endif
1484}
1485
1486#ifdef linux
1487static int
1488mem_truncate(sqlite3_file *file, sqlite_int64 offs)
1489{
1490 mem_file *mf = (mem_file *) file;
1491 mem_blk *mb = mf->mb;
1492 int rc = SQLITE_IOERR_TRUNCATE;
1493
1494 if (mb) {
1495 sqlite3_mutex_enter(mb->mutex);
1496 rc = mem_truncate_unlocked(file, offs);
1497 sqlite3_mutex_leave(mb->mutex);
1498 }
1499 return rc;
1500}
1501#endif
1502
1512static int
1513mem_write(sqlite3_file *file, const void *buf, int len, sqlite_int64 offs)
1514{
1515#ifdef linux
1516 mem_file *mf = (mem_file *) file;
1517 mem_blk *mb = mf->mb;
1518
1519 sqlite3_mutex_enter(mb->mutex);
1520 if (offs + len > mb->length) {
1521 if (mem_truncate_unlocked(file, offs + len) != SQLITE_OK) {
1522 sqlite3_mutex_leave(mb->mutex);
1523 return SQLITE_IOERR_WRITE;
1524 }
1525 }
1526 memcpy(mb->data + offs, buf, len);
1527 sqlite3_mutex_leave(mb->mutex);
1528 return SQLITE_OK;
1529#else
1530 return SQLITE_IOERR_WRITE;
1531#endif
1532}
1533
1541static int
1542mem_sync(sqlite3_file *file, int flags)
1543{
1544#ifdef linux
1545 return SQLITE_OK;
1546#else
1547 return SQLITE_IOERR_FSYNC;
1548#endif
1549}
1550
1558static int
1559mem_filesize(sqlite3_file *file, sqlite_int64 *size)
1560{
1561 mem_file *mf = (mem_file *) file;
1562 mem_blk *mb = mf->mb;
1563
1564 if (mb) {
1565#ifdef linux
1566 sqlite3_mutex_enter(mb->mutex);
1567#endif
1568 *size = mb->length;
1569#ifdef linux
1570 sqlite3_mutex_leave(mb->mutex);
1571#endif
1572 return SQLITE_OK;
1573 }
1574 return SQLITE_IOERR_FSTAT;
1575}
1576
1584static int
1585mem_lock(sqlite3_file *file, int lck)
1586{
1587#ifdef linux
1588 mem_file *mf = (mem_file *) file;
1589 mem_blk *mb = mf->mb;
1590 int rc = SQLITE_IOERR_LOCK;
1591
1592 if (mb) {
1593 sqlite3_mutex_enter(mb->mutex);
1594 if (lck > 0) {
1595 rc = SQLITE_BUSY;
1596 if ((mf->lock == 0) && (mb->lcnt == 0)) {
1597 mb->lcnt = 1;
1598 mf->lock = lck;
1599 rc = SQLITE_OK;
1600 } else if ((mf->lock > 0) && (mb->lcnt == 1)) {
1601 mf->lock = lck;
1602 rc = SQLITE_OK;
1603 }
1604 }
1605 sqlite3_mutex_leave(mb->mutex);
1606 }
1607 return rc;
1608#else
1609 return SQLITE_OK;
1610#endif
1611}
1612
1620static int
1621mem_unlock(sqlite3_file *file, int lck)
1622{
1623#ifdef linux
1624 mem_file *mf = (mem_file *) file;
1625 mem_blk *mb = mf->mb;
1626 int rc = SQLITE_IOERR_UNLOCK;
1627
1628 if (mb) {
1629 sqlite3_mutex_enter(mb->mutex);
1630 if (mf->lock == lck) {
1631 rc = SQLITE_OK;
1632 } else if (lck == 0) {
1633 if (mf->lock) {
1634 mb->lcnt = 0;
1635 mf->lock = 0;
1636 }
1637 rc = SQLITE_OK;
1638 } else if ((lck < mf->lock) && (mb->lcnt != 0)) {
1639 mf->lock = lck;
1640 rc = SQLITE_OK;
1641 }
1642 sqlite3_mutex_leave(mb->mutex);
1643 }
1644 return rc;
1645#else
1646 return SQLITE_OK;
1647#endif
1648}
1649
1657static int
1658mem_checkreservedlock(sqlite3_file *file, int *out)
1659{
1660#ifdef linux
1661 mem_file *mf = (mem_file *) file;
1662 mem_blk *mb = mf->mb;
1663 int rc = SQLITE_IOERR_CHECKRESERVEDLOCK;
1664
1665 if (mb) {
1666 sqlite3_mutex_enter(mb->mutex);
1667 *out = mf->lock >= 2;
1668 sqlite3_mutex_leave(mb->mutex);
1669 rc = SQLITE_OK;
1670 } else {
1671 *out = 0;
1672 }
1673 return rc;
1674#else
1675 *out = 0;
1676 return SQLITE_OK;
1677#endif
1678}
1679
1688static int
1689mem_filecontrol(sqlite3_file *file, int op, void *arg)
1690{
1691#ifdef SQLITE_FCNTL_PRAGMA
1692 if (op == SQLITE_FCNTL_PRAGMA) {
1693 return SQLITE_NOTFOUND;
1694 }
1695#endif
1696 return SQLITE_OK;
1697}
1698
1705static int
1706mem_sectorsize(sqlite3_file *file)
1707{
1708 return 4096;
1709}
1710
1717static int
1718mem_devicecharacteristics(sqlite3_file *file)
1719{
1720 return 0;
1721}
1722
1727static sqlite3_io_methods mem_methods = {
1728 1, /* iVersion */
1729 mem_close, /* xClose */
1730 mem_read, /* xRead */
1731 mem_write, /* xWrite */
1732 mem_truncate, /* xTruncate */
1733 mem_sync, /* xSync */
1734 mem_filesize, /* xFileSize */
1735 mem_lock, /* xLock */
1736 mem_unlock, /* xUnlock */
1737 mem_checkreservedlock, /* xCheckReservedLock */
1738 mem_filecontrol, /* xFileControl */
1739 mem_sectorsize, /* xSectorSize */
1740 mem_devicecharacteristics /* xDeviceCharacteristics */
1741};
1742
1753static int
1754mem_open(sqlite3_vfs *vfs, const char *name, sqlite3_file *file,
1755 int flags, int *outflags)
1756{
1757 mem_file *mf = (mem_file *) file;
1758 mem_blk *mb = 0;
1759#ifdef _WIN64
1760 unsigned long long t = 0;
1761#else
1762 unsigned long t = 0;
1763#endif
1764#if !defined(_WIN32) && !defined(_WIN64)
1765 mem_blk mb0;
1766 int pfd[2];
1767 int n;
1768#endif
1769
1770 if (!name) {
1771 return SQLITE_IOERR;
1772 }
1773 if (flags & (SQLITE_OPEN_MAIN_JOURNAL |
1774 SQLITE_OPEN_WAL |
1775#ifndef linux
1776 SQLITE_OPEN_READWRITE |
1777#endif
1778 SQLITE_OPEN_CREATE)) {
1779 return SQLITE_CANTOPEN;
1780 }
1781#ifdef _WIN64
1782 sscanf(name + 1, "%I64x", &t);
1783#else
1784 t = strtoul(name + 1, 0, 16);
1785#endif
1786 mb = (mem_blk *) t;
1787 if (!mb) {
1788 return SQLITE_CANTOPEN;
1789 }
1790#if !defined(_WIN32) && !defined(_WIN64)
1791 if (pipe(pfd) < 0) {
1792 return SQLITE_CANTOPEN;
1793 }
1794 n = (write(pfd[1], (char *) mb, sizeof (mem_blk)) < 0) ? errno : 0;
1795 if (n == EFAULT) {
1796cantopen:
1797 close(pfd[0]);
1798 close(pfd[1]);
1799 return SQLITE_CANTOPEN;
1800 }
1801 n = read(pfd[0], (char *) &mb0, sizeof (mem_blk));
1802 if (n != sizeof (mem_blk)) {
1803 goto cantopen;
1804 }
1805 if (memcmp(mb0.magic, MEM_MAGIC, 4) == 0) {
1806#ifdef linux
1807 n = (write(pfd[1], (char *) mb0.data, 1) < 0) ? errno : 0;
1808 if (n == EFAULT) {
1809 goto cantopen;
1810 }
1811#endif
1812 if (mb0.length > 0) {
1813 n = (write(pfd[1], (char *) mb0.data + mb0.length - 1, 1) < 0)
1814 ? errno : 0;
1815 if (n == EFAULT) {
1816 goto cantopen;
1817 }
1818 }
1819 close(pfd[0]);
1820 close(pfd[1]);
1821#ifdef linux
1822 sqlite3_mutex_enter(mb->mutex);
1823#endif
1824 mb->opened++;
1825#ifdef linux
1826 sqlite3_mutex_leave(mb->mutex);
1827#endif
1828 } else {
1829 goto cantopen;
1830 }
1831#else
1832 if (memcmp(mb->magic, MEM_MAGIC, 4) == 0) {
1833 mb->opened++;
1834 } else {
1835 return SQLITE_CANTOPEN;
1836 }
1837#endif
1838 memset(mf, 0, sizeof (mem_file));
1839 mf->mb = mb;
1840 mf->base.pMethods = &mem_methods;
1841 if (outflags) {
1842 *outflags = flags;
1843 }
1844 return SQLITE_OK;
1845}
1846
1855static int
1856mem_delete(sqlite3_vfs *vfs, const char *name, int sync)
1857{
1858 return SQLITE_IOERR_DELETE;
1859}
1860
1870static int
1871mem_access(sqlite3_vfs *vfs, const char *name, int flags, int *outflags)
1872{
1873 char *endp = 0;
1874 unsigned long t;
1875
1876 t = strtol(name + 1, &endp, 16);
1877 if ((t == 0) ||
1878#ifndef linux
1879 (flags == SQLITE_ACCESS_READWRITE) ||
1880#endif
1881 !endp || endp[0]) {
1882 *outflags = 0;
1883 } else {
1884 *outflags = 1;
1885 }
1886 return SQLITE_OK;
1887}
1888
1898static int
1899mem_fullpathname(sqlite3_vfs *vfs, const char *name, int len, char *out)
1900{
1901 strncpy(out, name, len);
1902 out[len - 1] = '\0';
1903 return SQLITE_OK;
1904}
1905
1913static void *
1914mem_dlopen(sqlite3_vfs *vfs, const char *name)
1915{
1916 return 0;
1917}
1918
1926static void
1927mem_dlerror(sqlite3_vfs *vfs, int len, char *out)
1928{
1929 static const char *errtxt = "Loadable extensions are not supported";
1930
1931 strncpy(out, errtxt, strlen(errtxt));
1932 out[len - 1] = '\0';
1933}
1934
1943static void
1944(*mem_dlsym(sqlite3_vfs *vfs, void *handle, const char *sym))(void)
1945{
1946 return 0;
1947}
1948
1955static void
1956mem_dlclose(sqlite3_vfs *vfs, void *handle)
1957{
1958}
1959
1968static int
1969mem_randomness(sqlite3_vfs *vfs, int len, char *out)
1970{
1971 sqlite3_vfs *ovfs = (sqlite3_vfs *) vfs->pAppData;
1972
1973 return ovfs->xRandomness(ovfs, len, out);
1974}
1975
1983static int
1984mem_sleep(sqlite3_vfs *vfs, int micro)
1985{
1986 sqlite3_vfs *ovfs = (sqlite3_vfs *) vfs->pAppData;
1987
1988 return ovfs->xSleep(ovfs, micro);
1989}
1990
1998static int
1999mem_currenttime(sqlite3_vfs *vfs, double *out)
2000{
2001 sqlite3_vfs *ovfs = (sqlite3_vfs *) vfs->pAppData;
2002
2003 return ovfs->xCurrentTime(ovfs, out);
2004}
2005
2010static sqlite3_vfs mem_vfs = {
2011 1, /* iVersion */
2012 sizeof (mem_file), /* szOsFile */
2013 256, /* mxPathname */
2014 0, /* pNext */
2015 mem_vfs_name, /* zName */
2016 0, /* pAppData */
2017 mem_open, /* xOpen */
2018 mem_delete, /* xDelete */
2019 mem_access, /* xAccess */
2020 mem_fullpathname, /* xFullPathname */
2021 mem_dlopen, /* xDlOpen */
2022 mem_dlerror, /* xDlError */
2023 mem_dlsym, /* xDlSym */
2024 mem_dlclose, /* xDlClose */
2025 mem_randomness, /* xDlError */
2026 mem_sleep, /* xDlSym */
2027 mem_currenttime /* xDlClose */
2028};
2029
2054static void
2055blob_attach_func(sqlite3_context *ctx, int argc, sqlite3_value **argv)
2056{
2057 unsigned long length;
2058 const unsigned char *data;
2059 mem_blk *mb = 0;
2060 char *sql = 0;
2061 int sqllen = 0;
2062#ifdef linux
2063 int isrw = 0;
2064#endif
2065
2066 if (argc != 2) {
2067 sqlite3_result_error(ctx, "need two arguments", -1);
2068 return;
2069 }
2070 data = (const unsigned char *) sqlite3_value_blob(argv[0]);
2071 length = sqlite3_value_bytes(argv[0]);
2072 if (!data || !length) {
2073 sqlite3_result_error(ctx, "empty blob", -1);
2074 return;
2075 }
2076 mb = mem_createmb(data, length);
2077 if (!mb) {
2078 sqlite3_result_error(ctx, "cannot map blob", -1);
2079 return;
2080 }
2081 sql = sqlite3_mprintf("ATTACH "
2082#ifdef _WIN64
2083 "'file:/%llX"
2084#else
2085 "'file:/%lX"
2086#endif
2087 "?vfs=%s&"
2088#ifdef linux
2089 "mode=rw&"
2090#else
2091 "mode=ro&"
2092#endif
2093 "cache=private' AS %Q",
2094#ifdef _WIN64
2095 (unsigned long long) mb,
2096#else
2097 (unsigned long) mb,
2098#endif
2099 mem_vfs_name,
2100 (char *) sqlite3_value_text(argv[1]));
2101 if (!sql) {
2102 sqlite3_result_error(ctx, "cannot map blob", -1);
2103 mem_destroymb(mb);
2104 return;
2105 }
2106#ifdef linux
2107 sqlite3_mutex_leave(mb->mutex);
2108#endif
2109 if (sqlite3_exec(sqlite3_context_db_handle(ctx), sql, 0, 0, 0)
2110 != SQLITE_OK) {
2111 sqlite3_free(sql);
2112 sqlite3_result_error(ctx, "cannot attach blob", -1);
2113#ifdef linux
2114 sqlite3_mutex_enter(mb->mutex);
2115#endif
2116 mem_destroymb(mb);
2117 return;
2118 }
2119 sqllen = strlen(sql);
2120 sqlite3_snprintf(sqllen, sql, "PRAGMA %Q.synchronous = OFF",
2121 (char *) sqlite3_value_text(argv[1]));
2122 sqlite3_exec(sqlite3_context_db_handle(ctx), sql, 0, 0, 0);
2123#ifdef linux
2124 sqlite3_snprintf(sqllen, sql, "PRAGMA %Q.journal_mode = OFF",
2125 (char *) sqlite3_value_text(argv[1]));
2126 if (sqlite3_exec(sqlite3_context_db_handle(ctx), sql, 0, 0, 0)
2127 == SQLITE_OK) {
2128 isrw = 1;
2129 }
2130#endif
2131#ifdef linux
2132 sqlite3_mutex_enter(mb->mutex);
2133#endif
2134 if (--mb->opened < 1) {
2135 sqlite3_snprintf(sqllen, sql, "DETACH %Q",
2136 (char *) sqlite3_value_text(argv[1]));
2137 sqlite3_exec(sqlite3_context_db_handle(ctx), sql, 0, 0, 0);
2138 sqlite3_free(sql);
2139 sqlite3_result_error(ctx, "cannot attach blob", -1);
2140 mem_destroymb(mb);
2141 return;
2142 }
2143#ifdef linux
2144 sqlite3_mutex_leave(mb->mutex);
2145 if (isrw) {
2146 sqlite3_snprintf(sqllen, sql,
2147 "file:/%lX?vfs=%s&mode=rw&cache=private",
2148 (unsigned long) mb, mem_vfs_name);
2149 sqlite3_result_text(ctx, sql, -1, sqlite3_free);
2150 return;
2151 }
2152#endif
2153 sqlite3_free(sql);
2154 sqlite3_result_null(ctx);
2155}
2156
2174static void
2175blob_dump_func(sqlite3_context *ctx, int argc, sqlite3_value **argv)
2176{
2177 char *uri, vfs[64];
2178#ifdef _WIN64
2179 unsigned long long addr = 0;
2180#else
2181 unsigned long addr = 0;
2182#endif
2183#ifdef linux
2184 int pfd[2], n;
2185 mem_blk *mb;
2186#endif
2187
2188 if (argc != 1) {
2189 sqlite3_result_error(ctx, "need one argument", -1);
2190 return;
2191 }
2192 uri = (char *) sqlite3_value_text(argv[0]);
2193 vfs[0] = '\0';
2194 if (!uri || (sscanf(uri,
2195#ifdef _WIN64
2196 "file:/%I64X?vfs=%63[^&]",
2197#else
2198 "file:/%lX?vfs=%63[^&]",
2199#endif
2200 &addr, vfs) != 2)) {
2201inval:
2202 sqlite3_result_error(ctx, "invalid object", -1);
2203 return;
2204 }
2205 vfs[63] = '\0';
2206 if ((strcmp(mem_vfs_name, vfs) != 0) || (addr == 0)) {
2207 goto inval;
2208 }
2209#ifdef linux
2210 if (pipe(pfd) < 0) {
2211 goto inval;
2212 }
2213 n = (write(pfd[1], (char *) addr, 1) < 0) ? errno : 0;
2214 close(pfd[0]);
2215 close(pfd[1]);
2216 if (n == EFAULT) {
2217 goto inval;
2218 }
2219 mb = (mem_blk *) addr;
2220 if (memcmp(mb->magic, MEM_MAGIC, 4) != 0) {
2221 goto inval;
2222 }
2223 sqlite3_mutex_enter(mb->mutex);
2224 sqlite3_result_blob(ctx, mb->data, mb->length, SQLITE_STATIC);
2225 sqlite3_mutex_leave(mb->mutex);
2226#else
2227 sqlite3_result_error(ctx, "unsupported function", -1);
2228#endif
2229}
2230
2231#endif /* SQLITE_OPEN_URI */
2232
2239#ifndef STANDALONE
2240static
2241#endif
2242int
2243zip_vtab_init(sqlite3 *db)
2244{
2245 sqlite3_create_function(db, "crc32", 1, SQLITE_UTF8,
2246 (void *) db, zip_crc32_func, 0, 0);
2247 sqlite3_create_function(db, "inflate", 1, SQLITE_UTF8,
2248 (void *) db, zip_inflate_func, 0, 0);
2249 sqlite3_create_function(db, "deflate", 1, SQLITE_UTF8,
2250 (void *) db, zip_deflate_func, 0, 0);
2251 sqlite3_create_function(db, "uncompress", 1, SQLITE_UTF8,
2252 (void *) db, zip_inflate_func, 0, 0);
2253 sqlite3_create_function(db, "compress", -1, SQLITE_UTF8,
2254 (void *) db, zip_compress_func, 0, 0);
2255#ifdef SQLITE_OPEN_URI
2256 if (!mem_vfs.pAppData) {
2257 sqlite3_vfs *parent = sqlite3_vfs_find(0);
2258
2259 if (parent) {
2260 sqlite3_snprintf(sizeof (mem_vfs_name), mem_vfs_name,
2261#ifdef _WIN64
2262 "mem_vfs_%llX", (unsigned long long) &mem_vfs
2263#else
2264 "mem_vfs_%lX", (unsigned long) &mem_vfs
2265#endif
2266 );
2267 if (sqlite3_vfs_register(&mem_vfs, 0) == SQLITE_OK) {
2268 mem_vfs.pAppData = (void *) parent;
2269 }
2270 }
2271 }
2272 if (mem_vfs.pAppData) {
2273 sqlite3_create_function(db, "blob_attach", 2, SQLITE_UTF8,
2274 (void *) db, blob_attach_func, 0, 0);
2275 sqlite3_create_function(db, "blob_dump", 1, SQLITE_UTF8,
2276 (void *) db, blob_dump_func, 0, 0);
2277 }
2278#endif
2279 return sqlite3_create_module(db, "zipfile", &zip_vtab_mod, 0);
2280}
2281
2282#ifndef STANDALONE
2283
2292int
2293sqlite3_extension_init(sqlite3 *db, char **errmsg,
2294 const sqlite3_api_routines *api)
2295{
2296 SQLITE_EXTENSION_INIT2(api);
2297 return zip_vtab_init(db);
2298}
2299
2300#endif
static SQLRETURN nomem(STMT *s)
Report S1000 (out of memory) SQL error given STMT.
Driver internal structure representing SQL statement (HSTMT).
Structure to describe ZIP virtual table cursor.
Definition zipfile.c:121
int nmatches
For filter EQ.
Definition zipfile.c:125
int usematches
For filter EQ.
Definition zipfile.c:124
int pos
ZIP file position.
Definition zipfile.c:123
int * matches
For filter EQ.
Definition zipfile.c:126
sqlite3_vtab_cursor cursor
SQLite virtual table cursor.
Definition zipfile.c:122
Structure to implement ZIP file handle.
Definition zipfile.c:89
unsigned char * entries[1]
Pointer to first entry.
Definition zipfile.c:98
off_t length
length of ZIP file
Definition zipfile.c:90
int baseoffs
Global offset for embedded ZIP files.
Definition zipfile.c:96
int nentries
Number of directory entries.
Definition zipfile.c:97
unsigned char * data
mmap()'ed ZIP file
Definition zipfile.c:91
Structure to describe a ZIP virtual table.
Definition zipfile.c:107
sqlite3 * db
Open database.
Definition zipfile.c:109
sqlite3_vtab vtab
SQLite virtual table.
Definition zipfile.c:108
int sorted
1 = sorted by path, -1 = sorting, 0 = unsorted
Definition zipfile.c:111
char tblname[1]
Name, format "database".
Definition zipfile.c:112
zip_file * zip
ZIP file handle.
Definition zipfile.c:110
static const sqlite3_module zip_vtab_mod
SQLite module descriptor.
Definition zipfile.c:1026
static int zip_vtab_filter(sqlite3_vtab_cursor *cursor, int idxNum, const char *idxStr, int argc, sqlite3_value **argv)
Filter function for virtual table.
Definition zipfile.c:670
#define ZIP_CENTRAL_MTIME_OFFS
Definition zipfile.c:59
#define ZIP_COMPMETH_STORED
Definition zipfile.c:75
static int zip_vtab_close(sqlite3_vtab_cursor *cursor)
Close virtual table cursor.
Definition zipfile.c:631
struct zip_vtab zip_vtab
static void zip_vtab_matchfunc(sqlite3_context *ctx, int argc, sqlite3_value **argv)
Internal MATCH function for virtual table.
Definition zipfile.c:957
#define ZIP_LOCAL_PATHLEN_OFFS
Definition zipfile.c:51
static void zip_compress_func(sqlite3_context *ctx, int argc, sqlite3_value **argv)
Compress data given blob and optional compression level.
Definition zipfile.c:1222
#define ZIP_CENTRAL_DIRSIZE_OFFS
Definition zipfile.c:72
#define zip_read_int(p)
Definition zipfile.c:78
#define ZIP_LOCAL_EXTRA_OFFS
Definition zipfile.c:52
#define ZIP_CENTRAL_CRC32_OFFS
Definition zipfile.c:61
#define ZIP_CENTRAL_DIRSTART_OFFS
Definition zipfile.c:73
static int zip_vtab_rowid(sqlite3_vtab_cursor *cursor, sqlite_int64 *rowidp)
Return current rowid of virtual table cursor.
Definition zipfile.c:931
static int zip_vtab_next(sqlite3_vtab_cursor *cursor)
Retrieve next row from virtual table cursor.
Definition zipfile.c:649
static int zip_vtab_bestindex(sqlite3_vtab *vtab, sqlite3_index_info *info)
Determines information for filter function according to constraints.
Definition zipfile.c:516
static void zip_close(zip_file *zip)
Close ZIP file handle.
Definition zipfile.c:340
#define zip_read_short(p)
Definition zipfile.c:80
#define ZIP_CENTRAL_COMMENTLEN_OFFS
Definition zipfile.c:66
#define ZIP_CENTRAL_COMPLEN_OFFS
Definition zipfile.c:62
#define ZIP_CENTRAL_PATHLEN_OFFS
Definition zipfile.c:64
#define ZIP_LOCAL_HEADER_LEN
Definition zipfile.c:53
#define ZIP_CENTRAL_COMPMETH_OFFS
Definition zipfile.c:58
static int zip_vtab_init(sqlite3 *db)
Module initializer creating SQLite module and functions.
Definition zipfile.c:2243
int sqlite3_extension_init(sqlite3 *db, char **errmsg, const sqlite3_api_routines *api)
Initializer for SQLite extension load mechanism.
Definition zipfile.c:2293
static int zip_vtab_connect(sqlite3 *db, void *aux, int argc, const char *const *argv, sqlite3_vtab **vtabp, char **errp)
Connect to virtual table.
Definition zipfile.c:412
static zip_file * zip_open(const char *filename)
Memory map ZIP file for reading and return handle to it.
Definition zipfile.c:184
static void zip_crc32_func(sqlite3_context *ctx, int argc, sqlite3_value **argv)
Compute CRC32 given blob.
Definition zipfile.c:1059
#define ZIP_CENTRAL_END_LEN
Definition zipfile.c:70
static char * unquote(char const *in)
Strip off quotes given string.
Definition zipfile.c:372
static int zip_vtab_open(sqlite3_vtab *vtab, sqlite3_vtab_cursor **cursorp)
Open virtual table and return cursor.
Definition zipfile.c:608
#define ZIP_CENTRAL_HEADER_LEN
Definition zipfile.c:57
#define ZIP_CENTRAL_END_SIG
Definition zipfile.c:69
#define ZIP_CENTRAL_UNCOMPLEN_OFFS
Definition zipfile.c:63
static int zip_vtab_disconnect(sqlite3_vtab *vtab)
Disconnect virtual table.
Definition zipfile.c:487
static int zip_vtab_destroy(sqlite3_vtab *vtab)
Destroy virtual table.
Definition zipfile.c:503
static int zip_vtab_create(sqlite3 *db, void *aux, int argc, const char *const *argv, sqlite3_vtab **vtabp, char **errp)
Create virtual table.
Definition zipfile.c:473
#define ZIP_CENTRAL_ENTS_OFFS
Definition zipfile.c:71
#define ZIP_SIG_LEN
Definition zipfile.c:47
#define ZIP_CENTRAL_MDATE_OFFS
Definition zipfile.c:60
static void zip_inflate_func(sqlite3_context *ctx, int argc, sqlite3_value **argv)
Inflate data given blob.
Definition zipfile.c:1084
static int zip_vtab_eof(sqlite3_vtab_cursor *cursor)
Return end of table state of virtual table cursor.
Definition zipfile.c:753
static void zip_deflate_func(sqlite3_context *ctx, int argc, sqlite3_value **argv)
Deflate data given blob and optional compression level.
Definition zipfile.c:1158
struct zip_file zip_file
#define ZIP_CENTRAL_EXTRALEN_OFFS
Definition zipfile.c:65
static int zip_vtab_column(sqlite3_vtab_cursor *cursor, sqlite3_context *ctx, int n)
Return column data of virtual table.
Definition zipfile.c:776
#define ZIP_CENTRAL_LOCALHDR_OFFS
Definition zipfile.c:67
#define ZIP_CENTRAL_HEADER_SIG
Definition zipfile.c:55
static int zip_vtab_findfunc(sqlite3_vtab *vtab, int narg, const char *name, void(**pfunc)(sqlite3_context *, int, sqlite3_value **), void **parg)
Find overloaded function on virtual table.
Definition zipfile.c:994
#define ZIP_COMPMETH_DEFLATED
Definition zipfile.c:76

Generated on Sun Nov 26 2023 by doxygen.
Contact: chw@ch-werner.de