mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-22 00:02:13 +03:00

and replace them with a much cleaner and more compact ext/misc/windirent.h. FossilOrigin-Name: acc978df52ec41ffdb5c27764f30d53efa1f25a314b7d98983dc0d211a36b570
164 lines
4.3 KiB
C
164 lines
4.3 KiB
C
/*
|
|
** 2025-06-05
|
|
**
|
|
** 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.
|
|
**
|
|
*************************************************************************
|
|
**
|
|
** An implementation of opendir(), readdir(), and closedir() for Windows,
|
|
** based on the FindFirstFile(), FindNextFile(), and FindClose() APIs
|
|
** of Win32.
|
|
**
|
|
** #include this file inside any C-code module that needs to use
|
|
** opendir()/readdir()/closedir(). This file is a no-op on non-Windows
|
|
** machines. On Windows, static functions are defined that implement
|
|
** those standard interfaces.
|
|
*/
|
|
#if defined(_WIN32) && defined(_MSC_VER) && !defined(SQLITE_WINDIRENT_H)
|
|
#define SQLITE_WINDIRENT_H
|
|
|
|
#ifndef WIN32_LEAN_AND_MEAN
|
|
#define WIN32_LEAN_AND_MEAN
|
|
#endif
|
|
#include <windows.h>
|
|
#include <io.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <errno.h>
|
|
#include <limits.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <string.h>
|
|
#ifndef FILENAME_MAX
|
|
# define FILENAME_MAX (260)
|
|
#endif
|
|
#ifndef S_ISREG
|
|
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
|
|
#endif
|
|
#ifndef S_ISDIR
|
|
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
|
|
#endif
|
|
#ifndef S_ISLNK
|
|
#define S_ISLNK(m) (0)
|
|
#endif
|
|
typedef unsigned short mode_t;
|
|
|
|
/* The dirent object for Windows is abbreviated. The only field really
|
|
** usable by applications is d_name[].
|
|
*/
|
|
struct dirent {
|
|
int d_ino; /* Inode number (synthesized) */
|
|
unsigned d_attributes; /* File attributes */
|
|
char d_name[FILENAME_MAX]; /* Null-terminated filename */
|
|
};
|
|
|
|
/* The internals of DIR are opaque according to standards. So it
|
|
** does not matter what we put here. */
|
|
typedef struct DIR DIR;
|
|
struct DIR {
|
|
intptr_t d_handle; /* Handle for findfirst()/findnext() */
|
|
struct dirent cur; /* Current entry */
|
|
};
|
|
|
|
/* Ignore hidden and system files */
|
|
#define WindowsFileToIgnore(a) \
|
|
((((a).attrib)&_A_HIDDEN) || (((a).attrib)&_A_SYSTEM))
|
|
|
|
/*
|
|
** Close a previously opened directory
|
|
*/
|
|
static int closedir(DIR *pDir){
|
|
int rc = 0;
|
|
if( pDir==0 ){
|
|
return EINVAL;
|
|
}
|
|
if( pDir->d_handle!=0 && pDir->d_handle!=(-1) ){
|
|
rc = _findclose(pDir->d_handle);
|
|
}
|
|
sqlite3_free(pDir);
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** Open a new directory. The directory name should be UTF-8 encoded.
|
|
** appropriate translations happen automatically.
|
|
*/
|
|
static DIR *opendir(const char *zDirName){
|
|
DIR *pDir;
|
|
wchar_t *b1;
|
|
sqlite3_int64 sz;
|
|
struct _wfinddata_t data;
|
|
|
|
pDir = sqlite3_malloc64( sizeof(DIR) );
|
|
if( pDir==0 ) return 0;
|
|
memset(pDir, 0, sizeof(DIR));
|
|
memset(&data, 0, sizeof(data));
|
|
sz = strlen(zDirName);
|
|
b1 = sqlite3_malloc64( (sz+3)*sizeof(b1[0]) );
|
|
if( b1==0 ){
|
|
closedir(pDir);
|
|
return NULL;
|
|
}
|
|
sz = MultiByteToWideChar(CP_UTF8, 0, zDirName, sz, b1, sz);
|
|
b1[sz++] = '\\';
|
|
b1[sz++] = '*';
|
|
b1[sz] = 0;
|
|
if( sz+1>sizeof(data.name)/sizeof(data.name[0]) ){
|
|
closedir(pDir);
|
|
sqlite3_free(b1);
|
|
return NULL;
|
|
}
|
|
memcpy(data.name, b1, (sz+1)*sizeof(b1[0]));
|
|
sqlite3_free(b1);
|
|
pDir->d_handle = _wfindfirst(data.name, &data);
|
|
if( pDir->d_handle<0 ){
|
|
closedir(pDir);
|
|
return NULL;
|
|
}
|
|
while( WindowsFileToIgnore(data) ){
|
|
memset(&data, 0, sizeof(data));
|
|
if( _wfindnext(pDir->d_handle, &data)==-1 ){
|
|
closedir(pDir);
|
|
return NULL;
|
|
}
|
|
}
|
|
pDir->cur.d_ino = 0;
|
|
pDir->cur.d_attributes = data.attrib;
|
|
WideCharToMultiByte(CP_UTF8, 0, data.name, -1,
|
|
pDir->cur.d_name, FILENAME_MAX, 0, 0);
|
|
return pDir;
|
|
}
|
|
|
|
/*
|
|
** Read the next entry from a directory.
|
|
**
|
|
** The returned struct-dirent object is managed by DIR. It is only
|
|
** valid until the next readdir() or closedir() call. Only the
|
|
** d_name[] field is meaningful. The d_name[] value has been
|
|
** translated into UTF8.
|
|
*/
|
|
static struct dirent *readdir(DIR *pDir){
|
|
struct _wfinddata_t data;
|
|
if( pDir==0 ) return 0;
|
|
if( (pDir->cur.d_ino++)==0 ){
|
|
return &pDir->cur;
|
|
}
|
|
do{
|
|
memset(&data, 0, sizeof(data));
|
|
if( _wfindnext(pDir->d_handle, &data)==-1 ){
|
|
return NULL;
|
|
}
|
|
}while( WindowsFileToIgnore(data) );
|
|
pDir->cur.d_attributes = data.attrib;
|
|
WideCharToMultiByte(CP_UTF8, 0, data.name, -1,
|
|
pDir->cur.d_name, FILENAME_MAX, 0, 0);
|
|
return &pDir->cur;
|
|
}
|
|
|
|
#endif /* defined(_WIN32) && defined(_MSC_VER) */
|