⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 winos.c

📁 在VC6环境下开发
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
** This file contains code that is specific to particular operating
** systems.  The purpose of this file is to provide a uniform abstraction
** on which the rest of eDb can operate.
*/

#include "eDbInit.h"
/*
** Macros used to determine whether or not to use threads.  The
** eDb_UNIX_THREADS macro is defined if we are synchronizing for
** Posix threads and eDb_W32_THREADS is defined if we are
** synchronizing using Win32 threads.
*/

#if defined(THREADSAFE) && THREADSAFE
# define eDb_W32_THREADS 1
#endif

/*
** Macros for performance tracing.  Normally turned off
*/
#if 0
static int last_page = 0;
__inline__ unsigned long long int hwtime(void){
  unsigned long long int x;
  __asm__("rdtsc\n\t"
          "mov %%edx, %%ecx\n\t"
          :"=A" (x));
  return x;
}
static unsigned long long int g_start;
static unsigned int elapse;
#define TIMER_START       g_start=hwtime()
#define TIMER_END         elapse=hwtime()-g_start
#define SEEK(X)           last_page=(X)
#define TRACE1(X)         fprintf(stderr,X)
#define TRACE2(X,Y)       fprintf(stderr,X,Y)
#define TRACE3(X,Y,Z)     fprintf(stderr,X,Y,Z)
#define TRACE4(X,Y,Z,A)   fprintf(stderr,X,Y,Z,A)
#define TRACE5(X,Y,Z,A,B) fprintf(stderr,X,Y,Z,A,B)
#else
#define TIMER_START
#define TIMER_END
#define SEEK(X)
#define TRACE1(X)
#define TRACE2(X,Y)
#define TRACE3(X,Y,Z)
#define TRACE4(X,Y,Z,A)
#define TRACE5(X,Y,Z,A,B)
#endif

/*
** If we compile with the eDb_TEST macro set, then the following block
** of code will give us the ability to simulate a disk I/O error.  This
** is used for testing the I/O recovery logic.
*/
#ifdef eDb_TEST
int eDb_io_error_pending = 0;
#define SimulateIOError(A)  \
   if( eDb_io_error_pending ) \
     if( eDb_io_error_pending-- == 1 ){ local_ioerr(); return A; }
static void local_ioerr(){
  eDb_io_error_pending = 0;  /* Really just a place to set a breakpoint */
}
#else
#define SimulateIOError(A)
#endif

/*
** When testing, keep a count of the number of open files.
*/
#ifdef eDb_TEST
int eDb_open_file_count = 0;
#define OpenCounter(X)  eDb_open_file_count+=(X)
#else
#define OpenCounter(X)
#endif


/*
** Delete the named file
*/
int eDbOsDelete(const char *zFilename){
	DeleteFile(zFilename);
	return eDb_OK;
}

/*
** Return TRUE if the named file exists.
*/
int eDbOsFileExists(const char *zFilename){
	return GetFileAttributes(zFilename) != 0xffffffff;
}

/*
** Attempt to open a file for both reading and writing.  If that
** fails, try opening it read-only.  If the file does not exist,
** try to create it.
**
** On success, a handle for the open file is written to *id
** and *pReadonly is set to 0 if the file was opened for reading and
** writing or 1 if the file was opened read-only.  The function returns
** eDb_OK.
**
** On failure, the function returns eDb_CANTOPEN and leaves
** *id and *pReadonly unchanged.
*/
int eDbOsOpenReadWrite(const char *zFilename,OsFile *id,int *pReadonly){
	HANDLE h = CreateFile(zFilename,
		GENERIC_READ | GENERIC_WRITE,
		FILE_SHARE_READ | FILE_SHARE_WRITE,
		NULL,
		OPEN_ALWAYS,
		FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
		NULL
	);
	if( h==INVALID_HANDLE_VALUE ){
		h = CreateFile(zFilename,
			GENERIC_READ,
			FILE_SHARE_READ,
			NULL,
			OPEN_ALWAYS,
			FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
			NULL
		);
		if( h==INVALID_HANDLE_VALUE ){
			return eDb_CANTOPEN;
		}
		*pReadonly = 1;
	}else{
		*pReadonly = 0;
	}
	id->h = h;
	id->locked = 0;
	OpenCounter(+1);
	return eDb_OK;
}


