Skip to content

Commit

Permalink
Refactored and unit-tested filter_special_opts. Shaved a bunch of yak…
Browse files Browse the repository at this point in the history
…s on the way.
  • Loading branch information
mpartel committed Feb 13, 2021
1 parent 2cf41a7 commit bc5313d
Show file tree
Hide file tree
Showing 15 changed files with 413 additions and 156 deletions.
10 changes: 8 additions & 2 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,14 @@ fi

AM_CONDITIONAL(BUILD_OS_IS_DARWIN, [test x"$build_os" = darwin])

my_CPPFLAGS="-D_REENTRANT -D_FILE_OFFSET_BITS=64"
my_CFLAGS="-Wall -fno-common"
# _XOPEN_SOURCE is >= 500 for pread/pwrite; >= 700 for utimensat.
# __BSD_VISIBLE is for flock() on FreeBSD. It otherwise gets hidden by _XOPEN_SOURCE.
# _BSD_SOURCE is for stat() nanosecond precision and lutimes().
# _DEFAULT_SOURCE is the new non-deprecated version of _BSD_SOURCE.
# _DARWIN_BETTER_REALPATH fixes MacOS realpath() broken around Catalina (#83).
my_CPPFLAGS="-D_REENTRANT -D_FILE_OFFSET_BITS=64 -D_XOPEN_SOURCE=700 -D__BSD_VISIBLE=1 -D_BSD_SOURCE -D_DEFAULT_SOURCE -D_DARWIN_BETTER_REALPATH"

my_CFLAGS="-Wall -fno-common -std=c99"
my_LDFLAGS="-pthread"
AC_SUBST([my_CPPFLAGS])
AC_SUBST([my_CFLAGS])
Expand Down
4 changes: 2 additions & 2 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

bin_PROGRAMS = bindfs

noinst_HEADERS = debug.h permchain.h userinfo.h misc.h usermap.h rate_limiter.h
bindfs_SOURCES = bindfs.c debug.c permchain.c userinfo.c misc.c usermap.c rate_limiter.c
noinst_HEADERS = debug.h permchain.h userinfo.h arena.h misc.h usermap.h rate_limiter.h
bindfs_SOURCES = bindfs.c debug.c permchain.c userinfo.c arena.c misc.c usermap.c rate_limiter.c

AM_CPPFLAGS = ${my_CPPFLAGS} ${fuse_CFLAGS} ${fuse3_CFLAGS}
AM_CFLAGS = ${my_CFLAGS}
Expand Down
50 changes: 50 additions & 0 deletions src/arena.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#include "arena.h"

struct block {
size_t size;
size_t used;
struct block *next;
char data_start[];
};

static const size_t min_block_room = 16 * 1024 - sizeof(struct block);

static void add_block(struct arena* a, size_t room_wanted)
{
if (room_wanted < min_block_room) {
room_wanted = min_block_room;
}
struct block *new_block = malloc(sizeof(struct block) + room_wanted);
new_block->size = room_wanted;
new_block->used = 0;
new_block->next = a->cur_block;
a->cur_block = new_block;
}

void arena_init(struct arena *a)
{
a->cur_block = NULL;
}

void* arena_malloc(struct arena *a, size_t amount)
{
struct block* b = a->cur_block;
if (b == NULL || b->size - b->used < amount) {
add_block(a, amount);
b = a->cur_block;
}
void* result = &b->data_start[b->used];
b->used += amount;
return result;
}

void arena_free(struct arena *a)
{
struct block* b = a->cur_block;
while (b != NULL) {
struct block* next = b->next;
free(b);
b = next;
}
a->cur_block = NULL;
}
15 changes: 15 additions & 0 deletions src/arena.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#ifndef INC_BINDFS_ARENA_H
#define INC_BINDFS_ARENA_H

#include <stdlib.h>

struct block;
struct arena {
struct block *cur_block;
};

void arena_init(struct arena *a);
void* arena_malloc(struct arena *a, size_t amount);
void arena_free(struct arena *a);

#endif
150 changes: 26 additions & 124 deletions src/bindfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,20 +31,6 @@

#include <config.h>

/* For >= 500 for pread/pwrite; >= 700 for utimensat */
#define _XOPEN_SOURCE 700

/* For flock() on FreeBSD. It otherwise gets hidden by _XOPEN_SOURCE */
#define __BSD_VISIBLE 1

/* For stat() nanosecond precision and lutimes() */
#define _BSD_SOURCE
/* The new non-deprecated version of _BSD_SOURCE */
#define _DEFAULT_SOURCE

/* Fix MacOS realpath() broken around Catalina (#83) */
#define _DARWIN_BETTER_REALPATH

#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
Expand Down Expand Up @@ -97,6 +83,7 @@
#include <fuse.h>
#include <fuse_opt.h>

#include "arena.h"
#include "debug.h"
#include "misc.h"
#include "permchain.h"
Expand Down Expand Up @@ -367,6 +354,7 @@ Why? Because some of those options like "nofail"
are special ones interpreted by systemd in /etc/fstab
*/
struct fuse_args filter_special_opts(struct fuse_args *args);
static bool keep_option(const char* opt);

