1
0
Fork 0
mirror of git://git.gnupg.org/gnupg.git synced 2025-07-02 22:46:30 +02:00

Fixed the card removed with cached app bug. (Famous last fix).

This commit is contained in:
Werner Koch 2008-11-03 19:09:34 +00:00
parent 338ddd0bb6
commit 4019792423
5 changed files with 66 additions and 46 deletions

View file

@ -81,7 +81,7 @@ struct slot_status_s
done. This is set once to indicate that the status
tracking for the slot has been initialized. */
unsigned int status; /* Last status of the slot. */
unsigned int changed; /* Last change counter of teh slot. */
unsigned int changed; /* Last change counter of the slot. */
};
@ -134,7 +134,7 @@ static pth_mutex_t status_file_update_lock;
/*-- Local prototypes --*/
static void update_reader_status_file (void);
static void update_reader_status_file (int set_card_removed_flag);
@ -171,7 +171,7 @@ update_card_removed (int slot, int value)
}
/* Let the card application layer know about the removal. */
if (value)
application_notify_card_removed (slot);
application_notify_card_reset (slot);
}
@ -256,7 +256,8 @@ hex_to_buffer (const char *string, size_t *r_length)
/* Reset the card and free the application context. With SEND_RESET
set to true actually send a RESET to the reader. */
set to true actually send a RESET to the reader; this is the normal
way of calling the function. */
static void
do_reset (ctrl_t ctrl, int send_reset)
{
@ -265,18 +266,22 @@ do_reset (ctrl_t ctrl, int send_reset)
if (!(slot == -1 || (slot >= 0 && slot < DIM(slot_table))))
BUG ();
/* If there is an active application, release it. */
if (ctrl->app_ctx)
{
release_application (ctrl->app_ctx);
ctrl->app_ctx = NULL;
}
/* If we want a real reset for the card, send the reset APDU and
tell the application layer about it. */
if (slot != -1 && send_reset && !IS_LOCKED (ctrl) )
{
if (apdu_reset (slot))
{
slot_table[slot].reset_failed = 1;
}
application_notify_card_reset (slot);
}
/* If we hold a lock, unlock now. */
@ -286,23 +291,23 @@ do_reset (ctrl_t ctrl, int send_reset)
log_info ("implicitly unlocking due to RESET\n");
}
/* Reset card removed flag for the current reader. We need to take
the lock here so that the ticker thread won't concurrently try to
update the file. Note that the update function will set the card
removed flag and we will later reset it - not a particualar nice
way of implementing it but it works. */
/* Reset the card removed flag for the current reader. We need to
take the lock here so that the ticker thread won't concurrently
try to update the file. Calling update_reader_status_file is
required to get hold of the new status of the card in the slot
table. */
if (!pth_mutex_acquire (&status_file_update_lock, 0, NULL))
{
log_error ("failed to acquire status_fle_update lock\n");
ctrl->reader_slot = -1;
return;
}
update_reader_status_file ();
update_card_removed (slot, 0);
update_reader_status_file (0); /* Update slot status table. */
update_card_removed (slot, 0); /* Clear card_removed flag. */
if (!pth_mutex_release (&status_file_update_lock))
log_error ("failed to release status_file_update lock\n");
/* Do this last, so that update_card_removed does its job. */
/* Do this last, so that the update_card_removed above does its job. */
ctrl->reader_slot = -1;
}
@ -1875,7 +1880,7 @@ scd_command_handler (ctrl_t ctrl, int fd)
}
}
/* Cleanup. */
/* Cleanup. We don't send an explicit reset to the card. */
do_reset (ctrl, 0);
/* Release the server object. */
@ -1951,9 +1956,9 @@ send_status_info (ctrl_t ctrl, const char *keyword, ...)
/* This is the core of scd_update_reader_status_file but the caller
needs to take care of the locking. */
needs to take care of the locking. */
static void
update_reader_status_file (void)
update_reader_status_file (int set_card_removed_flag)
{
int idx;
unsigned int status, changed;
@ -1990,7 +1995,7 @@ update_reader_status_file (void)
/* FIXME: Should this be IDX instead of ss->slot? This
depends on how client sessions will associate the reader
status with their session. */
sprintf (templ, "reader_%d.status", ss->slot);
snprintf (templ, sizeof templ, "reader_%d.status", ss->slot);
fname = make_filename (opt.homedir, templ, NULL );
fp = fopen (fname, "w");
if (fp)
@ -2047,7 +2052,7 @@ update_reader_status_file (void)
/* Set the card removed flag for all current sessions. We
will set this on any card change because a reset or
SERIALNO request must be done in any case. */
if (ss->any)
if (ss->any && set_card_removed_flag)
update_card_removed (idx, 1);
ss->any = 1;
@ -2090,7 +2095,7 @@ scd_update_reader_status_file (void)
{
if (!pth_mutex_acquire (&status_file_update_lock, 1, NULL))
return; /* locked - give up. */
update_reader_status_file ();
update_reader_status_file (1);
if (!pth_mutex_release (&status_file_update_lock))
log_error ("failed to release status_file_update lock\n");
}