From 9faee707fa3d4c40ddda566950bf4405de31a534 Mon Sep 17 00:00:00 2001 From: Rom Walton Date: Fri, 6 Jan 2012 18:44:34 +0000 Subject: [PATCH] - 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 --- checkin_notes | 10 + samples/vboxwrapper/floppyio.cpp | 551 ++++++++++++++++++++----------- samples/vboxwrapper/floppyio.h | 269 ++++++++++----- samples/vboxwrapper/vbox.cpp | 22 +- 4 files changed, 574 insertions(+), 278 deletions(-) diff --git a/checkin_notes b/checkin_notes index eec98f16d1..2344c84542 100644 --- a/checkin_notes +++ b/checkin_notes @@ -234,3 +234,13 @@ Rom 6 Jan 2012 ViewStatistics.cpp lib/ 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 diff --git a/samples/vboxwrapper/floppyio.cpp b/samples/vboxwrapper/floppyio.cpp index 431cde1215..01a06cfc74 100644 --- a/samples/vboxwrapper/floppyio.cpp +++ b/samples/vboxwrapper/floppyio.cpp @@ -1,201 +1,372 @@ -// File: FloppyIO.cpp -// Author: Ioannis Charalampidis -// -// 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 | -// +-----------------+------------------------------------------------+ -// -// Created on November 24, 2011, 12:30 PM - +// This file is part Floppy I/O, a Virtual Machine - Hypervisor intercommunication system. +// Copyright (C) 2011 Ioannis Charalampidis +// +// This program is free software: you can redistribute it and/or modify +// 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 +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see . + +// File: FloppyIO.cpp +// Author: Ioannis Charalampidis +// License: GNU Lesser General Public License - Version 3.0 +// +// 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 #include "boinc_win.h" #else +#include #include #include #include #endif +#include "util.h" #include "floppyio.h" using namespace std; - -// Floppy file constructor -// -// This constructor opens the specified floppy disk image, fills everything -// with zeroes and initializes the topology variables. -// -// @param filename The filename of the floppy disk image - -FloppyIO::FloppyIO(const char * filename) { - - // Open file - fstream *fIO = new fstream(filename, fstream::in | fstream::out | fstream::trunc); - - // Prepare floppy info - this->fIO = fIO; - this->szFloppy = DEFAULT_FLOPPY_SIZE; - - // Setup offsets and sizes of the I/O parts - this->szOutput = this->szFloppy/2-1; - this->ofsOutput = 0; - this->szInput = this->szOutput; - this->ofsInput = this->szOutput; - this->ofsCtrlByteOut = this->szInput+this->szOutput; - this->ofsCtrlByteIn = this->szInput+this->szOutput+1; - - // Reset floppy file - this->reset(); - -} - -// Advanced Floppy file constructor -// -// This constructor allows you to open a floppy disk image with extra flags. -// -// 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) -// F_SYNCHRONIZED The communication is synchronized, meaning that the code will block until the -// data are read/written from the guest. [NOT YET IMPLEMENTED] -// -// @param filename The filename of the floppy disk image - -FloppyIO::FloppyIO(const char * filename, int flags) { - - // Open file - ios_base::openmode fOpenFlags = fstream::in | fstream::out; - if ((flags & F_NOCREATE) == 0) fOpenFlags = fstream::trunc; - fstream *fIO = new fstream(filename, fOpenFlags); - - // Check for errors while F_NOCREATE is there - if ((flags & F_NOCREATE) != 0) { - if ( (fIO->rdstate() & ifstream::failbit ) != 0 ) { - - // Clear error flag - fIO->clear(); - - // Try to create file - fOpenFlags |= fstream::trunc; - fIO->open(filename, fOpenFlags); - - // Still errors? - if ( (fIO->rdstate() & ifstream::failbit ) != 0 ) { - cerr << "Error opening '" << filename << "'!\n"; - return; - } - - // Managed to open it? Reset it... - flags &= ~F_NOINIT; - } - - } - - // Prepare floppy info - this->fIO = fIO; - this->szFloppy = DEFAULT_FLOPPY_SIZE; - - // Setup offsets and sizes of the I/O parts - this->szOutput = this->szFloppy/2-1; - this->ofsOutput = 0; - this->szInput = this->szOutput; - this->ofsInput = this->szOutput; - this->ofsCtrlByteOut = this->szInput+this->szOutput; - this->ofsCtrlByteIn = this->szInput+this->szOutput+1; - - // Reset floppy file - if ((flags & F_NOINIT) == 0) this->reset(); - -} - - -// FloppyIO Destructor -// Closes the file descriptor and releases used memory - -FloppyIO::~FloppyIO() { - // Close file - this->fIO->close(); - - // Release memory - delete this->fIO; -} - -// Reset the floppy disk image -// This function zeroes-out the contents of the FD image - -void FloppyIO::reset() { - this->fIO->seekp(0); - char * buffer = new char[this->szFloppy]; - this->fIO->write(buffer, this->szFloppy); - delete[] buffer; -} - -// Send data to the floppy image I/O -// @param data -// @return -void FloppyIO::send(string strData) { - // Prepare send buffer - char * dataToSend = new char[this->szOutput]; - memset(dataToSend, 0, this->szOutput); - - // Initialize variables - int szData = strData.length(); - - // Copy the first szInput bytes - if (szData > this->szOutput-1) { - // Data more than the pad size? Trim... - strData.copy(dataToSend, this->szOutput-1, 0); - } else { - // Else, copy the string to send buffer - strData.copy(dataToSend, szData, 0); - } - - // Write the data to file - this->fIO->seekp(this->ofsOutput); - this->fIO->write(dataToSend, this->szOutput); - - // Notify the client that we placed data (Client should clear this on read) - this->fIO->seekp(this->ofsCtrlByteOut); - this->fIO->write("\x01", 1); -} - - -// Receive the input buffer contents -// @return Returns a string object with the file contents - -string FloppyIO::receive() { - static string ansBuffer; - char * dataToReceive = new char[this->szInput]; - int dataLength = this->szInput; - - // Find the size of the input string - for (int i=0; iszInput; i++) { - if (dataToReceive[0] == '\0') { - dataLength=i; - break; - } - } - - // 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); - - // Copy input data to string object - ansBuffer = dataToReceive; - return ansBuffer; - -} + +// FloppyIO Exception singleton +static FloppyIOException __FloppyIOExceptionSingleton; + +// Advanced Floppy file constructor +// +// This constructor allows you to open a floppy disk image with extra flags. +// +// 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) +// F_SYNCHRONIZED The communication is synchronized, meaning that the code will block until the +// data are read/written from the guest. +// F_EXCEPTIONS Throw exceptions if something goes wrong. +// F_CLIENT Swap in/out buffers for use from within the guest. +// +// @param filename The filename of the floppy disk image +// @param flags The flags that define how the FloppyIO class should function +// + +FloppyIO::FloppyIO(const char * filename, int flags) { + // Clear error flag + this->error = 0; + + // Prepare open flags and create file stream + ios_base::openmode fOpenFlags = fstream::in | fstream::out; + if ((flags & F_NOCREATE) == 0) fOpenFlags |= fstream::trunc; + fstream *fIO = new fstream( ); + this->fIO = fIO; + + // Enable exceptions on fIO if told so + if ((flags & F_EXCEPTIONS) != 0) { + fIO->exceptions( ifstream::failbit | ifstream::badbit ); + this->useExceptions=true; + } else { + this->useExceptions=false; + } + + // Try to open the file + fIO->open(filename, fOpenFlags); + + // Check for errors while F_NOCREATE is there + if ((flags & F_NOCREATE) != 0) { + if ( fIO->fail() ) { + + // Clear error flags + fIO->clear(); + + // Try to create file + fOpenFlags |= fstream::trunc; + fIO->open(filename, fOpenFlags); + + // Still errors? + if ( fIO->fail() ) { + this->setError(-3, "Error while creating floppy I/O file, because it wasn't found even though F_NOCREATE was specified!"); + return; + } + + // Managed to open it? Reset it... + flags &= ~F_NOINIT; + } + + } else { + + // Check for failures on open + if ( fIO->fail() ) { + this->setError(-3, "Error while creating floppy I/O file!"); + return; + } + + } + + // Prepare floppy info + this->szFloppy = DEFAULT_FIO_FLOPPY_SIZE; + + // Setup offsets and sizes of the I/O parts + if ((flags & F_CLIENT) != 0) { + // Guest mode + this->szOutput = this->szFloppy/2-1; + this->szInput = this->szOutput; + this->ofsOutput = this->szInput; + this->ofsInput = 0; + this->ofsCtrlByteIn = this->szInput+this->szOutput; + this->ofsCtrlByteOut = this->szInput+this->szOutput+1; + + } else { + // Hypervisor mode + this->szOutput = this->szFloppy/2-1; + this->szInput = this->szOutput; + this->ofsOutput = 0; + this->ofsInput = this->szOutput; + this->ofsCtrlByteOut = this->szInput+this->szOutput; + this->ofsCtrlByteIn = this->szInput+this->szOutput+1; + } + + // Update synchronization flags + this->synchronized = false; + this->syncTimeout = DEFAULT_FIO_SYNC_TIMEOUT; + if ((flags & F_SYNCHRONIZED) != 0) this->synchronized=true; + + // Reset floppy file + if ((flags & F_NOINIT) == 0) this->reset(); + +} + + +// FloppyIO Destructor +// Closes the file descriptor and releases used memory + +FloppyIO::~FloppyIO() { + // Close file + this->fIO->close(); + + // Release memory + delete this->fIO; +} + +// Reset the floppy disk image +// This function zeroes-out the contents of the FD image + +void FloppyIO::reset() { + // Check for ready state + if (!this->ready()) { + this->setError(-4, "Stream is not ready!"); + return; + } + + // Reset to the beginnig of file and fill with zeroes + this->fIO->seekp(0); + char * buffer = new char[this->szFloppy]; + memset(buffer, 0, this->szFloppy); + this->fIO->write(buffer, this->szFloppy); + delete[] buffer; +} + + +// Send data to the floppy image I/O +// +// @param strData The string to send +// @return The number of bytes sent if successful or -1 if an error occured. +// +int FloppyIO::send(string strData) { + // Prepare send buffer + char * dataToSend = new char[this->szOutput]; + memset(dataToSend, 0, this->szOutput); + + // Check for ready state + if (!this->ready()) return this->setError(-4, "Stream is not ready!"); + + // Initialize variables + int szData = (int)strData.length(); + int szPad = 0; + int bytesSent = szData; + + // Copy the first szInput bytes + if (szData > this->szOutput-1) { // -1 for the null-termination + // Data more than the pad size? Trim... + strData.copy(dataToSend, this->szOutput-1, 0); + bytesSent = this->szOutput-1; + } else { + // Else, copy the string to send buffer + strData.copy(dataToSend, szData, 0); + } + + // Check for stream status + if (!this->fIO->good()) return this->setError(-1, "I/O Stream reported no-good state while sending!"); + + // 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(); +} + + + diff --git a/samples/vboxwrapper/floppyio.h b/samples/vboxwrapper/floppyio.h index 6942d468a7..22ab47eef0 100644 --- a/samples/vboxwrapper/floppyio.h +++ b/samples/vboxwrapper/floppyio.h @@ -1,84 +1,185 @@ -// File: FloppyIO.h -// Author: Ioannis Charalampidis -// -// 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 | -// +-----------------+------------------------------------------------+ -// -// Created on November 24, 2011, 12:30 PM - -#ifndef FLOPPYIO_H -#define FLOPPYIO_H - -// Do not initialize (reset) floppy disk image at open. -// (Flag used at FloppyIO constructor) - -#define F_NOINIT 1 - - -// Do not create the filename (assume it exists) -// (Flag used at FloppyIO constructor) - -#define F_NOCREATE 2 - - -// Synchronize I/O [NOT YET IMPLEMENTED] -// This flag will block the script until the guest has read/written the data. -// (Flag used at FloppyIO constructor) - -#define F_SYNCHRONIZED 4 - -// Default floppy disk size (In bytes) -// -// VirtualBox complains if bigger than 28K -// It's supposed to go till 1474560 however (!.44 Mb) - -#define DEFAULT_FLOPPY_SIZE 28672 - - -// Floppy I/O Communication class - -class FloppyIO { -public: - - // Constructors - FloppyIO(const char * filename); - FloppyIO(const char * filename, int flags); - virtual ~FloppyIO(); - - // Functions - void reset(); - void send(std::string strData); - std::string receive(); - - // 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 - -private: - - // Floppy Info - std::fstream* fIO; - int szFloppy; - -}; - -#endif // FLOPPYIO_H - +// This file is part Floppy I/O, a Virtual Machine - Hypervisor intercommunication system. +// Copyright (C) 2011 Ioannis Charalampidis +// +// This program is free software: you can redistribute it and/or modify +// 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 +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see . + +// File: FloppyIO.h +// Author: Ioannis Charalampidis +// License: GNU Lesser General Public License - Version 3.0 +// +// 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 +// + +#ifndef FLOPPYIO_H +#define FLOPPYIO_H + +// Do not initialize (reset) floppy disk image at open. +// (Flag used by the FloppyIO constructor) +#define F_NOINIT 1 + +// Do not create the filename (assume it exists) +// (Flag used by the FloppyIO constructor) +#define F_NOCREATE 2 + +// Synchronize I/O. +// This flag will block the script until the guest has read/written the data. +// (Flag used by the FloppyIO constructor) +#define F_SYNCHRONIZED 4 + +// Use exceptions instead of error codes +// (Flag used by the FloppyIO constructor) +#define F_EXCEPTIONS 8 + +// Initialize FloppyIO in client mode. +// This flag will swap the input/output buffers, making the script usable from +// within the virtual machine. +// (Flag used by the FloppyIO constructor) +#define F_CLIENT 16 + +// +// Error code constants +// +#define FPIO_NOERR 0 // No error occured +#define FPIO_ERR_IO -1 // There was an I/O error on the strea, +#define FPIO_ERR_TIMEOUT -2 // The operation timed out +#define FPIO_ERR_CREATE -3 // Unable to freate the floppy file +#define FPIO_ERR_NOTREADY -4 // The I/O object is not ready + +// +// Structure of the synchronization control byte. +// +// This byte usually resides at the beginning of the +// 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 +// 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 + diff --git a/samples/vboxwrapper/vbox.cpp b/samples/vboxwrapper/vbox.cpp index ac63d2e7a6..6d7cccddca 100644 --- a/samples/vboxwrapper/vbox.cpp +++ b/samples/vboxwrapper/vbox.cpp @@ -320,11 +320,13 @@ CLEANUP: // Determine the real error code by parsing the output errcode_start = output.find("(0x"); - errcode_start += 1; - errcode_end = output.find(")", errcode_start); - errcode = output.substr(errcode_start, errcode_end - errcode_start); + if (errcode_start) { + errcode_start += 1; + 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 (!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. // 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( stderr,