~noskcaj/ubuntu/trusty/libextractor/merge

« back to all changes in this revision

Viewing changes to src/plugins/rpm/rpmextractor.c

  • Committer: Bazaar Package Importer
  • Author(s): Luca Falavigna
  • Date: 2008-11-10 22:21:49 UTC
  • mfrom: (1.10.3 upstream) (5.1.2 sid)
  • Revision ID: james.westby@ubuntu.com-20081110222149-pr35f3nmqy5cf52i
Tags: 0.5.21+dfsg-1ubuntu1
* Merge from Debian unstable, remaining Ubuntu changes:
  - (Build-)depend on libltdl7-dev (Ubuntu-specific change).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
     This file is part of libextractor.
3
 
     (C) 2002, 2003 Vidyut Samanta and Christian Grothoff
 
3
     (C) 2002, 2003, 2008 Vidyut Samanta and Christian Grothoff
4
4
 
5
5
     libextractor is free software; you can redistribute it and/or modify
6
6
     it under the terms of the GNU General Public License as published
20
20
 
21
21
#include "platform.h"
22
22
#include "extractor.h"
23
 
 
24
 
/* someone was using this non-portable function.  Mac OS X
25
 
 * doesn't have it so rpmextractor wouldn't load.  I rewrite
26
 
 * the function so that it will now work.  below is the
27
 
 * original FIXME notice.  -- Filip Pizlo 2003 */
28
 
/* FIXME: replace use of stpcpy to increase portability */
29
 
static char *
30
 
my_stpcpy (char *dest, const char *src)
31
 
{
32
 
  strcpy (dest, src);
33
 
  return dest + strlen (src);
34
 
}
35
 
 
36
 
/* **************** buffer-based IO ************** */
37
 
 
38
 
typedef struct
39
 
