Blame tools/fpgad/config_file.c

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
}