New API call iso_write_opts_set_scdbackup_tag()

This commit is contained in:
Thomas Schmitt 2009-08-31 23:09:16 +02:00
parent 9cfa55345e
commit c992687200
6 changed files with 193 additions and 40 deletions

View File

@ -67,8 +67,8 @@ The tree checksum tag is written after the ECMA-119 directory entries.
The session checksum tag is written after all payload including the checksum
array. (Then follows eventual padding.)
The tags are single lines of printable text, padded by 0 bytes. They have
the following format:
The tags are single lines of printable text at the very beginning of a block
of 2048 bytes. They have the following format:
Tag_id pos=# range_start=# range_size=# [session_start|next=#] md5=# self=#\n
@ -161,9 +161,14 @@ checksums as strings of 32 hex digits.
The MD5 checksum of the tag itself up to and including the last hex digit of
parameter "md5=".
The newline character at the end is mandatory. For now all bytes of the
block after that newline shall be zero. There may arise future extensions.
The newline character at the end is mandatory. After that newline there may
follow more lines. Their meaning is not necessarily described in this document.
One such line type is the scdbackup checksum tag, an ancestor of libisofs tags
which is suitable only for single session images which begin at LBA 0. It bears
a checksum record which by its MD5 covers all bytes from LBA 0 up to the
newline character preceding the scdbackup tag. See scdbackup/README appendix
VERIFY for details.
-------------------------------------------------------------------------------

View File