{
40
 
  char *data;
 
23
#include <rpm/rpmlib.h>
 
24
#include <rpm/rpmts.h>
 
25
#include <pthread.h>
 
26
#include <sys/types.h>
 
27
#include <signal.h>
 
28
 
 
29
/* ******************** pipe feeder ************************ */
 
30
 
 
31
struct PipeArgs {                              
 
32
  const char * data;
41
33
  size_t pos;
42
 
  size_t len;
43
 
} fdStruct;
44
 
 
45
 
typedef fdStruct *FD_t;
46
 
 
47
 
static int
48
 
timedRead (FD_t f, void *dst, size_t n)
49
 
{
50
 
  size_t min;
51
 
 
52
 
  if (f->len - f->pos >= n)
53
 
    min = n;
54
 
  else
55
 
    min = f->len - f->pos;
56
 
  memcpy (dst, &f->data[f->pos], min);
57
 
  f->pos += min;
58
 
  return min;
59
 
}
60
 
 
61
 
/* *************** RPM types ************************ */
62
 
 
63
 
typedef int int_32;
64
 
typedef unsigned int uint_32;
65
 
 
66
 
 
67
 
/**
68
 
 * Header private tags.
69
 
 * @note General use tags should start at 1000 (RPM's tag space starts there).
70
 
 */
71
 
#define HEADER_IMAGE            61
72
 
#define HEADER_SIGNATURES       62
73
 
#define HEADER_IMMUTABLE        63
74
 
#define HEADER_REGIONS          64
75
 
#define HEADER_I18NTABLE        100
76
 
#define HEADER_SIGBASE          256
77
 
#define HEADER_TAGBASE          1000
78
 
 
79
 
/**
80
 
 * Tags identify data in package headers.
81
 
 * @note tags should not have value 0!
82
 
 */
83
 
typedef enum rpmTag_e
84
 
{
85
 
 
86
 
  RPMTAG_HEADERIMAGE = HEADER_IMAGE,    /*!< Current image. */
87
 
  RPMTAG_HEADERSIGNATURES = HEADER_SIGNATURES,  /*!< Signatures. */
88
 
  RPMTAG_HEADERIMMUTABLE = HEADER_IMMUTABLE,    /*!< Original image. */
89
 
/*@-enummemuse@*/
90
 
  RPMTAG_HEADERREGIONS = HEADER_REGIONS,        /*!< Regions. */
91
 
 
92
 
  RPMTAG_HEADERI18NTABLE = HEADER_I18NTABLE,    /*!< I18N string locales. */
93
 
/*@=enummemuse@*/
94
 
 
95
 
/* Retrofit (and uniqify) signature tags for use by tagName() and rpmQuery. */
96
 
/* the md5 sum was broken *twice* on big endian machines */
97
 
/* XXX 2nd underscore prevents tagTable generation */
98
 
  RPMTAG_SIG_BASE = HEADER_SIGBASE,
99
 
  RPMTAG_SIGSIZE = RPMTAG_SIG_BASE + 1,
100
 
  RPMTAG_SIGLEMD5_1 = RPMTAG_SIG_BASE + 2,      /*!< internal - obsolate */
101
 
  RPMTAG_SIGPGP = RPMTAG_SIG_BASE + 3,
102
 
  RPMTAG_SIGLEMD5_2 = RPMTAG_SIG_BASE + 4,      /*!< internal - obsolate */
103
 
  RPMTAG_SIGMD5 = RPMTAG_SIG_BASE + 5,
104
 
  RPMTAG_SIGGPG = RPMTAG_SIG_BASE + 6,
105
 
  RPMTAG_SIGPGP5 = RPMTAG_SIG_BASE + 7, /*!< internal - obsolate */
106
 
 
107
 
  RPMTAG_BADSHA1_1 = RPMTAG_SIG_BASE + 8,       /*!< internal - obsolate */
108
 
  RPMTAG_BADSHA1_2 = RPMTAG_SIG_BASE + 9,       /*!< internal - obsolate */
109
 
 
110
 
  RPMTAG_PUBKEYS = RPMTAG_SIG_BASE + 10,
111
 
  RPMTAG_DSAHEADER = RPMTAG_SIG_BASE + 11,
112
 
  RPMTAG_RSAHEADER = RPMTAG_SIG_BASE + 12,
113
 
  RPMTAG_SHA1HEADER = RPMTAG_SIG_BASE + 13,
114
 
 
115
 
  RPMTAG_NAME = 1000,
116
 
  RPMTAG_VERSION = 1001,
117
 
  RPMTAG_RELEASE = 1002,
118
 
  RPMTAG_EPOCH = 1003,
119
 
#define RPMTAG_SERIAL   RPMTAG_EPOCH    /* backward comaptibility */
120
 
  RPMTAG_SUMMARY = 1004,
121
 
  RPMTAG_DESCRIPTION = 1005,
122
 
  RPMTAG_BUILDTIME = 1006,
123
 
  RPMTAG_BUILDHOST = 1007,
124
 
  RPMTAG_INSTALLTIME = 1008,
125
 
  RPMTAG_SIZE = 1009,
126
 
  RPMTAG_DISTRIBUTION = 1010,
127
 
  RPMTAG_VENDOR = 1011,
128
 
  RPMTAG_GIF = 1012,
129
 
  RPMTAG_XPM = 1013,
130
 
  RPMTAG_LICENSE = 1014,
131
 
#define RPMTAG_COPYRIGHT RPMTAG_LICENSE /* backward comaptibility */
132
 
  RPMTAG_PACKAGER = 1015,
133
 
  RPMTAG_GROUP = 1016,
134
 
/*@-enummemuse@*/
135
 
  RPMTAG_CHANGELOG = 1017,      /*!< internal */
136
 
/*@=enummemuse@*/
137
 
  RPMTAG_SOURCE = 1018,
138
 
  RPMTAG_PATCH = 1019,
139
 
  RPMTAG_URL = 1020,
140
 
  RPMTAG_OS = 1021,
141
 
  RPMTAG_ARCH = 1022,
142
 
  RPMTAG_PREIN = 1023,
143
 
  RPMTAG_POSTIN = 1024,
144
 
  RPMTAG_PREUN = 1025,
145
 
  RPMTAG_POSTUN = 1026,
146
 
  RPMTAG_OLDFILENAMES = 1027,   /* obsolete */
147
 
  RPMTAG_FILESIZES = 1028,
148
 
  RPMTAG_FILESTATES = 1029,
149
 
  RPMTAG_FILEMODES = 1030,
150
 
  RPMTAG_FILEUIDS = 1031,       /*!< internal */
151
 
  RPMTAG_FILEGIDS = 1032,       /*!< internal */
152
 
  RPMTAG_FILERDEVS = 1033,
153
 
  RPMTAG_FILEMTIMES = 1034,
154
 
  RPMTAG_FILEMD5S = 1035,
155
 
  RPMTAG_FILELINKTOS = 1036,
156
 
  RPMTAG_FILEFLAGS = 1037,
157
 
/*@-enummemuse@*/
158
 
  RPMTAG_ROOT = 1038,           /*!< internal - obsolete */
159
 
/*@=enummemuse@*/
160
 
  RPMTAG_FILEUSERNAME = 1039,
161
 
  RPMTAG_FILEGROUPNAME = 1040,
162
 
/*@-enummemuse@*/
163
 
  RPMTAG_EXCLUDE = 1041,        /*!< internal - obsolete */
164
 
  RPMTAG_EXCLUSIVE = 1042,      /*!< internal - obsolete */
165
 
/*@=enummemuse@*/
166
 
  RPMTAG_ICON = 1043,
167
 
  RPMTAG_SOURCERPM = 1044,
168
 
  RPMTAG_FILEVERIFYFLAGS = 1045,
169
 
  RPMTAG_ARCHIVESIZE = 1046,
170
 
  RPMTAG_PROVIDENAME = 1047,
171
 
#define RPMTAG_PROVIDES RPMTAG_PROVIDENAME      /* backward comaptibility */
172
 
  RPMTAG_REQUIREFLAGS = 1048,
173
 
  RPMTAG_REQUIRENAME = 1049,
174
 
  RPMTAG_REQUIREVERSION = 1050,
175
 
  RPMTAG_NOSOURCE = 1051,       /*!< internal */
176
 
  RPMTAG_NOPATCH = 1052,        /*!< internal */
177
 
  RPMTAG_CONFLICTFLAGS = 1053,
178
 
  RPMTAG_CONFLICTNAME = 1054,
179
 
  RPMTAG_CONFLICTVERSION = 1055,
180
 
  RPMTAG_DEFAULTPREFIX = 1056,  /*!< internal - deprecated */
181
 
  RPMTAG_BUILDROOT = 1057,      /*!< internal */
182
 
  RPMTAG_INSTALLPREFIX = 1058,  /*!< internal - deprecated */
183
 
  RPMTAG_EXCLUDEARCH = 1059,
184
 
  RPMTAG_EXCLUDEOS = 1060,
185
 
  RPMTAG_EXCLUSIVEARCH = 1061,
186
 
  RPMTAG_EXCLUSIVEOS = 1062,
187
 
  RPMTAG_AUTOREQPROV = 1063,    /*!< internal */
188
 
  RPMTAG_RPMVERSION = 1064,
189
 
  RPMTAG_TRIGGERSCRIPTS = 1065,
190
 
  RPMTAG_TRIGGERNAME = 1066,
191
 
  RPMTAG_TRIGGERVERSION = 1067,
192
 
  RPMTAG_TRIGGERFLAGS = 1068,
193
 
  RPMTAG_TRIGGERINDEX = 1069,
194
 
  RPMTAG_VERIFYSCRIPT = 1079,
195
 
  RPMTAG_CHANGELOGTIME = 1080,
196
 
  RPMTAG_CHANGELOGNAME = 1081,
197
 
  RPMTAG_CHANGELOGTEXT = 1082,
198
 
/*@-enummemuse@*/
199
 
  RPMTAG_BROKENMD5 = 1083,      /*!< internal */
200
 
/*@=enummemuse@*/
201
 
  RPMTAG_PREREQ = 1084,         /*!< internal */
202
 
  RPMTAG_PREINPROG = 1085,
203
 
  RPMTAG_POSTINPROG = 1086,
204
 
  RPMTAG_PREUNPROG = 1087,
205
 
  RPMTAG_POSTUNPROG = 1088,
206
 
  RPMTAG_BUILDARCHS = 1089,
207
 
  RPMTAG_OBSOLETENAME = 1090,
208
 
#define RPMTAG_OBSOLETES RPMTAG_OBSOLETENAME    /* backward comaptibility */
209
 
  RPMTAG_VERIFYSCRIPTPROG = 1091,
210
 
  RPMTAG_TRIGGERSCRIPTPROG = 1092,
211
 
  RPMTAG_DOCDIR = 1093,         /*!< internal */
212
 
  RPMTAG_COOKIE = 1094,
213
 
  RPMTAG_FILEDEVICES = 1095,
214
 
  RPMTAG_FILEINODES = 1096,
215
 
  RPMTAG_FILELANGS = 1097,
216
 
  RPMTAG_PREFIXES = 1098,
217
 
  RPMTAG_INSTPREFIXES = 1099,
218
 
  RPMTAG_TRIGGERIN = 1100,      /*!< internal */
219
 
  RPMTAG_TRIGGERUN = 1101,      /*!< internal */
220
 
  RPMTAG_TRIGGERPOSTUN = 1102,  /*!< internal */
221
 
  RPMTAG_AUTOREQ = 1103,        /*!< internal */
222
 
  RPMTAG_AUTOPROV = 1104,       /*!< internal */
223
 
/*@-enummemuse@*/
224
 
  RPMTAG_CAPABILITY = 1105,     /*!< internal - obsolete */
225
 
/*@=enummemuse@*/
226
 
  RPMTAG_SOURCEPACKAGE = 1106,  /*!< internal */
227
 
/*@-enummemuse@*/
228
 
  RPMTAG_OLDORIGFILENAMES = 1107,       /*!< internal - obsolete */
229
 
/*@=enummemuse@*/
230
 
  RPMTAG_BUILDPREREQ = 1108,    /*!< internal */
231
 
  RPMTAG_BUILDREQUIRES = 1109,  /*!< internal */
232
 
  RPMTAG_BUILDCONFLICTS = 1110, /*!< internal */
233
 
/*@-enummemuse@*/
234
 
  RPMTAG_BUILDMACROS = 1111,    /*!< internal */
235
 
/*@=enummemuse@*/
236
 
  RPMTAG_PROVIDEFLAGS = 1112,
237
 
  RPMTAG_PROVIDEVERSION = 1113,
238
 
  RPMTAG_OBSOLETEFLAGS = 1114,
239
 
  RPMTAG_OBSOLETEVERSION = 1115,
240
 
  RPMTAG_DIRINDEXES = 1116,
241
 
  RPMTAG_BASENAMES = 1117,
242
 
  RPMTAG_DIRNAMES = 1118,
243
 
  RPMTAG_ORIGDIRINDEXES = 1119, /*!< internal */
244
 
  RPMTAG_ORIGBASENAMES = 1120,  /*!< internal */
245
 
  RPMTAG_ORIGDIRNAMES = 1121,   /*!< internal */
246
 
  RPMTAG_OPTFLAGS = 1122,
247
 
  RPMTAG_DISTURL = 1123,
248
 
  RPMTAG_PAYLOADFORMAT = 1124,
249
 
  RPMTAG_PAYLOADCOMPRESSOR = 1125,
250
 
  RPMTAG_PAYLOADFLAGS = 1126,
251
 
  RPMTAG_MULTILIBS = 1127,
252
 
  RPMTAG_INSTALLTID = 1128,
253
 
  RPMTAG_REMOVETID = 1129,
254
 
  RPMTAG_SHA1RHN = 1130,        /*!< internal */
255
 
  RPMTAG_RHNPLATFORM = 1131,
256
 
  RPMTAG_PLATFORM = 1132,
257
 
/*@-enummemuse@*/
258
 
  RPMTAG_FIRSTFREE_TAG          /*!< internal */
259
 
/*@=enummemuse@*/
260
 
} rpmTag;
261
 
 
262
 
#define RPMTAG_EXTERNAL_TAG             1000000
263
 
 
264
 
/** \ingroup signature
265
 
 * Tags found in signature header from package.
266
 
 */
267
 
enum rpmtagSignature
268
 
{
269
 
  RPMSIGTAG_SIZE = 1000,        /*!< Header+Payload size in bytes. */
270
 
/* the md5 sum was broken *twice* on big endian machines */
271
 
  RPMSIGTAG_LEMD5_1 = 1001,     /*!< Broken MD5, take 1 */
272
 
  RPMSIGTAG_PGP = 1002,         /*!< PGP 2.6.3 signature. */
273
 
  RPMSIGTAG_LEMD5_2 = 1003,     /*!< Broken MD5, take 2 */
274
 
  RPMSIGTAG_MD5 = 1004,         /*!< MD5 signature. */
275
 
  RPMSIGTAG_GPG = 1005,         /*!< GnuPG signature. */
276
 
  RPMSIGTAG_PGP5 = 1006,        /*!< PGP5 signature @deprecated legacy. */
277
 
  RPMSIGTAG_PAYLOADSIZE = 1007,
278
 
  /*!< uncompressed payload size in bytes. */
279
 
  RPMSIGTAG_BADSHA1_1 = RPMTAG_BADSHA1_1,       /*!< Broken SHA1, take 1. */
280
 
  RPMSIGTAG_BADSHA1_2 = RPMTAG_BADSHA1_2,       /*!< Broken SHA1, take 2. */
281
 
  RPMSIGTAG_SHA1 = RPMTAG_SHA1HEADER,   /*!< sha1 header digest. */
282
 
  RPMSIGTAG_DSA = RPMTAG_DSAHEADER,     /*!< DSA header signature. */
283
 
  RPMSIGTAG_RSA = RPMTAG_RSAHEADER      /*!< RSA header signature. */
284
 
};
285
 
 
286
 
/**
287
 
 * Dependency Attributes.
288
 
 */
289
 
typedef enum rpmsenseFlags_e
290
 
{
291
 
  RPMSENSE_ANY = 0,
292
 
/*@-enummemuse@*/
293
 
  RPMSENSE_SERIAL = (1 << 0),   /*!< @todo Legacy. */
294
 
/*@=enummemuse@*/
295
 
  RPMSENSE_LESS = (1 << 1),
296
 
  RPMSENSE_GREATER = (1 << 2),
297
 
  RPMSENSE_EQUAL = (1 << 3),
298
 
  RPMSENSE_PROVIDES = (1 << 4), /* only used internally by builds */
299
 
  RPMSENSE_CONFLICTS = (1 << 5),        /* only used internally by builds */
300
 
  RPMSENSE_PREREQ = (1 << 6),   /*!< @todo Legacy. */
301
 
  RPMSENSE_OBSOLETES = (1 << 7),        /* only used internally by builds */
302
 
  RPMSENSE_INTERP = (1 << 8),   /*!< Interpreter used by scriptlet. */
303
 
  RPMSENSE_SCRIPT_PRE = ((1 << 9) | RPMSENSE_PREREQ),   /*!< %pre dependency. */
304
 
  RPMSENSE_SCRIPT_POST = ((1 << 10) | RPMSENSE_PREREQ), /*!< %post dependency. */
305
 
  RPMSENSE_SCRIPT_PREUN = ((1 << 11) | RPMSENSE_PREREQ),        /*!< %preun dependency. */
306
 
  RPMSENSE_SCRIPT_POSTUN = ((1 << 12) | RPMSENSE_PREREQ),       /*!< %postun dependency. */
307
 
  RPMSENSE_SCRIPT_VERIFY = (1 << 13),   /*!< %verify dependency. */
308
 
  RPMSENSE_FIND_REQUIRES = (1 << 14),   /*!< find-requires generated dependency. */
309
 
  RPMSENSE_FIND_PROVIDES = (1 << 15),   /*!< find-provides generated dependency. */
310
 
 
311
 
  RPMSENSE_TRIGGERIN = (1 << 16),       /*!< %triggerin dependency. */
312
 
  RPMSENSE_TRIGGERUN = (1 << 17),       /*!< %triggerun dependency. */
313
 
  RPMSENSE_TRIGGERPOSTUN = (1 << 18),   /*!< %triggerpostun dependency. */
314
 
  RPMSENSE_MULTILIB = (1 << 19),
315
 
  RPMSENSE_SCRIPT_PREP = (1 << 20),     /*!< %prep build dependency. */
316
 
  RPMSENSE_SCRIPT_BUILD = (1 << 21),    /*!< %build build dependency. */
317
 
  RPMSENSE_SCRIPT_INSTALL = (1 << 22),  /*!< %install build dependency. */
318
 
  RPMSENSE_SCRIPT_CLEAN = (1 << 23),    /*!< %clean build dependency. */
319
 
  RPMSENSE_RPMLIB = ((1 << 24) | RPMSENSE_PREREQ),      /*!< rpmlib(feature) dependency. */
320
 
/*@-enummemuse@*/
321
 
  RPMSENSE_TRIGGERPREIN = (1 << 25),    /*!< @todo Implement %triggerprein. */
322
 
/*@=enummemuse@*/
323
 
 
324
 
/*@-enummemuse@*/
325
 
  RPMSENSE_KEYRING = (1 << 26)
326
 
/*@=enummemuse@*/
327
 
} rpmsenseFlags;
328
 
 
329
 
/** \ingroup header
330
 
 * Include calculation for 8 bytes of (magic, 0)?
331
 
 */
332
 
enum hMagic
333
 
{
334
 
  HEADER_MAGIC_NO = 0,
335
 
  HEADER_MAGIC_YES = 1
336
 
};
337
 
 
338
 
/**
339
 
 * Package read return codes.
340
 
 */
341
 
typedef enum rpmRC_e
342
 
{
343
 
  RPMRC_OK = 0,
344
 
  RPMRC_BADMAGIC = 1,
345
 
  RPMRC_FAIL = 2,
346
 
  RPMRC_BADSIZE = 3,
347
 
  RPMRC_SHORTREAD = 4
348
 
} rpmRC;
349
 
 
350
 
/** \ingroup header
351
 
 * The basic types of data in tags from headers.
352
 
 */
353
 
typedef enum rpmTagType_e
354
 
{
355
 
#define RPM_MIN_TYPE            0
356
 
  RPM_NULL_TYPE = 0,
357
 
  RPM_CHAR_TYPE = 1,
358
 
  RPM_INT8_TYPE = 2,
359
 
  RPM_INT16_TYPE = 3,
360
 
  RPM_INT32_TYPE = 4,
361
 
/*    RPM_INT64_TYPE    = 5,   ---- These aren't supported (yet) */
362
 
  RPM_STRING_TYPE = 6,
363
 
  RPM_BIN_TYPE = 7,
364
 
  RPM_STRING_ARRAY_TYPE = 8,
365
 
  RPM_I18NSTRING_TYPE = 9
366
 
#define RPM_MAX_TYPE            9
367
 
} rpmTagType;
368
 
 
369
 
/*
370
 
 * Teach header.c about legacy tags.
371
 
 */
372
 
#define HEADER_OLDFILENAMES     1027
373
 
#define HEADER_BASENAMES        1117
374
 
 
375
 
#define REGION_TAG_TYPE         RPM_BIN_TYPE
376
 
#define REGION_TAG_COUNT        sizeof(struct entryInfo)
377
 
 
378
 
#define RPMLEAD_BINARY 0
379
 
#define RPMLEAD_SOURCE 1
380
 
 
381
 
#define RPMLEAD_MAGIC0 0xed
382
 
#define RPMLEAD_MAGIC1 0xab
383
 
#define RPMLEAD_MAGIC2 0xee
384
 
#define RPMLEAD_MAGIC3 0xdb
385
 
 
386
 
#define RPMLEAD_SIZE 96         /*!< Don't rely on sizeof(struct) */
387
 
 
388
 
/** \ingroup header
389
 
 * Maximum no. of bytes permitted in a header.
390
 
 */
391
 
/*@unchecked@*/
392
 
static size_t headerMaxbytes = (32 * 1024 * 1024);
393
 
 
394
 
/** \ingroup lead
395
 
 * The lead data structure.
396
 
 * The lead needs to be 8 byte aligned.
397
 
 * @deprecated The lead (except for signature_type) is legacy.
398
 
 * @todo Don't use any information from lead.
399
 
 */
400
 
struct rpmlead
401
 
{
402
 
  unsigned char magic[4];
403
 
  unsigned char major, minor;
404
 
  short type;
405
 
  short archnum;
406
 
  char name[66];
407
 
  short osnum;
408
 
  short signature_type;         /*!< Signature header type (RPMSIG_HEADERSIG) */
409
 
                                        /*@unused@*/ char reserved[16];
410
 
                                        /*!< Pad to 96 bytes -- 8 byte aligned */
411
 
};
412
 
 
413
 
/** \ingroup header
414
 
 * Alignment needs (and sizeof scalars types) for internal rpm data types.
415
 
 */
416
 
               /*@observer@*//*@unchecked@ */
417
 
static int typeSizes[] = {
418
 
  0,                            /*!< RPM_NULL_TYPE */
419
 
  1,                            /*!< RPM_CHAR_TYPE */
420
 
  1,                            /*!< RPM_INT8_TYPE */
421
 
  2,                            /*!< RPM_INT16_TYPE */
422
 
  4,                            /*!< RPM_INT32_TYPE */
423
 
  -1,                           /*!< RPM_INT64_TYPE */
424
 
  -1,                           /*!< RPM_STRING_TYPE */
425
 
  1,                            /*!< RPM_BIN_TYPE */
426
 
  -1,                           /*!< RPM_STRING_ARRAY_TYPE */
427
 
  -1                            /*!< RPM_I18NSTRING_TYPE */
428
 
};
429
 
 
430
 
/** \ingroup header
431
 
 */
432
 
enum headerSprintfExtenstionType
433
 
{
434
 
  HEADER_EXT_LAST = 0,          /*!< End of extension chain. */
435
 
  HEADER_EXT_FORMAT,            /*!< headerTagFormatFunction() extension */
436
 
  HEADER_EXT_MORE,              /*!< Chain to next table. */
437
 
  HEADER_EXT_TAG                /*!< headerTagTagFunction() extension */
438
 
};
439
 
 
440
 
/** \ingroup signature
441
 
 * Signature types stored in rpm lead.
442
 
 */
443
 
typedef enum sigType_e
444
 
{
445
 
  RPMSIGTYPE_NONE = 0,          /*!< unused, legacy. */
446
 
  RPMSIGTYPE_PGP262_1024 = 1,   /*!< unused, legacy. */
447
 
/*@-enummemuse@*/
448
 
  RPMSIGTYPE_BAD = 2,           /*!< Unknown signature type. */
449
 
/*@=enummemuse@*/
450
 
  RPMSIGTYPE_MD5 = 3,           /*!< unused, legacy. */
451
 
  RPMSIGTYPE_MD5_PGP = 4,       /*!< unused, legacy. */
452
 
  RPMSIGTYPE_HEADERSIG = 5,     /*!< Header style signature */
453
 
  RPMSIGTYPE_DISABLE = 6        /*!< Disable verification (debugging only) */
454
 
} sigType;
455
 
 
456
 
/** \ingroup header
457
 
 * HEADER_EXT_TAG format function prototype.
458
 
 * This will only ever be passed RPM_INT32_TYPE or RPM_STRING_TYPE to
459
 
 * help keep things simple.
460
 
 *
461
 
 * @param type          tag type
462
 
 * @param data          tag value
463
 
 * @param formatPrefix
464
 
 * @param padding
465
 
 * @param element
466
 
 * @return              formatted string
467
 
 */
468
 
typedef /*only@ */ char *(*headerTagFormatFunction) (int_32 type,
469
 
                                                     const void *data,
470
 
                                                     char *formatPrefix,
471
 
                                                     int padding,
472
 
                                                     int element);
473
 
 
474
 
 
475
 
/** \ingroup header
476
 
 * Associate tag names with numeric values.
477
 
 */
478
 
typedef /*@abstract@ */ struct headerTagTableEntry_s *headerTagTableEntry;
479
 
struct headerTagTableEntry_s
480
 
{
481
 
                                                /*@observer@*//*@null@ */ const char *name;
482
 
                                                /*!< Tag name. */
483
 
  int val;                      /*!< Tag numeric value. */
484
 
};
485
 
 
486
 
/** \ingroup header
487
 
 */
488
 
typedef /*@abstract@ */ struct headerIteratorS *HeaderIterator;
489
 
 
490
 
/** \ingroup header
491
 
 */
492
 
typedef /*@abstract@ *//*@refcounted@ */ struct headerToken *Header;
493
 
 
494
 
 
495
 
typedef int_32 *hTYP_t;
496
 
typedef const void *hPTR_t;
497
 
typedef int_32 *hCNT_t;
498
 
 
499
 
/** \ingroup header
500
 
 * HEADER_EXT_FORMAT format function prototype.
501
 
 * This is allowed to fail, which indicates the tag doesn't exist.
502
 
 *
503
 
 * @param h             header
504
 
 * @retval type         address of tag type
505
 
 * @retval data         address of tag value pointer
506
 
 * @retval count        address of no. of data items
507
 
 * @retval freedata     address of data-was-malloc'ed indicator
508
 
 * @return              0 on success
509
 
 */
510
 
typedef int (*headerTagTagFunction) (Header h,
511
 
                                     /*@null@ *//*@out@ */ hTYP_t type,
512
 
                                     /*@null@ *//*@out@ */ hPTR_t * data,
513
 
                                     /*@null@ *//*@out@ */ hCNT_t count,
514
 
                                     /*@null@ *//*@out@ */ int *freeData);
515
 
 
516
 
/** \ingroup header
517
 
 * Define header tag output formats.
518
 
 */
519
 
typedef /*@abstract@ */ struct headerSprintfExtension_s
520
 
  *headerSprintfExtension;
521
 
struct headerSprintfExtension_s
522
 
{
523
 
  enum headerSprintfExtenstionType type;        /*!< Type of extension. */
524
 
  /*@observer@*//*@null@ */
525
 
  const char *name;             /*!< Name of extension. */
526
 
  union
527
 
  {
528
 
    /*@observer@*//*@null@ */
529
 
    void *generic;              /*!< Private extension. */
530
 
    headerTagFormatFunction formatFunction;     /*!< HEADER_EXT_TAG extension. */
531
 
    headerTagTagFunction tagFunction;   /*!< HEADER_EXT_FORMAT extension. */
532
 
    struct headerSprintfExtension_s *more;      /*!< Chained table extension. */
533
 
  } u;
534
 
};
535
 
 
536
 
/** \ingroup header
537
 
 * Create new (empty) header instance.
538
 
 * @return              header
539
 
 */
540
 
typedef Header (*HDRnew) (void)
541
 
        /*@ */ ;
542
 
 
543
 
/** \ingroup header
544
 
 * Dereference a header instance.
545
 
 * @param h             header
546
 
 * @return              NULL always
547
 
 */
548
 
typedef
549
 
/*@null@*/ Header (*HDRfree) ( /*@null@ *//*@killref@ */ Header h)
550
 
        /*@modifies h @ */ ;
551
 
 
552
 
/** \ingroup header
553
 
 * Reference a header instance.
554
 
 * @param h             header
555
 
 * @return              referenced header instance
556
 
 */
557
 
typedef Header (*HDRlink) (Header h)
558
 
        /*@modifies h @ */ ;
559
 
 
560
 
/** \ingroup header
561
 
 * Dereference a header instance.
562
 
 * @param h             header
563
 
 * @return              NULL always
564
 
 */
565
 
typedef Header (*HDRunlink) ( /*@killref@ *//*@null@ */ Header h)
566
 
         /*@modifies h @ */ ;
567
 
 
568
 
/** \ingroup header
569
 
 * Sort tags in header.
570
 
 * @todo Eliminate from API.
571
 
 * @param h             header
572
 
 */
573
 
typedef void (*HDRsort) (Header h)
574
 
        /*@modifies h @ */ ;
575
 
 
576
 
/** \ingroup header
577
 
 * Restore tags in header to original ordering.
578
 
 * @todo Eliminate from API.
579
 
 * @param h             header
580
 
 */
581
 
typedef void (*HDRunsort) (Header h)
582
 
        /*@modifies h @ */ ;
583
 
 
584
 
/** \ingroup header
585
 
 * Return size of on-disk header representation in bytes.
586
 
 * @param h             header
587
 
 * @param magicp        include size of 8 bytes for (magic, 0)?
588
 
 * @return              size of on-disk header
589
 
 */
590
 
typedef unsigned int (*HDRsizeof) ( /*@null@ */ Header h, enum hMagic magicp)
591
 
        /*@modifies h @ */ ;
592
 
 
593
 
/** \ingroup header
594
 
 * Convert header to on-disk representation.
595
 
 * @param h             header (with pointers)
596
 
 * @return              on-disk header blob (i.e. with offsets)
597
 
 */
598
 
typedef
599
 
           /*@only@*//*@null@ */ void *(*HDRunload) (Header h)
600
 
        /*@modifies h @ */ ;
601
 
 
602
 
/** \ingroup header
603
 
 * Convert header to on-disk representation, and then reload.
604
 
 * This is used to insure that all header data is in one chunk.
605
 
 * @param h             header (with pointers)
606
 
 * @param tag           region tag
607
 
 * @return              on-disk header (with offsets)
608
 
 */
609
 
typedef
610
 
/*@null@*/ Header (*HDRreload) ( /*@only@ */ Header h, int tag)
611
 
        /*@modifies h @ */ ;
612
 
 
613
 
/** \ingroup header
614
 
 * Duplicate a header.
615
 
 * @param h             header
616
 
 * @return              new header instance
617
 
 */
618
 
typedef Header (*HDRcopy) (Header h)
619
 
        /*@modifies h @ */ ;
620
 
 
621
 
/** \ingroup header
622
 
 * Convert header to in-memory representation.
623
 
 * @param uh            on-disk header blob (i.e. with offsets)
624
 
 * @return              header
625
 
 */
626
 
typedef
627
 
/*@null@*/ Header (*HDRload) ( /*@kept@ */ void *uh)
628
 
        /*@modifies uh @ */ ;
629
 
 
630
 
/** \ingroup header
631
 
 * Make a copy and convert header to in-memory representation.
632
 
 * @param uh            on-disk header blob (i.e. with offsets)
633
 
 * @return              header
634
 
 */
635
 
typedef
636
 
/*@null@*/ Header (*HDRcopyload) (const void *uh)
637
 
        /*@ */ ;
638
 
 
639
 
/** \ingroup header
640
 
 * Read (and load) header from file handle.
641
 
 * @param fd            file handle
642
 
 * @param magicp        read (and verify) 8 bytes of (magic, 0)?
643
 
 * @return              header (or NULL on error)
644
 
 */
645
 
typedef
646
 
/*@null@*/ Header (*HDRhdrread) (FD_t fd, enum hMagic magicp)
647
 
        /*@modifies fd @ */ ;
648
 
 
649
 
/** \ingroup header
650
 
 * Write (with unload) header to file handle.
651
 
 * @param fd            file handle
652
 
 * @param h             header
653
 
 * @param magicp        prefix write with 8 bytes of (magic, 0)?
654
 
 * @return              0 on success, 1 on error
655
 
 */
656
 
typedef int (*HDRhdrwrite) (FD_t fd, /*@null@ */ Header h, enum hMagic magicp)
657
 
        /*@globals fileSystem @ */
658
 
        /*@modifies fd, h, fileSystem @ */ ;
659
 
 
660
 
/** \ingroup header
661
 
 * Check if tag is in header.
662
 
 * @param h             header
663
 
 * @param tag           tag
664
 
 * @return              1 on success, 0 on failure
665
 
 */
666
 
typedef int (*HDRisentry) ( /*@null@ */ Header h, int_32 tag)
667
 
        /*@ */ ;
668
 
 
669
 
/** \ingroup header
670
 
 * Free data allocated when retrieved from header.
671
 
 * @param h             header
672
 
 * @param data          address of data (or NULL)
673
 
 * @param type          type of data (or -1 to force free)
674
 
 * @return              NULL always
675
 
 */
676
 
typedef
677
 
/*@null@*/ void *(*HDRfreetag) (Header h,
678
 
                                /*@only@ *//*@null@ */ const void *data,
679
 
                                rpmTagType type)
680
 
        /*@modifies data @ */ ;
681
 
 
682
 
/** \ingroup header
683
 
 * Retrieve tag value.
684
 
 * Will never return RPM_I18NSTRING_TYPE! RPM_STRING_TYPE elements with
685
 
 * RPM_I18NSTRING_TYPE equivalent entries are translated (if HEADER_I18NTABLE
686
 
 * entry is present).
687
 
 *
688
 
 * @param h             header
689
 
 * @param tag           tag
690
 
 * @retval type         address of tag value data type (or NULL)
691
 
 * @retval p            address of pointer to tag value(s) (or NULL)
692
 
 * @retval c            address of number of values (or NULL)
693
 
 * @return              1 on success, 0 on failure
694
 
 */
695
 
typedef int (*HDRget) (Header h, int_32 tag,
696
 
                       /*@null@ *//*@out@ */ hTYP_t type,
697
 
                       /*@null@ *//*@out@ */ void **p,
698
 
                       /*@null@ *//*@out@ */ hCNT_t c)
699
 
        /*@modifies *type, *p, *c @ */ ;
700
 
 
701
 
/** \ingroup header
702
 
 * Retrieve tag value using header internal array.
703
 
 * Get an entry using as little extra RAM as possible to return the tag value.
704
 
 * This is only an issue for RPM_STRING_ARRAY_TYPE.
705
 
 *
706
 
 * @param h             header
707
 
 * @param tag           tag
708
 
 * @retval type         address of tag value data type (or NULL)
709
 
 * @retval p            address of pointer to tag value(s) (or NULL)
710
 
 * @retval c            address of number of values (or NULL)
711
 
 * @return              1 on success, 0 on failure
712
 
 */
713
 
typedef int (*HDRgetmin) (Header h, int_32 tag,
714
 
                          /*@null@ *//*@out@ */ hTYP_t type,
715
 
                          /*@null@ *//*@out@ */ hPTR_t * p,
716
 
                          /*@null@ *//*@out@ */ hCNT_t c)
717
 
        /*@modifies *type, *p, *c @ */ ;
718
 
 
719
 
/** \ingroup header
720
 
 * Add tag to header.
721
 
 * Duplicate tags are okay, but only defined for iteration (with the
722
 
 * exceptions noted below). While you are allowed to add i18n string
723
 
 * arrays through this function, you probably don't mean to. See
724
 
 * headerAddI18NString() instead.
725
 
 *
726
 
 * @param h             header
727
 
 * @param tag           tag
728
 
 * @param type          tag value data type
729
 
 * @param p             pointer to tag value(s)
730
 
 * @param c             number of values
731
 
 * @return              1 on success, 0 on failure
732
 
 */
733
 
typedef
734
 
  int (*HDRadd) (Header h, int_32 tag, int_32 type, const void *p, int_32 c)
735
 
        /*@modifies h @ */ ;
736
 
 
737
 
/** \ingroup header
738
 
 * Append element to tag array in header.
739
 
 * Appends item p to entry w/ tag and type as passed. Won't work on
740
 
 * RPM_STRING_TYPE. Any pointers into header memory returned from
741
 
 * headerGetEntryMinMemory() for this entry are invalid after this
742
 
 * call has been made!
743
 
 *
744
 
 * @param h             header
745
 
 * @param tag           tag
746
 
 * @param type          tag value data type
747
 
 * @param p             pointer to tag value(s)
748
 
 * @param c             number of values
749
 
 * @return              1 on success, 0 on failure
750
 
 */
751
 
typedef
752
 
  int (*HDRappend) (Header h, int_32 tag, int_32 type, const void *p,
753
 
                    int_32 c)
754
 
        /*@modifies h @ */ ;
755
 
 
756
 
/** \ingroup header
757
 
 * Add or append element to tag array in header.
758
 
 * @todo Arg "p" should have const.
759
 
 * @param h             header
760
 
 * @param tag           tag
761
 
 * @param type          tag value data type
762
 
 * @param p             pointer to tag value(s)
763
 
 * @param c             number of values
764
 
 * @return              1 on success, 0 on failure
765
 
 */
766
 
typedef
767
 
  int (*HDRaddorappend) (Header h, int_32 tag, int_32 type, const void *p,
768
 
                         int_32 c)
769
 
        /*@modifies h @ */ ;
770
 
 
771
 
/** \ingroup header
772
 
 * Add locale specific tag to header.
773
 
 * A NULL lang is interpreted as the C locale. Here are the rules:
774
 
 * \verbatim
775
 
 *      - If the tag isn't in the header, it's added with the passed string
776
 
 *         as new value.
777
 
 *      - If the tag occurs multiple times in entry, which tag is affected
778
 
 *         by the operation is undefined.
779
 
 *      - If the tag is in the header w/ this language, the entry is
780
 
 *         *replaced* (like headerModifyEntry()).
781
 
 * \endverbatim
782
 
 * This function is intended to just "do the right thing". If you need
783
 
 * more fine grained control use headerAddEntry() and headerModifyEntry().
784
 
 *
785
 
 * @param h             header
786
 
 * @param tag           tag
787
 
 * @param string        tag value
788
 
 * @param lang          locale
789
 
 * @return              1 on success, 0 on failure
790
 
 */
791
 
typedef
792
 
  int (*HDRaddi18n) (Header h, int_32 tag, const char *string,
793
 
                     const char *lang)
794
 
        /*@modifies h @ */ ;
795
 
 
796
 
/** \ingroup header
797
 
 * Modify tag in header.
798
 
 * If there are multiple entries with this tag, the first one gets replaced.
799
 
 * @param h             header
800
 
 * @param tag           tag
801
 
 * @param type          tag value data type
802
 
 * @param p             pointer to tag value(s)
803
 
 * @param c             number of values
804
 
 * @return              1 on success, 0 on failure
805
 
 */
806
 
typedef
807
 
  int (*HDRmodify) (Header h, int_32 tag, int_32 type, const void *p,
808
 
                    int_32 c)
809
 
        /*@modifies h @ */ ;
810
 
 
811
 
/** \ingroup header
812
 
 * Delete tag in header.
813
 
 * Removes all entries of type tag from the header, returns 1 if none were
814
 
 * found.
815
 
 *
816
 
 * @param h             header
817
 
 * @param tag           tag
818
 
 * @return              0 on success, 1 on failure (INCONSISTENT)
819
 
 */
820
 
typedef int (*HDRremove) (Header h, int_32 tag)
821
 
        /*@modifies h @ */ ;
822
 
 
823
 
                /*@-redef@*//* LCL: no clue */
824
 
/** \ingroup header
825
 
 */
826
 
typedef const char *errmsg_t;
827
 
typedef int_32 *hTAG_t;
828
 
 
829
 
/** \ingroup header
830
 
 * Return formatted output string from header tags.
831
 
 * The returned string must be free()d.
832
 
 *
833
 
 * @param h             header
834
 
 * @param fmt           format to use
835
 
 * @param tags          array of tag name/value pairs
836
 
 * @param extensions    chained table of formatting extensions.
837
 
 * @retval errmsg       error message (if any)
838
 
 * @return              formatted output string (malloc'ed)
839
 
 */
840
 
typedef
841
 
/*@only@*/ char *(*HDRhdrsprintf) (Header h, const char *fmt,
842
 
                                   const struct headerTagTableEntry_s * tags,
843
 
                                   const struct headerSprintfExtension_s *
844
 
                                   extensions,
845
 
                                   /*@null@ *//*@out@ */ errmsg_t * errmsg)
846
 
        /*@modifies *errmsg @ */ ;
847
 
 
848
 
/** \ingroup header
849
 
 * Duplicate tag values from one header into another.
850
 
 * @param headerFrom    source header
851
 
 * @param headerTo      destination header
852
 
 * @param tagstocopy    array of tags that are copied
853
 
 */
854
 
typedef
855
 
  void (*HDRcopytags) (Header headerFrom, Header headerTo, hTAG_t tagstocopy)
856
 
        /*@modifies headerFrom, headerTo @ */ ;
857
 
 
858
 
/** \ingroup header
859
 
 * Destroy header tag iterator.
860
 
 * @param hi            header tag iterator
861
 
 * @return              NULL always
862
 
 */
863
 
typedef HeaderIterator (*HDRfreeiter) ( /*@only@ */ HeaderIterator hi)
864
 
        /*@modifies hi @ */ ;
865
 
 
866
 
/** \ingroup header
867
 
 * Create header tag iterator.
868
 
 * @param h             header
869
 
 * @return              header tag iterator
870
 
 */
871
 
typedef HeaderIterator (*HDRinititer) (Header h)
872
 
        /*@modifies h */ ;
873
 
 
874
 
/** \ingroup header
875
 
 * Return next tag from header.
876
 
 * @param hi            header tag iterator
877
 
 * @retval tag          address of tag
878
 
 * @retval type         address of tag value data type
879
 
 * @retval p            address of pointer to tag value(s)
880
 
 * @retval c            address of number of values
881
 
 * @return              1 on success, 0 on failure
882
 
 */
883
 
typedef int (*HDRnextiter) (HeaderIterator hi,
884
 
                            /*@null@ *//*@out@ */ hTAG_t tag,
885
 
                            /*@null@ *//*@out@ */ hTYP_t type,
886
 
                            /*@null@ *//*@out@ */ hPTR_t * p,
887
 
                            /*@null@ *//*@out@ */ hCNT_t c)
888
 
        /*@modifies hi, *tag, *type, *p, *c @ */ ;
889
 
 
890
 
/** \ingroup header
891
 
 * Header method vectors.
892
 
 */
893
 
typedef /*@abstract@ */ struct HV_s *HV_t;
894
 
struct HV_s
895
 
{
896
 
  HDRnew hdrnew;
897
 
  HDRfree hdrfree;
898
 
  HDRlink hdrlink;
899
 
  HDRsort hdrsort;
900
 
  HDRunsort hdrunsort;
901
 
  HDRsizeof hdrsizeof;
902
 
  HDRunload hdrunload;
903
 
  HDRreload hdrreload;
904
 
  HDRcopy hdrcopy;
905
 
  HDRload hdrload;
906
 
  HDRcopyload hdrcopyload;
907
 
  HDRhdrread hdrread;
908
 
  HDRhdrwrite hdrwrite;
909
 
  HDRisentry hdrisentry;
910
 
  HDRfreetag hdrfreetag;
911
 
  HDRget hdrget;
912
 
  HDRgetmin hdrgetmin;
913
 
  HDRadd hdradd;
914
 
  HDRappend hdrappend;
915
 
  HDRaddorappend hdraddorappend;
916
 
  HDRaddi18n hdraddi18n;
917
 
  HDRmodify hdrmodify;
918
 
  HDRremove hdrremove;
919
 
  HDRhdrsprintf hdrsprintf;
920
 
  HDRcopytags hdrcopytags;
921
 
  HDRfreeiter hdrfreeiter;
922
 
  HDRinititer hdrinititer;
923
 
  HDRnextiter hdrnextiter;
924
 
  HDRunlink hdrunlink;
925
 
/*@null@*/
926
 
  void *hdrvecs;
927
 
/*@null@*/
928
 
  void *hdrdata;
929
 
  int hdrversion;
930
 
};
931
 
 
932
 
/** \ingroup header
933
 
 * Description of tag data.
934
 
 */
935
 
typedef /*@abstract@ */ struct entryInfo *entryInfo;
936
 
struct entryInfo
937
 
{
938
 
  int_32 tag;                   /*!< Tag identifier. */
939
 
  int_32 type;                  /*!< Tag data type. */
940
 
  int_32 offset;                /*!< Offset into data segment (ondisk only). */
941
 
  int_32 count;                 /*!< Number of tag elements. */
942
 
};
943
 
 
944
 
/** \ingroup header
945
 
 * A single tag from a Header.
946
 
 */
947
 
typedef /*@abstract@ */ struct indexEntry *indexEntry;
948
 
struct indexEntry
949
 
{
950
 
  struct entryInfo info;        /*!< Description of tag data. */
951
 
                                /*@owned@*/ void *data;
952
 
                                /*!< Location of tag data. */
953
 
  int length;                   /*!< No. bytes of data. */
954
 
  int rdlen;                    /*!< No. bytes of data in region. */
955
 
};
956
 
 
957
 
/** \ingroup header
958
 
 * The Header data structure.
959
 
 */
960
 
struct headerToken
961
 
{
962
 
                                /*@unused@*/ struct HV_s hv;
963
 
                                /*!< Header public methods. */
964
 
  void *blob;                   /*!< Header region blob. */
965
 
                                /*@owned@*/ indexEntry index;
966
 
                                /*!< Array of tags. */
967
 
  int indexUsed;                /*!< Current size of tag array. */
968
 
  int indexAlloced;             /*!< Allocated size of tag array. */
969
 
  int flags;
970
 
#define HEADERFLAG_SORTED       (1 << 0)        /*!< Are header entries sorted? */
971
 
#define HEADERFLAG_ALLOCATED    (1 << 1)        /*!< Is 1st header region allocated? */
972
 
#define HEADERFLAG_LEGACY       (1 << 2)        /*!< Header came from legacy source? */
973
 
                                /*@refs@*/ int nrefs;
974
 
                                /*!< Reference count. */
975
 
};
976
 
 
977
 
/**
978
 
 * Header tag iterator data structure.
979
 
 */
980
 
struct headerIteratorS
981
 
{
982
 
                                /*@unused@*/ Header h;
983
 
                                /*!< Header being iterated. */
984
 
                                /*@unused@*/ int next_index;
985
 
                                /*!< Next tag index. */
986
 
};
987
 
 
988
 
/*@}*/
989
 
/* ==================================================================== */
990
 
/** \name RPMTS */
991
 
/*@{*/
992
 
/**
993
 
 * Prototype for headerFreeData() vector.
994
 
 * @param data          address of data (or NULL)
995
 
 * @param type          type of data (or -1 to force free)
996
 
 * @return              NULL always
997
 
 */
998
 
typedef                         /*@null@ */
999
 
void *(*HFD_t) ( /*@only@ *//*@null@ */ const void *data, rpmTagType type)
1000
 
        /*@modifies data @ */ ;
1001
 
 
1002
 
/**
1003
 
 * Prototype for headerAddEntry() vector.
1004
 
 * Duplicate tags are okay, but only defined for iteration (with the
1005
 
 * exceptions noted below). While you are allowed to add i18n string
1006
 
 * arrays through this function, you probably don't mean to. See
1007
 
 * headerAddI18NString() instead.
1008
 
 *
1009
 
 * @param h             header
1010
 
 * @param tag           tag
1011
 
 * @param type          tag value data type
1012
 
 * @param p             pointer to tag value(s)
1013
 
 * @param c             number of values
1014
 
 * @return              1 on success, 0 on failure
1015
 
 */
1016
 
typedef int (*HAE_t) (Header h, rpmTag tag, rpmTagType type,
1017
 
                      const void *p, int_32 c)
1018
 
        /*@modifies h @ */ ;
1019
 
 
1020
 
/**
1021
 
 * Prototype for headerGetEntry() vector.
1022
 
 * Will never return RPM_I18NSTRING_TYPE! RPM_STRING_TYPE elements with
1023
 
 * RPM_I18NSTRING_TYPE equivalent entries are translated (if HEADER_I18NTABLE
1024
 
 * entry is present).
1025
 
 *
1026
 
 * @param h             header
1027
 
 * @param tag           tag
1028
 
 * @retval type         address of tag value data type (or NULL)
1029
 
 * @retval p            address of pointer to tag value(s) (or NULL)
1030
 
 * @retval c            address of number of values (or NULL)
1031
 
 * @return              1 on success, 0 on failure
1032
 
 */
1033
 
typedef int (*HGE_t) (Header h, rpmTag tag,
1034
 
                      /*@null@ *//*@out@ */ rpmTagType * type,
1035
 
                      /*@null@ *//*@out@ */ void **p,
1036
 
                      /*@null@ *//*@out@ */ int_32 * c)
1037
 
        /*@modifies *type, *p, *c @ */ ;
1038
 
 
1039
 
/**
1040
 
 * Prototype for headerRemoveEntry() vector.
1041
 
 * Delete tag in header.
1042
 
 * Removes all entries of type tag from the header, returns 1 if none were
1043
 
 * found.
1044
 
 *
1045
 
 * @param h             header
1046
 
 * @param tag           tag
1047
 
 * @return              0 on success, 1 on failure (INCONSISTENT)
1048
 
 */
1049
 
typedef int (*HRE_t) (Header h, int_32 tag)
1050
 
        /*@modifies h @ */ ;
1051
 
 
1052
 
#define ENTRY_IS_REGION(_e) \
1053
 
        (((_e)->info.tag >= HEADER_IMAGE) && ((_e)->info.tag < HEADER_REGIONS))
1054
 
 
1055
 
 
1056
 
#define alloca_strdup(_s)       strcpy(alloca(strlen(_s)+1), (_s))
1057
 
 
1058
 
/**
1059
 
 * Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
1060
 
 * @param p             memory to free
1061
 
 * @return              NULL always
1062
 
 */
1063
 
/*@unused@*/ static /*@null@ */ void *
1064
 
_free ( /*@only@ *//*@null@ *//*@out@ */ const void *p) /*@modifies *p @ */
1065
 
{
1066
 
  if (p != NULL)
1067
 
    free ((void *) p);
1068
 
  return NULL;
1069
 
}
1070
 
 
1071
 
/**
1072
 
 */
1073
 
static int
1074
 
indexCmp (const void *avp, const void *bvp)     /*@ */
1075
 
{
1076
 
  /*@-castexpose@ */
1077
 
  indexEntry ap = (indexEntry) avp, bp = (indexEntry) bvp;
1078
 
  /*@=castexpose@ */
1079
 
  return (ap->info.tag - bp->info.tag);
1080
 
}
1081
 
 
1082
 
/** \ingroup header
1083
 
 * Sort tags in header.
1084
 
 * @param h             header
1085
 
 */
1086
 
static void
1087
 
headerSort (Header h)
1088
 
        /*@modifies h @ */
1089
 
{
1090
 
  if (!(h->flags & HEADERFLAG_SORTED))
1091
 
    {
1092
 
      qsort (h->index, h->indexUsed, sizeof (*h->index), indexCmp);
1093
 
      h->flags |= HEADERFLAG_SORTED;
1094
 
    }
1095
 
}
1096
 
 
1097
 
/**
1098
 
 * Remove occurences of trailing character from string.
1099
 
 * @param s             string
1100
 
 * @param c             character to strip
1101
 
 * @return              string
1102
 
 */
1103
 
/*@unused@*/ static inline
1104
 
/*@only@*/ char *
1105
 
stripTrailingChar ( /*@only@ */ char *s, char c)
1106
 
        /*@modifies *s */
1107
 
{
1108
 
  char *t;
1109
 
  for (t = s + strlen (s) - 1; *t == c && t >= s; t--)
1110
 
    *t = '\0';
1111
 
  return s;
1112
 
}
1113
 
 
1114
 
/** \ingroup header
1115
 
 * Free data allocated when retrieved from header.
1116
 
 * @deprecated Use headerFreeTag() instead.
1117
 
 * @todo Remove from API.
1118
 
 *
1119
 
 * @param data          address of data (or NULL)
1120
 
 * @param type          type of data (or -1 to force free)
1121
 
 * @return              NULL always
1122
 
 */
1123
 
                                /*@unused@*/ static
1124
 
                                /*@null@ */
1125
 
void *
1126
 
headerFreeData ( /*@only@ *//*@null@ */ const void *data, rpmTagType type)
1127
 
        /*@modifies data @ */
1128
 
{
1129
 
  if (data)
1130
 
    {
1131
 
      /*@-branchstate@ */
1132
 
      if (type == -1 ||
1133
 
          type == RPM_STRING_ARRAY_TYPE ||
1134
 
          type == RPM_I18NSTRING_TYPE || type == RPM_BIN_TYPE)
1135
 
        free ((void *) data);
1136
 
      /*@=branchstate@ */
1137
 
    }
1138
 
  return NULL;
1139
 
}
1140
 
 
1141
 
 
1142
 
/**
1143
 
 * Return length of entry data.
1144
 
 * @todo Remove sanity check exit's.
1145
 
 * @param type          entry data type
1146
 
 * @param p             entry data
1147
 
 * @param count         entry item count
1148
 
 * @param onDisk        data is concatenated strings (with NUL's))?
1149
 
 * @return              no. bytes in data
1150
 
 */
1151
 
/*@mayexit@*/
1152
 
static int
1153
 
dataLength (int_32 type, hPTR_t p, int_32 count, int onDisk)
1154
 
        /*@ */
1155
 
{
1156
 
  int length = 0;
1157
 
 
1158
 
  switch (type)
1159
 
    {
1160
 
    case RPM_STRING_TYPE:
1161
 
      if (count == 1)
1162
 
        {                       /* Special case -- p is just the string */
1163
 
          length = strlen (p) + 1;
1164
 
          break;
1165
 
        }
1166
 
      /* This should not be allowed */
1167
 
      /*@-modfilesys@ */
1168
 
      /*@=modfilesys@ */
1169
 
      exit (EXIT_FAILURE);
1170
 
      /*@notreached@ */ break;
1171
 
 
1172
 
    case RPM_STRING_ARRAY_TYPE:
1173
 
    case RPM_I18NSTRING_TYPE:
1174
 
      {
1175
 
        int i;
1176
 
 
1177
 
        /* This is like RPM_STRING_TYPE, except it's *always* an array */
1178
 
        /* Compute sum of length of all strings, including null terminators */
1179
 
        i = count;
1180
 
 
1181
 
        if (onDisk)
1182
 
          {
1183
 
            const char *chptr = p;
1184
 
            int thisLen;
1185
 
 
1186
 
            while (i--)
1187
 
              {
1188
 
                thisLen = strlen (chptr) + 1;
1189
 
                length += thisLen;
1190
 
                chptr += thisLen;
1191
 
              }
1192
 
          }
1193
 
        else
1194
 
          {
1195
 
            const char **src = (const char **) p;
1196
 
            while (i--)
1197
 
              {
1198
 
                /* add one for null termination */
1199
 
                length += strlen (*src++) + 1;
1200
 
              }
1201
 
          }
1202
 
      }
1203
 
      break;
1204
 
 
1205
 
    default:
1206
 
      if (typeSizes[type] != -1)
1207
 
        {
1208
 
          length = typeSizes[type] * count;
1209
 
          break;
1210
 
        }
1211
 
      /*@-modfilesys@ */
1212
 
      /*@=modfilesys@ */
1213
 
      exit (EXIT_FAILURE);
1214
 
      /*@notreached@ */ break;
1215
 
    }
1216
 
 
1217
 
  return length;
1218
 
}
1219
 
 
1220
 
/**
1221
 
 */
1222
 
static void
1223
 
copyData (int_32 type, /*@out@ */ void *dstPtr, const void *srcPtr,
1224
 
          int_32 c, int dataLengtha)
1225
 
        /*@modifies *dstPtr @ */
1226
 
{
1227
 
  const char **src;
1228
 
  char *dst;
1229
 
  int i;
1230
 
 
1231
 
  switch (type)
1232
 
    {
1233
 
    case RPM_STRING_ARRAY_TYPE:
1234
 
    case RPM_I18NSTRING_TYPE:
1235
 
      /* Otherwise, p is char** */
1236
 
      i = c;
1237
 
      src = (const char **) srcPtr;
1238
 
      dst = dstPtr;
1239
 
      while (i--)
1240
 
        {
1241
 
          if (*src)
1242
 
            {
1243
 
              int len = strlen (*src) + 1;
1244
 
              memcpy (dst, *src, len);
1245
 
              dst += len;
1246
 
            }
1247
 
          src++;
1248
 
        }
1249
 
      break;
1250
 
 
1251
 
    default:
1252
 
      memmove (dstPtr, srcPtr, dataLengtha);
1253
 
      break;
1254
 
    }
1255
 
}
1256
 
 
1257
 
/**
1258
 
 * Return (malloc'ed) copy of entry data.
1259
 
 * @param type          entry data type
1260
 
 * @param p             entry data
1261
 
 * @param c             entry item count
1262
 
 * @retval lengthPtr    no. bytes in returned data
1263
 
 * @return              (malloc'ed) copy of entry data
1264
 
 */
 
34
  size_t size;
 
35
  int pi[2];
 
36
  int shutdown;
 
37
};
 
