* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
-#include <assert.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
static int cache_is_dirty;
-/* An object to pass infomation to cmp_krec_fpr. */
+/* An object to pass information to cmp_krec_fpr. */
struct cmp_krec_fpr_struct
{
int pubkey_algo;
int fprlen;
};
-/* An object used to pass infomation to cmp_[s]dir. */
+/* An object used to pass information to cmp_[s]dir. */
struct cmp_xdir_struct
{
int pubkey_algo;
\f
static void open_db (void);
+static void create_hashtable (TRUSTREC *vr, int type);
\f
*
* Returns: 0 on success or an error code.
*/
-int
+static int
put_record_into_cache (ulong recno, const char *data)
{
CACHE_CTRL r, unused;
}
/* Now put into the cache. */
- assert (unused);
+ log_assert (unused);
r = unused;
r->flags.used = 1;
r->recno = recno;
release_write_lock ();
/* Now put into the cache. */
- assert (unused);
+ log_assert (unused);
r = unused;
r->flags.used = 1;
r->recno = recno;
/*
* Simple transactions system:
* Everything between begin_transaction and end/cancel_transaction
- * is not immediatly written but at the time of end_transaction.
+ * is not immediately written but at the time of end_transaction.
*
* NOTE: The transaction code is disabled in the 1.2 branch, as it is
* not yet used.
rec.rectype = RECTYPE_VER;
rec.recnum = 0;
rc = tdbio_write_record (&rec);
+
if (!rc)
tdbio_sync ();
+
+ if (!rc)
+ create_hashtable (&rec, 0);
+
return rc;
}
int
tdbio_set_dbname (const char *new_dbname, int create, int *r_nofile)
{
- char *fname;
+ char *fname, *p;
struct stat statbuf;
static int initialized = 0;
+ int save_slash;
if (!initialized)
{
if (!new_dbname)
{
- fname = make_filename (opt.homedir, "trustdb" EXTSEP_S GPGEXT_GPG, NULL);
+ fname = make_filename (gnupg_homedir (),
+ "trustdb" EXTSEP_S GPGEXT_GPG, NULL);
}
else if (*new_dbname != DIRSEP_C )
{
if (strchr (new_dbname, DIRSEP_C))
fname = make_filename (new_dbname, NULL);
else
- fname = make_filename (opt.homedir, new_dbname, NULL);
+ fname = make_filename (gnupg_homedir (), new_dbname, NULL);
}
else
{
/* OK, we have the valid trustdb.gpg already. */
return 0;
}
+ else if (!create)
+ {
+ *r_nofile = 1;
+ return 0;
+ }
+
+ /* Here comes: No valid trustdb.gpg AND CREATE==1 */
+
+ /*
+ * Make sure the directory exists. This should be done before
+ * acquiring the lock, which assumes the existence of the directory.
+ */
+ p = strrchr (fname, DIRSEP_C);
+#if HAVE_W32_SYSTEM
+ {
+ /* Windows may either have a slash or a backslash. Take
+ care of it. */
+ char *pp = strrchr (fname, '/');
+ if (!p || pp > p)
+ p = pp;
+ }
+#endif /*HAVE_W32_SYSTEM*/
+ log_assert (p);
+ save_slash = *p;
+ *p = 0;
+ if (access (fname, F_OK))
+ {
+ try_make_homedir (fname);
+ if (access (fname, F_OK))
+ log_fatal (_("%s: directory does not exist!\n"), fname);
+ }
+ *p = save_slash;
take_write_lock ();
- if (access (fname, R_OK))
+ if (access (fname, R_OK) || stat (fname, &statbuf) || statbuf.st_size == 0)
{
+ FILE *fp;
+ TRUSTREC rec;
+ int rc;
+ mode_t oldmask;
+
#ifdef HAVE_W32CE_SYSTEM
/* We know how the cegcc implementation of access works ;-). */
if (GetLastError () == ERROR_FILE_NOT_FOUND)
else
gpg_err_set_errno (EIO);
#endif /*HAVE_W32CE_SYSTEM*/
- if (errno != ENOENT)
+ if (errno && errno != ENOENT)
log_fatal ( _("can't access '%s': %s\n"), fname, strerror (errno));
- if (!create)
- *r_nofile = 1;
- else
+ oldmask = umask (077);
+ if (is_secured_filename (fname))
{
- FILE *fp;
- TRUSTREC rec;
- int rc;
- char *p = strrchr (fname, DIRSEP_C);
- mode_t oldmask;
- int save_slash;
-
-#if HAVE_W32_SYSTEM
- {
- /* Windows may either have a slash or a backslash. Take
- care of it. */
- char *pp = strrchr (fname, '/');
- if (!p || pp > p)
- p = pp;
- }
-#endif /*HAVE_W32_SYSTEM*/
- assert (p);
- save_slash = *p;
- *p = 0;
- if (access (fname, F_OK))
- {
- try_make_homedir (fname);
- if (access (fname, F_OK))
- log_fatal (_("%s: directory does not exist!\n"), fname);
- }
- *p = save_slash;
-
- oldmask = umask (077);
- if (is_secured_filename (fname))
- {
- fp = NULL;
- gpg_err_set_errno (EPERM);
- }
- else
- fp = fopen (fname, "wb");
- umask(oldmask);
- if (!fp)
- log_fatal (_("can't create '%s': %s\n"), fname, strerror (errno));
- fclose (fp);
+ fp = NULL;
+ gpg_err_set_errno (EPERM);
+ }
+ else
+ fp = fopen (fname, "wb");
+ umask(oldmask);
+ if (!fp)
+ log_fatal (_("can't create '%s': %s\n"), fname, strerror (errno));
+ fclose (fp);
- db_fd = open (db_name, O_RDWR | MY_O_BINARY);
- if (db_fd == -1)
- log_fatal (_("can't open '%s': %s\n"), db_name, strerror (errno));
+ db_fd = open (db_name, O_RDWR | MY_O_BINARY);
+ if (db_fd == -1)
+ log_fatal (_("can't open '%s': %s\n"), db_name, strerror (errno));
- rc = create_version_record ();
- if (rc)
- log_fatal (_("%s: failed to create version record: %s"),
- fname, gpg_strerror (rc));
+ rc = create_version_record ();
+ if (rc)
+ log_fatal (_("%s: failed to create version record: %s"),
+ fname, gpg_strerror (rc));
- /* Read again to check that we are okay. */
- if (tdbio_read_record (0, &rec, RECTYPE_VER))
- log_fatal (_("%s: invalid trustdb created\n"), db_name);
+ /* Read again to check that we are okay. */
+ if (tdbio_read_record (0, &rec, RECTYPE_VER))
+ log_fatal (_("%s: invalid trustdb created\n"), db_name);
- if (!opt.quiet)
- log_info (_("%s: trustdb created\n"), db_name);
- }
+ if (!opt.quiet)
+ log_info (_("%s: trustdb created\n"), db_name);
}
release_write_lock ();
{
TRUSTREC rec;
- assert( db_fd == -1 );
+ log_assert( db_fd == -1 );
#ifdef HAVE_W32CE_SYSTEM
{
if (offset == -1)
log_fatal ("trustdb: lseek to end failed: %s\n", strerror(errno));
recnum = offset / TRUST_RECORD_LEN;
- assert (recnum); /* This is will never be the first record. */
+ log_assert (recnum); /* This is will never be the first record. */
if (!type)
vr->r.ver.trusthashtbl = recnum;
if (rc)
log_fatal (_("%s: error reading version record: %s\n"),
db_name, gpg_strerror (rc) );
- if (!vr.r.ver.trusthashtbl)
- create_hashtable (&vr, 0);
trusthashtbl = vr.r.ver.trusthashtbl;
}
* the result in REC. The return value of CMP() should be True if the
* record is the desired one.
*
- * Return: -1 if not found, 0 if found or another error code.
- * FIXME: Use GPG_ERR_NOT_FOUND instead of -1.
+ * Return: 0 if found, GPG_ERR_NOT_FOUND, or another error code.
*/
-static int
+static gpg_error_t
lookup_hashtable (ulong table, const byte *key, size_t keylen,
int (*cmpfnc)(const void*, const TRUSTREC *),
const void *cmpdata, TRUSTREC *rec )
item = rec->r.htbl.item[msb % ITEMS_PER_HTBL_RECORD];
if (!item)
- return -1; /* Not found. */
+ return gpg_error (GPG_ERR_NOT_FOUND);
rc = tdbio_read_record (item, rec, 0);
if (rc)
}
}
else
- return -1; /* not found */
+ return gpg_error (GPG_ERR_NOT_FOUND);
}
}
if ((*cmpfnc)(cmpdata, rec))
return 0; /* really found */
- return -1; /* no: not found */
+ return gpg_error (GPG_ERR_NOT_FOUND); /* no: not found */
}
rec->r.ver.trust_model = *p++;
rec->r.ver.min_cert_level = *p++;
p += 2;
- rec->r.ver.created = buf32_to_ulong(p); p += 4;
- rec->r.ver.nextcheck = buf32_to_ulong(p); p += 4;
+ rec->r.ver.created = buf32_to_ulong(p);
+ p += 4;
+ rec->r.ver.nextcheck = buf32_to_ulong(p);
p += 4;
p += 4;
- rec->r.ver.firstfree =buf32_to_ulong(p); p += 4;
p += 4;
- rec->r.ver.trusthashtbl =buf32_to_ulong(p); p += 4;
+ rec->r.ver.firstfree = buf32_to_ulong(p);
+ p += 4;
+ p += 4;
+ rec->r.ver.trusthashtbl = buf32_to_ulong(p);
if (recnum)
{
log_error( _("%s: version record with recnum %lu\n"), db_name,
break;
case RECTYPE_FREE:
- rec->r.free.next = buf32_to_ulong(p); p += 4;
+ rec->r.free.next = buf32_to_ulong(p);
break;
case RECTYPE_HTBL:
for (i=0; i < ITEMS_PER_HTBL_RECORD; i++)
{
- rec->r.htbl.item[i] = buf32_to_ulong(p); p += 4;
+ rec->r.htbl.item[i] = buf32_to_ulong(p);
+ p += 4;
}
break;
case RECTYPE_HLST:
- rec->r.hlst.next = buf32_to_ulong(p); p += 4;
+ rec->r.hlst.next = buf32_to_ulong(p);
+ p += 4;
for (i=0; i < ITEMS_PER_HLST_RECORD; i++)
{
- rec->r.hlst.rnum[i] = buf32_to_ulong(p); p += 4;
+ rec->r.hlst.rnum[i] = buf32_to_ulong(p);
+ p += 4;
}
break;
case RECTYPE_TRUST:
- memcpy (rec->r.trust.fingerprint, p, 20); p+=20;
+ memcpy (rec->r.trust.fingerprint, p, 20);
+ p+=20;
rec->r.trust.ownertrust = *p++;
rec->r.trust.depth = *p++;
rec->r.trust.min_ownertrust = *p++;
p++;
- rec->r.trust.validlist = buf32_to_ulong(p); p += 4;
+ rec->r.trust.validlist = buf32_to_ulong(p);
break;
case RECTYPE_VALID:
- memcpy (rec->r.valid.namehash, p, 20); p+=20;
+ memcpy (rec->r.valid.namehash, p, 20);
+ p+=20;
rec->r.valid.validity = *p++;
- rec->r.valid.next = buf32_to_ulong(p); p += 4;
+ rec->r.valid.next = buf32_to_ulong(p);
+ p += 4;
rec->r.valid.full_count = *p++;
rec->r.valid.marginal_count = *p++;
break;
if (offset == (off_t)(-1))
log_fatal ("trustdb: lseek to end failed: %s\n", strerror (errno));
recnum = offset / TRUST_RECORD_LEN;
- assert (recnum); /* this is will never be the first record */
+ log_assert (recnum); /* this is will never be the first record */
/* We must write a record, so that the next call to this
* function returns another recnum. */
memset (&rec, 0, sizeof rec);
* Given a 20 byte FINGERPRINT search its trust record and return
* that at REC.
*
- * Return: -1 if not found, 0 if found or another error code.
- * FIXME: Use GPG_ERR_NOT_FOUND instead of -1.
+ * Return: 0 if found, GPG_ERR_NOT_FOUND, or another error code.
*/
-int
+gpg_error_t
tdbio_search_trust_byfpr (const byte *fingerprint, TRUSTREC *rec)
{
int rc;
* Given a primary public key object PK search its trust record and
* return that at REC.
*
- * Return: -1 if not found, 0 if found or another error code.
- * FIXME: Use GPG_ERR_NOT_FOUND instead of -1.
+ * Return: 0 if found, GPG_ERR_NOT_FOUND, or another error code.
*/
-int
+gpg_error_t
tdbio_search_trust_bypk (PKT_public_key *pk, TRUSTREC *rec)
{
byte fingerprint[MAX_FINGERPRINT_LEN];