From: mistachkin Date: Mon, 30 Nov 2015 23:29:07 +0000 (+0000) Subject: Add experimental support for the 'test_fs' test module on Win32. X-Git-Tag: version-3.10.0~79^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=92af1ebc75d8077c4885d02436e3630d7e91d473;p=thirdparty%2Fsqlite.git Add experimental support for the 'test_fs' test module on Win32. FossilOrigin-Name: f3ffb3aeea95712e92919fd5071741327add9643 --- diff --git a/Makefile.in b/Makefile.in index eaf021b412..f8766ac8f7 100644 --- a/Makefile.in +++ b/Makefile.in @@ -402,6 +402,7 @@ TESTSRC = \ $(TOP)/src/test_tclvar.c \ $(TOP)/src/test_thread.c \ $(TOP)/src/test_vfs.c \ + $(TOP)/src/test_windirent.c \ $(TOP)/src/test_wsd.c \ $(TOP)/ext/fts3/fts3_term.c \ $(TOP)/ext/fts3/fts3_test.c \ diff --git a/Makefile.msc b/Makefile.msc index 57fba11c53..5c72001532 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -1071,6 +1071,7 @@ TESTSRC = \ $(TOP)\src\test_tclvar.c \ $(TOP)\src\test_thread.c \ $(TOP)\src\test_vfs.c \ + $(TOP)\src\test_windirent.c \ $(TOP)\src\test_wsd.c \ $(TOP)\ext\fts3\fts3_term.c \ $(TOP)\ext\fts3\fts3_test.c \ diff --git a/main.mk b/main.mk index 838e0753d9..f3a37dc194 100644 --- a/main.mk +++ b/main.mk @@ -312,6 +312,7 @@ TESTSRC = \ $(TOP)/src/test_tclvar.c \ $(TOP)/src/test_thread.c \ $(TOP)/src/test_vfs.c \ + $(TOP)/src/test_windirent.c \ $(TOP)/src/test_wsd.c # Extensions to be statically loaded. diff --git a/manifest b/manifest index 135ade46f1..885c09aea0 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,8 @@ -C Add\sthe\sSQLITE_PRINTF_PRECISION_LIMIT\scompile-time\soption. -D 2015-11-30T22:52:14.011 -F Makefile.in d828db6afa6c1fa060d01e33e4674408df1942a1 +C Add\sexperimental\ssupport\sfor\sthe\s'test_fs'\stest\smodule\son\sWin32. +D 2015-11-30T23:29:07.971 +F Makefile.in 23d9a63484a383fc64951b25ef44067930f98dc6 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 -F Makefile.msc e928e68168df69b353300ac87c10105206653a03 +F Makefile.msc e8fdca1cb89a1b58b5f4d3a130ea9a3d28cb314d F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7 F VERSION 8b9d3ac6f1962f94e06ba05462422a544f9c4e36 F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 @@ -263,7 +263,7 @@ F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60 -F main.mk ae99be5eb22933b1ecf80f94d41d25a3ea80aaf3 +F main.mk 9001039f432baeba1074e2d1885f3dfd572b8636 F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83 F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271 F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504 @@ -366,7 +366,7 @@ F src/test_btree.c 2e9978eca99a9a4bfa8cae949efb00886860a64f F src/test_config.c f2824de39f59d8d621e2d6ec5cc67006d000b2eb F src/test_demovfs.c 0de72c2c89551629f58486fde5734b7d90758852 F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc -F src/test_fs.c 9a56a587ce1db424af430d5ff650b5736b498238 +F src/test_fs.c aab47ac456316502faa265daadf9ac832fea12b9 F src/test_func.c 0d9c25956152adefee8881c6fadc8354793764d0 F src/test_hexio.c abfdecb6fa58c354623978efceb088ca18e379cd F src/test_init.c 66b33120ffe9cd853b5a905ec850d51151337b32 @@ -393,6 +393,8 @@ F src/test_tclvar.c d86412527da65468ee6fa1b8607c65d0af736bc4 F src/test_thread.c af391ec03d23486dffbcc250b7e58e073f172af9 F src/test_vfs.c 3b65d42e18b262805716bd96178c81da8f2d9283 F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698 +F src/test_windirent.c 8f5fada630348558d5745b334702f301da1ffc61 +F src/test_windirent.h b12055cab6227f7be10f5c19296f67c60cc5e2a5 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/threads.c bbfb74450643cb5372a43ad4f6cffd7e9dfcecb0 F src/tokenize.c 5606871a377f390af7040ec3c12e0d183512d785 @@ -1274,7 +1276,7 @@ F test/vtabC.test 4528f459a13136f982e75614d120aef165f17292 F test/vtabD.test 05b3f1d77117271671089e48719524b676842e96 F test/vtabE.test d5024aa42754962f6bb0afd261681686488e7afe F test/vtabF.test fd5ad376f5a34fe0891df1f3cddb4fe7c3eb077e -F test/vtabH.test 186f118d6a4dd25fdb36adfd471993003f83790c +F test/vtabH.test 2803a8773d1017ac93bbec6900fc7c35bb56c1c3 F test/vtabI.test 751b07636700dbdea328e4265b6077ccd6811a3f F test/vtab_alter.test 9e374885248f69e251bdaacf480b04a197f125e5 F test/vtab_err.test 0d4d8eb4def1d053ac7c5050df3024fd47a3fbd8 @@ -1406,7 +1408,10 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P bb1e2c4df0b81327923f121dd6c002845486a314 -R d3b18adc3009f6c25adcd36c4f052eab -U drh -Z 7ba0fba490eff520c14229730eb61dd8 +P ecad75d69e0d5c83dd3584d363e557e84b65f7f2 +R b2c7ca19fb46e255338240c0ac77a2e4 +T *branch * testFsWin32 +T *sym-testFsWin32 * +T -sym-trunk * +U mistachkin +Z b75cf97131a1f035edfb9c37c590fcf6 diff --git a/manifest.uuid b/manifest.uuid index 3749928415..2659aede24 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ecad75d69e0d5c83dd3584d363e557e84b65f7f2 \ No newline at end of file +f3ffb3aeea95712e92919fd5071741327add9643 \ No newline at end of file diff --git a/src/test_fs.c b/src/test_fs.c index 213b65689a..de332fa2f5 100644 --- a/src/test_fs.c +++ b/src/test_fs.c @@ -73,9 +73,16 @@ #if SQLITE_OS_UNIX # include # include +# ifndef DIRENT +# define DIRENT dirent +# endif #endif #if SQLITE_OS_WIN # include +# include "test_windirent.h" +# ifndef S_ISREG +# define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) +# endif #endif #ifndef SQLITE_OMIT_VIRTUALTABLE @@ -116,7 +123,7 @@ struct FsdirCsr { char *zDir; /* Buffer containing directory scanned */ DIR *pDir; /* Open directory */ sqlite3_int64 iRowid; - struct dirent entry; /* Current entry */ + struct DIRENT entry; /* Current entry */ }; /* @@ -220,7 +227,7 @@ static int fsdirNext(sqlite3_vtab_cursor *cur){ FsdirCsr *pCsr = (FsdirCsr*)cur; if( pCsr->pDir ){ - struct dirent *pRes = 0; + struct DIRENT *pRes = 0; readdir_r(pCsr->pDir, &pCsr->entry, &pRes); if( pRes==0 ){ closedir(pCsr->pDir); @@ -461,15 +468,34 @@ static int fstreeFilter( int rc; const char *zSql = "WITH r(d) AS (" -" SELECT CASE WHEN dir='/' THEN '' ELSE dir END || '/' || name " -" FROM fsdir WHERE dir=? AND name NOT LIKE '.%'" +" SELECT CASE WHEN dir=?2 THEN ?3 ELSE dir END || '/' || name " +" FROM fsdir WHERE dir=?1 AND name NOT LIKE '.%'" " UNION ALL" " SELECT dir || '/' || name FROM r, fsdir WHERE dir=d AND name NOT LIKE '.%'" ") SELECT d FROM r;"; - const char *zDir = "/"; - int nDir = 1; - char aWild[2] = {'\0', '\0' }; + char *zRoot; + int nRoot; + char *zPrefix; + int nPrefix; + const char *zDir; + int nDir; + char aWild[2] = { '\0', '\0' }; + +#if SQLITE_OS_WIN + zRoot = sqlite3_mprintf("%s%c", getenv("SystemDrive"), '/'); + nRoot = strlen(zRoot); + zPrefix = sqlite3_mprintf("%s", getenv("SystemDrive")); + nPrefix = strlen(zPrefix); +#else + zRoot = "/"; + nRoot = 1; + zPrefix = ""; + nPrefix = 0; +#endif + + zDir = zRoot; + nDir = nRoot; fstreeCloseFd(pCsr); sqlite3_finalize(pCsr->pStmt); @@ -490,9 +516,9 @@ static int fstreeFilter( break; } - if( zQuery[0]=='/' ){ + if( sqlite3_strnicmp(zQuery, zPrefix, nPrefix)==0 ){ int i; - for(i=1; zQuery[i]; i++){ + for(i=nPrefix; zQuery[i]; i++){ if( zQuery[i]==aWild[0] || zQuery[i]==aWild[1] ) break; if( zQuery[i]=='/' ) nDir = i; } @@ -501,6 +527,13 @@ static int fstreeFilter( } sqlite3_bind_text(pCsr->pStmt, 1, zDir, nDir, SQLITE_TRANSIENT); + sqlite3_bind_text(pCsr->pStmt, 2, zRoot, nRoot, SQLITE_TRANSIENT); + sqlite3_bind_text(pCsr->pStmt, 3, zPrefix, nPrefix, SQLITE_TRANSIENT); + +#if SQLITE_OS_WIN + sqlite3_free(zPrefix); + sqlite3_free(zRoot); +#endif return fstreeNext(pVtabCursor); } diff --git a/src/test_windirent.c b/src/test_windirent.c new file mode 100644 index 0000000000..11d7dc07d0 --- /dev/null +++ b/src/test_windirent.c @@ -0,0 +1,157 @@ +/* +** 2015 November 30 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This file contains code to implement most of the opendir() family of +** POSIX functions on Win32 using the MSVCRT. +*/ + +#if defined(_WIN32) && defined(_MSC_VER) + +#include "test_windirent.h" + +/* +** Implementation of the POSIX opendir() function using the MSVCRT. +*/ +LPDIR opendir( + const char *dirname +){ + struct _finddata_t data; + LPDIR dirp = (LPDIR)sqlite3_malloc(sizeof(DIR)); + SIZE_T namesize = sizeof(data.name) / sizeof(data.name[0]); + + if( dirp==NULL ) return NULL; + memset(dirp, 0, sizeof(DIR)); + + /* TODO: Remove this if Unix-style root paths are not used. */ + if( sqlite3_stricmp(dirname, "/")==0 ){ + dirname = getenv("SystemDrive"); + } + + _snprintf(data.name, namesize, "%s\\*", dirname); + dirp->d_handle = _findfirst(data.name, &data); + + if( dirp->d_handle==BAD_INTPTR_T ){ + closedir(dirp); + return NULL; + } + + /* TODO: Remove this block to allow hidden and system files. */ + if( data.attrib&_A_HIDDEN || data.attrib&_A_SYSTEM ){ + if( _findnext(dirp->d_handle, &data)==-1 ){ + closedir(dirp); + return NULL; + } + } + + dirp->d_first.d_attributes = data.attrib; + strncpy(dirp->d_first.d_name, data.name, NAME_MAX); + dirp->d_first.d_name[NAME_MAX] = '\0'; + + return dirp; +} + +/* +** Implementation of the POSIX readdir() function using the MSVCRT. +*/ +LPDIRENT readdir( + LPDIR dirp +){ + struct _finddata_t data; + + if( dirp==NULL ) return NULL; + + if( dirp->d_first.d_ino==0 ){ + dirp->d_first.d_ino++; + dirp->d_next.d_ino++; + + return &dirp->d_first; + } + +next: + + if( _findnext(dirp->d_handle, &data)==-1 ) return NULL; + + /* TODO: Remove this block to allow hidden and system files. */ + if( data.attrib&_A_HIDDEN ) goto next; + if( data.attrib&_A_SYSTEM ) goto next; + + dirp->d_next.d_ino++; + dirp->d_next.d_attributes = data.attrib; + strncpy(dirp->d_next.d_name, data.name, NAME_MAX); + dirp->d_next.d_name[NAME_MAX] = '\0'; + + return &dirp->d_next; +} + +/* +** Implementation of the POSIX readdir_r() function using the MSVCRT. +*/ +INT readdir_r( + LPDIR dirp, + LPDIRENT entry, + LPDIRENT *result +){ + struct _finddata_t data; + + if( dirp==NULL ) return EBADF; + + if( dirp->d_first.d_ino==0 ){ + dirp->d_first.d_ino++; + dirp->d_next.d_ino++; + + entry->d_ino = dirp->d_first.d_ino; + entry->d_attributes = dirp->d_first.d_attributes; + strncpy(entry->d_name, dirp->d_first.d_name, NAME_MAX); + entry->d_name[NAME_MAX] = '\0'; + + *result = entry; + return 0; + } + +next: + + if( _findnext(dirp->d_handle, &data)==-1 ){ + *result = NULL; + return ENOENT; + } + + /* TODO: Remove this block to allow hidden and system files. */ + if( data.attrib&_A_HIDDEN ) goto next; + if( data.attrib&_A_SYSTEM ) goto next; + + entry->d_ino = (ino_t)-1; /* not available */ + entry->d_attributes = data.attrib; + strncpy(entry->d_name, data.name, NAME_MAX); + entry->d_name[NAME_MAX] = '\0'; + + *result = entry; + return 0; +} + +/* +** Implementation of the POSIX closedir() function using the MSVCRT. +*/ +INT closedir( + LPDIR dirp +){ + INT result = 0; + + if( dirp==NULL ) return EINVAL; + + if( dirp->d_handle!=NULL_INTPTR_T && dirp->d_handle!=BAD_INTPTR_T ){ + result = _findclose(dirp->d_handle); + } + + sqlite3_free(dirp); + return result; +} + +#endif /* defined(WIN32) && defined(_MSC_VER) */ diff --git a/src/test_windirent.h b/src/test_windirent.h new file mode 100644 index 0000000000..0b8d1a7b51 --- /dev/null +++ b/src/test_windirent.h @@ -0,0 +1,105 @@ +/* +** 2015 November 30 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This file contains declarations for most of the opendir() family of +** POSIX functions on Win32 using the MSVCRT. +*/ + +#if defined(_WIN32) && defined(_MSC_VER) + +/* +** We need several data types from the Windows SDK header. +*/ + +#define WIN32_LEAN_AND_MEAN +#include "windows.h" + +/* +** We need several support functions from the SQLite core. +*/ + +#include "sqlite3.h" + +/* +** We need several things from the ANSI and MSVCRT headers. +*/ + +#include +#include +#include +#include +#include + +/* +** We may need to provide the "ino_t" type. +*/ + +#ifndef INO_T_DEFINED + #define INO_T_DEFINED + typedef unsigned short ino_t; +#endif + +/* +** We need to define "NAME_MAX" if it was not present in "limits.h". +*/ + +#ifndef NAME_MAX +# ifdef FILENAME_MAX +# define NAME_MAX (FILENAME_MAX) +# else +# define NAME_MAX (260) +# endif +#endif + +/* +** We need to define "NULL_INTPTR_T" and "BAD_INTPTR_T". +*/ + +#ifndef NULL_INTPTR_T +# define NULL_INTPTR_T ((intptr_t)(0)) +#endif + +#ifndef BAD_INTPTR_T +# define BAD_INTPTR_T ((intptr_t)(-1)) +#endif + +/* +** We need to provide the necessary structures and related types. +*/ + +typedef struct DIRENT DIRENT; +typedef struct DIR DIR; +typedef DIRENT *LPDIRENT; +typedef DIR *LPDIR; + +struct DIRENT { + ino_t d_ino; /* Sequence number, do not use. */ + unsigned d_attributes; /* Win32 file attributes. */ + char d_name[NAME_MAX + 1]; /* Name within the directory. */ +}; + +struct DIR { + intptr_t d_handle; /* Value returned by "_findfirst". */ + DIRENT d_first; /* DIRENT constructed based on "_findfirst". */ + DIRENT d_next; /* DIRENT constructed based on "_findnext". */ +}; + +/* +** Finally, we can provide the function prototypes for the opendir(), +** readdir(), readdir_r(), and closedir() POSIX functions. +*/ + +extern LPDIR opendir(const char *dirname); +extern LPDIRENT readdir(LPDIR dirp); +extern INT readdir_r(LPDIR dirp, LPDIRENT entry, LPDIRENT *result); +extern INT closedir(LPDIR dirp); + +#endif /* defined(WIN32) && defined(_MSC_VER) */ diff --git a/test/vtabH.test b/test/vtabH.test index 7216677d2a..6034d95fa1 100644 --- a/test/vtabH.test +++ b/test/vtabH.test @@ -108,7 +108,7 @@ foreach ::tclvar_set_omit {0 1} { #------------------------------------------------------------------------- # -if {$::tcl_platform(platform)=="unix"} { +if {1} { reset_db register_fs_module db do_execsql_test 3.0 { @@ -116,11 +116,41 @@ if {$::tcl_platform(platform)=="unix"} { SELECT name FROM fsdir WHERE dir = '.' AND name = '.' } {test.db .} + proc list_root_files {} { + if {$::tcl_platform(platform) eq "windows"} { + set res [list] + foreach name [glob -directory $::env(SystemDrive)/ -- *] { + if {[string index [file tail $name] 0] eq "."} continue + lappend res $name + } + return $res + } else { + return [exec ls -U /] + } + } + + proc list_files { pattern } { + if {$::tcl_platform(platform) eq "windows"} { + set res [list] + foreach name [glob -nocomplain $pattern] { + if {[string index [file tail $name] 0] eq "."} continue + lappend res $name + } + return $res + } else { + return [glob -nocomplain $pattern] + } + } + # Read the first 5 entries from the root directory. # set res [list] - foreach p [lrange [exec ls -U /] 0 4] { - lappend res "/$p" + foreach p [lrange [list_root_files] 0 4] { + if {$::tcl_platform(platform) eq "windows"} { + lappend res $p + } else { + lappend res "/$p" + } } do_execsql_test 3.1 { SELECT path FROM fstree LIMIT 5; @@ -130,7 +160,7 @@ if {$::tcl_platform(platform)=="unix"} { # proc contents {pattern} { set res [list] - foreach f [glob -nocomplain $pattern] { + foreach f [list_files $pattern] { lappend res $f if {[file isdir $f]} { set res [concat $res [contents "$f/*"]]