38
 
1265
39
static void *
1266
 
grabData (int_32 type, hPTR_t p, int_32 c,
1267
 
          /*@out@ */ int *lengthPtr)
1268
 
        /*@modifies *lengthPtr @ */
1269
 
{
1270
 
  int length = dataLength (type, p, c, 0);
1271
 
  void *data = malloc (length);
1272
 
 
1273
 
  copyData (type, data, p, c, length);
1274
 
 
1275
 
  if (lengthPtr)
1276
 
    *lengthPtr = length;
1277
 
  return data;
1278
 
}
1279
 
 
1280
 
 
1281
 
#define INDEX_MALLOC_SIZE       8
1282
 
 
1283
 
/** \ingroup header
1284
 
 * Add tag to header.
1285
 
 * Duplicate tags are okay, but only defined for iteration (with the
1286
 
 * exceptions noted below). While you are allowed to add i18n string
1287
 
 * arrays through this function, you probably don't mean to. See
1288
 
 * headerAddI18NString() instead.
1289
 
 *
1290
 
 * @param h             header
1291
 
 * @param tag           tag
1292
 
 * @param type          tag value data type
1293
 
 * @param p             pointer to tag value(s)
1294
 
 * @param c             number of values
1295
 
 * @return              1 on success, 0 on failure
1296
 
 */
1297
 
static int
1298
 
headerAddEntry (Header h, int_32 tag, int_32 type, const void *p, int_32 c)
1299
 
        /*@modifies h @ */
1300
 
{
1301
 
  indexEntry entry;
1302
 
 
1303
 
  /* Count must always be >= 1 for headerAddEntry. */
1304
 
  if (c <= 0)
1305
 
    return 0;
1306
 
 
1307
 
  /* Allocate more index space if necessary */
1308
 
  if (h->indexUsed == h->indexAlloced)
1309
 
    {
1310
 
      h->indexAlloced += INDEX_MALLOC_SIZE;
1311
 
      h->index = realloc (h->index, h->indexAlloced * sizeof (*h->index));
1312
 
    }
1313
 
 
1314
 
  /* Fill in the index */
1315
 
  entry = h->index + h->indexUsed;
1316
 
  entry->info.tag = tag;
1317
 
  entry->info.type = type;
1318
 
  entry->info.count = c;
1319
 
  entry->info.offset = 0;
1320
 
  entry->data = grabData (type, p, c, &entry->length);
1321
 
 
1322
 
  if (h->indexUsed > 0 && tag < h->index[h->indexUsed - 1].info.tag)
1323
 
    h->flags &= ~HEADERFLAG_SORTED;
1324
 
  h->indexUsed++;
1325
 
 
1326
 
  return 1;
1327
 
}
1328
 
 
1329
 
/** \ingroup header
1330
 
 * Dereference a header instance.
1331
 
 * @param h             header
1332
 
 * @return              NULL always
1333
 
 */
1334
 
static                          /*@null@ */
1335
 
Header headerFree ( /*@killref@ *//*@null@ */ Header h);
1336
 
        /*@modifies h @ */
1337
 
 
1338
 
 
1339
 
/** \ingroup header
1340
 
 * Destroy header tag iterator.
1341
 
 * @param hi            header tag iterator
1342
 
 * @return              NULL always
1343
 
 */
1344
 
static                          /*@null@ */
1345
 
  HeaderIterator
1346
 
headerFreeIterator ( /*@only@ */ HeaderIterator hi)
1347
 
        /*@modifies hi @ */
1348
 
{
1349
 
  hi->h = headerFree (hi->h);
1350
 
  hi = _free (hi);
1351
 
  return hi;
1352
 
}
1353
 
 
1354
 
/**
1355
 
 * Find matching (tag,type) entry in header.
1356
 
 * @param h             header
1357
 
 * @param tag           entry tag
1358
 
 * @param type          entry type
1359
 
 * @return              header entry
1360
 
 */
1361
 
static                          /*@null@ */
1362
 
  indexEntry
1363
 
findEntry ( /*@null@ */ Header h, int_32 tag, int_32 type)
1364
 
        /*@modifies h @ */
1365
 
{
1366
 
  indexEntry entry, entry2, last;
1367
 
  struct indexEntry key;
1368
 
 
1369
 
  if (h == NULL)
1370
 
    return NULL;
1371
 
  if (!(h->flags & HEADERFLAG_SORTED))
1372
 
    headerSort (h);
1373
 
 
1374
 
  key.info.tag = tag;
1375
 
 
1376
 
  entry2 = entry =
1377
 
    bsearch (&key, h->index, h->indexUsed, sizeof (*h->index), indexCmp);
1378
 
  if (entry == NULL)
1379
 
    return NULL;
1380
 
 
1381
 
  if (type == RPM_NULL_TYPE)
1382
 
    return entry;
1383
 
 
1384
 
  /* look backwards */
1385
 
  while (entry->info.tag == tag && entry->info.type != type &&
1386
 
         entry > h->index)
1387
 
    entry--;
1388
 
 
1389
 
  if (entry->info.tag == tag && entry->info.type == type)
1390
 
    return entry;
1391
 
 
1392
 
  last = h->index + h->indexUsed;
1393
 
  /*@-usereleased@ *//* FIX: entry2 = entry. Code looks bogus as well. */
1394
 
  while (entry2->info.tag == tag && entry2->info.type != type &&
1395
 
         entry2 < last)
1396
 
    entry2++;
1397
 
  /*@=usereleased@ */
1398
 
 
1399
 
  if (entry->info.tag == tag && entry->info.type == type)
1400
 
    return entry;
1401
 
 
1402
 
  return NULL;
1403
 
}
1404
 
 
1405
 
static int regionSwab ( /*@null@ */ indexEntry entry, int il, int dl,
1406
 
                       entryInfo pe, char *dataStart, int regionid);
1407
 
        /*@modifies *entry, *dataStart @ */
1408
 
 
1409
 
/** \ingroup header
1410
 
 * Retrieve data from header entry.
1411
 
 * @todo Permit retrieval of regions other than HEADER_IMUTABLE.
1412
 
 * @param entry         header entry
1413
 
 * @retval type         address of type (or NULL)
1414
 
 * @retval p            address of data (or NULL)
1415
 
 * @retval c            address of count (or NULL)
1416
 
 * @param minMem        string pointers refer to header memory?
1417
 
 * @return              1 on success, otherwise error.
1418
 
 */
1419
 
static int
1420
 
copyEntry (const indexEntry entry,
1421
 
           /*@null@ *//*@out@ */ hTYP_t type,
1422
 
           /*@null@ *//*@out@ */ hPTR_t * p,
1423
 
           /*@null@ *//*@out@ */ hCNT_t c,
1424
 
           int minMem)
1425
 
        /*@modifies *type, *p, *c @ */
1426
 
{
1427
 
  int_32 count = entry->info.count;
1428
 
  int rc = 1;                   /* XXX 1 on success. */
1429
 
 
1430
 
  if (p)
1431
 
    switch (entry->info.type)
1432
 
      {
1433
 
      case RPM_BIN_TYPE:
1434
 
        /*
1435
 
         * XXX This only works for
1436
 
         * XXX  "sealed" HEADER_IMMUTABLE/HEADER_SIGNATURES/HEADER_IMAGE.
1437
 
         * XXX This will *not* work for unsealed legacy HEADER_IMAGE (i.e.
1438
 
         * XXX a legacy header freshly read, but not yet unloaded to the rpmdb).
1439
 
         */
1440
 
        if (ENTRY_IS_REGION (entry))
1441
 
          {
1442
 
            int_32 *ei = ((int_32 *) entry->data) - 2;
1443
 
            /*@-castexpose@ */
1444
 
            entryInfo pe = (entryInfo) (ei + 2);
1445
 
            /*@=castexpose@ */
1446
 
            char *dataStart = (char *) (pe + ntohl (ei[0]));
1447
 
            int_32 rdl = -entry->info.offset;   /* negative offset */
1448
 
            int_32 ril = rdl / sizeof (*pe);
1449
 
 
1450
 
            /*@-sizeoftype@ */
1451
 
            rdl = entry->rdlen;
1452
 
            count = 2 * sizeof (*ei) + (ril * sizeof (*pe)) + rdl;
1453
 
            if (entry->info.tag == HEADER_IMAGE)
1454
 
              {
1455
 
                ril -= 1;
1456
 
                pe += 1;
1457
 
              }
1458
 
            else
1459
 
              {
1460
 
                count += REGION_TAG_COUNT;
1461
 
                rdl += REGION_TAG_COUNT;
1462
 
              }
1463
 
 
1464
 
            *p = malloc (count);
1465
 
            ei = (int_32 *) * p;
1466
 
            ei[0] = htonl (ril);
1467
 
            ei[1] = htonl (rdl);
1468
 
 
1469
 
            /*@-castexpose@ */
1470
 
            pe = (entryInfo) memcpy (ei + 2, pe, (ril * sizeof (*pe)));
1471
 
            /*@=castexpose@ */
1472
 
 
1473
 
            dataStart = (char *) memcpy (pe + ril, dataStart, rdl);
1474
 
            /*@=sizeoftype@ */
1475
 
 
1476
 
            rc = regionSwab (NULL, ril, 0, pe, dataStart, 0);
1477
 
            /* XXX 1 on success. */
1478
 
            rc = (rc < 0) ? 0 : 1;
1479
 
          }
1480
 
        else
1481
 
          {
1482
 
            count = entry->length;
1483
 
            *p = (!minMem
1484
 
                  ? memcpy (malloc (count), entry->data, count)
1485
 
                  : entry->data);
1486
 
          }
1487
 
        break;
1488
 
      case RPM_STRING_TYPE:
1489
 
        if (count == 1)
1490
 
          {
1491
 
            *p = entry->data;
1492
 
            break;
1493
 
          }
1494
 
        /*@fallthrough@ */
1495
 
      case RPM_STRING_ARRAY_TYPE:
1496
 
      case RPM_I18NSTRING_TYPE:
1497
 
        {
1498
 
          const char **ptrEntry;
1499
 
          /*@-sizeoftype@ */
1500
 
          int tableSize = count * sizeof (char *);
1501
 
          /*@=sizeoftype@ */
1502
 
          char *t;
1503
 
          int i;
1504
 
 
1505
 
          /*@-mods@ */
1506
 
          if (minMem)
1507
 
            {
1508
 
              *p = malloc (tableSize);
1509
 
              ptrEntry = (const char **) *p;
1510
 
              t = entry->data;
1511
 
            }
1512
 
          else
1513
 
            {
1514
 
              t = malloc (tableSize + entry->length);
1515
 
              *p = (void *) t;
1516
 
              ptrEntry = (const char **) *p;
1517
 
              t += tableSize;
1518
 
              memcpy (t, entry->data, entry->length);
1519
 
            }
1520
 
          /*@=mods@ */
1521
 
          for (i = 0; i < count; i++)
1522
 
            {
1523
 
              *ptrEntry++ = t;
1524
 
              t = strchr (t, 0);
1525
 
              t++;
1526
 
            }
1527
 
        }
1528
 
        break;
1529
 
 
1530
 
      default:
1531
 
        *p = entry->data;
1532
 
        break;
1533
 
      }
1534
 
  if (type)
1535
 
    *type = entry->info.type;
1536
 
  if (c)
1537
 
    *c = count;
1538
 
  return rc;
1539
 
}
1540
 
 
1541
 
#define ENTRY_IN_REGION(_e)     ((_e)->info.offset < 0)
1542
 
 
1543
 
/** \ingroup header
1544
 
 * Append element to tag array in header.
1545
 
 * Appends item p to entry w/ tag and type as passed. Won't work on
1546
 
 * RPM_STRING_TYPE. Any pointers into header memory returned from
1547
 
 * headerGetEntryMinMemory() for this entry are invalid after this
1548
 
 * call has been made!
1549
 
 *
1550
 
 * @param h             header
1551
 
 * @param tag           tag
1552
 
 * @param type          tag value data type
1553
 
 * @param p             pointer to tag value(s)
1554
 
 * @param c             number of values
1555
 
 * @return              1 on success, 0 on failure
1556
 
 */
1557
 
static int
1558
 
headerAppendEntry (Header h, int_32 tag, int_32 type, const void *p, int_32 c)
1559
 
        /*@modifies h @ */
1560
 
