2017-09-21 22:26:06 +03:00
/*
2016-02-19 00:49:30 +03:00
* Copyright ( C ) 2015 Red Hat , Inc .
*
2018-01-30 22:26:26 +03:00
* SPDX - License - Identifier : LGPL - 2.0 +
*
2016-02-19 00:49:30 +03:00
* This library 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 License , 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
2021-12-07 04:20:55 +03:00
* License along with this library . If not , see < https : //www.gnu.org/licenses/>.
2016-02-19 00:49:30 +03:00
*/
# include "config.h"
# include "libglnx.h"
2023-05-01 21:24:29 +03:00
# include <gio/gio.h>
2016-02-19 00:49:30 +03:00
# include <glib.h>
# include <stdlib.h>
# include <string.h>
2016-12-02 21:34:32 +03:00
# include "ostree-libarchive-private.h"
2016-02-19 00:49:30 +03:00
# include <archive.h>
# include <archive_entry.h>
2023-05-01 21:24:29 +03:00
# include <ostree.h>
2016-02-19 00:49:30 +03:00
2023-05-01 21:24:29 +03:00
typedef struct
{
2016-02-19 00:49:30 +03:00
OstreeRepo * repo ;
int fd ;
2016-02-22 19:18:30 +03:00
int fd_empty ;
2016-02-19 00:49:30 +03:00
char * tmpd ;
2017-08-29 18:46:19 +03:00
GError * skip_all ;
2016-02-19 00:49:30 +03:00
} TestData ;
static void
test_data_init ( TestData * td )
{
GError * error = NULL ;
2023-05-01 21:24:29 +03:00
g_autoptr ( OtAutoArchiveWrite ) a = archive_write_new ( ) ;
2016-02-19 00:49:30 +03:00
struct archive_entry * ae ;
2016-04-22 19:42:05 +03:00
uid_t uid = getuid ( ) ;
gid_t gid = getgid ( ) ;
2016-02-19 00:49:30 +03:00
td - > tmpd = g_mkdtemp ( g_strdup ( " /var/tmp/test-libarchive-import-XXXXXX " ) ) ;
g_assert_cmpint ( 0 , = = , chdir ( td - > tmpd ) ) ;
td - > fd = openat ( AT_FDCWD , " foo.tar.gz " , O_CREAT | O_EXCL | O_RDWR | O_CLOEXEC , 0644 ) ;
2023-05-01 21:24:29 +03:00
( void ) unlink ( " foo.tar.gz " ) ;
2016-02-19 00:49:30 +03:00
g_assert_no_error ( error ) ;
g_assert ( td - > fd > = 0 ) ;
2023-02-08 00:48:15 +03:00
2016-02-19 00:49:30 +03:00
g_assert_cmpint ( 0 , = = , archive_write_set_format_pax ( a ) ) ;
g_assert_cmpint ( 0 , = = , archive_write_add_filter_gzip ( a ) ) ;
g_assert_cmpint ( 0 , = = , archive_write_open_fd ( a , td - > fd ) ) ;
ae = archive_entry_new ( ) ;
archive_entry_set_pathname ( ae , " / " ) ;
archive_entry_set_mode ( ae , S_IFDIR | 0755 ) ;
2016-04-22 19:42:05 +03:00
archive_entry_set_uid ( ae , uid ) ;
archive_entry_set_gid ( ae , gid ) ;
2016-02-19 00:49:30 +03:00
g_assert_cmpint ( 0 , = = , archive_write_header ( a , ae ) ) ;
archive_entry_free ( ae ) ;
ae = archive_entry_new ( ) ;
archive_entry_set_pathname ( ae , " /file " ) ;
archive_entry_set_mode ( ae , S_IFREG | 0777 ) ;
2016-04-22 19:42:05 +03:00
archive_entry_set_uid ( ae , uid ) ;
archive_entry_set_gid ( ae , gid ) ;
2016-02-19 00:49:30 +03:00
archive_entry_set_size ( ae , 4 ) ;
g_assert_cmpint ( 0 , = = , archive_write_header ( a , ae ) ) ;
g_assert_cmpint ( 4 , = = , archive_write_data ( a , " foo \n " , 4 ) ) ;
archive_entry_free ( ae ) ;
ae = archive_entry_new ( ) ;
archive_entry_set_pathname ( ae , " /devnull " ) ;
archive_entry_set_mode ( ae , S_IFCHR | 0777 ) ;
2016-04-22 19:42:05 +03:00
archive_entry_set_uid ( ae , uid ) ;
archive_entry_set_gid ( ae , gid ) ;
2016-02-19 00:49:30 +03:00
archive_entry_set_devmajor ( ae , 1 ) ;
archive_entry_set_devminor ( ae , 3 ) ;
g_assert_cmpint ( 0 , = = , archive_write_header ( a , ae ) ) ;
archive_entry_free ( ae ) ;
ae = archive_entry_new ( ) ;
archive_entry_set_pathname ( ae , " /anotherfile " ) ;
archive_entry_set_mode ( ae , S_IFREG | 0777 ) ;
2016-04-22 19:42:05 +03:00
archive_entry_set_uid ( ae , uid ) ;
archive_entry_set_gid ( ae , gid ) ;
archive_entry_set_size ( ae , 4 ) ;
2020-11-17 03:46:10 +03:00
archive_entry_xattr_add_entry ( ae , " user.a_key " , " my value " , 8 ) ;
archive_entry_xattr_add_entry ( ae , " user.key2 " , " " , 0 ) ;
archive_entry_xattr_add_entry ( ae , " user.b_key " , " contains \0 nuls " , 14 ) ;
2016-04-22 19:42:05 +03:00
g_assert_cmpint ( 0 , = = , archive_write_header ( a , ae ) ) ;
g_assert_cmpint ( 4 , = = , archive_write_data ( a , " bar \n " , 4 ) ) ;
archive_entry_free ( ae ) ;
ae = archive_entry_new ( ) ;
archive_entry_set_pathname ( ae , " /etc " ) ;
archive_entry_set_mode ( ae , S_IFDIR | 0755 ) ;
archive_entry_set_uid ( ae , uid ) ;
archive_entry_set_gid ( ae , gid ) ;
g_assert_cmpint ( 0 , = = , archive_write_header ( a , ae ) ) ;
archive_entry_free ( ae ) ;
ae = archive_entry_new ( ) ;
archive_entry_set_pathname ( ae , " /etc/file " ) ;
archive_entry_set_mode ( ae , S_IFREG | 0777 ) ;
archive_entry_set_uid ( ae , uid ) ;
archive_entry_set_gid ( ae , gid ) ;
2016-02-19 00:49:30 +03:00
archive_entry_set_size ( ae , 4 ) ;
g_assert_cmpint ( 0 , = = , archive_write_header ( a , ae ) ) ;
g_assert_cmpint ( 4 , = = , archive_write_data ( a , " bar \n " , 4 ) ) ;
archive_entry_free ( ae ) ;
g_assert_cmpint ( ARCHIVE_OK , = = , archive_write_close ( a ) ) ;
2016-02-22 19:18:30 +03:00
td - > fd_empty = openat ( AT_FDCWD , " empty.tar.gz " , O_CREAT | O_EXCL | O_RDWR | O_CLOEXEC , 0644 ) ;
g_assert ( td - > fd_empty > = 0 ) ;
2023-05-01 21:24:29 +03:00
( void ) unlink ( " empty.tar.gz " ) ;
2016-02-22 19:18:30 +03:00
2016-12-02 21:34:32 +03:00
g_assert_cmpint ( ARCHIVE_OK , = = , archive_write_free ( a ) ) ;
2016-02-22 19:18:30 +03:00
a = archive_write_new ( ) ;
g_assert ( a ) ;
g_assert_cmpint ( 0 , = = , archive_write_set_format_pax ( a ) ) ;
g_assert_cmpint ( 0 , = = , archive_write_add_filter_gzip ( a ) ) ;
g_assert_cmpint ( 0 , = = , archive_write_open_fd ( a , td - > fd_empty ) ) ;
g_assert_cmpint ( ARCHIVE_OK , = = , archive_write_close ( a ) ) ;
2023-05-01 21:24:29 +03:00
{
g_autoptr ( GFile ) repopath = g_file_new_for_path ( " repo " ) ;
2016-02-19 00:49:30 +03:00
td - > repo = ostree_repo_new ( repopath ) ;
g_assert_cmpint ( 0 , = = , mkdir ( " repo " , 0755 ) ) ;
ostree_repo_create ( td - > repo , OSTREE_REPO_MODE_BARE_USER , NULL , & error ) ;
2017-08-29 18:46:19 +03:00
/* G_IO_ERROR_NOT_SUPPORTED probably means no extended attribute support */
if ( g_error_matches ( error , G_IO_ERROR , G_IO_ERROR_NOT_SUPPORTED ) )
g_propagate_prefixed_error ( & td - > skip_all , g_steal_pointer ( & error ) ,
" Unable to set up repository: " ) ;
else
g_assert_no_error ( error ) ;
2016-02-19 00:49:30 +03:00
}
}
static gboolean
spawn_cmdline ( const char * cmd , GError * * error )
{
int estatus ;
if ( ! g_spawn_command_line_sync ( cmd , NULL , NULL , & estatus , error ) )
return FALSE ;
if ( ! g_spawn_check_exit_status ( estatus , error ) )
return FALSE ;
return TRUE ;
}
2016-04-22 19:42:05 +03:00
static void
test_archive_setup ( int fd , struct archive * a )
{
g_assert_cmpint ( 0 , = = , lseek ( fd , 0 , SEEK_SET ) ) ;
g_assert_cmpint ( 0 , = = , archive_read_support_format_all ( a ) ) ;
g_assert_cmpint ( 0 , = = , archive_read_support_filter_all ( a ) ) ;
g_assert_cmpint ( 0 , = = , archive_read_open_fd ( a , fd , 8192 ) ) ;
}
2016-02-22 19:18:30 +03:00
static void
test_libarchive_noautocreate_empty ( gconstpointer data )
{
2023-05-01 21:24:29 +03:00
TestData * td = ( void * ) data ;
2016-02-22 19:18:30 +03:00
GError * error = NULL ;
2023-05-01 21:24:29 +03:00
g_autoptr ( OtAutoArchiveRead ) a = archive_read_new ( ) ;
OstreeRepoImportArchiveOptions opts = {
0 ,
} ;
2016-02-22 19:18:30 +03:00
glnx_unref_object OstreeMutableTree * mtree = ostree_mutable_tree_new ( ) ;
2017-08-29 18:46:19 +03:00
if ( td - > skip_all ! = NULL )
{
g_test_skip ( td - > skip_all - > message ) ;
return ;
}
2016-04-22 19:42:05 +03:00
test_archive_setup ( td - > fd_empty , a ) ;
2016-02-22 19:18:30 +03:00
( void ) ostree_repo_import_archive_to_mtree ( td - > repo , & opts , a , mtree , NULL , NULL , & error ) ;
g_assert_no_error ( error ) ;
g_assert ( ostree_mutable_tree_get_metadata_checksum ( mtree ) = = NULL ) ;
}
static void
test_libarchive_autocreate_empty ( gconstpointer data )
{
2023-05-01 21:24:29 +03:00
TestData * td = ( void * ) data ;
g_autoptr ( GError ) error = NULL ;
g_autoptr ( OtAutoArchiveRead ) a = archive_read_new ( ) ;
OstreeRepoImportArchiveOptions opts = {
0 ,
} ;
2016-02-22 19:18:30 +03:00
glnx_unref_object OstreeMutableTree * mtree = ostree_mutable_tree_new ( ) ;
2017-08-29 18:46:19 +03:00
if ( td - > skip_all ! = NULL )
{
g_test_skip ( td - > skip_all - > message ) ;
return ;
}
2016-02-22 19:18:30 +03:00
opts . autocreate_parents = 1 ;
2016-04-22 19:42:05 +03:00
test_archive_setup ( td - > fd_empty , a ) ;
2016-02-22 19:18:30 +03:00
( void ) ostree_repo_import_archive_to_mtree ( td - > repo , & opts , a , mtree , NULL , NULL , & error ) ;
g_assert_no_error ( error ) ;
g_assert ( ostree_mutable_tree_get_metadata_checksum ( mtree ) ! = NULL ) ;
}
2016-02-19 00:49:30 +03:00
static void
test_libarchive_error_device_file ( gconstpointer data )
{
2023-05-01 21:24:29 +03:00
TestData * td = ( void * ) data ;
g_autoptr ( GError ) error = NULL ;
g_autoptr ( OtAutoArchiveRead ) a = archive_read_new ( ) ;
OstreeRepoImportArchiveOptions opts = {
0 ,
} ;
2016-02-19 00:49:30 +03:00
glnx_unref_object OstreeMutableTree * mtree = ostree_mutable_tree_new ( ) ;
2017-08-29 18:46:19 +03:00
if ( td - > skip_all ! = NULL )
{
g_test_skip ( td - > skip_all - > message ) ;
return ;
}
2016-04-22 19:42:05 +03:00
test_archive_setup ( td - > fd , a ) ;
2016-02-19 00:49:30 +03:00
( void ) ostree_repo_import_archive_to_mtree ( td - > repo , & opts , a , mtree , NULL , NULL , & error ) ;
g_assert ( error ! = NULL ) ;
2016-12-02 21:34:32 +03:00
g_clear_error ( & error ) ;
2016-02-19 00:49:30 +03:00
}
2016-04-22 19:42:05 +03:00
static gboolean
skip_if_no_xattr ( TestData * td )
2016-02-19 00:49:30 +03:00
{
2016-04-22 19:42:05 +03:00
/* /var/tmp might actually be a tmpfs */
2016-03-11 12:09:48 +03:00
if ( setxattr ( td - > tmpd , " user.test-xattr-support " , " yes " , 4 , 0 ) ! = 0 )
{
int saved_errno = errno ;
2023-05-01 21:24:29 +03:00
g_autofree gchar * message = g_strdup_printf ( " unable to setxattr on \" %s \" : %s " , td - > tmpd ,
g_strerror ( saved_errno ) ) ;
2016-03-11 12:09:48 +03:00
g_test_skip ( message ) ;
2016-04-22 19:42:05 +03:00
return TRUE ;
2016-03-11 12:09:48 +03:00
}
2016-04-22 19:42:05 +03:00
return FALSE ;
}
2016-02-19 00:49:30 +03:00
2016-04-22 19:42:05 +03:00
static gboolean
2023-05-01 21:24:29 +03:00
import_write_and_ref ( OstreeRepo * repo , OstreeRepoImportArchiveOptions * opts , struct archive * a ,
const char * ref , OstreeRepoCommitModifier * modifier , GError * * error )
2016-04-22 19:42:05 +03:00
{
2023-05-01 21:24:29 +03:00
g_autoptr ( OstreeMutableTree ) mtree = ostree_mutable_tree_new ( ) ;
2016-02-19 00:49:30 +03:00
2016-04-22 19:42:05 +03:00
if ( ! ostree_repo_prepare_transaction ( repo , NULL , NULL , error ) )
2017-09-13 19:09:51 +03:00
return FALSE ;
2016-02-19 00:49:30 +03:00
2023-05-01 21:24:29 +03:00
if ( ! ostree_repo_import_archive_to_mtree ( repo , opts , a , mtree , modifier , NULL , error ) )
2017-09-13 19:09:51 +03:00
return FALSE ;
2016-02-19 00:49:30 +03:00
2023-05-01 21:24:29 +03:00
g_autoptr ( GFile ) root = NULL ;
2016-04-22 19:42:05 +03:00
if ( ! ostree_repo_write_mtree ( repo , mtree , & root , NULL , error ) )
2017-09-13 19:09:51 +03:00
return FALSE ;
2016-02-19 00:49:30 +03:00
2017-09-13 19:09:51 +03:00
g_autofree char * commit_checksum = NULL ;
2023-05-01 21:24:29 +03:00
if ( ! ostree_repo_write_commit ( repo , NULL , " " , " " , NULL , OSTREE_REPO_FILE ( root ) ,
2016-04-22 19:42:05 +03:00
& commit_checksum , NULL , error ) )
2017-09-13 19:09:51 +03:00
return FALSE ;
2016-02-19 00:49:30 +03:00
2016-04-22 19:42:05 +03:00
ostree_repo_transaction_set_ref ( repo , NULL , ref , commit_checksum ) ;
if ( ! ostree_repo_commit_transaction ( repo , NULL , NULL , error ) )
2017-09-13 19:09:51 +03:00
return FALSE ;
2016-04-22 19:42:05 +03:00
2017-09-13 19:09:51 +03:00
return TRUE ;
2016-04-22 19:42:05 +03:00
}
static void
test_libarchive_ignore_device_file ( gconstpointer data )
{
2023-05-01 21:24:29 +03:00
TestData * td = ( void * ) data ;
g_autoptr ( GError ) error = NULL ;
g_autoptr ( OtAutoArchiveRead ) a = archive_read_new ( ) ;
OstreeRepoImportArchiveOptions opts = {
0 ,
} ;
2016-04-22 19:42:05 +03:00
if ( skip_if_no_xattr ( td ) )
goto out ;
2017-08-29 18:46:19 +03:00
if ( td - > skip_all ! = NULL )
{
g_test_skip ( td - > skip_all - > message ) ;
goto out ;
}
2016-04-22 19:42:05 +03:00
test_archive_setup ( td - > fd , a ) ;
opts . ignore_unsupported_content = TRUE ;
if ( ! import_write_and_ref ( td - > repo , & opts , a , " foo " , NULL , & error ) )
2016-02-19 00:49:30 +03:00
goto out ;
2016-04-22 19:42:05 +03:00
/* check contents */
2016-02-19 00:49:30 +03:00
if ( ! spawn_cmdline ( " ostree --repo=repo ls foo file " , & error ) )
goto out ;
if ( ! spawn_cmdline ( " ostree --repo=repo ls foo anotherfile " , & error ) )
goto out ;
2016-04-22 19:42:05 +03:00
if ( ! spawn_cmdline ( " ostree --repo=repo ls foo /etc/file " , & error ) )
goto out ;
2016-02-19 00:49:30 +03:00
if ( spawn_cmdline ( " ostree --repo=repo ls foo devnull " , & error ) )
g_assert_not_reached ( ) ;
g_assert ( error ! = NULL ) ;
g_clear_error ( & error ) ;
2023-05-01 21:24:29 +03:00
out :
2016-02-19 00:49:30 +03:00
g_assert_no_error ( error ) ;
}
2016-04-22 19:42:05 +03:00
static gboolean
check_ostree_convention ( GError * error )
{
if ( ! spawn_cmdline ( " ostree --repo=repo ls bar file " , & error ) )
return FALSE ;
if ( ! spawn_cmdline ( " ostree --repo=repo ls bar anotherfile " , & error ) )
return FALSE ;
if ( ! spawn_cmdline ( " ostree --repo=repo ls bar /usr/etc/file " , & error ) )
return FALSE ;
if ( spawn_cmdline ( " ostree --repo=repo ls bar /etc/file " , & error ) )
g_assert_not_reached ( ) ;
g_assert ( error ! = NULL ) ;
g_clear_error ( & error ) ;
if ( spawn_cmdline ( " ostree --repo=repo ls bar devnull " , & error ) )
g_assert_not_reached ( ) ;
g_assert ( error ! = NULL ) ;
g_clear_error ( & error ) ;
return TRUE ;
}
static void
test_libarchive_ostree_convention ( gconstpointer data )
{
2023-05-01 21:24:29 +03:00
TestData * td = ( void * ) data ;
2016-04-22 19:42:05 +03:00
GError * error = NULL ;
2023-05-01 21:24:29 +03:00
g_autoptr ( OtAutoArchiveRead ) a = archive_read_new ( ) ;
OstreeRepoImportArchiveOptions opts = {
0 ,
} ;
2016-04-22 19:42:05 +03:00
if ( skip_if_no_xattr ( td ) )
goto out ;
2017-08-29 18:46:19 +03:00
if ( td - > skip_all ! = NULL )
{
g_test_skip ( td - > skip_all - > message ) ;
goto out ;
}
2016-04-22 19:42:05 +03:00
test_archive_setup ( td - > fd , a ) ;
opts . autocreate_parents = TRUE ;
opts . use_ostree_convention = TRUE ;
opts . ignore_unsupported_content = TRUE ;
if ( ! import_write_and_ref ( td - > repo , & opts , a , " bar " , NULL , & error ) )
goto out ;
if ( ! check_ostree_convention ( error ) )
goto out ;
2023-05-01 21:24:29 +03:00
out :
2016-04-22 19:42:05 +03:00
g_assert_no_error ( error ) ;
}
2023-05-01 21:24:29 +03:00
static GVariant *
xattr_cb ( OstreeRepo * repo , const char * path , GFileInfo * file_info , gpointer user_data )
2016-04-22 19:42:05 +03:00
{
2023-05-01 21:24:29 +03:00
g_auto ( GVariantBuilder ) builder ;
g_variant_builder_init ( & builder , ( GVariantType * ) " a(ayay) " ) ;
2016-04-22 19:42:05 +03:00
if ( strcmp ( path , " /anotherfile " ) = = 0 )
2023-05-01 21:24:29 +03:00
g_variant_builder_add ( & builder , " (@ay@ay) " , g_variant_new_bytestring ( " user.data " ) ,
2016-04-22 19:42:05 +03:00
g_variant_new_bytestring ( " mydata " ) ) ;
return g_variant_ref_sink ( g_variant_builder_end ( & builder ) ) ;
}
static void
test_libarchive_xattr_callback ( gconstpointer data )
{
2023-05-01 21:24:29 +03:00
TestData * td = ( void * ) data ;
2016-04-22 19:42:05 +03:00
GError * error = NULL ;
2023-05-01 21:24:29 +03:00
g_autoptr ( OtAutoArchiveRead ) a = archive_read_new ( ) ;
2016-04-22 19:42:05 +03:00
OstreeRepoImportArchiveOptions opts = { 0 } ;
2023-05-01 21:24:29 +03:00
g_autoptr ( OstreeRepoCommitModifier ) modifier = NULL ;
2016-04-22 19:42:05 +03:00
char buf [ 7 ] = { 0 } ;
if ( skip_if_no_xattr ( td ) )
goto out ;
2017-08-29 18:46:19 +03:00
if ( td - > skip_all ! = NULL )
{
g_test_skip ( td - > skip_all - > message ) ;
goto out ;
}
2016-04-22 19:42:05 +03:00
modifier = ostree_repo_commit_modifier_new ( 0 , NULL , NULL , NULL ) ;
2023-05-01 21:24:29 +03:00
ostree_repo_commit_modifier_set_xattr_callback ( modifier , xattr_cb , NULL , NULL ) ;
2016-04-22 19:42:05 +03:00
test_archive_setup ( td - > fd , a ) ;
opts . ignore_unsupported_content = TRUE ;
if ( ! import_write_and_ref ( td - > repo , & opts , a , " baz " , modifier , & error ) )
goto out ;
/* check contents */
if ( ! spawn_cmdline ( " ostree --repo=repo checkout baz baz-checkout " , & error ) )
goto out ;
g_assert_cmpint ( 0 , > , getxattr ( " baz-checkout/file " , " user.data " , NULL , 0 ) ) ;
g_assert_cmpint ( ENODATA , = = , errno ) ;
if ( getxattr ( " baz-checkout/anotherfile " , " user.data " , buf , sizeof buf ) < 0 )
{
glnx_set_prefix_error_from_errno ( & error , " %s " , " getxattr " ) ;
goto out ;
}
g_assert_cmpstr ( buf , = = , " mydata " ) ;
2023-05-01 21:24:29 +03:00
out :
2016-04-22 19:42:05 +03:00
g_assert_no_error ( error ) ;
}
2020-11-17 03:46:10 +03:00
static void
test_libarchive_xattr_import ( gconstpointer data )
{
2023-05-01 21:24:29 +03:00
TestData * td = ( void * ) data ;
2020-11-17 03:46:10 +03:00
GError * error = NULL ;
2023-05-01 21:24:29 +03:00
g_autoptr ( OtAutoArchiveRead ) a = archive_read_new ( ) ;
2020-11-17 03:46:10 +03:00
OstreeRepoImportArchiveOptions opts = { 0 } ;
char buf [ 15 ] = { 0 } ;
if ( skip_if_no_xattr ( td ) )
goto out ;
if ( td - > skip_all ! = NULL )
{
g_test_skip ( td - > skip_all - > message ) ;
goto out ;
}
test_archive_setup ( td - > fd , a ) ;
opts . ignore_unsupported_content = TRUE ;
if ( ! import_write_and_ref ( td - > repo , & opts , a , " baz " , NULL , & error ) )
goto out ;
/* check contents */
if ( ! spawn_cmdline ( " ostree --repo=repo checkout baz import-checkout " , NULL ) )
goto out ;
spawn_cmdline ( " ostree --repo=repo ls -R -X baz " , NULL ) ;
spawn_cmdline ( " attr -l import-checkout/anotherfile " , NULL ) ;
ssize_t x = getxattr ( " import-checkout/anotherfile " , " user.a_key " , buf , sizeof buf - 1 ) ;
g_assert_cmpint ( x , = = , 8 ) ;
g_assert_cmpstr ( buf , = = , " my value " ) ;
x = getxattr ( " import-checkout/anotherfile " , " user.key2 " , buf , sizeof buf - 1 ) ;
g_assert_cmpint ( x , = = , 0 ) ;
x = getxattr ( " import-checkout/anotherfile " , " user.b_key " , buf , sizeof buf - 1 ) ;
g_assert_cmpint ( x , = = , 14 ) ;
2023-05-01 21:24:29 +03:00
g_assert ( memcmp ( buf , " contains \0 nuls " , 14 ) = = 0 ) ;
2020-11-17 03:46:10 +03:00
2023-05-01 21:24:29 +03:00
out :
2020-11-17 03:46:10 +03:00
g_assert_no_error ( error ) ;
}
static void
test_libarchive_xattr_import_skip_xattr ( gconstpointer data )
{
2023-05-01 21:24:29 +03:00
TestData * td = ( void * ) data ;
2020-11-17 03:46:10 +03:00
GError * error = NULL ;
2023-05-01 21:24:29 +03:00
g_autoptr ( OtAutoArchiveRead ) a = archive_read_new ( ) ;
2020-11-17 03:46:10 +03:00
OstreeRepoImportArchiveOptions opts = { 0 } ;
2023-05-01 21:24:29 +03:00
g_autoptr ( OstreeRepoCommitModifier ) modifier = NULL ;
2020-11-17 03:46:10 +03:00
if ( skip_if_no_xattr ( td ) )
goto out ;
if ( td - > skip_all ! = NULL )
{
g_test_skip ( td - > skip_all - > message ) ;
goto out ;
}
test_archive_setup ( td - > fd , a ) ;
opts . ignore_unsupported_content = TRUE ;
2023-05-01 21:24:29 +03:00
modifier = ostree_repo_commit_modifier_new ( OSTREE_REPO_COMMIT_MODIFIER_FLAGS_SKIP_XATTRS , NULL ,
NULL , NULL ) ;
2020-11-17 03:46:10 +03:00
if ( ! import_write_and_ref ( td - > repo , & opts , a , " baz " , modifier , & error ) )
goto out ;
/* check contents */
if ( ! spawn_cmdline ( " ostree --repo=repo checkout baz import-checkout " , NULL ) )
goto out ;
ssize_t n_attrs = listxattr ( " import-checkout/anotherfile " , NULL , 0 ) ;
g_assert_cmpint ( n_attrs , = = , 0 ) ;
2023-05-01 21:24:29 +03:00
out :
2020-11-17 03:46:10 +03:00
g_assert_no_error ( error ) ;
}
2023-05-01 21:24:29 +03:00
static GVariant *
path_cb ( OstreeRepo * repo , const char * path , GFileInfo * file_info , gpointer user_data )
2016-04-22 19:42:05 +03:00
{
if ( strcmp ( path , " /etc/file " ) = = 0 )
2023-05-01 21:24:29 +03:00
* ( gboolean * ) user_data = TRUE ;
2016-04-22 19:42:05 +03:00
return NULL ;
}
static void
entry_pathname_test_helper ( gconstpointer data , gboolean on )
{
2023-05-01 21:24:29 +03:00
TestData * td = ( void * ) data ;
GError * error = NULL ;
g_autoptr ( OtAutoArchiveRead ) a = archive_read_new ( ) ;
OstreeRepoImportArchiveOptions opts = {
0 ,
} ;
2016-04-22 19:42:05 +03:00
OstreeRepoCommitModifier * modifier = NULL ;
gboolean met_etc_file = FALSE ;
2016-06-26 16:26:37 +03:00
if ( skip_if_no_xattr ( td ) )
goto out ;
2017-08-29 18:46:19 +03:00
if ( td - > skip_all ! = NULL )
{
g_test_skip ( td - > skip_all - > message ) ;
goto out ;
}
2016-04-22 19:42:05 +03:00
modifier = ostree_repo_commit_modifier_new ( 0 , NULL , NULL , NULL ) ;
2023-05-01 21:24:29 +03:00
ostree_repo_commit_modifier_set_xattr_callback ( modifier , path_cb , NULL , & met_etc_file ) ;
2016-04-22 19:42:05 +03:00
test_archive_setup ( td - > fd , a ) ;
opts . autocreate_parents = TRUE ;
opts . use_ostree_convention = TRUE ;
opts . ignore_unsupported_content = TRUE ;
opts . callback_with_entry_pathname = on ;
if ( ! import_write_and_ref ( td - > repo , & opts , a , " bar " , modifier , & error ) )
goto out ;
/* the flag shouldn't have any effect on the final tree */
if ( ! check_ostree_convention ( error ) )
goto out ;
if ( ! on & & met_etc_file )
{
g_set_error_literal ( & error , G_IO_ERROR , G_IO_ERROR_FAILED ,
" Received callback with /etc/file " ) ;
goto out ;
}
if ( on & & ! met_etc_file )
{
g_set_error_literal ( & error , G_IO_ERROR , G_IO_ERROR_FAILED ,
" Did not receive callback with /etc/file " ) ;
goto out ;
}
2016-11-18 18:32:59 +03:00
ostree_repo_commit_modifier_unref ( modifier ) ;
2023-05-01 21:24:29 +03:00
out :
2016-04-22 19:42:05 +03:00
g_assert_no_error ( error ) ;
}
static void
test_libarchive_no_use_entry_pathname ( gconstpointer data )
{
entry_pathname_test_helper ( data , FALSE ) ;
}
static void
test_libarchive_use_entry_pathname ( gconstpointer data )
{
entry_pathname_test_helper ( data , TRUE ) ;
}
static void
test_libarchive_selinux ( gconstpointer data )
{
2023-05-01 21:24:29 +03:00
TestData * td = ( void * ) data ;
2016-04-22 19:42:05 +03:00
GError * error = NULL ;
2023-05-01 21:24:29 +03:00
g_autoptr ( OtAutoArchiveRead ) a = archive_read_new ( ) ;
2016-04-22 19:42:05 +03:00
OstreeRepoImportArchiveOptions opts = { 0 } ;
glnx_unref_object OstreeSePolicy * sepol = NULL ;
2023-05-01 21:24:29 +03:00
g_autoptr ( OstreeRepoCommitModifier ) modifier = NULL ;
2016-04-22 19:42:05 +03:00
char buf [ 64 ] = { 0 } ;
if ( skip_if_no_xattr ( td ) )
goto out ;
2024-05-02 21:18:10 +03:00
// xref https://bugzilla.redhat.com/show_bug.cgi?id=2278652
if ( getenv ( " container " ) | | g_file_test ( " /run/.containerenv " , G_FILE_TEST_EXISTS )
| | g_file_test ( " /.dockerenv " , G_FILE_TEST_EXISTS ) )
2020-02-03 23:45:07 +03:00
{
// FIXME dedup this with libtest.sh have_selinux_relabel
g_test_skip ( " skip in containers for now " ) ;
goto out ;
}
2016-04-22 19:42:05 +03:00
2017-08-29 18:46:19 +03:00
if ( td - > skip_all ! = NULL )
{
g_test_skip ( td - > skip_all - > message ) ;
goto out ;
}
2016-04-22 19:42:05 +03:00
{
glnx_unref_object GFile * root = g_file_new_for_path ( " / " ) ;
2016-10-25 17:40:45 +03:00
sepol = ostree_sepolicy_new ( root , NULL , NULL ) ;
2016-04-22 19:42:05 +03:00
}
2016-10-25 17:40:45 +03:00
if ( sepol = = NULL | | ostree_sepolicy_get_name ( sepol ) = = NULL )
2016-04-22 19:42:05 +03:00
{
g_test_skip ( " SELinux disabled " ) ;
goto out ;
}
modifier = ostree_repo_commit_modifier_new ( 0 , NULL , NULL , NULL ) ;
ostree_repo_commit_modifier_set_sepolicy ( modifier , sepol ) ;
test_archive_setup ( td - > fd , a ) ;
opts . ignore_unsupported_content = TRUE ;
if ( ! import_write_and_ref ( td - > repo , & opts , a , " bob " , modifier , & error ) )
goto out ;
/* check contents */
if ( ! spawn_cmdline ( " ostree --repo=repo checkout bob bob-checkout " , & error ) )
goto out ;
if ( getxattr ( " bob-checkout/etc " , " security.selinux " , buf , sizeof buf ) < 0 )
{
glnx_set_prefix_error_from_errno ( & error , " %s " , " getxattr " ) ;
goto out ;
}
buf [ ( sizeof buf ) - 1 ] = ' \0 ' ;
g_assert_cmpstr ( buf , = = , " system_u:object_r:etc_t:s0 " ) ;
2023-05-01 21:24:29 +03:00
out :
2016-04-22 19:42:05 +03:00
g_assert_no_error ( error ) ;
}
2023-05-01 21:24:29 +03:00
int
main ( int argc , char * * argv )
2016-02-19 00:49:30 +03:00
{
2023-05-01 21:24:29 +03:00
TestData td = {
NULL ,
} ;
2016-02-19 00:49:30 +03:00
int r ;
test_data_init ( & td ) ;
g_test_init ( & argc , & argv , NULL ) ;
2016-02-22 19:18:30 +03:00
g_test_add_data_func ( " /libarchive/noautocreate-empty " , & td , test_libarchive_noautocreate_empty ) ;
g_test_add_data_func ( " /libarchive/autocreate-empty " , & td , test_libarchive_autocreate_empty ) ;
2016-02-19 00:49:30 +03:00
g_test_add_data_func ( " /libarchive/error-device-file " , & td , test_libarchive_error_device_file ) ;
g_test_add_data_func ( " /libarchive/ignore-device-file " , & td , test_libarchive_ignore_device_file ) ;
2016-04-22 19:42:05 +03:00
g_test_add_data_func ( " /libarchive/ostree-convention " , & td , test_libarchive_ostree_convention ) ;
2020-11-17 03:46:10 +03:00
g_test_add_data_func ( " /libarchive/xattr-import " , & td , test_libarchive_xattr_import ) ;
2023-05-01 21:24:29 +03:00
g_test_add_data_func ( " /libarchive/xattr-import-skip-xattr " , & td ,
test_libarchive_xattr_import_skip_xattr ) ;
2016-04-22 19:42:05 +03:00
g_test_add_data_func ( " /libarchive/xattr-callback " , & td , test_libarchive_xattr_callback ) ;
2023-05-01 21:24:29 +03:00
g_test_add_data_func ( " /libarchive/no-use-entry-pathname " , & td ,
test_libarchive_no_use_entry_pathname ) ;
2016-04-22 19:42:05 +03:00
g_test_add_data_func ( " /libarchive/use-entry-pathname " , & td , test_libarchive_use_entry_pathname ) ;
g_test_add_data_func ( " /libarchive/selinux " , & td , test_libarchive_selinux ) ;
2016-02-19 00:49:30 +03:00
2023-05-01 21:24:29 +03:00
r = g_test_run ( ) ;
2016-02-19 00:49:30 +03:00
2016-11-29 06:03:53 +03:00
g_clear_object ( & td . repo ) ;
2016-04-22 19:42:05 +03:00
if ( td . tmpd & & g_getenv ( " TEST_SKIP_CLEANUP " ) = = NULL )
2023-05-01 21:24:29 +03:00
( void ) glnx_shutil_rm_rf_at ( AT_FDCWD , td . tmpd , NULL , NULL ) ;
2016-11-18 18:32:59 +03:00
g_free ( td . tmpd ) ;
2016-02-19 00:49:30 +03:00
return r ;
}