|
|
|
@ -98,6 +98,41 @@ static const char* UnmountHelper(char umount) {
|
|
|
|
|
|
|
|
|
|
class MOUNT : public Program {
|
|
|
|
|
public:
|
|
|
|
|
void Move_Z(char new_z) {
|
|
|
|
|
char newz_drive = (char) toupper(new_z);
|
|
|
|
|
int i_newz = newz_drive - 'A';
|
|
|
|
|
if (i_newz >= 0 && i_newz < DOS_DRIVES-1 && !Drives[i_newz]) {
|
|
|
|
|
ZDRIVE_NUM = i_newz;
|
|
|
|
|
/* remap drives */
|
|
|
|
|
Drives[i_newz] = Drives[25];
|
|
|
|
|
Drives[25] = 0;
|
|
|
|
|
if (!first_shell) return; //Should not be possible
|
|
|
|
|
/* Update environment */
|
|
|
|
|
std::string line = "";
|
|
|
|
|
char ppp[2] = {newz_drive,0};
|
|
|
|
|
std::string tempenv = ppp; tempenv += ":\\";
|
|
|
|
|
if (first_shell->GetEnvStr("PATH",line)){
|
|
|
|
|
std::string::size_type idx = line.find('=');
|
|
|
|
|
std::string value = line.substr(idx +1 , std::string::npos);
|
|
|
|
|
while ( (idx = value.find("Z:\\")) != std::string::npos ||
|
|
|
|
|
(idx = value.find("z:\\")) != std::string::npos )
|
|
|
|
|
value.replace(idx,3,tempenv);
|
|
|
|
|
line = value;
|
|
|
|
|
}
|
|
|
|
|
if (!line.size()) line = tempenv;
|
|
|
|
|
first_shell->SetEnv("PATH",line.c_str());
|
|
|
|
|
tempenv += "COMMAND.COM";
|
|
|
|
|
first_shell->SetEnv("COMSPEC",tempenv.c_str());
|
|
|
|
|
|
|
|
|
|
/* Update batch file if running from Z: (very likely: autoexec) */
|
|
|
|
|
if(first_shell->bf) {
|
|
|
|
|
std::string &name = first_shell->bf->filename;
|
|
|
|
|
if(name.length() >2 && name[0] == 'Z' && name[1] == ':') name[0] = newz_drive;
|
|
|
|
|
}
|
|
|
|
|
/* Change the active drive */
|
|
|
|
|
if (DOS_GetDefaultDrive() == 25) DOS_SetDrive(i_newz);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
void ListMounts(void) {
|
|
|
|
|
char name[DOS_NAMELENGTH_ASCII];Bit32u size;Bit16u date;Bit16u time;Bit8u attr;
|
|
|
|
|
/* Command uses dta so set it to our internal dta */
|
|
|
|
@ -164,41 +199,10 @@ public:
|
|
|
|
|
/* Check for moving Z: */
|
|
|
|
|
/* Only allowing moving it once. It is merely a convenience added for the wine team */
|
|
|
|
|
if (ZDRIVE_NUM == 25 && cmd->FindString("-z", newz,false)) {
|
|
|
|
|
newz[0] = toupper(newz[0]);
|
|
|
|
|
int i_newz = newz[0] - 'A';
|
|
|
|
|
if (i_newz >= 0 && i_newz < DOS_DRIVES-1 && !Drives[i_newz]) {
|
|
|
|
|
ZDRIVE_NUM = i_newz;
|
|
|
|
|
/* remap drives */
|
|
|
|
|
Drives[i_newz] = Drives[25];
|
|
|
|
|
Drives[25] = 0;
|
|
|
|
|
if (!first_shell) return; //Should not be possible
|
|
|
|
|
/* Update environment */
|
|
|
|
|
std::string line = "";
|
|
|
|
|
char ppp[2] = {newz[0],0};
|
|
|
|
|
std::string tempenv = ppp; tempenv += ":\\";
|
|
|
|
|
if (first_shell->GetEnvStr("PATH",line)){
|
|
|
|
|
std::string::size_type idx = line.find('=');
|
|
|
|
|
std::string value = line.substr(idx +1 , std::string::npos);
|
|
|
|
|
while ( (idx = value.find("Z:\\")) != std::string::npos ||
|
|
|
|
|
(idx = value.find("z:\\")) != std::string::npos )
|
|
|
|
|
value.replace(idx,3,tempenv);
|
|
|
|
|
line = value;
|
|
|
|
|
}
|
|
|
|
|
if (!line.size()) line = tempenv;
|
|
|
|
|
first_shell->SetEnv("PATH",line.c_str());
|
|
|
|
|
tempenv += "COMMAND.COM";
|
|
|
|
|
first_shell->SetEnv("COMSPEC",tempenv.c_str());
|
|
|
|
|
|
|
|
|
|
/* Update batch file if running from Z: (very likely: autoexec) */
|
|
|
|
|
if(first_shell->bf) {
|
|
|
|
|
std::string &name = first_shell->bf->filename;
|
|
|
|
|
if(name.length() >2 && name[0] == 'Z' && name[1] == ':') name[0] = newz[0];
|
|
|
|
|
}
|
|
|
|
|
/* Change the active drive */
|
|
|
|
|
if (DOS_GetDefaultDrive() == 25) DOS_SetDrive(i_newz);
|
|
|
|
|
}
|
|
|
|
|
Move_Z(newz[0]);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Show list of cdroms */
|
|
|
|
|
if (cmd->FindExist("-cd",false)) {
|
|
|
|
|
int num = SDL_CDNumDrives();
|
|
|
|
@ -213,9 +217,9 @@ public:
|
|
|
|
|
cmd->FindString("-t",type,true);
|
|
|
|
|
bool iscdrom = (type =="cdrom"); //Used for mscdex bug cdrom label name emulation
|
|
|
|
|
if (type=="floppy" || type=="dir" || type=="cdrom" || type =="overlay") {
|
|
|
|
|
Bit16u sizes[4];
|
|
|
|
|
Bit16u sizes[4] ={0};
|
|
|
|
|
Bit8u mediaid;
|
|
|
|
|
std::string str_size;
|
|
|
|
|
std::string str_size = "";
|
|
|
|
|
if (type=="floppy") {
|
|
|
|
|
str_size="512,1,2880,2880";/* All space free */
|
|
|
|
|
mediaid=0xF0; /* Floppy 1.44 media */
|
|
|
|
@ -714,7 +718,7 @@ public:
|
|
|
|
|
FILE *usefile = getFSFile(temp_line.c_str(), &floppysize, &rombytesize);
|
|
|
|
|
if(usefile != NULL) {
|
|
|
|
|
if(diskSwap[i] != NULL) delete diskSwap[i];
|
|
|
|
|
diskSwap[i] = new imageDisk(usefile, (Bit8u *)temp_line.c_str(), floppysize, false);
|
|
|
|
|
diskSwap[i] = new imageDisk(usefile, temp_line.c_str(), floppysize, false);
|
|
|
|
|
if (usefile_1==NULL) {
|
|
|
|
|
usefile_1=usefile;
|
|
|
|
|
rombytesize_1=rombytesize;
|
|
|
|
@ -1225,9 +1229,7 @@ public:
|
|
|
|
|
WriteOut(MSG_Get("PROGRAM_CONFIG_SECURE_DISALLOW"));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
DOS_Drive * newdrive = NULL;
|
|
|
|
|
imageDisk * newImage = NULL;
|
|
|
|
|
Bit32u imagesize;
|
|
|
|
|
|
|
|
|
|
char drive;
|
|
|
|
|
std::string label;
|
|
|
|
|
std::vector<std::string> paths;
|
|
|
|
@ -1239,294 +1241,303 @@ public:
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::string type="hdd";
|
|
|
|
|
std::string fstype="fat";
|
|
|
|
|
std::string type = "hdd";
|
|
|
|
|
std::string fstype = "fat";
|
|
|
|
|
cmd->FindString("-t",type,true);
|
|
|
|
|
cmd->FindString("-fs",fstype,true);
|
|
|
|
|
if(type == "cdrom") type = "iso"; //Tiny hack for people who like to type -t cdrom
|
|
|
|
|
Bit8u mediaid;
|
|
|
|
|
if (type=="floppy" || type=="hdd" || type=="iso") {
|
|
|
|
|
Bit16u sizes[4];
|
|
|
|
|
bool imgsizedetect=false;
|
|
|
|
|
|
|
|
|
|
std::string str_size;
|
|
|
|
|
mediaid=0xF8;
|
|
|
|
|
|
|
|
|
|
if (type=="floppy") {
|
|
|
|
|
mediaid=0xF0;
|
|
|
|
|
} else if (type=="iso") {
|
|
|
|
|
//str_size="2048,1,65535,0"; // ignored, see drive_iso.cpp (AllocationInfo)
|
|
|
|
|
mediaid=0xF8;
|
|
|
|
|
fstype = "iso";
|
|
|
|
|
}
|
|
|
|
|
cmd->FindString("-size",str_size,true);
|
|
|
|
|
if ((type=="hdd") && (str_size.size()==0)) {
|
|
|
|
|
imgsizedetect=true;
|
|
|
|
|
} else {
|
|
|
|
|
char number[21] = { 0 };const char * scan = str_size.c_str();
|
|
|
|
|
Bitu index = 0;Bitu count = 0;
|
|
|
|
|
/* Parse the str_size string */
|
|
|
|
|
while (*scan && index < 20 && count < 4) {
|
|
|
|
|
if (*scan==',') {
|
|
|
|
|
number[index] = 0;
|
|
|
|
|
sizes[count++] = atoi(number);
|
|
|
|
|
index = 0;
|
|
|
|
|
} else number[index++] = *scan;
|
|
|
|
|
scan++;
|
|
|
|
|
}
|
|
|
|
|
if (count < 4) {
|
|
|
|
|
number[index] = 0; //always goes correct as index is max 20 at this point.
|
|
|
|
|
sizes[count] = atoi(number);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(fstype=="fat" || fstype=="iso") {
|
|
|
|
|
// get the drive letter
|
|
|
|
|
if (!cmd->FindCommand(1,temp_line) || (temp_line.size() > 2) || ((temp_line.size()>1) && (temp_line[1]!=':'))) {
|
|
|
|
|
WriteOut_NoParsing(MSG_Get("PROGRAM_IMGMOUNT_SPECIFY_DRIVE"));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
int i_drive = toupper(temp_line[0]);
|
|
|
|
|
if (!isalpha(i_drive) || (i_drive - 'A') >= DOS_DRIVES || (i_drive - 'A') <0) {
|
|
|
|
|
WriteOut_NoParsing(MSG_Get("PROGRAM_IMGMOUNT_SPECIFY_DRIVE"));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
drive = static_cast<char>(i_drive);
|
|
|
|
|
} else if (fstype=="none") {
|
|
|
|
|
cmd->FindCommand(1,temp_line);
|
|
|
|
|
if ((temp_line.size() > 1) || (!isdigit(temp_line[0]))) {
|
|
|
|
|
WriteOut_NoParsing(MSG_Get("PROGRAM_IMGMOUNT_SPECIFY2"));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
drive=temp_line[0];
|
|
|
|
|
if ((drive<'0') || (drive>=(MAX_DISK_IMAGES+'0'))) {
|
|
|
|
|
WriteOut_NoParsing(MSG_Get("PROGRAM_IMGMOUNT_SPECIFY2"));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
WriteOut(MSG_Get("PROGRAM_IMGMOUNT_FORMAT_UNSUPPORTED"),fstype.c_str());
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// find all file parameters, assuming that all option parameters have been removed
|
|
|
|
|
while(cmd->FindCommand((unsigned int)(paths.size() + 2), temp_line) && temp_line.size()) {
|
|
|
|
|
|
|
|
|
|
struct stat test;
|
|
|
|
|
if (stat(temp_line.c_str(),&test)) {
|
|
|
|
|
//See if it works if the ~ are written out
|
|
|
|
|
std::string homedir(temp_line);
|
|
|
|
|
Cross::ResolveHomedir(homedir);
|
|
|
|
|
if(!stat(homedir.c_str(),&test)) {
|
|
|
|
|
temp_line = homedir;
|
|
|
|
|
} else {
|
|
|
|
|
// convert dosbox filename to system filename
|
|
|
|
|
char fullname[CROSS_LEN];
|
|
|
|
|
char tmp[CROSS_LEN];
|
|
|
|
|
safe_strncpy(tmp, temp_line.c_str(), CROSS_LEN);
|
|
|
|
|
|
|
|
|
|
Bit8u dummy;
|
|
|
|
|
if (!DOS_MakeName(tmp, fullname, &dummy) || strncmp(Drives[dummy]->GetInfo(),"local directory",15)) {
|
|
|
|
|
WriteOut(MSG_Get("PROGRAM_IMGMOUNT_NON_LOCAL_DRIVE"));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
localDrive *ldp = dynamic_cast<localDrive*>(Drives[dummy]);
|
|
|
|
|
if (ldp==NULL) {
|
|
|
|
|
WriteOut(MSG_Get("PROGRAM_IMGMOUNT_FILE_NOT_FOUND"));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
ldp->GetSystemFilename(tmp, fullname);
|
|
|
|
|
temp_line = tmp;
|
|
|
|
|
|
|
|
|
|
if (stat(temp_line.c_str(),&test)) {
|
|
|
|
|
WriteOut(MSG_Get("PROGRAM_IMGMOUNT_FILE_NOT_FOUND"));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (S_ISDIR(test.st_mode)) {
|
|
|
|
|
WriteOut(MSG_Get("PROGRAM_IMGMOUNT_MOUNT"));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
paths.push_back(temp_line);
|
|
|
|
|
}
|
|
|
|
|
if (paths.size() == 0) {
|
|
|
|
|
WriteOut(MSG_Get("PROGRAM_IMGMOUNT_SPECIFY_FILE"));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (paths.size() == 1)
|
|
|
|
|
temp_line = paths[0];
|
|
|
|
|
|
|
|
|
|
if(fstype=="fat") {
|
|
|
|
|
if (imgsizedetect) {
|
|
|
|
|
FILE * diskfile = fopen_wrap(temp_line.c_str(), "rb+");
|
|
|
|
|
if (!diskfile) {
|
|
|
|
|
WriteOut(MSG_Get("PROGRAM_IMGMOUNT_INVALID_IMAGE"));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
fseek(diskfile, 0L, SEEK_END);
|
|
|
|
|
Bit32u fcsize = (Bit32u)(ftell(diskfile) / 512L);
|
|
|
|
|
Bit8u buf[512];
|
|
|
|
|
fseek(diskfile, 0L, SEEK_SET);
|
|
|
|
|
if (fread(buf,sizeof(Bit8u),512,diskfile)<512) {
|
|
|
|
|
fclose(diskfile);
|
|
|
|
|
WriteOut(MSG_Get("PROGRAM_IMGMOUNT_INVALID_IMAGE"));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
fclose(diskfile);
|
|
|
|
|
if ((buf[510]!=0x55) || (buf[511]!=0xaa)) {
|
|
|
|
|
WriteOut(MSG_Get("PROGRAM_IMGMOUNT_INVALID_GEOMETRY"));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
Bitu sectors=(Bitu)(fcsize/(16*63));
|
|
|
|
|
if (sectors*16*63!=fcsize) {
|
|
|
|
|
WriteOut(MSG_Get("PROGRAM_IMGMOUNT_INVALID_GEOMETRY"));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
sizes[0]=512; sizes[1]=63; sizes[2]=16; sizes[3]=sectors;
|
|
|
|
|
LOG_MSG("autosized image file: %d:%d:%d:%d",sizes[0],sizes[1],sizes[2],sizes[3]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Drives[drive-'A']) {
|
|
|
|
|
WriteOut(MSG_Get("PROGRAM_IMGMOUNT_ALREADY_MOUNTED"));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::vector<DOS_Drive*> imgDisks;
|
|
|
|
|
std::vector<std::string>::size_type i;
|
|
|
|
|
std::vector<DOS_Drive*>::size_type ct;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < paths.size(); i++) {
|
|
|
|
|
DOS_Drive* newDrive = new fatDrive(paths[i].c_str(),sizes[0],sizes[1],sizes[2],sizes[3],0);
|
|
|
|
|
imgDisks.push_back(newDrive);
|
|
|
|
|
if(!(dynamic_cast<fatDrive*>(newDrive))->created_successfully) {
|
|
|
|
|
WriteOut(MSG_Get("PROGRAM_IMGMOUNT_CANT_CREATE"));
|
|
|
|
|
for(ct = 0; ct < imgDisks.size(); ct++) {
|
|
|
|
|
delete imgDisks[ct];
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Update DriveManager
|
|
|
|
|
for(ct = 0; ct < imgDisks.size(); ct++) {
|
|
|
|
|
DriveManager::AppendDisk(drive - 'A', imgDisks[ct]);
|
|
|
|
|
}
|
|
|
|
|
DriveManager::InitializeDrive(drive - 'A');
|
|
|
|
|
|
|
|
|
|
// Set the correct media byte in the table
|
|
|
|
|
mem_writeb(Real2Phys(dos.tables.mediaid) + (drive - 'A') * 9, mediaid);
|
|
|
|
|
|
|
|
|
|
/* Command uses dta so set it to our internal dta */
|
|
|
|
|
RealPt save_dta = dos.dta();
|
|
|
|
|
dos.dta(dos.tables.tempdta);
|
|
|
|
|
|
|
|
|
|
for(ct = 0; ct < imgDisks.size(); ct++) {
|
|
|
|
|
DriveManager::CycleDisks(drive - 'A', (ct == (imgDisks.size() - 1)));
|
|
|
|
|
|
|
|
|
|
char root[7] = {drive,':','\\','*','.','*',0};
|
|
|
|
|
DOS_FindFirst(root, DOS_ATTR_VOLUME); // force obtaining the label and saving it in dirCache
|
|
|
|
|
}
|
|
|
|
|
dos.dta(save_dta);
|
|
|
|
|
|
|
|
|
|
std::string tmp(paths[0]);
|
|
|
|
|
for (i = 1; i < paths.size(); i++) {
|
|
|
|
|
tmp += "; " + paths[i];
|
|
|
|
|
}
|
|
|
|
|
WriteOut(MSG_Get("PROGRAM_MOUNT_STATUS_2"), drive, tmp.c_str());
|
|
|
|
|
|
|
|
|
|
if (paths.size() == 1) {
|
|
|
|
|
newdrive = imgDisks[0];
|
|
|
|
|
switch (drive - 'A') {
|
|
|
|
|
case 0:
|
|
|
|
|
case 1:
|
|
|
|
|
if(!((fatDrive *)newdrive)->loadedDisk->hardDrive) {
|
|
|
|
|
if(imageDiskList[drive - 'A'] != NULL) delete imageDiskList[drive - 'A'];
|
|
|
|
|
imageDiskList[drive - 'A'] = ((fatDrive *)newdrive)->loadedDisk;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
case 3:
|
|
|
|
|
if(((fatDrive *)newdrive)->loadedDisk->hardDrive) {
|
|
|
|
|
if(imageDiskList[drive - 'A'] != NULL) delete imageDiskList[drive - 'A'];
|
|
|
|
|
imageDiskList[drive - 'A'] = ((fatDrive *)newdrive)->loadedDisk;
|
|
|
|
|
updateDPT();
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else if (fstype=="iso") {
|
|
|
|
|
|
|
|
|
|
if (Drives[drive-'A']) {
|
|
|
|
|
WriteOut(MSG_Get("PROGRAM_IMGMOUNT_ALREADY_MOUNTED"));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
MSCDEX_SetCDInterface(CDROM_USE_SDL, -1);
|
|
|
|
|
// create new drives for all images
|
|
|
|
|
std::vector<DOS_Drive*> isoDisks;
|
|
|
|
|
std::vector<std::string>::size_type i;
|
|
|
|
|
std::vector<DOS_Drive*>::size_type ct;
|
|
|
|
|
for (i = 0; i < paths.size(); i++) {
|
|
|
|
|
int error = -1;
|
|
|
|
|
DOS_Drive* newDrive = new isoDrive(drive, paths[i].c_str(), mediaid, error);
|
|
|
|
|
isoDisks.push_back(newDrive);
|
|
|
|
|
switch (error) {
|
|
|
|
|
case 0 : break;
|
|
|
|
|
case 1 : WriteOut(MSG_Get("MSCDEX_ERROR_MULTIPLE_CDROMS")); break;
|
|
|
|
|
case 2 : WriteOut(MSG_Get("MSCDEX_ERROR_NOT_SUPPORTED")); break;
|
|
|
|
|
case 3 : WriteOut(MSG_Get("MSCDEX_ERROR_OPEN")); break;
|
|
|
|
|
case 4 : WriteOut(MSG_Get("MSCDEX_TOO_MANY_DRIVES")); break;
|
|
|
|
|
case 5 : WriteOut(MSG_Get("MSCDEX_LIMITED_SUPPORT")); break;
|
|
|
|
|
case 6 : WriteOut(MSG_Get("MSCDEX_INVALID_FILEFORMAT")); break;
|
|
|
|
|
default : WriteOut(MSG_Get("MSCDEX_UNKNOWN_ERROR")); break;
|
|
|
|
|
}
|
|
|
|
|
// error: clean up and leave
|
|
|
|
|
if (error) {
|
|
|
|
|
for(ct = 0; ct < isoDisks.size(); ct++) {
|
|
|
|
|
delete isoDisks[ct];
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Update DriveManager
|
|
|
|
|
for(ct = 0; ct < isoDisks.size(); ct++) {
|
|
|
|
|
DriveManager::AppendDisk(drive - 'A', isoDisks[ct]);
|
|
|
|
|
}
|
|
|
|
|
DriveManager::InitializeDrive(drive - 'A');
|
|
|
|
|
|
|
|
|
|
// Set the correct media byte in the table
|
|
|
|
|
mem_writeb(Real2Phys(dos.tables.mediaid) + (drive - 'A') * 9, mediaid);
|
|
|
|
|
|
|
|
|
|
// Print status message (success)
|
|
|
|
|
WriteOut(MSG_Get("MSCDEX_SUCCESS"));
|
|
|
|
|
std::string tmp(paths[0]);
|
|
|
|
|
for (i = 1; i < paths.size(); i++) {
|
|
|
|
|
tmp += "; " + paths[i];
|
|
|
|
|
}
|
|
|
|
|
WriteOut(MSG_Get("PROGRAM_MOUNT_STATUS_2"), drive, tmp.c_str());
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
FILE *newDisk = fopen_wrap(temp_line.c_str(), "rb+");
|
|
|
|
|
if (!newDisk) {
|
|
|
|
|
WriteOut(MSG_Get("PROGRAM_IMGMOUNT_INVALID_IMAGE"));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
fseek(newDisk,0L, SEEK_END);
|
|
|
|
|
imagesize = (ftell(newDisk) / 1024);
|
|
|
|
|
|
|
|
|
|
newImage = new imageDisk(newDisk, (Bit8u *)temp_line.c_str(), imagesize, (imagesize > 2880));
|
|
|
|
|
if(imagesize>2880) newImage->Set_Geometry(sizes[2],sizes[3],sizes[1],sizes[0]);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
//Check type and exit early.
|
|
|
|
|
if (type != "floppy" && type != "hdd" && type != "iso") {
|
|
|
|
|
WriteOut(MSG_Get("PROGRAM_IMGMOUNT_TYPE_UNSUPPORTED"),type.c_str());
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (fstype=="none") {
|
|
|
|
|
if(imageDiskList[drive-'0'] != NULL) delete imageDiskList[drive-'0'];
|
|
|
|
|
imageDiskList[drive-'0'] = newImage;
|
|
|
|
|
Bit16u sizes[4] = {0};
|
|
|
|
|
bool imgsizedetect = false;
|
|
|
|
|
|
|
|
|
|
std::string str_size = "";
|
|
|
|
|
Bit8u mediaid = 0xF8;
|
|
|
|
|
|
|
|
|
|
if (type == "floppy") {
|
|
|
|
|
mediaid = 0xF0;
|
|
|
|
|
} else if (type == "iso") {
|
|
|
|
|
//str_size="2048,1,65535,0"; // ignored, see drive_iso.cpp (AllocationInfo)
|
|
|
|
|
mediaid = 0xF8;
|
|
|
|
|
fstype = "iso";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cmd->FindString("-size",str_size,true);
|
|
|
|
|
if ((type=="hdd") && (str_size.size()==0)) {
|
|
|
|
|
imgsizedetect = true;
|
|
|
|
|
} else {
|
|
|
|
|
char number[21] = { 0 };const char * scan = str_size.c_str();
|
|
|
|
|
Bitu index = 0;Bitu count = 0;
|
|
|
|
|
/* Parse the str_size string */
|
|
|
|
|
while (*scan && index < 20 && count < 4) {
|
|
|
|
|
if (*scan==',') {
|
|
|
|
|
number[index] = 0;
|
|
|
|
|
sizes[count++] = atoi(number);
|
|
|
|
|
index = 0;
|
|
|
|
|
} else number[index++] = *scan;
|
|
|
|
|
scan++;
|
|
|
|
|
}
|
|
|
|
|
if (count < 4) {
|
|
|
|
|
number[index] = 0; //always goes correct as index is max 20 at this point.
|
|
|
|
|
sizes[count] = atoi(number);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(fstype=="fat" || fstype=="iso") {
|
|
|
|
|
// get the drive letter
|
|
|
|
|
if (!cmd->FindCommand(1,temp_line) || (temp_line.size() > 2) || ((temp_line.size()>1) && (temp_line[1]!=':'))) {
|
|
|
|
|
WriteOut_NoParsing(MSG_Get("PROGRAM_IMGMOUNT_SPECIFY_DRIVE"));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
int i_drive = toupper(temp_line[0]);
|
|
|
|
|
if (!isalpha(i_drive) || (i_drive - 'A') >= DOS_DRIVES || (i_drive - 'A') <0) {
|
|
|
|
|
WriteOut_NoParsing(MSG_Get("PROGRAM_IMGMOUNT_SPECIFY_DRIVE"));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
drive = static_cast<char>(i_drive);
|
|
|
|
|
} else if (fstype=="none") {
|
|
|
|
|
cmd->FindCommand(1,temp_line);
|
|
|
|
|
if ((temp_line.size() > 1) || (!isdigit(temp_line[0]))) {
|
|
|
|
|
WriteOut_NoParsing(MSG_Get("PROGRAM_IMGMOUNT_SPECIFY2"));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
drive = temp_line[0];
|
|
|
|
|
if ((drive<'0') || (drive>=(MAX_DISK_IMAGES+'0'))) {
|
|
|
|
|
WriteOut_NoParsing(MSG_Get("PROGRAM_IMGMOUNT_SPECIFY2"));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
WriteOut(MSG_Get("PROGRAM_IMGMOUNT_FORMAT_UNSUPPORTED"),fstype.c_str());
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// find all file parameters, assuming that all option parameters have been removed
|
|
|
|
|
while(cmd->FindCommand((unsigned int)(paths.size() + 2), temp_line) && temp_line.size()) {
|
|
|
|
|
|
|
|
|
|
struct stat test;
|
|
|
|
|
if (stat(temp_line.c_str(),&test)) {
|
|
|
|
|
//See if it works if the ~ are written out
|
|
|
|
|
std::string homedir(temp_line);
|
|
|
|
|
Cross::ResolveHomedir(homedir);
|
|
|
|
|
if(!stat(homedir.c_str(),&test)) {
|
|
|
|
|
temp_line = homedir;
|
|
|
|
|
} else {
|
|
|
|
|
// convert dosbox filename to system filename
|
|
|
|
|
char fullname[CROSS_LEN];
|
|
|
|
|
char tmp[CROSS_LEN];
|
|
|
|
|
safe_strncpy(tmp, temp_line.c_str(), CROSS_LEN);
|
|
|
|
|
|
|
|
|
|
Bit8u dummy;
|
|
|
|
|
if (!DOS_MakeName(tmp, fullname, &dummy) || strncmp(Drives[dummy]->GetInfo(),"local directory",15)) {
|
|
|
|
|
WriteOut(MSG_Get("PROGRAM_IMGMOUNT_NON_LOCAL_DRIVE"));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
localDrive *ldp = dynamic_cast<localDrive*>(Drives[dummy]);
|
|
|
|
|
if (ldp==NULL) {
|
|
|
|
|
WriteOut(MSG_Get("PROGRAM_IMGMOUNT_FILE_NOT_FOUND"));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
ldp->GetSystemFilename(tmp, fullname);
|
|
|
|
|
temp_line = tmp;
|
|
|
|
|
|
|
|
|
|
if (stat(temp_line.c_str(),&test)) {
|
|
|
|
|
WriteOut(MSG_Get("PROGRAM_IMGMOUNT_FILE_NOT_FOUND"));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (S_ISDIR(test.st_mode)) {
|
|
|
|
|
WriteOut(MSG_Get("PROGRAM_IMGMOUNT_MOUNT"));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
paths.push_back(temp_line);
|
|
|
|
|
}
|
|
|
|
|
if (paths.size() == 0) {
|
|
|
|
|
WriteOut(MSG_Get("PROGRAM_IMGMOUNT_SPECIFY_FILE"));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (paths.size() == 1)
|
|
|
|
|
temp_line = paths[0];
|
|
|
|
|
|
|
|
|
|
if(fstype=="fat") {
|
|
|
|
|
if (imgsizedetect) {
|
|
|
|
|
FILE * diskfile = fopen_wrap(temp_line.c_str(), "rb+");
|
|
|
|
|
if (!diskfile) {
|
|
|
|
|
WriteOut(MSG_Get("PROGRAM_IMGMOUNT_INVALID_IMAGE"));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
fseek(diskfile, 0L, SEEK_END);
|
|
|
|
|
Bit32u fcsize = (Bit32u)(ftell(diskfile) / 512L);
|
|
|
|
|
Bit8u buf[512];
|
|
|
|
|
fseek(diskfile, 0L, SEEK_SET);
|
|
|
|
|
if (fread(buf,sizeof(Bit8u),512,diskfile)<512) {
|
|
|
|
|
fclose(diskfile);
|
|
|
|
|
WriteOut(MSG_Get("PROGRAM_IMGMOUNT_INVALID_IMAGE"));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
fclose(diskfile);
|
|
|
|
|
if ((buf[510]!=0x55) || (buf[511]!=0xaa)) {
|
|
|
|
|
WriteOut(MSG_Get("PROGRAM_IMGMOUNT_INVALID_GEOMETRY"));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
Bitu sectors=(Bitu)(fcsize/(16*63));
|
|
|
|
|
if (sectors*16*63!=fcsize) {
|
|
|
|
|
WriteOut(MSG_Get("PROGRAM_IMGMOUNT_INVALID_GEOMETRY"));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
sizes[0]=512; sizes[1]=63; sizes[2]=16; sizes[3]=sectors;
|
|
|
|
|
|
|
|
|
|
LOG_MSG("autosized image file: %d:%d:%d:%d",sizes[0],sizes[1],sizes[2],sizes[3]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Drives[drive-'A']) {
|
|
|
|
|
WriteOut(MSG_Get("PROGRAM_IMGMOUNT_ALREADY_MOUNTED"));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::vector<DOS_Drive*> imgDisks;
|
|
|
|
|
std::vector<std::string>::size_type i;
|
|
|
|
|
std::vector<DOS_Drive*>::size_type ct;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < paths.size(); i++) {
|
|
|
|
|
DOS_Drive* newDrive = new fatDrive(paths[i].c_str(),sizes[0],sizes[1],sizes[2],sizes[3],0);
|
|
|
|
|
imgDisks.push_back(newDrive);
|
|
|
|
|
if(!(dynamic_cast<fatDrive*>(newDrive))->created_successfully) {
|
|
|
|
|
WriteOut(MSG_Get("PROGRAM_IMGMOUNT_CANT_CREATE"));
|
|
|
|
|
for(ct = 0; ct < imgDisks.size(); ct++) {
|
|
|
|
|
delete imgDisks[ct];
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Update DriveManager
|
|
|
|
|
for(ct = 0; ct < imgDisks.size(); ct++) {
|
|
|
|
|
DriveManager::AppendDisk(drive - 'A', imgDisks[ct]);
|
|
|
|
|
}
|
|
|
|
|
DriveManager::InitializeDrive(drive - 'A');
|
|
|
|
|
|
|
|
|
|
// Set the correct media byte in the table
|
|
|
|
|
mem_writeb(Real2Phys(dos.tables.mediaid) + (drive - 'A') * 9, mediaid);
|
|
|
|
|
|
|
|
|
|
/* Command uses dta so set it to our internal dta */
|
|
|
|
|
RealPt save_dta = dos.dta();
|
|
|
|
|
dos.dta(dos.tables.tempdta);
|
|
|
|
|
|
|
|
|
|
for(ct = 0; ct < imgDisks.size(); ct++) {
|
|
|
|
|
DriveManager::CycleDisks(drive - 'A', (ct == (imgDisks.size() - 1)));
|
|
|
|
|
|
|
|
|
|
char root[7] = {drive,':','\\','*','.','*',0};
|
|
|
|
|
DOS_FindFirst(root, DOS_ATTR_VOLUME); // force obtaining the label and saving it in dirCache
|
|
|
|
|
}
|
|
|
|
|
dos.dta(save_dta);
|
|
|
|
|
|
|
|
|
|
std::string tmp(paths[0]);
|
|
|
|
|
for (i = 1; i < paths.size(); i++) {
|
|
|
|
|
tmp += "; " + paths[i];
|
|
|
|
|
}
|
|
|
|
|
WriteOut(MSG_Get("PROGRAM_MOUNT_STATUS_2"), drive, tmp.c_str());
|
|
|
|
|
|
|
|
|
|
if (paths.size() == 1) {
|
|
|
|
|
DOS_Drive * newdrive = imgDisks[0];
|
|
|
|
|
switch (drive - 'A') {
|
|
|
|
|
case 0:
|
|
|
|
|
case 1:
|
|
|
|
|
if(!((fatDrive *)newdrive)->loadedDisk->hardDrive) {
|
|
|
|
|
if(imageDiskList[drive - 'A'] != NULL) delete imageDiskList[drive - 'A'];
|
|
|
|
|
imageDiskList[drive - 'A'] = ((fatDrive *)newdrive)->loadedDisk;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
case 3:
|
|
|
|
|
if(((fatDrive *)newdrive)->loadedDisk->hardDrive) {
|
|
|
|
|
if(imageDiskList[drive - 'A'] != NULL) delete imageDiskList[drive - 'A'];
|
|
|
|
|
imageDiskList[drive - 'A'] = ((fatDrive *)newdrive)->loadedDisk;
|
|
|
|
|
updateDPT();
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else if (fstype=="iso") {
|
|
|
|
|
|
|
|
|
|
if (Drives[drive-'A']) {
|
|
|
|
|
WriteOut(MSG_Get("PROGRAM_IMGMOUNT_ALREADY_MOUNTED"));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MSCDEX_SetCDInterface(CDROM_USE_SDL, -1);
|
|
|
|
|
// create new drives for all images
|
|
|
|
|
std::vector<DOS_Drive*> isoDisks;
|
|
|
|
|
std::vector<std::string>::size_type i;
|
|
|
|
|
std::vector<DOS_Drive*>::size_type ct;
|
|
|
|
|
for (i = 0; i < paths.size(); i++) {
|
|
|
|
|
int error = -1;
|
|
|
|
|
DOS_Drive* newDrive = new isoDrive(drive, paths[i].c_str(), mediaid, error);
|
|
|
|
|
isoDisks.push_back(newDrive);
|
|
|
|
|
switch (error) {
|
|
|
|
|
case 0 : break;
|
|
|
|
|
case 1 : WriteOut(MSG_Get("MSCDEX_ERROR_MULTIPLE_CDROMS")); break;
|
|
|
|
|
case 2 : WriteOut(MSG_Get("MSCDEX_ERROR_NOT_SUPPORTED")); break;
|
|
|
|
|
case 3 : WriteOut(MSG_Get("MSCDEX_ERROR_OPEN")); break;
|
|
|
|
|
case 4 : WriteOut(MSG_Get("MSCDEX_TOO_MANY_DRIVES")); break;
|
|
|
|
|
case 5 : WriteOut(MSG_Get("MSCDEX_LIMITED_SUPPORT")); break;
|
|
|
|
|
case 6 : WriteOut(MSG_Get("MSCDEX_INVALID_FILEFORMAT")); break;
|
|
|
|
|
default : WriteOut(MSG_Get("MSCDEX_UNKNOWN_ERROR")); break;
|
|
|
|
|
}
|
|
|
|
|
// error: clean up and leave
|
|
|
|
|
if (error) {
|
|
|
|
|
for(ct = 0; ct < isoDisks.size(); ct++) {
|
|
|
|
|
delete isoDisks[ct];
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Update DriveManager
|
|
|
|
|
for(ct = 0; ct < isoDisks.size(); ct++) {
|
|
|
|
|
DriveManager::AppendDisk(drive - 'A', isoDisks[ct]);
|
|
|
|
|
}
|
|
|
|
|
DriveManager::InitializeDrive(drive - 'A');
|
|
|
|
|
|
|
|
|
|
// Set the correct media byte in the table
|
|
|
|
|
mem_writeb(Real2Phys(dos.tables.mediaid) + (drive - 'A') * 9, mediaid);
|
|
|
|
|
|
|
|
|
|
// Print status message (success)
|
|
|
|
|
WriteOut(MSG_Get("MSCDEX_SUCCESS"));
|
|
|
|
|
std::string tmp(paths[0]);
|
|
|
|
|
for (i = 1; i < paths.size(); i++) {
|
|
|
|
|
tmp += "; " + paths[i];
|
|
|
|
|
}
|
|
|
|
|
WriteOut(MSG_Get("PROGRAM_MOUNT_STATUS_2"), drive, tmp.c_str());
|
|
|
|
|
|
|
|
|
|
} else if (fstype == "none") {
|
|
|
|
|
FILE *newDisk = fopen_wrap(temp_line.c_str(), "rb+");
|
|
|
|
|
if (!newDisk) {
|
|
|
|
|
WriteOut(MSG_Get("PROGRAM_IMGMOUNT_INVALID_IMAGE"));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
fseek(newDisk,0L, SEEK_END);
|
|
|
|
|
Bit32u imagesize = (ftell(newDisk) / 1024);
|
|
|
|
|
const bool hdd = (imagesize > 2880);
|
|
|
|
|
//Seems to make sense to require a valid geometry..
|
|
|
|
|
if (hdd && sizes[0] == 0 && sizes[1] == 0 && sizes[2] == 0 && sizes[3] == 0) {
|
|
|
|
|
fclose(newDisk);
|
|
|
|
|
WriteOut(MSG_Get("PROGRAM_IMGMOUNT_SPECIFY_GEOMETRY"));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
imageDisk * newImage = new imageDisk(newDisk, temp_line.c_str(), imagesize, hdd);
|
|
|
|
|
|
|
|
|
|
if (hdd) newImage->Set_Geometry(sizes[2],sizes[3],sizes[1],sizes[0]);
|
|
|
|
|
if(imageDiskList[drive - '0'] != NULL) delete imageDiskList[drive - '0'];
|
|
|
|
|
imageDiskList[drive - '0'] = newImage;
|
|
|
|
|
updateDPT();
|
|
|
|
|
WriteOut(MSG_Get("PROGRAM_IMGMOUNT_MOUNT_NUMBER"),drive-'0',temp_line.c_str());
|
|
|
|
|
WriteOut(MSG_Get("PROGRAM_IMGMOUNT_MOUNT_NUMBER"),drive - '0',temp_line.c_str());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// check if volume label is given. be careful for cdrom
|
|
|
|
|