{
1561
 
  indexEntry entry;
1562
 
  int length;
1563
 
 
1564
 
  /* First find the tag */
1565
 
  entry = findEntry (h, tag, type);
1566
 
  if (!entry)
1567
 
    return 0;
1568
 
 
1569
 
  if (type == RPM_STRING_TYPE || type == RPM_I18NSTRING_TYPE)
1570
 
    {
1571
 
      /* we can't do this */
1572
 
      return 0;
1573
 
    }
1574
 
 
1575
 
  length = dataLength (type, p, c, 0);
1576
 
 
1577
 
  if (ENTRY_IN_REGION (entry))
1578
 
    {
1579
 
      char *t = malloc (entry->length + length);
1580
 
      memcpy (t, entry->data, entry->length);
1581
 
      entry->data = t;
1582
 
      entry->info.offset = 0;
1583
 
    }
1584
 
  else
1585
 
    entry->data = realloc (entry->data, entry->length + length);
1586
 
 
1587
 
  copyData (type, ((char *) entry->data) + entry->length, p, c, length);
1588
 
 
1589
 
  entry->length += length;
1590
 
 
1591
 
  entry->info.count += c;
1592
 
 
1593
 
  return 1;
1594
 
}
1595
 
 
1596
 
/** \ingroup header
1597
 
 * Add or append element to tag array in header.
1598
 
 * @todo Arg "p" should have const.
1599
 
 * @param h             header
1600
 
 * @param tag           tag
1601
 
 * @param type          tag value data type
1602
 
 * @param p             pointer to tag value(s)
1603
 
 * @param c             number of values
1604
 
 * @return              1 on success, 0 on failure
1605
 
 */
1606
 
static int
1607
 
headerAddOrAppendEntry (Header h, int_32 tag, int_32 type,
1608
 
                        const void *p, int_32 c)
1609
 
        /*@modifies h @ */
1610
 
{
1611
 
  return (findEntry (h, tag, type)
1612
 
          ? headerAppendEntry (h, tag, type, p, c)
1613
 
          : headerAddEntry (h, tag, type, p, c));
1614
 
}
1615
 
 
1616
 
/**
1617
 
 * Does locale match entry in header i18n table?
1618
 
 *
1619
 
 * \verbatim
1620
 
 * The range [l,le) contains the next locale to match:
1621
 
 *    ll[_CC][.EEEEE][@dddd]
1622
 
 * where
1623
 
 *    ll        ISO language code (in lowercase).
1624
 
 *    CC        (optional) ISO coutnry code (in uppercase).
1625
 
 *    EEEEE     (optional) encoding (not really standardized).
1626
 
 *    dddd      (optional) dialect.
1627
 
 * \endverbatim
1628
 
 *
1629
 
 * @param td            header i18n table data, NUL terminated
1630
 
 * @param l             start of locale to match
1631
 
 * @param le            end of locale to match
1632
 
 * @return              1 on match, 0 on no match
1633
 
 */
1634
 
static int
1635
 
headerMatchLocale (const char *td, const char *l, const char *le)
1636
 
        /*@ */
1637
 
{
1638
 
  const char *fe;
1639
 
 
1640
 
 
1641
 
#if 0
1642
 
  {
1643
 
    const char *s, *ll, *CC, *EE, *dd;
1644
 
    char *lbuf, *t.
1645
 
      /* Copy the buffer and parse out components on the fly. */
1646
 
      lbuf = alloca (le - l + 1);
1647
 
    for (s = l, ll = t = lbuf; *s; s++, t++)
1648
 
      {
1649
 
        switch (*s)
1650
 
          {
1651
 
          case '_':
1652
 
            *t = '\0';
1653
 
            CC = t + 1;
1654
 
            break;
1655
 
          case '.':
1656
 
            *t = '\0';
1657
 
            EE = t + 1;
1658
 
            break;
1659
 
          case '@':
1660
 
            *t = '\0';
1661
 
            dd = t + 1;
1662
 
            break;
1663
 
          default:
1664
 
            *t = *s;
1665
 
            break;
1666
 
          }
1667
 
      }
1668
 
 
1669
 
    if (ll)                     /* ISO language should be lower case */
1670
 
      for (t = ll; *t; t++)
1671
 
        *t = tolower (*t);
1672
 
    if (CC)                     /* ISO country code should be upper case */
1673
 
      for (t = CC; *t; t++)
1674
 
        *t = toupper (*t);
1675
 
 
1676
 
    /* There are a total of 16 cases to attempt to match. */
1677
 
  }
1678
 
#endif
1679
 
 
1680
 
  /* First try a complete match. */
1681
 
  if (strlen (td) == (le - l) && !strncmp (td, l, (le - l)))
1682
 
    return 1;
1683
 
 
1684
 
  /* Next, try stripping optional dialect and matching.  */
1685
 
  for (fe = l; fe < le && *fe != '@'; fe++)
1686
 
    {
1687
 
    };
1688
 
  if (fe < le && !strncmp (td, l, (fe - l)))
1689
 
    return 1;
1690
 
 
1691
 
  /* Next, try stripping optional codeset and matching.  */
1692
 
  for (fe = l; fe < le && *fe != '.'; fe++)
1693
 
    {
1694
 
    };
1695
 
  if (fe < le && !strncmp (td, l, (fe - l)))
1696
 
    return 1;
1697
 
 
1698
 
  /* Finally, try stripping optional country code and matching. */
1699
 
  for (fe = l; fe < le && *fe != '_'; fe++)
1700
 
    {
1701
 
    };
1702
 
  if (fe < le && !strncmp (td, l, (fe - l)))
1703
 
    return 1;
1704
 
 
1705
 
  return 0;
1706
 
}
1707
 
 
1708
 
/**
1709
 
 * Return i18n string from header that matches locale.
1710
 
 * @param h             header
1711
 
 * @param entry         i18n string data
1712
 
 * @return              matching i18n string (or 1st string if no match)
1713
 
 */
1714
 
                /*@dependent@*//*@exposed@ */ static char *
1715
 
headerFindI18NString (Header h, indexEntry entry)
1716
 
        /*@ */
1717
 
{
1718
 
  const char *lang, *l, *le;
1719
 
  indexEntry table;
1720
 
 
1721
 
  /* XXX Drepper sez' this is the order. */
1722
 
  if ((lang = getenv ("LANGUAGE")) == NULL &&
1723
 
      (lang = getenv ("LC_ALL")) == NULL &&
1724
 
      (lang = getenv ("LC_MESSAGES")) == NULL &&
1725
 
      (lang = getenv ("LANG")) == NULL)
1726
 
    return entry->data;
1727
 
 
1728
 
  /*@-mods@ */
1729
 
  if ((table =
1730
 
       findEntry (h, HEADER_I18NTABLE, RPM_STRING_ARRAY_TYPE)) == NULL)
1731
 
    return entry->data;
1732
 
  /*@=mods@ */
1733
 
 
1734
 
  for (l = lang; *l != '\0'; l = le)
1735
 
    {
1736
 
      const char *td;
1737
 
      char *ed;
1738
 
      int langNum;
1739
 
 
1740
 
      while (*l && *l == ':')   /* skip leading colons */
1741
 
        l++;
1742
 
      if (*l == '\0')
1743
 
        break;
1744
 
      for (le = l; *le && *le != ':'; le++)     /* find end of this locale */
1745
 
        {
1746
 
        };
1747
 
 
1748
 
      /* For each entry in the header ... */
1749
 
      for (langNum = 0, td = table->data, ed = entry->data;
1750
 
           langNum < entry->info.count;
1751
 
           langNum++, td += strlen (td) + 1, ed += strlen (ed) + 1)
1752
 
        {
1753
 
 
1754
 
          if (headerMatchLocale (td, l, le))
1755
 
            return ed;
1756
 
 
1757
 
        }
1758
 
    }
1759
 
 
1760
 
  return entry->data;
1761
 
}
1762
 
 
1763
 
/**
1764
 
 * Retrieve tag data from header.
1765
 
 * @param h             header
1766
 
 * @param tag           tag to retrieve
1767
 
 * @retval type         address of type (or NULL)
1768
 
 * @retval p            address of data (or NULL)
1769
 
 * @retval c            address of count (or NULL)
1770
 
 * @param minMem        string pointers reference header memory?
1771
 
 * @return              1 on success, 0 on not found
1772
 
 */
1773
 
static int
1774
 
intGetEntry (Header h, int_32 tag,
1775
 
             /*@null@ *//*@out@ */ hTAG_t type,
1776
 
             /*@null@ *//*@out@ */ hPTR_t * p,
1777
 
             /*@null@ *//*@out@ */ hCNT_t c,
1778
 
             int minMem)
1779
 
        /*@modifies *type, *p, *c @ */
1780
 
{
1781
 
  indexEntry entry;
1782
 
  int rc;
1783
 
 
1784
 
  /* First find the tag */
1785
 
  /*@-mods@ *//*@ FIX: h modified by sort. */
1786
 
  entry = findEntry (h, tag, RPM_NULL_TYPE);
1787
 
  /*@mods@ */
1788
 
  if (entry == NULL)
1789
 
    {
1790
 
      if (type)
1791
 
        type = 0;
1792
 
      if (p)
1793
 
        *p = NULL;
1794
 
      if (c)
1795
 
        *c = 0;
1796
 
      return 0;
1797
 
    }
1798
 
 
1799
 
  switch (entry->info.type)
1800
 
    {
1801
 
    case RPM_I18NSTRING_TYPE:
1802
 
      rc = 1;
1803
 
      if (type)
1804
 
        *type = RPM_STRING_TYPE;
1805
 
      if (c)
1806
 
        *c = 1;
1807
 
      /*@-dependenttrans@ */
1808
 
      if (p)
1809
 
        *p = headerFindI18NString (h, entry);
1810
 
      /*@=dependenttrans@ */
1811
 
      break;
1812
 
    default:
1813
 
      rc = copyEntry (entry, type, p, c, minMem);
1814
 
      break;
1815
 
    }
1816
 
 
1817
 
  /* XXX 1 on success */
1818
 
  return ((rc == 1) ? 1 : 0);
1819
 
}
1820
 
 
1821
 
/** \ingroup header
1822
 
 * Retrieve tag value.
1823
 
 * Will never return RPM_I18NSTRING_TYPE! RPM_STRING_TYPE elements with
1824
 
 * RPM_I18NSTRING_TYPE equivalent entries are translated (if HEADER_I18NTABLE
1825
 
 * entry is present).
1826
 
 *
1827
 
 * @param h             header
1828
 
 * @param tag           tag
1829
 
 * @retval type         address of tag value data type (or NULL)
1830
 
 * @retval p            address of pointer to tag value(s) (or NULL)
1831
 
 * @retval c            address of number of values (or NULL)
1832
 
 * @return              1 on success, 0 on failure
1833
 
 */
1834
 
static int
1835
 
headerGetEntry (Header h, int_32 tag,
1836
 
                /*@null@ *//*@out@ */ hTYP_t type,
1837
 
                /*@null@ *//*@out@ */ void **p,
1838
 
                /*@null@ *//*@out@ */ hCNT_t c)
1839
 
        /*@modifies *type, *p, *c @ */
1840
 
{
1841
 
  return intGetEntry (h, tag, type, (hPTR_t *) p, c, 0);
1842
 
}
1843
 
 
1844
 
/** \ingroup header
1845
 
 */
1846
 
               /*@observer@*//*@unchecked@ */
1847
 
static unsigned char header_magic[8] = {
1848
 
  0x8e, 0xad, 0xe8, 0x01, 0x00, 0x00, 0x00, 0x00
1849
 
};
1850
 
 
1851
 
/** \ingroup header
1852
 
 * Return size of on-disk header representation in bytes.
1853
 
 * @param h             header
1854
 
 * @param magicp        include size of 8 bytes for (magic, 0)?
1855
 
 * @return              size of on-disk header
1856
 
 */
1857
 
static unsigned int
1858
 
headerSizeof ( /*@null@ */ Header h, enum hMagic magicp)
1859
 
        /*@modifies h @ */
1860
 
{
1861
 
  indexEntry entry;
1862
 
  unsigned int size = 0;
1863
 
  int i;
1864
 
 
1865
 
  if (h == NULL)
1866
 
    return size;
1867
 
 
1868
 
  headerSort (h);
1869
 
 
1870
 
  switch (magicp)
1871
 
    {
1872
 
    case HEADER_MAGIC_YES:
1873
 
      size += sizeof (header_magic);
1874
 
      break;
1875
 
    case HEADER_MAGIC_NO:
1876
 
      break;
1877
 
    }
1878
 
 
1879
 
  /*@-sizeoftype@ */
1880
 
  size += 2 * sizeof (int_32);  /* count of index entries */
1881
 
  /*@=sizeoftype@ */
1882
 
 
1883
 
  for (i = 0, entry = h->index; i < h->indexUsed; i++, entry++)
1884
 
    {
1885
 
      unsigned diff;
1886
 
      int_32 type;
1887
 
 
1888
 
      /* Regions go in as is ... */
1889
 
      if (ENTRY_IS_REGION (entry))
1890
 
        {
1891
 
          size += entry->length;
1892
 
          /* XXX Legacy regions do not include the region tag and data. */
1893
 
          /*@-sizeoftype@ */
1894
 
          if (i == 0 && (h->flags & HEADERFLAG_LEGACY))
1895
 
            size += sizeof (struct entryInfo) + entry->info.count;
1896
 
          /*@=sizeoftype@ */
1897
 
          continue;
1898
 
        }
1899
 
 
1900
 
      /* ... and region elements are skipped. */
1901
 
      if (entry->info.offset < 0)
1902
 
        continue;
1903
 
 
1904
 
      /* Alignment */
1905
 
      type = entry->info.type;
1906
 
      if (typeSizes[type] > 1)
1907
 
        {
1908
 
          diff = typeSizes[type] - (size % typeSizes[type]);
1909
 
          if (diff != typeSizes[type])
1910
 
            {
1911
 
              size += diff;
1912
 
            }
1913
 
        }
1914
 
 
1915
 
      /*@-sizeoftype@ */
1916
 
      size += sizeof (struct entryInfo) + entry->length;
1917
 
      /*@=sizeoftype@ */
1918
 
    }
1919
 
 
1920
 
  return size;
1921
 
}
1922
 
 
1923
 
/** \ingroup header
1924
 
 * Reference a header instance.
1925
 
 * @param h             header
1926
 
 * @return              referenced header instance
1927
 
 */
1928
 
static Header
1929
 
headerLink (Header h)
1930
 
        /*@modifies h @ */
1931
 
{
1932
 
  if (h != NULL)
1933
 
    h->nrefs++;
1934
 
  /*@-refcounttrans -nullret @ */
1935
 
  return h;
1936
 
  /*@=refcounttrans =nullret @ */
1937
 
}
1938
 
 
1939
 
/** \ingroup header
1940
 
 * Create header tag iterator.
1941
 
 * @param h             header
1942
 
 * @return              header tag iterator
1943
 
 */
1944
 
static HeaderIterator
1945
 
headerInitIterator (Header h)
1946
 
        /*@modifies h */
1947
 
{
1948
 
  HeaderIterator hi = malloc (sizeof (*hi));
1949
 
 
1950
 
  headerSort (h);
1951
 
 
1952
 
  hi->h = headerLink (h);
1953
 
  hi->next_index = 0;
1954
 
  return hi;
1955
 
}
1956
 
 
1957
 
/** \ingroup header
1958
 
 * Check if tag is in header.
1959
 
 * @param h             header
1960
 
 * @param tag           tag
1961
 
 * @return              1 on success, 0 on failure
1962
 
 */
1963
 
static int
1964
 
headerIsEntry ( /*@null@ */ Header h, int_32 tag)
1965
 
        /*@ */
1966
 
{
1967
 
  /*@-mods@ *//*@ FIX: h modified by sort. */
1968
 
  return (findEntry (h, tag, RPM_NULL_TYPE) ? 1 : 0);
1969
 
  /*@=mods@ */
1970
 
}
1971
 
 
1972
 
/** \ingroup header
1973
 
 * Return next tag from header.
1974
 
 * @param hi            header tag iterator
1975
 
 * @retval tag          address of tag
1976
 
 * @retval type         address of tag value data type
1977
 
 * @retval p            address of pointer to tag value(s)
1978
 
 * @retval c            address of number of values
1979
 
 * @return              1 on success, 0 on failure
1980
 
 */
1981
 
static int
1982
 
headerNextIterator (HeaderIterator hi,
1983
 
                    /*@null@ *//*@out@ */ hTAG_t tag,
1984
 
                    /*@null@ *//*@out@ */ hTYP_t type,
1985
 
                    /*@null@ *//*@out@ */ hPTR_t * p,
1986
 
                    /*@null@ *//*@out@ */ hCNT_t c,
1987
 
                    int do_copy)
1988
 
        /*@modifies hi, *tag, *type, *p, *c @ */
1989
 
{
1990
 
  Header h = hi->h;
1991
 
  int slot = hi->next_index;
1992
 
  indexEntry entry = NULL;
1993
 
  int rc;
1994
 
 
1995
 
  for (slot = hi->next_index; slot < h->indexUsed; slot++)
1996
 
    {
1997
 
      entry = h->index + slot;
1998
 
      if (!ENTRY_IS_REGION (entry))
1999
 
        break;
2000
 
    }
2001
 
  hi->next_index = slot;
2002
 
  if (entry == NULL || slot >= h->indexUsed)
2003
 
    return 0;
2004
 
  /*@-noeffect@ *//* LCL: no clue */
2005
 
  hi->next_index++;
2006
 
  /*@=noeffect@ */
2007
 
 
2008
 
  if (tag)
2009
 
    *tag = entry->info.tag;
2010
 
 
2011
 
  rc = copyEntry (entry, type, p, c, do_copy);
2012
 
 
2013
 
  /* XXX 1 on success */
2014
 
  return ((rc == 1) ? 1 : 0);
2015
 
}
2016
 
 
2017
 
/** \ingroup header
2018
 
 * Dereference a header instance.
2019
 
 * @param h             header
2020
 
 * @return              NULL always
2021
 
 */
2022
 
static                          /*@null@ */
2023
 
  Header
2024
 
headerUnlink ( /*@killref@ *//*@null@ */ Header h)
2025
 
        /*@modifies h @ */
2026
 
{
2027
 
  if (h != NULL)
2028
 
    h->nrefs--;
2029
 
  return NULL;
2030
 
}
2031
 
 
2032
 
/** \ingroup header
2033
 
 * Dereference a header instance.
2034
 
 * @param h             header
2035
 
 * @return              NULL always
2036
 
 */
