⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 db.c

📁 yum-metadata-parser 一个用C写的yum仓库解析库
💻 C
📖 第 1 页 / 共 2 页
字号:
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- *//* This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License, * version 2, as published by the Free Software Foundation * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 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, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307, USA. */#include <string.h>#include <unistd.h>#include "db.h"GQuarkyum_db_error_quark (void){    static GQuark quark;    if (!quark)        quark = g_quark_from_static_string ("yum_db_error");    return quark;}#define ENCODED_PACKAGE_FILE_FILES 2048#define ENCODED_PACKAGE_FILE_TYPES 60typedef struct {    GString *files;    GString *types;} EncodedPackageFile;static EncodedPackageFile *encoded_package_file_new (void){    EncodedPackageFile *enc;    enc = g_new0 (EncodedPackageFile, 1);    enc->files = g_string_sized_new (ENCODED_PACKAGE_FILE_FILES);    enc->types = g_string_sized_new (ENCODED_PACKAGE_FILE_TYPES);    return enc;}static voidencoded_package_file_free (EncodedPackageFile *file){    g_string_free (file->files, TRUE);    g_string_free (file->types, TRUE);    g_free (file);}static GHashTable *package_files_to_hash (GSList *files){    GHashTable *hash;    GSList *iter;    PackageFile *file;    EncodedPackageFile *enc;    char *dir;    char *name;    hash = g_hash_table_new_full (g_str_hash, g_str_equal,                                  (GDestroyNotify) g_free,                                  (GDestroyNotify) encoded_package_file_free);    for (iter = files; iter; iter = iter->next) {        file = (PackageFile *) iter->data;        dir = g_path_get_dirname (file->name);        name = g_path_get_basename (file->name);        enc = (EncodedPackageFile *) g_hash_table_lookup (hash, dir);        if (!enc) {            enc = encoded_package_file_new ();            g_hash_table_insert (hash, dir, enc);        } else            g_free (dir);        if (enc->files->len)            g_string_append_c (enc->files, '/');        g_string_append (enc->files, name);        g_free (name);        if (!strcmp (file->type, "dir"))            g_string_append_c (enc->types, 'd');        else if (!strcmp (file->type, "file"))            g_string_append_c (enc->types, 'f');        else if (!strcmp (file->type, "ghost"))            g_string_append_c (enc->types, 'g');    }    return hash;}char *yum_db_filename (const char *prefix){    char *filename;    filename = g_strconcat (prefix, ".sqlite", NULL);    return filename;}typedef enum {    DB_STATUS_OK,    DB_STATUS_VERSION_MISMATCH,    DB_STATUS_CHECKSUM_MISMATCH,    DB_STATUS_ERROR} DBStatus;static DBStatusdbinfo_status (sqlite3 *db, const char *checksum){    const char *query;    int rc;    sqlite3_stmt *handle = NULL;    DBStatus status = DB_STATUS_ERROR;    query = "SELECT dbversion, checksum FROM db_info";    rc = sqlite3_prepare (db, query, -1, &handle, NULL);    if (rc != SQLITE_OK)        goto cleanup;    while ((rc = sqlite3_step (handle)) == SQLITE_ROW) {        int dbversion;        const char *dbchecksum;        dbversion  = sqlite3_column_int  (handle, 0);        dbchecksum = (const char *) sqlite3_column_text (handle, 1);        if (dbversion != YUM_SQLITE_CACHE_DBVERSION) {            g_message ("Warning: cache file is version %d, we need %d, will regenerate",                       dbversion, YUM_SQLITE_CACHE_DBVERSION);            status = DB_STATUS_VERSION_MISMATCH;        } else if (strcmp (checksum, dbchecksum)) {            g_message ("sqlite cache needs updating, reading in metadata");            status = DB_STATUS_CHECKSUM_MISMATCH;        } else            status = DB_STATUS_OK;        break;    } cleanup:    if (handle)        sqlite3_finalize (handle);    return status;}static voidyum_db_create_dbinfo_table (sqlite3 *db, GError **err){    int rc;    const char *sql;    sql = "CREATE TABLE db_info (dbversion INTEGER, checksum TEXT)";    rc = sqlite3_exec (db, sql, NULL, NULL, NULL);    if (rc != SQLITE_OK) {        g_set_error (err, YUM_DB_ERROR, YUM_DB_ERROR,                     "Can not create db_info table: %s",                     sqlite3_errmsg (db));    }}sqlite3 *yum_db_open (const char *path,             const char *checksum,             CreateTablesFn create_tables,             GError **err){    int rc;    sqlite3 *db = NULL;    gboolean db_existed;    db_existed = g_file_test (path, G_FILE_TEST_EXISTS);    rc = sqlite3_open (path, &db);    if (rc == SQLITE_OK) {        if (db_existed) {            DBStatus status = dbinfo_status (db, checksum);            switch (status) {            case DB_STATUS_OK:                /* Everything is up-to-date */                sqlite3_close (db);                return NULL;                break;            case DB_STATUS_CHECKSUM_MISMATCH:                sqlite3_exec (db, "PRAGMA synchronous = 0", NULL, NULL, NULL);                sqlite3_exec (db, "DELETE FROM db_info", NULL, NULL, NULL);                return db;                break;            case DB_STATUS_VERSION_MISMATCH:            case DB_STATUS_ERROR:                sqlite3_close (db);                db = NULL;                unlink (path);                break;            }        }    } else {        /* Let's try to delete it and try again,           maybe it's a sqlite3 version mismatch. */        sqlite3_close (db);        db = NULL;        unlink (path);    }    if (!db) {        rc = sqlite3_open (path, &db);        if (rc != SQLITE_OK) {            g_set_error (err, YUM_DB_ERROR, YUM_DB_ERROR,                         "Can not open SQL database: %s",                         sqlite3_errmsg (db));            goto cleanup;        }    }    yum_db_create_dbinfo_table (db, err);    if (*err)        goto cleanup;    create_tables (db, err);    if (*err)        goto cleanup;    sqlite3_exec (db, "PRAGMA synchronous = 0", NULL, NULL, NULL); cleanup:    if (*err && db) {        sqlite3_close (db);        db = NULL;    }    return db;}voidyum_db_dbinfo_update (sqlite3 *db, const char *checksum, GError **err){    int rc;    char *sql;    sql = g_strdup_printf        ("INSERT INTO db_info (dbversion, checksum) VALUES (%d, '%s')",         YUM_SQLITE_CACHE_DBVERSION, checksum);    rc = sqlite3_exec (db, sql, NULL, NULL, NULL);    if (rc != SQLITE_OK)        g_set_error (err, YUM_DB_ERROR, YUM_DB_ERROR,                     "Can not update dbinfo table: %s",                     sqlite3_errmsg (db));    g_free (sql);}GHashTable *yum_db_read_package_ids (sqlite3 *db, GError **err){    const char *query;    int rc;    GHashTable *hash = NULL;    sqlite3_stmt *handle = NULL;    query = "SELECT pkgId, pkgKey FROM packages";    rc = sqlite3_prepare (db, query, -1, &handle, NULL);    if (rc != SQLITE_OK) {        g_set_error (err, YUM_DB_ERROR, YUM_DB_ERROR,                     "Can not prepare SQL clause: %s",                     sqlite3_errmsg (db));        goto cleanup;    }    hash = g_hash_table_new_full (g_str_hash, g_str_equal,                                  (GDestroyNotify) g_free, NULL);    while ((rc = sqlite3_step (handle)) == SQLITE_ROW) {        char *pkgId;        gint pkgKey;        pkgId  = g_strdup ((char *) sqlite3_column_text  (handle, 0));        pkgKey = sqlite3_column_int (handle, 1);        g_hash_table_insert (hash, pkgId, GINT_TO_POINTER (pkgKey));    }    if (rc != SQLITE_DONE)        g_set_error (err, YUM_DB_ERROR, YUM_DB_ERROR,                     "Error reading from SQL: %s",                     sqlite3_errmsg (db)); cleanup:    if (handle)        sqlite3_finalize (handle);    return hash;}voidyum_db_create_primary_tables (sqlite3 *db, GError **err){    int rc;    const char *sql;    sql =        "CREATE TABLE packages ("        "  pkgKey INTEGER PRIMARY KEY,"        "  pkgId TEXT,"        "  name TEXT,"        "  arch TEXT,"        "  version TEXT,"        "  epoch TEXT,"        "  release TEXT,"        "  summary TEXT,"        "  description TEXT,"        "  url TEXT,"        "  time_file INTEGER,"        "  time_build INTEGER,"        "  rpm_license TEXT,"        "  rpm_vendor TEXT,"        "  rpm_group TEXT,"        "  rpm_buildhost TEXT,"        "  rpm_sourcerpm TEXT,"        "  rpm_header_start INTEGER,"        "  rpm_header_end INTEGER,"        "  rpm_packager TEXT,"        "  size_package INTEGER,"        "  size_installed INTEGER,"        "  size_archive INTEGER,"        "  location_href TEXT,"        "  location_base TEXT,"        "  checksum_type TEXT)";    rc = sqlite3_exec (db, sql, NULL, NULL, NULL);    if (rc != SQLITE_OK) {        g_set_error (err, YUM_DB_ERROR, YUM_DB_ERROR,                     "Can not create packages table: %s",                     sqlite3_errmsg (db));        return;    }    sql = "CREATE INDEX packagename ON packages (name)";    rc = sqlite3_exec (db, sql, NULL, NULL, NULL);    if (rc != SQLITE_OK) {        g_set_error (err, YUM_DB_ERROR, YUM_DB_ERROR,                     "Can not create packagename index: %s",                     sqlite3_errmsg (db));        return;    }        sql = "CREATE INDEX packageId ON packages (pkgId)";    rc = sqlite3_exec (db, sql, NULL, NULL, NULL);    if (rc != SQLITE_OK) {        g_set_error (err, YUM_DB_ERROR, YUM_DB_ERROR,                     "Can not create packageId index: %s",                     sqlite3_errmsg (db));        return;    }    sql =        "CREATE TABLE files ("        "  name TEXT,"        "  type TEXT,"        "  pkgKey INTEGER)";    rc = sqlite3_exec (db, sql, NULL, NULL, NULL);    if (rc != SQLITE_OK) {        g_set_error (err, YUM_DB_ERROR, YUM_DB_ERROR,                     "Can not create files table: %s",                     sqlite3_errmsg (db));        return;    }    sql = "CREATE INDEX filenames ON files (name)";    rc = sqlite3_exec (db, sql, NULL, NULL, NULL);    if (rc != SQLITE_OK) {        g_set_error (err, YUM_DB_ERROR, YUM_DB_ERROR,                     "Can not create filenames index: %s",                     sqlite3_errmsg (db));        return;    }    sql =        "CREATE TABLE %s ("        "  name TEXT,"        "  flags TEXT,"        "  epoch TEXT,"        "  version TEXT,"        "  release TEXT,"        "  pkgKey INTEGER %s)";    const char *deps[] = { "requires", "provides", "conflicts", "obsoletes", NULL };    int i;    const char *pkgindexsql = "CREATE INDEX pkg%s on %s (pkgKey)";    const char *nameindexsql = "CREATE INDEX %sname ON %s (name)";    for (i = 0; deps[i]; i++) {        const char *prereq;        char *query;        if (!strcmp(deps[i], "requires")) {            prereq = ", pre BOOLEAN DEFAULT FALSE";        } else            prereq = "";        query = g_strdup_printf (sql, deps[i], prereq);        rc = sqlite3_exec (db, query, NULL, NULL, NULL);        g_free (query);        if (rc != SQLITE_OK) {            g_set_error (err, YUM_DB_ERROR, YUM_DB_ERROR,                         "Can not create %s table: %s",                         deps[i], sqlite3_errmsg (db));            return;        }        query = g_strdup_printf(pkgindexsql, deps[i], deps[i]);        rc = sqlite3_exec (db, query, NULL, NULL, NULL);        g_free (query);        if (rc != SQLITE_OK) {            g_set_error (err, YUM_DB_ERROR, YUM_DB_ERROR,                         "Can not create index on %s table: %s",                         deps[i], sqlite3_errmsg (db));            return;        }        if (i < 2) {            query = g_strdup_printf(nameindexsql, deps[i], deps[i]);            rc = sqlite3_exec (db, query, NULL, NULL, NULL);            if (rc != SQLITE_OK) {                g_set_error (err, YUM_DB_ERROR, YUM_DB_ERROR,                             "Can not create %sname index: %s",                             deps[i], sqlite3_errmsg (db));                return;            }        }    }    sql =        "CREATE TRIGGER removals AFTER DELETE ON packages"        "  BEGIN"        "    DELETE FROM files WHERE pkgKey = old.pkgKey;"        "    DELETE FROM requires WHERE pkgKey = old.pkgKey;"        "    DELETE FROM provides WHERE pkgKey = old.pkgKey;"        "    DELETE FROM conflicts WHERE pkgKey = old.pkgKey;"        "    DELETE FROM obsoletes WHERE pkgKey = old.pkgKey;"        "  END;";    rc = sqlite3_exec (db, sql, NULL, NULL, NULL);    if (rc != SQLITE_OK) {        g_set_error (err, YUM_DB_ERROR, YUM_DB_ERROR,                     "Can not create removals trigger: %s",                     sqlite3_errmsg (db));        return;    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -