2020-12-01 01:01:56 +01:00
|
|
|
// This file should rarely need to be changed. (which is intentional,
|
|
|
|
// because it is a pain to program here, it's a pain to recompile and
|
2021-01-04 13:30:32 +01:00
|
|
|
// reload it, and it's a pain to debug it.) Most of the behavior of
|
|
|
|
// TabFS -- the definitions of the synthetic files -- lives on the
|
|
|
|
// extension side, not here.
|
2020-12-01 01:01:56 +01:00
|
|
|
|
2019-02-25 22:02:25 +01:00
|
|
|
#include <stdlib.h>
|
2021-01-03 04:58:54 +01:00
|
|
|
#include <stdio.h>
|
2021-01-03 11:23:20 +01:00
|
|
|
#include <unistd.h>
|
2019-02-25 22:02:25 +01:00
|
|
|
#include <pthread.h>
|
2021-01-03 11:23:20 +01:00
|
|
|
#include <string.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <assert.h>
|
|
|
|
|
2019-02-25 22:02:25 +01:00
|
|
|
#include <fuse.h>
|
|
|
|
|
2020-12-28 03:20:34 +01:00
|
|
|
#include "vendor/frozen.h"
|
|
|
|
#include "vendor/frozen.c"
|
2020-12-02 06:46:21 +01:00
|
|
|
|
2021-01-03 11:23:20 +01:00
|
|
|
#define eprintln(fmt, ...) fprintf(stderr, fmt "\n", ##__VA_ARGS__)
|
|
|
|
|
|
|
|
// protects:
|
|
|
|
// - writing to stdout
|
|
|
|
// - the "waiters" global
|
|
|
|
static pthread_mutex_t write_lock = PTHREAD_MUTEX_INITIALIZER;
|
|
|
|
|
|
|
|
struct resumedata {
|
|
|
|
unsigned int id;
|
|
|
|
int msgpipe[2];
|
|
|
|
void *data;
|
|
|
|
size_t size;
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct resumedata **waiters;
|
|
|
|
static size_t numwaiters;
|
|
|
|
|
|
|
|
static void read_or_die(int fd, void *buf, size_t sz) {
|
|
|
|
size_t sofar = 0;
|
|
|
|
while (sofar < sz) {
|
|
|
|
ssize_t rv = read(fd, (char *)buf+sofar, sz-sofar);
|
|
|
|
if (rv == -1) {
|
|
|
|
if (errno == EINTR || errno == EAGAIN) continue;
|
|
|
|
perror("read error");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
if (rv == 0) exit(1);
|
|
|
|
sofar += (size_t)rv;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
static void write_or_die(int fd, void *buf, size_t sz) {
|
|
|
|
size_t sofar = 0;
|
|
|
|
while (sofar < sz) {
|
|
|
|
ssize_t rv = write(fd, (char *)buf+sofar, sz-sofar);
|
|
|
|
if (rv == -1) {
|
|
|
|
if (errno == EINTR || errno == EAGAIN) continue;
|
|
|
|
perror("write error");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
if (rv == 0) exit(1);
|
|
|
|
sofar += (size_t)rv;
|
|
|
|
}
|
|
|
|
}
|
2020-11-23 05:52:26 +01:00
|
|
|
|
2021-01-03 11:23:20 +01:00
|
|
|
// documented somewhere in https://developer.chrome.com/docs/apps/nativeMessaging/
|
2021-01-04 10:40:22 +01:00
|
|
|
#define MAX_MESSAGE_SIZE (size_t)(1024*1024)
|
2020-12-02 06:46:21 +01:00
|
|
|
|
2021-01-03 11:23:20 +01:00
|
|
|
static int do_exchange(unsigned int id,
|
|
|
|
char **datap, size_t *sizep,
|
|
|
|
const char *fmt, ...) {
|
|
|
|
*datap = NULL;
|
|
|
|
*sizep = 0;
|
2020-12-02 06:46:21 +01:00
|
|
|
|
2021-01-04 10:40:22 +01:00
|
|
|
char *jsonbuf = malloc(MAX_MESSAGE_SIZE);
|
|
|
|
struct json_out out = JSON_OUT_BUF(jsonbuf, MAX_MESSAGE_SIZE);
|
2020-12-02 06:46:21 +01:00
|
|
|
|
2021-01-03 11:23:20 +01:00
|
|
|
va_list args;
|
|
|
|
va_start(args, fmt);
|
|
|
|
size_t request_size = (size_t)json_vprintf(&out, fmt, args);
|
2020-12-02 06:46:21 +01:00
|
|
|
va_end(args);
|
2021-01-04 10:40:22 +01:00
|
|
|
if (request_size > MAX_MESSAGE_SIZE) {
|
2021-01-03 11:23:20 +01:00
|
|
|
eprintln("warning: request too big to send (%zu > %zu)",
|
2021-01-04 10:40:22 +01:00
|
|
|
request_size, MAX_MESSAGE_SIZE);
|
|
|
|
free(jsonbuf);
|
2021-01-03 11:23:20 +01:00
|
|
|
return -EMSGSIZE;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct resumedata mydata = {
|
|
|
|
.id = id,
|
|
|
|
.msgpipe = {-1, -1},
|
|
|
|
.data = NULL,
|
|
|
|
.size = 0,
|
|
|
|
};
|
|
|
|
if (-1 == pipe(mydata.msgpipe)) {
|
|
|
|
perror("exchange: pipe");
|
2021-01-04 10:40:22 +01:00
|
|
|
free(jsonbuf);
|
2021-01-03 11:23:20 +01:00
|
|
|
return -EIO;
|
|
|
|
}
|
|
|
|
|
|
|
|
pthread_mutex_lock(&write_lock);
|
2020-12-02 06:46:21 +01:00
|
|
|
|
2021-01-03 11:23:20 +01:00
|
|
|
uint32_t size_4bytes = request_size;
|
|
|
|
|
|
|
|
write_or_die(STDOUT_FILENO, &size_4bytes, sizeof(size_4bytes));
|
|
|
|
write_or_die(STDOUT_FILENO, jsonbuf, request_size);
|
2020-12-02 06:46:21 +01:00
|
|
|
|
2021-01-04 10:40:22 +01:00
|
|
|
free(jsonbuf); jsonbuf = NULL;
|
|
|
|
|
2021-01-03 11:23:20 +01:00
|
|
|
waiters = realloc(waiters, (numwaiters+1)*sizeof(*waiters));
|
|
|
|
waiters[numwaiters] = &mydata;
|
|
|
|
numwaiters += 1;
|
|
|
|
|
|
|
|
pthread_mutex_unlock(&write_lock);
|
|
|
|
|
|
|
|
char c;
|
|
|
|
read_or_die(mydata.msgpipe[0], &c, 1);
|
|
|
|
|
|
|
|
close(mydata.msgpipe[0]);
|
|
|
|
close(mydata.msgpipe[1]);
|
|
|
|
|
|
|
|
int err;
|
|
|
|
if (1 == json_scanf(mydata.data, mydata.size, "{error: %d}", &err)) {
|
|
|
|
free(mydata.data);
|
|
|
|
return -err;
|
2020-11-23 05:52:26 +01:00
|
|
|
}
|
2021-01-03 11:23:20 +01:00
|
|
|
|
|
|
|
*datap = mydata.data;
|
|
|
|
*sizep = mydata.size;
|
|
|
|
|
|
|
|
return 0;
|
2020-12-02 06:46:21 +01:00
|
|
|
}
|
2020-10-22 00:53:27 +02:00
|
|
|
|
2021-01-03 11:23:20 +01:00
|
|
|
static void *reader_main(void *ud) {
|
|
|
|
(void)ud;
|
|
|
|
for (;;) {
|
|
|
|
uint32_t size_4bytes;
|
|
|
|
read_or_die(STDIN_FILENO, &size_4bytes, sizeof(size_4bytes));
|
|
|
|
size_t insize = size_4bytes;
|
|
|
|
|
|
|
|
char *data = malloc(insize);
|
|
|
|
read_or_die(STDIN_FILENO, data, insize);
|
|
|
|
|
|
|
|
unsigned int id;
|
|
|
|
if (1 != json_scanf(data, insize, "{id: %u}", &id)) {
|
|
|
|
eprintln("reader: warning: got a message without an id, ignoring");
|
|
|
|
free(data);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
pthread_mutex_lock(&write_lock);
|
|
|
|
int found = 0;
|
|
|
|
unsigned int i = numwaiters;
|
|
|
|
while (i --> 0) {
|
|
|
|
if (waiters[i]->id == id) {
|
|
|
|
char c = '!';
|
|
|
|
waiters[i]->data = data;
|
|
|
|
waiters[i]->size = insize;
|
|
|
|
write_or_die(waiters[i]->msgpipe[1], &c, 1);
|
|
|
|
memmove(&waiters[i], &waiters[i+1],
|
|
|
|
(numwaiters-(i+1))*sizeof(*waiters));
|
|
|
|
numwaiters -= 1;
|
|
|
|
found = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!found) {
|
|
|
|
eprintln("reader: warning: got a message for nonexistent waiter %u", id);
|
|
|
|
free(data);
|
|
|
|
}
|
|
|
|
pthread_mutex_unlock(&write_lock);
|
2020-11-23 05:52:26 +01:00
|
|
|
}
|
2021-01-03 11:23:20 +01:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int count_fmt_args(const char *s) {
|
|
|
|
int cnt = 0;
|
|
|
|
for (; *s; s++) {
|
|
|
|
if (*s == '%') {
|
|
|
|
if (*(s+1) != '%') cnt++;
|
|
|
|
else s++;
|
|
|
|
}
|
2019-02-26 04:29:04 +01:00
|
|
|
}
|
2021-01-03 11:23:20 +01:00
|
|
|
return cnt;
|
|
|
|
}
|
2019-02-25 22:02:25 +01:00
|
|
|
|
2021-01-03 11:23:20 +01:00
|
|
|
#define exchange_json(datap, sizep, keys_fmt, ...) \
|
|
|
|
do { \
|
2021-01-04 10:40:22 +01:00
|
|
|
unsigned int id = (uintptr_t)pthread_self(); \
|
2021-01-03 11:23:20 +01:00
|
|
|
int req_rv = do_exchange(id, datap, sizep, \
|
|
|
|
"{id: %u, " keys_fmt "}", \
|
|
|
|
id, ##__VA_ARGS__); \
|
|
|
|
if (req_rv != 0) return req_rv; \
|
|
|
|
} while (0)
|
2019-02-25 22:02:25 +01:00
|
|
|
|
2021-01-03 11:23:20 +01:00
|
|
|
#define parse_and_free_response(data, size, keys_fmt, ...) \
|
|
|
|
do { \
|
|
|
|
if (*keys_fmt == '\0') { \
|
|
|
|
/* empty format string, skip the work */ \
|
|
|
|
free(data); data = NULL; \
|
|
|
|
} else { \
|
|
|
|
int num_expected = count_fmt_args(keys_fmt); \
|
|
|
|
int num_scanned = json_scanf(data, size, \
|
|
|
|
"{" keys_fmt "}", \
|
|
|
|
##__VA_ARGS__); \
|
|
|
|
if (num_scanned == num_expected) { \
|
|
|
|
free(data); data = NULL; \
|
|
|
|
} else { \
|
|
|
|
eprintln("%s: could only parse %d of %d keys!", \
|
|
|
|
__func__, num_expected, num_scanned); \
|
|
|
|
free(data); data = NULL; \
|
|
|
|
return -EIO; \
|
|
|
|
} \
|
|
|
|
} \
|
2020-12-02 06:46:21 +01:00
|
|
|
} while (0)
|
|
|
|
|
2019-02-26 04:29:04 +01:00
|
|
|
static int tabfs_getattr(const char *path, struct stat *stbuf) {
|
2021-01-03 11:23:20 +01:00
|
|
|
char *rdata;
|
|
|
|
size_t rsize;
|
|
|
|
exchange_json(&rdata, &rsize,
|
|
|
|
"op: %Q, path: %Q",
|
|
|
|
"getattr", path);
|
2020-12-02 06:46:21 +01:00
|
|
|
|
2019-02-25 22:02:25 +01:00
|
|
|
memset(stbuf, 0, sizeof(struct stat));
|
2021-01-03 11:23:20 +01:00
|
|
|
parse_and_free_response(rdata, rsize,
|
|
|
|
"st_mode: %d, st_nlink: %d, st_size: %d",
|
|
|
|
&stbuf->st_mode, &stbuf->st_nlink, &stbuf->st_size);
|
|
|
|
|
2020-12-02 06:46:21 +01:00
|
|
|
return 0;
|
2019-02-25 22:02:25 +01:00
|
|
|
}
|
|
|
|
|
2019-02-26 04:29:04 +01:00
|
|
|
static int tabfs_readlink(const char *path, char *buf, size_t size) {
|
2021-01-03 11:23:20 +01:00
|
|
|
char *rdata;
|
|
|
|
size_t rsize;
|
|
|
|
exchange_json(&rdata, &rsize,
|
|
|
|
"op: %Q, path: %Q",
|
|
|
|
"readlink", path);
|
2020-12-02 06:46:21 +01:00
|
|
|
|
2021-01-03 11:23:20 +01:00
|
|
|
char *scan_buf;
|
|
|
|
int scan_len;
|
|
|
|
parse_and_free_response(rdata, rsize,
|
|
|
|
"buf: %V",
|
|
|
|
&scan_buf, &scan_len);
|
|
|
|
|
|
|
|
// fuse.h:
|
|
|
|
// "If the linkname is too long to fit in the buffer, it should be truncated."
|
|
|
|
if ((size_t)scan_len >= size) scan_len = size-1;
|
|
|
|
|
|
|
|
memcpy(buf, scan_buf, scan_len);
|
|
|
|
buf[scan_len] = '\0';
|
|
|
|
|
|
|
|
free(scan_buf);
|
2020-12-02 06:46:21 +01:00
|
|
|
|
|
|
|
return 0;
|
2019-02-25 22:02:25 +01:00
|
|
|
}
|
|
|
|
|
2019-02-26 04:29:04 +01:00
|
|
|
static int tabfs_open(const char *path, struct fuse_file_info *fi) {
|
2021-01-03 11:23:20 +01:00
|
|
|
char *data;
|
|
|
|
size_t size;
|
|
|
|
exchange_json(&data, &size,
|
|
|
|
"op: %Q, path: %Q, flags: %d",
|
|
|
|
"open", path, fi->flags);
|
2020-12-02 06:46:21 +01:00
|
|
|
|
2021-01-03 11:23:20 +01:00
|
|
|
parse_and_free_response(data, size,
|
2021-01-12 08:25:42 +01:00
|
|
|
"fh: %llu",
|
2021-01-03 11:23:20 +01:00
|
|
|
&fi->fh);
|
2020-12-02 06:46:21 +01:00
|
|
|
|
|
|
|
return 0;
|
2019-02-25 22:02:25 +01:00
|
|
|
}
|
|
|
|
|
2021-01-03 11:23:20 +01:00
|
|
|
static int tabfs_read(const char *path,
|
|
|
|
char *buf,
|
|
|
|
size_t size,
|
|
|
|
off_t offset,
|
|
|
|
struct fuse_file_info *fi) {
|
|
|
|
char *rdata;
|
|
|
|
size_t rsize;
|
|
|
|
exchange_json(&rdata, &rsize,
|
2021-01-12 09:17:34 +01:00
|
|
|
"op: %Q, path: %Q, size: %d, offset: %lld, fh: %llu, flags: %d",
|
2021-01-03 11:23:20 +01:00
|
|
|
"read", path, size, offset, fi->fh, fi->flags);
|
2020-12-02 06:46:21 +01:00
|
|
|
|
2020-12-03 05:24:20 +01:00
|
|
|
char *scan_buf; int scan_len;
|
2021-01-03 11:23:20 +01:00
|
|
|
parse_and_free_response(rdata, rsize,
|
|
|
|
"buf: %V",
|
|
|
|
&scan_buf, &scan_len);
|
|
|
|
|
|
|
|
if ((size_t)scan_len > size) scan_len = size;
|
|
|
|
memcpy(buf, scan_buf, scan_len);
|
|
|
|
free(scan_buf);
|
2020-12-02 06:46:21 +01:00
|
|
|
|
2020-12-03 05:24:20 +01:00
|
|
|
return scan_len;
|
2019-02-25 22:02:25 +01:00
|
|
|
}
|
|
|
|
|
2021-01-03 11:23:20 +01:00
|
|
|
static int tabfs_write(const char *path,
|
|
|
|
const char *data,
|
|
|
|
size_t size,
|
|
|
|
off_t offset,
|
|
|
|
struct fuse_file_info *fi) {
|
|
|
|
char *rdata;
|
|
|
|
size_t rsize;
|
|
|
|
exchange_json(&rdata, &rsize,
|
2021-01-12 09:17:34 +01:00
|
|
|
"op: %Q, path: %Q, buf: %V, offset: %lld, fh: %llu, flags: %d",
|
2021-01-03 11:23:20 +01:00
|
|
|
"write", path, data, size, offset, fi->fh, fi->flags);
|
|
|
|
|
|
|
|
int ret;
|
|
|
|
parse_and_free_response(rdata, rsize,
|
|
|
|
"size: %d",
|
|
|
|
&ret);
|
|
|
|
|
|
|
|
return ret;
|
2019-03-02 21:16:08 +01:00
|
|
|
}
|
|
|
|
|
2019-02-25 22:02:25 +01:00
|
|
|
static int tabfs_release(const char *path, struct fuse_file_info *fi) {
|
2021-01-03 11:23:20 +01:00
|
|
|
char *data;
|
|
|
|
size_t size;
|
|
|
|
exchange_json(&data, &size,
|
2021-01-12 08:25:42 +01:00
|
|
|
"op: %Q, path: %Q, fh: %llu",
|
2021-01-03 11:23:20 +01:00
|
|
|
"release", path, fi->fh);
|
|
|
|
|
|
|
|
parse_and_free_response(data, size, "");
|
2020-12-02 06:46:21 +01:00
|
|
|
|
|
|
|
return 0;
|
2019-02-25 22:02:25 +01:00
|
|
|
}
|
|
|
|
|
2019-02-26 04:29:04 +01:00
|
|
|
static int tabfs_opendir(const char *path, struct fuse_file_info *fi) {
|
2021-01-03 11:23:20 +01:00
|
|
|
char *rdata;
|
|
|
|
size_t rsize;
|
|
|
|
exchange_json(&rdata, &rsize,
|
|
|
|
"op: %Q, path: %Q, flags: %d",
|
|
|
|
"opendir", path, fi->flags);
|
|
|
|
|
|
|
|
parse_and_free_response(rdata, rsize,
|
2021-01-12 08:25:42 +01:00
|
|
|
"fh: %llu",
|
2021-01-03 11:23:20 +01:00
|
|
|
&fi->fh);
|
|
|
|
|
2020-12-02 06:46:21 +01:00
|
|
|
return 0;
|
2019-02-25 22:02:25 +01:00
|
|
|
}
|
|
|
|
|
2021-01-03 11:23:20 +01:00
|
|
|
static int tabfs_readdir(const char *path,
|
|
|
|
void *buf,
|
|
|
|
fuse_fill_dir_t filler,
|
|
|
|
off_t offset,
|
|
|
|
struct fuse_file_info *fi) {
|
|
|
|
(void)fi;
|
2020-12-02 06:46:21 +01:00
|
|
|
|
2021-01-03 11:23:20 +01:00
|
|
|
char *rdata;
|
|
|
|
size_t rsize;
|
|
|
|
exchange_json(&rdata, &rsize,
|
2021-01-12 09:17:34 +01:00
|
|
|
"op: %Q, path: %Q, offset: %lld",
|
2021-01-03 11:23:20 +01:00
|
|
|
"readdir", path, offset);
|
2020-12-02 06:46:21 +01:00
|
|
|
|
|
|
|
struct json_token t;
|
2021-01-03 11:23:20 +01:00
|
|
|
for (int i = 0; json_scanf_array_elem(rdata, rsize, ".entries", i, &t) > 0; i++) {
|
|
|
|
char entry[t.len+1];
|
|
|
|
memcpy(entry, t.ptr, t.len);
|
|
|
|
entry[t.len] = '\0';
|
2020-12-02 06:46:21 +01:00
|
|
|
filler(buf, entry, NULL, 0);
|
|
|
|
}
|
|
|
|
|
2021-01-03 11:23:20 +01:00
|
|
|
parse_and_free_response(rdata, rsize, "");
|
|
|
|
|
2020-12-02 06:46:21 +01:00
|
|
|
return 0;
|
2019-02-25 22:02:25 +01:00
|
|
|
}
|
|
|
|
|
2020-12-19 08:54:36 +01:00
|
|
|
static int tabfs_releasedir(const char *path, struct fuse_file_info *fi) {
|
2021-01-03 11:23:20 +01:00
|
|
|
char *rdata;
|
|
|
|
size_t rsize;
|
|
|
|
exchange_json(&rdata, &rsize,
|
2021-01-12 08:25:42 +01:00
|
|
|
"op: %Q, path: %Q, fh: %llu",
|
2021-01-03 11:23:20 +01:00
|
|
|
"releasedir", path, fi->fh);
|
|
|
|
|
|
|
|
parse_and_free_response(rdata, rsize, "");
|
2020-12-02 06:46:21 +01:00
|
|
|
|
2020-12-19 08:54:36 +01:00
|
|
|
return 0;
|
|
|
|
}
|
2020-12-02 06:46:21 +01:00
|
|
|
|
2020-12-19 08:54:36 +01:00
|
|
|
static int tabfs_truncate(const char *path, off_t size) {
|
2021-01-03 11:23:20 +01:00
|
|
|
char *rdata;
|
|
|
|
size_t rsize;
|
|
|
|
exchange_json(&rdata, &rsize,
|
2021-01-12 09:30:29 +01:00
|
|
|
"op: %Q, path: %Q, size: %lld",
|
2021-01-03 11:23:20 +01:00
|
|
|
"truncate", path, size);
|
|
|
|
|
|
|
|
parse_and_free_response(rdata, rsize, "");
|
2020-12-19 08:54:36 +01:00
|
|
|
|
2020-12-02 06:46:21 +01:00
|
|
|
return 0;
|
2019-02-25 22:02:25 +01:00
|
|
|
}
|
|
|
|
|
2020-12-14 07:02:29 +01:00
|
|
|
static int tabfs_unlink(const char *path) {
|
2021-01-03 11:23:20 +01:00
|
|
|
char *rdata;
|
|
|
|
size_t rsize;
|
|
|
|
exchange_json(&rdata, &rsize,
|
|
|
|
"op: %Q, path: %Q",
|
|
|
|
"unlink", path);
|
|
|
|
|
|
|
|
parse_and_free_response(rdata, rsize, "");
|
2020-12-14 07:02:29 +01:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-01-01 02:33:11 +01:00
|
|
|
static int tabfs_mkdir(const char *path, mode_t mode) {
|
2021-01-03 11:23:20 +01:00
|
|
|
char *rdata;
|
|
|
|
size_t rsize;
|
|
|
|
exchange_json(&rdata, &rsize,
|
|
|
|
"op: %Q, path: %Q, mode: %d",
|
|
|
|
"mkdir", path, mode);
|
|
|
|
|
|
|
|
parse_and_free_response(rdata, rsize, "");
|
2021-01-01 02:33:11 +01:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-02-26 00:41:21 +01:00
|
|
|
static int tabfs_mknod(const char *path, mode_t mode, dev_t rdev) {
|
|
|
|
(void)rdev;
|
2021-01-03 11:23:20 +01:00
|
|
|
|
|
|
|
char *rdata;
|
|
|
|
size_t rsize;
|
|
|
|
exchange_json(&rdata, &rsize,
|
|
|
|
"op: %Q, path: %Q, mode: %d",
|
2021-02-26 00:41:21 +01:00
|
|
|
"mknod", path, mode);
|
2021-01-03 11:23:20 +01:00
|
|
|
|
|
|
|
parse_and_free_response(rdata, rsize, "");
|
2021-01-01 02:33:11 +01:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-01-03 11:23:20 +01:00
|
|
|
static const struct fuse_operations tabfs_oper = {
|
2021-01-01 02:33:11 +01:00
|
|
|
.getattr = tabfs_getattr,
|
2019-02-25 22:02:25 +01:00
|
|
|
.readlink = tabfs_readlink,
|
2020-12-14 07:02:29 +01:00
|
|
|
|
2021-01-03 11:23:20 +01:00
|
|
|
.open = tabfs_open,
|
|
|
|
.read = tabfs_read,
|
|
|
|
.write = tabfs_write,
|
|
|
|
.release = tabfs_release,
|
2019-02-25 22:02:25 +01:00
|
|
|
|
2021-01-03 11:23:20 +01:00
|
|
|
.opendir = tabfs_opendir,
|
|
|
|
.readdir = tabfs_readdir,
|
2020-12-14 07:02:29 +01:00
|
|
|
.releasedir = tabfs_releasedir,
|
|
|
|
|
2021-01-03 11:23:20 +01:00
|
|
|
.truncate = tabfs_truncate,
|
|
|
|
.unlink = tabfs_unlink,
|
2021-01-01 02:33:11 +01:00
|
|
|
|
2021-01-03 11:23:20 +01:00
|
|
|
.mkdir = tabfs_mkdir,
|
2021-02-26 00:41:21 +01:00
|
|
|
.mknod = tabfs_mknod,
|
2019-02-25 22:02:25 +01:00
|
|
|
};
|
|
|
|
|
2020-11-23 05:52:26 +01:00
|
|
|
int main(int argc, char **argv) {
|
2021-01-03 11:23:20 +01:00
|
|
|
(void)argc;
|
2021-01-05 02:17:07 +01:00
|
|
|
if (NULL == getenv("TABFS_MOUNT_DIR")) {
|
|
|
|
setenv("TABFS_MOUNT_DIR", "mnt", 1);
|
2021-01-03 04:58:54 +01:00
|
|
|
}
|
|
|
|
|
2021-01-03 11:23:20 +01:00
|
|
|
freopen("log.txt", "a", stderr);
|
|
|
|
setvbuf(stderr, NULL, _IONBF, 0);
|
|
|
|
|
|
|
|
char killcmd[128];
|
|
|
|
sprintf(killcmd, "pgrep tabfs | grep -v %d | xargs kill -9 2>/dev/null", getpid());
|
2020-10-22 15:47:00 +02:00
|
|
|
system(killcmd);
|
2021-01-03 04:58:54 +01:00
|
|
|
|
2021-01-03 11:23:20 +01:00
|
|
|
#if defined(__APPLE__)
|
2021-01-05 02:17:07 +01:00
|
|
|
system("diskutil umount force \"$TABFS_MOUNT_DIR\" >/dev/null");
|
2021-01-03 11:23:20 +01:00
|
|
|
#elif defined(__FreeBSD__)
|
2021-01-05 02:17:07 +01:00
|
|
|
system("umount -f \"$TABFS_MOUNT_DIR\" 2>/dev/null");
|
2020-10-28 04:53:39 +01:00
|
|
|
#else
|
2021-01-05 02:17:07 +01:00
|
|
|
system("fusermount -u \"$TABFS_MOUNT_DIR\" 2>/dev/null");
|
2020-10-28 04:53:39 +01:00
|
|
|
#endif
|
2020-10-22 15:47:00 +02:00
|
|
|
|
2021-01-05 02:17:07 +01:00
|
|
|
system("mkdir -p \"$TABFS_MOUNT_DIR\"");
|
2021-01-03 11:23:20 +01:00
|
|
|
|
|
|
|
pthread_t thread;
|
|
|
|
int err = pthread_create(&thread, NULL, reader_main, NULL);
|
|
|
|
if (err != 0) {
|
|
|
|
eprintln("pthread_create: %s", strerror(err));
|
|
|
|
exit(1);
|
2020-10-22 00:53:27 +02:00
|
|
|
}
|
2021-01-04 19:19:04 +01:00
|
|
|
|
2021-01-03 11:23:20 +01:00
|
|
|
pthread_detach(thread);
|
|
|
|
|
|
|
|
char *fuse_argv[] = {
|
|
|
|
argv[0],
|
|
|
|
"-f",
|
2021-01-04 10:40:22 +01:00
|
|
|
#if !defined(__APPLE__)
|
2021-01-11 17:23:53 +01:00
|
|
|
#if !defined(__FreeBSD__)
|
2021-01-03 11:23:20 +01:00
|
|
|
"-oauto_unmount",
|
2021-01-11 17:23:53 +01:00
|
|
|
#endif
|
2021-01-04 10:40:22 +01:00
|
|
|
#endif
|
2021-01-03 11:23:20 +01:00
|
|
|
"-odirect_io",
|
2021-01-05 02:17:07 +01:00
|
|
|
getenv("TABFS_MOUNT_DIR"),
|
2021-01-03 11:23:20 +01:00
|
|
|
NULL,
|
|
|
|
};
|
|
|
|
return fuse_main(
|
|
|
|
(sizeof(fuse_argv)/sizeof(*fuse_argv))-1,
|
|
|
|
(char **)&fuse_argv,
|
|
|
|
&tabfs_oper,
|
|
|
|
NULL);
|
2019-02-25 22:02:25 +01:00
|
|
|
}
|