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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
char sname[CBUFSIZE], dname[CBUFSIZE];
|
||||
FILE *fIn = NULL, *fOut = NULL;
|
||||
t_stat stat = SCPE_OK;
|
||||
char *buf = NULL;
|
||||
size_t bytes;
|
||||
char sname[CBUFSIZE];
|
||||
COPY_CTX copy_state;
|
||||
t_stat stat;
|
||||
|
||||
memset (©_state, 0, sizeof (copy_state));
|
||||
if ((!cptr) || (*cptr == 0))
|
||||
return SCPE_2FARG;
|
||||
cptr = get_glyph_quoted (cptr, sname, 0);
|
||||
if ((!cptr) || (*cptr == 0))
|
||||
return SCPE_2FARG;
|
||||
cptr = get_glyph_quoted (cptr, dname, 0);
|
||||
fIn = sim_fopen (sname, "rb");
|
||||
if (!fIn) {
|
||||
stat = sim_messagef (SCPE_ARG, "Can't open '%s' for input: %s\n", sname, strerror (errno));
|
||||
goto Cleanup_Return;
|
||||
}
|
||||
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;
|
||||
cptr = get_glyph_quoted (cptr, copy_state.destname, 0);
|
||||
stat = sim_dir_scan (sname, sim_copy_entry, ©_state);
|
||||
if ((stat == SCPE_OK) && (copy_state.count))
|
||||
return sim_messagef (SCPE_OK, " %3d file(s) copied\n", copy_state.count);
|
||||
return copy_state.stat;
|
||||
}
|
||||
|
||||
/* 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)
|
||||
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>
|
||||
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 <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)
|
||||
{
|
||||
|
|
|
@ -66,6 +66,7 @@ uint32 sim_fsize_name (const char *fname);
|
|||
t_offset sim_ftell (FILE *st);
|
||||
t_offset sim_fsize_ex (FILE *fptr);
|
||||
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_copy_swapped (void *dptr, const void *bptr, size_t size, size_t count);
|
||||
typedef struct SHMEM SHMEM;
|
||||
|
|
Loading…
Add table
Reference in a new issue