X-Git-Url: https://ruderich.org/simon/gitweb/?a=blobdiff_plain;ds=inline;f=nss%2Ffile.c;fp=nss%2Ffile.c;h=30ea4f9b5f96910f0cd0ba8d353cfa7dbccea076;hb=92afde4e875a96e1ab865e29b9f0d11b08d7db1c;hp=0000000000000000000000000000000000000000;hpb=748846b9a65726fd19d43b45a4db68ef4c2e77f4;p=nsscash%2Fnsscash.git
diff --git a/nss/file.c b/nss/file.c
new file mode 100644
index 0000000..30ea4f9
--- /dev/null
+++ b/nss/file.c
@@ -0,0 +1,88 @@
+/*
+ * Load and unload nsscash files
+ *
+ * Copyright (C) 2019 Simon Ruderich
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+#include "file.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+
+bool map_file(const char *path, struct file *f) {
+ // Fully initialize the struct for unmap_file() and other users
+ f->fd = -1;
+ f->size = 0;
+ f->next_index = 0;
+ f->header = NULL;
+
+ f->fd = open(path, O_RDONLY | O_CLOEXEC);
+ if (f->fd < 0) {
+ goto fail;
+ }
+ struct stat s;
+ if (fstat(f->fd, &s)) {
+ goto fail;
+ }
+ f->size = (size_t)s.st_size;
+
+ void *x = mmap(NULL, f->size, PROT_READ, MAP_PRIVATE, f->fd, 0);
+ if (x == MAP_FAILED) {
+ goto fail;
+ }
+
+ const struct header *h = x;
+ f->header = h;
+
+ // Check MAGIC
+ if (memcmp(h->magic, MAGIC, sizeof(h->magic))) {
+ errno = EINVAL;
+ goto fail;
+ }
+ // Only version 1 is supported at the moment; this will also prevent
+ // running on big-endian systems which is currently not possible
+ if (h->version != 1) {
+ errno = EINVAL;
+ goto fail;
+ }
+
+ return true;
+
+fail: {
+ int save_errno = errno;
+ unmap_file(f);
+ errno = save_errno;
+ return false;
+ }
+}
+
+void unmap_file(struct file *f) {
+ if (f->header != NULL) {
+ munmap((void *)f->header, f->size);
+ f->header = NULL;
+ }
+ if (f->fd != -1) {
+ close(f->fd);
+ f->fd = -1;
+ }
+}