static int is_mirroring_enabled()
{
Expand Down Expand Up @@ -2085,8 +2073,8 @@ static int parse_map_file(UserMap *map, UserMap *reverse_map, char *file, int as
UsermapStatus status;

// Toggle between UID (passwd) and GID (group)
const int (*value_to_id)(const char *username, uid_t *ret);
const UsermapStatus (*usermap_add)(UserMap *map, uid_t from, uid_t to);
int (*value_to_id)(const char *username, uid_t *ret);
UsermapStatus (*usermap_add)(UserMap *map, uid_t from, uid_t to);
const char *label_name, *label_id;
if (as_gid) {
value_to_id = &group_gid;
Expand Down Expand Up @@ -2336,11 +2324,27 @@ static void atexit_func()

struct fuse_args filter_special_opts(struct fuse_args *args)
{
bool ignore;
struct arena arena;
arena_init(&arena);
int tmp_argc = args->argc;
char **tmp_argv;

filter_o_opts(&keep_option, args->argc, (const char * const *)args->argv, &tmp_argc, &tmp_argv, &arena);

struct fuse_args new_args = FUSE_ARGS_INIT(0, (void*)0);
for (int i = 0; i < tmp_argc; i++) {
fuse_opt_add_arg(&new_args, tmp_argv[i]);
}

arena_free(&arena);
fuse_opt_free_args(args);
return new_args;
}

static bool keep_option(const char* opt)
{
// Copied from "libfuse/util/mount.fuse.c" (fuse-3.10.1)
const char *ignore_opts[] = {
static const char * const ignored_opts[] = {
"",
"user",
"nofail",
Expand All @@ -2352,114 +2356,12 @@ struct fuse_args filter_special_opts(struct fuse_args *args)
NULL
};

for (int i = 0; i < args->argc; i++) {
ignore = false;

/* If current element is exactly "-o" modify/check the following element */
if (strcmp(args->argv[i], "-o") == 0 && (i+1) < args->argc) {

/* remove ignored option from a comma separated list */
if (strchr(args->argv[i+1], ',') != NULL) {
char *tmpStr = (char*) calloc(strlen(args->argv[i+1]) + 1, sizeof(char));
char *ptr = strtok(args->argv[i+1], ",");
while (ptr != NULL) {
ignore = false;
for (int j = 0; ignore_opts[j]; j++) {
if (strcmp(ptr, ignore_opts[j]) == 0) {
ignore = true;
break;
}
}
if (!ignore) {
if (strlen(tmpStr) > 0) strcat(tmpStr, ",");
strcat(tmpStr, ptr);
}
ptr = strtok(NULL, ",");
}
if (strlen(tmpStr) > 0) {
args->argv[i+1] = (char*) calloc(strlen(tmpStr) + 1, sizeof(char));
strcpy(args->argv[i+1], tmpStr);
free(tmpStr);
ignore = false;
}
else {
ignore = true;
++i;
}
}

/* ignore this and the following element if it has exactly the ignored option */
else {
for (int j = 0; ignore_opts[j]; j++) {
if (strcmp(args->argv[i+1], ignore_opts[j]) == 0) {
ignore = true;
++i;
break;
}
}
}
}

/* else if element starts with "-o" */
else if (strncmp(args->argv[i], "-o", 2) == 0) {

/* remove ignored option from a comma seperated list */
if (strchr(args->argv[i], ',') != NULL) {
char *tmpStr = (char*) calloc(strlen(args->argv[i]) + 1, sizeof(char));
char *tmpStr2 = (char*) calloc(strlen(args->argv[i]) + 1 - 2, sizeof(char));
// remove first 2 chars from args->argv[i] and save this to tmpStr2
memcpy(tmpStr2, args->argv[i] + 2, strlen(args->argv[i]) - 2);
char *ptr = strtok(tmpStr2, ",");
while (ptr != NULL) {
ignore = false;
for (int j = 0; ignore_opts[j]; j++) {
if (strcmp(ptr, ignore_opts[j]) == 0) {
ignore = true;
break;
}
}
if (!ignore) {
if (strlen(tmpStr) > 0) strcat(tmpStr, ",");
strcat(tmpStr, ptr);
}
ptr = strtok(NULL, ",");
}
if (strlen(tmpStr) > 0) {
args->argv[i] = (char*) calloc(2 + strlen(tmpStr) + 1, sizeof(char));
strcat(args->argv[i], "-o");
strcat(args->argv[i], tmpStr);
free(tmpStr);
free(tmpStr2);
ignore = false;
}
else {
ignore = true;
}
}

/* ignore this element if it has exactly the ignored option */
else {
for (int j = 0; ignore_opts[j]; j++) {
char* tmpStr = (char*) calloc(2 + strlen(ignore_opts[j]) + 1, sizeof(char));
strcat(tmpStr, "-o");
strcat(tmpStr, ignore_opts[j]);
if (strcmp(args->argv[i], tmpStr) == 0) {
ignore = true;
free(tmpStr);
break;
}
free(tmpStr);
}
}
}
if (!ignore) {
fuse_opt_add_arg(&new_args, strdup(args->argv[i]));
for (int i = 0; ignored_opts[i] != NULL; ++i) {
if (strcmp(ignored_opts[i], opt) == 0) {
return false;
}
}

fuse_opt_free_args(args);

return new_args;
return true;
}

int main(int argc, char *argv[])
Expand Down
Loading

0 comments on commit bc5313d

Please sign in to comment.