mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-08 21:32:39 +00:00
Various improvements to MemoryBuffer::getFile:
- Use a RAII object to close the FD. - Use sys::StrError instead of thread-unsafe strerror calls. - Recover gracefully if read returns zero. This works around an issue on DragonFlyBSD where /dev/null has an st_size of 136 but we can't read 136 bytes from it. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@100106 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
0bf77de91f
commit
6a9cd41549
@ -14,6 +14,8 @@
|
|||||||
#include "llvm/Support/MemoryBuffer.h"
|
#include "llvm/Support/MemoryBuffer.h"
|
||||||
#include "llvm/ADT/OwningPtr.h"
|
#include "llvm/ADT/OwningPtr.h"
|
||||||
#include "llvm/ADT/SmallString.h"
|
#include "llvm/ADT/SmallString.h"
|
||||||
|
#include "llvm/ADT/StringExtras.h"
|
||||||
|
#include "llvm/System/Errno.h"
|
||||||
#include "llvm/System/Path.h"
|
#include "llvm/System/Path.h"
|
||||||
#include "llvm/System/Process.h"
|
#include "llvm/System/Process.h"
|
||||||
#include "llvm/System/Program.h"
|
#include "llvm/System/Program.h"
|
||||||
@ -167,6 +169,14 @@ public:
|
|||||||
sys::Path::UnMapFilePages(getBufferStart(), getBufferSize());
|
sys::Path::UnMapFilePages(getBufferStart(), getBufferSize());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// FileCloser - RAII object to make sure an FD gets closed properly.
|
||||||
|
class FileCloser {
|
||||||
|
int FD;
|
||||||
|
public:
|
||||||
|
FileCloser(int FD) : FD(FD) {}
|
||||||
|
~FileCloser() { ::close(FD); }
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryBuffer *MemoryBuffer::getFile(StringRef Filename, std::string *ErrStr,
|
MemoryBuffer *MemoryBuffer::getFile(StringRef Filename, std::string *ErrStr,
|
||||||
@ -178,9 +188,10 @@ MemoryBuffer *MemoryBuffer::getFile(StringRef Filename, std::string *ErrStr,
|
|||||||
SmallString<256> PathBuf(Filename.begin(), Filename.end());
|
SmallString<256> PathBuf(Filename.begin(), Filename.end());
|
||||||
int FD = ::open(PathBuf.c_str(), O_RDONLY|OpenFlags);
|
int FD = ::open(PathBuf.c_str(), O_RDONLY|OpenFlags);
|
||||||
if (FD == -1) {
|
if (FD == -1) {
|
||||||
if (ErrStr) *ErrStr = strerror(errno);
|
if (ErrStr) *ErrStr = sys::StrError();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
FileCloser FC(FD); // Close FD on return.
|
||||||
|
|
||||||
// If we don't know the file size, use fstat to find out. fstat on an open
|
// If we don't know the file size, use fstat to find out. fstat on an open
|
||||||
// file descriptor is cheaper than stat on a random path.
|
// file descriptor is cheaper than stat on a random path.
|
||||||
@ -190,8 +201,7 @@ MemoryBuffer *MemoryBuffer::getFile(StringRef Filename, std::string *ErrStr,
|
|||||||
|
|
||||||
// TODO: This should use fstat64 when available.
|
// TODO: This should use fstat64 when available.
|
||||||
if (fstat(FD, FileInfoPtr) == -1) {
|
if (fstat(FD, FileInfoPtr) == -1) {
|
||||||
if (ErrStr) *ErrStr = strerror(errno);
|
if (ErrStr) *ErrStr = sys::StrError();
|
||||||
::close(FD);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
FileSize = FileInfoPtr->st_size;
|
FileSize = FileInfoPtr->st_size;
|
||||||
@ -208,7 +218,6 @@ MemoryBuffer *MemoryBuffer::getFile(StringRef Filename, std::string *ErrStr,
|
|||||||
(FileSize & (sys::Process::GetPageSize()-1)) != 0) {
|
(FileSize & (sys::Process::GetPageSize()-1)) != 0) {
|
||||||
if (const char *Pages = sys::Path::MapInFilePages(FD, FileSize)) {
|
if (const char *Pages = sys::Path::MapInFilePages(FD, FileSize)) {
|
||||||
// Close the file descriptor, now that the whole file is in memory.
|
// Close the file descriptor, now that the whole file is in memory.
|
||||||
::close(FD);
|
|
||||||
return new MemoryBufferMMapFile(Filename, Pages, FileSize);
|
return new MemoryBufferMMapFile(Filename, Pages, FileSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -217,30 +226,30 @@ MemoryBuffer *MemoryBuffer::getFile(StringRef Filename, std::string *ErrStr,
|
|||||||
if (!Buf) {
|
if (!Buf) {
|
||||||
// Failed to create a buffer.
|
// Failed to create a buffer.
|
||||||
if (ErrStr) *ErrStr = "could not allocate buffer";
|
if (ErrStr) *ErrStr = "could not allocate buffer";
|
||||||
::close(FD);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
OwningPtr<MemoryBuffer> SB(Buf);
|
OwningPtr<MemoryBuffer> SB(Buf);
|
||||||
char *BufPtr = const_cast<char*>(SB->getBufferStart());
|
char *BufPtr = const_cast<char*>(SB->getBufferStart());
|
||||||
|
|
||||||
size_t BytesLeft = FileSize;
|
size_t BytesLeft = FileSize;
|
||||||
while (BytesLeft) {
|
while (BytesLeft) {
|
||||||
ssize_t NumRead = ::read(FD, BufPtr, BytesLeft);
|
ssize_t NumRead = ::read(FD, BufPtr, BytesLeft);
|
||||||
if (NumRead > 0) {
|
if (NumRead == -1) {
|
||||||
BytesLeft -= NumRead;
|
if (errno == EINTR)
|
||||||
BufPtr += NumRead;
|
continue;
|
||||||
} else if (NumRead == -1 && errno == EINTR) {
|
// Error while reading.
|
||||||
// try again
|
if (ErrStr) *ErrStr = sys::StrError();
|
||||||
} else {
|
|
||||||
// error reading.
|
|
||||||
if (ErrStr) *ErrStr = strerror(errno);
|
|
||||||
close(FD);
|
|
||||||
return 0;
|
return 0;
|
||||||
|
} else if (NumRead == 0) {
|
||||||
|
Buf->BufferEnd = BufPtr;
|
||||||
|
*BufPtr = 0; // Null terminate buffer.
|
||||||
|
return SB.take();
|
||||||
}
|
}
|
||||||
|
BytesLeft -= NumRead;
|
||||||
|
BufPtr += NumRead;
|
||||||
}
|
}
|
||||||
close(FD);
|
|
||||||
|
|
||||||
return SB.take();
|
return SB.take();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user