On Dec 28, 2010, at 11:43 AM, Silvan Calarco wrote: > On Tuesday 28 December 2010 17:01:50 Jeff Johnson wrote: >> On Dec 28, 2010, at 10:38 AM, Silvan Calarco wrote: >>> Hi, >>> I'm trying to port to rpm 5.2.1 an application that was previously made >>> for rpm 4.4.9. >>> >>> The application used to read the header with the following code: >>> FD_t fd; >>> fd = fdOpen(headerFile, O_RDONLY, 0); >>> >>> but with rpm 5.2.1 build stops with the error in the subject. >> >> The solution here is to use Fopen(), not fdOpen(). > > Ok, I replaced also a fdFileno() with Fileno() and the build completed > successfully. Now I just have to fix a list of warnings like these: > > rpmfunctions.c:124:21: warning: pointer targets in passing argument 3 of > ‘headerGetEntry’ differ in signedness > /usr/include/rpm/rpmlib.h:119:19: note: expected ‘hTYP_t’ but argument is of > type ‘int *’ > rpmfunctions.c:124:21: warning: pointer targets in passing argument 5 of > ‘headerGetEntry’ differ in signedness > /usr/include/rpm/rpmlib.h:119:19: note: expected ‘hCNT_t’ but argument is of > type ‘int *’ >
Hmmm ... that's some really old code ... hTYP_t/hCNT_t were an early attempt at typedef's in RPM. In rpm-5.x there's a union (what used to be the 4th arg in headerGetEntry as a void **) contained in rpmdb/rpmtag.h: union rpmDataType_u { /*...@null@*/ void * ptr; rpmuint8_t * ui8p; /*!< RPM_UINT8_TYPE | RPM_CHAR_TYPE */ rpmuint16_t * ui16p; /*!< RPM_UINT16_TYPE */ rpmuint32_t * ui32p; /*!< RPM_UINT32_TYPE */ rpmuint64_t * ui64p; /*!< RPM_UINT64_TYPE */ /*...@relnull@*/ const char * str; /*!< RPM_STRING_TYPE */ unsigned char * blob; /*!< RPM_BIN_TYPE */ const char ** argv; /*!< RPM_STRING_ARRAY_TYPE */ HE_t he; }; and hTYP_t (the 3rd arg to headerGetEntry) and hCNT_t (the 5th argument) have all been bundled into a structure struct _HE_s { rpmTag tag; rpmTagType t; /*...@owned@*/ /*...@null@*/ rpmTagData p; rpmTagCount c; int ix; unsigned int freeData : 1; unsigned int avail : 1; unsigned int append : 1; }; Note: the ix and the bit fields are only used by headerPut(). SO instead of headerGetEntry() the replacement becomes something like this (this is my paradigm anyways, adjust to tate if you dislike using alloca): HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he)); he->tag = RPMTAG_NAME; if (headerGet(h, he, 0) && he->t == RPM_STRING_TYPE && he->c == 1) *np = xstrdup(he->p.str); else *np = NULL; he->p.ptr = _free(he->p.ptr); The above snippet is in rpmdb/hdrnvr.c and is a bit more anal about checking type and count than necessary. But do note the final he->p.ptr = _free(he->p.ptr); (the _free is just a static inline so I don't have to worry about NULL pointers passed to free, and the assignment is just so that the original pointer cannot be accidentally reused == just my coding fetishes, use free(3) however you wish). The programming rule (and the single biggest change with rpm-5.x) is All data returned by headerGet() must be free'd. >>> Is that a headers problem or is it intended that I should use a different >>> approach? >> >> Different approach. But you can call through the FDIO_s vector to >> _fopen still if necessary, I don't recall any changes there. > > Ok. I'm just doing a "blind" port for now and will see if it works. > > To avoid patching a lot of sources and autotools I've also made a symlink > /usr/include/rpm/rpmlib.h pointing to /usr/include/rpm/rpm4compat.h, quite > ugly but it worked. > rpm4compat.h "works" surprisngly "well" (imho). But I'll be happy to assist getting rid of the need for using rpm4compat.h in any code. I can do RPM ports in my sleep, and I're _REALLY_ like not to have to carry around an ancient API forevermore. >> The intent is a stdio-like interface, with Fopen instead of fopen, Fread >> instead of fread. >> >> Note that the first argument to Fopen can be a URI too. That "works" for >> full content reads on ftp:// and (mostly, no redirects, no proxies, ...) >> on http:// in rpm-5.2.1. > > Good. > >>> Thanks for your help! >> >> np. I can/will help with any porting issues. > > Thank you also for helping in 4.4.9 -> 5.2.1 upgrade. Next step will be > upgrading to 5.3.6 and possibly integrating some openmamba patches upstream. > Cool. You might want to watch Per Oyvind's success/failures in Mandriva Cooker. AFAICT most of the pieces are in place for a rpm-4.6.1 -> rpm-5.3.6 upgrade. The jump from rpm-5.2.1 -> rpm-5.3.6 is a bit easier, but still has the _rpmmi_usermem and mmap PROT_READ issue. Unlike rpm-5.2.1, rpm-5.3.6 has removed the signature/digest check when reading rpmdb header's, and so disabling PROT_READ gets snarled up with security issues. (aside) The RPM security issues are rather ill specified: noo ne has ever bothered to define what threat model(s) apply to an rpmdb. Verifying signatures/digests whenever a header is read/written to an rpmdb (and PROT_READ protection) is likely hirrendously over-engineered and simply doesn't matter. But with the onslaught of SELinux "collections" and MeeGo MSSF and IMA-EVM all starting to use *.rpm packaging, well ... Someone ought to start thinking through RPM's "threat model" more carefully and precisely. hth 73 de Jeff______________________________________________________________________ RPM Package Manager http://rpm5.org Developer Communication List rpm-devel@rpm5.org