- VBOX: Use sscanf instead of strtol to convert a hex string.

- VBOX: Use new FloppyIO implementation that reports image
        creation errors.


    samples/vboxwrapper/
        floppyio.cpp, .h
        vbox.cpp

svn path=/trunk/boinc/; revision=25003
This commit is contained in:
Rom Walton 2012-01-06 18:44:34 +00:00
parent f208d2dba4
commit 9faee707fa
4 changed files with 574 additions and 278 deletions

View File

@ -234,3 +234,13 @@ Rom 6 Jan 2012
ViewStatistics.cpp ViewStatistics.cpp
lib/ lib/
gui_rpc_client_ops.cpp gui_rpc_client_ops.cpp
Rom 6 Jan 2012
- VBOX: Use sscanf instead of strtol to convert a hex string.
- VBOX: Use new FloppyIO implementation that reports image
creation errors.
samples/vboxwrapper/
floppyio.cpp, .h
vbox.cpp

View File

@ -1,201 +1,372 @@
// File: FloppyIO.cpp // This file is part Floppy I/O, a Virtual Machine - Hypervisor intercommunication system.
// Author: Ioannis Charalampidis <ioannis.charalampidis AT cern DOT ch> // Copyright (C) 2011 Ioannis Charalampidis
// //
// Hypervisor-Virtual machine bi-directional communication // This program is free software: you can redistribute it and/or modify
// through floppy disk. // it under the terms of the GNU Lesser General Public License as published by
// // the Free Software Foundation, either version 3 of the License, or
// This class provides the hypervisor-side of the script. // (at your option) any later version.
// For the guest-side, check the perl scripts that //
// were available with this code. // This program is distributed in the hope that it will be useful,
// // but WITHOUT ANY WARRANTY; without even the implied warranty of
// Here is the layout of the floppy disk image (Example of 28k): // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// // GNU Lesser General Public License for more details.
// +-----------------+------------------------------------------------+ //
// | 0x0000 - 0x37FF | Hypervisor -> Guest Buffer | // You should have received a copy of the GNU Lesser General Public License
// | 0x3800 - 0x6FFE | Guest -> Hypervisor Buffer | // along with this program. If not, see <http://www.gnu.org/licenses/>.
// | 0x6FFF | "Data available for guest" flag byte |
// | 0x7000 | "Data available for hypervisor" flag byte | // File: FloppyIO.cpp
// +-----------------+------------------------------------------------+ // Author: Ioannis Charalampidis <ioannis.charalampidis AT cern DOT ch>
// // License: GNU Lesser General Public License - Version 3.0
// Created on November 24, 2011, 12:30 PM //
// Hypervisor-Virtual machine bi-directional communication
// through floppy disk.
//
// This class provides the hypervisor-side of the script.
// For the guest-side, check the perl scripts that
// were available with this code.
//
// Here is the layout of the floppy disk image (Example of 28k):
//
// +-----------------+------------------------------------------------+
// | 0x0000 - 0x37FF | Hypervisor -> Guest Buffer |
// | 0x3800 - 0x6FFE | Guest -> Hypervisor Buffer |
// | 0x6FFF | "Data available for guest" flag byte |
// | 0x7000 | "Data available for hypervisor" flag byte |
// +-----------------+------------------------------------------------+
//
// Updated at January 5, 2012, 13:06 PM
#ifdef _WIN32 #ifdef _WIN32
#include "boinc_win.h" #include "boinc_win.h"
#else #else
#include <typeinfo>
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
#include <string.h> #include <string.h>
#endif #endif
#include "util.h"
#include "floppyio.h" #include "floppyio.h"
using namespace std; using namespace std;
// Floppy file constructor // FloppyIO Exception singleton
// static FloppyIOException __FloppyIOExceptionSingleton;
// This constructor opens the specified floppy disk image, fills everything
// with zeroes and initializes the topology variables. // Advanced Floppy file constructor
// //
// @param filename The filename of the floppy disk image // This constructor allows you to open a floppy disk image with extra flags.
//
FloppyIO::FloppyIO(const char * filename) { // F_NOINIT Disables the reseting of the image file at open
// F_NOCREATE Does not truncate the file at open (If not exists, the file will be created)
// Open file // F_SYNCHRONIZED The communication is synchronized, meaning that the code will block until the
fstream *fIO = new fstream(filename, fstream::in | fstream::out | fstream::trunc); // data are read/written from the guest.
// F_EXCEPTIONS Throw exceptions if something goes wrong.
// Prepare floppy info // F_CLIENT Swap in/out buffers for use from within the guest.
this->fIO = fIO; //
this->szFloppy = DEFAULT_FLOPPY_SIZE; // @param filename The filename of the floppy disk image
// @param flags The flags that define how the FloppyIO class should function
// Setup offsets and sizes of the I/O parts //
this->szOutput = this->szFloppy/2-1;
this->ofsOutput = 0; FloppyIO::FloppyIO(const char * filename, int flags) {
this->szInput = this->szOutput; // Clear error flag
this->ofsInput = this->szOutput; this->error = 0;
this->ofsCtrlByteOut = this->szInput+this->szOutput;
this->ofsCtrlByteIn = this->szInput+this->szOutput+1; // Prepare open flags and create file stream
ios_base::openmode fOpenFlags = fstream::in | fstream::out;
// Reset floppy file if ((flags & F_NOCREATE) == 0) fOpenFlags |= fstream::trunc;
this->reset(); fstream *fIO = new fstream( );
this->fIO = fIO;
}
// Enable exceptions on fIO if told so
// Advanced Floppy file constructor if ((flags & F_EXCEPTIONS) != 0) {
// fIO->exceptions( ifstream::failbit | ifstream::badbit );
// This constructor allows you to open a floppy disk image with extra flags. this->useExceptions=true;
// } else {
// F_NOINIT Disables the reseting of the image file at open this->useExceptions=false;
// F_NOCREATE Does not truncate the file at open (If not exists, the file will be created) }
// F_SYNCHRONIZED The communication is synchronized, meaning that the code will block until the
// data are read/written from the guest. [NOT YET IMPLEMENTED] // Try to open the file
// fIO->open(filename, fOpenFlags);
// @param filename The filename of the floppy disk image
// Check for errors while F_NOCREATE is there
FloppyIO::FloppyIO(const char * filename, int flags) { if ((flags & F_NOCREATE) != 0) {
if ( fIO->fail() ) {
// Open file
ios_base::openmode fOpenFlags = fstream::in | fstream::out; // Clear error flags
if ((flags & F_NOCREATE) == 0) fOpenFlags = fstream::trunc; fIO->clear();
fstream *fIO = new fstream(filename, fOpenFlags);
// Try to create file
// Check for errors while F_NOCREATE is there fOpenFlags |= fstream::trunc;
if ((flags & F_NOCREATE) != 0) { fIO->open(filename, fOpenFlags);
if ( (fIO->rdstate() & ifstream::failbit ) != 0 ) {
// Still errors?
// Clear error flag if ( fIO->fail() ) {
fIO->clear(); this->setError(-3, "Error while creating floppy I/O file, because it wasn't found even though F_NOCREATE was specified!");
return;
// Try to create file }
fOpenFlags |= fstream::trunc;
fIO->open(filename, fOpenFlags); // Managed to open it? Reset it...
flags &= ~F_NOINIT;
// Still errors? }
if ( (fIO->rdstate() & ifstream::failbit ) != 0 ) {
cerr << "Error opening '" << filename << "'!\n"; } else {
return;
} // Check for failures on open
if ( fIO->fail() ) {
// Managed to open it? Reset it... this->setError(-3, "Error while creating floppy I/O file!");
flags &= ~F_NOINIT; return;
} }
} }
// Prepare floppy info // Prepare floppy info
this->fIO = fIO; this->szFloppy = DEFAULT_FIO_FLOPPY_SIZE;
this->szFloppy = DEFAULT_FLOPPY_SIZE;
// Setup offsets and sizes of the I/O parts
// Setup offsets and sizes of the I/O parts if ((flags & F_CLIENT) != 0) {
this->szOutput = this->szFloppy/2-1; // Guest mode
this->ofsOutput = 0; this->szOutput = this->szFloppy/2-1;
this->szInput = this->szOutput; this->szInput = this->szOutput;
this->ofsInput = this->szOutput; this->ofsOutput = this->szInput;
this->ofsCtrlByteOut = this->szInput+this->szOutput; this->ofsInput = 0;
this->ofsCtrlByteIn = this->szInput+this->szOutput+1; this->ofsCtrlByteIn = this->szInput+this->szOutput;
this->ofsCtrlByteOut = this->szInput+this->szOutput+1;
// Reset floppy file
if ((flags & F_NOINIT) == 0) this->reset(); } else {
// Hypervisor mode
} this->szOutput = this->szFloppy/2-1;
this->szInput = this->szOutput;
this->ofsOutput = 0;
// FloppyIO Destructor this->ofsInput = this->szOutput;
// Closes the file descriptor and releases used memory this->ofsCtrlByteOut = this->szInput+this->szOutput;
this->ofsCtrlByteIn = this->szInput+this->szOutput+1;
FloppyIO::~FloppyIO() { }
// Close file
this->fIO->close(); // Update synchronization flags
this->synchronized = false;
// Release memory this->syncTimeout = DEFAULT_FIO_SYNC_TIMEOUT;
delete this->fIO; if ((flags & F_SYNCHRONIZED) != 0) this->synchronized=true;
}
// Reset floppy file
// Reset the floppy disk image if ((flags & F_NOINIT) == 0) this->reset();
// This function zeroes-out the contents of the FD image
}
void FloppyIO::reset() {
this->fIO->seekp(0);
char * buffer = new char[this->szFloppy]; // FloppyIO Destructor
this->fIO->write(buffer, this->szFloppy); // Closes the file descriptor and releases used memory
delete[] buffer;
} FloppyIO::~FloppyIO() {
// Close file
// Send data to the floppy image I/O this->fIO->close();
// @param data
// @return // Release memory
void FloppyIO::send(string strData) { delete this->fIO;
// Prepare send buffer }
char * dataToSend = new char[this->szOutput];
memset(dataToSend, 0, this->szOutput); // Reset the floppy disk image
// This function zeroes-out the contents of the FD image
// Initialize variables
int szData = strData.length(); void FloppyIO::reset() {
// Check for ready state
// Copy the first szInput bytes if (!this->ready()) {
if (szData > this->szOutput-1) { this->setError(-4, "Stream is not ready!");
// Data more than the pad size? Trim... return;
strData.copy(dataToSend, this->szOutput-1, 0); }
} else {
// Else, copy the string to send buffer // Reset to the beginnig of file and fill with zeroes
strData.copy(dataToSend, szData, 0); this->fIO->seekp(0);
} char * buffer = new char[this->szFloppy];
memset(buffer, 0, this->szFloppy);
// Write the data to file this->fIO->write(buffer, this->szFloppy);
this->fIO->seekp(this->ofsOutput); delete[] buffer;
this->fIO->write(dataToSend, this->szOutput); }
// Notify the client that we placed data (Client should clear this on read)
this->fIO->seekp(this->ofsCtrlByteOut); // Send data to the floppy image I/O
this->fIO->write("\x01", 1); //
} // @param strData The string to send
// @return The number of bytes sent if successful or -1 if an error occured.
//
// Receive the input buffer contents int FloppyIO::send(string strData) {
// @return Returns a string object with the file contents // Prepare send buffer
char * dataToSend = new char[this->szOutput];
string FloppyIO::receive() { memset(dataToSend, 0, this->szOutput);
static string ansBuffer;
char * dataToReceive = new char[this->szInput]; // Check for ready state
int dataLength = this->szInput; if (!this->ready()) return this->setError(-4, "Stream is not ready!");
// Find the size of the input string // Initialize variables
for (int i=0; i<this->szInput; i++) { int szData = (int)strData.length();
if (dataToReceive[0] == '\0') { int szPad = 0;
dataLength=i; int bytesSent = szData;
break;
} // Copy the first szInput bytes
} if (szData > this->szOutput-1) { // -1 for the null-termination
// Data more than the pad size? Trim...
// Read the input bytes from FD strData.copy(dataToSend, this->szOutput-1, 0);
this->fIO->seekg(this->ofsInput, ios_base::beg); bytesSent = this->szOutput-1;
this->fIO->read(dataToReceive, this->szInput); } else {
// Else, copy the string to send buffer
// Notify the client that we have read the data strData.copy(dataToSend, szData, 0);
this->fIO->seekp(this->ofsCtrlByteIn); }
this->fIO->write("\x00", 1);
// Check for stream status
// Copy input data to string object if (!this->fIO->good()) return this->setError(-1, "I/O Stream reported no-good state while sending!");
ansBuffer = dataToReceive;
return ansBuffer; // Write the data to file
this->fIO->seekp(this->ofsOutput);
} this->fIO->write(dataToSend, this->szOutput);
// Check if something went wrong after writing
if (!this->fIO->good()) return this->setError(-1, "I/O Stream reported no-good state while sending!");
// Notify the client that we placed data (Client should clear this on read)
this->fIO->seekp(this->ofsCtrlByteOut);
this->fIO->write("\x01", 1);
this->fIO->flush();
// If synchronized, wait for data to be written
if (this->synchronized) {
// Wait for input control byte to become 1
int iState = this->waitForSync(this->ofsCtrlByteOut, 0, this->syncTimeout);
if (iState<0) return iState;
}
// Return number of bytes sent
return bytesSent;
}
//
// Receive the input buffer contents
//
// @return Returns a string object with the buffer contents
//
string FloppyIO::receive() {
static string ansBuffer;
this->receive(&ansBuffer);
return ansBuffer;
}
//
// Receive the input buffer contents
//
// @param string A pointer to a string object that will receive the data
// @return Returns the length of the data received or -1 if an error occured.
//
int FloppyIO::receive(string * ansBuffer) {
char * dataToReceive = new char[this->szInput];
int dataLength = this->szInput;
// Check for ready state
if (!this->ready()) return this->setError(-4, "Stream is not ready!");
// If synchronized, wait for input data
if (this->synchronized) {
// Wait for input control byte to become 1
int iState = this->waitForSync(this->ofsCtrlByteIn, 1, this->syncTimeout);
if (iState<0) return iState;
}
// Check for stream status
if (!this->fIO->good()) return this->setError(-1, "I/O Stream reported no-good state while receiving!");
// Read the input bytes from FD
this->fIO->seekg(this->ofsInput, ios_base::beg);
this->fIO->read(dataToReceive, this->szInput);
// Notify the client that we have read the data
this->fIO->seekp(this->ofsCtrlByteIn);
this->fIO->write("\x00", 1);
this->fIO->flush();
// Copy input data to string object
*ansBuffer = dataToReceive;
return (int)ansBuffer->length();
}
// Wait for synchronization byte to be cleared.
// This function blocks until the byte at controlByteOffset has
// the synchronization bit cleared.
//
// @param controlByteOffset The offset (from the beginning of file) where to look for the control byte
// @param state The state the controlByte must be for this function to exit.
// @param timeout The time (in seconds) to wait for a change. 0 Will wait forever
// @return Returns 0 if everything succeeded, -1 if an error occured, -2 if timed out.
int FloppyIO::waitForSync(int controlByteOffset, char state, int timeout) {
time_t tExpired = time (NULL) + timeout;
char cStatusByte;
// Wait until expired or forever.
while ((timeout == 0) || ( time(NULL) <= tExpired)) {
// Check for stream status
if (!this->fIO->good()) return this->setError(-1, "I/O Stream reported no-good state while waiting for sync!");
// Check the synchronization byte
this->fIO->seekg(controlByteOffset, ios_base::beg);
this->fIO->read(&cStatusByte, 1);
// Is the control byte 0? Our job is finished...
if (cStatusByte == state) return 0;
// Sleep for a few milliseconds to decrease CPU-load
boinc_sleep(0.250);
}
// If we reached this point, we timed out
return this->setError(-2, "Timed-out while waiting for sync!");
}
//
// Set last error.
// This is a short-hand function to update the error variables.
//
// @param code The error code
// @param message The error message
// @return The error code
//
int FloppyIO::setError(int code, const string message) {
this->error = code;
// Chain errors
if (this->errorStr.empty()) {
this->errorStr = message;
} else {
this->errorStr = message + " (" + this->errorStr + ")";
}
// Should we raise an exception?
if (this->useExceptions)
throw *__FloppyIOExceptionSingleton.set(code, message);
// Otherwise return code
// (Useful for using single-lined: return this->setError(-1, "message..');
return code;
}
//
// Clear error state flags
//
void FloppyIO::clear() {
this->error = 0;
this->errorStr = "";
this->fIO->clear();
}
//
// Check if everything is in ready state
// @return Returns true if there are no errors and stream hasn't failed
//
bool FloppyIO::ready() {
if (this->error!=0) return false;
return this->fIO->good();
}