@ -31,11 +31,13 @@
#include "md5.h"
#endif
#include <ctype.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <locale.h>
#include <langinfo.h>
#include <stdio.h>
/*
* TODO #00011 : guard against bad path table usage with more than 65535 dirs
@ -1132,6 +1134,7 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
target->md5_file_checksums = opts->md5_file_checksums;
target->md5_session_checksum = opts->md5_session_checksum;
strcpy(target->scdbackup_tag_parm, opts->scdbackup_tag_parm);
target->checksum_idx_counter = 0;
target->checksum_ctx = NULL;
target->checksum_counter = 0;
@ -1866,6 +1869,39 @@ int iso_write_opts_set_record_md5(IsoWriteOpts *opts, int session, int files)
return ISO_SUCCESS;
}
int iso_write_opts_set_scdbackup_tag(IsoWriteOpts *opts,
char *name, char *timestamp)
{
#ifdef Libisofs_with_checksumS
char eff_name[81], eff_time[19];
int i;
for (i = 0; name[i] != 0 && i < 80; i++)
if (isspace((int) ((unsigned char *) name)[i]))
eff_name[i] = '_';
else
eff_name[i] = name[i];
if (i == 0)
eff_name[i++] = '_';
eff_name[i] = 0;
for (i = 0; timestamp[i] != 0 && i < 18; i++)
if (isspace((int) ((unsigned char *) timestamp)[i]))
eff_time[i] = '_';
else
eff_time[i] = timestamp[i];
if (i == 0)
eff_time[i++] = '_';
eff_time[i] = 0;
sprintf(opts->scdbackup_tag_parm, "%s %s", eff_name, eff_time);
#endif /* Libisofs_with_checksumS */
return ISO_SUCCESS;
}
int iso_write_opts_set_replace_mode(IsoWriteOpts *opts, int dir_mode,
int file_mode, int uid, int gid)
{

View File

@ -281,6 +281,15 @@ struct iso_write_opts {
*/
uint32_t data_start_lba;
/**
* If not empty: A text holding parameters "name" and "timestamp" for
* a scdbackup stream checksum tag. See scdbackup/README appendix VERIFY.
* It makes sense only for single session images which start at LBA 0.
* Such a tag may be part of a libisofs checksum tag block after the
* session tag line. It then covers the whole session up to its own start
* position.
*/
char scdbackup_tag_parm[100];
};
typedef struct ecma119_image Ecma119Image;
@ -464,6 +473,8 @@ struct ecma119_image
is submitted with ecma119_image_new() ?
*/
char scdbackup_tag_parm[96];
#endif /* Libisofs_with_checksumS */
/* Buffer for communication between burn_source and writer thread */

View File

@ -1446,6 +1446,27 @@ int iso_write_opts_set_sort_files(IsoWriteOpts *opts, int sort);
*/
int iso_write_opts_set_record_md5(IsoWriteOpts *opts, int session, int files);
/**
* Set the parameters "name" and "timestamp" for a scdbackup checksum tag.
* It will be appended to the libisofs session tag if the image starts at
* LBA 0 (see iso_write_opts_set_ms_block()). The scdbackup tag can be used
* to verify the image by command scdbackup_verify <device> -auto_end.
* See scdbackup/README appendix VERIFY for its inner details.
*
* @param name
* A word of up to 80 characters. Typically <volno>_<totalno> telling
* that this is volume <volno> of a total of <totalno> volumes.
* @param timestamp
* A string of 13 characters YYMMDD.hhmmss (e.g. A90831.190324).
* A9 = 2009, B0 = 2010, B1 = 2011, ... C0 = 2020, ...
* @return
* 1 indicates success, <0 is error
*
* @since 0.6.24
*/
int iso_write_opts_set_scdbackup_tag(IsoWriteOpts *opts,
char *name, char *timestamp);
/**
* Whether to set default values for files and directory permissions, gid and
* uid. All these take one of three values: 0, 1 or 2.
@ -5522,6 +5543,13 @@ int iso_md5_match(char first_md5[16], char second_md5[16]);
*/
#define ISO_MD5_STREAM_CHANGE 0xE430FE9A
/**
* Session does not start at LBA 0. scdbackup checksum tag not written.
* (WARNING, HIGH, -359)
* @since 0.6.24
*/
#define ISO_SCDBACKUP_TAG_NOT_0 0xD030FE99
/* ! PLACE NEW ERROR CODES HERE ! */

View File

@ -698,6 +698,66 @@ int checksum_writer_create(Ecma119Image *target)
}
static
int iso_md5_write_scdbackup_tag(Ecma119Image *t, char *tag_block, int flag)
{
#ifdef Libisofs_with_checksumS
void *ctx = NULL;
off_t pos = 0, line_start;
int record_len, block_len, res, i;
char postext[20], md5[16], record[160];
line_start = strlen(tag_block);
iso_md5_compute(t->checksum_ctx, tag_block, line_start);
res = iso_md5_clone(t->checksum_ctx, &ctx);
if (res < 0)
goto ex;
res = iso_md5_end(&ctx, md5);
pos = (off_t) t->checksum_tag_pos * (off_t) 2048 + line_start;
if(pos >= 1000000000)
sprintf(postext, "%u%9.9u", (unsigned int) (pos / 1000000000),
(unsigned int) (pos % 1000000000));
else
sprintf(postext, "%u", (unsigned int) pos),
sprintf(record, "%s %s ", t->scdbackup_tag_parm, postext);
record_len = strlen(record);
for (i = 0; i < 16; i++)
sprintf(record + record_len + 2 * i,
"%2.2x", ((unsigned char *) md5)[i]);
record_len+= 32;
res = iso_md5_start(&ctx);
if (res < 0)
goto ex;
iso_md5_compute(ctx, record, record_len);
iso_md5_end(&ctx, md5);
sprintf(tag_block + line_start, "scdbackup_checksum_tag_v0.1 %s %d %s ",
postext, record_len, record);
block_len = strlen(tag_block);
for (i = 0; i < 16; i++)
sprintf(tag_block + block_len + 2 * i,
"%2.2x", ((unsigned char *) md5)[i]);
block_len+= 32;
tag_block[block_len++]= '\n';
res = ISO_SUCCESS;
ex:;
if (ctx != NULL)
iso_md5_end(&ctx, md5);
return res;
#else
return ISO_SUCCESS;
#endif /* Libisofs_with_checksumS */
}
/* Write stream detectable checksum tag to extra block.
* @flag bit0-7= tag type
* 1= session tag (End checksumming.)
@ -719,11 +779,16 @@ int iso_md5_write_tag(Ecma119Image *t, int flag)
start = t->checksum_range_start;
memset(tag_block, 0, 2048);
mode = flag & 255;
if (mode < 1 || mode > 4)
return ISO_WRONG_ARG_VALUE;
res = iso_md5_clone(t->checksum_ctx, &ctx);
if (res < 0)
return res;
res = iso_md5_end(&ctx, md5);
if (mode == 1) {
res = iso_md5_end(&(t->checksum_ctx), md5);
size = t->checksum_range_size;
pos = t->checksum_tag_pos;
} else if (mode >= 2 && mode <= 4) {
} else {
if (mode == 2) {
pos = t->checksum_sb_tag_pos;
} else if (mode == 3) {
@ -733,46 +798,51 @@ int iso_md5_write_tag(Ecma119Image *t, int flag)
start = pos - (pos % 32);
}
size = pos - start;
res = iso_md5_clone(t->checksum_ctx, &ctx);
if (res < 0)
return res;
res = iso_md5_end(&ctx, md5);
} else {
return ISO_WRONG_ARG_VALUE;
}
if (res > 0) {
iso_util_tag_magic(mode, &tag_id, &tag_id_len, 0);
sprintf(tag_block,
"%s pos=%u range_start=%u range_size=%u",
tag_id, pos, start, size);
if (res < 0)
goto ex;
l = strlen(tag_block);
if (mode == 2) {
sprintf(tag_block + l, " next=%u", t->checksum_tree_tag_pos);
} else if (mode == 3) {
sprintf(tag_block + l, " next=%u", t->checksum_tag_pos);
} else if (mode == 4) {
sprintf(tag_block + l, " session_start=%u", t->ms_block);
}
strcat(tag_block + l, " md5=");
l = strlen(tag_block);
iso_util_tag_magic(mode, &tag_id, &tag_id_len, 0);
sprintf(tag_block, "%s pos=%u range_start=%u range_size=%u",
tag_id, pos, start, size);
l = strlen(tag_block);
if (mode == 2) {
sprintf(tag_block + l, " next=%u", t->checksum_tree_tag_pos);
} else if (mode == 3) {
sprintf(tag_block + l, " next=%u", t->checksum_tag_pos);
} else if (mode == 4) {
sprintf(tag_block + l, " session_start=%u", t->ms_block);
}
strcat(tag_block + l, " md5=");
l = strlen(tag_block);
for (i = 0; i < 16; i++)
sprintf(tag_block + l + 2 * i, "%2.2x",
((unsigned char *) md5)[i]);
l+= 32;
res = iso_md5_start(&ctx);
if (res > 0) {
iso_md5_compute(ctx, tag_block, l);
iso_md5_end(&ctx, md5);
strcpy(tag_block + l, " self=");
l += 6;
for (i = 0; i < 16; i++)
sprintf(tag_block + l + 2 * i, "%2.2x",
((unsigned char *) md5)[i]);
l+= 32;
res = iso_md5_start(&ctx);
if (res > 0) {
iso_md5_compute(ctx, tag_block, l);
iso_md5_end(&ctx, md5);
strcpy(tag_block + l, " self=");
l += 6;
for (i = 0; i < 16; i++)
sprintf(tag_block + l + 2 * i, "%2.2x",
((unsigned char *) md5)[i]);
}
tag_block[l + 32] = '\n';
}
tag_block[l + 32] = '\n';
if (mode == 1 && t->scdbackup_tag_parm[0]) {
if (t->ms_block > 0) {
iso_msg_submit(t->image->id, ISO_SCDBACKUP_TAG_NOT_0, 0, NULL);
} else {
res = iso_md5_write_scdbackup_tag(t, tag_block, 0);
if (res < 0)
goto ex;
}
}
if (mode == 4) {
if (t->opts_overwrite != NULL)
memcpy(t->opts_overwrite + pos * 2048, tag_block, 2048);
@ -783,6 +853,7 @@ int iso_md5_write_tag(Ecma119Image *t, int flag)
goto ex;
}
}
res = ISO_SUCCESS;
ex:;
if (ctx != NULL)

View File

@ -274,6 +274,8 @@ const char *iso_error_to_msg(int errcode)
return "Checksum tag with unexpected address range encountered";
case ISO_MD5_STREAM_CHANGE:
return "Detected file content changes while it was written into the image";
case ISO_SCDBACKUP_TAG_NOT_0:
return "Session does not start at LBA 0. scdbackup checksum tag not written.";
default:
return "Unknown error";
}