diff options
-rw-r--r-- | URPM.xs | 329 |
1 files changed, 170 insertions, 159 deletions
@@ -127,6 +127,25 @@ int rpmError_callback() { static int rpm_codeset_is_utf8 = 0; +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) + *char_backups[--BI].ptr = char_backups[BI].chr; +} + static SV* newSVpv_utf8(const char *s, STRLEN len) { @@ -135,31 +154,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 = '@'; - } -} - static char * get_name(Header header, int32_t tag) { struct rpmtd_s val; @@ -178,6 +172,58 @@ get_int(Header header, int32_t tag) { return ep ? *ep : 0; } +static int +get_fullname_parts(URPM__Package pkg, char **name, char **version, char **release, char **disttag, char **distepoch, char **arch, char **eos) { + char *_version = NULL, *_release = NULL, *_disttag = NULL, *_distepoch, *_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 ((_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 = get_name(pkg->h, RPMTAG_NAME); + if (version != NULL) *version = get_name(pkg->h, RPMTAG_VERSION); + if (release != NULL) *release = get_name(pkg->h, RPMTAG_RELEASE); + if (disttag != NULL) *disttag = get_name(pkg->h, RPMTAG_DISTTAG); + if (distepoch != NULL) *distepoch = get_name(pkg->h, RPMTAG_DISTEPOCH); + if (arch != NULL) *arch = headerIsEntry(pkg->h, RPMTAG_SOURCERPM) ? get_name(pkg->h, RPMTAG_ARCH) : "src"; + if (eos != NULL) *eos = NULL; + } + else + return 1; + return 0; +} + /* 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. */ @@ -644,40 +690,58 @@ return_list_tag(URPM__Package pkg, int32_t tag_name) { char *name; 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, &version, &release, &arch, &disttag, &distepoch, &eos)) + croak("invalid fullname"); + XPUSHs(sv_2mortal(newSVpv(name, 0))); } break; 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, &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, &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, &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, &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))); + get_fullname_parts(pkg, &name, &version, &release, &arch, &disttag, &distepoch, &eos); + XPUSHs(sv_2mortal(newSVpv(arch, 0))); } break; case RPMTAG_SUMMARY: XPUSHs(sv_2mortal(newSVpv(pkg->summary, 0))); break; } + restore_chars(); } PUTBACK; } @@ -1496,60 +1560,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)) + 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, &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, &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, &arch, NULL); + XPUSHs(sv_2mortal(newSVpv(arch, 0))); + restore_chars(); int Pkg_is_arch_compat__XS(pkg) @@ -1562,10 +1610,8 @@ 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, &arch, NULL); #ifndef RPM_ORG platform = rpmExpand(arch, "-%{_target_vendor}-%{_target_os}%{?_gnu}", NULL); RETVAL = rpmPlatformScore(platform, NULL, 0); @@ -1573,7 +1619,7 @@ Pkg_is_arch_compat__XS(pkg) #else RETVAL = rpmMachineScore(RPM_MACHTABLE_INSTARCH, arch); #endif - *eos = '@'; + restore_chars(); } else if (pkg->h && headerIsEntry(pkg->h, RPMTAG_SOURCERPM)) { char *arch = get_name(pkg->h, RPMTAG_ARCH); #ifndef RPM_ORG @@ -1609,11 +1655,11 @@ 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, &arch, &eos); platform = rpmExpand(arch, "-%{_target_vendor}-", eos, "%{?_gnu}", NULL); RETVAL = rpmPlatformScore(platform, NULL, 0); - *eos = '@'; + restore_chars(); _free(platform); } else { #else @@ -1746,39 +1792,38 @@ 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, &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) { - 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) { + } else if (pkg->h) { 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))); } } @@ -1821,51 +1866,34 @@ Pkg_compare_pkg(lpkg, rpkg) CODE: if (lpkg == rpkg) RETVAL = 0; else { + get_fullname_parts(lpkg, NULL, &lversion, &lrelease, &larch, NULL, NULL, &leos); 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 = '@'; + if ((s = strchr(leos, '@')) != NULL) { + backup_char(s); + lepoch = atoi(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"); + + get_fullname_parts(rpkg, NULL, &rversion, &rrelease, NULL, NULL, &rarch, &reos); 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 = '@'; + if ((s = strchr(reos, '@')) != NULL) { + backup_char(s); + repoch = atoi(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] = '-'; - larch[-1] = '.'; - } + restore_chars(); croak("undefined package"); } compare = lepoch - repoch; @@ -1875,12 +1903,10 @@ Pkg_compare_pkg(lpkg, rpkg) compare = rpmvercmp(lrelease, rrelease); if (!compare) { int lscore, rscore; - char *eolarch = strchr(larch, '@'); - char *eorarch = strchr(rarch, '@'); read_config_files(0); - if (eolarch) *eolarch = 0; lscore = rpmMachineScore(RPM_MACHTABLE_INSTARCH, larch); - if (eorarch) *eorarch = 0; rscore = rpmMachineScore(RPM_MACHTABLE_INSTARCH, rarch); + lscore = rpmMachineScore(RPM_MACHTABLE_INSTARCH, larch); + rscore = rpmMachineScore(RPM_MACHTABLE_INSTARCH, rarch); if (lscore == 0) { if (rscore == 0) #if 0 @@ -1897,20 +1923,11 @@ Pkg_compare_pkg(lpkg, rpkg) else compare = rscore - lscore; /* score are lower for better */ } - if (eolarch) *eolarch = '@'; - if (eorarch) *eorarch = '@'; } } } /* restore info string modified */ - if (lpkg->info) { - lrelease[-1] = '-'; - larch[-1] = '.'; - } - if (rpkg->info) { - rrelease[-1] = '-'; - rarch[-1] = '.'; - } + restore_chars(); RETVAL = compare; } OUTPUT: @@ -1925,22 +1942,19 @@ Pkg_compare(pkg, evr) int _epoch; char *_version; char *_release; + char *_arch; char *_eos; CODE: + get_fullname_parts(pkg, NULL, &_version, &_release, NULL, NULL, &_arch, &_eos); 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 = '@'; + if ((s = strchr(_eos, '@')) != NULL) { + backup_char(s); + _epoch = atoi(_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"); @@ -1981,10 +1995,7 @@ Pkg_compare(pkg, evr) } } /* restore info string modified */ - if (pkg->info) { - _release[-1] = '-'; - _eos[-1] = '.'; - } + restore_chars(); RETVAL = compare; OUTPUT: RETVAL |