int tdbio_set_dbname( const char *new_dbname, int create ) { char *fname; static int initialized = 0; if( !initialized ) { atexit( cleanup ); initialized = 1; } if(new_dbname==NULL) fname=make_filename(opt.homedir,"trustdb" EXTSEP_S "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); } else fname = xstrdup (new_dbname); if( access( fname, R_OK ) ) { if( errno != ENOENT ) { log_error( _("can't access `%s': %s\n"), fname, strerror(errno) ); xfree(fname); return G10ERR_TRUSTDB; } if( create ) { FILE *fp; TRUSTREC rec; int rc; char *p = strrchr( fname, DIRSEP_C ); mode_t oldmask; assert(p); *p = 0; if( access( fname, F_OK ) ) { try_make_homedir( fname ); log_fatal( _("%s: directory does not exist!\n"), fname ); } *p = DIRSEP_C; xfree(db_name); db_name = fname; #ifdef __riscos__ if( !lockhandle ) lockhandle = create_dotlock( db_name ); if( !lockhandle ) log_fatal( _("can't create lock for `%s'\n"), db_name ); if( make_dotlock( lockhandle, -1 ) ) log_fatal( _("can't lock `%s'\n"), db_name ); #endif /* __riscos__ */ oldmask=umask(077); if (is_secured_filename (fname)) { fp = NULL; 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) ); #ifndef __riscos__ if( !lockhandle ) lockhandle = create_dotlock( db_name ); if( !lockhandle ) log_fatal( _("can't create lock for `%s'\n"), db_name ); #endif /* !__riscos__ */ rc = create_version_record (); if( rc ) log_fatal( _("%s: failed to create version record: %s"), fname, g10_errstr(rc)); /* and 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); return 0; } } xfree(db_name); db_name = fname; return 0; }
int tdbio_set_dbname( const char *new_dbname, int create, int *r_nofile) { char *fname; struct stat statbuf; static int initialized = 0; if( !initialized ) { atexit( cleanup ); initialized = 1; } *r_nofile = 0; if(new_dbname==NULL) fname=make_filename(opt.homedir,"trustdb" EXTSEP_S "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); } else fname = xstrdup (new_dbname); xfree (db_name); db_name = fname; /* * Quick check for (likely) case where there is trustdb.gpg * already. This check is not required in theory, but it helps in * practice, avoiding costly operations of preparing and taking * the lock. */ if (stat (fname, &statbuf) == 0 && statbuf.st_size > 0) /* OK, we have the valid trustdb.gpg already. */ return 0; take_write_lock (); if( access( fname, R_OK ) ) { if( errno != ENOENT ) log_fatal( _("can't access `%s': %s\n"), fname, strerror(errno) ); if (!create) *r_nofile = 1; else { 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; 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) ); rc = create_version_record (); if( rc ) log_fatal( _("%s: failed to create version record: %s"), fname, g10_errstr(rc)); /* and 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); } } release_write_lock (); return 0; }
/* * Migrate the trustdb as just up to gpg 1.0.6 (trustdb version 2) * to the 2.1 version as used with 1.0.6b - This is pretty trivial as needs * only to scan the tdb and insert new the new trust records. The old ones are * obsolte from now on */ static void migrate_from_v2 () { TRUSTREC rec; int i, n; struct { ulong keyrecno; byte ot; byte okay; byte fpr[20]; } *ottable; int ottable_size, ottable_used; byte oldbuf[40]; ulong recno; int rc, count; ottable_size = 5; ottable = xmalloc (ottable_size * sizeof *ottable); ottable_used = 0; /* We have some restrictions here. We can't use the version record * and we can't use any of the old hashtables because we dropped the * code. So we first collect all ownertrusts and then use a second * pass fo find the associated keys. We have to do this all without using * the regular record read functions. */ /* get all the ownertrusts */ if (lseek (db_fd, 0, SEEK_SET ) == -1 ) log_fatal ("migrate_from_v2: lseek failed: %s\n", strerror (errno)); for (recno=0;;recno++) { do n = read (db_fd, oldbuf, 40); while (n==-1 && errno == EINTR); if (!n) break; /* eof */ if (n != 40) log_fatal ("migrate_vfrom_v2: read error or short read\n"); if (*oldbuf != 2) continue; /* v2 dir record */ if (ottable_used == ottable_size) { ottable_size += 1000; ottable = xrealloc (ottable, ottable_size * sizeof *ottable); } ottable[ottable_used].keyrecno = buftoulong (oldbuf+6); ottable[ottable_used].ot = oldbuf[18]; ottable[ottable_used].okay = 0; memset (ottable[ottable_used].fpr,0, 20); if (ottable[ottable_used].keyrecno && ottable[ottable_used].ot) ottable_used++; } log_info ("found %d ownertrust records\n", ottable_used); /* Read again and find the fingerprints */ if (lseek (db_fd, 0, SEEK_SET ) == -1 ) log_fatal ("migrate_from_v2: lseek failed: %s\n", strerror (errno)); for (recno=0;;recno++) { do n = read (db_fd, oldbuf, 40); while (n==-1 && errno == EINTR); if (!n) break; /* eof */ if (n != 40) log_fatal ("migrate_from_v2: read error or short read\n"); if (*oldbuf != 3) continue; /* v2 key record */ for (i=0; i < ottable_used; i++) { if (ottable[i].keyrecno == recno) { memcpy (ottable[i].fpr, oldbuf+20, 20); ottable[i].okay = 1; break; } } } /* got everything - create the v3 trustdb */ if (ftruncate (db_fd, 0)) log_fatal ("can't truncate `%s': %s\n", db_name, strerror (errno) ); if (create_version_record ()) log_fatal ("failed to recreate version record of `%s'\n", db_name); /* access the hash table, so it is store just after the version record, * this is not needed put a dump is more pretty */ get_trusthashrec (); /* And insert the old ownertrust values */ count = 0; for (i=0; i < ottable_used; i++) { if (!ottable[i].okay) continue; memset (&rec, 0, sizeof rec); rec.recnum = tdbio_new_recnum (); rec.rectype = RECTYPE_TRUST; memcpy(rec.r.trust.fingerprint, ottable[i].fpr, 20); rec.r.trust.ownertrust = ottable[i].ot; if (tdbio_write_record (&rec)) log_fatal ("failed to write trust record of `%s'\n", db_name); count++; } revalidation_mark (); rc = tdbio_sync (); if (rc) log_fatal ("failed to sync `%s'\n", db_name); log_info ("migrated %d version 2 ownertrusts\n", count); xfree (ottable); }
/* * Set the file name for the trustdb to NEW_DBNAME and if CREATE is * true create that file. If NEW_DBNAME is NULL a default name is * used, if the it does not contain a path component separator ('/') * the global GnuPG home directory is used. * * Returns: 0 on success or an error code. * * On the first call this function registers an atexit handler. * */ int tdbio_set_dbname (const char *new_dbname, int create, int *r_nofile) { char *fname, *p; struct stat statbuf; static int initialized = 0; int save_slash; if (!initialized) { atexit (cleanup); initialized = 1; } *r_nofile = 0; if (!new_dbname) { fname = make_filename (opt.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); } else { fname = xstrdup (new_dbname); } xfree (db_name); db_name = fname; /* Quick check for (likely) case where there already is a * trustdb.gpg. This check is not required in theory, but it helps * in practice avoiding costly operations of preparing and taking * the lock. */ if (!stat (fname, &statbuf) && statbuf.st_size > 0) { /* 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*/ 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)) { 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) gpg_err_set_errno (ENOENT); else gpg_err_set_errno (EIO); #endif /*HAVE_W32CE_SYSTEM*/ if (errno != ENOENT) log_fatal ( _("can't access '%s': %s\n"), fname, strerror (errno)); 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); 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)); /* 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); } release_write_lock (); return 0; }