2037
 
static                          /*@null@ */
2038
 
  Header
2039
 
headerFree ( /*@killref@ *//*@null@ */ Header h)
2040
 
        /*@modifies h @ */
2041
 
{
2042
 
  (void) headerUnlink (h);
2043
 
 
2044
 
  /*@-usereleased@ */
2045
 
  if (h == NULL || h->nrefs > 0)
2046
 
    return NULL;                /* XXX return previous header? */
2047
 
 
2048
 
  if (h->index)
2049
 
    {
2050
 
      indexEntry entry = h->index;
2051
 
      int i;
2052
 
      for (i = 0; i < h->indexUsed; i++, entry++)
2053
 
        {
2054
 
          if ((h->flags & HEADERFLAG_ALLOCATED) && ENTRY_IS_REGION (entry))
2055
 
            {
2056
 
              if (entry->length > 0)
2057
 
                {
2058
 
                  int_32 *ei = entry->data;
2059
 
                  if ((ei - 2) == h->blob)
2060
 
                    h->blob = _free (h->blob);
2061
 
                  entry->data = NULL;
2062
 
                }
2063
 
            }
2064
 
          else if (!ENTRY_IN_REGION (entry))
2065
 
            {
2066
 
              entry->data = _free (entry->data);
2067
 
            }
2068
 
          entry->data = NULL;
2069
 
        }
2070
 
      h->index = _free (h->index);
2071
 
    }
2072
 
 
2073
 
                                        /*@-refcounttrans@ */ h = _free (h);
2074
 
                                        /*@=refcounttrans@ */
2075
 
  return h;
2076
 
  /*@=usereleased@ */
2077
 
}
2078
 
 
2079
 
/**
2080
 
 * Sanity check on no. of tags.
2081
 
 * This check imposes a limit of 65K tags, more than enough.
2082
 
 */
2083
 
#define hdrchkTags(_ntags)      ((_ntags) & 0xffff0000)
2084
 
 
2085
 
/**
2086
 
 * Sanity check on data size and/or offset.
2087
 
 * This check imposes a limit of 16Mb, more than enough.
2088
 
 */
2089
 
#define hdrchkData(_nbytes)     ((_nbytes) & 0xff000000)
2090
 
 
2091
 
 
2092
 
 
2093
 
/** \ingroup header
2094
 
 * Swap int_32 and int_16 arrays within header region.
2095
 
 *
2096
 
 * This code is way more twisty than I would like.
2097
 
 *
2098
 
 * A bug with RPM_I18NSTRING_TYPE in rpm-2.5.x (fixed in August 1998)
2099
 
 * causes the offset and length of elements in a header region to disagree
2100
 
 * regarding the total length of the region data.
2101
 
 *
2102
 
 * The "fix" is to compute the size using both offset and length and
2103
 
 * return the larger of the two numbers as the size of the region.
2104
 
 * Kinda like computing left and right Riemann sums of the data elements
2105
 
 * to determine the size of a data structure, go figger :-).
2106
 
 *
2107
 
 * There's one other twist if a header region tag is in the set to be swabbed,
2108
 
 * as the data for a header region is located after all other tag data.
2109
 
 *
2110
 
 * @param entry         header entry
2111
 
 * @param il            no. of entries
2112
 
 * @param dl            start no. bytes of data
2113
 
 * @param pe            header physical entry pointer (swapped)
2114
 
 * @param dataStart     header data
2115
 
 * @param regionid      region offset
2116
 
 * @return              no. bytes of data in region, -1 on error
2117
 
 */
2118
 
static int
2119
 
regionSwab ( /*@null@ */ indexEntry entry, int il, int dl,
2120
 
            entryInfo pe, char *dataStart, int regionid)
2121
 
        /*@modifies *entry, *dataStart @ */
2122
 
{
2123
 
  char *tprev = NULL;
2124
 
  char *t = NULL;
2125
 
  int tdel, tl = dl;
2126
 
  struct indexEntry ieprev;
2127
 
 
2128
 
  memset (&ieprev, 0, sizeof (ieprev));
2129
 
  for (; il > 0; il--, pe++)
2130
 
    {
2131
 
      struct indexEntry ie;
2132
 
      int_32 type;
2133
 
 
2134
 
      ie.info.tag = ntohl (pe->tag);
2135
 
      ie.info.type = ntohl (pe->type);
2136
 
      if (ie.info.type < RPM_MIN_TYPE || ie.info.type > RPM_MAX_TYPE)
2137
 
        return -1;
2138
 
      ie.info.count = ntohl (pe->count);
2139
 
      ie.info.offset = ntohl (pe->offset);
2140
 
      ie.data = t = dataStart + ie.info.offset;
2141
 
      ie.length = dataLength (ie.info.type, ie.data, ie.info.count, 1);
2142
 
      ie.rdlen = 0;
2143
 
 
2144
 
      if (entry)
2145
 
        {
2146
 
          ie.info.offset = regionid;
2147
 
          *entry = ie;          /* structure assignment */
2148
 
          entry++;
2149
 
        }
2150
 
 
2151
 
      /* Alignment */
2152
 
      type = ie.info.type;
2153
 
      if (typeSizes[type] > 1)
2154
 
        {
2155
 
          unsigned diff;
2156
 
          diff = typeSizes[type] - (dl % typeSizes[type]);
2157
 
          if (diff != typeSizes[type])
2158
 
            {
2159
 
              dl += diff;
2160
 
              if (ieprev.info.type == RPM_I18NSTRING_TYPE)
2161
 
                ieprev.length += diff;
2162
 
            }
2163
 
        }
2164
 
      tdel = (tprev ? (t - tprev) : 0);
2165
 
      if (ieprev.info.type == RPM_I18NSTRING_TYPE)
2166
 
        tdel = ieprev.length;
2167
 
 
2168
 
      if (ie.info.tag >= HEADER_I18NTABLE)
2169
 
        {
2170
 
          tprev = t;
2171
 
        }
2172
 
      else
2173
 
        {
2174
 
          tprev = dataStart;
2175
 
          /* XXX HEADER_IMAGE tags don't include region sub-tag. */
2176
 
          /*@-sizeoftype@ */
2177
 
          if (ie.info.tag == HEADER_IMAGE)
2178
 
            tprev -= REGION_TAG_COUNT;
2179
 
          /*@=sizeoftype@ */
2180
 
        }
2181
 
 
2182
 
      /* Perform endian conversions */
2183
 
      switch (ntohl (pe->type))
2184
 
        {
2185
 
        case RPM_INT32_TYPE:
2186
 
          {
2187
 
            int_32 *it = (int_32 *) t;
2188
 
            for (; ie.info.count > 0; ie.info.count--, it += 1)
2189
 
              *it = htonl (*it);
2190
 
            t = (char *) it;
2191
 
          } /*@switchbreak@ */ break;
2192
 
        case RPM_INT16_TYPE:
2193
 
          {
2194
 
            unsigned short *it = (unsigned short *) t;
2195
 
            for (; ie.info.count > 0; ie.info.count--, it += 1)
2196
 
              *it = htons (*it);
2197
 
            t = (char *) it;
2198
 
          } /*@switchbreak@ */ break;
2199
 
        default:
2200
 
          t += ie.length;
2201
 
          /*@switchbreak@ */ break;
2202
 
        }
2203
 
 
2204
 
      dl += ie.length;
2205
 
      tl += tdel;
2206
 
      ieprev = ie;              /* structure assignment */
2207
 
 
2208
 
    }
2209
 
  tdel = (tprev ? (t - tprev) : 0);
2210
 
  tl += tdel;
2211
 
 
2212
 
  /* XXX
2213
 
   * There are two hacks here:
2214
 
   *  1) tl is 16b (i.e. REGION_TAG_COUNT) short while doing headerReload().
2215
 
   *  2) the 8/98 rpm bug with inserting i18n tags needs to use tl, not dl.
2216
 
   */
2217
 
  /*@-sizeoftype@ */
2218
 
  if (tl + REGION_TAG_COUNT == dl)
2219
 
    tl += REGION_TAG_COUNT;
2220
 
  /*@=sizeoftype@ */
2221
 
 
2222
 
  return dl;
2223
 
}
2224
 
 
2225
 
static int headerRemoveEntry (Header h, int_32 tag);
2226
 
 
2227
 
/** \ingroup header
2228
 
 * Convert header to in-memory representation.
2229
 
 * @param uh            on-disk header blob (i.e. with offsets)
2230
 
 * @return              header
2231
 
 */
2232
 
static                          /*@null@ */
2233
 
  Header
2234
 
headerLoad ( /*@kept@ */ void *uh)
2235
 
        /*@modifies uh @ */
2236
 
{
2237
 
  int_32 *ei = (int_32 *) uh;
2238
 
  int_32 il = ntohl (ei[0]);    /* index length */
2239
 
  int_32 dl = ntohl (ei[1]);    /* data length */
2240
 
  /*@-sizeoftype@ */
2241
 
  size_t pvlen = sizeof (il) + sizeof (dl) +
2242
 
    (il * sizeof (struct entryInfo)) + dl;
2243
 
  /*@=sizeoftype@ */
2244
 
  void *pv = uh;
2245
 
  Header h = NULL;
2246
 
  entryInfo pe;
2247
 
  char *dataStart;
2248
 
  indexEntry entry;
2249
 
  int rdlen;
2250
 
 
2251
 
  /* Sanity checks on header intro. */
2252
 
  if (hdrchkTags (il) || hdrchkData (dl))
2253
 
    goto errxit;
2254
 
 
2255
 
  ei = (int_32 *) pv;
2256
 
  /*@-castexpose@ */
2257
 
  pe = (entryInfo) & ei[2];
2258
 
  /*@=castexpose@ */
2259
 
  dataStart = (char *) (pe + il);
2260
 
 
2261
 
  h = calloc (1, sizeof (*h));
2262
 
  memset (h, 0, sizeof (*h));
2263
 
  /*@-assignexpose@ */
2264
 
  /*@=assignexpose@ */
2265
 
  /*@-assignexpose -kepttrans@ */
2266
 
  h->blob = uh;
2267
 
  /*@=assignexpose =kepttrans@ */
2268
 
  h->indexAlloced = il + 1;
2269
 
  h->indexUsed = il;
2270
 
  h->index = calloc (h->indexAlloced, sizeof (*h->index));
2271
 
  h->flags = HEADERFLAG_SORTED;
2272
 
  h->nrefs = 0;
2273
 
  h = headerLink (h);
2274
 
 
2275
 
  /*
2276
 
   * XXX XFree86-libs, ash, and pdksh from Red Hat 5.2 have bogus
2277
 
   * %verifyscript tag that needs to be diddled.
2278
 
   */
2279
 
  if (ntohl (pe->tag) == 15 &&
2280
 
      ntohl (pe->type) == RPM_STRING_TYPE && ntohl (pe->count) == 1)
2281
 
    {
2282
 
      pe->tag = htonl (1079);
2283
 
    }
2284
 
 
2285
 
  entry = h->index;
2286
 
  if (!(htonl (pe->tag) < HEADER_I18NTABLE))
2287
 
    {
2288
 
      h->flags |= HEADERFLAG_LEGACY;
2289
 
      entry->info.type = REGION_TAG_TYPE;
2290
 
      entry->info.tag = HEADER_IMAGE;
2291
 
      /*@-sizeoftype@ */
2292
 
      entry->info.count = REGION_TAG_COUNT;
2293
 
      /*@=sizeoftype@ */
2294
 
      entry->info.offset = ((char *) pe - dataStart);   /* negative offset */
2295
 
 
2296
 
      /*@-assignexpose@ */
2297
 
      entry->data = pe;
2298
 
      /*@=assignexpose@ */
2299
 
      entry->length = pvlen - sizeof (il) - sizeof (dl);
2300
 
      rdlen =
2301
 
        regionSwab (entry + 1, il, 0, pe, dataStart, entry->info.offset);
2302
 
#if 0                           /* XXX don't check, the 8/98 i18n bug fails here. */
2303
 
      if (rdlen != dl)
2304
 
        goto errxit;
2305
 
#endif
2306
 
      entry->rdlen = rdlen;
2307
 
      entry++;
2308
 
      h->indexUsed++;
2309
 
    }
2310
 
  else
2311
 
    {
2312
 
      int nb = ntohl (pe->count);
2313
 
      int_32 rdl;
2314
 
      int_32 ril;
2315
 
 
2316
 
      h->flags &= ~HEADERFLAG_LEGACY;
2317
 
 
2318
 
      entry->info.type = htonl (pe->type);
2319
 
      if (entry->info.type < RPM_MIN_TYPE || entry->info.type > RPM_MAX_TYPE)
2320
 
        goto errxit;
2321
 
      entry->info.count = htonl (pe->count);
2322
 
 
2323
 
      if (hdrchkTags (entry->info.count))
2324
 
        goto errxit;
2325
 
 
2326
 
      {
2327
 
        int off = ntohl (pe->offset);
2328
 
 
2329
 
        if (hdrchkData (off))
2330
 
          goto errxit;
2331
 
        if (off)
2332
 
          {
2333
 
            int_32 *stei = memcpy (alloca (nb), dataStart + off, nb);
2334
 
            rdl = -ntohl (stei[2]);     /* negative offset */
2335
 
            ril = rdl / sizeof (*pe);
2336
 
            if (hdrchkTags (ril) || hdrchkData (rdl))
2337
 
              goto errxit;
2338
 
            entry->info.tag = htonl (pe->tag);
2339
 
          }
2340
 
        else
2341
 
          {
2342
 
            ril = il;
2343
 
            /*@-sizeoftype@ */
2344
 
            rdl = (ril * sizeof (struct entryInfo));
2345
 
            /*@=sizeoftype@ */
2346
 
            entry->info.tag = HEADER_IMAGE;
2347
 
          }
2348
 
      }
2349
 
      entry->info.offset = -rdl;        /* negative offset */
2350
 
 
2351
 
      /*@-assignexpose@ */
2352
 
      entry->data = pe;
2353
 
      /*@=assignexpose@ */
2354
 
      entry->length = pvlen - sizeof (il) - sizeof (dl);
2355
 
      rdlen =
2356
 
        regionSwab (entry + 1, ril - 1, 0, pe + 1, dataStart,
2357
 
                    entry->info.offset);
2358
 
      if (rdlen < 0)
2359
 
        goto errxit;
2360
 
      entry->rdlen = rdlen;
2361
 
 
2362
 
      if (ril < h->indexUsed)
2363
 
        {
2364
 
          indexEntry newEntry = entry + ril;
2365
 
          int ne = (h->indexUsed - ril);
2366
 
          int rid = entry->info.offset + 1;
2367
 
          int rc;
2368
 
 
2369
 
          /* Load dribble entries from region. */
2370
 
          rc = regionSwab (newEntry, ne, 0, pe + ril, dataStart, rid);
2371
 
          if (rc < 0)
2372
 
            goto errxit;
2373
 
          rdlen += rc;
2374
 
 
2375
 
          {
2376
 
            indexEntry firstEntry = newEntry;
2377
 
            int save = h->indexUsed;
2378
 
            int j;
2379
 
 
2380
 
            /* Dribble entries replace duplicate region entries. */
2381
 
            h->indexUsed -= ne;
2382
 
            for (j = 0; j < ne; j++, newEntry++)
2383
 
              {
2384
 
                (void) headerRemoveEntry (h, newEntry->info.tag);
2385
 
                if (newEntry->info.tag == HEADER_BASENAMES)
2386
 
                  (void) headerRemoveEntry (h, HEADER_OLDFILENAMES);
2387
 
              }
2388
 
 
2389
 
            /* If any duplicate entries were replaced, move new entries down. */
2390
 
            if (h->indexUsed < (save - ne))
2391
 
              {
2392
 
                memmove (h->index + h->indexUsed, firstEntry,
2393
 
                         (ne * sizeof (*entry)));
2394
 
              }
2395
 
            h->indexUsed += ne;
2396
 
          }
2397
 
        }
2398
 
    }
2399
 
 
2400
 
  h->flags &= ~HEADERFLAG_SORTED;
2401
 
  headerSort (h);
2402
 
 
2403
 
  /*@-globstate -observertrans @ */
2404
 
  return h;
2405
 
  /*@=globstate =observertrans @ */
2406
 
 
2407
 
errxit:
2408
 
  /*@-usereleased@ */
2409
 
  if (h)
2410
 
    {
2411
 
      h->index = _free (h->index);
2412
 
      /*@-refcounttrans@ */
2413
 
      h = _free (h);
2414
 
      /*@=refcounttrans@ */
2415
 
    }
2416
 
  /*@=usereleased@ */
2417
 
  /*@-refcounttrans -globstate@ */
2418
 
  return h;
2419
 
  /*@=refcounttrans =globstate@ */
2420
 
}
2421
 
 
2422
 
/** \ingroup header
2423
 
 * Read (and load) header from file handle.
2424
 
 * @param fd            file handle
2425
 
 * @param magicp        read (and verify) 8 bytes of (magic, 0)?
2426
 
 * @return              header (or NULL on error)
2427
 
 */
2428
 
static                          /*@null@ */
2429
 
  Header
2430
 
headerRead (FD_t fd, enum hMagic magicp)
2431
 
        /*@modifies fd @ */
2432
 
