From ce335e84938eeab479a88bf46478d082eff2de3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Per=20=C3=98yvind=20Karlsen?= Date: Tue, 12 Oct 2010 23:34:33 +0000 Subject: * add support for fetching disttag & distepoch with get_fullname_parts() * refactorize get_fullname_parts() and friends using it --- URPM.xs | 372 ++++++++++++++++++++++++++++++---------------------------------- 1 file changed, 173 insertions(+), 199 deletions(-) diff --git a/URPM.xs b/URPM.xs index 43b0e4a..87f687a 100644 --- a/URPM.xs +++ b/URPM.xs @@ -120,6 +120,25 @@ int rpmError_callback() { static int rpm_codeset_is_utf8 = 0; +static struct s_backup { + char *ptr; + char chr; +} char_backups[32]; + +static int BI = 0; + +static void +backup_char(char *c) { + char_backups[BI].chr = *c, + *(char_backups[BI++].ptr = &(*c)) = 0; /* mark end of string to enable searching backwards */ +} + +static void +restore_chars() { + for(; BI > 0; char_backups[BI].ptr = NULL) + BI--, *char_backups[BI].ptr = char_backups[BI].chr; +} + static SV* newSVpv_utf8(const char *s, STRLEN len) { @@ -128,31 +147,6 @@ newSVpv_utf8(const char *s, STRLEN len) return sv; } -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 ((_eos = strchr(pkg->info, '@')) != NULL) { - *_eos = 0; /* mark end of string to enable searching backwards */ - if ((_arch = strrchr(pkg->info, '.')) != NULL) { - *_arch = 0; - if ((release != NULL || version != NULL || name != NULL) && (_release = strrchr(pkg->info, '-')) != NULL) { - *_release = 0; - if ((version != NULL || name != NULL) && (_version = strrchr(pkg->info, '-')) != NULL) { - if (name != NULL) *name = pkg->info; - if (version != NULL) *version = _version + 1; - } - if (release != NULL) *release = _release + 1; - *_release = '-'; - } - if (arch != NULL) *arch = _arch + 1; - *_arch = '.'; - } - if (eos != NULL) *eos = _eos; - *_eos = '@'; - } -} - /* Since the NVRA format won't change, we'll store it in a global variable so * that we only have to expand the macro once. */ @@ -227,6 +221,60 @@ get_int(Header header, rpmTag tag) { return (val->t == RPM_UINT32_TYPE) ? val->p.ui32p[val->ix >= 0 ? val->ix : 0] : 0; } +static int +get_fullname_parts(URPM__Package pkg, char **name, int *epoch, char **version, char **release, char **disttag, char **distepoch, char **arch, char **eos) { + char *_version = NULL, *_release = NULL, *_disttag = NULL, *_distepoch = NULL, *_arch = NULL, *_eos = NULL, *tmp = NULL; + + if(pkg->info) { + if ((_eos = strchr(pkg->info, '@')) != NULL) { + backup_char(_eos); + if (eos != NULL) *eos = _eos+1; + if (epoch != NULL) *epoch = isdigit(_eos[1]) ? atoi(_eos+1) : 0; + if ((_arch = strrchr(pkg->info, '.')) != NULL) { + backup_char(_arch); + if (arch != NULL) *arch = _arch + 1; + if (distepoch != NULL || disttag != NULL || release != NULL || version != NULL || name != NULL) { + if((_distepoch = strchr(strrchr(pkg->provides, '-'), ':')) != NULL) { + tmp = strrchr(_distepoch+1, ']'); + backup_char(tmp); + tmp = strstr(pkg->info, _distepoch+1); + backup_char(tmp); + } + if(distepoch != NULL) *distepoch = _distepoch ? _distepoch+1 : NULL; + if (disttag != NULL || release != NULL || version != NULL || name != NULL) { + if ((_disttag = strrchr(pkg->info, '-')) != NULL && (strstr(pkg->provides, _disttag)) == NULL) { + backup_char(_disttag); + } else _disttag = NULL; + if (disttag != NULL) *disttag = _disttag ? _disttag + 1: NULL; + if ((release != NULL || version != NULL || name != NULL) && (_release = strrchr(pkg->info, '-')) != NULL) { + backup_char(_release); + if (release != NULL) *release = _release + 1; + if ((version != NULL || name != NULL) && (_version = strrchr(pkg->info, '-')) != NULL) { + backup_char(_version); + if (version != NULL) *version = _version + 1; + if (name != NULL) *name = pkg->info; + } + } + } + } + } + } + } + else if(pkg->h) { + if (name != NULL) *name = (char*)get_name(pkg->h, RPMTAG_NAME); + if (epoch != NULL) *epoch = get_int(pkg->h, RPMTAG_EPOCH); + if (version != NULL) *version = (char*)get_name(pkg->h, RPMTAG_VERSION); + if (release != NULL) *release = (char*)get_name(pkg->h, RPMTAG_RELEASE); + if (disttag != NULL) *disttag = (char*)get_name(pkg->h, RPMTAG_DISTTAG); + if (distepoch != NULL) *distepoch = (char*)get_name(pkg->h, RPMTAG_DISTEPOCH); + if (arch != NULL) *arch = headerIsEntry(pkg->h, RPMTAG_SOURCERPM) ? (char*)get_name(pkg->h, RPMTAG_ARCH) : "src"; + if (eos != NULL) *eos = NULL; + } + else + return 1; + return 0; +} + static int sigsize_to_filesize(int sigsize) { return sigsize + 440; /* 440 is the rpm header size (?) empirical, but works */ @@ -644,36 +692,61 @@ return_list_tag(URPM__Package pkg, rpmTag tag_name) { } } else { char *name; + int epoch; char *version; char *release; + char *disttag; + char *distepoch; + char *arch; char *eos; switch (tag_name) { case RPMTAG_NAME: { - get_fullname_parts(pkg, &name, &version, &release, &arch, &eos); - if (version - name < 1) croak("invalid fullname"); - XPUSHs(sv_2mortal(newSVpv(name, version-name - 1))); + if(get_fullname_parts(pkg, &name, &epoch, &version, &release, &arch, &disttag, &distepoch, &eos)) + croak("invalid fullname"); + XPUSHs(sv_2mortal(newSVpv(name, 0))); } break; + case RPMTAG_EPOCH: { + if(get_fullname_parts(pkg, &name, &epoch, &version, &release, &arch, &disttag, &distepoch, &eos)) + croak("invalid fullname"); + XPUSHs(sv_2mortal(newSViv(epoch))); + } case RPMTAG_VERSION: { - get_fullname_parts(pkg, &name, &version, &release, &arch, &eos); - if (release - version < 1) croak("invalid fullname"); - XPUSHs(sv_2mortal(newSVpv(version, release-version - 1))); + if(get_fullname_parts(pkg, &name, &epoch, &version, &release, &arch, &disttag, &distepoch, &eos)) + croak("invalid fullname"); + XPUSHs(sv_2mortal(newSVpv(version, 0))); } break; case RPMTAG_RELEASE: { - get_fullname_parts(pkg, &name, &version, &release, &arch, &eos); - if (arch - release < 1) croak("invalid fullname"); - XPUSHs(sv_2mortal(newSVpv(release, arch-release - 1))); + if(get_fullname_parts(pkg, &name, &epoch, &version, &release, &arch, &disttag, &distepoch, &eos)) + croak("invalid fullname"); + XPUSHs(sv_2mortal(newSVpv(release, 0))); + + } + break; + case RPMTAG_DISTTAG: + { + if(get_fullname_parts(pkg, &name, &epoch, &version, &release, &arch, &disttag, &distepoch, &eos)) + croak("invalid fullname"); + XPUSHs(sv_2mortal(newSVpv(disttag, 0))); + } + break; + case RPMTAG_DISTEPOCH: + { + if(get_fullname_parts(pkg, &name, &epoch, &version, &release, &arch, &disttag, &distepoch, &eos)) + croak("invalid fullname"); + XPUSHs(sv_2mortal(newSVpv(distepoch, 0))); } break; case RPMTAG_ARCH: { - get_fullname_parts(pkg, &name, &version, &release, &arch, &eos); - XPUSHs(sv_2mortal(newSVpv(arch, eos-arch))); + if(get_fullname_parts(pkg, &name, &epoch, &version, &release, &arch, &disttag, &distepoch, &eos)) + croak("invalid fullname"); + XPUSHs(sv_2mortal(newSVpv(arch, 0))); } break; case RPMTAG_SUMMARY: @@ -683,6 +756,7 @@ return_list_tag(URPM__Package pkg, rpmTag tag_name) { croak("unexpected tag"); break; } + restore_chars(); } PUTBACK; } @@ -1545,60 +1619,44 @@ void Pkg_name(pkg) URPM::Package pkg PPCODE: - if (pkg->info) { - char *name; - char *version; + char *name; - get_fullname_parts(pkg, &name, &version, NULL, NULL, NULL); - if (version - name < 1) croak("invalid fullname"); - XPUSHs(sv_2mortal(newSVpv(name, version-name-1))); - } else if (pkg->h) { - XPUSHs(sv_2mortal(newSVpv(get_name(pkg->h, RPMTAG_NAME), 0))); - } + if(get_fullname_parts(pkg, &name, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) + croak("invalid fullname"); + XPUSHs(sv_2mortal(newSVpv(name, 0))); + restore_chars(); void Pkg_version(pkg) URPM::Package pkg PPCODE: - if (pkg->info) { - char *version; - char *release; + char *version; - get_fullname_parts(pkg, NULL, &version, &release, NULL, NULL); - if (release - version < 1) croak("invalid fullname"); - XPUSHs(sv_2mortal(newSVpv(version, release-version-1))); - } else if (pkg->h) { - XPUSHs(sv_2mortal(newSVpv(get_name(pkg->h, RPMTAG_VERSION), 0))); - } + if(get_fullname_parts(pkg, NULL, NULL, &version, NULL, NULL, NULL, NULL, NULL)) + croak("invalid fullname"); + XPUSHs(sv_2mortal(newSVpv(version, 0))); + restore_chars(); void Pkg_release(pkg) URPM::Package pkg PPCODE: - if (pkg->info) { - char *release; - char *arch; + char *release; - get_fullname_parts(pkg, NULL, NULL, &release, &arch, NULL); - if (arch - release < 1) croak("invalid fullname"); - XPUSHs(sv_2mortal(newSVpv(release, arch-release-1))); - } else if (pkg->h) { - XPUSHs(sv_2mortal(newSVpv(get_name(pkg->h, RPMTAG_RELEASE), 0))); - } + if(get_fullname_parts(pkg, NULL, NULL, NULL, &release, NULL, NULL, NULL, NULL)) + croak("invalid fullname"); + XPUSHs(sv_2mortal(newSVpv(release, 0))); + restore_chars(); void Pkg_arch(pkg) URPM::Package pkg PPCODE: - if (pkg->info) { - char *arch; - char *eos; + char *arch; - get_fullname_parts(pkg, NULL, NULL, NULL, &arch, &eos); - XPUSHs(sv_2mortal(newSVpv(arch, eos-arch))); - } else if (pkg->h) { - XPUSHs(sv_2mortal(newSVpv(headerIsEntry(pkg->h, RPMTAG_SOURCERPM) ? get_name(pkg->h, RPMTAG_ARCH) : "src", 0))); - } + get_fullname_parts(pkg, NULL, NULL, NULL, NULL, NULL, NULL, &arch, NULL); + XPUSHs(sv_2mortal(newSVpv(arch, 0))); + restore_chars(); int Pkg_is_arch_compat__XS(pkg) @@ -1609,14 +1667,12 @@ Pkg_is_arch_compat__XS(pkg) read_config_files(0); if (pkg->info) { char *arch; - char *eos; - get_fullname_parts(pkg, NULL, NULL, NULL, &arch, &eos); - *eos = 0; + get_fullname_parts(pkg, NULL, NULL, NULL, NULL, NULL, NULL, &arch, NULL); platform = rpmExpand(arch, "-%{_target_vendor}-%{_target_os}%{?_gnu}", NULL); RETVAL = rpmPlatformScore(platform, NULL, 0); _free(platform); - *eos = '@'; + restore_chars(); } else if (pkg->h && headerIsEntry(pkg->h, RPMTAG_SOURCERPM)) { const char *arch = get_name(pkg->h, RPMTAG_ARCH); platform = rpmExpand(arch, "-%{_target_vendor}-%{_target_os}%{?_gnu}", NULL); @@ -1647,11 +1703,10 @@ Pkg_is_platform_compat(pkg) char *arch; char *eos; - get_fullname_parts(pkg, NULL, NULL, NULL, &arch, &eos); - *eos = 0; + get_fullname_parts(pkg, NULL, NULL, NULL, NULL, NULL, NULL, &arch, &eos); platform = rpmExpand(arch, "-%{_target_vendor}-", eos, "%{?_gnu}", NULL); RETVAL = rpmPlatformScore(platform, NULL, 0); - *eos = '@'; + restore_chars(); _free(platform); } else { RETVAL = 0; @@ -1780,57 +1835,50 @@ Pkg_fullname(pkg) PREINIT: I32 gimme = GIMME_V; PPCODE: - if (pkg->info) { - if (gimme == G_SCALAR) { + if (gimme == G_ARRAY) { + char *name, *version, *release, *disttag, *distepoch, *arch, *eos; + int items = 4; + + if(get_fullname_parts(pkg, &name, NULL, &version, &release, &disttag, &distepoch, &arch, &eos)) + croak("invalid fullname"); + + /* XXX: This might result in the number of items and the order which returned + * being unexpected in the case of disttag/disttag being present. + */ + if(disttag != NULL) items++; + if(distepoch != NULL) items++; + + EXTEND(SP, items); + PUSHs(sv_2mortal(newSVpv(name, 0))); + PUSHs(sv_2mortal(newSVpv(version, 0))); + PUSHs(sv_2mortal(newSVpv(release, 0))); + if(disttag != NULL) + PUSHs(sv_2mortal(newSVpv(disttag, 0))); + if(distepoch != NULL) + PUSHs(sv_2mortal(newSVpv(distepoch, 0))); + PUSHs(sv_2mortal(newSVpv(arch, 0))); + restore_chars(); + } else if (gimme == G_SCALAR) { + if (pkg->info) { char *eos; - if ((eos = strchr(pkg->info, '@')) != NULL) { + if ((eos = strchr(pkg->info, '@')) != NULL) XPUSHs(sv_2mortal(newSVpv(pkg->info, eos-pkg->info))); - } - } else if (gimme == G_ARRAY) { - char *name, *version, *release, *arch, *eos; - get_fullname_parts(pkg, &name, &version, &release, &arch, &eos); - if (version - name < 1 || release - version < 1 || arch - release < 1) - croak("invalid fullname"); - EXTEND(SP, 4); - 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) { - const char *name = get_name(pkg->h, RPMTAG_NAME); - const char *version = get_name(pkg->h, RPMTAG_VERSION); - const char *release = get_name(pkg->h, RPMTAG_RELEASE); - const char *arch = headerIsEntry(pkg->h, RPMTAG_SOURCERPM) ? get_name(pkg->h, RPMTAG_ARCH) : "src"; - - if (gimme == G_SCALAR) { + } else if (pkg->h) { const char *nvra = get_nvra(pkg->h); XPUSHs(sv_2mortal(newSVpvf("%s", nvra))); _free(nvra); - } else if (gimme == G_ARRAY) { - EXTEND(SP, 4); - PUSHs(sv_2mortal(newSVpv(name, 0))); - PUSHs(sv_2mortal(newSVpv(version, 0))); - PUSHs(sv_2mortal(newSVpv(release, 0))); - PUSHs(sv_2mortal(newSVpv(arch, 0))); } } int Pkg_epoch(pkg) URPM::Package pkg + PREINIT: + int epoch; CODE: - if (pkg->info) { - char *s; - - if ((s = strchr(pkg->info, '@')) != NULL) { - RETVAL = strtoul(s+1, NULL, 10); - } else { - RETVAL = 0; - } - } else if (pkg->h) { - RETVAL = get_int(pkg->h, RPMTAG_EPOCH); - } else RETVAL = 0; + get_fullname_parts(pkg, NULL, &epoch, NULL, NULL, NULL, NULL, NULL, NULL); + restore_chars(); + RETVAL = epoch; OUTPUT: RETVAL @@ -1843,63 +1891,20 @@ Pkg_compare_pkg(lpkg, rpkg) int lepoch; char *lversion; char *lrelease; + char *ldistepoch; char *larch; char *leos; int repoch; char *rversion; char *rrelease; + char *rdistepoch; char *rarch; char *reos; CODE: if (lpkg == rpkg) RETVAL = 0; else { - 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 = (char*)get_name(lpkg->h, RPMTAG_VERSION); - lrelease = (char*)get_name(lpkg->h, RPMTAG_RELEASE); - larch = headerIsEntry(lpkg->h, RPMTAG_SOURCERPM) ? (char*)get_name(lpkg->h, RPMTAG_ARCH) : "src"; - } else croak("undefined package"); - if (rpkg->info) { - char *s; - - 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 = (char*)get_name(rpkg->h, RPMTAG_VERSION); - rrelease = (char*)get_name(rpkg->h, RPMTAG_RELEASE); - rarch = headerIsEntry(rpkg->h, RPMTAG_SOURCERPM) ? (char*)get_name(rpkg->h, RPMTAG_ARCH) : "src"; - } else { - /* restore info string modified */ - if (lpkg->info) { - lrelease[-1] = '-'; - larch[-1] = '.'; - } + if(get_fullname_parts(lpkg, NULL, &lepoch, &lversion, &lrelease, &ldistepoch, NULL, &larch, &leos) || get_fullname_parts(rpkg, NULL, &repoch, &rversion, &rrelease, &rdistepoch, NULL, &rarch, &reos)) croak("undefined package"); - } compare = lepoch - repoch; if (!compare) { compare = rpmvercmp(lversion, rversion); @@ -1945,15 +1950,7 @@ Pkg_compare_pkg(lpkg, rpkg) } } } - /* restore info string modified */ - if (lpkg->info) { - lrelease[-1] = '-'; - larch[-1] = '.'; - } - if (rpkg->info) { - rrelease[-1] = '-'; - rarch[-1] = '.'; - } + restore_chars(); RETVAL = compare; } OUTPUT: @@ -1968,25 +1965,11 @@ Pkg_compare(pkg, evr) int _epoch; char *_version; char *_release; + char *_distepoch; char *_eos; CODE: - if (pkg->info) { - char *s; - - 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(get_fullname_parts(pkg, NULL, &_epoch, &_version, &_release, &_distepoch, NULL, NULL, &_eos)) + croak("undefined package"); if (!compare) { char *epoch, *version, *release; @@ -1998,36 +1981,27 @@ Pkg_compare(pkg, 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 = (char*)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 = (char*)get_name(pkg->h, RPMTAG_RELEASE); compare = rpmvercmp(_release, release); } - release[-1] = '-'; /* restore in memory modification */ } else { compare = rpmvercmp(_version, version); } } } /* restore info string modified */ - if (pkg->info) { - _release[-1] = '-'; - _eos[-1] = '.'; - } + restore_chars(); RETVAL = compare; OUTPUT: RETVAL -- cgit v1.2.1