include "stdio.s7i";
include "time.s7i";
include "filesys.s7i";
include "filebits.s7i";
include "bytedata.s7i";
include "msgdigest.s7i";
include "strifile.s7i";
include "gzip.s7i";
include "lzma.s7i";
include "xz.s7i";
include "zstd.s7i";
include "bzip2.s7i";
include "cpio.s7i";
include "archive_base.s7i";
include "magic.s7i";
include "elf.s7i";
const string: RPM_LEAD_MAGIC is "\16#ed;\16#ab;\16#ee;\16#db;";
const string: RPM_HEADER_MAGIC is "\16#8e;\16#ad;\16#e8;";
const integer: RPM_LEAD_SIZE is 96;
const integer: RPM_HEADER_SIZE is 16;
const integer: RPM_INDEX_ENTRY_SIZE is 16;
const type: rpmPackageType is new enum
RPM_BINARY_PACKAGE, RPM_SOURCE_PACKAGE
end enum;
const type: rpmLead is new struct
var string: magic is "";
var integer: majorVersion is 0;
var integer: minorVersion is 0;
var rpmPackageType: packageType is RPM_BINARY_PACKAGE;
var integer: arch is 0;
var string: name is "";
var integer: os is 0;
var integer: sig is 0;
end struct;
const type: rpmHeader is new struct
var string: magic is "";
var integer: version is 0;
var string: reservedBytes is "\0;" mult 4;
var integer: indexCount is 0;
var integer: storeSize is 0;
end struct;
const type: rpmIndexEntry is new struct
var integer: tag is 0;
var integer: dataType is 0;
var integer: offset is 0;
var integer: count is 0;
var string: striValue is "";
var array string: arrayValue is 0 times "";
end struct;
const type: rpmTagMap is hash [integer] rpmIndexEntry;
const integer: RPM_NULL_TYPE is 0;
const integer: RPM_CHAR_TYPE is 1;
const integer: RPM_INT8_TYPE is 2;
const integer: RPM_INT16_TYPE is 3;
const integer: RPM_INT32_TYPE is 4;
const integer: RPM_INT64_TYPE is 5;
const integer: RPM_STRING_TYPE is 6;
const integer: RPM_BIN_TYPE is 7;
const integer: RPM_STRING_ARRAY_TYPE is 8;
const integer: RPM_I18NSTRING_TYPE is 9;
const integer: RPMTAG_HEADERIMMUTABLE is 63;
const integer: RPMTAG_HEADERI18NTABLE is 100;
const integer: RPMTAG_NAME is 1000;
const integer: RPMTAG_VERSION is 1001;
const integer: RPMTAG_RELEASE is 1002;
const integer: RPMTAG_EPOCH is 1003;
const integer: RPMTAG_SUMMARY is 1004;
const integer: RPMTAG_DESCRIPTION is 1005;
const integer: RPMTAG_BUILDTIME is 1006;
const integer: RPMTAG_BUILDHOST is 1007;
const integer: RPMTAG_INSTALLTIME is 1008;
const integer: RPMTAG_SIZE is 1009;
const integer: RPMTAG_DISTRIBUTION is 1010;
const integer: RPMTAG_VENDOR is 1011;
const integer: RPMTAG_GIF is 1012;
const integer: RPMTAG_XPM is 1013;
const integer: RPMTAG_LICENSE is 1014;
const integer: RPMTAG_PACKAGER is 1015;
const integer: RPMTAG_GROUP is 1016;
const integer: RPMTAG_CHANGELOG is 1017;
const integer: RPMTAG_SOURCE is 1018;
const integer: RPMTAG_PATCH is 1019;
const integer: RPMTAG_URL is 1020;
const integer: RPMTAG_OS is 1021;
const integer: RPMTAG_ARCH is 1022;
const integer: RPMTAG_PREIN is 1023;
const integer: RPMTAG_POSTIN is 1024;
const integer: RPMTAG_PREUN is 1025;
const integer: RPMTAG_POSTUN is 1026;
const integer: RPMTAG_OLDFILENAMES is 1027;
const integer: RPMTAG_FILESIZES is 1028;
const integer: RPMTAG_FILESTATES is 1029;
const integer: RPMTAG_FILEMODES is 1030;
const integer: RPMTAG_FILEUIDS is 1031;
const integer: RPMTAG_FILEGIDS is 1032;
const integer: RPMTAG_FILERDEVS is 1033;
const integer: RPMTAG_FILEMTIMES is 1034;
const integer: RPMTAG_FILEDIGESTS is 1035;
const integer: RPMTAG_FILELINKTOS is 1036;
const integer: RPMTAG_FILEFLAGS is 1037;
const integer: RPMTAG_ROOT is 1038;
const integer: RPMTAG_FILEUSERNAME is 1039;
const integer: RPMTAG_FILEGROUPNAME is 1040;
const integer: RPMTAG_EXCLUDE is 1041;
const integer: RPMTAG_EXCLUSIVE is 1042;
const integer: RPMTAG_ICON is 1043;
const integer: RPMTAG_SOURCERPM is 1044;
const integer: RPMTAG_FILEVERIFYFLAGS is 1045;
const integer: RPMTAG_ARCHIVESIZE is 1046;
const integer: RPMTAG_PROVIDENAME is 1047;
const integer: RPMTAG_REQUIREFLAGS is 1048;
const integer: RPMTAG_REQUIRENAME is 1049;
const integer: RPMTAG_REQUIREVERSION is 1050;
const integer: RPMTAG_NOSOURCE is 1051;
const integer: RPMTAG_NOPATCH is 1052;
const integer: RPMTAG_CONFLICTFLAGS is 1053;
const integer: RPMTAG_CONFLICTNAME is 1054;
const integer: RPMTAG_CONFLICTVERSION is 1055;
const integer: RPMTAG_DEFAULTPREFIX is 1056;
const integer: RPMTAG_BUILDROOT is 1057;
const integer: RPMTAG_INSTALLPREFIX is 1058;
const integer: RPMTAG_EXCLUDEARCH is 1059;
const integer: RPMTAG_EXCLUDEOS is 1060;
const integer: RPMTAG_EXCLUSIVEARCH is 1061;
const integer: RPMTAG_EXCLUSIVEOS is 1062;
const integer: RPMTAG_AUTOREQPROV is 1063;
const integer: RPMTAG_RPMVERSION is 1064;
const integer: RPMTAG_TRIGGERSCRIPTS is 1065;
const integer: RPMTAG_TRIGGERNAME is 1066;
const integer: RPMTAG_TRIGGERVERSION is 1067;
const integer: RPMTAG_TRIGGERFLAGS is 1068;
const integer: RPMTAG_TRIGGERINDEX is 1069;
const integer: RPMTAG_VERIFYSCRIPT is 1079;
const integer: RPMTAG_CHANGELOGTIME is 1080;
const integer: RPMTAG_CHANGELOGNAME is 1081;
const integer: RPMTAG_CHANGELOGTEXT is 1082;
const integer: RPMTAG_BROKENMD5 is 1083;
const integer: RPMTAG_PREREQ is 1084;
const integer: RPMTAG_PREINPROG is 1085;
const integer: RPMTAG_POSTINPROG is 1086;
const integer: RPMTAG_PREUNPROG is 1087;
const integer: RPMTAG_POSTUNPROG is 1088;
const integer: RPMTAG_BUILDARCHS is 1089;
const integer: RPMTAG_OBSOLETENAME is 1090;
const integer: RPMTAG_VERIFYSCRIPTPROG is 1091;
const integer: RPMTAG_TRIGGERSCRIPTPROG is 1092;
const integer: RPMTAG_DOCDIR is 1093;
const integer: RPMTAG_COOKIE is 1094;
const integer: RPMTAG_FILEDEVICES is 1095;
const integer: RPMTAG_FILEINODES is 1096;
const integer: RPMTAG_FILELANGS is 1097;
const integer: RPMTAG_PREFIXES is 1098;
const integer: RPMTAG_INSTPREFIXES is 1099;
const integer: RPMTAG_TRIGGERIN is 1100;
const integer: RPMTAG_TRIGGERUN is 1101;
const integer: RPMTAG_TRIGGERPOSTUN is 1102;
const integer: RPMTAG_AUTOREQ is 1103;
const integer: RPMTAG_AUTOPROV is 1104;
const integer: RPMTAG_CAPABILITY is 1105;
const integer: RPMTAG_SOURCEPACKAGE is 1106;
const integer: RPMTAG_OLDORIGFILENAMES is 1107;
const integer: RPMTAG_BUILDPREREQ is 1108;
const integer: RPMTAG_BUILDREQUIRES is 1109;
const integer: RPMTAG_BUILDCONFLICTS is 1110;
const integer: RPMTAG_BUILDMACROS is 1111;
const integer: RPMTAG_PROVIDEFLAGS is 1112;
const integer: RPMTAG_PROVIDEVERSION is 1113;
const integer: RPMTAG_OBSOLETEFLAGS is 1114;
const integer: RPMTAG_OBSOLETEVERSION is 1115;
const integer: RPMTAG_DIRINDEXES is 1116;
const integer: RPMTAG_BASENAMES is 1117;
const integer: RPMTAG_DIRNAMES is 1118;
const integer: RPMTAG_ORIGDIRINDEXES is 1119;
const integer: RPMTAG_ORIGBASENAMES is 1120;
const integer: RPMTAG_ORIGDIRNAMES is 1121;
const integer: RPMTAG_OPTFLAGS is 1122;
const integer: RPMTAG_DISTURL is 1123;
const integer: RPMTAG_PAYLOADFORMAT is 1124;
const integer: RPMTAG_PAYLOADCOMPRESSOR is 1125;
const integer: RPMTAG_PAYLOADFLAGS is 1126;
const integer: RPMTAG_INSTALLCOLOR is 1127;
const integer: RPMTAG_INSTALLTID is 1128;
const integer: RPMTAG_REMOVETID is 1129;
const integer: RPMTAG_SHA1RHN is 1130;
const integer: RPMTAG_RHNPLATFORM is 1131;
const integer: RPMTAG_PLATFORM is 1132;
const integer: RPMTAG_PATCHESNAME is 1133;
const integer: RPMTAG_PATCHESFLAGS is 1134;
const integer: RPMTAG_PATCHESVERSION is 1135;
const integer: RPMTAG_CACHECTIME is 1136;
const integer: RPMTAG_CACHEPKGPATH is 1137;
const integer: RPMTAG_CACHEPKGSIZE is 1138;
const integer: RPMTAG_CACHEPKGMTIME is 1139;
const integer: RPMTAG_FILECOLORS is 1140;
const integer: RPMTAG_FILECLASS is 1141;
const integer: RPMTAG_CLASSDICT is 1142;
const integer: RPMTAG_FILEDEPENDSX is 1143;
const integer: RPMTAG_FILEDEPENDSN is 1144;
const integer: RPMTAG_DEPENDSDICT is 1145;
const integer: RPMTAG_SOURCEPKGID is 1146;
const integer: RPMTAG_FILECONTEXTS is 1147;
const integer: RPMTAG_FSCONTEXTS is 1148;
const integer: RPMTAG_RECONTEXTS is 1149;
const integer: RPMTAG_POLICIES is 1150;
const integer: RPMTAG_PRETRANS is 1151;
const integer: RPMTAG_POSTTRANS is 1152;
const integer: RPMTAG_PRETRANSPROG is 1153;
const integer: RPMTAG_POSTTRANSPROG is 1154;
const integer: RPMTAG_DISTTAG is 1155;
const integer: RPMTAG_OLDSUGGESTSNAME is 1156;
const integer: RPMTAG_OLDSUGGESTSVERSION is 1157;
const integer: RPMTAG_OLDSUGGESTSFLAGS is 1158;
const integer: RPMTAG_OLDENHANCESNAME is 1159;
const integer: RPMTAG_OLDENHANCESVERSION is 1160;
const integer: RPMTAG_OLDENHANCESFLAGS is 1161;
const integer: RPMTAG_PRIORITY is 1162;
const integer: RPMTAG_CVSID is 1163;
const integer: RPMTAG_BLINKPKGID is 1164;
const integer: RPMTAG_BLINKHDRID is 1165;
const integer: RPMTAG_BLINKNEVRA is 1166;
const integer: RPMTAG_FLINKPKGID is 1167;
const integer: RPMTAG_FLINKHDRID is 1168;
const integer: RPMTAG_FLINKNEVRA is 1169;
const integer: RPMTAG_PACKAGEORIGIN is 1170;
const integer: RPMTAG_TRIGGERPREIN is 1171;
const integer: RPMTAG_BUILDSUGGESTS is 1172;
const integer: RPMTAG_BUILDENHANCES is 1173;
const integer: RPMTAG_SCRIPTSTATES is 1174;
const integer: RPMTAG_SCRIPTMETRICS is 1175;
const integer: RPMTAG_BUILDCPUCLOCK is 1176;
const integer: RPMTAG_FILEDIGESTALGOS is 1177;
const integer: RPMTAG_VARIANTS is 1178;
const integer: RPMTAG_XMAJOR is 1179;
const integer: RPMTAG_XMINOR is 1180;
const integer: RPMTAG_REPOTAG is 1181;
const integer: RPMTAG_KEYWORDS is 1182;
const integer: RPMTAG_BUILDPLATFORMS is 1183;
const integer: RPMTAG_PACKAGECOLOR is 1184;
const integer: RPMTAG_PACKAGEPREFCOLOR is 1185;
const integer: RPMTAG_XATTRSDICT is 1186;
const integer: RPMTAG_FILEXATTRSX is 1187;
const integer: RPMTAG_DEPATTRSDICT is 1188;
const integer: RPMTAG_CONFLICTATTRSX is 1189;
const integer: RPMTAG_OBSOLETEATTRSX is 1190;
const integer: RPMTAG_PROVIDEATTRSX is 1191;
const integer: RPMTAG_REQUIREATTRSX is 1192;
const integer: RPMTAG_BUILDPROVIDES is 1193;
const integer: RPMTAG_BUILDOBSOLETES is 1194;
const integer: RPMTAG_DBINSTANCE is 1195;
const integer: RPMTAG_NVRA is 1196;
const integer: RPMTAG_FILENAMES is 5000;
const integer: RPMTAG_FILEPROVIDE is 5001;
const integer: RPMTAG_FILEREQUIRE is 5002;
const integer: RPMTAG_FSNAMES is 5003;
const integer: RPMTAG_FSSIZES is 5004;
const integer: RPMTAG_TRIGGERCONDS is 5005;
const integer: RPMTAG_TRIGGERTYPE is 5006;
const integer: RPMTAG_ORIGFILENAMES is 5007;
const integer: RPMTAG_LONGFILESIZES is 5008;
const integer: RPMTAG_LONGSIZE is 5009;
const integer: RPMTAG_FILECAPS is 5010;
const integer: RPMTAG_FILEDIGESTALGO is 5011;
const integer: RPMTAG_BUGURL is 5012;
const integer: RPMTAG_EVR is 5013;
const integer: RPMTAG_NVR is 5014;
const integer: RPMTAG_NEVR is 5015;
const integer: RPMTAG_NEVRA is 5016;
const integer: RPMTAG_HEADERCOLOR is 5017;
const integer: RPMTAG_VERBOSE is 5018;
const integer: RPMTAG_EPOCHNUM is 5019;
const integer: RPMTAG_PREINFLAGS is 5020;
const integer: RPMTAG_POSTINFLAGS is 5021;
const integer: RPMTAG_PREUNFLAGS is 5022;
const integer: RPMTAG_POSTUNFLAGS is 5023;
const integer: RPMTAG_PRETRANSFLAGS is 5024;
const integer: RPMTAG_POSTTRANSFLAGS is 5025;
const integer: RPMTAG_VERIFYSCRIPTFLAGS is 5026;
const integer: RPMTAG_TRIGGERSCRIPTFLAGS is 5027;
const integer: RPMTAG_COLLECTIONS is 5029;
const integer: RPMTAG_POLICYNAMES is 5030;
const integer: RPMTAG_POLICYTYPES is 5031;
const integer: RPMTAG_POLICYTYPESINDEXES is 5032;
const integer: RPMTAG_POLICYFLAGS is 5033;
const integer: RPMTAG_VCS is 5034;
const integer: RPMTAG_ORDERNAME is 5035;
const integer: RPMTAG_ORDERVERSION is 5036;
const integer: RPMTAG_ORDERFLAGS is 5037;
const integer: RPMTAG_MSSFMANIFEST is 5038;
const integer: RPMTAG_MSSFDOMAIN is 5039;
const integer: RPMTAG_INSTFILENAMES is 5040;
const integer: RPMTAG_REQUIRENEVRS is 5041;
const integer: RPMTAG_PROVIDENEVRS is 5042;
const integer: RPMTAG_OBSOLETENEVRS is 5043;
const integer: RPMTAG_CONFLICTNEVRS is 5044;
const integer: RPMTAG_FILENLINKS is 5045;
const integer: RPMTAG_RECOMMENDNAME is 5046;
const integer: RPMTAG_RECOMMENDVERSION is 5047;
const integer: RPMTAG_RECOMMENDFLAGS is 5048;
const integer: RPMTAG_SUGGESTNAME is 5049;
const integer: RPMTAG_SUGGESTVERSION is 5050;
const integer: RPMTAG_SUGGESTFLAGS is 5051;
const integer: RPMTAG_SUPPLEMENTNAME is 5052;
const integer: RPMTAG_SUPPLEMENTVERSION is 5053;
const integer: RPMTAG_SUPPLEMENTFLAGS is 5054;
const integer: RPMTAG_ENHANCENAME is 5055;
const integer: RPMTAG_ENHANCEVERSION is 5056;
const integer: RPMTAG_ENHANCEFLAGS is 5057;
const integer: RPMTAG_RECOMMENDNEVRS is 5058;
const integer: RPMTAG_SUGGESTNEVRS is 5059;
const integer: RPMTAG_SUPPLEMENTNEVRS is 5060;
const integer: RPMTAG_ENHANCENEVRS is 5061;
const integer: RPMTAG_ENCODING is 5062;
const integer: RPMTAG_FILETRIGGERIN is 5063;
const integer: RPMTAG_FILETRIGGERUN is 5064;
const integer: RPMTAG_FILETRIGGERPOSTUN is 5065;
const integer: RPMTAG_FILETRIGGERSCRIPTS is 5066;
const integer: RPMTAG_FILETRIGGERSCRIPTPROG is 5067;
const integer: RPMTAG_FILETRIGGERSCRIPTFLAGS is 5068;
const integer: RPMTAG_FILETRIGGERNAME is 5069;
const integer: RPMTAG_FILETRIGGERINDEX is 5070;
const integer: RPMTAG_FILETRIGGERVERSION is 5071;
const integer: RPMTAG_FILETRIGGERFLAGS is 5072;
const integer: RPMTAG_TRANSFILETRIGGERIN is 5073;
const integer: RPMTAG_TRANSFILETRIGGERUN is 5074;
const integer: RPMTAG_TRANSFILETRIGGERPOSTUN is 5075;
const integer: RPMTAG_TRANSFILETRIGGERSCRIPTS is 5076;
const integer: RPMTAG_TRANSFILETRIGGERSCRIPTPROG is 5077;
const integer: RPMTAG_TRANSFILETRIGGERSCRIPTFLAGS is 5078;
const integer: RPMTAG_TRANSFILETRIGGERNAME is 5079;
const integer: RPMTAG_TRANSFILETRIGGERINDEX is 5080;
const integer: RPMTAG_TRANSFILETRIGGERVERSION is 5081;
const integer: RPMTAG_TRANSFILETRIGGERFLAGS is 5082;
const integer: RPMTAG_REMOVEPATHPOSTFIXES is 5083;
const integer: RPMTAG_FILETRIGGERPRIORITIES is 5084;
const integer: RPMTAG_TRANSFILETRIGGERPRIORITIES is 5085;
const integer: RPMTAG_FILETRIGGERCONDS is 5086;
const integer: RPMTAG_FILETRIGGERTYPE is 5087;
const integer: RPMTAG_TRANSFILETRIGGERCONDS is 5088;
const integer: RPMTAG_TRANSFILETRIGGERTYPE is 5089;
const integer: RPMTAG_FILESIGNATURES is 5090;
const integer: RPMTAG_FILESIGNATURELENGTH is 5091;
const integer: RPMTAG_PAYLOADDIGEST is 5092;
const integer: RPMTAG_PAYLOADDIGESTALGO is 5093;
const integer: RPMTAG_AUTOINSTALLED is 5094;
const integer: RPMTAG_IDENTITY is 5095;
const integer: RPMTAG_MODULARITYLABEL is 5096;
const integer: RPMTAG_PAYLOADDIGESTALT is 5097;
const integer: RPMTAG_ARCHSUFFIX is 5098;
const integer: RPMTAG_SPEC is 5099;
const integer: RPMSIGTAG_HEADERSIGNATURES is 62;
const integer: RPMSIGTAG_SIZE is 1000;
const integer: RPMSIGTAG_PGP is 1002;
const integer: RPMSIGTAG_MD5 is 1004;
const integer: RPMSIGTAG_GPG is 1005;
const integer: RPMSIGTAG_PAYLOADSIZE is 1007;
const integer: RPMSIGTAG_RESERVEDSPACE is 1008;
const integer: RPMSIGTAG_SIGSIZE is 257;
const integer: RPMSIGTAG_RSA is 268;
const integer: RPMSIGTAG_SHA1 is 269;
const integer: RPMSIGTAG_LONGSIGSIZE is 270;
const integer: RPMSIGTAG_SHA256 is 273;
const integer: RPMFILE_NONE is 0;
const integer: RPMFILE_CONFIG is 1 << 0;
const integer: RPMFILE_DOC is 1 << 1;
const integer: RPMFILE_DONOTUSE is 1 << 2;
const integer: RPMFILE_MISSINGOK is 1 << 3;
const integer: RPMFILE_NOREPLACE is 1 << 4;
const integer: RPMFILE_SPECFILE is 1 << 5;
const integer: RPMFILE_GHOST is 1 << 6;
const integer: RPMFILE_LICENSE is 1 << 7;
const integer: RPMFILE_README is 1 << 8;
const integer: RPMFILE_EXCLUDE is 1 << 9;
const integer: RPMFILE_UNPATCHED is 1 << 10;
const integer: RPMFILE_PUBKEY is 1 << 11;
const integer: RPMFILE_ARTIFACT is 1 << 12;
const integer: RPMSENSE_ANY is 0;
const integer: RPMSENSE_LESS is 1 << 1;
const integer: RPMSENSE_GREATER is 1 << 2;
const integer: RPMSENSE_EQUAL is 1 << 3;
const integer: RPMSENSE_POSTTRANS is 1 << 5;
const integer: RPMSENSE_PREREQ is 1 << 6;
const integer: RPMSENSE_PRETRANS is 1 << 7;
const integer: RPMSENSE_INTERP is 1 << 8;
const integer: RPMSENSE_SCRIPT_PRE is 1 << 9;
const integer: RPMSENSE_SCRIPT_POST is 1 << 10;
const integer: RPMSENSE_SCRIPT_PREUN is 1 << 11;
const integer: RPMSENSE_SCRIPT_POSTUN is 1 << 12;
const integer: RPMSENSE_SCRIPT_VERIFY is 1 << 13;
const integer: RPMSENSE_FIND_REQUIRES is 1 << 14;
const integer: RPMSENSE_FIND_PROVIDES is 1 << 15;
const integer: RPMSENSE_TRIGGERIN is 1 << 16;
const integer: RPMSENSE_TRIGGERUN is 1 << 17;
const integer: RPMSENSE_TRIGGERPOSTUN is 1 << 18;
const integer: RPMSENSE_MISSINGOK is 1 << 19;
const integer: RPMSENSE_RPMLIB is 1 << 24;
const integer: RPMSENSE_TRIGGERPREIN is 1 << 25;
const integer: RPMSENSE_KEYRING is 1 << 26;
const integer: RPMSENSE_CONFIG is 1 << 28;
const integer: RPM_DIGESTALGO_MD5 is 1;
const integer: RPM_DIGESTALGO_SHA1 is 2;
const integer: RPM_DIGESTALGO_RIPEMD160 is 3;
const integer: RPM_DIGESTALGO_MD2 is 5;
const integer: RPM_DIGESTALGO_TIGER192 is 6;
const integer: RPM_DIGESTALGO_HAVAL_5_160 is 7;
const integer: RPM_DIGESTALGO_SHA256 is 8;
const integer: RPM_DIGESTALGO_SHA384 is 9;
const integer: RPM_DIGESTALGO_SHA512 is 10;
const integer: RPM_DIGESTALGO_SHA224 is 11;
const integer: RPM_ALL_VERIFY_FLAGS is 4294967295;
const func string: sigtagName (in integer: tag) is func
result
var string: name is "";
begin
case tag of
when { 62}: name := "HEADERSIGNATURES";
when {1000}: name := "SIZE";
when {1001}: name := "LEMD5_1";
when {1002}: name := "PGP";
when {1003}: name := "LEMD5_2";
when {1004}: name := "MD5";
when {1005}: name := "GPG";
when {1006}: name := "PGP5";
when {1007}: name := "PAYLOADSIZE";
when {1008}: name := "RESERVEDSPACE";
when { 257}: name := "SIGSIZE";
when { 258}: name := "SIGLEMD5_1";
when { 259}: name := "SIGPGP";
when { 260}: name := "SIGLEMD5_2";
when { 261}: name := "SIGMD5";
when { 262}: name := "SIGGPG";
when { 263}: name := "SIGPGP5";
when { 264}: name := "BADSHA1_1";
when { 265}: name := "BADSHA1_2";
when { 267}: name := "DSA";
when { 268}: name := "RSA";
when { 269}: name := "SHA1";
when { 270}: name := "LONGSIGSIZE";
when { 271}: name := "LONGARCHIVESIZE";
when { 273}: name := "SHA256";
otherwise: name := "tag " <& tag;
end case;
end func;
const func string: rpmtagName (in integer: tag) is func
result
var string: name is "";
begin
case tag of
when {RPMTAG_HEADERIMMUTABLE}: name := "HEADERIMMUTABLE";
when {RPMTAG_HEADERI18NTABLE}: name := "HEADERI18NTABLE";
when {RPMTAG_NAME}: name := "NAME";
when {RPMTAG_VERSION}: name := "VERSION";
when {RPMTAG_RELEASE}: name := "RELEASE";
when {RPMTAG_EPOCH}: name := "EPOCH";
when {RPMTAG_SUMMARY}: name := "SUMMARY";
when {RPMTAG_DESCRIPTION}: name := "DESCRIPTION";
when {RPMTAG_BUILDTIME}: name := "BUILDTIME";
when {RPMTAG_BUILDHOST}: name := "BUILDHOST";
when {RPMTAG_INSTALLTIME}: name := "INSTALLTIME";
when {RPMTAG_SIZE}: name := "SIZE";
when {RPMTAG_DISTRIBUTION}: name := "DISTRIBUTION";
when {RPMTAG_VENDOR}: name := "VENDOR";
when {RPMTAG_GIF}: name := "GIF";
when {RPMTAG_XPM}: name := "XPM";
when {RPMTAG_LICENSE}: name := "LICENSE";
when {RPMTAG_PACKAGER}: name := "PACKAGER";
when {RPMTAG_GROUP}: name := "GROUP";
when {RPMTAG_CHANGELOG}: name := "CHANGELOG";
when {RPMTAG_SOURCE}: name := "SOURCE";
when {RPMTAG_PATCH}: name := "PATCH";
when {RPMTAG_URL}: name := "URL";
when {RPMTAG_OS}: name := "OS";
when {RPMTAG_ARCH}: name := "ARCH";
when {RPMTAG_PREIN}: name := "PREIN";
when {RPMTAG_POSTIN}: name := "POSTIN";
when {RPMTAG_PREUN}: name := "PREUN";
when {RPMTAG_POSTUN}: name := "POSTUN";
when {RPMTAG_OLDFILENAMES}: name := "OLDFILENAMES";
when {RPMTAG_FILESIZES}: name := "FILESIZES";
when {RPMTAG_FILESTATES}: name := "FILESTATES";
when {RPMTAG_FILEMODES}: name := "FILEMODES";
when {RPMTAG_FILEUIDS}: name := "FILEUIDS";
when {RPMTAG_FILEGIDS}: name := "FILEGIDS";
when {RPMTAG_FILERDEVS}: name := "FILERDEVS";
when {RPMTAG_FILEMTIMES}: name := "FILEMTIMES";
when {RPMTAG_FILEDIGESTS}: name := "FILEDIGESTS";
when {RPMTAG_FILELINKTOS}: name := "FILELINKTOS";
when {RPMTAG_FILEFLAGS}: name := "FILEFLAGS";
when {RPMTAG_ROOT}: name := "ROOT";
when {RPMTAG_FILEUSERNAME}: name := "FILEUSERNAME";
when {RPMTAG_FILEGROUPNAME}: name := "FILEGROUPNAME";
when {RPMTAG_EXCLUDE}: name := "EXCLUDE";
when {RPMTAG_EXCLUSIVE}: name := "EXCLUSIVE";
when {RPMTAG_ICON}: name := "ICON";
when {RPMTAG_SOURCERPM}: name := "SOURCERPM";
when {RPMTAG_FILEVERIFYFLAGS}: name := "FILEVERIFYFLAGS";
when {RPMTAG_ARCHIVESIZE}: name := "ARCHIVESIZE";
when {RPMTAG_PROVIDENAME}: name := "PROVIDENAME";
when {RPMTAG_REQUIREFLAGS}: name := "REQUIREFLAGS";
when {RPMTAG_REQUIRENAME}: name := "REQUIRENAME";
when {RPMTAG_REQUIREVERSION}: name := "REQUIREVERSION";
when {RPMTAG_NOSOURCE}: name := "NOSOURCE";
when {RPMTAG_NOPATCH}: name := "NOPATCH";
when {RPMTAG_CONFLICTFLAGS}: name := "CONFLICTFLAGS";
when {RPMTAG_CONFLICTNAME}: name := "CONFLICTNAME";
when {RPMTAG_CONFLICTVERSION}: name := "CONFLICTVERSION";
when {RPMTAG_DEFAULTPREFIX}: name := "DEFAULTPREFIX";
when {RPMTAG_BUILDROOT}: name := "BUILDROOT";
when {RPMTAG_INSTALLPREFIX}: name := "INSTALLPREFIX";
when {RPMTAG_EXCLUDEARCH}: name := "EXCLUDEARCH";
when {RPMTAG_EXCLUDEOS}: name := "EXCLUDEOS";
when {RPMTAG_EXCLUSIVEARCH}: name := "EXCLUSIVEARCH";
when {RPMTAG_EXCLUSIVEOS}: name := "EXCLUSIVEOS";
when {RPMTAG_AUTOREQPROV}: name := "AUTOREQPROV";
when {RPMTAG_RPMVERSION}: name := "RPMVERSION";
when {RPMTAG_TRIGGERSCRIPTS}: name := "TRIGGERSCRIPTS";
when {RPMTAG_TRIGGERNAME}: name := "TRIGGERNAME";
when {RPMTAG_TRIGGERVERSION}: name := "TRIGGERVERSION";
when {RPMTAG_TRIGGERFLAGS}: name := "TRIGGERFLAGS";
when {RPMTAG_TRIGGERINDEX}: name := "TRIGGERINDEX";
when {RPMTAG_VERIFYSCRIPT}: name := "VERIFYSCRIPT";
when {RPMTAG_CHANGELOGTIME}: name := "CHANGELOGTIME";
when {RPMTAG_CHANGELOGNAME}: name := "CHANGELOGNAME";
when {RPMTAG_CHANGELOGTEXT}: name := "CHANGELOGTEXT";
when {RPMTAG_BROKENMD5}: name := "BROKENMD5";
when {RPMTAG_PREREQ}: name := "PREREQ";
when {RPMTAG_PREINPROG}: name := "PREINPROG";
when {RPMTAG_POSTINPROG}: name := "POSTINPROG";
when {RPMTAG_PREUNPROG}: name := "PREUNPROG";
when {RPMTAG_POSTUNPROG}: name := "POSTUNPROG";
when {RPMTAG_BUILDARCHS}: name := "BUILDARCHS";
when {RPMTAG_OBSOLETENAME}: name := "OBSOLETENAME";
when {RPMTAG_VERIFYSCRIPTPROG}: name := "VERIFYSCRIPTPROG";
when {RPMTAG_TRIGGERSCRIPTPROG}: name := "TRIGGERSCRIPTPROG";
when {RPMTAG_DOCDIR}: name := "DOCDIR";
when {RPMTAG_COOKIE}: name := "COOKIE";
when {RPMTAG_FILEDEVICES}: name := "FILEDEVICES";
when {RPMTAG_FILEINODES}: name := "FILEINODES";
when {RPMTAG_FILELANGS}: name := "FILELANGS";
when {RPMTAG_PREFIXES}: name := "PREFIXES";
when {RPMTAG_INSTPREFIXES}: name := "INSTPREFIXES";
when {RPMTAG_TRIGGERIN}: name := "TRIGGERIN";
when {RPMTAG_TRIGGERUN}: name := "TRIGGERUN";
when {RPMTAG_TRIGGERPOSTUN}: name := "TRIGGERPOSTUN";
when {RPMTAG_AUTOREQ}: name := "AUTOREQ";
when {RPMTAG_AUTOPROV}: name := "AUTOPROV";
when {RPMTAG_CAPABILITY}: name := "CAPABILITY";
when {RPMTAG_SOURCEPACKAGE}: name := "SOURCEPACKAGE";
when {RPMTAG_OLDORIGFILENAMES}: name := "OLDORIGFILENAMES";
when {RPMTAG_BUILDPREREQ}: name := "BUILDPREREQ";
when {RPMTAG_BUILDREQUIRES}: name := "BUILDREQUIRES";
when {RPMTAG_BUILDCONFLICTS}: name := "BUILDCONFLICTS";
when {RPMTAG_BUILDMACROS}: name := "BUILDMACROS";
when {RPMTAG_PROVIDEFLAGS}: name := "PROVIDEFLAGS";
when {RPMTAG_PROVIDEVERSION}: name := "PROVIDEVERSION";
when {RPMTAG_OBSOLETEFLAGS}: name := "OBSOLETEFLAGS";
when {RPMTAG_OBSOLETEVERSION}: name := "OBSOLETEVERSION";
when {RPMTAG_DIRINDEXES}: name := "DIRINDEXES";
when {RPMTAG_BASENAMES}: name := "BASENAMES";
when {RPMTAG_DIRNAMES}: name := "DIRNAMES";
when {RPMTAG_ORIGDIRINDEXES}: name := "ORIGDIRINDEXES";
when {RPMTAG_ORIGBASENAMES}: name := "ORIGBASENAMES";
when {RPMTAG_ORIGDIRNAMES}: name := "ORIGDIRNAMES";
when {RPMTAG_OPTFLAGS}: name := "OPTFLAGS";
when {RPMTAG_DISTURL}: name := "DISTURL";
when {RPMTAG_PAYLOADFORMAT}: name := "PAYLOADFORMAT";
when {RPMTAG_PAYLOADCOMPRESSOR}: name := "PAYLOADCOMPRESSOR";
when {RPMTAG_PAYLOADFLAGS}: name := "PAYLOADFLAGS";
when {RPMTAG_INSTALLCOLOR}: name := "INSTALLCOLOR";
when {RPMTAG_INSTALLTID}: name := "INSTALLTID";
when {RPMTAG_REMOVETID}: name := "REMOVETID";
when {RPMTAG_SHA1RHN}: name := "SHA1RHN";
when {RPMTAG_RHNPLATFORM}: name := "RHNPLATFORM";
when {RPMTAG_PLATFORM}: name := "PLATFORM";
when {RPMTAG_PATCHESNAME}: name := "PATCHESNAME";
when {RPMTAG_PATCHESFLAGS}: name := "PATCHESFLAGS";
when {RPMTAG_PATCHESVERSION}: name := "PATCHESVERSION";
when {RPMTAG_CACHECTIME}: name := "CACHECTIME";
when {RPMTAG_CACHEPKGPATH}: name := "CACHEPKGPATH";
when {RPMTAG_CACHEPKGSIZE}: name := "CACHEPKGSIZE";
when {RPMTAG_CACHEPKGMTIME}: name := "CACHEPKGMTIME";
when {RPMTAG_FILECOLORS}: name := "FILECOLORS";
when {RPMTAG_FILECLASS}: name := "FILECLASS";
when {RPMTAG_CLASSDICT}: name := "CLASSDICT";
when {RPMTAG_FILEDEPENDSX}: name := "FILEDEPENDSX";
when {RPMTAG_FILEDEPENDSN}: name := "FILEDEPENDSN";
when {RPMTAG_DEPENDSDICT}: name := "DEPENDSDICT";
when {RPMTAG_SOURCEPKGID}: name := "SOURCEPKGID";
when {RPMTAG_FILECONTEXTS}: name := "FILECONTEXTS";
when {RPMTAG_FSCONTEXTS}: name := "FSCONTEXTS";
when {RPMTAG_RECONTEXTS}: name := "RECONTEXTS";
when {RPMTAG_POLICIES}: name := "POLICIES";
when {RPMTAG_PRETRANS}: name := "PRETRANS";
when {RPMTAG_POSTTRANS}: name := "POSTTRANS";
when {RPMTAG_PRETRANSPROG}: name := "PRETRANSPROG";
when {RPMTAG_POSTTRANSPROG}: name := "POSTTRANSPROG";
when {RPMTAG_DISTTAG}: name := "DISTTAG";
when {RPMTAG_OLDSUGGESTSNAME}: name := "OLDSUGGESTSNAME";
when {RPMTAG_OLDSUGGESTSVERSION}: name := "OLDSUGGESTSVERSION";
when {RPMTAG_OLDSUGGESTSFLAGS}: name := "OLDSUGGESTSFLAGS";
when {RPMTAG_OLDENHANCESNAME}: name := "OLDENHANCESNAME";
when {RPMTAG_OLDENHANCESVERSION}: name := "OLDENHANCESVERSION";
when {RPMTAG_OLDENHANCESFLAGS}: name := "OLDENHANCESFLAGS";
when {RPMTAG_PRIORITY}: name := "PRIORITY";
when {RPMTAG_CVSID}: name := "CVSID";
when {RPMTAG_BLINKPKGID}: name := "BLINKPKGID";
when {RPMTAG_BLINKHDRID}: name := "BLINKHDRID";
when {RPMTAG_BLINKNEVRA}: name := "BLINKNEVRA";
when {RPMTAG_FLINKPKGID}: name := "FLINKPKGID";
when {RPMTAG_FLINKHDRID}: name := "FLINKHDRID";
when {RPMTAG_FLINKNEVRA}: name := "FLINKNEVRA";
when {RPMTAG_PACKAGEORIGIN}: name := "PACKAGEORIGIN";
when {RPMTAG_TRIGGERPREIN}: name := "TRIGGERPREIN";
when {RPMTAG_BUILDSUGGESTS}: name := "BUILDSUGGESTS";
when {RPMTAG_BUILDENHANCES}: name := "BUILDENHANCES";
when {RPMTAG_SCRIPTSTATES}: name := "SCRIPTSTATES";
when {RPMTAG_SCRIPTMETRICS}: name := "SCRIPTMETRICS";
when {RPMTAG_BUILDCPUCLOCK}: name := "BUILDCPUCLOCK";
when {RPMTAG_FILEDIGESTALGOS}: name := "FILEDIGESTALGOS";
when {RPMTAG_VARIANTS}: name := "VARIANTS";
when {RPMTAG_XMAJOR}: name := "XMAJOR";
when {RPMTAG_XMINOR}: name := "XMINOR";
when {RPMTAG_REPOTAG}: name := "REPOTAG";
when {RPMTAG_KEYWORDS}: name := "KEYWORDS";
when {RPMTAG_BUILDPLATFORMS}: name := "BUILDPLATFORMS";
when {RPMTAG_PACKAGECOLOR}: name := "PACKAGECOLOR";
when {RPMTAG_PACKAGEPREFCOLOR}: name := "PACKAGEPREFCOLOR";
when {RPMTAG_XATTRSDICT}: name := "XATTRSDICT";
when {RPMTAG_FILEXATTRSX}: name := "FILEXATTRSX";
when {RPMTAG_DEPATTRSDICT}: name := "DEPATTRSDICT";
when {RPMTAG_CONFLICTATTRSX}: name := "CONFLICTATTRSX";
when {RPMTAG_OBSOLETEATTRSX}: name := "OBSOLETEATTRSX";
when {RPMTAG_PROVIDEATTRSX}: name := "PROVIDEATTRSX";
when {RPMTAG_REQUIREATTRSX}: name := "REQUIREATTRSX";
when {RPMTAG_BUILDPROVIDES}: name := "BUILDPROVIDES";
when {RPMTAG_BUILDOBSOLETES}: name := "BUILDOBSOLETES";
when {RPMTAG_DBINSTANCE}: name := "DBINSTANCE";
when {RPMTAG_NVRA}: name := "NVRA";
when {RPMTAG_FILENAMES}: name := "FILENAMES";
when {RPMTAG_FILEPROVIDE}: name := "FILEPROVIDE";
when {RPMTAG_FILEREQUIRE}: name := "FILEREQUIRE";
when {RPMTAG_FSNAMES}: name := "FSNAMES";
when {RPMTAG_FSSIZES}: name := "FSSIZES";
when {RPMTAG_TRIGGERCONDS}: name := "TRIGGERCONDS";
when {RPMTAG_TRIGGERTYPE}: name := "TRIGGERTYPE";
when {RPMTAG_ORIGFILENAMES}: name := "ORIGFILENAMES";
when {RPMTAG_LONGFILESIZES}: name := "LONGFILESIZES";
when {RPMTAG_LONGSIZE}: name := "LONGSIZE";
when {RPMTAG_FILECAPS}: name := "FILECAPS";
when {RPMTAG_FILEDIGESTALGO}: name := "FILEDIGESTALGO";
when {RPMTAG_BUGURL}: name := "BUGURL";
when {RPMTAG_EVR}: name := "EVR";
when {RPMTAG_NVR}: name := "NVR";
when {RPMTAG_NEVR}: name := "NEVR";
when {RPMTAG_NEVRA}: name := "NEVRA";
when {RPMTAG_HEADERCOLOR}: name := "HEADERCOLOR";
when {RPMTAG_VERBOSE}: name := "VERBOSE";
when {RPMTAG_EPOCHNUM}: name := "EPOCHNUM";
when {RPMTAG_PREINFLAGS}: name := "PREINFLAGS";
when {RPMTAG_POSTINFLAGS}: name := "POSTINFLAGS";
when {RPMTAG_PREUNFLAGS}: name := "PREUNFLAGS";
when {RPMTAG_POSTUNFLAGS}: name := "POSTUNFLAGS";
when {RPMTAG_PRETRANSFLAGS}: name := "PRETRANSFLAGS";
when {RPMTAG_POSTTRANSFLAGS}: name := "POSTTRANSFLAGS";
when {RPMTAG_VERIFYSCRIPTFLAGS}: name := "VERIFYSCRIPTFLAGS";
when {RPMTAG_TRIGGERSCRIPTFLAGS}: name := "TRIGGERSCRIPTFLAGS";
when {RPMTAG_COLLECTIONS}: name := "COLLECTIONS";
when {RPMTAG_POLICYNAMES}: name := "POLICYNAMES";
when {RPMTAG_POLICYTYPES}: name := "POLICYTYPES";
when {RPMTAG_POLICYTYPESINDEXES}: name := "POLICYTYPESINDEXES";
when {RPMTAG_POLICYFLAGS}: name := "POLICYFLAGS";
when {RPMTAG_VCS}: name := "VCS";
when {RPMTAG_ORDERNAME}: name := "ORDERNAME";
when {RPMTAG_ORDERVERSION}: name := "ORDERVERSION";
when {RPMTAG_ORDERFLAGS}: name := "ORDERFLAGS";
when {RPMTAG_MSSFMANIFEST}: name := "MSSFMANIFEST";
when {RPMTAG_MSSFDOMAIN}: name := "MSSFDOMAIN";
when {RPMTAG_INSTFILENAMES}: name := "INSTFILENAMES";
when {RPMTAG_REQUIRENEVRS}: name := "REQUIRENEVRS";
when {RPMTAG_PROVIDENEVRS}: name := "PROVIDENEVRS";
when {RPMTAG_OBSOLETENEVRS}: name := "OBSOLETENEVRS";
when {RPMTAG_CONFLICTNEVRS}: name := "CONFLICTNEVRS";
when {RPMTAG_FILENLINKS}: name := "FILENLINKS";
when {RPMTAG_RECOMMENDNAME}: name := "RECOMMENDNAME";
when {RPMTAG_RECOMMENDVERSION}: name := "RECOMMENDVERSION";
when {RPMTAG_RECOMMENDFLAGS}: name := "RECOMMENDFLAGS";
when {RPMTAG_SUGGESTNAME}: name := "SUGGESTNAME";
when {RPMTAG_SUGGESTVERSION}: name := "SUGGESTVERSION";
when {RPMTAG_SUGGESTFLAGS}: name := "SUGGESTFLAGS";
when {RPMTAG_SUPPLEMENTNAME}: name := "SUPPLEMENTNAME";
when {RPMTAG_SUPPLEMENTVERSION}: name := "SUPPLEMENTVERSION";
when {RPMTAG_SUPPLEMENTFLAGS}: name := "SUPPLEMENTFLAGS";
when {RPMTAG_ENHANCENAME}: name := "ENHANCENAME";
when {RPMTAG_ENHANCEVERSION}: name := "ENHANCEVERSION";
when {RPMTAG_ENHANCEFLAGS}: name := "ENHANCEFLAGS";
when {RPMTAG_RECOMMENDNEVRS}: name := "RECOMMENDNEVRS";
when {RPMTAG_SUGGESTNEVRS}: name := "SUGGESTNEVRS";
when {RPMTAG_SUPPLEMENTNEVRS}: name := "SUPPLEMENTNEVRS";
when {RPMTAG_ENHANCENEVRS}: name := "ENHANCENEVRS";
when {RPMTAG_ENCODING}: name := "ENCODING";
when {RPMTAG_FILETRIGGERIN}: name := "FILETRIGGERIN";
when {RPMTAG_FILETRIGGERUN}: name := "FILETRIGGERUN";
when {RPMTAG_FILETRIGGERPOSTUN}: name := "FILETRIGGERPOSTUN";
when {RPMTAG_FILETRIGGERSCRIPTS}: name := "FILETRIGGERSCRIPTS";
when {RPMTAG_FILETRIGGERSCRIPTPROG}: name := "FILETRIGGERSCRIPTPROG";
when {RPMTAG_FILETRIGGERSCRIPTFLAGS}: name := "FILETRIGGERSCRIPTFLAGS";
when {RPMTAG_FILETRIGGERNAME}: name := "FILETRIGGERNAME";
when {RPMTAG_FILETRIGGERINDEX}: name := "FILETRIGGERINDEX";
when {RPMTAG_FILETRIGGERVERSION}: name := "FILETRIGGERVERSION";
when {RPMTAG_FILETRIGGERFLAGS}: name := "FILETRIGGERFLAGS";
when {RPMTAG_TRANSFILETRIGGERIN}: name := "TRANSFILETRIGGERIN";
when {RPMTAG_TRANSFILETRIGGERUN}: name := "TRANSFILETRIGGERUN";
when {RPMTAG_TRANSFILETRIGGERPOSTUN}: name := "TRANSFILETRIGGERPOSTUN";
when {RPMTAG_TRANSFILETRIGGERSCRIPTS}: name := "TRANSFILETRIGGERSCRIPTS";
when {RPMTAG_TRANSFILETRIGGERSCRIPTPROG}: name := "TRANSFILETRIGGERSCRIPTPROG";
when {RPMTAG_TRANSFILETRIGGERSCRIPTFLAGS}: name := "TRANSFILETRIGGERSCRIPTFLAGS";
when {RPMTAG_TRANSFILETRIGGERNAME}: name := "TRANSFILETRIGGERNAME";
when {RPMTAG_TRANSFILETRIGGERINDEX}: name := "TRANSFILETRIGGERINDEX";
when {RPMTAG_TRANSFILETRIGGERVERSION}: name := "TRANSFILETRIGGERVERSION";
when {RPMTAG_TRANSFILETRIGGERFLAGS}: name := "TRANSFILETRIGGERFLAGS";
when {RPMTAG_REMOVEPATHPOSTFIXES}: name := "REMOVEPATHPOSTFIXES";
when {RPMTAG_FILETRIGGERPRIORITIES}: name := "FILETRIGGERPRIORITIES";
when {RPMTAG_TRANSFILETRIGGERPRIORITIES}: name := "TRANSFILETRIGGERPRIORITIES";
when {RPMTAG_FILETRIGGERCONDS}: name := "FILETRIGGERCONDS";
when {RPMTAG_FILETRIGGERTYPE}: name := "FILETRIGGERTYPE";
when {RPMTAG_TRANSFILETRIGGERCONDS}: name := "TRANSFILETRIGGERCONDS";
when {RPMTAG_TRANSFILETRIGGERTYPE}: name := "TRANSFILETRIGGERTYPE";
when {RPMTAG_FILESIGNATURES}: name := "FILESIGNATURES";
when {RPMTAG_FILESIGNATURELENGTH}: name := "FILESIGNATURELENGTH";
when {RPMTAG_PAYLOADDIGEST}: name := "PAYLOADDIGEST";
when {RPMTAG_PAYLOADDIGESTALGO}: name := "PAYLOADDIGESTALGO";
when {RPMTAG_AUTOINSTALLED}: name := "AUTOINSTALLED";
when {RPMTAG_IDENTITY}: name := "IDENTITY";
when {RPMTAG_MODULARITYLABEL}: name := "MODULARITYLABEL";
when {RPMTAG_PAYLOADDIGESTALT}: name := "PAYLOADDIGESTALT";
when {RPMTAG_ARCHSUFFIX}: name := "ARCHSUFFIX";
when {RPMTAG_SPEC}: name := "SPEC";
otherwise: name := "tag " <& tag;
end case;
end func;
const func string: rpmDependencyFlagsString (in integer: flags) is func
result
var string: flagsString is "";
local
var integer: bitNum is 0;
begin
for bitNum range 0 to 28 do
if bin32(flags) & (bin32(1) << bitNum) <> bin32(0) then
if flagsString <> "" then
flagsString &:= ", ";
end if;
case integer(bin32(1) << bitNum) of
when {RPMSENSE_LESS}: flagsString &:= "LESS";
when {RPMSENSE_GREATER}: flagsString &:= "GREATER";
when {RPMSENSE_EQUAL}: flagsString &:= "EQUAL";
when {RPMSENSE_POSTTRANS}: flagsString &:= "POSTTRANS";
when {RPMSENSE_PREREQ}: flagsString &:= "PREREQ";
when {RPMSENSE_PRETRANS}: flagsString &:= "PRETRANS";
when {RPMSENSE_INTERP}: flagsString &:= "INTERP";
when {RPMSENSE_SCRIPT_PRE}: flagsString &:= "SCRIPT_PRE";
when {RPMSENSE_SCRIPT_POST}: flagsString &:= "SCRIPT_POST";
when {RPMSENSE_SCRIPT_PREUN}: flagsString &:= "SCRIPT_PREUN";
when {RPMSENSE_SCRIPT_POSTUN}: flagsString &:= "SCRIPT_POSTUN";
when {RPMSENSE_SCRIPT_VERIFY}: flagsString &:= "SCRIPT_VERIFY";
when {RPMSENSE_FIND_REQUIRES}: flagsString &:= "FIND_REQUIRES";
when {RPMSENSE_FIND_PROVIDES}: flagsString &:= "FIND_PROVIDES";
when {RPMSENSE_TRIGGERIN}: flagsString &:= "TRIGGERIN";
when {RPMSENSE_TRIGGERUN}: flagsString &:= "TRIGGERUN";
when {RPMSENSE_TRIGGERPOSTUN}: flagsString &:= "TRIGGERPOSTUN";
when {RPMSENSE_MISSINGOK}: flagsString &:= "MISSINGOK";
when {RPMSENSE_RPMLIB}: flagsString &:= "RPMLIB";
when {RPMSENSE_TRIGGERPREIN}: flagsString &:= "TRIGGERPREIN";
when {RPMSENSE_KEYRING}: flagsString &:= "KEYRING";
when {RPMSENSE_CONFIG}: flagsString &:= "CONFIG";
otherwise: flagsString &:= "UNUSED_" <& bitNum;
end case;
end if;
end for;
flagsString &:= " " <& flags radix 16;
end func;
const proc: show (in rpmLead: lead) is func
begin
if lead.magic = RPM_LEAD_MAGIC then
writeln("Version " <& lead.majorVersion <& "." <& lead.minorVersion);
writeln("Type: " <& ord(lead.packageType));
writeln("Arch: " <& lead.arch);
writeln("Name: " <& literal(lead.name));
writeln("Os: " <& lead.os);
writeln("Signature version: " <& lead.sig);
else
writeln(" *** Rpm lead magic not okay.");
end if;
end func;
const proc: show (in rpmHeader: header) is func
local
var integer: idx is 0;
begin
if header.magic = RPM_HEADER_MAGIC then
writeln("Header version: " <& header.version);
writeln("IndexCount: " <& header.indexCount);
writeln("StoreSize: " <& header.storeSize);
else
writeln(" *** Rpm header magic not okay.");
end if;
end func;
const proc: show (in rpmIndexEntry: indexEntry) is func
local
var string: striValue is "";
begin
write("Tag: " <& indexEntry.tag);
write(" type: " <& indexEntry.dataType);
write(" offset: " <& indexEntry.offset);
writeln(" count: " <& indexEntry.count);
end func;
const func string: getUtf8z (in string: stri, inout integer: currPos) is func
result
var string: resultStri is "";
local
var string: utf8Stri is "";
begin
utf8Stri := getAsciiz(stri, currPos);
block
resultStri := fromUtf8(utf8Stri);
exception
catch RANGE_ERROR:
resultStri := utf8Stri;
end block;
end func;
const func string: getStriValue (in string: store,
in rpmIndexEntry: indexEntry) is func
result
var string: data is "";
local
var integer: index is 0;
var integer: currPos is 0;
begin
case indexEntry.dataType of
when {RPM_NULL_TYPE}:
data := "";
when {RPM_CHAR_TYPE}:
data := store[succ(indexEntry.offset) fixLen indexEntry.count];
when {RPM_INT8_TYPE}:
data := store[succ(indexEntry.offset) fixLen indexEntry.count];
when {RPM_INT16_TYPE}:
data := store[succ(indexEntry.offset) fixLen 2 * indexEntry.count];
when {RPM_INT32_TYPE}:
data := store[succ(indexEntry.offset) fixLen 4 * indexEntry.count];
when {RPM_INT64_TYPE}:
data := store[succ(indexEntry.offset) fixLen 8 * indexEntry.count];
when {RPM_STRING_TYPE}:
currPos := succ(indexEntry.offset);
data := getAsciiz(store, currPos);
when {RPM_BIN_TYPE}:
data := store[succ(indexEntry.offset) fixLen indexEntry.count];
when {RPM_STRING_ARRAY_TYPE, RPM_I18NSTRING_TYPE}:
currPos := succ(indexEntry.offset);
for index range 1 to indexEntry.count do
data &:= getAsciiz(store, currPos) & "\0;";
end for;
if data <> "" then
data := data[.. pred(length(data))];
end if;
end case;
end func;
const func array string: getArrayValue (in string: store,
in rpmIndexEntry: indexEntry) is func
result
var array string: arrayValue is 0 times "";
local
var integer: index is 0;
var integer: currPos is 0;
begin
case indexEntry.dataType of
when {RPM_STRING_ARRAY_TYPE, RPM_I18NSTRING_TYPE}:
currPos := succ(indexEntry.offset);
for index range 1 to indexEntry.count do
arrayValue &:= getAsciiz(store, currPos);
end for;
end case;
end func;
const func integer: getIntValue (in string: store,
in rpmIndexEntry: indexEntry) is func
result
var integer: number is 0;
begin
case indexEntry.dataType of
when {RPM_INT8_TYPE}:
number := bytes2Int(store[succ(indexEntry.offset) fixLen 1], UNSIGNED, BE);
when {RPM_INT16_TYPE}:
number := bytes2Int(store[succ(indexEntry.offset) fixLen 2], UNSIGNED, BE);
when {RPM_INT32_TYPE}:
number := bytes2Int(store[succ(indexEntry.offset) fixLen 4], UNSIGNED, BE);
when {RPM_INT64_TYPE}:
number := bytes2Int(store[succ(indexEntry.offset) fixLen 8], UNSIGNED, BE);
end case;
end func;
const proc: initLead (inout rpmLead: lead) is func
begin
lead.magic := RPM_LEAD_MAGIC;
lead.majorVersion := 3;
lead.minorVersion := 0;
lead.packageType := RPM_SOURCE_PACKAGE;
lead.arch := 1;
lead.name := "";
lead.os := 1;
lead.sig := 5;
end func;
const proc: readLead (inout file: rpmFile, inout rpmLead: lead) is func
local
var string: leadStri is "";
begin
leadStri := gets(rpmFile, RPM_LEAD_SIZE);
if length(leadStri) = RPM_LEAD_SIZE then
lead.magic := leadStri[ 1 fixLen 4];
lead.majorVersion := bytes2Int(leadStri[ 5 fixLen 1], UNSIGNED, BE);
lead.minorVersion := bytes2Int(leadStri[ 6 fixLen 1], UNSIGNED, BE);
lead.packageType := rpmPackageType conv bytes2Int(leadStri[ 7 fixLen 2], UNSIGNED, BE);
lead.arch := bytes2Int(leadStri[ 9 fixLen 2], UNSIGNED, BE);
lead.name := fromAsciiz(leadStri[11 fixLen 66], 1);
lead.os := bytes2Int(leadStri[77 fixLen 2], UNSIGNED, BE);
lead.sig := bytes2Int(leadStri[79 fixLen 2], UNSIGNED, BE);
end if;
end func;
const func string: str (in rpmLead: lead) is
return lead.magic <&
bytes( lead.majorVersion, UNSIGNED, BE, 1) <&
bytes( lead.minorVersion, UNSIGNED, BE, 1) <&
bytes(ord(lead.packageType), UNSIGNED, BE, 2) <&
bytes( lead.arch, UNSIGNED, BE, 2) <&
lead.name[.. 66] <&
length( lead.name) < 66 ? "\0;" mult 66 - length(lead.name) : "" <&
bytes( lead.os, UNSIGNED, BE, 2) <&
bytes( lead.sig, UNSIGNED, BE, 2) <&
"\0;" mult 16;
const proc: writeLead (inout file: outFile, inout rpmLead: lead) is func
begin
write(outFile, str(lead));
end func;
const proc: readHeader (inout file: rpmFile, inout rpmHeader: header) is func
local
var string: headerStri is "";
begin
headerStri := gets(rpmFile, RPM_HEADER_SIZE);
if length(headerStri) = RPM_HEADER_SIZE then
header.magic := headerStri[ 1 fixLen 3];
header.version := bytes2Int(headerStri[ 4 fixLen 1], UNSIGNED, BE);
header.reservedBytes := headerStri[ 5 fixLen 4];
header.indexCount := bytes2Int(headerStri[ 9 fixLen 4], UNSIGNED, BE);
header.storeSize := bytes2Int(headerStri[13 fixLen 4], UNSIGNED, BE);
end if;
end func;
const func string: str (in rpmHeader: header) is
return header.magic <&
bytes(header.version, UNSIGNED, BE, 1) <&
header.reservedBytes <&
bytes(header.indexCount, UNSIGNED, BE, 4) <&
bytes(header.storeSize, UNSIGNED, BE, 4);
const func string: str (in rpmIndexEntry: indexEntry) is
return bytes(indexEntry.tag, UNSIGNED, BE, 4) <&
bytes(indexEntry.dataType, UNSIGNED, BE, 4) <&
bytes(indexEntry.offset, SIGNED, BE, 4) <&
bytes(indexEntry.count, UNSIGNED, BE, 4);
const type: rpmDependency is new struct
var string: name is "";
var string: version is "";
var integer: flags is 0;
end struct;
const func boolean: (in rpmDependency: depend1) = (in rpmDependency: depend2) is
return depend1.name = depend2.name and
depend1.version = depend2.version and
depend1.flags = depend2.flags;
const func boolean: (in rpmDependency: depend1) <> (in rpmDependency: depend2) is
return depend1.name <> depend2.name or
depend1.version <> depend2.version or
depend1.flags <> depend2.flags;
const func integer: compare (in rpmDependency: depend1, in rpmDependency: depend2) is func
result
var integer: signumValue is 0;
begin
signumValue := compare(depend1.name, depend2.name);
if signumValue = 0 then
signumValue := compare(depend1.version, depend2.version);
if signumValue = 0 then
signumValue := compare(depend1.flags, depend2.flags);
end if;
end if;
end func;
const func integer: findDependency (in array rpmDependency: dependencies, in rpmDependency: dependency) is func
result
var integer: indexFound is 0;
local
var integer: index is 0;
begin
for key index range dependencies until indexFound <> 0 do
if dependencies[index] = dependency then
indexFound := index;
end if;
end for;
end func;
const proc: addDependency (inout array rpmDependency: dependencies, in rpmDependency: dependency) is func
local
var integer: index is 0;
var boolean: found is FALSE;
begin
for key index range dependencies until found do
found := dependencies[index] = dependency;
end for;
if not found then
dependencies &:= dependency;
end if;
end func;
const type: rpmCatalogEntry is new struct
var integer: fileSize is 0;
var integer: mode is 0;
var integer: uid is 0;
var integer: gid is 0;
var integer: rdev is 0;
var integer: mtime is 0;
var string: digest is "";
var string: linkTo is "";
var integer: flags is 0;
var string: userName is "";
var string: groupName is "";
var integer: verifyFlags is 0;
var integer: device is 0;
var integer: inode is 0;
var string: lang is "";
var integer: dirIndex is 0;
var string: baseName is "";
var integer: color is 0;
var integer: fileClass is 0;
var integer: dependX is 0;
var integer: dependN is 0;
var boolean: allDataPresent is FALSE;
var string: filePath is "";
var integer: fileNumber is 0;
var array rpmDependency: dependencies is 0 times rpmDependency.value;
var boolean: dirty is FALSE;
end struct;
const proc: write (in rpmCatalogEntry: catalogEntry) is func
begin
writeln("fileSize: " <& catalogEntry.fileSize);
writeln("mode: " <& catalogEntry.mode);
writeln("uid: " <& catalogEntry.uid);
writeln("gid: " <& catalogEntry.gid);
writeln("rdev: " <& catalogEntry.rdev);
writeln("mtime: " <& catalogEntry.mtime);
writeln("digest: " <& catalogEntry.digest);
writeln("linkTo: " <& catalogEntry.linkTo);
writeln("flags: " <& catalogEntry.flags);
writeln("userName: " <& catalogEntry.userName);
writeln("groupName: " <& catalogEntry.groupName);
writeln("verifyFlags: " <& catalogEntry.verifyFlags);
writeln("device: " <& catalogEntry.device);
writeln("inode: " <& catalogEntry.inode);
writeln("lang: " <& catalogEntry.lang);
writeln("dirIndex: " <& catalogEntry.dirIndex);
writeln("baseName: " <& catalogEntry.baseName);
writeln("color: " <& catalogEntry.color);
writeln("fileClass: " <& catalogEntry.fileClass);
writeln("dependX: " <& catalogEntry.dependX);
writeln("dependN: " <& catalogEntry.dependN);
writeln("allDataPresent: " <& catalogEntry.allDataPresent);
writeln("filePath: " <& catalogEntry.filePath);
writeln("fileNumber: " <& catalogEntry.fileNumber);
writeln("dirty: " <& catalogEntry.dirty);
end func;
const type: rpmCatalogType is hash [string] rpmCatalogEntry;
const type: rpmSection is new struct
var rpmHeader: head is rpmHeader.value;
var rpmTagMap: tagMap is rpmTagMap.value;
var string: indexData is "";
var string: store is "";
end struct;
const type: rpmArchive is sub emptyFileSys struct
var file: rpmFile is STD_NULL;
var rpmLead: lead is rpmLead.value;
var rpmSection: signature is rpmSection.value;
var rpmSection: header is rpmSection.value;
var integer: payloadPos is 0;
var integer: maximumInode is 0;
var boolean: useLongFileSizes is FALSE;
var archiveRegisterType: register is archiveRegisterType.value;
var rpmCatalogType: catalog is rpmCatalogType.value;
var integer: fileDigestAlgo is RPM_DIGESTALGO_MD5;
var array string: dirNames is 0 times "";
var array string: classDict is 0 times "";
var array rpmDependency: provided is 0 times rpmDependency.value;
var array rpmDependency: required is 0 times rpmDependency.value;
var array integer: dependsDict is 0 times 0;
var file: payloadFile is STD_NULL;
var fileSys: archive is fileSys.value;
var boolean: dirty is FALSE;
end struct;
const func array string: getStringArray (in rpmArchive: rpm, in integer: tag) is func
result
var array string: stringArray is 0 times "";
local
var rpmIndexEntry: stringArrayIndex is rpmIndexEntry.value;
var integer: stringPos is 0;
var integer: index is 0;
begin
if tag in rpm.header.tagMap then
stringArrayIndex := rpm.header.tagMap[tag];
stringPos := succ(stringArrayIndex.offset);
stringArray := stringArrayIndex.count times "";
for index range 1 to stringArrayIndex.count do
stringArray[index] := getUtf8z(rpm.header.store, stringPos);
end for;
end if;
end func;
const proc: createMinimumOfCatalog (inout rpmArchive: rpm) is func
local
var integer: oldFileNamePos is 0;
var integer: dirIndexPos is 0;
var integer: baseNamePos is 0;
var integer: digestPos is 0;
var integer: linkToPos is 0;
var integer: userNamePos is 0;
var integer: groupNamePos is 0;
var integer: inodePos is 0;
var integer: langPos is 0;
var integer: numberOfFiles is 0;
var rpmCatalogEntry: catalogEntry is rpmCatalogEntry.value;
var integer: fileNumber is 0;
begin
if RPMTAG_OLDFILENAMES in rpm.header.tagMap then
oldFileNamePos := succ(rpm.header.tagMap[RPMTAG_OLDFILENAMES].offset);
numberOfFiles := rpm.header.tagMap[RPMTAG_OLDFILENAMES].count;
else
rpm.dirNames := getStringArray(rpm, RPMTAG_DIRNAMES);
dirIndexPos := succ(rpm.header.tagMap[RPMTAG_DIRINDEXES].offset);
baseNamePos := succ(rpm.header.tagMap[RPMTAG_BASENAMES].offset);
numberOfFiles := rpm.header.tagMap[RPMTAG_BASENAMES].count;
end if;
digestPos := succ(rpm.header.tagMap[RPMTAG_FILEDIGESTS].offset);
linkToPos := succ(rpm.header.tagMap[RPMTAG_FILELINKTOS].offset);
userNamePos := succ(rpm.header.tagMap[RPMTAG_FILEUSERNAME].offset);
groupNamePos := succ(rpm.header.tagMap[RPMTAG_FILEGROUPNAME].offset);
inodePos := succ(rpm.header.tagMap[RPMTAG_FILEINODES].offset);
langPos := succ(rpm.header.tagMap[RPMTAG_FILELANGS].offset);
for fileNumber range 1 to numberOfFiles do
if oldFileNamePos <> 0 then
catalogEntry.filePath := getUtf8z(rpm.header.store, oldFileNamePos);
else
catalogEntry.dirIndex := bytes2Int(
rpm.header.store[dirIndexPos fixLen 4], UNSIGNED, BE);
dirIndexPos +:= 4;
catalogEntry.baseName := getUtf8z(rpm.header.store, baseNamePos);
catalogEntry.filePath := rpm.dirNames[succ(catalogEntry.dirIndex)];
catalogEntry.filePath &:= catalogEntry.baseName;
end if;
catalogEntry.digest := getAsciiz(rpm.header.store, digestPos);
catalogEntry.linkTo := getUtf8z(rpm.header.store, linkToPos);
catalogEntry.userName := getAsciiz(rpm.header.store, userNamePos);
catalogEntry.groupName := getAsciiz(rpm.header.store, groupNamePos);
catalogEntry.inode := bytes2Int(
rpm.header.store[inodePos fixLen 4], UNSIGNED, BE);
inodePos +:= 4;
rpm.maximumInode := max(rpm.maximumInode, catalogEntry.inode);
catalogEntry.lang := getAsciiz(rpm.header.store, langPos);
catalogEntry.fileNumber := fileNumber;
rpm.catalog @:= [catalogEntry.filePath] catalogEntry;
rpm.register @:= [catalogEntry.filePath] fileNumber;
end for;
end func;
const func integer: getInt (in rpmArchive: rpm, in integer: tag, in integer: index) is func
result
var integer: number is 0;
local
var rpmIndexEntry: indexEntry is rpmIndexEntry.value;
var integer: offset is 0;
var integer: pos is 0;
begin
if tag in rpm.header.tagMap then
indexEntry := rpm.header.tagMap[tag];
if index <= indexEntry.count then
offset := succ(indexEntry.offset);
case indexEntry.dataType of
when {RPM_INT8_TYPE}:
pos := offset + pred(index);
number := bytes2Int(rpm.header.store[pos fixLen 1], UNSIGNED, BE);
when {RPM_INT16_TYPE}:
pos := offset + pred(index) * 2;
number := bytes2Int(rpm.header.store[pos fixLen 2], UNSIGNED, BE);
when {RPM_INT32_TYPE}:
pos := offset + pred(index) * 4;
number := bytes2Int(rpm.header.store[pos fixLen 4], UNSIGNED, BE);
when {RPM_INT64_TYPE}:
pos := offset + pred(index) * 8;
number := bytes2Int(rpm.header.store[pos fixLen 8], UNSIGNED, BE);
otherwise:
raise RANGE_ERROR;
end case;
else
raise RANGE_ERROR;
end if;
end if;
end func;
const proc: readCatalogEntry (inout rpmArchive: rpm, inout rpmCatalogEntry: catalogEntry) is func
local
var integer: fileNumber is 0;
begin
fileNumber := catalogEntry.fileNumber;
if fileNumber = 0 then
raise RANGE_ERROR;
else
if rpm.useLongFileSizes then
catalogEntry.fileSize := getInt(rpm, RPMTAG_LONGFILESIZES, fileNumber);
else
catalogEntry.fileSize := getInt(rpm, RPMTAG_FILESIZES, fileNumber);
end if;
catalogEntry.mode := getInt(rpm, RPMTAG_FILEMODES, fileNumber);
catalogEntry.uid := getInt(rpm, RPMTAG_FILEUIDS, fileNumber);
catalogEntry.gid := getInt(rpm, RPMTAG_FILEGIDS, fileNumber);
catalogEntry.rdev := getInt(rpm, RPMTAG_FILERDEVS, fileNumber);
catalogEntry.mtime := getInt(rpm, RPMTAG_FILEMTIMES, fileNumber);
catalogEntry.flags := getInt(rpm, RPMTAG_FILEFLAGS, fileNumber);
catalogEntry.verifyFlags := getInt(rpm, RPMTAG_FILEVERIFYFLAGS, fileNumber);
catalogEntry.device := getInt(rpm, RPMTAG_FILEDEVICES, fileNumber);
catalogEntry.color := getInt(rpm, RPMTAG_FILECOLORS, fileNumber);
catalogEntry.fileClass := getInt(rpm, RPMTAG_FILECLASS, fileNumber);
catalogEntry.dependX := getInt(rpm, RPMTAG_FILEDEPENDSX, fileNumber);
catalogEntry.dependN := getInt(rpm, RPMTAG_FILEDEPENDSN, fileNumber);
catalogEntry.allDataPresent := TRUE;
rpm.catalog @:= [catalogEntry.filePath] catalogEntry;
end if;
end func;
const proc: updateIndexEntry (inout rpmSection: section, in integer: tag,
in integer: dataType, in integer: value) is func
local
var rpmIndexEntry: indexEntry is rpmIndexEntry.value;
begin
if tag in section.tagMap then
indexEntry := section.tagMap[tag];
else
indexEntry.tag := tag;
indexEntry.dataType := dataType;
indexEntry.count := 1;
end if;
case indexEntry.dataType of
when {RPM_INT8_TYPE}:
indexEntry.striValue := bytes(value, UNSIGNED, BE, 1);
when {RPM_INT16_TYPE}:
indexEntry.striValue := bytes(value, UNSIGNED, BE, 2);
when {RPM_INT32_TYPE}:
indexEntry.striValue := bytes(value, UNSIGNED, BE, 4);
when {RPM_INT64_TYPE}:
indexEntry.striValue := bytes(value, UNSIGNED, BE, 8);
otherwise:
raise RANGE_ERROR;
end case;
section.tagMap @:= [tag] indexEntry;
end func;
const proc: updateIndexEntry (inout rpmSection: section, in integer: tag,
in integer: dataType, in string: value) is func
local
var rpmIndexEntry: indexEntry is rpmIndexEntry.value;
begin
if tag in section.tagMap then
indexEntry := section.tagMap[tag];
else
indexEntry.tag := tag;
indexEntry.dataType := dataType;
end if;
case indexEntry.dataType of
when {RPM_STRING_TYPE}:
indexEntry.count := 1;
indexEntry.striValue := value;
when {RPM_BIN_TYPE}:
indexEntry.count := length(value);
indexEntry.striValue := value;
when {RPM_STRING_ARRAY_TYPE, RPM_I18NSTRING_TYPE}:
indexEntry.arrayValue := split(value, '\0;');
indexEntry.count := length(indexEntry.arrayValue);
indexEntry.striValue := value;
otherwise:
raise RANGE_ERROR;
end case;
section.tagMap @:= [tag] indexEntry;
end func;
const proc: updateIndexEntry (inout rpmSection: section, in integer: tag,
in integer: dataType, in array string: value) is func
local
var rpmIndexEntry: indexEntry is rpmIndexEntry.value;
var string: stri is "";
begin
if tag in section.tagMap then
indexEntry := section.tagMap[tag];
else
indexEntry.tag := tag;
indexEntry.dataType := dataType;
indexEntry.count := length(value);
end if;
for stri range value do
indexEntry.arrayValue &:= toUtf8(stri);
end for;
section.tagMap @:= [tag] indexEntry;
end func;
const proc: updateIndexEntry (inout rpmArchive: rpm, in integer: tag,
in integer: dataType, in integer: fileNumber, in integer: value) is func
local
var rpmIndexEntry: indexEntry is rpmIndexEntry.value;
var integer: dataSize is 0;
var string: data is "";
begin
if tag in rpm.header.tagMap then
indexEntry := rpm.header.tagMap[tag];
else
indexEntry.tag := tag;
indexEntry.dataType := dataType;
end if;
case indexEntry.dataType of
when {RPM_INT8_TYPE}:
dataSize := 1;
data := bytes(value, UNSIGNED, BE, 1);
when {RPM_INT16_TYPE}:
dataSize := 2;
data := bytes(value, UNSIGNED, BE, 2);
when {RPM_INT32_TYPE}:
dataSize := 4;
data := bytes(value, UNSIGNED, BE, 4);
when {RPM_INT64_TYPE}:
dataSize := 8;
data := bytes(value, UNSIGNED, BE, 8);
otherwise:
raise RANGE_ERROR;
end case;
if fileNumber > indexEntry.count then
indexEntry.striValue &:= "\0;" mult (fileNumber - indexEntry.count) * dataSize;
indexEntry.count := fileNumber;
end if;
indexEntry.striValue @:= [succ(pred(fileNumber) * dataSize)] data;
rpm.header.tagMap @:= [tag] indexEntry;
end func;
const proc: updateIndexEntry (inout rpmArchive: rpm, in integer: tag,
in integer: dataType, in integer: fileNumber, in string: value) is func
local
var rpmIndexEntry: indexEntry is rpmIndexEntry.value;
var string: data is "";
begin
if tag in rpm.header.tagMap then
indexEntry := rpm.header.tagMap[tag];
else
indexEntry.tag := tag;
indexEntry.dataType := dataType;
end if;
case indexEntry.dataType of
when {RPM_STRING_ARRAY_TYPE, RPM_I18NSTRING_TYPE}:
data := value;
otherwise:
raise RANGE_ERROR;
end case;
if fileNumber > indexEntry.count then
indexEntry.arrayValue &:= (fileNumber - indexEntry.count) times "";
indexEntry.count := fileNumber;
end if;
indexEntry.arrayValue[fileNumber] := data;
rpm.header.tagMap @:= [tag] indexEntry;
end func;
const proc: updateProvisions (inout rpmArchive: rpm) is func
local
var rpmDependency: dependency is rpmDependency.value;
var integer: index is 0;
var array string: provideName is 0 times "";
var array string: provideVersion is 0 times "";
begin
for dependency key index range rpm.provided do
provideName &:= dependency.name;
provideVersion &:= dependency.version;
updateIndexEntry(rpm, RPMTAG_PROVIDEFLAGS, RPM_INT32_TYPE, index, dependency.flags);
end for;
if length(provideName) <> 0 then
updateIndexEntry(rpm.header, RPMTAG_PROVIDENAME, RPM_STRING_ARRAY_TYPE, provideName);
updateIndexEntry(rpm.header, RPMTAG_PROVIDEVERSION, RPM_STRING_ARRAY_TYPE, provideVersion);
end if;
end func;
const proc: updateRequirements (inout rpmArchive: rpm) is func
local
var rpmDependency: dependency is rpmDependency.value;
var integer: index is 0;
var array string: requireName is 0 times "";
var array string: requireVersion is 0 times "";
begin
for dependency key index range rpm.required do
requireName &:= dependency.name;
requireVersion &:= dependency.version;
updateIndexEntry(rpm, RPMTAG_REQUIREFLAGS, RPM_INT32_TYPE, index, dependency.flags);
end for;
if length(requireName) <> 0 then
updateIndexEntry(rpm.header, RPMTAG_REQUIRENAME, RPM_STRING_ARRAY_TYPE, requireName);
updateIndexEntry(rpm.header, RPMTAG_REQUIREVERSION, RPM_STRING_ARRAY_TYPE, requireVersion);
end if;
end func;
const proc: updateDependencies (inout rpmArchive: rpm) is func
local
const integer: requiresFlag is bytes2Int("R\0;\0;\0;", UNSIGNED, BE);
var rpmCatalogEntry: catalogEntry is rpmCatalogEntry.value;
var rpmDependency: dependency is rpmDependency.value;
var integer: dependencyIndex is 0;
var integer: dependsDictEntry is 0;
begin
for catalogEntry range rpm.catalog do
if catalogEntry.dirty then
if length(catalogEntry.dependencies) <> 0 then
rpm.catalog[catalogEntry.filePath].dependX := length(rpm.dependsDict);
rpm.catalog[catalogEntry.filePath].dependN := length(catalogEntry.dependencies);
for dependency range catalogEntry.dependencies do
dependencyIndex := findDependency(rpm.required, dependency);
if dependencyIndex <> 0 then
dependsDictEntry := requiresFlag + pred(dependencyIndex);
rpm.dependsDict &:= dependsDictEntry;
updateIndexEntry(rpm, RPMTAG_DEPENDSDICT, RPM_INT32_TYPE,
length(rpm.dependsDict), dependsDictEntry);
else
raise RANGE_ERROR;
end if;
end for;
end if;
end if;
end for;
end func;
const proc: updateHeader (inout rpmArchive: rpm, in rpmCatalogEntry: catalogEntry) is func
begin
if rpm.useLongFileSizes then
updateIndexEntry(rpm, RPMTAG_LONGFILESIZES, RPM_INT64_TYPE,
catalogEntry.fileNumber, catalogEntry.fileSize);
else
updateIndexEntry(rpm, RPMTAG_FILESIZES, RPM_INT32_TYPE,
catalogEntry.fileNumber, catalogEntry.fileSize);
end if;
updateIndexEntry(rpm, RPMTAG_FILEMODES, RPM_INT16_TYPE,
catalogEntry.fileNumber, catalogEntry.mode);
updateIndexEntry(rpm, RPMTAG_FILERDEVS, RPM_INT16_TYPE,
catalogEntry.fileNumber, catalogEntry.rdev);
updateIndexEntry(rpm, RPMTAG_FILEMTIMES, RPM_INT32_TYPE,
catalogEntry.fileNumber, catalogEntry.mtime);
updateIndexEntry(rpm, RPMTAG_FILEDIGESTS, RPM_STRING_ARRAY_TYPE,
catalogEntry.fileNumber, catalogEntry.digest);
updateIndexEntry(rpm, RPMTAG_FILELINKTOS, RPM_STRING_ARRAY_TYPE,
catalogEntry.fileNumber, toUtf8(catalogEntry.linkTo));
updateIndexEntry(rpm, RPMTAG_FILEFLAGS, RPM_INT32_TYPE,
catalogEntry.fileNumber, catalogEntry.flags);
updateIndexEntry(rpm, RPMTAG_FILEUSERNAME, RPM_STRING_ARRAY_TYPE,
catalogEntry.fileNumber, catalogEntry.userName);
updateIndexEntry(rpm, RPMTAG_FILEGROUPNAME, RPM_STRING_ARRAY_TYPE,
catalogEntry.fileNumber, catalogEntry.groupName);
updateIndexEntry(rpm, RPMTAG_FILEVERIFYFLAGS, RPM_INT32_TYPE,
catalogEntry.fileNumber, catalogEntry.verifyFlags);
updateIndexEntry(rpm, RPMTAG_FILEDEVICES, RPM_INT32_TYPE,
catalogEntry.fileNumber, catalogEntry.device);
updateIndexEntry(rpm, RPMTAG_FILEINODES, RPM_INT32_TYPE,
catalogEntry.fileNumber, catalogEntry.inode);
updateIndexEntry(rpm, RPMTAG_FILELANGS, RPM_STRING_ARRAY_TYPE,
catalogEntry.fileNumber, catalogEntry.lang);
updateIndexEntry(rpm, RPMTAG_DIRINDEXES, RPM_INT32_TYPE,
catalogEntry.fileNumber, catalogEntry.dirIndex);
updateIndexEntry(rpm, RPMTAG_BASENAMES, RPM_STRING_ARRAY_TYPE,
catalogEntry.fileNumber, toUtf8(catalogEntry.baseName));
updateIndexEntry(rpm, RPMTAG_FILECOLORS, RPM_INT32_TYPE,
catalogEntry.fileNumber, catalogEntry.color);
updateIndexEntry(rpm, RPMTAG_FILECLASS, RPM_INT32_TYPE,
catalogEntry.fileNumber, catalogEntry.fileClass);
if length(rpm.dependsDict) <> 0 then
updateIndexEntry(rpm, RPMTAG_FILEDEPENDSX, RPM_INT32_TYPE,
catalogEntry.fileNumber, catalogEntry.dependX);
updateIndexEntry(rpm, RPMTAG_FILEDEPENDSN, RPM_INT32_TYPE,
catalogEntry.fileNumber, catalogEntry.dependN);
end if;
end func;
const proc: updateHeader (inout rpmArchive: rpm) is func
local
var integer: fileNumber is 0;
var rpmCatalogEntry: catalogEntry is rpmCatalogEntry.value;
begin
if rpm.useLongFileSizes and RPMTAG_FILESIZES in rpm.header.tagMap then
for fileNumber range 1 to rpm.header.tagMap[RPMTAG_FILESIZES].count do
updateIndexEntry(rpm, RPMTAG_LONGFILESIZES, RPM_INT64_TYPE, fileNumber,
getInt(rpm, RPMTAG_FILESIZES, fileNumber));
end for;
excl(rpm.header.tagMap, RPMTAG_FILESIZES);
end if;
for catalogEntry range rpm.catalog do
if catalogEntry.dirty then
updateHeader(rpm, catalogEntry);
end if;
end for;
end func;
const proc: update (inout rpmArchive: rpm, RPMTAG_SIZE) is func
local
var rpmCatalogEntry: catalogEntry is rpmCatalogEntry.value;
var integer: sumOfRegularFileSizes is 0;
begin
for catalogEntry range rpm.catalog do
case bin32(catalogEntry.mode) & MODE_FILE_TYPE_MASK of
when {MODE_FILE_REGULAR, MODE_FILE_SYMLINK}:
sumOfRegularFileSizes +:= catalogEntry.fileSize;
end case;
end for;
if sumOfRegularFileSizes >= 2 ** 32 then
updateIndexEntry(rpm.header, RPMTAG_LONGSIZE, RPM_INT64_TYPE, sumOfRegularFileSizes);
else
updateIndexEntry(rpm.header, RPMTAG_SIZE, RPM_INT32_TYPE, sumOfRegularFileSizes);
end if;
end func;
const func boolean: isDirty (in rpmArchive: rpm) is func
result
var boolean: isDirty is FALSE;
local
var rpmCatalogEntry: catalogEntry is rpmCatalogEntry.value;
begin
if rpm.dirty then
isDirty := TRUE;
else
for catalogEntry range rpm.catalog do
if catalogEntry.dirty then
isDirty := TRUE;
end if;
end for;
end if;
end func;
const proc: fillTagMap (in string: indexData, inout rpmTagMap: tagMap) is func
local
var integer: pos is 1;
var rpmIndexEntry: indexEntry is rpmIndexEntry.value;
begin
for pos range 1 to length(indexData) step 16 do
indexEntry.tag := bytes2Int(indexData[pos fixLen 4], UNSIGNED, BE);
indexEntry.dataType := bytes2Int(indexData[pos + 4 fixLen 4], UNSIGNED, BE);
indexEntry.offset := bytes2Int(indexData[pos + 8 fixLen 4], SIGNED, BE);
indexEntry.count := bytes2Int(indexData[pos + 12 fixLen 4], UNSIGNED, BE);
tagMap @:= [indexEntry.tag] indexEntry;
end for;
end func;
const proc: readSection (inout file: rpmFile, inout rpmSection: section) is func
begin
readHeader(rpmFile, section.head);
if section.head.magic = RPM_HEADER_MAGIC then
section.indexData := gets(rpmFile, section.head.indexCount * RPM_INDEX_ENTRY_SIZE);
fillTagMap(section.indexData, section.tagMap);
section.store := gets(rpmFile, section.head.storeSize);
end if;
end func;
const func string: sectionStri (inout rpmSection: section, in integer: sectionTag) is func
result
var string: sectionStri is "";
local
var rpmIndexEntry: sectionIndexEntry is rpmIndexEntry.value;
var integer: tag is 0;
begin
section.head.magic := RPM_HEADER_MAGIC;
section.head.version := 1;
section.head.indexCount := succ(length(section.tagMap));
section.head.storeSize := length(section.store) + 16;
sectionStri := str(section.head);
sectionIndexEntry.tag := sectionTag;
sectionIndexEntry.dataType := RPM_BIN_TYPE;
sectionIndexEntry.offset := length(section.store);
sectionIndexEntry.count := 16;
sectionStri &:= str(sectionIndexEntry);
for tag range sort(keys(section.tagMap)) do
sectionStri &:= str(section.tagMap[tag]);
end for;
sectionStri &:= section.store;
sectionIndexEntry.offset := -succ(length(section.tagMap)) * 16;
sectionStri &:= str(sectionIndexEntry);
end func;
const proc: assignIndexValues (inout rpmSection: section) is func
local
var rpmIndexEntry: indexEntry is rpmIndexEntry.value;
begin
if section.store <> "" then
for indexEntry range section.tagMap do
case indexEntry.dataType of
when {RPM_INT8_TYPE, RPM_INT16_TYPE, RPM_INT32_TYPE, RPM_INT64_TYPE,
RPM_STRING_TYPE, RPM_BIN_TYPE}:
if indexEntry.striValue = "" then
indexEntry.striValue := getStriValue(section.store, indexEntry);
end if;
when {RPM_STRING_ARRAY_TYPE, RPM_I18NSTRING_TYPE}:
if length(indexEntry.arrayValue) = 0 then
indexEntry.arrayValue := getArrayValue(section.store, indexEntry);
end if;
end case;
end for;
end if;
end func;
const proc: updateStore (inout rpmSection: section) is func
local
var integer: tag is 0;
var rpmIndexEntry: indexEntry is rpmIndexEntry.value;
var string: store is "";
begin
for tag range sort(keys(section.tagMap)) do
indexEntry := section.tagMap[tag];
indexEntry.offset := length(store);
case indexEntry.dataType of
when {RPM_INT8_TYPE}:
store &:= indexEntry.striValue;
when {RPM_INT16_TYPE}:
if odd(length(store)) then
store &:= "\0;";
end if;
indexEntry.offset := length(store);
store &:= indexEntry.striValue;
when {RPM_INT32_TYPE}:
if length(store) mod 4 <> 0 then
store &:= "\0;" mult (4 - length(store) mod 4);
end if;
indexEntry.offset := length(store);
store &:= indexEntry.striValue;
when {RPM_INT64_TYPE}:
if length(store) mod 8 <> 0 then
store &:= "\0;" mult (8 - length(store) mod 4);
end if;
indexEntry.offset := length(store);
store &:= indexEntry.striValue;
when {RPM_STRING_TYPE}:
store &:= indexEntry.striValue & "\0;";
when {RPM_BIN_TYPE}:
store &:= indexEntry.striValue;
when {RPM_STRING_ARRAY_TYPE, RPM_I18NSTRING_TYPE}:
if length(indexEntry.arrayValue) <> 0 then
store &:= join(indexEntry.arrayValue, "\0;") & "\0;";
end if;
end case;
section.tagMap @:= [indexEntry.tag] indexEntry;
end for;
section.store := store;
end func;
const func boolean: checkHeaderDigest (inout rpmArchive: rpm) is func
result
var boolean: okay is TRUE;
local
var string: referenceDigest is "";
var string: computedDigest is "";
begin
if RPMSIGTAG_SHA1 in rpm.signature.tagMap then
referenceDigest := getStriValue(rpm.signature.store, rpm.signature.tagMap[RPMSIGTAG_SHA1]);
computedDigest := hex(sha1(str(rpm.header.head) & rpm.header.indexData & rpm.header.store));
if referenceDigest <> computedDigest then
okay := FALSE;
end if;
end if;
if RPMSIGTAG_SHA256 in rpm.signature.tagMap then
referenceDigest := getStriValue(rpm.signature.store, rpm.signature.tagMap[RPMSIGTAG_SHA256]);
computedDigest := hex(sha256(str(rpm.header.head) & rpm.header.indexData & rpm.header.store));
if referenceDigest <> computedDigest then
okay := FALSE;
end if;
end if;
end func;
const proc: doSettings (inout rpmArchive: rpm) is func
local
var rpmIndexEntry: fileDigestAlgo is rpmIndexEntry.value;
var integer: dependsDictPos is 0;
var integer: count is 0;
var integer: index is 0;
begin
if RPMTAG_FILEDIGESTALGO in rpm.header.tagMap then
fileDigestAlgo := rpm.header.tagMap[RPMTAG_FILEDIGESTALGO];
rpm.fileDigestAlgo := bytes2Int(
rpm.header.store[succ(fileDigestAlgo.offset) fixLen 4], SIGNED, BE);
end if;
rpm.classDict := getStringArray(rpm, RPMTAG_CLASSDICT);
if RPMTAG_DEPENDSDICT in rpm.header.tagMap then
dependsDictPos := succ(rpm.header.tagMap[RPMTAG_DEPENDSDICT].offset);
count := rpm.header.tagMap[RPMTAG_DEPENDSDICT].count;
rpm.dependsDict := count times 0;
for index range 1 to count do
rpm.dependsDict[index] := bytes2Int(
rpm.header.store[dependsDictPos fixLen 4], UNSIGNED, BE);
dependsDictPos +:= 4;
end for;
end if;
end func;
const proc: readDependencies (inout rpmArchive: rpm) is func
local
var integer: flagsPos is 0;
var integer: namePos is 0;
var integer: versionPos is 0;
var integer: count is 0;
var integer: index is 0;
begin
if RPMTAG_PROVIDEFLAGS in rpm.header.tagMap and
RPMTAG_PROVIDENAME in rpm.header.tagMap and
RPMTAG_PROVIDEVERSION in rpm.header.tagMap then
flagsPos := succ(rpm.header.tagMap[RPMTAG_PROVIDEFLAGS].offset);
namePos := succ(rpm.header.tagMap[RPMTAG_PROVIDENAME].offset);
versionPos := succ(rpm.header.tagMap[RPMTAG_PROVIDEVERSION].offset);
count := rpm.header.tagMap[RPMTAG_PROVIDEFLAGS].count;
rpm.provided := count times rpmDependency.value;
for index range 1 to count do
rpm.provided[index].flags := bytes2Int(
rpm.header.store[flagsPos fixLen 4], UNSIGNED, BE);
flagsPos +:= 4;
rpm.provided[index].name := getAsciiz(rpm.header.store, namePos);
rpm.provided[index].version := getAsciiz(rpm.header.store, versionPos);
end for;
end if;
if RPMTAG_REQUIREFLAGS in rpm.header.tagMap and
RPMTAG_REQUIRENAME in rpm.header.tagMap and
RPMTAG_REQUIREVERSION in rpm.header.tagMap then
flagsPos := succ(rpm.header.tagMap[RPMTAG_REQUIREFLAGS].offset);
namePos := succ(rpm.header.tagMap[RPMTAG_REQUIRENAME].offset);
versionPos := succ(rpm.header.tagMap[RPMTAG_REQUIREVERSION].offset);
count := rpm.header.tagMap[RPMTAG_REQUIREFLAGS].count;
rpm.required := count times rpmDependency.value;
for index range 1 to count do
rpm.required[index].flags := bytes2Int(
rpm.header.store[flagsPos fixLen 4], UNSIGNED, BE);
flagsPos +:= 4;
rpm.required[index].name := getAsciiz(rpm.header.store, namePos);
rpm.required[index].version := getAsciiz(rpm.header.store, versionPos);
end for;
end if;
end func;
const func string: getDigest (in string: content, in integer: digestAlgo) is func
result
var string: digest is "";
begin
case digestAlgo of
when {RPM_DIGESTALGO_MD5}: digest := md5(content);
when {RPM_DIGESTALGO_SHA1}: digest := sha1(content);
when {RPM_DIGESTALGO_RIPEMD160}: digest := ripemd160(content);
when {RPM_DIGESTALGO_MD2}: noop;
when {RPM_DIGESTALGO_TIGER192}: noop;
when {RPM_DIGESTALGO_HAVAL_5_160}: noop;
when {RPM_DIGESTALGO_SHA256}: digest := sha256(content);
when {RPM_DIGESTALGO_SHA384}: digest := sha384(content);
when {RPM_DIGESTALGO_SHA512}: digest := sha512(content);
when {RPM_DIGESTALGO_SHA224}: digest := sha224(content);
end case;
end func;
const proc: checkPayloadDigest (inout rpmArchive: rpm) is func
local
var string: payloadContent is "";
var integer: digestPos is 0;
var string: referenceDigest is "";
var string: computedDigest is "";
var integer: digestAlgo is 0;
begin
if RPMTAG_PAYLOADDIGEST in rpm.header.tagMap and
RPMTAG_PAYLOADDIGESTALGO in rpm.header.tagMap then
seek(rpm.rpmFile, rpm.payloadPos);
payloadContent := gets(rpm.rpmFile, integer.last);
digestPos := succ(rpm.header.tagMap[RPMTAG_PAYLOADDIGEST].offset);
referenceDigest := getAsciiz(rpm.header.store, digestPos);
digestAlgo := getIntValue(rpm.header.store, rpm.header.tagMap[RPMTAG_PAYLOADDIGESTALGO]);
computedDigest := hex(getDigest(payloadContent, digestAlgo));
if referenceDigest <> computedDigest then
raise FILE_ERROR;
end if;
end if;
if RPMSIGTAG_MD5 in rpm.signature.tagMap then
if payloadContent = "" then
seek(rpm.rpmFile, rpm.payloadPos);
payloadContent := gets(rpm.rpmFile, integer.last);
end if;
referenceDigest := getStriValue(rpm.signature.store, rpm.signature.tagMap[RPMSIGTAG_MD5]);
computedDigest := md5(str(rpm.header.head) & rpm.header.indexData & rpm.header.store & payloadContent);
if referenceDigest <> computedDigest then
raise FILE_ERROR;
end if;
end if;
end func;
const proc: checkUncompressedDigest (inout rpmArchive: rpm) is func
local
var integer: digestPos is 0;
var string: referenceDigest is "";
var string: computedDigest is "";
var integer: digestAlgo is 0;
begin
if RPMTAG_PAYLOADDIGESTALT in rpm.header.tagMap and
RPMTAG_PAYLOADDIGESTALGO in rpm.header.tagMap then
digestPos := succ(rpm.header.tagMap[RPMTAG_PAYLOADDIGESTALT].offset);
referenceDigest := getAsciiz(rpm.header.store, digestPos);
digestAlgo := getIntValue(rpm.header.store, rpm.header.tagMap[RPMTAG_PAYLOADDIGESTALGO]);
computedDigest := hex(getDigest(gets(rpm.payloadFile, integer.last), digestAlgo));
seek(rpm.payloadFile, 1);
if referenceDigest <> computedDigest then
raise FILE_ERROR;
end if;
end if;
end func;
const proc: getArchive (inout rpmArchive: rpm) is func
local
var string: compressor is "";
var string: format is "";
var file: payload is STD_NULL;
begin
if rpm.payloadPos = 0 then
rpm.payloadFile := openStriFile();
else
checkPayloadDigest(rpm);
seek(rpm.rpmFile, rpm.payloadPos);
if RPMTAG_PAYLOADCOMPRESSOR in rpm.header.tagMap then
compressor := getStriValue(rpm.header.store, rpm.header.tagMap[RPMTAG_PAYLOADCOMPRESSOR]);
case compressor of
when {"gzip"}: payload := openGzipFile(rpm.rpmFile, READ);
when {"lzma"}: payload := openLzmaFile(rpm.rpmFile);
when {"xz"}: payload := openXzFile(rpm.rpmFile);
when {"zstd"}: payload := openZstdFile(rpm.rpmFile);
when {"bzip2"}: payload := openBzip2File(rpm.rpmFile, READ);
end case;
end if;
if payload <> STD_NULL then
rpm.payloadFile := openStriFile(gets(payload, integer.last));
close(payload);
end if;
end if;
if rpm.payloadFile <> STD_NULL then
if RPMTAG_PAYLOADFORMAT in rpm.header.tagMap then
format := getStriValue(rpm.header.store, rpm.header.tagMap[RPMTAG_PAYLOADFORMAT]);
case format of
when {"cpio"}: rpm.archive := openCpio(rpm.payloadFile);
end case;
elsif rpm.payloadPos = 0 then
rpm.archive := openCpio(rpm.payloadFile);
end if;
end if;
end func;
const func string: archiveFilePath (inout fileSys: archive, in string: filePath) is func
result
var string: archiveFilePath is "";
begin
if startsWith(filePath, "/") and
fileTypeSL(archive, filePath) = FILE_ABSENT then
archiveFilePath := "." & filePath;
else
archiveFilePath := filePath;
end if;
end func;
const func fileSys: openRpm (inout file: rpmFile) is func
result
var fileSys: newFileSys is fileSys.value;
local
var rpmArchive: rpm is rpmArchive.value;
begin
if length(rpmFile) = 0 then
initLead(rpm.lead);
rpm.rpmFile := rpmFile;
rpm.fileDigestAlgo := RPM_DIGESTALGO_SHA256;
newFileSys := toInterface(rpm);
else
seek(rpmFile, 1);
readLead(rpmFile, rpm.lead);
if rpm.lead.magic = RPM_LEAD_MAGIC then
rpm.rpmFile := rpmFile;
readSection(rpmFile, rpm.signature);
if rpm.signature.head.magic = RPM_HEADER_MAGIC then
ignore(gets(rpmFile, 7 - pred(rpm.signature.head.storeSize) mod 8));
readSection(rpmFile, rpm.header);
if rpm.header.head.magic = RPM_HEADER_MAGIC then
rpm.payloadPos := tell(rpmFile);
if checkHeaderDigest(rpm) then
doSettings(rpm);
createMinimumOfCatalog(rpm);
rpm.useLongFileSizes := RPMTAG_FILESIZES not in rpm.header.tagMap;
readDependencies(rpm);
newFileSys := toInterface(rpm);
end if;
end if;
end if;
end if;
end if;
end func;
const func fileSys: openRpm (in string: rpmFileName) is func
result
var fileSys: rpm is fileSys.value;
local
var file: rpmFile is STD_NULL;
begin
rpmFile := open(rpmFileName, "r");
rpm := openRpm(rpmFile);
end func;
const proc: close (inout rpmArchive: rpm) is func
local
var string: signatureSection is "";
var string: headerSection is "";
var string: payload is "";
begin
if isDirty(rpm) then
if length(rpm.rpmFile) = 0 then
writeLead(rpm.rpmFile, rpm.lead);
end if;
if rpm.archive <> fileSys.value then
seek(rpm.payloadFile, 1);
payload := gzip(gets(rpm.payloadFile, integer.last));
end if;
assignIndexValues(rpm.header);
rpm.provided := sort(rpm.provided);
updateProvisions(rpm);
rpm.required := sort(rpm.required);
updateRequirements(rpm);
updateDependencies(rpm);
updateHeader(rpm);
update(rpm, RPMTAG_SIZE);
updateIndexEntry(rpm.header, RPMTAG_DIRNAMES, RPM_STRING_ARRAY_TYPE, rpm.dirNames);
updateIndexEntry(rpm.header, RPMTAG_CLASSDICT, RPM_STRING_ARRAY_TYPE, rpm.classDict);
updateIndexEntry(rpm.header, RPMTAG_PAYLOADCOMPRESSOR, RPM_STRING_TYPE, "gzip");
updateIndexEntry(rpm.header, RPMTAG_PAYLOADFLAGS, RPM_STRING_TYPE, "9");
updateIndexEntry(rpm.header, RPMTAG_PAYLOADFORMAT, RPM_STRING_TYPE, "cpio");
if rpm.fileDigestAlgo <> RPM_DIGESTALGO_MD5 then
updateIndexEntry(rpm.header, RPMTAG_FILEDIGESTALGO, RPM_INT32_TYPE, rpm.fileDigestAlgo);
end if;
updateIndexEntry(rpm.header, RPMTAG_PAYLOADDIGEST, RPM_STRING_ARRAY_TYPE,
[] (hex(getDigest(payload, RPM_DIGESTALGO_SHA256))));
updateIndexEntry(rpm.header, RPMTAG_PAYLOADDIGESTALGO, RPM_INT32_TYPE, RPM_DIGESTALGO_SHA256);
seek(rpm.payloadFile, 1);
updateIndexEntry(rpm.header, RPMTAG_PAYLOADDIGESTALT, RPM_STRING_ARRAY_TYPE,
[] (hex(getDigest(gets(rpm.payloadFile, integer.last), RPM_DIGESTALGO_SHA256))));
updateStore(rpm.header);
headerSection := sectionStri(rpm.header, RPMTAG_HEADERIMMUTABLE);
updateIndexEntry(rpm.signature, RPMSIGTAG_SIZE, RPM_INT32_TYPE,
length(headerSection) + length(payload));
updateIndexEntry(rpm.signature, RPMSIGTAG_PAYLOADSIZE, RPM_INT32_TYPE,
length(rpm.payloadFile));
updateIndexEntry(rpm.signature, RPMSIGTAG_SHA1, RPM_STRING_TYPE,
hex(sha1(headerSection)));
updateIndexEntry(rpm.signature, RPMSIGTAG_SHA256, RPM_STRING_TYPE,
hex(sha256(headerSection)));
updateIndexEntry(rpm.signature, RPMSIGTAG_MD5, RPM_BIN_TYPE,
md5(headerSection & payload));
assignIndexValues(rpm.signature);
updateStore(rpm.signature);
signatureSection := sectionStri(rpm.signature, RPMSIGTAG_HEADERSIGNATURES);
updateIndexEntry(rpm.signature, RPMSIGTAG_RESERVEDSPACE, RPM_BIN_TYPE,
"\0;" mult 4505 - length(signatureSection) -
(7 - pred(length(signatureSection)) mod 8) -
RPM_LEAD_SIZE - RPM_INDEX_ENTRY_SIZE - 1);
rpm.signature.tagMap[RPMSIGTAG_RESERVEDSPACE].offset := length(rpm.signature.store);
rpm.signature.store &:= rpm.signature.tagMap[RPMSIGTAG_RESERVEDSPACE].striValue;
signatureSection := sectionStri(rpm.signature, RPMSIGTAG_HEADERSIGNATURES);
write(rpm.rpmFile, signatureSection);
write(rpm.rpmFile, "\0;" mult (7 - pred(length(signatureSection)) mod 8));
write(rpm.rpmFile, headerSection);
write(rpm.rpmFile, payload);
truncate(rpm.rpmFile, pred(tell(rpm.rpmFile)));
end if;
if rpm.archive <> fileSys.value then
close(rpm.archive);
end if;
rpm := rpmArchive.value;
end func;
const func rpmCatalogEntry: addImplicitDir (inout rpmArchive: rpm,
in string: dirPath) is func
result
var rpmCatalogEntry: catalogEntry is rpmCatalogEntry.value;
begin
catalogEntry.filePath := dirPath;
catalogEntry.mode := ord(MODE_FILE_DIR) + 8#775;
catalogEntry.allDataPresent := TRUE;
rpm.catalog @:= [dirPath] catalogEntry;
end func;
const func string: followSymlink (inout rpmArchive: rpm, in var string: filePath,
inout rpmCatalogEntry: catalogEntry) is func
result
var string: missingPath is "";
local
var integer: symlinkCount is MAX_SYMLINK_CHAIN_LENGTH;
var boolean: isSymlink is TRUE;
begin
repeat
if filePath in rpm.catalog then
catalogEntry := rpm.catalog[filePath];
elsif implicitDir(rpm.register, filePath) then
catalogEntry := addImplicitDir(rpm, filePath);
else
missingPath := filePath;
isSymlink := FALSE;
end if;
if missingPath = "" then
if not catalogEntry.allDataPresent then
readCatalogEntry(rpm, catalogEntry);
end if;
if bin32(catalogEntry.mode) & MODE_FILE_TYPE_MASK = MODE_FILE_SYMLINK then
decr(symlinkCount);
filePath := symlinkDestination(filePath, catalogEntry.linkTo);
else
isSymlink := FALSE;
end if;
end if;
until not isSymlink or symlinkCount < 0;
if isSymlink then
raise FILE_ERROR;
end if;
end func;
const func rpmCatalogEntry: followSymlink (inout rpmArchive: rpm, in string: filePath) is func
result
var rpmCatalogEntry: catalogEntry is rpmCatalogEntry.value;
local
var string: missingPath is "";
begin
missingPath := followSymlink(rpm, filePath, catalogEntry);
if missingPath <> "" then
raise FILE_ERROR;
end if;
end func;
const proc: fixRegisterAndCatalog (inout rpmArchive: rpm, in integer: insertPos,
in integer: numEntries) is func
local
var integer: headerPos is 1;
var string: filePath is "";
begin
for key filePath range rpm.register do
if rpm.register[filePath] >= insertPos then
rpm.register[filePath] +:= numEntries;
end if;
end for;
for key filePath range rpm.catalog do
if rpm.catalog[filePath].fileNumber >= insertPos then
rpm.catalog[filePath].fileNumber +:= numEntries;
end if;
end for;
end func;
const func integer: findNameIndex (in array string: nameList, in string: name) is func
result
var integer: nameIndex is 0;
local
var integer: index is 0;
begin
for key index range nameList until nameIndex <> 0 do
if nameList[index] = name then
nameIndex := index;
end if;
end for;
end func;
const func integer: getNameIndex (inout array string: nameList, in string: name) is func
result
var integer: nameIndex is 0;
begin
nameIndex := findNameIndex(nameList, name);
if nameIndex = 0 then
nameList &:= name;
nameIndex := length(nameList);
end if;
decr(nameIndex);
end func;
const func integer: fileClass (inout array string: nameList, in string: filePath,
in string: data) is func
result
var integer: fileClass is 0;
local
var string: description is "";
begin
description := magicDescription(getMagic(data));
if description = "" then
if endsWith(filePath, ".sd7") then
description := "Seed7 source";
elsif endsWith(filePath, ".s7i") then
description := "Seed7 library";
end if;
end if;
fileClass := getNameIndex(nameList, description);
end func;
const proc: setDependencies (inout rpmArchive: rpm,
inout rpmCatalogEntry: catalogEntry, in string: data) is func
local
var file: elfFile is STD_NULL;
var elfData: elf is elfData.value;
var rpmDependency: dependency is rpmDependency.value;
var string: name is "";
begin
elfFile := openStriFile(data);
elf := openElf(elfFile);
if elf.header.magic = ELF_MAGIC then
dependency.flags := RPMSENSE_FIND_REQUIRES;
for name range getVerNeeds(elf) do
dependency.name := name;
catalogEntry.dependencies &:= dependency;
addDependency(rpm.required, dependency);
end for;
for name range getDynamicNeeds(elf) do
dependency.name := name <& "()(" <& elf.header.addressSize <& "bit)";
catalogEntry.dependencies &:= dependency;
addDependency(rpm.required, dependency);
end for;
end if;
end func;
const proc: setDirIndexAndBaseName (inout rpmArchive: rpm,
inout rpmCatalogEntry: catalogEntry) is func
local
var integer: slashPos is 0;
var string: dirName is "";
begin
slashPos := rpos(catalogEntry.filePath, "/");
if slashPos <> 0 then
dirName := catalogEntry.filePath[.. slashPos];
catalogEntry.baseName := catalogEntry.filePath[succ(slashPos) ..];
else
dirName := "";
catalogEntry.baseName := catalogEntry.filePath;
end if;
catalogEntry.dirIndex := getNameIndex(rpm.dirNames, dirName);
end func;
const func array string: readDir (inout rpmArchive: rpm, in string: dirPath) is
return readDir(rpm.register, dirPath);
const func array string: readDir (inout rpmArchive: rpm, RECURSIVE) is
return sort(keys(rpm.register));
const func fileType: fileType (inout rpmArchive: rpm, in var string: filePath) is func
result
var fileType: aFileType is FILE_UNKNOWN;
local
var rpmCatalogEntry: catalogEntry is rpmCatalogEntry.value;
var integer: symlinkCount is MAX_SYMLINK_CHAIN_LENGTH;
var boolean: isSymlink is FALSE;
begin
if filePath <> "/" and endsWith(filePath, "/") then
raise RANGE_ERROR;
elsif filePath = "" then
aFileType := FILE_DIR;
else
repeat
isSymlink := FALSE;
if filePath in rpm.catalog then
catalogEntry := rpm.catalog[filePath];
elsif implicitDir(rpm.register, filePath) then
catalogEntry := addImplicitDir(rpm, filePath);
else
aFileType := FILE_ABSENT;
end if;
if aFileType = FILE_UNKNOWN then
if not catalogEntry.allDataPresent then
readCatalogEntry(rpm, catalogEntry);
end if;
case bin32(catalogEntry.mode) & MODE_FILE_TYPE_MASK of
when {MODE_FILE_REGULAR}: aFileType := FILE_REGULAR;
when {MODE_FILE_DIR}: aFileType := FILE_DIR;
when {MODE_FILE_CHAR}: aFileType := FILE_CHAR;
when {MODE_FILE_BLOCK}: aFileType := FILE_BLOCK;
when {MODE_FILE_FIFO}: aFileType := FILE_FIFO;
when {MODE_FILE_SOCKET}: aFileType := FILE_SOCKET;
when {MODE_FILE_SYMLINK}:
isSymlink := TRUE;
decr(symlinkCount);
filePath := symlinkDestination(filePath, catalogEntry.linkTo);
otherwise: aFileType := FILE_UNKNOWN;
end case;
end if;
until not isSymlink or symlinkCount < 0;
if isSymlink then
aFileType := FILE_SYMLINK;
end if;
end if;
end func;
const func fileType: fileTypeSL (inout rpmArchive: rpm, in string: filePath) is func
result
var fileType: aFileType is FILE_UNKNOWN;
local
var rpmCatalogEntry: catalogEntry is rpmCatalogEntry.value;
begin
if filePath <> "/" and endsWith(filePath, "/") then
raise RANGE_ERROR;
elsif filePath = "" then
aFileType := FILE_DIR;
else
if filePath in rpm.catalog then
catalogEntry := rpm.catalog[filePath];
elsif implicitDir(rpm.register, filePath) then
catalogEntry := addImplicitDir(rpm, filePath);
else
aFileType := FILE_ABSENT;
end if;
if aFileType = FILE_UNKNOWN then
if not catalogEntry.allDataPresent then
readCatalogEntry(rpm, catalogEntry);
end if;
case bin32(catalogEntry.mode) & MODE_FILE_TYPE_MASK of
when {MODE_FILE_REGULAR}: aFileType := FILE_REGULAR;
when {MODE_FILE_DIR}: aFileType := FILE_DIR;
when {MODE_FILE_CHAR}: aFileType := FILE_CHAR;
when {MODE_FILE_BLOCK}: aFileType := FILE_BLOCK;
when {MODE_FILE_FIFO}: aFileType := FILE_FIFO;
when {MODE_FILE_SOCKET}: aFileType := FILE_SOCKET;
when {MODE_FILE_SYMLINK}: aFileType := FILE_SYMLINK;
otherwise: aFileType := FILE_UNKNOWN;
end case;
end if;
end if;
end func;
const func fileMode: getFileMode (inout rpmArchive: rpm, in string: filePath) is func
result
var fileMode: mode is fileMode.value;
begin
if filePath <> "/" and endsWith(filePath, "/") then
raise RANGE_ERROR;
else
mode := fileMode(followSymlink(rpm, filePath).mode mod 8#1000);
end if;
end func;
const proc: setFileMode (inout rpmArchive: rpm, in string: filePath,
in fileMode: mode) is func
local
var rpmCatalogEntry: catalogEntry is rpmCatalogEntry.value;
begin
if filePath <> "/" and endsWith(filePath, "/") then
raise RANGE_ERROR;
else
catalogEntry := followSymlink(rpm, filePath);
if catalogEntry.fileNumber <> 0 then
catalogEntry.mode := (catalogEntry.mode >> 9 << 9) + integer(mode);
catalogEntry.dirty := TRUE;
rpm.catalog @:= [catalogEntry.filePath] catalogEntry;
if rpm.archive = fileSys.value then
getArchive(rpm);
end if;
setFileMode(rpm.archive,
archiveFilePath(rpm.archive, catalogEntry.filePath), mode);
else
raise FILE_ERROR;
end if;
end if;
end func;
const func integer: fileSize (inout rpmArchive: rpm, in string: filePath) is func
result
var integer: size is 0;
begin
if filePath <> "/" and endsWith(filePath, "/") then
raise RANGE_ERROR;
else
size := followSymlink(rpm, filePath).fileSize;
end if;
end func;
const func time: getMTime (inout rpmArchive: rpm, in string: filePath) is func
result
var time: modificationTime is time.value;
begin
if filePath <> "/" and endsWith(filePath, "/") then
raise RANGE_ERROR;
else
modificationTime := timestamp1970ToTime(
followSymlink(rpm, filePath).mtime);
end if;
end func;
const proc: setMTime (inout rpmArchive: rpm, in string: filePath,
in time: modificationTime) is func
local
var integer: mtime is 0;
var rpmCatalogEntry: catalogEntry is rpmCatalogEntry.value;
begin
mtime := timestamp1970(modificationTime);
if mtime < 0 or mtime >= 2 ** 31 or
(filePath <> "/" and endsWith(filePath, "/")) then
raise RANGE_ERROR;
else
catalogEntry := followSymlink(rpm, filePath);
if catalogEntry.fileNumber <> 0 then
catalogEntry.mtime := mtime;
catalogEntry.dirty := TRUE;
rpm.catalog @:= [catalogEntry.filePath] catalogEntry;
if rpm.archive = fileSys.value then
getArchive(rpm);
end if;
setMTime(rpm.archive,
archiveFilePath(rpm.archive, catalogEntry.filePath),
modificationTime);
end if;
end if;
end func;
const func string: getOwner (inout rpmArchive: rpm, in string: filePath) is func
result
var string: owner is "";
local
var rpmCatalogEntry: catalogEntry is rpmCatalogEntry.value;
begin
if filePath <> "/" and endsWith(filePath, "/") then
raise RANGE_ERROR;
else
catalogEntry := followSymlink(rpm, filePath);
if catalogEntry.userName <> "" then
owner := catalogEntry.userName;
else
owner := str(catalogEntry.uid);
end if;
end if;
end func;
const proc: setOwner (inout rpmArchive: rpm, in string: filePath,
in string: owner) is func
local
var rpmCatalogEntry: catalogEntry is rpmCatalogEntry.value;
begin
if filePath <> "/" and endsWith(filePath, "/") then
raise RANGE_ERROR;
else
catalogEntry := followSymlink(rpm, filePath);
if catalogEntry.fileNumber <> 0 then
if isDigitString(owner) then
catalogEntry.uid := integer(owner);
else
catalogEntry.uid := 0;
end if;
catalogEntry.userName := owner;
catalogEntry.dirty := TRUE;
rpm.catalog @:= [catalogEntry.filePath] catalogEntry;
if rpm.archive = fileSys.value then
getArchive(rpm);
end if;
block
setOwner(rpm.archive,
archiveFilePath(rpm.archive, catalogEntry.filePath),
owner);
exception
catch RANGE_ERROR: noop;
end block;
end if;
end if;
end func;
const func string: getGroup (inout rpmArchive: rpm, in string: filePath) is func
result
var string: group is "";
local
var rpmCatalogEntry: catalogEntry is rpmCatalogEntry.value;
begin
if filePath <> "/" and endsWith(filePath, "/") then
raise RANGE_ERROR;
else
catalogEntry := followSymlink(rpm, filePath);
if catalogEntry.groupName <> "" then
group := catalogEntry.groupName;
else
group := str(catalogEntry.gid);
end if;
end if;
end func;
const proc: setGroup (inout rpmArchive: rpm, in string: filePath,
in string: group) is func
local
var rpmCatalogEntry: catalogEntry is rpmCatalogEntry.value;
begin
if filePath <> "/" and endsWith(filePath, "/") then
raise RANGE_ERROR;
else
catalogEntry := followSymlink(rpm, filePath);
if catalogEntry.fileNumber <> 0 then
if isDigitString(group) then
catalogEntry.gid := integer(group);
else
catalogEntry.gid := 0;
end if;
catalogEntry.groupName := group;
catalogEntry.dirty := TRUE;
rpm.catalog @:= [catalogEntry.filePath] catalogEntry;
if rpm.archive = fileSys.value then
getArchive(rpm);
end if;
block
setGroup(rpm.archive,
archiveFilePath(rpm.archive, catalogEntry.filePath),
group);
exception
catch RANGE_ERROR: noop;
end block;
end if;
end if;
end func;
const func fileMode: getFileMode (inout rpmArchive: rpm, in string: filePath, SYMLINK) is func
result
var fileMode: mode is fileMode.value;
local
var rpmCatalogEntry: catalogEntry is rpmCatalogEntry.value;
begin
if filePath <> "/" and endsWith(filePath, "/") then
raise RANGE_ERROR;
elsif filePath = "" then
raise FILE_ERROR;
else
if filePath in rpm.catalog then
catalogEntry := rpm.catalog[filePath];
else
raise FILE_ERROR;
end if;
if not catalogEntry.allDataPresent then
readCatalogEntry(rpm, catalogEntry);
end if;
if bin32(catalogEntry.mode) & MODE_FILE_TYPE_MASK = MODE_FILE_SYMLINK then
mode := fileMode(catalogEntry.mode mod 8#1000);
else
raise FILE_ERROR;
end if;
end if;
end func;
const func time: getMTime (inout rpmArchive: rpm, in string: filePath, SYMLINK) is func
result
var time: modificationTime is time.value;
local
var rpmCatalogEntry: catalogEntry is rpmCatalogEntry.value;
begin
if filePath <> "/" and endsWith(filePath, "/") then
raise RANGE_ERROR;
elsif filePath = "" then
raise FILE_ERROR;
else
if filePath in rpm.catalog then
catalogEntry := rpm.catalog[filePath];
else
raise FILE_ERROR;
end if;
if not catalogEntry.allDataPresent then
readCatalogEntry(rpm, catalogEntry);
end if;
if bin32(catalogEntry.mode) & MODE_FILE_TYPE_MASK = MODE_FILE_SYMLINK then
modificationTime := timestamp1970ToTime(catalogEntry.mtime);
else
raise FILE_ERROR;
end if;
end if;
end func;
const proc: setMTime (inout rpmArchive: rpm, in string: filePath,
in time: modificationTime, SYMLINK) is func
local
var integer: mtime is 0;
var rpmCatalogEntry: catalogEntry is rpmCatalogEntry.value;
begin
mtime := timestamp1970(modificationTime);
if mtime < 0 or mtime >= 2 ** 31 or
(filePath <> "/" and endsWith(filePath, "/")) then
raise RANGE_ERROR;
elsif filePath = "" then
raise FILE_ERROR;
else
if filePath in rpm.catalog then
catalogEntry := rpm.catalog[filePath];
else
raise FILE_ERROR;
end if;
if not catalogEntry.allDataPresent then
readCatalogEntry(rpm, catalogEntry);
end if;
if bin32(catalogEntry.mode) & MODE_FILE_TYPE_MASK = MODE_FILE_SYMLINK then
catalogEntry.mtime := mtime;
catalogEntry.dirty := TRUE;
rpm.catalog @:= [catalogEntry.filePath] catalogEntry;
if rpm.archive = fileSys.value then
getArchive(rpm);
end if;
setMTime(rpm.archive,
archiveFilePath(rpm.archive, catalogEntry.filePath),
modificationTime, SYMLINK);
else
raise FILE_ERROR;
end if;
end if;
end func;
const func string: getOwner (inout rpmArchive: rpm, in string: filePath, SYMLINK) is func
result
var string: owner is "";
local
var rpmCatalogEntry: catalogEntry is rpmCatalogEntry.value;
begin
if filePath <> "/" and endsWith(filePath, "/") then
raise RANGE_ERROR;
elsif filePath = "" then
raise FILE_ERROR;
else
if filePath in rpm.catalog then
catalogEntry := rpm.catalog[filePath];
else
raise FILE_ERROR;
end if;
if not catalogEntry.allDataPresent then
readCatalogEntry(rpm, catalogEntry);
end if;
if bin32(catalogEntry.mode) & MODE_FILE_TYPE_MASK = MODE_FILE_SYMLINK then
if catalogEntry.userName <> "" then
owner := catalogEntry.userName;
else
owner := str(catalogEntry.uid);
end if;
else
raise FILE_ERROR;
end if;
end if;
end func;
const proc: setOwner (inout rpmArchive: rpm, in string: filePath,
in string: owner, SYMLINK) is func
local
var rpmCatalogEntry: catalogEntry is rpmCatalogEntry.value;
var integer: mtime is 0;
begin
if filePath <> "/" and endsWith(filePath, "/") then
raise RANGE_ERROR;
elsif filePath = "" then
raise FILE_ERROR;
else
if filePath in rpm.catalog then
catalogEntry := rpm.catalog[filePath];
else
raise FILE_ERROR;
end if;
if not catalogEntry.allDataPresent then
readCatalogEntry(rpm, catalogEntry);
end if;
if bin32(catalogEntry.mode) & MODE_FILE_TYPE_MASK = MODE_FILE_SYMLINK then
if isDigitString(owner) then
catalogEntry.uid := integer(owner);
else
catalogEntry.uid := 0;
end if;
catalogEntry.userName := owner;
catalogEntry.dirty := TRUE;
rpm.catalog @:= [catalogEntry.filePath] catalogEntry;
if rpm.archive = fileSys.value then
getArchive(rpm);
end if;
block
setOwner(rpm.archive,
archiveFilePath(rpm.archive, catalogEntry.filePath),
owner, SYMLINK);
exception
catch RANGE_ERROR: noop;
end block;
else
raise FILE_ERROR;
end if;
end if;
end func;
const func string: getGroup (inout rpmArchive: rpm, in string: filePath, SYMLINK) is func
result
var string: group is "";
local
var rpmCatalogEntry: catalogEntry is rpmCatalogEntry.value;
begin
if filePath <> "/" and endsWith(filePath, "/") then
raise RANGE_ERROR;
elsif filePath = "" then
raise FILE_ERROR;
else
if filePath in rpm.catalog then
catalogEntry := rpm.catalog[filePath];
else
raise FILE_ERROR;
end if;
if not catalogEntry.allDataPresent then
readCatalogEntry(rpm, catalogEntry);
end if;
if bin32(catalogEntry.mode) & MODE_FILE_TYPE_MASK = MODE_FILE_SYMLINK then
if catalogEntry.groupName <> "" then
group := catalogEntry.groupName;
else
group := str(catalogEntry.gid);
end if;
else
raise FILE_ERROR;
end if;
end if;
end func;
const proc: setGroup (inout rpmArchive: rpm, in string: filePath,
in string: group, SYMLINK) is func
local
var rpmCatalogEntry: catalogEntry is rpmCatalogEntry.value;
var integer: mtime is 0;
begin
if filePath <> "/" and endsWith(filePath, "/") then
raise RANGE_ERROR;
elsif filePath = "" then
raise FILE_ERROR;
else
if filePath in rpm.catalog then
catalogEntry := rpm.catalog[filePath];
else
raise FILE_ERROR;
end if;
if not catalogEntry.allDataPresent then
readCatalogEntry(rpm, catalogEntry);
end if;
if bin32(catalogEntry.mode) & MODE_FILE_TYPE_MASK = MODE_FILE_SYMLINK then
if isDigitString(group) then
catalogEntry.gid := integer(group);
else
catalogEntry.gid := 0;
end if;
catalogEntry.groupName := group;
catalogEntry.dirty := TRUE;
rpm.catalog @:= [catalogEntry.filePath] catalogEntry;
if rpm.archive = fileSys.value then
getArchive(rpm);
end if;
block
setGroup(rpm.archive,
archiveFilePath(rpm.archive, catalogEntry.filePath),
group, SYMLINK);
exception
catch RANGE_ERROR: noop;
end block;
else
raise FILE_ERROR;
end if;
end if;
end func;
const func string: readLink (inout rpmArchive: rpm, in string: filePath) is func
result
var string: linkPath is "";
local
var rpmCatalogEntry: catalogEntry is rpmCatalogEntry.value;
begin
if filePath <> "/" and endsWith(filePath, "/") then
raise RANGE_ERROR;
elsif filePath in rpm.catalog then
catalogEntry := rpm.catalog[filePath];
else
raise FILE_ERROR;
end if;
if not catalogEntry.allDataPresent then
readCatalogEntry(rpm, catalogEntry);
end if;
if bin32(catalogEntry.mode) & MODE_FILE_TYPE_MASK = MODE_FILE_SYMLINK then
linkPath := catalogEntry.linkTo;
else
raise FILE_ERROR;
end if;
end func;
const proc: makeLink (inout rpmArchive: rpm, in string: symlinkPath,
in string: targetPath) is func
local
var rpmCatalogEntry: catalogEntry is rpmCatalogEntry.value;
var integer: length is 0;
begin
if symlinkPath <> "/" and endsWith(symlinkPath, "/") then
raise RANGE_ERROR;
elsif symlinkPath = "" or symlinkPath in rpm.catalog or
implicitDir(rpm.register, symlinkPath) then
raise FILE_ERROR;
else
catalogEntry.fileSize := length(toUtf8(targetPath));
catalogEntry.mode := ord(MODE_FILE_SYMLINK) + 8#777;
catalogEntry.uid := 0;
catalogEntry.gid := 0;
catalogEntry.rdev := 0;
catalogEntry.mtime := timestamp1970(time(NOW));
catalogEntry.digest := "";
catalogEntry.linkTo := targetPath;
catalogEntry.flags := 0;
catalogEntry.userName := "";
catalogEntry.groupName := "";
catalogEntry.verifyFlags := RPM_ALL_VERIFY_FLAGS;
catalogEntry.device := 1;
incr(rpm.maximumInode);
catalogEntry.inode := rpm.maximumInode;
catalogEntry.lang := "";
catalogEntry.color := 0;
catalogEntry.fileClass := getNameIndex(rpm.classDict, "symbolic link");
catalogEntry.dependX := 0;
catalogEntry.dependN := 0;
catalogEntry.allDataPresent := TRUE;
catalogEntry.filePath := symlinkPath;
catalogEntry.fileNumber := succ(length(rpm.register));
catalogEntry.dirty := TRUE;
setDirIndexAndBaseName(rpm, catalogEntry);
rpm.catalog @:= [symlinkPath] catalogEntry;
rpm.register @:= [symlinkPath] catalogEntry.fileNumber;
makeLink(rpm.archive, archiveFilePath(rpm.archive, symlinkPath),
archiveFilePath(rpm.archive, targetPath));
end if;
end func;
const func string: getFile (inout rpmArchive: rpm, in string: filePath) is func
result
var string: content is "";
local
var rpmCatalogEntry: catalogEntry is rpmCatalogEntry.value;
var string: digest is "";
begin
if filePath <> "/" and endsWith(filePath, "/") then
raise RANGE_ERROR;
else
catalogEntry := followSymlink(rpm, filePath);
if bin32(catalogEntry.mode) & MODE_FILE_TYPE_MASK = MODE_FILE_REGULAR then
if rpm.archive = fileSys.value then
getArchive(rpm);
end if;
content := getFile(rpm.archive, archiveFilePath(rpm.archive, catalogEntry.filePath));
digest := hex(getDigest(content, rpm.fileDigestAlgo));
if catalogEntry.digest <> digest then
raise FILE_ERROR;
end if;
end if;
end if;
end func;
const proc: putFile (inout rpmArchive: rpm, in string: filePath,
in string: data) is func
local
var rpmCatalogEntry: catalogEntry is rpmCatalogEntry.value;
var string: missingPath is "";
begin
if filePath = "" or filePath <> "/" and endsWith(filePath, "/") then
raise RANGE_ERROR;
else
missingPath := followSymlink(rpm, filePath, catalogEntry);
if missingPath = "" then
if bin32(catalogEntry.mode) & MODE_FILE_TYPE_MASK <> MODE_FILE_REGULAR then
raise FILE_ERROR;
else
if rpm.archive = fileSys.value then
getArchive(rpm);
end if;
catalogEntry.fileSize := length(data);
catalogEntry.digest := hex(getDigest(data, rpm.fileDigestAlgo));
if startsWith(data, "\127;ELF\1;") then
catalogEntry.color := 1;
setDependencies(rpm, catalogEntry, data);
elsif startsWith(data, "\127;ELF\2;") then
catalogEntry.color := 2;
setDependencies(rpm, catalogEntry, data);
else
catalogEntry.color := 0;
end if;
catalogEntry.fileClass := fileClass(rpm.classDict, filePath, data);
catalogEntry.dirty := TRUE;
if length(data) >= 2 ** 32 then
rpm.useLongFileSizes := TRUE;
end if;
rpm.catalog @:= [catalogEntry.filePath] catalogEntry;
putFile(rpm.archive, archiveFilePath(rpm.archive, catalogEntry.filePath), data);
end if;
else
if rpm.archive = fileSys.value then
getArchive(rpm);
end if;
catalogEntry.fileSize := length(data);
catalogEntry.mode := ord(MODE_FILE_REGULAR) + 8#664;
catalogEntry.uid := 0;
catalogEntry.gid := 0;
catalogEntry.rdev := 0;
catalogEntry.mtime := timestamp1970(time(NOW));
catalogEntry.digest := hex(getDigest(data, rpm.fileDigestAlgo));
catalogEntry.linkTo := "";
catalogEntry.flags := 0;
catalogEntry.userName := "";
catalogEntry.groupName := "";
catalogEntry.verifyFlags := RPM_ALL_VERIFY_FLAGS;
catalogEntry.device := 1;
incr(rpm.maximumInode);
catalogEntry.inode := rpm.maximumInode;
catalogEntry.lang := "";
if startsWith(data, "\127;ELF\1;") then
catalogEntry.color := 1;
setDependencies(rpm, catalogEntry, data);
elsif startsWith(data, "\127;ELF\2;") then
catalogEntry.color := 2;
setDependencies(rpm, catalogEntry, data);
else
catalogEntry.color := 0;
end if;
catalogEntry.fileClass := fileClass(rpm.classDict, filePath, data);
catalogEntry.dependX := 0;
catalogEntry.dependN := 0;
catalogEntry.allDataPresent := TRUE;
catalogEntry.filePath := missingPath;
catalogEntry.fileNumber := succ(length(rpm.register));
catalogEntry.dirty := TRUE;
if length(data) >= 2 ** 32 then
rpm.useLongFileSizes := TRUE;
end if;
setDirIndexAndBaseName(rpm, catalogEntry);
rpm.catalog @:= [missingPath] catalogEntry;
rpm.register @:= [missingPath] catalogEntry.fileNumber;
putFile(rpm.archive, archiveFilePath(rpm.archive, missingPath), data);
end if;
end if;
end func;
const proc: makeDir (inout rpmArchive: rpm, in string: dirPath) is func
local
var rpmCatalogEntry: catalogEntry is rpmCatalogEntry.value;
var boolean: fileExists is TRUE;
var integer: fileNumber is 0;
var integer: length is 0;
begin
if dirPath = "" or dirPath <> "/" and endsWith(dirPath, "/") then
raise RANGE_ERROR;
elsif dirPath in rpm.catalog then
fileNumber := rpm.catalog[dirPath].fileNumber;
elsif implicitDir(rpm.register, dirPath) then
fileNumber := addImplicitDir(rpm, dirPath).fileNumber;
else
fileExists := FALSE;
end if;
if fileExists and fileNumber <> 0 then
raise FILE_ERROR;
else
if rpm.archive = fileSys.value then
getArchive(rpm);
end if;
catalogEntry.fileSize := 0;
catalogEntry.mode := ord(MODE_FILE_DIR) + 8#775;
catalogEntry.uid := 0;
catalogEntry.gid := 0;
catalogEntry.rdev := 0;
catalogEntry.mtime := timestamp1970(time(NOW));
catalogEntry.digest := "";
catalogEntry.linkTo := "";
catalogEntry.flags := 0;
catalogEntry.userName := "";
catalogEntry.groupName := "";
catalogEntry.verifyFlags := RPM_ALL_VERIFY_FLAGS;
catalogEntry.device := 1;
incr(rpm.maximumInode);
catalogEntry.inode := rpm.maximumInode;
catalogEntry.lang := "";
catalogEntry.color := 0;
catalogEntry.fileClass := getNameIndex(rpm.classDict, "directory");
catalogEntry.dependX := 0;
catalogEntry.dependN := 0;
catalogEntry.allDataPresent := TRUE;
catalogEntry.filePath := dirPath;
catalogEntry.fileNumber := succ(length(rpm.register));
catalogEntry.dirty := TRUE;
setDirIndexAndBaseName(rpm, catalogEntry);
rpm.catalog @:= [dirPath] catalogEntry;
rpm.register @:= [dirPath] catalogEntry.fileNumber;
makeDir(rpm.archive, archiveFilePath(rpm.archive, dirPath));
end if;
end func;
const proc: removeFile (inout rpmArchive: rpm, in string: filePath) is func
local
var rpmCatalogEntry: catalogEntry is rpmCatalogEntry.value;
var boolean: fileExists is TRUE;
begin
if filePath <> "/" and endsWith(filePath, "/") then
raise RANGE_ERROR;
elsif filePath in rpm.catalog then
catalogEntry := rpm.catalog[filePath];
elsif implicitDir(rpm.register, filePath) then
catalogEntry := addImplicitDir(rpm, filePath);
else
fileExists := FALSE;
end if;
if fileExists and
(bin32(catalogEntry.mode) & MODE_FILE_TYPE_MASK = MODE_FILE_REGULAR or
bin32(catalogEntry.mode) & MODE_FILE_TYPE_MASK = MODE_FILE_CHAR or
bin32(catalogEntry.mode) & MODE_FILE_TYPE_MASK = MODE_FILE_BLOCK or
bin32(catalogEntry.mode) & MODE_FILE_TYPE_MASK = MODE_FILE_FIFO or
bin32(catalogEntry.mode) & MODE_FILE_TYPE_MASK = MODE_FILE_SYMLINK or
bin32(catalogEntry.mode) & MODE_FILE_TYPE_MASK = MODE_FILE_SOCKET or
(bin32(catalogEntry.mode) & MODE_FILE_TYPE_MASK = MODE_FILE_DIR and
isEmptyDir(rpm.register, filePath))) then
if rpm.archive = fileSys.value then
getArchive(rpm);
end if;
excl(rpm.register, filePath);
excl(rpm.catalog, filePath);
fixRegisterAndCatalog(rpm, catalogEntry.fileNumber, -1);
removeFile(rpm.archive, archiveFilePath(rpm.archive, filePath));
rpm.dirty := TRUE;
else
raise FILE_ERROR;
end if;
end func;
const proc: for (inout string: filePath) range (inout rpmArchive: rpm) do
(in proc: statements)
end for is func
begin
for key filePath range rpm.register do
statements;
end for;
end func;
const func file: openFileInRpm (inout rpmArchive: rpm, in string: filePath,
in string: mode) is func
result
var file: newFile is STD_NULL;
begin
if mode = "r" then
if filePath <> "/" and endsWith(filePath, "/") then
raise RANGE_ERROR;
elsif filePath in rpm.catalog then
if rpm.archive = fileSys.value then
getArchive(rpm);
end if;
newFile := open(rpm.archive, archiveFilePath(rpm.archive, filePath), mode);
end if;
end if;
end func;
const func file: open (inout rpmArchive: rpm, in string: filePath,
in string: mode) is
return openFileInRpm(rpm, filePath, mode);