Esempio n. 1
0
int folders_init(void)
{
	int ret;
	const char *resources_dir = config_get(CONFIG_RESOURCES_DIR);
	const char *list_name;

	ULOGD("%s", __func__);

	list_name = "names";
	ret = load_words(resources_dir, list_name, &folders_names);
	if (ret < 0) {
		ULOGE("load_words %s: %s", list_name, strerror(-ret));
		return ret;
	}
	list_name = "adjectives";
	ret = load_words(resources_dir, list_name, &folders_adjectives);
	if (ret < 0) {
		ULOGE("load_words %s: %s", list_name, strerror(-ret));
		goto err;
	}

	return 0;
err:
	folders_cleanup();

	return ret;
}
Esempio n. 2
0
static unsigned read_index(const char *name)
{
	long index;
	char *bracket;
	char *endptr;

	bracket = strchr(name, '[');
	if (bracket == NULL) {
		ULOGE("access to an array must be performed with [...]");
		return -1;
	}

	errno = 0;
	index = strtol(bracket + 1, &endptr, 0);
	if (errno != 0)
		return UINT_MAX;
	if (bracket + 1 == endptr)
		return UINT_MAX;
	if (*endptr != ']') {
		ULOGE("invalid array access near '%s'", bracket);
		return UINT_MAX;
	}
	if (index >= INT_MAX) {
		ULOGE("index overflow: %ld", index);
		return UINT_MAX;
	}

	return index;
}
Esempio n. 3
0
int folder_add_property(const char *folder_name, const char *name)
{
	int ret;
	struct rs_node *node;
	struct folder_property *property;
	struct folder *folder;

	folder = folder_find(folder_name);
	if (folder == NULL) {
		ULOGE("folder %s doesn't exist", folder_name);
		return -ENOENT;
	}
	/* refuse repetitions */
	node = rs_dll_find_match(&folder->properties,
			folder_property_match_str_array_name, name);
	if (node != NULL)
		return -EEXIST;

	property = custom_property_new(name);
	if (property == NULL) {
		ret = -errno;
		ULOGE("custom_property: %m");
		return ret;
	}

	return folder_register_property(folder->name, property);
}
Esempio n. 4
0
static int sha1(struct firmware *firmware,
		unsigned char hash[SHA_DIGEST_LENGTH])
{
	int ret;
	size_t count;
	SHA_CTX ctx;
	FILE __attribute__((cleanup(ut_file_close))) *f = NULL;
	char buf[BUF_SIZE] = {0};

	SHA1_Init(&ctx);
	if (ut_file_is_dir(firmware->path)) {
		SHA1_Update(&ctx, firmware->path, strlen(firmware->path));
	} else {
		f = fopen(firmware->path, "rbe");
		if (f == NULL) {
			ret = -errno;
			ULOGE("%s: fopen(%s) : %m", firmware->path, __func__);
			return ret;
		}

		do {
			count = fread(buf, 1, BUF_SIZE, f);
			if (count != 0)
				SHA1_Update(&ctx, buf, count);
		} while (count == BUF_SIZE);
		if (ferror(f)) {
			ULOGE("error reading %s for sha1 computation",
					firmware->path);
			return -EIO;
		}
	}
	SHA1_Final(hash, &ctx);

	return 0;
}
Esempio n. 5
0
char *folder_get_info(const char *folder_name,
		const char *entity_identifier)
{
	int ret;
	char *info = NULL;
	char *old_info = NULL;
	char *value = NULL;
	const struct folder *folder;
	struct folder_entity *entity;
	struct rs_node *node = NULL;
	struct folder_property *property;

	errno = 0;
	if (ut_string_is_invalid(folder_name) ||
			ut_string_is_invalid(entity_identifier)) {
		errno = EINVAL;
		return NULL;
	}

	folder = folder_find(folder_name);
	if (folder == NULL) {
		errno = ENOENT;
		return NULL;
	}

	entity = find_entity(folder, entity_identifier);
	if (entity == NULL)
		return NULL;

	while ((node = rs_dll_next_from(&folder->properties, node)) != NULL) {
		property = to_property(node);
		ret = property_get(property, entity, &value);
		if (ret < 0) {
			ut_string_free(&info);
			ULOGE("property_get: %s", strerror(-ret));
			errno = -ret;
			return NULL;
		}
		old_info = info;
		ret = asprintf(&info, "%s%s: %s\n", info ? info : "",
				property->name, value);
		ut_string_free(&value);
		ut_string_free(&old_info);
		if (ret < 0) {
			info = NULL;
			ULOGE("asprintf error");
			errno = -ENOMEM;
			return NULL;
		}
	}

	return info == NULL ? strdup("") : info;
}
Esempio n. 6
0
int folder_entity_get_property(struct folder_entity *entity, const char *name,
		char **value)
{
	int ret = 0;
	struct rs_node *property_node;
	struct folder_property *property;
	bool is_array_access;
	unsigned index;

	if (entity == NULL || ut_string_is_invalid(name) || value == NULL)
		return -EINVAL;

	property_node = rs_dll_find_match(&entity->folder->properties,
			folder_property_match_str_array_name, name);
	if (property_node == NULL) {
		ULOGE("property \"%s\" not found for folder %s", name,
				entity->folder->name);
		return -ESRCH;
	}
	property = to_property(property_node);
	is_array_access = name[strlen(name) - 1] == ']';
	if (is_array_access && !folder_property_is_array(property)) {
		ULOGE("non-array property accessed as an array one");
		return -EINVAL;
	}


	if (is_array_access) {
		index = read_index(name);
		if (index == UINT_MAX)
			return -EINVAL;
		ret = property->geti(property, entity, index, value);
		if (ret < 0) {
			ULOGE("property->geti: %s", strerror(-ret));
			return ret;
		}
		if (*value == NULL) {
			*value = strdup("nil");
			if (*value == NULL)
				return -errno;
		}
	} else {
		ret = property_get(property, entity, value);
		if (ret < 0) {
			ULOGE("property_get: %s", strerror(-ret));
			return ret;
		}
	}

	return *value == NULL ? -errno : 0;
}
Esempio n. 7
0
static struct firmware *firmware_new(const char *path)
{
	int ret;
	const char *sha1;
	struct firmware *firmware;
	const char *firmware_repository_path =
			config_get(CONFIG_REPOSITORY_PATH);

