📄 open.c
字号:
/***
*open.c - file open
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
* defines _open() and _sopen() - open or create a file
*
*******************************************************************************/
#include <sect_attribs.h>
#include <cruntime.h>
#include <oscalls.h>
#include <msdos.h>
#include <errno.h>
#include <fcntl.h>
#include <internal.h>
#include <io.h>
#include <share.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys\types.h>
#include <sys\stat.h>
#include <mtdll.h>
#include <stdarg.h>
#include <tchar.h>
#define UTF16LE_BOM 0xFEFF /* UTF16 Little Endian Byte Order Mark */
#define UTF16BE_BOM 0xFFFE /* UTF16 Big Endian Byte Order Mark */
#define BOM_MASK 0xFFFF /* Mask for testing Byte Order Mark */
#define UTF8_BOM 0xBFBBEF /* UTF8 Byte Order Mark */
#define UTF16_BOMLEN 2 /* No of Bytes in a UTF16 BOM */
#define UTF8_BOMLEN 3 /* No of Bytes in a UTF8 BOM */
static errno_t __cdecl _tsopen_nolock ( int *,
int *,
const _TSCHAR *,
int,
int,
int,
int );
/***
*int _open(path, flag, pmode) - open or create a file
*
*Purpose:
* Opens the file and prepares for subsequent reading or writing.
* the flag argument specifies how to open the file:
* _O_APPEND - reposition file ptr to end before every write
* _O_BINARY - open in binary mode
* _O_CREAT - create a new file* no effect if file already exists
* _O_EXCL - return error if file exists, only use with O_CREAT
* _O_RDONLY - open for reading only
* _O_RDWR - open for reading and writing
* _O_TEXT - open in text mode
* _O_TRUNC - open and truncate to 0 length (must have write permission)
* _O_WRONLY - open for writing only
* _O_NOINHERIT -handle will not be inherited by child processes.
* exactly one of _O_RDONLY, _O_WRONLY, _O_RDWR must be given
*
* The pmode argument is only required when _O_CREAT is specified. Its
* flag settings:
* _S_IWRITE - writing permitted
* _S_IREAD - reading permitted
* _S_IREAD | _S_IWRITE - both reading and writing permitted
* The current file-permission maks is applied to pmode before
* setting the permission (see umask).
*
* The oflag and mode parameter have different meanings under DOS. See
* the A_xxx attributes in msdos.inc
*
* The file mode is opened in _SH_DENYNO share mode
*
* Note, the _creat() function also uses this function but setting up the
* correct arguments and calling _open(). _creat() sets the __creat_flag
* to 1 prior to calling _open() so _open() can return correctly. _open()
* returns the file handle in eax in this case.
*
*Entry:
* _TSCHAR *path - file name
* int flag - flags for _open()
* int pmode - permission mode for new files
*
*Exit:
* returns file handle of open file if successful
* returns -1 (and sets errno) if fails
*
*Exceptions:
*
*******************************************************************************/
int __cdecl _topen (
const _TSCHAR *path,
int oflag,
...
)
{
va_list ap;
int pmode = 0;
int fh = -1;
errno_t retval;
int unlock_flag = 0;
_VALIDATE_RETURN( (path != NULL), EINVAL, -1);
va_start(ap, oflag);
pmode = va_arg(ap, int);
va_end(ap);
__try {
/* Last parameter passed as 0 because we don't want to
validate pmode from open */
retval = _tsopen_nolock( &unlock_flag,
&fh,
path,
oflag,
_SH_DENYNO,
pmode,
0 );
}
__finally {
if ( unlock_flag )
{
if (retval)
{
_osfile(fh) &= ~FOPEN;
}
_unlock_fh(fh);
}
}
if (retval)
{
errno = retval;
return -1;
}
return fh;
}
errno_t __cdecl _tsopen_helper (
const _TSCHAR *path,
int oflag,
int shflag,
int pmode,
int * pfh,
int bSecure
)
{
errno_t retval;
int unlock_flag = 0;
_VALIDATE_RETURN_ERRCODE( (pfh != NULL), EINVAL);
*pfh = -1;
_VALIDATE_RETURN_ERRCODE( (path != NULL), EINVAL);
if(bSecure)
_VALIDATE_RETURN_ERRCODE(((pmode & (~(_S_IREAD | _S_IWRITE))) == 0), EINVAL);
__try {
retval = _tsopen_nolock( &unlock_flag,
pfh,
path,
oflag,
shflag,
pmode,
bSecure );
}
__finally {
if ( unlock_flag )
{
if (retval)
{
_osfile(*pfh) &= ~FOPEN;
}
_unlock_fh(*pfh);
}
}
/* in error case, ensure *pfh is -1 */
if (retval != 0)
{
*pfh = -1;
}
return retval;
}
static errno_t __cdecl _tsopen_nolock (
int *punlock_flag,
int *pfh,
const _TSCHAR *path,
int oflag,
int shflag,
int pmode,
int bSecure
)
{
int filepos; /* length of file - 1 */
_TSCHAR ch; /* character at end of file */
char fileflags; /* _osfile flags */
int fmode = 0;
HANDLE osfh; /* OS handle of opened file */
DWORD fileaccess; /* OS file access (requested) */
DWORD fileshare; /* OS file sharing mode */
DWORD filecreate; /* OS method of opening/creating */
DWORD fileattrib; /* OS file attribute flags */
DWORD isdev; /* device indicator in low byte */
SECURITY_ATTRIBUTES SecurityAttributes;
char tmode = __IOINFO_TM_ANSI; /* textmode - ANSI/UTF-8/UTF-16 */
errno_t retvalue = 0;
SecurityAttributes.nLength = sizeof( SecurityAttributes );
SecurityAttributes.lpSecurityDescriptor = NULL;
if (oflag & _O_NOINHERIT) {
SecurityAttributes.bInheritHandle = FALSE;
fileflags = FNOINHERIT;
}
else {
SecurityAttributes.bInheritHandle = TRUE;
fileflags = 0;
}
_ERRCHECK(_get_fmode(&fmode));
/* figure out binary/text mode */
if ((oflag & _O_BINARY) == 0)
if (oflag & (_O_TEXT | _O_WTEXT | _O_U16TEXT | _O_U8TEXT))
fileflags |= FTEXT;
else if (fmode != _O_BINARY) /* check default mode */
fileflags |= FTEXT;
/*
* decode the access flags
*/
switch( oflag & (_O_RDONLY | _O_WRONLY | _O_RDWR) ) {
case _O_RDONLY: /* read access */
fileaccess = GENERIC_READ;
break;
case _O_WRONLY: /* write access */
/* giving it read access as well
* because in append (a, not a+), we need
* to read the BOM to determine the encoding
* (ie. ANSI, UTF8, UTF16)
*/
if ((oflag & _O_APPEND)
&& (oflag & (_O_WTEXT | _O_U16TEXT | _O_U8TEXT)) != 0)
{
fileaccess = GENERIC_READ | GENERIC_WRITE;
}
else
{
fileaccess = GENERIC_WRITE;
}
break;
case _O_RDWR: /* read and write access */
fileaccess = GENERIC_READ | GENERIC_WRITE;
break;
default: /* error, bad oflag */
_doserrno = 0L; /* not an OS error */
*pfh = -1;
_VALIDATE_RETURN_ERRCODE(( "Invalid open flag" , 0 ), EINVAL);
}
/*
* decode sharing flags
*/
switch ( shflag ) {
case _SH_DENYRW: /* exclusive access */
fileshare = 0L;
break;
case _SH_DENYWR: /* share read access */
fileshare = FILE_SHARE_READ;
break;
case _SH_DENYRD: /* share write access */
fileshare = FILE_SHARE_WRITE;
break;
case _SH_DENYNO: /* share read and write access */
fileshare = FILE_SHARE_READ | FILE_SHARE_WRITE;
break;
case _SH_SECURE: /* share read access only if read-only */
if (fileaccess == GENERIC_READ)
fileshare = FILE_SHARE_READ;
else
fileshare = 0L;
break;
default: /* error, bad shflag */
_doserrno = 0L; /* not an OS error */
*pfh = -1;
_VALIDATE_RETURN_ERRCODE(( "Invalid sharing flag" , 0 ), EINVAL);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -