summaryrefslogtreecommitdiffstats
path: root/testsuites/libtests
diff options
context:
space:
mode:
authorChristian Mauderer <christian.mauderer@embedded-brains.de>2021-12-01 16:39:46 +0100
committerChristian Mauderer <christian.mauderer@embedded-brains.de>2021-12-09 08:23:47 +0100
commitffc57e3cf33ec0e2cc51ce214cedc24f390a7ea5 (patch)
tree210db2da29d65be56aff24dfc737c036a8707854 /testsuites/libtests
parentscore: Fix _Workspace_Initialize_for_one_area() (diff)
downloadrtems-ffc57e3cf33ec0e2cc51ce214cedc24f390a7ea5.tar.bz2
untar: Make behavior similar to GNU or BSD tar
RTEMS untar implementation had problems with overwriting or integrating archives into existing directory structures. This patch adapts the behavior to mimic that of a GNU tar or BSD tar and extends the tar01 test to check for the behavior. That is: * If a directory structure exists, the files from the archive will be integrated. Existing files are overwritten. * If a file exists and the archive contains a directory with the same name, the file is removed and a directory is created. In the above example: if l1/l2 is a file it will be overwritten with a new directory. * If a directory exists and the archive contains a file with the same name, the directory will be replaced if it is empty. If it contains files, the result is an error. * An archive also can contain only a file without the parent directories. If in that case one of the parent directories exists as a file extracting the archive results in an error. In the example: if l1/l2 is a file and the archive doesn't contain the directories but only the file l1/l2/x.txt that would be an error. * In case of an error, it is possible that the archive has been partially extracted. Closes #4568
Diffstat (limited to 'testsuites/libtests')
-rw-r--r--testsuites/libtests/tar01/init.c199
-rw-r--r--testsuites/libtests/tar01/tar01.doc1
-rw-r--r--testsuites/libtests/tar01/tar01.scn54
-rw-r--r--testsuites/libtests/tar01/tar01.tarbin10240 -> 10240 bytes
4 files changed, 245 insertions, 9 deletions
diff --git a/testsuites/libtests/tar01/init.c b/testsuites/libtests/tar01/init.c
index 4cad67a6ae..2deff3a482 100644
--- a/testsuites/libtests/tar01/init.c
+++ b/testsuites/libtests/tar01/init.c
@@ -7,6 +7,33 @@
* http://www.rtems.org/license/LICENSE.
*/
+/*
+ * Note on the used tar file: Generate the file on a system that supports
+ * symlinks with the following commands (tested on Linux - you might have to
+ * adapt on other systems):
+ *
+ * export WORK=some_work_directory
+ * rm -r ${WORK}
+ * mkdir -p ${WORK}/home/abc/def
+ * mkdir -p ${WORK}/home/dir
+ * cd ${WORK}
+ * echo "#! joel" > home/abc/def/test_script
+ * echo "ls -las /dev" >> home/abc/def/test_script
+ * chmod 755 home/abc/def/test_script
+ * echo "This is a test of loading an RTEMS filesystem from an" > home/test_file
+ * echo "initial tar image." >> home/test_file
+ * echo "Hello world" >> home/dir/file
+ * ln -s home/test_file symlink
+ * tar cf tar01.tar --format=ustar \
+ * symlink \
+ * home/test_file \
+ * home/abc/def/test_script \
+ * home/dir
+ *
+ * Note that "home/dir" is in the archive as separate directory. "home/abc" is
+ * only in the archive as a parent of the file "test_script".
+ */
+
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@@ -95,6 +122,84 @@ void test_untar_from_memory(void)
}
+static void assert_file_content(
+ const char *name,
+ const char *expected_content,
+ ssize_t expected_size
+)
+{
+ char buf[16];
+ int fd;
+ int rd;
+
+ fd = open(name, O_RDONLY);
+ rtems_test_assert( fd >= 0 );
+ do {
+ rd = read(fd, buf, sizeof(buf));
+ rtems_test_assert( rd >= 0 );
+ if (rd > 0) {
+ rtems_test_assert( expected_size - rd >= 0 );
+ rtems_test_assert( memcmp(buf, expected_content, rd) == 0 );
+ expected_content += rd;
+ expected_size -= rd;
+ }
+ } while(rd > 0);
+ rtems_test_assert( expected_size == 0 );
+ close(fd);
+}
+
+static void assert_content_like_expected(void)
+{
+ const char *directories[] = {
+ "home",
+ "home/abc",
+ "home/abc/def",
+ "home/dir",
+ };
+ const char *symlinks[] = {
+ "symlink",
+ };
+ const struct {
+ const char *name;
+ const char *content;
+ } files[] = {
+ {
+ .name = "home/abc/def/test_script",
+ .content = "#! joel\nls -las /dev\n",
+ }, {
+ .name = "home/test_file",
+ .content = "This is a test of loading an RTEMS filesystem from an\n"
+ "initial tar image.\n",
+ }, {
+ .name = "home/dir/file",
+ .content = "Hello world\n",
+ }
+ };
+ size_t i;
+ struct stat st;
+
+ for(i = 0; i < RTEMS_ARRAY_SIZE(directories); ++i) {
+ lstat(directories[i], &st);
+ rtems_test_assert( S_ISDIR(st.st_mode) );
+ }
+
+ for(i = 0; i < RTEMS_ARRAY_SIZE(symlinks); ++i) {
+ lstat(symlinks[i], &st);
+ rtems_test_assert( S_ISLNK(st.st_mode) );
+ }
+
+ for(i = 0; i < RTEMS_ARRAY_SIZE(files); ++i) {
+ lstat(files[i].name, &st);
+ rtems_test_assert( S_ISREG(st.st_mode) );
+
+ assert_file_content(
+ files[i].name,
+ files[i].content,
+ strlen(files[i].content)
+ );
+ }
+}
+
void test_untar_from_file(void)
{
int fd;
@@ -119,13 +224,105 @@ void test_untar_from_file(void)
rv = chdir( "/dest" );
rtems_test_assert( rv == 0 );
- /* Untar it */
+ /* Case 1: Untar it into empty directory */
rv = Untar_FromFile( "/test.tar" );
printf("Untaring from file - ");
if (rv != UNTAR_SUCCESSFUL) {
printf ("error: untar failed: %i\n", rv);
exit(1);
}
+ assert_content_like_expected();
+ printf ("successful\n");
+
+ /* Case 2: Most files exist */
+ rv = unlink("/dest/home/test_file");
+ rtems_test_assert( rv == 0 );
+
+ rv = Untar_FromFile( "/test.tar" );
+ printf("Untar from file into existing structure with one missing file - ");
+ if (rv != UNTAR_SUCCESSFUL) {
+ printf ("error: untar failed: %i\n", rv);
+ exit(1);
+ }
+ assert_content_like_expected();
+ printf ("successful\n");
+
+ /* Case 3: An empty directory exists where a file should be */
+ rv = unlink("/dest/home/test_file");
+ rtems_test_assert( rv == 0 );
+ rv = mkdir("/dest/home/test_file", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
+ rtems_test_assert( rv == 0 );
+
+ rv = Untar_FromFile( "/test.tar" );
+ printf("Untar from file; overwrite empty directory with file - ");
+ if (rv != UNTAR_SUCCESSFUL) {
+ printf ("error: untar failed: %i\n", rv);
+ exit(1);
+ }
+ assert_content_like_expected();
+ printf ("successful\n");
+
+ /* Case 4: A file exists where a parent directory should be created */
+ rv = unlink("/dest/home/abc/def/test_script");
+ rtems_test_assert( rv == 0 );
+ rv = unlink("/dest/home/abc/def");
+ rtems_test_assert( rv == 0 );
+ rv = unlink("/dest/home/abc");
+ rtems_test_assert( rv == 0 );
+ fd = creat("/dest/home/abc", S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+ rtems_test_assert( fd >= 0 );
+ close(fd);
+
+ rv = Untar_FromFile( "/test.tar" );
+ printf("Untar from file; file exists where parent dir should be created - ");
+ if (rv != UNTAR_FAIL) {
+ printf ("error: untar didn't fail like expected: %i\n", rv);
+ exit(1);
+ }
+ printf ("expected fail\n");
+ /* cleanup so that the next one works */
+ rv = unlink("/dest/home/abc");
+ rtems_test_assert( rv == 0 );
+
+ /* Case 5: A non-empty directory exists where a file should be created */
+ rv = unlink("/dest/home/test_file");
+ rtems_test_assert( rv == 0 );
+ rv = mkdir("/dest/home/test_file", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
+ rtems_test_assert( rv == 0 );
+ fd = creat("/dest/home/test_file/file",
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+ rtems_test_assert( fd >= 0 );
+ close(fd);
+
+ rv = Untar_FromFile( "/test.tar" );
+ printf("Untar from file; non-empty dir where file should be created - ");
+ if (rv != UNTAR_FAIL) {
+ printf ("error: untar didn't fail like expected: %i\n", rv);
+ exit(1);
+ }
+ printf ("expected fail\n");
+ /* cleanup so that the next one works */
+ rv = unlink("/dest/home/test_file/file");
+ rtems_test_assert( rv == 0 );
+ rv = unlink("/dest/home/test_file");
+ rtems_test_assert( rv == 0 );
+
+ /* Case 6: A file exists where a directory is explicitly in the archive */
+ rv = unlink("/dest/home/dir/file");
+ rtems_test_assert( rv == 0 );
+ rv = unlink("/dest/home/dir");
+ rtems_test_assert( rv == 0 );
+ fd = creat("/dest/home/dir", S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+ rtems_test_assert( fd >= 0 );
+ close(fd);
+
+ rv = Untar_FromFile( "/test.tar" );
+ printf("Untar from file; overwrite file with explicit directory - ");
+ if (rv != UNTAR_SUCCESSFUL) {
+ printf ("error: untar failed: %i\n", rv);
+ exit(1);
+ }
+ assert_content_like_expected();
printf ("successful\n");
/******************/
diff --git a/testsuites/libtests/tar01/tar01.doc b/testsuites/libtests/tar01/tar01.doc
index 060f98a813..adffdca291 100644
--- a/testsuites/libtests/tar01/tar01.doc
+++ b/testsuites/libtests/tar01/tar01.doc
@@ -20,3 +20,4 @@ directives:
concepts:
+ exercise these routines
++ check whether existing files are overwritten or not overwritten like expected
diff --git a/testsuites/libtests/tar01/tar01.scn b/testsuites/libtests/tar01/tar01.scn
index 68fa951881..dd72f9517b 100644
--- a/testsuites/libtests/tar01/tar01.scn
+++ b/testsuites/libtests/tar01/tar01.scn
@@ -1,9 +1,24 @@
-*** TAR01 TEST ***
-Untaring from memory - successful
+*** BEGIN OF TEST TAR 1 ***
+*** TEST VERSION: 6.0.0.e1efb4eb8a9d6dd5f6f37dafc9feb0a9e6a888f1
+*** TEST STATE: EXPECTED_PASS
+*** TEST BUILD: RTEMS_POSIX_API
+*** TEST TOOLS: 10.3.1 20210409 (RTEMS 6, RSB ad54d1dd3cf8249d9d39deb1dd28b2f294df062d-modified, Newlib eb03ac1)
+Untaring from memory - untar: memory at 0x11ece8 (10240)
+untar: symlink: home/test_file -> symlink
+untar: file: home/test_file (s:73,m:0644)
+untar: file: home/abc/def/test_script (s:21,m:0755)
+untar: dir: home/dir
+untar: file: home/dir/file (s:12,m:0644)
+successful
========= /home/test_file =========
(0)This is a test of loading an RTEMS filesystem from an
initial tar image.
+========= /home/abc/def/test_script =========
+(0)#! joel
+ls -las /dev
+
+ /home/abc/def/test_script: mode: 0755 want: 0755
========= /symlink =========
(0)This is a test of loading an RTEMS filesystem from an
initial tar image.
@@ -11,35 +26,58 @@ initial tar image.
Copy tar image to test.tar
Untaring from file - successful
+Untar from file into existing structure with one missing file - successful
+Untar from file; overwrite empty directory with file - successful
+Untar from file; file exists where parent dir should be created - expected fail
+Untar from file; non-empty dir where file should be created - expected fail
+Untar from file; overwrite file with explicit directory - successful
========= /dest/home/test_file =========
(0)This is a test of loading an RTEMS filesystem from an
initial tar image.
+========= /dest/home/abc/def/test_script =========
+(0)#! joel
+ls -las /dev
+
+ /dest/home/abc/def/test_script: mode: 0755 want: 0755
========= /dest/symlink =========
(0)This is a test of loading an RTEMS filesystem from an
initial tar image.
-Untaring chunks from memory - untar: dir: home
-untar: file: home/test_file (73)
+Untaring chunks from memory - untar: symlink: home/test_file -> symlink
+untar: file: home/test_file (s:73,m:0644)
+untar: file: home/abc/def/test_script (s:21,m:0755)
+untar: dir: home/dir
+untar: file: home/dir/file (s:12,m:0644)
successful
========= /dest2/home/test_file =========
(0)This is a test of loading an RTEMS filesystem from an
initial tar image.
+========= /dest2/home/abc/def/test_script =========
+(0)#! joel
+ls -las /dev
+
+ /dest2/home/abc/def/test_script: mode: 0755 want: 0755
========= /dest2/symlink =========
(0)This is a test of loading an RTEMS filesystem from an
initial tar image.
-Untaring chunks from tgz- untar: dir: home
-untar: file: home/test_file (73)
-successful
+Untaring chunks from tgz - successful
========= /dest3/home/test_file =========
(0)This is a test of loading an RTEMS filesystem from an
initial tar image.
+========= /dest3/home/abc/def/test_script =========
+(0)#! joel
+ls -las /dev
+
+ /dest3/home/abc/def/test_script: mode: 0755 want: 0755
========= /dest3/symlink =========
(0)This is a test of loading an RTEMS filesystem from an
initial tar image.
-*** END OF TAR01 TEST ***
+
+
+*** END OF TEST TAR 1 ***
diff --git a/testsuites/libtests/tar01/tar01.tar b/testsuites/libtests/tar01/tar01.tar
index 6c6952ef18..9874f426d1 100644
--- a/testsuites/libtests/tar01/tar01.tar
+++ b/testsuites/libtests/tar01/tar01.tar
Binary files differ