{
2433
 
  int_32 block[4];
2434
 
  int_32 *ei = NULL;
2435
 
  int_32 il;
2436
 
  int_32 dl;
2437
 
  int_32 magic;
2438
 
  Header h = NULL;
2439
 
  size_t len;
2440
 
  int i;
2441
 
 
2442
 
  memset (block, 0, sizeof (block));
2443
 
  i = 2;
2444
 
  if (magicp == HEADER_MAGIC_YES)
2445
 
    i += 2;
2446
 
 
2447
 
  /*@-type@ *//* FIX: cast? */
2448
 
  if (timedRead (fd, (char *) block, i * sizeof (*block)) !=
2449
 
      (i * sizeof (*block)))
2450
 
    goto exit;
2451
 
  /*@=type@ */
2452
 
 
2453
 
  i = 0;
2454
 
 
2455
 
  if (magicp == HEADER_MAGIC_YES)
2456
 
    {
2457
 
      magic = block[i++];
2458
 
      if (memcmp (&magic, header_magic, sizeof (magic)))
2459
 
        goto exit;
2460
 
      i++;
2461
 
    }
2462
 
 
2463
 
  il = ntohl (block[i]);
2464
 
  i++;
2465
 
  dl = ntohl (block[i]);
2466
 
  i++;
2467
 
 
2468
 
  /*@-sizeoftype@ */
2469
 
  len = sizeof (il) + sizeof (dl) + (il * sizeof (struct entryInfo)) + dl;
2470
 
  /*@=sizeoftype@ */
2471
 
 
2472
 
  /* Sanity checks on header intro. */
2473
 
  if (hdrchkTags (il) || hdrchkData (dl) || len > headerMaxbytes)
2474
 
    goto exit;
2475
 
 
2476
 
  ei = malloc (len);
2477
 
  ei[0] = htonl (il);
2478
 
  ei[1] = htonl (dl);
2479
 
  len -= sizeof (il) + sizeof (dl);
2480
 
 
2481
 
  /*@-type@ *//* FIX: cast? */
2482
 
  if (timedRead (fd, (char *) &ei[2], len) != len)
2483
 
    goto exit;
2484
 
  /*@=type@ */
2485
 
 
2486
 
  h = headerLoad (ei);
2487
 
 
2488
 
exit:
2489
 
  if (h)
2490
 
    {
2491
 
      if (h->flags & HEADERFLAG_ALLOCATED)
2492
 
        ei = _free (ei);
2493
 
      h->flags |= HEADERFLAG_ALLOCATED;
2494
 
    }
2495
 
  else if (ei)
2496
 
    ei = _free (ei);
2497
 
  /*@-mustmod@ *//* FIX: timedRead macro obscures annotation */
2498
 
  return h;
2499
 
  /*@-mustmod@ */
2500
 
}
2501
 
 
2502
 
/**
2503
 
 * Check package size.
2504
 
 * @todo rpmio: use fdSize rather than fstat(2) to get file size.
2505
 
 * @param fd                    package file handle
2506
 
 * @param siglen                signature header size
2507
 
 * @param pad                   signature padding
2508
 
 * @param datalen               length of header+payload
2509
 
 * @return                      rpmRC return code
2510
 
 */
2511
 
static rpmRC
2512
 
checkSize (FD_t fd, int siglen, int pad, int datalen)
2513
 
        /*@globals fileSystem @ */
2514
 
        /*@modifies fileSystem @ */
2515
 
{
2516
 
  rpmRC rc;
2517
 
 
2518
 
  rc = (((sizeof (struct rpmlead) + siglen + pad + datalen) - fd->len)
2519
 
        ? RPMRC_BADSIZE : RPMRC_OK);
2520
 
 
2521
 
  return rc;
2522
 
}
2523
 
 
2524
 
/** \ingroup header
2525
 
 * Create new (empty) header instance.
2526
 
 * @return              header
2527
 
 */
2528
 
static Header
2529
 
headerNew (void)
2530
 
        /*@ */
2531
 
{
2532
 
  Header h = calloc (1, sizeof (*h));
2533
 
 
2534
 
  memset (h, 0, sizeof (*h));
2535
 
  /*@-assignexpose@ */
2536
 
  /*@=assignexpose@ */
2537
 
  h->blob = NULL;
2538
 
  h->indexAlloced = INDEX_MALLOC_SIZE;
2539
 
  h->indexUsed = 0;
2540
 
  h->flags = HEADERFLAG_SORTED;
2541
 
 
2542
 
  h->index = (h->indexAlloced
2543
 
              ? calloc (h->indexAlloced, sizeof (*h->index)) : NULL);
2544
 
 
2545
 
  /*@-globstate -observertrans @ */
2546
 
  h->nrefs = 0;
2547
 
  return headerLink (h);
2548
 
  /*@=globstate =observertrans @ */
2549
 
}
2550
 
 
2551
 
typedef unsigned char byte;
2552
 
 
2553
 
static rpmRC
2554
 
rpmReadSignature (FD_t fd, Header * headerp, sigType sig_type)
2555
 
{
2556
 
  byte buf[2048];
2557
 
  int sigSize, pad;
2558
 
  int_32 type, count;
2559
 
  int_32 *archSize;
2560
 
  Header h = NULL;
2561
 
  rpmRC rc = RPMRC_FAIL;        /* assume failure */
2562
 
 
2563
 
  if (headerp)
2564
 
    *headerp = NULL;
2565
 
 
2566
 
  buf[0] = 0;
2567
 
  switch (sig_type)
2568
 
    {
2569
 
    case RPMSIGTYPE_NONE:
2570
 
      rc = RPMRC_OK;
2571
 
      break;
2572
 
    case RPMSIGTYPE_PGP262_1024:
2573
 
      /* These are always 256 bytes */
2574
 
      if (timedRead (fd, buf, 256) != 256)
2575
 
        break;
2576
 
      h = headerNew ();
2577
 
      (void) headerAddEntry (h, RPMSIGTAG_PGP, RPM_BIN_TYPE, buf, 152);
2578
 
      rc = RPMRC_OK;
2579
 
      break;
2580
 
    case RPMSIGTYPE_MD5:
2581
 
    case RPMSIGTYPE_MD5_PGP:
2582
 
      break;
2583
 
    case RPMSIGTYPE_HEADERSIG:
2584
 
    case RPMSIGTYPE_DISABLE:
2585
 
      /* This is a new style signature */
2586
 
      h = headerRead (fd, HEADER_MAGIC_YES);
2587
 
      if (h == NULL)
2588
 
        break;
2589
 
 
2590
 
      rc = RPMRC_OK;
2591
 
      sigSize = headerSizeof (h, HEADER_MAGIC_YES);
2592
 
 
2593
 
      /* XXX Legacy headers have a HEADER_IMAGE tag added. */
2594
 
      if (headerIsEntry (h, RPMTAG_HEADERIMAGE))
2595
 
        sigSize -= (16 + 16);
2596
 
 
2597
 
      pad = (8 - (sigSize % 8)) % 8;    /* 8-byte pad */
2598
 
      if (sig_type == RPMSIGTYPE_HEADERSIG)
2599
 
        {
2600
 
          if (!headerGetEntry (h, RPMSIGTAG_SIZE, &type,
2601
 
                               (void **) &archSize, &count))
2602
 
            break;
2603
 
          rc = checkSize (fd, sigSize, pad, *archSize);
2604
 
        }
2605
 
      if (pad && timedRead (fd, buf, pad) != pad)
2606
 
        rc = RPMRC_SHORTREAD;
2607
 
      break;
2608
 
    default:
2609
 
      break;
2610
 
    }
2611
 
 
2612
 
  if (rc == 0 && headerp)
2613
 
    /*@-nullderef@ */
2614
 
    *headerp = h;
2615
 
  /*@=nullderef@ */
2616
 
  else if (h)
2617
 
    h = headerFree (h);
2618
 
 
2619
 
  return rc;
2620
 
}
2621
 
 
2622
 
 
2623
 
static int
2624
 
readLead (FD_t fd, struct rpmlead *lead)
2625
 
{
2626
 
  memset (lead, 0, sizeof (*lead));
2627
 
  /*@-type@ *//* FIX: remove timed read */
2628
 
  if (timedRead (fd, (char *) lead, sizeof (*lead)) != sizeof (*lead))
2629
 
    {
2630
 
      return 1;
2631
 
    }
2632
 
  /*@=type@ */
2633
 
 
2634
 
  lead->type = ntohs (lead->type);
2635
 
  lead->archnum = ntohs (lead->archnum);
2636
 
  lead->osnum = ntohs (lead->osnum);
2637
 
 
2638
 
  if (lead->major >= 2)
2639
 
    lead->signature_type = ntohs (lead->signature_type);
2640
 
 
2641
 
  return 0;
2642
 
}
2643
 
 
2644
 
/** \ingroup header
2645
 
 * Retrieve tag value using header internal array.
2646
 
 * Get an entry using as little extra RAM as possible to return the tag value.
2647
 
 * This is only an issue for RPM_STRING_ARRAY_TYPE.
2648
 
 *
2649
 
 * @param h             header
2650
 
 * @param tag           tag
2651
 
 * @retval type         address of tag value data type (or NULL)
2652
 
 * @retval p            address of pointer to tag value(s) (or NULL)
2653
 
 * @retval c            address of number of values (or NULL)
2654
 
 * @return              1 on success, 0 on failure
2655
 
 */
2656
 
static int
2657
 
headerGetEntryMinMemory (Header h, int_32 tag,
2658
 
                         /*@null@ *//*@out@ */ hTYP_t type,
2659
 
                         /*@null@ *//*@out@ */ hPTR_t * p,
2660
 
                         /*@null@ *//*@out@ */ hCNT_t c)
2661
 
        /*@modifies *type, *p, *c @ */
2662
 
{
2663
 
  return intGetEntry (h, tag, type, p, c, 1);
2664
 
}
2665
 
 
2666
 
/** \ingroup header
2667
 
 * Delete tag in header.
2668
 
 * Removes all entries of type tag from the header, returns 1 if none were
2669
 
 * found.
2670
 
 *
2671
 
 * @param h             header
2672
 
 * @param tag           tag
2673
 
 * @return              0 on success, 1 on failure (INCONSISTENT)
2674
 
 */
2675
 
static int
2676
 
headerRemoveEntry (Header h, int_32 tag)
2677
 
        /*@modifies h @ */
2678
 
{
2679
 
  indexEntry last = h->index + h->indexUsed;
2680
 
  indexEntry entry, first;
2681
 
  int ne;
2682
 
 
2683
 
  entry = findEntry (h, tag, RPM_NULL_TYPE);
2684
 
  if (!entry)
2685
 
    return 1;
2686
 
 
2687
 
  /* Make sure entry points to the first occurence of this tag. */
2688
 
  while (entry > h->index && (entry - 1)->info.tag == tag)
2689
 
    entry--;
2690
 
 
2691
 
  /* Free data for tags being removed. */
2692
 
  for (first = entry; first < last; first++)
2693
 
    {
2694
 
      void *data;
2695
 
      if (first->info.tag != tag)
2696
 
        break;
2697
 
      data = first->data;
2698
 
      first->data = NULL;
2699
 
      first->length = 0;
2700
 
      if (ENTRY_IN_REGION (first))
2701
 
        continue;
2702
 
      data = _free (data);
2703
 
    }
2704
 
 
2705
 
  ne = (first - entry);
2706
 
  if (ne > 0)
2707
 
    {
2708
 
      h->indexUsed -= ne;
2709
 
      ne = last - first;
2710
 
      if (ne > 0)
2711
 
        memmove (entry, first, (ne * sizeof (*entry)));
2712
 
    }
2713
 
 
2714
 
  return 0;
2715
 
}
2716
 
 
2717
 
static int
2718
 
dncmp (const void *a, const void *b)
2719
 
{
2720
 
  const char *const *first = a;
2721
 
  const char *const *second = b;
2722
 
  return strcmp (*first, *second);
2723
 
}
2724
 
 
2725
 
static void
2726
 
compressFilelist (Header h)
2727
 
{
2728
 
  HGE_t hge = (HGE_t) headerGetEntryMinMemory;
2729
 
  HAE_t hae = (HAE_t) headerAddEntry;
2730
 
  HRE_t hre = (HRE_t) headerRemoveEntry;
2731
 
  HFD_t hfd = headerFreeData;
2732
 
  char **fileNames;
2733
 
  const char **dirNames;
2734
 
  const char **baseNames;
2735
 
  int_32 *dirIndexes;
2736
 
  rpmTagType fnt;
2737
 
  int count;
2738
 
  int i;
2739
 
  int dirIndex = -1;
2740
 
 
2741
 
  /*
2742
 
   * This assumes the file list is already sorted, and begins with a
2743
 
   * single '/'. That assumption isn't critical, but it makes things go
2744
 
   * a bit faster.
2745
 
   */
2746
 
 
2747
 
  if (headerIsEntry (h, RPMTAG_DIRNAMES))
2748
 
    {
2749
 
      (void) hre (h, RPMTAG_OLDFILENAMES);
2750
 
      return;                   /* Already converted. */
2751
 
    }
2752
 
 
2753
 
  if (!hge (h, RPMTAG_OLDFILENAMES, &fnt, (void **) &fileNames, &count))
2754
 
    return;                     /* no file list */
2755
 
  if (fileNames == NULL || count <= 0)
2756
 
    return;
2757
 
 
2758
 
  dirNames = alloca (sizeof (*dirNames) * count);       /* worst case */
2759
 
  baseNames = alloca (sizeof (*dirNames) * count);
2760
 
  dirIndexes = alloca (sizeof (*dirIndexes) * count);
2761
 
 
2762
 
  if (fileNames[0][0] != '/')
2763
 
    {
2764
 
      /* HACK. Source RPM, so just do things differently */
2765
 
      dirIndex = 0;
2766
 
      dirNames[dirIndex] = "";
2767
 
      for (i = 0; i < count; i++)
2768
 
        {
2769
 
          dirIndexes[i] = dirIndex;
2770
 
          baseNames[i] = fileNames[i];
2771
 
        }
2772
 
      goto exit;
2773
 
    }
2774
 
 
2775
 
  for (i = 0; i < count; i++)
2776
 
    {
2777
 
      const char **needle;
2778
 
      char savechar;
2779
 
      char *baseName;
2780
 
      int len;
2781
 
 
2782
 
      if (fileNames[i] == NULL) /* XXX can't happen */
2783
 
        continue;
2784
 
      baseName = strrchr (fileNames[i], '/') + 1;
2785
 
      len = baseName - fileNames[i];
2786
 
      needle = dirNames;
2787
 
      savechar = *baseName;
2788
 
      *baseName = '\0';
2789
 
      if (dirIndex < 0 ||
2790
 
          (needle =
2791
 
           bsearch (&fileNames[i], dirNames, dirIndex + 1,
2792
 
                    sizeof (dirNames[0]), dncmp)) == NULL)
2793
 
        {
2794
 
          char *s = alloca (len + 1);
2795
 
          memcpy (s, fileNames[i], len + 1);
2796
 
          s[len] = '\0';
2797
 
          dirIndexes[i] = ++dirIndex;
2798
 
          dirNames[dirIndex] = s;
2799
 
        }
2800
 
      else
2801
 
        dirIndexes[i] = needle - dirNames;
2802
 
 
2803
 
      *baseName = savechar;
2804
 
      baseNames[i] = baseName;
2805
 
    }
2806
 
 
2807
 
exit:
2808
 
  if (count > 0)
2809
 
    {
2810
 
      (void) hae (h, RPMTAG_DIRINDEXES, RPM_INT32_TYPE, dirIndexes, count);
2811
 
      (void) hae (h, RPMTAG_BASENAMES, RPM_STRING_ARRAY_TYPE,
2812
 
                  baseNames, count);
2813
 
      (void) hae (h, RPMTAG_DIRNAMES, RPM_STRING_ARRAY_TYPE,
2814
 
                  dirNames, dirIndex + 1);
2815
 
    }
2816
 
 
2817
 
  fileNames = hfd (fileNames, fnt);
2818
 
 
2819
 
  (void) hre (h, RPMTAG_OLDFILENAMES);
2820
 
}
2821
 
 
2822
 
static int
2823
 
headerNVR (Header h, const char **np, const char **vp, const char **rp)
2824
 
{
2825
 
  int type;
2826
 
  int count;
2827
 
 
2828
 
  if (np)
2829
 
    {
2830
 
      if (!(headerGetEntry (h, RPMTAG_NAME, &type, (void **) np, &count)
2831
 
            && type == RPM_STRING_TYPE && count == 1))
2832
 
        *np = NULL;
2833
 
    }
2834
 
  if (vp)
2835
 
    {
2836
 
      if (!(headerGetEntry (h, RPMTAG_VERSION, &type, (void **) vp, &count)
2837
 
            && type == RPM_STRING_TYPE && count == 1))
2838
 
        *vp = NULL;
2839
 
    }
2840
 
  if (rp)
2841
 
    {
2842
 
      if (!(headerGetEntry (h, RPMTAG_RELEASE, &type, (void **) rp, &count)
2843
 
            && type == RPM_STRING_TYPE && count == 1))
2844
 
        *rp = NULL;
2845
 
    }
2846
 
  return 0;
2847
 
}
2848
 
 
2849
 
/*
2850
 
 * Up to rpm 3.0.4, packages implicitly provided their own name-version-release.
2851
 
 * Retrofit an explicit "Provides: name = epoch:version-release.
2852
 
 */
2853
 
static void
2854
 
providePackageNVR (Header h)
2855
 
