diff --git a/scp.c b/scp.c index a7707e59..4df09f9f 100644 --- a/scp.c +++ b/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 */ diff --git a/sim_fio.c b/sim_fio.c index 258178de..d2223753 100644 --- a/sim_fio.c +++ b/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 int sim_set_fsize (FILE *fptr, t_addr size) { @@ -439,6 +467,54 @@ return ftruncate(fileno(fptr), (off_t)size); #include #include +#if HAVE_UTIME +#include +#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) { diff --git a/sim_fio.h b/sim_fio.h index 32d5ce8a..e372abae 100644 --- a/sim_fio.h +++ b/sim_fio.h @@ -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;