	ULOGD("indexing firmware %s", path);

	firmware = calloc(1, sizeof(*firmware));
	if (firmware == NULL)
		return NULL;

	firmware->entity.folder = folder_find(FIRMWARES_FOLDER_NAME);
	if (ut_file_is_dir(path)) {
		firmware->path = realpath(path, NULL);
		if (firmware->path == NULL) {
			ret = -errno;
			ULOGE("strdup: %m");
			goto err;
		}
		ULOGI("real path is %s", firmware->path);
	} else {
		ret = asprintf(&firmware->path, "%s/%s",
				firmware_repository_path, path);
		if (ret == -1) {
			firmware->path = NULL;
			ULOGE("asprintf error");
			errno = -ENOMEM;
			goto err;
		}
	}

	/* force sha1 computation while in parallel section */
	sha1 = compute_sha1(firmware);
	if (sha1 == NULL)
		goto err;

	ret = mount_firmware(firmware);
	if (ret < 0)
		ULOGW("read_firmware_info failed: %s\n", strerror(-ret));

	ULOGD("indexing firmware %s done", path);

	return firmware;
err:
	firmware_delete(&firmware);

	return NULL;
}
Esempio n. 8
0
const char *folders_list(void)
{
	int ret;
	struct folder *folder = folders + FOLDERS_MAX;

	/* the result is cached */
	if (list != NULL)
		return list;

	while (folder-- > folders) {
		if (folder->name == NULL)
			continue;
		ret = ut_string_append(&list, "%s ", folder->name);
		if (ret < 0) {
			ULOGC("ut_string_append");
			errno = -ret;
			return NULL;
		}
	}
	if (list == NULL) {
		ULOGE("no folder registered, that _is_ weird");
		errno = ENOENT;
		return NULL;
	}
	if (list[0] != '\0')
		list[strlen(list) - 1] = '\0';

	return list;
}
Esempio n. 9
0
/* result must be freed with free */
static char *folder_request_friendly_name(struct folder *folder)
{
	int ret;
	const char *adjective;
	const char *name;
	char *friendly_name = NULL;
	unsigned max_names = rs_dll_get_count(&folders_names) *
				rs_dll_get_count(&folders_adjectives);

	errno = 0;
	if (rs_dll_get_count(&folder->entities) > max_names) {
		ULOGC("more than %u entities in folder %s, weird...", max_names,
				folder->name);
		errno = ENOMEM;
		return NULL;
	}

	do {
		adjective = pick_random_word(&folders_adjectives);
		name = pick_random_word(&folders_names);
		ut_string_free(&friendly_name); /* in case we loop */
		ret = asprintf(&friendly_name, "%s_%s", adjective, name);
		if (ret < 0) {
			ULOGE("asprintf error");
			errno = ENOMEM;
			return NULL;
		}
	} while (find_entity(folder, friendly_name) != NULL);

	return friendly_name;
}
Esempio n. 10
0
int folder_store(const char *folder_name, struct folder_entity *entity)
{
	struct folder_entity *needle;
	struct folder *folder;

	ULOGD("%s(%s, %p)", __func__, folder_name, entity);

	folder = folder_find(folder_name);
	if (folder == NULL)
		return -ENOENT;
	entity->folder = folder;

	needle = find_entity(folder, folder_entity_get_sha1(entity));
	if (needle != NULL) {
		ULOGE("entity %s already exists",
				folder_entity_get_sha1(entity));
		return -EEXIST;
	}

	rs_dll_push(&folder->entities, &entity->node);

	/* must be done after stored, because it's _drop which frees it */
	ut_string_free(&entity->name);
	entity->name = folder_request_friendly_name(folder);
	if (entity->name == NULL)
		return -errno;

	return 0;
}
Esempio n. 11
0
static void unmount_firmware(struct firmware *firmware)
{
	int ret;
	struct io_process process;
	const char *mount_dir =
			folder_entity_get_base_workspace(&firmware->entity);

	ret = io_process_init_prepare_launch_and_wait(&process,
			&process_default_parameters, NULL, "/bin/umount",
			mount_dir, NULL);
	if (ret < 0)
		ULOGE("umount %s failed: %m", mount_dir);
	else if (process.status != 0)
		ULOGE("umount %s exited with status %d", mount_dir,
				process.status);
}
Esempio n. 12
0
static int client_start(const struct sockaddr *addr, uint32_t addrlen)
{
  int res;
  res = pomp_ctx_connect(s_app.ctx, addr, addrlen);
  if (res < 0)
    ULOGE("pomp_ctx_connect: err=%d(%s)", res, strerror(-res));
  return res;
}
Esempio n. 13
0
static int firmware_preparation_start(struct preparation *preparation)
{
	int ret;
	struct firmware_preparation *firmware_preparation;
	struct firmware *firmware = NULL;
	char buf[0x200] = {0};
	char *pbuf = &buf[0];
	const char *uuid = buf + 5;
	const char *id = preparation->identification_string;

	if (ut_file_is_dir(id)) {
		ret = get_from_path(&firmware, id);
		if (ret < 0)
			return ret;
		if (firmware == NULL)
			firmware = firmware_new(id);
		return preparation->completion(preparation, &firmware->entity);
	}

	firmware_preparation = ut_container_of(preparation,
			struct firmware_preparation, preparation);

	ret = ut_process_read_from_output(&pbuf, 0x200, "\"%s\" \"%s\" "
			"\"%s\" \"%s\" \"%s\" \"%s\"",
			config_get(CONFIG_CURL_HOOK),
			"uuid",
			id,
			config_get(CONFIG_REPOSITORY_PATH),
			"", /* we don't know uuid yet, of course */
			config_get(CONFIG_VERBOSE_HOOK_SCRIPTS));
	if (ret < 0) {
		ULOGE("uuid retrieval failed");
		return ret;
	}

	ut_string_rstrip(pbuf);
	/*
	 * the uuid corresponds to an already registered firmware, nothing to
	 * do and we consider it a success
	 */
	if (uuid_already_registered(uuid)) {
		firmware = get_from_uuid(uuid);
		return preparation->completion(preparation, &firmware->entity);
	}

	ret = io_process_init_prepare_and_launch(&firmware_preparation->process,
			&(struct io_process_parameters){
				.stdout_sep_cb = preparation_progress_sep_cb,
				.out_sep1 = '\n',
				.out_sep2 = IO_SRC_SEP_NO_SEP2,
				.stderr_sep_cb = log_warn_src_sep_cb,
				.err_sep1 = '\n',
				.err_sep2 = IO_SRC_SEP_NO_SEP2,
				.timeout = PREPARATION_TIMEOUT,
				.signum = PREPARATION_TIMEOUT_SIGNAL,
			},
Esempio n. 14
0
static int store_word(struct rs_dll *list, const char *word)
{
	int ret;
	struct word *w;

	w = calloc(1, sizeof(*w));
	if (w == NULL) {
		ret = -errno;
		ULOGE("calloc: %s", strerror(-ret));
		return ret;
	}
	w->word = strdup(word);
	if (w->word == NULL) {
		ret = -errno;
		ULOGE("calloc: %s", strerror(-ret));
		free(w);
		return ret;
	}

	return rs_dll_enqueue(list, &w->node);
}
Esempio n. 15
0
static int load_words(const char *resources_dir, const char *list_name,
		struct rs_dll *list)
{
	int ret;
	char __attribute__((cleanup(ut_string_free))) *path = NULL;
	FILE __attribute__((cleanup(ut_file_close))) *f = NULL;

	ret = asprintf(&path, "%s/%s", resources_dir, list_name);
	if (ret == -1) {
		path = NULL;
		ULOGE("asprintf error");
		exit(1);
	}
	f = fopen(path, "rbe");
	if (f == NULL) {
		ret = -errno;
		ULOGE("failure opening %s: %s", path, strerror(-ret));
		return ret;
	}

	return store_word_list(list, f);
}
Esempio n. 16
0
static int property_get(struct folder_property *property,
		struct folder_entity *entity, char **value)
{
	char *suffix;
	int i;
	int ret;

	if (!folder_property_is_array(property))
		return property->get(property, entity, value);

	for (i = 0;; i++) {
		ret = property->geti(property, entity, i, &suffix);
		if (ret < 0) {
			ut_string_free(value);
			ULOGE("property->geti: %s", strerror(-ret));
			return ret;
		}
		if (ut_string_match(suffix, "nil")) {
			ut_string_free(&suffix);
			break;
		}
		ret = ut_string_append(value, "%s ", suffix);
		ut_string_free(&suffix);
		if (ret < 0) {
			ut_string_free(value);
			ULOGE("ut_string_append: %s", strerror(-ret));
			return ret;
		}
	}
	if (*value == NULL) {
		*value = strdup(" ");
		if (*value == NULL)
			return -errno;
	}
	(*value)[strlen(*value) - 1] = '\0';

	return 0;
}
Esempio n. 17
0
int folder_register_properties(const char *folder,
		struct folder_property *properties)
{
	int ret;
	struct folder_property *property = properties;

	for (property = properties; property->name != NULL; property++) {
		ret = folder_register_property(folder, property);
		if (ret < 0) {
			ULOGE("folder_register_property: %s", strerror(-ret));
			return ret;
		}
	}

	return 0;
}
Esempio n. 18
0
static void preparation_progress_sep_cb(struct io_src_sep *sep, char *chunk,
		unsigned len)
{
	int ret;
	struct firmware_preparation *firmware_preparation;
	struct preparation *preparation;
	struct io_process *process;

	if (len == 0)
		return;

	process = ut_container_of(sep, struct io_process, stdout_src);
	firmware_preparation = ut_container_of(process,
			struct firmware_preparation, process);
	preparation = &firmware_preparation->preparation;

	chunk[len] = '\0';
	ut_string_rstrip(chunk);
	ULOGD("%s "FIRMWARES_FOLDER_NAME" preparation %s",
			preparation->identification_string, chunk);

	/*
	 * rearm the "watch dog", we don't want to abort a working dl because it
	 * took too long
	 */
	ret = io_process_set_timeout(process, PREPARATION_TIMEOUT,
			PREPARATION_TIMEOUT_SIGNAL);
	if (ret < 0)
		ULOGW("resetting firmware preparation timeout failed: %s",
				strerror(-ret));

	if (ut_string_match_prefix(chunk, "destination_file=")) {
		firmware_preparation->destination_file = strdup(chunk + 17);
		/*
		 * here the hook is stuck in a sleep, waiting for us to say it
		 * it can nicely die
		 */
		io_process_signal(process, SIGUSR1);
	} else {
		ret = firmwared_notify(FWD_ANSWER_PREPARE_PROGRESS,
				FWD_FORMAT_ANSWER_PREPARE_PROGRESS,
				preparation->seqnum, preparation->folder,
				preparation->identification_string, chunk);
		if (ret < 0)
			ULOGE("firmwared_notify: %s", strerror(-ret));
	}
}
Esempio n. 19
0
const char *folder_entity_get_base_workspace(struct folder_entity *entity)
{
	int ret;

	if (entity->base_workspace == NULL) {
		ret = asprintf(&entity->base_workspace, "%s/%s/%s",
				config_get(CONFIG_MOUNT_PATH),
				entity->folder->name,
				folder_entity_get_sha1(entity));
		if (ret < 0) {
			entity->base_workspace = NULL;
			ULOGE("asprintf base_workspace error");
			ret = -ENOMEM;
			return NULL;
		}
	}

	return entity->base_workspace;
}
Esempio n. 20
0
static void firmware_preparation_termination(struct io_process *process,
		pid_t pid, int status)
{
	int ret;
	struct firmware_preparation *firmware_preparation;
	struct preparation *preparation;
	struct firmware *firmware;

	firmware_preparation = ut_container_of(process,
			struct firmware_preparation, process);
	io_mon_remove_source(firmwared_get_mon(),
		io_process_get_src(&firmware_preparation->process));

	preparation = &firmware_preparation->preparation;

	if (status != 0) {
		if (WIFSIGNALED(status)) {
			ULOGD("curl hook terminated on signal %s",
					strsignal(WTERMSIG(status)));
		} else {
			if (WTERMSIG(status) != SIGUSR1) {
				ULOGE("curl hook error, use absolute paths");
				ret = -EINVAL;
				goto err;
			}
		}
	}

	/* TODO the following may block a long time */
	firmware = firmware_new(firmware_preparation->destination_file);

	preparation->completion(preparation, &firmware->entity);

	return;
err:
	firmwared_notify(FWD_ANSWER_ERROR, FWD_FORMAT_ANSWER_ERROR,
			preparation->seqnum, -ret, strerror(-ret));

	preparation->completion(preparation, NULL);
}
Esempio n. 21
0
static int entity_completion(struct preparation *preparation,
			struct folder_entity *entity)
{
	struct folder *folder;
	int ret = 0;

	if (entity == NULL) {
		ULOGW("%*s creation failed for identification string %s",
				(int)strlen(preparation->folder) - 1,
				preparation->folder,
				preparation->identification_string);
		ret = -EINVAL;
		goto out;
	}

	/* if already prepared, nothing to be done */
	folder = folder_find(preparation->folder);
	if (find_entity(folder, folder_entity_get_sha1(entity)))
		goto out;
	/* folder_store transfers the ownership of the entity to the folder */
	ret = folder_store(preparation->folder, entity);
	if (ret < 0) {
		do_drop(entity, false);
		ULOGE("folder_store: %s", strerror(-ret));
		goto out;
	}

	ret = 0;
out:
	if (ret >= 0)
		firmwared_notify(FWD_ANSWER_PREPARED,
				FWD_FORMAT_ANSWER_PREPARED,
				preparation->seqnum, preparation->folder,
				folder_entity_get_sha1(entity), entity->name);

	preparation->has_ended = true;

	return ret;
}
Esempio n. 22
0
static int store_word_list(struct rs_dll *list, FILE *f)
{
	int ret;
	char *cret;
	char buf[0x100];
	char *word;

	rs_dll_init(list, NULL);

	while ((cret = fgets(buf, 0xFF, f)) != NULL) {
		buf[0xFF] = '\0';
		word = ut_string_strip(buf);
		if (strlen(word) != 0) {
			ret = store_word(list, word);
			if (ret < 0) {
				ULOGE("store_word: %s", strerror(-ret));
				return ret;
			}
		}
	}

	return 0;
}
Esempio n. 23
0
static void client_event_cb(struct pomp_ctx *ctx, enum pomp_event event,
                struct pomp_conn *conn, const struct pomp_msg *msg,
                void *userdata)
{
  int fd, msgid;
  unsigned int bufsize;
  void *video_buffer;
  GstVideoFormat videoformat;
  unsigned int width, height;

  switch (event) {
    case POMP_EVENT_CONNECTED:
      ULOGI("connected to pimp user filter");
      break;
    case POMP_EVENT_DISCONNECTED:
      ULOGI("disconnected from pimp user filter");
      break;
    case POMP_EVENT_MSG:
      switch (msgid = pomp_msg_get_id(msg)) {
        case SEND_FD:
          pomp_msg_read(msg, "%x%u%u%u%u", &fd, &bufsize, &videoformat, &width, &height);
          ULOGI("received a FD from pimp: %d", fd);
          video_buffer = mmap(NULL, bufsize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
          s_app.process(video_buffer, bufsize, videoformat, width, height, s_app.priv);
          pomp_ctx_send(ctx, BUFFER_PROCESSING_DONE, NULL);
          break;
        default:
          ULOGW("received unknown message id from pimp : %d", msgid);
          break;
      }
      break;
    default:
      ULOGE("Unknown event: %d", event);
      break;
  }
}
Esempio n. 24
0
int folder_entity_set_property(struct folder_entity *entity, const char *name,
		const char *value)
{
	int ret;
	unsigned index;
	bool is_array_access;
	struct rs_node *property_node;
	struct folder_property *property;
	wordexp_t __attribute__((cleanup(wordfree)))we = {0};

	if (entity == NULL || ut_string_is_invalid(name) ||
			ut_string_is_invalid(value))
		return -EINVAL;

	property_node = rs_dll_find_match(&entity->folder->properties,
			folder_property_match_str_array_name, name);
	if (property_node == NULL) {
		ULOGE("property \"%s\" not found for folder %s", name,
				entity->folder->name);
		return -ESRCH;
	}
	property = to_property(property_node);
	is_array_access = name[strlen(name) - 1] == ']';
	if (is_array_access && !folder_property_is_array(property)) {
		ULOGE("non-array property accessed as an array one");
		return -EINVAL;
	}

	if (is_array_access) {
		if (property->seti == NULL) {
			ULOGE("property %s.%s[] is read-only",
					entity->folder->name, name);
			return -EPERM;
		}
		index = read_index(name);
		if (index == UINT_MAX)
			return -EINVAL;
		ret = property->seti(property, entity, index, value);
		if (ret < 0) {
			ULOGE("property->seti: %s", strerror(-ret));
			return ret;
		}
	} else {
		if (folder_property_is_array(property)) {
			if (property->seti == NULL) {
				ULOGE("property %s.%s[] is read-only",
						entity->folder->name, name);
				return -EPERM;
			}
			ret = wordexp(value, &we, 0);
			if (ret != 0) {
				ULOGE("wordexp error %d", ret);
				return ret == WRDE_NOSPACE ? ENOMEM : EINVAL;
			}

			for (index = 0; index < we.we_wordc; index++) {
				ret = property->seti(property, entity, index,
						we.we_wordv[index]);
				if (ret < 0) {
					ULOGE("property->seti: %s",
							strerror(-ret));
					return ret;
				}
			}
			ret = property->seti(property, entity, index, "nil");
			if (ret < 0) {
				ULOGE("property->seti: %s", strerror(-ret));
				return ret;
			}
		} else {
			if (property->set == NULL) {
				ULOGE("property %s.%s is read-only",
						entity->folder->name, name);
				return -EPERM;
			}
			ret = property->set(property, entity, value);
			if (ret < 0) {
				ULOGE("property->set: %s", strerror(-ret));
				return ret;
			}
		}
	}

	return 0;
}