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