|
|
|
@ -74,7 +74,7 @@
|
|
|
|
|
#include <windows.h>
|
|
|
|
|
#define SYSERROR() GetLastError()
|
|
|
|
|
#else
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
#include <cerrno>
|
|
|
|
|
#define SYSERROR() errno
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
@ -180,6 +180,8 @@ FB_UDR_END_FUNCTION
|
|
|
|
|
* external name 'MyFirstUDRKit!MFKLoadBlobFromFile!Load file and save to Blob'
|
|
|
|
|
* engine udr;
|
|
|
|
|
***/
|
|
|
|
|
// NOTE This function would be better as a procedure as that would allow it
|
|
|
|
|
// to return the bytes written to the blob.
|
|
|
|
|
FB_UDR_BEGIN_FUNCTION (MFK_LoadBlobFromFile)
|
|
|
|
|
//BEGIN
|
|
|
|
|
FB_UDR_MESSAGE(InMessage,
|
|
|
|
@ -205,8 +207,9 @@ FB_UDR_EXECUTE_FUNCTION
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::ifstream FileReader;
|
|
|
|
|
FileReader.open( in->afilename.str , std::ifstream::binary );
|
|
|
|
|
FileReader.open( in->afilename.str , std::ifstream::binary | std::ifstream::in );
|
|
|
|
|
if (! FileReader.is_open()) {
|
|
|
|
|
// if (! FileReader.good()) {
|
|
|
|
|
out->ablobNull = FB_TRUE;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
@ -238,7 +241,7 @@ FB_UDR_EXECUTE_FUNCTION
|
|
|
|
|
// What do we do with the partially written blob? Is cancel enough?
|
|
|
|
|
blob->cancel( status );
|
|
|
|
|
}
|
|
|
|
|
// ****** IT IS VITAL TO SET THIS IF WRITING TO BLOB SUCCEEDED ********
|
|
|
|
|
// ****** IT IS VITAL TO SET THIS IF WRITING TO BLOB WAS SUCCESSFUL ******* //
|
|
|
|
|
out->ablobNull = FB_FALSE;
|
|
|
|
|
|
|
|
|
|
blob->close( status );
|
|
|
|
@ -298,21 +301,32 @@ FB_UDR_EXECUTE_FUNCTION
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* DOC NOTE - We do not test for existence of the file here!
|
|
|
|
|
* This should be done prior to calling this function.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
std::ofstream FileWriter ( in->afilename.str , std::ofstream::binary );
|
|
|
|
|
std::ofstream FileWriter ( in->afilename.str , std::ofstream::binary | std::ofstream::out );
|
|
|
|
|
if (! FileWriter.is_open()) {
|
|
|
|
|
// if (! FileWriter.good()) {
|
|
|
|
|
out->resultNull = FB_TRUE;
|
|
|
|
|
|
|
|
|
|
// Convert system error to a negative value and assign to result
|
|
|
|
|
out->result = ( SYSERROR() * -1 );
|
|
|
|
|
// important to set this to false here otherwise the error code will
|
|
|
|
|
// be hidden and NULL returned to the firebird engine. This is because
|
|
|
|
|
// the test for out->resultNull has precedence.
|
|
|
|
|
|
|
|
|
|
// important to set out->resultNull to false here otherwise the error
|
|
|
|
|
// code willbe hidden and NULL returned to the firebird engine. This
|
|
|
|
|
// is because the test for out->resultNull has precedence.
|
|
|
|
|
if ( out->result < 0 ) {
|
|
|
|
|
out->resultNull = FB_FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// This might be useful but doesn't work because it requires libc++ and we compile with libstdc++ on linux
|
|
|
|
|
// else {
|
|
|
|
|
// std::filesystem::permissions ( in->afilename.str, std::filesystem::perms::owner_all | std::filesystem::perms::group_all,
|
|
|
|
|
// std::filesystem::perm_options::add );
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
att.reset(context->getAttachment(status));
|
|
|
|
@ -328,6 +342,7 @@ FB_UDR_EXECUTE_FUNCTION
|
|
|
|
|
|
|
|
|
|
std::vector<std::uint8_t> Buffer (MaxSegmentSize, 0);
|
|
|
|
|
unsigned BytesRead = 0;
|
|
|
|
|
unsigned BufferSize = 0;
|
|
|
|
|
|
|
|
|
|
for (bool Eof = false; !Eof; )
|
|
|
|
|
{
|
|
|
|
@ -336,6 +351,13 @@ FB_UDR_EXECUTE_FUNCTION
|
|
|
|
|
case IStatus::RESULT_OK:
|
|
|
|
|
case IStatus::RESULT_SEGMENT:
|
|
|
|
|
{
|
|
|
|
|
BufferSize = Buffer.size();
|
|
|
|
|
if ( BufferSize < BytesRead) {
|
|
|
|
|
BytesRead = BufferSize;
|
|
|
|
|
}
|
|
|
|
|
if ( BytesRead < MaxSegmentSize) {
|
|
|
|
|
Buffer.resize( BytesRead);
|
|
|
|
|
}
|
|
|
|
|
FileWriter.write( (char *) Buffer.data(), Buffer.size() );
|
|
|
|
|
out->result += BytesRead;
|
|
|
|
|
continue;
|
|
|
|
|