xref: /sqlite-3.40.0/ext/misc/fileio.c (revision 621a5e0c)
1 /*
2 ** 2014-06-13
3 **
4 ** The author disclaims copyright to this source code.  In place of
5 ** a legal notice, here is a blessing:
6 **
7 **    May you do good and not evil.
8 **    May you find forgiveness for yourself and forgive others.
9 **    May you share freely, never taking more than you give.
10 **
11 ******************************************************************************
12 **
13 ** This SQLite extension implements SQL functions readfile() and
14 ** writefile(), and eponymous virtual type "fsdir".
15 **
16 ** WRITEFILE(FILE, DATA [, MODE [, MTIME]]):
17 **
18 **   If neither of the optional arguments is present, then this UDF
19 **   function writes blob DATA to file FILE. If successful, the number
20 **   of bytes written is returned. If an error occurs, NULL is returned.
21 **
22 **   If the first option argument - MODE - is present, then it must
23 **   be passed an integer value that corresponds to a POSIX mode
24 **   value (file type + permissions, as returned in the stat.st_mode
25 **   field by the stat() system call). Three types of files may
26 **   be written/created:
27 **
28 **     regular files:  (mode & 0170000)==0100000
29 **     symbolic links: (mode & 0170000)==0120000
30 **     directories:    (mode & 0170000)==0040000
31 **
32 **   For a directory, the DATA is ignored. For a symbolic link, it is
33 **   interpreted as text and used as the target of the link. For a
34 **   regular file, it is interpreted as a blob and written into the
35 **   named file. Regardless of the type of file, its permissions are
36 **   set to (mode & 0777) before returning.
37 **
38 **   If the optional MTIME argument is present, then it is interpreted
39 **   as an integer - the number of seconds since the unix epoch. The
40 **   modification-time of the target file is set to this value before
41 **   returning.
42 **
43 **   If three or more arguments are passed to this function and an
44 **   error is encountered, an exception is raised.
45 **
46 ** READFILE(FILE):
47 **
48 **   Read and return the contents of file FILE (type blob) from disk.
49 **
50 ** FSDIR:
51 **
52 **   Used as follows:
53 **
54 **     SELECT * FROM fsdir($path [, $dir]);
55 **
56 **   Parameter $path is an absolute or relative pathname. If the file that it
57 **   refers to does not exist, it is an error. If the path refers to a regular
58 **   file or symbolic link, it returns a single row. Or, if the path refers
59 **   to a directory, it returns one row for the directory, and one row for each
60 **   file within the hierarchy rooted at $path.
61 **
62 **   Each row has the following columns:
63 **
64 **     name:  Path to file or directory (text value).
65 **     mode:  Value of stat.st_mode for directory entry (an integer).
66 **     mtime: Value of stat.st_mtime for directory entry (an integer).
67 **     data:  For a regular file, a blob containing the file data. For a
68 **            symlink, a text value containing the text of the link. For a
69 **            directory, NULL.
70 **
71 **   If a non-NULL value is specified for the optional $dir parameter and
72 **   $path is a relative path, then $path is interpreted relative to $dir.
73 **   And the paths returned in the "name" column of the table are also
74 **   relative to directory $dir.
75 **
76 ** Notes on building this extension for Windows:
77 **   Unless linked statically with the SQLite library, a preprocessor
78 **   symbol, FILEIO_WIN32_DLL, must be #define'd to create a stand-alone
79 **   DLL form of this extension for WIN32. See its use below for details.
80 */
81 #include "sqlite3ext.h"
82 SQLITE_EXTENSION_INIT1
83 #include <stdio.h>
84 #include <string.h>
85 #include <assert.h>
86 
87 #include <sys/types.h>
88 #include <sys/stat.h>
89 #include <fcntl.h>
90 #if !defined(_WIN32) && !defined(WIN32)
91 #  include <unistd.h>
92 #  include <dirent.h>
93 #  include <utime.h>
94 #  include <sys/time.h>
95 #else
96 #  include "windows.h"
97 #  include <io.h>
98 #  include <direct.h>
99 #  include "test_windirent.h"
100 #  define dirent DIRENT
101 #  ifndef chmod
102 #    define chmod _chmod
103 #  endif
104 #  ifndef stat
105 #    define stat _stat
106 #  endif
107 #  define mkdir(path,mode) _mkdir(path)
108 #  define lstat(path,buf) stat(path,buf)
109 #endif
110 #include <time.h>
111 #include <errno.h>
112 
113 
114 /*
115 ** Structure of the fsdir() table-valued function
116 */
117                  /*    0    1    2     3    4           5             */
118 #define FSDIR_SCHEMA "(name,mode,mtime,data,path HIDDEN,dir HIDDEN)"
119 #define FSDIR_COLUMN_NAME     0     /* Name of the file */
120 #define FSDIR_COLUMN_MODE     1     /* Access mode */
121 #define FSDIR_COLUMN_MTIME    2     /* Last modification time */
122 #define FSDIR_COLUMN_DATA     3     /* File content */
123 #define FSDIR_COLUMN_PATH     4     /* Path to top of search */
124 #define FSDIR_COLUMN_DIR      5     /* Path is relative to this directory */
125 
126 
127 /*
128 ** Set the result stored by context ctx to a blob containing the
129 ** contents of file zName.  Or, leave the result unchanged (NULL)
130 ** if the file does not exist or is unreadable.
131 **
132 ** If the file exceeds the SQLite blob size limit, through an
133 ** SQLITE_TOOBIG error.
134 **
135 ** Throw an SQLITE_IOERR if there are difficulties pulling the file
136 ** off of disk.
137 */
readFileContents(sqlite3_context * ctx,const char * zName)138 static void readFileContents(sqlite3_context *ctx, const char *zName){
139   FILE *in;
140   sqlite3_int64 nIn;
141   void *pBuf;
142   sqlite3 *db;
143   int mxBlob;
144 
145   in = fopen(zName, "rb");
146   if( in==0 ){
147     /* File does not exist or is unreadable. Leave the result set to NULL. */
148     return;
149   }
150   fseek(in, 0, SEEK_END);
151   nIn = ftell(in);
152   rewind(in);
153   db = sqlite3_context_db_handle(ctx);
154   mxBlob = sqlite3_limit(db, SQLITE_LIMIT_LENGTH, -1);
155   if( nIn>mxBlob ){
156     sqlite3_result_error_code(ctx, SQLITE_TOOBIG);
157     fclose(in);
158     return;
159   }
160   pBuf = sqlite3_malloc64( nIn ? nIn : 1 );
161   if( pBuf==0 ){
162     sqlite3_result_error_nomem(ctx);
163     fclose(in);
164     return;
165   }
166   if( nIn==(sqlite3_int64)fread(pBuf, 1, (size_t)nIn, in) ){
167     sqlite3_result_blob64(ctx, pBuf, nIn, sqlite3_free);
168   }else{
169     sqlite3_result_error_code(ctx, SQLITE_IOERR);
170     sqlite3_free(pBuf);
171   }
172   fclose(in);
173 }
174 
175 /*
176 ** Implementation of the "readfile(X)" SQL function.  The entire content
177 ** of the file named X is read and returned as a BLOB.  NULL is returned
178 ** if the file does not exist or is unreadable.
179 */
readfileFunc(sqlite3_context * context,int argc,sqlite3_value ** argv)180 static void readfileFunc(
181   sqlite3_context *context,
182   int argc,
183   sqlite3_value **argv
184 ){
185   const char *zName;
186   (void)(argc);  /* Unused parameter */
187   zName = (const char*)sqlite3_value_text(argv[0]);
188   if( zName==0 ) return;
189   readFileContents(context, zName);
190 }
191 
192 /*
193 ** Set the error message contained in context ctx to the results of
194 ** vprintf(zFmt, ...).
195 */
ctxErrorMsg(sqlite3_context * ctx,const char * zFmt,...)196 static void ctxErrorMsg(sqlite3_context *ctx, const char *zFmt, ...){
197   char *zMsg = 0;
198   va_list ap;
199   va_start(ap, zFmt);
200   zMsg = sqlite3_vmprintf(zFmt, ap);
201   sqlite3_result_error(ctx, zMsg, -1);
202   sqlite3_free(zMsg);
203   va_end(ap);
204 }
205 
206 #if defined(_WIN32)
207 /*
208 ** This function is designed to convert a Win32 FILETIME structure into the
209 ** number of seconds since the Unix Epoch (1970-01-01 00:00:00 UTC).
210 */
fileTimeToUnixTime(LPFILETIME pFileTime)211 static sqlite3_uint64 fileTimeToUnixTime(
212   LPFILETIME pFileTime
213 ){
214   SYSTEMTIME epochSystemTime;
215   ULARGE_INTEGER epochIntervals;
216   FILETIME epochFileTime;
217   ULARGE_INTEGER fileIntervals;
218 
219   memset(&epochSystemTime, 0, sizeof(SYSTEMTIME));
220   epochSystemTime.wYear = 1970;
221   epochSystemTime.wMonth = 1;
222   epochSystemTime.wDay = 1;
223   SystemTimeToFileTime(&epochSystemTime, &epochFileTime);
224   epochIntervals.LowPart = epochFileTime.dwLowDateTime;
225   epochIntervals.HighPart = epochFileTime.dwHighDateTime;
226 
227   fileIntervals.LowPart = pFileTime->dwLowDateTime;
228   fileIntervals.HighPart = pFileTime->dwHighDateTime;
229 
230   return (fileIntervals.QuadPart - epochIntervals.QuadPart) / 10000000;
231 }
232 
233 
234 #if defined(FILEIO_WIN32_DLL) && (defined(_WIN32) || defined(WIN32))
235 #  /* To allow a standalone DLL, use this next replacement function: */
236 #  undef sqlite3_win32_utf8_to_unicode
237 #  define sqlite3_win32_utf8_to_unicode utf8_to_utf16
238 #
utf8_to_utf16(const char * z)239 LPWSTR utf8_to_utf16(const char *z){
240   int nAllot = MultiByteToWideChar(CP_UTF8, 0, z, -1, NULL, 0);
241   LPWSTR rv = sqlite3_malloc(nAllot * sizeof(WCHAR));
242   if( rv!=0 && 0 < MultiByteToWideChar(CP_UTF8, 0, z, -1, rv, nAllot) )
243     return rv;
244   sqlite3_free(rv);
245   return 0;
246 }
247 #endif
248 
249 /*
250 ** This function attempts to normalize the time values found in the stat()
251 ** buffer to UTC.  This is necessary on Win32, where the runtime library
252 ** appears to return these values as local times.
253 */
statTimesToUtc(const char * zPath,struct stat * pStatBuf)254 static void statTimesToUtc(
255   const char *zPath,
256   struct stat *pStatBuf
257 ){
258   HANDLE hFindFile;
259   WIN32_FIND_DATAW fd;
260   LPWSTR zUnicodeName;
261   extern LPWSTR sqlite3_win32_utf8_to_unicode(const char*);
262   zUnicodeName = sqlite3_win32_utf8_to_unicode(zPath);
263   if( zUnicodeName ){
264     memset(&fd, 0, sizeof(WIN32_FIND_DATAW));
265     hFindFile = FindFirstFileW(zUnicodeName, &fd);
266     if( hFindFile!=NULL ){
267       pStatBuf->st_ctime = (time_t)fileTimeToUnixTime(&fd.ftCreationTime);
268       pStatBuf->st_atime = (time_t)fileTimeToUnixTime(&fd.ftLastAccessTime);
269       pStatBuf->st_mtime = (time_t)fileTimeToUnixTime(&fd.ftLastWriteTime);
270       FindClose(hFindFile);
271     }
272     sqlite3_free(zUnicodeName);
273   }
274 }
275 #endif
276 
277 /*
278 ** This function is used in place of stat().  On Windows, special handling
279 ** is required in order for the included time to be returned as UTC.  On all
280 ** other systems, this function simply calls stat().
281 */
fileStat(const char * zPath,struct stat * pStatBuf)282 static int fileStat(
283   const char *zPath,
284   struct stat *pStatBuf
285 ){
286 #if defined(_WIN32)
287   int rc = stat(zPath, pStatBuf);
288   if( rc==0 ) statTimesToUtc(zPath, pStatBuf);
289   return rc;
290 #else
291   return stat(zPath, pStatBuf);
292 #endif
293 }
294 
295 /*
296 ** This function is used in place of lstat().  On Windows, special handling
297 ** is required in order for the included time to be returned as UTC.  On all
298 ** other systems, this function simply calls lstat().
299 */
fileLinkStat(const char * zPath,struct stat * pStatBuf)300 static int fileLinkStat(
301   const char *zPath,
302   struct stat *pStatBuf
303 ){
304 #if defined(_WIN32)
305   int rc = lstat(zPath, pStatBuf);
306   if( rc==0 ) statTimesToUtc(zPath, pStatBuf);
307   return rc;
308 #else
309   return lstat(zPath, pStatBuf);
310 #endif
311 }
312 
313 /*
314 ** Argument zFile is the name of a file that will be created and/or written
315 ** by SQL function writefile(). This function ensures that the directory
316 ** zFile will be written to exists, creating it if required. The permissions
317 ** for any path components created by this function are set in accordance
318 ** with the current umask.
319 **
320 ** If an OOM condition is encountered, SQLITE_NOMEM is returned. Otherwise,
321 ** SQLITE_OK is returned if the directory is successfully created, or
322 ** SQLITE_ERROR otherwise.
323 */
makeDirectory(const char * zFile)324 static int makeDirectory(
325   const char *zFile
326 ){
327   char *zCopy = sqlite3_mprintf("%s", zFile);
328   int rc = SQLITE_OK;
329 
330   if( zCopy==0 ){
331     rc = SQLITE_NOMEM;
332   }else{
333     int nCopy = (int)strlen(zCopy);
334     int i = 1;
335 
336     while( rc==SQLITE_OK ){
337       struct stat sStat;
338       int rc2;
339 
340       for(; zCopy[i]!='/' && i<nCopy; i++);
341       if( i==nCopy ) break;
342       zCopy[i] = '\0';
343 
344       rc2 = fileStat(zCopy, &sStat);
345       if( rc2!=0 ){
346         if( mkdir(zCopy, 0777) ) rc = SQLITE_ERROR;
347       }else{
348         if( !S_ISDIR(sStat.st_mode) ) rc = SQLITE_ERROR;
349       }
350       zCopy[i] = '/';
351       i++;
352     }
353 
354     sqlite3_free(zCopy);
355   }
356 
357   return rc;
358 }
359 
360 /*
361 ** This function does the work for the writefile() UDF. Refer to
362 ** header comments at the top of this file for details.
363 */
writeFile(sqlite3_context * pCtx,const char * zFile,sqlite3_value * pData,mode_t mode,sqlite3_int64 mtime)364 static int writeFile(
365   sqlite3_context *pCtx,          /* Context to return bytes written in */
366   const char *zFile,              /* File to write */
367   sqlite3_value *pData,           /* Data to write */
368   mode_t mode,                    /* MODE parameter passed to writefile() */
369   sqlite3_int64 mtime             /* MTIME parameter (or -1 to not set time) */
370 ){
371   if( zFile==0 ) return 1;
372 #if !defined(_WIN32) && !defined(WIN32)
373   if( S_ISLNK(mode) ){
374     const char *zTo = (const char*)sqlite3_value_text(pData);
375     if( zTo==0 || symlink(zTo, zFile)<0 ) return 1;
376   }else
377 #endif
378   {
379     if( S_ISDIR(mode) ){
380       if( mkdir(zFile, mode) ){
381         /* The mkdir() call to create the directory failed. This might not
382         ** be an error though - if there is already a directory at the same
383         ** path and either the permissions already match or can be changed
384         ** to do so using chmod(), it is not an error.  */
385         struct stat sStat;
386         if( errno!=EEXIST
387          || 0!=fileStat(zFile, &sStat)
388          || !S_ISDIR(sStat.st_mode)
389          || ((sStat.st_mode&0777)!=(mode&0777) && 0!=chmod(zFile, mode&0777))
390         ){
391           return 1;
392         }
393       }
394     }else{
395       sqlite3_int64 nWrite = 0;
396       const char *z;
397       int rc = 0;
398       FILE *out = fopen(zFile, "wb");
399       if( out==0 ) return 1;
400       z = (const char*)sqlite3_value_blob(pData);
401       if( z ){
402         sqlite3_int64 n = fwrite(z, 1, sqlite3_value_bytes(pData), out);
403         nWrite = sqlite3_value_bytes(pData);
404         if( nWrite!=n ){
405           rc = 1;
406         }
407       }
408       fclose(out);
409       if( rc==0 && mode && chmod(zFile, mode & 0777) ){
410         rc = 1;
411       }
412       if( rc ) return 2;
413       sqlite3_result_int64(pCtx, nWrite);
414     }
415   }
416 
417   if( mtime>=0 ){
418 #if defined(_WIN32)
419 #if !SQLITE_OS_WINRT
420     /* Windows */
421     FILETIME lastAccess;
422     FILETIME lastWrite;
423     SYSTEMTIME currentTime;
424     LONGLONG intervals;
425     HANDLE hFile;
426     LPWSTR zUnicodeName;
427     extern LPWSTR sqlite3_win32_utf8_to_unicode(const char*);
428 
429     GetSystemTime(&currentTime);
430     SystemTimeToFileTime(&currentTime, &lastAccess);
431     intervals = Int32x32To64(mtime, 10000000) + 116444736000000000;
432     lastWrite.dwLowDateTime = (DWORD)intervals;
433     lastWrite.dwHighDateTime = intervals >> 32;
434     zUnicodeName = sqlite3_win32_utf8_to_unicode(zFile);
435     if( zUnicodeName==0 ){
436       return 1;
437     }
438     hFile = CreateFileW(
439       zUnicodeName, FILE_WRITE_ATTRIBUTES, 0, NULL, OPEN_EXISTING,
440       FILE_FLAG_BACKUP_SEMANTICS, NULL
441     );
442     sqlite3_free(zUnicodeName);
443     if( hFile!=INVALID_HANDLE_VALUE ){
444       BOOL bResult = SetFileTime(hFile, NULL, &lastAccess, &lastWrite);
445       CloseHandle(hFile);
446       return !bResult;
447     }else{
448       return 1;
449     }
450 #endif
451 #elif defined(AT_FDCWD) && 0 /* utimensat() is not universally available */
452     /* Recent unix */
453     struct timespec times[2];
454     times[0].tv_nsec = times[1].tv_nsec = 0;
455     times[0].tv_sec = time(0);
456     times[1].tv_sec = mtime;
457     if( utimensat(AT_FDCWD, zFile, times, AT_SYMLINK_NOFOLLOW) ){
458       return 1;
459     }
460 #else
461     /* Legacy unix */
462     struct timeval times[2];
463     times[0].tv_usec = times[1].tv_usec = 0;
464     times[0].tv_sec = time(0);
465     times[1].tv_sec = mtime;
466     if( utimes(zFile, times) ){
467       return 1;
468     }
469 #endif
470   }
471 
472   return 0;
473 }
474 
475 /*
476 ** Implementation of the "writefile(W,X[,Y[,Z]]])" SQL function.
477 ** Refer to header comments at the top of this file for details.
478 */
writefileFunc(sqlite3_context * context,int argc,sqlite3_value ** argv)479 static void writefileFunc(
480   sqlite3_context *context,
481   int argc,
482   sqlite3_value **argv
483 ){
484   const char *zFile;
485   mode_t mode = 0;
486   int res;
487   sqlite3_int64 mtime = -1;
488 
489   if( argc<2 || argc>4 ){
490     sqlite3_result_error(context,
491         "wrong number of arguments to function writefile()", -1
492     );
493     return;
494   }
495 
496   zFile = (const char*)sqlite3_value_text(argv[0]);
497   if( zFile==0 ) return;
498   if( argc>=3 ){
499     mode = (mode_t)sqlite3_value_int(argv[2]);
500   }
501   if( argc==4 ){
502     mtime = sqlite3_value_int64(argv[3]);
503   }
504 
505   res = writeFile(context, zFile, argv[1], mode, mtime);
506   if( res==1 && errno==ENOENT ){
507     if( makeDirectory(zFile)==SQLITE_OK ){
508       res = writeFile(context, zFile, argv[1], mode, mtime);
509     }
510   }
511 
512   if( argc>2 && res!=0 ){
513     if( S_ISLNK(mode) ){
514       ctxErrorMsg(context, "failed to create symlink: %s", zFile);
515     }else if( S_ISDIR(mode) ){
516       ctxErrorMsg(context, "failed to create directory: %s", zFile);
517     }else{
518       ctxErrorMsg(context, "failed to write file: %s", zFile);
519     }
520   }
521 }
522 
523 /*
524 ** SQL function:   lsmode(MODE)
525 **
526 ** Given a numberic st_mode from stat(), convert it into a human-readable
527 ** text string in the style of "ls -l".
528 */
lsModeFunc(sqlite3_context * context,int argc,sqlite3_value ** argv)529 static void lsModeFunc(
530   sqlite3_context *context,
531   int argc,
532   sqlite3_value **argv
533 ){
534   int i;
535   int iMode = sqlite3_value_int(argv[0]);
536   char z[16];
537   (void)argc;
538   if( S_ISLNK(iMode) ){
539     z[0] = 'l';
540   }else if( S_ISREG(iMode) ){
541     z[0] = '-';
542   }else if( S_ISDIR(iMode) ){
543     z[0] = 'd';
544   }else{
545     z[0] = '?';
546   }
547   for(i=0; i<3; i++){
548     int m = (iMode >> ((2-i)*3));
549     char *a = &z[1 + i*3];
550     a[0] = (m & 0x4) ? 'r' : '-';
551     a[1] = (m & 0x2) ? 'w' : '-';
552     a[2] = (m & 0x1) ? 'x' : '-';
553   }
554   z[10] = '\0';
555   sqlite3_result_text(context, z, -1, SQLITE_TRANSIENT);
556 }
557 
558 #ifndef SQLITE_OMIT_VIRTUALTABLE
559 
560 /*
561 ** Cursor type for recursively iterating through a directory structure.
562 */
563 typedef struct fsdir_cursor fsdir_cursor;
564 typedef struct FsdirLevel FsdirLevel;
565 
566 struct FsdirLevel {
567   DIR *pDir;                 /* From opendir() */
568   char *zDir;                /* Name of directory (nul-terminated) */
569 };
570 
571 struct fsdir_cursor {
572   sqlite3_vtab_cursor base;  /* Base class - must be first */
573 
574   int nLvl;                  /* Number of entries in aLvl[] array */
575   int iLvl;                  /* Index of current entry */
576   FsdirLevel *aLvl;          /* Hierarchy of directories being traversed */
577 
578   const char *zBase;
579   int nBase;
580 
581   struct stat sStat;         /* Current lstat() results */
582   char *zPath;               /* Path to current entry */
583   sqlite3_int64 iRowid;      /* Current rowid */
584 };
585 
586 typedef struct fsdir_tab fsdir_tab;
587 struct fsdir_tab {
588   sqlite3_vtab base;         /* Base class - must be first */
589 };
590 
591 /*
592 ** Construct a new fsdir virtual table object.
593 */
fsdirConnect(sqlite3 * db,void * pAux,int argc,const char * const * argv,sqlite3_vtab ** ppVtab,char ** pzErr)594 static int fsdirConnect(
595   sqlite3 *db,
596   void *pAux,
597   int argc, const char *const*argv,
598   sqlite3_vtab **ppVtab,
599   char **pzErr
600 ){
601   fsdir_tab *pNew = 0;
602   int rc;
603   (void)pAux;
604   (void)argc;
605   (void)argv;
606   (void)pzErr;
607   rc = sqlite3_declare_vtab(db, "CREATE TABLE x" FSDIR_SCHEMA);
608   if( rc==SQLITE_OK ){
609     pNew = (fsdir_tab*)sqlite3_malloc( sizeof(*pNew) );
610     if( pNew==0 ) return SQLITE_NOMEM;
611     memset(pNew, 0, sizeof(*pNew));
612     sqlite3_vtab_config(db, SQLITE_VTAB_DIRECTONLY);
613   }
614   *ppVtab = (sqlite3_vtab*)pNew;
615   return rc;
616 }
617 
618 /*
619 ** This method is the destructor for fsdir vtab objects.
620 */
fsdirDisconnect(sqlite3_vtab * pVtab)621 static int fsdirDisconnect(sqlite3_vtab *pVtab){
622   sqlite3_free(pVtab);
623   return SQLITE_OK;
624 }
625 
626 /*
627 ** Constructor for a new fsdir_cursor object.
628 */
fsdirOpen(sqlite3_vtab * p,sqlite3_vtab_cursor ** ppCursor)629 static int fsdirOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
630   fsdir_cursor *pCur;
631   (void)p;
632   pCur = sqlite3_malloc( sizeof(*pCur) );
633   if( pCur==0 ) return SQLITE_NOMEM;
634   memset(pCur, 0, sizeof(*pCur));
635   pCur->iLvl = -1;
636   *ppCursor = &pCur->base;
637   return SQLITE_OK;
638 }
639 
640 /*
641 ** Reset a cursor back to the state it was in when first returned
642 ** by fsdirOpen().
643 */
fsdirResetCursor(fsdir_cursor * pCur)644 static void fsdirResetCursor(fsdir_cursor *pCur){
645   int i;
646   for(i=0; i<=pCur->iLvl; i++){
647     FsdirLevel *pLvl = &pCur->aLvl[i];
648     if( pLvl->pDir ) closedir(pLvl->pDir);
649     sqlite3_free(pLvl->zDir);
650   }
651   sqlite3_free(pCur->zPath);
652   sqlite3_free(pCur->aLvl);
653   pCur->aLvl = 0;
654   pCur->zPath = 0;
655   pCur->zBase = 0;
656   pCur->nBase = 0;
657   pCur->nLvl = 0;
658   pCur->iLvl = -1;
659   pCur->iRowid = 1;
660 }
661 
662 /*
663 ** Destructor for an fsdir_cursor.
664 */
fsdirClose(sqlite3_vtab_cursor * cur)665 static int fsdirClose(sqlite3_vtab_cursor *cur){
666   fsdir_cursor *pCur = (fsdir_cursor*)cur;
667 
668   fsdirResetCursor(pCur);
669   sqlite3_free(pCur);
670   return SQLITE_OK;
671 }
672 
673 /*
674 ** Set the error message for the virtual table associated with cursor
675 ** pCur to the results of vprintf(zFmt, ...).
676 */
fsdirSetErrmsg(fsdir_cursor * pCur,const char * zFmt,...)677 static void fsdirSetErrmsg(fsdir_cursor *pCur, const char *zFmt, ...){
678   va_list ap;
679   va_start(ap, zFmt);
680   pCur->base.pVtab->zErrMsg = sqlite3_vmprintf(zFmt, ap);
681   va_end(ap);
682 }
683 
684 
685 /*
686 ** Advance an fsdir_cursor to its next row of output.
687 */
fsdirNext(sqlite3_vtab_cursor * cur)688 static int fsdirNext(sqlite3_vtab_cursor *cur){
689   fsdir_cursor *pCur = (fsdir_cursor*)cur;
690   mode_t m = pCur->sStat.st_mode;
691 
692   pCur->iRowid++;
693   if( S_ISDIR(m) ){
694     /* Descend into this directory */
695     int iNew = pCur->iLvl + 1;
696     FsdirLevel *pLvl;
697     if( iNew>=pCur->nLvl ){
698       int nNew = iNew+1;
699       sqlite3_int64 nByte = nNew*sizeof(FsdirLevel);
700       FsdirLevel *aNew = (FsdirLevel*)sqlite3_realloc64(pCur->aLvl, nByte);
701       if( aNew==0 ) return SQLITE_NOMEM;
702       memset(&aNew[pCur->nLvl], 0, sizeof(FsdirLevel)*(nNew-pCur->nLvl));
703       pCur->aLvl = aNew;
704       pCur->nLvl = nNew;
705     }
706     pCur->iLvl = iNew;
707     pLvl = &pCur->aLvl[iNew];
708 
709     pLvl->zDir = pCur->zPath;
710     pCur->zPath = 0;
711     pLvl->pDir = opendir(pLvl->zDir);
712     if( pLvl->pDir==0 ){
713       fsdirSetErrmsg(pCur, "cannot read directory: %s", pCur->zPath);
714       return SQLITE_ERROR;
715     }
716   }
717 
718   while( pCur->iLvl>=0 ){
719     FsdirLevel *pLvl = &pCur->aLvl[pCur->iLvl];
720     struct dirent *pEntry = readdir(pLvl->pDir);
721     if( pEntry ){
722       if( pEntry->d_name[0]=='.' ){
723        if( pEntry->d_name[1]=='.' && pEntry->d_name[2]=='\0' ) continue;
724        if( pEntry->d_name[1]=='\0' ) continue;
725       }
726       sqlite3_free(pCur->zPath);
727       pCur->zPath = sqlite3_mprintf("%s/%s", pLvl->zDir, pEntry->d_name);
728       if( pCur->zPath==0 ) return SQLITE_NOMEM;
729       if( fileLinkStat(pCur->zPath, &pCur->sStat) ){
730         fsdirSetErrmsg(pCur, "cannot stat file: %s", pCur->zPath);
731         return SQLITE_ERROR;
732       }
733       return SQLITE_OK;
734     }
735     closedir(pLvl->pDir);
736     sqlite3_free(pLvl->zDir);
737     pLvl->pDir = 0;
738     pLvl->zDir = 0;
739     pCur->iLvl--;
740   }
741 
742   /* EOF */
743   sqlite3_free(pCur->zPath);
744   pCur->zPath = 0;
745   return SQLITE_OK;
746 }
747 
748 /*
749 ** Return values of columns for the row at which the series_cursor
750 ** is currently pointing.
751 */
fsdirColumn(sqlite3_vtab_cursor * cur,sqlite3_context * ctx,int i)752 static int fsdirColumn(
753   sqlite3_vtab_cursor *cur,   /* The cursor */
754   sqlite3_context *ctx,       /* First argument to sqlite3_result_...() */
755   int i                       /* Which column to return */
756 ){
757   fsdir_cursor *pCur = (fsdir_cursor*)cur;
758   switch( i ){
759     case FSDIR_COLUMN_NAME: {
760       sqlite3_result_text(ctx, &pCur->zPath[pCur->nBase], -1, SQLITE_TRANSIENT);
761       break;
762     }
763 
764     case FSDIR_COLUMN_MODE:
765       sqlite3_result_int64(ctx, pCur->sStat.st_mode);
766       break;
767 
768     case FSDIR_COLUMN_MTIME:
769       sqlite3_result_int64(ctx, pCur->sStat.st_mtime);
770       break;
771 
772     case FSDIR_COLUMN_DATA: {
773       mode_t m = pCur->sStat.st_mode;
774       if( S_ISDIR(m) ){
775         sqlite3_result_null(ctx);
776 #if !defined(_WIN32) && !defined(WIN32)
777       }else if( S_ISLNK(m) ){
778         char aStatic[64];
779         char *aBuf = aStatic;
780         sqlite3_int64 nBuf = 64;
781         int n;
782 
783         while( 1 ){
784           n = readlink(pCur->zPath, aBuf, nBuf);
785           if( n<nBuf ) break;
786           if( aBuf!=aStatic ) sqlite3_free(aBuf);
787           nBuf = nBuf*2;
788           aBuf = sqlite3_malloc64(nBuf);
789           if( aBuf==0 ){
790             sqlite3_result_error_nomem(ctx);
791             return SQLITE_NOMEM;
792           }
793         }
794 
795         sqlite3_result_text(ctx, aBuf, n, SQLITE_TRANSIENT);
796         if( aBuf!=aStatic ) sqlite3_free(aBuf);
797 #endif
798       }else{
799         readFileContents(ctx, pCur->zPath);
800       }
801     }
802     case FSDIR_COLUMN_PATH:
803     default: {
804       /* The FSDIR_COLUMN_PATH and FSDIR_COLUMN_DIR are input parameters.
805       ** always return their values as NULL */
806       break;
807     }
808   }
809   return SQLITE_OK;
810 }
811 
812 /*
813 ** Return the rowid for the current row. In this implementation, the
814 ** first row returned is assigned rowid value 1, and each subsequent
815 ** row a value 1 more than that of the previous.
816 */
fsdirRowid(sqlite3_vtab_cursor * cur,sqlite_int64 * pRowid)817 static int fsdirRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
818   fsdir_cursor *pCur = (fsdir_cursor*)cur;
819   *pRowid = pCur->iRowid;
820   return SQLITE_OK;
821 }
822 
823 /*
824 ** Return TRUE if the cursor has been moved off of the last
825 ** row of output.
826 */
fsdirEof(sqlite3_vtab_cursor * cur)827 static int fsdirEof(sqlite3_vtab_cursor *cur){
828   fsdir_cursor *pCur = (fsdir_cursor*)cur;
829   return (pCur->zPath==0);
830 }
831 
832 /*
833 ** xFilter callback.
834 **
835 ** idxNum==1   PATH parameter only
836 ** idxNum==2   Both PATH and DIR supplied
837 */
fsdirFilter(sqlite3_vtab_cursor * cur,int idxNum,const char * idxStr,int argc,sqlite3_value ** argv)838 static int fsdirFilter(
839   sqlite3_vtab_cursor *cur,
840   int idxNum, const char *idxStr,
841   int argc, sqlite3_value **argv
842 ){
843   const char *zDir = 0;
844   fsdir_cursor *pCur = (fsdir_cursor*)cur;
845   (void)idxStr;
846   fsdirResetCursor(pCur);
847 
848   if( idxNum==0 ){
849     fsdirSetErrmsg(pCur, "table function fsdir requires an argument");
850     return SQLITE_ERROR;
851   }
852 
853   assert( argc==idxNum && (argc==1 || argc==2) );
854   zDir = (const char*)sqlite3_value_text(argv[0]);
855   if( zDir==0 ){
856     fsdirSetErrmsg(pCur, "table function fsdir requires a non-NULL argument");
857     return SQLITE_ERROR;
858   }
859   if( argc==2 ){
860     pCur->zBase = (const char*)sqlite3_value_text(argv[1]);
861   }
862   if( pCur->zBase ){
863     pCur->nBase = (int)strlen(pCur->zBase)+1;
864     pCur->zPath = sqlite3_mprintf("%s/%s", pCur->zBase, zDir);
865   }else{
866     pCur->zPath = sqlite3_mprintf("%s", zDir);
867   }
868 
869   if( pCur->zPath==0 ){
870     return SQLITE_NOMEM;
871   }
872   if( fileLinkStat(pCur->zPath, &pCur->sStat) ){
873     fsdirSetErrmsg(pCur, "cannot stat file: %s", pCur->zPath);
874     return SQLITE_ERROR;
875   }
876 
877   return SQLITE_OK;
878 }
879 
880 /*
881 ** SQLite will invoke this method one or more times while planning a query
882 ** that uses the generate_series virtual table.  This routine needs to create
883 ** a query plan for each invocation and compute an estimated cost for that
884 ** plan.
885 **
886 ** In this implementation idxNum is used to represent the
887 ** query plan.  idxStr is unused.
888 **
889 ** The query plan is represented by values of idxNum:
890 **
891 **  (1)  The path value is supplied by argv[0]
892 **  (2)  Path is in argv[0] and dir is in argv[1]
893 */
fsdirBestIndex(sqlite3_vtab * tab,sqlite3_index_info * pIdxInfo)894 static int fsdirBestIndex(
895   sqlite3_vtab *tab,
896   sqlite3_index_info *pIdxInfo
897 ){
898   int i;                 /* Loop over constraints */
899   int idxPath = -1;      /* Index in pIdxInfo->aConstraint of PATH= */
900   int idxDir = -1;       /* Index in pIdxInfo->aConstraint of DIR= */
901   int seenPath = 0;      /* True if an unusable PATH= constraint is seen */
902   int seenDir = 0;       /* True if an unusable DIR= constraint is seen */
903   const struct sqlite3_index_constraint *pConstraint;
904 
905   (void)tab;
906   pConstraint = pIdxInfo->aConstraint;
907   for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
908     if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
909     switch( pConstraint->iColumn ){
910       case FSDIR_COLUMN_PATH: {
911         if( pConstraint->usable ){
912           idxPath = i;
913           seenPath = 0;
914         }else if( idxPath<0 ){
915           seenPath = 1;
916         }
917         break;
918       }
919       case FSDIR_COLUMN_DIR: {
920         if( pConstraint->usable ){
921           idxDir = i;
922           seenDir = 0;
923         }else if( idxDir<0 ){
924           seenDir = 1;
925         }
926         break;
927       }
928     }
929   }
930   if( seenPath || seenDir ){
931     /* If input parameters are unusable, disallow this plan */
932     return SQLITE_CONSTRAINT;
933   }
934 
935   if( idxPath<0 ){
936     pIdxInfo->idxNum = 0;
937     /* The pIdxInfo->estimatedCost should have been initialized to a huge
938     ** number.  Leave it unchanged. */
939     pIdxInfo->estimatedRows = 0x7fffffff;
940   }else{
941     pIdxInfo->aConstraintUsage[idxPath].omit = 1;
942     pIdxInfo->aConstraintUsage[idxPath].argvIndex = 1;
943     if( idxDir>=0 ){
944       pIdxInfo->aConstraintUsage[idxDir].omit = 1;
945       pIdxInfo->aConstraintUsage[idxDir].argvIndex = 2;
946       pIdxInfo->idxNum = 2;
947       pIdxInfo->estimatedCost = 10.0;
948     }else{
949       pIdxInfo->idxNum = 1;
950       pIdxInfo->estimatedCost = 100.0;
951     }
952   }
953 
954   return SQLITE_OK;
955 }
956 
957 /*
958 ** Register the "fsdir" virtual table.
959 */
fsdirRegister(sqlite3 * db)960 static int fsdirRegister(sqlite3 *db){
961   static sqlite3_module fsdirModule = {
962     0,                         /* iVersion */
963     0,                         /* xCreate */
964     fsdirConnect,              /* xConnect */
965     fsdirBestIndex,            /* xBestIndex */
966     fsdirDisconnect,           /* xDisconnect */
967     0,                         /* xDestroy */
968     fsdirOpen,                 /* xOpen - open a cursor */
969     fsdirClose,                /* xClose - close a cursor */
970     fsdirFilter,               /* xFilter - configure scan constraints */
971     fsdirNext,                 /* xNext - advance a cursor */
972     fsdirEof,                  /* xEof - check for end of scan */
973     fsdirColumn,               /* xColumn - read data */
974     fsdirRowid,                /* xRowid - read data */
975     0,                         /* xUpdate */
976     0,                         /* xBegin */
977     0,                         /* xSync */
978     0,                         /* xCommit */
979     0,                         /* xRollback */
980     0,                         /* xFindMethod */
981     0,                         /* xRename */
982     0,                         /* xSavepoint */
983     0,                         /* xRelease */
984     0,                         /* xRollbackTo */
985     0,                         /* xShadowName */
986   };
987 
988   int rc = sqlite3_create_module(db, "fsdir", &fsdirModule, 0);
989   return rc;
990 }
991 #else         /* SQLITE_OMIT_VIRTUALTABLE */
992 # define fsdirRegister(x) SQLITE_OK
993 #endif
994 
995 #ifdef _WIN32
996 __declspec(dllexport)
997 #endif
sqlite3_fileio_init(sqlite3 * db,char ** pzErrMsg,const sqlite3_api_routines * pApi)998 int sqlite3_fileio_init(
999   sqlite3 *db,
1000   char **pzErrMsg,
1001   const sqlite3_api_routines *pApi
1002 ){
1003   int rc = SQLITE_OK;
1004   SQLITE_EXTENSION_INIT2(pApi);
1005   (void)pzErrMsg;  /* Unused parameter */
1006   rc = sqlite3_create_function(db, "readfile", 1,
1007                                SQLITE_UTF8|SQLITE_DIRECTONLY, 0,
1008                                readfileFunc, 0, 0);
1009   if( rc==SQLITE_OK ){
1010     rc = sqlite3_create_function(db, "writefile", -1,
1011                                  SQLITE_UTF8|SQLITE_DIRECTONLY, 0,
1012                                  writefileFunc, 0, 0);
1013   }
1014   if( rc==SQLITE_OK ){
1015     rc = sqlite3_create_function(db, "lsmode", 1, SQLITE_UTF8, 0,
1016                                  lsModeFunc, 0, 0);
1017   }
1018   if( rc==SQLITE_OK ){
1019     rc = fsdirRegister(db);
1020   }
1021   return rc;
1022 }
1023 
1024 #if defined(FILEIO_WIN32_DLL) && (defined(_WIN32) || defined(WIN32))
1025 /* To allow a standalone DLL, make test_windirent.c use the same
1026  * redefined SQLite API calls as the above extension code does.
1027  * Just pull in this .c to accomplish this. As a beneficial side
1028  * effect, this extension becomes a single translation unit. */
1029 #  include "test_windirent.c"
1030 #endif
1031