2015-03-20 03:45:30 +03:00
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
*
* Copyright ( C ) 2014 Colin Walters < walters @ verbum . org >
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation ; either version 2 of the licence or ( at
* your option ) any later version .
*
* This library 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
* Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library ; if not , write to the
* Free Software Foundation , Inc . , 59 Temple Place , Suite 330 ,
* Boston , MA 02111 - 1307 , USA .
*/
# include "config.h"
# include "string.h"
# include "rpmostree-db.h"
# include "rpmostree-cleanup.h"
2015-04-09 00:20:50 +03:00
/**
* SECTION : librpmostree - dbquery
* @ title : Query RPM database
* @ short_description : Access the RPM database in commits
*
* These APIs provide queryable access to the RPM database inside an
* OSTree repository .
*/
2015-03-20 03:45:30 +03:00
struct RpmOstreeDbQueryResult
{
volatile gint refcount ;
GPtrArray * packages ;
} ;
RpmOstreeDbQueryResult *
rpm_ostree_db_query_ref ( RpmOstreeDbQueryResult * result )
{
g_atomic_int_inc ( & result - > refcount ) ;
return result ;
}
void
rpm_ostree_db_query_unref ( RpmOstreeDbQueryResult * result )
{
if ( ! g_atomic_int_dec_and_test ( & result - > refcount ) )
return ;
g_ptr_array_unref ( result - > packages ) ;
g_free ( result ) ;
}
G_DEFINE_BOXED_TYPE ( RpmOstreeDbQueryResult , rpm_ostree_db_query_result ,
rpm_ostree_db_query_ref ,
rpm_ostree_db_query_unref ) ;
G_DEFINE_AUTOPTR_CLEANUP_FUNC ( RpmOstreeDbQueryResult , rpm_ostree_db_query_unref )
/**
* rpm_ostree_db_query_result_get_packages :
* @ queryresult : Query result
*
* Returns : ( transfer none ) ( array zero - terminated = 1 ) ( element - type utf8 ) : List of packages , % NULL terminated
*/
const char * const *
rpm_ostree_db_query_result_get_packages ( RpmOstreeDbQueryResult * queryresult )
{
return ( const char * const * ) queryresult - > packages - > pdata ;
}
/**
* rpm_ostree_db_query :
* @ repo : An OSTree repository
* @ ref : A branch name or commit
* @ query : ( allow - none ) : Currently , this must be % NULL
* @ cancellable : Cancellable
* @ error : Error
*
* Query the RPM packages present in the @ ref branch or commit in
* @ repo . At present , @ query must be % NULL ; all packages will be
* returned . A future enhancement to this API may allow querying a
* subset of packages .
*
* Returns : ( transfer full ) : A new query result , or % NULL on error
*/
RpmOstreeDbQueryResult *
rpm_ostree_db_query ( OstreeRepo * repo ,
const char * ref ,
GVariant * query ,
GCancellable * cancellable ,
GError * * error )
{
int rc ;
OstreeRepoCheckoutOptions checkout_options = { 0 , } ;
g_autofree char * commit = NULL ;
_cleanup_hysack_ HySack sack = NULL ;
_cleanup_hyquery_ HyQuery hquery = NULL ;
_cleanup_hypackagelist_ HyPackageList pkglist = NULL ;
g_autofree char * tempdir = g_strdup ( " /tmp/rpmostree-dbquery-XXXXXXXX " ) ;
g_autofree char * rpmdb_tempdir = NULL ;
gs_unref_object GFile * commit_rpmdb = NULL ;
glnx_fd_close int tempdir_dfd = - 1 ;
g_return_val_if_fail ( query = = NULL , FALSE ) ;
if ( ! ostree_repo_resolve_rev ( repo , ref , FALSE , & commit , error ) )
goto out ;
if ( mkdtemp ( tempdir ) = = NULL )
{
glnx_set_error_from_errno ( error ) ;
goto out ;
}
if ( ! glnx_opendirat ( AT_FDCWD , tempdir , FALSE , & tempdir_dfd , error ) )
goto out ;
/* Create intermediate dirs */
if ( ! glnx_shutil_mkdir_p_at ( tempdir_dfd , " usr/share " , 0777 , cancellable , error ) )
goto out ;
checkout_options . mode = OSTREE_REPO_CHECKOUT_MODE_USER ;
checkout_options . subpath = " usr/share/rpm " ;
if ( ! ostree_repo_checkout_tree_at ( repo , & checkout_options ,
tempdir_dfd , " usr/share/rpm " ,
commit ,
cancellable , error ) )
goto out ;
# if BUILDOPT_HAWKEY_SACK_CREATE2
sack = hy_sack_create ( NULL , NULL ,
rpmdb_tempdir ,
NULL ,
0 ) ;
# else
sack = hy_sack_create ( NULL , NULL ,
rpmdb_tempdir ,
0 ) ;
# endif
if ( sack = = NULL )
{
g_set_error ( error , G_IO_ERROR , G_IO_ERROR_FAILED ,
" Failed to create sack cache " ) ;
goto out ;
}
rc = hy_sack_load_system_repo ( sack , NULL , 0 ) ;
if ( ! hif_error_set_from_hawkey ( rc , error ) )
{
g_prefix_error ( error , " Failed to load system repo: " ) ;
goto out ;
}
hquery = hy_query_create ( sack ) ;
hy_query_filter ( hquery , HY_PKG_REPONAME , HY_EQ , HY_SYSTEM_REPO_NAME ) ;
pkglist = hy_query_run ( hquery ) ;
( void ) glnx_shutil_rm_rf_at ( AT_FDCWD , tempdir , cancellable , NULL ) ;
/* Do output creation now, no errors can be thrown */
{
RpmOstreeDbQueryResult * result = g_new0 ( RpmOstreeDbQueryResult , 1 ) ;
int i , c ;
result - > refcount = 1 ;
result - > packages = g_ptr_array_new_with_free_func ( free ) ;
c = hy_packagelist_count ( pkglist ) ;
for ( i = 0 ; i < c ; i + + )
{
HyPackage pkg = hy_packagelist_get ( pkglist , i ) ;
g_ptr_array_add ( result - > packages , hy_package_get_nevra ( pkg ) ) ;
}
g_ptr_array_add ( result - > packages , NULL ) ;
return g_steal_pointer ( & result ) ;
}
out :
return NULL ;
}