View File

@ -1,84 +1,185 @@
// File: FloppyIO.h // This file is part Floppy I/O, a Virtual Machine - Hypervisor intercommunication system.
// Author: Ioannis Charalampidis <ioannis.charalampidis AT cern DOT ch> // Copyright (C) 2011 Ioannis Charalampidis
// //
// Hypervisor-Virtual machine bi-directional communication // This program is free software: you can redistribute it and/or modify
// through floppy disk. // it under the terms of the GNU Lesser General Public License as published by
// // the Free Software Foundation, either version 3 of the License, or
// This class provides the hypervisor-side of the script. // (at your option) any later version.
// For the guest-side, check the perl scripts that //
// were available with this code. // This program is distributed in the hope that it will be useful,
// // but WITHOUT ANY WARRANTY; without even the implied warranty of
// Here is the layout of the floppy disk image (Example of 28k): // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// // GNU Lesser General Public License for more details.
// +-----------------+------------------------------------------------+ //
// | 0x0000 - 0x37FF | Hypervisor -> Guest Buffer | // You should have received a copy of the GNU Lesser General Public License
// | 0x3800 - 0x6FFE | Guest -> Hypervisor Buffer | // along with this program. If not, see <http://www.gnu.org/licenses/>.
// | 0x6FFF | "Data available for guest" flag byte |
// | 0x7000 | "Data available for hypervisor" flag byte | // File: FloppyIO.h
// +-----------------+------------------------------------------------+ // Author: Ioannis Charalampidis <ioannis.charalampidis AT cern DOT ch>
// // License: GNU Lesser General Public License - Version 3.0
// Created on November 24, 2011, 12:30 PM //
// Hypervisor-Virtual machine bi-directional communication
#ifndef FLOPPYIO_H // through floppy disk.
#define FLOPPYIO_H //
// This class provides the hypervisor-side of the script.
// Do not initialize (reset) floppy disk image at open. // For the guest-side, check the perl scripts that
// (Flag used at FloppyIO constructor) // were available with this code.
//
#define F_NOINIT 1 // Here is the layout of the floppy disk image (Example of 28k):
//
// +-----------------+------------------------------------------------+
// Do not create the filename (assume it exists) // | 0x0000 - 0x37FF | Hypervisor -> Guest Buffer |
// (Flag used at FloppyIO constructor) // | 0x3800 - 0x6FFE | Guest -> Hypervisor Buffer |
// | 0x6FFF | "Data available for guest" flag byte |
#define F_NOCREATE 2 // | 0x7000 | "Data available for hypervisor" flag byte |
// +-----------------+------------------------------------------------+
//
// Synchronize I/O [NOT YET IMPLEMENTED] // Updated at January 5, 2012, 13:06 PM
// This flag will block the script until the guest has read/written the data. //
// (Flag used at FloppyIO constructor)
#ifndef FLOPPYIO_H
#define F_SYNCHRONIZED 4 #define FLOPPYIO_H
// Default floppy disk size (In bytes) // Do not initialize (reset) floppy disk image at open.
// // (Flag used by the FloppyIO constructor)
// VirtualBox complains if bigger than 28K #define F_NOINIT 1
// It's supposed to go till 1474560 however (!.44 Mb)
// Do not create the filename (assume it exists)
#define DEFAULT_FLOPPY_SIZE 28672 // (Flag used by the FloppyIO constructor)
#define F_NOCREATE 2
// Floppy I/O Communication class // Synchronize I/O.
// This flag will block the script until the guest has read/written the data.
class FloppyIO { // (Flag used by the FloppyIO constructor)
public: #define F_SYNCHRONIZED 4
// Constructors // Use exceptions instead of error codes
FloppyIO(const char * filename); // (Flag used by the FloppyIO constructor)
FloppyIO(const char * filename, int flags); #define F_EXCEPTIONS 8
virtual ~FloppyIO();
// Initialize FloppyIO in client mode.
// Functions // This flag will swap the input/output buffers, making the script usable from
void reset(); // within the virtual machine.
void send(std::string strData); // (Flag used by the FloppyIO constructor)
std::string receive(); #define F_CLIENT 16
// Topology info //
int ofsInput; // Input buffer offset & size // Error code constants
int szInput; //
int ofsOutput; // Output buffer offset & size #define FPIO_NOERR 0 // No error occured
int szOutput; #define FPIO_ERR_IO -1 // There was an I/O error on the strea,
#define FPIO_ERR_TIMEOUT -2 // The operation timed out
int ofsCtrlByteIn; // Control byte offset for input #define FPIO_ERR_CREATE -3 // Unable to freate the floppy file
int ofsCtrlByteOut; // Control byte offset for output #define FPIO_ERR_NOTREADY -4 // The I/O object is not ready
private: //
// Structure of the synchronization control byte.
// Floppy Info //
std::fstream* fIO; // This byte usually resides at the beginning of the
int szFloppy; // floppy file for the receive buffer and at the end
// of the file for the sending buffer.
}; //
// It's purpose is to force the entire floppy image
#endif // FLOPPYIO_H // to be re-written/re-read by the hypervisor/guest OS and
// to synchronize the I/O in case of large ammount of
// data being exchanged.
//
typedef struct fpio_ctlbyte {
unsigned short bDataPresent : 1;
unsigned short bReserved : 7;
} fpio_ctlbytex;
// Default floppy disk size (In bytes)
//
// VirtualBox complains if bigger than 28K
// It's supposed to go till 1474560 however (1.44 Mb)
#define DEFAULT_FIO_FLOPPY_SIZE 28672
// Default synchronization timeout (seconds).
// This constant defines how long we should wait for synchronization
// feedback from the guest before aborting.
#define DEFAULT_FIO_SYNC_TIMEOUT 5
//
// Floppy I/O Communication class
//
class FloppyIO {
public:
// Construcors
FloppyIO(const char * filename, int flags = 0);
virtual ~FloppyIO();
// Functions
void reset();
int send(std::string strData);
std::string receive();
int receive(std::string* strBuffer);
// Topology info
int ofsInput; // Input buffer offset & size
int szInput;
int ofsOutput; // Output buffer offset & size
int szOutput;
int ofsCtrlByteIn; // Control byte offset for input
int ofsCtrlByteOut; // Control byte offset for output
// Synchronization stuff
bool synchronized; // The read/writes are synchronized
int syncTimeout; // For how long should we wait
// Error reporting and checking
int error;
std::string errorStr;
bool useExceptions; // If TRUE errors will raise exceptions
void clear(); // Clear errors
bool ready(); // Returns TRUE if there are no errors
private:
// Floppy Info
std::fstream* fIO;
int szFloppy;
// Functions
int waitForSync(int controlByteOffset, char state, int timeout);
int setError(int code, std::string message);
};
//
// Floppy I/O Exceptions
//
class FloppyIOException: public std::exception {
public:
int code;
std::string message;
// Default constructor/destructor
FloppyIOException() { this->code=0; this->message=""; };
virtual ~FloppyIOException() throw() { };
// Get description
virtual const char* what() const throw() {
static std::ostringstream oss (std::ostringstream::out);
oss << this->message << ". Error code = " << this->code;
return oss.str().c_str();
}
// Change the message and return my instance
// (Used for singleton format)
FloppyIOException * set(int code, std::string message) {
this->code = code;
this->message = message;
return this;
}
};
#endif // FLOPPYIO_H

