$(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 \
$(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 \
$(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.
-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
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
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
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
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
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
-ecad75d69e0d5c83dd3584d363e557e84b65f7f2
\ No newline at end of file
+f3ffb3aeea95712e92919fd5071741327add9643
\ No newline at end of file
#if SQLITE_OS_UNIX
# include <unistd.h>
# include <dirent.h>
+# ifndef DIRENT
+# define DIRENT dirent
+# endif
#endif
#if SQLITE_OS_WIN
# include <io.h>
+# include "test_windirent.h"
+# ifndef S_ISREG
+# define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
+# endif
#endif
#ifndef SQLITE_OMIT_VIRTUALTABLE
char *zDir; /* Buffer containing directory scanned */
DIR *pDir; /* Open directory */
sqlite3_int64 iRowid;
- struct dirent entry; /* Current entry */
+ struct DIRENT entry; /* Current entry */
};
/*
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);
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);
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;
}
}
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);
}
--- /dev/null
+/*
+** 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) */
--- /dev/null
+/*
+** 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 <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <io.h>
+#include <limits.h>
+
+/*
+** 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) */
#-------------------------------------------------------------------------
#
-if {$::tcl_platform(platform)=="unix"} {
+if {1} {
reset_db
register_fs_module db
do_execsql_test 3.0 {
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;
#
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/*"]]