Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/amachronic/microtar.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAidan MacDonald <amachronic@protonmail.com>2021-11-06 16:58:53 +0300
committerAidan MacDonald <amachronic@protonmail.com>2021-11-06 17:00:05 +0300
commitf5726a59e269aaabd45fca5e9b891d4ab8a4dc59 (patch)
tree8e4e941cee7626881f0286a29ba1f3e5cef25989
parenta88dfe430bb40703a172e580156de031ccbd5987 (diff)
Basic archive creation support in mtar
This is hardly usable and doesn't handle directories or deal with filenames properly. It's here mainly to test library code.
-rw-r--r--mtar.c58
1 files changed, 55 insertions, 3 deletions
diff --git a/mtar.c b/mtar.c
index e88732c..4a9a27b 100644
--- a/mtar.c
+++ b/mtar.c
@@ -91,7 +91,7 @@ int extract_foreach_cb(mtar_t* tar, const mtar_header_t* h, void* arg)
return 0;
}
- int fd = open(h->name, O_CREAT|O_WRONLY, h->mode);
+ int fd = open(h->name, O_CREAT|O_WRONLY|O_TRUNC, h->mode);
if(fd < 0)
die(E_FS, "extracting \"%s\" failed: %s", h->name, strerror(errno));
@@ -121,6 +121,47 @@ void extract_files(mtar_t* tar, char** files, int num_files)
die(E_TAR, "extraction failed: %s", mtar_strerror(err));
}
+void add_files(mtar_t* tar, char** files, int num_files)
+{
+ for(int i = 0; i < num_files; ++i) {
+ int fd = open(files[i], O_RDONLY);
+ if(fd < 0)
+ die(E_FS, "adding \"%s\" failed: %s", files[i], strerror(errno));
+
+ off_t off = lseek(fd, 0, SEEK_END);
+ if(off < 0)
+ die(E_FS, "adding \"%s\" failed: %s", files[i], strerror(errno));
+
+ unsigned filesize = off;
+ lseek(fd, 0, SEEK_SET);
+
+ int err = mtar_write_file_header(tar, files[i], filesize);
+ if(err)
+ die(E_TAR, "adding \"%s\" failed: %s", files[i], mtar_strerror(err));
+
+ char iobuf[1024];
+ while(1) {
+ int rcount = read(fd, iobuf, sizeof(iobuf));
+ if(rcount < 0)
+ die(E_FS, "adding \"%s\" failed: %s", files[i], strerror(errno));
+ if(rcount == 0)
+ break;
+
+ int wcount = mtar_write_data(tar, iobuf, rcount);
+ if(wcount < 0)
+ die(E_TAR, "adding \"%s\" failed: %s", files[i], mtar_strerror(wcount));
+ if(wcount != rcount)
+ die(E_TAR, "adding \"%s\" failed: write too short %d/%d", files[i], wcount, rcount);
+ }
+
+ close(fd);
+
+ err = mtar_end_data(tar);
+ if(err)
+ die(E_TAR, "adding \"%s\" failed: %s", files[i], mtar_strerror(err));
+ }
+}
+
int main(int argc, char* argv[])
{
++argv, --argc;
@@ -164,8 +205,12 @@ int main(int argc, char* argv[])
if(op == OP_LIST && argc != 0)
die(E_ARGS, "excess arguments on command line");
+ const char* mode = "rb";
+ if(op == OP_CREATE)
+ mode = "wb";
+
mtar_t tar;
- int err = mtar_open(&tar, archive_name, "rb");
+ int err = mtar_open(&tar, archive_name, mode);
if(err)
die(E_TAR, "can't open archive: %s", mtar_strerror(err));
@@ -178,6 +223,13 @@ int main(int argc, char* argv[])
extract_files(&tar, argv, argc);
break;
+ case OP_CREATE:
+ add_files(&tar, argv, argc);
+ err = mtar_finalize(&tar);
+ if(err)
+ die(E_TAR, "failed to finalize archive: %s", mtar_strerror(err));
+ break;
+
default:
die(E_OTHER, "not implemented");
break;
@@ -185,7 +237,7 @@ int main(int argc, char* argv[])
err = mtar_close(&tar);
if(err)
- die(E_TAR, "failed to finalize archive: %s", mtar_strerror(err));
+ die(E_TAR, "failed to close archive: %s", mtar_strerror(err));
return 0;
}