From c8e62965bc90eabff5c4b7cb349bd8e41584c01b Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Tue, 25 Jun 2019 09:23:38 +0200 Subject: [PATCH] scd: Return a stable list with "getinfo card_list". * scd/app.c (compare_card_list_items): New. (app_send_card_list): Sort the card objects by slot. -- This is required so that in gpg-card a "list N" command always returns the expected card. Sorting by slot should be sufficient. Signed-off-by: Werner Koch --- scd/app-common.h | 2 +- scd/app.c | 41 +++++++++++++++++++++++++++++++++++++---- scd/command.c | 2 +- 3 files changed, 39 insertions(+), 6 deletions(-) diff --git a/scd/app-common.h b/scd/app-common.h index 97b9b39ef..460046f89 100644 --- a/scd/app-common.h +++ b/scd/app-common.h @@ -223,7 +223,7 @@ const char *strcardtype (cardtype_t t); const char *strapptype (apptype_t t); void app_update_priority_list (const char *arg); -void app_send_card_list (ctrl_t ctrl); +gpg_error_t app_send_card_list (ctrl_t ctrl); char *card_get_serialno (card_t card); char *app_get_serialno (app_t app); diff --git a/scd/app.c b/scd/app.c index c568b636b..1ad6b9ed6 100644 --- a/scd/app.c +++ b/scd/app.c @@ -1601,22 +1601,55 @@ initialize_module_command (void) } -void +/* Sort helper for app_send_card_list. */ +static int +compare_card_list_items (const void *arg_a, const void *arg_b) +{ + const card_t a = *(const card_t *)arg_a; + const card_t b = *(const card_t *)arg_b; + + return a->slot - b->slot; +} + + +/* Send status lines with the serialno of all inserted cards. */ +gpg_error_t app_send_card_list (ctrl_t ctrl) { + gpg_error_t err; card_t c; char buf[65]; + card_t *cardlist = NULL; + int n, ncardlist; npth_mutex_lock (&card_list_lock); - for (c = card_top; c; c = c->next) + for (n=0, c = card_top; c; c = c->next) + n++; + cardlist = xtrycalloc (n, sizeof *cardlist); + if (!cardlist) { - if (DIM (buf) < 2 * c->serialnolen + 1) + err = gpg_error_from_syserror (); + goto leave; + } + for (ncardlist=0, c = card_top; c; c = c->next) + cardlist[ncardlist++] = c; + qsort (cardlist, ncardlist, sizeof *cardlist, compare_card_list_items); + + for (n=0; n < ncardlist; n++) + { + if (DIM (buf) < 2 * cardlist[n]->serialnolen + 1) continue; - bin2hex (c->serialno, c->serialnolen, buf); + bin2hex (cardlist[n]->serialno, cardlist[n]->serialnolen, buf); send_status_direct (ctrl, "SERIALNO", buf); } + + err = 0; + + leave: npth_mutex_unlock (&card_list_lock); + xfree (cardlist); + return err; } diff --git a/scd/command.c b/scd/command.c index 2b851c5fd..f341b6ae2 100644 --- a/scd/command.c +++ b/scd/command.c @@ -1630,7 +1630,7 @@ cmd_getinfo (assuan_context_t ctx, char *line) { ctrl_t ctrl = assuan_get_pointer (ctx); - app_send_card_list (ctrl); + rc = app_send_card_list (ctrl); } else rc = set_error (GPG_ERR_ASS_PARAMETER, "unknown value for WHAT");