Improve copy so it supports appending of files. Fixes a few installers.
Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@2744
This commit is contained in:
parent
d6037bb2fe
commit
ab0d4104e2
2 changed files with 141 additions and 86 deletions
|
@ -16,7 +16,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* $Id: shell.cpp,v 1.79 2007-01-08 19:59:06 qbix79 Exp $ */
|
||||
/* $Id: shell.cpp,v 1.80 2007-01-10 09:04:33 qbix79 Exp $ */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
@ -424,6 +424,7 @@ void SHELL_Init() {
|
|||
MSG_Add("SHELL_CMD_ECHO_ON","ECHO is on.\n");
|
||||
MSG_Add("SHELL_CMD_ECHO_OFF","ECHO is off.\n");
|
||||
MSG_Add("SHELL_ILLEGAL_SWITCH","Illegal switch: %s.\n");
|
||||
MSG_Add("SHELL_MISSING_PARAMETER","Required parameter missing.\n");
|
||||
MSG_Add("SHELL_CMD_CHDIR_ERROR","Unable to change to: %s.\n");
|
||||
MSG_Add("SHELL_CMD_CHDIR_HINT","To change to different drive type \033[31m%c:\033[0m\n");
|
||||
MSG_Add("SHELL_CMD_MKDIR_ERROR","Unable to make: %s.\n");
|
||||
|
|
|
@ -16,11 +16,12 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* $Id: shell_cmds.cpp,v 1.70 2007-01-08 19:45:42 qbix79 Exp $ */
|
||||
/* $Id: shell_cmds.cpp,v 1.71 2007-01-10 09:04:33 qbix79 Exp $ */
|
||||
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include "shell.h"
|
||||
#include "callback.h"
|
||||
#include "regs.h"
|
||||
|
@ -97,7 +98,7 @@ void DOS_Shell::DoCommand(char * line) {
|
|||
}
|
||||
cmd_index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
*cmd_write++=*line++;
|
||||
}
|
||||
*cmd_write=0;
|
||||
|
@ -454,6 +455,14 @@ void DOS_Shell::CMD_DIR(char * args) {
|
|||
WriteOut(MSG_Get("SHELL_CMD_DIR_BYTES_FREE"),dir_count,numformat);
|
||||
dos.dta(save_dta);
|
||||
}
|
||||
struct copysource {
|
||||
std::string filename;
|
||||
bool concat;
|
||||
copysource(std::string filein,bool concatin):
|
||||
filename(filein),concat(concatin){ };
|
||||
copysource():filename(""),concat(false){ };
|
||||
};
|
||||
|
||||
|
||||
void DOS_Shell::CMD_COPY(char * args) {
|
||||
HELP("COPY");
|
||||
|
@ -465,10 +474,13 @@ void DOS_Shell::CMD_COPY(char * args) {
|
|||
DOS_DTA dta(dos.dta());
|
||||
Bit32u size;Bit16u date;Bit16u time;Bit8u attr;
|
||||
char name[DOS_NAMELENGTH_ASCII];
|
||||
|
||||
std::vector<copysource> sources;
|
||||
// ignore /b and /t switches: always copy binary
|
||||
ScanCMDBool(args,"B");
|
||||
ScanCMDBool(args,"T");
|
||||
while(ScanCMDBool(args,"B")) ;
|
||||
while(ScanCMDBool(args,"T")) ; //Shouldn't this be A ?
|
||||
while(ScanCMDBool(args,"A")) ;
|
||||
ScanCMDBool(args,"Y");
|
||||
ScanCMDBool(args,"-Y");
|
||||
|
||||
char * rem=ScanCMDRemain(args);
|
||||
if (rem) {
|
||||
|
@ -476,95 +488,137 @@ void DOS_Shell::CMD_COPY(char * args) {
|
|||
dos.dta(save_dta);
|
||||
return;
|
||||
}
|
||||
// source/target
|
||||
char* source = StripWord(args);
|
||||
char* target = NULL;
|
||||
if (args && *args) target = StripWord(args);
|
||||
if (!target || !*target) target = defaulttarget;
|
||||
|
||||
// Target and Source have to be there
|
||||
if (!source || !strlen(source)) {
|
||||
WriteOut(MSG_Get("SHELL_CMD_FILE_NOT_FOUND"),args);
|
||||
// Gather all sources (extension to copy more then 1 file specified at commandline)
|
||||
// Concatating files go as follows: All parts except for the last bear the concat flag.
|
||||
// This construction allows them to be counted (only the non concat set)
|
||||
char* source_p = NULL;
|
||||
while ( (source_p = StripWord(args)) && *source_p ) {
|
||||
do {
|
||||
char* plus = strchr(source_p,'+');
|
||||
if(plus) *plus++ = 0;
|
||||
sources.push_back(copysource(source_p,(plus)?true:false));
|
||||
source_p = plus;
|
||||
} while(source_p && *source_p);
|
||||
}
|
||||
// At least one source has to be there
|
||||
if (!sources.size() || !sources[0].filename.size()) {
|
||||
WriteOut(MSG_Get("SHELL_MISSING_PARAMETER"));
|
||||
dos.dta(save_dta);
|
||||
return;
|
||||
return;
|
||||
};
|
||||
|
||||
/* Make a full path in the args */
|
||||
char pathSource[DOS_PATHLENGTH];
|
||||
char pathTarget[DOS_PATHLENGTH];
|
||||
|
||||
if (!DOS_Canonicalize(source,pathSource)) {
|
||||
WriteOut(MSG_Get("SHELL_ILLEGAL_PATH"));
|
||||
dos.dta(save_dta);
|
||||
return;
|
||||
}
|
||||
// cut search pattern
|
||||
char* pos = strrchr(pathSource,'\\');
|
||||
if (pos) *(pos+1) = 0;
|
||||
|
||||
if (!DOS_Canonicalize(target,pathTarget)) {
|
||||
WriteOut(MSG_Get("SHELL_ILLEGAL_PATH"));
|
||||
dos.dta(save_dta);
|
||||
return;
|
||||
}
|
||||
char* temp = strstr(pathTarget,"*.*");
|
||||
if(temp) *temp = 0;//strip off *.* from target
|
||||
|
||||
// add '\\' if target is a directoy
|
||||
if (pathTarget[strlen(pathTarget)-1]!='\\') {
|
||||
if (DOS_FindFirst(pathTarget,0xffff & ~DOS_ATTR_VOLUME)) {
|
||||
dta.GetResult(name,size,date,time,attr);
|
||||
if (attr & DOS_ATTR_DIRECTORY)
|
||||
strcat(pathTarget,"\\");
|
||||
}
|
||||
};
|
||||
|
||||
bool ret=DOS_FindFirst(source,0xffff & ~DOS_ATTR_VOLUME);
|
||||
if (!ret) {
|
||||
WriteOut(MSG_Get("SHELL_CMD_FILE_NOT_FOUND"),source);
|
||||
dos.dta(save_dta);
|
||||
return;
|
||||
copysource target;
|
||||
// If more then one object exists and last target is not part of a
|
||||
// concat sequence then make it the target.
|
||||
if(sources.size()>1 && !sources[sources.size()-2].concat){
|
||||
target = sources.back();
|
||||
sources.pop_back();
|
||||
}
|
||||
//If no target => default target with concat flag true to detect a+b+c
|
||||
if(target.filename.size() == 0) target = copysource(defaulttarget,true);
|
||||
|
||||
copysource oldsource;
|
||||
copysource source;
|
||||
Bit32u count = 0;
|
||||
while(sources.size()) {
|
||||
/* Get next source item and keep track of old source for concat start end */
|
||||
oldsource = source;
|
||||
source = sources[0];
|
||||
sources.erase(sources.begin());
|
||||
|
||||
Bit16u sourceHandle,targetHandle;
|
||||
char nameTarget[DOS_PATHLENGTH];
|
||||
char nameSource[DOS_PATHLENGTH];
|
||||
//Skip first file if doing a+b+c. Set target to first file
|
||||
if(!oldsource.concat && source.concat && target.concat) {
|
||||
target = source;
|
||||
continue;
|
||||
}
|
||||
|
||||
while (ret) {
|
||||
dta.GetResult(name,size,date,time,attr);
|
||||
/* Make a full path in the args */
|
||||
char pathSource[DOS_PATHLENGTH];
|
||||
char pathTarget[DOS_PATHLENGTH];
|
||||
|
||||
if ((attr & DOS_ATTR_DIRECTORY)==0) {
|
||||
strcpy(nameSource,pathSource);
|
||||
strcat(nameSource,name);
|
||||
// Open Source
|
||||
if (DOS_OpenFile(nameSource,0,&sourceHandle)) {
|
||||
// Create Target
|
||||
strcpy(nameTarget,pathTarget);
|
||||
if (nameTarget[strlen(nameTarget)-1]=='\\') strcat(nameTarget,name);
|
||||
|
||||
if (DOS_CreateFile(nameTarget,0,&targetHandle)) {
|
||||
// Copy
|
||||
static Bit8u buffer[0x8000]; // static, otherwise stack overflow possible.
|
||||
bool failed = false;
|
||||
Bit16u toread = 0x8000;
|
||||
do {
|
||||
failed |= DOS_ReadFile(sourceHandle,buffer,&toread);
|
||||
failed |= DOS_WriteFile(targetHandle,buffer,&toread);
|
||||
} while (toread==0x8000);
|
||||
failed |= DOS_CloseFile(sourceHandle);
|
||||
failed |= DOS_CloseFile(targetHandle);
|
||||
WriteOut(" %s\n",name);
|
||||
count++;
|
||||
} else {
|
||||
DOS_CloseFile(sourceHandle);
|
||||
WriteOut(MSG_Get("SHELL_CMD_COPY_FAILURE"),target);
|
||||
}
|
||||
} else WriteOut(MSG_Get("SHELL_CMD_COPY_FAILURE"),source);
|
||||
if (!DOS_Canonicalize(const_cast<char*>(source.filename.c_str()),pathSource)) {
|
||||
WriteOut(MSG_Get("SHELL_ILLEGAL_PATH"));
|
||||
dos.dta(save_dta);
|
||||
return;
|
||||
}
|
||||
// cut search pattern
|
||||
char* pos = strrchr(pathSource,'\\');
|
||||
if (pos) *(pos+1) = 0;
|
||||
|
||||
if (!DOS_Canonicalize(const_cast<char*>(target.filename.c_str()),pathTarget)) {
|
||||
WriteOut(MSG_Get("SHELL_ILLEGAL_PATH"));
|
||||
dos.dta(save_dta);
|
||||
return;
|
||||
}
|
||||
char* temp = strstr(pathTarget,"*.*");
|
||||
if(temp) *temp = 0;//strip off *.* from target
|
||||
|
||||
// add '\\' if target is a directoy
|
||||
if (pathTarget[strlen(pathTarget)-1]!='\\') {
|
||||
if (DOS_FindFirst(pathTarget,0xffff & ~DOS_ATTR_VOLUME)) {
|
||||
dta.GetResult(name,size,date,time,attr);
|
||||
if (attr & DOS_ATTR_DIRECTORY)
|
||||
strcat(pathTarget,"\\");
|
||||
}
|
||||
};
|
||||
ret=DOS_FindNext();
|
||||
};
|
||||
|
||||
//Find first sourcefile
|
||||
bool ret = DOS_FindFirst(const_cast<char*>(source.filename.c_str()),0xffff & ~DOS_ATTR_VOLUME);
|
||||
if (!ret) {
|
||||
WriteOut(MSG_Get("SHELL_CMD_FILE_NOT_FOUND"),const_cast<char*>(source.filename.c_str()));
|
||||
dos.dta(save_dta);
|
||||
return;
|
||||
}
|
||||
|
||||
Bit16u sourceHandle,targetHandle;
|
||||
char nameTarget[DOS_PATHLENGTH];
|
||||
char nameSource[DOS_PATHLENGTH];
|
||||
|
||||
while (ret) {
|
||||
dta.GetResult(name,size,date,time,attr);
|
||||
|
||||
if ((attr & DOS_ATTR_DIRECTORY)==0) {
|
||||
strcpy(nameSource,pathSource);
|
||||
strcat(nameSource,name);
|
||||
// Open Source
|
||||
if (DOS_OpenFile(nameSource,0,&sourceHandle)) {
|
||||
// Create Target or open it if in concat mode
|
||||
strcpy(nameTarget,pathTarget);
|
||||
if (nameTarget[strlen(nameTarget)-1]=='\\') strcat(nameTarget,name);
|
||||
|
||||
//Don't create a newfile when in concat mode
|
||||
if (oldsource.concat || DOS_CreateFile(nameTarget,0,&targetHandle)) {
|
||||
Bit32u dummy=0;
|
||||
//In concat mode. Open the target and seek to the eof
|
||||
if (!oldsource.concat || (DOS_OpenFile(nameTarget,OPEN_READWRITE,&targetHandle) &&
|
||||
DOS_SeekFile(targetHandle,&dummy,DOS_SEEK_END))) {
|
||||
// Copy
|
||||
static Bit8u buffer[0x8000]; // static, otherwise stack overflow possible.
|
||||
bool failed = false;
|
||||
Bit16u toread = 0x8000;
|
||||
do {
|
||||
failed |= DOS_ReadFile(sourceHandle,buffer,&toread);
|
||||
failed |= DOS_WriteFile(targetHandle,buffer,&toread);
|
||||
} while (toread==0x8000);
|
||||
failed |= DOS_CloseFile(sourceHandle);
|
||||
failed |= DOS_CloseFile(targetHandle);
|
||||
WriteOut(" %s\n",name);
|
||||
if(!source.concat) count++; //Only count concat files once
|
||||
} else {
|
||||
DOS_CloseFile(sourceHandle);
|
||||
WriteOut(MSG_Get("SHELL_CMD_COPY_FAILURE"),const_cast<char*>(target.filename.c_str()));
|
||||
}
|
||||
} else {
|
||||
DOS_CloseFile(sourceHandle);
|
||||
WriteOut(MSG_Get("SHELL_CMD_COPY_FAILURE"),const_cast<char*>(target.filename.c_str()));
|
||||
}
|
||||
} else WriteOut(MSG_Get("SHELL_CMD_COPY_FAILURE"),const_cast<char*>(source.filename.c_str()));
|
||||
};
|
||||
//On the next file
|
||||
ret = DOS_FindNext();
|
||||
};
|
||||
}
|
||||
|
||||
WriteOut(MSG_Get("SHELL_CMD_COPY_SUCCESS"),count);
|
||||
dos.dta(save_dta);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue