opensc-explorer: add function 'get_record'

This commit is contained in:
Peter Marschall 2020-01-12 10:40:05 +01:00 committed by Frank Morgner
parent f55c4e5c93
commit 5714dbfa08
2 changed files with 115 additions and 0 deletions

View File

@ -403,6 +403,31 @@
</listitem>
</varlistentry>
<varlistentry>
<term>
<command>get_record</command>
<replaceable>file-id</replaceable>
<replaceable>rec-no</replaceable>
<arg choice="opt"><replaceable>output</replaceable></arg>
</term>
<listitem>
<para>
Copy a record of a record-oriented EF to a local file.
The local file is specified by
<replaceable>output</replaceable>
while the card file and the record are specified by
<replaceable>file-id</replaceable> and
<replaceable>rec-no</replaceable>,
</para>
<para>
If <replaceable>output</replaceable> is omitted,
the name of the output file will be derived from the
full card path to <replaceable>file-id</replaceable>.
and the <replaceable>rec-no</replaceable>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<command>help</command>

View File

@ -100,6 +100,7 @@ static int do_verify(int argc, char **argv);
static int do_change(int argc, char **argv);
static int do_unblock(int argc, char **argv);
static int do_get(int argc, char **argv);
static int do_get_record(int argc, char **argv);
static int do_update_binary(int argc, char **argv);
static int do_update_record(int argc, char **argv);
static int do_put(int argc, char **argv);
@ -174,6 +175,9 @@ static struct command cmds[] = {
{ do_get,
"get", "<file-id> [<output-file>]",
"copy an EF to a local file" },
{ do_get_record,
"get_record", "<file-id> <rec-no> [<output-file>]",
"copy a record of an EF to a local file" },
{ do_get_data,
"do_get", "<hex-tag> [<output-file>]",
"get a data object" },
@ -1474,6 +1478,92 @@ err:
return -err;
}
static int do_get_record(int argc, char **argv)
{
u8 buf[SC_MAX_EXT_APDU_RESP_SIZE];
int r, err = 1;
size_t rec, count = 0;
sc_path_t path;
sc_file_t *file = NULL;
char *filename;
FILE *outf = NULL;
if (argc < 2 || argc > 3)
return usage(do_get);
if (arg_to_path(argv[0], &path, 0) != 0)
return usage(do_get);
rec = strtoul(argv[1], NULL, 10);
filename = (argc == 3) ? argv[2] : path_to_filename(&path, '_', rec);
outf = (strcmp(filename, "-") == 0)
? stdout
: fopen(filename, "wb");
if (outf == NULL) {
perror(filename);
goto err;
}
r = sc_lock(card);
if (r == SC_SUCCESS)
r = sc_select_file(card, &path, &file);
sc_unlock(card);
if (r || file == NULL) {
check_ret(r, SC_AC_OP_SELECT, "Unable to select file", current_file);
goto err;
}
/* fail on wrong file type */
if (file->type != SC_FILE_TYPE_WORKING_EF ||
(file->ef_structure != SC_FILE_EF_LINEAR_FIXED &&
file->ef_structure != SC_FILE_EF_LINEAR_FIXED_TLV &&
file->ef_structure != SC_FILE_EF_LINEAR_VARIABLE &&
file->ef_structure != SC_FILE_EF_LINEAR_VARIABLE_TLV)) {
fprintf(stderr, "Only record-oriented working EFs may be read\n");
goto err;
}
/* fail on out of bound record index:
* must be > 0 and if record_count is set <= record_count */
if (rec < 1 || (file->record_count > 0 && rec > file->record_count)) {
fprintf(stderr, "Invalid record number %"SC_FORMAT_LEN_SIZE_T"u\n", rec);
goto err;
}
r = sc_read_record(card, rec, buf, sizeof(buf), SC_RECORD_BY_REC_NR);
if (r < 0) {
fprintf(stderr, "Cannot read record %"SC_FORMAT_LEN_SIZE_T"u; return %i\n", rec, r);
goto err;
}
count = r;
if (count > 0) {
size_t written = fwrite(buf, 1, (size_t) r, outf);
if (written != count) {
fprintf(stderr, "Cannot write to file %s (only %"SC_FORMAT_LEN_SIZE_T"u of %"SC_FORMAT_LEN_SIZE_T"u bytes written)",
filename, written, count);
goto err;
}
}
if (outf == stdout) {
fwrite("\n", 1, 1, outf);
}
else {
printf("Total of %"SC_FORMAT_LEN_SIZE_T"u bytes read from %s and saved to %s.\n",
count, argv[0], filename);
}
err = 0;
err:
sc_file_free(file);
if (outf != NULL && outf != stdout)
fclose(outf);
select_current_path_or_die();
return -err;
}
static int do_update_binary(int argc, char **argv)
{
u8 buf[SC_MAX_EXT_APDU_DATA_SIZE];