| /* |
| * Host Resources MIB - Installed Software group implementation - hr_swinst.c |
| * |
| */ |
| |
| #include <net-snmp/net-snmp-config.h> |
| #include <net-snmp/net-snmp-features.h> |
| |
| #if HAVE_SYS_PARAM_H |
| #include <sys/param.h> |
| #endif |
| #include <sys/stat.h> |
| #if TIME_WITH_SYS_TIME |
| # include <sys/time.h> |
| # include <time.h> |
| #else |
| # if HAVE_SYS_TIME_H |
| # include <sys/time.h> |
| # else |
| # include <time.h> |
| # endif |
| #endif |
| #if HAVE_DIRENT_H |
| #include <dirent.h> |
| #else |
| # define dirent direct |
| # if HAVE_SYS_NDIR_H |
| # include <sys/ndir.h> |
| # endif |
| # if HAVE_SYS_DIR_H |
| # include <sys/dir.h> |
| # endif |
| # if HAVE_NDIR_H |
| # include <ndir.h> |
| # endif |
| #endif |
| #ifdef HAVE_PKGLOCS_H |
| #include <pkglocs.h> |
| #endif |
| #ifdef HAVE_PKGINFO_H |
| #include <pkginfo.h> |
| #endif |
| |
| #ifdef HAVE_LIBRPM |
| #include <rpm/rpmlib.h> |
| #include <rpm/header.h> |
| #include <fcntl.h> |
| |
| #ifdef HAVE_RPM_RPMFILEUTIL_H |
| #include <rpm/rpmfileutil.h> |
| #endif |
| |
| #ifdef HAVE_RPMGETPATH |
| #include <rpm/rpmmacro.h> |
| #endif |
| |
| #ifdef HAVE_RPM_RPMTS_H |
| #include <rpm/rpmts.h> |
| #include <rpm/rpmdb.h> |
| #endif |
| #endif |
| |
| #if HAVE_STRING_H |
| #include <string.h> |
| #else |
| #include <strings.h> |
| #endif |
| |
| #include "host_res.h" |
| #include "hr_swinst.h" |
| #include <net-snmp/utilities.h> |
| |
| #define HRSWINST_MONOTONICALLY_INCREASING |
| |
| netsnmp_feature_require(date_n_time) |
| |
| /********************* |
| * |
| * Kernel & interface information, |
| * and internal forward declarations |
| * |
| *********************/ |
| |
| /* |
| * Reorganize the global data into a single static structure. |
| * |
| * Old New |
| *====================================================== |
| * HRSW_directory swi->swi_directory |
| * HRSW_name[100] swi->swi_name[SNMP_MAXPATH] |
| * HRSW_index swi->swi_index |
| * |
| * swi->swi_dbpath (RPM only) |
| * swi->swi_maxrec (RPM only) |
| * swi->swi_nrec (RPM only) |
| * swi->swi_recs (RPM only) |
| * rpm_db swi->swi_rpmdb (RPM only) |
| * swi->swi_h (RPM only) |
| * swi->swi_prevx (RPM only) |
| * |
| * dp swi->swi_dp |
| * de_p swi->swi_dep |
| */ |
| typedef struct { |
| #if HAVE_LIBRPM |
| char *swi_directory; |
| #else |
| const char *swi_directory; |
| #endif |
| char swi_name[SNMP_MAXPATH]; /* XXX longest file name */ |
| int swi_index; |
| |
| #if HAVE_LIBRPM |
| const char *swi_dbpath; |
| |
| time_t swi_timestamp; /* modify time on database */ |
| int swi_maxrec; /* no. of allocations */ |
| int swi_nrec; /* no. of valid offsets */ |
| int *swi_recs; /* db record offsets */ |
| rpmts swi_rpmts; |
| Header swi_h; |
| int swi_prevx; |
| #else |
| DIR *swi_dp; |
| struct dirent *swi_dep; |
| #endif |
| |
| } SWI_t; |
| |
| static SWI_t _myswi = { NULL, "", 0 }; /* XXX static for now */ |
| |
| int header_hrswinst(struct variable *, oid *, size_t *, int, |
| size_t *, WriteMethod **); |
| int header_hrswInstEntry(struct variable *, oid *, size_t *, |
| int, size_t *, WriteMethod **); |
| |
| #define starttime (*(const struct timeval*)netsnmp_get_agent_starttime()) |
| |
| /********************* |
| * |
| * Initialisation & common implementation functions |
| * |
| *********************/ |
| extern void Init_HR_SWInst(void); |
| extern int Get_Next_HR_SWInst(void); |
| extern void End_HR_SWInst(void); |
| extern int Save_HR_SW_info(int ix); |
| |
| #ifdef HAVE_LIBRPM |
| static void Mark_HRSW_token(void); |
| static void Release_HRSW_token(void); |
| #else |
| #define Mark_HRSW_token() |
| #define Release_HRSW_token() |
| #endif |
| |
| |
| #define HRSWINST_CHANGE 1 |
| #define HRSWINST_UPDATE 2 |
| #define HRSWINST_INDEX 3 |
| #define HRSWINST_NAME 4 |
| #define HRSWINST_ID 5 |
| #define HRSWINST_TYPE 6 |
| #define HRSWINST_DATE 7 |
| |
| struct variable4 hrswinst_variables[] = { |
| {HRSWINST_CHANGE, ASN_TIMETICKS, NETSNMP_OLDAPI_RONLY, |
| var_hrswinst, 1, {1}}, |
| {HRSWINST_UPDATE, ASN_TIMETICKS, NETSNMP_OLDAPI_RONLY, |
| var_hrswinst, 1, {2}}, |
| {HRSWINST_INDEX, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, |
| var_hrswinst, 3, {3, 1, 1}}, |
| {HRSWINST_NAME, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY, |
| var_hrswinst, 3, {3, 1, 2}}, |
| {HRSWINST_ID, ASN_OBJECT_ID, NETSNMP_OLDAPI_RONLY, |
| var_hrswinst, 3, {3, 1, 3}}, |
| {HRSWINST_TYPE, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, |
| var_hrswinst, 3, {3, 1, 4}}, |
| {HRSWINST_DATE, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY, |
| var_hrswinst, 3, {3, 1, 5}} |
| }; |
| oid hrswinst_variables_oid[] = { 1, 3, 6, 1, 2, 1, 25, 6 }; |
| |
| |
| #ifdef PKGLOC /* Description from HRSW_dir/.../pkginfo: DESC= */ |
| #define _PATH_HRSW_directory PKGLOC |
| #endif |
| #ifdef hpux9 /* Description from HRSW_dir/.../index: fd: */ |
| #define _PATH_HRSW_directory "/system" |
| #endif |
| #ifdef hpux10 /* Description from HRSW_dir/.../pfiles/INDEX: title */ |
| #define _PATH_HRSW_directory "/var/adm/sw/products" |
| #endif |
| #ifdef hpux11 /* Description from HRSW_dir/.../pfiles/INDEX: title */ |
| #define _PATH_HRSW_directory "/var/adm/sw/products" |
| #endif |
| #ifdef freebsd2 |
| #define _PATH_HRSW_directory "/var/db/pkg" |
| #endif |
| #if defined(linux) && !defined(HAVE_LIBRPM) |
| #define _PATH_HRSW_directory "/var/cache/hrmib" |
| #endif |
| |
| void |
| init_hr_swinst(void) |
| { |
| #if defined(HAVE_LIBRPM) || defined(_PATH_HRSW_directory) |
| SWI_t *swi = &_myswi; /* XXX static for now */ |
| #endif |
| #ifdef HAVE_LIBRPM |
| struct stat stat_buf; |
| #endif |
| |
| /* |
| * Read settings from config file, |
| * or take system-specific defaults |
| */ |
| |
| #ifdef HAVE_LIBRPM |
| if (swi->swi_directory == NULL) { |
| char path[SNMP_MAXPATH]; |
| |
| /* |
| * XXX distinguish between rpm-2.5.x and rpm-2.9x |
| */ |
| #ifdef HAVE_RPMGETPATH |
| rpmReadConfigFiles(NULL, NULL); |
| swi->swi_dbpath = rpmGetPath("%{_dbpath}", NULL); |
| #else |
| swi->swi_dbpath = "/var/lib/rpm"; /* Most likely */ |
| #endif |
| if (swi->swi_directory != NULL) |
| free(swi->swi_directory); |
| snprintf(path, sizeof(path), "%s/Packages", swi->swi_dbpath); |
| if (stat(path, &stat_buf) == -1) |
| snprintf(path, sizeof(path), "%s/packages.rpm", swi->swi_dbpath); |
| path[ sizeof(path)-1 ] = 0; |
| swi->swi_directory = strdup(path); |
| } |
| #else |
| # ifdef _PATH_HRSW_directory |
| if (swi->swi_directory == NULL) { |
| swi->swi_directory = _PATH_HRSW_directory; |
| } |
| strcpy(swi->swi_name, "[installed name]"); /* default name */ |
| # else |
| /* |
| * XXX SunOS4 package directory is ?? -MJS |
| */ |
| return; /* packages not known - don't register */ |
| # endif |
| #endif |
| |
| REGISTER_MIB("host/hr_swinst", hrswinst_variables, variable4, |
| hrswinst_variables_oid); |
| } |
| |
| /* |
| * header_hrswinst(... |
| * Arguments: |
| * vp IN - pointer to variable entry that points here |
| * name IN/OUT - IN/name requested, OUT/name found |
| * length IN/OUT - length of IN/OUT oid's |
| * exact IN - TRUE if an exact match was requested |
| * var_len OUT - length of variable or 0 if function returned |
| * write_method |
| */ |
| |
| int |
| header_hrswinst(struct variable *vp, |
| oid * name, |
| size_t * length, |
| int exact, size_t * var_len, WriteMethod ** write_method) |
| { |
| #define HRSWINST_NAME_LENGTH 9 |
| oid newname[MAX_OID_LEN]; |
| int result; |
| |
| DEBUGMSGTL(("host/hr_swinst", "var_hrswinst: ")); |
| DEBUGMSGOID(("host/hr_swinst", name, *length)); |
| DEBUGMSG(("host/hr_swinst", " %d\n", exact)); |
| |
| memcpy((char *) newname, (char *) vp->name, vp->namelen * sizeof(oid)); |
| newname[HRSWINST_NAME_LENGTH] = 0; |
| result = snmp_oid_compare(name, *length, newname, vp->namelen + 1); |
| if ((exact && (result != 0)) || (!exact && (result >= 0))) |
| return (MATCH_FAILED); |
| memcpy((char *) name, (char *) newname, |
| (vp->namelen + 1) * sizeof(oid)); |
| *length = vp->namelen + 1; |
| |
| *write_method = (WriteMethod*)0; |
| *var_len = sizeof(long); /* default to 'long' results */ |
| return (MATCH_SUCCEEDED); |
| } |
| |
| int |
| header_hrswInstEntry(struct variable *vp, |
| oid * name, |
| size_t * length, |
| int exact, |
| size_t * var_len, WriteMethod ** write_method) |
| { |
| #define HRSWINST_ENTRY_NAME_LENGTH 11 |
| oid newname[MAX_OID_LEN]; |
| int swinst_idx, LowIndex = -1; |
| int result; |
| int err = 0, errcount = 0; |
| |
| DEBUGMSGTL(("host/hr_swinst", "var_hrswinstEntry: ")); |
| DEBUGMSGOID(("host/hr_swinst", name, *length)); |
| DEBUGMSG(("host/hr_swinst", " %d\n", exact)); |
| |
| memcpy((char *) newname, (char *) vp->name, vp->namelen * sizeof(oid)); |
| /* |
| * Find "next" installed software entry |
| */ |
| |
| do { |
| Init_HR_SWInst(); |
| while ((swinst_idx = Get_Next_HR_SWInst()) != -1) { |
| DEBUGMSG(("host/hr_swinst", "(index %d ....", swinst_idx)); |
| |
| newname[HRSWINST_ENTRY_NAME_LENGTH] = swinst_idx; |
| DEBUGMSGOID(("host/hr_swinst", newname, *length)); |
| DEBUGMSG(("host/hr_swinst", "\n")); |
| result = snmp_oid_compare(name, *length, newname, vp->namelen + 1); |
| if (exact && (result == 0)) { |
| LowIndex = swinst_idx; |
| err = Save_HR_SW_info(LowIndex); |
| break; |
| } |
| if ((!exact && (result < 0)) && |
| (LowIndex == -1 || swinst_idx < LowIndex)) { |
| LowIndex = swinst_idx; |
| err = Save_HR_SW_info(LowIndex); |
| #ifdef HRSWINST_MONOTONICALLY_INCREASING |
| break; |
| #endif |
| } |
| } |
| if (err != 0 ) |
| errcount++; |
| /* restart until Save_HR_SW_info() succeeds,max. 3 times */ |
| } while (err != 0 && errcount < 3); |
| if (err != 0) { |
| DEBUGMSGTL(("host/hr_swinst", "restart did not help, bailing out\n")); |
| return (MATCH_FAILED); |
| } |
| |
| Mark_HRSW_token(); |
| End_HR_SWInst(); |
| |
| if (LowIndex == -1) { |
| DEBUGMSGTL(("host/hr_swinst", "... index out of range\n")); |
| return (MATCH_FAILED); |
| } |
| |
| memcpy((char *) name, (char *) newname, |
| (vp->namelen + 1) * sizeof(oid)); |
| *length = vp->namelen + 1; |
| *write_method = (WriteMethod*)0; |
| *var_len = sizeof(long); /* default to 'long' results */ |
| |
| DEBUGMSGTL(("host/hr_inst", "... get installed S/W stats ")); |
| DEBUGMSGOID(("host/hr_inst", name, *length)); |
| DEBUGMSG(("host/hr_inst", "\n")); |
| return LowIndex; |
| } |
| |
| /********************* |
| * |
| * System specific implementation functions |
| * |
| *********************/ |
| |
| |
| u_char * |
| var_hrswinst(struct variable * vp, |
| oid * name, |
| size_t * length, |
| int exact, size_t * var_len, WriteMethod ** write_method) |
| { |
| SWI_t *swi = &_myswi; /* XXX static for now */ |
| int sw_idx = 0; |
| static char string[SNMP_MAXPATH]; |
| u_char *ret = NULL; |
| struct stat stat_buf; |
| |
| if (vp->magic < HRSWINST_INDEX) { |
| if (header_hrswinst(vp, name, length, exact, var_len, write_method) |
| == MATCH_FAILED) |
| return NULL; |
| } else { |
| |
| sw_idx = |
| header_hrswInstEntry(vp, name, length, exact, var_len, |
| write_method); |
| if (sw_idx == MATCH_FAILED) |
| return NULL; |
| } |
| |
| switch (vp->magic) { |
| case HRSWINST_CHANGE: |
| case HRSWINST_UPDATE: |
| string[0] = '\0'; |
| |
| if (swi->swi_directory != NULL) |
| strlcpy(string, swi->swi_directory, sizeof(string)); |
| |
| if (*string && (stat(string, &stat_buf) != -1)) { |
| if (stat_buf.st_mtime > starttime.tv_sec) |
| /* |
| * changed 'recently' - i.e. since this agent started |
| */ |
| long_return = (stat_buf.st_mtime - starttime.tv_sec) * 100; |
| else |
| long_return = 0; /* predates this agent */ |
| } else |
| #if NETSNMP_NO_DUMMY_VALUES |
| return NULL; |
| #else |
| long_return = 363136200; |
| #endif |
| ret = (u_char *) & long_return; |
| break; |
| |
| case HRSWINST_INDEX: |
| long_return = sw_idx; |
| ret = (u_char *) & long_return; |
| break; |
| case HRSWINST_NAME: |
| { |
| #ifdef HAVE_PKGINFO |
| char *pver; |
| # endif |
| strlcpy(string, swi->swi_name, sizeof(string)); |
| |
| /* If we are on a solaris machine, the package names do not include versioning info, |
| * so we must add it manually |
| */ |
| #ifdef HAVE_PKGINFO |
| pver = pkgparam(swi->swi_name, "VERSION"); |
| /* 1 spot for the terminating null and one for the dash */ |
| if (pver && |
| (strlen(pver) + 2 + strlen(string) <= sizeof(string))) { |
| strcat(string, "-"); |
| strcat(string, pver); |
| } |
| # endif |
| |
| /* |
| * This will be unchanged from the initial "null" |
| * value, if swi->swi_name is not defined |
| */ |
| string[sizeof(string) - 1] = '\0'; |
| *var_len = strlen(string); |
| ret = (u_char *) string; |
| } |
| break; |
| case HRSWINST_ID: |
| *var_len = nullOidLen; |
| ret = (u_char *) nullOid; |
| break; |
| case HRSWINST_TYPE: |
| { |
| #ifdef HAVE_PKGINFO |
| /* |
| * at least on solaris2 this works |
| */ |
| char *catg = pkgparam(swi->swi_name, "CATEGORY"); |
| |
| if (catg == NULL) { |
| long_return = 1; /* unknown */ |
| } else { |
| if (strstr(catg, "system") != NULL) { |
| long_return = 2; /* operatingSystem */ |
| } else if (strstr(catg, "application") != NULL) { |
| long_return = 4; /* applcation */ |
| } else { |
| long_return = 1; /* unknown */ |
| } |
| free(catg); |
| } |
| #else |
| # ifdef HAVE_LIBRPM |
| char *rpm_groups; |
| if ( headerGetEntry(swi->swi_h, RPMTAG_GROUP, NULL, (void **) &rpm_groups, NULL) ) { |
| if ( strstr(rpm_groups, "System Environment") != NULL ) |
| long_return = 2; /* operatingSystem */ |
| else |
| long_return = 4; /* applcation */ |
| } else { |
| long_return = 1; /* unknown */ |
| } |
| # else |
| long_return = 1; /* unknown */ |
| # endif |
| #endif |
| ret = (u_char *) & long_return; |
| } |
| break; |
| case HRSWINST_DATE: |
| { |
| #ifdef HAVE_LIBRPM |
| int32_t *rpm_data; |
| if ( headerGetEntry(swi->swi_h, RPMTAG_INSTALLTIME, NULL, (void **) &rpm_data, NULL) ) { |
| time_t installTime = *rpm_data; |
| ret = date_n_time(&installTime, var_len); |
| } else { |
| ret = date_n_time(NULL, var_len); |
| } |
| #else |
| if (swi->swi_directory != NULL) { |
| snprintf(string, sizeof(string), "%s/%s", |
| swi->swi_directory, swi->swi_name); |
| string[ sizeof(string)-1 ] = 0; |
| if (stat(string, &stat_buf) >= 0) |
| ret = date_n_time(&stat_buf.st_mtime, var_len); |
| else |
| goto err; |
| } else { |
| err: |
| #if NETSNMP_NO_DUMMY_VALUES |
| ret = NULL; |
| #else |
| sprintf(string, "back in the mists of time"); |
| *var_len = strlen(string); |
| ret = (u_char *) string; |
| #endif |
| } |
| #endif |
| } |
| break; |
| default: |
| DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_hrswinst\n", |
| vp->magic)); |
| ret = NULL; |
| break; |
| } |
| Release_HRSW_token(); |
| return ret; |
| } |
| |
| |
| /********************* |
| * |
| * Internal implementation functions |
| * |
| *********************/ |
| |
| #ifdef HAVE_LIBRPM |
| static void |
| Check_HRSW_cache(void *xxx) |
| { |
| SWI_t *swi = (SWI_t *) xxx; |
| |
| /* |
| * Make sure cache is up-to-date |
| */ |
| if (swi->swi_recs != NULL) { |
| struct stat sb; |
| lstat(swi->swi_directory, &sb); |
| if (swi->swi_timestamp == sb.st_mtime) |
| return; |
| swi->swi_timestamp = sb.st_mtime; |
| swi->swi_maxrec = 0; |
| } |
| |
| /* |
| * Get header offsets |
| */ |
| { |
| int ix = 0; |
| int offset; |
| |
| rpmdbMatchIterator mi = NULL; |
| Header h; |
| mi = rpmtsInitIterator(swi->swi_rpmts, RPMDBI_PACKAGES, NULL, 0); |
| while ((h = rpmdbNextIterator(mi)) != NULL) { |
| offset = rpmdbGetIteratorOffset(mi); |
| |
| if (ix >= swi->swi_maxrec) { |
| swi->swi_maxrec += 256; |
| swi->swi_recs = (swi->swi_recs == NULL) |
| ? (int *) malloc(swi->swi_maxrec * sizeof(int)) |
| : (int *) realloc(swi->swi_recs, |
| swi->swi_maxrec * sizeof(int)); |
| } |
| swi->swi_recs[ix++] = offset; |
| } |
| rpmdbFreeIterator(mi); |
| |
| swi->swi_nrec = ix; |
| } |
| } |
| #endif /* HAVE_LIBRPM */ |
| |
| void |
| Init_HR_SWInst(void) |
| { |
| SWI_t *swi = &_myswi; /* XXX static for now */ |
| swi->swi_index = 0; |
| |
| #ifdef HAVE_LIBRPM |
| if (swi->swi_rpmts != NULL) |
| return; |
| swi->swi_rpmts = rpmtsCreate(); |
| rpmtsSetVSFlags( swi->swi_rpmts, (_RPMVSF_NOSIGNATURES|_RPMVSF_NODIGESTS)); |
| Check_HRSW_cache(swi); |
| #else |
| if (swi->swi_directory != NULL) { |
| if (swi->swi_dp != NULL) { |
| closedir(swi->swi_dp); |
| swi->swi_dp = NULL; |
| } |
| if ((swi->swi_dp = opendir(swi->swi_directory)) == NULL) |
| swi->swi_index = -1; |
| } else |
| swi->swi_index = -1; |
| #endif |
| } |
| |
| int |
| Get_Next_HR_SWInst(void) |
| { |
| SWI_t *swi = &_myswi; /* XXX static for now */ |
| |
| if (swi->swi_index == -1) |
| return -1; |
| |
| #ifdef HAVE_LIBRPM |
| /* |
| * XXX Watchout: index starts with 1 |
| */ |
| if (0 <= swi->swi_index && swi->swi_index < swi->swi_nrec) |
| return ++swi->swi_index; |
| #else |
| if (swi->swi_directory != NULL) { |
| while ((swi->swi_dep = readdir(swi->swi_dp)) != NULL) { |
| if (swi->swi_dep->d_name[0] == '.') |
| continue; |
| |
| /* |
| * Ought to check for "properly-formed" entry |
| */ |
| |
| return ++swi->swi_index; |
| } |
| } |
| #endif |
| |
| return -1; |
| } |
| |
| int |
| Save_HR_SW_info(int ix) |
| { |
| SWI_t *swi = &_myswi; /* XXX static for now */ |
| |
| #ifdef HAVE_LIBRPM |
| /* |
| * XXX Watchout: ix starts with 1 |
| */ |
| if (1 <= ix && ix <= swi->swi_nrec && ix != swi->swi_prevx) { |
| int offset; |
| Header h; |
| char *n, *v, *r; |
| |
| offset = swi->swi_recs[ix - 1]; |
| |
| { |
| rpmdbMatchIterator mi; |
| mi = rpmtsInitIterator(swi->swi_rpmts, RPMDBI_PACKAGES, |
| &offset, sizeof(offset)); |
| if ((h = rpmdbNextIterator(mi)) != NULL) |
| h = headerLink(h); |
| rpmdbFreeIterator(mi); |
| } |
| |
| if (h == NULL) { |
| DEBUGMSGTL(("host/hr_swinst", |
| "RPM cache has probably expired when reading entry %d, " |
| "reloading...\n", ix)); |
| swi->swi_timestamp = 0; |
| return -1; |
| } |
| if (swi->swi_h != NULL) |
| headerFree(swi->swi_h); |
| swi->swi_h = h; |
| swi->swi_prevx = ix; |
| |
| headerGetEntry(swi->swi_h, RPMTAG_NAME, NULL, (void **) &n, NULL); |
| headerGetEntry(swi->swi_h, RPMTAG_VERSION, NULL, (void **) &v, |
| NULL); |
| headerGetEntry(swi->swi_h, RPMTAG_RELEASE, NULL, (void **) &r, |
| NULL); |
| snprintf(swi->swi_name, sizeof(swi->swi_name), "%s-%s-%s", n, v, r); |
| swi->swi_name[ sizeof(swi->swi_name)-1 ] = 0; |
| } |
| #else |
| snprintf(swi->swi_name, sizeof(swi->swi_name), "%s", swi->swi_dep->d_name); |
| swi->swi_name[ sizeof(swi->swi_name)-1 ] = 0; |
| #endif |
| return 0; |
| } |
| |
| #ifdef HAVE_LIBRPM |
| void |
| Mark_HRSW_token(void) |
| { |
| } |
| |
| void |
| Release_HRSW_token(void) |
| { |
| SWI_t *swi = &_myswi; /* XXX static for now */ |
| if (swi != NULL && swi->swi_h) { |
| headerFree(swi->swi_h); |
| swi->swi_h = NULL; |
| swi->swi_prevx = -1; |
| } |
| } |
| #endif /* HAVE_LIBRPM */ |
| |
| void |
| End_HR_SWInst(void) |
| { |
| SWI_t *swi = &_myswi; /* XXX static for now */ |
| |
| #ifdef HAVE_LIBRPM |
| rpmtsFree(swi->swi_rpmts); /* or only on finishing ? */ |
| swi->swi_rpmts = NULL; |
| #else |
| if (swi->swi_dp != NULL) |
| closedir(swi->swi_dp); |
| swi->swi_dp = NULL; |
| #endif |
| } |