mirror of https://github.com/vmware/tdnf.git
189 lines
4.6 KiB
C
189 lines
4.6 KiB
C
/*
|
|
* Copyright (C) 2022-2023 VMware, Inc. All Rights Reserved.
|
|
*
|
|
* Licensed under the GNU Lesser General Public License v2.1 (the "License");
|
|
* you may not use this file except in compliance with the License. The terms
|
|
* of the License are located in the COPYING file of this distribution.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <time.h>
|
|
/* for O_RDONLY */
|
|
#include <fcntl.h>
|
|
#include <getopt.h>
|
|
|
|
#include <sqlite3.h>
|
|
|
|
#include <rpm/rpmlib.h>
|
|
#include <rpm/rpmdb.h>
|
|
#include <rpm/rpmlog.h>
|
|
#include <rpm/rpmps.h>
|
|
#include <rpm/rpmts.h>
|
|
#include <rpm/rpmdb.h>
|
|
|
|
#include "history.h"
|
|
|
|
#define ERR_CMDLINE 1
|
|
#define ERR_SYSTEM 2
|
|
#define ERR_RPMTS 3
|
|
|
|
#define pr_err(fmt, ...) \
|
|
fprintf(stderr, fmt, ##__VA_ARGS__)
|
|
|
|
#define fail(_rc, fmt, ...) { \
|
|
rc = _rc; \
|
|
pr_err(fmt, ##__VA_ARGS__); \
|
|
goto error; \
|
|
}
|
|
|
|
#define check_cond(COND) if(!(COND)) { \
|
|
pr_err("check_cond failed in %s line %d\n", \
|
|
__FUNCTION__, __LINE__); \
|
|
rc = -1; \
|
|
((void)(rc)); /* suppress "set but not used" warning */ \
|
|
goto error; \
|
|
}
|
|
|
|
#define check_ptr(ptr) if(!(ptr)) { \
|
|
pr_err("check_ptr failed in %s line %d\n", \
|
|
__FUNCTION__, __LINE__); \
|
|
rc = -1; \
|
|
((void)(rc)); /* suppress "set but not used" warning */ \
|
|
goto error; \
|
|
}
|
|
|
|
#define check_rc(rc) if((rc) != 0) { \
|
|
pr_err("check_rc failed in %s line %d\n", \
|
|
__FUNCTION__, __LINE__); \
|
|
goto error; \
|
|
}
|
|
|
|
#define safe_free(ptr) { if ((ptr) != NULL) { free(ptr); ptr = NULL; }}
|
|
|
|
|
|
void usage(const char *cmdname)
|
|
{
|
|
printf("tdnf history db utility\n\n");
|
|
printf("Usage:\n\n");
|
|
printf("%s [-f dbfile] [-r rootdir] init|update\n", cmdname);
|
|
printf("%s [-f dbfile] mark install|remove [pkg[...]]\n", cmdname);
|
|
printf("\n");
|
|
printf("Commands:\n\n");
|
|
printf("init - Initialize the history db.\n");
|
|
printf("mark - Mark a package as user installed ('install') or auto installed ('remove').\n");
|
|
printf("update - Update the history db using the current rpm db.\n");
|
|
printf("\n");
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
char *db_file = HISTORY_DB_DIR"/"HISTORY_DB_FILE;
|
|
char *rpm_root_dir = "/";
|
|
rpmts ts = NULL;
|
|
struct history_ctx *ctx = NULL;
|
|
int rc = 0;
|
|
|
|
while(1) {
|
|
int c;
|
|
|
|
static struct option long_options[] = {
|
|
{"file", 1, 0, 'f'},
|
|
{"rootdir", 1, 0, 'r'},
|
|
{0, 0, 0, 0}
|
|
};
|
|
|
|
c = getopt_long(argc, argv, "f:r:",
|
|
long_options, NULL);
|
|
|
|
if (c == -1)
|
|
break;
|
|
|
|
switch(c){
|
|
case 'f':
|
|
db_file = optarg;
|
|
break;
|
|
case 'r':
|
|
rpm_root_dir = optarg;
|
|
break;
|
|
case '?':
|
|
default:
|
|
/* If it's an error, getopt has already produced an error message. */
|
|
usage(argv[0]);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
rpmReadConfigFiles(NULL, NULL);
|
|
|
|
ts = rpmtsCreate();
|
|
check_ptr(ts);
|
|
|
|
if(rpmtsSetRootDir(ts, rpm_root_dir)) {
|
|
fail(ERR_RPMTS, "could not set rpm root dir\n");
|
|
}
|
|
|
|
if(rpmtsOpenDB(ts, O_RDONLY)) {
|
|
fail(ERR_RPMTS, "could not open rpmdb\n");
|
|
}
|
|
|
|
ctx = create_history_ctx(db_file);
|
|
check_ptr(ctx);
|
|
|
|
/*
|
|
* Process the action(s).
|
|
*/
|
|
if (optind < argc) {
|
|
int argcount = 0;
|
|
char *action = NULL;
|
|
|
|
while (optind + argcount < argc)
|
|
argcount++;
|
|
|
|
/*
|
|
* Find the action.
|
|
*/
|
|
action = argv[optind];
|
|
if(strcmp(action, "init") == 0 || strcmp(action, "update") == 0) {
|
|
rc = history_sync(ctx, ts);
|
|
check_rc(rc);
|
|
} else if(strcmp(action, "mark") == 0) {
|
|
char *subaction = NULL;
|
|
int flag = 0;
|
|
int i;
|
|
|
|
if (argcount < 2) {
|
|
usage(argv[0]);
|
|
fail(ERR_CMDLINE, "expected 'remove' or 'install'\n");
|
|
}
|
|
subaction = argv[optind+1];
|
|
if (strcmp(subaction, "remove") == 0) {
|
|
flag = 1;
|
|
} else if(strcmp(subaction, "install") == 0) {
|
|
flag = 0;
|
|
} else {
|
|
usage(argv[0]);
|
|
fail(ERR_CMDLINE, "unknown sub command '%s'\n", subaction);
|
|
}
|
|
for (i = optind + 2; argv[i]; i++) {
|
|
rc = history_set_auto_flag(ctx, argv[i], flag);
|
|
check_rc(rc);
|
|
}
|
|
} else {
|
|
usage(argv[0]);
|
|
fail(ERR_CMDLINE, "unknown command '%s'\n", action);
|
|
}
|
|
} else {
|
|
usage(argv[0]);
|
|
fail(ERR_CMDLINE, "command expected\n");
|
|
}
|
|
error:
|
|
if (ctx)
|
|
destroy_history_ctx(ctx);
|
|
if (ts) {
|
|
rpmtsCloseDB(ts);
|
|
rpmtsFree(ts);
|
|
}
|
|
exit(rc);
|
|
}
|