diff --git a/.travis.yml b/.travis.yml
index 06f16e2d..df4b3e97 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -80,7 +80,7 @@ install:
# Ubuntu's default umask is 0002, but this break's swupd hash calculations.
before_script:
- autoreconf --verbose --warnings=none --install --force
- - ./configure CFLAGS="$CFLAGS -fsanitize=address -Werror" --prefix=/usr --with-fallback-capaths=$TRAVIS_BUILD_DIR/swupd_test_certificates --with-systemdsystemunitdir=/usr/lib/systemd/system --with-config-file-path=./testconfig
+ - ./configure CFLAGS="$CFLAGS -fsanitize=address -Werror" --prefix=/usr --enable-third-party --with-fallback-capaths=$TRAVIS_BUILD_DIR/swupd_test_certificates --with-systemdsystemunitdir=/usr/lib/systemd/system --with-config-file-path=./testconfig
- sudo find test/functional -exec chmod g-w {} \;
- make &&
sudo sh -c 'umask 0022 && make install' &&
diff --git a/Makefile.am b/Makefile.am
index 09a6fe9f..9b579c62 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -32,6 +32,11 @@ bin_PROGRAMS = swupd
AM_CPPFLAGS = $(AM_CFLAGS) $(libarchive_CFLAGS)
swupd_SOURCES = \
+ src/3rd_party_add.c \
+ src/3rd_party.c \
+ src/3rd_party_internal.h \
+ src/3rd_party_list.c \
+ src/3rd_party_remove.c \
src/alias.c \
src/alias.h \
src/autoupdate.c \
diff --git a/configure.ac b/configure.ac
index 1a233677..0a7821f0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -72,6 +72,25 @@ AS_IF(
[SIGVERIFICATION="no"]
)
+AC_ARG_ENABLE(
+ [third-party],
+ [AS_HELP_STRING([--enable-third-party], [Enable 3rd-party (disabled by default)])]
+)
+THIRDPARTY="no"
+AS_IF(
+ [test "x$enable_third_party" = "xyes"],
+ [AC_DEFINE(THIRDPARTY, 1, [Enable third party])
+ THIRDPARTY="yes"],
+ [THIRDPARTY="no"]
+)
+
+AH_TEMPLATE([THIRDPARTY_REPO_PREFIX], [prefix path for third party repos])
+
+AS_IF(
+ [test "$enable_third_party" = "yes"],
+ [AC_DEFINE([THIRDPARTY_REPO_PREFIX], ["/opt/user-repo/"])]
+)
+
AC_ARG_ENABLE(
[tests],
[AS_HELP_STRING([--disable-tests], [Do not enable unit or functional test framework (enabled by default)])]
@@ -383,6 +402,7 @@ Configuration to build swupd-client:
Version URL: ${VERSIONURL}
Format Identifier: ${FORMATID}
Signature verification: ${SIGVERIFICATION}
+ Third party: ${THIRDPARTY}
Update certificate path: ${cert_path}
Configuration file path(s): ${config_file_path}
Use bzip compression: ${BZIP}
diff --git a/src/3rd_party.c b/src/3rd_party.c
new file mode 100644
index 00000000..04c6b8f6
--- /dev/null
+++ b/src/3rd_party.c
@@ -0,0 +1,110 @@
+/*
+ * Software Updater - client side
+ *
+ * Copyright © 2019 Intel Corporation.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 or later of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+#define _GNU_SOURCE
+#include "config.h"
+#include "swupd.h"
+#include "swupd_internal.h"
+
+#ifdef THIRDPARTY
+
+static struct subcmd third_party_commands[] = {
+ { "add", "Add third party repo", third_party_add_main },
+ { "remove", "Remove third party repo", third_party_remove_main },
+ { "list", "List third party repo", third_party_list_main },
+ { 0 }
+};
+
+static void print_help(const char *name)
+{
+ print("Usage:\n");
+ print(" or %s SUBCOMMAND [OPTION...]\n\n", basename((char *)name));
+ print("Help Options:\n");
+ print(" -h, --help Show help options\n");
+ print("Subcommands:\n");
+
+ struct subcmd *entry = third_party_commands;
+
+ while (entry->name != NULL) {
+ print(" %-20s %-30s\n", entry->name, entry->doc);
+ entry++;
+ }
+ print("\n");
+ print("To view subcommand options, run `%s SUBCOMMAND --help'\n", basename((char *)name));
+}
+
+static const struct option prog_opts[] = {
+ { "help", no_argument, 0, 'h' },
+ { 0 }
+};
+
+static int parse_options(int argc, char **argv, int *index)
+{
+ int opt;
+ int ret;
+
+ /* The leading "-" in the optstring is required to preserve option parsing order */
+ while ((opt = getopt_long(argc, argv, "-h", prog_opts, NULL)) != -1) {
+ switch (opt) {
+ case 'h':
+ print_help(argv[0]);
+ exit(EXIT_SUCCESS);
+ case '\01':
+ /* found a subcommand, or a random non-option argument */
+ ret = subcmd_index(optarg, third_party_commands);
+ if (ret < 0) {
+ error("unrecognized subcommand `%s'\n\n",
+ optarg);
+ goto error;
+ } else {
+ *index = ret;
+ return 0;
+ }
+ case '?':
+ /* for unknown options, an error message is printed automatically */
+ info("\n");
+ goto error;
+ default:
+ /* should be unreachable */
+ break;
+ }
+ }
+
+ /* no subcommands implies -h/--help */
+ print_help(argv[0]);
+ exit(EXIT_SUCCESS);
+error:
+ print_help(argv[0]);
+ return -1;
+}
+
+enum swupd_code third_party_main(int argc, char **argv)
+{
+ int index = 0, ret;
+
+ if (parse_options(argc, argv, &index) < 0) {
+ return SWUPD_INVALID_OPTION;
+ }
+ optind = 0;
+ ret = third_party_commands[index].mainfunc(argc - 1, argv + 1);
+
+ return ret;
+}
+
+#endif
diff --git a/src/3rd_party_add.c b/src/3rd_party_add.c
new file mode 100644
index 00000000..35057b8d
--- /dev/null
+++ b/src/3rd_party_add.c
@@ -0,0 +1,94 @@
+/*
+ * Software Updater - client side
+ *
+ * Copyright © 2019 Intel Corporation.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 or later of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+#define _GNU_SOURCE
+#include "3rd_party_internal.h"
+#include "config.h"
+
+#ifdef THIRDPARTY
+
+static void print_help(void)
+{
+ print("Usage:\n");
+ print(" swupd 3rd-party add [repo-name] [repo-URL]\n\n");
+
+ global_print_help();
+ print("\n");
+}
+
+static const struct global_options opts = {
+ NULL,
+ 0,
+ NULL,
+ print_help,
+};
+
+static bool parse_options(int argc, char **argv)
+{
+#define EXACT_ARG_COUNT 2
+ int ind = global_parse_options(argc, argv, &opts);
+
+ if (ind < 0) {
+ return false;
+ }
+
+ if (argc == 1) {
+ error("The positional args: repo-name and URL are missing\n\n");
+ return false;
+ } else if (argc == 2) {
+ error("The positional args: repo-URL is missing\n\n");
+ return false;
+ }
+
+ /* Ensure that repo add only expects only two args: repo-name, repo-url */
+ if ((argc - ind) != EXACT_ARG_COUNT) {
+ error("Unexpected arguments\n\n");
+ return false;
+ }
+
+ return true;
+}
+
+enum swupd_code third_party_add_main(int argc, char **argv)
+{
+
+ enum swupd_code ret = SWUPD_OK;
+ const int step_in_third_party_add = 1;
+
+ if (!parse_options(argc, argv)) {
+ print_help();
+ return SWUPD_INVALID_OPTION;
+ }
+ progress_init_steps("third-party", step_in_third_party_add);
+
+ ret = swupd_init(SWUPD_NO_ROOT);
+ if (ret != SWUPD_OK) {
+ goto finish;
+ }
+
+ /* TODO implement */
+
+ swupd_deinit();
+
+finish:
+ progress_finish_steps(ret);
+ return ret;
+}
+
+#endif
diff --git a/src/3rd_party_internal.h b/src/3rd_party_internal.h
new file mode 100644
index 00000000..75334e68
--- /dev/null
+++ b/src/3rd_party_internal.h
@@ -0,0 +1,26 @@
+#ifndef __THIRD_PARTY_INTERNAL_H
+#define __THIRD_PARTY_INTERNAL_H
+
+#include "swupd.h"
+
+/**
+ * @file
+ * @brief Common functions which can be used by 3rd-party add,
+ * remove, list
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef THIRDPARTY
+
+/* TODO Implement */
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/3rd_party_list.c b/src/3rd_party_list.c
new file mode 100644
index 00000000..096b4172
--- /dev/null
+++ b/src/3rd_party_list.c
@@ -0,0 +1,83 @@
+/*
+ * Software Updater - client side
+ *
+ * Copyright © 2019 Intel Corporation.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 or later of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+#define _GNU_SOURCE
+#include "3rd_party_internal.h"
+#include "config.h"
+
+#ifdef THIRDPARTY
+
+static void print_help(void)
+{
+ print("Usage:\n");
+ print(" swupd 3rd-party list\n\n");
+
+ global_print_help();
+ print("\n");
+}
+
+static const struct global_options opts = {
+ NULL,
+ 0,
+ NULL,
+ print_help,
+};
+
+static bool parse_options(int argc, char **argv)
+{
+ int ind = global_parse_options(argc, argv, &opts);
+
+ if (ind < 0) {
+ return false;
+ }
+
+ if (argc > ind) {
+ error("Unexpected arguments\n\n");
+ return false;
+ }
+
+ return true;
+}
+
+enum swupd_code third_party_list_main(int argc, char **argv)
+{
+ enum swupd_code ret = SWUPD_OK;
+ const int step_in_third_party_list = 1;
+
+ if (!parse_options(argc, argv)) {
+ print_help();
+ return SWUPD_INVALID_OPTION;
+ }
+ progress_init_steps("third-party", step_in_third_party_list);
+
+ ret = swupd_init(SWUPD_NO_ROOT);
+ if (ret != SWUPD_OK) {
+ goto finish;
+ }
+
+ /* TODO Implement */
+
+ swupd_deinit();
+
+finish:
+ progress_finish_steps(ret);
+ return ret;
+}
+
+#endif
diff --git a/src/3rd_party_remove.c b/src/3rd_party_remove.c
new file mode 100644
index 00000000..c874a066
--- /dev/null
+++ b/src/3rd_party_remove.c
@@ -0,0 +1,90 @@
+/*
+ * Software Updater - client side
+ *
+ * Copyright © 2019 Intel Corporation.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 or later of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+#define _GNU_SOURCE
+#include "3rd_party_internal.h"
+#include "config.h"
+
+#ifdef THIRDPARTY
+
+static void print_help(void)
+{
+ print("Usage:\n");
+ print(" swupd 3rd-party remove [repo-name]\n\n");
+
+ global_print_help();
+ print("\n");
+}
+
+static const struct global_options opts = {
+ NULL,
+ 0,
+ NULL,
+ print_help,
+};
+
+static bool parse_options(int argc, char **argv)
+{
+#define EXACT_ARG_COUNT 1
+ int ind = global_parse_options(argc, argv, &opts);
+
+ if (ind < 0) {
+ return false;
+ }
+
+ if (argc == 1) {
+ error("The positional args: repo-name is missing\n\n");
+ return false;
+ }
+
+ /* Ensure that repo remove only expects only one arg: repo-name */
+ if ((argc - ind) != EXACT_ARG_COUNT) {
+ error("Unexpected arguments\n\n");
+ return false;
+ }
+
+ return true;
+}
+
+enum swupd_code third_party_remove_main(int argc, char **argv)
+{
+ enum swupd_code ret = SWUPD_OK;
+ const int step_in_third_party_remove = 1;
+
+ if (!parse_options(argc, argv)) {
+ print_help();
+ return SWUPD_INVALID_OPTION;
+ }
+ progress_init_steps("third-party", step_in_third_party_remove);
+
+ ret = swupd_init(SWUPD_NO_ROOT);
+ if (ret != SWUPD_OK) {
+ goto finish;
+ }
+
+ /* TODO Implement */
+
+ swupd_deinit();
+
+finish:
+ progress_finish_steps(ret);
+ return ret;
+}
+
+#endif
diff --git a/src/main.c b/src/main.c
index 7caa5903..d6a9a1b8 100644
--- a/src/main.c
+++ b/src/main.c
@@ -28,12 +28,6 @@
#include "swupd_build_opts.h"
#include "swupd_internal.h"
-struct subcmd {
- char *name;
- char *doc;
- enum swupd_code (*mainfunc)(int, char **);
-};
-
static enum swupd_code external_search_main(int argc, char **argv)
{
int ret;
@@ -49,7 +43,7 @@ static enum swupd_code external_search_main(int argc, char **argv)
// TODO(castulo): remove the superseded command from the help menu by end of November 2019,
// so it is not visible but the command must remain available in the back so we don't break users
-static struct subcmd commands[] = {
+static struct subcmd main_commands[] = {
{ "info", "Show the version and the update URLs", info_main },
{ "autoupdate", "Enable/disable automatic system updates", autoupdate_main },
{ "check-update", "Check if a new OS version is available", check_update_main },
@@ -91,7 +85,7 @@ static void print_help(const char *name)
print(" -v, --version Output version information and exit\n\n");
print("Subcommands:\n");
- struct subcmd *entry = commands;
+ struct subcmd *entry = main_commands;
while (entry->name != NULL) {
print(" %-20s %-30s\n", entry->name, entry->doc);
@@ -115,27 +109,6 @@ static void print_compile_opts(void)
info("Compile-time configuration:\n%s\n", BUILD_CONFIGURE);
}
-static int subcmd_index(char *arg)
-{
- struct subcmd *entry = commands;
- int i = 0;
- size_t input_len;
- size_t cmd_len;
-
- input_len = strlen(arg);
-
- while (entry->name != NULL) {
- cmd_len = strlen(entry->name);
- if (cmd_len == input_len && strcmp(arg, entry->name) == 0) {
- return i;
- }
- entry++;
- i++;
- }
-
- return -1;
-}
-
static int parse_options(int argc, char **argv, int *index)
{
int opt;
@@ -153,7 +126,7 @@ static int parse_options(int argc, char **argv, int *index)
exit(EXIT_SUCCESS);
case '\01':
/* found a subcommand, or a random non-option argument */
- ret = subcmd_index(optarg);
+ ret = subcmd_index(optarg, main_commands);
if (ret < 0) {
error("unrecognized subcommand `%s'\n\n",
optarg);
@@ -204,7 +177,7 @@ int main(int argc, char **argv)
*/
optind = 0;
- ret = commands[index].mainfunc(argc - 1, argv + 1);
+ ret = main_commands[index].mainfunc(argc - 1, argv + 1);
return ret;
}
diff --git a/src/swupd_internal.h b/src/swupd_internal.h
index 6c0d8f38..ed33458d 100644
--- a/src/swupd_internal.h
+++ b/src/swupd_internal.h
@@ -1,6 +1,9 @@
#ifndef __SWUPD_INTERNAL__
#define __SWUPD_INTERNAL__
+#include
+#include
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -22,6 +25,57 @@ enum swupd_code repair_main(int argc, char **argv);
enum swupd_code diagnose_main(int argc, char **argv);
enum swupd_code bundle_info_main(int argc, char **argv);
enum swupd_code verify_main(int argc, char **argv);
+enum swupd_code third_party_main(int argc, char **argv);
+
+/**
+ * @brief Creates a new third-party repo under THIRDPARTY_REPO_PREFIX
+ * if it does not exist
+ *
+ * @return SWUPD_OK on success
+ */
+extern enum swupd_code third_party_add_main(int argc, char **argv);
+
+/**
+ * @brief Removes a third-party repo under THIRDPARTY_REPO_PREFIX
+ * if it does exist
+ *
+ * @return SWUPD_OK on success
+ */
+extern enum swupd_code third_party_remove_main(int argc, char **argv);
+
+/**
+ * @brief Lists all the third-party repos under THIRDPARTY_REPO_PREFIX
+ *
+ * @return SWUPD_OK on success
+ */
+extern enum swupd_code third_party_list_main(int argc, char **argv);
+
+struct subcmd {
+ char *name;
+ char *doc;
+ enum swupd_code (*mainfunc)(int, char **);
+};
+
+static inline int subcmd_index(char *arg, struct subcmd *commands)
+{
+ struct subcmd *entry = commands;
+ int i = 0;
+ size_t input_len;
+ size_t cmd_len;
+
+ input_len = strlen(arg);
+
+ while (entry->name != NULL) {
+ cmd_len = strlen(entry->name);
+ if (cmd_len == input_len && strcmp(arg, entry->name) == 0) {
+ return i;
+ }
+ entry++;
+ i++;
+ }
+
+ return -1;
+}
#ifdef __cplusplus
}
diff --git a/swupd.bash b/swupd.bash
index 4d8b4ce8..ea1de16b 100644
--- a/swupd.bash
+++ b/swupd.bash
@@ -28,7 +28,9 @@ _swupd()
for ((i=COMP_CWORD-1;i>=0;i--))
do case "${COMP_WORDS[$i]}" in
("$1")
- opts="--help --version autoupdate bundle-add bundle-remove bundle-list hashdump update diagnose check-update search search-file info clean mirror os-install repair verify "
+ opts="--help --version autoupdate bundle-add bundle-remove
+ bundle-list hashdump update diagnose check-update search
+ search-file info clean mirror os-install repair verify 3rd-party"
break;;
("info")
opts="$global "
@@ -81,6 +83,15 @@ _swupd()
("verify")
opts="$global --version --manifest --fix --picky --picky-tree --picky-whitelist --install --quick --force --install "
break;;
+ ("3rd-party")
+ opts="$global add remove list"
+ break;;
+ ("add")
+ opts="$global --repo"
+ break;;
+ ("remove")
+ opts="$global --repo"
+ break;;
esac
done
# Add in additional completion options if we need to
diff --git a/swupd.zsh b/swupd.zsh
index 36652490..956039b9 100644
--- a/swupd.zsh
+++ b/swupd.zsh
@@ -175,6 +175,7 @@ if [[ -n "$state" ]]; then
"mirror:Configure mirror url for swupd content"
"clean:Clean cached files"
"hashdump:Dump the HMAC hash of a file"
+ "3rd-party: Indicate Swupd to use user's third party repo"
)
_describe -t subcmds 'swupd subcommand' subcmds && ret=0
;;
@@ -183,6 +184,32 @@ if [[ -n "$state" ]]; then
info)
_arguments $global_opts && ret=0
;;
+ 3rd-party)
+ local -a thirdparty; thirdparty=(
+ $global_opt
+ '(help)list[List third party repo(s)]'
+ '(help)remove[Remove third party repo]'
+ '(help)add[Add third party repo]'
+ _arguments $thirdparty && ret=0
+ ;;
+ add)
+ local -a add; add=(
+ $global_opt
+ '(help)Positional arg: [repo-name]'
+ '(help)Positional arg: [repo-url]'
+ _arguments $add && ret=0
+ ;;
+ remove)
+ local -a remove; remove=(
+ $global_opt
+ '(help)Positional arg: [repo-name]'
+ _arguments $remove && ret=0
+ ;;
+ list)
+ local -a list; list=(
+ $global_opt
+ _arguments $list && ret=0
+ ;;
autoupdate)
local -a autoupdates; autoupdates=(
$global_opts