feat: add -z (--strip) to remove ECC data from an iso

This commit is contained in:
Stéphane Lesimple
2021-01-30 12:18:03 +01:00
parent fd4f8424f7
commit c336d039a9
12 changed files with 165 additions and 8 deletions

View File

@@ -67,6 +67,7 @@ typedef enum
MODE_SHOW_SECTOR,
MODE_TRUNCATE,
MODE_ZERO_UNREADABLE,
MODE_STRIP_ECC,
/* don't use the ascii range 32-127 so that we
avoid collision with the single-char options */
@@ -280,6 +281,7 @@ int main(int argc, char *argv[])
{"sim-defects", 1, 0, MODIFIER_SIMULATE_DEFECTS},
{"speed-warning", 2, 0, MODIFIER_SPEED_WARNING},
{"spinup-delay", 1, 0, MODIFIER_SPINUP_DELAY},
{"strip", 0, 0, 'z'},
{"test", 2, 0, 't'},
{"threads", 1, 0, 'x'},
{"truncate", 2, 0, MODIFIER_TRUNCATE},
@@ -291,7 +293,7 @@ int main(int argc, char *argv[])
};
c = getopt_long(argc, argv,
"a:cd:e:fhi:j:lm::n:o:p:r::s::t::uvx:",
"a:cd:e:fhi:j:lm::n:o:p:r::s::t::uvx:z",
long_options, &option_index);
if(c == -1) break;
@@ -395,6 +397,9 @@ int main(int argc, char *argv[])
if(Closure->codecThreads < 1 || Closure->codecThreads > MAX_CODEC_THREADS)
Stop(_("--threads must be 1..%d\n"), MAX_CODEC_THREADS);
break;
case 'z':
mode = MODE_STRIP_ECC;
break;
case 0 : break; /* flag argument */
@@ -918,6 +923,10 @@ int main(int argc, char *argv[])
TruncateImageFile(debug_arg);
break;
case MODE_STRIP_ECC:
StripECCFromImageFile();
break;
case MODE_ZERO_UNREADABLE:
ZeroUnreadable();
break;
@@ -945,6 +954,7 @@ int main(int argc, char *argv[])
" dvdisaster -f,--fix # Try to fix medium image using .ecc information.\n"
" dvdisaster -s,--scan # Scan the medium for read errors.\n"
" dvdisaster -t,--test # Test integrity of the .iso and .ecc files.\n"
" dvdisaster -z,--strip # Strip ECC data from an augmented .iso.\n"
" dvdisaster -u,--unlink # Delete .iso files (when other actions complete)\n\n"));
PrintCLI(_("Drive and file specification:\n"

View File

@@ -354,6 +354,7 @@ typedef struct _GlobalClosure
GtkWidget *scanButton;
GtkWidget *fixButton;
GtkWidget *testButton;
GtkWidget *stripButton;
/*** The preferences window */
@@ -1012,7 +1013,8 @@ typedef enum
ACTION_VERIFY, /* VERIFY, CREATE and FIX have separate windows assigned */
ACTION_CREATE, /* for each method. */
ACTION_CREATE_CONT,
ACTION_FIX
ACTION_FIX,
ACTION_STRIP /* --- does not have a window */
} MajorActions;
void CreateMainWindow(int*, char***);
@@ -1200,6 +1202,7 @@ void LockLabelSize(GtkLabel*, char*, ...) PRINTF_FORMAT(2);
int ConfirmImageDeletion(char *);
int ConfirmEccDeletion(char *);
void StripECCFromImageFile(void);
#ifndef WITH_CLI_ONLY_YES
/***

View File

@@ -72,6 +72,7 @@ void CreateIconFactory()
create_icon(ifact, "dvdisaster-scan", dvdisaster_scan);
create_icon(ifact, "dvdisaster-fix", dvdisaster_fix);
create_icon(ifact, "dvdisaster-verify", dvdisaster_verify);
create_icon(ifact, "dvdisaster-strip", dvdisaster_strip);
/*** Stock GTK icons to defeat theming */

View File

@@ -189,6 +189,11 @@ static void action_cb(GtkWidget *widget, gpointer data)
CreateGThread((GThreadFunc)ReadMediumLinear, (gpointer)1);
break;
case ACTION_STRIP:
AllowActions(FALSE);
CreateGThread((GThreadFunc)StripECCFromImageFile, (gpointer)0);
break;
case ACTION_VERIFY:
/* If something is wrong with the .iso or .ecc files
we fall back to the RS01 method for verifying since it is robust
@@ -315,6 +320,13 @@ static GtkWidget* create_action_bar(GtkNotebook *notebook)
gtk_box_pack_start(GTK_BOX(vbox), wid, FALSE, FALSE, 0);
AttachTooltip(wid, _("tooltip|Consistency check"), _("Tests consistency of error correction data and image file."));
/*** Strip */
Closure->stripButton = wid = create_button(_("button|Strip"), "dvdisaster-strip");
g_signal_connect(G_OBJECT(wid), "clicked", G_CALLBACK(action_cb), (gpointer)ACTION_STRIP);
gtk_box_pack_start(GTK_BOX(vbox), wid, FALSE, FALSE, 0);
AttachTooltip(wid, _("tooltip|Strip ECC"), _("Strip ECC data from an augmented image."));
/*** Stop */
wid = create_button(_("button|Stop"), "dvdisaster-gtk-stop");

View File

@@ -822,6 +822,7 @@ static gboolean allow_actions_idle_func(gpointer data)
gtk_widget_set_sensitive(Closure->createButton, s);
gtk_widget_set_sensitive(Closure->fixButton, s);
gtk_widget_set_sensitive(Closure->testButton, s);
gtk_widget_set_sensitive(Closure->stripButton, s);
gtk_widget_set_sensitive(Closure->prefsButton, s);
if(!s && Closure->prefsWindow)
@@ -1358,3 +1359,78 @@ int ConfirmEccDeletion(char *file)
#endif
}
/*
* --strip method and associated cleanup func
*/
static void stripecc_cleanup(gpointer data)
{
Image *image = (Image*)data;
UnregisterCleanup();
if (image)
CloseImage(image);
#ifndef WITH_CLI_ONLY_YES
if(Closure->guiMode)
{ AllowActions(TRUE);
g_thread_exit(0);
}
#endif
}
void StripECCFromImageFile()
{ Image *image = NULL;
gint64 end;
RegisterCleanup(_("Strip ECC aborted"), stripecc_cleanup, (gpointer)image);
/*** Open the image file */
image = OpenImageFromFile(Closure->imageName, O_RDWR, IMG_PERMS);
if(!image)
Stop(_("Can't open %s:\n%s"), Closure->imageName, strerror(errno));
if (!image->eccHeader)
Stop(_("Image is not augmented (no dvdisaster signature found)."));
PrintLog("Image is augmented (expected sectors = %" PRId64 ")\n", image->expectedSectors);
end = uchar_to_gint64(image->eccHeader->sectors);
if (end <= 0)
Stop(_("Invalid end data sector (%" PRId64 "), aborting"), end);
PrintLog(_("Truncating image to %" PRId64 " sectors.\n"), end);
/*** Last chance to cancel in GUI mode */
#ifndef WITH_CLI_ONLY_YES
if(Closure->guiMode)
{ int answer = ModalDialog(GTK_MESSAGE_QUESTION, GTK_BUTTONS_OK_CANCEL, NULL,
_("We're about to truncate the image from %" PRId64 " sectors (%" PRId64 " MiB)\n"
"to %" PRId64 " sectors (%" PRId64 " MiB), removing any dvdisaster-added ECC data.\n"
"This will restore the image to its pre-augmented original size."),
image->expectedSectors, image->expectedSectors >> 9, end, end >> 9);
/* >> 9 is 2048 bytes (1 sector) to MiB */
if (answer != 1)
Stop(_("Aborted on user request"));
}
#endif
/*** Truncate it. */
if(!LargeTruncate(image->file, (gint64)(2048*end)))
Stop(_("Could not truncate %s: %s\n"),Closure->imageName,strerror(errno));
PrintLog(_("Image successfully truncated back to its original size.\n"));
#ifndef WITH_CLI_ONLY_YES
ModalDialog(GTK_MESSAGE_INFO, GTK_BUTTONS_OK, NULL, _("Image successfully truncated"));
#endif
/*** Clean up */
stripecc_cleanup((gpointer)image);
}