From 6caade489f8bd15dccdde6c69452d920ead2201e Mon Sep 17 00:00:00 2001 From: José Bollo Date: Thu, 2 Aug 2018 18:48:57 +0200 Subject: Add the external binding feature MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit introduce two new features: TODO: manage security by setting correct Smack label to the exported files Bugs-AGL: SPEC-1439 Bugs-AGL: SPEC-1663 Change-Id: I70aad7d523ece7a2ae0058b79708a02ef81144e2 Signed-off-by: José Bollo --- conf/system/afm-user-setup@.service | 1 + conf/unit/afm-unit-debug.conf.in | 36 +++++++++- conf/unit/afm-unit.conf.in | 36 +++++++++- conf/unit/generate-unit-conf/Makefile | 2 +- conf/unit/generate-unit-conf/afm-unit | 6 +- conf/unit/generate-unit-conf/binder.inc | 5 +- conf/unit/generate-unit-conf/provided-api.inc | 72 ++++++++++++++++++++ conf/unit/generate-unit-conf/provided-binding.inc | 33 ++++++++++ conf/unit/generate-unit-conf/provided.inc | 80 ----------------------- conf/unit/generate-unit-conf/service.inc | 10 ++- docs/2.2-config.xml.md | 27 ++++++-- src/wgt-json.c | 26 ++++++++ src/wgt-strings.c | 2 + src/wgt-strings.h | 2 + 14 files changed, 243 insertions(+), 95 deletions(-) create mode 100644 conf/unit/generate-unit-conf/provided-api.inc create mode 100644 conf/unit/generate-unit-conf/provided-binding.inc delete mode 100644 conf/unit/generate-unit-conf/provided.inc diff --git a/conf/system/afm-user-setup@.service b/conf/system/afm-user-setup@.service index 40c3427..ba6f78e 100644 --- a/conf/system/afm-user-setup@.service +++ b/conf/system/afm-user-setup@.service @@ -6,6 +6,7 @@ Type=oneshot ExecStart=-/bin/sh -c "/bin/mkdir /run/user/%i; /bin/chown %i:%i /run/user/%i; /usr/bin/chsmack -a '*' /run/user/%i" ExecStart=-/bin/sh -c "/bin/mkdir /run/user/%i/apis; /bin/chown %i:%i /run/user/%i/apis; /usr/bin/chsmack -a '*' /run/user/%i/apis" ExecStart=-/bin/sh -c "/bin/mkdir /run/user/%i/apis/ws; /bin/chown %i:%i /run/user/%i/apis/ws; /usr/bin/chsmack -a '*' /run/user/%i/apis/ws" +ExecStart=-/bin/sh -c "/bin/mkdir /run/user/%i/apis/link; /bin/chown %i:%i /run/user/%i/apis/link; /usr/bin/chsmack -a '*' /run/user/%i/apis/link" ExecStart=-/bin/sh -c "/bin/ln -sf /run/platform/display/wayland-0 /run/user/%i/wayland-0; /bin/chown %i:%i /run/user/%i/wayland-0; /usr/bin/chsmack -a '*' /run/user/%i/wayland-0" diff --git a/conf/unit/afm-unit-debug.conf.in b/conf/unit/afm-unit-debug.conf.in index 55af22d..01d3c2e 100644 --- a/conf/unit/afm-unit-debug.conf.in +++ b/conf/unit/afm-unit-debug.conf.in @@ -111,6 +111,12 @@ After=user@%i.service ConditionSecurity=smack %nl # Automatic bound to required api +{{#required-binding}} +{{#value=extern}} +BindsTo=afm-link-{{name}}@%i.service +After=afm-link-{{name}}@%i.service +{{/value=extern}} +{{/required-binding}} {{#required-api}} {{#value=auto|ws}} BindsTo=afm-api-{{name}}@%i.service @@ -119,8 +125,8 @@ After=afm-api-{{name}}@%i.service {{/required-api}} {{#provided-api}} {{#value=ws|auto}} -Requires=afm-api-{{name}}@%i.service -After=afm-api-{{name}}@%i.service +Requires=afm-api-{{name}}@%i.socket +After=afm-api-{{name}}@%i.socket {{/value=ws|auto}} {{/provided-api}} %nl @@ -174,10 +180,13 @@ ExecStart=/usr/bin/afb-daemon \ {{#required-api}} \ {{#value=auto|ws}}--ws-client=unix:@afm_users_rundir@/%i/apis/ws/{{name}}{{/value=auto|ws}} \ {{#value=dbus}}--dbus-client={{name}}{{/value=dbus}} \ - {{#value=link}}--binding=@afm_users_rundir@/%i/apis/lib/{{name}}{{/value=link}} \ {{#value=cloud}}--cloud-client={{name}}{{/value=cloud}} \ {{#value=local}}--binding={{:#metadata.install-dir}}/{{name}}{{/value=local}} \ {{/required-api}} \ + {{#required-binding}} \ + {{#value=local}}--binding={{:#metadata.install-dir}}/{{name}}{{/value=local}} \ + {{#value=extern}}--binding=@afm_users_rundir@/%i/apis/link/{{name}}{{/value=extern}} \ + {{/required-binding}} \ {{#provided-api}} \ {{#value=auto|ws}}--ws-server=sd:{{name}}{{/value=auto|ws}} \ {{#value=dbus}}--dbus-server={{name}}{{/value=dbus}} \ @@ -250,6 +259,27 @@ Service=afm-{{#required-permission.urn:AGL:permission::public:hidden}}service{{/ %end systemd-unit {{/value=ws|auto}} {{/provided-api}} +;------------------------------------------------------------------------------- +;---- P R O V I D E D B I N D I N G ---- +;------------------------------------------------------------------------------- +{{#provided-binding}} +;------------------------------------------------------------------------------- +;---- T H E S E R V I C E O F T H E B I N D I N G ---- +;------------------------------------------------------------------------------- +%begin systemd-unit +# auto generated by wgtpkg-unit for {{:id}} version {{:version}} target {{:#target}} of {{:idaver}} +%systemd-unit system +%systemd-unit service afm-link-{{name}}@ +[Unit] +Description=Provides binding {{name}} for user %i +Requires=afm-user-setup@%i.service +After=afm-user-setup@%i.service +[Service] +Type=oneshot +RemainAfterExit=yes +ExecStart=/bin/ln -s {{:#metadata.install-dir}}/{{value}} @afm_users_rundir@/%i/apis/link/{{name}} +%end systemd-unit +{{/provided-binding}} {{/targets}} ;--------------------------------------------------------------------------------- ; End of file afm-unit.conf mode DEVEL diff --git a/conf/unit/afm-unit.conf.in b/conf/unit/afm-unit.conf.in index 0cbe103..74c57ea 100644 --- a/conf/unit/afm-unit.conf.in +++ b/conf/unit/afm-unit.conf.in @@ -111,6 +111,12 @@ After=user@%i.service ConditionSecurity=smack %nl # Automatic bound to required api +{{#required-binding}} +{{#value=extern}} +BindsTo=afm-link-{{name}}@%i.service +After=afm-link-{{name}}@%i.service +{{/value=extern}} +{{/required-binding}} {{#required-api}} {{#value=auto|ws}} BindsTo=afm-api-{{name}}@%i.service @@ -119,8 +125,8 @@ After=afm-api-{{name}}@%i.service {{/required-api}} {{#provided-api}} {{#value=ws|auto}} -Requires=afm-api-{{name}}@%i.service -After=afm-api-{{name}}@%i.service +Requires=afm-api-{{name}}@%i.socket +After=afm-api-{{name}}@%i.socket {{/value=ws|auto}} {{/provided-api}} %nl @@ -174,10 +180,13 @@ ExecStart=/usr/bin/afb-daemon \ {{#required-api}} \ {{#value=auto|ws}}--ws-client=unix:@afm_users_rundir@/%i/apis/ws/{{name}}{{/value=auto|ws}} \ {{#value=dbus}}--dbus-client={{name}}{{/value=dbus}} \ - {{#value=link}}--binding=@afm_users_rundir@/%i/apis/lib/{{name}}{{/value=link}} \ {{#value=cloud}}--cloud-client={{name}}{{/value=cloud}} \ {{#value=local}}--binding={{:#metadata.install-dir}}/{{name}}{{/value=local}} \ {{/required-api}} \ + {{#required-binding}} \ + {{#value=local}}--binding={{:#metadata.install-dir}}/{{name}}{{/value=local}} \ + {{#value=extern}}--binding=@afm_users_rundir@/%i/apis/link/{{name}}{{/value=extern}} \ + {{/required-binding}} \ {{#provided-api}} \ {{#value=auto|ws}}--ws-server=sd:{{name}}{{/value=auto|ws}} \ {{#value=dbus}}--dbus-server={{name}}{{/value=dbus}} \ @@ -250,6 +259,27 @@ Service=afm-{{#required-permission.urn:AGL:permission::public:hidden}}service{{/ %end systemd-unit {{/value=ws|auto}} {{/provided-api}} +;------------------------------------------------------------------------------- +;---- P R O V I D E D B I N D I N G ---- +;------------------------------------------------------------------------------- +{{#provided-binding}} +;------------------------------------------------------------------------------- +;---- T H E S E R V I C E O F T H E B I N D I N G ---- +;------------------------------------------------------------------------------- +%begin systemd-unit +# auto generated by wgtpkg-unit for {{:id}} version {{:version}} target {{:#target}} of {{:idaver}} +%systemd-unit system +%systemd-unit service afm-link-{{name}}@ +[Unit] +Description=Provides binding {{name}} for user %i +Requires=afm-user-setup@%i.service +After=afm-user-setup@%i.service +[Service] +Type=oneshot +RemainAfterExit=yes +ExecStart=/bin/ln -s {{:#metadata.install-dir}}/{{value}} @afm_users_rundir@/%i/apis/link/{{name}} +%end systemd-unit +{{/provided-binding}} {{/targets}} ;--------------------------------------------------------------------------------- ; End of file afm-unit.conf mode RELEASE diff --git a/conf/unit/generate-unit-conf/Makefile b/conf/unit/generate-unit-conf/Makefile index 5f5346b..562f025 100644 --- a/conf/unit/generate-unit-conf/Makefile +++ b/conf/unit/generate-unit-conf/Makefile @@ -2,7 +2,7 @@ MAIN = afm-unit -FILES = $(MAIN) binder.inc provided.inc service.inc Makefile +FILES = $(MAIN) binder.inc provided-api.inc provided-binding.inc service.inc Makefile DIR = .. diff --git a/conf/unit/generate-unit-conf/afm-unit b/conf/unit/generate-unit-conf/afm-unit index 40a56fc..99d986d 100644 --- a/conf/unit/generate-unit-conf/afm-unit +++ b/conf/unit/generate-unit-conf/afm-unit @@ -53,6 +53,8 @@ define( `UNIT_NAME_SERVICE', `UNIT_NAME_BASE%i.service') define( `UNIT_NAME_API_BASE', `afm-api-$1') define( `UNIT_NAME_API_SERVICE', `UNIT_NAME_API_BASE($1)@$2.service') define( `UNIT_NAME_API_SOCKET', `UNIT_NAME_API_BASE($1)@$2.socket') +define( `UNIT_NAME_BINDING_BASE', `afm-link-$1') +define( `UNIT_NAME_BINDING_SERVICE', `UNIT_NAME_BINDING_BASE($1)@$2.service') define( `APP_DATA_DIR', `/home/%i/app-data') define( `USER_RUN_DIR', `@afm_users_rundir@/%i') define( `DEBUGGING_DIR', `@afm_platform_rundir@/debug') @@ -144,7 +146,9 @@ divert(0)dnl include(service.inc) -include(provided.inc) +include(provided-api.inc) + +include(provided-binding.inc) {{/targets}} ;--------------------------------------------------------------------------------- diff --git a/conf/unit/generate-unit-conf/binder.inc b/conf/unit/generate-unit-conf/binder.inc index 98efd4e..57f4166 100644 --- a/conf/unit/generate-unit-conf/binder.inc +++ b/conf/unit/generate-unit-conf/binder.inc @@ -33,10 +33,13 @@ ENDIF \ {{#required-api}} \ ON_VALUE(auto|ws, --ws-client=unix:USER_RUN_DIR/apis/ws/{{name}}) \ ON_VALUE(dbus, --dbus-client={{name}}) \ - ON_VALUE(link, --binding=USER_RUN_DIR/apis/lib/{{name}}) \ ON_VALUE(cloud, --cloud-client={{name}}) \ ON_VALUE(local, --binding={{:#metadata.install-dir}}/{{name}}) \ {{/required-api}} \ + {{#required-binding}} \ + ON_VALUE(local, --binding={{:#metadata.install-dir}}/{{name}}) \ + ON_VALUE(extern, --binding=USER_RUN_DIR/apis/link/{{name}}) \ + {{/required-binding}} \ {{#provided-api}} \ ON_VALUE(auto|ws, --ws-server=sd:{{name}}) \ ON_VALUE(dbus, --dbus-server={{name}}) \ diff --git a/conf/unit/generate-unit-conf/provided-api.inc b/conf/unit/generate-unit-conf/provided-api.inc new file mode 100644 index 0000000..8a667a9 --- /dev/null +++ b/conf/unit/generate-unit-conf/provided-api.inc @@ -0,0 +1,72 @@ +dnl vim: set filetype=sysctl.conf.m4 syntax=sysctl.conf.m4: +;------------------------------------------------------------------------------- +;---- P R O V I D E D A P I S ---- +;------------------------------------------------------------------------------- + +{{#provided-api}} + +;------------------------------------------------------------------------------- +;---- T H E S E R V I C E O F T H E A P I ---- +;------------------------------------------------------------------------------- +%begin systemd-unit + +# auto generated by wgtpkg-unit for {{:id}} version {{:version}} target {{:#target}} of {{:idaver}} + +%systemd-unit system +%systemd-unit service UNIT_NAME_API_BASE({{name}})@ + +[Unit] +Description=Provides api {{name}} for user %i +X-AFM-API-TYPE={{value}} + +Requires=afm-user-setup@%i.service +After=afm-user-setup@%i.service + +{{#value=ws|auto}} +Requires=UNIT_NAME_API_BASE({{name}})@%i.socket +After=UNIT_NAME_API_BASE({{name}})@%i.socket +{{/value=ws|auto}} + +[Service] +Type=oneshot +RemainAfterExit=yes +{{#value=ws|auto}} +ExecStart=/bin/true +{{/value=ws|auto}} + +%end systemd-unit + + +;------------------------------------------------------------------------------- +;---- T H E S O C K E T O F T H E A P I ---- +;------------------------------------------------------------------------------- +{{#value=ws|auto}} + +%begin systemd-unit + +# auto generated by wgtpkg-unit for {{:id}} version {{:version}} target {{:#target}} of {{:idaver}} + +%systemd-unit system +%systemd-unit socket UNIT_NAME_API_BASE({{name}})@ +[Unit] +Description=Provides websocket api {{name}} for user %i +Requires=afm-user-setup@%i.service +After=afm-user-setup@%i.service +DefaultDependencies=no + +[Socket] +SmackLabel=* +SmackLabelIPIn=System +SmackLabelIPOut=System +ListenStream=USER_RUN_DIR/apis/ws/{{name}} +FileDescriptorName={{name}} +Service=UNIT_NAME_SERVICE + +%end systemd-unit + + +{{/value=ws|auto}} + +{{/provided-api}} + + diff --git a/conf/unit/generate-unit-conf/provided-binding.inc b/conf/unit/generate-unit-conf/provided-binding.inc new file mode 100644 index 0000000..a5636ee --- /dev/null +++ b/conf/unit/generate-unit-conf/provided-binding.inc @@ -0,0 +1,33 @@ +dnl vim: set filetype=sysctl.conf.m4 syntax=sysctl.conf.m4: +;------------------------------------------------------------------------------- +;---- P R O V I D E D B I N D I N G ---- +;------------------------------------------------------------------------------- + +{{#provided-binding}} + +;------------------------------------------------------------------------------- +;---- T H E S E R V I C E O F T H E B I N D I N G ---- +;------------------------------------------------------------------------------- +%begin systemd-unit + +# auto generated by wgtpkg-unit for {{:id}} version {{:version}} target {{:#target}} of {{:idaver}} + +%systemd-unit system +%systemd-unit service UNIT_NAME_BINDING_BASE({{name}})@ + +[Unit] +Description=Provides binding {{name}} for user %i + +Requires=afm-user-setup@%i.service +After=afm-user-setup@%i.service + +[Service] +Type=oneshot +RemainAfterExit=yes +ExecStart=/bin/ln -s {{:#metadata.install-dir}}/{{value}} USER_RUN_DIR/apis/link/{{name}} + +%end systemd-unit + +{{/provided-binding}} + + diff --git a/conf/unit/generate-unit-conf/provided.inc b/conf/unit/generate-unit-conf/provided.inc deleted file mode 100644 index 267e2ed..0000000 --- a/conf/unit/generate-unit-conf/provided.inc +++ /dev/null @@ -1,80 +0,0 @@ -dnl vim: set filetype=sysctl.conf.m4 syntax=sysctl.conf.m4: -;------------------------------------------------------------------------------- -;---- P R O V I D E D A P I S ---- -;------------------------------------------------------------------------------- - -{{#provided-api}} - -;------------------------------------------------------------------------------- -;---- T H E S E R V I C E O F T H E A P I ---- -;------------------------------------------------------------------------------- -%begin systemd-unit - -# auto generated by wgtpkg-unit for {{:id}} version {{:version}} target {{:#target}} of {{:idaver}} - -%systemd-unit system -%systemd-unit service UNIT_NAME_API_BASE({{name}})@ - -[Unit] -Description=Provides api {{name}} for user %i -X-AFM-API-TYPE={{value}} - -Requires=afm-user-setup@%i.service -After=afm-user-setup@%i.service - -{{#value=ws|auto}} -Requires=UNIT_NAME_API_BASE({{name}})@%i.socket -After=UNIT_NAME_API_BASE({{name}})@%i.socket -{{/value=ws|auto}} - -[Service] -Type=oneshot -RemainAfterExit=yes -{{#value=ws|auto}} -ExecStart=/bin/true -{{/value=ws|auto}} -dnl {{#value=link}} -dnl ExecStart=/bin/ln -s {{:#metadata.install-dir}}/ USER_RUN_DIR/apis/link/{{name}} -dnl {{/value=link}} - -dnl %nl -dnl [Install] -dnl WantedBy=afm-user-session@.target -dnl %systemd-unit wanted-by afm-user-session@.target - -%end systemd-unit - - -;------------------------------------------------------------------------------- -;---- T H E S O C K E T O F T H E A P I ---- -;------------------------------------------------------------------------------- -{{#value=ws|auto}} - -%begin systemd-unit - -# auto generated by wgtpkg-unit for {{:id}} version {{:version}} target {{:#target}} of {{:idaver}} - -%systemd-unit system -%systemd-unit socket UNIT_NAME_API_BASE({{name}})@ -[Unit] -Description=Provides websocket api {{name}} for user %i -Requires=afm-user-setup@%i.service -After=afm-user-setup@%i.service -DefaultDependencies=no - -[Socket] -SmackLabel=* -SmackLabelIPIn=System -SmackLabelIPOut=System -ListenStream=USER_RUN_DIR/apis/ws/{{name}} -FileDescriptorName={{name}} -Service=UNIT_NAME_SERVICE - -%end systemd-unit - - -{{/value=ws|auto}} - -{{/provided-api}} - - diff --git a/conf/unit/generate-unit-conf/service.inc b/conf/unit/generate-unit-conf/service.inc index 3efa975..1df4210 100644 --- a/conf/unit/generate-unit-conf/service.inc +++ b/conf/unit/generate-unit-conf/service.inc @@ -40,6 +40,12 @@ ConditionSecurity=smack %nl # Automatic bound to required api +{{#required-binding}} +{{#value=extern}} +BindsTo=UNIT_NAME_BINDING_SERVICE({{name}},%i) +After=UNIT_NAME_BINDING_SERVICE({{name}},%i) +{{/value=extern}} +{{/required-binding}} {{#required-api}} {{#value=auto|ws}} BindsTo=UNIT_NAME_API_SERVICE({{name}},%i) @@ -48,8 +54,8 @@ After=UNIT_NAME_API_SERVICE({{name}},%i) {{/required-api}} {{#provided-api}} {{#value=ws|auto}} -Requires=UNIT_NAME_API_SERVICE({{name}},%i) -After=UNIT_NAME_API_SERVICE({{name}},%i) +Requires=UNIT_NAME_API_SOCKET({{name}},%i) +After=UNIT_NAME_API_SOCKET({{name}},%i) {{/value=ws|auto}} {{/provided-api}} diff --git a/docs/2.2-config.xml.md b/docs/2.2-config.xml.md index a7f32dc..39ea23d 100644 --- a/docs/2.2-config.xml.md +++ b/docs/2.2-config.xml.md @@ -156,7 +156,7 @@ The name is the name of the required API. The value describes how to connect to the required api. It is either: -- local: +- local: OBSOLETE, PROVIDED FOR COMPATIBILITY The binding is a local shared object. In that case, the name is the relative path of the shared object to be loaded. @@ -171,14 +171,33 @@ It is either: - dbus: The framework connect using internal dbus -- link: - The framework connect in memory by dynamically linking - - cloud: [PROPOSAL - NOT IMPLEMENTED] The framework connect externally using websock. In that case, the name includes data to access the service. Example: `` +#### required-binding: param name=[name or path] + +The name or the path of the required BINDING. + +The value describes how to connect to the required binding. +It is either: + +- local: + The binding is a local shared object. + In that case, the name is the relative path of the + shared object to be loaded. + +- extern: + The binding is external. The name is the exported binding name. + See provided-binding. + +#### provided-binding: param name=[exported name] + +Exports a local binding to other applications. + +The value must contain the path to the exported binding. + ### required-permission: feature name="urn:AGL:widget:required-permission" List of the permissions required by the unit. diff --git a/src/wgt-json.c b/src/wgt-json.c index bb1ba55..f4212d0 100644 --- a/src/wgt-json.c +++ b/src/wgt-json.c @@ -387,6 +387,26 @@ static int add_required_api(struct json_object *targets, const struct wgt_desc_f return add_targeted_params(targets, feat, actions); } +/* Treats the feature "provided_binding" */ +static int add_provided_binding(struct json_object *targets, const struct wgt_desc_feature *feat) +{ + static struct paramaction actions[] = { + { .name = string_sharp_target, .action = NULL, .closure = NULL }, /* TODO: should be an error! */ + { .name = NULL, .action = add_param_array, .closure = (void*)string_provided_binding } + }; + return add_targeted_params(targets, feat, actions); +} + +/* Treats the feature "required_binding" */ +static int add_required_binding(struct json_object *targets, const struct wgt_desc_feature *feat) +{ + static struct paramaction actions[] = { + { .name = string_sharp_target, .action = NULL, .closure = NULL }, /* skip #target */ + { .name = NULL, .action = add_param_array, .closure = (void*)string_required_binding } + }; + return add_targeted_params(targets, feat, actions); +} + /* Treats the feature "required_permission" */ static int add_required_permission(struct json_object *targets, const struct wgt_desc_feature *feat) { @@ -460,9 +480,15 @@ static struct json_object *to_json(const struct wgt_desc *desc) else if (!strcmp(featname, string_provided_api)) { rc2 = add_provided_api(targets, feat); } + else if (!strcmp(featname, string_provided_binding)) { + rc2 = add_provided_binding(targets, feat); + } else if (!strcmp(featname, string_required_api)) { rc2 = add_required_api(targets, feat); } + else if (!strcmp(featname, string_required_binding)) { + rc2 = add_required_binding(targets, feat); + } else if (!strcmp(featname, string_required_permission)) { rc2 = add_required_permission(targets, feat); } else { diff --git a/src/wgt-strings.c b/src/wgt-strings.c index 9185ee9..5dc5e68 100644 --- a/src/wgt-strings.c +++ b/src/wgt-strings.c @@ -57,8 +57,10 @@ const char string_list[] = "list"; const char string_main[] = "main"; const char string_optional[] = "optional"; const char string_provided_api[] = "provided-api"; +const char string_provided_binding[] = "provided-binding"; const char string_provided_unit[] = "provided-unit"; const char string_required_api[] = "required-api"; +const char string_required_binding[] = "required-binding"; const char string_required_permission[] = "required-permission"; const char string_targets[] = "targets"; const char string_sharp_target[] = "#target"; diff --git a/src/wgt-strings.h b/src/wgt-strings.h index 0a9c0e9..6f58db1 100644 --- a/src/wgt-strings.h +++ b/src/wgt-strings.h @@ -55,8 +55,10 @@ extern const char string_list[]; extern const char string_main[]; extern const char string_optional[]; extern const char string_provided_api[]; +extern const char string_provided_binding[]; extern const char string_provided_unit[]; extern const char string_required_api[]; +extern const char string_required_binding[]; extern const char string_required_permission[]; extern const char string_sharp_target[]; extern const char string_targets[]; -- cgit 1.2.3-korg