diff options
Diffstat (limited to 'URPM.xs')
-rw-r--r-- | URPM.xs | 1583 |
1 files changed, 1050 insertions, 533 deletions
@@ -20,15 +20,15 @@ #include <sys/wait.h> #include <fcntl.h> #include <unistd.h> +#include <zlib.h> #include <libintl.h> -// fix compiling (error: conflicting types for ‘fflush’): #undef Fflush #undef Mkdir #undef Stat #undef Fstat -static inline void *_free(const void * p) { +static inline void *_free(const void * p) { if (p != NULL) free((void *)p); return NULL; } @@ -99,6 +99,11 @@ typedef struct s_Package* URPM__Package; #define FILTER_MODE_ALL_FILES 0 #define FILTER_MODE_CONF_FILES 2 +/* promote epoch sense should be : + 0 for compability with old packages + 1 for rpm 4.2 and better new approach. */ +#define PROMOTE_EPOCH_SENSE 1 + static ssize_t write_nocheck(int fd, const void *buf, size_t count) { return write(fd, buf, count); } @@ -108,34 +113,11 @@ static const void* unused_variable(const void *p) { static int rpmError_callback_data; -static int rpmError_callback() { +int rpmError_callback() { write_nocheck(rpmError_callback_data, rpmlogMessage(), strlen(rpmlogMessage())); return RPMLOG_DEFAULT; } -static inline int _run_cb_while_traversing(SV *callback, Header header) { - dSP; - URPM__Package pkg = calloc(1, sizeof(struct s_Package)); - - pkg->flag = FLAG_ID_INVALID | FLAG_NO_HEADER_FREE; - pkg->h = header; - - PUSHMARK(SP); - mXPUSHs(sv_setref_pv(newSVpvs(""), "URPM::Package", pkg)); - PUTBACK; - - int count = call_sv(callback, G_SCALAR); - - SPAGAIN; - pkg->h = NULL; /* avoid using it anymore, in case it has been copied inside callback */ - return count; -} - -static inline void _header_free(URPM__Package pkg) { - if (pkg->h && !(pkg->flag & FLAG_NO_HEADER_FREE)) - pkg->h = headerFree(pkg->h); -} - static int rpm_codeset_is_utf8 = 0; static SV* @@ -150,8 +132,6 @@ static void get_fullname_parts(URPM__Package pkg, char **name, char **version, char **release, char **arch, char **eos) { char *_version = NULL, *_release = NULL, *_arch = NULL, *_eos = NULL; - if (!pkg->info) - return; if ((_eos = strchr(pkg->info, '@')) != NULL) { *_eos = 0; /* mark end of string to enable searching backwards */ if ((_arch = strrchr(pkg->info, '.')) != NULL) { @@ -174,7 +154,7 @@ get_fullname_parts(URPM__Package pkg, char **name, char **version, char **releas } static char * -get_name(const Header header, rpmTag tag) { +get_name(Header header, int32_t tag) { struct rpmtd_s val; headerGet(header, tag, &val, HEADERGET_MINMEM); @@ -182,13 +162,8 @@ get_name(const Header header, rpmTag tag) { return name ? name : ""; } -static char* -get_arch(const Header header) { - return headerIsEntry(header, RPMTAG_SOURCERPM) ? get_name(header, RPMTAG_ARCH) : "src"; -} - static int -get_int(const Header header, rpmTag tag) { +get_int(Header header, int32_t tag) { struct rpmtd_s val; headerGet(header, tag, &val, HEADERGET_DEFAULT); @@ -202,24 +177,21 @@ get_filesize(const Header h) { } static int -print_list_entry(char *buff, int sz, const char *name, rpmsenseFlags flags, const char *evr) { +print_list_entry(char *buff, int sz, const char *name, uint32_t flags, const char *evr) { int len = strlen(name); char *p = buff; - if (len >= sz || !strncmp(name, "rpmlib(", 7)) - return -1; + if (len >= sz || !strncmp(name, "rpmlib(", 7)) return -1; memcpy(p, name, len); p += len; if (flags & (RPMSENSE_PREREQ|RPMSENSE_SCRIPT_PREUN|RPMSENSE_SCRIPT_PRE|RPMSENSE_SCRIPT_POSTUN|RPMSENSE_SCRIPT_POST)) { - if (p - buff + 3 >= sz) - return -1; + if (p - buff + 3 >= sz) return -1; memcpy(p, "[*]", 4); p += 3; } if (evr != NULL) { len = strlen(evr); if (len > 0) { - if (p - buff + 6 + len >= sz) - return -1; + if (p - buff + 6 + len >= sz) return -1; *p++ = '['; if (flags & RPMSENSE_LESS) *p++ = '<'; if (flags & RPMSENSE_GREATER) *p++ = '>'; @@ -236,35 +208,85 @@ print_list_entry(char *buff, int sz, const char *name, rpmsenseFlags flags, cons } static int -ranges_overlap(rpmsenseFlags aflags, char *sa, rpmsenseFlags bflags, char *sb) { +ranges_overlap(uint32_t aflags, char *sa, uint32_t bflags, char *sb, int b_nopromote) { if (!aflags || !bflags) return 1; /* really faster to test it there instead of later */ else { - int res; + int sense = 0; char *eosa = strchr(sa, ']'); char *eosb = strchr(sb, ']'); - rpmds dsa, dsb; + char *ea, *va, *ra, *eb, *vb, *rb; if (eosa) *eosa = 0; if (eosb) *eosb = 0; - - dsa = rpmdsSingle(RPMTAG_REQUIRENAME, "", sa, aflags); - dsb = rpmdsSingle(RPMTAG_REQUIRENAME, "", sb, bflags); - res = rpmdsCompare(dsa, dsb); - rpmdsFree(dsa); - rpmdsFree(dsb); - + /* parse sa as an [epoch:]version[-release] */ + for (ea = sa; *sa >= '0' && *sa <= '9'; ++sa); + if (*sa == ':') { + *sa++ = 0; /* ea could be an empty string (should be interpreted as 0) */ + va = sa; + } else { + va = ea; /* no epoch */ + ea = NULL; + } + if ((ra = strrchr(sa, '-'))) *ra++ = 0; + /* parse sb as an [epoch:]version[-release] */ + for (eb = sb; *sb >= '0' && *sb <= '9'; ++sb); + if (*sb == ':') { + *sb++ = 0; /* ea could be an empty string (should be interpreted as 0) */ + vb = sb; + } else { + vb = eb; /* no epoch */ + eb = NULL; + } + if ((rb = strrchr(sb, '-'))) *rb++ = 0; + /* now compare epoch */ + if (ea && eb) + sense = rpmvercmp(*ea ? ea : "0", *eb ? eb : "0"); + else if (ea && *ea && atol(ea) > 0) + sense = b_nopromote ? 1 : 0; + else if (eb && *eb && atol(eb) > 0) + sense = -1; + /* now compare version and release if epoch has not been enough */ + if (sense == 0) { + sense = rpmvercmp(va, vb); + if (sense == 0 && ra && *ra && rb && *rb) + sense = rpmvercmp(ra, rb); + } + /* restore all character that have been modified inline */ + if (rb) rb[-1] = '-'; + if (ra) ra[-1] = '-'; + if (eb) vb[-1] = ':'; + if (ea) va[-1] = ':'; if (eosb) *eosb = ']'; if (eosa) *eosa = ']'; - - return res; + /* finish the overlap computation */ + if (sense < 0 && ((aflags & RPMSENSE_GREATER) || (bflags & RPMSENSE_LESS))) + return 1; + else if (sense > 0 && ((aflags & RPMSENSE_LESS) || (bflags & RPMSENSE_GREATER))) + return 1; + else if (sense == 0 && (((aflags & RPMSENSE_EQUAL) && (bflags & RPMSENSE_EQUAL)) || + ((aflags & RPMSENSE_LESS) && (bflags & RPMSENSE_LESS)) || + ((aflags & RPMSENSE_GREATER) && (bflags & RPMSENSE_GREATER)))) + return 1; + else + return 0; } } -typedef int (*callback_list_str)(char *s, int slen, const char *name, const rpmsenseFlags flags, const char *evr, void *param); +static int has_old_suggests; +int32_t is_old_suggests(int32_t flags) { + int is = flags & RPMSENSE_MISSINGOK; + if (is) has_old_suggests = is; + return is; +} +int32_t is_not_old_suggests(int32_t flags) { + return !is_old_suggests(flags); +} + +typedef int (*callback_list_str)(char *s, int slen, const char *name, const uint32_t flags, const char *evr, void *param); static int -callback_list_str_xpush(char *s, int slen, const char *name, rpmsenseFlags flags, const char *evr, __attribute__((unused)) void *param) { +callback_list_str_xpush(char *s, int slen, const char *name, uint32_t flags, const char *evr, __attribute__((unused)) void *param) { dSP; if (s) mXPUSHs(newSVpv(s, slen)); @@ -279,11 +301,26 @@ callback_list_str_xpush(char *s, int slen, const char *name, rpmsenseFlags flags return 0; } static int -callback_list_str_xpush_requires(char *s, int slen, const char *name, const rpmsenseFlags flags, const char *evr, __attribute__((unused)) void *param) { +callback_list_str_xpush_requires(char *s, int slen, const char *name, const uint32_t flags, const char *evr, __attribute__((unused)) void *param) { dSP; if (s) mXPUSHs(newSVpv(s, slen)); - else { + else if (is_not_old_suggests(flags)) { + char buff[4096]; + int len = print_list_entry(buff, sizeof(buff)-1, name, flags, evr); + if (len >= 0) + mXPUSHs(newSVpv(buff, len)); + } + PUTBACK; + /* returning zero indicates to continue processing */ + return 0; +} +static int +callback_list_str_xpush_old_suggests(char *s, int slen, const char *name, uint32_t flags, const char *evr, __attribute__((unused)) void *param) { + dSP; + if (s) + mXPUSHs(newSVpv(s, slen)); + else if (is_old_suggests(flags)) { char buff[4096]; int len = print_list_entry(buff, sizeof(buff)-1, name, flags, evr); if (len >= 0) @@ -295,14 +332,15 @@ callback_list_str_xpush_requires(char *s, int slen, const char *name, const rpms } struct cb_overlap_s { - rpmsenseFlags flags; - int direction; /* indicate to compare the above at left or right to the iteration element */ char *name; + int32_t flags; char *evr; + int direction; /* indicate to compare the above at left or right to the iteration element */ + int b_nopromote; }; static int -callback_list_str_overlap(char *s, int slen, const char *name, rpmsenseFlags flags, const char *evr, void *param) { +callback_list_str_overlap(char *s, int slen, const char *name, uint32_t flags, const char *evr, void *param) { struct cb_overlap_s *os = (struct cb_overlap_s *)param; int result = 0; char *eos = NULL; @@ -312,11 +350,7 @@ callback_list_str_overlap(char *s, int slen, const char *name, rpmsenseFlags fla /* we need to extract name, flags and evr from a full sense information, store result in local copy */ if (s) { - if (slen) { - eos = s + slen; - eosc = *eos; - *eos = 0; - } + if (slen) { eos = s + slen; eosc = *eos; *eos = 0; } name = s; while (*s && *s != ' ' && *s != '[' && *s != '<' && *s != '>' && *s != '=') ++s; if (*s) { @@ -335,17 +369,14 @@ callback_list_str_overlap(char *s, int slen, const char *name, rpmsenseFlags fla } /* mark end of name */ - if (eon) { - eonc = *eon; - *eon = 0; - } + if (eon) { eonc = *eon; *eon = 0; } /* names should be equal, else it will not overlap */ if (!strcmp(name, os->name)) { /* perform overlap according to direction needed, negative for left */ if (os->direction < 0) - result = ranges_overlap(os->flags, os->evr, flags, (char *) evr); + result = ranges_overlap(os->flags, os->evr, flags, (char *) evr, os->b_nopromote); else - result = ranges_overlap(flags, (char *) evr, os->flags, os->evr); + result = ranges_overlap(flags, (char *) evr, os->flags, os->evr, os->b_nopromote); } /* fprintf(stderr, "cb_list_str_overlap result=%d, os->direction=%d, os->name=%s, os->evr=%s, name=%s, evr=%s\n", @@ -359,7 +390,7 @@ callback_list_str_overlap(char *s, int slen, const char *name, rpmsenseFlags fla } static int -return_list_str(char *s, const Header header, rpmTag tag_name, rpmTag tag_flags, rpmTag tag_version, callback_list_str f, void *param) { +return_list_str(char *s, Header header, int32_t tag_name, int32_t tag_flags, int32_t tag_version, callback_list_str f, void *param) { int count = 0; if (s != NULL) { @@ -367,29 +398,23 @@ return_list_str(char *s, const Header header, rpmTag tag_name, rpmTag tag_flags, if (tag_flags && tag_version) { while(ps != NULL) { ++count; - if (f(s, ps-s, NULL, 0, NULL, param)) - return -count; + if (f(s, ps-s, NULL, 0, NULL, param)) return -count; s = ps + 1; ps = strchr(s, '@'); } ++count; - if (f(s, 0, NULL, 0, NULL, param)) - return -count; + if (f(s, 0, NULL, 0, NULL, param)) return -count; } else { char *eos; while(ps != NULL) { *ps = 0; eos = strchr(s, '['); if (!eos) eos = strchr(s, ' '); ++count; - if (f(s, eos ? eos-s : ps-s, NULL, 0, NULL, param)) { - *ps = '@'; - return -count; - } + if (f(s, eos ? eos-s : ps-s, NULL, 0, NULL, param)) { *ps = '@'; return -count; } *ps = '@'; /* restore in memory modified char */ s = ps + 1; ps = strchr(s, '@'); } eos = strchr(s, '['); if (!eos) eos = strchr(s, ' '); ++count; - if (f(s, eos ? eos-s : 0, NULL, 0, NULL, param)) - return -count; + if (f(s, eos ? eos-s : 0, NULL, 0, NULL, param)) return -count; } } else if (header) { struct rpmtd_s list, flags, list_evr; @@ -419,20 +444,18 @@ return_list_str(char *s, const Header header, rpmTag tag_name, rpmTag tag_flags, } static int -xpush_simple_list_str(const Header header, rpmTag tag_name) { +xpush_simple_list_str(Header header, int32_t tag_name) { dSP; if (header) { struct rpmtd_s list; const char *val; int size; - if (!headerGet(header, tag_name, &list, HEADERGET_DEFAULT)) - return 0; + if (!headerGet(header, tag_name, &list, HEADERGET_DEFAULT)) return 0; size = rpmtdCount(&list); - EXTEND(SP, size); while ((val = rpmtdNextString(&list))) { - mPUSHs(newSVpv(val, 0)); + mXPUSHs(newSVpv(val, 0)); } rpmtdFreeData(&list); PUTBACK; @@ -440,18 +463,33 @@ xpush_simple_list_str(const Header header, rpmTag tag_name) { } else return 0; } -static void -return_list_number(const Header header, rpmTag tag_name) { +void +return_list_int32_t(Header header, int32_t tag_name) { + dSP; + if (header) { + struct rpmtd_s list; + + if (headerGet(header, tag_name, &list, HEADERGET_DEFAULT)) { + uint32_t *val; + while ((val = rpmtdNextUint32(&list))) + mXPUSHs(newSViv(*val)); + rpmtdFreeData(&list); + } + } + PUTBACK; +} + +void +return_list_uint_16(Header header, int32_t tag_name) { dSP; if (header) { struct rpmtd_s list; if (headerGet(header, tag_name, &list, HEADERGET_DEFAULT)) { int count = rpmtdCount(&list); int i; - EXTEND(SP, count); + uint16_t *list_ = list.data; for(i = 0; i < count; i++) { - rpmtdNext(&list); - mPUSHs(newSViv(rpmtdGetNumber(&list))); + mXPUSHs(newSViv(list_[i])); } rpmtdFreeData(&list); } @@ -459,37 +497,34 @@ return_list_number(const Header header, rpmTag tag_name) { PUTBACK; } -static void -return_list_tag_modifier(const Header header, rpmTag tag_name) { +void +return_list_tag_modifier(Header header, int32_t tag_name) { dSP; int i; struct rpmtd_s td; - if (!headerGet(header, tag_name, &td, HEADERGET_DEFAULT)) - return; + if (!headerGet(header, tag_name, &td, HEADERGET_DEFAULT)) return; int count = rpmtdCount(&td); - rpmtdInit(&td); + int32_t *list = td.data; for (i = 0; i < count; i++) { char buff[15]; char *s = buff; - int32_t tag; - rpmtdNext(&td); - tag = rpmtdGetNumber(&td); - - if (tag_name == RPMTAG_FILEFLAGS) { - if (tag & RPMFILE_CONFIG) *s++ = 'c'; - if (tag & RPMFILE_DOC) *s++ = 'd'; - if (tag & RPMFILE_GHOST) *s++ = 'g'; - if (tag & RPMFILE_LICENSE) *s++ = 'l'; - if (tag & RPMFILE_MISSINGOK) *s++ = 'm'; - if (tag & RPMFILE_NOREPLACE) *s++ = 'n'; - if (tag & RPMFILE_SPECFILE) *s++ = 'S'; - if (tag & RPMFILE_README) *s++ = 'R'; - if (tag & RPMFILE_EXCLUDE) *s++ = 'e'; - if (tag & RPMFILE_ICON) *s++ = 'i'; - if (tag & RPMFILE_UNPATCHED) *s++ = 'u'; - if (tag & RPMFILE_PUBKEY) *s++ = 'p'; - } else { + switch (tag_name) { + case RPMTAG_FILEFLAGS: + if (list[i] & RPMFILE_CONFIG) *s++ = 'c'; + if (list[i] & RPMFILE_DOC) *s++ = 'd'; + if (list[i] & RPMFILE_GHOST) *s++ = 'g'; + if (list[i] & RPMFILE_LICENSE) *s++ = 'l'; + if (list[i] & RPMFILE_MISSINGOK) *s++ = 'm'; + if (list[i] & RPMFILE_NOREPLACE) *s++ = 'n'; + if (list[i] & RPMFILE_SPECFILE) *s++ = 'S'; + if (list[i] & RPMFILE_README) *s++ = 'R'; + if (list[i] & RPMFILE_EXCLUDE) *s++ = 'e'; + if (list[i] & RPMFILE_ICON) *s++ = 'i'; + if (list[i] & RPMFILE_UNPATCHED) *s++ = 'u'; + if (list[i] & RPMFILE_PUBKEY) *s++ = 'p'; + break; + default: rpmtdFreeData(&td); return; } @@ -500,15 +535,16 @@ return_list_tag_modifier(const Header header, rpmTag tag_name) { PUTBACK; } -static void -return_list_tag(const URPM__Package pkg, rpmTag tag_name) { +void +return_list_tag(URPM__Package pkg, int32_t tag_name) { dSP; if (pkg->h != NULL) { struct rpmtd_s td; if (headerGet(pkg->h, tag_name, &td, HEADERGET_DEFAULT)) { + void *list = td.data; int32_t count = rpmtdCount(&td); if (tag_name == RPMTAG_ARCH) - mXPUSHs(newSVpv(headerIsEntry(pkg->h, RPMTAG_SOURCERPM) ? rpmtdGetString(&td) : "src", 0)); + mXPUSHs(newSVpv(headerIsEntry(pkg->h, RPMTAG_SOURCERPM) ? (char *) list : "src", 0)); else switch (rpmtdType(&td)) { case RPM_NULL_TYPE: @@ -519,25 +555,27 @@ return_list_tag(const URPM__Package pkg, rpmTag tag_name) { case RPM_INT32_TYPE: { int i; - EXTEND(SP, count); + int *r; + r = (int *)list; for (i=0; i < count; i++) { - rpmtdNext(&td); - mPUSHs(newSViv(rpmtdGetNumber(&td))); + mXPUSHs(newSViv(r[i])); } } break; case RPM_STRING_TYPE: - mPUSHs(newSVpv(rpmtdGetString(&td), 0)); + mXPUSHs(newSVpv((char *) list, 0)); break; case RPM_BIN_TYPE: break; case RPM_STRING_ARRAY_TYPE: { int i; - EXTEND(SP, count); - rpmtdInit(&td); - for (i = 0; i < count; i++) - mPUSHs(newSVpv(rpmtdNextString(&td), 0)); + char **s; + + s = (char **)list; + for (i = 0; i < count; i++) { + mXPUSHs(newSVpv(s[i], 0)); + } } break; case RPM_I18NSTRING_TYPE: @@ -583,21 +621,18 @@ return_list_tag(const URPM__Package pkg, rpmTag tag_name) { case RPMTAG_SUMMARY: mXPUSHs(newSVpv(pkg->summary, 0)); break; - default: - croak("unexpected tag %s", tag_name); - break; } } PUTBACK; } -static void -return_files(const Header header, int filter_mode) { +void +return_files(Header header, int filter_mode) { dSP; if (header) { char buff[4096]; - char *p; const char *s; + char *p, *s; STRLEN len; unsigned int i; @@ -617,19 +652,17 @@ return_files(const Header header, int filter_mode) { char **baseNames = td_baseNames.data; char **dirNames = td_dirNames.data; int32_t *dirIndexes = td_dirIndexes.data; - int is_oldfilenames = !baseNames || !dirNames || !dirIndexes; - if (is_oldfilenames) { - if (!headerGet(header, RPMTAG_OLDFILENAMES, &td_list, HEADERGET_DEFAULT)) - return; - rpmtdInit(&td_list); + char **list = NULL; + if (!baseNames || !dirNames || !dirIndexes) { + if (!headerGet(header, RPMTAG_OLDFILENAMES, &td_list, HEADERGET_DEFAULT)) return; + list = td_list.data; } - rpm_count_t count = is_oldfilenames ? rpmtdCount(&td_list) : rpmtdCount(&td_baseNames); - for(i = 0; i < count; i++) { - if (is_oldfilenames) { - s = rpmtdNextString(&td_list); - len = strlen(s); + for(i = 0; i < rpmtdCount(&td_baseNames); i++) { + if (list) { + s = list[i]; + len = strlen(list[i]); } else { len = strlen(dirNames[dirIndexes[i]]); if (len >= sizeof(buff)) continue; @@ -648,15 +681,14 @@ return_files(const Header header, int filter_mode) { mXPUSHs(newSVpv(s, len)); } - rpmtdFreeData(&td_baseNames); - rpmtdFreeData(&td_dirNames); - if (is_oldfilenames) - rpmtdFreeData(&td_list); + free(baseNames); + free(dirNames); + free(list); } PUTBACK; } -static void +void return_problems(rpmps ps, int translate_message, int raw_message) { dSP; if (ps && rpmpsNumProblems(ps) > 0) { @@ -720,9 +752,9 @@ return_problems(rpmps ps, int translate_message, int raw_message) { } static char * -pack_list(const Header header, rpmTag tag_name, rpmTag tag_flags, rpmTag tag_version) { +pack_list(Header header, int32_t tag_name, int32_t tag_flags, int32_t tag_version, int32_t (*check_flag)(int32_t)) { char buff[65536]; - rpmTag *flags = NULL; + int32_t *flags = NULL; char **list_evr = NULL; unsigned int i; char *p = buff; @@ -735,6 +767,7 @@ pack_list(const Header header, rpmTag tag_name, rpmTag tag_flags, rpmTag tag_ver if (tag_flags && headerGet(header, tag_flags, &td_flags, HEADERGET_DEFAULT)) flags = td_flags.data; if (tag_version && headerGet(header, tag_version, &td_list_evr, HEADERGET_DEFAULT)) list_evr = td_list_evr.data; for(i = 0; i < rpmtdCount(&td); i++) { + if (check_flag && !check_flag(flags[i])) continue; int len = print_list_entry(p, sizeof(buff)-(p-buff)-1, list[i], flags ? flags[i] : 0, list_evr ? list_evr[i] : NULL); if (len < 0) continue; p += len; @@ -750,30 +783,35 @@ pack_list(const Header header, rpmTag tag_name, rpmTag tag_flags, rpmTag tag_ver } static void -pack_header(const URPM__Package pkg) { +pack_header(URPM__Package pkg) { if (pkg->h) { if (pkg->info == NULL) { char buff[1024]; - const char *p = buff; - const char *nvr = headerGetAsString(pkg->h, RPMTAG_NVR); - const char *arch = get_arch(pkg->h); + char *p = buff; + char *name = get_name(pkg->h, RPMTAG_NAME); + char *version = get_name(pkg->h, RPMTAG_VERSION); + char *release = get_name(pkg->h, RPMTAG_RELEASE); + char *arch = headerIsEntry(pkg->h, RPMTAG_SOURCERPM) ? get_name(pkg->h, RPMTAG_ARCH) : "src"; - p += 1 + snprintf(buff, sizeof(buff), "%s.%s@%d@%d@%s", nvr, arch, + p += 1 + snprintf(buff, sizeof(buff), "%s-%s-%s.%s@%d@%d@%s", name, version, release, arch, get_int(pkg->h, RPMTAG_EPOCH), get_int(pkg->h, RPMTAG_SIZE), get_name(pkg->h, RPMTAG_GROUP)); pkg->info = memcpy(malloc(p-buff), buff, p-buff); } if (pkg->filesize == 0) pkg->filesize = get_filesize(pkg->h); - if (pkg->requires == NULL && pkg->suggests == NULL) { - pkg->requires = pack_list(pkg->h, RPMTAG_REQUIRENAME, RPMTAG_REQUIREFLAGS, RPMTAG_REQUIREVERSION); - pkg->suggests = pack_list(pkg->h, RPMTAG_SUGGESTSNAME, 0, 0); - } + if (pkg->requires == NULL && pkg->suggests == NULL) + has_old_suggests = 0; + pkg->requires = pack_list(pkg->h, RPMTAG_REQUIRENAME, RPMTAG_REQUIREFLAGS, RPMTAG_REQUIREVERSION, is_not_old_suggests); + if (has_old_suggests) + pkg->suggests = pack_list(pkg->h, RPMTAG_REQUIRENAME, RPMTAG_REQUIREFLAGS, RPMTAG_REQUIREVERSION, is_old_suggests); + else + pkg->suggests = pack_list(pkg->h, RPMTAG_SUGGESTSNAME, 0, 0, NULL); if (pkg->obsoletes == NULL) - pkg->obsoletes = pack_list(pkg->h, RPMTAG_OBSOLETENAME, RPMTAG_OBSOLETEFLAGS, RPMTAG_OBSOLETEVERSION); + pkg->obsoletes = pack_list(pkg->h, RPMTAG_OBSOLETENAME, RPMTAG_OBSOLETEFLAGS, RPMTAG_OBSOLETEVERSION, NULL); if (pkg->conflicts == NULL) - pkg->conflicts = pack_list(pkg->h, RPMTAG_CONFLICTNAME, RPMTAG_CONFLICTFLAGS, RPMTAG_CONFLICTVERSION); + pkg->conflicts = pack_list(pkg->h, RPMTAG_CONFLICTNAME, RPMTAG_CONFLICTFLAGS, RPMTAG_CONFLICTVERSION, NULL); if (pkg->provides == NULL) - pkg->provides = pack_list(pkg->h, RPMTAG_PROVIDENAME, RPMTAG_PROVIDEFLAGS, RPMTAG_PROVIDEVERSION); + pkg->provides = pack_list(pkg->h, RPMTAG_PROVIDENAME, RPMTAG_PROVIDEFLAGS, RPMTAG_PROVIDEVERSION, NULL); if (pkg->summary == NULL) { char *summary = get_name(pkg->h, RPMTAG_SUMMARY); int len = 1 + strlen(summary); @@ -781,13 +819,13 @@ pack_header(const URPM__Package pkg) { pkg->summary = memcpy(malloc(len), summary, len); } - _header_free(pkg); + if (!(pkg->flag & FLAG_NO_HEADER_FREE)) pkg->h =headerFree(pkg->h); pkg->h = NULL; } } static void -update_hash_entry(HV *hash, const char *name, STRLEN len, int force, IV use_sense, const URPM__Package pkg) { +update_hash_entry(HV *hash, char *name, STRLEN len, int force, IV use_sense, URPM__Package pkg) { SV** isv; if (!len) len = strlen(name); @@ -813,24 +851,24 @@ update_hash_entry(HV *hash, const char *name, STRLEN len, int force, IV use_sens } static void -update_provide_entry(const char *name, STRLEN len, int force, IV use_sense, const URPM__Package pkg, HV *provides) { +update_provide_entry(char *name, STRLEN len, int force, IV use_sense, URPM__Package pkg, HV *provides) { update_hash_entry(provides, name, len, force, use_sense, pkg); } static void -update_provides(const URPM__Package pkg, HV *provides) { +update_provides(URPM__Package pkg, HV *provides) { if (pkg->h) { int len; struct rpmtd_s td, td_flags; - rpmsenseFlags *flags = NULL; + int32_t *flags = NULL; unsigned int i; /* examine requires for files which need to be marked in provides */ if (headerGet(pkg->h, RPMTAG_REQUIRENAME, &td, HEADERGET_DEFAULT)) { + char **list = td.data; for (i = 0; i < rpmtdCount(&td); ++i) { - const char *s = rpmtdNextString(&td); - len = strlen(s); - if (s[0] == '/') (void)hv_fetch(provides, s, len, 1); + len = strlen(list[i]); + if (list[i][0] == '/') (void)hv_fetch(provides, list[i], len, 1); } } @@ -880,15 +918,16 @@ update_provides(const URPM__Package pkg, HV *provides) { } static void -update_obsoletes(const URPM__Package pkg, HV *obsoletes) { +update_obsoletes(URPM__Package pkg, HV *obsoletes) { if (pkg->h) { struct rpmtd_s td; /* update all provides */ if (headerGet(pkg->h, RPMTAG_OBSOLETENAME, &td, HEADERGET_DEFAULT)) { + char **list = td.data; unsigned int i; for (i = 0; i < rpmtdCount(&td); ++i) - update_hash_entry(obsoletes, rpmtdNextString(&td), 0, 1, 0, pkg); + update_hash_entry(obsoletes, list[i], 0, 1, 0, pkg); } } else { char *ps, *s; @@ -909,9 +948,10 @@ update_obsoletes(const URPM__Package pkg, HV *obsoletes) { } static void -update_provides_files(const URPM__Package pkg, HV *provides) { +update_provides_files(URPM__Package pkg, HV *provides) { if (pkg->h) { STRLEN len; + char **list = NULL; unsigned int i; struct rpmtd_s td_baseNames, td_dirIndexes, td_dirNames; @@ -937,26 +977,25 @@ update_provides_files(const URPM__Package pkg, HV *provides) { update_provide_entry(buff, p-buff, 0, 0, pkg, provides); } - rpmtdFreeData(&td_baseNames); - rpmtdFreeData(&td_dirNames); + free(baseNames); + free(dirNames); } else { struct rpmtd_s td; - - if (headerGet(pkg->h, RPMTAG_OLDFILENAMES, &td, HEADERGET_DEFAULT)) { + headerGet(pkg->h, RPMTAG_OLDFILENAMES, &td, HEADERGET_DEFAULT); + if (list) { for (i = 0; i < rpmtdCount(&td); i++) { - const char *s = rpmtdNextString(&td); - len = strlen(s); + len = strlen(list[i]); - update_provide_entry(s, len, 0, 0, pkg, provides); + update_provide_entry(list[i], len, 0, 0, pkg, provides); } - rpmtdFreeData(&td); + free(list); } } } } -static FD_t +FD_t open_archive(char *filename, int *empty_archive) { int fd; FD_t rfd = NULL; @@ -1038,7 +1077,7 @@ parse_line(AV *depslist, HV *provides, HV *obsoletes, URPM__Package pkg, char *b pkg->info = memcpy(malloc(data_len), data, data_len); pkg->flag &= ~FLAG_ID; pkg->flag |= 1 + av_len(depslist); - sv_pkg = sv_setref_pv(newSVpvs(""), "URPM::Package", + sv_pkg = sv_setref_pv(newSVpv("", 0), "URPM::Package", _pkg = memcpy(malloc(sizeof(struct s_Package)), pkg, sizeof(struct s_Package))); if (call_package_callback(urpm, sv_pkg, callback)) { if (provides) update_provides(_pkg, provides); @@ -1153,7 +1192,7 @@ update_header(char *filename, URPM__Package pkg, __attribute__((unused)) int kee if (fd != NULL && rpmReadPackageFile(ts, fd, filename, &header) == 0 && header) { Fclose(fd); - _header_free(pkg); + if (pkg->h && !(pkg->flag & FLAG_NO_HEADER_FREE)) pkg->h = headerFree(pkg->h); pkg->h = header; pkg->flag &= ~FLAG_NO_HEADER_FREE; @@ -1168,7 +1207,7 @@ update_header(char *filename, URPM__Package pkg, __attribute__((unused)) int kee close(d); if (fd != NULL) { - _header_free(pkg); + if (pkg->h && !(pkg->flag & FLAG_NO_HEADER_FREE)) pkg->h = headerFree(pkg->h); pkg->h = headerRead(fd, HEADER_MAGIC_YES); pkg->flag &= ~FLAG_NO_HEADER_FREE; Fclose(fd); @@ -1192,9 +1231,9 @@ read_config_files(int force) { return rc; } -static rpmVSFlags +static void ts_nosignature(rpmts ts) { - return rpmtsSetVSFlags(ts, _RPMVSF_NODIGESTS | _RPMVSF_NOSIGNATURES); + rpmtsSetVSFlags(ts, _RPMVSF_NODIGESTS | _RPMVSF_NOSIGNATURES); } static void *rpmRunTransactions_callback(__attribute__((unused)) const void *h, @@ -1295,11 +1334,20 @@ static void *rpmRunTransactions_callback(__attribute__((unused)) const void *h, i = POPi; fd = fdDup(i); if (fd) { +#ifdef RPM490 fd = fdLink(fd); - Fcntl(fd, F_SETFD, (void *)1); /* necessary to avoid forked/execed process to lock removable media */ +#else + fd = fdLink(fd, "persist perl-URPM"); +#endif + Fcntl(fd, F_SETFD, (void *)1); /* necessary to avoid forked/execed process to lock removable */ } PUTBACK; } else if (callback == td->callback_close) { +#ifdef RPM490 + fd = fdFree(fd); +#else + fd = fdFree(fd, "persist perl-URPM"); +#endif if (fd) { Fclose(fd); fd = NULL; @@ -1312,8 +1360,7 @@ static void *rpmRunTransactions_callback(__attribute__((unused)) const void *h, return callback == td->callback_open ? fd : NULL; } -static rpmTag -rpmtag_from_string(char *tag) +int rpmtag_from_string(char *tag) { if (!strcmp(tag, "name")) return RPMTAG_NAME; @@ -1334,44 +1381,6 @@ rpmtag_from_string(char *tag) else croak("unknown tag [%s]", tag); } -static int compare_evrs(int lepoch, char*lversion, char*lrelease, int repoch, char*rversion, char*rrelease) { - int compare; - compare = lepoch - repoch; - if (!compare) { - compare = rpmvercmp(lversion, rversion); - if (!compare && rrelease) - compare = rpmvercmp(lrelease, rrelease); - } - return compare; -} - -static int get_e_v_r(URPM__Package pkg, int *epoch, char **version, char **release, char **arch) { - if (pkg->info) { - char *s, *eos; - - if ((s = strchr(pkg->info, '@')) != NULL) { - if ((eos = strchr(s+1, '@')) != NULL) - *eos = 0; /* mark end of string to enable searching backwards */ - *epoch = atoi(s+1); - if (eos != NULL) *eos = '@'; - } else - *epoch = 0; - get_fullname_parts(pkg, NULL, version, release, arch, &eos); - /* temporarily mark end of each substring */ - (*release)[-1] = 0; - (*arch)[-1] = 0; - return 1; - } else if (pkg->h) { - *epoch = get_int(pkg->h, RPMTAG_EPOCH); - *version = get_name(pkg->h, RPMTAG_VERSION); - *release = get_name(pkg->h, RPMTAG_RELEASE); - *arch = get_arch(pkg->h); - return 1; - } - return 0; -} - - MODULE = URPM PACKAGE = URPM::Package PREFIX = Pkg_ void @@ -1386,7 +1395,7 @@ Pkg_DESTROY(pkg) free(pkg->provides); free(pkg->rflags); free(pkg->summary); - _header_free(pkg); + if (pkg->h && !(pkg->flag & FLAG_NO_HEADER_FREE)) pkg->h = headerFree(pkg->h); free(pkg); void @@ -1445,7 +1454,7 @@ Pkg_arch(pkg) get_fullname_parts(pkg, NULL, NULL, NULL, &arch, &eos); mXPUSHs(newSVpv(arch, eos-arch)); } else if (pkg->h) { - mXPUSHs(newSVpv(get_arch(pkg->h), 0)); + mXPUSHs(newSVpv(headerIsEntry(pkg->h, RPMTAG_SOURCERPM) ? get_name(pkg->h, RPMTAG_ARCH) : "src", 0)); } int @@ -1471,6 +1480,19 @@ Pkg_is_arch_compat__XS(pkg) OUTPUT: RETVAL +int +Pkg_is_platform_compat(pkg) + URPM::Package pkg + INIT: + CODE: + croak("is_platform_compat() is available only since rpm 4.4.8"); + { /* to match last } and avoid another #ifdef for it */ + RETVAL = 0; + } + + OUTPUT: + RETVAL + void Pkg_summary(pkg) URPM::Package pkg @@ -1484,57 +1506,94 @@ Pkg_summary(pkg) void Pkg_description(pkg) URPM::Package pkg - ALIAS: - sourcerpm = 1 - packager = 2 - buildhost = 3 - url = 4 - license = 5 - distribution = 6 - vendor = 7 - os = 8 - payload_format = 9 - disttag = 10 PPCODE: if (pkg->h) - switch (ix) { - case 0: - mXPUSHs(newSVpv_utf8(get_name(pkg->h, RPMTAG_DESCRIPTION), 0)); break; - case 1: - mXPUSHs(newSVpv(get_name(pkg->h, RPMTAG_SOURCERPM), 0)); break; - case 2: - mXPUSHs(newSVpv_utf8(get_name(pkg->h, RPMTAG_PACKAGER), 0)); break; - case 3: - mXPUSHs(newSVpv(get_name(pkg->h, RPMTAG_BUILDHOST), 0)); break; - case 4: - mXPUSHs(newSVpv(get_name(pkg->h, RPMTAG_URL), 0)); break; - case 5: - mXPUSHs(newSVpv(get_name(pkg->h, RPMTAG_LICENSE), 0)); break; - case 6: - mXPUSHs(newSVpv(get_name(pkg->h, RPMTAG_DISTRIBUTION), 0)); break; - case 7: - mXPUSHs(newSVpv(get_name(pkg->h, RPMTAG_VENDOR), 0)); break; - case 8: - mXPUSHs(newSVpv(get_name(pkg->h, RPMTAG_OS), 0)); break; - case 9: - mXPUSHs(newSVpv(get_name(pkg->h, RPMTAG_PAYLOADFORMAT), 0)); break; - case 10: - mXPUSHs(newSVpv(get_name(pkg->h, RPMTAG_DISTTAG), 0)); break; - } + mXPUSHs(newSVpv_utf8(get_name(pkg->h, RPMTAG_DESCRIPTION), 0)); + +void +Pkg_sourcerpm(pkg) + URPM::Package pkg + PPCODE: + if (pkg->h) + mXPUSHs(newSVpv(get_name(pkg->h, RPMTAG_SOURCERPM), 0)); + +void +Pkg_packager(pkg) + URPM::Package pkg + PPCODE: + if (pkg->h) + mXPUSHs(newSVpv_utf8(get_name(pkg->h, RPMTAG_PACKAGER), 0)); + +void +Pkg_buildhost(pkg) + URPM::Package pkg + PPCODE: + if (pkg->h) + mXPUSHs(newSVpv(get_name(pkg->h, RPMTAG_BUILDHOST), 0)); int Pkg_buildtime(pkg) URPM::Package pkg - ALIAS: - installtid = 1 CODE: if (pkg->h) - RETVAL = get_int(pkg->h, ix == 1 ? RPMTAG_INSTALLTID : RPMTAG_BUILDTIME); + RETVAL = get_int(pkg->h, RPMTAG_BUILDTIME); + else + RETVAL = 0; + OUTPUT: + RETVAL + +int +Pkg_installtid(pkg) + URPM::Package pkg + CODE: + if (pkg->h) + RETVAL = get_int(pkg->h, RPMTAG_INSTALLTID); else RETVAL = 0; OUTPUT: RETVAL +void +Pkg_url(pkg) + URPM::Package pkg + PPCODE: + if (pkg->h) + mXPUSHs(newSVpv(get_name(pkg->h, RPMTAG_URL), 0)); + +void +Pkg_license(pkg) + URPM::Package pkg + PPCODE: + if (pkg->h) + mXPUSHs(newSVpv(get_name(pkg->h, RPMTAG_LICENSE), 0)); + +void +Pkg_distribution(pkg) + URPM::Package pkg + PPCODE: + if (pkg->h) + mXPUSHs(newSVpv(get_name(pkg->h, RPMTAG_DISTRIBUTION), 0)); + +void +Pkg_vendor(pkg) + URPM::Package pkg + PPCODE: + if (pkg->h) + mXPUSHs(newSVpv(get_name(pkg->h, RPMTAG_VENDOR), 0)); + +void +Pkg_os(pkg) + URPM::Package pkg + PPCODE: + if (pkg->h) + mXPUSHs(newSVpv(get_name(pkg->h, RPMTAG_OS), 0)); + +void +Pkg_payload_format(pkg) + URPM::Package pkg + PPCODE: + if (pkg->h) + mXPUSHs(newSVpv(get_name(pkg->h, RPMTAG_PAYLOADFORMAT), 0)); void Pkg_fullname(pkg) @@ -1554,24 +1613,25 @@ Pkg_fullname(pkg) if (version - name < 1 || release - version < 1 || arch - release < 1) croak("invalid fullname"); EXTEND(SP, 4); - mPUSHs(newSVpv(name, version-name-1)); - mPUSHs(newSVpv(version, release-version-1)); - mPUSHs(newSVpv(release, arch-release-1)); - mPUSHs(newSVpv(arch, eos-arch)); + PUSHs(sv_2mortal(newSVpv(name, version-name-1))); + PUSHs(sv_2mortal(newSVpv(version, release-version-1))); + PUSHs(sv_2mortal(newSVpv(release, arch-release-1))); + PUSHs(sv_2mortal(newSVpv(arch, eos-arch))); } } else if (pkg->h) { - char *arch = get_arch(pkg->h); + char *name = get_name(pkg->h, RPMTAG_NAME); + char *version = get_name(pkg->h, RPMTAG_VERSION); + char *release = get_name(pkg->h, RPMTAG_RELEASE); + char *arch = headerIsEntry(pkg->h, RPMTAG_SOURCERPM) ? get_name(pkg->h, RPMTAG_ARCH) : "src"; if (gimme == G_SCALAR) { - char *s = headerGetAsString(pkg->h, RPMTAG_NVR); - mXPUSHs(newSVpvf("%s.%s", s, arch)); - free(s); + mXPUSHs(newSVpvf("%s-%s-%s.%s", name, version, release, arch)); } else if (gimme == G_ARRAY) { EXTEND(SP, 4); - mPUSHs(newSVpv(get_name(pkg->h, RPMTAG_NAME), 0)); - mPUSHs(newSVpv(get_name(pkg->h, RPMTAG_VERSION), 0)); - mPUSHs(newSVpv(get_name(pkg->h, RPMTAG_RELEASE), 0)); - mPUSHs(newSVpv(arch, 0)); + PUSHs(sv_2mortal(newSVpv(name, 0))); + PUSHs(sv_2mortal(newSVpv(version, 0))); + PUSHs(sv_2mortal(newSVpv(release, 0))); + PUSHs(sv_2mortal(newSVpv(arch, 0))); } } @@ -1583,8 +1643,7 @@ Pkg_epoch(pkg) char *s, *eos; if ((s = strchr(pkg->info, '@')) != NULL) { - if ((eos = strchr(s+1, '@')) != NULL) - *eos = 0; /* mark end of string to enable searching backwards */ + if ((eos = strchr(s+1, '@')) != NULL) *eos = 0; /* mark end of string to enable searching backwards */ RETVAL = atoi(s+1); if (eos != NULL) *eos = '@'; } else @@ -1601,16 +1660,57 @@ Pkg_compare_pkg(lpkg, rpkg) URPM::Package rpkg PREINIT: int compare = 0; - int lepoch, repoch; - char *lversion, *lrelease, *larch; - char *rversion, *rrelease, *rarch; + int lepoch; + char *lversion; + char *lrelease; + char *larch; + char *leos; + int repoch; + char *rversion; + char *rrelease; + char *rarch; + char *reos; CODE: if (lpkg == rpkg) RETVAL = 0; else { - if (!get_e_v_r(lpkg, &lepoch, &lversion, &lrelease, &larch)) - croak("undefined package"); + if (lpkg->info) { + char *s; + + if ((s = strchr(lpkg->info, '@')) != NULL) { + if ((leos = strchr(s+1, '@')) != NULL) *leos = 0; /* mark end of string to enable searching backwards */ + lepoch = atoi(s+1); + if (leos != NULL) *leos = '@'; + } else + lepoch = 0; + get_fullname_parts(lpkg, NULL, &lversion, &lrelease, &larch, &leos); + /* temporarily mark end of each substring */ + lrelease[-1] = 0; + larch[-1] = 0; + } else if (lpkg->h) { + lepoch = get_int(lpkg->h, RPMTAG_EPOCH); + lversion = get_name(lpkg->h, RPMTAG_VERSION); + lrelease = get_name(lpkg->h, RPMTAG_RELEASE); + larch = headerIsEntry(lpkg->h, RPMTAG_SOURCERPM) ? get_name(lpkg->h, RPMTAG_ARCH) : "src"; + } else croak("undefined package"); + if (rpkg->info) { + char *s; - if (!get_e_v_r(rpkg, &repoch, &rversion, &rrelease, &rarch)) { + if ((s = strchr(rpkg->info, '@')) != NULL) { + if ((reos = strchr(s+1, '@')) != NULL) *reos = 0; /* mark end of string to enable searching backwards */ + repoch = atoi(s+1); + if (reos != NULL) *reos = '@'; + } else + repoch = 0; + get_fullname_parts(rpkg, NULL, &rversion, &rrelease, &rarch, &reos); + /* temporarily mark end of each substring */ + rrelease[-1] = 0; + rarch[-1] = 0; + } else if (rpkg->h) { + repoch = get_int(rpkg->h, RPMTAG_EPOCH); + rversion = get_name(rpkg->h, RPMTAG_VERSION); + rrelease = get_name(rpkg->h, RPMTAG_RELEASE); + rarch = headerIsEntry(rpkg->h, RPMTAG_SOURCERPM) ? get_name(rpkg->h, RPMTAG_ARCH) : "src"; + } else { /* restore info string modified */ if (lpkg->info) { lrelease[-1] = '-'; @@ -1618,9 +1718,12 @@ Pkg_compare_pkg(lpkg, rpkg) } croak("undefined package"); } - compare = compare_evrs(lepoch, lversion, lrelease, repoch, rversion, rrelease); - // equal? compare arches too + compare = lepoch - repoch; if (!compare) { + compare = rpmvercmp(lversion, rversion); + if (!compare) { + compare = rpmvercmp(lrelease, rrelease); + if (!compare) { int lscore, rscore; char *eolarch = strchr(larch, '@'); char *eorarch = strchr(rarch, '@'); @@ -1630,8 +1733,11 @@ Pkg_compare_pkg(lpkg, rpkg) if (eorarch) *eorarch = 0; rscore = rpmMachineScore(RPM_MACHTABLE_INSTARCH, rarch); if (lscore == 0) { if (rscore == 0) +#if 0 /* Nanar: TODO check this * hu ?? what is the goal of strcmp, some of arch are equivalent */ + compare = 0 +#endif compare = strcmp(larch, rarch); else compare = -1; @@ -1643,6 +1749,8 @@ Pkg_compare_pkg(lpkg, rpkg) } if (eolarch) *eolarch = '@'; if (eorarch) *eorarch = '@'; + } + } } /* restore info string modified */ if (lpkg->info) { @@ -1663,38 +1771,70 @@ Pkg_compare(pkg, evr) URPM::Package pkg char *evr PREINIT: - int _epoch, repoch = 0; - char *_version, *_release, *_eos; + int compare = 0; + int _epoch; + char *_version; + char *_release; + char *_eos; CODE: - if (!get_e_v_r(pkg, &_epoch, &_version, &_release, &_eos)) - croak("undefined package"); + if (pkg->info) { + char *s; - char *epoch = NULL, *version, *release; + if ((s = strchr(pkg->info, '@')) != NULL) { + if ((_eos = strchr(s+1, '@')) != NULL) *_eos = 0; /* mark end of string to enable searching backwards */ + _epoch = atoi(s+1); + if (_eos != NULL) *_eos = '@'; + } else + _epoch = 0; + get_fullname_parts(pkg, NULL, &_version, &_release, &_eos, NULL); + /* temporarily mark end of each substring */ + _release[-1] = 0; + _eos[-1] = 0; + } else if (pkg->h) + _epoch = get_int(pkg->h, RPMTAG_EPOCH); + else croak("undefined package"); + if (!compare) { + char *epoch, *version, *release; - /* extract epoch and version from evr */ - version = evr; - while (*version && isdigit(*version)) version++; - if (*version == ':') { - epoch = evr; - *version++ = 0; - if (!*epoch) epoch = "0"; - version[-1] = ':'; /* restore in memory modification */ - } else { - /* there is no epoch defined, so assume epoch = 0 */ + /* extract epoch and version from evr */ version = evr; + while (*version && isdigit(*version)) version++; + if (*version == ':') { + epoch = evr; + *version++ = 0; + if (!*epoch) epoch = "0"; + compare = _epoch - (*epoch ? atoi(epoch) : 0); + version[-1] = ':'; /* restore in memory modification */ + } else { + /* there is no epoch defined, so assume epoch = 0 */ + version = evr; + compare = _epoch; + } + if (!compare) { + if (!pkg->info) + _version = get_name(pkg->h, RPMTAG_VERSION); + /* continue extracting release if any */ + if ((release = strrchr(version, '-')) != NULL) { + *release++ = 0; + compare = rpmvercmp(_version, version); + if (!compare) { + /* need to compare with release here */ + if (!pkg->info) + _release = get_name(pkg->h, RPMTAG_RELEASE); + compare = rpmvercmp(_release, release); + } + release[-1] = '-'; /* restore in memory modification */ + } else { + compare = rpmvercmp(_version, version); + } + } } - if ((release = strrchr(version, '-')) != NULL) - *release++ = 0; - repoch = epoch && *epoch ? atoi(epoch) : 0; - - RETVAL = compare_evrs(_epoch, _version, _release, repoch, version, release); /* restore info string modified */ if (pkg->info) { _release[-1] = '-'; _eos[-1] = '.'; } - if (release) - release[-1] = '-'; /* restore in memory modification */ + RETVAL = compare; OUTPUT: RETVAL @@ -1706,8 +1846,7 @@ Pkg_size(pkg) char *s, *eos; if ((s = strchr(pkg->info, '@')) != NULL && (s = strchr(s+1, '@')) != NULL) { - if ((eos = strchr(s+1, '@')) != NULL) - *eos = 0; /* mark end of string to enable searching backwards */ + if ((eos = strchr(s+1, '@')) != NULL) *eos = 0; /* mark end of string to enable searching backwards */ RETVAL = atoi(s+1); if (eos != NULL) *eos = '@'; } else @@ -1767,10 +1906,12 @@ Pkg_filename(pkg) memcpy(eon, savbuf, 4); } } else if (pkg->h) { - char *nvr = headerGetAsString(pkg->h, RPMTAG_NVR); - char *arch = get_arch(pkg->h); + char *name = get_name(pkg->h, RPMTAG_NAME); + char *version = get_name(pkg->h, RPMTAG_VERSION); + char *release = get_name(pkg->h, RPMTAG_RELEASE); + char *arch = headerIsEntry(pkg->h, RPMTAG_SOURCERPM) ? get_name(pkg->h, RPMTAG_ARCH) : "src"; - mXPUSHs(newSVpvf("%s.%s.rpm", nvr, arch)); + mXPUSHs(newSVpvf("%s-%s-%s.%s.rpm", name, version, release, arch)); } # deprecated @@ -1787,10 +1928,12 @@ Pkg_header_filename(pkg) } else if (pkg->h) { char buff[1024]; char *p = buff; - char *nvr = headerGetAsString(pkg->h, RPMTAG_NVR); - char *arch = get_arch(pkg->h); + char *name = get_name(pkg->h, RPMTAG_NAME); + char *version = get_name(pkg->h, RPMTAG_VERSION); + char *release = get_name(pkg->h, RPMTAG_RELEASE); + char *arch = headerIsEntry(pkg->h, RPMTAG_SOURCERPM) ? get_name(pkg->h, RPMTAG_ARCH) : "src"; - p += snprintf(buff, sizeof(buff), "%s.%s", nvr, arch); + p += snprintf(buff, sizeof(buff), "%s-%s-%s.%s", name, version, release, arch); mXPUSHs(newSVpv(buff, p-buff)); } @@ -1798,8 +1941,9 @@ void Pkg_id(pkg) URPM::Package pkg PPCODE: - if ((pkg->flag & FLAG_ID) <= FLAG_ID_MAX) + if ((pkg->flag & FLAG_ID) <= FLAG_ID_MAX) { mXPUSHs(newSViv(pkg->flag & FLAG_ID)); + } void Pkg_set_id(pkg, id=-1) @@ -1834,7 +1978,10 @@ Pkg_suggests(pkg) URPM::Package pkg PPCODE: PUTBACK; - return_list_str(pkg->suggests, pkg->h, RPMTAG_SUGGESTSNAME, 0, 0, callback_list_str_xpush, NULL); + int count = return_list_str(pkg->suggests, pkg->h, RPMTAG_SUGGESTSNAME, 0, 0, callback_list_str_xpush, NULL); + if (count == 0) + return_list_str(pkg->suggests, pkg->h, RPMTAG_REQUIRENAME, RPMTAG_REQUIREFLAGS, 0, + callback_list_str_xpush_old_suggests, NULL); SPAGAIN; void @@ -1849,46 +1996,22 @@ Pkg_obsoletes(pkg) void Pkg_obsoletes_nosense(pkg) URPM::Package pkg - ALIAS: - conflicts_nosense = 1 - provides_nosense = 2 PPCODE: PUTBACK; - rpmTag tag; - char *s; - switch (ix) { - case 1: tag = RPMTAG_CONFLICTNAME; s = pkg->conflicts; break; - case 2: tag = RPMTAG_PROVIDENAME; s = pkg->provides; break; - default: tag = RPMTAG_OBSOLETENAME; s = pkg->obsoletes; break; - } - return_list_str(s, pkg->h, tag, 0, 0, callback_list_str_xpush, NULL); + return_list_str(pkg->obsoletes, pkg->h, RPMTAG_OBSOLETENAME, 0, 0, callback_list_str_xpush, NULL); SPAGAIN; int -Pkg_obsoletes_overlap(pkg, s) +Pkg_obsoletes_overlap(pkg, s, b_nopromote=1, direction=-1) URPM::Package pkg char *s - ALIAS: - provides_overlap = 1 + int b_nopromote + int direction PREINIT: struct cb_overlap_s os; char *eon = NULL; char eonc = '\0'; - rpmTag tag_name; - rpmTag tag_flags, tag_version; - CODE: - switch (ix) { - case 1: - tag_name = RPMTAG_PROVIDENAME; - tag_flags = RPMTAG_PROVIDEFLAGS; - tag_version = RPMTAG_PROVIDEVERSION; - break; - default: - tag_name = RPMTAG_OBSOLETENAME; - tag_flags = RPMTAG_OBSOLETEFLAGS; - tag_version = RPMTAG_OBSOLETEVERSION; - break; - } + CODE: os.name = s; os.flags = 0; while (*s && *s != ' ' && *s != '[' && *s != '<' && *s != '>' && *s != '=') ++s; @@ -1905,14 +2028,12 @@ Pkg_obsoletes_overlap(pkg, s) os.evr = s; } else os.evr = ""; - os.direction = ix == 0 ? -1 : 1; + os.direction = direction; + os.b_nopromote = b_nopromote; /* mark end of name */ - if (eon) { - eonc = *eon; - *eon = 0; - } + if (eon) { eonc = *eon; *eon = 0; } /* return_list_str returns a negative value is the callback has returned non-zero */ - RETVAL = return_list_str(ix == 0 ? pkg->obsoletes : pkg->provides, pkg->h, tag_name, tag_flags, tag_version, + RETVAL = return_list_str(pkg->obsoletes, pkg->h, RPMTAG_OBSOLETENAME, RPMTAG_OBSOLETEFLAGS, RPMTAG_OBSOLETEVERSION, callback_list_str_overlap, &os) < 0; /* restore end of name */ if (eon) *eon = eonc; @@ -1929,6 +2050,14 @@ Pkg_conflicts(pkg) SPAGAIN; void +Pkg_conflicts_nosense(pkg) + URPM::Package pkg + PPCODE: + PUTBACK; + return_list_str(pkg->conflicts, pkg->h, RPMTAG_CONFLICTNAME, 0, 0, callback_list_str_xpush, NULL); + SPAGAIN; + +void Pkg_provides(pkg) URPM::Package pkg PPCODE: @@ -1938,69 +2067,220 @@ Pkg_provides(pkg) SPAGAIN; void +Pkg_provides_nosense(pkg) + URPM::Package pkg + PPCODE: + PUTBACK; + return_list_str(pkg->provides, pkg->h, RPMTAG_PROVIDENAME, 0, 0, callback_list_str_xpush, NULL); + SPAGAIN; + +int +Pkg_provides_overlap(pkg, s, b_nopromote=1, direction=1) + URPM::Package pkg + char *s + int b_nopromote + int direction + PREINIT: + struct cb_overlap_s os; + char *eon = NULL; + char eonc = '\0'; + CODE: + os.name = s; + os.flags = 0; + while (*s && *s != ' ' && *s != '[' && *s != '<' && *s != '>' && *s != '=') ++s; + if (*s) { + eon = s; + while (*s) { + if (*s == ' ' || *s == '[' || *s == '*' || *s == ']'); + else if (*s == '<') os.flags |= RPMSENSE_LESS; + else if (*s == '>') os.flags |= RPMSENSE_GREATER; + else if (*s == '=') os.flags |= RPMSENSE_EQUAL; + else break; + ++s; + } + os.evr = s; + } else + os.evr = ""; + os.direction = direction; + os.b_nopromote = b_nopromote; + /* mark end of name */ + if (eon) { eonc = *eon; *eon = 0; } + /* return_list_str returns a negative value is the callback has returned non-zero */ + RETVAL = return_list_str(pkg->provides, pkg->h, RPMTAG_PROVIDENAME, RPMTAG_PROVIDEFLAGS, RPMTAG_PROVIDEVERSION, + callback_list_str_overlap, &os) < 0; + /* restore end of name */ + if (eon) *eon = eonc; + OUTPUT: + RETVAL + +void Pkg_buildarchs(pkg) URPM::Package pkg - ALIAS: - excludearchs = 1 - exclusivearchs = 2 - dirnames = 3 - filelinktos = 4 - files_md5sum = 5 - files_owner = 6 - files_group = 7 - changelog_name = 8 - changelog_text = 9 PPCODE: PUTBACK; - rpmTag tag; - switch (ix) { - case 1: tag = RPMTAG_EXCLUDEARCH; break; - case 2: tag = RPMTAG_EXCLUSIVEARCH; break; - case 3: tag = RPMTAG_DIRNAMES; break; - case 4: tag = RPMTAG_FILELINKTOS; break; - case 5: tag = RPMTAG_FILEMD5S; break; - case 6: tag = RPMTAG_FILEUSERNAME; break; - case 7: tag = RPMTAG_FILEGROUPNAME; break; - case 8: tag = RPMTAG_CHANGELOGNAME; break; - case 9: tag = RPMTAG_CHANGELOGTEXT; break; - default: tag = RPMTAG_BUILDARCHS; break; - } - xpush_simple_list_str(pkg->h, tag); + xpush_simple_list_str(pkg->h, RPMTAG_BUILDARCHS); + SPAGAIN; + +void +Pkg_excludearchs(pkg) + URPM::Package pkg + PPCODE: + PUTBACK; + xpush_simple_list_str(pkg->h, RPMTAG_EXCLUDEARCH); + SPAGAIN; + +void +Pkg_exclusivearchs(pkg) + URPM::Package pkg + PPCODE: + PUTBACK; + xpush_simple_list_str(pkg->h, RPMTAG_EXCLUSIVEARCH); + SPAGAIN; + +void +Pkg_dirnames(pkg) + URPM::Package pkg + PPCODE: + PUTBACK; + xpush_simple_list_str(pkg->h, RPMTAG_DIRNAMES); + SPAGAIN; + +void Pkg_distepoch(pkg) + URPM::Package pkg + PPCODE: +#ifdef RPMTAG_DISTEPOCH + if (pkg->h) { + mXPUSHs(newSVpv(get_name(pkg->h, RPMTAG_DISTEPOCH), 0)); + } +#else + croak("distepoch isn't available with this rpm version"); +#endif + +void Pkg_disttag(pkg) + URPM::Package pkg + PPCODE: + if (pkg->h) { + mXPUSHs(newSVpv(get_name(pkg->h, RPMTAG_DISTTAG), 0)); + } + +void +Pkg_filelinktos(pkg) + URPM::Package pkg + PPCODE: + PUTBACK; + xpush_simple_list_str(pkg->h, RPMTAG_FILELINKTOS); SPAGAIN; void Pkg_files(pkg) URPM::Package pkg - ALIAS: - conf_files = 1 PPCODE: PUTBACK; - return_files(pkg->h, ix == 0 ? 0 : FILTER_MODE_CONF_FILES); + return_files(pkg->h, 0); + SPAGAIN; + +void +Pkg_files_md5sum(pkg) + URPM::Package pkg + PPCODE: + PUTBACK; + xpush_simple_list_str(pkg->h, RPMTAG_FILEMD5S); + SPAGAIN; + +void +Pkg_files_owner(pkg) + URPM::Package pkg + PPCODE: + PUTBACK; + xpush_simple_list_str(pkg->h, RPMTAG_FILEUSERNAME); + SPAGAIN; + +void +Pkg_files_group(pkg) + URPM::Package pkg + PPCODE: + PUTBACK; + xpush_simple_list_str(pkg->h, RPMTAG_FILEGROUPNAME); SPAGAIN; void Pkg_files_mtime(pkg) URPM::Package pkg - ALIAS: - files_size = 1 - files_uid = 2 - files_gid = 3 - files_mode = 4 - files_flags = 5 - changelog_time = 6 PPCODE: PUTBACK; - rpmTag tag; - switch (ix) { - case 1: tag = RPMTAG_FILESIZES; break; - case 2: tag = RPMTAG_FILEUIDS; break; - case 3: tag = RPMTAG_FILEGIDS; break; - case 4: tag = RPMTAG_FILEMODES; break; - case 5: tag = RPMTAG_FILEFLAGS; break; - case 6: tag = RPMTAG_CHANGELOGTIME; break; - default: tag = RPMTAG_FILEMTIMES; break; - } - return_list_number(pkg->h, tag); + return_list_int32_t(pkg->h, RPMTAG_FILEMTIMES); + SPAGAIN; + +void +Pkg_files_size(pkg) + URPM::Package pkg + PPCODE: + PUTBACK; + return_list_int32_t(pkg->h, RPMTAG_FILESIZES); + SPAGAIN; + +void +Pkg_files_uid(pkg) + URPM::Package pkg + PPCODE: + PUTBACK; + return_list_int32_t(pkg->h, RPMTAG_FILEUIDS); + SPAGAIN; + +void +Pkg_files_gid(pkg) + URPM::Package pkg + PPCODE: + PUTBACK; + return_list_int32_t(pkg->h, RPMTAG_FILEGIDS); + SPAGAIN; + +void +Pkg_files_mode(pkg) + URPM::Package pkg + PPCODE: + PUTBACK; + return_list_uint_16(pkg->h, RPMTAG_FILEMODES); + SPAGAIN; + +void +Pkg_files_flags(pkg) + URPM::Package pkg + PPCODE: + PUTBACK; + return_list_int32_t(pkg->h, RPMTAG_FILEFLAGS); + SPAGAIN; + +void +Pkg_conf_files(pkg) + URPM::Package pkg + PPCODE: + PUTBACK; + return_files(pkg->h, FILTER_MODE_CONF_FILES); + SPAGAIN; + +void +Pkg_changelog_time(pkg) + URPM::Package pkg + PPCODE: + PUTBACK; + return_list_int32_t(pkg->h, RPMTAG_CHANGELOGTIME); + SPAGAIN; + +void +Pkg_changelog_name(pkg) + URPM::Package pkg + PPCODE: + PUTBACK; + xpush_simple_list_str(pkg->h, RPMTAG_CHANGELOGNAME); + SPAGAIN; + +void +Pkg_changelog_text(pkg) + URPM::Package pkg + PPCODE: + PUTBACK; + xpush_simple_list_str(pkg->h, RPMTAG_CHANGELOGTEXT); SPAGAIN; void @@ -2013,23 +2293,26 @@ Pkg_queryformat(pkg, fmt) if (pkg->h) { s = headerFormat(pkg->h, fmt, NULL); if (s) - mXPUSHs(newSVpv_utf8(s, 0)); + mXPUSHs(newSVpv_utf8(s,0)); } void Pkg_get_tag(pkg, tagname) URPM::Package pkg int tagname; - ALIAS: - get_tag_modifiers = 1 PPCODE: PUTBACK; - if (ix == 0) - return_list_tag(pkg, tagname); - else - return_list_tag_modifier(pkg->h, tagname); + return_list_tag(pkg, tagname); SPAGAIN; +void +Pkg_get_tag_modifiers(pkg, tagname) + URPM::Package pkg + int tagname; + PPCODE: + PUTBACK; + return_list_tag_modifier(pkg->h, tagname); + SPAGAIN; void Pkg_pack_header(pkg) @@ -2045,7 +2328,10 @@ Pkg_update_header(pkg, filename, ...) int packing = 0; int keep_all_tags = 0; CODE: - if (items > 3) { + /* compability mode with older interface of parse_hdlist */ + if (items == 3) + packing = SvIV(ST(2)); + else if (items > 3) { int i; for (i = 2; i < items-1; i+=2) { STRLEN len; @@ -2066,7 +2352,7 @@ void Pkg_free_header(pkg) URPM::Package pkg CODE: - _header_free(pkg); + if (pkg->h && !(pkg->flag & FLAG_NO_HEADER_FREE)) pkg->h = headerFree(pkg->h); pkg->h = NULL; void @@ -2173,56 +2459,135 @@ Pkg_set_flag(pkg, name, value=1) RETVAL int +Pkg_flag_skip(pkg) + URPM::Package pkg + CODE: + RETVAL = pkg->flag & FLAG_SKIP; + OUTPUT: + RETVAL + +int Pkg_set_flag_skip(pkg, value=1) URPM::Package pkg int value - ALIAS: - set_flag_base = 1 - set_flag_disable_obsolete = 2 - set_flag_installed = 3 - set_flag_requested = 4 - set_flag_required = 5 - set_flag_upgrade = 6 CODE: - unsigned flag; - switch (ix) { - case 1: flag = FLAG_BASE; break; - case 2: flag = FLAG_DISABLE_OBSOLETE; break; - case 3: flag = FLAG_INSTALLED; break; - case 4: flag = FLAG_REQUESTED; break; - case 5: flag = FLAG_REQUIRED; break; - case 6: flag = FLAG_UPGRADE; break; - default: flag = FLAG_SKIP; break; - } - RETVAL = pkg->flag & flag; - if (value) pkg->flag |= flag; - else pkg->flag &= ~flag; + RETVAL = pkg->flag & FLAG_SKIP; + if (value) pkg->flag |= FLAG_SKIP; + else pkg->flag &= ~FLAG_SKIP; OUTPUT: RETVAL +int +Pkg_flag_base(pkg) + URPM::Package pkg + CODE: + RETVAL = pkg->flag & FLAG_BASE; + OUTPUT: + RETVAL + +int +Pkg_set_flag_base(pkg, value=1) + URPM::Package pkg + int value + CODE: + RETVAL = pkg->flag & FLAG_BASE; + if (value) pkg->flag |= FLAG_BASE; + else pkg->flag &= ~FLAG_BASE; + OUTPUT: + RETVAL + +int +Pkg_flag_disable_obsolete(pkg) + URPM::Package pkg + CODE: + RETVAL = pkg->flag & FLAG_DISABLE_OBSOLETE; + OUTPUT: + RETVAL + +int +Pkg_set_flag_disable_obsolete(pkg, value=1) + URPM::Package pkg + int value + CODE: + RETVAL = pkg->flag & FLAG_DISABLE_OBSOLETE; + if (value) pkg->flag |= FLAG_DISABLE_OBSOLETE; + else pkg->flag &= ~FLAG_DISABLE_OBSOLETE; + OUTPUT: + RETVAL + +int +Pkg_flag_installed(pkg) + URPM::Package pkg + CODE: + RETVAL = pkg->flag & FLAG_INSTALLED; + OUTPUT: + RETVAL + +int +Pkg_set_flag_installed(pkg, value=1) + URPM::Package pkg + int value + CODE: + RETVAL = pkg->flag & FLAG_INSTALLED; + if (value) pkg->flag |= FLAG_INSTALLED; + else pkg->flag &= ~FLAG_INSTALLED; + OUTPUT: + RETVAL + +int +Pkg_flag_requested(pkg) + URPM::Package pkg + CODE: + RETVAL = pkg->flag & FLAG_REQUESTED; + OUTPUT: + RETVAL + +int +Pkg_set_flag_requested(pkg, value=1) + URPM::Package pkg + int value + CODE: + RETVAL = pkg->flag & FLAG_REQUESTED; + if (value) pkg->flag |= FLAG_REQUESTED; + else pkg->flag &= ~FLAG_REQUESTED; + OUTPUT: + RETVAL int Pkg_flag_required(pkg) URPM::Package pkg - ALIAS: - flag_upgrade = 1 - flag_disable_obsolete = 2 - flag_requested = 3 - flag_installed = 4 - flag_base = 5 - flag_skip = 6 CODE: - unsigned flag; - switch (ix) { - case 1: flag = FLAG_UPGRADE; break; - case 2: flag = FLAG_DISABLE_OBSOLETE; break; - case 3: flag = FLAG_REQUESTED; break; - case 4: flag = FLAG_INSTALLED; break; - case 5: flag = FLAG_BASE; break; - case 6: flag = FLAG_SKIP; break; - default: flag = FLAG_REQUIRED; break; - } - RETVAL = pkg->flag & flag; + RETVAL = pkg->flag & FLAG_REQUIRED; + OUTPUT: + RETVAL + +int +Pkg_set_flag_required(pkg, value=1) + URPM::Package pkg + int value + CODE: + RETVAL = pkg->flag & FLAG_REQUIRED; + if (value) pkg->flag |= FLAG_REQUIRED; + else pkg->flag &= ~FLAG_REQUIRED; + OUTPUT: + RETVAL + +int +Pkg_flag_upgrade(pkg) + URPM::Package pkg + CODE: + RETVAL = pkg->flag & FLAG_UPGRADE; + OUTPUT: + RETVAL + +int +Pkg_set_flag_upgrade(pkg, value=1) + URPM::Package pkg + int value + CODE: + RETVAL = pkg->flag & FLAG_UPGRADE; + if (value) pkg->flag |= FLAG_UPGRADE; + else pkg->flag &= ~FLAG_UPGRADE; OUTPUT: RETVAL @@ -2341,7 +2706,7 @@ Db_open(prefix=NULL, write_perm=0) RETVAL int -Db_rebuild(prefix=NULL) +Db_rebuild(prefix="") char *prefix PREINIT: rpmts ts; @@ -2355,7 +2720,7 @@ Db_rebuild(prefix=NULL) RETVAL int -Db_verify(prefix=NULL) +Db_verify(prefix="") char *prefix PREINIT: rpmts ts; @@ -2381,20 +2746,35 @@ Db_traverse(db,callback) PREINIT: Header header; rpmdbMatchIterator mi; - rpmVSFlags ovsflags; int count = 0; CODE: +#ifdef RPM490 db->ts = rpmtsLink(db->ts); - ovsflags = ts_nosignature(db->ts); +#else + db->ts = rpmtsLink(db->ts, "URPM::DB::traverse"); +#endif + ts_nosignature(db->ts); mi = rpmtsInitIterator(db->ts, RPMDBI_PACKAGES, NULL, 0); while ((header = rpmdbNextIterator(mi))) { if (SvROK(callback)) { - _run_cb_while_traversing(callback, header); + dSP; + URPM__Package pkg = calloc(1, sizeof(struct s_Package)); + + pkg->flag = FLAG_ID_INVALID | FLAG_NO_HEADER_FREE; + pkg->h = header; + + PUSHMARK(SP); + mXPUSHs(sv_setref_pv(newSVpv("", 0), "URPM::Package", pkg)); + PUTBACK; + + call_sv(callback, G_DISCARD | G_SCALAR); + + SPAGAIN; + pkg->h = NULL; /* avoid using it anymore, in case it has been copied inside callback */ } ++count; } rpmdbFreeIterator(mi); - rpmtsSetVSFlags(db->ts, ovsflags); (void)rpmtsFree(db->ts); RETVAL = count; OUTPUT: @@ -2410,29 +2790,45 @@ Db_traverse_tag(db,tag,names,callback) Header header; rpmdbMatchIterator mi; int count = 0; - rpmVSFlags ovsflags; CODE: if (SvROK(names) && SvTYPE(SvRV(names)) == SVt_PVAV) { AV* names_av = (AV*)SvRV(names); int len = av_len(names_av); - int i; - rpmTag rpmtag = rpmtag_from_string(tag); + int i, rpmtag; + + rpmtag = rpmtag_from_string(tag); for (i = 0; i <= len; ++i) { STRLEN str_len; SV **isv = av_fetch(names_av, i, 0); char *name = SvPV(*isv, str_len); +#ifdef RPM490 db->ts = rpmtsLink(db->ts); - ovsflags = ts_nosignature(db->ts); +#else + db->ts = rpmtsLink(db->ts, "URPM::DB::traverse_tag"); +#endif + ts_nosignature(db->ts); mi = rpmtsInitIterator(db->ts, rpmtag, name, str_len); while ((header = rpmdbNextIterator(mi))) { if (SvROK(callback)) { - _run_cb_while_traversing(callback, header); + dSP; + URPM__Package pkg = calloc(1, sizeof(struct s_Package)); + + pkg->flag = FLAG_ID_INVALID | FLAG_NO_HEADER_FREE; + pkg->h = header; + + PUSHMARK(SP); + mXPUSHs(sv_setref_pv(newSVpv("", 0), "URPM::Package", pkg)); + PUTBACK; + + call_sv(callback, G_DISCARD | G_SCALAR); + + SPAGAIN; + pkg->h = NULL; /* avoid using it anymore, in case it has been copied inside callback */ } ++count; } (void)rpmdbFreeIterator(mi); - rpmtsSetVSFlags(db->ts, ovsflags); (void)rpmtsFree(db->ts); } } else croak("bad arguments list"); @@ -2450,21 +2846,36 @@ Db_traverse_tag_find(db,tag,name,callback) Header header; rpmdbMatchIterator mi; CODE: - rpmTag rpmtag = rpmtag_from_string(tag); + int rpmtag = rpmtag_from_string(tag); int found = 0; - rpmVSFlags ovsflags; +#ifdef RPM490 db->ts = rpmtsLink(db->ts); - ovsflags = ts_nosignature(db->ts); +#else + db->ts = rpmtsLink(db->ts, "URPM::DB::traverse_tag"); +#endif + ts_nosignature(db->ts); mi = rpmtsInitIterator(db->ts, rpmtag, name, 0); while ((header = rpmdbNextIterator(mi))) { - int count = _run_cb_while_traversing(callback, header); + dSP; + URPM__Package pkg = calloc(1, sizeof(struct s_Package)); + + pkg->flag = FLAG_ID_INVALID | FLAG_NO_HEADER_FREE; + pkg->h = header; + + PUSHMARK(SP); + mXPUSHs(sv_setref_pv(newSVpv("", 0), "URPM::Package", pkg)); + PUTBACK; + + int count = call_sv(callback, G_SCALAR); + + SPAGAIN; + pkg->h = NULL; /* avoid using it anymore, in case it has been copied inside callback */ if (count == 1 && POPi) { found = 1; break; } } - rpmtsSetVSFlags(db->ts, ovsflags); (void)rpmdbFreeIterator(mi); (void)rpmtsFree(db->ts); RETVAL = found; @@ -2472,12 +2883,17 @@ Db_traverse_tag_find(db,tag,name,callback) RETVAL URPM::Transaction -Db_create_transaction(db) +Db_create_transaction(db, prefix="/") URPM::DB db + char *prefix CODE: /* this is *REALLY* dangerous to create a new transaction while another is open, so use the db transaction instead. */ +#ifdef RPM490 db->ts = rpmtsLink(db->ts); +#else + db->ts = rpmtsLink(db->ts, "URPM::DB::create_transaction"); +#endif ++db->count; RETVAL = db; OUTPUT: @@ -2508,7 +2924,10 @@ Trans_add(trans, pkg, ...) if ((pkg->flag & FLAG_ID) <= FLAG_ID_MAX && pkg->h != NULL) { int update = 0; rpmRelocation *relocations = NULL; - if (items > 3) { + /* compability mode with older interface of add */ + if (items == 3) + update = SvIV(ST(2)); + else if (items > 3) { int i; for (i = 2; i < items-1; i+=2) { STRLEN len; @@ -2545,7 +2964,19 @@ Trans_remove(trans, name) Header h; rpmdbMatchIterator mi; int count = 0; + char *boa = NULL, *bor = NULL; CODE: + /* hide arch in name if present */ + if ((boa = strrchr(name, '.'))) { + *boa = 0; + if ((bor = strrchr(name, '-'))) { + *bor = 0; + if (!strrchr(name, '-')) + *boa = '.'; boa = NULL; + *bor = '-'; bor = NULL; + } else + *boa = '.'; boa = NULL; + } mi = rpmtsInitIterator(trans->ts, RPMDBI_LABEL, name, 0); while ((h = rpmdbNextIterator(mi))) { unsigned int recOffset = rpmdbGetIteratorOffset(mi); @@ -2555,6 +2986,7 @@ Trans_remove(trans, name) } } rpmdbFreeIterator(mi); + if (boa) *boa = '.'; RETVAL=count; OUTPUT: RETVAL @@ -2576,7 +3008,7 @@ Trans_traverse(trans, callback) pkg->flag = FLAG_ID_INVALID | FLAG_NO_HEADER_FREE; pkg->h = h; PUSHMARK(SP); - mXPUSHs(sv_setref_pv(newSVpvs(""), "URPM::Package", pkg)); + mXPUSHs(sv_setref_pv(newSVpv("", 0), "URPM::Package", pkg)); PUTBACK; call_sv(callback, G_DISCARD | G_SCALAR); SPAGAIN; @@ -2608,7 +3040,7 @@ Trans_check(trans, ...) if (gimme == G_SCALAR) mXPUSHs(newSViv(0)); else if (gimme == G_ARRAY) - mXPUSHs(newSVpvs("error while checking dependencies")); + mXPUSHs(newSVpv("error while checking dependencies", 0)); } else { rpmps ps = rpmtsProblems(trans->ts); if (rpmpsNumProblems(ps) > 0) { @@ -2639,7 +3071,7 @@ Trans_order(trans) if (gimme == G_SCALAR) mXPUSHs(newSViv(0)); else if (gimme == G_ARRAY) - mXPUSHs(newSVpvs("error while ordering dependencies")); + mXPUSHs(newSVpv("error while ordering dependencies", 0)); } int @@ -2654,22 +3086,39 @@ char * Trans_Element_name(trans, index) URPM::Transaction trans int index - ALIAS: - Element_version = 1 - Element_release = 2 - Element_fullname = 3 CODE: rpmte te = rpmtsElement(trans->ts, index); - if (te) { - switch (ix) { - case 1: RETVAL = (char *) rpmteV(te); break; - case 2: RETVAL = (char *) rpmteR(te); break; - case 3: RETVAL = (char *) rpmteNEVRA(te); break; - default: RETVAL = (char *) rpmteN(te); break; - } - } else { - RETVAL = NULL; - } + RETVAL = te ? (char *) rpmteN(te) : NULL; + OUTPUT: + RETVAL + +char * +Trans_Element_version(trans, index) + URPM::Transaction trans + int index + CODE: + rpmte te = rpmtsElement(trans->ts, index); + RETVAL = te ? (char *) rpmteV(te) : NULL; + OUTPUT: + RETVAL + +char * +Trans_Element_release(trans, index) + URPM::Transaction trans + int index + CODE: + rpmte te = rpmtsElement(trans->ts, index); + RETVAL = te ? (char *) rpmteR(te) : NULL; + OUTPUT: + RETVAL + +char * +Trans_Element_fullname(trans, index) + URPM::Transaction trans + int index + CODE: + rpmte te = rpmtsElement(trans->ts, index); + RETVAL = te ? (char *) rpmteNEVRA(te) : NULL; OUTPUT: RETVAL @@ -2746,7 +3195,11 @@ Trans_run(trans, data, ...) if (repa) free(repa); } rpmtsSetFlags(trans->ts, transFlags); +#ifdef RPM490 trans->ts = rpmtsLink(trans->ts); +#else + trans->ts = rpmtsLink(trans->ts, "URPM::Transaction::run"); +#endif rpmtsSetNotifyCallback(trans->ts, rpmRunTransactions_callback, &td); if (rpmtsRun(trans->ts, NULL, probFilter) > 0) { rpmps ps = rpmtsProblems(trans->ts); @@ -2776,15 +3229,22 @@ Urpm_read_config_files() OUTPUT: RETVAL +void +Urpm_list_rpm_tag(urpm=Nullsv) + SV *urpm + CODE: + croak("list_rpm_tag() has been removed from perl-URPM. please report if you need it back"); + int rpmvercmp(one, two) char *one char *two int -Urpm_ranges_overlap(a, b) +Urpm_ranges_overlap(a, b, b_nopromote=1) char *a char *b + int b_nopromote PREINIT: char *sa = a, *sb = b; int aflags = 0, bflags = 0; @@ -2814,7 +3274,7 @@ Urpm_ranges_overlap(a, b) else break; ++sb; } - RETVAL = ranges_overlap(aflags, sa, bflags, sb); + RETVAL = ranges_overlap(aflags, sa, bflags, sb, b_nopromote); } OUTPUT: RETVAL @@ -2834,13 +3294,12 @@ Urpm_parse_synthesis__XS(urpm, filename, ...) if (depslist != NULL) { char buff[65536]; - char *p, *eol, *t; + char *p, *eol; int buff_len; struct s_Package pkg; - FD_t f = NULL; + gzFile f; int start_id = 1 + av_len(depslist); SV *callback = NULL; - rpmCompressedMagic compressed = COMPRESSED_OTHER; if (items > 2) { int i; @@ -2854,35 +3313,19 @@ Urpm_parse_synthesis__XS(urpm, filename, ...) } PUTBACK; - int rc = rpmFileIsCompressed(filename, &compressed); - - switch (compressed) { - case COMPRESSED_BZIP2: t = "r.bzip2"; break; - case COMPRESSED_LZMA: - case COMPRESSED_XZ: - t = "r.xz"; break; - case COMPRESSED_OTHER: - default: - t = "r.gzip"; break; - } - f = Fopen(filename, "r.fdio"); - - if (!rc && (f = Fdopen(f, t)) != NULL && !Ferror(f)) { + if ((f = gzopen(filename, "rb")) != NULL) { memset(&pkg, 0, sizeof(struct s_Package)); buff[sizeof(buff)-1] = 0; p = buff; int ok = 1; - while ((buff_len = Fread(p, sizeof(buff)-1-(p-buff), 1, f)) >= 0 && + while ((buff_len = gzread(f, p, sizeof(buff)-1-(p-buff))) >= 0 && (buff_len += p-buff)) { buff[buff_len] = 0; p = buff; if ((eol = strchr(p, '\n')) != NULL) { do { *eol++ = 0; - if (!parse_line(depslist, provides, obsoletes, &pkg, p, urpm, callback)) { - ok = 0; - break; - } + if (!parse_line(depslist, provides, obsoletes, &pkg, p, urpm, callback)) { ok = 0; break; } p = eol; } while ((eol = strchr(p, '\n')) != NULL); } else { @@ -2891,15 +3334,17 @@ Urpm_parse_synthesis__XS(urpm, filename, ...) ok = 0; break; } + if (gzeof(f)) { + if (!parse_line(depslist, provides, obsoletes, &pkg, p, urpm, callback)) ok = 0; + break; + } else { /* move the remaining non-complete-line at beginning */ memmove(buff, p, buff_len-(p-buff)); /* point to the end of the non-complete-line */ p = &buff[buff_len-(p-buff)]; + } } - // EOF: - if (!parse_line(depslist, provides, obsoletes, &pkg, p, urpm, callback)) - ok = 0; - if (Fclose(f) != 0) ok = 0; + if (gzclose(f) != 0) ok = 0; SPAGAIN; if (ok) { mXPUSHs(newSViv(start_id)); @@ -2944,7 +3389,10 @@ Urpm_parse_hdlist__XS(urpm, filename, ...) int packing = 0; SV *callback = NULL; - if (items > 3) { + /* compability mode with older interface of parse_hdlist */ + if (items == 3) + packing = SvTRUE(ST(2)); + else if (items > 3) { int i; for (i = 2; i < items-1; i+=2) { STRLEN len; @@ -2961,13 +3409,14 @@ Urpm_parse_hdlist__XS(urpm, filename, ...) do { header = headerRead(fd, HEADER_MAGIC_YES); if (header != NULL) { - struct s_Package *_pkg; + struct s_Package pkg, *_pkg; SV *sv_pkg; - _pkg = calloc(1, sizeof(struct s_Package)); - _pkg->flag = 1 + av_len(depslist); - _pkg->h = header; - sv_pkg = sv_setref_pv(newSVpvs(""), "URPM::Package", _pkg); + memset(&pkg, 0, sizeof(struct s_Package)); + pkg.flag = 1 + av_len(depslist); + pkg.h = header; + sv_pkg = sv_setref_pv(newSVpv("", 0), "URPM::Package", + _pkg = memcpy(malloc(sizeof(struct s_Package)), &pkg, sizeof(struct s_Package))); if (call_package_callback(urpm, sv_pkg, callback)) { if (provides) { update_provides(_pkg, provides); @@ -3011,14 +3460,17 @@ Urpm_parse_rpm(urpm, filename, ...) HV *obsoletes = fobsoletes && SvROK(*fobsoletes) && SvTYPE(SvRV(*fobsoletes)) == SVt_PVHV ? (HV*)SvRV(*fobsoletes) : NULL; if (depslist != NULL) { - struct s_Package *_pkg; + struct s_Package pkg, *_pkg; SV *sv_pkg; int packing = 0; int keep_all_tags = 0; SV *callback = NULL; rpmVSFlags vsflags = RPMVSF_DEFAULT; - if (items > 3) { + /* compability mode with older interface of parse_hdlist */ + if (items == 3) + packing = SvTRUE(ST(2)); + else if (items > 3) { int i; for (i = 2; i < items-1; i+=2) { STRLEN len; @@ -3052,11 +3504,12 @@ Urpm_parse_rpm(urpm, filename, ...) } } PUTBACK; - _pkg = calloc(1, sizeof(struct s_Package)); - _pkg->flag = 1 + av_len(depslist); + memset(&pkg, 0, sizeof(struct s_Package)); + pkg.flag = 1 + av_len(depslist); + _pkg = memcpy(malloc(sizeof(struct s_Package)), &pkg, sizeof(struct s_Package)); if (update_header(filename, _pkg, keep_all_tags, vsflags)) { - sv_pkg = sv_setref_pv(newSVpvs(""), "URPM::Package", _pkg); + sv_pkg = sv_setref_pv(newSVpv("", 0), "URPM::Package", _pkg); if (call_package_callback(urpm, sv_pkg, callback)) { if (provides) { update_provides(_pkg, provides); @@ -3148,7 +3601,7 @@ Urpm_get_gpg_fingerprint(filename) char * -Urpm_verify_signature(filename, prefix=NULL) +Urpm_verify_signature(filename, prefix="/") char *filename char *prefix PREINIT: @@ -3213,7 +3666,11 @@ Urpm_import_pubkey_file(db, filename) size_t pktlen = 0; int rc; CODE: +#ifdef RPM490 rpmts ts = rpmtsLink(db->ts); +#else + rpmts ts = rpmtsLink(db->ts, "URPM::import_pubkey_file"); +#endif rpmtsClean(ts); if ((rc = pgpReadPkts(filename, (uint8_t ** ) &pkt, &pktlen)) <= 0) @@ -3230,17 +3687,44 @@ Urpm_import_pubkey_file(db, filename) RETVAL int -Urpm_archscore(param) - const char * param - ALIAS: - osscore = 1 +Urpm_import_pubkey(...) + CODE: + unused_variable(&items); + croak("import_pubkey() is dead. use import_pubkey_file() instead"); + RETVAL = 1; + OUTPUT: + RETVAL + +int +Urpm_archscore(arch) + const char * arch PREINIT: CODE: read_config_files(0); - RETVAL=rpmMachineScore(ix == 0 ? RPM_MACHTABLE_INSTARCH : RPM_MACHTABLE_INSTOS, param); + RETVAL=rpmMachineScore(RPM_MACHTABLE_INSTARCH, arch); OUTPUT: RETVAL +int +Urpm_osscore(os) + const char * os + PREINIT: + CODE: + read_config_files(0); + RETVAL=rpmMachineScore(RPM_MACHTABLE_INSTOS, os); + OUTPUT: + RETVAL + +int +Urpm_platformscore(platform) + const char * platform + CODE: + read_config_files(0); + unused_variable(platform); + croak("platformscore() is available only since rpm 4.4.8"); + RETVAL=0; + OUTPUT: + RETVAL void Urpm_stream2header(fp) @@ -3266,6 +3750,7 @@ void Urpm_spec2srcheader(specfile) char *specfile PREINIT: + rpmts ts = rpmtsCreate(); URPM__Package pkg; Spec spec = NULL; Header header = NULL; @@ -3273,33 +3758,65 @@ Urpm_spec2srcheader(specfile) /* ensure the config is in memory with all macro */ read_config_files(0); /* Do not verify architecture */ +#define SPEC_ANYARCH 1 /* Do not verify whether sources exist */ +#define SPEC_FORCE 1 +#ifdef RPM490 spec = rpmSpecParse(specfile, RPMSPEC_ANYARCH|RPMSPEC_FORCE, NULL); if (spec) { header = rpmSpecSourceHeader(spec); +#else + if (!parseSpec(ts, specfile, "/", NULL, 0, NULL, NULL, SPEC_ANYARCH, SPEC_FORCE)) { +#endif SV *sv_pkg; +#ifndef RPM490 + // FIXME: has disappeared in rpm-4.9.0rpmSpecParse + // (See http://www.rpm.org/wiki/Releases/4.9.0) + spec = rpmtsSetSpec(ts, NULL); + header = spec->sourceHeader; + if (! header) + initSourceHeader(spec); +#endif pkg = (URPM__Package)calloc(1, sizeof(struct s_Package)); headerPutString(header, RPMTAG_SOURCERPM, ""); + + { + struct rpmtd_s td = { + .tag = RPMTAG_ARCH, + .type = RPM_STRING_TYPE, + .data = (void *) "src", + .count = 1, + }; /* parseSpec() sets RPMTAG_ARCH to %{_target_cpu} whereas we really a header similar to .src.rpm header */ - headerPutString(header, RPMTAG_ARCH, "src"); + headerMod(header, &td); + } +#ifdef RPM490 pkg->h = headerLink(header); +#else + pkg->h = headerLink(spec->sourceHeader); +#endif sv_pkg = sv_newmortal(); sv_setref_pv(sv_pkg, "URPM::Package", (void*)pkg); XPUSHs(sv_pkg); +#ifdef RPM490 spec = rpmSpecFree(spec); +#else + spec = freeSpec(spec); +#endif } else { XPUSHs(&PL_sv_undef); - /* apparently rpmlib sets errno to this when given a bad spec. */ + /* apparently rpmlib sets errno this when given a bad spec. */ if (errno == EBADF) errno = 0; } + ts = rpmtsFree(ts); void expand(name) char * name PPCODE: const char * value = rpmExpand(name, NULL); - mXPUSHs(newSVpv(value, 0)); + XPUSHs(sv_2mortal(newSVpv(value, 0))); void add_macro_noexpand(macro) |