Skip to content
This repository has been archived by the owner on Jan 6, 2023. It is now read-only.

Next #19

Closed
wants to merge 14 commits into from
Closed

Next #19

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ libcve_la_SOURCES = \
library/cve-check-tool.h \
library/cve-string.h \
library/cve-string.c \
library/cve-db-lock.h \
library/cve-db-lock.c \
library/fetch.c \
library/fetch.h \
library/template.c \
Expand Down
4 changes: 2 additions & 2 deletions src/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@

#include <sqlite3.h>

#define YEAR_START 2002
#define URI_PREFIX "http://static.nvd.nist.gov/feeds/xml/cve"
const char nvd_file[] = "nvd.db";
const char nvd_dir[] = "NVDS";

struct CveDB {
/** XML traversal state */
Expand Down
3 changes: 3 additions & 0 deletions src/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
#include <libxml/xmlreader.h>
#include "common.h"

extern const char nvd_file[]; /* nvd.db */
extern const char nvd_dir[]; /* NVDS */

/**
* A CVE Database, using the National Vulnerability Database as its source
*/
Expand Down
156 changes: 156 additions & 0 deletions src/library/cve-db-lock.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
/*
* cve-check-tool.c
*
* Copyright (C) 2015-2016 Sergey Popovich <[email protected]>.
*
* cve-check-tool is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/

#define _GNU_SOURCE

#include <sys/types.h>
#include <sys/stat.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <assert.h>

#include "core.h"
#include "util.h"
#include "cve-db-lock.h"

static const short int locktype2l_type[] = {
[LT_READ] = F_RDLCK,
[LT_WRITE] = F_WRLCK,
};

static const char locktype2string[][sizeof("write")] = {
[LT_READ] = "read",
[LT_WRITE] = "write",
};

static int db_lock_fd = -1;
static char *db_lock_fname;

#ifndef O_NOFOLLOW
#define O_NOFOLLOW 0
#endif

bool cve_db_lock_init(const char *db_path)
{
const int flags = O_RDWR|O_CREAT|O_NONBLOCK|O_NOFOLLOW;
const mode_t mode = S_IRUSR|S_IWUSR;

assert(db_lock_fd == -1);
assert(db_lock_fname == NULL);
assert(db_path != NULL);

db_lock_fname = get_db_dot_fname(db_path, "cve.lock");
if (db_lock_fname)
db_lock_fd = open(db_lock_fname, flags, mode);

return db_lock_fd != -1;
}

void cve_db_lock_fini(void)
{
assert(db_lock_fd != -1);
assert(db_lock_fname != NULL);

close(db_lock_fd);
db_lock_fd = -1;

unlink(db_lock_fname);
free(db_lock_fname);
db_lock_fname = NULL;
}

bool cve_db_lock(enum locktype lt, int wait)
{
const char *lt_str = locktype2string[lt];
unsigned int waited;

assert(db_lock_fd != -1);

if (wait < 0)
waited = wait = 2;
else
waited = 0;

do {
struct flock fl = {
.l_type = locktype2l_type[lt],
.l_whence = SEEK_SET,
};
int ret;

ret = fcntl(db_lock_fd, F_SETLK, &fl);
if (!ret)
return true;
if (errno != EAGAIN && errno != EACCES) {
fprintf(stderr,
"Error acquiring database lock: %s\n",
strerror(errno));
break;
}

if (waited % 2)
goto sleep;
fputs("Another app holds the lock on database", stderr);
if (wait) {
int remaining = wait - waited;
if (remaining <= 0) {
fprintf(stderr,
"; %s lock is not acquired\n", lt_str);
break;
}
fprintf(stderr,
"; acquiring %s lock within %ds ...",
lt_str, remaining);
} else {
fputs("; waiting indefinitely", stderr);
}
fputc('\n', stderr);
sleep:
sleep(1);
waited++;
if (wait && waited >= (unsigned int) wait)
waited = (wait + 1) & ~1; /* last round: make it even */
} while (1);

return false;
}

void cve_db_unlock(void)
{
struct flock fl = {
.l_type = F_UNLCK,
.l_whence = SEEK_SET,
};
int ret;

ret = fcntl(db_lock_fd, F_SETLK, &fl);

assert(ret == 0);
}

/*
* Editor modelines - https://www.wireshark.org/tools/modelines.html
*
* Local variables:
* c-basic-offset: 8
* tab-width: 8
* indent-tabs-mode: nil
* End:
*
* vi: set shiftwidth=8 tabstop=8 expandtab:
* :indentSize=8:tabSize=8:noTabs=true:
*/
97 changes: 97 additions & 0 deletions src/library/cve-db-lock.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*
* cve-check-tool.h
*
* Copyright (C) 2015-2016 Sergey Popovich <[email protected]>.
*
* cve-check-tool is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/

#include <stdbool.h>

/**
* Enumerate to represent possible locking types to imply on the
* database file
*/
enum locktype {
LT_READ = 0, /**<Shared lock type */
LT_WRITE, /**<Exclusive lock type */
};

enum {
LOCK_WAIT_SECS = 5 * 60, /**<Wait for lock to aquire 5 minutes */
};

/**
* Initialize lock on the database by opening it's file and saving
* descriptor for later use by other locking functions
*
* @note If database file does not exists it will be created
*
* @param db_file Database file to operate on
* @return True if database file opened successfuly and false overwise
*/
bool cve_db_lock_init(const char *db_file);

/**
* Finalizes lock usage on database file by closing corresponding
* file descriptor
*
* @note Any locking, if applied to the file descriptor will be released
*/
void cve_db_lock_fini(void);

/**
* Try to aquire lock of the given type on the previously initialized
* database file descriptor within given timeout
*
* @param lt Lock type to aquire as specified by the enum locktype
* @param wait Number of seconds to wait for lock before giving up
* If specified as < 0 then return immediately, 0 means wait
* indefinitely to aquire lock.
*/
bool cve_db_lock(enum locktype lt, int wait);

/**
* Helper routine to aquire shared (read) lock within given timeout
*
* @note Calls cve_db_lock() with LT_READ to perform real work
*
* @param wait Number of seconds to wait for lock before giving up
*/
static inline bool cve_db_read_lock(int wait)
{
return cve_db_lock(LT_READ, wait);
}

/**
* Helper routine to aquire exclusive (write) lock within given timeout
*
* @note Calls cve_db_lock() with LT_WRITE to perform real work
*
* @param wait Number of seconds to wait for lock before giving up
*/
static inline bool cve_db_write_lock(int wait)
{
return cve_db_lock(LT_WRITE, wait);
}

/**
* Releases previously aquired lock from database file
*/
void cve_db_unlock(void);

/*
* Editor modelines - https://www.wireshark.org/tools/modelines.html
*
* Local variables:
* c-basic-offset: 8
* tab-width: 8
* indent-tabs-mode: nil
* End:
*
* vi: set shiftwidth=8 tabstop=8 expandtab:
* :indentSize=8:tabSize=8:noTabs=true:
*/
35 changes: 33 additions & 2 deletions src/library/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@

#define streq(x,y) strcmp(x,y) == 0

DEF_AUTOFREE(char, free)

bool find_sources(const char *path, package_match_func match, bool recurse, cve_add_callback cb)
{
struct stat st = {.st_ino = 0};
Expand Down Expand Up @@ -329,6 +327,39 @@ char *cve_get_file_parent(const char *p)
return dirname(r);
}

char *get_db_dot_fname(const char *db_path, const char *suffix)
{
autofree(char) *path = NULL;
char *dot_fname;
int ret = -1;

path = strdup(db_path);
if (path) {
const char *dir;
char *file;

file = strrchr(path, '/');
if (file) {
*file++ = '\0';
if (!*file)
file = (char *) nvd_file;
dir = *path ? path : ".";
} else {
file = path;
dir = ".";
}

ret = asprintf(&dot_fname, "%s/.%s.%s", dir, file, suffix);
}

if (ret == -1) {
/* dot_fname contents undefined on error: force to NULL */
dot_fname = NULL;
}

return dot_fname;
}

/*
* Editor modelines - https://www.wireshark.org/tools/modelines.html
*
Expand Down
10 changes: 10 additions & 0 deletions src/library/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ DEF_AUTOFREE(GZlibDecompressor, g_object_unref)
DEF_AUTOFREE(GKeyFile, g_key_file_unref)
DEF_AUTOFREE(cve_string, cve_string_free)
DEF_AUTOFREE(CveDB, cve_db_free)
DEF_AUTOFREE(char, free)

/**
* Suger-utility: Determine if a string contains a certain word
Expand Down Expand Up @@ -270,6 +271,15 @@ bool cve_is_dir(const char *p);
*/
char *cve_get_file_parent(const char *p);

/**
* Return absolute path to the dot file in format .basename(db_path).suffix
*
* @note This is an allocated string, and must be freed by the caller
* @param db_path Path to the database directory
* @return a newly allocated string or NULL in case of error
*/
char *get_db_dot_fname(const char *db_path, const char *suffix);

/*
* Editor modelines - https://www.wireshark.org/tools/modelines.html
*
Expand Down
Loading