nar

simple archives
git clone git://git.kocotian.pl/nar.git
Log | Files | Refs | LICENSE

commit 329695dd70ab47175849cd9b4c662e92ec3be982
parent 02253f088516cd0129fdb00a94108bdc4eef43f7
Author: kocotian <kocotian@kocotian.pl>
Date:   Thu, 28 Jan 2021 19:38:30 +0100

archive creating

Diffstat:
ASTRUCTURE.wiki | 25+++++++++++++++++++++++++
Mnar.c | 90+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 115 insertions(+), 0 deletions(-)

diff --git a/STRUCTURE.wiki b/STRUCTURE.wiki @@ -0,0 +1,25 @@ += NAR Structure = + +Typical NAR archive contains: +- Archive header +- File array (just files) + +== NAR Archive header == + +| Bytes | Description | +|-------|------------------------------| +| 4 | *NAR[Line Feed]* magic value | + +== NAR File array == + +File array structure: + +| Bytes | Description | +|--------------|-------------------------------| +| 8 | File size | +| 2 | File mode | +| 4 | Owner ID | +| 4 | Owner's Group ID | +| *Length* + 1 | File name (NULL terminated) | +| *File size* | File content | +| 1 | End of file confirmation byte | diff --git a/nar.c b/nar.c @@ -3,18 +3,108 @@ #define _XOPEN_SOURCE 700 +#include <fcntl.h> #include <stdio.h> +#include <string.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> #include "arg.h" #include "util.h" +static void create(char *fn, int fc, char *farr[]); +static void usage(void); + +const char eofbyte = 'k'; char *argv0; +int verbose; + +void +create(char *fn, int fc, char *farr[]) +{ + int fd, fdl; + struct stat sb; + int i = -1; + void *membuf; + + u_int64_t b64; + u_int32_t b32; + u_int16_t b16; + + /* opening a file */ + if (fn != NULL) { + if ((fd = open(fn, O_CREAT | O_WRONLY, 0644)) < 0) + die("error while opening %s:", fn); + } + else + fd = 1; /* if no filename, default will be stdout */ + + /* write magic value */ + write(fd, "NAR\n", 4); + + /* main creation loop */ + while (++i < fc) { + if (verbose) + fprintf(stderr, "adding file %s\n", farr[i]); + if (stat(farr[i], &sb) < 0) + die("stat: %s:", farr[i]); + b64 = sb.st_size; write(fd, &b64, 8); + b16 = sb.st_mode; write(fd, &b16, 2); + b32 = sb.st_uid; write(fd, &b32, 4); + b32 = sb.st_gid; write(fd, &b32, 4); + write(fd, farr[i], strlen(farr[i]) + 1); + if ((fdl = open(farr[i], O_RDONLY)) < 0) + die("open: %s:", farr[i]); + membuf = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fdl, 0); + write(fd, membuf, sb.st_size); + munmap(membuf, sb.st_size); + write(fd, &eofbyte, 1); + close(fdl); + } + + /* closing a file */ + if (fn != NULL) + close(fd); +} + +void +usage(void) +{ + die("usage: %s [-cx] [-v] [-f filename]", argv0); +} int main(int argc, char *argv[]) { + char *filename = NULL; + char flag = 0; + + verbose = 0; + ARGBEGIN { + case 'c': case 'x': /* FALLTHROUGH */ + if (!flag) + flag = ARGC(); + else + die("you can't specify more than one operation on the same time"); + break; + case 'v': + verbose = 1; + break; + case 'f': + filename = ARGF(); + break; default: + usage(); break; } ARGEND; + + switch (flag) { + case 'c': create(filename, argc, argv); break; + default: usage(); break; + } + + return 0; }