This is an automated email from the ASF dual-hosted git repository.
pengzheng pushed a commit to branch feature/522-support-uncompressed-bundle
in repository https://gitbox.apache.org/repos/asf/celix.git
The following commit(s) were added to
refs/heads/feature/522-support-uncompressed-bundle by this push:
new b0909e78 Remove dangling link to non-existing uncompressed bundle
during bundle installation/updating.
b0909e78 is described below
commit b0909e78bb669692f724f5e2185b7ffddf38f4c6
Author: PengZheng <[email protected]>
AuthorDate: Tue Jun 27 20:21:10 2023 +0800
Remove dangling link to non-existing uncompressed bundle during bundle
installation/updating.
---
libs/error_injector/stat/CMakeLists.txt | 1 +
libs/error_injector/stat/include/stat_ei.h | 2 ++
libs/error_injector/stat/src/stat_ei.cc | 17 ++++++++---
libs/error_injector/unistd/CMakeLists.txt | 1 +
libs/error_injector/unistd/include/unistd_ei.h | 2 ++
libs/error_injector/unistd/src/unistd_ei.cc | 10 +++++++
libs/framework/gtest/CMakeLists.txt | 1 +
.../BundleArchiveWithErrorInjectionTestSuite.cc | 33 ++++++++++++++++++++++
.../src/CelixBundleContextBundlesTestSuite.cc | 31 +++++++++++++-------
.../CelixFrameworkUtilsErrorInjectionTestSuite.cc | 5 ++--
.../gtest/src/CelixFrameworkUtilsTestSuite.cc | 4 +--
libs/framework/src/bundle_archive.c | 27 ++++++++++++++----
libs/framework/src/framework.c | 7 -----
13 files changed, 111 insertions(+), 30 deletions(-)
diff --git a/libs/error_injector/stat/CMakeLists.txt
b/libs/error_injector/stat/CMakeLists.txt
index 31ed0559..67e050f9 100644
--- a/libs/error_injector/stat/CMakeLists.txt
+++ b/libs/error_injector/stat/CMakeLists.txt
@@ -23,5 +23,6 @@ target_link_libraries(stat_ei PUBLIC Celix::error_injector)
target_link_options(stat_ei INTERFACE
LINKER:--wrap,mkdir
LINKER:--wrap,stat
+ LINKER:--wrap,lstat
)
add_library(Celix::stat_ei ALIAS stat_ei)
diff --git a/libs/error_injector/stat/include/stat_ei.h
b/libs/error_injector/stat/include/stat_ei.h
index 439a9bab..73089c34 100644
--- a/libs/error_injector/stat/include/stat_ei.h
+++ b/libs/error_injector/stat/include/stat_ei.h
@@ -31,6 +31,8 @@ CELIX_EI_DECLARE(mkdir, int);
CELIX_EI_DECLARE(stat, int);
+CELIX_EI_DECLARE(lstat, int);
+
#ifdef __cplusplus
}
#endif
diff --git a/libs/error_injector/stat/src/stat_ei.cc
b/libs/error_injector/stat/src/stat_ei.cc
index 7edf5744..1a095d62 100644
--- a/libs/error_injector/stat/src/stat_ei.cc
+++ b/libs/error_injector/stat/src/stat_ei.cc
@@ -22,9 +22,9 @@
extern "C" {
-int __real_mkdir (const char *__path, __mode_t __mode);
+int __real_mkdir(const char *__path, __mode_t __mode);
CELIX_EI_DEFINE(mkdir, int)
-int __wrap_mkdir (const char *__path, __mode_t __mode) {
+int __wrap_mkdir(const char *__path, __mode_t __mode) {
errno = EACCES;
CELIX_EI_IMPL(mkdir);
errno = 0;
@@ -32,12 +32,21 @@ int __wrap_mkdir (const char *__path, __mode_t __mode) {
}
-int __real_stat (const char *__restrict __file, struct stat *__restrict __buf);
+int __real_stat(const char *__restrict __file, struct stat *__restrict __buf);
CELIX_EI_DEFINE(stat, int)
-int __wrap_stat (const char *__restrict __file, struct stat *__restrict __buf)
{
+int __wrap_stat(const char *__restrict __file, struct stat *__restrict __buf) {
errno = EOVERFLOW;
CELIX_EI_IMPL(stat);
errno = 0;
return __real_stat(__file, __buf);
}
+
+int __real_lstat(const char *__restrict __file, struct stat *__restrict __buf);
+CELIX_EI_DEFINE(lstat, int)
+int __wrap_lstat(const char *__restrict __file, struct stat *__restrict __buf)
{
+ errno = EACCES;
+ CELIX_EI_IMPL(lstat);
+ errno = 0;
+ return __real_lstat(__file, __buf);
+}
}
\ No newline at end of file
diff --git a/libs/error_injector/unistd/CMakeLists.txt
b/libs/error_injector/unistd/CMakeLists.txt
index 1835afcf..328fc427 100644
--- a/libs/error_injector/unistd/CMakeLists.txt
+++ b/libs/error_injector/unistd/CMakeLists.txt
@@ -23,5 +23,6 @@ target_link_libraries(unistd_ei PUBLIC Celix::error_injector)
target_link_options(unistd_ei INTERFACE
LINKER:--wrap,getcwd
LINKER:--wrap,symlink
+ LINKER:--wrap,unlink
)
add_library(Celix::unistd_ei ALIAS unistd_ei)
diff --git a/libs/error_injector/unistd/include/unistd_ei.h
b/libs/error_injector/unistd/include/unistd_ei.h
index 8ded930c..dde5dccc 100644
--- a/libs/error_injector/unistd/include/unistd_ei.h
+++ b/libs/error_injector/unistd/include/unistd_ei.h
@@ -31,6 +31,8 @@ CELIX_EI_DECLARE(getcwd, char*);
CELIX_EI_DECLARE(symlink, int);
+CELIX_EI_DECLARE(unlink, int);
+
#ifdef __cplusplus
}
#endif
diff --git a/libs/error_injector/unistd/src/unistd_ei.cc
b/libs/error_injector/unistd/src/unistd_ei.cc
index 22673e99..5f01ddc7 100644
--- a/libs/error_injector/unistd/src/unistd_ei.cc
+++ b/libs/error_injector/unistd/src/unistd_ei.cc
@@ -39,4 +39,14 @@ int __wrap_symlink(const char *target, const char *linkpath)
{
errno = 0;
return __real_symlink(target, linkpath);
}
+
+int __real_unlink(const char *pathname);
+CELIX_EI_DEFINE(unlink, int)
+int __wrap_unlink(const char *pathname) {
+ errno = EACCES;
+ CELIX_EI_IMPL(unlink);
+ errno = 0;
+ return __real_unlink(pathname);
}
+
+}
\ No newline at end of file
diff --git a/libs/framework/gtest/CMakeLists.txt
b/libs/framework/gtest/CMakeLists.txt
index 05491882..2d57dc7b 100644
--- a/libs/framework/gtest/CMakeLists.txt
+++ b/libs/framework/gtest/CMakeLists.txt
@@ -147,6 +147,7 @@ if (LINKER_WRAP_SUPPORTED)
Celix::hash_map_ei
Celix::properties_ei
Celix::stdlib_ei
+ Celix::stat_ei
GTest::gtest GTest::gtest_main
)
diff --git
a/libs/framework/gtest/src/BundleArchiveWithErrorInjectionTestSuite.cc
b/libs/framework/gtest/src/BundleArchiveWithErrorInjectionTestSuite.cc
index 4861ea44..9525c3b1 100644
--- a/libs/framework/gtest/src/BundleArchiveWithErrorInjectionTestSuite.cc
+++ b/libs/framework/gtest/src/BundleArchiveWithErrorInjectionTestSuite.cc
@@ -19,6 +19,7 @@
#include <gtest/gtest.h>
+#include <thread>
#include <unistd.h>
#include "celix_constants.h"
@@ -36,6 +37,8 @@
#include "framework_private.h"
#include "malloc_ei.h"
#include "manifest.h"
+#include "stat_ei.h"
+#include "unistd_ei.h"
class BundleArchiveWithErrorInjectionTestSuite : public ::testing::Test {
public:
@@ -62,6 +65,8 @@ class BundleArchiveWithErrorInjectionTestSuite : public
::testing::Test {
celix_ei_expect_celix_utils_deleteDirectory(nullptr, 0, CELIX_SUCCESS);
celix_ei_expect_celix_utils_writeOrCreateString(nullptr, 0, nullptr);
celix_ei_expect_celix_utils_extractZipData(nullptr, 0, CELIX_SUCCESS);
+ celix_ei_expect_lstat(nullptr, 0, 0);
+ celix_ei_expect_unlink(nullptr, 0, 0);
}
void installBundleAndExpectFailure() {
@@ -192,6 +197,34 @@ TEST_F(CelixBundleArchiveErrorInjectionTestSuite,
ArchiveCreateErrorTest) {
EXPECT_FALSE(celix_utils_directoryExists(TEST_ARCHIVE_ROOT));
teardownErrorInjectors();
+ celix_ei_expect_lstat((void*) celix_bundleArchive_create, 2, -1);
+ EXPECT_EQ(CELIX_ERROR_MAKE(CELIX_FACILITY_CERRNO,EACCES),
+ celix_bundleArchive_create(&fw, TEST_ARCHIVE_ROOT, 1,
SIMPLE_TEST_BUNDLE1_LOCATION, &archive));
+ EXPECT_EQ(nullptr, archive);
+ EXPECT_FALSE(celix_utils_directoryExists(TEST_ARCHIVE_ROOT));
+ teardownErrorInjectors();
+
+ const char* testExtractDir = "extractBundleTestDir";
+ EXPECT_EQ(CELIX_SUCCESS,
celix_utils_extractZipFile(SIMPLE_TEST_BUNDLE1_LOCATION, testExtractDir,
nullptr));
+ EXPECT_EQ(CELIX_SUCCESS,
+ celix_bundleArchive_create(&fw, TEST_ARCHIVE_ROOT, 2,
testExtractDir, &archive));
+ bundleArchive_destroy(archive);
+ archive = nullptr;
+ std::this_thread::sleep_for(std::chrono::milliseconds(10));
+ celix_utils_touch(SIMPLE_TEST_BUNDLE1_LOCATION);
+ celix_ei_expect_unlink((void*)celix_bundleArchive_create, 2, -1);
+ EXPECT_EQ(CELIX_ERROR_MAKE(CELIX_FACILITY_CERRNO,EACCES),
+ celix_bundleArchive_create(&fw, TEST_ARCHIVE_ROOT, 2,
SIMPLE_TEST_BUNDLE1_LOCATION, &archive));
+ EXPECT_EQ(nullptr, archive);
+ celix_utils_deleteDirectory(testExtractDir, nullptr);
+ teardownErrorInjectors();
+
+ EXPECT_EQ(CELIX_SUCCESS,
+ celix_bundleArchive_create(&fw, TEST_ARCHIVE_ROOT, 1,
SIMPLE_TEST_BUNDLE1_LOCATION, &archive));
+ bundleArchive_destroy(archive);
+ archive = nullptr;
+ std::this_thread::sleep_for(std::chrono::milliseconds(10));
+ celix_utils_touch(SIMPLE_TEST_BUNDLE1_LOCATION);
celix_ei_expect_celix_utils_deleteDirectory((void*)celix_bundleArchive_create,
2, CELIX_FILE_IO_EXCEPTION);
EXPECT_EQ(CELIX_FILE_IO_EXCEPTION,
celix_bundleArchive_create(&fw, TEST_ARCHIVE_ROOT, 1,
SIMPLE_TEST_BUNDLE1_LOCATION, &archive));
diff --git a/libs/framework/gtest/src/CelixBundleContextBundlesTestSuite.cc
b/libs/framework/gtest/src/CelixBundleContextBundlesTestSuite.cc
index 37cf9b2a..e68e08d4 100644
--- a/libs/framework/gtest/src/CelixBundleContextBundlesTestSuite.cc
+++ b/libs/framework/gtest/src/CelixBundleContextBundlesTestSuite.cc
@@ -307,20 +307,31 @@ TEST_F(CelixBundleContextBundlesTestSuite,
UpdateBundlesTest) {
ASSERT_FALSE(celix_bundleContext_updateBundle(ctx, bndId1, TEST_BND2_LOC));
ASSERT_TRUE(celix_bundleContext_isBundleInstalled(ctx, bndId1));
- // remove it from cache before updating
- ASSERT_EQ(bndId2, celix_bundleContext_installBundle(ctx, TEST_BND2_LOC,
false));
- ASSERT_TRUE(celix_bundleContext_uninstallBundle(ctx, bndId2));
- auto sn1 = celix_bundleContext_getBundleSymbolicName(ctx, bndId1);
- ASSERT_TRUE(celix_bundleContext_updateBundle(ctx, bndId1, TEST_BND2_LOC));
- auto sn2 = celix_bundleContext_getBundleSymbolicName(ctx, bndId1);
- ASSERT_STRNE(sn1, sn2);
- free(sn2);
- free(sn1);
-
ASSERT_TRUE(celix_bundleContext_unloadBundle(ctx, bndId1));
ASSERT_FALSE(celix_bundleContext_updateBundle(ctx, bndId1, NULL));
}
+TEST_F(CelixBundleContextBundlesTestSuite,
UpdateCorruptUncompressedBundlesTest) {
+ const char* testExtractDir1 = "extractBundleTestDir1";
+ const char* testExtractDir2 = "extractBundleTestDir2";
+ celix_utils_deleteDirectory(testExtractDir1, nullptr);
+ EXPECT_EQ(CELIX_SUCCESS, celix_utils_extractZipFile(TEST_BND1_LOC,
testExtractDir1, nullptr));
+ long bndId1 = celix_bundleContext_installBundle(ctx, testExtractDir1,
true);
+ ASSERT_TRUE(bndId1 >= 0L);
+ ASSERT_TRUE(celix_bundleContext_isBundleInstalled(ctx, bndId1));
+ ASSERT_TRUE(celix_bundleContext_isBundleActive(ctx, bndId1));
+
+ // make the symbolic link in cache dangling
+ celix_utils_deleteDirectory(testExtractDir1, nullptr);
+
+ std::this_thread::sleep_for(std::chrono::milliseconds{10});
+ EXPECT_EQ(CELIX_SUCCESS, celix_utils_extractZipFile(TEST_BND2_LOC,
testExtractDir2, nullptr));
+ ASSERT_TRUE(celix_bundleContext_updateBundle(ctx, bndId1,
testExtractDir2));
+
+ celix_utils_deleteDirectory(testExtractDir1, nullptr);
+ celix_utils_deleteDirectory(testExtractDir2, nullptr);
+}
+
TEST_F(CelixBundleContextBundlesTestSuite, StartBundleWithException) {
long bndId = celix_bundleContext_installBundle(ctx,
TEST_BND_WITH_EXCEPTION_LOC, true);
ASSERT_TRUE(bndId > 0); //bundle is installed, but not started
diff --git
a/libs/framework/gtest/src/CelixFrameworkUtilsErrorInjectionTestSuite.cc
b/libs/framework/gtest/src/CelixFrameworkUtilsErrorInjectionTestSuite.cc
index 58ab0901..cee8be4b 100644
--- a/libs/framework/gtest/src/CelixFrameworkUtilsErrorInjectionTestSuite.cc
+++ b/libs/framework/gtest/src/CelixFrameworkUtilsErrorInjectionTestSuite.cc
@@ -21,6 +21,7 @@
#include <dirent.h>
#include <time.h>
+#include <unistd.h>
#include "celix/FrameworkFactory.h"
#include "celix/FrameworkUtils.h"
@@ -95,7 +96,7 @@ TEST_F(CelixFrameworkUtilsErrorInjectionTestSuite,
ExtractUncompressedBundleTest
const char* testExtractDir = "extractBundleTestDir";
const char* testLinkDir = "linkBundleTestDir";
celix_utils_deleteDirectory(testExtractDir, nullptr);
- celix_utils_deleteDirectory(testLinkDir, nullptr);
+ unlink(testLinkDir);
EXPECT_EQ(CELIX_SUCCESS,
celix_utils_extractZipFile(SIMPLE_TEST_BUNDLE1_LOCATION, testExtractDir,
nullptr));
// failed to get realpath of bundle
@@ -109,7 +110,7 @@ TEST_F(CelixFrameworkUtilsErrorInjectionTestSuite,
ExtractUncompressedBundleTest
EXPECT_EQ(status, CELIX_ERROR_MAKE(CELIX_FACILITY_CERRNO,EIO));
celix_utils_deleteDirectory(testExtractDir, nullptr);
- celix_utils_deleteDirectory(testLinkDir, nullptr);
+ unlink(testLinkDir);
}
TEST_F(CelixFrameworkUtilsErrorInjectionTestSuite, CheckBundleAge) {
diff --git a/libs/framework/gtest/src/CelixFrameworkUtilsTestSuite.cc
b/libs/framework/gtest/src/CelixFrameworkUtilsTestSuite.cc
index 667ff309..2dbecd80 100644
--- a/libs/framework/gtest/src/CelixFrameworkUtilsTestSuite.cc
+++ b/libs/framework/gtest/src/CelixFrameworkUtilsTestSuite.cc
@@ -121,7 +121,7 @@ TEST_F(CelixFrameworkUtilsTestSuite,
ExtractUncompressedBundleTest) {
const char* testExtractDir = "extractBundleTestDir";
const char* testLinkDir = "linkBundleTestDir";
celix_utils_deleteDirectory(testExtractDir, nullptr);
- celix_utils_deleteDirectory(testLinkDir, nullptr);
+ unlink(testLinkDir);
EXPECT_EQ(CELIX_SUCCESS,
celix_utils_extractZipFile(SIMPLE_TEST_BUNDLE1_LOCATION, testExtractDir,
nullptr));
//valid bundle path -> install a symbolic link
@@ -135,7 +135,7 @@ TEST_F(CelixFrameworkUtilsTestSuite,
ExtractUncompressedBundleTest) {
EXPECT_EQ(0, memcmp(&st2, &st3, sizeof(struct stat)));
celix_utils_deleteDirectory(testExtractDir, nullptr);
- celix_utils_deleteDirectory(testLinkDir, nullptr);
+ unlink(testLinkDir);
}
TEST_F(CelixFrameworkUtilsTestSuite, ExtractEmbeddedBundleTest) {
diff --git a/libs/framework/src/bundle_archive.c
b/libs/framework/src/bundle_archive.c
index 9bb0b0fd..bd151729 100644
--- a/libs/framework/src/bundle_archive.c
+++ b/libs/framework/src/bundle_archive.c
@@ -125,13 +125,30 @@ celix_bundleArchive_extractBundle(bundle_archive_t*
archive, const char* bundleU
* If dlopen/dlsym is used with newer files, but with the same inode
already used in dlopen/dlsym this leads to
* segfaults.
*/
- const char* error;
- status = celix_utils_deleteDirectory(archive->resourceCacheRoot, &error);
- if (status != CELIX_SUCCESS) {
- fw_logCode(archive->fw->logger, CELIX_LOG_LEVEL_ERROR, status, "Failed
to remove existing bundle archive revision directory '%s': %s",
archive->resourceCacheRoot, error);
+ const char* error = NULL;
+ struct stat st;
+ status = lstat(archive->resourceCacheRoot, &st);
+ if(status == -1 && errno != ENOENT) {
+ status = CELIX_ERROR_MAKE(CELIX_FACILITY_CERRNO,errno);
+ fw_logCode(archive->fw->logger, CELIX_LOG_LEVEL_ERROR, status, "Failed
to stat bundle archive directory '%s'", archive->resourceCacheRoot);
return status;
}
-
+ if (status == 0) {
+ // celix_utils_deleteDirectory does not work for dangling symlinks, so
handle this case separately
+ if (S_ISLNK(st.st_mode)) {
+ status = unlink(archive->resourceCacheRoot);
+ if (status == -1) {
+ status = CELIX_ERROR_MAKE(CELIX_FACILITY_CERRNO,errno);
+ error = "Failed to remove existing bundle symlink";
+ }
+ } else {
+ status = celix_utils_deleteDirectory(archive->resourceCacheRoot,
&error);
+ }
+ if (status != CELIX_SUCCESS) {
+ fw_logCode(archive->fw->logger, CELIX_LOG_LEVEL_ERROR, status,
"Failed to remove existing bundle archive revision directory '%s': %s",
archive->resourceCacheRoot, error);
+ return status;
+ }
+ }
status = celix_framework_utils_extractBundle(archive->fw, bundleUrl,
archive->resourceCacheRoot);
if (status != CELIX_SUCCESS) {
fw_log(archive->fw->logger, CELIX_LOG_LEVEL_ERROR, "Failed to
initialize archive. Failed to extract bundle zip to revision directory.");
diff --git a/libs/framework/src/framework.c b/libs/framework/src/framework.c
index d86a7e93..57f3f41f 100644
--- a/libs/framework/src/framework.c
+++ b/libs/framework/src/framework.c
@@ -2308,7 +2308,6 @@ celix_status_t
celix_framework_updateBundleEntry(celix_framework_t* framework,
celix_status_t status = CELIX_SUCCESS;
long bundleId = bndEntry->bndId;
const char* errMsg;
- char *bndRoot = NULL;
fw_log(framework->logger, CELIX_LOG_LEVEL_DEBUG, "Updating bundle %s",
celix_bundle_getSymbolicName(bndEntry->bnd));
celix_bundle_state_e bndState = celix_bundle_getState(bndEntry->bnd);
char *location = celix_bundle_getLocation(bndEntry->bnd);
@@ -2326,7 +2325,6 @@ celix_status_t
celix_framework_updateBundleEntry(celix_framework_t* framework,
status = CELIX_ILLEGAL_STATE;
break;
}
- bndRoot = celix_bundle_getEntry(bndEntry->bnd, NULL);
}
status = celix_framework_uninstallBundleEntryImpl(framework, bndEntry,
false);
if (status != CELIX_SUCCESS) {
@@ -2335,10 +2333,6 @@ celix_status_t
celix_framework_updateBundleEntry(celix_framework_t* framework,
break;
}
// bndEntry is now invalid
- if (bndRoot) {
- // the bundle is updated with a new location, so the old bundle
root can be removed
- celix_utils_deleteDirectory(bndRoot, NULL);
- }
status = celix_framework_installBundleInternalImpl(framework,
updatedBundleUrl, &bundleId);
if (status != CELIX_SUCCESS) {
errMsg = "reinstall failure";
@@ -2361,7 +2355,6 @@ celix_status_t
celix_framework_updateBundleEntry(celix_framework_t* framework,
}
} while(0);
framework_logIfError(framework->logger, status, errMsg, "Could not update
bundle from %s", updatedBundleUrl);
- free(bndRoot);
free(location);
return status;
}