/*
** Attempt to open a new file for exclusive access by this process.
** The file will be opened for both reading and writing.  To avoid
** a potential security problem, we do not allow the file to have
** previously existed.  Nor do we allow the file to be a symbolic
** link.
**
** If delFlag is true, then make arrangements to automatically delete
** the file when it is closed.
**
** On success, write the file handle into *id and return eDb_OK.
**
** On failure, return eDb_CANTOPEN.
*/
int eDbOsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){
	HANDLE h;
	int fileflags;
	if( delFlag ){
		fileflags = FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_RANDOM_ACCESS
			| FILE_FLAG_DELETE_ON_CLOSE;
	}else{
		fileflags = FILE_FLAG_RANDOM_ACCESS;
	}
	h = CreateFile(zFilename,
		GENERIC_READ | GENERIC_WRITE,
		0,
		NULL,
		CREATE_ALWAYS,
		fileflags,
		NULL
	);
	if( h==INVALID_HANDLE_VALUE ){
		return eDb_CANTOPEN;
	}
	id->h = h;
	id->locked = 0;
	OpenCounter(+1);
	return eDb_OK;
}

/*
** Attempt to open a new file for read-only access.
**
** On success, write the file handle into *id and return eDb_OK.
**
** On failure, return eDb_CANTOPEN.
*/
int eDbOsOpenReadOnly(const char *zFilename, OsFile *id){
	HANDLE h = CreateFile(zFilename,
		GENERIC_READ,
		0,
		NULL,
		OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
		NULL
	);
	if( h==INVALID_HANDLE_VALUE ){
		return eDb_CANTOPEN;
	}
	id->h = h;
	id->locked = 0;
	OpenCounter(+1);
	return eDb_OK;
}

/*
** Attempt to open a file descriptor for the directory that contains a
** file.  This file descriptor can be used to fsync() the directory
** in order to make sure the creation of a new file is actually written
** to disk.
**
** This routine is only meaningful for Unix.  It is a no-op under
** windows since windows does not support hard links.
**
** On success, a handle for a previously open file is at *id is
** updated with the new directory file descriptor and eDb_OK is
** returned.
**
** On failure, the function returns eDb_CANTOPEN and leaves
** *id unchanged.
*/
int eDbOsOpenDirectory(const char *zDirname,OsFile *id){
	return eDb_OK;
}

/*
** Create a temporary file name in zBuf.  zBuf must be big enough to
** hold at least eDb_TEMPNAME_SIZE characters.
*/
void eDbRandomness(int N, void *pBuf);
int eDbOsTempFileName(char *zBuf){
	static char zChars[] =
		"abcdefghijklmnopqrstuvwxyz"
		"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
		"0123456789";
	int i, j;
	char zTempPath[eDb_TEMPNAME_SIZE];
	GetTempPath(eDb_TEMPNAME_SIZE-30, zTempPath);
	for(i=strlen(zTempPath); i>0 && zTempPath[i-1]=='\\'; i--){}
	zTempPath[i] = 0;
	for(;;){
		sprintf(zBuf, "%s\\"TEMP_FILE_PREFIX, zTempPath);
		j = strlen(zBuf);
		eDbRandomness(15, &zBuf[j]);
		for(i=0; i<15; i++, j++){
		  zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
		}
		zBuf[j] = 0;
		if( !eDbOsFileExists(zBuf) ) break;
	}
	return eDb_OK; 
}

/*
** Close a file.
*/
int eDbOsClose(OsFile *id){
	CloseHandle(id->h);
	OpenCounter(-1);
	return eDb_OK;
}

