Page 1 of 1
how to set this up in C++?
Posted: Fri Jun 01, 2007 11:06 pm
by earlz
I am trying to make a simple disk image handling library..
basically what it will do is allow you to open up a file and use it as a disk image. Then you can read and write sectors and such to it..good for making prototype filesystem stuff..
I am having a problem determining how the constructor should be set up..
if I have something like "Disk(unsigned int size,string& filename)" then what do I do if filename doesn't exist? or if I can't create it?
but if I wait until a "open_disk(string& filename)" then it's not initialized until you call that...
what should I do!?
also, anyone see anything wrong with this basic class I made?
Code: Select all
class Disk{
disk_geometry dg;
public:
//constructors..
virtual ~Disk();
Disk(disk_geometry *geo,string& filename);
Disk(unsigned int c,unsigned int h,unsigned int s,const string& filename);
Disk(const Disk& source);
//Interface:
virtual unsigned long long DiskSize(){
return dg.bps*dg.spt*dg.cph*dg.hpd;
}
virtual char *ReadSector(unsigned int abs_sector); //?
};
Posted: Fri Jun 01, 2007 11:11 pm
by pcmattman
Have a constructor with just the filename, with a 'has_init' boolean variable somewhere. Once a usable environment has been created, you can set has_init to true.
Other functions will check has_init before they attempt to do anything.
Posted: Fri Jun 01, 2007 11:22 pm
by earlz
hmm...one idea would be to use a stream handle(or whatever..I'm not familiar with most of the C++ IO)
that way your sure it is open...hmm...
I think that idea of yours is best guess though...
Posted: Fri Jun 01, 2007 11:28 pm
by pcmattman
Well if you use ifstream to read in the data, then you can use its fail() function to find out if it's good or not...
I'd suggest learning how to do C++ streaming i/o.
Re: how to set this up in C++?
Posted: Sat Jun 02, 2007 1:15 am
by Candy
hckr83 wrote:if I have something like "Disk(unsigned int size,string& filename)" then what do I do if filename doesn't exist? or if I can't create it?
throw cannot_create_file_exception();
but if I wait until a "open_disk(string& filename)" then it's not initialized until you call that...
_state = Error;
what should I do!?
Make a design choice - do you want the C++ method, the C method or the state method?
C method:
Code: Select all
makeDisk() {
<do disk creation things>
if (disk.state == Error) {
<do disk deletion things>
return 0;
}
return disk;
}
Posted: Sat Jun 02, 2007 7:35 am
by earlz
state=error?
do you mean have this like a public variable?
I don't really want to mess with exceptions right now..I just got through the first volume...tried skimming the second volume and it looks a bit overwhelming..
I don't really want to do it that C way...
Posted: Sat Jun 02, 2007 11:24 am
by Alboin
hckr83 wrote:I don't really want to mess with exceptions right now..I just got through the first volume...tried skimming the second volume and it looks a bit overwhelming..
I don't really want to do it that C way...
It's difficult to do something without knowing how to do it. Just read...
By the by, what book are you reading?
Posted: Sat Jun 02, 2007 1:28 pm
by Kevin McGuire
Code: Select all
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdint.h>
#include <string.h>
struct sVirtualDiskHeader
{
uint32_t BytesPerSector;
uint32_t SectorsPerTrack;
uint32_t TracksPerHead;
uint32_t Heads;
uint32_t OtherInformation;
};
class cVirtualDiskFile
{
private:
sVirtualDiskHeader vdh; /// virtual disk header.
bool diskStateUsing; /// was this object created from a disk file?
char *diskStateFile;
void *data;
uint32_t dataSize;
public:
cVirtualDiskFile(char *file);
~cVirtualDiskFile();
bool SaveStateToDisk();
};
cVirtualDiskFile::cVirtualDiskFile(char *file)
{
int fdescriptor;
struct stat fdstat;
/// copy file path from potential temporary location to a managed location by us.
diskStateFile = (char*)malloc(strlen(file));
strcpy(diskStateFile, file);
fdescriptor = open(diskStateFile, O_RDWR | O_CREAT, S_IRWXU | S_IRGRP);
if(!fdescriptor)
{
diskStateUsing = false;
return;
}
fstat(fdescriptor, &fdstat);
if(read(fdescriptor, &vdh, sizeof(sVirtualDiskHeader)) < sizeof(sVirtualDiskHeader))
{
/// empty or corrupted file, just consider this a new image and error on save.
memset(&vdh, 0, sizeof(sVirtualDiskHeader));
close(fdescriptor);
diskStateUsing = false;
return;
}
/// could store the data size in the header..
data = malloc(fdstat.st_size - sizeof(sVirtualDiskHeader));
dataSize = fdstat.st_size - sizeof(sVirtualDiskHeader);
read(fdescriptor, data, fdstat.st_size - sizeof(sVirtualDiskHeader));
close(fdescriptor);
diskStateUsing = true;
return;
}
cVirtualDiskFile::~cVirtualDiskFile()
{
/// we implied that we are using a disk file so I figure it is implied that we sync our
/// memory state with the disk file state before deconstruction.
if(diskStateUsing)
{
SaveStateToDisk();
}
free(data);
if(diskStateFile)
{
free(diskStateFile);
}
}
bool cVirtualDiskFile::SaveStateToDisk()
{
int fdescriptor;
fdescriptor = open(diskStateFile, O_RDWR | O_CREAT | O_TRUNC, S_IRWXU | S_IRGRP);
if(!fdescriptor)
{
return false;
}
write(fdescriptor, &vdh, sizeof(sVirtualDiskHeader));
write(fdescriptor, data, dataSize);
close(fdescriptor);
return true;
}
int main(int argc, char *argv[])
{
cVirtualDiskFile vdf("test.data");
return 0;
}
It constructs a object by opening a file and pulling that file state into memory. If a failure happens then it just considers that it is
not using a disk state. You could have a method that checks a result code for the object to determine if something went wrong or just the application's implementation code will notice that some fields in the header are zero when it is supposed to be opening a existing disk image.
When you deconstruct the object it will write the data back to the disk file unless a failure happened in which it will assume to be in memory-only mode. You can also force a sync with the disk file by calling
cVirtualDiskFile::SaveStateToDisk().