X-Git-Url: https://ruderich.org/simon/gitweb/?a=blobdiff_plain;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; + } +}