#include "db_config.h"
#include "db_int.h"
#define MAX_SECTOR_SIZE 4096
int
__os_get_cluster_size(path, psize)
const char *path;
u_int32_t *psize;
{
#if (WINVER < 0x500) || defined(DB_WINCE)
*psize = DB_DEF_IOSIZE;
return (0);
#else
BYTE clustershift, sectorshift, *pcluster;
char buffer[MAX_SECTOR_SIZE];
DWORD flags, infolen, length, mcl, name_size;
HANDLE vhandle;
int ret;
NTFS_VOLUME_DATA_BUFFER ntfsinfo;
size_t name_len;
TCHAR *env_path, name_buffer[MAX_PATH + 1], root_path[MAX_PATH + 1];
WORD *psector;
if (path == NULL || psize == NULL) {
return (EINVAL);
}
name_size = MAX_PATH + 1;
*psize = 0;
TO_TSTRING(NULL, path, env_path, ret);
if (ret != 0)
return (ret);
if (!GetVolumePathName(env_path, root_path, name_size)) {
FREE_STRING(NULL, env_path);
return (__os_posix_err(__os_get_syserr()));
}
FREE_STRING(NULL, env_path);
if (!GetVolumeNameForVolumeMountPoint(
root_path, name_buffer, name_size))
return (__os_posix_err(__os_get_syserr()));
name_len = _tcsclen(name_buffer);
if (name_len > 0)
name_buffer[name_len - 1] = _T('\0');
vhandle = CreateFile(name_buffer, FILE_READ_ATTRIBUTES | FILE_READ_DATA,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
if (vhandle == INVALID_HANDLE_VALUE)
return (__os_posix_err(__os_get_syserr()));
if (!GetVolumeInformation(root_path, NULL, name_size, NULL, &mcl,
&flags, name_buffer, name_size)) {
ret = __os_posix_err(__os_get_syserr());
CloseHandle(vhandle);
return (ret);
}
ret = 0;
if (_tcscmp(name_buffer, _T("NTFS")) == 0) {
if (DeviceIoControl(
vhandle,
FSCTL_GET_NTFS_VOLUME_DATA,
NULL,
0,
&ntfsinfo,
sizeof(NTFS_VOLUME_DATA_BUFFER),
&infolen,
NULL))
*psize = ntfsinfo.BytesPerCluster;
else
ret = __os_posix_err(__os_get_syserr());
} else if (_tcscmp(name_buffer, _T("exFAT")) == 0) {
if (ReadFile(vhandle, buffer, MAX_SECTOR_SIZE, &length, NULL)) {
sectorshift = *(BYTE *)(&buffer[0x6C]);
clustershift = *(BYTE *)(&buffer[0x6D]);
*psize = 1 << sectorshift;
*psize = (*psize) << clustershift;
}
else
ret = __os_posix_err(__os_get_syserr());
} else if (_tcscmp(name_buffer, _T("FAT")) == 0 ||
_tcscmp(name_buffer, _T("FAT32")) == 0) {
if (ReadFile(vhandle, buffer, MAX_SECTOR_SIZE, &length, NULL)) {
psector = (WORD *)(&buffer[0x0B]);
pcluster = (BYTE *)(&buffer[0x0D]);
*psize = (*psector) * (*pcluster);
}
else
ret = __os_posix_err(__os_get_syserr());
}
CloseHandle(vhandle);
return (ret);
#endif
}
int
__os_exists(env, path, isdirp)
ENV *env;
const char *path;
int *isdirp;
{
DB_ENV *dbenv;
DWORD attrs;
_TCHAR *tpath;
int ret;
dbenv = env == NULL ? NULL : env->dbenv;
TO_TSTRING(env, path, tpath, ret);
if (ret != 0)
return (ret);
if (dbenv != NULL &&
FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS | DB_VERB_FILEOPS_ALL))
__db_msg(env, DB_STR_A("0033", "fileops: stat %s",
"%s"), path);
RETRY_CHK(
((attrs = GetFileAttributes(tpath)) == (DWORD)-1 ? 1 : 0), ret);
if (ret == 0) {
if (isdirp != NULL)
*isdirp = (attrs & FILE_ATTRIBUTE_DIRECTORY);
} else
ret = __os_posix_err(ret);
FREE_STRING(env, tpath);
return (ret);
}
int
__os_ioinfo(env, path, fhp, mbytesp, bytesp, iosizep)
ENV *env;
const char *path;
DB_FH *fhp;
u_int32_t *mbytesp, *bytesp, *iosizep;
{
int ret;
BY_HANDLE_FILE_INFORMATION bhfi;
unsigned __int64 filesize;
u_int32_t io_sz;
RETRY_CHK((!GetFileInformationByHandle(fhp->handle, &bhfi)), ret);
if (ret != 0) {
__db_syserr(env, ret, DB_STR("0034",
"GetFileInformationByHandle"));
return (__os_posix_err(ret));
}
filesize = ((unsigned __int64)bhfi.nFileSizeHigh << 32) +
bhfi.nFileSizeLow;
if (mbytesp != NULL)
*mbytesp = (u_int32_t)(filesize / MEGABYTE);
if (bytesp != NULL)
*bytesp = (u_int32_t)(filesize % MEGABYTE);
if (iosizep != NULL) {
if (__os_get_cluster_size(path, &io_sz) != 0 || io_sz < 1025)
*iosizep = DB_DEF_IOSIZE;
else
*iosizep = io_sz;
}
return (0);
}