5 Commits
Author SHA1 Message Date
Konrad Dybcio f803b4d573 meson.build: Set v1.1 version
Signed-off-by: Konrad Dybcio <konrad.dybcio@linaro.org>
2024-07-23 14:22:35 +02:00
Stefan Hansson 0197df8e61 Add support for zstd-compressed readonly files
We need this to load compressed files from linux-firmware.

Closes https://github.com/linux-msm/tqftpserv/issues/19

Signed-off-by: Stefan Hansson <newbyte@postmarketos.org>
Tested-by: Nikita Travkin <nikita@trvn.ru>
2024-07-23 14:20:00 +02:00
Alexey Minnekhanov 47e8957271 meson.build: Make systemd dep optional
Some distros still don't use SystemD (yet), make it optional.

It is not required to build the binary, just to install systemd
unit file.

Signed-off-by: Alexey Minnekhanov <alexey.min@gmail.com>
2024-04-30 23:51:30 +02:00
Konrad Dybcio 5f9f263ae2 treewide: meson 2024-04-23 19:38:37 +02:00
Konrad Dybcio 3a10a7dd6f treewide: use SPDX license IDs 2024-04-08 23:53:19 +02:00
8 changed files with 203 additions and 28 deletions

No files matched your search

-25
View File
@@ -1,25 +0,0 @@
TQFTPSERV := tqftpserv
CFLAGS += -Wall -g -O2
LDFLAGS += -lqrtr
prefix ?= /usr/local
bindir := $(prefix)/bin
servicedir := $(prefix)/lib/systemd/system
SRCS := tqftpserv.c translate.c
OBJS := $(SRCS:.c=.o)
$(TQFTPSERV): $(OBJS)
$(CC) -o $@ $^ $(LDFLAGS)
tqftpserv.service: tqftpserv.service.in
@sed 's+TQFTPSERV_PATH+$(bindir)+g' $< > $@
install: $(TQFTPSERV) tqftpserv.service
@install -D -m 755 $(TQFTPSERV) $(DESTDIR)$(bindir)/$(TQFTPSERV)
@install -D -m 644 tqftpserv.service $(DESTDIR)$(servicedir)/tqftpserv.service
clean:
rm -f $(TQFTPSERV) $(OBJS) tqftpserv.service
+44
View File
@@ -0,0 +1,44 @@
# SPDX-License-Identifier: BSD-3-Clause
project('tqftpserv',
'c',
version: '1.1',
default_options: [
'warning_level=1',
'buildtype=release',
])
prefix = get_option('prefix')
zstd_dep = dependency('libzstd')
# Not required to build the executable, only to install unit file
systemd = dependency('systemd', required : false)
if systemd.found()
systemd_system_unit_dir = get_option('systemd-unit-prefix')
if systemd_system_unit_dir == ''
systemd_system_unit_dir = systemd.get_variable(
pkgconfig : 'systemdsystemunitdir',
pkgconfig_define: ['prefix', prefix])
endif
endif
qrtr_dep = dependency('qrtr')
tqftpserv_srcs = ['translate.c',
'tqftpserv.c',
'zstd-decompress.c']
executable('tqftpserv',
tqftpserv_srcs,
dependencies : [qrtr_dep, zstd_dep],
install : true)
if systemd.found()
systemd_unit_conf = configuration_data()
systemd_unit_conf.set('prefix', prefix)
configure_file(
input : 'tqftpserv.service.in',
output : 'tqftpserv.service',
configuration : systemd_unit_conf,
install_dir : systemd_system_unit_dir)
endif
+4
View File
@@ -0,0 +1,4 @@
option('systemd-unit-prefix',
type: 'string',
description: 'Directory for systemd system unit files'
)
+4
View File
@@ -15,6 +15,7 @@
#include "list.h"
#include "translate.h"
#include "zstd-decompress.h"
#define MAX(x, y) ((x) > (y) ? (x) : (y))
@@ -570,6 +571,8 @@ int main(int argc, char **argv)
exit(1);
}
zstd_init();
for (;;) {
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
@@ -671,6 +674,7 @@ int main(int argc, char **argv)
}
close(fd);
zstd_free();
return 0;
}
+1 -1
View File
@@ -4,7 +4,7 @@ Requires=qrtr-ns.service
After=qrtr-ns.service
[Service]
ExecStart=TQFTPSERV_PATH/tqftpserv
ExecStart=@prefix@/bin/tqftpserv
Restart=always
[Install]
+31 -2
View File
@@ -16,6 +16,7 @@
#include <unistd.h>
#include "translate.h"
#include "zstd-decompress.h"
#define READONLY_PATH "/readonly/firmware/image/"
#define READWRITE_PATH "/readwrite/"
@@ -28,6 +29,8 @@
#define TQFTPSERV_TMP "/data/vendor/tmp/tqftpserv"
#endif
static int open_maybe_compressed(const char *path);
static void read_fw_path_from_sysfs(char *outbuffer, size_t bufsize)
{
size_t pathsize;
@@ -118,7 +121,7 @@ static int translate_readonly(const char *file)
strcat(path, "/");
strcat(path, file);
fd = open(path, O_RDONLY);
fd = open_maybe_compressed(path);
if (fd >= 0)
break;
if (errno != ENOENT)
@@ -135,7 +138,8 @@ static int translate_readonly(const char *file)
strcat(path, "/");
strcat(path, file);
fd = open(path, O_RDONLY);
fd = open_maybe_compressed(path);
if (fd >= 0)
break;
@@ -201,3 +205,28 @@ int translate_open(const char *path, int flags)
errno = ENOENT;
return -1;
}
/* linux-firmware uses .zst as file extension */
#define ZSTD_EXTENSION ".zst"
/**
* open_maybe_compressed() - open a file and maybe decompress it if necessary
* @filename: path to a file that may be compressed (should not include compression format extension)
*
* Return: opened fd on success, -1 on error
*/
static int open_maybe_compressed(const char *path)
{
int fd = -1;
if (access(path, F_OK) == 0) {
fd = open(path, O_RDONLY);
} else {
char *path_with_zstd_extension = NULL;
asprintf(&path_with_zstd_extension, "%s%s", path, ZSTD_EXTENSION);
fd = zstd_decompress_file(path_with_zstd_extension);
free(path_with_zstd_extension);
}
return fd;
}
+104
View File
@@ -0,0 +1,104 @@
// SPDX-License-Identifier: BSD-3-Clause
/*
* Copyright (c) 2024, Stefan Hansson
*/
/* For memfd_create */
#define _GNU_SOURCE
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <zstd.h>
#include "zstd-decompress.h"
static ZSTD_DCtx *zstd_context = NULL;
/**
* zstd_init() - set up state for decompression. Needs to be called before zstd_decompress_file()
*/
void zstd_init()
{
zstd_context = ZSTD_createDCtx();
}
/**
* zstd_free() - free state used for decompression. zstd_decompress_file() may not be called after this
*/
void zstd_free()
{
ZSTD_freeDCtx(zstd_context);
}
/**
* zstd_decompress_file() - decompress a zstd-compressed file
* @filename: path to a file to decompress
*
* Return: opened fd on success, -1 on error
*/
int zstd_decompress_file(const char *filename)
{
/* Figure out the size of the file. */
struct stat file_stat;
if (stat(filename, &file_stat) == -1) {
perror("stat failed");
return -1;
}
const size_t file_size = file_stat.st_size;
const int input_file_fd = open(filename, 0);
if (input_file_fd == -1) {
perror("open failed");
return -1;
}
void* const compressed_buffer = mmap(NULL, file_size, PROT_READ, MAP_POPULATE | MAP_PRIVATE, input_file_fd, 0);
if (compressed_buffer == MAP_FAILED) {
perror("mmap failed");
close(input_file_fd);
return -1;
}
close(input_file_fd);
const unsigned long long decompressed_size = ZSTD_getFrameContentSize(compressed_buffer, file_size);
if (decompressed_size == ZSTD_CONTENTSIZE_UNKNOWN) {
fprintf(stderr, "Content size could not be determined for %s\n", filename);
return -1;
}
if (decompressed_size == ZSTD_CONTENTSIZE_ERROR) {
fprintf(stderr, "Error getting content size for %s\n", filename);
return -1;
}
void* const decompressed_buffer = malloc((size_t)decompressed_size);
if (decompressed_buffer == NULL) {
perror("malloc failed");
return -1;
}
const size_t return_size = ZSTD_decompressDCtx(zstd_context, decompressed_buffer, decompressed_size, compressed_buffer, file_size);
if (ZSTD_isError(return_size)) {
fprintf(stderr, "ZSTD_decompress failed: %s\n", ZSTD_getErrorName(return_size));
return -1;
}
const int output_file_fd = memfd_create(filename, 0);
if (output_file_fd == -1) {
perror("memfd_create failed");
return -1;
}
if (write(output_file_fd, decompressed_buffer, decompressed_size) != decompressed_size) {
perror("write failed");
close(output_file_fd);
return -1;
}
return output_file_fd;
}
+15
View File
@@ -0,0 +1,15 @@
// SPDX-License-Identifier: BSD-3-Clause
/*
* Copyright (c) 2024, Stefan Hansson
*/
#ifndef __ZSTD_DECOMPRESS_H__
#define __ZSTD_DECOMPRESS_H__
#include <stdbool.h>
void zstd_init();
void zstd_free();
int zstd_decompress_file(const char *filename);
#endif