/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- * * Copyright (C) 2007 Tom Parker * * Licensed under the GNU General Public License Version 2 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * 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 "pk-backend-apt.h" #include #include #include typedef enum {FIELD_PKG=1,FIELD_VER,FIELD_DEPS,FIELD_ARCH,FIELD_SHORT,FIELD_LONG,FIELD_REPO} Fields; void apt_build_db(PkBackend * backend, sqlite3 *db) { GMatchInfo *match_info; GError *error = NULL; gchar *contents = NULL; gchar *sdir; const gchar *fname; GRegex *origin, *suite; GDir *dir; GHashTable *releases; int res; sqlite3_stmt *package = NULL; pk_backend_change_status(backend, PK_STATUS_ENUM_QUERY); pk_backend_no_percentage_updates(backend); sdir = g_build_filename(_config->Find("Dir").c_str(),_config->Find("Dir::State").c_str(),_config->Find("Dir::State::lists").c_str(), NULL); dir = g_dir_open(sdir,0,&error); if (error!=NULL) { pk_backend_error_code(backend, PK_ERROR_ENUM_INTERNAL_ERROR, "can't open %s",dir); g_error_free(error); goto search_task_cleanup; } origin = g_regex_new("^Origin: (\\S+)",(GRegexCompileFlags)(G_REGEX_CASELESS|G_REGEX_OPTIMIZE|G_REGEX_MULTILINE),(GRegexMatchFlags)0,NULL); suite = g_regex_new("^Suite: (\\S+)",(GRegexCompileFlags)(G_REGEX_CASELESS|G_REGEX_OPTIMIZE|G_REGEX_MULTILINE),(GRegexMatchFlags)0,NULL); releases = g_hash_table_new_full(g_str_hash,g_str_equal,g_free,g_free); while ((fname = g_dir_read_name(dir))!=NULL) { gchar *temp, *parsed_name; gchar** items = g_strsplit(fname,"_",-1); guint len = g_strv_length(items); if(len<=3) // minimum is __ { g_strfreev(items); continue; } /* warning: nasty hack with g_strjoinv */ temp = items[len-2]; items[len-2] = NULL; parsed_name = g_strjoinv("_",items); items[len-2] = temp; if (g_ascii_strcasecmp(items[len-1],"Release")==0 && g_ascii_strcasecmp(items[len-2],"source")!=0) { gchar * repo = NULL, *fullname; fullname = g_build_filename(sdir,fname,NULL); if (g_file_get_contents(fullname,&contents,NULL,NULL) == FALSE) { pk_backend_error_code(backend, PK_ERROR_ENUM_INTERNAL_ERROR, "error loading %s",fullname); goto search_task_cleanup; } g_free(fullname); g_regex_match (origin, contents, (GRegexMatchFlags)0, &match_info); if (!g_match_info_matches(match_info)) { pk_backend_error_code(backend, PK_ERROR_ENUM_INTERNAL_ERROR, "origin regex failure in %s",fname); goto search_task_cleanup; } repo = g_match_info_fetch (match_info, 1); g_regex_match (suite, contents, (GRegexMatchFlags)0, &match_info); if (g_match_info_matches(match_info)) { temp = g_strconcat(repo,"/",g_match_info_fetch (match_info, 1),NULL); g_free(repo); repo = temp; } temp = parsed_name; parsed_name = g_strconcat(temp,"_",items[len-2],NULL); g_free(temp); pk_debug("type is %s, group is %s, parsed_name is %s",items[len-2],items[len-1],parsed_name); g_hash_table_insert(releases, parsed_name, repo); g_free(contents); contents = NULL; } else g_free(parsed_name); g_strfreev(items); } g_dir_close(dir); /* and then we need to do this again, but this time we're looking for the packages */ dir = g_dir_open(sdir,0,&error); res = sqlite3_prepare_v2(db, "insert or replace into packages values (?,?,?,?,?,?,?)", -1, &package, NULL); if (res!=SQLITE_OK) pk_error("sqlite error during insert prepare: %s", sqlite3_errmsg(db)); else pk_debug("insert prepare ok for %p",package); while ((fname = g_dir_read_name(dir))!=NULL) { gchar** items = g_strsplit(fname,"_",-1); guint len = g_strv_length(items); if(len<=3) // minimum is __ { g_strfreev(items); continue; } if (g_ascii_strcasecmp(items[len-1],"Packages")==0) { const gchar *repo; gchar *temp=NULL, *parsed_name=NULL; gchar *fullname= NULL; gchar *begin=NULL, *next=NULL, *description = NULL; glong count = 0; gboolean haspk = FALSE; /* warning: nasty hack with g_strjoinv */ if (g_str_has_prefix(items[len-2],"binary-")) { temp = items[len-3]; items[len-3] = NULL; parsed_name = g_strjoinv("_",items); items[len-3] = temp; } else { temp = items[len-1]; items[len-1] = NULL; parsed_name = g_strjoinv("_",items); items[len-1] = temp; } pk_debug("type is %s, group is %s, parsed_name is %s",items[len-2],items[len-1],parsed_name); repo = (const gchar *)g_hash_table_lookup(releases,parsed_name); if (repo == NULL) { pk_debug("Can't find repo for %s, marking as \"unknown\"",parsed_name); repo = g_strdup("unknown"); //g_assert(0); } else pk_debug("repo for %s is %s",parsed_name,repo); g_free(parsed_name); fullname = g_build_filename(sdir,fname,NULL); pk_debug("loading %s",fullname); if (g_file_get_contents(fullname,&contents,NULL,NULL) == FALSE) { pk_backend_error_code(backend, PK_ERROR_ENUM_INTERNAL_ERROR, "error loading %s",fullname); goto search_task_cleanup; } /*else pk_debug("loaded");*/ res = sqlite3_bind_text(package,FIELD_REPO,repo,-1,SQLITE_TRANSIENT); if (res!=SQLITE_OK) pk_error("sqlite error during repo bind: %s", sqlite3_errmsg(db)); /*else pk_debug("repo bind ok");*/ res = sqlite3_exec(db,"begin",NULL,NULL,NULL); g_assert(res == SQLITE_OK); begin = contents; while (true) { next = strstr(begin,"\n"); if (next!=NULL) { next[0] = '\0'; next++; } if (begin[0]=='\0') { if (haspk) { if (description!=NULL) { res=sqlite3_bind_text(package,FIELD_LONG,description,-1,SQLITE_TRANSIENT); if (res!=SQLITE_OK) pk_error("sqlite error during description bind: %s", sqlite3_errmsg(db)); g_free(description); description = NULL; } res = sqlite3_step(package); if (res!=SQLITE_DONE) pk_error("sqlite error during step: %s", sqlite3_errmsg(db)); sqlite3_reset(package); //pk_debug("added package"); haspk = FALSE; } //g_assert(0); } else if (begin[0]==' ') { if (description == NULL) description = g_strdup(&begin[1]); else { gchar *oldval = description; description = g_strconcat(oldval, "\n",&begin[1],NULL); g_free(oldval); } } else { gchar *colon = strchr(begin,':'); g_assert(colon!=NULL); colon[0] = '\0'; colon+=2; /*if (strlen(colon)>3000) pk_error("strlen(colon) = %d\ncolon = %s",strlen(colon),colon);*/ //pk_debug("entry = '%s','%s'",begin,colon); if (begin[0] == 'P' && g_strcasecmp("Package",begin)==0) { res=sqlite3_bind_text(package,FIELD_PKG,colon,-1,SQLITE_STATIC); haspk = TRUE; count++; if (count%1000==0) pk_debug("Package %ld (%s)",count,colon); } else if (begin[0] == 'V' && g_strcasecmp("Version",begin)==0) res=sqlite3_bind_text(package,FIELD_VER,colon,-1,SQLITE_STATIC); else if (begin[0] == 'D' && g_strcasecmp("Depends",begin)==0) res=sqlite3_bind_text(package,FIELD_DEPS,colon,-1,SQLITE_STATIC); else if (begin[0] == 'A' && g_strcasecmp("Architecture",begin)==0) res=sqlite3_bind_text(package,FIELD_ARCH,colon,-1,SQLITE_STATIC); else if (begin[0] == 'D' && g_strcasecmp("Description",begin)==0) res=sqlite3_bind_text(package,FIELD_SHORT,colon,-1,SQLITE_STATIC); if (res!=SQLITE_OK) pk_error("sqlite error during %s bind: %s", begin, sqlite3_errmsg(db)); } if (next == NULL) break; begin = next; } res = sqlite3_exec(db,"commit",NULL,NULL,NULL); if (res!=SQLITE_OK) pk_error("sqlite error during commit: %s", sqlite3_errmsg(db)); res = sqlite3_clear_bindings(package); if (res!=SQLITE_OK) pk_error("sqlite error during clear: %s", sqlite3_errmsg(db)); g_free(contents); contents = NULL; } } sqlite3_finalize(package); search_task_cleanup: g_dir_close(dir); g_free(sdir); g_free(contents); }