rpm  4.5
header-py.c
Go to the documentation of this file.
1 
5 #include "system.h"
6 
7 #include "rpmio_internal.h"
8 #include "rpmcli.h" /* XXX for rpmCheckSig */
9 
10 #include "legacy.h"
11 #include "misc.h"
12 #include "header_internal.h"
13 
14 #include "rpmts.h" /* XXX rpmtsCreate/rpmtsFree */
15 #define _RPMEVR_INTERNAL
16 #include "rpmevr.h"
17 
18 #include "header-py.h"
19 #include "rpmds-py.h"
20 #include "rpmfi-py.h"
21 
22 #include "debug.h"
23 
135 struct hdrObject_s {
136  PyObject_HEAD
138  char ** md5list;
139  char ** fileList;
140  char ** linkList;
143  int_32 * uids, * gids; /* XXX these tags are not used anymore */
144  unsigned short * rdevs;
145  unsigned short * modes;
146 } ;
147 
150 /*@unused@*/ static inline Header headerAllocated(Header h)
151  /*@modifies h @*/
152 {
154  return 0;
155 }
156 
157 /*@-boundsread@*/
158 static int dncmp(const void * a, const void * b)
159  /*@*/
160 {
161  const char *const * first = a;
162  const char *const * second = b;
163  return strcmp(*first, *second);
164 }
165 /*@=boundsread@*/
166 
171 static void expandFilelist(Header h)
172  /*@modifies h @*/
173 {
174  HAE_t hae = (HAE_t)headerAddEntry;
176  const char ** fileNames = NULL;
177  int count = 0;
178  int xx;
179 
180  /*@-branchstate@*/
182  rpmfiBuildFNames(h, RPMTAG_BASENAMES, &fileNames, &count);
183  if (fileNames == NULL || count <= 0)
184  return;
186  fileNames, count);
187  fileNames = _free(fileNames);
188  }
189  /*@=branchstate@*/
190 
191  xx = hre(h, RPMTAG_DIRNAMES);
192  xx = hre(h, RPMTAG_BASENAMES);
193  xx = hre(h, RPMTAG_DIRINDEXES);
194 }
195 
196 /*@-bounds@*/
201 static void compressFilelist(Header h)
202  /*@modifies h @*/
203 {
205  HAE_t hae = (HAE_t)headerAddEntry;
207  HFD_t hfd = headerFreeData;
208  char ** fileNames;
209  const char ** dirNames;
210  const char ** baseNames;
211  int_32 * dirIndexes;
212  rpmTagType fnt;
213  int count;
214  int i, xx;
215  int dirIndex = -1;
216 
217  /*
218  * This assumes the file list is already sorted, and begins with a
219  * single '/'. That assumption isn't critical, but it makes things go
220  * a bit faster.
221  */
222 
223  if (headerIsEntry(h, RPMTAG_DIRNAMES)) {
224  xx = hre(h, RPMTAG_OLDFILENAMES);
225  return; /* Already converted. */
226  }
227 
228  if (!hge(h, RPMTAG_OLDFILENAMES, &fnt, &fileNames, &count))
229  return; /* no file list */
230  if (fileNames == NULL || count <= 0)
231  return;
232 
233  dirNames = alloca(sizeof(*dirNames) * count); /* worst case */
234  baseNames = alloca(sizeof(*dirNames) * count);
235  dirIndexes = alloca(sizeof(*dirIndexes) * count);
236 
237  if (fileNames[0][0] != '/') {
238  /* HACK. Source RPM, so just do things differently */
239  dirIndex = 0;
240  dirNames[dirIndex] = "";
241  for (i = 0; i < count; i++) {
242  dirIndexes[i] = dirIndex;
243  baseNames[i] = fileNames[i];
244  }
245  goto exit;
246  }
247 
248  /*@-branchstate@*/
249  for (i = 0; i < count; i++) {
250  const char ** needle;
251  char savechar;
252  char * baseName;
253  int len;
254 
255  if (fileNames[i] == NULL) /* XXX can't happen */
256  continue;
257  baseName = strrchr(fileNames[i], '/') + 1;
258  len = baseName - fileNames[i];
259  needle = dirNames;
260  savechar = *baseName;
261  *baseName = '\0';
262 /*@-compdef@*/
263  if (dirIndex < 0 ||
264  (needle = bsearch(&fileNames[i], dirNames, dirIndex + 1, sizeof(dirNames[0]), dncmp)) == NULL) {
265  char *s = alloca(len + 1);
266  memcpy(s, fileNames[i], len + 1);
267  s[len] = '\0';
268  dirIndexes[i] = ++dirIndex;
269  dirNames[dirIndex] = s;
270  } else
271  dirIndexes[i] = needle - dirNames;
272 /*@=compdef@*/
273 
274  *baseName = savechar;
275  baseNames[i] = baseName;
276  }
277  /*@=branchstate@*/
278 
279 exit:
280  if (count > 0) {
281  xx = hae(h, RPMTAG_DIRINDEXES, RPM_INT32_TYPE, dirIndexes, count);
283  baseNames, count);
285  dirNames, dirIndex + 1);
286  }
287 
288  fileNames = hfd(fileNames, fnt);
289 
290  xx = hre(h, RPMTAG_OLDFILENAMES);
291 }
292 /*@=bounds@*/
293 /* make a header with _all_ the tags we need */
296 static void mungeFilelist(Header h)
297  /*@*/
298 {
299  const char ** fileNames = NULL;
300  int count = 0;
301 
305  compressFilelist(h);
306 
307  rpmfiBuildFNames(h, RPMTAG_BASENAMES, &fileNames, &count);
308 
309  if (fileNames == NULL || count <= 0)
310  return;
311 
312  /* XXX Legacy tag needs to go away. */
314  fileNames, count);
315 
316  fileNames = _free(fileNames);
317 }
318 
324 static void providePackageNVR(Header h)
325 {
327  HFD_t hfd = headerFreeData;
328  const char *name, *version, *release;
329  int_32 * epoch;
330  const char *pEVR;
331  char *p;
332  int_32 pFlags = RPMSENSE_EQUAL;
333  const char ** provides = NULL;
334  const char ** providesEVR = NULL;
335  rpmTagType pnt, pvt;
336  int_32 * provideFlags = NULL;
337  int providesCount;
338  int i, xx;
339  int bingo = 1;
340 
341  /* Generate provides for this package name-version-release. */
342  xx = headerNVR(h, &name, &version, &release);
343  if (!(name && version && release))
344  return;
345  pEVR = p = alloca(21 + strlen(version) + 1 + strlen(release) + 1);
346  *p = '\0';
347  if (hge(h, RPMTAG_EPOCH, NULL, &epoch, NULL)) {
348  sprintf(p, "%d:", *epoch);
349  while (*p != '\0')
350  p++;
351  }
352  (void) stpcpy( stpcpy( stpcpy(p, version) , "-") , release);
353 
354  /*
355  * Rpm prior to 3.0.3 does not have versioned provides.
356  * If no provides at all are available, we can just add.
357  */
358  if (!hge(h, RPMTAG_PROVIDENAME, &pnt, &provides, &providesCount))
359  goto exit;
360 
361  /*
362  * Otherwise, fill in entries on legacy packages.
363  */
364  if (!hge(h, RPMTAG_PROVIDEVERSION, &pvt, &providesEVR, NULL)) {
365  for (i = 0; i < providesCount; i++) {
366  char * vdummy = "";
367  int_32 fdummy = RPMSENSE_ANY;
369  &vdummy, 1);
371  &fdummy, 1);
372  }
373  goto exit;
374  }
375 
376  xx = hge(h, RPMTAG_PROVIDEFLAGS, NULL, &provideFlags, NULL);
377 
378  /*@-nullderef@*/ /* LCL: providesEVR is not NULL */
379  if (provides && providesEVR && provideFlags)
380  for (i = 0; i < providesCount; i++) {
381  if (!(provides[i] && providesEVR[i]))
382  continue;
383  if (!(provideFlags[i] == RPMSENSE_EQUAL &&
384  !strcmp(name, provides[i]) && !strcmp(pEVR, providesEVR[i])))
385  continue;
386  bingo = 0;
387  break;
388  }
389  /*@=nullderef@*/
390 
391 exit:
392  provides = hfd(provides, pnt);
393  providesEVR = hfd(providesEVR, pvt);
394 
395  if (bingo) {
397  &name, 1);
399  &pFlags, 1);
401  &pEVR, 1);
402  }
403 }
404 
409 
412 static PyObject * hdrKeyList(hdrObject * s)
413  /*@*/
414 {
415  PyObject * list, *o;
416  HeaderIterator hi;
417  int tag, type;
418 
419  list = PyList_New(0);
420 
421  hi = headerInitIterator(s->h);
422  while (headerNextIterator(hi, &tag, &type, NULL, NULL)) {
423  if (tag == HEADER_I18NTABLE) continue;
424 
425  switch (type) {
426  case RPM_OPENPGP_TYPE:
427  case RPM_ASN1_TYPE:
428  case RPM_BIN_TYPE:
429  case RPM_INT64_TYPE:
430  case RPM_INT32_TYPE:
431  case RPM_INT16_TYPE:
432  case RPM_INT8_TYPE:
433  case RPM_CHAR_TYPE:
435  case RPM_STRING_TYPE:
436  PyList_Append(list, o=PyInt_FromLong(tag));
437  Py_DECREF(o);
438  }
439  }
440  headerFreeIterator(hi);
441 
442  return list;
443 }
444 
447 static PyObject * hdrUnload(hdrObject * s, PyObject * args, PyObject *keywords)
448  /*@*/
449 {
450  char * buf;
451  PyObject * rc;
452  int len, legacy = 0;
453  Header h;
454  static char *kwlist[] = { "legacyHeader", NULL};
455 
456  if (!PyArg_ParseTupleAndKeywords(args, keywords, "|i", kwlist, &legacy))
457  return NULL;
458 
459  h = headerLink(s->h);
460  /* XXX this legacy switch is a hack, needs to be removed. */
461  if (legacy) {
462  h = headerCopy(s->h); /* XXX strip region tags, etc */
463  headerFree(s->h);
464  }
465  len = headerSizeof(h, 0);
466  buf = headerUnload(h);
467  h = headerFree(h);
468 
469  if (buf == NULL || len == 0) {
470  PyErr_SetString(pyrpmError, "can't unload bad header\n");
471  return NULL;
472  }
473 
474  rc = PyString_FromStringAndSize(buf, len);
475  buf = _free(buf);
476 
477  return rc;
478 }
479 
482 static PyObject * hdrExpandFilelist(hdrObject * s)
483  /*@*/
484 {
485  expandFilelist (s->h);
486 
487  Py_INCREF(Py_None);
488  return Py_None;
489 }
490 
493 static PyObject * hdrCompressFilelist(hdrObject * s)
494  /*@*/
495 {
496  compressFilelist (s->h);
497 
498  Py_INCREF(Py_None);
499  return Py_None;
500 }
501 
504 static PyObject * hdrGetOrigin(hdrObject * s)
505  /*@*/
506 {
507  const char * origin = NULL;
508  if (s->h != NULL)
509 
510  origin = headerGetOrigin(s->h);
511  if (origin != NULL)
512  return Py_BuildValue("s", origin);
513  Py_INCREF(Py_None);
514  return Py_None;
515 }
516 
519 static PyObject * hdrSetOrigin(hdrObject * s, PyObject * args, PyObject * kwds)
520  /*@*/
521 {
522  char * kwlist[] = {"origin", NULL};
523  const char * origin = NULL;
524 
525  if (!PyArg_ParseTupleAndKeywords(args, kwds, "s:SetOrigin", kwlist, &origin))
526  return NULL;
527 
528  if (s->h != NULL && origin != NULL)
529  headerSetOrigin(s->h, origin);
530 
531  Py_INCREF(Py_None);
532  return Py_None;
533 }
534 
537 static PyObject * hdrFullFilelist(hdrObject * s)
538  /*@*/
539 {
540  mungeFilelist (s->h);
541 
542  Py_INCREF(Py_None);
543  return Py_None;
544 }
545 
548 static PyObject * hdrSprintf(hdrObject * s, PyObject * args, PyObject * kwds)
549  /*@*/
550 {
551  char * fmt;
552  char * r;
553  errmsg_t err;
554  PyObject * result;
555  char * kwlist[] = {"format", NULL};
556 
557  if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &fmt))
558  return NULL;
559 
560  r = headerSprintf(s->h, fmt, rpmTagTable, rpmHeaderFormats, &err);
561  if (!r) {
562  PyErr_SetString(pyrpmError, err);
563  return NULL;
564  }
565 
566  result = Py_BuildValue("s", r);
567  r = _free(r);
568 
569  return result;
570 }
571 
576 /*@unchecked@*/ /*@observer@*/
577 static struct PyMethodDef hdr_methods[] = {
578  {"keys", (PyCFunction) hdrKeyList, METH_NOARGS,
579  NULL },
580  {"unload", (PyCFunction) hdrUnload, METH_VARARGS|METH_KEYWORDS,
581  NULL },
582  {"expandFilelist", (PyCFunction) hdrExpandFilelist,METH_NOARGS,
583  NULL },
584  {"compressFilelist",(PyCFunction) hdrCompressFilelist,METH_NOARGS,
585  NULL },
586  {"fullFilelist", (PyCFunction) hdrFullFilelist, METH_NOARGS,
587  NULL },
588  {"getorigin", (PyCFunction) hdrGetOrigin, METH_NOARGS,
589  NULL },
590  {"setorigin", (PyCFunction) hdrSetOrigin, METH_NOARGS,
591  NULL },
592  {"sprintf", (PyCFunction) hdrSprintf, METH_VARARGS|METH_KEYWORDS,
593  NULL },
594 
595  {"dsOfHeader", (PyCFunction)hdr_dsOfHeader, METH_NOARGS,
596  NULL},
597  {"dsFromHeader", (PyCFunction)hdr_dsFromHeader, METH_VARARGS|METH_KEYWORDS,
598  NULL},
599  {"fiFromHeader", (PyCFunction)hdr_fiFromHeader, METH_VARARGS|METH_KEYWORDS,
600  NULL},
601 
602  {NULL, NULL} /* sentinel */
603 };
604 
607 static int hdr_compare(hdrObject * a, hdrObject * b)
608  /*@*/
609 {
610  return rpmVersionCompare(a->h, b->h);
611 }
612 
613 static long hdr_hash(PyObject * h)
614 {
615  return (long) h;
616 }
617 
618 
621 static void hdr_dealloc(hdrObject * s)
622  /*@*/
623 {
624  if (s->h) headerFree(s->h);
625  s->md5list = _free(s->md5list);
626  s->fileList = _free(s->fileList);
627  s->linkList = _free(s->linkList);
628  PyObject_Del(s);
629 }
630 
633 long tagNumFromPyObject (PyObject *item)
634 {
635  char * str;
636  int i;
637 
638  if (PyInt_Check(item)) {
639  return PyInt_AsLong(item);
640  } else if (PyString_Check(item) || PyUnicode_Check(item)) {
641  str = PyString_AsString(item);
642  for (i = 0; i < rpmTagTableSize; i++)
643  if (!xstrcasecmp(rpmTagTable[i].name + 7, str)) break;
644  if (i < rpmTagTableSize) return rpmTagTable[i].val;
645  }
646  return -1;
647 }
648 
662 static int rpmHeaderGetEntry(Header h, int_32 tag, /*@out@*/ int_32 *type,
663  /*@out@*/ void **p, /*@out@*/ int_32 *c)
664  /*@modifies *type, *p, *c @*/
665 {
666  switch (tag) {
667  case RPMTAG_OLDFILENAMES:
668  { const char ** fl = NULL;
669  int count;
670  rpmfiBuildFNames(h, RPMTAG_BASENAMES, &fl, &count);
671  if (count > 0) {
672  *p = fl;
673  if (c) *c = count;
674  if (type) *type = RPM_STRING_ARRAY_TYPE;
675  return 1;
676  }
677  if (c) *c = 0;
678  return 0;
679  } /*@notreached@*/ break;
680 
681  case RPMTAG_GROUP:
682  case RPMTAG_DESCRIPTION:
683  case RPMTAG_SUMMARY:
684  { char fmt[128];
685  const char * msgstr;
686  const char * errstr;
687 
688  fmt[0] = '\0';
689  (void) stpcpy( stpcpy( stpcpy( fmt, "%{"), tagName(tag)), "}\n");
690 
691  /* XXX FIXME: memory leak. */
692  msgstr = headerSprintf(h, fmt, rpmTagTable, rpmHeaderFormats, &errstr);
693  if (msgstr) {
694  *p = (void *) msgstr;
695  if (type) *type = RPM_STRING_TYPE;
696  if (c) *c = 1;
697  return 1;
698  } else {
699  if (c) *c = 0;
700  return 0;
701  }
702  } /*@notreached@*/ break;
703 
704  default:
705  return headerGetEntry(h, tag, type, p, c);
706  /*@notreached@*/ break;
707  }
708  /*@notreached@*/
709 }
710 
713 static PyObject * hdr_subscript(hdrObject * s, PyObject * item)
714  /*@*/
715 {
716  int type, count, i, tag = -1;
717  void * data;
718  PyObject * o, * metao;
719  char ** stringArray;
720  int forceArray = 0;
721  int freeData = 0;
722  char * str;
723  const struct headerSprintfExtension_s * ext = NULL;
724  const struct headerSprintfExtension_s * extensions = rpmHeaderFormats;
725 
726  if (PyCObject_Check (item))
727  ext = PyCObject_AsVoidPtr(item);
728  else
729  tag = tagNumFromPyObject (item);
730  if (tag == -1 && (PyString_Check(item) || PyUnicode_Check(item))) {
731  /* if we still don't have the tag, go looking for the header
732  extensions */
733  str = PyString_AsString(item);
734  while (extensions->name) {
735  if (extensions->type == HEADER_EXT_TAG
736  && !xstrcasecmp(extensions->name + 7, str)) {
737  ext = extensions;
738  }
739  extensions++;
740  }
741  }
742 
743  /* Retrieve data from extension or header. */
744  if (ext) {
745  HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
746  ext->u.tagFunction(s->h, he);
747  type = he->t;
748  data = he->p.ptr;
749  count = he->c;
750  freeData = he->freeData;
751  } else {
752  if (tag == -1) {
753  PyErr_SetString(PyExc_KeyError, "unknown header tag");
754  return NULL;
755  }
756 
757  if (!rpmHeaderGetEntry(s->h, tag, &type, &data, &count)) {
758  switch (tag) {
759  case RPMTAG_EPOCH:
760  case RPMTAG_NAME:
761  case RPMTAG_VERSION:
762  case RPMTAG_RELEASE:
763  case RPMTAG_ARCH:
764  case RPMTAG_OS:
765  Py_INCREF(Py_None);
766  return Py_None;
767  break;
768  default:
769  return PyList_New(0);
770  break;
771  }
772  }
773  }
774 
775  switch (tag) {
776  case RPMTAG_OLDFILENAMES:
777  case RPMTAG_FILESIZES:
778  case RPMTAG_FILESTATES:
779  case RPMTAG_FILEMODES:
780  case RPMTAG_FILEUIDS:
781  case RPMTAG_FILEGIDS:
782  case RPMTAG_FILERDEVS:
783  case RPMTAG_FILEMTIMES:
784  case RPMTAG_FILEMD5S:
785  case RPMTAG_FILELINKTOS:
786  case RPMTAG_FILEFLAGS:
787  case RPMTAG_ROOT:
788  case RPMTAG_FILEUSERNAME:
790  case RPMTAG_REQUIRENAME:
791  case RPMTAG_REQUIREFLAGS:
793  case RPMTAG_PROVIDENAME:
794  case RPMTAG_PROVIDEFLAGS:
796  case RPMTAG_OBSOLETENAME:
799  case RPMTAG_CONFLICTNAME:
804  forceArray = 1;
805  break;
806  case RPMTAG_SUMMARY:
807  case RPMTAG_GROUP:
808  case RPMTAG_DESCRIPTION:
809  freeData = 1;
810  break;
811  default:
812  break;
813  }
814 
815  switch (type) {
816  case RPM_OPENPGP_TYPE:
817  case RPM_ASN1_TYPE:
818  case RPM_BIN_TYPE:
819  o = PyString_FromStringAndSize(data, count);
820  break;
821 
822  case RPM_INT64_TYPE:
823  if (count != 1 || forceArray) {
824  metao = PyList_New(0);
825  for (i = 0; i < count; i++) {
826  o = PyInt_FromLong(((long long *) data)[i]);
827  PyList_Append(metao, o);
828  Py_DECREF(o);
829  }
830  o = metao;
831  } else {
832  o = PyInt_FromLong(*((long long *) data));
833  }
834  break;
835  case RPM_INT32_TYPE:
836  if (count != 1 || forceArray) {
837  metao = PyList_New(0);
838  for (i = 0; i < count; i++) {
839  o = PyInt_FromLong(((int *) data)[i]);
840  PyList_Append(metao, o);
841  Py_DECREF(o);
842  }
843  o = metao;
844  } else {
845  o = PyInt_FromLong(*((int *) data));
846  }
847  break;
848 
849  case RPM_CHAR_TYPE:
850  case RPM_INT8_TYPE:
851  if (count != 1 || forceArray) {
852  metao = PyList_New(0);
853  for (i = 0; i < count; i++) {
854  o = PyInt_FromLong(((char *) data)[i]);
855  PyList_Append(metao, o);
856  Py_DECREF(o);
857  }
858  o = metao;
859  } else {
860  o = PyInt_FromLong(*((char *) data));
861  }
862  break;
863 
864  case RPM_INT16_TYPE:
865  if (count != 1 || forceArray) {
866  metao = PyList_New(0);
867  for (i = 0; i < count; i++) {
868  o = PyInt_FromLong(((short *) data)[i]);
869  PyList_Append(metao, o);
870  Py_DECREF(o);
871  }
872  o = metao;
873  } else {
874  o = PyInt_FromLong(*((short *) data));
875  }
876  break;
877 
879  stringArray = data;
880 
881  metao = PyList_New(0);
882  for (i = 0; i < count; i++) {
883  o = PyString_FromString(stringArray[i]);
884  PyList_Append(metao, o);
885  Py_DECREF(o);
886  }
887  free (stringArray);
888  o = metao;
889  break;
890 
891  case RPM_STRING_TYPE:
892  if (count != 1 || forceArray) {
893  stringArray = data;
894 
895  metao = PyList_New(0);
896  for (i=0; i < count; i++) {
897  o = PyString_FromString(stringArray[i]);
898  PyList_Append(metao, o);
899  Py_DECREF(o);
900  }
901  o = metao;
902  } else {
903  o = PyString_FromString(data);
904  if (freeData)
905  free (data);
906  }
907  break;
908 
909  default:
910  PyErr_SetString(PyExc_TypeError, "unsupported type in header");
911  return NULL;
912  }
913 
914  return o;
915 }
916 
917 static PyObject * hdr_getattro(PyObject * o, PyObject * n)
918  /*@*/
919 {
920  PyObject * res = PyObject_GenericGetAttr(o, n);
921  if (res == NULL)
922  res = hdr_subscript(o, n);
923  return res;
924 }
925 
926 static int hdr_setattro(PyObject * o, PyObject * n, PyObject * v)
927  /*@*/
928 {
929  return PyObject_GenericSetAttr(o, n, v);
930 }
931 
934 /*@unchecked@*/ /*@observer@*/
935 static PyMappingMethods hdr_as_mapping = {
936  (inquiry) 0, /* mp_length */
937  (binaryfunc) hdr_subscript, /* mp_subscript */
938  (objobjargproc)0, /* mp_ass_subscript */
939 };
940 
943 static char hdr_doc[] =
944 "";
945 
948 /*@unchecked@*/ /*@observer@*/
949 PyTypeObject hdr_Type = {
950  PyObject_HEAD_INIT(&PyType_Type)
951  0, /* ob_size */
952  "rpm.hdr", /* tp_name */
953  sizeof(hdrObject), /* tp_size */
954  0, /* tp_itemsize */
955  (destructor) hdr_dealloc, /* tp_dealloc */
956  0, /* tp_print */
957  (getattrfunc) 0, /* tp_getattr */
958  0, /* tp_setattr */
959  (cmpfunc) hdr_compare, /* tp_compare */
960  0, /* tp_repr */
961  0, /* tp_as_number */
962  0, /* tp_as_sequence */
963  &hdr_as_mapping, /* tp_as_mapping */
964  hdr_hash, /* tp_hash */
965  0, /* tp_call */
966  0, /* tp_str */
967  (getattrofunc) hdr_getattro, /* tp_getattro */
968  (setattrofunc) hdr_setattro, /* tp_setattro */
969  0, /* tp_as_buffer */
970  Py_TPFLAGS_DEFAULT, /* tp_flags */
971  hdr_doc, /* tp_doc */
972 #if Py_TPFLAGS_HAVE_ITER
973  0, /* tp_traverse */
974  0, /* tp_clear */
975  0, /* tp_richcompare */
976  0, /* tp_weaklistoffset */
977  0, /* tp_iter */
978  0, /* tp_iternext */
979  hdr_methods, /* tp_methods */
980  0, /* tp_members */
981  0, /* tp_getset */
982  0, /* tp_base */
983  0, /* tp_dict */
984  0, /* tp_descr_get */
985  0, /* tp_descr_set */
986  0, /* tp_dictoffset */
987  0, /* tp_init */
988  0, /* tp_alloc */
989  0, /* tp_new */
990  0, /* tp_free */
991  0, /* tp_is_gc */
992 #endif
993 };
994 
996 {
997  hdrObject * hdr = PyObject_New(hdrObject, &hdr_Type);
998  hdr->h = headerLink(h);
999  hdr->fileList = hdr->linkList = hdr->md5list = NULL;
1000  hdr->uids = hdr->gids = hdr->mtimes = hdr->fileSizes = NULL;
1001  hdr->modes = hdr->rdevs = NULL;
1002  return hdr;
1003 }
1004 
1006 {
1007  return s->h;
1008 }
1009 
1012 PyObject * hdrLoad(PyObject * self, PyObject * args, PyObject * kwds)
1013 {
1014  hdrObject * hdr;
1015  char * copy = NULL;
1016  char * obj;
1017  Header h;
1018  int len;
1019  char * kwlist[] = {"headers", NULL};
1020 
1021  if (!PyArg_ParseTupleAndKeywords(args, kwds, "s#", kwlist, &obj, &len))
1022  return NULL;
1023 
1024  /* malloc is needed to avoid surprises from data swab in headerLoad(). */
1025  copy = malloc(len);
1026  if (copy == NULL) {
1027  PyErr_SetString(pyrpmError, "out of memory");
1028  return NULL;
1029  }
1030  memcpy (copy, obj, len);
1031 
1032  h = headerLoad(copy);
1033  if (!h) {
1034  PyErr_SetString(pyrpmError, "bad header");
1035  return NULL;
1036  }
1037  headerAllocated(h);
1038  compressFilelist (h);
1039  providePackageNVR (h);
1040 
1041  hdr = hdr_Wrap(h);
1042  h = headerFree(h); /* XXX ref held by hdr */
1043 
1044  return (PyObject *) hdr;
1045 }
1046 
1049 PyObject * rpmReadHeaders (FD_t fd)
1050 {
1051  PyObject * list;
1052  Header h;
1053  hdrObject * hdr;
1054 
1055  if (!fd) {
1056  PyErr_SetFromErrno(pyrpmError);
1057  return NULL;
1058  }
1059 
1060  list = PyList_New(0);
1061  Py_BEGIN_ALLOW_THREADS
1062  h = headerRead(fd, HEADER_MAGIC_YES);
1063  Py_END_ALLOW_THREADS
1064 
1065  while (h) {
1066  compressFilelist(h);
1067  providePackageNVR(h);
1068  hdr = hdr_Wrap(h);
1069  if (PyList_Append(list, (PyObject *) hdr)) {
1070  Py_DECREF(list);
1071  Py_DECREF(hdr);
1072  return NULL;
1073  }
1074  Py_DECREF(hdr);
1075 
1076  h = headerFree(h); /* XXX ref held by hdr */
1077 
1078  Py_BEGIN_ALLOW_THREADS
1079  h = headerRead(fd, HEADER_MAGIC_YES);
1080  Py_END_ALLOW_THREADS
1081  }
1082 
1083  return list;
1084 }
1085 
1088 PyObject * rpmHeaderFromFD(PyObject * self, PyObject * args, PyObject * kwds)
1089 {
1090  FD_t fd;
1091  int fileno;
1092  PyObject * list;
1093  char * kwlist[] = {"fd", NULL};
1094 
1095  if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, &fileno))
1096  return NULL;
1097 
1098  fd = fdDup(fileno);
1099 
1100  list = rpmReadHeaders (fd);
1101  Fclose(fd);
1102 
1103  return list;
1104 }
1105 
1108 PyObject * rpmHeaderFromFile(PyObject * self, PyObject * args, PyObject *kwds)
1109 {
1110  char * filespec;
1111  FD_t fd;
1112  PyObject * list;
1113  char * kwlist[] = {"file", NULL};
1114 
1115  if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &filespec))
1116  return NULL;
1117 
1118  fd = Fopen(filespec, "r.fdio");
1119 
1120  if (!fd) {
1121  PyErr_SetFromErrno(pyrpmError);
1122  return NULL;
1123  }
1124 
1125  list = rpmReadHeaders (fd);
1126  Fclose(fd);
1127 
1128  return list;
1129 }
1130 
1135 int rpmMergeHeaders(PyObject * list, FD_t fd, int matchTag)
1136 {
1137  Header h;
1138  HeaderIterator hi;
1139  int_32 * newMatch;
1140  int_32 * oldMatch;
1141  hdrObject * hdr;
1142  int count = 0;
1143  int type, c, tag;
1144  void * p;
1145 
1146  Py_BEGIN_ALLOW_THREADS
1147  h = headerRead(fd, HEADER_MAGIC_YES);
1148  Py_END_ALLOW_THREADS
1149 
1150  while (h) {
1151  if (!headerGetEntry(h, matchTag, NULL, &newMatch, NULL)) {
1152  PyErr_SetString(pyrpmError, "match tag missing in new header");
1153  return 1;
1154  }
1155 
1156  hdr = (hdrObject *) PyList_GetItem(list, count++);
1157  if (!hdr) return 1;
1158 
1159  if (!headerGetEntry(hdr->h, matchTag, NULL, &oldMatch, NULL)) {
1160  PyErr_SetString(pyrpmError, "match tag missing in new header");
1161  return 1;
1162  }
1163 
1164  if (*newMatch != *oldMatch) {
1165  PyErr_SetString(pyrpmError, "match tag mismatch");
1166  return 1;
1167  }
1168 
1169  hdr->md5list = _free(hdr->md5list);
1170  hdr->fileList = _free(hdr->fileList);
1171  hdr->linkList = _free(hdr->linkList);
1172 
1173  for (hi = headerInitIterator(h);
1174  headerNextIterator(hi, &tag, &type, (void *) &p, &c);
1175  p = headerFreeData(p, type))
1176  {
1177  /* could be dupes */
1178  headerRemoveEntry(hdr->h, tag);
1179  headerAddEntry(hdr->h, tag, type, p, c);
1180  }
1181 
1182  headerFreeIterator(hi);
1183  h = headerFree(h);
1184 
1185  Py_BEGIN_ALLOW_THREADS
1186  h = headerRead(fd, HEADER_MAGIC_YES);
1187  Py_END_ALLOW_THREADS
1188  }
1189 
1190  return 0;
1191 }
1192 
1193 PyObject *
1194 rpmMergeHeadersFromFD(PyObject * self, PyObject * args, PyObject * kwds)
1195 {
1196  FD_t fd;
1197  int fileno;
1198  PyObject * list;
1199  int rc;
1200  int matchTag;
1201  char * kwlist[] = {"list", "fd", "matchTag", NULL};
1202 
1203  if (!PyArg_ParseTupleAndKeywords(args, kwds, "Oii", kwlist, &list,
1204  &fileno, &matchTag))
1205  return NULL;
1206 
1207  if (!PyList_Check(list)) {
1208  PyErr_SetString(PyExc_TypeError, "first parameter must be a list");
1209  return NULL;
1210  }
1211 
1212  fd = fdDup(fileno);
1213 
1214  rc = rpmMergeHeaders (list, fd, matchTag);
1215  Fclose(fd);
1216 
1217  if (rc) {
1218  return NULL;
1219  }
1220 
1221  Py_INCREF(Py_None);
1222  return Py_None;
1223 }
1224 
1227 PyObject *
1228 rpmSingleHeaderFromFD(PyObject * self, PyObject * args, PyObject * kwds)
1229 {
1230  FD_t fd;
1231  int fileno;
1232  off_t offset;
1233  PyObject * tuple;
1234  Header h;
1235  char * kwlist[] = {"fd", NULL};
1236 
1237  if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, &fileno))
1238  return NULL;
1239 
1240  offset = lseek(fileno, 0, SEEK_CUR);
1241 
1242  fd = fdDup(fileno);
1243 
1244  if (!fd) {
1245  PyErr_SetFromErrno(pyrpmError);
1246  return NULL;
1247  }
1248 
1249  Py_BEGIN_ALLOW_THREADS
1250  h = headerRead(fd, HEADER_MAGIC_YES);
1251  Py_END_ALLOW_THREADS
1252 
1253  Fclose(fd);
1254 
1255  tuple = PyTuple_New(2);
1256 
1257  if (h && tuple) {
1258  PyTuple_SET_ITEM(tuple, 0, (PyObject *) hdr_Wrap(h));
1259  PyTuple_SET_ITEM(tuple, 1, PyLong_FromLong(offset));
1260  h = headerFree(h);
1261  } else {
1262  Py_INCREF(Py_None);
1263  Py_INCREF(Py_None);
1264  PyTuple_SET_ITEM(tuple, 0, Py_None);
1265  PyTuple_SET_ITEM(tuple, 1, Py_None);
1266  }
1267 
1268  return tuple;
1269 }
1270 
1273 PyObject * versionCompare (PyObject * self, PyObject * args, PyObject * kwds)
1274 {
1275  hdrObject * h1, * h2;
1276  char * kwlist[] = {"version0", "version1", NULL};
1277 
1278  if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!O!", kwlist, &hdr_Type,
1279  &h1, &hdr_Type, &h2))
1280  return NULL;
1281 
1282  return Py_BuildValue("i", hdr_compare(h1, h2));
1283 }
1284 
1285 PyObject * labelCompare (PyObject * self, PyObject * args)
1286 {
1287  EVR_t A = memset(alloca(sizeof(*A)), 0, sizeof(*A));
1288  EVR_t B = memset(alloca(sizeof(*B)), 0, sizeof(*B));
1289  int rc;
1290 
1291  if (!PyArg_ParseTuple(args, "(zzz)(zzz)",
1292  &A->E, &A->V, &A->R, &B->E, &B->V, &B->R))
1293  return NULL;
1294 
1295  if (A->E == NULL) A->E = "0";
1296  if (B->E == NULL) B->E = "0";
1297  if (A->V == NULL) A->E = "";
1298  if (B->V == NULL) B->E = "";
1299  if (A->R == NULL) A->E = "";
1300  if (B->R == NULL) B->E = "";
1301 
1302  rc = rpmEVRcompare(A, B);
1303 
1304  return Py_BuildValue("i", rc);
1305 }