| | @@ -1796,10 +1796,11 @@ |
| 1796 | 1796 | # ifdef FILENAME_MAX |
| 1797 | 1797 | # define NAME_MAX (FILENAME_MAX) |
| 1798 | 1798 | # else |
| 1799 | 1799 | # define NAME_MAX (260) |
| 1800 | 1800 | # endif |
| 1801 | +# define DIRENT_NAME_MAX (NAME_MAX) |
| 1801 | 1802 | #endif |
| 1802 | 1803 | |
| 1803 | 1804 | /* |
| 1804 | 1805 | ** We need to define "NULL_INTPTR_T" and "BAD_INTPTR_T". |
| 1805 | 1806 | */ |
| | @@ -1839,12 +1840,11 @@ |
| 1839 | 1840 | #endif |
| 1840 | 1841 | |
| 1841 | 1842 | /* |
| 1842 | 1843 | ** Provide a macro, for use by the implementation, to determine if a |
| 1843 | 1844 | ** particular directory entry should be skipped over when searching for |
| 1844 | | -** the next directory entry that should be returned by the readdir() or |
| 1845 | | -** readdir_r() functions. |
| 1845 | +** the next directory entry that should be returned by the readdir(). |
| 1846 | 1846 | */ |
| 1847 | 1847 | |
| 1848 | 1848 | #ifndef is_filtered |
| 1849 | 1849 | # define is_filtered(a) ((((a).attrib)&_A_HIDDEN) || (((a).attrib)&_A_SYSTEM)) |
| 1850 | 1850 | #endif |
| | @@ -1856,16 +1856,15 @@ |
| 1856 | 1856 | |
| 1857 | 1857 | extern const char *windirent_getenv(const char *name); |
| 1858 | 1858 | |
| 1859 | 1859 | /* |
| 1860 | 1860 | ** Finally, we can provide the function prototypes for the opendir(), |
| 1861 | | -** readdir(), readdir_r(), and closedir() POSIX functions. |
| 1861 | +** readdir(), and closedir() POSIX functions. |
| 1862 | 1862 | */ |
| 1863 | 1863 | |
| 1864 | 1864 | extern LPDIR opendir(const char *dirname); |
| 1865 | 1865 | extern LPDIRENT readdir(LPDIR dirp); |
| 1866 | | -extern INT readdir_r(LPDIR dirp, LPDIRENT entry, LPDIRENT *result); |
| 1867 | 1866 | extern INT closedir(LPDIR dirp); |
| 1868 | 1867 | |
| 1869 | 1868 | #endif /* defined(WIN32) && defined(_MSC_VER) */ |
| 1870 | 1869 | |
| 1871 | 1870 | /************************* End test_windirent.h ********************/ |
| | @@ -1918,27 +1917,45 @@ |
| 1918 | 1917 | |
| 1919 | 1918 | /* |
| 1920 | 1919 | ** Implementation of the POSIX opendir() function using the MSVCRT. |
| 1921 | 1920 | */ |
| 1922 | 1921 | LPDIR opendir( |
| 1923 | | - const char *dirname |
| 1922 | + const char *dirname /* Directory name, UTF8 encoding */ |
| 1924 | 1923 | ){ |
| 1925 | | - struct _finddata_t data; |
| 1924 | + struct _wfinddata_t data; |
| 1926 | 1925 | LPDIR dirp = (LPDIR)sqlite3_malloc(sizeof(DIR)); |
| 1927 | 1926 | SIZE_T namesize = sizeof(data.name) / sizeof(data.name[0]); |
| 1927 | + wchar_t *b1; |
| 1928 | + sqlite3_int64 sz; |
| 1928 | 1929 | |
| 1929 | 1930 | if( dirp==NULL ) return NULL; |
| 1930 | 1931 | memset(dirp, 0, sizeof(DIR)); |
| 1931 | 1932 | |
| 1932 | 1933 | /* TODO: Remove this if Unix-style root paths are not used. */ |
| 1933 | 1934 | if( sqlite3_stricmp(dirname, "/")==0 ){ |
| 1934 | 1935 | dirname = windirent_getenv("SystemDrive"); |
| 1935 | 1936 | } |
| 1936 | 1937 | |
| 1937 | | - memset(&data, 0, sizeof(struct _finddata_t)); |
| 1938 | | - _snprintf(data.name, namesize, "%s\\*", dirname); |
| 1939 | | - dirp->d_handle = _findfirst(data.name, &data); |
| 1938 | + memset(&data, 0, sizeof(data)); |
| 1939 | + sz = strlen(dirname); |
| 1940 | + b1 = sqlite3_malloc64( (sz+3)*sizeof(b1[0]) ); |
| 1941 | + if( b1==0 ){ |
| 1942 | + closedir(dirp); |
| 1943 | + return NULL; |
| 1944 | + } |
| 1945 | + sz = MultiByteToWideChar(CP_UTF8, 0, dirname, sz, b1, sz); |
| 1946 | + b1[sz++] = '\\'; |
| 1947 | + b1[sz++] = '*'; |
| 1948 | + b1[sz] = 0; |
| 1949 | + if( sz+1>(sqlite3_int64)namesize ){ |
| 1950 | + closedir(dirp); |
| 1951 | + sqlite3_free(b1); |
| 1952 | + return NULL; |
| 1953 | + } |
| 1954 | + memcpy(data.name, b1, (sz+1)*sizeof(b1[0])); |
| 1955 | + sqlite3_free(b1); |
| 1956 | + dirp->d_handle = _wfindfirst(data.name, &data); |
| 1940 | 1957 | |
| 1941 | 1958 | if( dirp->d_handle==BAD_INTPTR_T ){ |
| 1942 | 1959 | closedir(dirp); |
| 1943 | 1960 | return NULL; |
| 1944 | 1961 | } |
| | @@ -1945,34 +1962,33 @@ |
| 1945 | 1962 | |
| 1946 | 1963 | /* TODO: Remove this block to allow hidden and/or system files. */ |
| 1947 | 1964 | if( is_filtered(data) ){ |
| 1948 | 1965 | next: |
| 1949 | 1966 | |
| 1950 | | - memset(&data, 0, sizeof(struct _finddata_t)); |
| 1951 | | - if( _findnext(dirp->d_handle, &data)==-1 ){ |
| 1967 | + memset(&data, 0, sizeof(data)); |
| 1968 | + if( _wfindnext(dirp->d_handle, &data)==-1 ){ |
| 1952 | 1969 | closedir(dirp); |
| 1953 | 1970 | return NULL; |
| 1954 | 1971 | } |
| 1955 | 1972 | |
| 1956 | 1973 | /* TODO: Remove this block to allow hidden and/or system files. */ |
| 1957 | 1974 | if( is_filtered(data) ) goto next; |
| 1958 | 1975 | } |
| 1959 | 1976 | |
| 1960 | 1977 | dirp->d_first.d_attributes = data.attrib; |
| 1961 | | - strncpy(dirp->d_first.d_name, data.name, NAME_MAX); |
| 1962 | | - dirp->d_first.d_name[NAME_MAX] = '\0'; |
| 1963 | | - |
| 1978 | + WideCharToMultiByte(CP_UTF8, 0, data.name, -1, |
| 1979 | + dirp->d_first.d_name, DIRENT_NAME_MAX, 0, 0); |
| 1964 | 1980 | return dirp; |
| 1965 | 1981 | } |
| 1966 | 1982 | |
| 1967 | 1983 | /* |
| 1968 | 1984 | ** Implementation of the POSIX readdir() function using the MSVCRT. |
| 1969 | 1985 | */ |
| 1970 | 1986 | LPDIRENT readdir( |
| 1971 | 1987 | LPDIR dirp |
| 1972 | 1988 | ){ |
| 1973 | | - struct _finddata_t data; |
| 1989 | + struct _wfinddata_t data; |
| 1974 | 1990 | |
| 1975 | 1991 | if( dirp==NULL ) return NULL; |
| 1976 | 1992 | |
| 1977 | 1993 | if( dirp->d_first.d_ino==0 ){ |
| 1978 | 1994 | dirp->d_first.d_ino++; |
| | @@ -1981,69 +1997,23 @@ |
| 1981 | 1997 | return &dirp->d_first; |
| 1982 | 1998 | } |
| 1983 | 1999 | |
| 1984 | 2000 | next: |
| 1985 | 2001 | |
| 1986 | | - memset(&data, 0, sizeof(struct _finddata_t)); |
| 1987 | | - if( _findnext(dirp->d_handle, &data)==-1 ) return NULL; |
| 2002 | + memset(&data, 0, sizeof(data)); |
| 2003 | + if( _wfindnext(dirp->d_handle, &data)==-1 ) return NULL; |
| 1988 | 2004 | |
| 1989 | 2005 | /* TODO: Remove this block to allow hidden and/or system files. */ |
| 1990 | 2006 | if( is_filtered(data) ) goto next; |
| 1991 | 2007 | |
| 1992 | 2008 | dirp->d_next.d_ino++; |
| 1993 | 2009 | dirp->d_next.d_attributes = data.attrib; |
| 1994 | | - strncpy(dirp->d_next.d_name, data.name, NAME_MAX); |
| 1995 | | - dirp->d_next.d_name[NAME_MAX] = '\0'; |
| 1996 | | - |
| 2010 | + WideCharToMultiByte(CP_UTF8, 0, data.name, -1, |
| 2011 | + dirp->d_next.d_name, DIRENT_NAME_MAX, 0, 0); |
| 1997 | 2012 | return &dirp->d_next; |
| 1998 | 2013 | } |
| 1999 | 2014 | |
| 2000 | | -/* |
| 2001 | | -** Implementation of the POSIX readdir_r() function using the MSVCRT. |
| 2002 | | -*/ |
| 2003 | | -INT readdir_r( |
| 2004 | | - LPDIR dirp, |
| 2005 | | - LPDIRENT entry, |
| 2006 | | - LPDIRENT *result |
| 2007 | | -){ |
| 2008 | | - struct _finddata_t data; |
| 2009 | | - |
| 2010 | | - if( dirp==NULL ) return EBADF; |
| 2011 | | - |
| 2012 | | - if( dirp->d_first.d_ino==0 ){ |
| 2013 | | - dirp->d_first.d_ino++; |
| 2014 | | - dirp->d_next.d_ino++; |
| 2015 | | - |
| 2016 | | - entry->d_ino = dirp->d_first.d_ino; |
| 2017 | | - entry->d_attributes = dirp->d_first.d_attributes; |
| 2018 | | - strncpy(entry->d_name, dirp->d_first.d_name, NAME_MAX); |
| 2019 | | - entry->d_name[NAME_MAX] = '\0'; |
| 2020 | | - |
| 2021 | | - *result = entry; |
| 2022 | | - return 0; |
| 2023 | | - } |
| 2024 | | - |
| 2025 | | -next: |
| 2026 | | - |
| 2027 | | - memset(&data, 0, sizeof(struct _finddata_t)); |
| 2028 | | - if( _findnext(dirp->d_handle, &data)==-1 ){ |
| 2029 | | - *result = NULL; |
| 2030 | | - return ENOENT; |
| 2031 | | - } |
| 2032 | | - |
| 2033 | | - /* TODO: Remove this block to allow hidden and/or system files. */ |
| 2034 | | - if( is_filtered(data) ) goto next; |
| 2035 | | - |
| 2036 | | - entry->d_ino = (ino_t)-1; /* not available */ |
| 2037 | | - entry->d_attributes = data.attrib; |
| 2038 | | - strncpy(entry->d_name, data.name, NAME_MAX); |
| 2039 | | - entry->d_name[NAME_MAX] = '\0'; |
| 2040 | | - |
| 2041 | | - *result = entry; |
| 2042 | | - return 0; |
| 2043 | | -} |
| 2044 | | - |
| 2045 | 2015 | /* |
| 2046 | 2016 | ** Implementation of the POSIX closedir() function using the MSVCRT. |
| 2047 | 2017 | */ |
| 2048 | 2018 | INT closedir( |
| 2049 | 2019 | LPDIR dirp |
| | @@ -8061,18 +8031,13 @@ |
| 8061 | 8031 | # include "windows.h" |
| 8062 | 8032 | # include <io.h> |
| 8063 | 8033 | # include <direct.h> |
| 8064 | 8034 | /* # include "test_windirent.h" */ |
| 8065 | 8035 | # define dirent DIRENT |
| 8066 | | -# ifndef chmod |
| 8067 | | -# define chmod _chmod |
| 8068 | | -# endif |
| 8069 | | -# ifndef stat |
| 8070 | | -# define stat _stat |
| 8071 | | -# endif |
| 8072 | | -# define mkdir(path,mode) _mkdir(path) |
| 8073 | | -# define lstat(path,buf) stat(path,buf) |
| 8036 | +# define stat _stat |
| 8037 | +# define chmod(path,mode) fileio_chmod(path,mode) |
| 8038 | +# define mkdir(path,mode) fileio_mkdir(path) |
| 8074 | 8039 | #endif |
| 8075 | 8040 | #include <time.h> |
| 8076 | 8041 | #include <errno.h> |
| 8077 | 8042 | |
| 8078 | 8043 | /* When used as part of the CLI, the sqlite3_stdio.h module will have |
| | @@ -8093,10 +8058,44 @@ |
| 8093 | 8058 | #define FSDIR_COLUMN_MTIME 2 /* Last modification time */ |
| 8094 | 8059 | #define FSDIR_COLUMN_DATA 3 /* File content */ |
| 8095 | 8060 | #define FSDIR_COLUMN_PATH 4 /* Path to top of search */ |
| 8096 | 8061 | #define FSDIR_COLUMN_DIR 5 /* Path is relative to this directory */ |
| 8097 | 8062 | |
| 8063 | +/* |
| 8064 | +** UTF8 chmod() function for Windows |
| 8065 | +*/ |
| 8066 | +#if defined(_WIN32) || defined(WIN32) |
| 8067 | +static int fileio_chmod(const char *zPath, int pmode){ |
| 8068 | + sqlite3_int64 sz = strlen(zPath); |
| 8069 | + wchar_t *b1 = sqlite3_malloc64( (sz+1)*sizeof(b1[0]) ); |
| 8070 | + int rc; |
| 8071 | + if( b1==0 ) return -1; |
| 8072 | + sz = MultiByteToWideChar(CP_UTF8, 0, zPath, sz, b1, sz); |
| 8073 | + b1[sz] = 0; |
| 8074 | + rc = _wchmod(b1, pmode); |
| 8075 | + sqlite3_free(b1); |
| 8076 | + return rc; |
| 8077 | +} |
| 8078 | +#endif |
| 8079 | + |
| 8080 | +/* |
| 8081 | +** UTF8 mkdir() function for Windows |
| 8082 | +*/ |
| 8083 | +#if defined(_WIN32) || defined(WIN32) |
| 8084 | +static int fileio_mkdir(const char *zPath){ |
| 8085 | + sqlite3_int64 sz = strlen(zPath); |
| 8086 | + wchar_t *b1 = sqlite3_malloc64( (sz+1)*sizeof(b1[0]) ); |
| 8087 | + int rc; |
| 8088 | + if( b1==0 ) return -1; |
| 8089 | + sz = MultiByteToWideChar(CP_UTF8, 0, zPath, sz, b1, sz); |
| 8090 | + b1[sz] = 0; |
| 8091 | + rc = _wmkdir(b1); |
| 8092 | + sqlite3_free(b1); |
| 8093 | + return rc; |
| 8094 | +} |
| 8095 | +#endif |
| 8096 | + |
| 8098 | 8097 | |
| 8099 | 8098 | /* |
| 8100 | 8099 | ** Set the result stored by context ctx to a blob containing the |
| 8101 | 8100 | ** contents of file zName. Or, leave the result unchanged (NULL) |
| 8102 | 8101 | ** if the file does not exist or is unreadable. |
| | @@ -8254,11 +8253,17 @@ |
| 8254 | 8253 | static int fileStat( |
| 8255 | 8254 | const char *zPath, |
| 8256 | 8255 | struct stat *pStatBuf |
| 8257 | 8256 | ){ |
| 8258 | 8257 | #if defined(_WIN32) |
| 8259 | | - int rc = stat(zPath, pStatBuf); |
| 8258 | + sqlite3_int64 sz = strlen(zPath); |
| 8259 | + wchar_t *b1 = sqlite3_malloc64( (sz+1)*sizeof(b1[0]) ); |
| 8260 | + int rc; |
| 8261 | + if( b1==0 ) return 1; |
| 8262 | + sz = MultiByteToWideChar(CP_UTF8, 0, zPath, sz, b1, sz); |
| 8263 | + b1[sz] = 0; |
| 8264 | + rc = _wstat(b1, pStatBuf); |
| 8260 | 8265 | if( rc==0 ) statTimesToUtc(zPath, pStatBuf); |
| 8261 | 8266 | return rc; |
| 8262 | 8267 | #else |
| 8263 | 8268 | return stat(zPath, pStatBuf); |
| 8264 | 8269 | #endif |
| | @@ -8272,13 +8277,11 @@ |
| 8272 | 8277 | static int fileLinkStat( |
| 8273 | 8278 | const char *zPath, |
| 8274 | 8279 | struct stat *pStatBuf |
| 8275 | 8280 | ){ |
| 8276 | 8281 | #if defined(_WIN32) |
| 8277 | | - int rc = lstat(zPath, pStatBuf); |
| 8278 | | - if( rc==0 ) statTimesToUtc(zPath, pStatBuf); |
| 8279 | | - return rc; |
| 8282 | + return fileStat(zPath, pStatBuf); |
| 8280 | 8283 | #else |
| 8281 | 8284 | return lstat(zPath, pStatBuf); |
| 8282 | 8285 | #endif |
| 8283 | 8286 | } |
| 8284 | 8287 | |
| | @@ -16784,11 +16787,11 @@ |
| 16784 | 16787 | case SQLITE_FCNTL_POWERSAFE_OVERWRITE: zOp = "POWERSAFE_OVERWRITE"; break; |
| 16785 | 16788 | case SQLITE_FCNTL_PRAGMA: { |
| 16786 | 16789 | const char *const* a = (const char*const*)pArg; |
| 16787 | 16790 | if( a[1] && strcmp(a[1],"vfstrace")==0 && a[2] ){ |
| 16788 | 16791 | const u8 *zArg = (const u8*)a[2]; |
| 16789 | | - if( zArg[0]>='0' && zArg[0]<=9 ){ |
| 16792 | + if( zArg[0]>='0' && zArg[0]<='9' ){ |
| 16790 | 16793 | pInfo->mTrace = (sqlite3_uint64)strtoll(a[2], 0, 0); |
| 16791 | 16794 | }else{ |
| 16792 | 16795 | static const struct { |
| 16793 | 16796 | const char *z; |
| 16794 | 16797 | unsigned int m; |
| 16795 | 16798 | |