mirror of
https://github.com/rcornwell/sims.git
synced 2026-05-05 23:45:14 +00:00
SCP: Updated to current version
This commit is contained in:
667
sim_disk.c
667
sim_disk.c
@@ -162,16 +162,12 @@ static void *
|
||||
_disk_io(void *arg)
|
||||
{
|
||||
UNIT* volatile uptr = (UNIT*)arg;
|
||||
int sched_policy;
|
||||
struct sched_param sched_priority;
|
||||
struct disk_context *ctx = (struct disk_context *)uptr->disk_ctx;
|
||||
|
||||
/* Boost Priority for this I/O thread vs the CPU instruction execution
|
||||
thread which in general won't be readily yielding the processor when
|
||||
this thread needs to run */
|
||||
pthread_getschedparam (pthread_self(), &sched_policy, &sched_priority);
|
||||
++sched_priority.sched_priority;
|
||||
pthread_setschedparam (pthread_self(), sched_policy, &sched_priority);
|
||||
sim_os_set_thread_priority (PRIORITY_ABOVE_NORMAL);
|
||||
|
||||
sim_debug (ctx->dbit, ctx->dptr, "_disk_io(unit=%d) starting\n", (int)(uptr-ctx->dptr->units));
|
||||
|
||||
@@ -243,7 +239,7 @@ if (ctx) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void _disk_cancel (UNIT *uptr)
|
||||
static t_bool _disk_cancel (UNIT *uptr)
|
||||
{
|
||||
struct disk_context *ctx = (struct disk_context *)uptr->disk_ctx;
|
||||
|
||||
@@ -256,6 +252,7 @@ if (ctx) {
|
||||
pthread_mutex_unlock (&ctx->io_lock);
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
#else
|
||||
#define AIO_CALLSETUP
|
||||
@@ -289,9 +286,9 @@ static t_bool sim_os_disk_isavailable_raw (FILE *f);
|
||||
static t_stat sim_os_disk_rdsect (UNIT *uptr, t_lba lba, uint8 *buf, t_seccnt *sectsread, t_seccnt sects);
|
||||
static t_stat sim_os_disk_wrsect (UNIT *uptr, t_lba lba, uint8 *buf, t_seccnt *sectswritten, t_seccnt sects);
|
||||
static t_stat sim_os_disk_info_raw (FILE *f, uint32 *sector_size, uint32 *removable);
|
||||
static t_stat sim_disk_pdp11_bad_block (UNIT *uptr, int32 sec);
|
||||
static char *HostPathToVhdPath (const char *szHostPath, char *szVhdPath, size_t VhdPathSize);
|
||||
static char *VhdPathToHostPath (const char *szVhdPath, char *szHostPath, size_t HostPathSize);
|
||||
static t_offset get_filesystem_size (UNIT *uptr);
|
||||
|
||||
struct sim_disk_fmt {
|
||||
const char *name; /* name */
|
||||
@@ -425,18 +422,29 @@ return (uptr->flags & DKUF_WRP)? TRUE: FALSE;
|
||||
|
||||
t_offset sim_disk_size (UNIT *uptr)
|
||||
{
|
||||
t_offset physical_size, filesystem_size;
|
||||
t_bool saved_quiet = sim_quiet;
|
||||
|
||||
switch (DK_GET_FMT (uptr)) { /* case on format */
|
||||
case DKUF_F_STD: /* SIMH format */
|
||||
return sim_fsize_ex (uptr->fileref);
|
||||
physical_size = sim_fsize_ex (uptr->fileref);
|
||||
break;
|
||||
case DKUF_F_VHD: /* VHD format */
|
||||
return sim_vhd_disk_size (uptr->fileref);
|
||||
physical_size = sim_vhd_disk_size (uptr->fileref);
|
||||
break;
|
||||
case DKUF_F_RAW: /* Raw Physical Disk Access */
|
||||
return sim_os_disk_size_raw (uptr->fileref);
|
||||
physical_size = sim_os_disk_size_raw (uptr->fileref);
|
||||
break;
|
||||
default:
|
||||
return (t_offset)-1;
|
||||
}
|
||||
sim_quiet = TRUE;
|
||||
filesystem_size = get_filesystem_size (uptr);
|
||||
sim_quiet = saved_quiet;
|
||||
if ((filesystem_size == (t_offset)-1) ||
|
||||
(filesystem_size < physical_size))
|
||||
return physical_size;
|
||||
return filesystem_size;
|
||||
}
|
||||
|
||||
/* Enable asynchronous operation */
|
||||
@@ -471,7 +479,7 @@ if (ctx->asynch_io) {
|
||||
}
|
||||
uptr->a_check_completion = _disk_completion_dispatch;
|
||||
uptr->a_is_active = _disk_is_active;
|
||||
uptr->a_cancel = _disk_cancel;
|
||||
uptr->cancel = _disk_cancel;
|
||||
return SCPE_OK;
|
||||
#endif
|
||||
}
|
||||
@@ -841,6 +849,452 @@ uptr->disk_ctx = NULL;
|
||||
return stat;
|
||||
}
|
||||
|
||||
#pragma pack(push,1)
|
||||
typedef struct _ODS1_HomeBlock
|
||||
{
|
||||
uint16 hm1_w_ibmapsize;
|
||||
uint32 hm1_l_ibmaplbn;
|
||||
uint16 hm1_w_maxfiles;
|
||||
uint16 hm1_w_cluster;
|
||||
uint16 hm1_w_devtype;
|
||||
uint16 hm1_w_structlev;
|
||||
#define HM1_C_LEVEL1 0401
|
||||
#define HM1_C_LEVEL2 0402
|
||||
uint8 hm1_t_volname[12];
|
||||
uint8 hm1_b_fill_1[4];
|
||||
uint16 hm1_w_volowner;
|
||||
uint16 hm1_w_protect;
|
||||
uint16 hm1_w_volchar;
|
||||
uint16 hm1_w_fileprot;
|
||||
uint8 hm1_b_fill_2[6];
|
||||
uint8 hm1_b_window;
|
||||
uint8 hm1_b_extend;
|
||||
uint8 hm1_b_lru_lim;
|
||||
uint8 hm1_b_fill_3[11];
|
||||
uint16 hm1_w_checksum1;
|
||||
uint8 hm1_t_credate[14];
|
||||
uint8 hm1_b_fill_4[382];
|
||||
uint32 hm1_l_serialnum;
|
||||
uint8 hm1_b_fill_5[12];
|
||||
uint8 hm1_t_volname2[12];
|
||||
uint8 hm1_t_ownername[12];
|
||||
uint8 hm1_t_format[12];
|
||||
uint8 hm1_t_fill_6[2];
|
||||
uint16 hm1_w_checksum2;
|
||||
} ODS1_HomeBlock;
|
||||
|
||||
typedef struct _ODS2_HomeBlock
|
||||
{
|
||||
uint32 hm2_l_homelbn;
|
||||
uint32 hm2_l_alhomelbn;
|
||||
uint32 hm2_l_altidxlbn;
|
||||
uint8 hm2_b_strucver;
|
||||
uint8 hm2_b_struclev;
|
||||
uint16 hm2_w_cluster;
|
||||
uint16 hm2_w_homevbn;
|
||||
uint16 hm2_w_alhomevbn;
|
||||
uint16 hm2_w_altidxvbn;
|
||||
uint16 hm2_w_ibmapvbn;
|
||||
uint32 hm2_l_ibmaplbn;
|
||||
uint32 hm2_l_maxfiles;
|
||||
uint16 hm2_w_ibmapsize;
|
||||
uint16 hm2_w_resfiles;
|
||||
uint16 hm2_w_devtype;
|
||||
uint16 hm2_w_rvn;
|
||||
uint16 hm2_w_setcount;
|
||||
uint16 hm2_w_volchar;
|
||||
uint32 hm2_l_volowner;
|
||||
uint32 hm2_l_reserved;
|
||||
uint16 hm2_w_protect;
|
||||
uint16 hm2_w_fileprot;
|
||||
uint16 hm2_w_reserved;
|
||||
uint16 hm2_w_checksum1;
|
||||
uint32 hm2_q_credate[2];
|
||||
uint8 hm2_b_window;
|
||||
uint8 hm2_b_lru_lim;
|
||||
uint16 hm2_w_extend;
|
||||
uint32 hm2_q_retainmin[2];
|
||||
uint32 hm2_q_retainmax[2];
|
||||
uint32 hm2_q_revdate[2];
|
||||
uint8 hm2_r_min_class[20];
|
||||
uint8 hm2_r_max_class[20];
|
||||
uint8 hm2_r_reserved[320];
|
||||
uint32 hm2_l_serialnum;
|
||||
uint8 hm2_t_strucname[12];
|
||||
uint8 hm2_t_volname[12];
|
||||
uint8 hm2_t_ownername[12];
|
||||
uint8 hm2_t_format[12];
|
||||
uint16 hm2_w_reserved2;
|
||||
uint16 hm2_w_checksum2;
|
||||
} ODS2_HomeBlock;
|
||||
|
||||
typedef struct _ODS1_FileHeader
|
||||
{
|
||||
uint8 fh1_b_idoffset;
|
||||
uint8 fh1_b_mpoffset;
|
||||
uint16 fh1_w_fid_num;
|
||||
uint16 fh1_w_fid_seq;
|
||||
uint16 fh1_w_struclev;
|
||||
uint16 fh1_w_fileowner;
|
||||
uint16 fh1_w_fileprot;
|
||||
uint16 fh1_w_filechar;
|
||||
uint16 fh1_w_recattr;
|
||||
uint8 fh1_b_fill_1[494];
|
||||
uint16 fh1_w_checksum;
|
||||
} ODS1_FileHeader;
|
||||
|
||||
typedef struct _ODS2_FileHeader
|
||||
{
|
||||
uint8 fh2_b_idoffset;
|
||||
uint8 fh2_b_mpoffset;
|
||||
uint8 fh2_b_acoffset;
|
||||
uint8 fh2_b_rsoffset;
|
||||
uint16 fh2_w_seg_num;
|
||||
uint16 fh2_w_structlev;
|
||||
uint16 fh2_w_fid[3];
|
||||
uint16 fh2_w_ext_fid[3];
|
||||
uint16 fh2_w_recattr[16];
|
||||
uint32 fh2_l_filechar;
|
||||
uint16 fh2_w_remaining[228];
|
||||
} ODS2_FileHeader;
|
||||
|
||||
typedef union _ODS2_Retreval
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned fm2___fill : 14; /* type specific data */
|
||||
unsigned fm2_v_format : 2; /* format type code */
|
||||
} fm2_r_word0_bits;
|
||||
struct
|
||||
{
|
||||
unsigned fm2_v_exact : 1; /* exact placement specified */
|
||||
unsigned fm2_v_oncyl : 1; /* on cylinder allocation desired */
|
||||
unsigned fm2___fill : 10;
|
||||
unsigned fm2_v_lbn : 1; /* use LBN of next map pointer */
|
||||
unsigned fm2_v_rvn : 1; /* place on specified RVN */
|
||||
unsigned fm2_v_format0 : 2;
|
||||
} fm2_r_map_bits0;
|
||||
struct
|
||||
{
|
||||
unsigned fm2_b_count1 : 8; /* low byte described below */
|
||||
unsigned fm2_v_highlbn1 : 6; /* high order LBN */
|
||||
unsigned fm2_v_format1 : 2;
|
||||
unsigned fm2_w_lowlbn1 : 16; /* low order LBN */
|
||||
} fm2_r_map_bits1;
|
||||
struct
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned fm2_v_count2 : 14; /* count field */
|
||||
unsigned fm2_v_format2 : 2;
|
||||
unsigned fm2_l_lowlbn2 : 16; /* low order LBN */
|
||||
} fm2_r_map2_long0;
|
||||
uint16 fm2_l_highlbn2; /* high order LBN */
|
||||
} fm2_r_map_bits2;
|
||||
struct
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned fm2_v_highcount3 : 14; /* low order count field */
|
||||
unsigned fm2_v_format3 : 2;
|
||||
unsigned fm2_w_lowcount3 : 16; /* high order count field */
|
||||
} fm2_r_map3_long0;
|
||||
uint32 fm2_l_lbn3;
|
||||
} fm2_r_map_bits3;
|
||||
} ODS2_Retreval;
|
||||
|
||||
typedef struct _ODS1_Retreval
|
||||
{
|
||||
uint8 fm1_b_ex_segnum;
|
||||
uint8 fm1_b_ex_rvn;
|
||||
uint16 fm1_w_ex_filnum;
|
||||
uint16 fm1_w_ex_filseq;
|
||||
uint8 fm1_b_countsize;
|
||||
uint8 fm1_b_lbnsize;
|
||||
uint8 fm1_b_inuse;
|
||||
uint8 fm1_b_avail;
|
||||
union {
|
||||
struct {
|
||||
uint8 fm1_b_highlbn;
|
||||
uint8 fm1_b_count;
|
||||
uint16 fm1_w_lowlbn;
|
||||
} fm1_s_fm1def1;
|
||||
struct {
|
||||
uint8 fm1_b_highlbn;
|
||||
uint8 fm1_b_count;
|
||||
uint16 fm1_w_lowlbn;
|
||||
} fm1_s_fm1def2;
|
||||
} fm1_pointers[4];
|
||||
} ODS1_Retreval;
|
||||
|
||||
typedef struct _ODS1_StorageControlBlock
|
||||
{
|
||||
uint8 scb_b_unused[3];
|
||||
uint8 scb_b_bitmapblks;
|
||||
struct _bitmapblk {
|
||||
uint16 scb_w_freeblks;
|
||||
uint16 scb_w_freeptr;
|
||||
} scb_r_blocks[1];
|
||||
} ODS1_SCB;
|
||||
|
||||
|
||||
typedef struct _ODS2_StorageControlBlock
|
||||
{
|
||||
uint8 scb_b_strucver; /* 1 */
|
||||
uint8 scb_b_struclev; /* 2 */
|
||||
uint16 scb_w_cluster;
|
||||
uint32 scb_l_volsize;
|
||||
uint32 scb_l_blksize;
|
||||
uint32 scb_l_sectors;
|
||||
uint32 scb_l_tracks;
|
||||
uint32 scb_l_cylinder;
|
||||
uint32 scb_l_status;
|
||||
uint32 scb_l_status2;
|
||||
uint16 scb_w_writecnt;
|
||||
uint8 scb_t_volockname[12];
|
||||
uint32 scb_q_mounttime[2];
|
||||
uint16 scb_w_backrev;
|
||||
uint32 scb_q_genernum[2];
|
||||
uint8 scb_b_reserved[446];
|
||||
uint16 scb_w_checksum;
|
||||
} ODS2_SCB;
|
||||
#pragma pack(pop)
|
||||
|
||||
static uint16
|
||||
ODSChecksum (void *Buffer, uint16 WordCount)
|
||||
{
|
||||
int i;
|
||||
uint16 Sum = 0;
|
||||
uint16 CheckSum = 0;
|
||||
uint16 *Buf = (uint16 *)Buffer;
|
||||
|
||||
for (i=0; i<WordCount; i++)
|
||||
CheckSum += Buf[i];
|
||||
return CheckSum;
|
||||
}
|
||||
|
||||
|
||||
static t_offset get_ods2_filesystem_size (UNIT *uptr)
|
||||
{
|
||||
DEVICE *dptr;
|
||||
t_addr saved_capac;
|
||||
struct disk_context *ctx = (struct disk_context *)uptr->disk_ctx;
|
||||
t_offset temp_capac = 512 * (t_offset)0xFFFFFFFFu; /* Make sure we can access the largest sector */
|
||||
uint32 capac_factor;
|
||||
ODS2_HomeBlock Home;
|
||||
ODS2_FileHeader Header;
|
||||
ODS2_Retreval *Retr;
|
||||
ODS2_SCB Scb;
|
||||
uint16 CheckSum1, CheckSum2;
|
||||
uint32 ScbLbn;
|
||||
t_offset ret_val = (t_offset)-1;
|
||||
|
||||
if ((dptr = find_dev_from_unit (uptr)) == NULL)
|
||||
return ret_val;
|
||||
capac_factor = ((dptr->dwidth / dptr->aincr) == 16) ? 2 : 1; /* save capacity units (word: 2, byte: 1) */
|
||||
saved_capac = uptr->capac;
|
||||
uptr->capac = (t_addr)(temp_capac/(capac_factor*((dptr->flags & DEV_SECTORS) ? 512 : 1)));
|
||||
if (sim_disk_rdsect (uptr, 512 / ctx->sector_size, (uint8 *)&Home, NULL, sizeof (Home) / ctx->sector_size))
|
||||
goto Return_Cleanup;
|
||||
CheckSum1 = ODSChecksum (&Home, (uint16)((((char *)&Home.hm2_w_checksum1)-((char *)&Home.hm2_l_homelbn))/2));
|
||||
CheckSum2 = ODSChecksum (&Home, (uint16)((((char *)&Home.hm2_w_checksum2)-((char *)&Home.hm2_l_homelbn))/2));
|
||||
if ((Home.hm2_l_homelbn == 0) ||
|
||||
(Home.hm2_l_alhomelbn == 0) ||
|
||||
(Home.hm2_l_altidxlbn == 0) ||
|
||||
((Home.hm2_b_struclev != 2) && (Home.hm2_b_struclev != 5)) ||
|
||||
(Home.hm2_b_strucver == 0) ||
|
||||
(Home.hm2_w_cluster == 0) ||
|
||||
(Home.hm2_w_homevbn == 0) ||
|
||||
(Home.hm2_w_alhomevbn == 0) ||
|
||||
(Home.hm2_w_ibmapvbn == 0) ||
|
||||
(Home.hm2_l_ibmaplbn == 0) ||
|
||||
(Home.hm2_w_resfiles >= Home.hm2_l_maxfiles) ||
|
||||
(Home.hm2_w_ibmapsize == 0) ||
|
||||
(Home.hm2_w_resfiles < 5) ||
|
||||
(Home.hm2_w_checksum1 != CheckSum1) ||
|
||||
(Home.hm2_w_checksum2 != CheckSum2))
|
||||
goto Return_Cleanup;
|
||||
if (sim_disk_rdsect (uptr, (Home.hm2_l_ibmaplbn+Home.hm2_w_ibmapsize+1) * (512 / ctx->sector_size),
|
||||
(uint8 *)&Header, NULL, sizeof (Header) / ctx->sector_size))
|
||||
goto Return_Cleanup;
|
||||
CheckSum1 = ODSChecksum (&Header, 255);
|
||||
if (CheckSum1 != *(((uint16 *)&Header)+255)) /* Verify Checksum on BITMAP.SYS file header */
|
||||
goto Return_Cleanup;
|
||||
Retr = (ODS2_Retreval *)(((uint16*)(&Header))+Header.fh2_b_mpoffset);
|
||||
/* The BitMap File has a single extent, which may be preceeded by a placement descriptor */
|
||||
if (Retr->fm2_r_word0_bits.fm2_v_format == 0)
|
||||
Retr = (ODS2_Retreval *)(((uint16 *)Retr)+1); /* skip placement descriptor */
|
||||
switch (Retr->fm2_r_word0_bits.fm2_v_format)
|
||||
{
|
||||
case 1:
|
||||
ScbLbn = (Retr->fm2_r_map_bits1.fm2_v_highlbn1<<16)+Retr->fm2_r_map_bits1.fm2_w_lowlbn1;
|
||||
break;
|
||||
case 2:
|
||||
ScbLbn = (Retr->fm2_r_map_bits2.fm2_l_highlbn2<<16)+Retr->fm2_r_map_bits2.fm2_r_map2_long0.fm2_l_lowlbn2;
|
||||
break;
|
||||
case 3:
|
||||
ScbLbn = Retr->fm2_r_map_bits3.fm2_l_lbn3;
|
||||
break;
|
||||
}
|
||||
Retr = (ODS2_Retreval *)(((uint16 *)Retr)+Retr->fm2_r_word0_bits.fm2_v_format+1);
|
||||
if (sim_disk_rdsect (uptr, ScbLbn * (512 / ctx->sector_size), (uint8 *)&Scb, NULL, sizeof (Scb) / ctx->sector_size))
|
||||
goto Return_Cleanup;
|
||||
CheckSum1 = ODSChecksum (&Scb, 255);
|
||||
if (CheckSum1 != *(((uint16 *)&Scb)+255)) /* Verify Checksum on Storage Control Block */
|
||||
goto Return_Cleanup;
|
||||
if ((Scb.scb_w_cluster != Home.hm2_w_cluster) ||
|
||||
(Scb.scb_b_strucver != Home.hm2_b_strucver) ||
|
||||
(Scb.scb_b_struclev != Home.hm2_b_struclev))
|
||||
goto Return_Cleanup;
|
||||
if (!sim_quiet) {
|
||||
sim_printf ("%s%d: '%s' Contains ODS%d File system\n", sim_dname (dptr), (int)(uptr-dptr->units), uptr->filename, Home.hm2_b_struclev);
|
||||
sim_printf ("%s%d: Volume Name: %12.12s ", sim_dname (dptr), (int)(uptr-dptr->units), Home.hm2_t_volname);
|
||||
sim_printf ("Format: %12.12s ", Home.hm2_t_format);
|
||||
sim_printf ("Sectors In Volume: %u\n", Scb.scb_l_volsize);
|
||||
}
|
||||
ret_val = ((t_offset)Scb.scb_l_volsize) * 512;
|
||||
|
||||
Return_Cleanup:
|
||||
uptr->capac = saved_capac;
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
static t_offset get_ods1_filesystem_size (UNIT *uptr)
|
||||
{
|
||||
DEVICE *dptr;
|
||||
t_addr saved_capac;
|
||||
struct disk_context *ctx = (struct disk_context *)uptr->disk_ctx;
|
||||
t_offset temp_capac = 512 * (t_offset)0xFFFFFFFFu; /* Make sure we can access the largest sector */
|
||||
uint32 capac_factor;
|
||||
ODS1_HomeBlock Home;
|
||||
ODS1_FileHeader Header;
|
||||
ODS1_Retreval *Retr;
|
||||
uint8 scb_buf[512];
|
||||
ODS1_SCB *Scb = (ODS1_SCB *)scb_buf;
|
||||
uint16 CheckSum1, CheckSum2;
|
||||
uint32 ScbLbn;
|
||||
t_offset ret_val = (t_offset)-1;
|
||||
|
||||
if ((dptr = find_dev_from_unit (uptr)) == NULL)
|
||||
return ret_val;
|
||||
capac_factor = ((dptr->dwidth / dptr->aincr) == 16) ? 2 : 1; /* save capacity units (word: 2, byte: 1) */
|
||||
saved_capac = uptr->capac;
|
||||
uptr->capac = (t_addr)(temp_capac/(capac_factor*((dptr->flags & DEV_SECTORS) ? 512 : 1)));
|
||||
if (sim_disk_rdsect (uptr, 512 / ctx->sector_size, (uint8 *)&Home, NULL, sizeof (Home) / ctx->sector_size))
|
||||
goto Return_Cleanup;
|
||||
CheckSum1 = ODSChecksum (&Home, (uint16)((((char *)&Home.hm1_w_checksum1)-((char *)&Home.hm1_w_ibmapsize))/2));
|
||||
CheckSum2 = ODSChecksum (&Home, (uint16)((((char *)&Home.hm1_w_checksum2)-((char *)&Home.hm1_w_ibmapsize))/2));
|
||||
if ((Home.hm1_w_ibmapsize == 0) ||
|
||||
(Home.hm1_l_ibmaplbn == 0) ||
|
||||
(Home.hm1_w_maxfiles == 0) ||
|
||||
(Home.hm1_w_cluster != 1) ||
|
||||
((Home.hm1_w_structlev != HM1_C_LEVEL1) && (Home.hm1_w_structlev != HM1_C_LEVEL2)) ||
|
||||
(Home.hm1_l_ibmaplbn == 0) ||
|
||||
(Home.hm1_w_checksum1 != CheckSum1) ||
|
||||
(Home.hm1_w_checksum2 != CheckSum2))
|
||||
goto Return_Cleanup;
|
||||
if (sim_disk_rdsect (uptr, (((Home.hm1_l_ibmaplbn << 16) + ((Home.hm1_l_ibmaplbn >> 16) & 0xFFFF)) + Home.hm1_w_ibmapsize + 1) * (512 / ctx->sector_size),
|
||||
(uint8 *)&Header, NULL, sizeof (Header) / ctx->sector_size))
|
||||
goto Return_Cleanup;
|
||||
CheckSum1 = ODSChecksum (&Header, 255);
|
||||
if (CheckSum1 != *(((uint16 *)&Header)+255)) /* Verify Checksum on BITMAP.SYS file header */
|
||||
goto Return_Cleanup;
|
||||
|
||||
Retr = (ODS1_Retreval *)(((uint16*)(&Header))+Header.fh1_b_mpoffset);
|
||||
ScbLbn = (Retr->fm1_pointers[0].fm1_s_fm1def1.fm1_b_highlbn<<16)+Retr->fm1_pointers[0].fm1_s_fm1def1.fm1_w_lowlbn;
|
||||
if (sim_disk_rdsect (uptr, ScbLbn * (512 / ctx->sector_size), (uint8 *)Scb, NULL, 512 / ctx->sector_size))
|
||||
goto Return_Cleanup;
|
||||
if (Scb->scb_b_bitmapblks < 127)
|
||||
ret_val = (((t_offset)Scb->scb_r_blocks[Scb->scb_b_bitmapblks].scb_w_freeblks << 16) + Scb->scb_r_blocks[Scb->scb_b_bitmapblks].scb_w_freeptr) * 512;
|
||||
else
|
||||
ret_val = (((t_offset)Scb->scb_r_blocks[0].scb_w_freeblks << 16) + Scb->scb_r_blocks[0].scb_w_freeptr) * 512;
|
||||
if (!sim_quiet) {
|
||||
sim_printf ("%s%d: '%s' Contains an ODS1 File system\n", sim_dname (dptr), (int)(uptr-dptr->units), uptr->filename);
|
||||
sim_printf ("%s%d: Volume Name: %12.12s ", sim_dname (dptr), (int)(uptr-dptr->units), Home.hm1_t_volname);
|
||||
sim_printf ("Format: %12.12s ", Home.hm1_t_format);
|
||||
sim_printf ("Sectors In Volume: %u\n", (uint32)(ret_val / 512));
|
||||
}
|
||||
|
||||
Return_Cleanup:
|
||||
uptr->capac = saved_capac;
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
typedef struct ultrix_disklabel {
|
||||
uint32 pt_magic; /* magic no. indicating part. info exits */
|
||||
uint32 pt_valid; /* set by driver if pt is current */
|
||||
struct pt_info {
|
||||
uint32 pi_nblocks; /* no. of sectors */
|
||||
uint32 pi_blkoff; /* block offset for start */
|
||||
} pt_part[8];
|
||||
} ultrix_disklabel;
|
||||
|
||||
#define PT_MAGIC 0x032957 /* Partition magic number */
|
||||
#define PT_VALID 1 /* Indicates if struct is valid */
|
||||
|
||||
static t_offset get_ultrix_filesystem_size (UNIT *uptr)
|
||||
{
|
||||
DEVICE *dptr;
|
||||
t_addr saved_capac;
|
||||
struct disk_context *ctx = (struct disk_context *)uptr->disk_ctx;
|
||||
t_offset temp_capac = 512 * (t_offset)0xFFFFFFFFu; /* Make sure we can access the largest sector */
|
||||
uint32 capac_factor;
|
||||
uint8 sector_buf[512];
|
||||
ultrix_disklabel *Label = (ultrix_disklabel *)(sector_buf + sizeof (sector_buf) - sizeof (ultrix_disklabel));
|
||||
t_offset ret_val = (t_offset)-1;
|
||||
int i;
|
||||
uint32 max_lbn = 0, max_lbn_partnum = 0;
|
||||
|
||||
if ((dptr = find_dev_from_unit (uptr)) == NULL)
|
||||
return ret_val;
|
||||
capac_factor = ((dptr->dwidth / dptr->aincr) == 16) ? 2 : 1; /* save capacity units (word: 2, byte: 1) */
|
||||
saved_capac = uptr->capac;
|
||||
uptr->capac = (t_addr)(temp_capac/(capac_factor*((dptr->flags & DEV_SECTORS) ? 512 : 1)));
|
||||
if (sim_disk_rdsect (uptr, 31 * (512 / ctx->sector_size), sector_buf, NULL, 512 / ctx->sector_size))
|
||||
goto Return_Cleanup;
|
||||
|
||||
if ((Label->pt_magic != PT_MAGIC) ||
|
||||
(Label->pt_valid != PT_VALID))
|
||||
goto Return_Cleanup;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
uint32 end_lbn = Label->pt_part[i].pi_blkoff + Label->pt_part[i].pi_nblocks;
|
||||
if (end_lbn > max_lbn) {
|
||||
max_lbn = end_lbn;
|
||||
max_lbn_partnum = i;
|
||||
}
|
||||
}
|
||||
if (!sim_quiet) {
|
||||
sim_printf ("%s%d: '%s' Contains Ultrix partitions\n", sim_dname (dptr), (int)(uptr-dptr->units), uptr->filename);
|
||||
sim_printf ("Partition with highest sector: %c, Sectors On Disk: %u\n", 'a' + max_lbn_partnum, max_lbn);
|
||||
}
|
||||
ret_val = ((t_offset)max_lbn) * 512;
|
||||
|
||||
Return_Cleanup:
|
||||
uptr->capac = saved_capac;
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
typedef t_offset (*FILESYSTEM_CHECK)(UNIT *uptr);
|
||||
|
||||
static t_offset get_filesystem_size (UNIT *uptr)
|
||||
{
|
||||
static FILESYSTEM_CHECK checks[] = {
|
||||
&get_ods2_filesystem_size,
|
||||
&get_ods1_filesystem_size,
|
||||
&get_ultrix_filesystem_size,
|
||||
NULL
|
||||
};
|
||||
t_offset ret_val;
|
||||
int i;
|
||||
|
||||
for (i = 0; checks[i] != NULL; i++) {
|
||||
ret_val = checks[i] (uptr);
|
||||
if (ret_val != (t_offset)-1)
|
||||
break;
|
||||
}
|
||||
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,
|
||||
uint32 dbit, const char *dtype, uint32 pdp11tracksize, int completion_delay)
|
||||
@@ -854,7 +1308,7 @@ t_offset (*size_function)(FILE *file);
|
||||
t_stat (*storage_function)(FILE *file, uint32 *sector_size, uint32 *removable) = NULL;
|
||||
t_bool created = FALSE, copied = FALSE;
|
||||
t_bool auto_format = FALSE;
|
||||
t_offset capac;
|
||||
t_offset capac, filesystem_capac;
|
||||
|
||||
if (uptr->flags & UNIT_DIS) /* disabled? */
|
||||
return SCPE_UDIS;
|
||||
@@ -1044,6 +1498,8 @@ else
|
||||
switch (DK_GET_FMT (uptr)) { /* case on format */
|
||||
case DKUF_F_STD: /* SIMH format */
|
||||
if (NULL == (uptr->fileref = sim_vhd_disk_open (cptr, "rb"))) {
|
||||
if (errno == EBADF) /* VHD but broken */
|
||||
return SCPE_OPENERR;
|
||||
open_function = sim_fopen;
|
||||
size_function = sim_fsize_ex;
|
||||
break;
|
||||
@@ -1139,7 +1595,7 @@ if (storage_function)
|
||||
|
||||
if ((created) && (!copied)) {
|
||||
t_stat r = SCPE_OK;
|
||||
uint8 *secbuf = (uint8 *)calloc (1, ctx->sector_size); /* alloc temp sector buf */
|
||||
uint8 *secbuf = (uint8 *)calloc (128, ctx->sector_size); /* alloc temp sector buf */
|
||||
|
||||
/*
|
||||
On a newly created disk, we write a zero sector to the last and the
|
||||
@@ -1154,10 +1610,16 @@ if ((created) && (!copied)) {
|
||||
*/
|
||||
if (secbuf == NULL)
|
||||
r = SCPE_MEM;
|
||||
if (r == SCPE_OK)
|
||||
r = sim_disk_wrsect (uptr, (t_lba)(((((t_offset)uptr->capac)*ctx->capac_factor*((dptr->flags & DEV_SECTORS) ? 512 : 1)) - ctx->sector_size)/ctx->sector_size), secbuf, NULL, 1); /* Write Last Sector */
|
||||
if (r == SCPE_OK)
|
||||
r = sim_disk_wrsect (uptr, (t_lba)(0), secbuf, NULL, 1); /* Write First Sector */
|
||||
if (r == SCPE_OK) { /* Write all blocks */
|
||||
t_lba lba;
|
||||
t_lba total_lbas = (t_lba)((((t_offset)uptr->capac)*ctx->capac_factor*((dptr->flags & DEV_SECTORS) ? 512 : 1))/ctx->sector_size);
|
||||
|
||||
for (lba = 0; (r == SCPE_OK) && (lba < total_lbas); lba += 128) {
|
||||
t_seccnt sectors = ((lba + 128) <= total_lbas) ? 128 : total_lbas - lba;
|
||||
|
||||
r = sim_disk_wrsect (uptr, lba, secbuf, NULL, sectors);
|
||||
}
|
||||
}
|
||||
free (secbuf);
|
||||
if (r != SCPE_OK) {
|
||||
sim_disk_detach (uptr); /* report error now */
|
||||
@@ -1198,9 +1660,10 @@ if ((created) && (!copied)) {
|
||||
}
|
||||
if (!sim_quiet)
|
||||
sim_printf ("%s%d: Initialized To Sector Address %dMB. 100%% complete.\n", sim_dname (dptr), (int)(uptr-dptr->units), (int)((((float)lba)*sector_size)/1000000));
|
||||
free (init_buf);
|
||||
}
|
||||
if (pdp11tracksize)
|
||||
sim_disk_pdp11_bad_block (uptr, pdp11tracksize);
|
||||
sim_disk_pdp11_bad_block (uptr, pdp11tracksize, sector_size/sizeof(uint16));
|
||||
}
|
||||
|
||||
if (sim_switches & SWMASK ('K')) {
|
||||
@@ -1254,22 +1717,42 @@ if (sim_switches & SWMASK ('K')) {
|
||||
uptr->dynflags |= UNIT_DISK_CHK;
|
||||
}
|
||||
|
||||
filesystem_capac = get_filesystem_size (uptr);
|
||||
capac = size_function (uptr->fileref);
|
||||
if (capac && (capac != (t_offset)-1)) {
|
||||
if (dontautosize) {
|
||||
t_addr saved_capac = uptr->capac;
|
||||
|
||||
if ((filesystem_capac != (t_offset)-1) &&
|
||||
(filesystem_capac > (((t_offset)uptr->capac)*ctx->capac_factor*((dptr->flags & DEV_SECTORS) ? 512 : 1)))) {
|
||||
if (!sim_quiet) {
|
||||
uptr->capac = (t_addr)(filesystem_capac/(ctx->capac_factor*((dptr->flags & DEV_SECTORS) ? 512 : 1)));
|
||||
sim_printf ("%s%d: The file system on the disk %s is larger than simulated device (%s > ", sim_dname (dptr), (int)(uptr-dptr->units), cptr, sprint_capac (dptr, uptr));
|
||||
uptr->capac = saved_capac;
|
||||
sim_printf ("%s)\n", sprint_capac (dptr, uptr));
|
||||
}
|
||||
sim_disk_detach (uptr);
|
||||
return SCPE_OPENERR;
|
||||
}
|
||||
if ((capac < (((t_offset)uptr->capac)*ctx->capac_factor*((dptr->flags & DEV_SECTORS) ? 512 : 1))) && (DKUF_F_STD != DK_GET_FMT (uptr))) {
|
||||
if (!sim_quiet) {
|
||||
sim_printf ("%s%d: non expandable disk %s is smaller than simulated device (", sim_dname (dptr), (int)(uptr-dptr->units), cptr);
|
||||
sim_print_val ((t_addr)(capac/ctx->capac_factor), 10, T_ADDR_W, PV_LEFT);
|
||||
sim_printf ("%s < ", (ctx->capac_factor == 2) ? "W" : "");
|
||||
sim_print_val (uptr->capac*((dptr->flags & DEV_SECTORS) ? 512 : 1), 10, T_ADDR_W, PV_LEFT);
|
||||
sim_printf ("%s)\n", (ctx->capac_factor == 2) ? "W" : "");
|
||||
uptr->capac = (t_addr)(capac/(ctx->capac_factor*((dptr->flags & DEV_SECTORS) ? 512 : 1)));
|
||||
sim_printf ("%s%d: non expandable disk %s is smaller than simulated device (%s < ", sim_dname (dptr), (int)(uptr-dptr->units), cptr, sprint_capac (dptr, uptr));
|
||||
uptr->capac = saved_capac;
|
||||
sim_printf ("%s)\n", sprint_capac (dptr, uptr));
|
||||
}
|
||||
sim_disk_detach (uptr);
|
||||
return SCPE_OPENERR;
|
||||
}
|
||||
}
|
||||
else
|
||||
if ((capac > (((t_offset)uptr->capac)*ctx->capac_factor*((dptr->flags & DEV_SECTORS) ? 512 : 1))) || (DKUF_F_STD != DK_GET_FMT (uptr)))
|
||||
else {
|
||||
if ((filesystem_capac != (t_offset)-1) &&
|
||||
(filesystem_capac > capac))
|
||||
capac = filesystem_capac;
|
||||
if ((capac != (((t_offset)uptr->capac)*ctx->capac_factor*((dptr->flags & DEV_SECTORS) ? 512 : 1))) ||
|
||||
(DKUF_F_STD != DK_GET_FMT (uptr)))
|
||||
uptr->capac = (t_addr)(capac/(ctx->capac_factor*((dptr->flags & DEV_SECTORS) ? 512 : 1)));
|
||||
}
|
||||
}
|
||||
|
||||
#if defined (SIM_ASYNCH_IO)
|
||||
@@ -1396,6 +1879,7 @@ fprintf (st, " disk)\n");
|
||||
fprintf (st, " -M Merge a Differencing VHD into its parent VHD disk\n");
|
||||
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");
|
||||
fprintf (st, "Examples:\n");
|
||||
@@ -1528,20 +2012,21 @@ return SCPE_OK;
|
||||
Inputs:
|
||||
uptr = pointer to unit
|
||||
sec = number of sectors per surface
|
||||
wds = number of words per sector
|
||||
Outputs:
|
||||
sta = status code
|
||||
*/
|
||||
|
||||
static t_stat sim_disk_pdp11_bad_block (UNIT *uptr, int32 sec)
|
||||
t_stat sim_disk_pdp11_bad_block (UNIT *uptr, int32 sec, int32 wds)
|
||||
{
|
||||
struct disk_context *ctx = (struct disk_context *)uptr->disk_ctx;
|
||||
int32 i;
|
||||
t_addr da;
|
||||
int32 wds = ctx->sector_size/sizeof (uint16);
|
||||
uint16 *buf;
|
||||
DEVICE *dptr;
|
||||
char *namebuf, *c;
|
||||
uint32 packid;
|
||||
t_stat stat = SCPE_OK;
|
||||
|
||||
if ((sec < 2) || (wds < 16))
|
||||
return SCPE_ARG;
|
||||
@@ -1551,8 +2036,6 @@ if ((dptr = find_dev_from_unit (uptr)) == NULL)
|
||||
return SCPE_NOATT;
|
||||
if (uptr->flags & UNIT_RO)
|
||||
return SCPE_RO;
|
||||
if (ctx->capac_factor != 2) /* Must be Word oriented Capacity */
|
||||
return SCPE_IERR;
|
||||
if (!get_yn ("Overwrite last track? [N]", FALSE))
|
||||
return SCPE_OK;
|
||||
if ((buf = (uint16 *) malloc (wds * sizeof (uint16))) == NULL)
|
||||
@@ -1571,24 +2054,30 @@ buf[2] = buf[3] = 0;
|
||||
for (i = 4; i < wds; i++)
|
||||
buf[i] = 0177777u;
|
||||
da = (uptr->capac*((dptr->flags & DEV_SECTORS) ? 512 : 1)) - (sec * wds);
|
||||
for (i = 0; (i < sec) && (i < 10); i++, da += wds)
|
||||
if (sim_disk_wrsect (uptr, (t_lba)(da/wds), (uint8 *)buf, NULL, 1)) {
|
||||
free (buf);
|
||||
return SCPE_IOERR;
|
||||
for (i = 0; (stat == SCPE_OK) && (i < sec) && (i < 10); i++, da += wds)
|
||||
if (ctx)
|
||||
stat = sim_disk_wrsect (uptr, (t_lba)(da/wds), (uint8 *)buf, NULL, 1);
|
||||
else {
|
||||
if (sim_fseek (uptr->fileref, da, SEEK_SET)) {
|
||||
stat = SCPE_IOERR;
|
||||
break;
|
||||
}
|
||||
if (wds != sim_fwrite (buf, sizeof (uint16), wds, uptr->fileref))
|
||||
stat = SCPE_IOERR;
|
||||
}
|
||||
free (buf);
|
||||
return SCPE_OK;
|
||||
return stat;
|
||||
}
|
||||
|
||||
void sim_disk_data_trace(UNIT *uptr, const uint8 *data, size_t lba, size_t len, const char* txt, int detail, uint32 reason)
|
||||
{
|
||||
struct disk_context *ctx = (struct disk_context *)uptr->disk_ctx;
|
||||
DEVICE *dptr = find_dev_from_unit (uptr);
|
||||
|
||||
if (sim_deb && (ctx->dptr->dctrl & reason)) {
|
||||
if (sim_deb && (dptr->dctrl & reason)) {
|
||||
char pos[32];
|
||||
|
||||
sprintf (pos, "lbn: %08X ", (unsigned int)lba);
|
||||
sim_data_trace(ctx->dptr, uptr, (detail ? data : NULL), pos, len, txt, reason);
|
||||
sim_data_trace(dptr, uptr, (detail ? data : NULL), pos, len, txt, reason);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1674,9 +2163,18 @@ errno = EINVAL;
|
||||
#else
|
||||
#include <winioctl.h>
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
WINBASEAPI BOOL WINAPI GetFileSizeEx(HANDLE hFile, PLARGE_INTEGER lpFileSize);
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
struct _device_type {
|
||||
int32 Type;
|
||||
char *desc;
|
||||
const char *desc;
|
||||
} DeviceTypes[] = {
|
||||
{FILE_DEVICE_8042_PORT, "8042_PORT"},
|
||||
{FILE_DEVICE_ACPI, "ACPI"},
|
||||
@@ -1821,7 +2319,6 @@ static t_offset sim_os_disk_size_raw (FILE *Disk)
|
||||
{
|
||||
DWORD IoctlReturnSize;
|
||||
LARGE_INTEGER Size;
|
||||
WINBASEAPI BOOL WINAPI GetFileSizeEx(HANDLE hFile, PLARGE_INTEGER lpFileSize);
|
||||
|
||||
if (GetFileSizeEx((HANDLE)Disk, &Size))
|
||||
return (t_offset)(Size.QuadPart);
|
||||
@@ -2872,29 +3369,47 @@ if ((sDynamic) &&
|
||||
if (0 == memcmp (sDynamic->ParentLocatorEntries[j].PlatformCode, "W2ru", 4)) {
|
||||
const char *c;
|
||||
|
||||
if ((c = strrchr (szVHDPath, '\\')))
|
||||
memcpy (CheckPath, szVHDPath, c-szVHDPath+1);
|
||||
strncpy (CheckPath+strlen(CheckPath), ParentName, sizeof (CheckPath)-(strlen (CheckPath)+1));
|
||||
if ((c = strrchr (szVHDPath, '\\'))) {
|
||||
memcpy (CheckPath, szVHDPath, c-szVHDPath+1);
|
||||
strncpy (CheckPath+strlen(CheckPath), ParentName, sizeof (CheckPath)-(strlen (CheckPath)+1));
|
||||
}
|
||||
}
|
||||
VhdPathToHostPath (CheckPath, CheckPath, sizeof (CheckPath));
|
||||
if ((0 == GetVHDFooter(CheckPath,
|
||||
&sParentFooter,
|
||||
NULL,
|
||||
NULL,
|
||||
&ParentModificationTime,
|
||||
NULL,
|
||||
0)) &&
|
||||
(0 == memcmp (sDynamic->ParentUniqueID, sParentFooter.UniqueID, sizeof (sParentFooter.UniqueID))) &&
|
||||
((sDynamic->ParentTimeStamp == ParentModificationTime) ||
|
||||
((NtoHl(sDynamic->ParentTimeStamp)-NtoHl(ParentModificationTime)) == 3600) ||
|
||||
(sim_switches & SWMASK ('O')))) {
|
||||
strncpy (szParentVHDPath, CheckPath, ParentVHDPathSize);
|
||||
if (0 == GetVHDFooter(CheckPath,
|
||||
&sParentFooter,
|
||||
NULL,
|
||||
NULL,
|
||||
&ParentModificationTime,
|
||||
NULL,
|
||||
0)) {
|
||||
if ((0 == memcmp (sDynamic->ParentUniqueID, sParentFooter.UniqueID, sizeof (sParentFooter.UniqueID))) &&
|
||||
((sDynamic->ParentTimeStamp == ParentModificationTime) ||
|
||||
((NtoHl(sDynamic->ParentTimeStamp)-NtoHl(ParentModificationTime)) == 3600) ||
|
||||
(sim_switches & SWMASK ('O'))))
|
||||
strncpy (szParentVHDPath, CheckPath, ParentVHDPathSize);
|
||||
else {
|
||||
if (0 != memcmp (sDynamic->ParentUniqueID, sParentFooter.UniqueID, sizeof (sParentFooter.UniqueID)))
|
||||
sim_printf ("Error Invalid Parent VHD '%s' for Differencing VHD: %s\n", CheckPath, szVHDPath);
|
||||
else
|
||||
sim_printf ("Error Parent VHD '%s' has been modified since Differencing VHD: %s was created\n", CheckPath, szVHDPath);
|
||||
Return = EINVAL; /* File Corrupt/Invalid */
|
||||
}
|
||||
break;
|
||||
}
|
||||
else {
|
||||
struct stat statb;
|
||||
|
||||
if (0 == stat (CheckPath, &statb)) {
|
||||
sim_printf ("Parent VHD '%s' corrupt for Differencing VHD: %s\n", CheckPath, szVHDPath);
|
||||
Return = EBADF; /* File Corrupt/Invalid */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!*szParentVHDPath) {
|
||||
Return = EINVAL; /* File Corrupt */
|
||||
sim_printf ("Error Invalid Parent VHD for Differencing VHD\n");
|
||||
if (Return != EINVAL) /* File Not Corrupt? */
|
||||
sim_printf ("Missing Parent VHD for Differencing VHD: %s\n", szVHDPath);
|
||||
Return = EBADF;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2985,6 +3500,7 @@ return (char *)(&hVHD->Footer.DriveType[0]);
|
||||
static FILE *sim_vhd_disk_open (const char *szVHDPath, const char *DesiredAccess)
|
||||
{
|
||||
VHDHANDLE hVHD = (VHDHANDLE) calloc (1, sizeof(*hVHD));
|
||||
int NeedUpdate = FALSE;
|
||||
int Status;
|
||||
|
||||
if (!hVHD)
|
||||
@@ -3017,9 +3533,22 @@ static FILE *sim_vhd_disk_open (const char *szVHDPath, const char *DesiredAccess
|
||||
0);
|
||||
if (Status)
|
||||
goto Cleanup_Return;
|
||||
if (ParentModifiedTimeStamp != hVHD->Dynamic.ParentTimeStamp) {
|
||||
Status = EBADF;
|
||||
goto Cleanup_Return;
|
||||
if ((0 != memcmp (hVHD->Dynamic.ParentUniqueID, ParentFooter.UniqueID, sizeof (ParentFooter.UniqueID))) ||
|
||||
(ParentModifiedTimeStamp != hVHD->Dynamic.ParentTimeStamp)) {
|
||||
if (sim_switches & SWMASK ('O')) { /* OVERRIDE consistency checks? */
|
||||
if ((sim_switches & SWMASK ('U')) && /* FIX (UPDATE) consistency checks AND */
|
||||
(strchr (DesiredAccess, '+'))) { /* open for write/update? */
|
||||
memcpy (hVHD->Dynamic.ParentUniqueID, ParentFooter.UniqueID, sizeof (ParentFooter.UniqueID));
|
||||
hVHD->Dynamic.ParentTimeStamp = ParentModifiedTimeStamp;
|
||||
hVHD->Dynamic.Checksum = 0;
|
||||
hVHD->Dynamic.Checksum = NtoHl (CalculateVhdFooterChecksum (&hVHD->Dynamic, sizeof(hVHD->Dynamic)));
|
||||
NeedUpdate = TRUE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
Status = EBADF;
|
||||
goto Cleanup_Return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (hVHD->Footer.SavedState) {
|
||||
@@ -3036,6 +3565,18 @@ Cleanup_Return:
|
||||
sim_vhd_disk_close ((FILE *)hVHD);
|
||||
hVHD = NULL;
|
||||
}
|
||||
else {
|
||||
if (NeedUpdate) { /* Update Differencing Disk Header? */
|
||||
if (WriteFilePosition(hVHD->File,
|
||||
&hVHD->Dynamic,
|
||||
sizeof (hVHD->Dynamic),
|
||||
NULL,
|
||||
NtoHll (hVHD->Footer.DataOffset))) {
|
||||
sim_vhd_disk_close ((FILE *)hVHD);
|
||||
hVHD = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
errno = Status;
|
||||
return (FILE *)hVHD;
|
||||
}
|
||||
@@ -3452,7 +3993,7 @@ if ((szFileSpec[0] != '/') || (strchr (szFileSpec, ':')))
|
||||
else
|
||||
strncpy (szFullFileSpecBuffer, szFileSpec, BufferSize);
|
||||
if ((c = strstr (szFullFileSpecBuffer, "]/")))
|
||||
memcpy (c+1, c+2, strlen(c+2)+1);
|
||||
memmove (c+1, c+2, strlen(c+2)+1);
|
||||
memset (szFullFileSpecBuffer + strlen (szFullFileSpecBuffer), 0, BufferSize - strlen (szFullFileSpecBuffer));
|
||||
#endif
|
||||
}
|
||||
@@ -3480,14 +4021,14 @@ if ((c = strrchr (szVhdPath, ']'))) {
|
||||
while ((c = strchr (szVhdPath, '/')))
|
||||
*c = '\\';
|
||||
for (c = strstr (szVhdPath, "\\.\\"); c; c = strstr (szVhdPath, "\\.\\"))
|
||||
memcpy (c, c+2, strlen(c+2)+1);
|
||||
memmove (c, c+2, strlen(c+2)+1);
|
||||
for (c = strstr (szVhdPath, "\\\\"); c; c = strstr (szVhdPath, "\\\\"))
|
||||
memcpy (c, c+1, strlen(c+1)+1);
|
||||
memmove (c, c+1, strlen(c+1)+1);
|
||||
while ((c = strstr (szVhdPath, "\\..\\"))) {
|
||||
*c = '\0';
|
||||
d = strrchr (szVhdPath, '\\');
|
||||
if (d)
|
||||
memcpy (d, c+3, strlen(c+3)+1);
|
||||
memmove (d, c+3, strlen(c+3)+1);
|
||||
else
|
||||
return d;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user