/*
** Read data from a file into a buffer.  Return eDb_OK if all
** bytes were read successfully and eDb_IOERR if anything goes
** wrong.
*/
int eDbOsRead(OsFile *id, void *pBuf, int amt){
	DWORD got;
	SimulateIOError(eDb_IOERR);
	TRACE2("READ %d\n", last_page);
	if( !ReadFile(id->h, pBuf, amt, &got, 0) ){
		got = 0;
	}
	if( got==(DWORD)amt ){
		return eDb_OK;
	}else{
		return eDb_IOERR;
	}
}

/*
** Write data from a buffer into a file.  Return eDb_OK on success
** or some other error code on failure.
*/
int eDbOsWrite(OsFile *id, const void *pBuf, int amt){
	int rc;
	DWORD wrote;
	SimulateIOError(eDb_IOERR);
	TRACE2("WRITE %d\n", last_page);
	while( amt>0 && (rc = WriteFile(id->h, pBuf, amt, &wrote, 0))!=0 && wrote>0 ){
		amt -= wrote;
		pBuf = &((char*)pBuf)[wrote];
	}
	if( !rc || amt>(int)wrote ){
		return eDb_FULL;
	}
	return eDb_OK;
}

/*
** Move the read/write pointer in a file.
*/
int eDbOsSeek(OsFile *id, off_t offset){
	//SEEK(offset/1024 + 1);
	LONG upperBits = (LONG)(offset>>32);
	LONG lowerBits = (LONG)(offset & 0xffffffff);
	DWORD rc;
	rc = SetFilePointer(id->h, lowerBits, &upperBits, FILE_BEGIN);
	/* TRACE3("SEEK rc=0x%x upper=0x%x\n", rc, upperBits); */
	return eDb_OK;
}

/*
** Make sure all writes to a particular file are committed to disk.
**
** Under Unix, also make sure that the directory entry for the file
** has been created by fsync-ing the directory that contains the file.
** If we do not do this and we encounter a power failure, the directory
** entry for the journal might not exist after we reboot.  The next
** eDb to access the file will not know that the journal exists (because
** the directory entry for the journal was never created) and the transaction
** will not roll back - possibly leading to database corruption.
*/
int eDbOsSync(OsFile *id){
	if( FlushFileBuffers(id->h) ){
		return eDb_OK;
	}else{
		return eDb_IOERR;
	}
}

/*
** Truncate an open file to a specified size
*/
int eDbOsTruncate(OsFile *id, off_t nByte){
	//SimulateIOError(eDb_IOERR);
	LONG upperBits = (LONG)(nByte>>32);
	SetFilePointer(id->h, (LONG)nByte, &upperBits, FILE_BEGIN);
	SetEndOfFile(id->h);
	return eDb_OK;
}

/*
** Determine the current size of a file in bytes
*/
int eDbOsFileSize(OsFile *id, off_t *pSize){
	DWORD upperBits, lowerBits;
	SimulateIOError(eDb_IOERR);
	lowerBits = GetFileSize(id->h, &upperBits);
	*pSize = (((off_t)upperBits)<<32) + lowerBits;
	return eDb_OK;
}
/*
** Return true (non-zero) if we are running under WinNT, Win2K or WinXP.
** Return false (zero) for Win95, Win98, or WinME.
**
** Here is an interesting observation:  Win95, Win98, and WinME lack
** the LockFileEx() API.  But we can still statically link against that
** API as long as we don't call it win running Win95/98/ME.  A call to
** this routine is used to determine if the host is Win95/98/ME or
** WinNT/2K/XP so that we will know whether or not we can safely call
** the LockFileEx() API.
*/
int isNT(void){
	static int osType = 0;   /* 0=unknown 1=win95 2=winNT */
	if( osType==0 ){
		OSVERSIONINFO sInfo;
		sInfo.dwOSVersionInfoSize = sizeof(sInfo);
		GetVersionEx(&sInfo);
		osType = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;
	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -