mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2026-11-09 08:37:58 +08:00
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
This commit is contained in:
1 parent
39e6f53298
commit
ffc57e3cf3
5 files changed
+282
-29
No files matched your search
@@ -126,30 +126,25 @@ Make_Path(const rtems_printer *printer, char *path)
|
||||
|
||||
*p = '\0';
|
||||
if (p[1] == '\0') {
|
||||
/* Speculatively unlink the last component so that it can be re-created */
|
||||
unlink(path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (mkdir(path, S_IRWXU | S_IRWXG | S_IRWXO) != 0) {
|
||||
if (errno == EEXIST || errno == EISDIR) {
|
||||
if (errno == EEXIST) {
|
||||
/* If it exists already: Check whether it is a directory */
|
||||
struct stat sb;
|
||||
|
||||
if (stat(path, &sb) != 0) {
|
||||
if (lstat(path, &sb) != 0) {
|
||||
Print_Error(printer, "lstat", path);
|
||||
return -1;
|
||||
} else if (!S_ISDIR(sb.st_mode)) {
|
||||
rtems_printf(printer,
|
||||
"untar: mkdir: %s: exists but is not a directory\n",
|
||||
path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!S_ISDIR(sb.st_mode)) {
|
||||
if (unlink(path) != 0) {
|
||||
Print_Error(printer, "unlink", path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mkdir(path, S_IRWXU | S_IRWXG | S_IRWXO) != 0) {
|
||||
Print_Error(printer, "mkdir (unlink)", path);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Print_Error(printer, "mkdir", path);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,6 +201,12 @@ Untar_ProcessHeader(
|
||||
|
||||
if (Make_Path(ctx->printer, ctx->file_path) != 0) {
|
||||
retval = UNTAR_FAIL;
|
||||
} else {
|
||||
/*
|
||||
* Speculatively unlink. This should unlink everything but non-empty
|
||||
* directories or write protected stuff.
|
||||
*/
|
||||
unlink(ctx->file_path);
|
||||
}
|
||||
|
||||
if (ctx->linkflag == SYMTYPE) {
|
||||
@@ -225,8 +226,22 @@ Untar_ProcessHeader(
|
||||
rtems_printf(ctx->printer, "untar: dir: %s\n", ctx->file_path);
|
||||
r = mkdir(ctx->file_path, ctx->mode);
|
||||
if (r != 0) {
|
||||
Print_Error(ctx->printer, "mkdir", ctx->file_path);
|
||||
retval = UNTAR_FAIL;
|
||||
if (errno == EEXIST) {
|
||||
/* If it exists already: Check whether it is a directory */
|
||||
struct stat sb;
|
||||
if (lstat(ctx->file_path, &sb) != 0) {
|
||||
Print_Error(ctx->printer, "lstat", ctx->file_path);
|
||||
retval = UNTAR_FAIL;
|
||||
} else if (!S_ISDIR(sb.st_mode)) {
|
||||
rtems_printf(ctx->printer,
|
||||
"untar: mkdir: %s: exists but is not a directory\n",
|
||||
ctx->file_path);
|
||||
retval = UNTAR_FAIL;
|
||||
}
|
||||
} else {
|
||||
Print_Error(ctx->printer, "mkdir", ctx->file_path);
|
||||
retval = UNTAR_FAIL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -426,7 +441,9 @@ Untar_FromFile_Print(
|
||||
*/
|
||||
|
||||
if ((out_fd = creat(ctx.file_path, ctx.mode)) == -1) {
|
||||
(void) lseek(fd, SEEK_CUR, 512UL * ctx.nblocks);
|
||||
/* Couldn't create that file. Abort. */
|
||||
retval = UNTAR_FAIL;
|
||||
break;
|
||||
} else {
|
||||
for (i = 0; i < ctx.nblocks; i++) {
|
||||
n = read(fd, bufr, 512);
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -20,3 +20,4 @@ directives:
|
||||
concepts:
|
||||
|
||||
+ exercise these routines
|
||||
+ check whether existing files are overwritten or not overwritten like expected
|
||||
@@ -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 ***
|
||||
Binary file not shown.
Reference in new issue
Block a user