📄 open.c
字号:
/*
* decode open/create method flags
*/
switch ( oflag & (_O_CREAT | _O_EXCL | _O_TRUNC) ) {
case 0:
case _O_EXCL: // ignore EXCL w/o CREAT
filecreate = OPEN_EXISTING;
break;
case _O_CREAT:
filecreate = OPEN_ALWAYS;
break;
case _O_CREAT | _O_EXCL:
case _O_CREAT | _O_TRUNC | _O_EXCL:
filecreate = CREATE_NEW;
break;
case _O_TRUNC:
case _O_TRUNC | _O_EXCL: // ignore EXCL w/o CREAT
filecreate = TRUNCATE_EXISTING;
break;
case _O_CREAT | _O_TRUNC:
filecreate = CREATE_ALWAYS;
break;
default:
// this can't happen ... all cases are covered
_doserrno = 0L;
*pfh = -1;
_VALIDATE_RETURN_ERRCODE(( "Invalid open flag" , 0 ), EINVAL);
}
/*
* decode file attribute flags if _O_CREAT was specified
*/
fileattrib = FILE_ATTRIBUTE_NORMAL; /* default */
if ( oflag & _O_CREAT ) {
if ( !((pmode & ~_umaskval) & _S_IWRITE) )
fileattrib = FILE_ATTRIBUTE_READONLY;
}
/*
* Set temporary file (delete-on-close) attribute if requested.
*/
if ( oflag & _O_TEMPORARY ) {
fileattrib |= FILE_FLAG_DELETE_ON_CLOSE;
fileaccess |= DELETE;
fileshare |= FILE_SHARE_DELETE;
}
/*
* Set temporary file (delay-flush-to-disk) attribute if requested.
*/
if ( oflag & _O_SHORT_LIVED )
fileattrib |= FILE_ATTRIBUTE_TEMPORARY;
/*
* Set sequential or random access attribute if requested.
*/
if ( oflag & _O_SEQUENTIAL )
fileattrib |= FILE_FLAG_SEQUENTIAL_SCAN;
else if ( oflag & _O_RANDOM )
fileattrib |= FILE_FLAG_RANDOM_ACCESS;
/*
* get an available handle.
*
* multi-thread note: the returned handle is locked!
*/
if ( (*pfh = _alloc_osfhnd()) == -1 ) {
_doserrno = 0L; /* not an OS error */
*pfh = -1;
errno = EMFILE;
return errno; /* return error to caller */
}
/* Beyond this do not set *pfh = -1 on errors for MT.
Because the caller needs to release the lock on the
handle */
*punlock_flag = 1;
/*
* try to open/create the file
*/
if ( (osfh = CreateFile( (LPTSTR)path,
fileaccess,
fileshare,
&SecurityAttributes,
filecreate,
fileattrib,
NULL ))
== (HANDLE)(-1) )
{
if ((fileaccess & (GENERIC_READ | GENERIC_WRITE)) == (GENERIC_READ | GENERIC_WRITE) &&
(oflag & _O_WRONLY))
{
/*
* We just failed on CreateFile(), because we might be trying
* open something for read while it cannot be read (eg. pipes or devices).
* So try again with GENERIC_WRITE and we will have to use the default
* encoding. We won't be able to determine the encoding from reading
* the BOM.
*/
fileaccess &= ~GENERIC_READ;
if ( (osfh = CreateFile( (LPTSTR)path,
fileaccess,
fileshare,
&SecurityAttributes,
filecreate,
fileattrib,
NULL ))
== (HANDLE)(-1) )
{
/*
* OS call to open/create file failed! map the error, release
* the lock, and return -1. note that it's not necessary to
* call _free_osfhnd (it hasn't been used yet), but we do need
* to clear the FOPEN that was set by _alloc_osfhnd.
*/
_osfile(*pfh) &= ~FOPEN;
_dosmaperr(GetLastError());
retvalue = errno;
goto exit;
}
}
else
{
/*
* OS call to open/create file failed! map the error, release
* the lock, and return -1. note that it's not necessary to
* call _free_osfhnd (it hasn't been used yet), but we do need
* to clear the FOPEN that was set by _alloc_osfhnd.
*/
_osfile(*pfh) &= ~FOPEN;
_dosmaperr(GetLastError());
retvalue = errno;
goto exit;
}
}
/* find out what type of file (file/device/pipe) */
if ( (isdev = GetFileType(osfh)) == FILE_TYPE_UNKNOWN) {
DWORD dwLastError = 0;
_osfile(*pfh) &= ~FOPEN;
dwLastError = GetLastError();
_dosmaperr(dwLastError);
CloseHandle(osfh);
if (dwLastError == ERROR_SUCCESS)
{
/*
* If GetFileType returns FILE_TYPE_UNKNOWN but doesn't fail,
* GetLastError returns ERROR_SUCCESS.
* This function is not designed to deal with unknown types of files
* and must return an error.
*/
errno = EACCES;
}
retvalue = errno;
goto exit;
}
/* use isdev value to set flags */
if (isdev == FILE_TYPE_CHAR)
fileflags |= FDEV;
else if (isdev == FILE_TYPE_PIPE) {
fileflags |= FPIPE;
}
/*
* the file is open. now, set the info in _osfhnd array
*/
_set_osfhnd(*pfh, (intptr_t)osfh);
/*
* mark the handle as open. store flags gathered so far in _osfile
* array.
*/
fileflags |= FOPEN;
_osfile(*pfh) = fileflags;
/* TextMode set to ANSI by default, if we find a BOM, then
we reset it to the appropriate type below */
_textmode(*pfh) = __IOINFO_TM_ANSI;
if ( !(fileflags & (FDEV|FPIPE)) && (fileflags & FTEXT) &&
(oflag & _O_RDWR) )
{
/* We have a text mode file. If it ends in CTRL-Z, we wish to
remove the CTRL-Z character, so that appending will work.
We do this by seeking to the end of file, reading the last
byte, and shortening the file if it is a CTRL-Z. */
if ((filepos = _lseek_nolock(*pfh, -1, SEEK_END)) == -1) {
/* OS error -- should ignore negative seek error,
since that means we had a zero-length file. */
if (_doserrno != ERROR_NEGATIVE_SEEK) {
_close_nolock(*pfh);
retvalue = errno;
goto exit;
}
}
else {
/* Seek was OK, read the last char in file. The last
char is a CTRL-Z if and only if _read returns 0
and ch ends up with a CTRL-Z. */
ch = 0;
if (_read_nolock(*pfh, &ch, 1) == 0 && ch == 26) {
/* read was OK and we got CTRL-Z! Wipe it
out! */
if (_chsize_nolock(*pfh,filepos) == -1)
{
_close_nolock(*pfh);
retvalue = errno;
goto exit;
}
}
/* now rewind the file to the beginning */
if ((filepos = _lseek_nolock(*pfh, 0, SEEK_SET)) == -1) {
_close_nolock(*pfh);
retvalue = errno;
goto exit;
}
}
}
if ( fileflags & FTEXT) {
int count;
/* Set default tmode per oflag. BOM will change the defualt. */
/* If oflag does not specify file type get type from _fmode */
if ( (oflag & (_O_TEXT | _O_WTEXT | _O_U16TEXT | _O_U8TEXT) ) == 0 )
{
/* Type specified in default mode? */
if ( (fmode & (_O_TEXT | _O_WTEXT | _O_U16TEXT | _O_U8TEXT) ) == 0)
oflag |= _O_TEXT; /* default to ANSI */
else
oflag |= fmode & (_O_TEXT | _O_WTEXT | _O_U16TEXT | _O_U8TEXT);
}
/* Now oflags should be set to one of the text modes */
_ASSERTE( (oflag & (_O_TEXT | _O_WTEXT | _O_U16TEXT | _O_U8TEXT) ) != 0 );
switch ( oflag & (_O_TEXT | _O_WTEXT | _O_U16TEXT | _O_U8TEXT) )
{
case _O_TEXT :
tmode = __IOINFO_TM_ANSI;
break;
case _O_WTEXT :
case _O_WTEXT | _O_TEXT :
if ( (oflag & (_O_WRONLY | _O_CREAT | _O_TRUNC)) ==
(_O_WRONLY | _O_CREAT | _O_TRUNC) )
tmode = __IOINFO_TM_UTF16LE;
break;
case _O_U16TEXT :
case _O_U16TEXT | _O_TEXT :
tmode = __IOINFO_TM_UTF16LE;
break;
case _O_U8TEXT :
case _O_U8TEXT | _O_TEXT :
tmode = __IOINFO_TM_UTF8;
break;
}
/* If the file hasn't been opened with the UNICODE flags then we
have nothing to do - textmode's already set to default specified in oflag */
if((oflag & (_O_WTEXT | _O_U16TEXT | _O_U8TEXT)) != 0) {
int bom = 0;
int bWriteBom = 0;
int bCheckBom = 0;
if ( !(fileflags & FDEV) ) {
switch ( fileaccess & (GENERIC_READ | GENERIC_WRITE) ) {
case GENERIC_READ :
{
bCheckBom = 1;
break;
}
case GENERIC_WRITE :
{
switch ( filecreate ) {
/* Write BOM if empty file */
case OPEN_EXISTING :
case OPEN_ALWAYS :
{
/* Check if the file contains at least one byte */
/* Fall through otherwise */
if( _lseeki64_nolock(*pfh, 0, SEEK_END) != 0) {
if(_lseeki64_nolock(*pfh, 0, SEEK_SET) == -1) {
_close_nolock(*pfh);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -