SCP: Make COPY command more robust
This commit is contained in:
parent
64376cad58
commit
7317645dd7
3 changed files with 123 additions and 27 deletions
73
scp.c
73
scp.c
|
@ -5352,41 +5352,60 @@ if (stat == SCPE_OK)
|
||||||
return sim_messagef (SCPE_ARG, "No such file or directory: %s\n", cptr);
|
return sim_messagef (SCPE_ARG, "No such file or directory: %s\n", cptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
t_stat stat;
|
||||||
|
int count;
|
||||||
|
char destname[CBUFSIZE];
|
||||||
|
} COPY_CTX;
|
||||||
|
|
||||||
|
static void sim_copy_entry (const char *directory,
|
||||||
|
const char *filename,
|
||||||
|
t_offset FileSize,
|
||||||
|
const struct stat *filestat,
|
||||||
|
void *context)
|
||||||
|
{
|
||||||
|
COPY_CTX *ctx = (COPY_CTX *)context;
|
||||||
|
struct stat deststat;
|
||||||
|
char FullPath[PATH_MAX + 1];
|
||||||
|
char dname[CBUFSIZE];\
|
||||||
|
t_stat st;
|
||||||
|
|
||||||
|
sim_strlcpy (dname, ctx->destname, sizeof (dname));
|
||||||
|
|
||||||
|
sprintf (FullPath, "%s%s", directory, filename);
|
||||||
|
|
||||||
|
if ((dname[strlen (dname) - 1] == '/') || (dname[strlen (dname) - 1] == '\\'))
|
||||||
|
dname[strlen (dname) - 1] = '\0';
|
||||||
|
if ((!stat (dname, &deststat)) && (deststat.st_mode & S_IFDIR)) {
|
||||||
|
char *dslash = (strrchr (dname, '/') ? "/" : (strrchr (dname, '\\') ? "\\" : "/"));
|
||||||
|
|
||||||
|
dname[sizeof (dname) - 1] = '\0';
|
||||||
|
snprintf (&dname[strlen (dname)], sizeof (dname) - strlen (dname), "%s%s", dslash, filename);
|
||||||
|
}
|
||||||
|
st = sim_copyfile (FullPath, dname, TRUE);
|
||||||
|
if (SCPE_OK == st)
|
||||||
|
++ctx->count;
|
||||||
|
else
|
||||||
|
ctx->stat = st;
|
||||||
|
}
|
||||||
|
|
||||||
t_stat copy_cmd (int32 flg, CONST char *cptr)
|
t_stat copy_cmd (int32 flg, CONST char *cptr)
|
||||||
{
|
{
|
||||||
char sname[CBUFSIZE], dname[CBUFSIZE];
|
char sname[CBUFSIZE];
|
||||||
FILE *fIn = NULL, *fOut = NULL;
|
COPY_CTX copy_state;
|
||||||
t_stat stat = SCPE_OK;
|
t_stat stat;
|
||||||
char *buf = NULL;
|
|
||||||
size_t bytes;
|
|
||||||
|
|
||||||
|
memset (©_state, 0, sizeof (copy_state));
|
||||||
if ((!cptr) || (*cptr == 0))
|
if ((!cptr) || (*cptr == 0))
|
||||||
return SCPE_2FARG;
|
return SCPE_2FARG;
|
||||||
cptr = get_glyph_quoted (cptr, sname, 0);
|
cptr = get_glyph_quoted (cptr, sname, 0);
|
||||||
if ((!cptr) || (*cptr == 0))
|
if ((!cptr) || (*cptr == 0))
|
||||||
return SCPE_2FARG;
|
return SCPE_2FARG;
|
||||||
cptr = get_glyph_quoted (cptr, dname, 0);
|
cptr = get_glyph_quoted (cptr, copy_state.destname, 0);
|
||||||
fIn = sim_fopen (sname, "rb");
|
stat = sim_dir_scan (sname, sim_copy_entry, ©_state);
|
||||||
if (!fIn) {
|
if ((stat == SCPE_OK) && (copy_state.count))
|
||||||
stat = sim_messagef (SCPE_ARG, "Can't open '%s' for input: %s\n", sname, strerror (errno));
|
return sim_messagef (SCPE_OK, " %3d file(s) copied\n", copy_state.count);
|
||||||
goto Cleanup_Return;
|
return copy_state.stat;
|
||||||
}
|
|
||||||
fOut = sim_fopen (dname, "wb");
|
|
||||||
if (!fOut) {
|
|
||||||
stat = sim_messagef (SCPE_ARG, "Can't open '%s' for output: %s\n", dname, strerror (errno));
|
|
||||||
goto Cleanup_Return;
|
|
||||||
}
|
|
||||||
buf = malloc (BUFSIZ);
|
|
||||||
while (bytes = fread (buf, 1, BUFSIZ, fIn))
|
|
||||||
fwrite (buf, 1, bytes, fOut);
|
|
||||||
stat = sim_messagef (SCPE_OK, " 1 file copied\n");
|
|
||||||
Cleanup_Return:
|
|
||||||
free (buf);
|
|
||||||
if (fIn)
|
|
||||||
fclose (fIn);
|
|
||||||
if (fOut)
|
|
||||||
fclose (fOut);
|
|
||||||
return stat;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Breakpoint commands */
|
/* Breakpoint commands */
|
||||||
|
|
76
sim_fio.c
76
sim_fio.c
|
@ -375,6 +375,34 @@ return sim_fseeko (st, (t_offset)offset, whence);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
|
static const char *
|
||||||
|
GetErrorText(DWORD dwError)
|
||||||
|
{
|
||||||
|
static char szMsgBuffer[2048];
|
||||||
|
DWORD dwStatus;
|
||||||
|
|
||||||
|
dwStatus = FormatMessageA (FORMAT_MESSAGE_FROM_SYSTEM|
|
||||||
|
FORMAT_MESSAGE_IGNORE_INSERTS, // __in DWORD dwFlags,
|
||||||
|
NULL, // __in_opt LPCVOID lpSource,
|
||||||
|
dwError, // __in DWORD dwMessageId,
|
||||||
|
0, // __in DWORD dwLanguageId,
|
||||||
|
szMsgBuffer, // __out LPTSTR lpBuffer,
|
||||||
|
sizeof (szMsgBuffer) -1, // __in DWORD nSize,
|
||||||
|
NULL); // __in_opt va_list *Arguments
|
||||||
|
if (0 == dwStatus)
|
||||||
|
snprintf(szMsgBuffer, sizeof(szMsgBuffer) - 1, "Error Code: %d", dwError);
|
||||||
|
while (sim_isspace (szMsgBuffer[strlen (szMsgBuffer)-1]))
|
||||||
|
szMsgBuffer[strlen (szMsgBuffer) - 1] = '\0';
|
||||||
|
return szMsgBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat sim_copyfile (const char *source_file, const char *dest_file, t_bool overwrite_existing)
|
||||||
|
{
|
||||||
|
if (CopyFileA (source_file, dest_file, !overwrite_existing))
|
||||||
|
return SCPE_OK;
|
||||||
|
return sim_messagef (SCPE_ARG, "Error Copying '%s' to '%s': %s\n", source_file, dest_file, GetErrorText (GetLastError ()));
|
||||||
|
}
|
||||||
|
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
int sim_set_fsize (FILE *fptr, t_addr size)
|
int sim_set_fsize (FILE *fptr, t_addr size)
|
||||||
{
|
{
|
||||||
|
@ -439,6 +467,54 @@ return ftruncate(fileno(fptr), (off_t)size);
|
||||||
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#if HAVE_UTIME
|
||||||
|
#include <utime.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
t_stat sim_copyfile (const char *source_file, const char *dest_file, t_bool overwrite_existing)
|
||||||
|
{
|
||||||
|
FILE *fIn = NULL, *fOut = NULL;
|
||||||
|
t_stat st = SCPE_OK;
|
||||||
|
char *buf = NULL;
|
||||||
|
size_t bytes;
|
||||||
|
|
||||||
|
fIn = sim_fopen (source_file, "rb");
|
||||||
|
if (!fIn) {
|
||||||
|
st = sim_messagef (SCPE_ARG, "Can't open '%s' for input: %s\n", source_file, strerror (errno));
|
||||||
|
goto Cleanup_Return;
|
||||||
|
}
|
||||||
|
fOut = sim_fopen (dest_file, "wb");
|
||||||
|
if (!fOut) {
|
||||||
|
st = sim_messagef (SCPE_ARG, "Can't open '%s' for output: %s\n", dest_file, strerror (errno));
|
||||||
|
goto Cleanup_Return;
|
||||||
|
}
|
||||||
|
buf = malloc (BUFSIZ);
|
||||||
|
while ((bytes = fread (buf, 1, BUFSIZ, fIn)))
|
||||||
|
fwrite (buf, 1, bytes, fOut);
|
||||||
|
Cleanup_Return:
|
||||||
|
free (buf);
|
||||||
|
if (fIn)
|
||||||
|
fclose (fIn);
|
||||||
|
if (fOut)
|
||||||
|
fclose (fOut);
|
||||||
|
#if defined(HAVE_UTIME)
|
||||||
|
if (st == SCPE_OK) {
|
||||||
|
struct stat statb;
|
||||||
|
|
||||||
|
if (!stat (source_file, &statb)) {
|
||||||
|
struct utimbuf utim;
|
||||||
|
|
||||||
|
utim.actime = statb.st_atime;
|
||||||
|
utim.modtime = statb.st_mtime;
|
||||||
|
if (utime (dest_file, &utim))
|
||||||
|
st = SCPE_IOERR;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
st = SCPE_IOERR;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return st;
|
||||||
|
}
|
||||||
|
|
||||||
int sim_set_fifo_nonblock (FILE *fptr)
|
int sim_set_fifo_nonblock (FILE *fptr)
|
||||||
{
|
{
|
||||||
|
|
|
@ -66,6 +66,7 @@ uint32 sim_fsize_name (const char *fname);
|
||||||
t_offset sim_ftell (FILE *st);
|
t_offset sim_ftell (FILE *st);
|
||||||
t_offset sim_fsize_ex (FILE *fptr);
|
t_offset sim_fsize_ex (FILE *fptr);
|
||||||
t_offset sim_fsize_name_ex (const char *fname);
|
t_offset sim_fsize_name_ex (const char *fname);
|
||||||
|
t_stat sim_copyfile (const char *source_file, const char *dest_file, t_bool overwrite_existing);
|
||||||
void sim_buf_swap_data (void *bptr, size_t size, size_t count);
|
void sim_buf_swap_data (void *bptr, size_t size, size_t count);
|
||||||
void sim_buf_copy_swapped (void *dptr, const void *bptr, size_t size, size_t count);
|
void sim_buf_copy_swapped (void *dptr, const void *bptr, size_t size, size_t count);
|
||||||
typedef struct SHMEM SHMEM;
|
typedef struct SHMEM SHMEM;
|
||||||
|
|
Loading…
Add table
Reference in a new issue