2002-03-25 23:16:26 +03:00
/** \ingroup rpmbuild
* \ file build / pack . c
* Assemble components of an RPM package .
*/
# include "system.h"
2002-03-26 01:02:39 +03:00
# include "rpmio_internal.h"
# include "rpmbuild.h"
2002-03-25 23:16:26 +03:00
# include "buildio.h"
# include "misc.h"
# include "signature.h"
# include "rpmlead.h"
# include "debug.h"
/*@access StringBuf @*/ /* compared with NULL */
/*@access TFI_t @*/ /* compared with NULL */
/*@access Header @*/ /* compared with NULL */
/*@access FD_t @*/ /* compared with NULL */
/*@access CSA_t @*/
/**
*/
static inline int genSourceRpmName ( Spec spec )
/*@modifies spec->sourceRpmName @*/
{
if ( spec - > sourceRpmName = = NULL ) {
const char * name , * version , * release ;
char fileName [ BUFSIZ ] ;
2019-02-25 05:06:13 +03:00
( void ) headerNVRD ( spec - > packages - > header , & name , & version , & release , NULL ) ;
2002-03-25 23:16:26 +03:00
sprintf ( fileName , " %s-%s-%s.%ssrc.rpm " , name , version , release ,
spec - > noSource ? " no " : " " ) ;
spec - > sourceRpmName = xstrdup ( fileName ) ;
}
return 0 ;
}
/**
* @ todo Create transaction set * much * earlier .
*/
static int cpio_doio ( FD_t fdo , /*@unused@*/ Header h , CSA_t csa ,
2018-01-29 02:47:56 +03:00
const char * fmode )
2002-03-25 23:16:26 +03:00
/*@globals rpmGlobalMacroContext,
fileSystem @ */
/*@modifies fdo, csa, rpmGlobalMacroContext, fileSystem @*/
{
const char * rootDir = " / " ;
rpmdb rpmdb = NULL ;
rpmTransactionSet ts = rpmtransCreateSet ( rpmdb , rootDir ) ;
TFI_t fi = csa - > cpioList ;
const char * failedFile = NULL ;
FD_t cfd ;
int rc , ec ;
2018-01-29 02:47:56 +03:00
{
2002-03-25 23:16:26 +03:00
/*@-nullpass@*/
( void ) Fflush ( fdo ) ;
cfd = Fdopen ( fdDup ( Fileno ( fdo ) ) , fmode ) ;
/*@=nullpass@*/
}
if ( cfd = = NULL )
return 1 ;
rc = fsmSetup ( fi - > fsm , FSM_PKGBUILD , ts , fi , cfd ,
& csa - > cpioArchiveSize , & failedFile ) ;
( void ) Fclose ( cfd ) ;
ec = fsmTeardown ( fi - > fsm ) ;
if ( ! rc ) rc = ec ;
if ( rc ) {
if ( failedFile )
rpmError ( RPMERR_CPIO , _ ( " create archive failed on file %s: %s \n " ) ,
failedFile , cpioStrerror ( rc ) ) ;
else
rpmError ( RPMERR_CPIO , _ ( " create archive failed: %s \n " ) ,
cpioStrerror ( rc ) ) ;
rc = 1 ;
}
failedFile = _free ( failedFile ) ;
ts = rpmtransFree ( ts ) ;
return rc ;
}
/**
*/
static int cpio_copy ( FD_t fdo , CSA_t csa )
/*@globals fileSystem@*/
/*@modifies fdo, csa, fileSystem @*/
{
char buf [ BUFSIZ ] ;
size_t nb ;
while ( ( nb = Fread ( buf , sizeof ( buf [ 0 ] ) , sizeof ( buf ) , csa - > cpioFdIn ) ) > 0 ) {
if ( Fwrite ( buf , sizeof ( buf [ 0 ] ) , nb , fdo ) ! = nb ) {
rpmError ( RPMERR_CPIO , _ ( " cpio_copy write failed: %s \n " ) ,
Fstrerror ( fdo ) ) ;
return 1 ;
}
csa - > cpioArchiveSize + = nb ;
}
if ( Ferror ( csa - > cpioFdIn ) ) {
rpmError ( RPMERR_CPIO , _ ( " cpio_copy read failed: %s \n " ) ,
Fstrerror ( csa - > cpioFdIn ) ) ;
return 1 ;
}
return 0 ;
}
/**
*/
static /*@only@*/ /*@null@*/ StringBuf addFileToTagAux ( Spec spec ,
const char * file , /*@only@*/ StringBuf sb )
/*@globals rpmGlobalMacroContext,
fileSystem @ */
/*@modifies rpmGlobalMacroContext, fileSystem @*/
{
char buf [ BUFSIZ ] ;
const char * fn = buf ;
FILE * f ;
FD_t fd ;
/* XXX use rpmGenPath(rootdir, "%{_buildir}/%{_buildsubdir}/", file) */
fn = rpmGetPath ( " %{_builddir}/ " , spec - > buildSubdir , " / " , file , NULL ) ;
fd = Fopen ( fn , " r.ufdio " ) ;
if ( fn ! = buf ) fn = _free ( fn ) ;
if ( fd = = NULL | | Ferror ( fd ) ) {
sb = freeStringBuf ( sb ) ;
return NULL ;
}
/*@-type@*/ /* FIX: cast? */
if ( ( f = fdGetFp ( fd ) ) ! = NULL )
/*@=type@*/
while ( fgets ( buf , sizeof ( buf ) , f ) ) {
/* XXX display fn in error msg */
if ( expandMacros ( spec , spec - > macros , buf , sizeof ( buf ) ) ) {
rpmError ( RPMERR_BADSPEC , _ ( " line: %s \n " ) , buf ) ;
sb = freeStringBuf ( sb ) ;
break ;
}
appendStringBuf ( sb , buf ) ;
}
( void ) Fclose ( fd ) ;
return sb ;
}
/**
*/
static int addFileToTag ( Spec spec , const char * file , Header h , int tag )
/*@globals rpmGlobalMacroContext,
fileSystem @ */
/*@modifies h, rpmGlobalMacroContext, fileSystem @*/
{
HGE_t hge = ( HGE_t ) headerGetEntryMinMemory ;
StringBuf sb = newStringBuf ( ) ;
char * s ;
if ( hge ( h , tag , NULL , ( void * * ) & s , NULL ) ) {
appendLineStringBuf ( sb , s ) ;
( void ) headerRemoveEntry ( h , tag ) ;
}
if ( ( sb = addFileToTagAux ( spec , file , sb ) ) = = NULL )
return 1 ;
( void ) headerAddEntry ( h , tag , RPM_STRING_TYPE , getStringBuf ( sb ) , 1 ) ;
sb = freeStringBuf ( sb ) ;
return 0 ;
}
/**
*/
static int addFileToArrayTag ( Spec spec , const char * file , Header h , int tag )
/*@globals rpmGlobalMacroContext,
fileSystem @ */
/*@modifies h, rpmGlobalMacroContext, fileSystem @*/
{
StringBuf sb = newStringBuf ( ) ;
char * s ;
if ( ( sb = addFileToTagAux ( spec , file , sb ) ) = = NULL )
return 1 ;
s = getStringBuf ( sb ) ;
( void ) headerAddOrAppendEntry ( h , tag , RPM_STRING_ARRAY_TYPE , & s , 1 ) ;
sb = freeStringBuf ( sb ) ;
return 0 ;
}
/**
*/
static int processScriptFiles ( Spec spec , Package pkg )
/*@globals rpmGlobalMacroContext,
fileSystem @ */
/*@modifies pkg->header, rpmGlobalMacroContext, fileSystem @*/
{
struct TriggerFileEntry * p ;
if ( pkg - > preInFile ) {
if ( addFileToTag ( spec , pkg - > preInFile , pkg - > header , RPMTAG_PREIN ) ) {
rpmError ( RPMERR_BADFILENAME ,
_ ( " Could not open PreIn file: %s \n " ) , pkg - > preInFile ) ;
return RPMERR_BADFILENAME ;
}
}
if ( pkg - > preUnFile ) {
if ( addFileToTag ( spec , pkg - > preUnFile , pkg - > header , RPMTAG_PREUN ) ) {
rpmError ( RPMERR_BADFILENAME ,
_ ( " Could not open PreUn file: %s \n " ) , pkg - > preUnFile ) ;
return RPMERR_BADFILENAME ;
}
}
if ( pkg - > postInFile ) {
if ( addFileToTag ( spec , pkg - > postInFile , pkg - > header , RPMTAG_POSTIN ) ) {
rpmError ( RPMERR_BADFILENAME ,
_ ( " Could not open PostIn file: %s \n " ) , pkg - > postInFile ) ;
return RPMERR_BADFILENAME ;
}
}
if ( pkg - > postUnFile ) {
if ( addFileToTag ( spec , pkg - > postUnFile , pkg - > header , RPMTAG_POSTUN ) ) {
rpmError ( RPMERR_BADFILENAME ,
_ ( " Could not open PostUn file: %s \n " ) , pkg - > postUnFile ) ;
return RPMERR_BADFILENAME ;
}
}
if ( pkg - > verifyFile ) {
if ( addFileToTag ( spec , pkg - > verifyFile , pkg - > header ,
RPMTAG_VERIFYSCRIPT ) ) {
rpmError ( RPMERR_BADFILENAME ,
_ ( " Could not open VerifyScript file: %s \n " ) , pkg - > verifyFile ) ;
return RPMERR_BADFILENAME ;
}
}
for ( p = pkg - > triggerFiles ; p ! = NULL ; p = p - > next ) {
( void ) headerAddOrAppendEntry ( pkg - > header , RPMTAG_TRIGGERSCRIPTPROG ,
RPM_STRING_ARRAY_TYPE , & ( p - > prog ) , 1 ) ;
if ( p - > script ) {
( void ) headerAddOrAppendEntry ( pkg - > header , RPMTAG_TRIGGERSCRIPTS ,
RPM_STRING_ARRAY_TYPE , & ( p - > script ) , 1 ) ;
} else if ( p - > fileName ) {
if ( addFileToArrayTag ( spec , p - > fileName , pkg - > header ,
RPMTAG_TRIGGERSCRIPTS ) ) {
rpmError ( RPMERR_BADFILENAME ,
_ ( " Could not open Trigger script file: %s \n " ) ,
p - > fileName ) ;
return RPMERR_BADFILENAME ;
}
} else {
/* This is dumb. When the header supports NULL string */
/* this will go away. */
char * bull = " " ;
( void ) headerAddOrAppendEntry ( pkg - > header , RPMTAG_TRIGGERSCRIPTS ,
RPM_STRING_ARRAY_TYPE , & bull , 1 ) ;
}
}
return 0 ;
}
int readRPM ( const char * fileName , Spec * specp , struct rpmlead * lead ,
Header * sigs , CSA_t csa )
{
FD_t fdi ;
Spec spec ;
rpmRC rc ;
fdi = ( fileName ! = NULL )
? Fopen ( fileName , " r.ufdio " )
: fdDup ( STDIN_FILENO ) ;
if ( fdi = = NULL | | Ferror ( fdi ) ) {
rpmError ( RPMERR_BADMAGIC , _ ( " readRPM: open %s: %s \n " ) ,
( fileName ? fileName : " <stdin> " ) ,
Fstrerror ( fdi ) ) ;
if ( fdi ) ( void ) Fclose ( fdi ) ;
return RPMERR_BADMAGIC ;
}
/* Get copy of lead */
/*@-sizeoftype@*/
if ( ( rc = Fread ( lead , sizeof ( char ) , sizeof ( * lead ) , fdi ) ) ! = sizeof ( * lead ) ) {
rpmError ( RPMERR_BADMAGIC , _ ( " readRPM: read %s: %s \n " ) ,
( fileName ? fileName : " <stdin> " ) ,
Fstrerror ( fdi ) ) ;
return RPMERR_BADMAGIC ;
}
/*@=sizeoftype@*/
/* XXX FIXME: EPIPE on <stdin> */
if ( Fseek ( fdi , 0 , SEEK_SET ) = = - 1 ) {
rpmError ( RPMERR_FSEEK , _ ( " %s: Fseek failed: %s \n " ) ,
( fileName ? fileName : " <stdin> " ) , Fstrerror ( fdi ) ) ;
return RPMERR_FSEEK ;
}
/* Reallocate build data structures */
spec = newSpec ( ) ;
spec - > packages = newPackage ( spec ) ;
/* XXX the header just allocated will be allocated again */
spec - > packages - > header = headerFree ( spec - > packages - > header ) ;
/* Read the rpm lead, signatures, and header */
rc = rpmReadPackageInfo ( fdi , sigs , & spec - > packages - > header ) ;
switch ( rc ) {
case RPMRC_BADMAGIC :
rpmError ( RPMERR_BADMAGIC , _ ( " readRPM: %s is not an RPM package \n " ) ,
( fileName ? fileName : " <stdin> " ) ) ;
return RPMERR_BADMAGIC ;
case RPMRC_OK :
break ;
case RPMRC_FAIL :
case RPMRC_BADSIZE :
case RPMRC_SHORTREAD :
default :
rpmError ( RPMERR_BADMAGIC , _ ( " readRPM: reading header from %s \n " ) ,
( fileName ? fileName : " <stdin> " ) ) ;
return RPMERR_BADMAGIC ;
/*@notreached@*/ break ;
}
/*@-branchstate@*/
if ( specp )
* specp = spec ;
else
spec = freeSpec ( spec ) ;
/*@=branchstate@*/
if ( csa ! = NULL )
csa - > cpioFdIn = fdi ;
else
( void ) Fclose ( fdi ) ;
return 0 ;
}
2003-11-24 21:59:03 +03:00
#if 0
2002-03-25 23:16:26 +03:00
/*@unchecked@*/
static unsigned char header_magic [ 8 ] = {
0x8e , 0xad , 0xe8 , 0x01 , 0x00 , 0x00 , 0x00 , 0x00
} ;
2003-11-24 21:59:03 +03:00
# endif
2002-03-25 23:16:26 +03:00
# define RPMPKGVERSION_MIN 30004
# define RPMPKGVERSION_MAX 40003
/*@unchecked@*/
static int rpmpkg_version = - 1 ;
static int rpmLeadVersion ( void )
/*@globals rpmpkg_version, rpmGlobalMacroContext @*/
/*@modifies rpmpkg_version, rpmGlobalMacroContext @*/
{
int rpmlead_version ;
/* Intitialize packaging version from macro configuration. */
if ( rpmpkg_version < 0 ) {
2005-09-29 19:46:13 +04:00
rpmpkg_version = rpmExpandNumeric ( " %{?_package_version} " ) ;
2002-03-25 23:16:26 +03:00
if ( rpmpkg_version < RPMPKGVERSION_MIN )
rpmpkg_version = RPMPKGVERSION_MIN ;
if ( rpmpkg_version > RPMPKGVERSION_MAX )
rpmpkg_version = RPMPKGVERSION_MAX ;
}
rpmlead_version = rpmpkg_version / 10000 ;
2008-08-20 11:34:12 +04:00
if ( rpmlead_version < 3 | | rpmlead_version > 4 )
2002-03-25 23:16:26 +03:00
rpmlead_version = 3 ;
return rpmlead_version ;
}
2018-01-29 02:13:14 +03:00
// Estimate the uncompressed size of cpio archive before it is actually written.
static uint64_t calcArchiveSize ( TFI_t fi )
{
uint64_t size = 124 ; // cpio trailer
for ( int i = 0 ; i < fi - > fc ; i + + ) {
if ( fi - > actions [ i ] = = FA_SKIP ) // %ghost
continue ;
size + = 110 ; // cpio header
size + = strlen ( fi - > apath [ i ] ) + 1 ;
size = ( size + 3 ) & ~ ( uint64_t ) 3 ;
if ( ! S_ISREG ( fi - > fsts [ i ] . st_mode ) & & ! S_ISLNK ( fi - > fsts [ i ] . st_mode ) )
continue ;
if ( fi - > fsts [ i ] . st_nlink > 1 ) {
// Only the first hardlink occurrence counts.
int found = 0 ;
for ( int j = i - 1 ; j > = 0 ; j - - ) {
if ( fi - > actions [ j ] = = FA_SKIP )
continue ;
if ( fi - > fsts [ i ] . st_dev ! = fi - > fsts [ j ] . st_dev )
continue ;
if ( fi - > fsts [ i ] . st_ino ! = fi - > fsts [ j ] . st_ino )
continue ;
found = 1 ;
break ;
}
if ( found )
continue ;
}
// Valid for symlinks, target not null-terminated.
size + = fi - > fsts [ i ] . st_size ;
size = ( size + 3 ) & ~ ( uint64_t ) 3 ;
}
return size ;
}
2018-01-29 02:47:56 +03:00
// LZMA compressions levels 6-9 are equivalent, except for the dictionary size,
// which is 8-64M. For smaller inputs, levels 7-9 are downgraded automatically.
static void downgradeLzmaLevel ( char * mode , uint64_t archiveSize )
{
2020-12-20 01:43:47 +03:00
if ( ! ( mode [ 1 ] > = ' 0 ' & & mode [ 1 ] < = ' 9 ' ) )
return ;
char * p = & mode [ 2 ] ;
if ( * p = = ' T ' ) {
do
p + + ;
while ( * p > = ' 0 ' & & * p < = ' 9 ' ) ;
}
if ( ! ( p [ 0 ] = = ' . ' & & ( p [ 1 ] = = ' l ' | | p [ 1 ] = = ' x ' ) & & p [ 2 ] = = ' z ' ) )
return ;
2018-01-29 02:47:56 +03:00
# define S(m) ((m << 20) + (m << 10))
2020-12-20 01:43:47 +03:00
// For small payloads, downgrade XZ->LZMA automatically. XZ only makes
// sense in multi-threaded mode (to speed up compression). The default
// block size in multi-threaded mode is three times the dictionary size.
// There has to be at least two blocks, the second block not too small,
// so we require at least five times the dictionary size.
# define T(m) ((m << 20) * 5)
# define ForceLzma memcpy(&mode[2], ".lzdio", 7)
2018-01-29 02:47:56 +03:00
switch ( mode [ 1 ] ) {
case ' 9 ' :
2020-12-20 01:43:47 +03:00
if ( archiveSize < T ( 64 ) ) ForceLzma ;
if ( archiveSize > S ( 32 ) ) break ;
2018-01-29 02:47:56 +03:00
mode [ 1 ] = ' 8 ' ;
/*@fallthrough@*/
case ' 8 ' :
2020-12-20 01:43:47 +03:00
if ( archiveSize < T ( 32 ) ) ForceLzma ;
if ( archiveSize > S ( 16 ) ) break ;
2018-01-29 02:47:56 +03:00
mode [ 1 ] = ' 7 ' ;
/*@fallthrough@*/
case ' 7 ' :
2020-12-20 01:43:47 +03:00
if ( archiveSize < T ( 16 ) ) ForceLzma ;
if ( archiveSize > S ( 8 ) ) break ;
2018-01-29 02:47:56 +03:00
mode [ 1 ] = ' 6 ' ;
2020-12-20 01:43:47 +03:00
/*@fallthrough@*/
case ' 6 ' :
case ' 5 ' :
if ( archiveSize < T ( 8 ) ) ForceLzma ;
break ;
case ' 4 ' :
case ' 3 ' :
if ( archiveSize < T ( 4 ) ) ForceLzma ;
break ;
case ' 2 ' :
if ( archiveSize < T ( 2 ) ) ForceLzma ;
break ;
case ' 1 ' :
if ( archiveSize < T ( 1 ) ) ForceLzma ;
break ;
case 0 :
// Dictionary size is 256K, but block size is 1M.
if ( archiveSize < ( 7 < < 18 ) ) ForceLzma ;
2018-01-29 02:47:56 +03:00
}
# undef S
2020-12-20 01:43:47 +03:00
# undef T
2018-01-29 02:47:56 +03:00
}
2002-03-25 23:16:26 +03:00
int writeRPM ( Header * hdrp , const char * fileName , int type ,
CSA_t csa , char * passPhrase , const char * * cookie )
{
FD_t fd = NULL ;
FD_t ifd = NULL ;
int count , sigtype ;
const char * sigtarget ;
const char * sha1 = NULL ;
2003-11-24 21:59:03 +03:00
const char * s ;
2002-03-25 23:16:26 +03:00
char buf [ BUFSIZ ] ;
Header h ;
Header sig = NULL ;
int rc = 0 ;
2021-01-05 14:57:48 +03:00
rpmioThreads = 0 ;
2018-01-29 02:13:14 +03:00
uint64_t archiveSize = calcArchiveSize ( csa - > cpioList ) ;
if ( archiveSize > = UINT32_MAX ) { // sic, UINT32_MAX proper is kind of special
rpmError ( RPMERR_FWRITE , " cpio archive too big - %uM \n " ,
( unsigned ) ( archiveSize > > 20 ) ) ;
return RPMERR_FWRITE ;
}
2002-03-25 23:16:26 +03:00
/* Transfer header reference form *hdrp to h. */
h = headerLink ( * hdrp ) ;
* hdrp = headerFree ( * hdrp ) ;
if ( Fileno ( csa - > cpioFdIn ) < 0 ) {
csa - > cpioArchiveSize = 0 ;
/* Add a bogus archive size to the Header */
( void ) headerAddEntry ( h , RPMTAG_ARCHIVESIZE , RPM_INT32_TYPE ,
& csa - > cpioArchiveSize , 1 ) ;
}
/* Binary packages now have explicit Provides: name = version-release. */
if ( type = = RPMLEAD_BINARY )
providePackageNVR ( h ) ;
2018-01-29 02:47:56 +03:00
char * rpmio_flags = NULL ;
2011-02-03 09:31:31 +03:00
const char * N , * dash ;
2002-03-25 23:16:26 +03:00
/* Save payload information */
/*@-branchstate@*/
switch ( type ) {
case RPMLEAD_SOURCE :
rpmio_flags = rpmExpand ( " %{?_source_payload} " , NULL ) ;
break ;
case RPMLEAD_BINARY :
2019-02-25 05:06:13 +03:00
headerName ( h , & N ) ;
2011-02-03 09:31:31 +03:00
dash = strrchr ( N , ' - ' ) ;
if ( dash & & strcmp ( dash , " -debuginfo " ) = = 0 )
rpmio_flags = rpmExpand ( " %{?_debuginfo_payload} " , NULL ) ;
if ( ! ( rpmio_flags & & * rpmio_flags ) )
rpmio_flags = rpmExpand ( " %{?_binary_payload} " , NULL ) ;
2002-03-25 23:16:26 +03:00
break ;
}
/*@=branchstate@*/
2018-01-29 02:47:56 +03:00
if ( ! ( rpmio_flags & & * rpmio_flags = = ' w ' ) ) {
2002-03-25 23:16:26 +03:00
rpmio_flags = _free ( rpmio_flags ) ;
rpmio_flags = xstrdup ( " w9.gzdio " ) ;
}
2018-01-29 02:47:56 +03:00
downgradeLzmaLevel ( rpmio_flags , archiveSize ) ;
2002-03-25 23:16:26 +03:00
s = strchr ( rpmio_flags , ' . ' ) ;
if ( s ) {
( void ) headerAddEntry ( h , RPMTAG_PAYLOADFORMAT , RPM_STRING_TYPE , " cpio " , 1 ) ;
if ( s [ 1 ] = = ' g ' & & s [ 2 ] = = ' z ' )
( void ) headerAddEntry ( h , RPMTAG_PAYLOADCOMPRESSOR , RPM_STRING_TYPE ,
" gzip " , 1 ) ;
2017-11-20 04:42:20 +03:00
# ifdef HAVE_BZLIB_H
2002-03-25 23:16:26 +03:00
if ( s [ 1 ] = = ' b ' & & s [ 2 ] = = ' z ' ) {
( void ) headerAddEntry ( h , RPMTAG_PAYLOADCOMPRESSOR , RPM_STRING_TYPE ,
" bzip2 " , 1 ) ;
2009-06-16 19:21:34 +04:00
( void ) rpmlibNeedsFeature ( h , " PayloadIsBzip2 " , NULL ) ;
2002-03-25 23:16:26 +03:00
}
2017-11-20 04:42:20 +03:00
# endif
2008-05-24 12:30:04 +04:00
if ( s [ 1 ] = = ' l ' & & s [ 2 ] = = ' z ' ) {
( void ) headerAddEntry ( h , RPMTAG_PAYLOADCOMPRESSOR , RPM_STRING_TYPE ,
" lzma " , 1 ) ;
2009-06-16 19:21:34 +04:00
( void ) rpmlibNeedsFeature ( h , " PayloadIsLzma " , NULL ) ;
2009-09-23 06:34:29 +04:00
}
if ( s [ 1 ] = = ' x ' & & s [ 2 ] = = ' z ' ) {
( void ) headerAddEntry ( h , RPMTAG_PAYLOADCOMPRESSOR , RPM_STRING_TYPE ,
" xz " , 1 ) ;
( void ) rpmlibNeedsFeature ( h , " PayloadIsXz " , NULL ) ;
2008-05-24 12:30:04 +04:00
}
2002-03-25 23:16:26 +03:00
strcpy ( buf , rpmio_flags ) ;
buf [ s - rpmio_flags ] = ' \0 ' ;
( void ) headerAddEntry ( h , RPMTAG_PAYLOADFLAGS , RPM_STRING_TYPE , buf + 1 , 1 ) ;
}
/* Create and add the cookie */
if ( cookie ) {
2002-06-13 15:28:05 +04:00
if ( ! headerGetEntry ( h , RPMTAG_BUILDHOST , NULL , ( void * * ) & s , NULL ) )
s = buildHost ( ) ;
sprintf ( buf , " %s %d " , s , ( int ) ( * getBuildTime ( ) ) ) ;
2002-03-25 23:16:26 +03:00
* cookie = xstrdup ( buf ) ;
( void ) headerAddEntry ( h , RPMTAG_COOKIE , RPM_STRING_TYPE , * cookie , 1 ) ;
}
/* Reallocate the header into one contiguous region. */
h = headerReload ( h , RPMTAG_HEADERIMMUTABLE ) ;
if ( h = = NULL ) { /* XXX can't happen */
rc = RPMERR_RELOAD ;
rpmError ( RPMERR_RELOAD , _ ( " Unable to create immutable header region. \n " ) ) ;
goto exit ;
}
/* Re-reference reallocated header. */
* hdrp = headerLink ( h ) ;
/*
* Write the header + archive into a temp file so that the size of
* archive ( after compression ) can be added to the header .
*/
if ( makeTempFile ( NULL , & sigtarget , & fd ) ) {
rc = RPMERR_CREATE ;
rpmError ( RPMERR_CREATE , _ ( " Unable to open temp file. \n " ) ) ;
goto exit ;
}
if ( headerWrite ( fd , h , HEADER_MAGIC_YES ) ) {
rc = RPMERR_NOSPACE ;
rpmError ( RPMERR_NOSPACE , _ ( " Unable to write temp header \n " ) ) ;
} else { /* Write the archive and get the size */
if ( csa - > cpioList ! = NULL ) {
rc = cpio_doio ( fd , h , csa , rpmio_flags ) ;
} else if ( Fileno ( csa - > cpioFdIn ) > = 0 ) {
rc = cpio_copy ( fd , csa ) ;
} else {
rc = RPMERR_BADARG ;
rpmError ( RPMERR_BADARG , _ ( " Bad CSA data \n " ) ) ;
}
}
if ( rc )
goto exit ;
/*
* Set the actual archive size , and rewrite the header .
* This used to be done using headerModifyEntry ( ) , but now that headers
* have regions , the value is scribbled directly into the header data
* area . Some new scheme for adding the final archive size will have
* to be devised if headerGetEntryMinMemory ( ) ever changes to return
* a pointer to memory not in the region , probably by appending
* the archive size to the header region rather than including the
* archive size within the header region .
*/
if ( Fileno ( csa - > cpioFdIn ) < 0 ) {
2018-01-29 02:13:14 +03:00
if ( archiveSize ! = csa - > cpioArchiveSize ) {
rpmError ( RPMERR_FWRITE , " wrong archive size: % " PRIu64 " -> %u \n " ,
archiveSize , csa - > cpioArchiveSize ) ;
rc = RPMERR_FWRITE ;
goto exit ;
}
2002-03-25 23:16:26 +03:00
HGE_t hge = ( HGE_t ) headerGetEntryMinMemory ;
2018-01-29 02:13:14 +03:00
uint32_t * sizep ;
if ( hge ( h , RPMTAG_ARCHIVESIZE , NULL , ( void * ) & sizep , NULL ) )
* sizep = csa - > cpioArchiveSize ;
else {
rpmError ( RPMERR_FWRITE , " cannot add RPMTAG_ARCHIVESIZE \n " ) ;
rc = RPMERR_FWRITE ;
goto exit ;
}
2002-03-25 23:16:26 +03:00
}
( void ) Fflush ( fd ) ;
if ( Fseek ( fd , 0L , SEEK_SET ) = = - 1 ) {
rc = RPMERR_FSEEK ;
rpmError ( RPMERR_FSEEK , _ ( " %s: Fseek failed: %s \n " ) ,
sigtarget , Fstrerror ( fd ) ) ;
}
fdInitDigest ( fd , PGPHASHALGO_SHA1 , 0 ) ;
if ( headerWrite ( fd , h , HEADER_MAGIC_YES ) ) {
rc = RPMERR_NOSPACE ;
rpmError ( RPMERR_NOSPACE , _ ( " Unable to write final header \n " ) ) ;
}
( void ) Fflush ( fd ) ;
fdFiniDigest ( fd , PGPHASHALGO_SHA1 , ( void * * ) & sha1 , NULL , 1 ) ;
( void ) Fclose ( fd ) ;
fd = NULL ;
( void ) Unlink ( fileName ) ;
if ( rc )
goto exit ;
/* Generate the signature */
( void ) fflush ( stdout ) ;
sig = rpmNewSignature ( ) ;
( void ) rpmAddSignature ( sig , sigtarget , RPMSIGTAG_SIZE , passPhrase ) ;
( void ) rpmAddSignature ( sig , sigtarget , RPMSIGTAG_MD5 , passPhrase ) ;
if ( ( sigtype = rpmLookupSignatureType ( RPMLOOKUPSIG_QUERY ) ) > 0 ) {
rpmMessage ( RPMMESS_NORMAL , _ ( " Generating signature: %d \n " ) , sigtype ) ;
( void ) rpmAddSignature ( sig , sigtarget , sigtype , passPhrase ) ;
}
if ( sha1 ) {
( void ) headerAddEntry ( sig , RPMTAG_SHA1HEADER , RPM_STRING_TYPE , sha1 , 1 ) ;
sha1 = _free ( sha1 ) ;
}
/* Reallocate the signature into one contiguous region. */
sig = headerReload ( sig , RPMTAG_HEADERSIGNATURES ) ;
if ( sig = = NULL ) { /* XXX can't happen */
rc = RPMERR_RELOAD ;
rpmError ( RPMERR_RELOAD , _ ( " Unable to reload signature header. \n " ) ) ;
goto exit ;
}
/* Open the output file */
fd = Fopen ( fileName , " w.ufdio " ) ;
if ( fd = = NULL | | Ferror ( fd ) ) {
rc = RPMERR_CREATE ;
rpmError ( RPMERR_CREATE , _ ( " Could not open %s: %s \n " ) ,
fileName , Fstrerror ( fd ) ) ;
goto exit ;
}
/* Write the lead section into the package. */
{ int archnum = - 1 ;
int osnum = - 1 ;
struct rpmlead lead ;
if ( Fileno ( csa - > cpioFdIn ) < 0 ) {
# ifndef DYING
rpmGetArchInfo ( NULL , & archnum ) ;
rpmGetOsInfo ( NULL , & osnum ) ;
# endif
} else if ( csa - > lead ! = NULL ) {
archnum = csa - > lead - > archnum ;
osnum = csa - > lead - > osnum ;
}
memset ( & lead , 0 , sizeof ( lead ) ) ;
lead . major = rpmLeadVersion ( ) ;
lead . minor = 0 ;
lead . type = type ;
lead . archnum = archnum ;
lead . osnum = osnum ;
lead . signature_type = RPMSIGTYPE_HEADERSIG ;
{ const char * name , * version , * release ;
( void ) headerNVR ( h , & name , & version , & release ) ;
sprintf ( buf , " %s-%s-%s " , name , version , release ) ;
strncpy ( lead . name , buf , sizeof ( lead . name ) ) ;
}
if ( writeLead ( fd , & lead ) ) {
rc = RPMERR_NOSPACE ;
rpmError ( RPMERR_NOSPACE , _ ( " Unable to write package: %s \n " ) ,
Fstrerror ( fd ) ) ;
goto exit ;
}
}
/* Write the signature section into the package. */
rc = rpmWriteSignature ( fd , sig ) ;
if ( rc )
goto exit ;
/* Append the header and archive */
ifd = Fopen ( sigtarget , " r.ufdio " ) ;
if ( ifd = = NULL | | Ferror ( ifd ) ) {
rc = RPMERR_READ ;
rpmError ( RPMERR_READ , _ ( " Unable to open sigtarget %s: %s \n " ) ,
sigtarget , Fstrerror ( ifd ) ) ;
goto exit ;
}
/* Add signatures to header, and write header into the package. */
{ Header nh = headerRead ( ifd , HEADER_MAGIC_YES ) ;
if ( nh = = NULL ) {
rc = RPMERR_READ ;
rpmError ( RPMERR_READ , _ ( " Unable to read header from %s: %s \n " ) ,
sigtarget , Fstrerror ( ifd ) ) ;
goto exit ;
}
# ifdef NOTYET
( void ) headerMergeLegacySigs ( nh , sig ) ;
# endif
rc = headerWrite ( fd , nh , HEADER_MAGIC_YES ) ;
nh = headerFree ( nh ) ;
if ( rc ) {
rc = RPMERR_NOSPACE ;
rpmError ( RPMERR_NOSPACE , _ ( " Unable to write header to %s: %s \n " ) ,
fileName , Fstrerror ( fd ) ) ;
goto exit ;
}
}
/* Write the payload into the package. */
while ( ( count = Fread ( buf , sizeof ( buf [ 0 ] ) , sizeof ( buf ) , ifd ) ) > 0 ) {
if ( count = = - 1 ) {
rc = RPMERR_READ ;
rpmError ( RPMERR_READ , _ ( " Unable to read payload from %s: %s \n " ) ,
sigtarget , Fstrerror ( ifd ) ) ;
goto exit ;
}
if ( Fwrite ( buf , sizeof ( buf [ 0 ] ) , count , fd ) ! = count ) {
rc = RPMERR_NOSPACE ;
rpmError ( RPMERR_NOSPACE , _ ( " Unable to write payload to %s: %s \n " ) ,
fileName , Fstrerror ( fd ) ) ;
goto exit ;
}
}
rc = 0 ;
exit :
sha1 = _free ( sha1 ) ;
h = headerFree ( h ) ;
sig = rpmFreeSignature ( sig ) ;
if ( ifd ) {
( void ) Fclose ( ifd ) ;
ifd = NULL ;
}
if ( fd ) {
( void ) Fclose ( fd ) ;
fd = NULL ;
}
if ( sigtarget ) {
( void ) Unlink ( sigtarget ) ;
sigtarget = _free ( sigtarget ) ;
}
2021-01-05 14:57:48 +03:00
/* Expand rpmio_flags for an actual 'T' value. */
if ( rpmioThreads ) {
char * src_flags = xstrdup ( rpmio_flags ) ;
char * psrc = src_flags ;
# define SIZE_SPRINTF_U (sizeof(unsigned int) * 3)
rpmio_flags = xrealloc ( rpmio_flags , strlen ( rpmio_flags ) + 1 + SIZE_SPRINTF_U ) ;
char * pdst = rpmio_flags ;
while ( * psrc ) {
if ( * psrc = = ' T ' ) {
int n = snprintf ( pdst , SIZE_SPRINTF_U + 1 , " T%u " , rpmioThreads ) ;
assert ( n < SIZE_SPRINTF_U + 1 ) ;
pdst + = n ;
while ( isdigit ( * + + psrc ) ) ;
break ; /* Only can expand once. */
} else
* pdst + + = * psrc + + ;
}
while ( * psrc )
* pdst + + = * psrc + + ;
* pdst = ' \0 ' ;
free ( src_flags ) ;
}
2002-03-25 23:16:26 +03:00
if ( rc = = 0 )
2020-12-20 01:43:47 +03:00
rpmMessage ( RPMMESS_NORMAL , _ ( " Wrote: %s (%s) \n " ) ,
fileName , rpmio_flags ) ;
2002-03-25 23:16:26 +03:00
else
( void ) Unlink ( fileName ) ;
2020-12-20 01:43:47 +03:00
rpmio_flags = _free ( rpmio_flags ) ;
2002-03-25 23:16:26 +03:00
return rc ;
}
/*@unchecked@*/
static int_32 copyTags [ ] = {
RPMTAG_CHANGELOGTIME ,
RPMTAG_CHANGELOGNAME ,
RPMTAG_CHANGELOGTEXT ,
0
} ;
int packageBinaries ( Spec spec )
{
struct cpioSourceArchive_s csabuf ;
CSA_t csa = & csabuf ;
int rc ;
const char * errorString ;
Package pkg ;
for ( pkg = spec - > packages ; pkg ! = NULL ; pkg = pkg - > next ) {
const char * fn ;
if ( pkg - > fileList = = NULL )
continue ;
if ( ( rc = processScriptFiles ( spec , pkg ) ) )
return rc ;
if ( spec - > cookie ) {
( void ) headerAddEntry ( pkg - > header , RPMTAG_COOKIE ,
RPM_STRING_TYPE , spec - > cookie , 1 ) ;
}
/* Copy changelog from src rpm */
headerCopyTags ( spec - > packages - > header , pkg - > header , copyTags ) ;
( void ) headerAddEntry ( pkg - > header , RPMTAG_RPMVERSION ,
RPM_STRING_TYPE , VERSION , 1 ) ;
2002-06-13 15:28:05 +04:00
if ( ! headerIsEntry ( pkg - > header , RPMTAG_BUILDHOST ) )
( void ) headerAddEntry ( pkg - > header , RPMTAG_BUILDHOST ,
2002-03-25 23:16:26 +03:00
RPM_STRING_TYPE , buildHost ( ) , 1 ) ;
( void ) headerAddEntry ( pkg - > header , RPMTAG_BUILDTIME ,
RPM_INT32_TYPE , getBuildTime ( ) , 1 ) ;
providePackageNVR ( pkg - > header ) ;
2005-09-29 20:01:17 +04:00
{ const char * optflags = rpmExpand ( " %{?optflags} " , NULL ) ;
2002-03-25 23:16:26 +03:00
( void ) headerAddEntry ( pkg - > header , RPMTAG_OPTFLAGS , RPM_STRING_TYPE ,
optflags , 1 ) ;
optflags = _free ( optflags ) ;
}
( void ) genSourceRpmName ( spec ) ;
( void ) headerAddEntry ( pkg - > header , RPMTAG_SOURCERPM , RPM_STRING_TYPE ,
spec - > sourceRpmName , 1 ) ;
{ const char * binFormat = rpmGetPath ( " %{_rpmfilename} " , NULL ) ;
char * binRpm , * binDir ;
binRpm = headerSprintf ( pkg - > header , binFormat , rpmTagTable ,
rpmHeaderFormats , & errorString ) ;
binFormat = _free ( binFormat ) ;
if ( binRpm = = NULL ) {
const char * name ;
2019-02-25 05:06:13 +03:00
( void ) headerName ( pkg - > header , & name ) ;
2002-03-25 23:16:26 +03:00
rpmError ( RPMERR_BADFILENAME , _ ( " Could not generate output "
" filename for package %s: %s \n " ) , name , errorString ) ;
return RPMERR_BADFILENAME ;
}
fn = rpmGetPath ( " %{_rpmdir}/ " , binRpm , NULL ) ;
if ( ( binDir = strchr ( binRpm , ' / ' ) ) ! = NULL ) {
struct stat st ;
const char * dn ;
* binDir = ' \0 ' ;
dn = rpmGetPath ( " %{_rpmdir}/ " , binRpm , NULL ) ;
if ( Stat ( dn , & st ) < 0 ) {
switch ( errno ) {
case ENOENT :
2002-08-29 19:00:42 +04:00
if ( MkdirP ( dn , 0755 ) = = 0 )
2002-03-25 23:16:26 +03:00
/*@switchbreak@*/ break ;
/*@fallthrough@*/
default :
rpmError ( RPMERR_BADFILENAME , _ ( " cannot create %s: %s \n " ) ,
dn , strerror ( errno ) ) ;
/*@switchbreak@*/ break ;
}
}
dn = _free ( dn ) ;
}
binRpm = _free ( binRpm ) ;
}
memset ( csa , 0 , sizeof ( * csa ) ) ;
csa - > cpioArchiveSize = 0 ;
/*@-type@*/ /* LCL: function typedefs */
csa - > cpioFdIn = fdNew ( " init (packageBinaries) " ) ;
/*@-assignexpose -newreftrans@*/
/*@i@*/ csa - > cpioList = pkg - > cpioList ;
/*@=assignexpose =newreftrans@*/
rc = writeRPM ( & pkg - > header , fn , RPMLEAD_BINARY ,
csa , spec - > passPhrase , NULL ) ;
csa - > cpioFdIn = fdFree ( csa - > cpioFdIn , " init (packageBinaries) " ) ;
/*@=type@*/
fn = _free ( fn ) ;
if ( rc )
return rc ;
}
return 0 ;
}
int packageSources ( Spec spec )
{
struct cpioSourceArchive_s csabuf ;
CSA_t csa = & csabuf ;
int rc ;
2020-04-21 18:18:38 +03:00
time_t buildtime ;
int_32 buildtime32 ;
int_32 * override_buildtime = NULL ;
const char * env_buildtime = getenv ( " SOURCE_DATE_EPOCH " ) ;
2002-03-25 23:16:26 +03:00
/* Add some cruft */
( void ) headerAddEntry ( spec - > sourceHeader , RPMTAG_RPMVERSION ,
RPM_STRING_TYPE , VERSION , 1 ) ;
2002-06-13 15:28:05 +04:00
if ( ! headerIsEntry ( spec - > sourceHeader , RPMTAG_BUILDHOST ) )
( void ) headerAddEntry ( spec - > sourceHeader , RPMTAG_BUILDHOST ,
2002-03-25 23:16:26 +03:00
RPM_STRING_TYPE , buildHost ( ) , 1 ) ;
2020-04-21 18:18:38 +03:00
if ( env_buildtime & & * env_buildtime ) {
char * endptr ;
errno = 0 ;
buildtime = strtol ( env_buildtime , & endptr , 10 ) ;
if ( env_buildtime = = endptr | | * endptr
| | ( ( buildtime = = LONG_MIN | | buildtime = = LONG_MAX )
& & errno ! = 0 ) ) {
rpmlog ( RPMLOG_ERR , _ ( " unable to parse %s=%s \n " ) ,
" SOURCE_DATE_EPOCH " , env_buildtime ) ;
} else {
buildtime32 = ( typeof ( buildtime32 ) ) buildtime ;
override_buildtime = & buildtime32 ;
}
}
2002-03-25 23:16:26 +03:00
( void ) headerAddEntry ( spec - > sourceHeader , RPMTAG_BUILDTIME ,
2020-04-21 18:18:38 +03:00
RPM_INT32_TYPE , override_buildtime ? : getBuildTime ( ) , 1 ) ;
2002-03-25 23:16:26 +03:00
( void ) genSourceRpmName ( spec ) ;
spec - > cookie = _free ( spec - > cookie ) ;
/* XXX this should be %_srpmdir */
2003-09-12 21:22:05 +04:00
{
const char * fn = rpmGetPath ( " %{_srcrpmdir}/ " , spec - > sourceRpmName , NULL ) ;
{
const char * dn = rpmGetPath ( " %{_srcrpmdir}/ " , NULL ) ;
struct stat st ;
2002-03-25 23:16:26 +03:00
2003-09-12 21:22:05 +04:00
if ( Stat ( dn , & st ) < 0 ) {
switch ( errno ) {
case ENOENT :
if ( MkdirP ( dn , 0755 ) = = 0 )
/*@switchbreak@*/ break ;
/*@fallthrough@*/
default :
rpmError ( RPMERR_BADFILENAME , _ ( " cannot create %s: %s \n " ) ,
dn , strerror ( errno ) ) ;
/*@switchbreak@*/ break ;
}
}
dn = _free ( dn ) ;
}
2002-03-25 23:16:26 +03:00
memset ( csa , 0 , sizeof ( * csa ) ) ;
csa - > cpioArchiveSize = 0 ;
/*@-type@*/ /* LCL: function typedefs */
csa - > cpioFdIn = fdNew ( " init (packageSources) " ) ;
/*@-assignexpose -newreftrans@*/
/*@i@*/ csa - > cpioList = spec - > sourceCpioList ;
/*@=assignexpose =newreftrans@*/
rc = writeRPM ( & spec - > sourceHeader , fn , RPMLEAD_SOURCE ,
csa , spec - > passPhrase , & ( spec - > cookie ) ) ;
csa - > cpioFdIn = fdFree ( csa - > cpioFdIn , " init (packageSources) " ) ;
/*@=type@*/
fn = _free ( fn ) ;
}
return rc ;
}