1
0
mirror of https://github.com/rcornwell/sims.git synced 2026-01-11 23:52:48 +00:00

SCP: Updated to current.

This commit is contained in:
Richard Cornwell 2020-04-04 21:12:28 -04:00
parent 554fab9268
commit 9a63bc521e
6 changed files with 505 additions and 202 deletions

104
scp.c
View File

@ -754,57 +754,58 @@ const struct scp_error {
const char *code;
const char *message;
} scp_errors[1+SCPE_MAX_ERR-SCPE_BASE] =
{{"NXM", "Address space exceeded"},
{"UNATT", "Unit not attached"},
{"IOERR", "I/O error"},
{"CSUM", "Checksum error"},
{"FMT", "Format error"},
{"NOATT", "Unit not attachable"},
{"OPENERR", "File open error"},
{"MEM", "Memory exhausted"},
{"ARG", "Invalid argument"},
{"STEP", "Step expired"},
{"UNK", "Unknown command"},
{"RO", "Read only argument"},
{"INCOMP", "Command not completed"},
{"STOP", "Simulation stopped"},
{"EXIT", "Goodbye"},
{"TTIERR", "Console input I/O error"},
{"TTOERR", "Console output I/O error"},
{"EOF", "End of file"},
{"REL", "Relocation error"},
{"NOPARAM", "No settable parameters"},
{"ALATT", "Unit already attached"},
{"TIMER", "Hardware timer error"},
{"SIGERR", "Signal handler setup error"},
{"TTYERR", "Console terminal setup error"},
{"SUB", "Subscript out of range"},
{"NOFNC", "Command not allowed"},
{"UDIS", "Unit disabled"},
{"NORO", "Read only operation not allowed"},
{"INVSW", "Invalid switch"},
{"MISVAL", "Missing value"},
{"2FARG", "Too few arguments"},
{"2MARG", "Too many arguments"},
{"NXDEV", "Non-existent device"},
{"NXUN", "Non-existent unit"},
{"NXREG", "Non-existent register"},
{"NXPAR", "Non-existent parameter"},
{"NEST", "Nested DO command limit exceeded"},
{"IERR", "Internal error"},
{"MTRLNT", "Invalid magtape record length"},
{"LOST", "Console Telnet connection lost"},
{"TTMO", "Console Telnet connection timed out"},
{"STALL", "Console Telnet output stall"},
{"AFAIL", "Assertion failed"},
{"INVREM", "Invalid remote console command"},
{"EXPECT", "Expect matched"},
{"AMBREG", "Ambiguous register name"},
{"REMOTE", "remote console command"},
{"INVEXPR", "invalid expression"},
{"SIGTERM", "SIGTERM received"},
{"FSSIZE", "File System size larger than disk size"},
{"RUNTIME", "Run time limit exhausted"},
{{"NXM", "Address space exceeded"},
{"UNATT", "Unit not attached"},
{"IOERR", "I/O error"},
{"CSUM", "Checksum error"},
{"FMT", "Format error"},
{"NOATT", "Unit not attachable"},
{"OPENERR", "File open error"},
{"MEM", "Memory exhausted"},
{"ARG", "Invalid argument"},
{"STEP", "Step expired"},
{"UNK", "Unknown command"},
{"RO", "Read only argument"},
{"INCOMP", "Command not completed"},
{"STOP", "Simulation stopped"},
{"EXIT", "Goodbye"},
{"TTIERR", "Console input I/O error"},
{"TTOERR", "Console output I/O error"},
{"EOF", "End of file"},
{"REL", "Relocation error"},
{"NOPARAM", "No settable parameters"},
{"ALATT", "Unit already attached"},
{"TIMER", "Hardware timer error"},
{"SIGERR", "Signal handler setup error"},
{"TTYERR", "Console terminal setup error"},
{"SUB", "Subscript out of range"},
{"NOFNC", "Command not allowed"},
{"UDIS", "Unit disabled"},
{"NORO", "Read only operation not allowed"},
{"INVSW", "Invalid switch"},
{"MISVAL", "Missing value"},
{"2FARG", "Too few arguments"},
{"2MARG", "Too many arguments"},
{"NXDEV", "Non-existent device"},
{"NXUN", "Non-existent unit"},
{"NXREG", "Non-existent register"},
{"NXPAR", "Non-existent parameter"},
{"NEST", "Nested DO command limit exceeded"},
{"IERR", "Internal error"},
{"MTRLNT", "Invalid magtape record length"},
{"LOST", "Console Telnet connection lost"},
{"TTMO", "Console Telnet connection timed out"},
{"STALL", "Console Telnet output stall"},
{"AFAIL", "Assertion failed"},
{"INVREM", "Invalid remote console command"},
{"EXPECT", "Expect matched"},
{"AMBREG", "Ambiguous register name"},
{"REMOTE", "remote console command"},
{"INVEXPR", "invalid expression"},
{"SIGTERM", "SIGTERM received"},
{"FSSIZE", "File System size larger than disk size"},
{"RUNTIME", "Run time limit exhausted"},
{"INCOMPVHD", "Incompatible VHD Container"},
};
const size_t size_map[] = { sizeof (int8),
@ -6089,7 +6090,6 @@ if (flag) {
fprintf (st, "\n Time taken by msleep(1): %dms", os_ms_sleep_1);
if (eth_version ())
fprintf (st, "\n Ethernet packet info: %s", eth_version());
fprintf (st, "\n Time taken by msleep(1): %dms", os_ms_sleep_1);
#if defined(__VMS)
if (1) {
char *arch =

View File

@ -433,8 +433,9 @@ typedef uint32 t_addr;
#define SCPE_SIGTERM (SCPE_BASE + 48) /* SIGTERM has been received */
#define SCPE_FSSIZE (SCPE_BASE + 49) /* File System size larger than disk size */
#define SCPE_RUNTIME (SCPE_BASE + 50) /* Run Time Limit Exhausted */
#define SCPE_INCOMPVHD (SCPE_BASE + 51) /* Incompatible VHD Container */
#define SCPE_MAX_ERR (SCPE_BASE + 50) /* Maximum SCPE Error Value */
#define SCPE_MAX_ERR (SCPE_BASE + 51) /* Maximum SCPE Error Value */
#define SCPE_KFLAG 0x10000000 /* tti data flag */
#define SCPE_BREAK 0x20000000 /* tti break flag */
#define SCPE_NOMESSAGE 0x40000000 /* message display supression flag */
@ -675,9 +676,9 @@ struct UNIT {
#define UNIT_V_DF_TAPE 10 /* Bit offset for Tape Density reservation */
#define UNIT_S_DF_TAPE 3 /* Bits Reserved for Tape Density */
#define UNIT_V_TAPE_FMT 13 /* Bit offset for Tape Format */
#define UNIT_S_TAPE_FMT 3 /* Bits Reserved for Tape Format */
#define UNIT_S_TAPE_FMT 4 /* Bits Reserved for Tape Format */
#define UNIT_M_TAPE_FMT (((1 << UNIT_S_TAPE_FMT) - 1) << UNIT_V_TAPE_FMT)
#define UNIT_V_TAPE_ANSI 16 /* Bit offset for ANSI Tape Type */
#define UNIT_V_TAPE_ANSI 17 /* Bit offset for ANSI Tape Type */
#define UNIT_S_TAPE_ANSI 4 /* Bits Reserved for ANSI Tape Type */
#define UNIT_M_TAPE_ANSI (((1 << UNIT_S_TAPE_ANSI) - 1) << UNIT_V_TAPE_ANSI)

View File

@ -53,14 +53,6 @@ Public routines:
sim_disk_data_trace debug support
sim_disk_test unit test routine
Guest-specific routines for PDP-10 which uses 1024 byte sectors and
requires mapping functions to allow access to the underlying 512 byte
sectors provided by the sim_disk routines
sim_disk_pdp10_attach attach disk unit
sim_disk_pdp10_rdsect read PDP-10 disk sectors
sim_disk_pdp10_wrsect write PDP-10 disk sectors
Internal routines:
sim_os_disk_open_raw platform specific open raw device
@ -282,8 +274,8 @@ static t_offset sim_vhd_disk_size (FILE *f);
static t_stat sim_vhd_disk_rdsect (UNIT *uptr, t_lba lba, uint8 *buf, t_seccnt *sectsread, t_seccnt sects);
static t_stat sim_vhd_disk_wrsect (UNIT *uptr, t_lba lba, uint8 *buf, t_seccnt *sectswritten, t_seccnt sects);
static t_stat sim_vhd_disk_clearerr (UNIT *uptr);
static t_stat sim_vhd_disk_set_dtype (FILE *f, const char *dtype);
static const char *sim_vhd_disk_get_dtype (FILE *f);
static t_stat sim_vhd_disk_set_dtype (FILE *f, const char *dtype, uint32 SectorSize, uint32 xfer_element_size);
static const char *sim_vhd_disk_get_dtype (FILE *f, uint32 *SectorSize, uint32 *xfer_element_size);
static t_stat sim_os_disk_implemented_raw (void);
static FILE *sim_os_disk_open_raw (const char *rawdevicename, const char *openmode);
static int sim_os_disk_close_raw (FILE *f);
@ -306,11 +298,11 @@ struct sim_disk_fmt {
};
static struct sim_disk_fmt fmts[] = {
{ "AUTO", 0, DKUF_F_AUTO, NULL},
{ "SIMH", 0, DKUF_F_STD, NULL},
{ "RAW", 0, DKUF_F_RAW, sim_os_disk_implemented_raw},
{ "VHD", 0, DKUF_F_VHD, sim_vhd_disk_implemented},
{ NULL, 0, 0, NULL}
{ "AUTO detect", 0, DKUF_F_AUTO, NULL},
{ "SIMH", 0, DKUF_F_STD, NULL},
{ "RAW", 0, DKUF_F_RAW, sim_os_disk_implemented_raw},
{ "VHD", 0, DKUF_F_VHD, sim_vhd_disk_implemented},
{ NULL, 0, 0, NULL}
};
/* Set disk format */
@ -321,10 +313,10 @@ uint32 f;
if (uptr == NULL)
return SCPE_IERR;
if (cptr == NULL)
if ((cptr == NULL) || (*cptr == '\0'))
return SCPE_ARG;
for (f = 0; fmts[f].name; f++) {
if (fmts[f].name && (strcmp (cptr, fmts[f].name) == 0)) {
if (fmts[f].name && (MATCH_CMD (cptr, fmts[f].name) == 0)) {
if ((fmts[f].impl_fnc) && (fmts[f].impl_fnc() != SCPE_OK))
return SCPE_NOFNC;
uptr->flags = (uptr->flags & ~DKUF_FMT) |
@ -2031,13 +2023,13 @@ for (i = 0; checks[i] != NULL; i++) {
return ret_val;
}
t_stat sim_disk_attach (UNIT *uptr, const char *cptr, size_t sector_size, size_t xfer_element_size, t_bool dontautosize,
t_stat sim_disk_attach (UNIT *uptr, const char *cptr, size_t sector_size, size_t xfer_element_size, t_bool dontchangecapac,
uint32 dbit, const char *dtype, uint32 pdp11tracksize, int completion_delay)
{
return sim_disk_attach_ex (uptr, cptr, sector_size, xfer_element_size, dontautosize, dbit, dtype, pdp11tracksize, completion_delay, NULL);
return sim_disk_attach_ex (uptr, cptr, sector_size, xfer_element_size, dontchangecapac, dbit, dtype, pdp11tracksize, completion_delay, NULL);
}
t_stat sim_disk_attach_ex (UNIT *uptr, const char *cptr, size_t sector_size, size_t xfer_element_size, t_bool dontautosize,
t_stat sim_disk_attach_ex (UNIT *uptr, const char *cptr, size_t sector_size, size_t xfer_element_size, t_bool dontchangecapac,
uint32 dbit, const char *dtype, uint32 pdp11tracksize, int completion_delay, const char **drivetypes)
{
struct disk_context *ctx;
@ -2079,7 +2071,7 @@ if (sim_switches & SWMASK ('D')) { /* create difference dis
vhd = sim_vhd_disk_create_diff (gbuf, cptr);
if (vhd) {
sim_vhd_disk_close (vhd);
return sim_disk_attach (uptr, gbuf, sector_size, xfer_element_size, dontautosize, dbit, dtype, pdp11tracksize, completion_delay);
return sim_disk_attach (uptr, gbuf, sector_size, xfer_element_size, dontchangecapac, dbit, dtype, pdp11tracksize, completion_delay);
}
return sim_messagef (SCPE_ARG, "Unable to create differencing VHD: %s\n", gbuf);
}
@ -2098,7 +2090,7 @@ if (sim_switches & SWMASK ('C')) { /* create vhd disk & cop
sim_switches |= SWMASK ('R') | SWMASK ('E');
sim_quiet = TRUE;
/* First open the source of the copy operation */
r = sim_disk_attach (uptr, cptr, sector_size, xfer_element_size, dontautosize, dbit, dtype, pdp11tracksize, completion_delay);
r = sim_disk_attach (uptr, cptr, sector_size, xfer_element_size, dontchangecapac, dbit, dtype, pdp11tracksize, completion_delay);
sim_quiet = saved_sim_quiet;
if (r != SCPE_OK) {
sim_switches = saved_sim_switches;
@ -2228,7 +2220,7 @@ else
t_stat r;
sim_vhd_disk_close (vhd);
r = sim_disk_attach (uptr, Parent, sector_size, xfer_element_size, dontautosize, dbit, dtype, pdp11tracksize, completion_delay);
r = sim_disk_attach (uptr, Parent, sector_size, xfer_element_size, dontchangecapac, dbit, dtype, pdp11tracksize, completion_delay);
free (Parent);
return r;
}
@ -2328,13 +2320,27 @@ else { /* normal */
} /* end if null */
} /* end else */
if (DK_GET_FMT (uptr) == DKUF_F_VHD) {
if ((created) && dtype)
sim_vhd_disk_set_dtype (uptr->fileref, dtype);
if (dtype && strcmp (dtype, sim_vhd_disk_get_dtype (uptr->fileref))) {
char cmd[32];
uint32 sector_size, xfer_element_size;
sprintf (cmd, "%s%d %s", dptr->name, (int)(uptr-dptr->units), sim_vhd_disk_get_dtype (uptr->fileref));
set_cmd (0, cmd);
if ((created) && dtype)
sim_vhd_disk_set_dtype (uptr->fileref, dtype, ctx->sector_size, ctx->xfer_element_size);
if (dtype && strcmp (dtype, sim_vhd_disk_get_dtype (uptr->fileref, &sector_size, &xfer_element_size))) {
char cmd[32];
t_stat r = SCPE_OK;
if (((sector_size == 0) || (sector_size == ctx->sector_size)) &&
((xfer_element_size == 0) || (xfer_element_size == ctx->xfer_element_size))) {
sprintf (cmd, "%s%d %s", dptr->name, (int)(uptr-dptr->units), sim_vhd_disk_get_dtype (uptr->fileref, NULL, NULL));
r = set_cmd (0, cmd);
if (r != SCPE_OK)
r = sim_messagef (r, "Can't set %s%d to drive type %s\n", dptr->name, (int)(uptr-dptr->units), sim_vhd_disk_get_dtype (uptr->fileref, NULL, NULL));
}
else
r = sim_messagef (SCPE_INCOMPVHD, "VHD incompatible with %s simulator\n", sim_name);
if (r != SCPE_OK) {
sim_disk_detach (uptr); /* report error now */
return r;
}
}
}
uptr->flags = uptr->flags | UNIT_ATT;
@ -2468,9 +2474,11 @@ filesystem_size = get_filesystem_size (uptr);
container_size = size_function (uptr->fileref);
current_unit_size = ((t_offset)uptr->capac)*ctx->capac_factor*((dptr->flags & DEV_SECTORS) ? 512 : 1);
if (container_size && (container_size != (t_offset)-1)) {
if (dontautosize) {
if (dontchangecapac) {
t_addr saved_capac = uptr->capac;
if (filesystem_size == (t_offset)-1) /* No file system found? */
filesystem_size = container_size; /* Assume full container */
if (filesystem_size != (t_offset)-1) {
const char *drive_type = NULL;
@ -2600,16 +2608,53 @@ return SCPE_OK;
t_stat sim_disk_attach_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr)
{
static struct example_fields {
const char *dname;
const char *dtype;
const char *dsize;
const char *dtype2;
const char *dsize2;
const char *dtype3;
const char *dsize3;
const char *dtype4;
const char *dsize4;
} ex_data[] = {
{"RQ", "RD54", "159MB", "RX50", "409KB", "RA81", "456MB", "RA92", "1505MB"},
{"RP", "RM03", "33MW", "RM03", "33MW", "RP07", "258MW", "RM03", "15MW"},
{"RP", "RM03", "39MW", "RM03", "39MW", "RP07", "110MW", "RM03", "15MW"},
};
struct example_fields *ex = &ex_data[0];
if (strcmp (dptr->name, "RP") == 0)
ex = &ex_data[1];
if (strstr (sim_name, "-10")) {
ex = &ex_data[2];
if (strstr (sim_name, "PDP") == NULL)
ex->dname = "RPA";
}
fprintf (st, "%s Disk Attach Help\n\n", dptr->name);
fprintf (st, "Disk container files can be one of 3 different types:\n\n");
fprintf (st, " SIMH A disk is an unstructured binary file of the size appropriate\n");
fprintf (st, " for the disk drive being simulated\n");
fprintf (st, " VHD Virtual Disk format which is described in the \"Microsoft\n");
fprintf (st, " Virtual Hard Disk (VHD) Image Format Specification\". The\n");
fprintf (st, " VHD implementation includes support for 1) Fixed (Preallocated)\n");
fprintf (st, " disks, 2) Dynamically Expanding disks, and 3) Differencing disks.\n");
fprintf (st, " RAW platform specific access to physical disk or CDROM drives\n\n");
fprintf (st, "Disk container files can be one of several different types:\n\n");
if (strstr (sim_name, "-10") == NULL) {
fprintf (st, " SIMH A disk is an unstructured binary file of the size appropriate\n");
fprintf (st, " for the disk drive being simulated accessed by C runtime APIs\n");
fprintf (st, " VHD Virtual Disk format which is described in the \"Microsoft\n");
fprintf (st, " Virtual Hard Disk (VHD) Image Format Specification\". The\n");
fprintf (st, " VHD implementation includes support for 1) Fixed (Preallocated)\n");
fprintf (st, " disks, 2) Dynamically Expanding disks, and 3) Differencing disks.\n");
fprintf (st, " RAW platform specific access to physical disk or CDROM drives\n\n");
}
else {
fprintf (st, " SIMH A disk is an unstructured binary file of 64bit integers\n"
" access by C runtime APIs\n");
fprintf (st, " VHD A disk is an unstructured binary file of 64bit integers\n"
" contained in a VHD container\n");
fprintf (st, " RAW A disk is an unstructured binary file of 64bit integers\n"
" accessed by direct read/write APIs\n");
fprintf (st, " DBD9 Compatible with KLH10 is a packed big endian word\n");
fprintf (st, " DLD9 Compatible with KLH10 is a packed little endian word\n\n");
}
fprintf (st, "Virtual (VHD) Disks supported conform to \"Virtual Hard Disk Image Format\n");
fprintf (st, "Specification\", Version 1.0 October 11, 2006.\n");
fprintf (st, "Dynamically expanding disks never change their \"Virtual Size\", but they don't\n");
@ -2676,54 +2721,62 @@ fprintf (st, " -M Merge a Differencing VHD into its parent VHD disk\
fprintf (st, " -O Override consistency checks when attaching differencing disks\n");
fprintf (st, " which have unexpected parent disk GUID or timestamps\n\n");
fprintf (st, " -U Fix inconsistencies which are overridden by the -O switch\n");
fprintf (st, " -Y Answer Yes to prompt to overwrite last track (on disk create)\n");
fprintf (st, " -N Answer No to prompt to overwrite last track (on disk create)\n");
if (strstr (sim_name, "-10") == NULL) {
fprintf (st, " -Y Answer Yes to prompt to overwrite last track (on disk create)\n");
fprintf (st, " -N Answer No to prompt to overwrite last track (on disk create)\n");
}
fprintf (st, "Examples:\n");
fprintf (st, " sim> show rq\n");
fprintf (st, " RQ, address=20001468-2000146B*, no vector, 4 units\n");
fprintf (st, " RQ0, 159MB, not attached, write enabled, RD54, autosize, SIMH format\n");
fprintf (st, " RQ1, 159MB, not attached, write enabled, RD54, autosize, SIMH format\n");
fprintf (st, " RQ2, 159MB, not attached, write enabled, RD54, autosize, SIMH format\n");
fprintf (st, " RQ3, 409KB, not attached, write enabled, RX50, autosize, SIMH format\n");
fprintf (st, " sim> atta rq0 RA81.vhd\n");
fprintf (st, " sim> show rq0\n");
fprintf (st, " RQ0, 456MB, attached to RA81.vhd, write enabled, RA81, autosize, VHD format\n");
fprintf (st, " sim> set rq2 ra92\n");
fprintf (st, " sim> att rq2 -f vhd RA92.vhd\n");
fprintf (st, " RQ2: creating new file\n");
fprintf (st, " sim> sho rq2\n");
fprintf (st, " RQ2, 1505MB, attached to RA92.vhd, write enabled, RA92, autosize, VHD format\n");
fprintf (st, " sim> dir RA92.vhd\n");
fprintf (st, " sim> show %s\n", ex->dname);
fprintf (st, " %s, address=20001468-2000146B*, no vector, 4 units\n", ex->dname);
fprintf (st, " %s0, %s, not attached, write enabled, %s, autosize, AUTO detect format\n", ex->dname, ex->dsize, ex->dtype);
fprintf (st, " %s1, %s, not attached, write enabled, %s, autosize, AUTO detect format\n", ex->dname, ex->dsize, ex->dtype);
fprintf (st, " %s2, %s, not attached, write enabled, %s, autosize, AUTO detect format\n", ex->dname, ex->dsize, ex->dtype);
fprintf (st, " %s3, %s, not attached, write enabled, %s, autosize, AUTO detect format\n", ex->dname, ex->dsize2, ex->dtype2);
fprintf (st, " sim> # attach an existing VHD and determine its size and type automatically\n");
fprintf (st, " sim> attach %s0 %s.vhd\n", ex->dname, ex->dtype3);
fprintf (st, " sim> show %s0\n", ex->dname);
fprintf (st, " %s0, %s, attached to %s.vhd, write enabled, %s, autosize, VHD format\n", ex->dname, ex->dsize3, ex->dtype3, ex->dtype3);
fprintf (st, " sim> # create a new %s drive type VHD\n", ex->dtype4);
fprintf (st, " sim> set %s2 %s\n", ex->dname, ex->dtype4);
fprintf (st, " sim> attach %s2 -f vhd %s.vhd\n", ex->dname, ex->dtype4);
fprintf (st, " %s2: creating new file\n", ex->dname);
fprintf (st, " sim> show %s2\n", ex->dname);
fprintf (st, " %s2, %s, attached to %s.vhd, write enabled, %s, autosize, VHD format\n", ex->dname, ex->dsize4, ex->dtype4, ex->dtype4);
fprintf (st, " sim> # examine the size consumed by the %s VHD file\n", ex->dsize4);
fprintf (st, " sim> dir %s.vhd\n", ex->dtype4);
fprintf (st, " Directory of H:\\Data\n\n");
fprintf (st, " 04/14/2011 12:57 PM 5,120 RA92.vhd\n");
fprintf (st, " 04/14/2011 12:57 PM 5,120 %s.vhd\n", ex->dtype4);
fprintf (st, " 1 File(s) 5,120 bytes\n");
fprintf (st, " sim> atta rq3 -d RA92-1-Diff.vhd RA92.vhd\n");
fprintf (st, " sim> atta rq3 -c RA92-1.vhd RA92.vhd\n");
fprintf (st, " RQ3: creating new virtual disk 'RA92-1.vhd'\n");
fprintf (st, " RQ3: Copied 1505MB. 99%% complete.\n");
fprintf (st, " RQ3: Copied 1505MB. Done.\n");
fprintf (st, " sim> sh rq3\n");
fprintf (st, " RQ3, 1505MB, attached to RA92-1.vhd, write enabled, RA92, autosize, VHD format\n");
fprintf (st, " sim> dir RA92*\n");
fprintf (st, " sim> # create a differencing vhd (%s-1-Diff.vhd) with %s.vhd as parent\n", ex->dtype4, ex->dtype4);
fprintf (st, " sim> attach %s3 -d %s-1-Diff.vhd %s.vhd\n", ex->dname, ex->dtype4, ex->dtype4);
fprintf (st, " sim> # create a VHD (%s-1.vhd) which is a copy of an existing disk\n", ex->dtype4);
fprintf (st, " sim> attach %s3 -c %s-1.vhd %s.vhd\n", ex->dname, ex->dtype4, ex->dtype4);
fprintf (st, " %s3: creating new virtual disk '%s-1.vhd'\n", ex->dname, ex->dtype4);
fprintf (st, " %s3: Copied %s. 99%% complete.\n", ex->dname, ex->dsize4);
fprintf (st, " %s3: Copied %s. Done.\n", ex->dname, ex->dsize4);
fprintf (st, " sim> show %s3\n", ex->dname);
fprintf (st, " %s3, %s, attached to %s-1.vhd, write enabled, %s, autosize, VHD format\n", ex->dname, ex->dsize4, ex->dtype4, ex->dtype4);
fprintf (st, " sim> dir %s*\n", ex->dtype4);
fprintf (st, " Directory of H:\\Data\n\n");
fprintf (st, " 04/14/2011 01:12 PM 5,120 RA92-1.vhd\n");
fprintf (st, " 04/14/2011 12:58 PM 5,120 RA92.vhd\n");
fprintf (st, " 04/14/2011 01:12 PM 5,120 %s-1.vhd\n", ex->dtype4);
fprintf (st, " 04/14/2011 12:58 PM 5,120 %s.vhd\n", ex->dtype4);
fprintf (st, " 2 File(s) 10,240 bytes\n");
fprintf (st, " sim> sho rq2\n");
fprintf (st, " RQ2, 1505MB, not attached, write enabled, RA92, autosize, VHD format\n");
fprintf (st, " sim> set rq2 ra81\n");
fprintf (st, " sim> set rq2 noauto\n");
fprintf (st, " sim> sho rq2\n");
fprintf (st, " RQ2, 456MB, not attached, write enabled, RA81, noautosize, VHD format\n");
fprintf (st, " sim> set rq2 format=simh\n");
fprintf (st, " sim> sho rq2\n");
fprintf (st, " RQ2, 456MB, not attached, write enabled, RA81, noautosize, SIMH format\n");
fprintf (st, " sim> atta rq2 -c RA81-Copy.vhd VMS055.dsk\n");
fprintf (st, " RQ2: creating new virtual disk 'RA81-Copy.vhd'\n");
fprintf (st, " RQ2: Copied 456MB. 99%% complete.\n");
fprintf (st, " RQ2: Copied 456MB. Done.\n");
fprintf (st, " sim> sho rq2\n");
fprintf (st, " RQ2, 456MB, attached to RA81-Copy.vhd, write enabled, RA81, noautosize, VHD format\n");
fprintf (st, " sim> show %s2\n", ex->dname);
fprintf (st, " %s2, %s, not attached, write enabled, %s, autosize, VHD format\n", ex->dname, ex->dsize4, ex->dtype4);
fprintf (st, " sim> set %s2 %s\n", ex->dname, ex->dtype3);
fprintf (st, " sim> set %s2 noauto\n", ex->dname);
fprintf (st, " sim> show %s2\n", ex->dname);
fprintf (st, " %s2, %s, not attached, write enabled, %s, noautosize, VHD format\n", ex->dname, ex->dsize3, ex->dtype3);
fprintf (st, " sim> set %s2 format=simh\n", ex->dname);
fprintf (st, " sim> show %s2\n", ex->dname);
fprintf (st, " %s2, %s, not attached, write enabled, %s, noautosize, SIMH format\n", ex->dname, ex->dsize3, ex->dtype3);
fprintf (st, " sim> # create a VHD from an existing SIMH format disk\n");
fprintf (st, " sim> attach %s2 -c %s-Copy.vhd XYZZY.dsk\n", ex->dname, ex->dtype3);
fprintf (st, " %s2: creating new virtual disk '%s-Copy.vhd'\n", ex->dname, ex->dtype3);
fprintf (st, " %s2: Copied %s. 99%% complete.\n", ex->dname, ex->dsize3);
fprintf (st, " %s2: Copied %s. Done.\n", ex->dname, ex->dsize3);
fprintf (st, " sim> show %s2\n", ex->dname);
fprintf (st, " %s2, %s, attached to %s-Copy.vhd, write enabled, %s, noautosize, VHD format\n", ex->dname, ex->dsize3, ex->dtype3, ex->dtype3);
return SCPE_OK;
}
@ -2877,37 +2930,6 @@ if (sim_deb && (dptr->dctrl & reason)) {
}
}
/* Guest specific Disk I/O support */
#define PDP10_SECTORS 2 /* PDP-10 sectors are 1024 bytes */
t_stat sim_disk_pdp10_attach (UNIT *uptr, const char *cptr, size_t sector_size, size_t xfer_element_size, t_bool dontautosize,
uint32 dbit, const char *dtype, int completion_delay, const char **drivetypes)
{
return sim_disk_attach_ex (uptr, cptr, sector_size / PDP10_SECTORS, xfer_element_size, dontautosize, dbit, dtype, 0, completion_delay, drivetypes);
}
t_stat sim_disk_pdp10_rdsect (UNIT *uptr, t_lba lba, uint8 *buf, t_seccnt *sectsread, t_seccnt sects)
{
t_seccnt sectors;
t_stat r = sim_disk_rdsect (uptr, lba * PDP10_SECTORS, buf, &sectors, sects * PDP10_SECTORS);
if (sectsread)
*sectsread = sectors / PDP10_SECTORS;
return r;
}
t_stat sim_disk_pdp10_wrsect (UNIT *uptr, t_lba lba, uint8 *buf, t_seccnt *sectswritten, t_seccnt sects)
{
t_seccnt sectors;
t_stat r = sim_disk_wrsect (uptr, lba * PDP10_SECTORS, buf, &sectors, sects * PDP10_SECTORS);
if (sectswritten)
*sectswritten = sectors / PDP10_SECTORS;
return r;
}
/* OS Specific RAW Disk I/O support */
#if defined _WIN32
@ -3858,10 +3880,12 @@ typedef struct _VHD_Footer {
name as a nul terminated string.
*/
uint8 DriveType[16];
uint32 DriveSectorSize;
uint32 DriveTransferElementSize;
/*
This field contains zeroes. It is 400 bytes in size.
This field contains zeroes. It is 392 bytes in size.
*/
uint8 Reserved[400];
uint8 Reserved[392];
} VHD_Footer;
/*
@ -4331,13 +4355,15 @@ static t_stat sim_vhd_disk_implemented (void)
return SCPE_OK;
}
static t_stat sim_vhd_disk_set_dtype (FILE *f, const char *dtype)
static t_stat sim_vhd_disk_set_dtype (FILE *f, const char *dtype, uint32 SectorSize, uint32 xfer_element_size)
{
VHDHANDLE hVHD = (VHDHANDLE)f;
int Status = 0;
memset (hVHD->Footer.DriveType, '\0', sizeof hVHD->Footer.DriveType);
memcpy (hVHD->Footer.DriveType, dtype, ((1+strlen (dtype)) < sizeof (hVHD->Footer.DriveType)) ? (1+strlen (dtype)) : sizeof (hVHD->Footer.DriveType));
hVHD->Footer.DriveSectorSize = NtoHl (SectorSize);
hVHD->Footer.DriveTransferElementSize = NtoHl (xfer_element_size);
hVHD->Footer.Checksum = 0;
hVHD->Footer.Checksum = NtoHl (CalculateVhdFooterChecksum (&hVHD->Footer, sizeof(hVHD->Footer)));
@ -4383,10 +4409,14 @@ if (Status)
return SCPE_OK;
}
static const char *sim_vhd_disk_get_dtype (FILE *f)
static const char *sim_vhd_disk_get_dtype (FILE *f, uint32 *SectorSize, uint32 *xfer_element_size)
{
VHDHANDLE hVHD = (VHDHANDLE)f;
if (SectorSize)
*SectorSize = NtoHl (hVHD->Footer.DriveSectorSize);
if (xfer_element_size)
*xfer_element_size = NtoHl (hVHD->Footer.DriveTransferElementSize);
return (char *)(&hVHD->Footer.DriveType[0]);
}
@ -5052,6 +5082,8 @@ hVHD->Dynamic.Checksum = NtoHl (CalculateVhdFooterChecksum (&hVHD->Dynamic, size
hVHD->Footer.Checksum = 0;
hVHD->Footer.DiskType = NtoHl (VHD_DT_Differencing);
memcpy (hVHD->Footer.DriveType, ParentFooter.DriveType, sizeof (hVHD->Footer.DriveType));
hVHD->Footer.DriveSectorSize = ParentFooter.DriveSectorSize;
hVHD->Footer.DriveTransferElementSize = ParentFooter.DriveTransferElementSize;
hVHD->Footer.Checksum = NtoHl (CalculateVhdFooterChecksum (&hVHD->Footer, sizeof(hVHD->Footer)));
if (WriteFilePosition (hVHD->File,

View File

@ -68,10 +68,25 @@ typedef void (*DISK_PCALLBACK)(UNIT *unit, t_stat status);
/* Prototypes */
t_stat sim_disk_attach (UNIT *uptr, const char *cptr, size_t sector_size, size_t xfer_element_size, t_bool dontautosize,
uint32 debugbit, const char *drivetype, uint32 pdp11_tracksize, int completion_delay);
t_stat sim_disk_attach_ex (UNIT *uptr, const char *cptr, size_t sector_size, size_t xfer_element_size, t_bool dontautosize,
uint32 dbit, const char *dtype, uint32 pdp11tracksize, int completion_delay, const char **drivetypes);
t_stat sim_disk_attach (UNIT *uptr,
const char *cptr,
size_t sector_size, size_t xfer_element_size,
t_bool dontchangecapac,
uint32 debugbit,
const char *drivetype,
uint32 pdp11_tracksize,
int completion_delay);
t_stat sim_disk_attach_ex (UNIT *uptr,
const char *cptr,
size_t sector_size,
size_t xfer_element_size,
t_bool dontchangecapac, /* if false just change uptr->capac as needed */
uint32 dbit, /* debug bit */
const char *dtype, /* drive type */
uint32 pdp11tracksize, /* BAD144 track */
int completion_delay, /* Minimum Delay for asynch I/O completion */
const char **drivetypes); /* list of drive types (from smallest to largest) */
/* to try and fit the container/file system into */
t_stat sim_disk_detach (UNIT *uptr);
t_stat sim_disk_attach_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr);
t_stat sim_disk_rdsect (UNIT *uptr, t_lba lba, uint8 *buf, t_seccnt *sectsread, t_seccnt sects);

View File

@ -114,6 +114,7 @@ static struct sim_tape_fmt {
{ "TAR", UNIT_RO, 0, 0 },
{ "ANSI", UNIT_RO, 0, 0 },
{ "FIXED", UNIT_RO, 0, 0 },
{ "DOS11", UNIT_RO, 0, 0 },
{ NULL, 0, 0, 0 }
};
@ -518,7 +519,26 @@ static void sim_tape_add_ansi_entry (const char *directory,
const struct stat *filestat,
void *context);
static t_bool memory_tape_add_block (MEMORY_TAPE *tape, uint8 *block, uint32 size);
typedef struct DOS11_HDR {
uint16 fname[2]; /* File name (RAD50 - 6 characters) */
uint16 ext; /* Extension (RAD50 - 3 characters) */
uint8 prog; /* Programmer # */
uint8 proj; /* Project # */
uint16 prot; /* Protection */
uint16 date; /* (year - 1970) * 1000 + day of year */
uint16 fname3; /* File name (RAD50 - 3 characters) */
} DOS11_HDR;
#define DOS11_PROT 0233
static void sim_tape_add_dos11_entry (const char *directory,
const char *filename,
t_offset FileSize,
const struct stat *filestat,
void *context);
static t_stat sim_export_tape (UNIT *uptr, const char *export_file);
static FILE *tape_open_and_check_file(const char *filename);
static int tape_classify_file_contents (FILE *f, size_t *max_record_size, t_bool *lf_line_endings, t_bool *crlf_line_endings);
@ -659,8 +679,6 @@ else {
if ((MT_GET_FMT (uptr) == MTUF_F_TAR) && (uptr->recsize == 0))
uptr->recsize = TAR_DFLT_RECSIZE;
}
if (sim_switches & SWMASK ('X'))
cptr = get_glyph_nc (cptr, export_file, 0); /* get spec */
if ((MT_GET_FMT (uptr) == MTUF_F_TPC) ||
(MT_GET_FMT (uptr) == MTUF_F_TAR) ||
(MT_GET_FMT (uptr) >= MTUF_F_ANSI))
@ -807,6 +825,48 @@ switch (MT_GET_FMT (uptr)) {
}
break;
case MTUF_F_DOS11:
if (1) {
const char *ocptr = cptr;
int file_errors = 0;
uptr->recsize = 512;
tape = memory_create_tape();
tape->block_size = uptr->recsize;
uptr->fileref = (FILE *)tape;
if (!uptr->fileref)
return SCPE_MEM;
while (*cptr != 0) {
uint32 initial_file_count = tape->file_count;
cptr = get_glyph_nc (cptr, gbuf, ','); /* Get filename */
r = sim_dir_scan (gbuf, sim_tape_add_dos11_entry, tape);
if (r != SCPE_OK)
sim_messagef (SCPE_ARG, "file not found: %s\n", gbuf);
if (tape->file_count == initial_file_count)
++file_errors;
}
if ((tape->file_count > 0) && (file_errors == 0)) {
r = SCPE_OK;
memory_tape_add_block (tape, NULL, 0); /* Tape Mark */
memory_tape_add_block (tape, NULL, 0); /* Tape Mark */
uptr->flags |= UNIT_ATT;
uptr->filename = (char *)malloc (strlen (ocptr) + 1);
strcpy (uptr->filename, ocptr);
uptr->tape_eom = tape->record_count;
}
else {
r = SCPE_ARG;
memory_free_tape (uptr->fileref);
uptr->fileref = NULL;
cptr = ocptr;
}
}
break;
case MTUF_F_TAR:
if (uptr->recsize == 0)
uptr->recsize = TAR_DFLT_RECSIZE; /* Apply default block size */
@ -820,6 +880,7 @@ if (r != SCPE_OK) { /* error? */
case MTUF_F_ANSI:
case MTUF_F_TAR:
case MTUF_F_FIXED:
case MTUF_F_DOS11:
r = sim_messagef (r, "Error opening %s format internal tape image generated from: %s\n", _sim_tape_format_name (uptr), cptr);
break;
default:
@ -975,7 +1036,8 @@ fprintf (st, " -E Must Exist (if not specified, the default behavior
fprintf (st, " attempt to create the indicated virtual tape file).\n");
fprintf (st, " -F Open the indicated tape container in a specific format\n");
fprintf (st, " (default is SIMH, alternatives are E11, TPC, P7B, AWS, TAR,\n");
fprintf (st, " ANSI-VMS, ANSI-RT11, ANSI-RSX11, ANSI-RSTS, ANSI-VAR, FIXED)\n");
fprintf (st, " ANSI-VMS, ANSI-RT11, ANSI-RSX11, ANSI-RSTS, ANSI-VAR, FIXED,\n");
fprintf (st, " DOS11)\n");
fprintf (st, " -B For TAR format tapes, the record size for data read from the\n");
fprintf (st, " specified file. This record size will be used for all but \n");
fprintf (st, " possibly the last record which will be what remains unread.\n");
@ -1000,12 +1062,23 @@ fprintf (st, " accessible directly as files on the tape.\n\n");
fprintf (st, " FIXED format will present the contents of a file (text or binary) as\n");
fprintf (st, " fixed sized records/blocks with ascii text data optionally converted\n");
fprintf (st, " to EBCDIC.\n\n");
fprintf (st, " DOS11 format will present the contents of a file preceeded by a DOS11\n");
fprintf (st, " 14-byte header. All files will be owned by [1,1], have a default\n");
fprintf (st, " protection of <233> and a date in the range 1972 - 1999 with the\n");
fprintf (st, " month/day layout as the current year. The file name on the tape\n");
fprintf (st, " will be sanitized to contain only alphanumeric characters from the\n");
fprintf (st, " original source file name. Characters 7 - 9 of the file name will be\n");
fprintf (st, " placed in an otherwise unused word in the header which some DEC\n");
fprintf (st, " operating systems will be able to process. If the resulting\n");
fprintf (st, " filename is NULL, a filename in the range 000000 - 999999 will be\n");
fprintf (st, " generated based of the file position on the tape.\n\n");
fprintf (st, "Examples:\n\n");
fprintf (st, " sim> ATTACH %s -F ANSI-VMS Hobbyist-USE-ONLY-VA.TXT\n", dptr->name);
fprintf (st, " sim> ATTACH %s -F ANSI-RSX11 *.TXT,*.ini,*.exe\n", dptr->name);
fprintf (st, " sim> ATTACH %s -FX ANSI-RSTS RSTS.tap *.TXT,*.SAV\n", dptr->name);
fprintf (st, " sim> ATTACH %s -F ANSI-RT11 *.TXT,*.TSK\n", dptr->name);
fprintf (st, " sim> ATTACH %s -FB FIXED 80 SOMEFILE.TXT\n\n", dptr->name);
fprintf (st, " sim> ATTACH %s -FB FIXED 80 SOMEFILE.TXT\n", dptr->name);
fprintf (st, " sim> ATTACH %s -F DOS11 *.LDA,*.TXT\n\n", dptr->name);
return SCPE_OK;
}
@ -1422,6 +1495,7 @@ switch (f) { /* otherwise the read method
case MTUF_F_ANSI:
case MTUF_F_FIXED:
case MTUF_F_DOS11:
if (1) {
MEMORY_TAPE *tape = (MEMORY_TAPE *)uptr->fileref;
@ -1757,6 +1831,7 @@ switch (f) { /* otherwise the read me
case MTUF_F_ANSI:
case MTUF_F_FIXED:
case MTUF_F_DOS11:
if (1) {
MEMORY_TAPE *tape = (MEMORY_TAPE *)uptr->fileref;
@ -4340,6 +4415,203 @@ tape->ansi_type = -1;
return tape;
}
static const char rad50[] = " ABCDEFGHIJKLMNOPQRSTUVWXYZ%.%0123456789";
static uint16 dos11_ascR50(char *inbuf)
{
uint16 value;
value = (strchr (rad50, *inbuf++) - rad50) * 03100;
value += (strchr (rad50, *inbuf++) - rad50) * 050;
value += (strchr (rad50, *inbuf++) - rad50);
return value;
}
/*
* Sanitize a filename to generate a DOS-11 compatible version. Ignore
* non-alphanumerics, upper case lower case characters and terminate on '.'
*/
static void dos11_sanitize(char *buf, int len, const char *inbuf)
{
while ((len != 0) && (*inbuf != '\0') && (*inbuf !='.')) {
char ch = toupper (*inbuf++);
if (isalnum(ch)) {
*buf++ = ch;
len--;
}
}
}
static int dos11_copy_ascii_file(FILE *f, MEMORY_TAPE *tape, char *buf, size_t bufSize)
{
char ch, tmp[512];
t_bool crlast = FALSE;
int error = 0;
size_t i, data_read, offset = 0;
memset (buf, 0, bufSize);
while (!feof (f) && !error) {
data_read = fread (tmp, 1, sizeof (tmp), f);
if (data_read > 0)
for (i = 0; i < data_read; i++) {
ch = tmp[i];
if (ch == '\n') {
if (!crlast) {
buf[offset++] = '\r';
if (offset == bufSize) {
error = memory_tape_add_block (tape, (uint8 *)buf, bufSize);
offset = 0;
memset (buf, 0, bufSize);
}
}
buf[offset++] = ch;
if (offset == bufSize) {
error = memory_tape_add_block (tape, (uint8 *)buf, bufSize);
offset = 0;
memset (buf, 0, bufSize);
}
crlast = FALSE;
}
else {
crlast = ch == '\r';
buf[offset++] = ch;
if (offset == bufSize) {
error = memory_tape_add_block (tape, (uint8 *)buf, bufSize);
offset = 0;
memset (buf, 0, bufSize);
}
}
}
}
if (offset != 0)
error = memory_tape_add_block (tape, (uint8 *)buf, bufSize);
return error;
}
static void sim_tape_add_dos11_entry (const char *directory,
const char *filename,
t_offset FileSize,
const struct stat *filestat,
void *context)
{
MEMORY_TAPE *tape = (MEMORY_TAPE *)context;
char FullPath[PATH_MAX + 1];
FILE *f;
size_t max_record_size;
t_bool lf_line_endings;
t_bool crlf_line_endings;
uint8 *block = NULL;
int error = 0;
DOS11_HDR hdr;
char fname[9], ext[3];
const char *ptr;
struct tm *tm;
time_t now = time (NULL);
uint16 today;
int year;
/*
* Compute a suitable year for file creation date. This year will have the
* same calendar as the current year but will be in the 20th century so that
* DOS/BATCH-11 will be able to interpret it correctly.
*/
tm = localtime (&now);
year = tm->tm_year + 1900;
while (year >= 2000)
year -= 28;
today = ((year - 70) * 1000) + tm->tm_yday + 1;
sprintf (FullPath, "%s%s", directory, filename);
f = tape_open_and_check_file(FullPath);
if (f == NULL)
return;
tape_classify_file_contents (f, &max_record_size, &lf_line_endings, &crlf_line_endings);
memset (&hdr, 0, sizeof (hdr));
memset (fname, ' ', sizeof (fname));
memset (ext, ' ', sizeof (ext));
dos11_sanitize (fname, sizeof (fname), filename);
ptr = strchr (filename, '.');
if (ptr != NULL)
dos11_sanitize (ext, sizeof (ext), ++ptr);
/*
* If we were unable to generate a valid DOS11 filename, generate one based
* on the file number on the tape (000000 - 999999).
*/
if (fname[0] == ' ') {
char temp[10];
sprintf(temp, "%06u ", tape->file_count % 100000);
memcpy(fname, temp, sizeof(fname));
}
hdr.fname[0] = dos11_ascR50 (&fname[0]);
hdr.fname[1] = dos11_ascR50 (&fname[3]);
hdr.ext = dos11_ascR50 (&ext[0]);
hdr.prog = 1;
hdr.proj = 1;
hdr.prot = DOS11_PROT;
hdr.date = today;
hdr.fname3 = dos11_ascR50 (&fname[6]);
memory_tape_add_block (tape, (uint8 *)&hdr, sizeof (hdr));
rewind (f);
block = (uint8 *)calloc (tape->block_size, 1);
if (lf_line_endings || crlf_line_endings)
error = dos11_copy_ascii_file (f, tape, (char *)block, tape->block_size);
else {
size_t data_read;
while (!feof (f) && !error) {
data_read = fread (block, 1, tape->block_size, f);
if (data_read > 0)
error = memory_tape_add_block (tape, block, data_read);
}
}
fclose (f);
free (block);
memory_tape_add_block (tape, NULL, 0);
++tape->file_count;
}
static FILE *tape_open_and_check_file(const char *filename)
{
FILE *file = fopen(filename, "rb");
if (file != NULL) {
struct stat statb;
memset (&statb, 0, sizeof (statb));
if (fstat (fileno (file), &statb) == 0) {
if (((S_IFDIR | S_IFREG) & statb.st_mode) == S_IFREG)
return file;
sim_printf ("Can't put a %s on tape: %s\n",
statb.st_mode & S_IFREG ? "directory" : "non regular file",
filename);
fclose (file);
return NULL;
}
sim_printf ("Can't stat: %s\n", filename);
fclose (file);
return NULL;
}
sim_printf ("Can't open: %s - %s\n", filename, strerror (errno));
return NULL;
}
static int tape_classify_file_contents (FILE *f, size_t *max_record_size, t_bool *lf_line_endings, t_bool *crlf_line_endings)
{
long pos = -1;
@ -4412,7 +4684,6 @@ return tape;
static int ansi_add_file_to_tape (MEMORY_TAPE *tape, const char *filename)
{
FILE *f;
struct stat statb;
struct ansi_tape_parameters *ansi = &ansi_args[tape->ansi_type];
uint8 *block = NULL;
size_t max_record_size;
@ -4427,27 +4698,10 @@ HDR2 hdr2;
HDR3 hdr3;
HDR4 hdr4;
f = fopen (filename, "rb");
if (f == NULL) {
sim_printf ("Can't open: %s - %s\n", filename, strerror(errno));
return errno;
}
memset (&statb, 0, sizeof (statb));
if (fstat (fileno (f), &statb)) {
sim_printf ("Can't stat: %s\n", filename);
fclose (f);
return -1;
}
if (S_IFDIR & statb.st_mode) {
sim_printf ("Can't put a directory on tape: %s\n", filename);
fclose (f);
return -1;
}
if (!(S_IFREG & statb.st_mode)) {
sim_printf ("Can't put a non regular file on tape: %s\n", filename);
fclose (f);
return -1;
}
f = tape_open_and_check_file(filename);
if (f == NULL)
return TRUE;
tape_classify_file_contents (f, &max_record_size, &lf_line_endings, &crlf_line_endings);
ansi_make_HDR1 (&hdr1, &tape->vol1, &hdr4, filename, tape->ansi_type);
sprintf (file_sequence, "%04d", 1 + tape->file_count);
@ -4580,4 +4834,4 @@ free (buf);
fclose (f);
uptr->pos = saved_pos;
return r;
}
}

View File

@ -100,6 +100,7 @@ typedef struct {
#define MTUF_F_TAR 5 /* TAR format */
#define MTUF_F_ANSI 6 /* ANSI format */
#define MTUF_F_FIXED 7 /* FIXED format */
#define MTUF_F_DOS11 8 /* DOS11 format */
#define MTAT_F_VMS 0 /* VMS ANSI type */
#define MTAT_F_RSX11 1 /* RSX-11 ANSI type */