{
2856
 
  HGE_t hge = (HGE_t) headerGetEntryMinMemory;
2857
 
  HFD_t hfd = headerFreeData;
2858
 
  const char *name, *version, *release;
2859
 
  int_32 *epoch;
2860
 
  const char *pEVR;
2861
 
  char *p;
2862
 
  int_32 pFlags = RPMSENSE_EQUAL;
2863
 
  const char **provides = NULL;
2864
 
  const char **providesEVR = NULL;
2865
 
  rpmTagType pnt, pvt = RPM_NULL_TYPE;
2866
 
  int_32 *provideFlags = NULL;
2867
 
  int providesCount;
2868
 
  int i;
2869
 
  int bingo = 1;
2870
 
 
2871
 
  /* Generate provides for this package name-version-release. */
2872
 
  (void) headerNVR (h, &name, &version, &release);
2873
 
  if (!(name && version && release))
2874
 
    return;
2875
 
  pEVR = p = alloca (21 + strlen (version) + 1 + strlen (release) + 1);
2876
 
  *p = '\0';
2877
 
  if (hge (h, RPMTAG_EPOCH, NULL, (void **) &epoch, NULL))
2878
 
    {
2879
 
      sprintf (p, "%d:", *epoch);
2880
 
      while (*p != '\0')
2881
 
        p++;
2882
 
    }
2883
 
  (void) my_stpcpy (my_stpcpy (my_stpcpy (p, version), "-"), release);
2884
 
 
2885
 
  /*
2886
 
   * Rpm prior to 3.0.3 does not have versioned provides.
2887
 
   * If no provides at all are available, we can just add.
2888
 
   */
2889
 
  if (!hge (h, RPMTAG_PROVIDENAME, &pnt, (void **) &provides, &providesCount))
2890
 
    goto exit;
2891
 
 
2892
 
  /*
2893
 
   * Otherwise, fill in entries on legacy packages.
2894
 
   */
2895
 
  if (!hge (h, RPMTAG_PROVIDEVERSION, &pvt, (void **) &providesEVR, NULL))
2896
 
    {
2897
 
      for (i = 0; i < providesCount; i++)
2898
 
        {
2899
 
          char *vdummy = "";
2900
 
          int_32 fdummy = RPMSENSE_ANY;
2901
 
          (void) headerAddOrAppendEntry (h, RPMTAG_PROVIDEVERSION,
2902
 
                                         RPM_STRING_ARRAY_TYPE, &vdummy, 1);
2903
 
          (void) headerAddOrAppendEntry (h, RPMTAG_PROVIDEFLAGS,
2904
 
                                         RPM_INT32_TYPE, &fdummy, 1);
2905
 
        }
2906
 
      goto exit;
2907
 
    }
2908
 
 
2909
 
  (void) hge (h, RPMTAG_PROVIDEFLAGS, NULL, (void **) &provideFlags, NULL);
2910
 
 
2911
 
  if (provides && providesEVR && provideFlags)
2912
 
    for (i = 0; i < providesCount; i++)
2913
 
      {
2914
 
        if (!(provides[i] && providesEVR[i]))
2915
 
          continue;
2916
 
        if (!(provideFlags[i] == RPMSENSE_EQUAL &&
2917
 
              !strcmp (name, provides[i]) && !strcmp (pEVR, providesEVR[i])))
2918
 
          continue;
2919
 
        bingo = 0;
2920
 
        break;
2921
 
      }
2922
 
 
2923
 
exit:
2924
 
  provides = hfd (provides, pnt);
2925
 
  providesEVR = hfd (providesEVR, pvt);
2926
 
 
2927
 
  if (bingo)
2928
 
    {
2929
 
      (void) headerAddOrAppendEntry (h, RPMTAG_PROVIDENAME,
2930
 
                                     RPM_STRING_ARRAY_TYPE, &name, 1);
2931
 
      (void) headerAddOrAppendEntry (h, RPMTAG_PROVIDEFLAGS, RPM_INT32_TYPE,
2932
 
                                     &pFlags, 1);
2933
 
      (void) headerAddOrAppendEntry (h, RPMTAG_PROVIDEVERSION,
2934
 
                                     RPM_STRING_ARRAY_TYPE, &pEVR, 1);
2935
 
    }
2936
 
}
2937
 
 
2938
 
static Header rpmFreeSignature (Header h);
2939
 
 
2940
 
/**
2941
 
 * Retrieve package components from file handle.
2942
 
 * @param fd            file handle
2943
 
 * @param leadPtr       address of lead (or NULL)
2944
 
 * @param sigs          address of signatures (or NULL)
2945
 
 * @param hdrPtr        address of header (or NULL)
2946
 
 * @return              rpmRC return code
2947
 
 */
2948
 
static rpmRC
2949
 
readPackageHeaders (FD_t fd,
2950
 
                    /*@null@ *//*@out@ */ struct rpmlead *leadPtr,
2951
 
                    /*@null@ *//*@out@ */ Header * sigs,
2952
 
                    /*@null@ *//*@out@ */ Header * hdrPtr)
2953
 
        /*@modifies fd, *leadPtr, *sigs, *hdrPtr @ */
2954
 
{
2955
 
  Header hdrBlock;
2956
 
  struct rpmlead leadBlock;
2957
 
  Header *hdr = NULL;
2958
 
  struct rpmlead *lead;
2959
 
  char *defaultPrefix;
2960
 
  rpmRC rc;
2961
 
 
2962
 
  hdr = hdrPtr ? hdrPtr : &hdrBlock;
2963
 
  lead = leadPtr ? leadPtr : &leadBlock;
2964
 
 
2965
 
  if (readLead (fd, lead))
2966
 
    return RPMRC_FAIL;
2967
 
 
2968
 
  if (lead->magic[0] != RPMLEAD_MAGIC0 || lead->magic[1] != RPMLEAD_MAGIC1 ||
2969
 
      lead->magic[2] != RPMLEAD_MAGIC2 || lead->magic[3] != RPMLEAD_MAGIC3)
2970
 
    {
2971
 
      return RPMRC_BADMAGIC;
2972
 
    }
2973
 
 
2974
 
  switch (lead->major)
2975
 
    {
2976
 
    case 1:
2977
 
      return RPMRC_FAIL;
2978
 
      /*@notreached@ */ break;
2979
 
    case 2:
2980
 
    case 3:
2981
 
    case 4:
2982
 
      rc = rpmReadSignature (fd, sigs, lead->signature_type);
2983
 
      if (rc == RPMRC_FAIL)
2984
 
        return rc;
2985
 
      *hdr = headerRead (fd, (lead->major >= 3)
2986
 
                         ? HEADER_MAGIC_YES : HEADER_MAGIC_NO);
2987
 
      if (*hdr == NULL)
2988
 
        {
2989
 
          if (sigs != NULL)
2990
 
            *sigs = rpmFreeSignature (*sigs);
2991
 
          return RPMRC_FAIL;
2992
 
        }
2993
 
 
2994
 
      /*
2995
 
       * We don't use these entries (and rpm >= 2 never has) and they are
2996
 
       * pretty misleading. Let's just get rid of them so they don't confuse
2997
 
       * anyone.
2998
 
       */
2999
 
      if (headerIsEntry (*hdr, RPMTAG_FILEUSERNAME))
3000
 
        (void) headerRemoveEntry (*hdr, RPMTAG_FILEUIDS);
3001
 
      if (headerIsEntry (*hdr, RPMTAG_FILEGROUPNAME))
3002
 
        (void) headerRemoveEntry (*hdr, RPMTAG_FILEGIDS);
3003
 
 
3004
 
      /*
3005
 
       * We switched the way we do relocateable packages. We fix some of
3006
 
       * it up here, though the install code still has to be a bit
3007
 
       * careful. This fixup makes queries give the new values though,
3008
 
       * which is quite handy.
3009
 
       */
3010
 
      if (headerGetEntry (*hdr, RPMTAG_DEFAULTPREFIX, NULL,
3011
 
                          (void **) &defaultPrefix, NULL))
3012
 
        {
3013
 
          defaultPrefix =
3014
 
            stripTrailingChar (alloca_strdup (defaultPrefix), '/');
3015
 
          (void) headerAddEntry (*hdr, RPMTAG_PREFIXES, RPM_STRING_ARRAY_TYPE,
3016
 
                                 &defaultPrefix, 1);
3017
 
        }
3018
 
 
3019
 
      /*
3020
 
       * The file list was moved to a more compressed format which not
3021
 
       * only saves memory (nice), but gives fingerprinting a nice, fat
3022
 
       * speed boost (very nice). Go ahead and convert old headers to
3023
 
       * the new style (this is a noop for new headers).
3024
 
       */
3025
 
      if (lead->major < 4)
3026
 
        compressFilelist (*hdr);
3027
 
 
3028
 
      /* XXX binary rpms always have RPMTAG_SOURCERPM, source rpms do not */
3029
 
      if (lead->type == RPMLEAD_SOURCE)
3030
 
        {
3031
 
          int_32 one = 1;
3032
 
          if (!headerIsEntry (*hdr, RPMTAG_SOURCEPACKAGE))
3033
 
            (void) headerAddEntry (*hdr, RPMTAG_SOURCEPACKAGE, RPM_INT32_TYPE,
3034
 
                                   &one, 1);
3035
 
        }
3036
 
      else if (lead->major < 4)
3037
 
        {
3038
 
          /* Retrofit "Provide: name = EVR" for binary packages. */
3039
 
          providePackageNVR (*hdr);
3040
 
        }
3041
 
      break;
3042
 
 
3043
 
    default:
3044
 
      return RPMRC_FAIL;
3045
 
      /*@notreached@ */ break;
3046
 
    }
3047
 
 
3048
 
  if (hdrPtr == NULL)
3049
 
    *hdr = headerFree (*hdr);
3050
 
 
3051
 
  return RPMRC_OK;
3052
 
}
3053
 
 
3054
 
static void
3055
 
headerMergeLegacySigs (Header h, const Header sig)
3056
 
{
3057
 
  HFD_t hfd = (HFD_t) headerFreeData;
3058
 
  HAE_t hae = (HAE_t) headerAddEntry;
3059
 
  HeaderIterator hi;
3060
 
  int_32 tag, type, count;
3061
 
  const void *ptr;
3062
 
 
3063
 
  /*@-mods@ *//* FIX: undocumented modification of sig */
3064
 
  for (hi = headerInitIterator (sig);
3065
 
       /*@=mods@ */
3066
 
       headerNextIterator (hi, &tag, &type, &ptr, &count, 0);
3067
 
       ptr = hfd (ptr, type))
3068
 
    {
3069
 
      switch (tag)
3070
 
        {
3071
 
        case RPMSIGTAG_SIZE:
3072
 
          tag = RPMTAG_SIGSIZE;
3073
 
          /*@switchbreak@ */ break;
3074
 
        case RPMSIGTAG_LEMD5_1:
3075
 
          tag = RPMTAG_SIGLEMD5_1;
3076
 
          /*@switchbreak@ */ break;
3077
 
        case RPMSIGTAG_PGP:
3078
 
          tag = RPMTAG_SIGPGP;
3079
 
          /*@switchbreak@ */ break;
3080
 
        case RPMSIGTAG_LEMD5_2:
3081
 
          tag = RPMTAG_SIGLEMD5_2;
3082
 
          /*@switchbreak@ */ break;
3083
 
        case RPMSIGTAG_MD5:
3084
 
          tag = RPMTAG_SIGMD5;
3085
 
          /*@switchbreak@ */ break;
3086
 
        case RPMSIGTAG_GPG:
3087
 
          tag = RPMTAG_SIGGPG;
3088
 
          /*@switchbreak@ */ break;
3089
 
        case RPMSIGTAG_PGP5:
3090
 
          tag = RPMTAG_SIGPGP5;
3091
 
          /*@switchbreak@ */ break;
3092
 
        case RPMSIGTAG_PAYLOADSIZE:
3093
 
          tag = RPMTAG_ARCHIVESIZE;
3094
 
          /*@switchbreak@ */ break;
3095
 
        case RPMSIGTAG_SHA1:
3096
 
        case RPMSIGTAG_DSA:
3097
 
        case RPMSIGTAG_RSA:
3098
 
        default:
3099
 
          if (!(tag >= HEADER_SIGBASE && tag < HEADER_TAGBASE))
3100
 
            continue;
3101
 
          /*@switchbreak@ */ break;
3102
 
        }
3103
 
      if (ptr == NULL)
3104
 
        continue;               /* XXX can't happen */
3105
 
      if (!headerIsEntry (h, tag))
3106
 
        hae (h, tag, type, ptr, count);
3107
 
    }
3108
 
  hi = headerFreeIterator (hi);
3109
 
}
3110
 
 
3111
 
static Header
3112
 
rpmFreeSignature (Header h)
3113
 
{
3114
 
  return headerFree (h);
3115
 
}
3116
 
 
3117
 
static rpmRC
3118
 
rpmReadPackageHeader (FD_t fd, Header * hdrp, int *isSource, int *major,
3119
 
                      int *minor)
3120
 
{
3121
 
  struct rpmlead lead;
3122
 
  Header sig = NULL;
3123
 
  rpmRC rc = readPackageHeaders (fd, &lead, &sig, hdrp);
3124
 
 
3125
 
  if (rc != RPMRC_OK)
3126
 
    goto exit;
3127
 
 
3128
 
  if (hdrp && *hdrp && sig)
3129
 
    {
3130
 
      headerMergeLegacySigs (*hdrp, sig);
3131
 
      sig = rpmFreeSignature (sig);
3132
 
    }
3133
 
 
3134
 
  if (isSource)
3135
 
    *isSource = lead.type == RPMLEAD_SOURCE;
3136
 
  /*@-mods@ */
3137
 
  if (major)
3138
 
    *major = lead.major;
3139
 
  if (minor)
3140
 
    *minor = lead.minor;
3141
 
  /*@=mods@ */
3142
 
 
3143
 
exit:
3144
 
  return rc;
3145
 
}
3146
 
 
3147
 
 
3148
 
/* ******************** real libextractor stuff ************************ */
 
40
pipe_feeder(void * args)
 
41
{
 
42
  ssize_t ret;
 
43
  struct PipeArgs * p = args;
 
44
 
 
45
  while ( (p->shutdown == 0) &&
 
46
          (0 < (ret = WRITE(p->pi[1],
 
47
                            &p->data[p->pos],
 
48
                            p->size - p->pos))) )
 
49
          p->pos += ret;
 
50
  CLOSE(p->pi[1]);
 
51
  return NULL;                      
 
52
}
 
53
 
 
54
static void
 
55
sigalrmHandler (int sig)
 
56
{
 
57
  /* do nothing */
 
58
}
 
59
 
 
60
 
 
61
/* *************** real libextractor stuff ***************** */
3149
62
 
3150
63
static struct EXTRACTOR_Keywords *
3151
64
addKeyword (EXTRACTOR_KeywordType type,
3152
 
            char *keyword, struct EXTRACTOR_Keywords *next)
 
65
            const char *keyword, struct EXTRACTOR_Keywords *next)
3153
66
{
3154
67
  EXTRACTOR_KeywordList *result;
3155
68
 
3168
81
  EXTRACTOR_KeywordType type;
3169
82
} Matches;
3170
83
 
3171
 
/* SEE:
3172
 
   http://rikers.org/rpmbook/node119.html#SECTION031425200000000000000 */
3173
84
static Matches tests[] = {
3174
85
  {RPMTAG_NAME, EXTRACTOR_TITLE},
3175
86
  {RPMTAG_VERSION, EXTRACTOR_VERSIONNUMBER},
3190
101
  {0, 0},
3191
102
};
3192
103
 
3193
 
/* mimetype = application/rpm */
 
104
static void discardCB() {
 
105
  /* do nothing! */
 
106
}
 
107
 
 
108
/* mimetype = application/x-rpm */
3194
109
struct EXTRACTOR_Keywords *
3195
 
libextractor_rpm_extract (char *filename,
3196
 
                          char *data,
 
110
libextractor_rpm_extract (const char *filename,
 
111
                          const char *data,
3197
112
                          size_t size, struct EXTRACTOR_Keywords *prev)
3198
113
{
3199
 
  fdStruct handle;
 
114
  struct PipeArgs parg;
 
115
  pthread_t pthr;
 
116
  void * unused;
3200
117
  Header hdr;
3201
118
  HeaderIterator hi;
3202
119
  int_32 tag;
3203
120
  int_32 type;
3204
121
  int_32 c;
3205
122
  hPTR_t p;
3206
 
  int isSource;
3207
 
  int major;
3208
 
  int minor;
3209
123
  int i;
3210
 
  char verb[40];
 
124
  FD_t fdi;
 
125
  rpmRC rc;
 
126
  rpmts ts;
 
127
  struct sigaction sig;
 
128
  struct sigaction old;
3211
129
 
3212
 
  handle.data = data;
3213
 
  handle.pos = 0;
3214
 
  handle.len = size;
3215
 
  if (0 != rpmReadPackageHeader (&handle, &hdr, &isSource, &major, &minor))
 
130
  if (0 != pipe(parg.pi))
 
131
    return prev;
 
132
  fdi = NULL;
 
133
  parg.data = data;
 
134
  parg.pos = 0;
 
135
  parg.size = size;
 
136
  parg.shutdown = 0;
 
137
  if (0 != pthread_create(&pthr,
 
138
                          NULL,
 
139
                          &pipe_feeder,
 
140
                          &parg))
3216
141
    {
 
142
      CLOSE(parg.pi[0]);
 
143
      CLOSE(parg.pi[1]);
3217
144
      return prev;
3218
145
    }
 
146
  rpmlogSetCallback(&discardCB);
 
147
  fdi = fdDup(parg.pi[0]);
 
148
  ts = rpmtsCreate();
 
149
  rc = rpmReadPackageFile (ts, fdi, "GNU libextractor", &hdr);
 
150
  switch (rc)
 
151
    {
 
152
    case RPMRC_OK:
 
153
    case RPMRC_NOKEY:
 
154
    case RPMRC_NOTTRUSTED:
 
155
      break;
 
156
    case RPMRC_NOTFOUND:
 
157
    case RPMRC_FAIL:
 
158
    default:
 
159
      goto END;
 
160
    }
3219
161
  prev = addKeyword (EXTRACTOR_MIMETYPE,
3220
 
                     "application/x-redhat-package-manager", prev);
3221
 
  /* FIXME: add platform! */
3222
 
  if (isSource)
3223
 
    sprintf (verb, _("Source RPM %d.%d"), major, minor);
3224
 
  else
3225
 
    sprintf (verb, _("Binary RPM %d.%d"), major, minor);
3226
 
  prev = addKeyword (EXTRACTOR_UNKNOWN, verb, prev);
 
162
                     "application/x-rpm", prev);
3227
163
  hi = headerInitIterator (hdr);
3228
 
  while (1 == headerNextIterator (hi, &tag, &type, &p, &c, 0))
 
164
  while (1 == headerNextIterator (hi, &tag, &type, &p, &c))
3229
165
    {
3230
166
      i = 0;
3231
167
      while (tests[i].rtype != 0)
3330
266
    }
3331
267
  headerFreeIterator (hi);
3332
268
  headerFree (hdr);
 
269
  rpmtsFree(ts);
 
270
 END:                                           
 
271
  /* make sure SIGALRM does not kill us */
 
272
  memset (&sig, 0, sizeof (struct sigaction));
 
273
  memset (&old, 0, sizeof (struct sigaction));
 
274
  sig.sa_flags = SA_NODEFER;
 
275
  sig.sa_handler = &sigalrmHandler;
 
276
  sigaction (SIGALRM, &sig, &old);
 
277
  parg.shutdown = 1;
 
278
  pthread_kill(pthr, SIGALRM);
 
279
  pthread_join(pthr, &unused);
 
280
  sigaction (SIGALRM, &old, &sig);
 
281
  Fclose(fdi);
 
282
  CLOSE(parg.pi[0]);
3333
283
  return prev;
3334
284
}
3335
285
 
3336
 
 
3337
 
 
3338
 
 
3339
286
/* end of rpmextractor.c */