| | @@ -2074,11 +2074,11 @@ |
| 2074 | 2074 | # define dirent DIRENT |
| 2075 | 2075 | # ifndef stat |
| 2076 | 2076 | # define stat _stat |
| 2077 | 2077 | # endif |
| 2078 | 2078 | # define mkdir(path,mode) _mkdir(path) |
| 2079 | | -# define lstat(path,buf) _stat(path,buf) |
| 2079 | +# define lstat(path,buf) stat(path,buf) |
| 2080 | 2080 | #endif |
| 2081 | 2081 | #include <time.h> |
| 2082 | 2082 | #include <errno.h> |
| 2083 | 2083 | |
| 2084 | 2084 | |
| | @@ -4998,17 +4998,22 @@ |
| 4998 | 4998 | } |
| 4999 | 4999 | |
| 5000 | 5000 | return rc; |
| 5001 | 5001 | } |
| 5002 | 5002 | |
| 5003 | | -static int zipfileGetMode(ZipfileTab *pTab, sqlite3_value *pVal, int *pMode){ |
| 5003 | +static int zipfileGetMode( |
| 5004 | + ZipfileTab *pTab, |
| 5005 | + sqlite3_value *pVal, |
| 5006 | + u32 defaultMode, /* Value to use if pVal IS NULL */ |
| 5007 | + u32 *pMode |
| 5008 | +){ |
| 5004 | 5009 | const char *z = (const char*)sqlite3_value_text(pVal); |
| 5005 | | - int mode = 0; |
| 5010 | + u32 mode = 0; |
| 5006 | 5011 | if( z==0 ){ |
| 5007 | | - mode = 33188; /* -rw-r--r-- */ |
| 5012 | + mode = defaultMode; |
| 5008 | 5013 | }else if( z[0]>=0 && z[0]<=9 ){ |
| 5009 | | - mode = sqlite3_value_int(pVal); |
| 5014 | + mode = (unsigned int)sqlite3_value_int(pVal); |
| 5010 | 5015 | }else{ |
| 5011 | 5016 | const char zTemplate[11] = "-rwxrwxrwx"; |
| 5012 | 5017 | int i; |
| 5013 | 5018 | if( strlen(z)!=10 ) goto parse_error; |
| 5014 | 5019 | switch( z[0] ){ |
| | @@ -5043,20 +5048,24 @@ |
| 5043 | 5048 | ){ |
| 5044 | 5049 | ZipfileTab *pTab = (ZipfileTab*)pVtab; |
| 5045 | 5050 | int rc = SQLITE_OK; /* Return Code */ |
| 5046 | 5051 | ZipfileEntry *pNew = 0; /* New in-memory CDS entry */ |
| 5047 | 5052 | |
| 5048 | | - int mode; /* Mode for new entry */ |
| 5053 | + u32 mode; /* Mode for new entry */ |
| 5049 | 5054 | i64 mTime; /* Modification time for new entry */ |
| 5050 | 5055 | i64 sz = 0; /* Uncompressed size */ |
| 5051 | 5056 | const char *zPath; /* Path for new entry */ |
| 5052 | 5057 | int nPath; /* strlen(zPath) */ |
| 5053 | 5058 | const u8 *pData = 0; /* Pointer to buffer containing content */ |
| 5054 | 5059 | int nData = 0; /* Size of pData buffer in bytes */ |
| 5055 | 5060 | int iMethod = 0; /* Compression method for new entry */ |
| 5056 | 5061 | u8 *pFree = 0; /* Free this */ |
| 5057 | 5062 | ZipfileCDS cds; /* New Central Directory Structure entry */ |
| 5063 | + |
| 5064 | + int bIsDir = 0; |
| 5065 | + |
| 5066 | + int mNull; |
| 5058 | 5067 | |
| 5059 | 5068 | assert( pTab->zFile ); |
| 5060 | 5069 | assert( pTab->pWriteFd ); |
| 5061 | 5070 | |
| 5062 | 5071 | if( sqlite3_value_type(apVal[0])!=SQLITE_NULL ){ |
| | @@ -5069,24 +5078,21 @@ |
| 5069 | 5078 | } |
| 5070 | 5079 | } |
| 5071 | 5080 | if( nVal==1 ) return SQLITE_OK; |
| 5072 | 5081 | } |
| 5073 | 5082 | |
| 5074 | | - zPath = (const char*)sqlite3_value_text(apVal[2]); |
| 5075 | | - nPath = (int)strlen(zPath); |
| 5076 | | - rc = zipfileGetMode(pTab, apVal[3], &mode); |
| 5077 | | - if( rc!=SQLITE_OK ) return rc; |
| 5078 | | - if( sqlite3_value_type(apVal[4])==SQLITE_NULL ){ |
| 5079 | | - mTime = (sqlite3_int64)time(0); |
| 5080 | | - }else{ |
| 5081 | | - mTime = sqlite3_value_int64(apVal[4]); |
| 5082 | | - } |
| 5083 | | - |
| 5084 | | - if( sqlite3_value_type(apVal[5])==SQLITE_NULL /* sz */ |
| 5085 | | - && sqlite3_value_type(apVal[6])==SQLITE_NULL /* rawdata */ |
| 5086 | | - && sqlite3_value_type(apVal[7])!=SQLITE_NULL /* data */ |
| 5087 | | - ){ |
| 5083 | + mNull = (sqlite3_value_type(apVal[5])==SQLITE_NULL ? 0x0 : 0x8) /* sz */ |
| 5084 | + + (sqlite3_value_type(apVal[6])==SQLITE_NULL ? 0x0 : 0x4) /* rawdata */ |
| 5085 | + + (sqlite3_value_type(apVal[7])==SQLITE_NULL ? 0x0 : 0x2) /* data */ |
| 5086 | + + (sqlite3_value_type(apVal[8])==SQLITE_NULL ? 0x0 : 0x1); /* method */ |
| 5087 | + if( mNull==0x00 ){ |
| 5088 | + /* All four are NULL - this must be a directory */ |
| 5089 | + bIsDir = 1; |
| 5090 | + } |
| 5091 | + else if( mNull==0x2 || mNull==0x3 ){ |
| 5092 | + /* Value specified for "data", and possibly "method". This must be |
| 5093 | + ** a regular file or a symlink. */ |
| 5088 | 5094 | const u8 *aIn = sqlite3_value_blob(apVal[7]); |
| 5089 | 5095 | int nIn = sqlite3_value_bytes(apVal[7]); |
| 5090 | 5096 | int bAuto = sqlite3_value_type(apVal[8])==SQLITE_NULL; |
| 5091 | 5097 | |
| 5092 | 5098 | iMethod = sqlite3_value_int(apVal[8]); |
| | @@ -5103,16 +5109,14 @@ |
| 5103 | 5109 | pData = aIn; |
| 5104 | 5110 | nData = nIn; |
| 5105 | 5111 | } |
| 5106 | 5112 | } |
| 5107 | 5113 | } |
| 5108 | | - }else |
| 5109 | | - if( sqlite3_value_type(apVal[5])!=SQLITE_NULL /* sz */ |
| 5110 | | - && sqlite3_value_type(apVal[6])!=SQLITE_NULL /* rawdata */ |
| 5111 | | - && sqlite3_value_type(apVal[7])==SQLITE_NULL /* data */ |
| 5112 | | - && sqlite3_value_type(apVal[8])!=SQLITE_NULL /* method */ |
| 5113 | | - ){ |
| 5114 | + } |
| 5115 | + else if( mNull==0x0D ){ |
| 5116 | + /* Values specified for "sz", "rawdata" and "method". In other words, |
| 5117 | + ** pre-compressed data is being inserted. */ |
| 5114 | 5118 | pData = sqlite3_value_blob(apVal[6]); |
| 5115 | 5119 | nData = sqlite3_value_bytes(apVal[6]); |
| 5116 | 5120 | sz = sqlite3_value_int(apVal[5]); |
| 5117 | 5121 | iMethod = sqlite3_value_int(apVal[8]); |
| 5118 | 5122 | if( iMethod<0 || iMethod>65535 ){ |
| | @@ -5119,13 +5123,35 @@ |
| 5119 | 5123 | pTab->base.zErrMsg = sqlite3_mprintf( |
| 5120 | 5124 | "zipfile: invalid compression method: %d", iMethod |
| 5121 | 5125 | ); |
| 5122 | 5126 | rc = SQLITE_ERROR; |
| 5123 | 5127 | } |
| 5124 | | - }else{ |
| 5128 | + } |
| 5129 | + else{ |
| 5125 | 5130 | rc = SQLITE_CONSTRAINT; |
| 5126 | 5131 | } |
| 5132 | + |
| 5133 | + if( rc==SQLITE_OK ){ |
| 5134 | + rc = zipfileGetMode(pTab, apVal[3], |
| 5135 | + (bIsDir ? (S_IFDIR + 0755) : (S_IFREG + 0644)), &mode |
| 5136 | + ); |
| 5137 | + if( rc==SQLITE_OK && (bIsDir == ((mode & S_IFDIR)==0)) ){ |
| 5138 | + /* The "mode" attribute is a directory, but data has been specified. |
| 5139 | + ** Or vice-versa - no data but "mode" is a file or symlink. */ |
| 5140 | + rc = SQLITE_CONSTRAINT; |
| 5141 | + } |
| 5142 | + } |
| 5143 | + |
| 5144 | + if( rc==SQLITE_OK ){ |
| 5145 | + zPath = (const char*)sqlite3_value_text(apVal[2]); |
| 5146 | + nPath = (int)strlen(zPath); |
| 5147 | + if( sqlite3_value_type(apVal[4])==SQLITE_NULL ){ |
| 5148 | + mTime = (sqlite3_int64)time(0); |
| 5149 | + }else{ |
| 5150 | + mTime = sqlite3_value_int64(apVal[4]); |
| 5151 | + } |
| 5152 | + } |
| 5127 | 5153 | |
| 5128 | 5154 | if( rc==SQLITE_OK ){ |
| 5129 | 5155 | /* Create the new CDS record. */ |
| 5130 | 5156 | memset(&cds, 0, sizeof(cds)); |
| 5131 | 5157 | cds.iVersionMadeBy = ZIPFILE_NEWENTRY_MADEBY; |
| 5132 | 5158 | |