6969** directory, NULL.
7070**
7171** 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
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
7474** relative to directory $dir.
7575**
7676** Notes on building this extension for Windows:
@@ -98,14 +98,9 @@ SQLITE_EXTENSION_INIT1
9898# include <direct.h>
9999# include "test_windirent.h"
100100# 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)
101+ # define stat _stat
102+ # define chmod (path ,mode ) fileio_chmod(path,mode)
103+ # define mkdir (path ,mode ) fileio_mkdir(path)
109104#endif
110105#include <time.h>
111106#include <errno.h>
@@ -130,9 +125,43 @@ SQLITE_EXTENSION_INIT1
130125#define FSDIR_COLUMN_PATH 4 /* Path to top of search */
131126#define FSDIR_COLUMN_DIR 5 /* Path is relative to this directory */
132127
128+ /*
129+ ** UTF8 chmod() function for Windows
130+ */
131+ #if defined(_WIN32 ) || defined(WIN32 )
132+ static int fileio_chmod (const char * zPath , int pmode ){
133+ sqlite3_int64 sz = strlen (zPath );
134+ wchar_t * b1 = sqlite3_malloc64 ( (sz + 1 )* sizeof (b1 [0 ]) );
135+ int rc ;
136+ if ( b1 == 0 ) return -1 ;
137+ sz = MultiByteToWideChar (CP_UTF8 , 0 , zPath , sz , b1 , sz );
138+ b1 [sz ] = 0 ;
139+ rc = _wchmod (b1 , pmode );
140+ sqlite3_free (b1 );
141+ return rc ;
142+ }
143+ #endif
133144
134145/*
135- ** Set the result stored by context ctx to a blob containing the
146+ ** UTF8 mkdir() function for Windows
147+ */
148+ #if defined(_WIN32 ) || defined(WIN32 )
149+ static int fileio_mkdir (const char * zPath ){
150+ sqlite3_int64 sz = strlen (zPath );
151+ wchar_t * b1 = sqlite3_malloc64 ( (sz + 1 )* sizeof (b1 [0 ]) );
152+ int rc ;
153+ if ( b1 == 0 ) return -1 ;
154+ sz = MultiByteToWideChar (CP_UTF8 , 0 , zPath , sz , b1 , sz );
155+ b1 [sz ] = 0 ;
156+ rc = _wmkdir (b1 );
157+ sqlite3_free (b1 );
158+ return rc ;
159+ }
160+ #endif
161+
162+
163+ /*
164+ ** Set the result stored by context ctx to a blob containing the
136165** contents of file zName. Or, leave the result unchanged (NULL)
137166** if the file does not exist or is unreadable.
138167**
@@ -291,7 +320,13 @@ static int fileStat(
291320 struct stat * pStatBuf
292321){
293322#if defined(_WIN32 )
294- int rc = stat (zPath , pStatBuf );
323+ sqlite3_int64 sz = strlen (zPath );
324+ wchar_t * b1 = sqlite3_malloc64 ( (sz + 1 )* sizeof (b1 [0 ]) );
325+ int rc ;
326+ if ( b1 == 0 ) return 1 ;
327+ sz = MultiByteToWideChar (CP_UTF8 , 0 , zPath , sz , b1 , sz );
328+ b1 [sz ] = 0 ;
329+ rc = _wstat (b1 , pStatBuf );
295330 if ( rc == 0 ) statTimesToUtc (zPath , pStatBuf );
296331 return rc ;
297332#else
@@ -309,9 +344,7 @@ static int fileLinkStat(
309344 struct stat * pStatBuf
310345){
311346#if defined(_WIN32 )
312- int rc = lstat (zPath , pStatBuf );
313- if ( rc == 0 ) statTimesToUtc (zPath , pStatBuf );
314- return rc ;
347+ return fileStat (zPath , pStatBuf );
315348#else
316349 return lstat (zPath , pStatBuf );
317350#endif
@@ -365,7 +398,7 @@ static int makeDirectory(
365398}
366399
367400/*
368- ** This function does the work for the writefile() UDF. Refer to
401+ ** This function does the work for the writefile() UDF. Refer to
369402** header comments at the top of this file for details.
370403*/
371404static int writeFile (
@@ -467,10 +500,10 @@ static int writeFile(
467500 return 1 ;
468501 }
469502#else
470- /* Legacy unix.
503+ /* Legacy unix.
471504 **
472505 ** Do not use utimes() on a symbolic link - it sees through the link and
473- ** modifies the timestamps on the target. Or fails if the target does
506+ ** modifies the timestamps on the target. Or fails if the target does
474507 ** not exist. */
475508 if ( 0 == S_ISLNK (mode ) ){
476509 struct timeval times [2 ];
@@ -488,7 +521,7 @@ static int writeFile(
488521}
489522
490523/*
491- ** Implementation of the "writefile(W,X[,Y[,Z]]])" SQL function.
524+ ** Implementation of the "writefile(W,X[,Y[,Z]]])" SQL function.
492525** Refer to header comments at the top of this file for details.
493526*/
494527static void writefileFunc (
@@ -502,7 +535,7 @@ static void writefileFunc(
502535 sqlite3_int64 mtime = -1 ;
503536
504537 if ( argc < 2 || argc > 4 ){
505- sqlite3_result_error (context ,
538+ sqlite3_result_error (context ,
506539 "wrong number of arguments to function writefile()" , -1
507540 );
508541 return ;
@@ -572,7 +605,7 @@ static void lsModeFunc(
572605
573606#ifndef SQLITE_OMIT_VIRTUALTABLE
574607
575- /*
608+ /*
576609** Cursor type for recursively iterating through a directory structure.
577610*/
578611typedef struct fsdir_cursor fsdir_cursor ;
@@ -720,7 +753,7 @@ static int fsdirNext(sqlite3_vtab_cursor *cur){
720753 }
721754 pCur -> iLvl = iNew ;
722755 pLvl = & pCur -> aLvl [iNew ];
723-
756+
724757 pLvl -> zDir = pCur -> zPath ;
725758 pCur -> zPath = 0 ;
726759 pLvl -> pDir = opendir (pLvl -> zDir );
@@ -851,7 +884,7 @@ static int fsdirEof(sqlite3_vtab_cursor *cur){
851884** idxNum==2 Both PATH and DIR supplied
852885*/
853886static int fsdirFilter (
854- sqlite3_vtab_cursor * cur ,
887+ sqlite3_vtab_cursor * cur ,
855888 int idxNum , const char * idxStr ,
856889 int argc , sqlite3_value * * argv
857890){
@@ -940,7 +973,7 @@ static int fsdirBestIndex(
940973 }
941974 break ;
942975 }
943- }
976+ }
944977 }
945978 if ( seenPath || seenDir ){
946979 /* If input parameters are unusable, disallow this plan */
@@ -1013,14 +1046,14 @@ static int fsdirRegister(sqlite3 *db){
10131046#endif
10141047SQLITE_API
10151048int sqlite3_fileio_init (
1016- sqlite3 * db ,
1017- char * * pzErrMsg ,
1049+ sqlite3 * db ,
1050+ char * * pzErrMsg ,
10181051 const sqlite3_api_routines * pApi
10191052){
10201053 int rc = SQLITE_OK ;
10211054 SQLITE_EXTENSION_INIT2 (pApi );
10221055 (void )pzErrMsg ; /* Unused parameter */
1023- rc = sqlite3_create_function (db , "readfile" , 1 ,
1056+ rc = sqlite3_create_function (db , "readfile" , 1 ,
10241057 SQLITE_UTF8 |SQLITE_DIRECTONLY , 0 ,
10251058 readfileFunc , 0 , 0 );
10261059 if ( rc == SQLITE_OK ){
0 commit comments