mirror of
https://github.com/ctm/executor.git
synced 2024-11-12 08:08:23 +00:00
265 lines
5.7 KiB
C
265 lines
5.7 KiB
C
|
/* Copyright 1997 by Abacus Research and
|
||
|
* Development, Inc. All rights reserved.
|
||
|
*/
|
||
|
|
||
|
#if !defined (OMIT_RCSID_STRINGS)
|
||
|
char ROMlib_rcsid_checkpoint[] =
|
||
|
"$Id: checkpoint.c 63 2004-12-24 18:19:43Z ctm $";
|
||
|
#endif
|
||
|
|
||
|
#if defined (STANDALONE_TEST)
|
||
|
|
||
|
#warning do not check this in
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
typedef unsigned char boolean_t;
|
||
|
typedef unsigned int uint32;
|
||
|
#define PUBLIC
|
||
|
#define PRIVATE static
|
||
|
PRIVATE uint32 ROMlib_macdrives;
|
||
|
PRIVATE uint32 ROMlib_dosdrives;
|
||
|
enum { FALSE, TRUE };
|
||
|
|
||
|
#endif
|
||
|
|
||
|
#include "rsys/common.h"
|
||
|
#include "rsys/stdfile.h"
|
||
|
#include "rsys/option.h"
|
||
|
#include "rsys/checkpoint.h"
|
||
|
|
||
|
#if defined (MSDOS) || defined (CYGWIN32)
|
||
|
|
||
|
#if defined (CYGWIN32)
|
||
|
#include "winfs.h"
|
||
|
#endif
|
||
|
|
||
|
PRIVATE boolean_t checkpointing_p = TRUE;
|
||
|
|
||
|
PUBLIC checkpoint_t *checkpointp; /* globals are bad, but we use one in
|
||
|
this case because checkpointing is
|
||
|
effectively a global issue currently
|
||
|
and we don't want to modify the various
|
||
|
routines that we checkpoint to take
|
||
|
an additional argument */
|
||
|
|
||
|
PRIVATE uint32
|
||
|
extract_bad_drives_from_string (const char *opt, const char *str)
|
||
|
{
|
||
|
int len;
|
||
|
char *p;
|
||
|
uint32 good_drives;
|
||
|
uint32 retval;
|
||
|
|
||
|
while (*str != ' ')
|
||
|
++str;
|
||
|
++str;
|
||
|
len = strspn (str, "abcdefghijklmnopqrstuvwxyz-");
|
||
|
p = alloca (len+1);
|
||
|
memcpy (p, str, len);
|
||
|
p[len] = 0;
|
||
|
good_drives = parse_drive_opt (opt, p);
|
||
|
retval = ~good_drives & ((1 << 26)-1);
|
||
|
return retval;
|
||
|
}
|
||
|
|
||
|
PUBLIC checkpoint_t *
|
||
|
checkpoint_init (void)
|
||
|
{
|
||
|
checkpoint_t *retval;
|
||
|
FILE *fp;
|
||
|
|
||
|
retval = malloc (sizeof *retval);
|
||
|
memset (retval, 0, sizeof *retval);
|
||
|
fp = executor_dir_fopen (CHECKPOINT_FILE, "r");
|
||
|
if (fp)
|
||
|
{
|
||
|
char buf[1024], *p;
|
||
|
int nread;
|
||
|
|
||
|
nread = fread (buf, 1, sizeof buf-1, fp);
|
||
|
fclose (fp);
|
||
|
buf[sizeof buf -1] = 0;
|
||
|
if (strstr (buf, "-nosound"))
|
||
|
retval->sound_fails = TRUE;
|
||
|
if (strstr (buf, "-skipaspi"))
|
||
|
retval->aspi_fails = TRUE;
|
||
|
p = strstr (buf, "-macdrives ");
|
||
|
if (p)
|
||
|
retval->bad_macdrives
|
||
|
= extract_bad_drives_from_string ("macdrives", p);
|
||
|
p = strstr (buf, "-dosdrives ");
|
||
|
if (p)
|
||
|
retval->bad_dosdrives
|
||
|
= extract_bad_drives_from_string ("dosdrives", p);
|
||
|
}
|
||
|
return retval;
|
||
|
}
|
||
|
|
||
|
PRIVATE void
|
||
|
write_drive_string (FILE *fp, uint32 drive)
|
||
|
{
|
||
|
drive &= (1 << 26)-1; /* only represent A-Z */
|
||
|
if (!drive)
|
||
|
fprintf (fp, "\"\"\n");
|
||
|
else
|
||
|
{
|
||
|
int drive_bit;
|
||
|
|
||
|
drive_bit = 0;
|
||
|
while (drive)
|
||
|
{
|
||
|
while ((drive & (1 << drive_bit)) == 0)
|
||
|
drive_bit++;
|
||
|
if ((drive & (1 << (drive_bit+1))) == 0)
|
||
|
{
|
||
|
fprintf (fp, "%c", 'a' + drive_bit);
|
||
|
drive &= ~(1 << drive_bit);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if ((drive & (1 << (drive_bit+2))) == 0)
|
||
|
{
|
||
|
fprintf (fp, "%c%c", 'a' + drive_bit, 'a' + drive_bit + 1);
|
||
|
drive &= ~((1 << drive_bit) | (1 << (drive_bit+1)));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
int last_good_bit;
|
||
|
uint32 mask;
|
||
|
|
||
|
last_good_bit = drive_bit+2;
|
||
|
mask = (1 << drive_bit) | (1 << (drive_bit+1))
|
||
|
| (1 << (drive_bit+2));
|
||
|
while ((drive & (1 << (last_good_bit+1))) != 0)
|
||
|
{
|
||
|
++last_good_bit;
|
||
|
mask |= (1 << last_good_bit);
|
||
|
}
|
||
|
fprintf (fp, "%c-%c", 'a' + drive_bit, 'a' + last_good_bit);
|
||
|
drive &= ~mask;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
fprintf (fp, "\n");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#define CHECKPOINT_PREAMBLE \
|
||
|
"# This file was created because Executor found a problem while it was\n" \
|
||
|
"# probing your system. The lines in this file that don't start with\n" \
|
||
|
"# a '#' are commands that Executor uses to bypass the failing subsystems.\n" \
|
||
|
"#\n" \
|
||
|
"# DO NOT ALTER THIS FILE unless you know what you're doing and even then\n" \
|
||
|
"# make sure you make a backup, first.\n"
|
||
|
|
||
|
PRIVATE void
|
||
|
write_checkpoint_file (checkpoint_t *cp)
|
||
|
{
|
||
|
FILE *fp;
|
||
|
|
||
|
if (!(cp->sound_fails
|
||
|
|| cp->aspi_fails
|
||
|
|| cp->bad_macdrives
|
||
|
|| cp->bad_dosdrives))
|
||
|
executor_dir_remove (CHECKPOINT_FILE);
|
||
|
else
|
||
|
{
|
||
|
fp = executor_dir_fopen (CHECKPOINT_FILE, "w");
|
||
|
if (fp)
|
||
|
{
|
||
|
fprintf (fp, CHECKPOINT_PREAMBLE);
|
||
|
if (cp->sound_fails)
|
||
|
fprintf (fp, "-nosound\n");
|
||
|
if (cp->aspi_fails)
|
||
|
fprintf (fp, "-skipaspi\n");
|
||
|
if (cp->bad_macdrives)
|
||
|
{
|
||
|
uint32 macdrives;
|
||
|
|
||
|
macdrives = ROMlib_macdrives ? ROMlib_macdrives : ~0;
|
||
|
macdrives &= ~cp->bad_macdrives;
|
||
|
fprintf (fp, "-macdrives ");
|
||
|
write_drive_string (fp, macdrives);
|
||
|
}
|
||
|
if (cp->bad_dosdrives)
|
||
|
{
|
||
|
uint32 dosdrives;
|
||
|
|
||
|
dosdrives = ROMlib_dosdrives ? ROMlib_dosdrives : ~0;
|
||
|
dosdrives &= ~cp->bad_dosdrives;
|
||
|
fprintf (fp, "-dosdrives ");
|
||
|
write_drive_string (fp, dosdrives);
|
||
|
}
|
||
|
fclose (fp);
|
||
|
sync ();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
PUBLIC void
|
||
|
checkpoint_sound (checkpoint_t *cp, checkpoint_option option)
|
||
|
{
|
||
|
if (checkpointing_p && cp)
|
||
|
{
|
||
|
cp->sound_fails = option == begin;
|
||
|
write_checkpoint_file (cp);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
PUBLIC void
|
||
|
checkpoint_aspi (checkpoint_t *cp, checkpoint_option option)
|
||
|
{
|
||
|
if (checkpointing_p && cp)
|
||
|
{
|
||
|
cp->aspi_fails = option == begin;
|
||
|
write_checkpoint_file (cp);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
PUBLIC void
|
||
|
checkpoint_macdrive (checkpoint_t *cp, checkpoint_option option, uint32 drive)
|
||
|
{
|
||
|
if (checkpointing_p && cp)
|
||
|
{
|
||
|
if (option == begin)
|
||
|
cp->bad_macdrives |= drive;
|
||
|
else
|
||
|
cp->bad_macdrives &= ~drive;
|
||
|
write_checkpoint_file (cp);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
PUBLIC void
|
||
|
checkpoint_dosdrives (checkpoint_t *cp, checkpoint_option option, uint32 drive)
|
||
|
{
|
||
|
if (checkpointing_p && cp)
|
||
|
{
|
||
|
if (option == begin)
|
||
|
cp->bad_dosdrives |= drive;
|
||
|
else
|
||
|
cp->bad_dosdrives &= ~drive;
|
||
|
write_checkpoint_file (cp);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
PUBLIC void
|
||
|
disable_checkpointing (void)
|
||
|
{
|
||
|
checkpointing_p = FALSE;
|
||
|
}
|
||
|
|
||
|
#if defined (STANDALONE_TEST)
|
||
|
PUBLIC int
|
||
|
main (void)
|
||
|
{
|
||
|
checkpoint_t *cp;
|
||
|
|
||
|
cp = checkpoint_init ();
|
||
|
return 0;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
#endif
|