commit 329695dd70ab47175849cd9b4c662e92ec3be982
parent 02253f088516cd0129fdb00a94108bdc4eef43f7
Author: kocotian <kocotian@kocotian.pl>
Date: Thu, 28 Jan 2021 19:38:30 +0100
archive creating
Diffstat:
A | STRUCTURE.wiki | | | 25 | +++++++++++++++++++++++++ |
M | nar.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;
}