nkiss

WIP
git clone git://git.nihaljere.xyz/nkiss
Log | Files | Refs

commit c37dcd6c0ddfee55ec676ddf644e863c28c1b453
parent 858326c0faa59d484157d59cf713b2c572e6bfa7
Author: Nihal Jere <nihal@nihaljere.xyz>
Date:   Tue,  9 Mar 2021 23:23:15 -0600

add manifest.* to contain manifest operations

Diffstat:
Mcommon.h | 1+
Amanifest.c | 101+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amanifest.h | 9+++++++++
3 files changed, 111 insertions(+), 0 deletions(-)

diff --git a/common.h b/common.h @@ -10,6 +10,7 @@ #define PATH_LEN 512 #define URL_LEN 2048 #define ALT_MAX 256 +#define MANIFEST_LINES 100 #define KISS_INSTALLED "/var/db/kiss/installed" #define KISS_CHOICES "/var/db/kiss/choices" diff --git a/manifest.c b/manifest.c @@ -0,0 +1,101 @@ +#include <fcntl.h> +#include <sys/mman.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> + +#include "common.h" +#include "manifest.h" + +int +manifest_open(struct manifest_t *manifest, char path[PATH_LEN]) +{ + int fd, linelimit; + struct stat s; + char *start = NULL, **lines = NULL, **temp; + size_t lc, cc; + + linelimit = MANIFEST_LINES; + if ((lines = calloc(MANIFEST_LINES, sizeof(char *))) == NULL) + goto err; + + if ((fd = open(path, O_RDONLY)) == -1) + goto err; + + if (fstat(fd, &s) == -1) + goto err; + + /* load the whole manifest into memory, with permissions that will allow us + * to write to the memory map without writing to the file */ + start = mmap(NULL, s.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); + if (start == MAP_FAILED) { + start = 0; + goto err; + } + close(fd); + fd = 0; + + cc = s.st_size; + + /* create array of pointers to the each line, and replace \n with \0. + * since manifest is sorted, we can use this to search for file names when + * validating a tarball on install */ + lines[0] = start; + lc = 1; + for (int i = 0; i < cc; i++) { + if (start[i] != '\n') + continue; + + if (lc == linelimit) { + if ((temp = realloc(lines, linelimit*2*sizeof(char *))) == NULL) + goto err; + lines = temp; + linelimit *= 2; + } + + start[i] = '\0'; + + if (++i == cc) + break; + + lines[lc++] = start + i; + } + + /* one we know how many lines there are, we can shrink to only as much as + * we need */ + if ((temp = realloc(lines, (lc+1)*sizeof(char *))) == NULL) + goto err; + + /* null terminate to more easily know when we're done */ + temp[lc] = 0; + + manifest->start = start; + manifest->lines = temp; + manifest->lc = lc; + manifest->cc = cc; + + return 0; +err: + if (lines) free(lines); + if (fd) close(fd); + if (start) munmap(start, cc); + return -1; +} + +int +manifest_close(struct manifest_t *manifest) +{ + if (munmap(manifest->start, manifest->cc) == -1) + return -1; + manifest->start = NULL; + + free(manifest->lines); + manifest->lines = NULL; + + manifest->lc = 0; + manifest->cc = 0; + + return 0; +} diff --git a/manifest.h b/manifest.h @@ -0,0 +1,9 @@ +struct manifest_t { + char *start; + char **lines; + size_t lc; + size_t cc; +}; + +int manifest_open(struct manifest_t *manifest, char path[PATH_LEN]); +int manifest_close(struct manifest_t *manifest);