summaryrefslogtreecommitdiffstats
path: root/README-AGL.md
blob: 92a2c46a2dc3a605213019fc7f32404e96e53217 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
Overview
========

The
[AGL Project](https://www.automotivelinux.org/) is an automotive-specific
development environment that provides a Linux distribution
[AGL UCB](https://www.automotivelinux.org/software/unified-code-base).

AGL uses layers designed to be compatible with the
[Yocto Project](https://www.yoctoproject.org) and the
[OpenEmbedded Project (OE)](https://www.openembedded.org/wiki/Main_Page).

This section provides information about the layers used by the AGL Project:

* **`meta-agl`**: Minimal set of software needed to create an AGL distribution
  used to boot a system.
  AGL profiles are built on top of this minimal set of software.

* **`meta-agl-demo`**: Provides a reference or demo platform and applications
  for the AGL Distribution.
  The reference UI is part of the `meta-agl-demo` layer.

* **`meta-agl-devel`**: Contains components under development or being tested.
  This layer also contains software packages that OEMs need but do not exist
  in AGL.


**WRITER NOTES:** The content for this section is the `README-AGL.md`
  file that is in the `meta-agl` layer, which is a Gerrit layer.
  You can clone the layer using this command:

    ```
    $ git clone https://gerrit.automotivelinux.org/gerrit/AGL/meta-agl
color: #e6db74 } /* Literal.String.Affix */ .highlight .sb { color: #e6db74 } /* Literal.String.Backtick */ .highlight .sc { color: #e6db74 } /* Literal.String.Char */ .highlight .dl { color: #e6db74 } /* Literal.String.Delimiter */ .highlight .sd { color: #e6db74 } /* Literal.String.Doc */ .highlight .s2 { color: #e6db74 } /* Literal.String.Double */ .highlight .se { color: #ae81ff } /* Literal.String.Escape */ .highlight .sh { color: #e6db74 } /* Literal.String.Heredoc */ .highlight .si { color: #e6db74 } /* Literal.String.Interpol */ .highlight .sx { color: #e6db74 } /* Literal.String.Other */ .highlight .sr { color: #e6db74 } /* Literal.String.Regex */ .highlight .s1 { color: #e6db74 } /* Literal.String.Single */ .highlight .ss { color: #e6db74 } /* Literal.String.Symbol */ .highlight .bp { color: #f8f8f2 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #a6e22e } /* Name.Function.Magic */ .highlight .vc { color: #f8f8f2 } /* Name.Variable.Class */ .highlight .vg { color: #f8f8f2 } /* Name.Variable.Global */ .highlight .vi { color: #f8f8f2 } /* Name.Variable.Instance */ .highlight .vm { color: #f8f8f2 } /* Name.Variable.Magic */ .highlight .il { color: #ae81ff } /* Literal.Number.Integer.Long */ } @media (prefers-color-scheme: light) { .highlight .hll { background-color: #ffffcc } .highlight .c { color: #888888 } /* Comment */ .highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ .highlight .k { color: #008800; font-weight: bold } /* Keyword */ .highlight .ch { color: #888888 } /* Comment.Hashbang */ .highlight .cm { color: #888888 } /* Comment.Multiline */ .highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */ .highlight .cpf { color: #888888 } /* Comment.PreprocFile */ .highlight .c1 { color: #888888 } /* Comment.Single */ .highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */ .highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .gr { color: #aa0000 } /* Generic.Error */ .highlight .gh { color: #333333 } /* Generic.Heading */ .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ .highlight .go { color: #888888 } /* Generic.Output */ .highlight .gp { color: #555555 } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #666666 } /* Generic.Subheading */ .highlight .gt { color: #aa0000 } /* Generic.Traceback */ .highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #008800 } /* Keyword.Pseudo */ .highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */ }
/*
 * Copyright (C) 2015, 2016 "IoT.bzh"
 * Author: José Bollo <jose.bollo@iot.bzh>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#define _GNU_SOURCE

#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#include <curl/curl.h>

#include "curl-wrap.h"
#include "escape.h"


/* internal representation of buffers */
struct buffer {
	size_t size;
	char *data;
};

static const char* curl_concatenate_args(const char * const *args, const char *sep, size_t *length)
{
	int i;
	size_t lq;
	const char *null;
	char *result, *front;

	/* ensure args */
	if (!args) {
		null = NULL;
		args = &null;
	}
	if (!sep)
		sep = "";

	/* compute lengths */
	lq = 0;
	i = 0;
	while (args[i]) {
		lq += strlen(args[i]);
		i++;
	}

	/* allocation */
	result = malloc(1 + lq + (i ? i - 1 : 0) * strlen(sep));
	if (result) {
		/* make the resulting args string contenated */
		i = 0;
		front = result;
		while (args[i]) {
			if (i) {
				front = stpcpy(front, sep);
			}
			front = stpcpy(front, args[i]);
			i++;
		}
		*front = 0;
		if (length)
			*length = (size_t)(front - result);
	}
	return result;
}

/* write callback for filling buffers with the response */
static size_t write_callback(char *ptr, size_t size, size_t nmemb, void *userdata)
{
	struct buffer *buffer = userdata;
	size_t sz = size * nmemb;
	size_t old_size = buffer->size;
	size_t new_size = old_size + sz;
	char *data = realloc(buffer->data, new_size + 1);
	if (!data)
		return 0;
	memcpy(&data[old_size], ptr, sz);
	data[new_size] = 0;
	buffer->size = new_size;
	buffer->data = data;
	return sz;
}

/*
 * Perform the CURL operation for 'curl' and put the result in
 * memory. If 'result' isn't NULL it receives the returned content
 * that then must be freed. If 'size' isn't NULL, it receives the
 * size of the returned content. Note that if not NULL, the real
 * content is one byte greater than the read size and the last byte
 * zero. This facility allows to handle the returned content as a
 * null terminated C-string.
 */
int curl_wrap_perform(CURL *curl, char **result, size_t *size)
{
	int rc;
	struct buffer buffer;
	CURLcode code;

	/* init tthe buffer */
	buffer.size = 0;
	buffer.data = NULL;

	/* Perform the request, res will get the return code */
	curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
	curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);

	/* Perform the request, res will get the return code */
	code = curl_easy_perform(curl);
	rc = code == CURLE_OK;

	/* Check for no errors */
	if (rc) {
		/* no error */
		if (size)
			*size = buffer.size;
		if (result)
			*result = buffer.data;
		else
			free(buffer.data);
	} else {
		/* had error */
		if (size)
			*size = 0;
		if (result)
			*result = NULL;
		free(buffer.data);
	}

	return rc;
}

void curl_wrap_do(CURL *curl, void (*callback)(void *closure, int status, CURL *curl, const char *result, size_t size), void *closure)
{
	int rc;
	char *result;
	size_t size;
	char errbuf[CURL_ERROR_SIZE];

	curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf);
	rc = curl_wrap_perform(curl, &result, &size);
	if (rc)
		callback(closure, rc, curl, result, size);
	else
		callback(closure, rc, curl, errbuf, 0);
	free(result);
	curl_easy_cleanup(curl);
}

int curl_wrap_content_type_is(CURL *curl, const char *value)
{
	char *actual;
	CURLcode code;

	code = curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &actual);
	if (code != CURLE_OK || !actual)
		return 0;

	return !strncasecmp(actual, value, strcspn(actual, "; "));
}

long curl_wrap_response_code_get(CURL *curl)
{
	long rc;
	CURLcode code;

	code = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &rc);
	return (code == CURLE_OK) ? rc : 0;
}

CURL *curl_wrap_prepare_get_url(const char *url)
{
	CURL *curl;
	CURLcode code;

	curl = curl_easy_init();
	if(curl) {
		code = curl_easy_setopt(curl, CURLOPT_URL, url);
		if (code == CURLE_OK)
			return curl;
		curl_easy_cleanup(curl);
	}
	return NULL;
}

CURL *curl_wrap_prepare_get(const char *base, const char *path, const char * const *args)
{
	CURL *res;
	char *url;

	url = escape_url(base, path, args, NULL);
	res = url ? curl_wrap_prepare_get_url(url) : NULL;
	free(url);
	return res;
}

int curl_wrap_add_header(CURL *curl, const char *header)
{
	int rc;
	struct curl_slist *list;

	list = curl_slist_append(NULL, header);
	rc = list ? curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list) == CURLE_OK : 0;
/*
	curl_slist_free_all(list);
*/
	return rc;
}

int curl_wrap_add_header_value(CURL *curl, const char *name, const char *value)
{
	char *h;
	int rc;

	rc = asprintf(&h, "%s: %s", name, value);
	rc = rc < 0 ? 0 : curl_wrap_add_header(curl, h);
	free(h);
	return rc;
}


CURL *curl_wrap_prepare_post_url_data(const char *url, const char *datatype, const char *data, size_t szdata)
{
	CURL *curl;

	curl = curl_easy_init();
	if (curl
	&& CURLE_OK == curl_easy_setopt(curl, CURLOPT_URL, url)
	&& (!szdata || CURLE_OK == curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, szdata))
	&& CURLE_OK == curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data)
	&& (!datatype || curl_wrap_add_header_value(curl, "content-type", datatype)))
		return curl;
	curl_easy_cleanup(curl);
	return NULL;
}

static CURL *curl_wrap_prepare_post(const char *base, const char *path, int unescape_flag, const char *separator, const char * const *args, const char *simple_args)
{
	CURL *res;
	char *url;
	const char *data = NULL;
	size_t szdata = 0;

	url = escape_url(base, path, NULL, NULL);
	if(args) {
		data = unescape_flag ?
			curl_concatenate_args(args, separator, &szdata) :
			escape_args(args, &szdata);
	}
	else {
		data = unescape_flag ?
			escape_str(simple_args, &szdata) :
			simple_args;
	}
	szdata = szdata ? szdata : strlen(data);

	res = url ? curl_wrap_prepare_post_url_data(url, NULL, data, szdata) : NULL;
	free(url);
	return res;
}

CURL *curl_wrap_prepare_post_simple_unescaped(const char *base, const char *path, const char *args)
{
	return curl_wrap_prepare_post(base, path, 1, NULL, NULL, args);
}

CURL *curl_wrap_prepare_post_simple_escaped(const char *base, const char *path, char *args)
{
	return curl_wrap_prepare_post(base, path, 0, NULL, NULL, args);
}

CURL *curl_wrap_prepare_post_unescaped(const char *base, const char *path, const char *separator, const char * const *args)
{
	return curl_wrap_prepare_post(base, path, 1, separator, args, NULL);
}

CURL *curl_wrap_prepare_post_escaped(const char *base, const char *path, const char * const *args)
{
	return curl_wrap_prepare_post(base, path, 0, NULL, args, NULL);
}

/* vim: set colorcolumn=80: */