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 */ 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 */ 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 */ 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 */ 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 # 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 */ 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 */ 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 */ 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 */ 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 */ 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(¤tTime); 430 SystemTimeToFileTime(¤tTime, &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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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