mirror of
https://github.com/clearlinux/swupd-server.git
synced 2026-10-04 16:08:29 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
75039ad6b9 | ||
|
|
9b316bf95c | ||
|
|
b618516167 | ||
|
|
7542d2152a | ||
|
|
490326f2b9 | ||
|
|
307d2427a1 | ||
|
|
72dd27a886 | ||
|
|
7e38f013ef | ||
|
|
4e0fdd4193 | ||
|
|
f01d9ca6c8 | ||
|
|
944dfa1d93 | ||
|
|
963e8117b4 | ||
|
|
57292a5a03 | ||
|
|
fe6f47e4c3 | ||
|
|
13189dd4d4 |
+25
@@ -0,0 +1,25 @@
|
|||||||
|
sudo: required
|
||||||
|
dist: trusty
|
||||||
|
language: c
|
||||||
|
|
||||||
|
# Pre-install missing build dependencies:
|
||||||
|
# - libmagic (pull from repo)
|
||||||
|
# - libcheck 0.9.10 is slightly too old, since 0.9.12 adds TAP support
|
||||||
|
# - bsdiff 1.* is the Clear Linux OS fork
|
||||||
|
before_install:
|
||||||
|
- sudo apt-get -qq update
|
||||||
|
- sudo apt-get install -y libmagic-dev
|
||||||
|
|
||||||
|
install:
|
||||||
|
- wget http://downloads.sourceforge.net/project/check/check/0.10.0/check-0.10.0.tar.gz
|
||||||
|
- tar -xvf check-0.10.0.tar.gz
|
||||||
|
- pushd check-0.10.0 && ./configure --prefix=/usr && make -j48 && sudo make install && popd
|
||||||
|
- wget https://github.com/clearlinux/bsdiff/releases/download/v1.0.2/bsdiff-1.0.2.tar.xz
|
||||||
|
- tar -xvf bsdiff-1.0.2.tar.xz
|
||||||
|
- pushd bsdiff-1.0.2 && ./configure --prefix=/usr --disable-tests && make -j48 && sudo make install && popd
|
||||||
|
|
||||||
|
# Ubuntu's default umask is 0002, but this break's swupd hash calculations.
|
||||||
|
script:
|
||||||
|
- sudo find test/functional -exec chmod g-w {} \;
|
||||||
|
- autoreconf --verbose --warnings=none --install --force && ./configure && make -j48 && sudo sh -c 'umask 0022 && make -j48 check'
|
||||||
|
after_failure: cat test-suite.log
|
||||||
+2
-4
@@ -26,7 +26,6 @@ swupd_create_update_SOURCES = \
|
|||||||
src/manifest.c \
|
src/manifest.c \
|
||||||
src/pack.c \
|
src/pack.c \
|
||||||
src/rename.c \
|
src/rename.c \
|
||||||
src/signature.c \
|
|
||||||
src/stats.c \
|
src/stats.c \
|
||||||
src/type_change.c \
|
src/type_change.c \
|
||||||
src/versions.c \
|
src/versions.c \
|
||||||
@@ -44,7 +43,6 @@ swupd_make_pack_SOURCES = \
|
|||||||
src/manifest.c \
|
src/manifest.c \
|
||||||
src/pack.c \
|
src/pack.c \
|
||||||
src/rename.c \
|
src/rename.c \
|
||||||
src/signature.c \
|
|
||||||
src/stats.c \
|
src/stats.c \
|
||||||
src/xattrs.c
|
src/xattrs.c
|
||||||
|
|
||||||
@@ -61,7 +59,6 @@ swupd_make_fullfiles_SOURCES = \
|
|||||||
src/manifest.c \
|
src/manifest.c \
|
||||||
src/pack.c \
|
src/pack.c \
|
||||||
src/rename.c \
|
src/rename.c \
|
||||||
src/signature.c \
|
|
||||||
src/stats.c \
|
src/stats.c \
|
||||||
src/xattrs.c
|
src/xattrs.c
|
||||||
|
|
||||||
@@ -118,7 +115,8 @@ dist_check_SCRIPTS = \
|
|||||||
test/functional/pack/test.bats \
|
test/functional/pack/test.bats \
|
||||||
test/functional/full-run/test.bats \
|
test/functional/full-run/test.bats \
|
||||||
test/functional/full-run-delta/test.bats \
|
test/functional/full-run-delta/test.bats \
|
||||||
test/functional/file-name-blacklisted/test.bats
|
test/functional/file-name-blacklisted/test.bats \
|
||||||
|
test/functional/state-file/test.bats
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if COVERAGE
|
if COVERAGE
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
# Process this file with autoconf to produce a configure script.
|
# Process this file with autoconf to produce a configure script.
|
||||||
|
|
||||||
AC_PREREQ([2.66])
|
AC_PREREQ([2.66])
|
||||||
AC_INIT(swupd-server, 3.3.1, tudor.marcu@intel.com)
|
AC_INIT(swupd-server, 3.3.2, tudor.marcu@intel.com)
|
||||||
AM_INIT_AUTOMAKE([foreign -Wall -W subdir-objects])
|
AM_INIT_AUTOMAKE([foreign -Wall -W subdir-objects])
|
||||||
AM_SILENT_RULES([yes])
|
AM_SILENT_RULES([yes])
|
||||||
AC_PROG_CC
|
AC_PROG_CC
|
||||||
|
|||||||
+3
-7
@@ -20,12 +20,12 @@
|
|||||||
#define TAR_COMMAND "bsdtar"
|
#define TAR_COMMAND "bsdtar"
|
||||||
#define TAR_XATTR_ARGS ""
|
#define TAR_XATTR_ARGS ""
|
||||||
#define TAR_XATTR_ARGS_STRLIST
|
#define TAR_XATTR_ARGS_STRLIST
|
||||||
#define TAR_WARN_ARGS ""
|
#define TAR_WARN_ARGS_STRLIST
|
||||||
#else
|
#else
|
||||||
#define TAR_COMMAND "tar"
|
#define TAR_COMMAND "tar"
|
||||||
#define TAR_XATTR_ARGS "--xattrs --xattrs-include='*'"
|
#define TAR_XATTR_ARGS "--xattrs --xattrs-include='*'"
|
||||||
#define TAR_XATTR_ARGS_STRLIST "--xattrs", "--xattrs-include='*'",
|
#define TAR_XATTR_ARGS_STRLIST "--xattrs", "--xattrs-include='*'",
|
||||||
#define TAR_WARN_ARGS "--warning=no-timestamp"
|
#define TAR_WARN_ARGS_STRLIST "--warning=no-timestamp",
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if SWUPD_WITH_SELINUX
|
#if SWUPD_WITH_SELINUX
|
||||||
@@ -143,7 +143,6 @@ extern int current_version;
|
|||||||
extern int newversion;
|
extern int newversion;
|
||||||
extern int minversion;
|
extern int minversion;
|
||||||
extern unsigned long long int format;
|
extern unsigned long long int format;
|
||||||
extern bool enable_signing;
|
|
||||||
|
|
||||||
extern char *state_dir;
|
extern char *state_dir;
|
||||||
extern char *packstage_dir;
|
extern char *packstage_dir;
|
||||||
@@ -258,9 +257,6 @@ extern int system_argv(char *const argv[]);
|
|||||||
extern int system_argv_fd(char *const argv[], int newstdin, int newstdout, int newstderr);
|
extern int system_argv_fd(char *const argv[], int newstdin, int newstdout, int newstderr);
|
||||||
extern int system_argv_pipe(char *const argvp1[], int stdinp1, int stderrp1,
|
extern int system_argv_pipe(char *const argvp1[], int stdinp1, int stderrp1,
|
||||||
char *const argvp2[], int stdoutp2, int stderrp2);
|
char *const argvp2[], int stdoutp2, int stderrp2);
|
||||||
|
extern int num_threads(float scaling);
|
||||||
extern bool signature_initialize(void);
|
|
||||||
extern void signature_terminate(void);
|
|
||||||
extern bool signature_sign(const char *filename);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+2
-2
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
my $target = $ARGV[0];
|
my $target = $ARGV[0];
|
||||||
system("rm /tmp/Manifest");
|
system("rm /tmp/Manifest");
|
||||||
system("wget --quiet --no-proxy --no-check-certificate --output-document=/tmp/Manifest https://download.clearlinux.org/update/$target/Manifest.os-core");
|
system("wget --quiet --output-document=/tmp/Manifest https://download.clearlinux.org/update/$target/Manifest.os-core");
|
||||||
|
|
||||||
|
|
||||||
my $from = $target;
|
my $from = $target;
|
||||||
@@ -15,7 +15,7 @@ while ($from > $target - 100) {
|
|||||||
$from = $from - 10;
|
$from = $from - 10;
|
||||||
print "Testing the $from-$target pack\n";
|
print "Testing the $from-$target pack\n";
|
||||||
system("rm /tmp/pack.tar");
|
system("rm /tmp/pack.tar");
|
||||||
system("wget --quiet --no-proxy --no-check-certificate --output-document=/tmp/pack.tar https://download.clearlinux.org/update/$target/pack-os-core-from-$from.tar");
|
system("wget --quiet ---output-document=/tmp/pack.tar https://download.clearlinux.org/update/$target/pack-os-core-from-$from.tar");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+134
-45
@@ -275,7 +275,7 @@ static void get_hash(gpointer data, gpointer user_data)
|
|||||||
/* disallow characters which can do unexpected things when the filename is
|
/* disallow characters which can do unexpected things when the filename is
|
||||||
* used on a tar command line via system("tar [args] filename [more args]");
|
* used on a tar command line via system("tar [args] filename [more args]");
|
||||||
*/
|
*/
|
||||||
static bool illegal_characters(char *filename)
|
static bool illegal_characters(const char *filename)
|
||||||
{
|
{
|
||||||
char c;
|
char c;
|
||||||
int i;
|
int i;
|
||||||
@@ -301,27 +301,151 @@ static bool illegal_characters(char *filename)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct file *add_file(struct manifest *manifest,
|
||||||
|
const char *entry_name,
|
||||||
|
char *sub_filename,
|
||||||
|
char *fullname,
|
||||||
|
bool do_hash)
|
||||||
|
{
|
||||||
|
GError *err = NULL;
|
||||||
|
struct file *file;
|
||||||
|
|
||||||
|
if (illegal_characters(entry_name)) {
|
||||||
|
printf("WARNING: Filename %s includes illegal character(s) ...skipping.\n", sub_filename);
|
||||||
|
free(sub_filename);
|
||||||
|
free(fullname);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
file = calloc(1, sizeof(struct file));
|
||||||
|
assert(file);
|
||||||
|
|
||||||
|
file->last_change = manifest->version;
|
||||||
|
file->filename = sub_filename;
|
||||||
|
|
||||||
|
populate_file_struct(file, fullname);
|
||||||
|
if (file->is_deleted) {
|
||||||
|
/*
|
||||||
|
* populate_file_struct() logs a stat() failure, but
|
||||||
|
* does not abort. When adding files that should
|
||||||
|
* exist, this case is an error.
|
||||||
|
*/
|
||||||
|
LOG(NULL, "file not found", "%s", fullname);
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* if for some reason there is a file in the official build
|
||||||
|
* which should not be included in the Manifest, then open a bug
|
||||||
|
* to get it removed, and work around its presence by
|
||||||
|
* excluding it here, eg:
|
||||||
|
if (strncmp(file->filename, "/dev/", 5) == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (do_hash) {
|
||||||
|
/* compute the hash from a thread */
|
||||||
|
int ret;
|
||||||
|
ret = g_thread_pool_push(threadpool, file, &err);
|
||||||
|
if (ret == FALSE) {
|
||||||
|
printf("GThread hash computation push error\n");
|
||||||
|
printf("%s\n", err->message);
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
manifest->files = g_list_prepend(manifest->files, file);
|
||||||
|
manifest->count++;
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void iterate_directory(struct manifest *manifest, char *pathprefix,
|
static void iterate_directory(struct manifest *manifest, char *pathprefix,
|
||||||
char *subpath, bool do_hash)
|
char *subpath, bool do_hash)
|
||||||
{
|
{
|
||||||
DIR *dir;
|
DIR *dir;
|
||||||
struct dirent *entry;
|
struct dirent *entry;
|
||||||
char *fullpath;
|
char *fullpath;
|
||||||
int ret;
|
|
||||||
GError *err = NULL;
|
|
||||||
|
|
||||||
string_or_die(&fullpath, "%s/%s", pathprefix, subpath);
|
string_or_die(&fullpath, "%s/%s", pathprefix, subpath);
|
||||||
|
|
||||||
dir = opendir(fullpath);
|
dir = opendir(fullpath);
|
||||||
if (!dir) {
|
if (!dir) {
|
||||||
|
bool fatal_error = errno != ENOENT;
|
||||||
|
FILE *content;
|
||||||
|
|
||||||
free(fullpath);
|
free(fullpath);
|
||||||
|
if (fatal_error) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* If there is a <dir>.content.txt instead of
|
||||||
|
* the actual directory, then read that
|
||||||
|
* file. It has a list of path names,
|
||||||
|
* including all directories. The
|
||||||
|
* corresponding file system entry is then
|
||||||
|
* expected to be in a pre-populated "full"
|
||||||
|
* directory.
|
||||||
|
*
|
||||||
|
* Only supported at top level (i.e. empty
|
||||||
|
* subpath) to keep the code and testing
|
||||||
|
* simpler.
|
||||||
|
*/
|
||||||
|
assert(!subpath[0]);
|
||||||
|
string_or_die(&fullpath, "%s.content.txt", pathprefix);
|
||||||
|
content = fopen(fullpath, "r");
|
||||||
|
free(fullpath);
|
||||||
|
fullpath = NULL;
|
||||||
|
if (content) {
|
||||||
|
char *line = NULL;
|
||||||
|
size_t len = 0;
|
||||||
|
ssize_t read;
|
||||||
|
const char *full;
|
||||||
|
int full_len;
|
||||||
|
/*
|
||||||
|
* determine path to "full" directory: it is assumed to be alongside
|
||||||
|
* "pathprefix", i.e. pathprefix/../full. But pathprefix does not exit,
|
||||||
|
* so we have to strip the last path component.
|
||||||
|
*/
|
||||||
|
full = strrchr(pathprefix, '/');
|
||||||
|
if (full) {
|
||||||
|
full_len = full - pathprefix + 1;
|
||||||
|
full = pathprefix;
|
||||||
|
} else {
|
||||||
|
full = "";
|
||||||
|
full_len = 0;
|
||||||
|
}
|
||||||
|
while ((read = getline(&line, &len, content)) != -1) {
|
||||||
|
if (read) {
|
||||||
|
const char *entry_name = strrchr(line, '/');
|
||||||
|
if (entry_name) {
|
||||||
|
entry_name++;
|
||||||
|
} else {
|
||||||
|
entry_name = line;
|
||||||
|
}
|
||||||
|
if (line[read - 1] == '\n') {
|
||||||
|
line[read - 1] = 0;
|
||||||
|
}
|
||||||
|
string_or_die(&fullpath, "%.*sfull/%s", full_len, full, line);
|
||||||
|
add_file(manifest,
|
||||||
|
entry_name,
|
||||||
|
strdup(line),
|
||||||
|
fullpath,
|
||||||
|
do_hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If both directory and content file are missing, silently (?)
|
||||||
|
// don't add anything to the manifest.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (dir) {
|
while (dir) {
|
||||||
struct file *file;
|
|
||||||
char *sub_filename;
|
char *sub_filename;
|
||||||
char *fullname;
|
char *fullname;
|
||||||
|
struct file *file;
|
||||||
|
|
||||||
entry = readdir(dir);
|
entry = readdir(dir);
|
||||||
if (!entry) {
|
if (!entry) {
|
||||||
@@ -334,50 +458,14 @@ static void iterate_directory(struct manifest *manifest, char *pathprefix,
|
|||||||
}
|
}
|
||||||
|
|
||||||
string_or_die(&sub_filename, "%s/%s", subpath, entry->d_name);
|
string_or_die(&sub_filename, "%s/%s", subpath, entry->d_name);
|
||||||
|
|
||||||
if (illegal_characters(entry->d_name)) {
|
|
||||||
printf("WARNING: Filename %s includes illegal character(s) ...skipping.\n", sub_filename);
|
|
||||||
free(sub_filename);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
file = calloc(1, sizeof(struct file));
|
|
||||||
if (!file) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
file->last_change = manifest->version;
|
|
||||||
file->filename = sub_filename;
|
|
||||||
|
|
||||||
string_or_die(&fullname, "%s/%s", fullpath, entry->d_name);
|
string_or_die(&fullname, "%s/%s", fullpath, entry->d_name);
|
||||||
populate_file_struct(file, fullname);
|
|
||||||
free(fullname);
|
|
||||||
|
|
||||||
if (file->is_dir) {
|
/* takes ownership of the strings, so we don't need to free it */
|
||||||
iterate_directory(manifest, pathprefix, file->filename, do_hash);
|
file = add_file(manifest, entry->d_name, sub_filename, fullname, do_hash);
|
||||||
}
|
|
||||||
|
|
||||||
/* if for some reason there is a file in the official build
|
if (file && file->is_dir) {
|
||||||
* which should not be included in the Manifest, then open a bug
|
iterate_directory(manifest, pathprefix, file->filename, do_hash);
|
||||||
* to get it removed, and work around its presence by
|
|
||||||
* excluding it here, eg:
|
|
||||||
if (strncmp(file->filename, "/dev/", 5) == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
if (do_hash) {
|
|
||||||
/* compute the hash from a thread */
|
|
||||||
ret = g_thread_pool_push(threadpool, file, &err);
|
|
||||||
if (ret == FALSE) {
|
|
||||||
printf("GThread hash computation push error\n");
|
|
||||||
printf("%s\n", err->message);
|
|
||||||
closedir(dir);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
manifest->files = g_list_prepend(manifest->files, file);
|
|
||||||
manifest->count++;
|
|
||||||
}
|
}
|
||||||
closedir(dir);
|
closedir(dir);
|
||||||
free(fullpath);
|
free(fullpath);
|
||||||
@@ -387,6 +475,7 @@ struct manifest *full_manifest_from_directory(int version)
|
|||||||
{
|
{
|
||||||
struct manifest *manifest;
|
struct manifest *manifest;
|
||||||
char *dir;
|
char *dir;
|
||||||
|
int numthreads = num_threads(1.0);
|
||||||
|
|
||||||
LOG(NULL, "Computing hashes", "for %i/full", version);
|
LOG(NULL, "Computing hashes", "for %i/full", version);
|
||||||
|
|
||||||
@@ -394,7 +483,7 @@ struct manifest *full_manifest_from_directory(int version)
|
|||||||
|
|
||||||
string_or_die(&dir, "%s/%i/full", image_dir, version);
|
string_or_die(&dir, "%s/%i/full", image_dir, version);
|
||||||
|
|
||||||
threadpool = g_thread_pool_new(get_hash, dir, 12, FALSE, NULL);
|
threadpool = g_thread_pool_new(get_hash, dir, numthreads, FALSE, NULL);
|
||||||
|
|
||||||
iterate_directory(manifest, dir, "", true);
|
iterate_directory(manifest, dir, "", true);
|
||||||
|
|
||||||
|
|||||||
+16
-8
@@ -39,15 +39,21 @@ void chroot_create_full(int newversion)
|
|||||||
char *full_dir;
|
char *full_dir;
|
||||||
|
|
||||||
string_or_die(&full_dir, "%s/%i/full/", image_dir, newversion);
|
string_or_die(&full_dir, "%s/%i/full/", image_dir, newversion);
|
||||||
|
if (!access(full_dir, R_OK|X_OK)) {
|
||||||
|
free(full_dir);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
g_mkdir_with_parents(full_dir, S_IRWXU);
|
g_mkdir_with_parents(full_dir, S_IRWXU);
|
||||||
|
|
||||||
/* start with base */
|
/* start with base */
|
||||||
LOG(NULL, "Copying chroot os-core to full", "");
|
|
||||||
string_or_die(¶m, "%s/%i/os-core/", image_dir, newversion);
|
string_or_die(¶m, "%s/%i/os-core/", image_dir, newversion);
|
||||||
char *const rsynccmd[] = { "rsync", "-aAX", param, full_dir, NULL };
|
if (!access(param, F_OK)) {
|
||||||
if (system_argv(rsynccmd) != 0) {
|
LOG(NULL, "Copying chroot os-core to full", "");
|
||||||
assert(0);
|
char *const rsynccmd[] = { "rsync", "-aAX", param, full_dir, NULL };
|
||||||
|
if (system_argv(rsynccmd) != 0) {
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
free(param);
|
free(param);
|
||||||
|
|
||||||
@@ -58,11 +64,13 @@ void chroot_create_full(int newversion)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG(NULL, "Overlaying bundle chroot onto full", "%s", group);
|
|
||||||
string_or_die(¶m, "%s/%i/%s/", image_dir, newversion, group);
|
string_or_die(¶m, "%s/%i/%s/", image_dir, newversion, group);
|
||||||
char *const rsynccmd[] = { "rsync", "-aAX", "--ignore-existing", param, full_dir, NULL };
|
if (!access(param, F_OK)) {
|
||||||
if (system_argv(rsynccmd) != 0) {
|
LOG(NULL, "Overlaying bundle chroot onto full", "%s", group);
|
||||||
assert(0);
|
char *const rsynccmd[] = { "rsync", "-aAX", "--ignore-existing", param, full_dir, NULL };
|
||||||
|
if (system_argv(rsynccmd) != 0) {
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
free(param);
|
free(param);
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-14
@@ -29,6 +29,7 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
#include <locale.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -49,12 +50,12 @@ static void banner(void)
|
|||||||
static const struct option prog_opts[] = {
|
static const struct option prog_opts[] = {
|
||||||
{ "help", no_argument, 0, 'h' },
|
{ "help", no_argument, 0, 'h' },
|
||||||
{ "version", no_argument, 0, 'v' },
|
{ "version", no_argument, 0, 'v' },
|
||||||
|
{ "log-stdout", no_argument, 0, 'l' },
|
||||||
{ "osversion", required_argument, 0, 'o' },
|
{ "osversion", required_argument, 0, 'o' },
|
||||||
{ "minversion", required_argument, 0, 'm' },
|
{ "minversion", required_argument, 0, 'm' },
|
||||||
{ "format", required_argument, 0, 'F' },
|
{ "format", required_argument, 0, 'F' },
|
||||||
{ "getformat", no_argument, 0, 'g' },
|
{ "getformat", no_argument, 0, 'g' },
|
||||||
{ "statedir", required_argument, 0, 'S' },
|
{ "statedir", required_argument, 0, 'S' },
|
||||||
{ "signcontent", no_argument, 0, 's' },
|
|
||||||
{ 0, 0, 0, 0 }
|
{ 0, 0, 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -67,12 +68,12 @@ static void print_help(const char *name)
|
|||||||
printf(" -v, --version Show software version\n");
|
printf(" -v, --version Show software version\n");
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf("Application Options:\n");
|
printf("Application Options:\n");
|
||||||
|
printf(" -l, --log-stdout Write log messages also to stdout\n");
|
||||||
printf(" -o, --osversion The OS version for which to create an update\n");
|
printf(" -o, --osversion The OS version for which to create an update\n");
|
||||||
printf(" -m, --minversion Optional minimum file version to write into manifests per file\n");
|
printf(" -m, --minversion Optional minimum file version to write into manifests per file\n");
|
||||||
printf(" -F, --format Format number for the update\n");
|
printf(" -F, --format Format number for the update\n");
|
||||||
printf(" -g, --getformat Print current format string and exit\n");
|
printf(" -g, --getformat Print current format string and exit\n");
|
||||||
printf(" -S, --statedir Optional directory to use for state [ default:=%s ]\n", SWUPD_SERVER_STATE_DIR);
|
printf(" -S, --statedir Optional directory to use for state [ default:=%s ]\n", SWUPD_SERVER_STATE_DIR);
|
||||||
printf(" -s, --signcontent Enables cryptographic signing of update content\n");
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,12 +81,15 @@ static bool parse_options(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
int opt;
|
int opt;
|
||||||
|
|
||||||
while ((opt = getopt_long(argc, argv, "hvo:m:F:g:S:s", prog_opts, NULL)) != -1) {
|
while ((opt = getopt_long(argc, argv, "hvo:m:F:g:S:", prog_opts, NULL)) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case '?':
|
case '?':
|
||||||
case 'h':
|
case 'h':
|
||||||
print_help(argv[0]);
|
print_help(argv[0]);
|
||||||
return false;
|
return false;
|
||||||
|
case 'l':
|
||||||
|
init_log_stdout();
|
||||||
|
break;
|
||||||
case 'v':
|
case 'v':
|
||||||
banner();
|
banner();
|
||||||
return false;
|
return false;
|
||||||
@@ -124,9 +128,6 @@ static bool parse_options(int argc, char **argv)
|
|||||||
free_globals();
|
free_globals();
|
||||||
}
|
}
|
||||||
exit(0);
|
exit(0);
|
||||||
case 's':
|
|
||||||
enable_signing = true;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,6 +141,7 @@ static bool parse_options(int argc, char **argv)
|
|||||||
static void populate_dirs(int version)
|
static void populate_dirs(int version)
|
||||||
{
|
{
|
||||||
char *newversiondir;
|
char *newversiondir;
|
||||||
|
char *newversiondircontent = NULL;
|
||||||
|
|
||||||
string_or_die(&newversiondir, "%s/%d", image_dir, version);
|
string_or_die(&newversiondir, "%s/%d", image_dir, version);
|
||||||
|
|
||||||
@@ -181,9 +183,11 @@ static void populate_dirs(int version)
|
|||||||
}
|
}
|
||||||
|
|
||||||
string_or_die(&newversiondir, "%s/%d/%s", image_dir, version, group);
|
string_or_die(&newversiondir, "%s/%d/%s", image_dir, version, group);
|
||||||
|
string_or_die(&newversiondircontent, "%s/%d/%s.content.txt", image_dir, version, group);
|
||||||
|
|
||||||
/* Create the bundle directory(s) as needed */
|
/* Create the bundle directory(s) as needed */
|
||||||
if (access(newversiondir, F_OK | R_OK) != 0) {
|
if (access(newversiondir, F_OK | R_OK) != 0 &&
|
||||||
|
access(newversiondircontent, F_OK | R_OK) != 0) {
|
||||||
printf("%s does not exist...creating\n", group);
|
printf("%s does not exist...creating\n", group);
|
||||||
if (mkdir(newversiondir, 0755) != 0) {
|
if (mkdir(newversiondir, 0755) != 0) {
|
||||||
printf("Failed to create %s subdirectory\n", group);
|
printf("Failed to create %s subdirectory\n", group);
|
||||||
@@ -192,6 +196,7 @@ static void populate_dirs(int version)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(newversiondir);
|
free(newversiondir);
|
||||||
|
free(newversiondircontent);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int check_build_env(void)
|
static int check_build_env(void)
|
||||||
@@ -259,6 +264,11 @@ int main(int argc, char **argv)
|
|||||||
/* keep valgrind working well */
|
/* keep valgrind working well */
|
||||||
setenv("G_SLICE", "always-malloc", 0);
|
setenv("G_SLICE", "always-malloc", 0);
|
||||||
|
|
||||||
|
if (!setlocale(LC_ALL, "")) {
|
||||||
|
fprintf(stderr, "%s: setlocale() failed\n", argv[0]);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
if (!parse_options(argc, argv)) {
|
if (!parse_options(argc, argv)) {
|
||||||
free_globals();
|
free_globals();
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
@@ -272,12 +282,6 @@ int main(int argc, char **argv)
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initilize the crypto signature module */
|
|
||||||
if (!signature_initialize()) {
|
|
||||||
printf("Can't initialize the crypto signature module!\n");
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
string_or_die(&file_path, "%s/server.ini", state_dir);
|
string_or_die(&file_path, "%s/server.ini", state_dir);
|
||||||
if (!read_configuration_file(file_path)) {
|
if (!read_configuration_file(file_path)) {
|
||||||
printf("Failed to read %s configuration file!\n", state_dir);
|
printf("Failed to read %s configuration file!\n", state_dir);
|
||||||
@@ -530,7 +534,6 @@ exit:
|
|||||||
}
|
}
|
||||||
release_configuration_data();
|
release_configuration_data();
|
||||||
release_group_file();
|
release_group_file();
|
||||||
signature_terminate();
|
|
||||||
g_list_free(manifests_last_versions_list);
|
g_list_free(manifests_last_versions_list);
|
||||||
|
|
||||||
close_log(newversion, exit_status);
|
close_log(newversion, exit_status);
|
||||||
|
|||||||
+4
-3
@@ -72,7 +72,7 @@ static void create_fullfile(struct file *file)
|
|||||||
string_or_die(&origin, "%s/%i/full/%s", indir, file->last_change, file->filename);
|
string_or_die(&origin, "%s/%i/full/%s", indir, file->last_change, file->filename);
|
||||||
if (lstat(origin, &sbuf) < 0) {
|
if (lstat(origin, &sbuf) < 0) {
|
||||||
/* no input file: means earlier phase of update creation failed */
|
/* no input file: means earlier phase of update creation failed */
|
||||||
LOG(NULL, "Failed to stat %s\n", origin);
|
LOG(NULL, "Failed to stat", "%s: %s", origin, strerror(errno));
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -291,10 +291,11 @@ static void submit_fullfile_tasks(GList *files)
|
|||||||
int ret;
|
int ret;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
GError *err = NULL;
|
GError *err = NULL;
|
||||||
|
int numthreads = num_threads(3.0);
|
||||||
|
|
||||||
LOG(NULL, "fullfile threadpool", "%d threads", sysconf(_SC_NPROCESSORS_ONLN) * 3);
|
LOG(NULL, "fullfile threadpool", "%d threads", numthreads);
|
||||||
threadpool = g_thread_pool_new(create_fullfile_task, NULL,
|
threadpool = g_thread_pool_new(create_fullfile_task, NULL,
|
||||||
sysconf(_SC_NPROCESSORS_ONLN) * 3,
|
numthreads,
|
||||||
TRUE, NULL);
|
TRUE, NULL);
|
||||||
|
|
||||||
printf("Starting downloadable fullfiles data creation\n");
|
printf("Starting downloadable fullfiles data creation\n");
|
||||||
|
|||||||
@@ -34,7 +34,6 @@
|
|||||||
int newversion = -1;
|
int newversion = -1;
|
||||||
int minversion = 0;
|
int minversion = 0;
|
||||||
unsigned long long int format = 0;
|
unsigned long long int format = 0;
|
||||||
bool enable_signing = false;
|
|
||||||
|
|
||||||
char *state_dir = NULL;
|
char *state_dir = NULL;
|
||||||
char *packstage_dir = NULL;
|
char *packstage_dir = NULL;
|
||||||
|
|||||||
@@ -284,3 +284,28 @@ void check_root(void)
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int num_threads(float scaling)
|
||||||
|
{
|
||||||
|
const char *var = getenv("SWUPD_NUM_THREADS");
|
||||||
|
int result = sysconf(_SC_NPROCESSORS_ONLN) * scaling;
|
||||||
|
|
||||||
|
if (var && *var) {
|
||||||
|
char *endptr;
|
||||||
|
long int value;
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
value = strtol(var, &endptr, 0);
|
||||||
|
|
||||||
|
if ((errno != 0 && value == 0) || *endptr) {
|
||||||
|
LOG(NULL, "SWUPD_NUM_THREADS must be an integer", "%s", var);
|
||||||
|
} else if ((errno == ERANGE && (value == LONG_MAX || value == LONG_MIN)) ||
|
||||||
|
value < 1 || value > INT_MAX) {
|
||||||
|
LOG(NULL, "SWUPD_NUM_THREADS out of range", "%s", var);
|
||||||
|
} else {
|
||||||
|
result = (int)value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|||||||
+9
-9
@@ -44,15 +44,15 @@ static void runtime_state_heuristics(struct file *file)
|
|||||||
{
|
{
|
||||||
/* these are shipped directories that are not themselves state,
|
/* these are shipped directories that are not themselves state,
|
||||||
* rather only their contents are state */
|
* rather only their contents are state */
|
||||||
if ((strncmp(file->filename, "/usr/src/debug", 14) == 0) ||
|
if ((strcmp(file->filename, "/usr/src/debug") == 0) ||
|
||||||
(strncmp(file->filename, "/dev", 4) == 0) ||
|
(strcmp(file->filename, "/dev") == 0) ||
|
||||||
(strncmp(file->filename, "/home", 5) == 0) ||
|
(strcmp(file->filename, "/home") == 0) ||
|
||||||
(strncmp(file->filename, "/proc", 5) == 0) ||
|
(strcmp(file->filename, "/proc") == 0) ||
|
||||||
(strncmp(file->filename, "/root", 5) == 0) ||
|
(strcmp(file->filename, "/root") == 0) ||
|
||||||
(strncmp(file->filename, "/run", 4) == 0) ||
|
(strcmp(file->filename, "/run") == 0) ||
|
||||||
(strncmp(file->filename, "/sys", 4) == 0) ||
|
(strcmp(file->filename, "/sys") == 0) ||
|
||||||
(strncmp(file->filename, "/tmp", 4) == 0) ||
|
(strcmp(file->filename, "/tmp") == 0) ||
|
||||||
(strncmp(file->filename, "/var", 4) == 0)) {
|
(strcmp(file->filename, "/var") == 0)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
|
|
||||||
#include "swupd.h"
|
#include "swupd.h"
|
||||||
|
|
||||||
static FILE *logfile;
|
static FILE *logfile[2];
|
||||||
|
|
||||||
static struct timeval start_time;
|
static struct timeval start_time;
|
||||||
|
|
||||||
@@ -41,13 +41,13 @@ void init_log(const char *prefix, const char *bundle, int start, int end)
|
|||||||
{
|
{
|
||||||
char *filename;
|
char *filename;
|
||||||
string_or_die(&filename, "%s%s-from-%i-to-%i.log", prefix, bundle, start, end);
|
string_or_die(&filename, "%s%s-from-%i-to-%i.log", prefix, bundle, start, end);
|
||||||
logfile = fopen(filename, "w");
|
logfile[0] = fopen(filename, "w");
|
||||||
free(filename);
|
free(filename);
|
||||||
gettimeofday(&start_time, NULL);
|
gettimeofday(&start_time, NULL);
|
||||||
}
|
}
|
||||||
void init_log_stdout(void)
|
void init_log_stdout(void)
|
||||||
{
|
{
|
||||||
logfile = stdout;
|
logfile[1] = stdout;
|
||||||
gettimeofday(&start_time, NULL);
|
gettimeofday(&start_time, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,8 +91,9 @@ void __log_message(struct file *file, char *msg, char *filename, int linenr, con
|
|||||||
char *logstring = NULL;
|
char *logstring = NULL;
|
||||||
char filebuf[4096];
|
char filebuf[4096];
|
||||||
char filebuf2[4096];
|
char filebuf2[4096];
|
||||||
|
int i;
|
||||||
|
|
||||||
if (!logfile) {
|
if (!logfile[0] && !logfile[1]) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,12 +120,16 @@ void __log_message(struct file *file, char *msg, char *filename, int linenr, con
|
|||||||
strcat(filebuf2, " ");
|
strcat(filebuf2, " ");
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(logfile, "%3i.%03i %5s %s:%03i\t| %s\t| %s\t| %s\n",
|
for (i = 0; i < 2; i++) {
|
||||||
(int)current_time.tv_sec, (int)current_time.tv_usec / 1000, logstring, filebuf, linenr, filebuf2, msg, buf);
|
if (logfile[i]) {
|
||||||
|
fprintf(logfile[i], "%3i.%03i %5s %s:%03i\t| %s\t| %s\t| %s\n",
|
||||||
|
(int)current_time.tv_sec, (int)current_time.tv_usec / 1000, logstring, filebuf, linenr, filebuf2, msg, buf);
|
||||||
|
fflush(logfile[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
free(logstring);
|
free(logstring);
|
||||||
free(buf);
|
free(buf);
|
||||||
fflush(logfile);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void close_log(int version, int exit_status)
|
void close_log(int version, int exit_status)
|
||||||
@@ -133,7 +138,7 @@ void close_log(int version, int exit_status)
|
|||||||
int t_sec;
|
int t_sec;
|
||||||
int t_msec;
|
int t_msec;
|
||||||
|
|
||||||
if (!logfile) {
|
if (!logfile[0] && !logfile[1]) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,6 +164,8 @@ void close_log(int version, int exit_status)
|
|||||||
printf("Update build failed for version %i\n", version);
|
printf("Update build failed for version %i\n", version);
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(logfile);
|
if (logfile[0]) {
|
||||||
logfile = NULL;
|
fclose(logfile[0]);
|
||||||
|
logfile[0] = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
|
#include <locale.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -32,6 +33,7 @@
|
|||||||
|
|
||||||
static const struct option prog_opts[] = {
|
static const struct option prog_opts[] = {
|
||||||
{ "help", no_argument, 0, 'h' },
|
{ "help", no_argument, 0, 'h' },
|
||||||
|
{ "log-stdout", no_argument, 0, 'l' },
|
||||||
{ "statedir", required_argument, 0, 'S' },
|
{ "statedir", required_argument, 0, 'S' },
|
||||||
{ 0, 0, 0, 0 }
|
{ 0, 0, 0, 0 }
|
||||||
};
|
};
|
||||||
@@ -42,6 +44,7 @@ static void usage(const char *name)
|
|||||||
printf(" %s <version>\n\n", name);
|
printf(" %s <version>\n\n", name);
|
||||||
printf("Help options:\n");
|
printf("Help options:\n");
|
||||||
printf(" -h, --help Show help options\n");
|
printf(" -h, --help Show help options\n");
|
||||||
|
printf(" -l, --log-stdout Write log messages also to stdout\n");
|
||||||
printf(" -S, --statedir Optional directory to use for state [ default:=%s ]\n", SWUPD_SERVER_STATE_DIR);
|
printf(" -S, --statedir Optional directory to use for state [ default:=%s ]\n", SWUPD_SERVER_STATE_DIR);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
@@ -56,6 +59,9 @@ static bool parse_options(int argc, char **argv)
|
|||||||
case 'h':
|
case 'h':
|
||||||
usage(argv[0]);
|
usage(argv[0]);
|
||||||
return false;
|
return false;
|
||||||
|
case 'l':
|
||||||
|
init_log_stdout();
|
||||||
|
break;
|
||||||
case 'S':
|
case 'S':
|
||||||
if (!optarg || !set_state_dir(optarg)) {
|
if (!optarg || !set_state_dir(optarg)) {
|
||||||
printf("Invalid --statedir argument '%s'\n\n", optarg);
|
printf("Invalid --statedir argument '%s'\n\n", optarg);
|
||||||
@@ -88,6 +94,11 @@ int main(int argc, char **argv)
|
|||||||
/* keep valgrind working well */
|
/* keep valgrind working well */
|
||||||
setenv("G_SLICE", "always-malloc", 0);
|
setenv("G_SLICE", "always-malloc", 0);
|
||||||
|
|
||||||
|
if (!setlocale(LC_ALL, "")) {
|
||||||
|
fprintf(stderr, "%s: setlocale() failed\n", argv[0]);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
if (!parse_options(argc, argv)) {
|
if (!parse_options(argc, argv)) {
|
||||||
free_state_globals();
|
free_state_globals();
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
|||||||
+11
-13
@@ -27,6 +27,7 @@
|
|||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
#include <locale.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -45,8 +46,8 @@ static void banner(void)
|
|||||||
|
|
||||||
static const struct option prog_opts[] = {
|
static const struct option prog_opts[] = {
|
||||||
{ "help", no_argument, 0, 'h' },
|
{ "help", no_argument, 0, 'h' },
|
||||||
|
{ "log-stdout", no_argument, 0, 'l' },
|
||||||
{ "statedir", required_argument, 0, 'S' },
|
{ "statedir", required_argument, 0, 'S' },
|
||||||
{ "signcontent", no_argument, 0, 's' },
|
|
||||||
{ 0, 0, 0, 0 }
|
{ 0, 0, 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -56,8 +57,8 @@ static void usage(const char *name)
|
|||||||
printf(" %s <start version> <latest version> <bundle>\n\n", name);
|
printf(" %s <start version> <latest version> <bundle>\n\n", name);
|
||||||
printf("Help options:\n");
|
printf("Help options:\n");
|
||||||
printf(" -h, --help Show help options\n");
|
printf(" -h, --help Show help options\n");
|
||||||
|
printf(" -l, --log-stdout Write log messages also to stdout\n");
|
||||||
printf(" -S, --statedir Optional directory to use for state [ default:=%s ]\n", SWUPD_SERVER_STATE_DIR);
|
printf(" -S, --statedir Optional directory to use for state [ default:=%s ]\n", SWUPD_SERVER_STATE_DIR);
|
||||||
printf(" -s, --signcontent Enables cryptographic signing of update content\n");
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,15 +72,15 @@ static bool parse_options(int argc, char **argv)
|
|||||||
case 'h':
|
case 'h':
|
||||||
usage(argv[0]);
|
usage(argv[0]);
|
||||||
return false;
|
return false;
|
||||||
|
case 'l':
|
||||||
|
init_log_stdout();
|
||||||
|
break;
|
||||||
case 'S':
|
case 'S':
|
||||||
if (!optarg || !set_state_dir(optarg)) {
|
if (!optarg || !set_state_dir(optarg)) {
|
||||||
printf("Invalid --statedir argument ''%s'\n\n", optarg);
|
printf("Invalid --statedir argument ''%s'\n\n", optarg);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 's':
|
|
||||||
enable_signing = true;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,6 +102,11 @@ int main(int argc, char **argv)
|
|||||||
int exit_status = EXIT_FAILURE;
|
int exit_status = EXIT_FAILURE;
|
||||||
char *file_path = NULL;
|
char *file_path = NULL;
|
||||||
|
|
||||||
|
if (!setlocale(LC_ALL, "")) {
|
||||||
|
fprintf(stderr, "%s: setlocale() failed\n", argv[0]);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
if (!parse_options(argc, argv)) {
|
if (!parse_options(argc, argv)) {
|
||||||
free_state_globals();
|
free_state_globals();
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
@@ -114,12 +120,6 @@ int main(int argc, char **argv)
|
|||||||
banner();
|
banner();
|
||||||
check_root();
|
check_root();
|
||||||
|
|
||||||
/* Initilize the crypto signature module */
|
|
||||||
if (!signature_initialize()) {
|
|
||||||
printf("Can't initialize the crypto signature module!\n");
|
|
||||||
return exit_status;
|
|
||||||
}
|
|
||||||
|
|
||||||
string_or_die(&file_path, "%s/server.ini", state_dir);
|
string_or_die(&file_path, "%s/server.ini", state_dir);
|
||||||
read_configuration_file(file_path);
|
read_configuration_file(file_path);
|
||||||
free(file_path);
|
free(file_path);
|
||||||
@@ -152,8 +152,6 @@ int main(int argc, char **argv)
|
|||||||
exit_status = EXIT_SUCCESS;
|
exit_status = EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
signature_terminate();
|
|
||||||
|
|
||||||
printf("Pack creation %s (pack-%s %i to %li)\n",
|
printf("Pack creation %s (pack-%s %i to %li)\n",
|
||||||
exit_status == EXIT_SUCCESS ? "complete" : "failed",
|
exit_status == EXIT_SUCCESS ? "complete" : "failed",
|
||||||
module, start_version, end_version);
|
module, start_version, end_version);
|
||||||
|
|||||||
+5
-42
@@ -695,29 +695,6 @@ static void compute_content_size(struct manifest *manifest)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns 0 == success, -1 == failure */
|
|
||||||
static int write_manifest_signature(struct manifest *manifest, const char *suffix)
|
|
||||||
{
|
|
||||||
char *conf = config_output_dir();
|
|
||||||
char *filename = NULL;
|
|
||||||
int ret = -1;
|
|
||||||
|
|
||||||
if (conf == NULL) {
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
string_or_die(&filename, "%s/%i/Manifest.%s%s", conf, manifest->version,
|
|
||||||
manifest->component, suffix);
|
|
||||||
if (!signature_sign(filename)) {
|
|
||||||
fprintf(stderr, "Creating signature for '%s' failed\n", filename);
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
ret = 0;
|
|
||||||
exit:
|
|
||||||
free(filename);
|
|
||||||
free(conf);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Returns 0 == success, -1 == failure */
|
/* Returns 0 == success, -1 == failure */
|
||||||
static int write_manifest_plain(struct manifest *manifest)
|
static int write_manifest_plain(struct manifest *manifest)
|
||||||
{
|
{
|
||||||
@@ -851,7 +828,7 @@ exit:
|
|||||||
static int write_manifest_tar(struct manifest *manifest)
|
static int write_manifest_tar(struct manifest *manifest)
|
||||||
{
|
{
|
||||||
char *conf = config_output_dir();
|
char *conf = config_output_dir();
|
||||||
char *directory, *manifesttar, *manifestcomp, *manifestsigned;
|
char *directory, *manifesttar, *manifestcomp;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (conf == NULL) {
|
if (conf == NULL) {
|
||||||
@@ -861,19 +838,11 @@ static int write_manifest_tar(struct manifest *manifest)
|
|||||||
string_or_die(&directory, "--directory=%s/%i", conf, manifest->version);
|
string_or_die(&directory, "--directory=%s/%i", conf, manifest->version);
|
||||||
string_or_die(&manifesttar, "%s/%i/Manifest.%s.tar", conf, manifest->version, manifest->component);
|
string_or_die(&manifesttar, "%s/%i/Manifest.%s.tar", conf, manifest->version, manifest->component);
|
||||||
string_or_die(&manifestcomp, "Manifest.%s", manifest->component);
|
string_or_die(&manifestcomp, "Manifest.%s", manifest->component);
|
||||||
string_or_die(&manifestsigned, "Manifest.%s.signed", manifest->component);
|
|
||||||
|
|
||||||
/* now, tar the thing up for efficient full file download */
|
/* now, tar the thing up for efficient full file download */
|
||||||
/* and put the signature of the plain manifest into the archive, too */
|
char *const tarcmd[] = { TAR_COMMAND, directory, TAR_PERM_ATTR_ARGS_STRLIST, "-Jcf",
|
||||||
if (enable_signing) {
|
manifesttar, manifestcomp, NULL };
|
||||||
char *const tarcmd[] = { TAR_COMMAND, directory, TAR_PERM_ATTR_ARGS_STRLIST, "-Jcf",
|
ret = system_argv(tarcmd);
|
||||||
manifesttar, manifestcomp, manifestsigned, NULL };
|
|
||||||
ret = system_argv(tarcmd);
|
|
||||||
} else {
|
|
||||||
char *const tarcmd[] = { TAR_COMMAND, directory, TAR_PERM_ATTR_ARGS_STRLIST, "-Jcf",
|
|
||||||
manifesttar, manifestcomp, NULL };
|
|
||||||
ret = system_argv(tarcmd);
|
|
||||||
}
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
fprintf(stderr, "Creation of Manifest.tar failed\n");
|
fprintf(stderr, "Creation of Manifest.tar failed\n");
|
||||||
}
|
}
|
||||||
@@ -881,7 +850,6 @@ static int write_manifest_tar(struct manifest *manifest)
|
|||||||
free(directory);
|
free(directory);
|
||||||
free(manifesttar);
|
free(manifesttar);
|
||||||
free(manifestcomp);
|
free(manifestcomp);
|
||||||
free(manifestsigned);
|
|
||||||
free(conf);
|
free(conf);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -911,9 +879,7 @@ bool compute_hash_with_xattrs(const char *filename)
|
|||||||
int write_manifest(struct manifest *manifest)
|
int write_manifest(struct manifest *manifest)
|
||||||
{
|
{
|
||||||
if (write_manifest_plain(manifest) == 0 &&
|
if (write_manifest_plain(manifest) == 0 &&
|
||||||
write_manifest_signature(manifest, "") == 0 &&
|
write_manifest_tar(manifest) == 0) {
|
||||||
write_manifest_tar(manifest) == 0 &&
|
|
||||||
write_manifest_signature(manifest, ".tar") == 0) {
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
@@ -1115,9 +1081,6 @@ void create_manifest_delta(int oldversion, int newversion, char *module)
|
|||||||
}
|
}
|
||||||
LOG(NULL, "Failed to rename", "");
|
LOG(NULL, "Failed to rename", "");
|
||||||
}
|
}
|
||||||
if (!signature_sign(outfile)) {
|
|
||||||
fprintf(stderr, "Creating signature for '%s' failed\n", outfile);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
sleep(1); /* we raced. whatever. sleep for a bit to get the other guy to make progress */
|
sleep(1); /* we raced. whatever. sleep for a bit to get the other guy to make progress */
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-28
@@ -116,7 +116,7 @@ static void explode_pack_stage(int from_version, int to_version, char *module)
|
|||||||
* time on the client...
|
* time on the client...
|
||||||
*/
|
*/
|
||||||
string_or_die(¶m, "%s/%s/%i_to_%i/staged", packstage_dir, module, from_version, to_version);
|
string_or_die(¶m, "%s/%s/%i_to_%i/staged", packstage_dir, module, from_version, to_version);
|
||||||
char *const tarcmd[] = { TAR_COMMAND, "-C", param, TAR_WARN_ARGS, TAR_PERM_ATTR_ARGS_STRLIST, "-xf", path, NULL };
|
char *const tarcmd[] = { TAR_COMMAND, "-C", param, TAR_WARN_ARGS_STRLIST TAR_PERM_ATTR_ARGS_STRLIST, "-xf", path, NULL };
|
||||||
if (system_argv(tarcmd) == 0) {
|
if (system_argv(tarcmd) == 0) {
|
||||||
unlink(path);
|
unlink(path);
|
||||||
}
|
}
|
||||||
@@ -285,10 +285,11 @@ static void make_pack_deltas(GList *files)
|
|||||||
struct file *file;
|
struct file *file;
|
||||||
int ret;
|
int ret;
|
||||||
GError *err = NULL;
|
GError *err = NULL;
|
||||||
|
int numthreads = num_threads(1.0);
|
||||||
|
|
||||||
LOG(NULL, "pack deltas threadpool", "%d threads", sysconf(_SC_NPROCESSORS_ONLN));
|
LOG(NULL, "pack deltas threadpool", "%d threads", numthreads);
|
||||||
threadpool = g_thread_pool_new(create_delta, NULL,
|
threadpool = g_thread_pool_new(create_delta, NULL,
|
||||||
sysconf(_SC_NPROCESSORS_ONLN), FALSE, NULL);
|
numthreads, FALSE, NULL);
|
||||||
|
|
||||||
item = g_list_first(files);
|
item = g_list_first(files);
|
||||||
while (item) {
|
while (item) {
|
||||||
@@ -307,24 +308,6 @@ static void make_pack_deltas(GList *files)
|
|||||||
g_thread_pool_free(threadpool, FALSE, TRUE);
|
g_thread_pool_free(threadpool, FALSE, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns 0 == success, -1 == failure */
|
|
||||||
static int write_pack_signature(struct packdata *pack)
|
|
||||||
{
|
|
||||||
char *filename = NULL;
|
|
||||||
int ret = -1;
|
|
||||||
|
|
||||||
string_or_die(&filename, "%s/%i/pack-%s-from-%i.tar",
|
|
||||||
staging_dir, pack->to, pack->module, pack->from);
|
|
||||||
if (!signature_sign(filename)) {
|
|
||||||
fprintf(stderr, "Creating signature for '%s' failed\n", filename);
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
ret = 0;
|
|
||||||
exit:
|
|
||||||
free(filename);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Returns 0 == success, other == failure */
|
/* Returns 0 == success, other == failure */
|
||||||
static int make_final_pack(struct packdata *pack)
|
static int make_final_pack(struct packdata *pack)
|
||||||
{
|
{
|
||||||
@@ -507,13 +490,6 @@ static int make_final_pack(struct packdata *pack)
|
|||||||
if ((ret != 0) && (ret != 1)) {
|
if ((ret != 0) && (ret != 1)) {
|
||||||
fprintf(stderr, "Unexpected return value (%d) creating tar of pack %s from %i to %i\n",
|
fprintf(stderr, "Unexpected return value (%d) creating tar of pack %s from %i to %i\n",
|
||||||
ret, pack->module, pack->from, pack->to);
|
ret, pack->module, pack->from, pack->to);
|
||||||
} else {
|
|
||||||
/* Write the signature file */
|
|
||||||
ret = write_pack_signature(pack);
|
|
||||||
if (ret != 0) {
|
|
||||||
fprintf(stderr, "Failure creating signature of pack %s from %i to %i\n",
|
|
||||||
pack->module, pack->from, pack->to);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* and clean up */
|
/* and clean up */
|
||||||
|
|||||||
-173
@@ -1,173 +0,0 @@
|
|||||||
/*
|
|
||||||
* Software Updater - server side
|
|
||||||
*
|
|
||||||
* Copyright © 2012-2016 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* Authors:
|
|
||||||
* Tom Keel <thomas.keel@intel.com>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define _GNU_SOURCE
|
|
||||||
#include <err.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include "swupd.h"
|
|
||||||
|
|
||||||
static char *make_filename(const char *, const char *, const char *);
|
|
||||||
|
|
||||||
static char *leaf_key = NULL;
|
|
||||||
static char *leaf_cert = NULL;
|
|
||||||
static char *ca_chain_cert = NULL;
|
|
||||||
static char *passphrase = NULL;
|
|
||||||
|
|
||||||
static bool initialized = false;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Initialize this module.
|
|
||||||
* @return true <=> success
|
|
||||||
*/
|
|
||||||
bool signature_initialize(void)
|
|
||||||
{
|
|
||||||
if (!enable_signing) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *cdir;
|
|
||||||
char *pphr;
|
|
||||||
struct stat s;
|
|
||||||
|
|
||||||
if (initialized) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
cdir = getenv("SWUPD_CERTS_DIR");
|
|
||||||
if (cdir == NULL || cdir[0] == '\0') {
|
|
||||||
printf("No certificates directory specified\n");
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
if (stat(cdir, &s)) {
|
|
||||||
printf("Can't stat certificates directory '%s' (%s)\n", cdir,
|
|
||||||
strerror(errno));
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
leaf_key = make_filename(cdir, "LEAF_KEY", "leaf key");
|
|
||||||
if (leaf_key == NULL) {
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
leaf_cert = make_filename(cdir, "LEAF_CERT", "leaf certificate");
|
|
||||||
if (leaf_cert == NULL) {
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
ca_chain_cert = make_filename(cdir, "CA_CHAIN_CERT", "CA chain certificate");
|
|
||||||
if (ca_chain_cert == NULL) {
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
pphr = getenv("PASSPHRASE");
|
|
||||||
if (pphr == NULL || (passphrase = strdup(pphr)) == NULL) {
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
if (stat(passphrase, &s)) {
|
|
||||||
printf("Can't stat '%s' (%s)\n", passphrase,
|
|
||||||
strerror(errno));
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
initialized = true;
|
|
||||||
return true;
|
|
||||||
err:
|
|
||||||
signature_terminate();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Make filename from dir name and env variable containing basename */
|
|
||||||
static char *make_filename(const char *dir, const char *env, const char *desc)
|
|
||||||
{
|
|
||||||
char *fn = getenv(env);
|
|
||||||
char *result = NULL;
|
|
||||||
struct stat s;
|
|
||||||
|
|
||||||
if (fn == NULL || fn[0] == '\0') {
|
|
||||||
printf("No %s file specified\n", desc);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
string_or_die(&result, "%s/%s", dir, fn);
|
|
||||||
if (stat(result, &s)) {
|
|
||||||
printf("Can't stat %s '%s' (%s)\n", desc, result, strerror(errno));
|
|
||||||
free(result);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Terminate this module, free resources.
|
|
||||||
*/
|
|
||||||
void signature_terminate(void)
|
|
||||||
{
|
|
||||||
if (!enable_signing) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(leaf_key);
|
|
||||||
free(leaf_cert);
|
|
||||||
free(ca_chain_cert);
|
|
||||||
free(passphrase);
|
|
||||||
|
|
||||||
leaf_key = NULL;
|
|
||||||
leaf_cert = NULL;
|
|
||||||
ca_chain_cert = NULL;
|
|
||||||
passphrase = NULL;
|
|
||||||
|
|
||||||
initialized = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Write the signature file corresponding to the given data file.
|
|
||||||
* The name of the signature file is the name of the data file with suffix
|
|
||||||
* ".signed" appended.
|
|
||||||
*/
|
|
||||||
bool signature_sign(const char *filename)
|
|
||||||
{
|
|
||||||
char *param1, *param2;
|
|
||||||
int status;
|
|
||||||
|
|
||||||
if (!enable_signing) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!initialized) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
string_or_die(¶m1, "%s.signed", filename);
|
|
||||||
string_or_die(¶m2, "file:%s", passphrase);
|
|
||||||
char *const opensslcmd[] = { "openssl", "smime", "-sign", "-in", (char *)filename, "-binary",
|
|
||||||
"-out", param1, "-outform", " PEM", "-md", "sha256", "-inkey",
|
|
||||||
leaf_key, "-signer", leaf_cert, "-certfile", ca_chain_cert,
|
|
||||||
"-passin", param2, NULL };
|
|
||||||
status = system_argv(opensslcmd);
|
|
||||||
if (status != 0) {
|
|
||||||
printf("Bad status %d from signing command\n", status);
|
|
||||||
}
|
|
||||||
free(param1);
|
|
||||||
free(param2);
|
|
||||||
|
|
||||||
return status == 0;
|
|
||||||
}
|
|
||||||
@@ -14,6 +14,7 @@ load "../swupdlib"
|
|||||||
}
|
}
|
||||||
|
|
||||||
@test "make_fullfiles root priv check" {
|
@test "make_fullfiles root priv check" {
|
||||||
|
[ $EUID -eq 0 ] && skip "test can only be run as non-root"
|
||||||
run $MAKE_FULLFILES foo
|
run $MAKE_FULLFILES foo
|
||||||
[ "$status" -eq 1 ]
|
[ "$status" -eq 1 ]
|
||||||
[[ "$output" =~ "not being run as root.. exiting" ]]
|
[[ "$output" =~ "not being run as root.. exiting" ]]
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ load "../swupdlib"
|
|||||||
}
|
}
|
||||||
|
|
||||||
@test "make_pack root priv check" {
|
@test "make_pack root priv check" {
|
||||||
|
[ $EUID -eq 0 ] && skip "test can only be run as non-root"
|
||||||
run $MAKE_PACK foo bar foo
|
run $MAKE_PACK foo bar foo
|
||||||
[ "$status" -eq 1 ]
|
[ "$status" -eq 1 ]
|
||||||
[[ "$output" =~ "not being run as root.. exiting" ]]
|
[[ "$output" =~ "not being run as root.. exiting" ]]
|
||||||
|
|||||||
Executable
+28
@@ -0,0 +1,28 @@
|
|||||||
|
#!/usr/bin/env bats
|
||||||
|
|
||||||
|
# common functions
|
||||||
|
load "../swupdlib"
|
||||||
|
|
||||||
|
setup() {
|
||||||
|
clean_test_dir
|
||||||
|
init_test_dir
|
||||||
|
|
||||||
|
init_server_ini
|
||||||
|
set_latest_ver 0
|
||||||
|
init_groups_ini os-core
|
||||||
|
|
||||||
|
set_os_release 10 os-core
|
||||||
|
track_bundle 10 os-core
|
||||||
|
|
||||||
|
gen_file_plain 10 os-core "/var/lib/test"
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "state file marked in manifest" {
|
||||||
|
sudo $CREATE_UPDATE --osversion 10 --statedir $DIR --format 3
|
||||||
|
|
||||||
|
# a file and dir installed in /var should be marked state
|
||||||
|
grep '^D\.s\..*/var/lib$' $DIR/www/10/Manifest.os-core
|
||||||
|
grep '^F\.s\..*/var/lib/test$' $DIR/www/10/Manifest.os-core
|
||||||
|
}
|
||||||
|
|
||||||
|
# vi: ft=sh ts=8 sw=2 sts=2 et tw=80
|
||||||
@@ -91,7 +91,7 @@ gen_file_plain() {
|
|||||||
local name="$3"
|
local name="$3"
|
||||||
|
|
||||||
# Add plain text file into a bundle
|
# Add plain text file into a bundle
|
||||||
mkdir -p $DIR/image/$ver/$bundle
|
mkdir -p $DIR/image/$ver/$bundle/$(dirname "$name")
|
||||||
echo "$name" > $DIR/image/$ver/$bundle/"$name"
|
echo "$name" > $DIR/image/$ver/$bundle/"$name"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,7 +101,7 @@ gen_file_plain_change() {
|
|||||||
local name="$3"
|
local name="$3"
|
||||||
|
|
||||||
# Add plain text file into a bundle
|
# Add plain text file into a bundle
|
||||||
mkdir -p $DIR/image/$ver/$bundle
|
mkdir -p $DIR/image/$ver/$bundle/$(dirname "$name")
|
||||||
echo "$ver $name" > $DIR/image/$ver/$bundle/"$name"
|
echo "$ver $name" > $DIR/image/$ver/$bundle/"$name"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ load "../swupdlib"
|
|||||||
}
|
}
|
||||||
|
|
||||||
@test "create_update root priv check" {
|
@test "create_update root priv check" {
|
||||||
|
[ $EUID -eq 0 ] && skip "test can only be run as non-root"
|
||||||
run $CREATE_UPDATE -F 3 -o 10
|
run $CREATE_UPDATE -F 3 -o 10
|
||||||
[ "$status" -eq 1 ]
|
[ "$status" -eq 1 ]
|
||||||
[[ "$output" =~ "not being run as root.. exiting" ]]
|
[[ "$output" =~ "not being run as root.. exiting" ]]
|
||||||
|
|||||||
Reference in New Issue
Block a user