Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals  

zipfile.c

Go to the documentation of this file.
00001 
00018 #ifdef linux
00019 #define _GNU_SOURCE
00020 #endif
00021 
00022 #ifdef STANDALONE
00023 #include <sqlite3.h>
00024 #else
00025 #include <sqlite3ext.h>
00026 static SQLITE_EXTENSION_INIT1
00027 #endif
00028 
00029 #if defined(_WIN32) || defined(_WIN64)
00030 #include <windows.h>
00031 #else
00032 #include <sys/mman.h>
00033 #include <fcntl.h>
00034 #include <unistd.h>
00035 #include <errno.h>
00036 #endif
00037 
00038 #include <stdio.h>
00039 #include <stdlib.h>
00040 #include <string.h>
00041 #include <limits.h>
00042 
00043 #include <zlib.h>
00044 
00045 #undef snprintf
00046 
00047 #define ZIP_SIG_LEN                     4
00048 
00049 #define ZIP_LOCAL_HEADER_SIG            0x04034b50
00050 #define ZIP_LOCAL_HEADER_FLAGS          6
00051 #define ZIP_LOCAL_PATHLEN_OFFS          26
00052 #define ZIP_LOCAL_EXTRA_OFFS            28
00053 #define ZIP_LOCAL_HEADER_LEN            30
00054 
00055 #define ZIP_CENTRAL_HEADER_SIG          0x02014b50
00056 #define ZIP_CENTRAL_HEADER_FLAGS        8
00057 #define ZIP_CENTRAL_HEADER_LEN          46
00058 #define ZIP_CENTRAL_COMPMETH_OFFS       10
00059 #define ZIP_CENTRAL_MTIME_OFFS          12
00060 #define ZIP_CENTRAL_MDATE_OFFS          14
00061 #define ZIP_CENTRAL_CRC32_OFFS          16
00062 #define ZIP_CENTRAL_COMPLEN_OFFS        20
00063 #define ZIP_CENTRAL_UNCOMPLEN_OFFS      24
00064 #define ZIP_CENTRAL_PATHLEN_OFFS        28
00065 #define ZIP_CENTRAL_EXTRALEN_OFFS       30
00066 #define ZIP_CENTRAL_COMMENTLEN_OFFS     32
00067 #define ZIP_CENTRAL_LOCALHDR_OFFS       42
00068 
00069 #define ZIP_CENTRAL_END_SIG             0x06054b50
00070 #define ZIP_CENTRAL_END_LEN             22
00071 #define ZIP_CENTRAL_ENTS_OFFS           8
00072 #define ZIP_CENTRAL_DIRSIZE_OFFS        12
00073 #define ZIP_CENTRAL_DIRSTART_OFFS       16
00074 
00075 #define ZIP_COMPMETH_STORED             0
00076 #define ZIP_COMPMETH_DEFLATED           8
00077 
00078 #define zip_read_int(p)         \
00079     ((p)[0] | ((p)[1] << 8) | ((p)[2] << 16) | ((p)[3] << 24))
00080 #define zip_read_short(p)       \
00081     ((p)[0] | ((p)[1] << 8))
00082 
00089 typedef struct zip_file {
00090     off_t length;               
00091     unsigned char *data;        
00092 #if defined(_WIN32) || defined(_WIN64)
00093     HANDLE h;                   
00094     HANDLE mh;                  
00095 #endif
00096     int baseoffs;               
00097     int nentries;               
00098     unsigned char *entries[1];  
00099 } zip_file;
00100 
00107 typedef struct zip_vtab {
00108     sqlite3_vtab vtab;  
00109     sqlite3 *db;        
00110     zip_file *zip;      
00111     int sorted;         
00112     char tblname[1];    
00113 } zip_vtab;
00114 
00121 typedef struct {
00122     sqlite3_vtab_cursor cursor;         
00123     int pos;                            
00124     int usematches;                     
00125     int nmatches;                       
00126     int *matches;                       
00127 } zip_cursor;
00128 
00129 #ifdef SQLITE_OPEN_URI
00130 
00137 typedef struct mem_blk {
00138 #define MEM_MAGIC "MVFS"
00139     char magic[4];                      
00140     int opened;                         
00141 #if defined(_WIN32) || defined(_WIN64)
00142     HANDLE mh;                          
00143 #else
00144     long psize;                         
00145 #ifdef linux
00146     sqlite3_mutex *mutex;               
00147     int lcnt;                           
00148 #endif
00149 #endif
00150     unsigned long size;                 
00151     unsigned long length;               
00152     unsigned char *data;                
00153 } mem_blk;
00154 
00161 typedef struct mem_file {
00162     sqlite3_file base;                  
00163 #ifdef linux
00164     int lock;                           
00165 #endif
00166     mem_blk *mb;                        
00167 } mem_file;
00168 
00169 /*
00170  * Private VFS name
00171  */
00172 
00173 static char mem_vfs_name[64];
00174 
00175 #endif /* SQLITE_OPEN_URI */
00176 
00183 static zip_file *
00184 zip_open(const char *filename)
00185 {
00186 #if defined(_WIN32) || defined(_WIN64)
00187     HANDLE h, mh = INVALID_HANDLE_VALUE;
00188     DWORD length;
00189     unsigned char *data = 0;
00190 #else
00191     int fd;
00192     off_t length;
00193     unsigned char *data = MAP_FAILED;
00194 #endif
00195     int nentries, baseoffs = 0, i;
00196     zip_file *zip = 0;
00197     unsigned char *p, *q;
00198 
00199     if (!filename) {
00200         return 0;
00201     }
00202 #if defined(_WIN32) || defined(_WIN64)
00203     h = CreateFile(filename, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0);
00204     if (h == INVALID_HANDLE_VALUE) {
00205         goto error;
00206     }
00207     length = GetFileSize(h, 0);
00208     if ((length == INVALID_FILE_SIZE) || (length < ZIP_CENTRAL_END_LEN)) {
00209         goto error;
00210     }
00211     mh = CreateFileMapping(h, 0, PAGE_READONLY, 0, length, 0);
00212     if (mh == INVALID_HANDLE_VALUE) {
00213         goto error;
00214     }
00215     data = MapViewOfFile(mh, FILE_MAP_READ, 0, 0, length);
00216     if (!data) {
00217         goto error;
00218     }
00219 #else
00220     fd = open(filename, O_RDONLY);
00221     if (fd < 0) {
00222         goto error;
00223     }
00224     length = lseek(fd, 0, SEEK_END);
00225     if ((length == -1) || (length < ZIP_CENTRAL_END_LEN)) {
00226         goto error;
00227     }
00228     data = (unsigned char *) mmap(0, length, PROT_READ,
00229                                   MAP_FILE | MAP_PRIVATE, fd, 0);
00230     if (data == MAP_FAILED) {
00231         goto error;
00232     }
00233     close(fd);
00234     fd = -1;
00235 #endif
00236     p = data + length - ZIP_CENTRAL_END_LEN;
00237     while (p >= data) {
00238         if (*p == (ZIP_CENTRAL_END_SIG & 0xFF)) {
00239             if (zip_read_int(p) == ZIP_CENTRAL_END_SIG) {
00240                 break;
00241             }
00242             p -= ZIP_SIG_LEN;
00243         } else {
00244             --p;
00245         }
00246     }
00247     if (p < data) {
00248         goto error;
00249     }
00250     nentries = zip_read_short(p + ZIP_CENTRAL_ENTS_OFFS);
00251     if (nentries == 0) {
00252         goto error;
00253     }
00254     q = data + zip_read_int(p + ZIP_CENTRAL_DIRSTART_OFFS);
00255     p -= zip_read_int(p + ZIP_CENTRAL_DIRSIZE_OFFS);
00256     if (p < data || p > data + length || q < data || q > data + length) {
00257         goto error;
00258     }
00259     baseoffs = p - q;
00260     q = p;
00261     for (i = 0; i < nentries; i++) {
00262         int pathlen, comlen, extra;
00263 
00264         if ((q + ZIP_CENTRAL_HEADER_LEN) > (data + length)) {
00265             goto error;
00266         }
00267         if (zip_read_int(q) != ZIP_CENTRAL_HEADER_SIG) {
00268             goto error;
00269         }
00270         pathlen = zip_read_short(q + ZIP_CENTRAL_PATHLEN_OFFS);
00271         comlen = zip_read_short(q + ZIP_CENTRAL_COMMENTLEN_OFFS);
00272         extra = zip_read_short(q + ZIP_CENTRAL_EXTRALEN_OFFS);
00273         q += pathlen + comlen + extra + ZIP_CENTRAL_HEADER_LEN;
00274     }
00275     zip = sqlite3_malloc(sizeof (zip_file) +
00276                          nentries * sizeof (unsigned char *));
00277     if (!zip) {
00278         goto error;
00279     }
00280 #if defined(_WIN32) || defined(_WIN64)
00281     zip->h = zip->mh = INVALID_HANDLE_VALUE;
00282 #endif
00283     zip->length = length;
00284     zip->data = data;
00285     zip->baseoffs = baseoffs;
00286     zip->nentries = nentries;
00287     q = p;
00288     for (i = 0; i < nentries; i++) {
00289         int pathlen, comlen, extra;
00290 
00291         if ((q + ZIP_CENTRAL_HEADER_LEN) > (data + length)) {
00292             goto error;
00293         }
00294         if (zip_read_int(q) != ZIP_CENTRAL_HEADER_SIG) {
00295             goto error;
00296         }
00297         zip->entries[i] = q;
00298         pathlen = zip_read_short(q + ZIP_CENTRAL_PATHLEN_OFFS);
00299         comlen = zip_read_short(q + ZIP_CENTRAL_COMMENTLEN_OFFS);
00300         extra = zip_read_short(q + ZIP_CENTRAL_EXTRALEN_OFFS);
00301         q += pathlen + comlen + extra + ZIP_CENTRAL_HEADER_LEN;
00302     }
00303     zip->entries[i] = 0;
00304 #if defined(_WIN32) || defined(_WIN64)
00305     zip->h = h;
00306     zip->mh = mh;
00307 #endif
00308     return zip;
00309 error:
00310     if (zip) {
00311         sqlite3_free(zip);
00312     }
00313 #if defined(_WIN32) || defined(_WIN64)
00314     if (data) {
00315         UnmapViewOfFile(data);
00316     }
00317     if (mh != INVALID_HANDLE_VALUE) {
00318         CloseHandle(mh);
00319     }
00320     if (h != INVALID_HANDLE_VALUE) {
00321         CloseHandle(h);
00322     }
00323 #else
00324     if (data != MAP_FAILED) {
00325         munmap(data, length);
00326     }
00327     if (fd >= 0) {
00328         close(fd);
00329     }
00330 #endif
00331     return 0;
00332 }
00333 
00339 static void
00340 zip_close(zip_file *zip)
00341 {
00342     if (zip) {
00343 #if defined(_WIN32) || defined(_WIN64)
00344         if (zip->data) {
00345             UnmapViewOfFile(zip->data);
00346         }
00347         if (zip->mh != INVALID_HANDLE_VALUE) {
00348             CloseHandle(zip->mh);
00349         }
00350         if (zip->h != INVALID_HANDLE_VALUE) {
00351             CloseHandle(zip->h);
00352         }
00353 #else
00354         if (zip->data) {
00355             munmap(zip->data, zip->length);
00356         }
00357 #endif
00358         zip->length = 0;
00359         zip->data = 0;
00360         zip->nentries = 0;
00361         sqlite3_free(zip);
00362     }
00363 }
00364 
00371 static char *
00372 unquote(char const *in)
00373 {
00374     char c, *ret;
00375     int i;
00376 
00377     ret = sqlite3_malloc(strlen(in) + 1);
00378     if (ret) {
00379         c = in[0];
00380         if ((c == '"') || (c == '\'')) {
00381             i = strlen(in + 1);
00382             if ((i > 0) && (in[i] == c)) {
00383                 strcpy(ret, in + 1);
00384                 ret[i - 1] = '\0';
00385                 return ret;
00386             }
00387         }
00388         strcpy(ret, in);
00389     }
00390     return ret;
00391 }
00392 
00411 static int
00412 zip_vtab_connect(sqlite3* db, void *aux, int argc, const char * const *argv,
00413                  sqlite3_vtab **vtabp, char **errp)
00414 {
00415     zip_file *zip = 0;
00416     int rc = SQLITE_ERROR;
00417     char *filename;
00418     zip_vtab *vtab;
00419 
00420     if (argc < 4) {
00421         *errp = sqlite3_mprintf("input file name missing");
00422         return SQLITE_ERROR;
00423     }
00424     filename = unquote(argv[3]);
00425     if (filename) {
00426         zip = zip_open(filename);
00427         sqlite3_free(filename);
00428     }
00429     if (!zip) {
00430         *errp = sqlite3_mprintf("unable to open input file");
00431         return rc;
00432     }
00433     vtab = sqlite3_malloc(sizeof(zip_vtab) + 6 +
00434                           strlen(argv[1]) + strlen(argv[2]));
00435     if (!vtab) {
00436         zip_close(zip);
00437         *errp = sqlite3_mprintf("out of memory");
00438         return rc;
00439     }
00440     memset(vtab, 0, sizeof (*vtab));
00441     strcpy(vtab->tblname, "\"");
00442     strcat(vtab->tblname, argv[1]);
00443     strcat(vtab->tblname, "\".\"");
00444     strcat(vtab->tblname, argv[2]);
00445     strcat(vtab->tblname, "\"");
00446     vtab->db = db;
00447     vtab->zip = zip;
00448     rc = sqlite3_declare_vtab(db, "CREATE TABLE x(path, comp, mtime, "
00449                               "crc32, length, data, clength, cdata, isdir)");
00450     if (rc != SQLITE_OK) {
00451         zip_close(zip);
00452         sqlite3_free(vtab);
00453         *errp = sqlite3_mprintf("table definition failed (error %d)", rc);
00454         return rc;
00455     }
00456     *vtabp = &vtab->vtab;
00457     *errp = 0;
00458     return SQLITE_OK;
00459 }
00460 
00472 static int
00473 zip_vtab_create(sqlite3* db, void *aux, int argc,
00474                 const char *const *argv,
00475                 sqlite3_vtab **vtabp, char **errp)
00476 {
00477     return zip_vtab_connect(db, aux, argc, argv, vtabp, errp);
00478 }
00479 
00486 static int
00487 zip_vtab_disconnect(sqlite3_vtab *vtab)
00488 {
00489     zip_vtab *tab = (zip_vtab *) vtab;
00490 
00491     zip_close(tab->zip);
00492     sqlite3_free(tab);
00493     return SQLITE_OK;
00494 }
00495 
00502 static int
00503 zip_vtab_destroy(sqlite3_vtab *vtab)
00504 {
00505     return zip_vtab_disconnect(vtab);
00506 }
00507 
00515 static int
00516 zip_vtab_bestindex(sqlite3_vtab *vtab, sqlite3_index_info *info)
00517 {
00518     zip_vtab *tab = (zip_vtab *) vtab;
00519     int i;
00520 
00521     info->idxNum = 0;
00522     if (tab->sorted == 0) {
00523         char *sql = 0;
00524         unsigned char **entries = 0;
00525         sqlite3_stmt *stmt = 0;
00526         int rc, count, i;
00527         size_t tmp;
00528 
00529         /* perform sorting on 0th column (path, string) */
00530         tab->sorted = -1;
00531         entries = sqlite3_malloc(tab->zip->nentries * sizeof (entries));
00532         sql = sqlite3_mprintf("SELECT rowid FROM %s ORDER BY path",
00533                               tab->tblname);
00534         if (sql && entries) {
00535             rc = sqlite3_prepare_v2(tab->db, sql, -1, &stmt, 0);
00536             if ((rc == SQLITE_OK) && stmt) {
00537                 count = 0;
00538                 while (1) {
00539                     rc = sqlite3_step(stmt);
00540                     if (rc != SQLITE_ROW) {
00541                         break;
00542                     }
00543                     tmp = sqlite3_column_int(stmt, 0);
00544                     entries[count++] = (unsigned char *) tmp;
00545                 }
00546                 if ((rc == SQLITE_DONE) && (count == tab->zip->nentries)) {
00547                     for (i = 0; i < count; i++) {
00548                         tmp = (size_t) entries[i];
00549                         tmp = (size_t) tab->zip->entries[tmp];
00550                         entries[i] = (unsigned char *) tmp;
00551                     }
00552                     memcpy(tab->zip->entries, entries, i * sizeof (entries));
00553                     tab->sorted = 1;
00554                 }
00555             }
00556         }
00557         if (stmt) {
00558             sqlite3_finalize(stmt);
00559         }
00560         if (sql) {
00561             sqlite3_free(sql);
00562         }
00563         if (entries) {
00564             sqlite3_free(entries);
00565         }
00566     }
00567     /* no optimization while table is being sorted or is unsorted */
00568     if (tab->sorted != 1) {
00569         return SQLITE_OK;
00570     }
00571     /* support EQ or simple MATCH constraint on 0th column (path) */
00572     for (i = 0; i < info->nConstraint; i++) {
00573         if (info->aConstraint[i].usable &&
00574             (info->aConstraint[i].iColumn == 0)) {
00575             if (info->aConstraint[i].op == SQLITE_INDEX_CONSTRAINT_EQ) {
00576                 info->idxNum = 1;
00577                 info->aConstraintUsage[i].argvIndex = 1;
00578                 info->aConstraintUsage[i].omit = 1;
00579                 info->estimatedCost = 1.0;
00580                 break;
00581             } else if (info->aConstraint[i].op ==
00582                        SQLITE_INDEX_CONSTRAINT_MATCH) {
00583                 info->idxNum = 2;
00584                 info->aConstraintUsage[i].argvIndex = 1;
00585                 info->aConstraintUsage[i].omit = 1;
00586                 info->estimatedCost = 2.0;
00587                 break;
00588             }
00589         }
00590     }
00591     /* ORDER BY is ascending on 0th column (path) when table is sorted */
00592     if (info->nOrderBy > 0) {
00593         if ((info->aOrderBy[0].iColumn == 0) && !info->aOrderBy[0].desc) {
00594             info->orderByConsumed = 1;
00595         }
00596     }
00597     return SQLITE_OK;
00598 }
00599 
00607 static int
00608 zip_vtab_open(sqlite3_vtab *vtab, sqlite3_vtab_cursor **cursorp)
00609 {
00610     zip_cursor *cur = sqlite3_malloc(sizeof(*cur));
00611 
00612     if (!cur) {
00613         return SQLITE_ERROR;
00614     }
00615     cur->cursor.pVtab = vtab;
00616     cur->pos = -1;
00617     cur->usematches = 0;
00618     cur->nmatches = 0;
00619     cur->matches = 0;
00620     *cursorp = &cur->cursor;
00621     return SQLITE_OK;
00622 }
00623 
00630 static int
00631 zip_vtab_close(sqlite3_vtab_cursor *cursor)
00632 {
00633     zip_cursor *cur = (zip_cursor *) cursor;
00634 
00635     if (cur->matches) {
00636         sqlite3_free(cur->matches);
00637     }
00638     sqlite3_free(cur);
00639     return SQLITE_OK;
00640 }
00641 
00648 static int
00649 zip_vtab_next(sqlite3_vtab_cursor *cursor)
00650 {
00651     zip_cursor *cur = (zip_cursor *) cursor;
00652 
00653     if (cur->nmatches >= 0) {
00654         cur->pos++;
00655     }
00656     return SQLITE_OK;
00657 }
00658 
00669 static int
00670 zip_vtab_filter(sqlite3_vtab_cursor *cursor, int idxNum,
00671                 const char *idxStr, int argc, sqlite3_value **argv)
00672 {
00673     zip_cursor *cur = (zip_cursor *) cursor;
00674     zip_vtab *tab = (zip_vtab *) cur->cursor.pVtab;
00675 
00676     if (cur->matches) {
00677         sqlite3_free(cur->matches);
00678         cur->matches = 0;
00679     }
00680     cur->usematches = 0;
00681     cur->nmatches = 0;
00682     /* if EQ or MATCH constraint is active, add match array to cursor */
00683     if (idxNum && (argc > 0)) {
00684         int i, k, d, found, leneq, len;
00685         unsigned char *eq;
00686 
00687         eq = (unsigned char *) sqlite3_value_text(argv[0]);
00688         if (!eq) {
00689             cur->nmatches = -1;
00690             goto done;
00691         }
00692         if (idxNum > 1) {
00693             unsigned char *p = (unsigned char *) strrchr((char *) eq, '*');
00694 
00695             if (!p || (p[1] != '\0')) {
00696                 return SQLITE_ERROR;
00697             }
00698             leneq = p - eq;
00699         } else {
00700             leneq = sqlite3_value_bytes(argv[0]);
00701             if (leneq == 0) {
00702                 cur->nmatches = -1;
00703                 goto done;
00704             }
00705         }
00706         cur->matches = sqlite3_malloc(tab->zip->nentries * sizeof (int));
00707         if (!cur->matches) {
00708             return SQLITE_NOMEM;
00709         }
00710         cur->usematches = 1;
00711         memset(cur->matches, 0, tab->zip->nentries * sizeof (int));
00712         for (k = found = 0; k < tab->zip->nentries; k++) {
00713             len = zip_read_short(tab->zip->entries[k] +
00714                                  ZIP_CENTRAL_PATHLEN_OFFS);
00715             if (idxNum > 1) {
00716                 if (len < leneq) {
00717                     continue;
00718                 }
00719             } else if (len != leneq) {
00720                 if (found) {
00721                     break;
00722                 }
00723                 continue;
00724             }
00725             d = memcmp(tab->zip->entries[k] + ZIP_CENTRAL_HEADER_LEN,
00726                        eq, leneq);
00727             if (d == 0) {
00728                 found++;
00729                 cur->matches[k] = 1;
00730             } else if (d > 0) {
00731                 break;
00732             }
00733         }
00734         for (i = k = 0; i < tab->zip->nentries; i++) {
00735             if (cur->matches[i]) {
00736                 cur->matches[k++] = i;
00737             }
00738         }
00739         cur->nmatches = k;
00740     }
00741 done:
00742     cur->pos = -1;
00743     return zip_vtab_next(cursor);
00744 }
00745 
00752 static int
00753 zip_vtab_eof(sqlite3_vtab_cursor *cursor)
00754 {
00755     zip_cursor *cur = (zip_cursor *) cursor;
00756     zip_vtab *tab = (zip_vtab *) cur->cursor.pVtab;
00757 
00758     if (cur->nmatches < 0) {
00759         return 1;
00760     }
00761     if (cur->usematches) {
00762         return cur->pos >= cur->nmatches;
00763     }
00764     return cur->pos >= tab->zip->nentries;
00765 }
00766 
00775 static int
00776 zip_vtab_column(sqlite3_vtab_cursor *cursor, sqlite3_context *ctx, int n)
00777 {
00778     zip_cursor *cur = (zip_cursor *) cursor;
00779     zip_vtab *tab = (zip_vtab *) cur->cursor.pVtab;
00780     unsigned char *data = 0;
00781     unsigned char *dest = 0;
00782     int length;
00783 
00784     if (cur->usematches) {
00785         int pos;
00786 
00787         if ((cur->pos < 0) || (cur->pos >= cur->nmatches)) {
00788             sqlite3_result_error(ctx, "out of bounds", -1);
00789             return SQLITE_ERROR;
00790         }
00791         pos = cur->matches[cur->pos];
00792         data = tab->zip->entries[pos];
00793     } else {
00794         if ((cur->pos < 0) || (cur->pos >= tab->zip->nentries)) {
00795             sqlite3_result_error(ctx, "out of bounds", -1);
00796             return SQLITE_ERROR;
00797         }
00798         data = tab->zip->entries[cur->pos];
00799     }
00800     switch (n) {
00801     case 0:     /* "path": pathname */
00802         length = zip_read_short(data + ZIP_CENTRAL_PATHLEN_OFFS);
00803         data += ZIP_CENTRAL_HEADER_LEN;
00804         sqlite3_result_text(ctx, (char *) data, length, SQLITE_TRANSIENT);
00805         return SQLITE_OK;
00806     case 1:     /* "comp": compression method */
00807         length = zip_read_short(data + ZIP_CENTRAL_COMPMETH_OFFS);
00808         sqlite3_result_int(ctx, length);
00809         return SQLITE_OK;
00810     case 2:     /* "mtime": modification time/date */
00811         {
00812             int time = zip_read_short(data + ZIP_CENTRAL_MTIME_OFFS);
00813             int date = zip_read_short(data + ZIP_CENTRAL_MDATE_OFFS);
00814             char mtbuf[64];
00815 
00816             sprintf(mtbuf, "%04d-%02d-%02d %02d:%02d:%02d",
00817                     (date >> 9) + 1980, (date >> 5) & 0xf, date & 0x1f,
00818                     time >> 11, (time >> 5) & 0x3f, (time & 0x1f) << 1);
00819             sqlite3_result_text(ctx, mtbuf, -1, SQLITE_TRANSIENT);
00820             return SQLITE_OK;
00821         }
00822     case 3:     /* "crc32": CRC32 of uncompress data */
00823         length = zip_read_int(data + ZIP_CENTRAL_CRC32_OFFS);
00824         sqlite3_result_int(ctx, length);
00825         return SQLITE_OK;
00826     case 4:     /* "length": uncompress length of data */
00827         length = zip_read_int(data + ZIP_CENTRAL_UNCOMPLEN_OFFS);
00828         sqlite3_result_int(ctx, length);
00829         return SQLITE_OK;
00830     case 5:     /* "data": uncompressed data */
00831         {
00832             int clength, offs, extra, pathlen, cmeth;
00833 
00834             offs = tab->zip->baseoffs +
00835                 zip_read_int(data + ZIP_CENTRAL_LOCALHDR_OFFS);
00836             if ((offs + ZIP_LOCAL_HEADER_LEN) > tab->zip->length) {
00837                 goto donull;
00838             }
00839             extra = zip_read_short(tab->zip->data + offs +
00840                                    ZIP_LOCAL_EXTRA_OFFS);
00841             pathlen = zip_read_short(tab->zip->data + offs +
00842                                      ZIP_LOCAL_PATHLEN_OFFS);
00843             length = zip_read_int(data + ZIP_CENTRAL_UNCOMPLEN_OFFS);
00844             clength = zip_read_int(data + ZIP_CENTRAL_COMPLEN_OFFS);
00845             cmeth = zip_read_short(data + ZIP_CENTRAL_COMPMETH_OFFS);
00846             offs += ZIP_LOCAL_HEADER_LEN + pathlen + extra;
00847             if ((offs + clength) > tab->zip->length) {
00848                 goto donull;
00849             }
00850             data = tab->zip->data + offs;
00851             if (cmeth == ZIP_COMPMETH_STORED) {
00852                 sqlite3_result_blob(ctx, data, clength, SQLITE_TRANSIENT);
00853                 return SQLITE_OK;
00854             } else if (cmeth == ZIP_COMPMETH_DEFLATED) {
00855                 z_stream stream;
00856                 int err;
00857 
00858                 stream.zalloc = Z_NULL;
00859                 stream.zfree = Z_NULL;
00860                 stream.next_in = data;
00861                 stream.avail_in = clength;
00862                 stream.next_out = dest = sqlite3_malloc(length);
00863                 stream.avail_out = length;
00864                 stream.opaque = 0;
00865                 if (!dest) {
00866                     goto donull;
00867                 }
00868                 if (inflateInit2(&stream, -15) != Z_OK) {
00869                     goto donull;
00870                 }
00871                 err = inflate(&stream, Z_SYNC_FLUSH);
00872                 inflateEnd(&stream);
00873                 if ((err == Z_STREAM_END) ||
00874                     ((err == Z_OK) && (stream.avail_in == 0))) {
00875                     sqlite3_result_blob(ctx, dest, length, sqlite3_free);
00876                     return SQLITE_OK;
00877                 }
00878             }
00879         donull:
00880             if (dest) {
00881                 sqlite3_free(dest);
00882             }
00883             sqlite3_result_null(ctx);
00884             return SQLITE_OK;
00885         }
00886     case 6:     /* "clength": compressed length */
00887         length = zip_read_int(data + ZIP_CENTRAL_COMPLEN_OFFS);
00888         sqlite3_result_int(ctx, length);
00889         return SQLITE_OK;
00890     case 7:     /* "cdata": raw data */
00891         {
00892             int clength, offs, extra, pathlen;
00893 
00894             offs = tab->zip->baseoffs +
00895                 zip_read_int(data + ZIP_CENTRAL_LOCALHDR_OFFS);
00896             if ((offs + ZIP_LOCAL_HEADER_LEN) > tab->zip->length) {
00897                 goto donull;
00898             }
00899             extra = zip_read_short(tab->zip->data + offs +
00900                                    ZIP_LOCAL_EXTRA_OFFS);
00901             pathlen = zip_read_short(tab->zip->data + offs +
00902                                      ZIP_LOCAL_PATHLEN_OFFS);
00903             length = zip_read_int(data + ZIP_CENTRAL_UNCOMPLEN_OFFS);
00904             clength = zip_read_int(data + ZIP_CENTRAL_COMPLEN_OFFS);
00905             offs += ZIP_LOCAL_HEADER_LEN + pathlen + extra;
00906             if ((offs + clength) > tab->zip->length) {
00907                 goto donull;
00908             }
00909             data = tab->zip->data + offs;
00910             sqlite3_result_blob(ctx, data, clength, SQLITE_TRANSIENT);
00911             return SQLITE_OK;
00912         }
00913     case 8:     /* "isdir": directory indicator */
00914         length = zip_read_short(data + ZIP_CENTRAL_PATHLEN_OFFS);
00915         data += ZIP_CENTRAL_HEADER_LEN;
00916         sqlite3_result_int(ctx, (length > 0 && data[length - 1] == '/'));
00917         return SQLITE_OK;
00918     }
00919     sqlite3_result_error(ctx, "invalid column number", -1);
00920     return SQLITE_ERROR;
00921 }
00922 
00930 static int
00931 zip_vtab_rowid(sqlite3_vtab_cursor *cursor, sqlite_int64 *rowidp)
00932 {
00933     zip_cursor *cur = (zip_cursor *) cursor;
00934 
00935     if (cur->nmatches < 0) {
00936         *rowidp = -1;
00937     } else if ((cur->pos >= 0) && (cur->usematches > 0)) {
00938         if (cur->pos < cur->nmatches) {
00939             *rowidp = cur->matches[cur->pos];
00940         } else {
00941             *rowidp = -1;
00942         }
00943     } else {
00944         *rowidp = cur->pos;
00945     }
00946     return SQLITE_OK;
00947 }
00948 
00956 static void
00957 zip_vtab_matchfunc(sqlite3_context *ctx, int argc, sqlite3_value **argv)
00958 {
00959     int ret = 0;
00960 
00961     if (argc == 2) {
00962         unsigned char *q = (unsigned char *) sqlite3_value_text(argv[0]);
00963         unsigned char *p = (unsigned char *) sqlite3_value_text(argv[1]);
00964 
00965         if (p && q) {
00966             unsigned char *eq = (unsigned char *) strrchr((char *) q, '*');
00967             int lenq, lenp;
00968 
00969             if (eq && (eq[1] == '\0')) {
00970                 lenq = eq - q;
00971                 if (lenq) {
00972                     lenp = strlen((char *) p);
00973                     if ((lenp >= lenq) && !memcmp(p, q, lenq)) {
00974                         ret = 1;
00975                     }
00976                 }
00977             }
00978         }
00979     }
00980     sqlite3_result_int(ctx, ret);
00981 }
00982 
00993 static int
00994 zip_vtab_findfunc(sqlite3_vtab *vtab, int narg, const char *name,
00995                   void (**pfunc)(sqlite3_context *, int, sqlite3_value **),
00996                   void **parg)
00997 {
00998     if ((narg == 2) && !strcmp(name, "match")) {
00999         *pfunc = zip_vtab_matchfunc;
01000         *parg = 0;
01001         return 1;
01002     }
01003     return 0;
01004 }
01005 
01006 #if (SQLITE_VERSION_NUMBER > 3004000)
01007 
01014 static int
01015 zip_vtab_rename(sqlite3_vtab *vtab, const char *newname)
01016 {
01017     return SQLITE_OK;
01018 }
01019 
01020 #endif
01021 
01026 static const sqlite3_module zip_vtab_mod = {
01027     1,                   /* iVersion */
01028     zip_vtab_create,     /* xCreate */
01029     zip_vtab_connect,    /* xConnect */
01030     zip_vtab_bestindex,  /* xBestIndex */
01031     zip_vtab_disconnect, /* xDisconnect */
01032     zip_vtab_destroy,    /* xDestroy */
01033     zip_vtab_open,       /* xOpen */
01034     zip_vtab_close,      /* xClose */
01035     zip_vtab_filter,     /* xFilter */
01036     zip_vtab_next,       /* xNext */
01037     zip_vtab_eof,        /* xEof */
01038     zip_vtab_column,     /* xColumn */
01039     zip_vtab_rowid,      /* xRowid */
01040     0,                   /* xUpdate */
01041     0,                   /* xBegin */
01042     0,                   /* xSync */
01043     0,                   /* xCommit */
01044     0,                   /* xRollback */
01045     zip_vtab_findfunc,   /* xFindFunction */
01046 #if (SQLITE_VERSION_NUMBER > 3004000)
01047     zip_vtab_rename,     /* xRename */
01048 #endif
01049 };
01050 
01058 static void
01059 zip_crc32_func(sqlite3_context *ctx, int argc, sqlite3_value **argv)
01060 {
01061     int crc, length;
01062     unsigned char *data;
01063 
01064     if (argc != 1) {
01065         sqlite3_result_error(ctx, "need one argument", -1);
01066     }
01067     data = (unsigned char *) sqlite3_value_blob(argv[0]);
01068     length = sqlite3_value_bytes(argv[0]);
01069     crc = crc32(0, 0, 0);
01070     if (data && (length > 0)) {
01071         crc = crc32(crc, data, length);
01072     }
01073     sqlite3_result_int(ctx, crc);
01074 }
01075 
01083 static void
01084 zip_inflate_func(sqlite3_context *ctx, int argc, sqlite3_value **argv)
01085 {
01086     int err, length, dlength, avail;
01087     unsigned char *data, *dest, *newdest;
01088     z_stream stream;
01089 
01090     if (argc != 1) {
01091         sqlite3_result_error(ctx, "need one argument", -1);
01092         return;
01093     }
01094     data = (unsigned char *) sqlite3_value_blob(argv[0]);
01095     length = sqlite3_value_bytes(argv[0]);
01096     stream.zalloc = Z_NULL;
01097     stream.zfree = Z_NULL;
01098     stream.next_in = data;
01099     stream.avail_in = length;
01100     avail = length;
01101     stream.next_out = dest = sqlite3_malloc(avail);
01102     stream.avail_out = avail;
01103     stream.opaque = 0;
01104     if (!dest) {
01105         goto oom;
01106     }
01107     if (inflateInit2(&stream, -15) != Z_OK) {
01108         goto nomem;
01109     }
01110     dlength = 0;
01111     while (1) {
01112         err = inflate(&stream, Z_SYNC_FLUSH);
01113         if ((err == Z_STREAM_END) ||
01114             ((err == Z_OK) && (stream.avail_in == 0))) {
01115             dlength += length - stream.avail_out;
01116             newdest = sqlite3_realloc(dest, dlength);
01117             inflateEnd(&stream);
01118             if (!newdest) {
01119 nomem:
01120                 if (dest) {
01121                     sqlite3_free(dest);
01122                 }
01123 oom:
01124                 sqlite3_result_error_nomem(ctx);
01125                 return;
01126             }
01127             sqlite3_result_blob(ctx, newdest, dlength, sqlite3_free);
01128             return;
01129         }
01130         if ((err == Z_BUF_ERROR) || (err == Z_OK)) {
01131             newdest = sqlite3_realloc(dest, avail + length);
01132             dlength += length - stream.avail_out;
01133             if (!newdest) {
01134                 inflateEnd(&stream);
01135                 goto nomem;
01136             }
01137             avail += length;
01138             stream.next_out = newdest + (stream.next_out - dest);
01139             dest = newdest;
01140             stream.avail_out += length;
01141         } else {
01142             inflateEnd(&stream);
01143             sqlite3_free(dest);
01144             sqlite3_result_error(ctx, "inflate error", -1);
01145             return;
01146         }
01147     }
01148 }
01149 
01157 static void
01158 zip_deflate_func(sqlite3_context *ctx, int argc, sqlite3_value **argv)
01159 {
01160     int err, level = 9;
01161     unsigned long avail, length;
01162     unsigned char *data, *dest = 0;
01163     z_stream stream;
01164 
01165     if ((argc < 1) || (argc > 2)) {
01166         sqlite3_result_error(ctx, "need one or two arguments", -1);
01167         return;
01168     }
01169     if (argc > 1) {
01170         level = sqlite3_value_int(argv[1]);
01171     }
01172     data = (unsigned char *) sqlite3_value_blob(argv[0]);
01173     length = sqlite3_value_bytes(argv[0]);
01174     stream.zalloc = Z_NULL;
01175     stream.zfree = Z_NULL;
01176     stream.next_in = data;
01177     stream.avail_in = length;
01178     stream.next_out = 0;
01179     stream.avail_out = 0;
01180     stream.opaque = 0;
01181     if (deflateInit2(&stream, level, Z_DEFLATED, -15, 8,
01182                      Z_DEFAULT_STRATEGY) != Z_OK) {
01183         goto deflerr;
01184     }
01185     avail = deflateBound(&stream, length);
01186     if (avail == 0) {
01187         sqlite3_result_null(ctx);
01188         return;
01189     }
01190     stream.next_out = dest = sqlite3_malloc(avail);
01191     stream.avail_out = avail;
01192     if (!dest) {
01193         sqlite3_result_error_nomem(ctx);
01194         return;
01195     }
01196     err = deflate(&stream, Z_FINISH);
01197     if (err != Z_STREAM_END) {
01198         deflateEnd(&stream);
01199 deflerr:
01200         if (dest) {
01201             sqlite3_free(dest);
01202         }
01203         sqlite3_result_error(ctx, "deflate error", -1);
01204         return;
01205     }
01206     length = stream.total_out;
01207     err = deflateEnd(&stream);
01208     if (err != Z_OK) {
01209         goto deflerr;
01210     }
01211     sqlite3_result_blob(ctx, dest, length, sqlite3_free);
01212 }
01213 
01221 static void
01222 zip_compress_func(sqlite3_context *ctx, int argc, sqlite3_value **argv)
01223 {
01224     int err, level = 9;
01225     unsigned long length, dlength;
01226     unsigned char *data, *dest;
01227 
01228     if ((argc < 1) || (argc > 2)) {
01229         sqlite3_result_error(ctx, "need one or two arguments", -1);
01230         return;
01231     }
01232     if (argc > 1) {
01233         level = sqlite3_value_int(argv[1]);
01234     }
01235     data = (unsigned char *) sqlite3_value_blob(argv[0]);
01236     length = sqlite3_value_bytes(argv[0]);
01237     dlength = compressBound(length);
01238     dest = sqlite3_malloc(dlength);
01239     if (!dest) {
01240         sqlite3_result_error_nomem(ctx);
01241         return;
01242     }
01243     err = compress2(dest, &dlength, data, length, level);
01244     if (err == Z_OK) {
01245         sqlite3_result_blob(ctx, dest, dlength, sqlite3_free);
01246         return;
01247     }
01248     if (err == Z_MEM_ERROR) {
01249         sqlite3_result_error(ctx, "memory error", -1);
01250     } else if (err == Z_BUF_ERROR) {
01251         sqlite3_result_error(ctx, "buffer error", -1);
01252     } else {
01253         sqlite3_result_error(ctx, "compress error", -1);
01254     }
01255     sqlite3_free(dest);
01256 }
01257 
01258 #ifdef SQLITE_OPEN_URI
01259 
01267 static mem_blk *
01268 mem_createmb(const unsigned char *data, unsigned long length)
01269 {
01270     mem_blk *mb;
01271 #if defined(_WIN32) || defined(_WIN64)
01272     HANDLE mh;
01273 #else
01274     long psize;
01275 #endif
01276     unsigned long size;
01277 
01278 #if defined(_WIN32) || defined(_WIN64)
01279     size = sizeof (mem_blk) + length;
01280     mh = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE,
01281                            0, size, 0);
01282     if (mh == INVALID_HANDLE_VALUE) {
01283         return 0;
01284     }
01285     mb = (mem_blk *) MapViewOfFile(mh, FILE_MAP_ALL_ACCESS, 0, 0, length);
01286     if (!mb) {
01287         return 0;
01288     }
01289 #else
01290     psize = sysconf(_SC_PAGESIZE);
01291 #ifdef linux
01292     mb = (mem_blk *) sqlite3_malloc(sizeof (mem_blk));
01293     if (!mb) {
01294         return 0;
01295     }
01296     size = length + 1;
01297     mb->data = (unsigned char *) mmap(0, size, PROT_READ | PROT_WRITE,
01298                                       MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
01299     if (mb->data == MAP_FAILED) {
01300         sqlite3_free(mb);
01301         return 0;
01302     }
01303 #else
01304     size = sizeof (mem_blk) + psize + length + 1;
01305     mb = (mem_blk *) mmap(0, size, PROT_READ | PROT_WRITE,
01306                           MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
01307     if (mb == MAP_FAILED) {
01308         return 0;
01309     }
01310 #endif
01311 #endif
01312     if (mb) {
01313         memcpy(mb->magic, MEM_MAGIC, 4);
01314         mb->opened = 1;
01315         mb->size = size;
01316         mb->length = length;
01317 #if defined(_WIN32) || defined(_WIN64)
01318         mb->mh = mh;
01319         mb->data = (unsigned char *) (mb + 1);
01320         memcpy(mb->data, data, length);
01321 #else
01322         mb->psize = psize;
01323 #ifdef linux
01324         mb->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
01325         sqlite3_mutex_enter(mb->mutex);
01326         mb->lcnt = 0;
01327         memcpy(mb->data, data, length);
01328 #else
01329         if (psize >= sizeof (mem_blk)) {
01330             mb->data = (unsigned char *) mb + psize;
01331             memcpy(mb->data, data, length);
01332 #ifndef linux
01333             mprotect(mb->data, length, PROT_READ);
01334 #endif
01335         } else {
01336             mb->data = (unsigned char *) (mb + 1);
01337             memcpy(mb->data, data, length);
01338         }
01339 #endif
01340 #endif
01341     }
01342     return mb;
01343 }
01344 
01350 static void
01351 mem_destroymb(mem_blk *mb)
01352 {
01353 #if defined(_WIN32) || defined(_WIN64)
01354     HANDLE mh;
01355 #endif
01356 
01357     if (mb) {
01358         memset(mb->magic, 0, 4);
01359 #if defined(_WIN32) || defined(_WIN64)
01360         mh = mb->mh;
01361         UnmapViewOfFile(mb);
01362         CloseHandle(mh);
01363 #else
01364 #ifdef linux
01365         munmap(mb->data, mb->size);
01366         sqlite3_mutex_leave(mb->mutex);
01367         sqlite3_mutex_free(mb->mutex);
01368         sqlite3_free(mb);
01369 #else
01370         munmap(mb, mb->size);
01371 #endif
01372 #endif
01373     }
01374 }
01375 
01382 static int
01383 mem_close(sqlite3_file *file)
01384 {
01385     mem_file *mf = (mem_file *) file;
01386     mem_blk *mb = mf->mb;
01387 
01388     if (mb) {
01389 #ifdef linux
01390         sqlite3_mutex_enter(mb->mutex);
01391         if (mf->lock > 0) {
01392             mb->lcnt = 0;
01393         }
01394 #endif
01395         mb->opened--;
01396         if (mb->opened <= 0) {
01397             mem_destroymb(mb);
01398         }
01399 #ifdef linux
01400         else {
01401             sqlite3_mutex_leave(mb->mutex);
01402         }
01403 #endif
01404         mf->mb = 0;
01405     }
01406     return SQLITE_OK;
01407 }
01408 
01418 static int
01419 mem_read(sqlite3_file *file, void *buf, int len, sqlite_int64 offs)
01420 {
01421     mem_file *mf = (mem_file *) file;
01422     mem_blk *mb = mf->mb;
01423     int rc = SQLITE_IOERR_READ;
01424 
01425 #ifdef linux
01426     if (mb) {
01427         sqlite3_mutex_enter(mb->mutex);
01428     }
01429 #endif
01430     if (mb && (offs <= mb->length)) {
01431         rc = SQLITE_OK;
01432         if (offs + len > mb->length) {
01433             rc = SQLITE_IOERR_SHORT_READ;
01434             len = mb->length - offs;
01435         }
01436         memcpy(buf, mb->data + offs, len);
01437     }
01438 #ifdef linux
01439     if (mb) {
01440         sqlite3_mutex_leave(mb->mutex);
01441     }
01442 #endif
01443     return rc;
01444 }
01445 
01453 static int
01454 #ifdef linux
01455 mem_truncate_unlocked(sqlite3_file *file, sqlite_int64 offs)
01456 #else
01457 mem_truncate(sqlite3_file *file, sqlite_int64 offs)
01458 #endif
01459 {
01460 #ifdef linux
01461     mem_file *mf = (mem_file *) file;
01462     mem_blk *mb = mf->mb;
01463     unsigned char *p;
01464     long psize = mb->psize;
01465     unsigned long length = offs;
01466     unsigned long size;
01467 
01468     size = length + 1;
01469     if ((psize > 0) && (size / psize == mb->size / psize)) {
01470         p = mb->data;
01471     } else {
01472         p = mremap(mb->data, mb->size, size, MREMAP_MAYMOVE);
01473     }
01474     if (p == MAP_FAILED) {
01475         return SQLITE_IOERR_TRUNCATE;
01476     }
01477     mb->size = size;
01478     mb->length = length;
01479     mb->data = p;
01480     return SQLITE_OK;
01481 #else
01482     return SQLITE_IOERR_TRUNCATE;
01483 #endif
01484 }
01485 
01486 #ifdef linux
01487 static int
01488 mem_truncate(sqlite3_file *file, sqlite_int64 offs)
01489 {
01490     mem_file *mf = (mem_file *) file;
01491     mem_blk *mb = mf->mb;
01492     int rc = SQLITE_IOERR_TRUNCATE;
01493 
01494     if (mb) {
01495         sqlite3_mutex_enter(mb->mutex);
01496         rc = mem_truncate_unlocked(file, offs);
01497         sqlite3_mutex_leave(mb->mutex);
01498     }
01499     return rc;
01500 }
01501 #endif
01502 
01512 static int
01513 mem_write(sqlite3_file *file, const void *buf, int len, sqlite_int64 offs)
01514 {
01515 #ifdef linux
01516     mem_file *mf = (mem_file *) file;
01517     mem_blk *mb = mf->mb;
01518 
01519     sqlite3_mutex_enter(mb->mutex);
01520     if (offs + len > mb->length) {
01521         if (mem_truncate_unlocked(file, offs + len) != SQLITE_OK) {
01522             sqlite3_mutex_leave(mb->mutex);
01523             return SQLITE_IOERR_WRITE;
01524         }
01525     }
01526     memcpy(mb->data + offs, buf, len);
01527     sqlite3_mutex_leave(mb->mutex);
01528     return SQLITE_OK;
01529 #else
01530     return SQLITE_IOERR_WRITE;
01531 #endif
01532 }
01533 
01541 static int
01542 mem_sync(sqlite3_file *file, int flags)
01543 {
01544 #ifdef linux
01545     return SQLITE_OK;
01546 #else
01547     return SQLITE_IOERR_FSYNC;
01548 #endif
01549 }
01550 
01558 static int
01559 mem_filesize(sqlite3_file *file, sqlite_int64 *size)
01560 {
01561     mem_file *mf = (mem_file *) file;
01562     mem_blk *mb = mf->mb;
01563 
01564     if (mb) {
01565 #ifdef linux
01566         sqlite3_mutex_enter(mb->mutex);
01567 #endif
01568         *size = mb->length;
01569 #ifdef linux
01570         sqlite3_mutex_leave(mb->mutex);
01571 #endif
01572         return SQLITE_OK;
01573     }
01574     return SQLITE_IOERR_FSTAT;
01575 }
01576 
01584 static int
01585 mem_lock(sqlite3_file *file, int lck)
01586 {
01587 #ifdef linux
01588     mem_file *mf = (mem_file *) file;
01589     mem_blk *mb = mf->mb;
01590     int rc = SQLITE_IOERR_LOCK;
01591 
01592     if (mb) {
01593         sqlite3_mutex_enter(mb->mutex);
01594         if (lck > 0) {
01595             rc = SQLITE_BUSY;
01596             if ((mf->lock == 0) && (mb->lcnt == 0)) {
01597                 mb->lcnt = 1;
01598                 mf->lock = lck;
01599                 rc = SQLITE_OK;
01600             } else if ((mf->lock > 0) && (mb->lcnt == 1)) {
01601                 mf->lock = lck;
01602                 rc = SQLITE_OK;
01603             }
01604         }
01605         sqlite3_mutex_leave(mb->mutex);
01606     }
01607     return rc;
01608 #else
01609     return SQLITE_OK;
01610 #endif
01611 }
01612 
01620 static int
01621 mem_unlock(sqlite3_file *file, int lck)
01622 {
01623 #ifdef linux
01624     mem_file *mf = (mem_file *) file;
01625     mem_blk *mb = mf->mb;
01626     int rc = SQLITE_IOERR_UNLOCK;
01627 
01628     if (mb) {
01629         sqlite3_mutex_enter(mb->mutex);
01630         if (mf->lock == lck) {
01631             rc = SQLITE_OK;
01632         } else if (lck == 0) {
01633             if (mf->lock) {
01634                 mb->lcnt = 0;
01635                 mf->lock = 0;
01636             }
01637             rc = SQLITE_OK;
01638         } else if ((lck < mf->lock) && (mb->lcnt != 0)) {
01639             mf->lock = lck;
01640             rc = SQLITE_OK;
01641         }
01642         sqlite3_mutex_leave(mb->mutex);
01643     }
01644     return rc;
01645 #else
01646     return SQLITE_OK;
01647 #endif
01648 }
01649 
01657 static int
01658 mem_checkreservedlock(sqlite3_file *file, int *out)
01659 {
01660 #ifdef linux
01661     mem_file *mf = (mem_file *) file;
01662     mem_blk *mb = mf->mb;
01663     int rc = SQLITE_IOERR_CHECKRESERVEDLOCK;
01664 
01665     if (mb) {
01666         sqlite3_mutex_enter(mb->mutex);
01667         *out = mf->lock >= 2;
01668         sqlite3_mutex_leave(mb->mutex);
01669         rc = SQLITE_OK;
01670     } else {
01671         *out = 0;
01672     }
01673     return rc;
01674 #else
01675     *out = 0;
01676     return SQLITE_OK;
01677 #endif
01678 }
01679 
01688 static int
01689 mem_filecontrol(sqlite3_file *file, int op, void *arg)
01690 {
01691 #ifdef SQLITE_FCNTL_PRAGMA
01692     if (op == SQLITE_FCNTL_PRAGMA) {
01693         return SQLITE_NOTFOUND;
01694     }
01695 #endif
01696     return SQLITE_OK;
01697 }
01698 
01705 static int
01706 mem_sectorsize(sqlite3_file *file)
01707 {
01708     return 4096;
01709 }
01710 
01717 static int
01718 mem_devicecharacteristics(sqlite3_file *file)
01719 {
01720     return 0;
01721 }
01722 
01727 static sqlite3_io_methods mem_methods = {
01728     1,                          /* iVersion */
01729     mem_close,                  /* xClose */
01730     mem_read,                   /* xRead */
01731     mem_write,                  /* xWrite */
01732     mem_truncate,               /* xTruncate */
01733     mem_sync,                   /* xSync */
01734     mem_filesize,               /* xFileSize */
01735     mem_lock,                   /* xLock */
01736     mem_unlock,                 /* xUnlock */
01737     mem_checkreservedlock,      /* xCheckReservedLock */
01738     mem_filecontrol,            /* xFileControl */
01739     mem_sectorsize,             /* xSectorSize */
01740     mem_devicecharacteristics   /* xDeviceCharacteristics */
01741 };
01742 
01753 static int
01754 mem_open(sqlite3_vfs *vfs, const char *name, sqlite3_file *file,
01755          int flags, int *outflags)
01756 {
01757     mem_file *mf = (mem_file *) file;
01758     mem_blk *mb = 0;
01759 #ifdef _WIN64
01760     unsigned long long t = 0;
01761 #else
01762     unsigned long t = 0;
01763 #endif
01764 #if !defined(_WIN32) && !defined(_WIN64)
01765     mem_blk mb0;
01766     int pfd[2];
01767     int n;
01768 #endif
01769 
01770     if (!name) {
01771         return SQLITE_IOERR;
01772     }
01773     if (flags & (SQLITE_OPEN_MAIN_JOURNAL |
01774                  SQLITE_OPEN_WAL |
01775 #ifndef linux
01776                  SQLITE_OPEN_READWRITE |
01777 #endif
01778                  SQLITE_OPEN_CREATE)) {
01779         return SQLITE_CANTOPEN;
01780     }
01781 #ifdef _WIN64
01782     sscanf(name + 1, "%I64x", &t);
01783 #else
01784     t = strtoul(name + 1, 0, 16);
01785 #endif
01786     mb = (mem_blk *) t;
01787     if (!mb) {
01788         return SQLITE_CANTOPEN;
01789     }
01790 #if !defined(_WIN32) && !defined(_WIN64)
01791     if (pipe(pfd) < 0) {
01792         return SQLITE_CANTOPEN;
01793     }
01794     n = (write(pfd[1], (char *) mb, sizeof (mem_blk)) < 0) ? errno : 0;
01795     if (n == EFAULT) {
01796 cantopen:
01797         close(pfd[0]);
01798         close(pfd[1]);
01799         return SQLITE_CANTOPEN;
01800     }
01801     n = read(pfd[0], (char *) &mb0, sizeof (mem_blk));
01802     if (n != sizeof (mem_blk)) {
01803         goto cantopen;
01804     }
01805     if (memcmp(mb0.magic, MEM_MAGIC, 4) == 0) {
01806 #ifdef linux
01807         n = (write(pfd[1], (char *) mb0.data, 1) < 0) ? errno : 0;
01808         if (n == EFAULT) {
01809             goto cantopen;
01810         }
01811 #endif
01812         if (mb0.length > 0) {
01813             n = (write(pfd[1], (char *) mb0.data + mb0.length - 1, 1) < 0)
01814               ? errno : 0;
01815             if (n == EFAULT) {
01816                 goto cantopen;
01817             }
01818         }
01819         close(pfd[0]);
01820         close(pfd[1]);
01821 #ifdef linux
01822         sqlite3_mutex_enter(mb->mutex);
01823 #endif
01824         mb->opened++;
01825 #ifdef linux
01826         sqlite3_mutex_leave(mb->mutex);
01827 #endif
01828     } else {
01829         goto cantopen;
01830     }
01831 #else
01832     if (memcmp(mb->magic, MEM_MAGIC, 4) == 0) {
01833         mb->opened++;
01834     } else {
01835         return SQLITE_CANTOPEN;
01836     }
01837 #endif
01838     memset(mf, 0, sizeof (mem_file));
01839     mf->mb = mb;
01840     mf->base.pMethods = &mem_methods;
01841     if (outflags) {
01842         *outflags = flags;
01843     }
01844     return SQLITE_OK;
01845 }
01846 
01855 static int
01856 mem_delete(sqlite3_vfs *vfs, const char *name, int sync)
01857 {
01858     return SQLITE_IOERR_DELETE;
01859 }
01860 
01870 static int
01871 mem_access(sqlite3_vfs *vfs, const char *name, int flags, int *outflags)
01872 {
01873     char *endp = 0;
01874     unsigned long t;
01875 
01876     t = strtol(name + 1, &endp, 16);
01877     if ((t == 0) ||
01878 #ifndef linux
01879         (flags == SQLITE_ACCESS_READWRITE) ||
01880 #endif
01881         !endp || endp[0]) {
01882         *outflags = 0;
01883     } else {
01884         *outflags = 1;
01885     }
01886     return SQLITE_OK;
01887 }
01888 
01898 static int
01899 mem_fullpathname(sqlite3_vfs *vfs, const char *name, int len, char *out)
01900 {
01901     strncpy(out, name, len);
01902     out[len - 1] = '\0';
01903     return SQLITE_OK;
01904 }
01905 
01913 static void *
01914 mem_dlopen(sqlite3_vfs *vfs, const char *name)
01915 {
01916     return 0;
01917 }
01918 
01926 static void
01927 mem_dlerror(sqlite3_vfs *vfs, int len, char *out)
01928 {
01929     static const char *errtxt = "Loadable extensions are not supported";
01930 
01931     strncpy(out, errtxt, strlen(errtxt));
01932     out[len - 1] = '\0';
01933 }
01934 
01943 static void
01944 (*mem_dlsym(sqlite3_vfs *vfs, void *handle, const char *sym))(void)
01945 {
01946     return 0;
01947 }
01948 
01955 static void
01956 mem_dlclose(sqlite3_vfs *vfs, void *handle)
01957 {
01958 }
01959 
01968 static int
01969 mem_randomness(sqlite3_vfs *vfs, int len, char *out)
01970 {
01971     sqlite3_vfs *ovfs = (sqlite3_vfs *) vfs->pAppData;
01972 
01973     return ovfs->xRandomness(ovfs, len, out);
01974 }
01975 
01983 static int
01984 mem_sleep(sqlite3_vfs *vfs, int micro)
01985 {
01986     sqlite3_vfs *ovfs = (sqlite3_vfs *) vfs->pAppData;
01987 
01988     return ovfs->xSleep(ovfs, micro);
01989 }
01990 
01998 static int
01999 mem_currenttime(sqlite3_vfs *vfs, double *out)
02000 {
02001     sqlite3_vfs *ovfs = (sqlite3_vfs *) vfs->pAppData;
02002 
02003     return ovfs->xCurrentTime(ovfs, out);
02004 }
02005 
02010 static sqlite3_vfs mem_vfs = {
02011     1,                  /* iVersion */
02012     sizeof (mem_file),  /* szOsFile */
02013     256,                /* mxPathname */
02014     0,                  /* pNext */
02015     mem_vfs_name,       /* zName */
02016     0,                  /* pAppData */
02017     mem_open,           /* xOpen */
02018     mem_delete,         /* xDelete */
02019     mem_access,         /* xAccess */
02020     mem_fullpathname,   /* xFullPathname */
02021     mem_dlopen,         /* xDlOpen */
02022     mem_dlerror,        /* xDlError */
02023     mem_dlsym,          /* xDlSym */
02024     mem_dlclose,        /* xDlClose */
02025     mem_randomness,     /* xDlError */
02026     mem_sleep,          /* xDlSym */
02027     mem_currenttime     /* xDlClose */
02028 };
02029 
02054 static void
02055 blob_attach_func(sqlite3_context *ctx, int argc, sqlite3_value **argv)
02056 {
02057     unsigned long length;
02058     const unsigned char *data;
02059     mem_blk *mb = 0;
02060     char *sql = 0;
02061     int sqllen = 0;
02062 #ifdef linux
02063     int isrw = 0;
02064 #endif
02065 
02066     if (argc != 2) {
02067         sqlite3_result_error(ctx, "need two arguments", -1);
02068         return;
02069     }
02070     data = (const unsigned char *) sqlite3_value_blob(argv[0]);
02071     length = sqlite3_value_bytes(argv[0]);
02072     if (!data || !length) {
02073         sqlite3_result_error(ctx, "empty blob", -1);
02074         return;
02075     }
02076     mb = mem_createmb(data, length);
02077     if (!mb) {
02078         sqlite3_result_error(ctx, "cannot map blob", -1);
02079         return;
02080     }
02081     sql = sqlite3_mprintf("ATTACH "
02082 #ifdef _WIN64
02083                           "'file:/%llX"
02084 #else
02085                           "'file:/%lX"
02086 #endif
02087                           "?vfs=%s&"
02088 #ifdef linux
02089                           "mode=rw&"
02090 #else
02091                           "mode=ro&"
02092 #endif
02093                           "cache=private' AS %Q",
02094 #ifdef _WIN64
02095                           (unsigned long long) mb,
02096 #else
02097                           (unsigned long) mb,
02098 #endif
02099                           mem_vfs_name,
02100                           (char *) sqlite3_value_text(argv[1]));
02101     if (!sql) {
02102         sqlite3_result_error(ctx, "cannot map blob", -1);
02103         mem_destroymb(mb);
02104         return;
02105     }
02106 #ifdef linux
02107     sqlite3_mutex_leave(mb->mutex);
02108 #endif
02109     if (sqlite3_exec(sqlite3_context_db_handle(ctx), sql, 0, 0, 0)
02110         != SQLITE_OK) {
02111         sqlite3_free(sql);
02112         sqlite3_result_error(ctx, "cannot attach blob", -1);
02113 #ifdef linux
02114         sqlite3_mutex_enter(mb->mutex);
02115 #endif
02116         mem_destroymb(mb);
02117         return;
02118     }
02119     sqllen = strlen(sql);
02120     sqlite3_snprintf(sqllen, sql, "PRAGMA %Q.synchronous = OFF",
02121                      (char *) sqlite3_value_text(argv[1]));
02122     sqlite3_exec(sqlite3_context_db_handle(ctx), sql, 0, 0, 0);
02123 #ifdef linux
02124     sqlite3_snprintf(sqllen, sql, "PRAGMA %Q.journal_mode = OFF",
02125                      (char *) sqlite3_value_text(argv[1]));
02126     if (sqlite3_exec(sqlite3_context_db_handle(ctx), sql, 0, 0, 0)
02127         == SQLITE_OK) {
02128         isrw = 1;
02129     }
02130 #endif
02131 #ifdef linux
02132     sqlite3_mutex_enter(mb->mutex);
02133 #endif
02134     if (--mb->opened < 1) {
02135         sqlite3_snprintf(sqllen, sql, "DETACH %Q",
02136                          (char *) sqlite3_value_text(argv[1]));
02137         sqlite3_exec(sqlite3_context_db_handle(ctx), sql, 0, 0, 0);
02138         sqlite3_free(sql);
02139         sqlite3_result_error(ctx, "cannot attach blob", -1);
02140         mem_destroymb(mb);
02141         return;
02142     }
02143 #ifdef linux
02144     sqlite3_mutex_leave(mb->mutex);
02145     if (isrw) {
02146         sqlite3_snprintf(sqllen, sql,
02147                          "file:/%lX?vfs=%s&mode=rw&cache=private",
02148                          (unsigned long) mb, mem_vfs_name);
02149         sqlite3_result_text(ctx, sql, -1, sqlite3_free);
02150         return;
02151     }
02152 #endif
02153     sqlite3_free(sql);
02154     sqlite3_result_null(ctx);
02155 }
02156 
02174 static void
02175 blob_dump_func(sqlite3_context *ctx, int argc, sqlite3_value **argv)
02176 {
02177     char *uri, vfs[64];
02178 #ifdef _WIN64
02179     unsigned long long addr = 0;
02180 #else
02181     unsigned long addr = 0;
02182 #endif
02183 #ifdef linux
02184     int pfd[2], n;
02185     mem_blk *mb;
02186 #endif
02187 
02188     if (argc != 1) {
02189         sqlite3_result_error(ctx, "need one argument", -1);
02190         return;
02191     }
02192     uri = (char *) sqlite3_value_text(argv[0]);
02193     vfs[0] = '\0';
02194     if (!uri || (sscanf(uri,
02195 #ifdef _WIN64
02196                         "file:/%I64X?vfs=%63[^&]",
02197 #else
02198                         "file:/%lX?vfs=%63[^&]",
02199 #endif
02200                         &addr, vfs) != 2)) {
02201 inval:
02202         sqlite3_result_error(ctx, "invalid object", -1);
02203         return;
02204     }
02205     vfs[63] = '\0';
02206     if ((strcmp(mem_vfs_name, vfs) != 0) || (addr == 0)) {
02207         goto inval;
02208     }
02209 #ifdef linux
02210     if (pipe(pfd) < 0) {
02211         goto inval;
02212     }
02213     n = (write(pfd[1], (char *) addr, 1) < 0) ? errno : 0;
02214     close(pfd[0]);
02215     close(pfd[1]);
02216     if (n == EFAULT) {
02217         goto inval;
02218     }
02219     mb = (mem_blk *) addr;
02220     if (memcmp(mb->magic, MEM_MAGIC, 4) != 0) {
02221         goto inval;
02222     }
02223     sqlite3_mutex_enter(mb->mutex);
02224     sqlite3_result_blob(ctx, mb->data, mb->length, SQLITE_STATIC);
02225     sqlite3_mutex_leave(mb->mutex);
02226 #else
02227     sqlite3_result_error(ctx, "unsupported function", -1);
02228 #endif
02229 }
02230 
02231 #endif /* SQLITE_OPEN_URI */
02232 
02239 #ifndef STANDALONE
02240 static
02241 #endif
02242 int
02243 zip_vtab_init(sqlite3 *db)
02244 {
02245     sqlite3_create_function(db, "crc32", 1, SQLITE_UTF8,
02246                             (void *) db, zip_crc32_func, 0, 0);
02247     sqlite3_create_function(db, "inflate", 1, SQLITE_UTF8,
02248                             (void *) db, zip_inflate_func, 0, 0);
02249     sqlite3_create_function(db, "deflate", 1, SQLITE_UTF8,
02250                             (void *) db, zip_deflate_func, 0, 0);
02251     sqlite3_create_function(db, "uncompress", 1, SQLITE_UTF8,
02252                             (void *) db, zip_inflate_func, 0, 0);
02253     sqlite3_create_function(db, "compress", -1, SQLITE_UTF8,
02254                             (void *) db, zip_compress_func, 0, 0);
02255 #ifdef SQLITE_OPEN_URI
02256     if (!mem_vfs.pAppData) {
02257         sqlite3_vfs *parent = sqlite3_vfs_find(0);
02258 
02259         if (parent) {
02260             sqlite3_snprintf(sizeof (mem_vfs_name), mem_vfs_name,
02261 #ifdef _WIN64
02262                              "mem_vfs_%llX", (unsigned long long) &mem_vfs
02263 #else
02264                              "mem_vfs_%lX", (unsigned long) &mem_vfs
02265 #endif
02266                             );
02267             if (sqlite3_vfs_register(&mem_vfs, 0) == SQLITE_OK) {
02268                 mem_vfs.pAppData = (void *) parent;
02269             }
02270         }
02271     }
02272     if (mem_vfs.pAppData) {
02273         sqlite3_create_function(db, "blob_attach", 2, SQLITE_UTF8,
02274                                 (void *) db, blob_attach_func, 0, 0);
02275         sqlite3_create_function(db, "blob_dump", 1, SQLITE_UTF8,
02276                                 (void *) db, blob_dump_func, 0, 0);
02277     }
02278 #endif
02279     return sqlite3_create_module(db, "zipfile", &zip_vtab_mod, 0);
02280 }
02281 
02282 #ifndef STANDALONE
02283 
02292 int
02293 sqlite3_extension_init(sqlite3 *db, char **errmsg,
02294                        const sqlite3_api_routines *api)
02295 {
02296     SQLITE_EXTENSION_INIT2(api);
02297     return zip_vtab_init(db);
02298 }
02299 
02300 #endif

Generated on 23 Oct 2023 by doxygen.
Contact: chw@ch-werner.de