# define STRUCT_STAT struct _stat
# define chmod(path,mode) fileio_chmod(path,mode)
# define mkdir(path,mode) fileio_mkdir(path)
+ extern LPWSTR sqlite3_win32_utf8_to_unicode(const char*);
+ extern char *sqlite3_win32_unicode_to_utf8(LPCWSTR);
#endif
#include <time.h>
#include <errno.h>
*/
#if defined(_WIN32) || defined(WIN32)
static int fileio_chmod(const char *zPath, int pmode){
- sqlite3_int64 sz = strlen(zPath);
- wchar_t *b1 = sqlite3_malloc64( (sz+1)*sizeof(b1[0]) );
int rc;
+ wchar_t *b1 = sqlite3_win32_utf8_to_unicode(zPath);
if( b1==0 ) return -1;
- sz = MultiByteToWideChar(CP_UTF8, 0, zPath, sz, b1, sz);
- b1[sz] = 0;
rc = _wchmod(b1, pmode);
sqlite3_free(b1);
return rc;
*/
#if defined(_WIN32) || defined(WIN32)
static int fileio_mkdir(const char *zPath){
- sqlite3_int64 sz = strlen(zPath);
- wchar_t *b1 = sqlite3_malloc64( (sz+1)*sizeof(b1[0]) );
int rc;
+ wchar_t *b1 = sqlite3_win32_utf8_to_unicode(zPath);
if( b1==0 ) return -1;
- sz = MultiByteToWideChar(CP_UTF8, 0, zPath, sz, b1, sz);
- b1[sz] = 0;
rc = _wmkdir(b1);
sqlite3_free(b1);
return rc;
return (fileIntervals.QuadPart - epochIntervals.QuadPart) / 10000000;
}
-
-
-#if defined(FILEIO_WIN32_DLL) && (defined(_WIN32) || defined(WIN32))
-# /* To allow a standalone DLL, use this next replacement function: */
-# undef sqlite3_win32_utf8_to_unicode
-# define sqlite3_win32_utf8_to_unicode utf8_to_utf16
-#
-LPWSTR utf8_to_utf16(const char *z){
- int nAllot = MultiByteToWideChar(CP_UTF8, 0, z, -1, NULL, 0);
- LPWSTR rv = sqlite3_malloc(nAllot * sizeof(WCHAR));
- if( rv!=0 && 0 < MultiByteToWideChar(CP_UTF8, 0, z, -1, rv, nAllot) )
- return rv;
- sqlite3_free(rv);
- return 0;
-}
-#endif
-
-/*
-** This function attempts to normalize the time values found in the stat()
-** buffer to UTC. This is necessary on Win32, where the runtime library
-** appears to return these values as local times.
-*/
-static void statTimesToUtc(
- const char *zPath,
- STRUCT_STAT *pStatBuf
-){
- HANDLE hFindFile;
- WIN32_FIND_DATAW fd;
- LPWSTR zUnicodeName;
- extern LPWSTR sqlite3_win32_utf8_to_unicode(const char*);
- zUnicodeName = sqlite3_win32_utf8_to_unicode(zPath);
- if( zUnicodeName ){
- memset(&fd, 0, sizeof(WIN32_FIND_DATAW));
- hFindFile = FindFirstFileW(zUnicodeName, &fd);
- if( hFindFile!=NULL ){
- pStatBuf->st_ctime = (time_t)fileTimeToUnixTime(&fd.ftCreationTime);
- pStatBuf->st_atime = (time_t)fileTimeToUnixTime(&fd.ftLastAccessTime);
- pStatBuf->st_mtime = (time_t)fileTimeToUnixTime(&fd.ftLastWriteTime);
- FindClose(hFindFile);
- }
- sqlite3_free(zUnicodeName);
- }
-}
-#endif
+#endif /* _WIN32 */
/*
** This function is used in place of stat(). On Windows, special handling
STRUCT_STAT *pStatBuf
){
#if defined(_WIN32)
- sqlite3_int64 sz = strlen(zPath);
- wchar_t *b1 = sqlite3_malloc64( (sz+1)*sizeof(b1[0]) );
int rc;
+ wchar_t *b1 = sqlite3_win32_utf8_to_unicode(zPath);
if( b1==0 ) return 1;
- sz = MultiByteToWideChar(CP_UTF8, 0, zPath, sz, b1, sz);
- b1[sz] = 0;
rc = _wstat(b1, pStatBuf);
- if( rc==0 ) statTimesToUtc(zPath, pStatBuf);
+ if( rc==0 ){
+ HANDLE hFindFile;
+ WIN32_FIND_DATAW fd;
+ memset(&fd, 0, sizeof(WIN32_FIND_DATAW));
+ hFindFile = FindFirstFileW(b1, &fd);
+ if( hFindFile!=NULL ){
+ pStatBuf->st_ctime = (time_t)fileTimeToUnixTime(&fd.ftCreationTime);
+ pStatBuf->st_atime = (time_t)fileTimeToUnixTime(&fd.ftLastAccessTime);
+ pStatBuf->st_mtime = (time_t)fileTimeToUnixTime(&fd.ftLastWriteTime);
+ FindClose(hFindFile);
+ }
+ }
sqlite3_free(b1);
return rc;
#else
# define fsdirRegister(x) SQLITE_OK
#endif
+/*
+** The realpath() C-language function, implemented as an SQL function.
+*/
+static void realpathFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+#if !defined(_WIN32) /* BEGIN unix */
+
+ const char *zPath; /* Input */
+ char *zOut = 0; /* Result */
+ char *z = 0; /* Temporary buffer */
+#if defined(PATH_MAX)
+ char zBuf[PATH_MAX+1]; /* Space for the temporary buffer */
+#endif
+
+ (void)argc;
+ zPath = (const char*)sqlite3_value_text(argv[0]);
+ if( zPath==0 ) return;
+
+#if defined(PATH_MAX)
+ z = realpath(zPath, zBuf);
+ if( z ){
+ zOut = sqlite3_mprintf("%s", zBuf);
+ }
+#endif /* defined(PATH_MAX) */
+ if( zOut==0 ){
+ /* Try POSIX.1-2008 malloc behavior */
+ z = realpath(zPath, NULL);
+ if( z ){
+ zOut = sqlite3_mprintf("%s", z);
+ free(z);
+ }
+ }
+
+#else /* End UNIX, Begin WINDOWS */
+
+ const char *zPath; /* Input */
+ wchar_t *zPath16; /* UTF16 translation of zPath */
+ char *zOut = 0; /* Result */
+ wchar_t *z = 0; /* Temporary buffer */
+
+ (void)argc;
+ zPath = (const char*)sqlite3_value_text(argv[0]);
+ if( zPath==0 ) return;
+
+ zPath16 = sqlite3_win32_utf8_to_unicode(zPath);
+ if( zPath16==0 ) return;
+ z = _wfullpath(NULL, zPath16, 0);
+ sqlite3_free(zPath16);
+ if( z==0 ){
+ sqlite3_result_error(context, "unable to resolve path", -1);
+ return;
+ }
+ zOut = sqlite3_win32_unicode_to_utf8(z);
+ free(z);
+
+#endif /* End WINDOWS, Begin common code */
+
+ if( zOut==0 ){
+ sqlite3_result_error(context, "unable to resolve path", -1);
+ return;
+ }
+ sqlite3_result_text(context, zOut, -1, sqlite3_free);
+}
+
+
#ifdef _WIN32
__declspec(dllexport)
#endif
if( rc==SQLITE_OK ){
rc = fsdirRegister(db);
}
+ if( rc==SQLITE_OK ){
+ rc = sqlite3_create_function(db, "realpath", 1,
+ SQLITE_UTF8, 0,
+ realpathFunc, 0, 0);
+ }
+
return rc;
}
-C Fix\stypos\sand\sinclude\swording\sin\sthe\sdocumentation\sfor\nSQLITE_DBCONFIG_FP_DIGITS.
-D 2026-02-21T21:19:41.549
+C Add\sthe\srealpath()\sSQL\sfunction\sto\sthe\sfileio.c\sextension.\s\sAnd\sclean\sup\nthe\sUTF8\shandling\son\sthe\sWindows\sside\sof\sthat\sextension\swhile\swe\sare\sat\sit.
+D 2026-02-22T20:44:52.610
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F ext/misc/decimal.c e1da22eee70d7e3eaa99a6b761bc03c4d01d7ffa554bf3178b1f1f184932806c
F ext/misc/eval.c 04bc9aada78c888394204b4ed996ab834b99726fb59603b0ee3ed6e049755dc1
F ext/misc/explain.c 606100185fb90d6a1eade1ed0414d53503c86820d8956a06e3b0a56291894f2b
-F ext/misc/fileio.c 452300ca34fadafd2bb9eb09557de5a518da1fd2349f9f9cedd22b1566a7164f
+F ext/misc/fileio.c 6bbde149252e989fce657bfba66754dd7c545311546292cf33976e6b455a658c
F ext/misc/fossildelta.c 86dfa83f85f7ccd640591d8a5c6865346d0c2ee6a949d78591eceb892f1cbfec
F ext/misc/fuzzer.c 6b231352815304ba60d8e9ec2ee73d4918e74d9b76bda8940ba2b64e8777515e
F ext/misc/ieee754.c 2901d08a586d00a1d3c0fd89e03c57ee9e2b5f013b0daab9e49c7a48a9d5946b
F tool/warnings.sh d924598cf2f55a4ecbc2aeb055c10bd5f48114793e7ba25f9585435da29e7e98
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c
-P f16c7c4000f2b992f7245dcaf669f13ed464579f8894f3c16842eebf41285c70
-R 944ea7c224f9333bdc2c56f7b2ed487a
+P c30cee1224904eb2092daa0ad9494aec7c7a8c6c1661f5b91b62c3ef0c5ea95b
+R a026dfab96aebae2bd7cee1e81138b75
U drh
-Z ef2f611c8a724472ddbfbfc7d613ba7b
+Z 7731fd8c09c5128d6fba3a643ba9f80c
# Remove this line to create a well-formed Fossil manifest.