diff --git a/agent/findkey.c b/agent/findkey.c index a5f022574..9e5550225 100644 --- a/agent/findkey.c +++ b/agent/findkey.c @@ -146,6 +146,8 @@ agent_write_private_key (const unsigned char *grip, } } + nvc_modified (pk, 1); /* Clear that flag after a read. */ + if (!pk) { /* Key is still in the old format or does not exist - create a @@ -242,7 +244,7 @@ agent_write_private_key (const unsigned char *grip, ; /* No need to update Token entry. */ else { - err = nve_set (item, token); + err = nve_set (pk, item, token); if (err) goto leave; } @@ -263,6 +265,13 @@ agent_write_private_key (const unsigned char *grip, goto leave; } + /* Check whether we need to write the file at all. */ + if (!nvc_modified (pk, 0)) + { + err = 0; + goto leave; + } + /* Create a temporary file for writing. */ tmpfname = fname_from_keygrip (grip, 1); fp = tmpfname ? es_fopen (tmpfname, "wbx,mode=-rw") : NULL; diff --git a/common/name-value.c b/common/name-value.c index 0dffc63b4..b7bc32844 100644 --- a/common/name-value.c +++ b/common/name-value.c @@ -48,6 +48,7 @@ struct name_value_container struct name_value_entry *first; struct name_value_entry *last; unsigned int private_key_mode:1; + unsigned int modified:1; }; @@ -87,11 +88,15 @@ my_error (gpg_err_code_t ec) /* Allocation and deallocation. */ -/* Allocate a private key container structure. */ +/* Allocate a name value container structure. */ nvc_t nvc_new (void) { - return xtrycalloc (1, sizeof (struct name_value_container)); + nvc_t nvc; + nvc = xtrycalloc (1, sizeof (struct name_value_container)); + if (nvc) + nvc->modified = 1; + return nvc; } @@ -142,6 +147,24 @@ nvc_release (nvc_t pk) xfree (pk); } + +/* Return the modified-flag of the container and clear it if CLEAR is + * set. That flag is set for a new container and set with each + * update. */ +int +nvc_modified (nvc_t pk, int clear) +{ + int modified; + + if (!pk) + return 0; + modified = pk->modified; + if (clear) + pk->modified = 0; + return modified; +} + + /* Dealing with names and values. */ @@ -427,6 +450,8 @@ _nvc_add (nvc_t pk, char *name, char *value, strlist_t raw_value, else pk->first = pk->last = e; + pk->modified = 1; + leave: if (err) { @@ -470,6 +495,7 @@ gpg_error_t nvc_set (nvc_t pk, const char *name, const char *value) { nve_t e; + char *v; if (! valid_name (name)) return GPG_ERR_INV_NAME; @@ -477,7 +503,12 @@ nvc_set (nvc_t pk, const char *name, const char *value) e = nvc_lookup (pk, name); if (e) { - char *v; + if (e->value && value && !strcmp (e->value, value)) + { + /* Setting same value - ignore this call and don't set the + * modified flag. */ + return 0; + } v = xtrystrdup (value); if (v == NULL) @@ -489,7 +520,7 @@ nvc_set (nvc_t pk, const char *name, const char *value) wipememory (e->value, strlen (e->value)); xfree (e->value); e->value = v; - + pk->modified = 1; return 0; } else @@ -497,9 +528,10 @@ nvc_set (nvc_t pk, const char *name, const char *value) } -/* Update entry E to VALUE. */ +/* Update entry E to VALUE. PK is optional; if given its modified + * flag will be updated. */ gpg_error_t -nve_set (nve_t e, const char *value) +nve_set (nvc_t pk, nve_t e, const char *value) { char *v; @@ -516,6 +548,8 @@ nve_set (nve_t e, const char *value) wipememory (e->value, strlen (e->value)); xfree (e->value); e->value = v; + if (pk) + pk->modified = 1; return 0; } @@ -536,6 +570,7 @@ nvc_delete (nvc_t pk, nve_t entry) pk->last = entry->prev; nve_release (entry, pk->private_key_mode); + pk->modified = 1; } diff --git a/common/name-value.h b/common/name-value.h index b3fc2f63c..dfded6678 100644 --- a/common/name-value.h +++ b/common/name-value.h @@ -50,6 +50,9 @@ nvc_t nvc_new_private_key (void); /* Release a name value container structure. */ void nvc_release (nvc_t pk); +/* Return the modified flag and optionally clear it. */ +int nvc_modified (nvc_t pk, int clear); + /* Get the name. */ char *nve_name (nve_t pke); @@ -92,8 +95,8 @@ gpg_error_t nvc_add (nvc_t pk, const char *name, const char *value); first entry is updated. */ gpg_error_t nvc_set (nvc_t pk, const char *name, const char *value); -/* Update entry E to VALUE. */ -gpg_error_t nve_set (nve_t e, const char *value); +/* Update entry E to VALUE. PK is optional. */ +gpg_error_t nve_set (nvc_t pk, nve_t e, const char *value); /* Delete the given entry from PK. */ void nvc_delete (nvc_t pk, nve_t pke);