View File

@ -320,11 +320,13 @@ CLEANUP:
// Determine the real error code by parsing the output // Determine the real error code by parsing the output
errcode_start = output.find("(0x"); errcode_start = output.find("(0x");
errcode_start += 1; if (errcode_start) {
errcode_end = output.find(")", errcode_start); errcode_start += 1;
errcode = output.substr(errcode_start, errcode_end - errcode_start); errcode_end = output.find(")", errcode_start);
errcode = output.substr(errcode_start, errcode_end - errcode_start);
retval = strtol(errcode.c_str(), NULL, NULL); sscanf(errcode.c_str(), "%x", &retval);
}
// If something couldn't be found, just return ERR_FOPEN // If something couldn't be found, just return ERR_FOPEN
if (!retval) retval = ERR_FOPEN; if (!retval) retval = ERR_FOPEN;
@ -801,6 +803,18 @@ int VBOX_VM::register_vm() {
// NOTE: This creates the floppy.img file at runtime for use by the VM. // NOTE: This creates the floppy.img file at runtime for use by the VM.
// //
pFloppy = new FloppyIO(floppy_image_filename.c_str()); pFloppy = new FloppyIO(floppy_image_filename.c_str());
if (!pFloppy->ready()) {
fprintf(
stderr,
"%s Creating virtual floppy image failed.\n"
"%s Error Code '%d' Error Message '%s'\n",
boinc_msg_prefix(buf, sizeof(buf)),
boinc_msg_prefix(buf, sizeof(buf)),
pFloppy->error,
pFloppy->errorStr.c_str()
);
return ERR_FWRITE;
}
fprintf( fprintf(
stderr, stderr,