/
githubmirror
/
kmod
Обзор
Документация
Войти
/
githubmirror
/
kmod
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
libkmod/libkmod-file.c
155 строк
3 KB
Emil Velikov
Include fcntl.h where needed
06 авг 2026, 22:26
06 авг 2026, 22:26
0bff81d
Код
Авторство
О чём код?
// SPDX-License-Identifier: LGPL-2.1-or-later /* * Copyright (C) 2011-2013 ProFUSION embedded systems */ #include <errno.h> #include <fcntl.h> #include <limits.h> #include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/mman.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> #include <shared/util.h> #include "libkmod.h" #include "libkmod-internal.h" #include "libkmod-internal-file.h" static const char magic_zstd[] = { 0x28, 0xB5, 0x2F, 0xFD }; static const char magic_xz[] = { 0xfd, '7', 'z', 'X', 'Z', 0 }; static const char magic_zlib[] = { 0x1f, 0x8b }; static int load_reg(struct kmod_file *file) { struct stat st; if (fstat(file->fd, &st) < 0) return -errno; file->size = st.st_size; if ((uintmax_t)file->size > SIZE_MAX) return -ENOMEM; file->memory = mmap(NULL, file->size, PROT_READ, MAP_PRIVATE, file->fd, 0); if (file->memory == MAP_FAILED) { file->memory = NULL; return -errno; } return 0; } static const struct comp_type { size_t magic_size; enum kmod_file_compression_type compression; const char *magic_bytes; int (*load)(struct kmod_file *file); } comp_types[] = { // clang-format off { sizeof(magic_zstd), KMOD_FILE_COMPRESSION_ZSTD, magic_zstd, kmod_file_load_zstd }, { sizeof(magic_xz), KMOD_FILE_COMPRESSION_XZ, magic_xz, kmod_file_load_xz }, { sizeof(magic_zlib), KMOD_FILE_COMPRESSION_ZLIB, magic_zlib, kmod_file_load_zlib }, { 0, KMOD_FILE_COMPRESSION_NONE, NULL, load_reg }, // clang-format on }; int kmod_file_open(const struct kmod_ctx *ctx, const char *filename, struct kmod_file **out_file) { _cleanup_free_ struct kmod_file *file; char buf[7]; ssize_t sz; int ret; assert_cc(sizeof(magic_zstd) < sizeof(buf)); assert_cc(sizeof(magic_xz) < sizeof(buf)); assert_cc(sizeof(magic_zlib) < sizeof(buf)); file = calloc(1, sizeof(struct kmod_file)); if (file == NULL) { file = NULL; return -ENOMEM; } file->fd = open(filename, O_RDONLY | O_CLOEXEC); if (file->fd < 0) return -errno; /* * Bail out if underlying fd is not seekable - that is not supported */ ret = lseek(file->fd, 0, SEEK_CUR); if (ret < 0) return ret; sz = pread_str_safe(file->fd, buf, sizeof(buf), 0); if (sz != (sizeof(buf) - 1)) { if (sz < 0) ret = (int)sz; else ret = -EINVAL; close(file->fd); return ret; } for (unsigned int i = 0; i < ARRAY_SIZE(comp_types); i++) { const struct comp_type *itr = &comp_types[i]; file->load = itr->load; file->compression = itr->compression; if (itr->magic_size && memcmp(buf, itr->magic_bytes, itr->magic_size) == 0) { break; } } file->ctx = ctx; *out_file = file; file = NULL; return 0; } int kmod_file_get_contents(const struct kmod_file *file, const void **contents, off_t *size) { if (!file->memory) { int ret = file->load((struct kmod_file *)file); /* The load functions already log possible errors. */ if (ret) return ret; } *contents = file->memory; *size = file->size; return 0; } enum kmod_file_compression_type kmod_file_get_compression(const struct kmod_file *file) { return file->compression; } int kmod_file_get_fd(const struct kmod_file *file) { return file->fd; } void kmod_file_unref(struct kmod_file *file) { if (file->compression == KMOD_FILE_COMPRESSION_NONE) { if (file->memory) munmap(file->memory, file->size); } else { free(file->memory); } close(file->fd); free(file); }