opensc-explorer: add function 'get_record'
This commit is contained in:
parent
f55c4e5c93
commit
5714dbfa08
|
@ -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>
|
||||
|
|
|
@ -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];
|
||||
|
|
Loading…
Reference in New Issue