📄 w95io.c
字号:
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- *//* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is the Netscape Portable Runtime (NSPR). * * The Initial Developer of the Original Code is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998-2000 Netscape Communications Corporation. All * Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL"), in which case the provisions of the GPL are applicable * instead of those above. If you wish to allow use of your * version of this file only under the terms of the GPL and not to * allow others to use your version of this file under the MPL, * indicate your decision by deleting the provisions above and * replace them with the notice and other provisions required by * the GPL. If you do not delete the provisions above, a recipient * may use your version of this file under either the MPL or the * GPL. *//* Windows 95 IO module * * Assumes synchronous I/O. * */#include "primpl.h"#include <direct.h>#include <mbstring.h>struct _MDLock _pr_ioq_lock;/* * NSPR-to-NT access right mapping table for files. */static DWORD fileAccessTable[] = { FILE_GENERIC_READ, FILE_GENERIC_WRITE, FILE_GENERIC_EXECUTE};/* * NSPR-to-NT access right mapping table for directories. */static DWORD dirAccessTable[] = { FILE_GENERIC_READ, FILE_GENERIC_WRITE|FILE_DELETE_CHILD, FILE_GENERIC_EXECUTE};/* * The NSPR epoch (00:00:00 1 Jan 1970 UTC) in FILETIME. * We store the value in a PRTime variable for convenience. * This constant is used by _PR_FileTimeToPRTime(). */#if defined(__MINGW32__)static const PRTime _pr_filetime_offset = 116444736000000000LL;#elsestatic const PRTime _pr_filetime_offset = 116444736000000000i64;#endifvoid_PR_MD_INIT_IO(){ WORD WSAVersion = 0x0101; WSADATA WSAData; int err; err = WSAStartup( WSAVersion, &WSAData ); PR_ASSERT(0 == err);#ifdef DEBUG /* Doublecheck _pr_filetime_offset's hard-coded value is correct. */ { SYSTEMTIME systime; union { PRTime prt; FILETIME ft; } filetime; BOOL rv; systime.wYear = 1970; systime.wMonth = 1; /* wDayOfWeek is ignored */ systime.wDay = 1; systime.wHour = 0; systime.wMinute = 0; systime.wSecond = 0; systime.wMilliseconds = 0; rv = SystemTimeToFileTime(&systime, &filetime.ft); PR_ASSERT(0 != rv); PR_ASSERT(filetime.prt == _pr_filetime_offset); }#endif /* DEBUG */ _PR_NT_InitSids();}PRStatus_PR_MD_WAIT(PRThread *thread, PRIntervalTime ticks){ DWORD rv; PRUint32 msecs = (ticks == PR_INTERVAL_NO_TIMEOUT) ? INFINITE : PR_IntervalToMilliseconds(ticks); rv = WaitForSingleObject(thread->md.blocked_sema, msecs); switch(rv) { case WAIT_OBJECT_0: return PR_SUCCESS; break; case WAIT_TIMEOUT: _PR_THREAD_LOCK(thread); if (thread->state == _PR_IO_WAIT) { ; } else { if (thread->wait.cvar != NULL) { thread->wait.cvar = NULL; _PR_THREAD_UNLOCK(thread); } else { /* The CVAR was notified just as the timeout * occurred. This led to us being notified twice. * call WaitForSingleObject() to clear the semaphore. */ _PR_THREAD_UNLOCK(thread); rv = WaitForSingleObject(thread->md.blocked_sema, 0); PR_ASSERT(rv == WAIT_OBJECT_0); } } return PR_SUCCESS; break; default: return PR_FAILURE; break; }}PRStatus_PR_MD_WAKEUP_WAITER(PRThread *thread){ if ( _PR_IS_NATIVE_THREAD(thread) ) { if (ReleaseSemaphore(thread->md.blocked_sema, 1, NULL) == FALSE) return PR_FAILURE; else return PR_SUCCESS; }}/* --- FILE IO ----------------------------------------------------------- *//* * _PR_MD_OPEN() -- Open a file * * returns: a fileHandle * * The NSPR open flags (osflags) are translated into flags for Win95 * * Mode seems to be passed in as a unix style file permissions argument * as in 0666, in the case of opening the logFile. * */PRInt32_PR_MD_OPEN(const char *name, PRIntn osflags, int mode){ HANDLE file; PRInt32 access = 0; PRInt32 flags = 0; PRInt32 flag6 = 0; if (osflags & PR_SYNC) flag6 = FILE_FLAG_WRITE_THROUGH; if (osflags & PR_RDONLY || osflags & PR_RDWR) access |= GENERIC_READ; if (osflags & PR_WRONLY || osflags & PR_RDWR) access |= GENERIC_WRITE; if ( osflags & PR_CREATE_FILE && osflags & PR_EXCL ) flags = CREATE_NEW; else if (osflags & PR_CREATE_FILE) { if (osflags & PR_TRUNCATE) flags = CREATE_ALWAYS; else flags = OPEN_ALWAYS; } else { if (osflags & PR_TRUNCATE) flags = TRUNCATE_EXISTING; else flags = OPEN_EXISTING; } file = CreateFile(name, access, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, flags, flag6, NULL); if (file == INVALID_HANDLE_VALUE) { _PR_MD_MAP_OPEN_ERROR(GetLastError()); return -1; } return (PRInt32)file;}PRInt32_PR_MD_OPEN_FILE(const char *name, PRIntn osflags, int mode){ HANDLE file; PRInt32 access = 0; PRInt32 flags = 0; PRInt32 flag6 = 0; SECURITY_ATTRIBUTES sa; LPSECURITY_ATTRIBUTES lpSA = NULL; PSECURITY_DESCRIPTOR pSD = NULL; PACL pACL = NULL; if (osflags & PR_CREATE_FILE) { if (_PR_NT_MakeSecurityDescriptorACL(mode, fileAccessTable, &pSD, &pACL) == PR_SUCCESS) { sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = pSD; sa.bInheritHandle = FALSE; lpSA = &sa; } } if (osflags & PR_SYNC) flag6 = FILE_FLAG_WRITE_THROUGH; if (osflags & PR_RDONLY || osflags & PR_RDWR) access |= GENERIC_READ; if (osflags & PR_WRONLY || osflags & PR_RDWR) access |= GENERIC_WRITE; if ( osflags & PR_CREATE_FILE && osflags & PR_EXCL ) flags = CREATE_NEW; else if (osflags & PR_CREATE_FILE) { if (osflags & PR_TRUNCATE) flags = CREATE_ALWAYS; else flags = OPEN_ALWAYS; } else { if (osflags & PR_TRUNCATE) flags = TRUNCATE_EXISTING; else flags = OPEN_EXISTING; } file = CreateFile(name, access, FILE_SHARE_READ|FILE_SHARE_WRITE, lpSA, flags, flag6, NULL); if (lpSA != NULL) { _PR_NT_FreeSecurityDescriptorACL(pSD, pACL); } if (file == INVALID_HANDLE_VALUE) { _PR_MD_MAP_OPEN_ERROR(GetLastError()); return -1; } return (PRInt32)file;}PRInt32_PR_MD_READ(PRFileDesc *fd, void *buf, PRInt32 len){ PRUint32 bytes; int rv, err; rv = ReadFile((HANDLE)fd->secret->md.osfd, (LPVOID)buf, len, &bytes, NULL); if (rv == 0) { err = GetLastError(); /* ERROR_HANDLE_EOF can only be returned by async io */ PR_ASSERT(err != ERROR_HANDLE_EOF); if (err == ERROR_BROKEN_PIPE) return 0; else { _PR_MD_MAP_READ_ERROR(err); return -1; } } return bytes;}PRInt32_PR_MD_WRITE(PRFileDesc *fd, const void *buf, PRInt32 len){ PRInt32 f = fd->secret->md.osfd; PRInt32 bytes; int rv; PRThread *me = _PR_MD_CURRENT_THREAD(); rv = WriteFile((HANDLE)f, buf, len, &bytes, NULL ); if (rv == 0) { _PR_MD_MAP_WRITE_ERROR(GetLastError()); return -1; } return bytes;} /* --- end _PR_MD_WRITE() --- */PROffset32_PR_MD_LSEEK(PRFileDesc *fd, PROffset32 offset, PRSeekWhence whence){ DWORD moveMethod; PROffset32 rv; switch (whence) { case PR_SEEK_SET: moveMethod = FILE_BEGIN; break; case PR_SEEK_CUR: moveMethod = FILE_CURRENT; break; case PR_SEEK_END: moveMethod = FILE_END; break; default: PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return -1; } rv = SetFilePointer((HANDLE)fd->secret->md.osfd, offset, NULL, moveMethod); /* * If the lpDistanceToMoveHigh argument (third argument) is * NULL, SetFilePointer returns 0xffffffff on failure. */ if (-1 == rv) { _PR_MD_MAP_LSEEK_ERROR(GetLastError()); } return rv;}PROffset64_PR_MD_LSEEK64(PRFileDesc *fd, PROffset64 offset, PRSeekWhence whence){ DWORD moveMethod; LARGE_INTEGER li; DWORD err; switch (whence) { case PR_SEEK_SET: moveMethod = FILE_BEGIN; break; case PR_SEEK_CUR: moveMethod = FILE_CURRENT; break; case PR_SEEK_END: moveMethod = FILE_END; break; default: PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return -1; } li.QuadPart = offset; li.LowPart = SetFilePointer((HANDLE)fd->secret->md.osfd, li.LowPart, &li.HighPart, moveMethod); if (0xffffffff == li.LowPart && (err = GetLastError()) != NO_ERROR) { _PR_MD_MAP_LSEEK_ERROR(err); li.QuadPart = -1; } return li.QuadPart;}/* * This is documented to succeed on read-only files, but Win32's * FlushFileBuffers functions fails with "access denied" in such a * case. So we only signal an error if the error is *not* "access * denied". */PRInt32_PR_MD_FSYNC(PRFileDesc *fd){ /* * From the documentation: * * On Windows NT, the function FlushFileBuffers fails if hFile * is a handle to console output. That is because console * output is not buffered. The function returns FALSE, and * GetLastError returns ERROR_INVALID_HANDLE. * * On the other hand, on Win95, it returns without error. I cannot * assume that 0, 1, and 2 are console, because if someone closes * System.out and then opens a file, they might get file descriptor * 1. An error on *that* version of 1 should be reported, whereas * an error on System.out (which was the original 1) should be * ignored. So I use isatty() to ensure that such an error was due * to this bogosity, and if it was, I ignore the error. */ BOOL ok = FlushFileBuffers((HANDLE)fd->secret->md.osfd); if (!ok) { DWORD err = GetLastError(); if (err != ERROR_ACCESS_DENIED) { // from winerror.h _PR_MD_MAP_FSYNC_ERROR(err); return -1; } } return 0;}PRInt32_MD_CloseFile(PRInt32 osfd){ PRInt32 rv; rv = (CloseHandle((HANDLE)osfd))?0:-1; if (rv == -1) _PR_MD_MAP_CLOSE_ERROR(GetLastError()); return rv;}/* --- DIR IO ------------------------------------------------------------ */#define GetFileFromDIR(d) (d)->d_entry.cFileName#define FileIsHidden(d) ((d)->d_entry.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)void FlipSlashes(char *cp, int len){ while (--len >= 0) { if (cp[0] == '/') { cp[0] = PR_DIRECTORY_SEPARATOR; } cp = _mbsinc(cp); }} /* end FlipSlashes() *//***** Local implementations of standard Unix RTL functions which are not provided** by the VC RTL.***/PRStatus_PR_MD_CLOSE_DIR(_MDDir *d){ if ( d ) { if (FindClose(d->d_hdl)) { d->magic = (PRUint32)-1; return PR_SUCCESS; } else { _PR_MD_MAP_CLOSEDIR_ERROR(GetLastError()); return PR_FAILURE; } } PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return PR_FAILURE;}PRStatus_PR_MD_OPEN_DIR(_MDDir *d, const char *name){ char filename[ MAX_PATH ]; int len; len = strlen(name); /* Need 5 bytes for \*.* and the trailing null byte. */ if (len + 5 > MAX_PATH) { PR_SetError(PR_NAME_TOO_LONG_ERROR, 0); return PR_FAILURE; } strcpy(filename, name); /* * If 'name' ends in a slash or backslash, do not append * another backslash. */ if (filename[len - 1] == '/' || filename[len - 1] == '\\') { len--; } strcpy(&filename[len], "\\*.*"); FlipSlashes( filename, strlen(filename) ); d->d_hdl = FindFirstFile( filename, &(d->d_entry) ); if ( d->d_hdl == INVALID_HANDLE_VALUE ) { _PR_MD_MAP_OPENDIR_ERROR(GetLastError()); return PR_FAILURE; } d->firstEntry = PR_TRUE; d->magic = _MD_MAGIC_DIR; return PR_SUCCESS;}char *_PR_MD_READ_DIR(_MDDir *d, PRIntn flags){ PRInt32 err; BOOL rv; char *fileName; if ( d ) { while (1) { if (d->firstEntry) { d->firstEntry = PR_FALSE; rv = 1; } else { rv = FindNextFile(d->d_hdl, &(d->d_entry)); } if (rv == 0) { break; } fileName = GetFileFromDIR(d); if ( (flags & PR_SKIP_DOT) && (fileName[0] == '.') && (fileName[1] == '\0')) continue; if ( (flags & PR_SKIP_DOT_DOT) && (fileName[0] == '.') && (fileName[1] == '.') && (fileName[2] == '\0')) continue;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -