|
Packit |
6639f8 |
// Copyright(c) 2018-2020, Intel Corporation
|
|
Packit |
6639f8 |
//
|
|
Packit |
6639f8 |
// Redistribution and use in source and binary forms, with or without
|
|
Packit |
6639f8 |
// modification, are permitted provided that the following conditions are met:
|
|
Packit |
6639f8 |
//
|
|
Packit |
6639f8 |
// * Redistributions of source code must retain the above copyright notice,
|
|
Packit |
6639f8 |
// this list of conditions and the following disclaimer.
|
|
Packit |
6639f8 |
// * Redistributions in binary form must reproduce the above copyright notice,
|
|
Packit |
6639f8 |
// this list of conditions and the following disclaimer in the documentation
|
|
Packit |
6639f8 |
// and/or other materials provided with the distribution.
|
|
Packit |
6639f8 |
// * Neither the name of Intel Corporation nor the names of its contributors
|
|
Packit |
6639f8 |
// may be used to endorse or promote products derived from this software
|
|
Packit |
6639f8 |
// without specific prior written permission.
|
|
Packit |
6639f8 |
//
|
|
Packit |
6639f8 |
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
Packit |
6639f8 |
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
Packit |
6639f8 |
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
Packit |
6639f8 |
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
Packit |
6639f8 |
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
Packit |
6639f8 |
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
Packit |
6639f8 |
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
Packit |
6639f8 |
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
Packit |
6639f8 |
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
Packit |
6639f8 |
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
Packit |
6639f8 |
// POSSIBILITY OF SUCH DAMAGE.
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
#ifdef HAVE_CONFIG_H
|
|
Packit |
6639f8 |
#include <config.h>
|
|
Packit |
6639f8 |
#endif // HAVE_CONFIG_H
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
#include <sys/types.h>
|
|
Packit |
6639f8 |
#include <pwd.h>
|
|
Packit |
6639f8 |
#include "config_file.h"
|
|
Packit |
6639f8 |
#include "monitored_device.h"
|
|
Packit |
6639f8 |
#include "api/sysfs.h"
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
#include <json-c/json.h>
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
#ifdef LOG
|
|
Packit |
6639f8 |
#undef LOG
|
|
Packit |
6639f8 |
#endif
|
|
Packit |
6639f8 |
#define LOG(format, ...) \
|
|
Packit |
6639f8 |
log_printf("cfg: " format, ##__VA_ARGS__)
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
#define CFG_TRY_FILE(__f) \
|
|
Packit |
6639f8 |
do { \
|
|
Packit |
6639f8 |
canon = canonicalize_file_name(__f); \
|
|
Packit |
6639f8 |
if (canon) { \
|
|
Packit |
6639f8 |
\
|
|
Packit |
6639f8 |
if (!cmd_path_is_symlink(__f)) { \
|
|
Packit |
6639f8 |
size_t len = strnlen(canon, \
|
|
Packit |
6639f8 |
sizeof(c->cfgfile) - 1); \
|
|
Packit |
6639f8 |
memcpy(c->cfgfile, \
|
|
Packit |
6639f8 |
canon, \
|
|
Packit |
6639f8 |
len); \
|
|
Packit |
6639f8 |
c->cfgfile[len] = '\0'; \
|
|
Packit |
6639f8 |
free(canon); \
|
|
Packit |
6639f8 |
return 0; \
|
|
Packit |
6639f8 |
} \
|
|
Packit |
6639f8 |
\
|
|
Packit |
6639f8 |
free(canon); \
|
|
Packit |
6639f8 |
} \
|
|
Packit |
6639f8 |
} while (0)
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
int cfg_find_config_file(struct fpgad_config *c)
|
|
Packit |
6639f8 |
{
|
|
Packit |
6639f8 |
char path[PATH_MAX];
|
|
Packit |
6639f8 |
char *e;
|
|
Packit |
6639f8 |
char *canon = NULL;
|
|
Packit |
6639f8 |
uid_t uid;
|
|
Packit |
6639f8 |
size_t len;
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
uid = geteuid();
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
e = getenv("FPGAD_CONFIG_FILE");
|
|
Packit |
6639f8 |
if (e) {
|
|
Packit |
6639f8 |
// try $FPGAD_CONFIG_FILE
|
|
Packit |
6639f8 |
len = strnlen(e, sizeof(path) - 1);
|
|
Packit |
6639f8 |
memcpy(path, e, len);
|
|
Packit |
6639f8 |
path[len] = '\0';
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
CFG_TRY_FILE(path);
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
if (!uid) {
|
|
Packit |
6639f8 |
CFG_TRY_FILE("/var/lib/opae/fpgad.cfg");
|
|
Packit |
6639f8 |
} else {
|
|
Packit |
6639f8 |
struct passwd *passwd;
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
passwd = getpwuid(uid);
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
// try $HOME/.opae/fpgad.cfg
|
|
Packit |
6639f8 |
snprintf(path, sizeof(path),
|
|
Packit |
6639f8 |
"%s/.opae/fpgad.cfg", passwd->pw_dir);
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
CFG_TRY_FILE(path);
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
CFG_TRY_FILE("/etc/opae/fpgad.cfg");
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
return 1; // not found
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
STATIC char *cfg_read_file(const char *file)
|
|
Packit |
6639f8 |
{
|
|
Packit |
6639f8 |
FILE *fp;
|
|
Packit |
6639f8 |
size_t len;
|
|
Packit |
6639f8 |
char *buf;
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
fp = fopen(file, "r");
|
|
Packit |
6639f8 |
if (!fp) {
|
|
Packit |
6639f8 |
LOG("fopen failed.\n");
|
|
Packit |
6639f8 |
return NULL;
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
if (fseek(fp, 0, SEEK_END)) {
|
|
Packit |
6639f8 |
LOG("fseek failed.\n");
|
|
Packit |
6639f8 |
fclose(fp);
|
|
Packit |
6639f8 |
return NULL;
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
len = (size_t)ftell(fp);
|
|
Packit |
6639f8 |
++len; // for \0
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
if (len == 1) {
|
|
Packit |
6639f8 |
LOG("%s is empty.\n", file);
|
|
Packit |
6639f8 |
fclose(fp);
|
|
Packit |
6639f8 |
return NULL;
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
if (fseek(fp, 0, SEEK_SET)) {
|
|
Packit |
6639f8 |
LOG("fseek failed.\n");
|
|
Packit |
6639f8 |
fclose(fp);
|
|
Packit |
6639f8 |
return NULL;
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
buf = (char *)malloc(len);
|
|
Packit |
6639f8 |
if (!buf) {
|
|
Packit |
6639f8 |
LOG("malloc failed.\n");
|
|
Packit |
6639f8 |
fclose(fp);
|
|
Packit |
6639f8 |
return NULL;
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
if ((fread(buf, 1, len - 1, fp) != len - 1) ||
|
|
Packit |
6639f8 |
ferror(fp)) {
|
|
Packit |
6639f8 |
LOG("fread failed.\n");
|
|
Packit |
6639f8 |
fclose(fp);
|
|
Packit |
6639f8 |
free(buf);
|
|
Packit |
6639f8 |
return NULL;
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
fclose(fp);
|
|
Packit |
6639f8 |
buf[len - 1] = '\0';
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
return buf;
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
typedef struct _cfg_vendor_device_id {
|
|
Packit |
6639f8 |
uint16_t vendor_id;
|
|
Packit |
6639f8 |
uint16_t device_id;
|
|
Packit |
6639f8 |
struct _cfg_vendor_device_id *next;
|
|
Packit |
6639f8 |
} cfg_vendor_device_id;
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
typedef struct _cfg_plugin_configuration {
|
|
Packit |
6639f8 |
char *configuration;
|
|
Packit |
6639f8 |
bool enabled;
|
|
Packit |
6639f8 |
char *library;
|
|
Packit |
6639f8 |
cfg_vendor_device_id *devices;
|
|
Packit |
6639f8 |
struct _cfg_plugin_configuration *next;
|
|
Packit |
6639f8 |
} cfg_plugin_configuration;
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
STATIC cfg_vendor_device_id *alloc_device(uint16_t vendor_id,
|
|
Packit |
6639f8 |
uint16_t device_id)
|
|
Packit |
6639f8 |
{
|
|
Packit |
6639f8 |
cfg_vendor_device_id *p;
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
p = (cfg_vendor_device_id *)malloc(sizeof(cfg_vendor_device_id));
|
|
Packit |
6639f8 |
if (p) {
|
|
Packit |
6639f8 |
p->vendor_id = vendor_id;
|
|
Packit |
6639f8 |
p->device_id = device_id;
|
|
Packit |
6639f8 |
p->next = NULL;
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
return p;
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
STATIC cfg_plugin_configuration *alloc_configuration(char *configuration,
|
|
Packit |
6639f8 |
bool enabled,
|
|
Packit |
6639f8 |
char *library,
|
|
Packit |
6639f8 |
cfg_vendor_device_id *devs)
|
|
Packit |
6639f8 |
{
|
|
Packit |
6639f8 |
cfg_plugin_configuration *p;
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
p = (cfg_plugin_configuration *)
|
|
Packit |
6639f8 |
malloc(sizeof(cfg_plugin_configuration));
|
|
Packit |
6639f8 |
if (p) {
|
|
Packit |
6639f8 |
p->configuration = configuration;
|
|
Packit |
6639f8 |
p->enabled = enabled;
|
|
Packit |
6639f8 |
p->library = library;
|
|
Packit |
6639f8 |
p->devices = devs;
|
|
Packit |
6639f8 |
p->next = NULL;
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
return p;
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
STATIC cfg_vendor_device_id *
|
|
Packit |
6639f8 |
cfg_process_plugin_devices(const char *name,
|
|
Packit |
6639f8 |
json_object *j_devices)
|
|
Packit |
6639f8 |
{
|
|
Packit |
6639f8 |
int i;
|
|
Packit |
6639f8 |
int devs;
|
|
Packit |
6639f8 |
cfg_vendor_device_id *head = NULL;
|
|
Packit |
6639f8 |
cfg_vendor_device_id *id = NULL;
|
|
Packit |
6639f8 |
uint16_t vendor_id;
|
|
Packit |
6639f8 |
uint16_t device_id;
|
|
Packit |
6639f8 |
const char *s;
|
|
Packit |
6639f8 |
char *endptr;
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
if (!json_object_is_type(j_devices, json_type_array)) {
|
|
Packit |
6639f8 |
LOG("'devices' JSON object not array.\n");
|
|
Packit |
6639f8 |
return NULL;
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
devs = json_object_array_length(j_devices);
|
|
Packit |
6639f8 |
for (i = 0 ; i < devs ; ++i) {
|
|
Packit |
6639f8 |
json_object *j_dev = json_object_array_get_idx(j_devices, i);
|
|
Packit |
6639f8 |
json_object *j_vid;
|
|
Packit |
6639f8 |
json_object *j_did;
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
if (!json_object_is_type(j_dev, json_type_array)) {
|
|
Packit |
6639f8 |
LOG("%s 'devices' entry %d not array.\n",
|
|
Packit |
6639f8 |
name, i);
|
|
Packit |
6639f8 |
goto out_free;
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
if (json_object_array_length(j_dev) != 2) {
|
|
Packit |
6639f8 |
LOG("%s 'devices' entry %d not array[2].\n",
|
|
Packit |
6639f8 |
name, i);
|
|
Packit |
6639f8 |
goto out_free;
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
j_vid = json_object_array_get_idx(j_dev, 0);
|
|
Packit |
6639f8 |
if (json_object_is_type(j_vid, json_type_string)) {
|
|
Packit |
6639f8 |
s = json_object_get_string(j_vid);
|
|
Packit |
6639f8 |
endptr = NULL;
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
vendor_id = (uint16_t)strtoul(s, &endptr, 0);
|
|
Packit |
6639f8 |
if (*endptr != '\0') {
|
|
Packit |
6639f8 |
LOG("%s malformed Vendor ID at devices[%d]\n",
|
|
Packit |
6639f8 |
name, i);
|
|
Packit |
6639f8 |
goto out_free;
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
} else if (json_object_is_type(j_vid, json_type_int)) {
|
|
Packit |
6639f8 |
vendor_id = (uint16_t)json_object_get_int(j_vid);
|
|
Packit |
6639f8 |
} else {
|
|
Packit |
6639f8 |
LOG("%s invalid Vendor ID at devices[%d]\n",
|
|
Packit |
6639f8 |
name, i);
|
|
Packit |
6639f8 |
goto out_free;
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
j_did = json_object_array_get_idx(j_dev, 1);
|
|
Packit |
6639f8 |
if (json_object_is_type(j_did, json_type_string)) {
|
|
Packit |
6639f8 |
s = json_object_get_string(j_did);
|
|
Packit |
6639f8 |
endptr = NULL;
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
device_id = (uint16_t)strtoul(s, &endptr, 0);
|
|
Packit |
6639f8 |
if (*endptr != '\0') {
|
|
Packit |
6639f8 |
LOG("%s malformed Device ID at devices[%d]\n",
|
|
Packit |
6639f8 |
name, i);
|
|
Packit |
6639f8 |
goto out_free;
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
} else if (json_object_is_type(j_did, json_type_int)) {
|
|
Packit |
6639f8 |
device_id = (uint16_t)json_object_get_int(j_did);
|
|
Packit |
6639f8 |
} else {
|
|
Packit |
6639f8 |
LOG("%s invalid Device ID at devices[%d]\n",
|
|
Packit |
6639f8 |
name, i);
|
|
Packit |
6639f8 |
goto out_free;
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
if (!head) {
|
|
Packit |
6639f8 |
head = alloc_device(vendor_id, device_id);
|
|
Packit |
6639f8 |
if (!head) {
|
|
Packit |
6639f8 |
LOG("malloc failed.\n");
|
|
Packit |
6639f8 |
goto out_free;
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
id = head;
|
|
Packit |
6639f8 |
} else {
|
|
Packit |
6639f8 |
id->next = alloc_device(vendor_id, device_id);
|
|
Packit |
6639f8 |
if (!id->next) {
|
|
Packit |
6639f8 |
LOG("malloc failed.\n");
|
|
Packit |
6639f8 |
goto out_free;
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
id = id->next;
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
return head;
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
out_free:
|
|
Packit |
6639f8 |
for (id = head ; id ; ) {
|
|
Packit |
6639f8 |
cfg_vendor_device_id *trash = id;
|
|
Packit |
6639f8 |
id = id->next;
|
|
Packit |
6639f8 |
free(trash);
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
return NULL;
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
STATIC int cfg_process_plugin(const char *name,
|
|
Packit |
6639f8 |
json_object *j_configurations,
|
|
Packit |
6639f8 |
cfg_plugin_configuration **list)
|
|
Packit |
6639f8 |
{
|
|
Packit |
6639f8 |
json_object *j_cfg_plugin = NULL;
|
|
Packit |
6639f8 |
json_object *j_cfg_plugin_configuration = NULL;
|
|
Packit |
6639f8 |
json_object *j_enabled = NULL;
|
|
Packit |
6639f8 |
json_object *j_plugin = NULL;
|
|
Packit |
6639f8 |
json_object *j_devices = NULL;
|
|
Packit |
6639f8 |
char *configuration = NULL;
|
|
Packit |
6639f8 |
bool enabled = false;
|
|
Packit |
6639f8 |
char *plugin = NULL;
|
|
Packit |
6639f8 |
cfg_plugin_configuration *c = NULL;
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
if (!json_object_object_get_ex(j_configurations,
|
|
Packit |
6639f8 |
name,
|
|
Packit |
6639f8 |
&j_cfg_plugin)) {
|
|
Packit |
6639f8 |
LOG("couldn't find configurations section"
|
|
Packit |
6639f8 |
" for %s.\n", name);
|
|
Packit |
6639f8 |
return 1;
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
if (!json_object_object_get_ex(j_cfg_plugin,
|
|
Packit |
6639f8 |
"configuration",
|
|
Packit |
6639f8 |
&j_cfg_plugin_configuration)) {
|
|
Packit |
6639f8 |
LOG("couldn't find %s configuration section.\n", name);
|
|
Packit |
6639f8 |
return 1;
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
configuration = (char *)json_object_to_json_string_ext(
|
|
Packit |
6639f8 |
j_cfg_plugin_configuration,
|
|
Packit |
6639f8 |
JSON_C_TO_STRING_PLAIN);
|
|
Packit |
6639f8 |
if (!configuration) {
|
|
Packit |
6639f8 |
LOG("failed to parse configuration for %s.\n", name);
|
|
Packit |
6639f8 |
return 1;
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
configuration = cstr_dup(configuration);
|
|
Packit |
6639f8 |
if (!configuration) {
|
|
Packit |
6639f8 |
LOG("cstr_dup failed.\n");
|
|
Packit |
6639f8 |
return 1;
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
if (!json_object_object_get_ex(j_cfg_plugin,
|
|
Packit |
6639f8 |
"enabled",
|
|
Packit |
6639f8 |
&j_enabled)) {
|
|
Packit |
6639f8 |
LOG("couldn't find enabled key"
|
|
Packit |
6639f8 |
" for %s.\n", name);
|
|
Packit |
6639f8 |
goto out_free;
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
if (!json_object_is_type(j_enabled, json_type_boolean)) {
|
|
Packit |
6639f8 |
LOG("enabled key for %s not boolean.\n", name);
|
|
Packit |
6639f8 |
goto out_free;
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
enabled = json_object_get_boolean(j_enabled);
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
if (!json_object_object_get_ex(j_cfg_plugin,
|
|
Packit |
6639f8 |
"plugin",
|
|
Packit |
6639f8 |
&j_plugin)) {
|
|
Packit |
6639f8 |
LOG("couldn't find plugin key"
|
|
Packit |
6639f8 |
" for %s.\n", name);
|
|
Packit |
6639f8 |
goto out_free;
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
if (!json_object_is_type(j_plugin, json_type_string)) {
|
|
Packit |
6639f8 |
LOG("plugin key for %s not string.\n", name);
|
|
Packit |
6639f8 |
goto out_free;
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
plugin = cstr_dup(json_object_get_string(j_plugin));
|
|
Packit |
6639f8 |
if (!plugin) {
|
|
Packit |
6639f8 |
LOG("cstr_dup failed.\n");
|
|
Packit |
6639f8 |
goto out_free;
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
if (!json_object_object_get_ex(j_cfg_plugin,
|
|
Packit |
6639f8 |
"devices",
|
|
Packit |
6639f8 |
&j_devices)) {
|
|
Packit |
6639f8 |
LOG("couldn't find devices key"
|
|
Packit |
6639f8 |
" for %s.\n", name);
|
|
Packit |
6639f8 |
goto out_free;
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
if (!(*list)) { // list is empty
|
|
Packit |
6639f8 |
c = alloc_configuration(configuration,
|
|
Packit |
6639f8 |
enabled,
|
|
Packit |
6639f8 |
plugin,
|
|
Packit |
6639f8 |
NULL);
|
|
Packit |
6639f8 |
if (!c) {
|
|
Packit |
6639f8 |
LOG("malloc failed.\n");
|
|
Packit |
6639f8 |
goto out_free;
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
*list = c;
|
|
Packit |
6639f8 |
} else {
|
|
Packit |
6639f8 |
for (c = *list ; c->next ; c = c->next)
|
|
Packit |
6639f8 |
/* find the end of the list */ ;
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
c->next = alloc_configuration(configuration,
|
|
Packit |
6639f8 |
enabled,
|
|
Packit |
6639f8 |
plugin,
|
|
Packit |
6639f8 |
NULL);
|
|
Packit |
6639f8 |
if (!c->next) {
|
|
Packit |
6639f8 |
LOG("malloc failed.\n");
|
|
Packit |
6639f8 |
goto out_free;
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
c = c->next;
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
c->devices = cfg_process_plugin_devices(name, j_devices);
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
return 0;
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
out_free:
|
|
Packit |
6639f8 |
if (configuration)
|
|
Packit |
6639f8 |
free(configuration);
|
|
Packit |
6639f8 |
if (plugin)
|
|
Packit |
6639f8 |
free(plugin);
|
|
Packit |
6639f8 |
if (c)
|
|
Packit |
6639f8 |
free(c);
|
|
Packit |
6639f8 |
return 1;
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
STATIC fpgad_supported_device *
|
|
Packit |
6639f8 |
cfg_json_to_supported(cfg_plugin_configuration *configurations)
|
|
Packit |
6639f8 |
{
|
|
Packit |
6639f8 |
cfg_plugin_configuration *c;
|
|
Packit |
6639f8 |
cfg_vendor_device_id *d;
|
|
Packit |
6639f8 |
size_t num_devices = 0;
|
|
Packit |
6639f8 |
fpgad_supported_device *supported;
|
|
Packit |
6639f8 |
int i;
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
// find the number of devices
|
|
Packit |
6639f8 |
for (c = configurations ; c ; c = c->next) {
|
|
Packit |
6639f8 |
if (!c->enabled) // skip it
|
|
Packit |
6639f8 |
continue;
|
|
Packit |
6639f8 |
for (d = c->devices ; d ; d = d->next) {
|
|
Packit |
6639f8 |
++num_devices;
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
++num_devices; // +1 for NULL terminator
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
supported = calloc(num_devices, sizeof(fpgad_supported_device));
|
|
Packit |
6639f8 |
if (!supported) {
|
|
Packit |
6639f8 |
LOG("calloc failed.\n");
|
|
Packit |
6639f8 |
return NULL;
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
i = 0;
|
|
Packit |
6639f8 |
for (c = configurations ; c ; c = c->next) {
|
|
Packit |
6639f8 |
if (!c->enabled) // skip it
|
|
Packit |
6639f8 |
continue;
|
|
Packit |
6639f8 |
for (d = c->devices ; d ; d = d->next) {
|
|
Packit |
6639f8 |
fpgad_supported_device *dev = &supported[i++];
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
dev->vendor_id = d->vendor_id;
|
|
Packit |
6639f8 |
dev->device_id = d->device_id;
|
|
Packit |
6639f8 |
dev->library_path = cstr_dup(c->library);
|
|
Packit |
6639f8 |
dev->config = cstr_dup(c->configuration);
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
for (c = configurations ; c ; ) {
|
|
Packit |
6639f8 |
cfg_plugin_configuration *ctrash = c;
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
for (d = c->devices ; d ; ) {
|
|
Packit |
6639f8 |
cfg_vendor_device_id *dtrash = d;
|
|
Packit |
6639f8 |
d = d->next;
|
|
Packit |
6639f8 |
free(dtrash);
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
c = c->next;
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
if (ctrash->configuration)
|
|
Packit |
6639f8 |
free(ctrash->configuration);
|
|
Packit |
6639f8 |
if (ctrash->library)
|
|
Packit |
6639f8 |
free(ctrash->library);
|
|
Packit |
6639f8 |
free(ctrash);
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
return supported;
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
STATIC bool cfg_verify_supported_devices(fpgad_supported_device *d)
|
|
Packit |
6639f8 |
{
|
|
Packit |
6639f8 |
while (d->library_path) {
|
|
Packit |
6639f8 |
char *sub = NULL;
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
if (d->library_path[0] == '/') {
|
|
Packit |
6639f8 |
LOG("plugin library paths may not "
|
|
Packit |
6639f8 |
"be absolute paths: %s\n", d->library_path);
|
|
Packit |
6639f8 |
return false;
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
if (cmd_path_is_symlink(d->library_path)) {
|
|
Packit |
6639f8 |
LOG("plugin library paths may not "
|
|
Packit |
6639f8 |
"contain links: %s\n", d->library_path);
|
|
Packit |
6639f8 |
return false;
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
sub = strstr((char *)d->library_path, "..");
|
|
Packit |
6639f8 |
if (sub) {
|
|
Packit |
6639f8 |
LOG("plugin library paths may not "
|
|
Packit |
6639f8 |
"contain .. : %s\n", d->library_path);
|
|
Packit |
6639f8 |
return false;
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
++d;
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
return true;
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
int cfg_load_config(struct fpgad_config *c)
|
|
Packit |
6639f8 |
{
|
|
Packit |
6639f8 |
char *cfg_buf;
|
|
Packit |
6639f8 |
json_object *root = NULL;
|
|
Packit |
6639f8 |
json_object *j_configurations = NULL;
|
|
Packit |
6639f8 |
json_object *j_plugins = NULL;
|
|
Packit |
6639f8 |
enum json_tokener_error j_err = json_tokener_success;
|
|
Packit |
6639f8 |
int res = 1;
|
|
Packit |
6639f8 |
int num_plugins;
|
|
Packit |
6639f8 |
int i;
|
|
Packit |
6639f8 |
cfg_plugin_configuration *configurations = NULL;
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
cfg_buf = cfg_read_file(c->cfgfile);
|
|
Packit |
6639f8 |
if (!cfg_buf)
|
|
Packit |
6639f8 |
return res;
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
root = json_tokener_parse_verbose(cfg_buf, &j_err);
|
|
Packit |
6639f8 |
if (!root) {
|
|
Packit |
6639f8 |
LOG("error parsing %s: %s\n",
|
|
Packit |
6639f8 |
c->cfgfile,
|
|
Packit |
6639f8 |
json_tokener_error_desc(j_err));
|
|
Packit |
6639f8 |
goto out_free;
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
if (!json_object_object_get_ex(root,
|
|
Packit |
6639f8 |
"configurations",
|
|
Packit |
6639f8 |
&j_configurations)) {
|
|
Packit |
6639f8 |
LOG("failed to find configurations section in %s.\n",
|
|
Packit |
6639f8 |
c->cfgfile);
|
|
Packit |
6639f8 |
goto out_put;
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
if (!json_object_object_get_ex(root, "plugins", &j_plugins)) {
|
|
Packit |
6639f8 |
LOG("failed to find plugins section in %s.\n", c->cfgfile);
|
|
Packit |
6639f8 |
goto out_put;
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
if (!json_object_is_type(j_plugins, json_type_array)) {
|
|
Packit |
6639f8 |
LOG("'plugins' JSON object not array.\n");
|
|
Packit |
6639f8 |
goto out_put;
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
num_plugins = json_object_array_length(j_plugins);
|
|
Packit |
6639f8 |
for (i = 0 ; i < num_plugins ; ++i) {
|
|
Packit |
6639f8 |
json_object *j_plugin;
|
|
Packit |
6639f8 |
const char *plugin_name;
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
j_plugin = json_object_array_get_idx(j_plugins, i);
|
|
Packit |
6639f8 |
plugin_name = json_object_get_string(j_plugin);
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
if (cfg_process_plugin(plugin_name,
|
|
Packit |
6639f8 |
j_configurations,
|
|
Packit |
6639f8 |
&configurations))
|
|
Packit |
6639f8 |
goto out_put;
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
if (!configurations) {
|
|
Packit |
6639f8 |
LOG("no configurations found in %s.\n", c->cfgfile);
|
|
Packit |
6639f8 |
goto out_put;
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
c->supported_devices = cfg_json_to_supported(configurations);
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
if (c->supported_devices) {
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
if (cfg_verify_supported_devices(c->supported_devices)) {
|
|
Packit |
6639f8 |
res = 0;
|
|
Packit |
6639f8 |
} else {
|
|
Packit |
6639f8 |
fpgad_supported_device *trash = c->supported_devices;
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
LOG("invalid configuration file\n");
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
while (trash->library_path) {
|
|
Packit |
6639f8 |
free((void *)trash->library_path);
|
|
Packit |
6639f8 |
if (trash->config)
|
|
Packit |
6639f8 |
free((void *)trash->config);
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
++trash;
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
free(c->supported_devices);
|
|
Packit |
6639f8 |
c->supported_devices = NULL;
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
}
|
|
Packit |
6639f8 |
|
|
Packit |
6639f8 |
out_put:
|
|
Packit |
6639f8 |
json_object_put(root);
|
|
Packit |
6639f8 |
out_free:
|
|
Packit |
6639f8 |
free(cfg_buf);
|
|
Packit |
6639f8 |
return res;
|
|
Packit |
6639f8 |
}
|