mirror of
https://github.com/clearlinux/swupd-server.git
synced 2026-10-04 16:08:29 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
22823ec8c8 | ||
|
|
c69a5d87bf | ||
|
|
b103c214a0 | ||
|
|
beeb3ff9b2 | ||
|
|
1aca06882a | ||
|
|
adb8241a83 | ||
|
|
c963ce9aa6 | ||
|
|
04a1bdfd16 | ||
|
|
1518aa4335 | ||
|
|
9c1a4a3542 | ||
|
|
a9f13e939c | ||
|
|
75039ad6b9 | ||
|
|
9b316bf95c | ||
|
|
b618516167 | ||
|
|
7542d2152a | ||
|
|
490326f2b9 | ||
|
|
307d2427a1 | ||
|
|
72dd27a886 | ||
|
|
7e38f013ef | ||
|
|
4e0fdd4193 | ||
|
|
f01d9ca6c8 | ||
|
|
944dfa1d93 | ||
|
|
963e8117b4 | ||
|
|
57292a5a03 | ||
|
|
fe6f47e4c3 | ||
|
|
13189dd4d4 | ||
|
|
b417fc4391 | ||
|
|
478cdc5272 | ||
|
|
2992dc1978 | ||
|
|
ec31238e1a | ||
|
|
9148ea8a8e | ||
|
|
74c8f86a94 | ||
|
|
a43964b110 | ||
|
|
983b17d68d | ||
|
|
5420a1ea1b | ||
|
|
1c75f53604 | ||
|
|
2890a11c5a | ||
|
|
2401aae76e | ||
|
|
30b46b9027 | ||
|
|
c8ae097ed0 | ||
|
|
076a76fc4e | ||
|
|
63fb5fb61b | ||
|
|
7758a6bb77 | ||
|
|
36c4e6324f | ||
|
|
c4f61cb023 | ||
|
|
379d5189fc | ||
|
|
6eca4601b0 | ||
|
|
4940d0cf83 | ||
|
|
04d2af2f64 | ||
|
|
1f98322737 | ||
|
|
ddca171dad | ||
|
|
62c31f0088 | ||
|
|
54874bd4e1 | ||
|
|
9fe3ad2241 | ||
|
|
be83996e48 | ||
|
|
7f3b760430 | ||
|
|
74f4afa655 | ||
|
|
ea02b67a93 | ||
|
|
8af939c817 | ||
|
|
4128fbbb9b | ||
|
|
0d08824801 | ||
|
|
8f98e0f570 | ||
|
|
76e5af734b | ||
|
|
b7192ee686 | ||
|
|
b0e0b7f77d | ||
|
|
746b9a56a8 | ||
|
|
adfc1067ff | ||
|
|
122f674e74 |
+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
|
||||||
+32
-9
@@ -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 \
|
||||||
@@ -37,13 +36,13 @@ swupd_make_pack_SOURCES = \
|
|||||||
src/config.c \
|
src/config.c \
|
||||||
src/delta.c \
|
src/delta.c \
|
||||||
src/globals.c \
|
src/globals.c \
|
||||||
|
src/groups.c \
|
||||||
src/helpers.c \
|
src/helpers.c \
|
||||||
src/log.c \
|
src/log.c \
|
||||||
src/make_packs.c \
|
src/make_packs.c \
|
||||||
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
|
||||||
|
|
||||||
@@ -53,13 +52,13 @@ swupd_make_fullfiles_SOURCES = \
|
|||||||
src/delta.c \
|
src/delta.c \
|
||||||
src/fullfiles.c \
|
src/fullfiles.c \
|
||||||
src/globals.c \
|
src/globals.c \
|
||||||
|
src/groups.c \
|
||||||
src/helpers.c \
|
src/helpers.c \
|
||||||
src/log.c \
|
src/log.c \
|
||||||
src/make_fullfiles.c \
|
src/make_fullfiles.c \
|
||||||
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
|
||||||
|
|
||||||
@@ -110,13 +109,16 @@ TESTS = $(dist_check_SCRIPTS)
|
|||||||
dist_check_SCRIPTS = \
|
dist_check_SCRIPTS = \
|
||||||
test/functional/basic/test.bats \
|
test/functional/basic/test.bats \
|
||||||
test/functional/delete-no-version-bump/test.bats \
|
test/functional/delete-no-version-bump/test.bats \
|
||||||
test/functional/include-version-bump/test.bats \
|
test/functional/file-name-blacklisted/test.bats \
|
||||||
test/functional/update/test.bats \
|
|
||||||
test/functional/fullfiles/test.bats \
|
|
||||||
test/functional/pack/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/full-run/test.bats \
|
||||||
|
test/functional/fullfiles/test.bats \
|
||||||
|
test/functional/include-version-bump/test.bats \
|
||||||
|
test/functional/no-delta/test.bats \
|
||||||
|
test/functional/pack/test.bats \
|
||||||
|
test/functional/state-file/test.bats \
|
||||||
|
test/functional/subtract-delete/test.bats \
|
||||||
|
test/functional/update/test.bats
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if COVERAGE
|
if COVERAGE
|
||||||
@@ -134,6 +136,27 @@ endif
|
|||||||
distclean-local:
|
distclean-local:
|
||||||
rm -rf aclocal.m4 autogen.sh autom4te.cache config.h.in config.h.in~ configure depcomp install-sh Makefile.in missing compile
|
rm -rf aclocal.m4 autogen.sh autom4te.cache config.h.in config.h.in~ configure depcomp install-sh Makefile.in missing compile
|
||||||
|
|
||||||
|
compliant:
|
||||||
|
@git diff --quiet --exit-code include src; ret=$$?; \
|
||||||
|
if [ $$ret -eq 1 ]; then \
|
||||||
|
echo "Error: can only check code style when include/ and src/ are clean."; \
|
||||||
|
echo "Stash or commit your changes and try again."; \
|
||||||
|
exit $$ret; \
|
||||||
|
elif [ $$ret -gt 1 ]; then \
|
||||||
|
exit $$ret; \
|
||||||
|
fi; \
|
||||||
|
clang-format -i -style=file include/*.h src/*.c; ret=$$?; \
|
||||||
|
if [ $$ret -ne 0 ]; then \
|
||||||
|
exit $$ret; \
|
||||||
|
fi; \
|
||||||
|
git diff --quiet --exit-code include src; ret=$$?; \
|
||||||
|
if [ $$ret -eq 1 ]; then \
|
||||||
|
echo "Code style issues found. Run 'git diff' to view issues."; \
|
||||||
|
elif [ $$ret -eq 0 ]; then \
|
||||||
|
echo "No code style issues found."; \
|
||||||
|
fi; \
|
||||||
|
exit $$ret
|
||||||
|
|
||||||
release:
|
release:
|
||||||
@git rev-parse v$(PACKAGE_VERSION) &> /dev/null; \
|
@git rev-parse v$(PACKAGE_VERSION) &> /dev/null; \
|
||||||
if [ "$$?" -eq 0 ]; then \
|
if [ "$$?" -eq 0 ]; then \
|
||||||
|
|||||||
+2
-6
@@ -15,7 +15,7 @@ error() {
|
|||||||
# eg: all of openstack, pnp, bat, cloud stuff, non-basic scripting language bundles
|
# eg: all of openstack, pnp, bat, cloud stuff, non-basic scripting language bundles
|
||||||
${SWUPDREPO}/mk_groups_ini.sh
|
${SWUPDREPO}/mk_groups_ini.sh
|
||||||
|
|
||||||
PREVREL=`cat ${UPDATEDIR}/image/latest.version`
|
PREVREL=`cat ${UPDATEDIR}/image/LAST_VER`
|
||||||
|
|
||||||
export SWUPD_CERTS_DIR=${SWUPD_CERTS_DIR:-"/root/swupd-certs"}
|
export SWUPD_CERTS_DIR=${SWUPD_CERTS_DIR:-"/root/swupd-certs"}
|
||||||
export LEAF_KEY="leaf.key.pem"
|
export LEAF_KEY="leaf.key.pem"
|
||||||
@@ -45,12 +45,8 @@ for job in $(jobs -p); do
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
# create delta packs for 2 versions back
|
|
||||||
NUM_PACKS=2
|
|
||||||
${SWUPDREPO}/pack_maker.sh ${VER} ${NUM_PACKS}
|
|
||||||
|
|
||||||
# expose the new build to staging / testing
|
# expose the new build to staging / testing
|
||||||
echo ${VER} > ${UPDATEDIR}/image/latest.version
|
echo ${VER} > ${UPDATEDIR}/image/LAST_VER
|
||||||
|
|
||||||
STAGING_FILE="${UPDATEDIR}/www/version/formatstaging/latest"
|
STAGING_FILE="${UPDATEDIR}/www/version/formatstaging/latest"
|
||||||
if [ ! -f "${STAGING_FILE}" ]; then
|
if [ ! -f "${STAGING_FILE}" ]; then
|
||||||
|
|||||||
+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.2.3, timothy.c.pepper@linux.intel.com)
|
AC_INIT(swupd-server, 3.3.4, 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
|
||||||
|
|||||||
+15
-9
@@ -19,19 +19,25 @@
|
|||||||
#if SWUPD_WITH_BSDTAR
|
#if SWUPD_WITH_BSDTAR
|
||||||
#define TAR_COMMAND "bsdtar"
|
#define TAR_COMMAND "bsdtar"
|
||||||
#define TAR_XATTR_ARGS ""
|
#define TAR_XATTR_ARGS ""
|
||||||
#define TAR_WARN_ARGS ""
|
#define TAR_XATTR_ARGS_STRLIST
|
||||||
|
#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_WARN_ARGS "--warning=no-timestamp"
|
#define TAR_XATTR_ARGS_STRLIST "--xattrs", "--xattrs-include='*'",
|
||||||
|
#define TAR_WARN_ARGS_STRLIST "--warning=no-timestamp",
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if SWUPD_WITH_SELINUX
|
#if SWUPD_WITH_SELINUX
|
||||||
#define TAR_PERM_ATTR_ARGS "--preserve-permissions --selinux " TAR_XATTR_ARGS
|
#define TAR_PERM_ATTR_ARGS "--preserve-permissions --selinux " TAR_XATTR_ARGS
|
||||||
|
#define TAR_PERM_ATTR_ARGS_STRLIST TAR_XATTR_ARGS_STRLIST "--preserve-permissions", "--selinux"
|
||||||
#else
|
#else
|
||||||
#define TAR_PERM_ATTR_ARGS "--preserve-permissions " TAR_XATTR_ARGS
|
#define TAR_PERM_ATTR_ARGS "--preserve-permissions " TAR_XATTR_ARGS
|
||||||
|
#define TAR_PERM_ATTR_ARGS_STRLIST TAR_XATTR_ARGS_STRLIST "--preserve-permissions"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define SWUPD_HASH_DIRNAME "DIRECTORY"
|
||||||
|
|
||||||
#if SWUPD_WITH_STATELESS
|
#if SWUPD_WITH_STATELESS
|
||||||
#define OS_IS_STATELESS 1
|
#define OS_IS_STATELESS 1
|
||||||
#else
|
#else
|
||||||
@@ -137,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;
|
||||||
@@ -215,6 +220,7 @@ extern void read_group_file(char *filename);
|
|||||||
extern void release_group_file(void);
|
extern void release_group_file(void);
|
||||||
extern char *group_groups(char *group);
|
extern char *group_groups(char *group);
|
||||||
extern char *group_packages(char *group);
|
extern char *group_packages(char *group);
|
||||||
|
extern char *group_status(char *group);
|
||||||
extern char *next_group(void);
|
extern char *next_group(void);
|
||||||
|
|
||||||
extern void apply_heuristics(struct manifest *manifest);
|
extern void apply_heuristics(struct manifest *manifest);
|
||||||
@@ -238,7 +244,7 @@ extern void type_change_detection(struct manifest *manifest);
|
|||||||
|
|
||||||
extern void rename_detection(struct manifest *manifest, int last_change, GList *last_versions_list);
|
extern void rename_detection(struct manifest *manifest, int last_change, GList *last_versions_list);
|
||||||
extern void link_renames(GList *newfiles, struct manifest *from_manifest);
|
extern void link_renames(GList *newfiles, struct manifest *from_manifest);
|
||||||
extern void __create_delta(struct file *file, int from_version);
|
extern void __create_delta(struct file *file, int from_version, char *from_hash);
|
||||||
|
|
||||||
extern void account_delta_hit(void);
|
extern void account_delta_hit(void);
|
||||||
extern void account_delta_miss(void);
|
extern void account_delta_miss(void);
|
||||||
@@ -246,11 +252,11 @@ extern void account_delta_miss(void);
|
|||||||
extern FILE *fopen_exclusive(const char *filename); /* no mode, opens for write only */
|
extern FILE *fopen_exclusive(const char *filename); /* no mode, opens for write only */
|
||||||
extern void dump_file_info(struct file *file);
|
extern void dump_file_info(struct file *file);
|
||||||
extern void string_or_die(char **strp, const char *fmt, ...);
|
extern void string_or_die(char **strp, const char *fmt, ...);
|
||||||
extern void print_elapsed_time(struct timeval *previous_time, struct timeval *current_time);
|
extern void print_elapsed_time(const char *step, struct timeval *previous_time, struct timeval *current_time);
|
||||||
extern int system_argv(char *const argv[]);
|
extern int system_argv(char *const argv[]);
|
||||||
|
extern int system_argv_fd(char *const argv[], int newstdin, int newstdout, int newstderr);
|
||||||
extern bool signature_initialize(void);
|
extern int system_argv_pipe(char *const argvp1[], int stdinp1, int stderrp1,
|
||||||
extern void signature_terminate(void);
|
char *const argvp2[], int stdoutp2, int stderrp2);
|
||||||
extern bool signature_sign(const char *filename);
|
extern int num_threads(float scaling);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+6
-2
@@ -18,8 +18,8 @@ if [ ! -f "$SWUPD_SERVER_INI" ]; then
|
|||||||
sed -i "s|/var/lib/update|$UPDATEDIR|" $SWUPD_SERVER_INI
|
sed -i "s|/var/lib/update|$UPDATEDIR|" $SWUPD_SERVER_INI
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ ! -f "$UPDATEDIR/image/latest.version" ]; then
|
if [ ! -f "$UPDATEDIR/image/LAST_VER" ]; then
|
||||||
echo "0" > $UPDATEDIR/image/latest.version
|
echo "0" > $UPDATEDIR/image/LAST_VER
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "rebuilding $SWUPD_GROUPS_INI based on $BUNDLEREPO"
|
echo "rebuilding $SWUPD_GROUPS_INI based on $BUNDLEREPO"
|
||||||
@@ -27,7 +27,11 @@ rm -f $SWUPD_GROUPS_INI
|
|||||||
|
|
||||||
for bundle in $(ls $BUNDLEREPO/bundles)
|
for bundle in $(ls $BUNDLEREPO/bundles)
|
||||||
do
|
do
|
||||||
|
status=$(awk -F: '/^# .STATUS/ {print $2}' $BUNDLEREPO/$bundle | tr -cd '[[:alnum:]]')
|
||||||
echo "[$bundle]" >> $SWUPD_GROUPS_INI
|
echo "[$bundle]" >> $SWUPD_GROUPS_INI
|
||||||
echo "group=$bundle" >> $SWUPD_GROUPS_INI
|
echo "group=$bundle" >> $SWUPD_GROUPS_INI
|
||||||
|
if [ -n "$status" ]; then
|
||||||
|
echo "status=$status" >> $SWUPD_GROUPS_INI
|
||||||
|
fi
|
||||||
echo "" >> $SWUPD_GROUPS_INI
|
echo "" >> $SWUPD_GROUPS_INI
|
||||||
done
|
done
|
||||||
|
|||||||
-112
@@ -1,112 +0,0 @@
|
|||||||
#!/bin/bash -e
|
|
||||||
# usage:
|
|
||||||
# pack_maker.sh <to version> <back_count>
|
|
||||||
# pack_maker.sh 2820 2
|
|
||||||
# pack_maker.sh 2730 3
|
|
||||||
#
|
|
||||||
# For each bundle changed as of the Manifest.MoM at the <to version>,
|
|
||||||
# create version-pair packs going back <back_count>
|
|
||||||
# versions of that bundle. For example if bundle "editors" changed in 2650
|
|
||||||
# and the script is run as "pack_maker.sh 2650 2", it will find that
|
|
||||||
# "editors" last two change points were 2550 and 2260 and thus create a
|
|
||||||
# 2550-to-2650 and a 2260-to-2650 version pair pack for the "editors"
|
|
||||||
# bundle.
|
|
||||||
|
|
||||||
#NOTE: fullfiles must be created before calling this script
|
|
||||||
#NOTE: zero packs need similarly created
|
|
||||||
|
|
||||||
#NOTE: build numbers are sparse, search back for the next oldest existing build
|
|
||||||
#NOTE: in the future isn't simply -10, and when that change happens we must also
|
|
||||||
# consider which version-pair packs are meaningful for intermediate builds
|
|
||||||
# and revert builds.
|
|
||||||
|
|
||||||
SWUPDREPO=${SWUPDREPO:-"/usr/src/clear-projects/swupd-server"}
|
|
||||||
BUNDLEREPO=${BUNDLEREPO:-"/usr/src/clear-projects/clr-bundles"}
|
|
||||||
UPDATEDIR=${UPDATEDIR:-"/var/lib/update"}
|
|
||||||
SWUPDWEBDIR="${UPDATEDIR}/www"
|
|
||||||
SWUPD_CERTS_DIR=${SWUPD_CERTS_DIR=:-"/root/swupd-certs"}
|
|
||||||
|
|
||||||
export XZ_DEFAULTS="--threads 0"
|
|
||||||
|
|
||||||
export SWUPD_CERTS_DIR
|
|
||||||
export LEAF_KEY="leaf.key.pem"
|
|
||||||
export LEAF_CERT="leaf.cert.pem"
|
|
||||||
export CA_CHAIN_CERT="ca-chain.cert.pem"
|
|
||||||
export PASSPHRASE="${SWUPD_CERTS_DIR}/passphrase"
|
|
||||||
|
|
||||||
VER=$1
|
|
||||||
BACK_COUNT=$2
|
|
||||||
|
|
||||||
if [ "${BACK_COUNT}" == "" ]; then
|
|
||||||
echo "missing to pack count"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "${VER}" == "" ]; then
|
|
||||||
echo "missing to version"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
MOM=${SWUPDWEBDIR}/${VER}/Manifest.MoM
|
|
||||||
if [ ! -e ${MOM} ]; then
|
|
||||||
echo "invalid version (no ${MOM})"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
#time ${SWUPDREPO}/swupd_make_fullfiles --statedir ${UPDATEDIR} ${VER}
|
|
||||||
|
|
||||||
BUNDLE_LIST=$(cat ${MOM} | awk -v V=${VER} '$1 ~ /^M\./ && $3 == V { print $4 }')
|
|
||||||
|
|
||||||
# build packs for all bundles changed in $VER
|
|
||||||
for BUNDLE in $BUNDLE_LIST; do
|
|
||||||
#${SWUPDREPO}/swupd_make_pack --statedir ${UPDATEDIR} 0 ${VER} ${BUNDLE} &
|
|
||||||
|
|
||||||
BUNDLE_VER_LIST=""
|
|
||||||
MANIFEST_VER=$(cat ${SWUPDWEBDIR}/$VER/Manifest.MoM | grep "^previous:" | cut -f 2)
|
|
||||||
BUNDLE_VER=""
|
|
||||||
COUNT=0
|
|
||||||
while [ $COUNT -lt $BACK_COUNT ] && [ $MANIFEST_VER -gt 0 ]; do
|
|
||||||
MOM=${SWUPDWEBDIR}/$MANIFEST_VER/Manifest.MoM
|
|
||||||
if [ -e ${MOM} ]; then
|
|
||||||
BUNDLE_VER=$(cat ${MOM} | grep " ${BUNDLE}$" | cut -f 3)
|
|
||||||
if [ "$BUNDLE_VER" != "" ]; then
|
|
||||||
BUNDLE_VER_LIST="$BUNDLE_VER $BUNDLE_VER_LIST"
|
|
||||||
MANIFEST_VER=$(cat ${SWUPDWEBDIR}/$BUNDLE_VER/Manifest.MoM | grep "^previous:" | cut -f 2)
|
|
||||||
let COUNT=$((COUNT+1))
|
|
||||||
else
|
|
||||||
# back in history to where bundle didn't exist yet
|
|
||||||
MANIFEST_VER=0
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
# seek backwards until a manifest if found
|
|
||||||
MANIFEST_VER=$((MANIFEST_VER-10))
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
for v in $BUNDLE_VER_LIST; do
|
|
||||||
if [ -e ${SWUPDWEBDIR}/${VER}/pack-${BUNDLE}-from-$v.tar ]; then
|
|
||||||
echo "${VER}/pack-${BUNDLE}-from-$v.tar already exists, skipping."
|
|
||||||
else
|
|
||||||
${SWUPDREPO}/swupd_make_pack --statedir ${UPDATEDIR} $v ${VER} ${BUNDLE} &
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
done
|
|
||||||
|
|
||||||
for job in $(jobs -p)
|
|
||||||
do
|
|
||||||
wait ${job}
|
|
||||||
RET=$?
|
|
||||||
if [ "$RET" != "0" ]; then
|
|
||||||
echo "pack creation failure!"
|
|
||||||
exit $RET
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
# NOTE: your devops will want to expose the completed swupd server build to
|
|
||||||
# trial usage at some point. This would be done via code like:
|
|
||||||
#
|
|
||||||
# echo ${VER} > ${SWUPDWEBDIR}/../image/latest.version
|
|
||||||
# STAGING=$(cat ${SWUPDWEBDIR}/version/formatstaging/latest)
|
|
||||||
# if [ "${STAGING}" -lt "${VER}" ]; then
|
|
||||||
# echo ${VER} > ${SWUPDWEBDIR}/version/formatstaging/latest
|
|
||||||
# fi
|
|
||||||
+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
-47
@@ -222,7 +222,7 @@ int compute_hash(struct file *file, char *filename)
|
|||||||
hmac_sha256_for_string(file->hash,
|
hmac_sha256_for_string(file->hash,
|
||||||
(const unsigned char *)key,
|
(const unsigned char *)key,
|
||||||
key_len,
|
key_len,
|
||||||
file->filename); //file->filename not filename
|
SWUPD_HASH_DIRNAME); // Make independent of dirname
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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,149 @@ 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 +456,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 (entry->d_type == DT_DIR) {
|
/* takes ownership of the strings, so we don't need to free it */
|
||||||
|
file = add_file(manifest, entry->d_name, sub_filename, fullname, do_hash);
|
||||||
|
|
||||||
|
if (file && file->is_dir) {
|
||||||
iterate_directory(manifest, pathprefix, file->filename, do_hash);
|
iterate_directory(manifest, pathprefix, file->filename, do_hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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 */
|
|
||||||
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 +473,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 +481,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);
|
||||||
|
|
||||||
@@ -418,7 +505,7 @@ GList *get_sub_manifest_includes(char *component, int version)
|
|||||||
char *included;
|
char *included;
|
||||||
char line[8192];
|
char line[8192];
|
||||||
|
|
||||||
conf = config_output_dir();
|
conf = config_image_base();
|
||||||
if (conf == NULL) {
|
if (conf == NULL) {
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|||||||
+23
-14
@@ -34,22 +34,28 @@
|
|||||||
|
|
||||||
void chroot_create_full(int newversion)
|
void chroot_create_full(int newversion)
|
||||||
{
|
{
|
||||||
int ret;
|
|
||||||
char *group;
|
char *group;
|
||||||
char *command;
|
char *param;
|
||||||
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(&command, "rsync -aAX %s/%i/os-core/ %s",
|
if (!access(param, F_OK)) {
|
||||||
image_dir, newversion, full_dir);
|
LOG(NULL, "Copying chroot os-core to full", "");
|
||||||
ret = system(command);
|
char *const rsynccmd[] = { "rsync", "-aAX", param, full_dir, NULL };
|
||||||
assert(ret == 0);
|
if (system_argv(rsynccmd) != 0) {
|
||||||
free(command);
|
assert(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(param);
|
||||||
|
|
||||||
/* overlay any new files from each group */
|
/* overlay any new files from each group */
|
||||||
while (1) {
|
while (1) {
|
||||||
@@ -58,12 +64,15 @@ 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(&command, "rsync -aAX --ignore-existing %s/%i/%s/ %s",
|
if (!access(param, F_OK)) {
|
||||||
image_dir, newversion, group, full_dir);
|
LOG(NULL, "Overlaying bundle chroot onto full", "%s", group);
|
||||||
ret = system(command);
|
char *const rsynccmd[] = { "rsync", "-aAX", "--ignore-existing", param, full_dir, NULL };
|
||||||
assert(ret == 0);
|
if (system_argv(rsynccmd) != 0) {
|
||||||
free(command);
|
assert(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(param);
|
||||||
}
|
}
|
||||||
free(full_dir);
|
free(full_dir);
|
||||||
}
|
}
|
||||||
|
|||||||
+49
-25
@@ -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,13 +141,14 @@ 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);
|
||||||
|
|
||||||
if ((access(newversiondir, F_OK | R_OK) != 0) && (version == 0)) {
|
if ((access(newversiondir, F_OK | R_OK) != 0) && (version == 0)) {
|
||||||
char *latestpath = NULL;
|
char *latestpath = NULL;
|
||||||
|
|
||||||
string_or_die(&latestpath, "%s/latest.version", image_dir);
|
string_or_die(&latestpath, "%s/LAST_VER", image_dir);
|
||||||
|
|
||||||
printf("** %s does not exist... creating and populating\n", newversiondir);
|
printf("** %s does not exist... creating and populating\n", newversiondir);
|
||||||
if (mkdir(newversiondir, 0755) != 0) {
|
if (mkdir(newversiondir, 0755) != 0) {
|
||||||
@@ -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)
|
||||||
@@ -212,6 +217,25 @@ static int check_build_env(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int check_group_file(void)
|
||||||
|
{
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
// Ensure the os-core group is defined
|
||||||
|
while (1) {
|
||||||
|
char *group = next_group();
|
||||||
|
if (!group) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (strcmp(group, "os-core") == 0) {
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
struct manifest *new_core = NULL;
|
struct manifest *new_core = NULL;
|
||||||
@@ -240,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;
|
||||||
@@ -253,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);
|
||||||
@@ -270,8 +293,13 @@ int main(int argc, char **argv)
|
|||||||
string_or_die(&file_path, "%s/groups.ini", state_dir);
|
string_or_die(&file_path, "%s/groups.ini", state_dir);
|
||||||
read_group_file(file_path);
|
read_group_file(file_path);
|
||||||
free(file_path);
|
free(file_path);
|
||||||
|
ret = check_group_file();
|
||||||
|
if (ret != 0) {
|
||||||
|
printf("os-core bundle is not listed in groups.ini, this is required.\n");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
read_current_version("latest.version");
|
read_current_version("LAST_VER");
|
||||||
printf("Last processed version is %i\n", current_version);
|
printf("Last processed version is %i\n", current_version);
|
||||||
|
|
||||||
populate_dirs(newversion);
|
populate_dirs(newversion);
|
||||||
@@ -288,7 +316,7 @@ int main(int argc, char **argv)
|
|||||||
printf("Syncing bundle chroots with full chroot\n");
|
printf("Syncing bundle chroots with full chroot\n");
|
||||||
chroot_create_full(newversion);
|
chroot_create_full(newversion);
|
||||||
|
|
||||||
print_elapsed_time(&previous_time, ¤t_time);
|
print_elapsed_time("full chroot creation", &previous_time, ¤t_time);
|
||||||
|
|
||||||
printf("Calculating full manifest (this is expensive/slow)\n");
|
printf("Calculating full manifest (this is expensive/slow)\n");
|
||||||
old_full = manifest_from_file(current_version, "full");
|
old_full = manifest_from_file(current_version, "full");
|
||||||
@@ -307,7 +335,7 @@ int main(int argc, char **argv)
|
|||||||
#warning disabled rename detection for some simplicity
|
#warning disabled rename detection for some simplicity
|
||||||
// rename_detection(new_full);
|
// rename_detection(new_full);
|
||||||
|
|
||||||
print_elapsed_time(&previous_time, ¤t_time);
|
print_elapsed_time("full manifest creation", &previous_time, ¤t_time);
|
||||||
|
|
||||||
printf("Entering phase 2: Doing the os-core bundle\n");
|
printf("Entering phase 2: Doing the os-core bundle\n");
|
||||||
/* Phase 2 : the os-core set */
|
/* Phase 2 : the os-core set */
|
||||||
@@ -357,7 +385,6 @@ int main(int argc, char **argv)
|
|||||||
printf("Core component manifest write failed\n");
|
printf("Core component manifest write failed\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
create_manifest_deltas(new_core, manifests_last_versions_list);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nest_manifest(new_MoM, new_core);
|
nest_manifest(new_MoM, new_core);
|
||||||
@@ -458,7 +485,6 @@ int main(int argc, char **argv)
|
|||||||
printf("%s component manifest write failed\n", group);
|
printf("%s component manifest write failed\n", group);
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
create_manifest_deltas(newm, manifests_last_versions_list);
|
|
||||||
} else {
|
} else {
|
||||||
LOG(NULL, "", "%s component has not changed (after pruning), no new manifest", group);
|
LOG(NULL, "", "%s component has not changed (after pruning), no new manifest", group);
|
||||||
printf("%s component has not changed (after pruning), no new manifest\n", group);
|
printf("%s component has not changed (after pruning), no new manifest\n", group);
|
||||||
@@ -469,7 +495,7 @@ int main(int argc, char **argv)
|
|||||||
nest_manifest(new_MoM, newm);
|
nest_manifest(new_MoM, newm);
|
||||||
}
|
}
|
||||||
|
|
||||||
print_elapsed_time(&previous_time, ¤t_time);
|
print_elapsed_time("bundle manifest creation", &previous_time, ¤t_time);
|
||||||
|
|
||||||
printf("Entering phase 4: completion manifests \n");
|
printf("Entering phase 4: completion manifests \n");
|
||||||
/* Phase 4 : manifest completion */
|
/* Phase 4 : manifest completion */
|
||||||
@@ -480,9 +506,8 @@ int main(int argc, char **argv)
|
|||||||
printf("Failed to write new MoM\n");
|
printf("Failed to write new MoM\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
create_manifest_deltas(new_MoM, manifests_last_versions_list);
|
|
||||||
|
|
||||||
print_elapsed_time(&previous_time, ¤t_time);
|
print_elapsed_time("MoM creation", &previous_time, ¤t_time);
|
||||||
|
|
||||||
printf("Entering phase 5: creating download content\n");
|
printf("Entering phase 5: creating download content\n");
|
||||||
/* Phase 5: wrapping up */
|
/* Phase 5: wrapping up */
|
||||||
@@ -499,17 +524,16 @@ int main(int argc, char **argv)
|
|||||||
/* Step 8: Prepare delta directory */
|
/* Step 8: Prepare delta directory */
|
||||||
prepare_delta_dir(new_full);
|
prepare_delta_dir(new_full);
|
||||||
|
|
||||||
print_elapsed_time(&previous_time, ¤t_time);
|
print_elapsed_time("finalize update", &previous_time, ¤t_time);
|
||||||
|
|
||||||
exit_status = EXIT_SUCCESS;
|
exit_status = EXIT_SUCCESS;
|
||||||
exit:
|
exit:
|
||||||
if (exit_status == EXIT_SUCCESS) {
|
if (exit_status == EXIT_SUCCESS) {
|
||||||
write_cookiecrumbs_to_download_area(newversion);
|
write_cookiecrumbs_to_download_area(newversion);
|
||||||
//write_new_version("latest.version", newversion);
|
//write_new_version("LAST_VER", newversion);
|
||||||
}
|
}
|
||||||
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);
|
||||||
|
|||||||
+12
-14
@@ -35,14 +35,13 @@
|
|||||||
#include "swupd.h"
|
#include "swupd.h"
|
||||||
#include "xattrs.h"
|
#include "xattrs.h"
|
||||||
|
|
||||||
void __create_delta(struct file *file, int from_version)
|
void __create_delta(struct file *file, int from_version, char *from_hash)
|
||||||
{
|
{
|
||||||
char *original, *newfile, *outfile, *dotfile, *testnewfile, *sanitycheck;
|
char *original, *newfile, *outfile, *dotfile, *testnewfile, *conf;
|
||||||
char *conf;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (file->is_link) {
|
if (!file->is_file || !file->peer->is_file) {
|
||||||
return;
|
return; /* only support deltas between two regular files right now */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (file->is_deleted) {
|
if (file->is_deleted) {
|
||||||
@@ -62,10 +61,9 @@ void __create_delta(struct file *file, int from_version)
|
|||||||
|
|
||||||
conf = config_output_dir();
|
conf = config_output_dir();
|
||||||
|
|
||||||
string_or_die(&outfile, "%s/%i/delta/%i-%i-%s", conf, file->last_change, from_version, file->last_change, file->hash);
|
string_or_die(&outfile, "%s/%i/delta/%i-%i-%s-%s", conf, file->last_change, from_version, file->last_change, from_hash, file->hash);
|
||||||
string_or_die(&dotfile, "%s/%i/delta/.%i-%i-%s", conf, file->last_change, from_version, file->last_change, file->hash);
|
string_or_die(&dotfile, "%s/%i/delta/.%i-%i-%s-%s", conf, file->last_change, from_version, file->last_change, from_hash, file->hash);
|
||||||
string_or_die(&testnewfile, "%s/%i/delta/.%i-%i-%s.testnewfile", conf, file->last_change, from_version, file->last_change, file->hash);
|
string_or_die(&testnewfile, "%s/%i/delta/.%i-%i-%s-%s.testnewfile", conf, file->last_change, from_version, file->last_change, from_hash, file->hash);
|
||||||
string_or_die(&sanitycheck, "cmp -s \"%s\" \"%s\"", newfile, testnewfile);
|
|
||||||
|
|
||||||
LOG(file, "Making delta", "%s->%s", original, newfile);
|
LOG(file, "Making delta", "%s->%s", original, newfile);
|
||||||
|
|
||||||
@@ -99,7 +97,7 @@ void __create_delta(struct file *file, int from_version)
|
|||||||
ret = 0;
|
ret = 0;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
xattrs_copy(original, newfile);
|
xattrs_copy(original, testnewfile);
|
||||||
|
|
||||||
/* does xattrs have been correctly copied?*/
|
/* does xattrs have been correctly copied?*/
|
||||||
if (xattrs_compare(original, testnewfile) != 0) {
|
if (xattrs_compare(original, testnewfile) != 0) {
|
||||||
@@ -110,13 +108,14 @@ void __create_delta(struct file *file, int from_version)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = system(sanitycheck);
|
char *const sanitycheck[] = { "cmp", "-s", newfile, testnewfile, NULL };
|
||||||
if (ret == -1 || !WIFEXITED(ret) || WEXITSTATUS(ret) == 2) {
|
ret = system_argv(sanitycheck);
|
||||||
|
if (ret == -1 || ret == 2) {
|
||||||
printf("Sanity check system command failed %i. \n", ret);
|
printf("Sanity check system command failed %i. \n", ret);
|
||||||
printf("%s->%s via diff %s yielded %s\n", original, newfile, dotfile, testnewfile);
|
printf("%s->%s via diff %s yielded %s\n", original, newfile, dotfile, testnewfile);
|
||||||
assert(0);
|
assert(0);
|
||||||
goto out;
|
goto out;
|
||||||
} else if (WEXITSTATUS(ret) == 1) {
|
} else if (ret == 1) {
|
||||||
printf("Delta application resulted in file mismatch %i. \n", ret);
|
printf("Delta application resulted in file mismatch %i. \n", ret);
|
||||||
printf("%s->%s via diff %s yielded %s\n", original, newfile, dotfile, testnewfile);
|
printf("%s->%s via diff %s yielded %s\n", original, newfile, dotfile, testnewfile);
|
||||||
LOG(file, "Delta mismatch:", "%s->%s via diff %s yielded %s", original, newfile, dotfile, testnewfile);
|
LOG(file, "Delta mismatch:", "%s->%s via diff %s yielded %s", original, newfile, dotfile, testnewfile);
|
||||||
@@ -137,7 +136,6 @@ void __create_delta(struct file *file, int from_version)
|
|||||||
LOG(NULL, "Failed to rename", "");
|
LOG(NULL, "Failed to rename", "");
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
free(sanitycheck);
|
|
||||||
free(testnewfile);
|
free(testnewfile);
|
||||||
free(conf);
|
free(conf);
|
||||||
free(newfile);
|
free(newfile);
|
||||||
|
|||||||
+53
-35
@@ -24,6 +24,7 @@
|
|||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@@ -41,7 +42,6 @@
|
|||||||
static void create_fullfile(struct file *file)
|
static void create_fullfile(struct file *file)
|
||||||
{
|
{
|
||||||
char *origin;
|
char *origin;
|
||||||
char *tarcommand = NULL;
|
|
||||||
char *tarname = NULL;
|
char *tarname = NULL;
|
||||||
char *rename_source = NULL;
|
char *rename_source = NULL;
|
||||||
char *rename_target = NULL;
|
char *rename_target = NULL;
|
||||||
@@ -49,6 +49,8 @@ static void create_fullfile(struct file *file)
|
|||||||
int ret;
|
int ret;
|
||||||
struct stat sbuf;
|
struct stat sbuf;
|
||||||
char *empty, *indir, *outdir;
|
char *empty, *indir, *outdir;
|
||||||
|
char *param1, *param2;
|
||||||
|
int stderrfd;
|
||||||
|
|
||||||
if (file->is_deleted) {
|
if (file->is_deleted) {
|
||||||
return; /* file got deleted -> by definition we cannot tar it up */
|
return; /* file got deleted -> by definition we cannot tar it up */
|
||||||
@@ -70,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,13 +93,22 @@ static void create_fullfile(struct file *file)
|
|||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
string_or_die(&tarcommand, TAR_COMMAND " -C %s " TAR_PERM_ATTR_ARGS " -cf - --exclude='%s/?*' './%s' 2> /dev/null | " TAR_COMMAND " -C %s " TAR_PERM_ATTR_ARGS " -xf - 2> /dev/null",
|
string_or_die(¶m1, "--exclude=%s/?*", base);
|
||||||
dir, base, base, rename_tmpdir);
|
string_or_die(¶m2, "./%s", base);
|
||||||
if (system(tarcommand) != 0) {
|
char *const tarcfcmd[] = { TAR_COMMAND, "-C", dir, TAR_PERM_ATTR_ARGS_STRLIST, "-cf", "-", param1, param2, NULL };
|
||||||
LOG(NULL, "Failed to run command:", "%s", tarcommand);
|
char *const tarxfcmd[] = { TAR_COMMAND, "-C", rename_tmpdir, TAR_PERM_ATTR_ARGS_STRLIST, "-xf", "-", NULL };
|
||||||
|
|
||||||
|
stderrfd = open("/dev/null", O_WRONLY);
|
||||||
|
if (stderrfd == -1) {
|
||||||
|
LOG(NULL, "Failed to open /dev/null", "");
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
free(tarcommand);
|
if (system_argv_pipe(tarcfcmd, -1, stderrfd, tarxfcmd, -1, stderrfd) != 0) {
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
free(param1);
|
||||||
|
free(param2);
|
||||||
|
close(stderrfd);
|
||||||
|
|
||||||
string_or_die(&rename_source, "%s/%s", rename_tmpdir, base);
|
string_or_die(&rename_source, "%s/%s", rename_tmpdir, base);
|
||||||
string_or_die(&rename_target, "%s/%s", rename_tmpdir, file->hash);
|
string_or_die(&rename_target, "%s/%s", rename_tmpdir, file->hash);
|
||||||
@@ -108,13 +119,13 @@ static void create_fullfile(struct file *file)
|
|||||||
free(rename_source);
|
free(rename_source);
|
||||||
|
|
||||||
/* for a directory file, tar up simply with gzip */
|
/* for a directory file, tar up simply with gzip */
|
||||||
string_or_die(&tarcommand, TAR_COMMAND " -C %s " TAR_PERM_ATTR_ARGS " -zcf %s/%i/files/%s.tar %s",
|
string_or_die(¶m1, "%s/%i/files/%s.tar", outdir, file->last_change, file->hash);
|
||||||
rename_tmpdir, outdir, file->last_change, file->hash, file->hash);
|
char *const tarcmd[] = { TAR_COMMAND, "-C", rename_tmpdir, TAR_PERM_ATTR_ARGS_STRLIST, "-zcf", param1, file->hash, NULL };
|
||||||
if (system(tarcommand) != 0) {
|
|
||||||
LOG(NULL, "Failed to run command:", "%s", tarcommand);
|
if (system_argv(tarcmd) != 0) {
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
free(tarcommand);
|
free(param1);
|
||||||
|
|
||||||
if (rmdir(rename_target)) {
|
if (rmdir(rename_target)) {
|
||||||
LOG(NULL, "rmdir failed for %s", rename_target);
|
LOG(NULL, "rmdir failed for %s", rename_target);
|
||||||
@@ -144,29 +155,38 @@ static void create_fullfile(struct file *file)
|
|||||||
|
|
||||||
/* step 2a: tar it with each compression type */
|
/* step 2a: tar it with each compression type */
|
||||||
// lzma
|
// lzma
|
||||||
string_or_die(&tarcommand, TAR_COMMAND " --directory=%s " TAR_PERM_ATTR_ARGS " -Jcf %s/%i/files/%s.tar.xz %s",
|
string_or_die(¶m1, "--directory=%s", empty);
|
||||||
empty, outdir, file->last_change, file->hash, file->hash);
|
string_or_die(¶m2, "%s/%i/files/%s.tar.xz", outdir, file->last_change, file->hash);
|
||||||
if (system(tarcommand) != 0) {
|
char *const tarlzmacmd[] = { TAR_COMMAND, param1, TAR_PERM_ATTR_ARGS_STRLIST, "-Jcf", param2, file->hash, NULL };
|
||||||
LOG(NULL, "Failed to run command:", "%s", tarcommand);
|
|
||||||
|
if (system_argv(tarlzmacmd) != 0) {
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
free(tarcommand);
|
free(param1);
|
||||||
|
free(param2);
|
||||||
|
|
||||||
// gzip
|
// gzip
|
||||||
string_or_die(&tarcommand, TAR_COMMAND " --directory=%s " TAR_PERM_ATTR_ARGS " -zcf %s/%i/files/%s.tar.gz %s",
|
string_or_die(¶m1, "--directory=%s", empty);
|
||||||
empty, outdir, file->last_change, file->hash, file->hash);
|
string_or_die(¶m2, "%s/%i/files/%s.tar.gz", outdir, file->last_change, file->hash);
|
||||||
if (system(tarcommand) != 0) {
|
char *const targzipcmd[] = { TAR_COMMAND, param1, TAR_PERM_ATTR_ARGS_STRLIST, "-zcf", param2, file->hash, NULL };
|
||||||
LOG(NULL, "Failed to run command:", "%s", tarcommand);
|
|
||||||
|
if (system_argv(targzipcmd) != 0) {
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
free(tarcommand);
|
free(param1);
|
||||||
|
free(param2);
|
||||||
|
|
||||||
#ifdef SWUPD_WITH_BZIP2
|
#ifdef SWUPD_WITH_BZIP2
|
||||||
string_or_die(&tarcommand, TAR_COMMAND " --directory=%s " TAR_PERM_ATTR_ARGS " -jcf %s/%i/files/%s.tar.bz2 %s",
|
string_or_die(¶m1, "--directory=%s", empty);
|
||||||
empty, outdir, file->last_change, file->hash, file->hash);
|
string_or_die(¶m2, "%s/%i/files/%s.tar.bz2", outdir, file->last_change, file->hash);
|
||||||
if (system(tarcommand) != 0) {
|
char *const tarbzip2cmd[] = { TAR_COMMAND, param1, TAR_PERM_ATTR_ARGS_STRLIST, "-jcf", param2, file->hash, NULL };
|
||||||
LOG(NULL, "Failed to run command:", "%s", tarcommand);
|
|
||||||
|
if (system_argv(tarbzip2cmd) != 0) {
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
free(tarcommand);
|
free(param1);
|
||||||
|
free(param2);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* step 2b: pick the smallest of the three compression formats */
|
/* step 2b: pick the smallest of the three compression formats */
|
||||||
@@ -232,7 +252,7 @@ static GList *get_deduplicated_fullfile_list(struct manifest *manifest)
|
|||||||
manifest->files = g_list_sort(manifest->files, file_sort_hash);
|
manifest->files = g_list_sort(manifest->files, file_sort_hash);
|
||||||
|
|
||||||
list = g_list_first(manifest->files);
|
list = g_list_first(manifest->files);
|
||||||
while (prev == NULL) {
|
while (prev == NULL && list != NULL) {
|
||||||
tmp = list->data;
|
tmp = list->data;
|
||||||
list = g_list_next(list);
|
list = g_list_next(list);
|
||||||
|
|
||||||
@@ -271,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");
|
||||||
@@ -302,17 +323,14 @@ void create_fullfiles(struct manifest *manifest)
|
|||||||
{
|
{
|
||||||
GList *deduped_file_list;
|
GList *deduped_file_list;
|
||||||
char *path;
|
char *path;
|
||||||
char *cmd;
|
|
||||||
char *conf, *empty;
|
char *conf, *empty;
|
||||||
|
|
||||||
empty = config_empty_dir();
|
empty = config_empty_dir();
|
||||||
|
|
||||||
string_or_die(&cmd, "rm -rf %s", empty);
|
char *const rmcmd[] = { "rm", "-rf", empty, NULL };
|
||||||
if (system(cmd) != 0) {
|
if (system_argv(rmcmd) != 0) {
|
||||||
LOG(NULL, "Failed to run command:", "%s", cmd);
|
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
free(cmd);
|
|
||||||
g_mkdir_with_parents(empty, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
|
g_mkdir_with_parents(empty, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
|
||||||
free(empty);
|
free(empty);
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -51,6 +51,13 @@ char *group_groups(char *group)
|
|||||||
return g_key_file_get_value(groupfile, group, "groups", NULL);
|
return g_key_file_get_value(groupfile, group, "groups", NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *group_status(char *group)
|
||||||
|
{
|
||||||
|
assert(groupfile != NULL);
|
||||||
|
|
||||||
|
return g_key_file_get_value(groupfile, group, "status", NULL);
|
||||||
|
}
|
||||||
|
|
||||||
void read_group_file(char *filename)
|
void read_group_file(char *filename)
|
||||||
{
|
{
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
|
|||||||
+121
-7
@@ -101,22 +101,27 @@ void string_or_die(char **strp, const char *fmt, ...)
|
|||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
if (vasprintf(strp, fmt, ap) <= 0) {
|
if (vasprintf(strp, fmt, ap) < 0) {
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_elapsed_time(struct timeval *previous_time, struct timeval *current_time)
|
/* "step" should be a descriptive string for the process that completed before
|
||||||
|
* this function is called */
|
||||||
|
void print_elapsed_time(const char *step, struct timeval *previous_time,
|
||||||
|
struct timeval *current_time)
|
||||||
{
|
{
|
||||||
char *elapsed;
|
char *elapsed;
|
||||||
|
|
||||||
|
assert(strlen(step) > 0);
|
||||||
|
|
||||||
gettimeofday(current_time, NULL);
|
gettimeofday(current_time, NULL);
|
||||||
elapsed = get_elapsed_time(previous_time, current_time);
|
elapsed = get_elapsed_time(previous_time, current_time);
|
||||||
if (strcmp(elapsed, " ") == 0) {
|
if (strcmp(elapsed, " ") == 0) {
|
||||||
printf("\t~0.0 elapsed for Manifest.full creation\n");
|
printf("\t~0.0 elapsed for '%s' step\n", step);
|
||||||
} else {
|
} else {
|
||||||
printf("\t%s elapsed for full chroot creation\n", elapsed);
|
printf("\t%s elapsed for '%s' step\n", elapsed, step);
|
||||||
}
|
}
|
||||||
previous_time->tv_sec = current_time->tv_sec;
|
previous_time->tv_sec = current_time->tv_sec;
|
||||||
previous_time->tv_usec = current_time->tv_usec;
|
previous_time->tv_usec = current_time->tv_usec;
|
||||||
@@ -148,7 +153,7 @@ int system_argv(char *const argv[])
|
|||||||
{
|
{
|
||||||
int child_exit_status;
|
int child_exit_status;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
int status;
|
int status = -1;
|
||||||
|
|
||||||
pid = fork();
|
pid = fork();
|
||||||
|
|
||||||
@@ -181,9 +186,93 @@ int system_argv(char *const argv[])
|
|||||||
LOG(NULL, "Failed to run command:", "%s", cmdline);
|
LOG(NULL, "Failed to run command:", "%s", cmdline);
|
||||||
free(cmdline);
|
free(cmdline);
|
||||||
}
|
}
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
int system_argv_fd(char *const argv[], int newstdin, int newstdout, int newstderr)
|
||||||
|
{
|
||||||
|
int child_exit_status;
|
||||||
|
pid_t pid;
|
||||||
|
int status = -1;
|
||||||
|
|
||||||
|
pid = fork();
|
||||||
|
|
||||||
|
if (pid == 0) { /* child */
|
||||||
|
if (newstdin >= 0) {
|
||||||
|
if (dup2(newstdin, STDIN_FILENO) == -1) {
|
||||||
|
LOG(NULL, "Could not redirect stdin", "");
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
close(newstdin);
|
||||||
|
}
|
||||||
|
if (newstdout >= 0) {
|
||||||
|
if (dup2(newstdout, STDOUT_FILENO) == -1) {
|
||||||
|
LOG(NULL, "Could not redirect stdout", "");
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
close(newstdout);
|
||||||
|
}
|
||||||
|
if (newstderr >= 0) {
|
||||||
|
if (dup2(newstderr, STDERR_FILENO) == -1) {
|
||||||
|
LOG(NULL, "Could not redirect stderr", "");
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
close(newstderr);
|
||||||
|
}
|
||||||
|
|
||||||
|
execvp(*argv, argv);
|
||||||
|
LOG(NULL, "This line must not be reached", "");
|
||||||
|
assert(0);
|
||||||
|
} else if (pid < 0) {
|
||||||
|
LOG(NULL, "Failed to fork a child process", "");
|
||||||
|
assert(0);
|
||||||
|
} else {
|
||||||
|
pid_t ws = waitpid(pid, &child_exit_status, 0);
|
||||||
|
|
||||||
|
if (ws == -1) {
|
||||||
|
LOG(NULL, "Failed to wait for child process", "");
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (WIFEXITED(child_exit_status)) {
|
||||||
|
status = WEXITSTATUS(child_exit_status);
|
||||||
|
} else {
|
||||||
|
LOG(NULL, "Child process didn't exit", "");
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status != 0) {
|
||||||
|
char *cmdline = NULL;
|
||||||
|
|
||||||
|
concat_str_array(&cmdline, argv);
|
||||||
|
LOG(NULL, "Failed to run command:", "%s", cmdline);
|
||||||
|
free(cmdline);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
int system_argv_pipe(char *const argvp1[], int stdinp1, int stderrp1,
|
||||||
|
char *const argvp2[], int stdoutp2, int stderrp2)
|
||||||
|
{
|
||||||
|
int statusp2;
|
||||||
|
int pipefd[2];
|
||||||
|
|
||||||
|
if (pipe(pipefd)) {
|
||||||
|
LOG(NULL, "Failed to create a pipe", "");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
system_argv_fd(argvp1, stdinp1, pipefd[1], stderrp1);
|
||||||
|
close(pipefd[1]);
|
||||||
|
statusp2 = system_argv_fd(argvp2, pipefd[0], stdoutp2, stderrp2);
|
||||||
|
close(pipefd[0]);
|
||||||
|
|
||||||
|
/* Returns the status of the failed process if any
|
||||||
|
If both processes failed returns the status of first one */
|
||||||
|
return statusp2;
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_root(void)
|
void check_root(void)
|
||||||
@@ -195,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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
+48
-61
@@ -64,7 +64,7 @@ int file_sort_version(gconstpointer a, gconstpointer b)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return strcmp(B->filename, A->filename);
|
return strcmp(A->filename, B->filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
int file_sort_filename(gconstpointer a, gconstpointer b)
|
int file_sort_filename(gconstpointer a, gconstpointer b)
|
||||||
@@ -582,6 +582,16 @@ void subtract_manifests(struct manifest *m1, struct manifest *m2)
|
|||||||
list1 = g_list_next(list1);
|
list1 = g_list_next(list1);
|
||||||
list2 = g_list_next(list2);
|
list2 = g_list_next(list2);
|
||||||
|
|
||||||
|
/* When both files are marked deleted, skip
|
||||||
|
* subtraction. Preserving the deleted entries in both
|
||||||
|
* manifests is required for 'swupd update' to know
|
||||||
|
* when to delete the file, because the m2 bundle may
|
||||||
|
* be installed with or without the m1 bundle.
|
||||||
|
*/
|
||||||
|
if (file1->is_deleted && file2->is_deleted) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (file1->is_deleted == file2->is_deleted && file1->is_file == file2->is_file) {
|
if (file1->is_deleted == file2->is_deleted && file1->is_file == file2->is_file) {
|
||||||
m1->files = g_list_delete_link(m1->files, todel);
|
m1->files = g_list_delete_link(m1->files, todel);
|
||||||
m1->count--;
|
m1->count--;
|
||||||
@@ -695,29 +705,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)
|
||||||
{
|
{
|
||||||
@@ -728,9 +715,9 @@ static int write_manifest_plain(struct manifest *manifest)
|
|||||||
char *base = NULL, *dir;
|
char *base = NULL, *dir;
|
||||||
char *conf = config_output_dir();
|
char *conf = config_output_dir();
|
||||||
char *filename = NULL;
|
char *filename = NULL;
|
||||||
|
char *status = NULL;
|
||||||
char *submanifest_filename = NULL;
|
char *submanifest_filename = NULL;
|
||||||
char *manifest_tempdir = NULL;
|
char *manifest_tempdir = NULL;
|
||||||
char *tarcommand = NULL;
|
|
||||||
char *tempmanifest = NULL;
|
char *tempmanifest = NULL;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
|
||||||
@@ -763,6 +750,10 @@ static int write_manifest_plain(struct manifest *manifest)
|
|||||||
compute_content_size(manifest);
|
compute_content_size(manifest);
|
||||||
fprintf(out, "contentsize:\t%llu\n", (long long unsigned int)manifest->contentsize);
|
fprintf(out, "contentsize:\t%llu\n", (long long unsigned int)manifest->contentsize);
|
||||||
includes = manifest->includes;
|
includes = manifest->includes;
|
||||||
|
status = group_status(manifest->component);
|
||||||
|
if (status) {
|
||||||
|
fprintf(out, "status:\t%s\n", status);
|
||||||
|
}
|
||||||
while (includes) {
|
while (includes) {
|
||||||
struct manifest *sub = includes->data;
|
struct manifest *sub = includes->data;
|
||||||
includes = g_list_next(includes);
|
includes = g_list_next(includes);
|
||||||
@@ -796,16 +787,22 @@ static int write_manifest_plain(struct manifest *manifest)
|
|||||||
goto write_entry;
|
goto write_entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *param1, *param2;
|
||||||
|
|
||||||
/* Untar the Manifest.BUNDLE.tar and calculate the hash on that,
|
/* Untar the Manifest.BUNDLE.tar and calculate the hash on that,
|
||||||
* otherwise we may get incorrect hashes due to owner permissions on
|
* otherwise we may get incorrect hashes due to owner permissions on
|
||||||
* the files. */
|
* the files. */
|
||||||
string_or_die(&tarcommand, TAR_COMMAND " -C %s " TAR_PERM_ATTR_ARGS " -xf %s.tar 2> /dev/null",
|
string_or_die(¶m1, "%s", manifest_tempdir);
|
||||||
manifest_tempdir, submanifest_filename);
|
string_or_die(¶m2, "%s.tar", submanifest_filename);
|
||||||
if (system(tarcommand) != 0) {
|
char *const tarcmd[] = { TAR_COMMAND, "-C", param1, TAR_PERM_ATTR_ARGS_STRLIST, "-xf", param2, NULL };
|
||||||
LOG(NULL, "Failed to run command:", "%s", tarcommand);
|
ret = system_argv(tarcmd);
|
||||||
|
free(param1);
|
||||||
|
free(param2);
|
||||||
|
|
||||||
|
if (ret != 0) {
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
free(tarcommand);
|
|
||||||
string_or_die(&tempmanifest, "%s/Manifest.%s", manifest_tempdir, file->filename);
|
string_or_die(&tempmanifest, "%s/Manifest.%s", manifest_tempdir, file->filename);
|
||||||
populate_file_struct(file, tempmanifest);
|
populate_file_struct(file, tempmanifest);
|
||||||
ret = compute_hash(file, tempmanifest);
|
ret = compute_hash(file, tempmanifest);
|
||||||
@@ -815,18 +812,19 @@ static int write_manifest_plain(struct manifest *manifest)
|
|||||||
}
|
}
|
||||||
unlink(tempmanifest);
|
unlink(tempmanifest);
|
||||||
free(tempmanifest);
|
free(tempmanifest);
|
||||||
write_entry:
|
write_entry:
|
||||||
fprintf(out, "%s\t%s\t%i\t%s\n", file_type_to_string(file), file->hash, file->last_change, file->filename);
|
fprintf(out, "%s\t%s\t%i\t%s\n", file_type_to_string(file), file->hash, file->last_change, file->filename);
|
||||||
free(submanifest_filename);
|
free(submanifest_filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
exit:
|
exit:
|
||||||
if (rmdir(manifest_tempdir) != 0) {
|
if (manifest_tempdir) {
|
||||||
LOG(NULL, "rmdir failed for %s: %s", manifest_tempdir, strerror(errno));
|
if (rmdir(manifest_tempdir) != 0) {
|
||||||
|
LOG(NULL, "rmdir failed for %s: %s", manifest_tempdir, strerror(errno));
|
||||||
|
}
|
||||||
|
free(manifest_tempdir);
|
||||||
}
|
}
|
||||||
free(manifest_tempdir);
|
|
||||||
|
|
||||||
if (out) {
|
if (out) {
|
||||||
fclose(out);
|
fclose(out);
|
||||||
}
|
}
|
||||||
@@ -840,34 +838,28 @@ 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 *tarcmd = NULL;
|
char *directory, *manifesttar, *manifestcomp;
|
||||||
int ret = -1;
|
int ret = 0;
|
||||||
|
|
||||||
if (conf == NULL) {
|
if (conf == NULL) {
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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(&manifestcomp, "Manifest.%s", 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 };
|
||||||
string_or_die(&tarcmd, TAR_COMMAND " --directory=%s/%i " TAR_PERM_ATTR_ARGS " -Jcf "
|
ret = system_argv(tarcmd);
|
||||||
"%s/%i/Manifest.%s.tar Manifest.%s Manifest.%s.signed",
|
if (ret) {
|
||||||
conf, manifest->version, conf, manifest->version, manifest->component,
|
fprintf(stderr, "Creation of Manifest.tar failed\n");
|
||||||
manifest->component, manifest->component);
|
|
||||||
} else {
|
|
||||||
string_or_die(&tarcmd, TAR_COMMAND " --directory=%s/%i " TAR_PERM_ATTR_ARGS " -Jcf "
|
|
||||||
"%s/%i/Manifest.%s.tar Manifest.%s",
|
|
||||||
conf, manifest->version, conf, manifest->version, manifest->component,
|
|
||||||
manifest->component);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (system(tarcmd) != 0) {
|
free(directory);
|
||||||
fprintf(stderr, "Creation of Manifest.tar failed\n");
|
free(manifesttar);
|
||||||
goto exit;
|
free(manifestcomp);
|
||||||
}
|
|
||||||
ret = 0;
|
|
||||||
exit:
|
|
||||||
free(tarcmd);
|
|
||||||
free(conf);
|
free(conf);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -897,9 +889,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;
|
||||||
@@ -1101,9 +1091,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 */
|
||||||
}
|
}
|
||||||
|
|||||||
+40
-59
@@ -40,21 +40,19 @@
|
|||||||
|
|
||||||
static void empty_pack_stage(int full, int from_version, int to_version, char *module)
|
static void empty_pack_stage(int full, int from_version, int to_version, char *module)
|
||||||
{
|
{
|
||||||
char *cmd;
|
char *param;
|
||||||
char *path;
|
char *path;
|
||||||
int ret;
|
|
||||||
|
|
||||||
// clean any stale data (eg: re-run after a failure)
|
// clean any stale data (eg: re-run after a failure)
|
||||||
string_or_die(&cmd, "rm -rf %s/%s/%i_to_%i/", packstage_dir, module,
|
string_or_die(¶m, "%s/%s/%i_to_%i/", packstage_dir, module, from_version, to_version);
|
||||||
from_version, to_version);
|
char *const rmcmd[] = { "rm", "-fr", param, NULL };
|
||||||
ret = system(cmd);
|
if (system_argv(rmcmd) != 0) {
|
||||||
if (ret) {
|
|
||||||
fprintf(stderr, "Failed to clean %s/%s/%i_to_%i\n",
|
fprintf(stderr, "Failed to clean %s/%s/%i_to_%i\n",
|
||||||
packstage_dir, module, from_version, to_version);
|
packstage_dir, module, from_version, to_version);
|
||||||
free(cmd);
|
free(param);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
free(cmd);
|
free(param);
|
||||||
|
|
||||||
if (!full) {
|
if (!full) {
|
||||||
// (re)create module/version/{delta,staged}
|
// (re)create module/version/{delta,staged}
|
||||||
@@ -89,7 +87,7 @@ static void explode_pack_stage(int from_version, int to_version, char *module)
|
|||||||
}
|
}
|
||||||
free(path);
|
free(path);
|
||||||
while (1) {
|
while (1) {
|
||||||
char *path, *tar;
|
char *path, *param;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
entry = readdir(dir);
|
entry = readdir(dir);
|
||||||
@@ -117,13 +115,12 @@ static void explode_pack_stage(int from_version, int to_version, char *module)
|
|||||||
* the resulting pack is slightly smaller, and in addition, we're saving CPU
|
* the resulting pack is slightly smaller, and in addition, we're saving CPU
|
||||||
* time on the client...
|
* time on the client...
|
||||||
*/
|
*/
|
||||||
string_or_die(&tar, TAR_COMMAND " --directory=%s/%s/%i_to_%i/staged " TAR_WARN_ARGS " " TAR_PERM_ATTR_ARGS " -xf %s",
|
string_or_die(¶m, "%s/%s/%i_to_%i/staged", packstage_dir, module, from_version, to_version);
|
||||||
packstage_dir, module, from_version, to_version, path);
|
char *const tarcmd[] = { TAR_COMMAND, "-C", param, TAR_WARN_ARGS_STRLIST TAR_PERM_ATTR_ARGS_STRLIST, "-xf", path, NULL };
|
||||||
ret = system(tar);
|
if (system_argv(tarcmd) == 0) {
|
||||||
if (!ret) {
|
|
||||||
unlink(path);
|
unlink(path);
|
||||||
}
|
}
|
||||||
free(tar);
|
free(param);
|
||||||
free(path);
|
free(path);
|
||||||
}
|
}
|
||||||
closedir(dir);
|
closedir(dir);
|
||||||
@@ -257,8 +254,8 @@ static GList *consolidate_packs_delta_files(GList *files, struct packdata *pack)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
string_or_die(&from, "%s/%i/delta/%i-%i-%s", staging_dir, file->last_change,
|
string_or_die(&from, "%s/%i/delta/%i-%i-%s-%s", staging_dir, file->last_change,
|
||||||
file->peer->last_change, file->last_change, file->hash);
|
file->peer->last_change, file->last_change, file->peer->hash, file->hash);
|
||||||
|
|
||||||
ret = stat(from, &stat_delta);
|
ret = stat(from, &stat_delta);
|
||||||
if (ret && !find_file_in_list(files, file)) {
|
if (ret && !find_file_in_list(files, file)) {
|
||||||
@@ -277,7 +274,7 @@ static void create_delta(gpointer data, __unused__ gpointer user_data)
|
|||||||
|
|
||||||
/* if the file was not found in the from version, skip delta creation */
|
/* if the file was not found in the from version, skip delta creation */
|
||||||
if (file->peer) {
|
if (file->peer) {
|
||||||
__create_delta(file, file->peer->last_change);
|
__create_delta(file, file->peer->last_change, file->peer->hash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -288,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) {
|
||||||
@@ -310,31 +308,13 @@ 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)
|
||||||
{
|
{
|
||||||
GList *item;
|
GList *item;
|
||||||
struct file *file;
|
struct file *file;
|
||||||
int ret;
|
int ret;
|
||||||
char *tar;
|
char *param1, *param2;
|
||||||
double penalty;
|
double penalty;
|
||||||
|
|
||||||
LOG(NULL, "make_final_pack", "%s: %i to %i", pack->module, pack->from, pack->to);
|
LOG(NULL, "make_final_pack", "%s: %i to %i", pack->module, pack->from, pack->to);
|
||||||
@@ -356,11 +336,11 @@ static int make_final_pack(struct packdata *pack)
|
|||||||
|
|
||||||
/* for each file changed since <X> */
|
/* for each file changed since <X> */
|
||||||
/* locate delta, check if the diff it's from is >= <X> */
|
/* locate delta, check if the diff it's from is >= <X> */
|
||||||
string_or_die(&from, "%s/%i/delta/%i-%i-%s", staging_dir, file->last_change,
|
string_or_die(&from, "%s/%i/delta/%i-%i-%s-%s", staging_dir, file->last_change,
|
||||||
file->peer->last_change, file->last_change, file->hash);
|
file->peer->last_change, file->last_change, file->peer->hash, file->hash);
|
||||||
string_or_die(&to, "%s/%s/%i_to_%i/delta/%i-%i-%s", packstage_dir,
|
string_or_die(&to, "%s/%s/%i_to_%i/delta/%i-%i-%s-%s", packstage_dir,
|
||||||
pack->module, pack->from, pack->to, file->peer->last_change,
|
pack->module, pack->from, pack->to, file->peer->last_change,
|
||||||
file->last_change, file->hash);
|
file->last_change, file->peer->hash, file->hash);
|
||||||
string_or_die(&tarfrom, "%s/%i/files/%s.tar", staging_dir,
|
string_or_die(&tarfrom, "%s/%i/files/%s.tar", staging_dir,
|
||||||
file->last_change, file->hash);
|
file->last_change, file->hash);
|
||||||
string_or_die(&tarto, "%s/%s/%i_to_%i/staged/%s.tar", packstage_dir,
|
string_or_die(&tarto, "%s/%s/%i_to_%i/staged/%s.tar", packstage_dir,
|
||||||
@@ -438,6 +418,8 @@ static int make_final_pack(struct packdata *pack)
|
|||||||
explode_pack_stage(pack->from, pack->to, pack->module);
|
explode_pack_stage(pack->from, pack->to, pack->module);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *bundle_delta = NULL;
|
||||||
|
|
||||||
/* now... link in the Manifest pack */
|
/* now... link in the Manifest pack */
|
||||||
if (pack->from != 0) {
|
if (pack->from != 0) {
|
||||||
char *from, *to;
|
char *from, *to;
|
||||||
@@ -457,14 +439,18 @@ static int make_final_pack(struct packdata *pack)
|
|||||||
|
|
||||||
ret = link(from, to);
|
ret = link(from, to);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
LOG(NULL, "Failed to link", "Manifest-delta-from-%i", pack->from);
|
LOG(NULL, "Failed to link", "Manifest-%s-delta-from-%i (%s)", pack->module, pack->from, strerror(errno));
|
||||||
|
} else {
|
||||||
|
string_or_die(&bundle_delta, "Manifest-%s-delta-from-%i", pack->module, pack->from);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(from);
|
free(from);
|
||||||
free(to);
|
free(to);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* now... link in the MoM Manifest into the base pack */
|
char *mom_delta = NULL;
|
||||||
|
|
||||||
|
/* now... link in the MoM Manifest into the os-core pack */
|
||||||
if ((pack->from != 0) && (strcmp(pack->module, "os-core") == 0)) {
|
if ((pack->from != 0) && (strcmp(pack->module, "os-core") == 0)) {
|
||||||
char *from, *to;
|
char *from, *to;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
@@ -482,7 +468,9 @@ static int make_final_pack(struct packdata *pack)
|
|||||||
|
|
||||||
ret = link(from, to);
|
ret = link(from, to);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
LOG(NULL, "Failed to link", "Manifest-delta-from-%i", pack->from);
|
LOG(NULL, "Failed to link", "Manifest-MoM-delta-from-%i (%s)", pack->from, strerror(errno));
|
||||||
|
} else {
|
||||||
|
string_or_die(&mom_delta, "Manifest-MoM-delta-from-%i", pack->from);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(from);
|
free(from);
|
||||||
@@ -491,24 +479,17 @@ static int make_final_pack(struct packdata *pack)
|
|||||||
|
|
||||||
/* tar the staging directory up */
|
/* tar the staging directory up */
|
||||||
LOG(NULL, "starting tar for pack", "%s: %i to %i", pack->module, pack->from, pack->to);
|
LOG(NULL, "starting tar for pack", "%s: %i to %i", pack->module, pack->from, pack->to);
|
||||||
string_or_die(&tar, TAR_COMMAND " " TAR_PERM_ATTR_ARGS " --directory=%s/%s/%i_to_%i/ "
|
string_or_die(¶m1, "%s/%s/%i_to_%i/", packstage_dir, pack->module, pack->from, pack->to);
|
||||||
"--numeric-owner -Jcf %s/%i/pack-%s-from-%i.tar delta staged",
|
string_or_die(¶m2, "%s/%i/pack-%s-from-%i.tar", staging_dir, pack->to, pack->module, pack->from);
|
||||||
packstage_dir, pack->module, pack->from, pack->to, staging_dir, pack->to,
|
char *const tarcmd[] = { TAR_COMMAND, "-C", param1, TAR_PERM_ATTR_ARGS_STRLIST, "--numeric-owner", "-Jcf", param2, "delta", "staged", bundle_delta, mom_delta, NULL };
|
||||||
pack->module, pack->from);
|
ret = system_argv(tarcmd);
|
||||||
ret = system(tar);
|
free(param1);
|
||||||
free(tar);
|
free(param2);
|
||||||
LOG(NULL, "finished tar for pack", "%s: %i to %i", pack->module, pack->from, pack->to);
|
LOG(NULL, "finished tar for pack", "%s: %i to %i", pack->module, pack->from, pack->to);
|
||||||
/* FIXME: this is a hack workaround, needs diagnosed and removed */
|
/* FIXME: this is a hack workaround, needs diagnosed and removed */
|
||||||
if ((ret != 0) && (ret != 256)) {
|
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 */
|
||||||
|
|||||||
-171
@@ -1,171 +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 const char *CMD_FMT = "openssl smime -sign -in %s -binary "
|
|
||||||
"-out %s.signed -outform PEM -md sha256 -inkey %s -signer %s "
|
|
||||||
"-certfile %s -passin file:%s";
|
|
||||||
|
|
||||||
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 *cmd = NULL;
|
|
||||||
int status;
|
|
||||||
|
|
||||||
if (!enable_signing) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!initialized) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
string_or_die(&cmd, CMD_FMT, filename, filename, leaf_key, leaf_cert,
|
|
||||||
ca_chain_cert, passphrase);
|
|
||||||
status = system(cmd);
|
|
||||||
if (status) {
|
|
||||||
printf("Bad status %d from signing command:%s\n", status, cmd);
|
|
||||||
}
|
|
||||||
free(cmd);
|
|
||||||
return status == 0;
|
|
||||||
}
|
|
||||||
+41
-12
@@ -27,6 +27,7 @@
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -126,35 +127,63 @@ void ensure_version_image_exists(int version)
|
|||||||
void write_cookiecrumbs_to_download_area(int version)
|
void write_cookiecrumbs_to_download_area(int version)
|
||||||
{
|
{
|
||||||
char *conf;
|
char *conf;
|
||||||
char *cmd;
|
char *filename, *strformat;
|
||||||
|
FILE *versionfd, *formatfd;
|
||||||
|
|
||||||
conf = config_output_dir();
|
conf = config_output_dir();
|
||||||
if (conf == NULL) {
|
if (conf == NULL) {
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
string_or_die(&cmd, "echo %s > %s/%i/swupd-server-src-version", VERSION, conf, version);
|
string_or_die(&filename, "%s/%i/swupd-server-src-version", conf, version);
|
||||||
if (system(cmd) != 0) {
|
versionfd = fopen(filename, "w");
|
||||||
|
if (versionfd == NULL) {
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
free(cmd);
|
if (fwrite(VERSION, 1, strlen(VERSION), versionfd) != strlen(VERSION)) {
|
||||||
|
|
||||||
string_or_die(&cmd, "echo %llu > %s/%i/format", format, conf, version);
|
|
||||||
if (system(cmd) != 0) {
|
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
free(cmd);
|
fclose(versionfd);
|
||||||
|
free(filename);
|
||||||
|
|
||||||
/* written from pack_maker.sh */
|
string_or_die(&filename, "%s/%i/format", conf, version);
|
||||||
|
string_or_die(&strformat, "%llu", format);
|
||||||
|
formatfd = fopen(filename, "w");
|
||||||
|
if (formatfd == NULL) {
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
if (fwrite(strformat, 1, strlen(strformat), formatfd) != strlen(strformat)) {
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
fclose(formatfd);
|
||||||
|
free(filename);
|
||||||
|
free(strformat);
|
||||||
|
|
||||||
|
/* Updating the WEBDIR/version/formatN/latest file is an operation very closely tied to a DevOps
|
||||||
|
* workflow and not something swupd should make a decision about.
|
||||||
|
*
|
||||||
|
* The supported format values (replacing the "N" in the path above) are:
|
||||||
|
*
|
||||||
|
* - "staging": intended for testing only
|
||||||
|
* - [1-+inf] (positive integer): the number that a corresponding version of swupd-client
|
||||||
|
* understands to run software updates. For example, if a given swupd-client release understands
|
||||||
|
* format 1, then WEBDIR/version/format1/latest contains the value of most recent release that
|
||||||
|
* that swupd-client can update to.
|
||||||
|
*
|
||||||
|
* Adapt this step appropriately for your DevOps flow.
|
||||||
|
*/
|
||||||
#if 0
|
#if 0
|
||||||
FILE *file;
|
FILE *file;
|
||||||
char *fullfile = NULL;
|
char *fullfile = NULL;
|
||||||
|
char *param;
|
||||||
|
|
||||||
string_or_die(&cmd, "mkdir -p %s/version/formatstaging/", conf);
|
string_or_die($param, "%s/version/formatstaging/", conf);
|
||||||
if (system(cmd) != 0) {
|
char *const mkdircmd[] = { "mkdir", "-p", param, NULL };
|
||||||
|
|
||||||
|
if (system_argv(mkdircmd) != 0) {
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
free(cmd);
|
free(param);
|
||||||
|
|
||||||
string_or_die(&fullfile, "%s/version/formatstaging/latest", conf);
|
string_or_die(&fullfile, "%s/version/formatstaging/latest", conf);
|
||||||
file = fopen(fullfile, "w");
|
file = fopen(fullfile, "w");
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ setup() {
|
|||||||
track_bundle 20 included-two
|
track_bundle 20 included-two
|
||||||
track_bundle 20 included-nested
|
track_bundle 20 included-nested
|
||||||
|
|
||||||
gen_file_to_delta 10 4096 20 4 test-bundle
|
gen_file_to_delta 10 4096 20 4 test-bundle randomfile
|
||||||
|
|
||||||
gen_file_plain 10 test-bundle foo
|
gen_file_plain 10 test-bundle foo
|
||||||
gen_file_plain 10 test-bundle foobarbaz
|
gen_file_plain 10 test-bundle foobarbaz
|
||||||
@@ -79,6 +79,11 @@ setup() {
|
|||||||
[[ 1 -eq $(grep '/foobarbaz$' $DIR/www/20/Manifest.included-nested | wc -l) ]]
|
[[ 1 -eq $(grep '/foobarbaz$' $DIR/www/20/Manifest.included-nested | wc -l) ]]
|
||||||
[[ 6 -eq $(tar -tf $DIR/www/10/pack-test-bundle-from-0.tar | wc -l) ]]
|
[[ 6 -eq $(tar -tf $DIR/www/10/pack-test-bundle-from-0.tar | wc -l) ]]
|
||||||
[[ 4 -eq $(tar -tf $DIR/www/20/pack-test-bundle-from-0.tar | wc -l) ]]
|
[[ 4 -eq $(tar -tf $DIR/www/20/pack-test-bundle-from-0.tar | wc -l) ]]
|
||||||
|
|
||||||
|
# delta packs should contain appropriate delta manifests
|
||||||
|
[[ $(tar -tf $DIR/www/20/pack-os-core-from-10.tar | grep '^Manifest-os-core-delta-from-10') ]]
|
||||||
|
[[ $(tar -tf $DIR/www/20/pack-os-core-from-10.tar | grep '^Manifest-MoM-delta-from-10') ]]
|
||||||
|
[[ $(tar -tf $DIR/www/20/pack-test-bundle-from-10.tar | grep '^Manifest-test-bundle-delta-from-10') ]]
|
||||||
}
|
}
|
||||||
|
|
||||||
# vi: ft=sh ts=8 sw=2 sts=2 et tw=80
|
# vi: ft=sh ts=8 sw=2 sts=2 et tw=80
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ setup() {
|
|||||||
[[ 1 -eq $(grep '/usr/share/clear$' $DIR/www/10/Manifest.os-core | wc -l) ]]
|
[[ 1 -eq $(grep '/usr/share/clear$' $DIR/www/10/Manifest.os-core | wc -l) ]]
|
||||||
[[ 1 -eq $(grep '/usr/share/clear/bundles$' $DIR/www/10/Manifest.os-core | wc -l) ]]
|
[[ 1 -eq $(grep '/usr/share/clear/bundles$' $DIR/www/10/Manifest.os-core | wc -l) ]]
|
||||||
[[ 4 -eq $(tar -tf $DIR/www/10/pack-test-bundle-from-0.tar | wc -l) ]]
|
[[ 4 -eq $(tar -tf $DIR/www/10/pack-test-bundle-from-0.tar | wc -l) ]]
|
||||||
[[ 9 -eq $(tar -tf $DIR/www/10/pack-os-core-from-0.tar | wc -l) ]]
|
[[ 5 -eq $(tar -tf $DIR/www/10/pack-os-core-from-0.tar | wc -l) ]]
|
||||||
}
|
}
|
||||||
|
|
||||||
# vi: ft=sh ts=8 sw=2 sts=2 et tw=80
|
# vi: ft=sh ts=8 sw=2 sts=2 et tw=80
|
||||||
|
|||||||
@@ -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" ]]
|
||||||
|
|||||||
Executable
+73
@@ -0,0 +1,73 @@
|
|||||||
|
#!/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
|
||||||
|
set_os_release 20 os-core
|
||||||
|
track_bundle 20 os-core
|
||||||
|
|
||||||
|
# symlink -> regular file type change (L -> F)
|
||||||
|
gen_file_to_delta 10 4096 20 4 os-core testfile1
|
||||||
|
gen_symlink_to_file 10 os-core testsym1 testfile1
|
||||||
|
copy_file 10 os-core testfile1 20 os-core testsym1
|
||||||
|
|
||||||
|
# regular file -> symlink type change (F -> L)
|
||||||
|
gen_file_to_delta 10 4096 20 4 os-core testfile2
|
||||||
|
copy_file 10 os-core testfile2 10 os-core testsym2
|
||||||
|
gen_symlink_to_file 20 os-core testsym2 testfile2
|
||||||
|
|
||||||
|
# symlink change + symlink target change; delta should be created for
|
||||||
|
# testfile3, but not for the dereferenced testsym3
|
||||||
|
gen_file_to_delta 10 4096 20 4 os-core testfile3
|
||||||
|
copy_file 20 os-core testfile3 20 os-core testfile4
|
||||||
|
gen_symlink_to_file 10 os-core testsym3 testfile3
|
||||||
|
gen_symlink_to_file 20 os-core testsym3 testfile4
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "no deltas created for type changes or dereferenced symlinks" {
|
||||||
|
sudo $CREATE_UPDATE --osversion 10 --statedir $DIR --format 3
|
||||||
|
set_latest_ver 10
|
||||||
|
sudo $CREATE_UPDATE --osversion 20 --statedir $DIR --format 3
|
||||||
|
|
||||||
|
# attempt to create some deltas
|
||||||
|
sudo $MAKE_PACK --statedir $DIR 10 20 os-core
|
||||||
|
|
||||||
|
# F -> F deltas should exist
|
||||||
|
hash1=$(hash_for 10 os-core "/testfile1")
|
||||||
|
hash2=$(hash_for 20 os-core "/testfile1")
|
||||||
|
[ -f $DIR/www/20/delta/10-20-$hash1-$hash2 ]
|
||||||
|
|
||||||
|
hash1=$(hash_for 10 os-core "/testfile2")
|
||||||
|
hash2=$(hash_for 20 os-core "/testfile2")
|
||||||
|
[ -f $DIR/www/20/delta/10-20-$hash1-$hash2 ]
|
||||||
|
|
||||||
|
hash1=$(hash_for 10 os-core "/testfile3")
|
||||||
|
hash2=$(hash_for 20 os-core "/testfile3")
|
||||||
|
[ -f $DIR/www/20/delta/10-20-$hash1-$hash2 ]
|
||||||
|
|
||||||
|
# deltas for symlink type changes should not be created
|
||||||
|
hash1=$(hash_for 10 os-core "/testsym1")
|
||||||
|
hash2=$(hash_for 20 os-core "/testsym1")
|
||||||
|
[ ! -f $DIR/www/20/delta/10-20-$hash1-$hash2 ]
|
||||||
|
|
||||||
|
hash1=$(hash_for 10 os-core "/testsym2")
|
||||||
|
hash2=$(hash_for 20 os-core "/testsym2")
|
||||||
|
[ ! -f $DIR/www/20/delta/10-20-$hash1-$hash2 ]
|
||||||
|
|
||||||
|
hash1=$(hash_for 10 os-core "/testsym3")
|
||||||
|
hash2=$(hash_for 20 os-core "/testsym3")
|
||||||
|
[ ! -f $DIR/www/20/delta/10-20-$hash1-$hash2 ]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# vi: ft=sh ts=8 sw=2 sts=2 et tw=80
|
||||||
@@ -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
|
||||||
Executable
+56
@@ -0,0 +1,56 @@
|
|||||||
|
#!/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 test-bundle
|
||||||
|
|
||||||
|
# start with both bundles containing a file "foo"
|
||||||
|
set_os_release 10 os-core
|
||||||
|
track_bundle 10 os-core
|
||||||
|
track_bundle 10 test-bundle
|
||||||
|
gen_file_plain 10 os-core foo
|
||||||
|
gen_file_plain 10 test-bundle foo
|
||||||
|
|
||||||
|
# delete "foo" from os-core (the included bundle)
|
||||||
|
set_os_release 20 os-core
|
||||||
|
track_bundle 20 os-core
|
||||||
|
track_bundle 20 test-bundle
|
||||||
|
gen_file_plain 20 test-bundle foo
|
||||||
|
|
||||||
|
# delete "foo" from test-bundle
|
||||||
|
set_os_release 30 os-core
|
||||||
|
track_bundle 30 os-core
|
||||||
|
track_bundle 30 test-bundle
|
||||||
|
|
||||||
|
# make modification (add new file) to test-bundle
|
||||||
|
set_os_release 40 os-core
|
||||||
|
track_bundle 40 os-core
|
||||||
|
track_bundle 40 test-bundle
|
||||||
|
gen_file_plain 40 test-bundle foobar
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "no subtraction for two deleted files" {
|
||||||
|
sudo $CREATE_UPDATE --osversion 10 --statedir $DIR --format 3
|
||||||
|
set_latest_ver 10
|
||||||
|
sudo $CREATE_UPDATE --osversion 20 --statedir $DIR --format 3
|
||||||
|
set_latest_ver 20
|
||||||
|
sudo $CREATE_UPDATE --osversion 30 --statedir $DIR --format 3
|
||||||
|
set_latest_ver 30
|
||||||
|
sudo $CREATE_UPDATE --osversion 40 --statedir $DIR --format 3
|
||||||
|
set_latest_ver 40
|
||||||
|
|
||||||
|
# If the file is absent in test-bundle, this means it was subtracted. If
|
||||||
|
# present, subtraction was not performed.
|
||||||
|
hash1=$(hash_for 40 test-bundle "/foo")
|
||||||
|
[ -n "$hash1" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# vi: ft=sh ts=8 sw=2 sts=2 et tw=80
|
||||||
@@ -27,7 +27,7 @@ init_server_ini() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
set_latest_ver() {
|
set_latest_ver() {
|
||||||
echo "$1" > $DIR/image/latest.version
|
echo "$1" > $DIR/image/LAST_VER
|
||||||
}
|
}
|
||||||
|
|
||||||
init_groups_ini() {
|
init_groups_ini() {
|
||||||
@@ -35,6 +35,7 @@ init_groups_ini() {
|
|||||||
cat >> $DIR/groups.ini << EOF
|
cat >> $DIR/groups.ini << EOF
|
||||||
[$bundle]
|
[$bundle]
|
||||||
group=$bundle
|
group=$bundle
|
||||||
|
status=ACTIVE
|
||||||
EOF
|
EOF
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
@@ -57,9 +58,9 @@ gen_includes_file() {
|
|||||||
local bundle=$1
|
local bundle=$1
|
||||||
local ver=$2
|
local ver=$2
|
||||||
local includes="${@:3}"
|
local includes="${@:3}"
|
||||||
mkdir -p $DIR/www/$ver/noship
|
mkdir -p $DIR/image/$ver/noship
|
||||||
for b in $includes; do
|
for b in $includes; do
|
||||||
cat >> $DIR/www/$ver/noship/"$bundle"-includes << EOF
|
cat >> $DIR/image/$ver/noship/"$bundle"-includes << EOF
|
||||||
$b
|
$b
|
||||||
EOF
|
EOF
|
||||||
done
|
done
|
||||||
@@ -71,16 +72,17 @@ gen_file_to_delta() {
|
|||||||
local newver=$3
|
local newver=$3
|
||||||
local newbytes=$4
|
local newbytes=$4
|
||||||
local bundle=$5
|
local bundle=$5
|
||||||
|
local name=$6
|
||||||
|
|
||||||
# create some random data for the original version
|
# create some random data for the original version
|
||||||
mkdir -p $DIR/image/$origver/$bundle
|
mkdir -p $DIR/image/$origver/$bundle
|
||||||
dd if=/dev/urandom of=$DIR/image/$origver/$bundle/randomfile bs=1 count=$origsize
|
dd if=/dev/urandom of=$DIR/image/$origver/$bundle/$name bs=1 count=$origsize
|
||||||
|
|
||||||
# append more random data to the end of the file in the new version
|
# append more random data to the end of the file in the new version
|
||||||
TMP=$(mktemp foo.XXXXXX)
|
TMP=$(mktemp foo.XXXXXX)
|
||||||
mkdir -p $DIR/image/$newver/$bundle
|
mkdir -p $DIR/image/$newver/$bundle
|
||||||
dd if=/dev/urandom of=$TMP bs=1 count=$newbytes
|
dd if=/dev/urandom of=$TMP bs=1 count=$newbytes
|
||||||
cat $DIR/image/$origver/$bundle/randomfile $TMP > $DIR/image/$newver/$bundle/randomfile
|
cat $DIR/image/$origver/$bundle/$name $TMP > $DIR/image/$newver/$bundle/$name
|
||||||
rm $TMP
|
rm $TMP
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,7 +92,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"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,8 +102,39 @@ 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"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gen_symlink_to_file() {
|
||||||
|
local ver=$1
|
||||||
|
local bundle=$2
|
||||||
|
local symname="$3"
|
||||||
|
local filename="$4"
|
||||||
|
|
||||||
|
mkdir -p $DIR/image/$ver/$bundle/$(dirname "$symname")
|
||||||
|
ln -s "$filename" $DIR/image/$ver/$bundle/"$symname"
|
||||||
|
}
|
||||||
|
|
||||||
|
copy_file() {
|
||||||
|
local origver=$1
|
||||||
|
local origbundle=$2
|
||||||
|
local origname="$3"
|
||||||
|
local newver=$4
|
||||||
|
local newbundle=$5
|
||||||
|
local newname="$6"
|
||||||
|
|
||||||
|
mkdir -p $DIR/image/$newver/$newbundle/$(dirname "$newname")
|
||||||
|
cp -a $DIR/image/$origver/$origbundle/"$origname" $DIR/image/$newver/$newbundle/"$newname"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Gets the hash for file NAME in BUNDLE manifest for VER
|
||||||
|
hash_for() {
|
||||||
|
local ver=$1
|
||||||
|
local bundle=$2
|
||||||
|
local name="$3"
|
||||||
|
|
||||||
|
awk -F'\t' -v NAME="$name" 'NF == 4 && $4 == NAME { print $2 }' $DIR/www/$ver/Manifest.$bundle
|
||||||
|
}
|
||||||
|
|
||||||
# vi: ft=sh ts=8 sw=2 sts=2 et tw=80
|
# vi: ft=sh ts=8 sw=2 sts=2 et tw=80
|
||||||
|
|||||||
@@ -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