mirror of https://github.com/xemu-project/xemu.git
virtiofsd: Format imported files to qemu style
Mostly using a set like: indent -nut -i 4 -nlp -br -cs -ce --no-space-after-function-call-names file clang-format -style=file -i -- file clang-tidy -fix-errors -checks=readability-braces-around-statements file clang-format -style=file -i -- file With manual cleanups. The .clang-format used is below. Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> Reviewed by: Aleksandar Markovic <amarkovic@wavecomp.com> Language: Cpp AlignAfterOpenBracket: Align AlignConsecutiveAssignments: false # although we like it, it creates churn AlignConsecutiveDeclarations: false AlignEscapedNewlinesLeft: true AlignOperands: true AlignTrailingComments: false # churn AllowAllParametersOfDeclarationOnNextLine: true AllowShortBlocksOnASingleLine: false AllowShortCaseLabelsOnASingleLine: false AllowShortFunctionsOnASingleLine: None AllowShortIfStatementsOnASingleLine: false AllowShortLoopsOnASingleLine: false AlwaysBreakAfterReturnType: None # AlwaysBreakAfterDefinitionReturnType is taken into account AlwaysBreakBeforeMultilineStrings: false BinPackArguments: true BinPackParameters: true BraceWrapping: AfterControlStatement: false AfterEnum: false AfterFunction: true AfterStruct: false AfterUnion: false BeforeElse: false IndentBraces: false BreakBeforeBinaryOperators: None BreakBeforeBraces: Custom BreakBeforeTernaryOperators: false BreakStringLiterals: true ColumnLimit: 80 ContinuationIndentWidth: 4 Cpp11BracedListStyle: false DerivePointerAlignment: false DisableFormat: false ForEachMacros: [ 'CPU_FOREACH', 'CPU_FOREACH_REVERSE', 'CPU_FOREACH_SAFE', 'IOMMU_NOTIFIER_FOREACH', 'QLIST_FOREACH', 'QLIST_FOREACH_ENTRY', 'QLIST_FOREACH_RCU', 'QLIST_FOREACH_SAFE', 'QLIST_FOREACH_SAFE_RCU', 'QSIMPLEQ_FOREACH', 'QSIMPLEQ_FOREACH_SAFE', 'QSLIST_FOREACH', 'QSLIST_FOREACH_SAFE', 'QTAILQ_FOREACH', 'QTAILQ_FOREACH_REVERSE', 'QTAILQ_FOREACH_SAFE', 'QTAILQ_RAW_FOREACH', 'RAMBLOCK_FOREACH' ] IncludeCategories: - Regex: '^"qemu/osdep.h' Priority: -3 - Regex: '^"(block|chardev|crypto|disas|exec|fpu|hw|io|libdecnumber|migration|monitor|net|qapi|qemu|qom|standard-headers|sysemu|ui)/' Priority: -2 - Regex: '^"(elf.h|qemu-common.h|glib-compat.h|qemu-io.h|trace-tcg.h)' Priority: -1 - Regex: '.*' Priority: 1 IncludeIsMainRegex: '$' IndentCaseLabels: false IndentWidth: 4 IndentWrappedFunctionNames: false KeepEmptyLinesAtTheStartOfBlocks: false MacroBlockBegin: '.*_BEGIN$' # only PREC_BEGIN ? MacroBlockEnd: '.*_END$' MaxEmptyLinesToKeep: 2 PointerAlignment: Right ReflowComments: true SortIncludes: true SpaceAfterCStyleCast: false SpaceBeforeAssignmentOperators: true SpaceBeforeParens: ControlStatements SpaceInEmptyParentheses: false SpacesBeforeTrailingComments: 1 SpacesInContainerLiterals: true SpacesInParentheses: false SpacesInSquareBrackets: false Standard: Auto UseTab: Never ... Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
This commit is contained in:
parent
a3e23f3254
commit
7387863d03
|
@ -1,252 +1,272 @@
|
||||||
/*
|
/*
|
||||||
FUSE: Filesystem in Userspace
|
* FUSE: Filesystem in Userspace
|
||||||
Copyright (C) 2010 Miklos Szeredi <miklos@szeredi.hu>
|
* Copyright (C) 2010 Miklos Szeredi <miklos@szeredi.hu>
|
||||||
|
*
|
||||||
Functions for dealing with `struct fuse_buf` and `struct
|
* Functions for dealing with `struct fuse_buf` and `struct
|
||||||
fuse_bufvec`.
|
* fuse_bufvec`.
|
||||||
|
*
|
||||||
This program can be distributed under the terms of the GNU LGPLv2.
|
* This program can be distributed under the terms of the GNU LGPLv2.
|
||||||
See the file COPYING.LIB
|
* See the file COPYING.LIB
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "fuse_i.h"
|
#include "fuse_i.h"
|
||||||
#include "fuse_lowlevel.h"
|
#include "fuse_lowlevel.h"
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
size_t fuse_buf_size(const struct fuse_bufvec *bufv)
|
size_t fuse_buf_size(const struct fuse_bufvec *bufv)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
|
|
||||||
for (i = 0; i < bufv->count; i++) {
|
for (i = 0; i < bufv->count; i++) {
|
||||||
if (bufv->buf[i].size == SIZE_MAX)
|
if (bufv->buf[i].size == SIZE_MAX) {
|
||||||
size = SIZE_MAX;
|
size = SIZE_MAX;
|
||||||
else
|
} else {
|
||||||
size += bufv->buf[i].size;
|
size += bufv->buf[i].size;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t min_size(size_t s1, size_t s2)
|
static size_t min_size(size_t s1, size_t s2)
|
||||||
{
|
{
|
||||||
return s1 < s2 ? s1 : s2;
|
return s1 < s2 ? s1 : s2;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t fuse_buf_write(const struct fuse_buf *dst, size_t dst_off,
|
static ssize_t fuse_buf_write(const struct fuse_buf *dst, size_t dst_off,
|
||||||
const struct fuse_buf *src, size_t src_off,
|
const struct fuse_buf *src, size_t src_off,
|
||||||
size_t len)
|
size_t len)
|
||||||
{
|
{
|
||||||
ssize_t res = 0;
|
ssize_t res = 0;
|
||||||
size_t copied = 0;
|
size_t copied = 0;
|
||||||
|
|
||||||
while (len) {
|
while (len) {
|
||||||
if (dst->flags & FUSE_BUF_FD_SEEK) {
|
if (dst->flags & FUSE_BUF_FD_SEEK) {
|
||||||
res = pwrite(dst->fd, (char *)src->mem + src_off, len,
|
res = pwrite(dst->fd, (char *)src->mem + src_off, len,
|
||||||
dst->pos + dst_off);
|
dst->pos + dst_off);
|
||||||
} else {
|
} else {
|
||||||
res = write(dst->fd, (char *)src->mem + src_off, len);
|
res = write(dst->fd, (char *)src->mem + src_off, len);
|
||||||
}
|
}
|
||||||
if (res == -1) {
|
if (res == -1) {
|
||||||
if (!copied)
|
if (!copied) {
|
||||||
return -errno;
|
return -errno;
|
||||||
break;
|
}
|
||||||
}
|
break;
|
||||||
if (res == 0)
|
}
|
||||||
break;
|
if (res == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
copied += res;
|
copied += res;
|
||||||
if (!(dst->flags & FUSE_BUF_FD_RETRY))
|
if (!(dst->flags & FUSE_BUF_FD_RETRY)) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
src_off += res;
|
src_off += res;
|
||||||
dst_off += res;
|
dst_off += res;
|
||||||
len -= res;
|
len -= res;
|
||||||
}
|
}
|
||||||
|
|
||||||
return copied;
|
return copied;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t fuse_buf_read(const struct fuse_buf *dst, size_t dst_off,
|
static ssize_t fuse_buf_read(const struct fuse_buf *dst, size_t dst_off,
|
||||||
const struct fuse_buf *src, size_t src_off,
|
const struct fuse_buf *src, size_t src_off,
|
||||||
size_t len)
|
size_t len)
|
||||||
{
|
{
|
||||||
ssize_t res = 0;
|
ssize_t res = 0;
|
||||||
size_t copied = 0;
|
size_t copied = 0;
|
||||||
|
|
||||||
while (len) {
|
while (len) {
|
||||||
if (src->flags & FUSE_BUF_FD_SEEK) {
|
if (src->flags & FUSE_BUF_FD_SEEK) {
|
||||||
res = pread(src->fd, (char *)dst->mem + dst_off, len,
|
res = pread(src->fd, (char *)dst->mem + dst_off, len,
|
||||||
src->pos + src_off);
|
src->pos + src_off);
|
||||||
} else {
|
} else {
|
||||||
res = read(src->fd, (char *)dst->mem + dst_off, len);
|
res = read(src->fd, (char *)dst->mem + dst_off, len);
|
||||||
}
|
}
|
||||||
if (res == -1) {
|
if (res == -1) {
|
||||||
if (!copied)
|
if (!copied) {
|
||||||
return -errno;
|
return -errno;
|
||||||
break;
|
}
|
||||||
}
|
break;
|
||||||
if (res == 0)
|
}
|
||||||
break;
|
if (res == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
copied += res;
|
copied += res;
|
||||||
if (!(src->flags & FUSE_BUF_FD_RETRY))
|
if (!(src->flags & FUSE_BUF_FD_RETRY)) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
dst_off += res;
|
dst_off += res;
|
||||||
src_off += res;
|
src_off += res;
|
||||||
len -= res;
|
len -= res;
|
||||||
}
|
}
|
||||||
|
|
||||||
return copied;
|
return copied;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t fuse_buf_fd_to_fd(const struct fuse_buf *dst, size_t dst_off,
|
static ssize_t fuse_buf_fd_to_fd(const struct fuse_buf *dst, size_t dst_off,
|
||||||
const struct fuse_buf *src, size_t src_off,
|
const struct fuse_buf *src, size_t src_off,
|
||||||
size_t len)
|
size_t len)
|
||||||
{
|
{
|
||||||
char buf[4096];
|
char buf[4096];
|
||||||
struct fuse_buf tmp = {
|
struct fuse_buf tmp = {
|
||||||
.size = sizeof(buf),
|
.size = sizeof(buf),
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
};
|
};
|
||||||
ssize_t res;
|
ssize_t res;
|
||||||
size_t copied = 0;
|
size_t copied = 0;
|
||||||
|
|
||||||
tmp.mem = buf;
|
tmp.mem = buf;
|
||||||
|
|
||||||
while (len) {
|
while (len) {
|
||||||
size_t this_len = min_size(tmp.size, len);
|
size_t this_len = min_size(tmp.size, len);
|
||||||
size_t read_len;
|
size_t read_len;
|
||||||
|
|
||||||
res = fuse_buf_read(&tmp, 0, src, src_off, this_len);
|
res = fuse_buf_read(&tmp, 0, src, src_off, this_len);
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
if (!copied)
|
if (!copied) {
|
||||||
return res;
|
return res;
|
||||||
break;
|
}
|
||||||
}
|
break;
|
||||||
if (res == 0)
|
}
|
||||||
break;
|
if (res == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
read_len = res;
|
read_len = res;
|
||||||
res = fuse_buf_write(dst, dst_off, &tmp, 0, read_len);
|
res = fuse_buf_write(dst, dst_off, &tmp, 0, read_len);
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
if (!copied)
|
if (!copied) {
|
||||||
return res;
|
return res;
|
||||||
break;
|
}
|
||||||
}
|
break;
|
||||||
if (res == 0)
|
}
|
||||||
break;
|
if (res == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
copied += res;
|
copied += res;
|
||||||
|
|
||||||
if (res < this_len)
|
if (res < this_len) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
dst_off += res;
|
dst_off += res;
|
||||||
src_off += res;
|
src_off += res;
|
||||||
len -= res;
|
len -= res;
|
||||||
}
|
}
|
||||||
|
|
||||||
return copied;
|
return copied;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t fuse_buf_copy_one(const struct fuse_buf *dst, size_t dst_off,
|
static ssize_t fuse_buf_copy_one(const struct fuse_buf *dst, size_t dst_off,
|
||||||
const struct fuse_buf *src, size_t src_off,
|
const struct fuse_buf *src, size_t src_off,
|
||||||
size_t len, enum fuse_buf_copy_flags flags)
|
size_t len, enum fuse_buf_copy_flags flags)
|
||||||
{
|
{
|
||||||
int src_is_fd = src->flags & FUSE_BUF_IS_FD;
|
int src_is_fd = src->flags & FUSE_BUF_IS_FD;
|
||||||
int dst_is_fd = dst->flags & FUSE_BUF_IS_FD;
|
int dst_is_fd = dst->flags & FUSE_BUF_IS_FD;
|
||||||
|
|
||||||
if (!src_is_fd && !dst_is_fd) {
|
if (!src_is_fd && !dst_is_fd) {
|
||||||
char *dstmem = (char *)dst->mem + dst_off;
|
char *dstmem = (char *)dst->mem + dst_off;
|
||||||
char *srcmem = (char *)src->mem + src_off;
|
char *srcmem = (char *)src->mem + src_off;
|
||||||
|
|
||||||
if (dstmem != srcmem) {
|
if (dstmem != srcmem) {
|
||||||
if (dstmem + len <= srcmem || srcmem + len <= dstmem)
|
if (dstmem + len <= srcmem || srcmem + len <= dstmem) {
|
||||||
memcpy(dstmem, srcmem, len);
|
memcpy(dstmem, srcmem, len);
|
||||||
else
|
} else {
|
||||||
memmove(dstmem, srcmem, len);
|
memmove(dstmem, srcmem, len);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
} else if (!src_is_fd) {
|
} else if (!src_is_fd) {
|
||||||
return fuse_buf_write(dst, dst_off, src, src_off, len);
|
return fuse_buf_write(dst, dst_off, src, src_off, len);
|
||||||
} else if (!dst_is_fd) {
|
} else if (!dst_is_fd) {
|
||||||
return fuse_buf_read(dst, dst_off, src, src_off, len);
|
return fuse_buf_read(dst, dst_off, src, src_off, len);
|
||||||
} else {
|
} else {
|
||||||
return fuse_buf_fd_to_fd(dst, dst_off, src, src_off, len);
|
return fuse_buf_fd_to_fd(dst, dst_off, src, src_off, len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct fuse_buf *fuse_bufvec_current(struct fuse_bufvec *bufv)
|
static const struct fuse_buf *fuse_bufvec_current(struct fuse_bufvec *bufv)
|
||||||
{
|
{
|
||||||
if (bufv->idx < bufv->count)
|
if (bufv->idx < bufv->count) {
|
||||||
return &bufv->buf[bufv->idx];
|
return &bufv->buf[bufv->idx];
|
||||||
else
|
} else {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fuse_bufvec_advance(struct fuse_bufvec *bufv, size_t len)
|
static int fuse_bufvec_advance(struct fuse_bufvec *bufv, size_t len)
|
||||||
{
|
{
|
||||||
const struct fuse_buf *buf = fuse_bufvec_current(bufv);
|
const struct fuse_buf *buf = fuse_bufvec_current(bufv);
|
||||||
|
|
||||||
bufv->off += len;
|
bufv->off += len;
|
||||||
assert(bufv->off <= buf->size);
|
assert(bufv->off <= buf->size);
|
||||||
if (bufv->off == buf->size) {
|
if (bufv->off == buf->size) {
|
||||||
assert(bufv->idx < bufv->count);
|
assert(bufv->idx < bufv->count);
|
||||||
bufv->idx++;
|
bufv->idx++;
|
||||||
if (bufv->idx == bufv->count)
|
if (bufv->idx == bufv->count) {
|
||||||
return 0;
|
return 0;
|
||||||
bufv->off = 0;
|
}
|
||||||
}
|
bufv->off = 0;
|
||||||
return 1;
|
}
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t fuse_buf_copy(struct fuse_bufvec *dstv, struct fuse_bufvec *srcv,
|
ssize_t fuse_buf_copy(struct fuse_bufvec *dstv, struct fuse_bufvec *srcv,
|
||||||
enum fuse_buf_copy_flags flags)
|
enum fuse_buf_copy_flags flags)
|
||||||
{
|
{
|
||||||
size_t copied = 0;
|
size_t copied = 0;
|
||||||
|
|
||||||
if (dstv == srcv)
|
if (dstv == srcv) {
|
||||||
return fuse_buf_size(dstv);
|
return fuse_buf_size(dstv);
|
||||||
|
}
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
const struct fuse_buf *src = fuse_bufvec_current(srcv);
|
const struct fuse_buf *src = fuse_bufvec_current(srcv);
|
||||||
const struct fuse_buf *dst = fuse_bufvec_current(dstv);
|
const struct fuse_buf *dst = fuse_bufvec_current(dstv);
|
||||||
size_t src_len;
|
size_t src_len;
|
||||||
size_t dst_len;
|
size_t dst_len;
|
||||||
size_t len;
|
size_t len;
|
||||||
ssize_t res;
|
ssize_t res;
|
||||||
|
|
||||||
if (src == NULL || dst == NULL)
|
if (src == NULL || dst == NULL) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
src_len = src->size - srcv->off;
|
src_len = src->size - srcv->off;
|
||||||
dst_len = dst->size - dstv->off;
|
dst_len = dst->size - dstv->off;
|
||||||
len = min_size(src_len, dst_len);
|
len = min_size(src_len, dst_len);
|
||||||
|
|
||||||
res = fuse_buf_copy_one(dst, dstv->off, src, srcv->off, len, flags);
|
res = fuse_buf_copy_one(dst, dstv->off, src, srcv->off, len, flags);
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
if (!copied)
|
if (!copied) {
|
||||||
return res;
|
return res;
|
||||||
break;
|
}
|
||||||
}
|
break;
|
||||||
copied += res;
|
}
|
||||||
|
copied += res;
|
||||||
|
|
||||||
if (!fuse_bufvec_advance(srcv, res) ||
|
if (!fuse_bufvec_advance(srcv, res) ||
|
||||||
!fuse_bufvec_advance(dstv, res))
|
!fuse_bufvec_advance(dstv, res)) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (res < len)
|
if (res < len) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return copied;
|
return copied;
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,21 +1,23 @@
|
||||||
/* FUSE: Filesystem in Userspace
|
/*
|
||||||
Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
|
* FUSE: Filesystem in Userspace
|
||||||
|
* Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
|
||||||
This program can be distributed under the terms of the GNU LGPLv2.
|
*
|
||||||
See the file COPYING.LIB.
|
* This program can be distributed under the terms of the GNU LGPLv2.
|
||||||
*/
|
* See the file COPYING.LIB.
|
||||||
|
*/
|
||||||
|
|
||||||
/** @file */
|
/** @file */
|
||||||
|
|
||||||
#if !defined(FUSE_H_) && !defined(FUSE_LOWLEVEL_H_)
|
#if !defined(FUSE_H_) && !defined(FUSE_LOWLEVEL_H_)
|
||||||
#error "Never include <fuse_common.h> directly; use <fuse.h> or <fuse_lowlevel.h> instead."
|
#error \
|
||||||
|
"Never include <fuse_common.h> directly; use <fuse.h> or <fuse_lowlevel.h> instead."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef FUSE_COMMON_H_
|
#ifndef FUSE_COMMON_H_
|
||||||
#define FUSE_COMMON_H_
|
#define FUSE_COMMON_H_
|
||||||
|
|
||||||
#include "fuse_opt.h"
|
|
||||||
#include "fuse_log.h"
|
#include "fuse_log.h"
|
||||||
|
#include "fuse_opt.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
@ -25,7 +27,7 @@
|
||||||
/** Minor version of FUSE library interface */
|
/** Minor version of FUSE library interface */
|
||||||
#define FUSE_MINOR_VERSION 2
|
#define FUSE_MINOR_VERSION 2
|
||||||
|
|
||||||
#define FUSE_MAKE_VERSION(maj, min) ((maj) * 10 + (min))
|
#define FUSE_MAKE_VERSION(maj, min) ((maj) * 10 + (min))
|
||||||
#define FUSE_VERSION FUSE_MAKE_VERSION(FUSE_MAJOR_VERSION, FUSE_MINOR_VERSION)
|
#define FUSE_VERSION FUSE_MAKE_VERSION(FUSE_MAJOR_VERSION, FUSE_MINOR_VERSION)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -38,67 +40,83 @@
|
||||||
* descriptors can share a single file handle.
|
* descriptors can share a single file handle.
|
||||||
*/
|
*/
|
||||||
struct fuse_file_info {
|
struct fuse_file_info {
|
||||||
/** Open flags. Available in open() and release() */
|
/** Open flags. Available in open() and release() */
|
||||||
int flags;
|
int flags;
|
||||||
|
|
||||||
/** In case of a write operation indicates if this was caused
|
/*
|
||||||
by a delayed write from the page cache. If so, then the
|
* In case of a write operation indicates if this was caused
|
||||||
context's pid, uid, and gid fields will not be valid, and
|
* by a delayed write from the page cache. If so, then the
|
||||||
the *fh* value may not match the *fh* value that would
|
* context's pid, uid, and gid fields will not be valid, and
|
||||||
have been sent with the corresponding individual write
|
* the *fh* value may not match the *fh* value that would
|
||||||
requests if write caching had been disabled. */
|
* have been sent with the corresponding individual write
|
||||||
unsigned int writepage : 1;
|
* requests if write caching had been disabled.
|
||||||
|
*/
|
||||||
|
unsigned int writepage:1;
|
||||||
|
|
||||||
/** Can be filled in by open, to use direct I/O on this file. */
|
/** Can be filled in by open, to use direct I/O on this file. */
|
||||||
unsigned int direct_io : 1;
|
unsigned int direct_io:1;
|
||||||
|
|
||||||
/** Can be filled in by open. It signals the kernel that any
|
/*
|
||||||
currently cached file data (ie., data that the filesystem
|
* Can be filled in by open. It signals the kernel that any
|
||||||
provided the last time the file was open) need not be
|
* currently cached file data (ie., data that the filesystem
|
||||||
invalidated. Has no effect when set in other contexts (in
|
* provided the last time the file was open) need not be
|
||||||
particular it does nothing when set by opendir()). */
|
* invalidated. Has no effect when set in other contexts (in
|
||||||
unsigned int keep_cache : 1;
|
* particular it does nothing when set by opendir()).
|
||||||
|
*/
|
||||||
|
unsigned int keep_cache:1;
|
||||||
|
|
||||||
/** Indicates a flush operation. Set in flush operation, also
|
/*
|
||||||
maybe set in highlevel lock operation and lowlevel release
|
* Indicates a flush operation. Set in flush operation, also
|
||||||
operation. */
|
* maybe set in highlevel lock operation and lowlevel release
|
||||||
unsigned int flush : 1;
|
* operation.
|
||||||
|
*/
|
||||||
|
unsigned int flush:1;
|
||||||
|
|
||||||
/** Can be filled in by open, to indicate that the file is not
|
/*
|
||||||
seekable. */
|
* Can be filled in by open, to indicate that the file is not
|
||||||
unsigned int nonseekable : 1;
|
* seekable.
|
||||||
|
*/
|
||||||
|
unsigned int nonseekable:1;
|
||||||
|
|
||||||
/* Indicates that flock locks for this file should be
|
/*
|
||||||
released. If set, lock_owner shall contain a valid value.
|
* Indicates that flock locks for this file should be
|
||||||
May only be set in ->release(). */
|
* released. If set, lock_owner shall contain a valid value.
|
||||||
unsigned int flock_release : 1;
|
* May only be set in ->release().
|
||||||
|
*/
|
||||||
|
unsigned int flock_release:1;
|
||||||
|
|
||||||
/** Can be filled in by opendir. It signals the kernel to
|
/*
|
||||||
enable caching of entries returned by readdir(). Has no
|
* Can be filled in by opendir. It signals the kernel to
|
||||||
effect when set in other contexts (in particular it does
|
* enable caching of entries returned by readdir(). Has no
|
||||||
nothing when set by open()). */
|
* effect when set in other contexts (in particular it does
|
||||||
unsigned int cache_readdir : 1;
|
* nothing when set by open()).
|
||||||
|
*/
|
||||||
|
unsigned int cache_readdir:1;
|
||||||
|
|
||||||
/** Padding. Reserved for future use*/
|
/** Padding. Reserved for future use*/
|
||||||
unsigned int padding : 25;
|
unsigned int padding:25;
|
||||||
unsigned int padding2 : 32;
|
unsigned int padding2:32;
|
||||||
|
|
||||||
/** File handle id. May be filled in by filesystem in create,
|
/*
|
||||||
* open, and opendir(). Available in most other file operations on the
|
* File handle id. May be filled in by filesystem in create,
|
||||||
* same file handle. */
|
* open, and opendir(). Available in most other file operations on the
|
||||||
uint64_t fh;
|
* same file handle.
|
||||||
|
*/
|
||||||
|
uint64_t fh;
|
||||||
|
|
||||||
/** Lock owner id. Available in locking operations and flush */
|
/** Lock owner id. Available in locking operations and flush */
|
||||||
uint64_t lock_owner;
|
uint64_t lock_owner;
|
||||||
|
|
||||||
/** Requested poll events. Available in ->poll. Only set on kernels
|
/*
|
||||||
which support it. If unsupported, this field is set to zero. */
|
* Requested poll events. Available in ->poll. Only set on kernels
|
||||||
uint32_t poll_events;
|
* which support it. If unsupported, this field is set to zero.
|
||||||
|
*/
|
||||||
|
uint32_t poll_events;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**************************************************************************
|
/*
|
||||||
* Capability bits for 'fuse_conn_info.capable' and 'fuse_conn_info.want' *
|
* Capability bits for 'fuse_conn_info.capable' and 'fuse_conn_info.want'
|
||||||
**************************************************************************/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates that the filesystem supports asynchronous read requests.
|
* Indicates that the filesystem supports asynchronous read requests.
|
||||||
|
@ -110,7 +128,7 @@ struct fuse_file_info {
|
||||||
*
|
*
|
||||||
* This feature is enabled by default when supported by the kernel.
|
* This feature is enabled by default when supported by the kernel.
|
||||||
*/
|
*/
|
||||||
#define FUSE_CAP_ASYNC_READ (1 << 0)
|
#define FUSE_CAP_ASYNC_READ (1 << 0)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates that the filesystem supports "remote" locking.
|
* Indicates that the filesystem supports "remote" locking.
|
||||||
|
@ -118,7 +136,7 @@ struct fuse_file_info {
|
||||||
* This feature is enabled by default when supported by the kernel,
|
* This feature is enabled by default when supported by the kernel,
|
||||||
* and if getlk() and setlk() handlers are implemented.
|
* and if getlk() and setlk() handlers are implemented.
|
||||||
*/
|
*/
|
||||||
#define FUSE_CAP_POSIX_LOCKS (1 << 1)
|
#define FUSE_CAP_POSIX_LOCKS (1 << 1)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates that the filesystem supports the O_TRUNC open flag. If
|
* Indicates that the filesystem supports the O_TRUNC open flag. If
|
||||||
|
@ -127,14 +145,14 @@ struct fuse_file_info {
|
||||||
*
|
*
|
||||||
* This feature is enabled by default when supported by the kernel.
|
* This feature is enabled by default when supported by the kernel.
|
||||||
*/
|
*/
|
||||||
#define FUSE_CAP_ATOMIC_O_TRUNC (1 << 3)
|
#define FUSE_CAP_ATOMIC_O_TRUNC (1 << 3)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates that the filesystem supports lookups of "." and "..".
|
* Indicates that the filesystem supports lookups of "." and "..".
|
||||||
*
|
*
|
||||||
* This feature is disabled by default.
|
* This feature is disabled by default.
|
||||||
*/
|
*/
|
||||||
#define FUSE_CAP_EXPORT_SUPPORT (1 << 4)
|
#define FUSE_CAP_EXPORT_SUPPORT (1 << 4)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates that the kernel should not apply the umask to the
|
* Indicates that the kernel should not apply the umask to the
|
||||||
|
@ -142,7 +160,7 @@ struct fuse_file_info {
|
||||||
*
|
*
|
||||||
* This feature is disabled by default.
|
* This feature is disabled by default.
|
||||||
*/
|
*/
|
||||||
#define FUSE_CAP_DONT_MASK (1 << 6)
|
#define FUSE_CAP_DONT_MASK (1 << 6)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates that libfuse should try to use splice() when writing to
|
* Indicates that libfuse should try to use splice() when writing to
|
||||||
|
@ -150,7 +168,7 @@ struct fuse_file_info {
|
||||||
*
|
*
|
||||||
* This feature is disabled by default.
|
* This feature is disabled by default.
|
||||||
*/
|
*/
|
||||||
#define FUSE_CAP_SPLICE_WRITE (1 << 7)
|
#define FUSE_CAP_SPLICE_WRITE (1 << 7)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates that libfuse should try to move pages instead of copying when
|
* Indicates that libfuse should try to move pages instead of copying when
|
||||||
|
@ -158,7 +176,7 @@ struct fuse_file_info {
|
||||||
*
|
*
|
||||||
* This feature is disabled by default.
|
* This feature is disabled by default.
|
||||||
*/
|
*/
|
||||||
#define FUSE_CAP_SPLICE_MOVE (1 << 8)
|
#define FUSE_CAP_SPLICE_MOVE (1 << 8)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates that libfuse should try to use splice() when reading from
|
* Indicates that libfuse should try to use splice() when reading from
|
||||||
|
@ -167,7 +185,7 @@ struct fuse_file_info {
|
||||||
* This feature is enabled by default when supported by the kernel and
|
* This feature is enabled by default when supported by the kernel and
|
||||||
* if the filesystem implements a write_buf() handler.
|
* if the filesystem implements a write_buf() handler.
|
||||||
*/
|
*/
|
||||||
#define FUSE_CAP_SPLICE_READ (1 << 9)
|
#define FUSE_CAP_SPLICE_READ (1 << 9)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If set, the calls to flock(2) will be emulated using POSIX locks and must
|
* If set, the calls to flock(2) will be emulated using POSIX locks and must
|
||||||
|
@ -180,14 +198,14 @@ struct fuse_file_info {
|
||||||
* This feature is enabled by default when supported by the kernel and
|
* This feature is enabled by default when supported by the kernel and
|
||||||
* if the filesystem implements a flock() handler.
|
* if the filesystem implements a flock() handler.
|
||||||
*/
|
*/
|
||||||
#define FUSE_CAP_FLOCK_LOCKS (1 << 10)
|
#define FUSE_CAP_FLOCK_LOCKS (1 << 10)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates that the filesystem supports ioctl's on directories.
|
* Indicates that the filesystem supports ioctl's on directories.
|
||||||
*
|
*
|
||||||
* This feature is enabled by default when supported by the kernel.
|
* This feature is enabled by default when supported by the kernel.
|
||||||
*/
|
*/
|
||||||
#define FUSE_CAP_IOCTL_DIR (1 << 11)
|
#define FUSE_CAP_IOCTL_DIR (1 << 11)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Traditionally, while a file is open the FUSE kernel module only
|
* Traditionally, while a file is open the FUSE kernel module only
|
||||||
|
@ -209,7 +227,7 @@ struct fuse_file_info {
|
||||||
*
|
*
|
||||||
* This feature is enabled by default when supported by the kernel.
|
* This feature is enabled by default when supported by the kernel.
|
||||||
*/
|
*/
|
||||||
#define FUSE_CAP_AUTO_INVAL_DATA (1 << 12)
|
#define FUSE_CAP_AUTO_INVAL_DATA (1 << 12)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates that the filesystem supports readdirplus.
|
* Indicates that the filesystem supports readdirplus.
|
||||||
|
@ -217,7 +235,7 @@ struct fuse_file_info {
|
||||||
* This feature is enabled by default when supported by the kernel and if the
|
* This feature is enabled by default when supported by the kernel and if the
|
||||||
* filesystem implements a readdirplus() handler.
|
* filesystem implements a readdirplus() handler.
|
||||||
*/
|
*/
|
||||||
#define FUSE_CAP_READDIRPLUS (1 << 13)
|
#define FUSE_CAP_READDIRPLUS (1 << 13)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates that the filesystem supports adaptive readdirplus.
|
* Indicates that the filesystem supports adaptive readdirplus.
|
||||||
|
@ -245,7 +263,7 @@ struct fuse_file_info {
|
||||||
* if the filesystem implements both a readdirplus() and a readdir()
|
* if the filesystem implements both a readdirplus() and a readdir()
|
||||||
* handler.
|
* handler.
|
||||||
*/
|
*/
|
||||||
#define FUSE_CAP_READDIRPLUS_AUTO (1 << 14)
|
#define FUSE_CAP_READDIRPLUS_AUTO (1 << 14)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates that the filesystem supports asynchronous direct I/O submission.
|
* Indicates that the filesystem supports asynchronous direct I/O submission.
|
||||||
|
@ -256,7 +274,7 @@ struct fuse_file_info {
|
||||||
*
|
*
|
||||||
* This feature is enabled by default when supported by the kernel.
|
* This feature is enabled by default when supported by the kernel.
|
||||||
*/
|
*/
|
||||||
#define FUSE_CAP_ASYNC_DIO (1 << 15)
|
#define FUSE_CAP_ASYNC_DIO (1 << 15)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates that writeback caching should be enabled. This means that
|
* Indicates that writeback caching should be enabled. This means that
|
||||||
|
@ -265,7 +283,7 @@ struct fuse_file_info {
|
||||||
*
|
*
|
||||||
* This feature is disabled by default.
|
* This feature is disabled by default.
|
||||||
*/
|
*/
|
||||||
#define FUSE_CAP_WRITEBACK_CACHE (1 << 16)
|
#define FUSE_CAP_WRITEBACK_CACHE (1 << 16)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates support for zero-message opens. If this flag is set in
|
* Indicates support for zero-message opens. If this flag is set in
|
||||||
|
@ -278,7 +296,7 @@ struct fuse_file_info {
|
||||||
* Setting (or unsetting) this flag in the `want` field has *no
|
* Setting (or unsetting) this flag in the `want` field has *no
|
||||||
* effect*.
|
* effect*.
|
||||||
*/
|
*/
|
||||||
#define FUSE_CAP_NO_OPEN_SUPPORT (1 << 17)
|
#define FUSE_CAP_NO_OPEN_SUPPORT (1 << 17)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates support for parallel directory operations. If this flag
|
* Indicates support for parallel directory operations. If this flag
|
||||||
|
@ -288,7 +306,7 @@ struct fuse_file_info {
|
||||||
*
|
*
|
||||||
* This feature is enabled by default when supported by the kernel.
|
* This feature is enabled by default when supported by the kernel.
|
||||||
*/
|
*/
|
||||||
#define FUSE_CAP_PARALLEL_DIROPS (1 << 18)
|
#define FUSE_CAP_PARALLEL_DIROPS (1 << 18)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates support for POSIX ACLs.
|
* Indicates support for POSIX ACLs.
|
||||||
|
@ -307,7 +325,7 @@ struct fuse_file_info {
|
||||||
*
|
*
|
||||||
* This feature is disabled by default.
|
* This feature is disabled by default.
|
||||||
*/
|
*/
|
||||||
#define FUSE_CAP_POSIX_ACL (1 << 19)
|
#define FUSE_CAP_POSIX_ACL (1 << 19)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates that the filesystem is responsible for unsetting
|
* Indicates that the filesystem is responsible for unsetting
|
||||||
|
@ -316,7 +334,7 @@ struct fuse_file_info {
|
||||||
*
|
*
|
||||||
* This feature is enabled by default when supported by the kernel.
|
* This feature is enabled by default when supported by the kernel.
|
||||||
*/
|
*/
|
||||||
#define FUSE_CAP_HANDLE_KILLPRIV (1 << 20)
|
#define FUSE_CAP_HANDLE_KILLPRIV (1 << 20)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates support for zero-message opendirs. If this flag is set in
|
* Indicates support for zero-message opendirs. If this flag is set in
|
||||||
|
@ -328,7 +346,7 @@ struct fuse_file_info {
|
||||||
*
|
*
|
||||||
* Setting (or unsetting) this flag in the `want` field has *no effect*.
|
* Setting (or unsetting) this flag in the `want` field has *no effect*.
|
||||||
*/
|
*/
|
||||||
#define FUSE_CAP_NO_OPENDIR_SUPPORT (1 << 24)
|
#define FUSE_CAP_NO_OPENDIR_SUPPORT (1 << 24)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ioctl flags
|
* Ioctl flags
|
||||||
|
@ -340,12 +358,12 @@ struct fuse_file_info {
|
||||||
*
|
*
|
||||||
* FUSE_IOCTL_MAX_IOV: maximum of in_iovecs + out_iovecs
|
* FUSE_IOCTL_MAX_IOV: maximum of in_iovecs + out_iovecs
|
||||||
*/
|
*/
|
||||||
#define FUSE_IOCTL_COMPAT (1 << 0)
|
#define FUSE_IOCTL_COMPAT (1 << 0)
|
||||||
#define FUSE_IOCTL_UNRESTRICTED (1 << 1)
|
#define FUSE_IOCTL_UNRESTRICTED (1 << 1)
|
||||||
#define FUSE_IOCTL_RETRY (1 << 2)
|
#define FUSE_IOCTL_RETRY (1 << 2)
|
||||||
#define FUSE_IOCTL_DIR (1 << 4)
|
#define FUSE_IOCTL_DIR (1 << 4)
|
||||||
|
|
||||||
#define FUSE_IOCTL_MAX_IOV 256
|
#define FUSE_IOCTL_MAX_IOV 256
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Connection information, passed to the ->init() method
|
* Connection information, passed to the ->init() method
|
||||||
|
@ -355,114 +373,114 @@ struct fuse_file_info {
|
||||||
* value must usually be smaller than the indicated value.
|
* value must usually be smaller than the indicated value.
|
||||||
*/
|
*/
|
||||||
struct fuse_conn_info {
|
struct fuse_conn_info {
|
||||||
/**
|
/**
|
||||||
* Major version of the protocol (read-only)
|
* Major version of the protocol (read-only)
|
||||||
*/
|
*/
|
||||||
unsigned proto_major;
|
unsigned proto_major;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Minor version of the protocol (read-only)
|
* Minor version of the protocol (read-only)
|
||||||
*/
|
*/
|
||||||
unsigned proto_minor;
|
unsigned proto_minor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maximum size of the write buffer
|
* Maximum size of the write buffer
|
||||||
*/
|
*/
|
||||||
unsigned max_write;
|
unsigned max_write;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maximum size of read requests. A value of zero indicates no
|
* Maximum size of read requests. A value of zero indicates no
|
||||||
* limit. However, even if the filesystem does not specify a
|
* limit. However, even if the filesystem does not specify a
|
||||||
* limit, the maximum size of read requests will still be
|
* limit, the maximum size of read requests will still be
|
||||||
* limited by the kernel.
|
* limited by the kernel.
|
||||||
*
|
*
|
||||||
* NOTE: For the time being, the maximum size of read requests
|
* NOTE: For the time being, the maximum size of read requests
|
||||||
* must be set both here *and* passed to fuse_session_new()
|
* must be set both here *and* passed to fuse_session_new()
|
||||||
* using the ``-o max_read=<n>`` mount option. At some point
|
* using the ``-o max_read=<n>`` mount option. At some point
|
||||||
* in the future, specifying the mount option will no longer
|
* in the future, specifying the mount option will no longer
|
||||||
* be necessary.
|
* be necessary.
|
||||||
*/
|
*/
|
||||||
unsigned max_read;
|
unsigned max_read;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maximum readahead
|
* Maximum readahead
|
||||||
*/
|
*/
|
||||||
unsigned max_readahead;
|
unsigned max_readahead;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Capability flags that the kernel supports (read-only)
|
* Capability flags that the kernel supports (read-only)
|
||||||
*/
|
*/
|
||||||
unsigned capable;
|
unsigned capable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Capability flags that the filesystem wants to enable.
|
* Capability flags that the filesystem wants to enable.
|
||||||
*
|
*
|
||||||
* libfuse attempts to initialize this field with
|
* libfuse attempts to initialize this field with
|
||||||
* reasonable default values before calling the init() handler.
|
* reasonable default values before calling the init() handler.
|
||||||
*/
|
*/
|
||||||
unsigned want;
|
unsigned want;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maximum number of pending "background" requests. A
|
* Maximum number of pending "background" requests. A
|
||||||
* background request is any type of request for which the
|
* background request is any type of request for which the
|
||||||
* total number is not limited by other means. As of kernel
|
* total number is not limited by other means. As of kernel
|
||||||
* 4.8, only two types of requests fall into this category:
|
* 4.8, only two types of requests fall into this category:
|
||||||
*
|
*
|
||||||
* 1. Read-ahead requests
|
* 1. Read-ahead requests
|
||||||
* 2. Asynchronous direct I/O requests
|
* 2. Asynchronous direct I/O requests
|
||||||
*
|
*
|
||||||
* Read-ahead requests are generated (if max_readahead is
|
* Read-ahead requests are generated (if max_readahead is
|
||||||
* non-zero) by the kernel to preemptively fill its caches
|
* non-zero) by the kernel to preemptively fill its caches
|
||||||
* when it anticipates that userspace will soon read more
|
* when it anticipates that userspace will soon read more
|
||||||
* data.
|
* data.
|
||||||
*
|
*
|
||||||
* Asynchronous direct I/O requests are generated if
|
* Asynchronous direct I/O requests are generated if
|
||||||
* FUSE_CAP_ASYNC_DIO is enabled and userspace submits a large
|
* FUSE_CAP_ASYNC_DIO is enabled and userspace submits a large
|
||||||
* direct I/O request. In this case the kernel will internally
|
* direct I/O request. In this case the kernel will internally
|
||||||
* split it up into multiple smaller requests and submit them
|
* split it up into multiple smaller requests and submit them
|
||||||
* to the filesystem concurrently.
|
* to the filesystem concurrently.
|
||||||
*
|
*
|
||||||
* Note that the following requests are *not* background
|
* Note that the following requests are *not* background
|
||||||
* requests: writeback requests (limited by the kernel's
|
* requests: writeback requests (limited by the kernel's
|
||||||
* flusher algorithm), regular (i.e., synchronous and
|
* flusher algorithm), regular (i.e., synchronous and
|
||||||
* buffered) userspace read/write requests (limited to one per
|
* buffered) userspace read/write requests (limited to one per
|
||||||
* thread), asynchronous read requests (Linux's io_submit(2)
|
* thread), asynchronous read requests (Linux's io_submit(2)
|
||||||
* call actually blocks, so these are also limited to one per
|
* call actually blocks, so these are also limited to one per
|
||||||
* thread).
|
* thread).
|
||||||
*/
|
*/
|
||||||
unsigned max_background;
|
unsigned max_background;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Kernel congestion threshold parameter. If the number of pending
|
* Kernel congestion threshold parameter. If the number of pending
|
||||||
* background requests exceeds this number, the FUSE kernel module will
|
* background requests exceeds this number, the FUSE kernel module will
|
||||||
* mark the filesystem as "congested". This instructs the kernel to
|
* mark the filesystem as "congested". This instructs the kernel to
|
||||||
* expect that queued requests will take some time to complete, and to
|
* expect that queued requests will take some time to complete, and to
|
||||||
* adjust its algorithms accordingly (e.g. by putting a waiting thread
|
* adjust its algorithms accordingly (e.g. by putting a waiting thread
|
||||||
* to sleep instead of using a busy-loop).
|
* to sleep instead of using a busy-loop).
|
||||||
*/
|
*/
|
||||||
unsigned congestion_threshold;
|
unsigned congestion_threshold;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When FUSE_CAP_WRITEBACK_CACHE is enabled, the kernel is responsible
|
* When FUSE_CAP_WRITEBACK_CACHE is enabled, the kernel is responsible
|
||||||
* for updating mtime and ctime when write requests are received. The
|
* for updating mtime and ctime when write requests are received. The
|
||||||
* updated values are passed to the filesystem with setattr() requests.
|
* updated values are passed to the filesystem with setattr() requests.
|
||||||
* However, if the filesystem does not support the full resolution of
|
* However, if the filesystem does not support the full resolution of
|
||||||
* the kernel timestamps (nanoseconds), the mtime and ctime values used
|
* the kernel timestamps (nanoseconds), the mtime and ctime values used
|
||||||
* by kernel and filesystem will differ (and result in an apparent
|
* by kernel and filesystem will differ (and result in an apparent
|
||||||
* change of times after a cache flush).
|
* change of times after a cache flush).
|
||||||
*
|
*
|
||||||
* To prevent this problem, this variable can be used to inform the
|
* To prevent this problem, this variable can be used to inform the
|
||||||
* kernel about the timestamp granularity supported by the file-system.
|
* kernel about the timestamp granularity supported by the file-system.
|
||||||
* The value should be power of 10. The default is 1, i.e. full
|
* The value should be power of 10. The default is 1, i.e. full
|
||||||
* nano-second resolution. Filesystems supporting only second resolution
|
* nano-second resolution. Filesystems supporting only second resolution
|
||||||
* should set this to 1000000000.
|
* should set this to 1000000000.
|
||||||
*/
|
*/
|
||||||
unsigned time_gran;
|
unsigned time_gran;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For future use.
|
* For future use.
|
||||||
*/
|
*/
|
||||||
unsigned reserved[22];
|
unsigned reserved[22];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct fuse_session;
|
struct fuse_session;
|
||||||
|
@ -489,21 +507,20 @@ struct fuse_conn_info_opts;
|
||||||
* -o async_read sets FUSE_CAP_ASYNC_READ in conn->want
|
* -o async_read sets FUSE_CAP_ASYNC_READ in conn->want
|
||||||
* -o sync_read unsets FUSE_CAP_ASYNC_READ in conn->want
|
* -o sync_read unsets FUSE_CAP_ASYNC_READ in conn->want
|
||||||
* -o atomic_o_trunc sets FUSE_CAP_ATOMIC_O_TRUNC in conn->want
|
* -o atomic_o_trunc sets FUSE_CAP_ATOMIC_O_TRUNC in conn->want
|
||||||
* -o no_remote_lock Equivalent to -o no_remote_flock,no_remote_posix_lock
|
* -o no_remote_lock Equivalent to -o
|
||||||
* -o no_remote_flock Unsets FUSE_CAP_FLOCK_LOCKS in conn->want
|
*no_remote_flock,no_remote_posix_lock -o no_remote_flock Unsets
|
||||||
* -o no_remote_posix_lock Unsets FUSE_CAP_POSIX_LOCKS in conn->want
|
*FUSE_CAP_FLOCK_LOCKS in conn->want -o no_remote_posix_lock Unsets
|
||||||
* -o [no_]splice_write (un-)sets FUSE_CAP_SPLICE_WRITE in conn->want
|
*FUSE_CAP_POSIX_LOCKS in conn->want -o [no_]splice_write (un-)sets
|
||||||
* -o [no_]splice_move (un-)sets FUSE_CAP_SPLICE_MOVE in conn->want
|
*FUSE_CAP_SPLICE_WRITE in conn->want -o [no_]splice_move (un-)sets
|
||||||
* -o [no_]splice_read (un-)sets FUSE_CAP_SPLICE_READ in conn->want
|
*FUSE_CAP_SPLICE_MOVE in conn->want -o [no_]splice_read (un-)sets
|
||||||
* -o [no_]auto_inval_data (un-)sets FUSE_CAP_AUTO_INVAL_DATA in conn->want
|
*FUSE_CAP_SPLICE_READ in conn->want -o [no_]auto_inval_data (un-)sets
|
||||||
* -o readdirplus=no unsets FUSE_CAP_READDIRPLUS in conn->want
|
*FUSE_CAP_AUTO_INVAL_DATA in conn->want -o readdirplus=no unsets
|
||||||
* -o readdirplus=yes sets FUSE_CAP_READDIRPLUS and unsets
|
*FUSE_CAP_READDIRPLUS in conn->want -o readdirplus=yes sets
|
||||||
* FUSE_CAP_READDIRPLUS_AUTO in conn->want
|
*FUSE_CAP_READDIRPLUS and unsets FUSE_CAP_READDIRPLUS_AUTO in conn->want -o
|
||||||
* -o readdirplus=auto sets FUSE_CAP_READDIRPLUS and
|
*readdirplus=auto sets FUSE_CAP_READDIRPLUS and FUSE_CAP_READDIRPLUS_AUTO
|
||||||
* FUSE_CAP_READDIRPLUS_AUTO in conn->want
|
*in conn->want -o [no_]async_dio (un-)sets FUSE_CAP_ASYNC_DIO in
|
||||||
* -o [no_]async_dio (un-)sets FUSE_CAP_ASYNC_DIO in conn->want
|
*conn->want -o [no_]writeback_cache (un-)sets FUSE_CAP_WRITEBACK_CACHE in
|
||||||
* -o [no_]writeback_cache (un-)sets FUSE_CAP_WRITEBACK_CACHE in conn->want
|
*conn->want -o time_gran=N sets conn->time_gran
|
||||||
* -o time_gran=N sets conn->time_gran
|
|
||||||
*
|
*
|
||||||
* Known options will be removed from *args*, unknown options will be
|
* Known options will be removed from *args*, unknown options will be
|
||||||
* passed through unchanged.
|
* passed through unchanged.
|
||||||
|
@ -511,7 +528,7 @@ struct fuse_conn_info_opts;
|
||||||
* @param args argument vector (input+output)
|
* @param args argument vector (input+output)
|
||||||
* @return parsed options
|
* @return parsed options
|
||||||
**/
|
**/
|
||||||
struct fuse_conn_info_opts* fuse_parse_conn_info_opts(struct fuse_args *args);
|
struct fuse_conn_info_opts *fuse_parse_conn_info_opts(struct fuse_args *args);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function applies the (parsed) parameters in *opts* to the
|
* This function applies the (parsed) parameters in *opts* to the
|
||||||
|
@ -521,7 +538,7 @@ struct fuse_conn_info_opts* fuse_parse_conn_info_opts(struct fuse_args *args);
|
||||||
* option has been explicitly set.
|
* option has been explicitly set.
|
||||||
*/
|
*/
|
||||||
void fuse_apply_conn_info_opts(struct fuse_conn_info_opts *opts,
|
void fuse_apply_conn_info_opts(struct fuse_conn_info_opts *opts,
|
||||||
struct fuse_conn_info *conn);
|
struct fuse_conn_info *conn);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Go into the background
|
* Go into the background
|
||||||
|
@ -552,81 +569,81 @@ const char *fuse_pkgversion(void);
|
||||||
*/
|
*/
|
||||||
void fuse_pollhandle_destroy(struct fuse_pollhandle *ph);
|
void fuse_pollhandle_destroy(struct fuse_pollhandle *ph);
|
||||||
|
|
||||||
/* ----------------------------------------------------------- *
|
/*
|
||||||
* Data buffer *
|
* Data buffer
|
||||||
* ----------------------------------------------------------- */
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Buffer flags
|
* Buffer flags
|
||||||
*/
|
*/
|
||||||
enum fuse_buf_flags {
|
enum fuse_buf_flags {
|
||||||
/**
|
/**
|
||||||
* Buffer contains a file descriptor
|
* Buffer contains a file descriptor
|
||||||
*
|
*
|
||||||
* If this flag is set, the .fd field is valid, otherwise the
|
* If this flag is set, the .fd field is valid, otherwise the
|
||||||
* .mem fields is valid.
|
* .mem fields is valid.
|
||||||
*/
|
*/
|
||||||
FUSE_BUF_IS_FD = (1 << 1),
|
FUSE_BUF_IS_FD = (1 << 1),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Seek on the file descriptor
|
* Seek on the file descriptor
|
||||||
*
|
*
|
||||||
* If this flag is set then the .pos field is valid and is
|
* If this flag is set then the .pos field is valid and is
|
||||||
* used to seek to the given offset before performing
|
* used to seek to the given offset before performing
|
||||||
* operation on file descriptor.
|
* operation on file descriptor.
|
||||||
*/
|
*/
|
||||||
FUSE_BUF_FD_SEEK = (1 << 2),
|
FUSE_BUF_FD_SEEK = (1 << 2),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retry operation on file descriptor
|
* Retry operation on file descriptor
|
||||||
*
|
*
|
||||||
* If this flag is set then retry operation on file descriptor
|
* If this flag is set then retry operation on file descriptor
|
||||||
* until .size bytes have been copied or an error or EOF is
|
* until .size bytes have been copied or an error or EOF is
|
||||||
* detected.
|
* detected.
|
||||||
*/
|
*/
|
||||||
FUSE_BUF_FD_RETRY = (1 << 3),
|
FUSE_BUF_FD_RETRY = (1 << 3),
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Buffer copy flags
|
* Buffer copy flags
|
||||||
*/
|
*/
|
||||||
enum fuse_buf_copy_flags {
|
enum fuse_buf_copy_flags {
|
||||||
/**
|
/**
|
||||||
* Don't use splice(2)
|
* Don't use splice(2)
|
||||||
*
|
*
|
||||||
* Always fall back to using read and write instead of
|
* Always fall back to using read and write instead of
|
||||||
* splice(2) to copy data from one file descriptor to another.
|
* splice(2) to copy data from one file descriptor to another.
|
||||||
*
|
*
|
||||||
* If this flag is not set, then only fall back if splice is
|
* If this flag is not set, then only fall back if splice is
|
||||||
* unavailable.
|
* unavailable.
|
||||||
*/
|
*/
|
||||||
FUSE_BUF_NO_SPLICE = (1 << 1),
|
FUSE_BUF_NO_SPLICE = (1 << 1),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Force splice
|
* Force splice
|
||||||
*
|
*
|
||||||
* Always use splice(2) to copy data from one file descriptor
|
* Always use splice(2) to copy data from one file descriptor
|
||||||
* to another. If splice is not available, return -EINVAL.
|
* to another. If splice is not available, return -EINVAL.
|
||||||
*/
|
*/
|
||||||
FUSE_BUF_FORCE_SPLICE = (1 << 2),
|
FUSE_BUF_FORCE_SPLICE = (1 << 2),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Try to move data with splice.
|
* Try to move data with splice.
|
||||||
*
|
*
|
||||||
* If splice is used, try to move pages from the source to the
|
* If splice is used, try to move pages from the source to the
|
||||||
* destination instead of copying. See documentation of
|
* destination instead of copying. See documentation of
|
||||||
* SPLICE_F_MOVE in splice(2) man page.
|
* SPLICE_F_MOVE in splice(2) man page.
|
||||||
*/
|
*/
|
||||||
FUSE_BUF_SPLICE_MOVE = (1 << 3),
|
FUSE_BUF_SPLICE_MOVE = (1 << 3),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Don't block on the pipe when copying data with splice
|
* Don't block on the pipe when copying data with splice
|
||||||
*
|
*
|
||||||
* Makes the operations on the pipe non-blocking (if the pipe
|
* Makes the operations on the pipe non-blocking (if the pipe
|
||||||
* is full or empty). See SPLICE_F_NONBLOCK in the splice(2)
|
* is full or empty). See SPLICE_F_NONBLOCK in the splice(2)
|
||||||
* man page.
|
* man page.
|
||||||
*/
|
*/
|
||||||
FUSE_BUF_SPLICE_NONBLOCK= (1 << 4),
|
FUSE_BUF_SPLICE_NONBLOCK = (1 << 4),
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -636,36 +653,36 @@ enum fuse_buf_copy_flags {
|
||||||
* be supplied as a memory pointer or as a file descriptor
|
* be supplied as a memory pointer or as a file descriptor
|
||||||
*/
|
*/
|
||||||
struct fuse_buf {
|
struct fuse_buf {
|
||||||
/**
|
/**
|
||||||
* Size of data in bytes
|
* Size of data in bytes
|
||||||
*/
|
*/
|
||||||
size_t size;
|
size_t size;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Buffer flags
|
* Buffer flags
|
||||||
*/
|
*/
|
||||||
enum fuse_buf_flags flags;
|
enum fuse_buf_flags flags;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Memory pointer
|
* Memory pointer
|
||||||
*
|
*
|
||||||
* Used unless FUSE_BUF_IS_FD flag is set.
|
* Used unless FUSE_BUF_IS_FD flag is set.
|
||||||
*/
|
*/
|
||||||
void *mem;
|
void *mem;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* File descriptor
|
* File descriptor
|
||||||
*
|
*
|
||||||
* Used if FUSE_BUF_IS_FD flag is set.
|
* Used if FUSE_BUF_IS_FD flag is set.
|
||||||
*/
|
*/
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* File position
|
* File position
|
||||||
*
|
*
|
||||||
* Used if FUSE_BUF_FD_SEEK flag is set.
|
* Used if FUSE_BUF_FD_SEEK flag is set.
|
||||||
*/
|
*/
|
||||||
off_t pos;
|
off_t pos;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -677,41 +694,39 @@ struct fuse_buf {
|
||||||
* Allocate dynamically to add more than one buffer.
|
* Allocate dynamically to add more than one buffer.
|
||||||
*/
|
*/
|
||||||
struct fuse_bufvec {
|
struct fuse_bufvec {
|
||||||
/**
|
/**
|
||||||
* Number of buffers in the array
|
* Number of buffers in the array
|
||||||
*/
|
*/
|
||||||
size_t count;
|
size_t count;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Index of current buffer within the array
|
* Index of current buffer within the array
|
||||||
*/
|
*/
|
||||||
size_t idx;
|
size_t idx;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Current offset within the current buffer
|
* Current offset within the current buffer
|
||||||
*/
|
*/
|
||||||
size_t off;
|
size_t off;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Array of buffers
|
* Array of buffers
|
||||||
*/
|
*/
|
||||||
struct fuse_buf buf[1];
|
struct fuse_buf buf[1];
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Initialize bufvec with a single buffer of given size */
|
/* Initialize bufvec with a single buffer of given size */
|
||||||
#define FUSE_BUFVEC_INIT(size__) \
|
#define FUSE_BUFVEC_INIT(size__) \
|
||||||
((struct fuse_bufvec) { \
|
((struct fuse_bufvec){ /* .count= */ 1, \
|
||||||
/* .count= */ 1, \
|
/* .idx = */ 0, \
|
||||||
/* .idx = */ 0, \
|
/* .off = */ 0, /* .buf = */ \
|
||||||
/* .off = */ 0, \
|
{ /* [0] = */ { \
|
||||||
/* .buf = */ { /* [0] = */ { \
|
/* .size = */ (size__), \
|
||||||
/* .size = */ (size__), \
|
/* .flags = */ (enum fuse_buf_flags)0, \
|
||||||
/* .flags = */ (enum fuse_buf_flags) 0, \
|
/* .mem = */ NULL, \
|
||||||
/* .mem = */ NULL, \
|
/* .fd = */ -1, \
|
||||||
/* .fd = */ -1, \
|
/* .pos = */ 0, \
|
||||||
/* .pos = */ 0, \
|
} } })
|
||||||
} } \
|
|
||||||
} )
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get total size of data in a fuse buffer vector
|
* Get total size of data in a fuse buffer vector
|
||||||
|
@ -730,16 +745,16 @@ size_t fuse_buf_size(const struct fuse_bufvec *bufv);
|
||||||
* @return actual number of bytes copied or -errno on error
|
* @return actual number of bytes copied or -errno on error
|
||||||
*/
|
*/
|
||||||
ssize_t fuse_buf_copy(struct fuse_bufvec *dst, struct fuse_bufvec *src,
|
ssize_t fuse_buf_copy(struct fuse_bufvec *dst, struct fuse_bufvec *src,
|
||||||
enum fuse_buf_copy_flags flags);
|
enum fuse_buf_copy_flags flags);
|
||||||
|
|
||||||
/* ----------------------------------------------------------- *
|
/*
|
||||||
* Signal handling *
|
* Signal handling
|
||||||
* ----------------------------------------------------------- */
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exit session on HUP, TERM and INT signals and ignore PIPE signal
|
* Exit session on HUP, TERM and INT signals and ignore PIPE signal
|
||||||
*
|
*
|
||||||
* Stores session in a global variable. May only be called once per
|
* Stores session in a global variable. May only be called once per
|
||||||
* process until fuse_remove_signal_handlers() is called.
|
* process until fuse_remove_signal_handlers() is called.
|
||||||
*
|
*
|
||||||
* Once either of the POSIX signals arrives, the signal handler calls
|
* Once either of the POSIX signals arrives, the signal handler calls
|
||||||
|
@ -766,12 +781,12 @@ int fuse_set_signal_handlers(struct fuse_session *se);
|
||||||
*/
|
*/
|
||||||
void fuse_remove_signal_handlers(struct fuse_session *se);
|
void fuse_remove_signal_handlers(struct fuse_session *se);
|
||||||
|
|
||||||
/* ----------------------------------------------------------- *
|
/*
|
||||||
* Compatibility stuff *
|
* Compatibility stuff
|
||||||
* ----------------------------------------------------------- */
|
*/
|
||||||
|
|
||||||
#if !defined(FUSE_USE_VERSION) || FUSE_USE_VERSION < 30
|
#if !defined(FUSE_USE_VERSION) || FUSE_USE_VERSION < 30
|
||||||
# error only API version 30 or greater is supported
|
#error only API version 30 or greater is supported
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -781,11 +796,14 @@ void fuse_remove_signal_handlers(struct fuse_session *se);
|
||||||
* On 32bit systems please add -D_FILE_OFFSET_BITS=64 to your compile flags!
|
* On 32bit systems please add -D_FILE_OFFSET_BITS=64 to your compile flags!
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if defined(__GNUC__) && (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 6) && !defined __cplusplus
|
#if defined(__GNUC__) && \
|
||||||
|
(__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 6) && \
|
||||||
|
!defined __cplusplus
|
||||||
_Static_assert(sizeof(off_t) == 8, "fuse: off_t must be 64bit");
|
_Static_assert(sizeof(off_t) == 8, "fuse: off_t must be 64bit");
|
||||||
#else
|
#else
|
||||||
struct _fuse_off_t_must_be_64bit_dummy_struct \
|
struct _fuse_off_t_must_be_64bit_dummy_struct {
|
||||||
{ unsigned _fuse_off_t_must_be_64bit:((sizeof(off_t) == 8) ? 1 : -1); };
|
unsigned _fuse_off_t_must_be_64bit:((sizeof(off_t) == 8) ? 1 : -1);
|
||||||
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* FUSE_COMMON_H_ */
|
#endif /* FUSE_COMMON_H_ */
|
||||||
|
|
|
@ -1,71 +1,71 @@
|
||||||
/*
|
/*
|
||||||
FUSE: Filesystem in Userspace
|
* FUSE: Filesystem in Userspace
|
||||||
Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
|
* Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
|
||||||
|
*
|
||||||
This program can be distributed under the terms of the GNU LGPLv2.
|
* This program can be distributed under the terms of the GNU LGPLv2.
|
||||||
See the file COPYING.LIB
|
* See the file COPYING.LIB
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "fuse.h"
|
#include "fuse.h"
|
||||||
#include "fuse_lowlevel.h"
|
#include "fuse_lowlevel.h"
|
||||||
|
|
||||||
struct fuse_req {
|
struct fuse_req {
|
||||||
struct fuse_session *se;
|
struct fuse_session *se;
|
||||||
uint64_t unique;
|
uint64_t unique;
|
||||||
int ctr;
|
int ctr;
|
||||||
pthread_mutex_t lock;
|
pthread_mutex_t lock;
|
||||||
struct fuse_ctx ctx;
|
struct fuse_ctx ctx;
|
||||||
struct fuse_chan *ch;
|
struct fuse_chan *ch;
|
||||||
int interrupted;
|
int interrupted;
|
||||||
unsigned int ioctl_64bit : 1;
|
unsigned int ioctl_64bit:1;
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
uint64_t unique;
|
uint64_t unique;
|
||||||
} i;
|
} i;
|
||||||
struct {
|
struct {
|
||||||
fuse_interrupt_func_t func;
|
fuse_interrupt_func_t func;
|
||||||
void *data;
|
void *data;
|
||||||
} ni;
|
} ni;
|
||||||
} u;
|
} u;
|
||||||
struct fuse_req *next;
|
struct fuse_req *next;
|
||||||
struct fuse_req *prev;
|
struct fuse_req *prev;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct fuse_notify_req {
|
struct fuse_notify_req {
|
||||||
uint64_t unique;
|
uint64_t unique;
|
||||||
void (*reply)(struct fuse_notify_req *, fuse_req_t, fuse_ino_t,
|
void (*reply)(struct fuse_notify_req *, fuse_req_t, fuse_ino_t,
|
||||||
const void *, const struct fuse_buf *);
|
const void *, const struct fuse_buf *);
|
||||||
struct fuse_notify_req *next;
|
struct fuse_notify_req *next;
|
||||||
struct fuse_notify_req *prev;
|
struct fuse_notify_req *prev;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct fuse_session {
|
struct fuse_session {
|
||||||
char *mountpoint;
|
char *mountpoint;
|
||||||
volatile int exited;
|
volatile int exited;
|
||||||
int fd;
|
int fd;
|
||||||
int debug;
|
int debug;
|
||||||
int deny_others;
|
int deny_others;
|
||||||
struct fuse_lowlevel_ops op;
|
struct fuse_lowlevel_ops op;
|
||||||
int got_init;
|
int got_init;
|
||||||
struct cuse_data *cuse_data;
|
struct cuse_data *cuse_data;
|
||||||
void *userdata;
|
void *userdata;
|
||||||
uid_t owner;
|
uid_t owner;
|
||||||
struct fuse_conn_info conn;
|
struct fuse_conn_info conn;
|
||||||
struct fuse_req list;
|
struct fuse_req list;
|
||||||
struct fuse_req interrupts;
|
struct fuse_req interrupts;
|
||||||
pthread_mutex_t lock;
|
pthread_mutex_t lock;
|
||||||
int got_destroy;
|
int got_destroy;
|
||||||
int broken_splice_nonblock;
|
int broken_splice_nonblock;
|
||||||
uint64_t notify_ctr;
|
uint64_t notify_ctr;
|
||||||
struct fuse_notify_req notify_list;
|
struct fuse_notify_req notify_list;
|
||||||
size_t bufsize;
|
size_t bufsize;
|
||||||
int error;
|
int error;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct fuse_chan {
|
struct fuse_chan {
|
||||||
pthread_mutex_t lock;
|
pthread_mutex_t lock;
|
||||||
int ctr;
|
int ctr;
|
||||||
int fd;
|
int fd;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -76,19 +76,20 @@ struct fuse_chan {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
struct fuse_module {
|
struct fuse_module {
|
||||||
char *name;
|
char *name;
|
||||||
fuse_module_factory_t factory;
|
fuse_module_factory_t factory;
|
||||||
struct fuse_module *next;
|
struct fuse_module *next;
|
||||||
struct fusemod_so *so;
|
struct fusemod_so *so;
|
||||||
int ctr;
|
int ctr;
|
||||||
};
|
};
|
||||||
|
|
||||||
int fuse_send_reply_iov_nofree(fuse_req_t req, int error, struct iovec *iov,
|
int fuse_send_reply_iov_nofree(fuse_req_t req, int error, struct iovec *iov,
|
||||||
int count);
|
int count);
|
||||||
void fuse_free_req(fuse_req_t req);
|
void fuse_free_req(fuse_req_t req);
|
||||||
|
|
||||||
void fuse_session_process_buf_int(struct fuse_session *se,
|
void fuse_session_process_buf_int(struct fuse_session *se,
|
||||||
const struct fuse_buf *buf, struct fuse_chan *ch);
|
const struct fuse_buf *buf,
|
||||||
|
struct fuse_chan *ch);
|
||||||
|
|
||||||
|
|
||||||
#define FUSE_MAX_MAX_PAGES 256
|
#define FUSE_MAX_MAX_PAGES 256
|
||||||
|
|
|
@ -1,40 +1,40 @@
|
||||||
/*
|
/*
|
||||||
FUSE: Filesystem in Userspace
|
* FUSE: Filesystem in Userspace
|
||||||
Copyright (C) 2019 Red Hat, Inc.
|
* Copyright (C) 2019 Red Hat, Inc.
|
||||||
|
*
|
||||||
Logging API.
|
* Logging API.
|
||||||
|
*
|
||||||
This program can be distributed under the terms of the GNU LGPLv2.
|
* This program can be distributed under the terms of the GNU LGPLv2.
|
||||||
See the file COPYING.LIB
|
* See the file COPYING.LIB
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "fuse_log.h"
|
#include "fuse_log.h"
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
static void default_log_func(
|
static void default_log_func(__attribute__((unused)) enum fuse_log_level level,
|
||||||
__attribute__(( unused )) enum fuse_log_level level,
|
const char *fmt, va_list ap)
|
||||||
const char *fmt, va_list ap)
|
|
||||||
{
|
{
|
||||||
vfprintf(stderr, fmt, ap);
|
vfprintf(stderr, fmt, ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
static fuse_log_func_t log_func = default_log_func;
|
static fuse_log_func_t log_func = default_log_func;
|
||||||
|
|
||||||
void fuse_set_log_func(fuse_log_func_t func)
|
void fuse_set_log_func(fuse_log_func_t func)
|
||||||
{
|
{
|
||||||
if (!func)
|
if (!func) {
|
||||||
func = default_log_func;
|
func = default_log_func;
|
||||||
|
}
|
||||||
|
|
||||||
log_func = func;
|
log_func = func;
|
||||||
}
|
}
|
||||||
|
|
||||||
void fuse_log(enum fuse_log_level level, const char *fmt, ...)
|
void fuse_log(enum fuse_log_level level, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
log_func(level, fmt, ap);
|
log_func(level, fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
/*
|
/*
|
||||||
FUSE: Filesystem in Userspace
|
* FUSE: Filesystem in Userspace
|
||||||
Copyright (C) 2019 Red Hat, Inc.
|
* Copyright (C) 2019 Red Hat, Inc.
|
||||||
|
*
|
||||||
This program can be distributed under the terms of the GNU LGPLv2.
|
* This program can be distributed under the terms of the GNU LGPLv2.
|
||||||
See the file COPYING.LIB.
|
* See the file COPYING.LIB.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef FUSE_LOG_H_
|
#ifndef FUSE_LOG_H_
|
||||||
#define FUSE_LOG_H_
|
#define FUSE_LOG_H_
|
||||||
|
@ -22,14 +22,14 @@
|
||||||
* These levels correspond to syslog(2) log levels since they are widely used.
|
* These levels correspond to syslog(2) log levels since they are widely used.
|
||||||
*/
|
*/
|
||||||
enum fuse_log_level {
|
enum fuse_log_level {
|
||||||
FUSE_LOG_EMERG,
|
FUSE_LOG_EMERG,
|
||||||
FUSE_LOG_ALERT,
|
FUSE_LOG_ALERT,
|
||||||
FUSE_LOG_CRIT,
|
FUSE_LOG_CRIT,
|
||||||
FUSE_LOG_ERR,
|
FUSE_LOG_ERR,
|
||||||
FUSE_LOG_WARNING,
|
FUSE_LOG_WARNING,
|
||||||
FUSE_LOG_NOTICE,
|
FUSE_LOG_NOTICE,
|
||||||
FUSE_LOG_INFO,
|
FUSE_LOG_INFO,
|
||||||
FUSE_LOG_DEBUG
|
FUSE_LOG_DEBUG
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -45,8 +45,8 @@ enum fuse_log_level {
|
||||||
* @param fmt sprintf-style format string including newline
|
* @param fmt sprintf-style format string including newline
|
||||||
* @param ap format string arguments
|
* @param ap format string arguments
|
||||||
*/
|
*/
|
||||||
typedef void (*fuse_log_func_t)(enum fuse_log_level level,
|
typedef void (*fuse_log_func_t)(enum fuse_log_level level, const char *fmt,
|
||||||
const char *fmt, va_list ap);
|
va_list ap);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Install a custom log handler function.
|
* Install a custom log handler function.
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,18 +1,18 @@
|
||||||
/*
|
/*
|
||||||
FUSE: Filesystem in Userspace
|
* FUSE: Filesystem in Userspace
|
||||||
Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
|
* Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
|
||||||
|
*
|
||||||
This program can be distributed under the terms of the GNU LGPLv2.
|
* This program can be distributed under the terms of the GNU LGPLv2.
|
||||||
See the file COPYING.LIB
|
* See the file COPYING.LIB
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Versioned symbols cannot be used in some cases because it
|
* Versioned symbols cannot be used in some cases because it
|
||||||
- confuse the dynamic linker in uClibc
|
* - confuse the dynamic linker in uClibc
|
||||||
- not supported on MacOSX (in MachO binary format)
|
* - not supported on MacOSX (in MachO binary format)
|
||||||
*/
|
*/
|
||||||
#if (!defined(__UCLIBC__) && !defined(__APPLE__))
|
#if (!defined(__UCLIBC__) && !defined(__APPLE__))
|
||||||
#define FUSE_SYMVER(x) __asm__(x)
|
#define FUSE_SYMVER(x) __asm__(x)
|
||||||
#else
|
#else
|
||||||
|
@ -25,11 +25,11 @@
|
||||||
/* Is this hack still needed? */
|
/* Is this hack still needed? */
|
||||||
static inline void fuse_mutex_init(pthread_mutex_t *mut)
|
static inline void fuse_mutex_init(pthread_mutex_t *mut)
|
||||||
{
|
{
|
||||||
pthread_mutexattr_t attr;
|
pthread_mutexattr_t attr;
|
||||||
pthread_mutexattr_init(&attr);
|
pthread_mutexattr_init(&attr);
|
||||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ADAPTIVE_NP);
|
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ADAPTIVE_NP);
|
||||||
pthread_mutex_init(mut, &attr);
|
pthread_mutex_init(mut, &attr);
|
||||||
pthread_mutexattr_destroy(&attr);
|
pthread_mutexattr_destroy(&attr);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -1,423 +1,450 @@
|
||||||
/*
|
/*
|
||||||
FUSE: Filesystem in Userspace
|
* FUSE: Filesystem in Userspace
|
||||||
Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
|
* Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
|
||||||
|
*
|
||||||
Implementation of option parsing routines (dealing with `struct
|
* Implementation of option parsing routines (dealing with `struct
|
||||||
fuse_args`).
|
* fuse_args`).
|
||||||
|
*
|
||||||
This program can be distributed under the terms of the GNU LGPLv2.
|
* This program can be distributed under the terms of the GNU LGPLv2.
|
||||||
See the file COPYING.LIB
|
* See the file COPYING.LIB
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "fuse_opt.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "fuse_i.h"
|
#include "fuse_i.h"
|
||||||
#include "fuse_opt.h"
|
|
||||||
#include "fuse_misc.h"
|
#include "fuse_misc.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
struct fuse_opt_context {
|
struct fuse_opt_context {
|
||||||
void *data;
|
void *data;
|
||||||
const struct fuse_opt *opt;
|
const struct fuse_opt *opt;
|
||||||
fuse_opt_proc_t proc;
|
fuse_opt_proc_t proc;
|
||||||
int argctr;
|
int argctr;
|
||||||
int argc;
|
int argc;
|
||||||
char **argv;
|
char **argv;
|
||||||
struct fuse_args outargs;
|
struct fuse_args outargs;
|
||||||
char *opts;
|
char *opts;
|
||||||
int nonopt;
|
int nonopt;
|
||||||
};
|
};
|
||||||
|
|
||||||
void fuse_opt_free_args(struct fuse_args *args)
|
void fuse_opt_free_args(struct fuse_args *args)
|
||||||
{
|
{
|
||||||
if (args) {
|
if (args) {
|
||||||
if (args->argv && args->allocated) {
|
if (args->argv && args->allocated) {
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < args->argc; i++)
|
for (i = 0; i < args->argc; i++) {
|
||||||
free(args->argv[i]);
|
free(args->argv[i]);
|
||||||
free(args->argv);
|
}
|
||||||
}
|
free(args->argv);
|
||||||
args->argc = 0;
|
}
|
||||||
args->argv = NULL;
|
args->argc = 0;
|
||||||
args->allocated = 0;
|
args->argv = NULL;
|
||||||
}
|
args->allocated = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int alloc_failed(void)
|
static int alloc_failed(void)
|
||||||
{
|
{
|
||||||
fuse_log(FUSE_LOG_ERR, "fuse: memory allocation failed\n");
|
fuse_log(FUSE_LOG_ERR, "fuse: memory allocation failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fuse_opt_add_arg(struct fuse_args *args, const char *arg)
|
int fuse_opt_add_arg(struct fuse_args *args, const char *arg)
|
||||||
{
|
{
|
||||||
char **newargv;
|
char **newargv;
|
||||||
char *newarg;
|
char *newarg;
|
||||||
|
|
||||||
assert(!args->argv || args->allocated);
|
assert(!args->argv || args->allocated);
|
||||||
|
|
||||||
newarg = strdup(arg);
|
newarg = strdup(arg);
|
||||||
if (!newarg)
|
if (!newarg) {
|
||||||
return alloc_failed();
|
return alloc_failed();
|
||||||
|
}
|
||||||
|
|
||||||
newargv = realloc(args->argv, (args->argc + 2) * sizeof(char *));
|
newargv = realloc(args->argv, (args->argc + 2) * sizeof(char *));
|
||||||
if (!newargv) {
|
if (!newargv) {
|
||||||
free(newarg);
|
free(newarg);
|
||||||
return alloc_failed();
|
return alloc_failed();
|
||||||
}
|
}
|
||||||
|
|
||||||
args->argv = newargv;
|
args->argv = newargv;
|
||||||
args->allocated = 1;
|
args->allocated = 1;
|
||||||
args->argv[args->argc++] = newarg;
|
args->argv[args->argc++] = newarg;
|
||||||
args->argv[args->argc] = NULL;
|
args->argv[args->argc] = NULL;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fuse_opt_insert_arg_common(struct fuse_args *args, int pos,
|
static int fuse_opt_insert_arg_common(struct fuse_args *args, int pos,
|
||||||
const char *arg)
|
const char *arg)
|
||||||
{
|
{
|
||||||
assert(pos <= args->argc);
|
assert(pos <= args->argc);
|
||||||
if (fuse_opt_add_arg(args, arg) == -1)
|
if (fuse_opt_add_arg(args, arg) == -1) {
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (pos != args->argc - 1) {
|
if (pos != args->argc - 1) {
|
||||||
char *newarg = args->argv[args->argc - 1];
|
char *newarg = args->argv[args->argc - 1];
|
||||||
memmove(&args->argv[pos + 1], &args->argv[pos],
|
memmove(&args->argv[pos + 1], &args->argv[pos],
|
||||||
sizeof(char *) * (args->argc - pos - 1));
|
sizeof(char *) * (args->argc - pos - 1));
|
||||||
args->argv[pos] = newarg;
|
args->argv[pos] = newarg;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fuse_opt_insert_arg(struct fuse_args *args, int pos, const char *arg)
|
int fuse_opt_insert_arg(struct fuse_args *args, int pos, const char *arg)
|
||||||
{
|
{
|
||||||
return fuse_opt_insert_arg_common(args, pos, arg);
|
return fuse_opt_insert_arg_common(args, pos, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int next_arg(struct fuse_opt_context *ctx, const char *opt)
|
static int next_arg(struct fuse_opt_context *ctx, const char *opt)
|
||||||
{
|
{
|
||||||
if (ctx->argctr + 1 >= ctx->argc) {
|
if (ctx->argctr + 1 >= ctx->argc) {
|
||||||
fuse_log(FUSE_LOG_ERR, "fuse: missing argument after `%s'\n", opt);
|
fuse_log(FUSE_LOG_ERR, "fuse: missing argument after `%s'\n", opt);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
ctx->argctr++;
|
ctx->argctr++;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int add_arg(struct fuse_opt_context *ctx, const char *arg)
|
static int add_arg(struct fuse_opt_context *ctx, const char *arg)
|
||||||
{
|
{
|
||||||
return fuse_opt_add_arg(&ctx->outargs, arg);
|
return fuse_opt_add_arg(&ctx->outargs, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int add_opt_common(char **opts, const char *opt, int esc)
|
static int add_opt_common(char **opts, const char *opt, int esc)
|
||||||
{
|
{
|
||||||
unsigned oldlen = *opts ? strlen(*opts) : 0;
|
unsigned oldlen = *opts ? strlen(*opts) : 0;
|
||||||
char *d = realloc(*opts, oldlen + 1 + strlen(opt) * 2 + 1);
|
char *d = realloc(*opts, oldlen + 1 + strlen(opt) * 2 + 1);
|
||||||
|
|
||||||
if (!d)
|
if (!d) {
|
||||||
return alloc_failed();
|
return alloc_failed();
|
||||||
|
}
|
||||||
|
|
||||||
*opts = d;
|
*opts = d;
|
||||||
if (oldlen) {
|
if (oldlen) {
|
||||||
d += oldlen;
|
d += oldlen;
|
||||||
*d++ = ',';
|
*d++ = ',';
|
||||||
}
|
}
|
||||||
|
|
||||||
for (; *opt; opt++) {
|
for (; *opt; opt++) {
|
||||||
if (esc && (*opt == ',' || *opt == '\\'))
|
if (esc && (*opt == ',' || *opt == '\\')) {
|
||||||
*d++ = '\\';
|
*d++ = '\\';
|
||||||
*d++ = *opt;
|
}
|
||||||
}
|
*d++ = *opt;
|
||||||
*d = '\0';
|
}
|
||||||
|
*d = '\0';
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fuse_opt_add_opt(char **opts, const char *opt)
|
int fuse_opt_add_opt(char **opts, const char *opt)
|
||||||
{
|
{
|
||||||
return add_opt_common(opts, opt, 0);
|
return add_opt_common(opts, opt, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int fuse_opt_add_opt_escaped(char **opts, const char *opt)
|
int fuse_opt_add_opt_escaped(char **opts, const char *opt)
|
||||||
{
|
{
|
||||||
return add_opt_common(opts, opt, 1);
|
return add_opt_common(opts, opt, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int add_opt(struct fuse_opt_context *ctx, const char *opt)
|
static int add_opt(struct fuse_opt_context *ctx, const char *opt)
|
||||||
{
|
{
|
||||||
return add_opt_common(&ctx->opts, opt, 1);
|
return add_opt_common(&ctx->opts, opt, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int call_proc(struct fuse_opt_context *ctx, const char *arg, int key,
|
static int call_proc(struct fuse_opt_context *ctx, const char *arg, int key,
|
||||||
int iso)
|
int iso)
|
||||||
{
|
{
|
||||||
if (key == FUSE_OPT_KEY_DISCARD)
|
if (key == FUSE_OPT_KEY_DISCARD) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (key != FUSE_OPT_KEY_KEEP && ctx->proc) {
|
if (key != FUSE_OPT_KEY_KEEP && ctx->proc) {
|
||||||
int res = ctx->proc(ctx->data, arg, key, &ctx->outargs);
|
int res = ctx->proc(ctx->data, arg, key, &ctx->outargs);
|
||||||
if (res == -1 || !res)
|
if (res == -1 || !res) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
if (iso)
|
}
|
||||||
return add_opt(ctx, arg);
|
if (iso) {
|
||||||
else
|
return add_opt(ctx, arg);
|
||||||
return add_arg(ctx, arg);
|
} else {
|
||||||
|
return add_arg(ctx, arg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int match_template(const char *t, const char *arg, unsigned *sepp)
|
static int match_template(const char *t, const char *arg, unsigned *sepp)
|
||||||
{
|
{
|
||||||
int arglen = strlen(arg);
|
int arglen = strlen(arg);
|
||||||
const char *sep = strchr(t, '=');
|
const char *sep = strchr(t, '=');
|
||||||
sep = sep ? sep : strchr(t, ' ');
|
sep = sep ? sep : strchr(t, ' ');
|
||||||
if (sep && (!sep[1] || sep[1] == '%')) {
|
if (sep && (!sep[1] || sep[1] == '%')) {
|
||||||
int tlen = sep - t;
|
int tlen = sep - t;
|
||||||
if (sep[0] == '=')
|
if (sep[0] == '=') {
|
||||||
tlen ++;
|
tlen++;
|
||||||
if (arglen >= tlen && strncmp(arg, t, tlen) == 0) {
|
}
|
||||||
*sepp = sep - t;
|
if (arglen >= tlen && strncmp(arg, t, tlen) == 0) {
|
||||||
return 1;
|
*sepp = sep - t;
|
||||||
}
|
return 1;
|
||||||
}
|
}
|
||||||
if (strcmp(t, arg) == 0) {
|
}
|
||||||
*sepp = 0;
|
if (strcmp(t, arg) == 0) {
|
||||||
return 1;
|
*sepp = 0;
|
||||||
}
|
return 1;
|
||||||
return 0;
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct fuse_opt *find_opt(const struct fuse_opt *opt,
|
static const struct fuse_opt *find_opt(const struct fuse_opt *opt,
|
||||||
const char *arg, unsigned *sepp)
|
const char *arg, unsigned *sepp)
|
||||||
{
|
{
|
||||||
for (; opt && opt->templ; opt++)
|
for (; opt && opt->templ; opt++) {
|
||||||
if (match_template(opt->templ, arg, sepp))
|
if (match_template(opt->templ, arg, sepp)) {
|
||||||
return opt;
|
return opt;
|
||||||
return NULL;
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fuse_opt_match(const struct fuse_opt *opts, const char *opt)
|
int fuse_opt_match(const struct fuse_opt *opts, const char *opt)
|
||||||
{
|
{
|
||||||
unsigned dummy;
|
unsigned dummy;
|
||||||
return find_opt(opts, opt, &dummy) ? 1 : 0;
|
return find_opt(opts, opt, &dummy) ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int process_opt_param(void *var, const char *format, const char *param,
|
static int process_opt_param(void *var, const char *format, const char *param,
|
||||||
const char *arg)
|
const char *arg)
|
||||||
{
|
{
|
||||||
assert(format[0] == '%');
|
assert(format[0] == '%');
|
||||||
if (format[1] == 's') {
|
if (format[1] == 's') {
|
||||||
char **s = var;
|
char **s = var;
|
||||||
char *copy = strdup(param);
|
char *copy = strdup(param);
|
||||||
if (!copy)
|
if (!copy) {
|
||||||
return alloc_failed();
|
return alloc_failed();
|
||||||
|
}
|
||||||
|
|
||||||
free(*s);
|
free(*s);
|
||||||
*s = copy;
|
*s = copy;
|
||||||
} else {
|
} else {
|
||||||
if (sscanf(param, format, var) != 1) {
|
if (sscanf(param, format, var) != 1) {
|
||||||
fuse_log(FUSE_LOG_ERR, "fuse: invalid parameter in option `%s'\n", arg);
|
fuse_log(FUSE_LOG_ERR, "fuse: invalid parameter in option `%s'\n",
|
||||||
return -1;
|
arg);
|
||||||
}
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int process_opt(struct fuse_opt_context *ctx,
|
static int process_opt(struct fuse_opt_context *ctx, const struct fuse_opt *opt,
|
||||||
const struct fuse_opt *opt, unsigned sep,
|
unsigned sep, const char *arg, int iso)
|
||||||
const char *arg, int iso)
|
|
||||||
{
|
{
|
||||||
if (opt->offset == -1U) {
|
if (opt->offset == -1U) {
|
||||||
if (call_proc(ctx, arg, opt->value, iso) == -1)
|
if (call_proc(ctx, arg, opt->value, iso) == -1) {
|
||||||
return -1;
|
return -1;
|
||||||
} else {
|
}
|
||||||
void *var = (char *)ctx->data + opt->offset;
|
} else {
|
||||||
if (sep && opt->templ[sep + 1]) {
|
void *var = (char *)ctx->data + opt->offset;
|
||||||
const char *param = arg + sep;
|
if (sep && opt->templ[sep + 1]) {
|
||||||
if (opt->templ[sep] == '=')
|
const char *param = arg + sep;
|
||||||
param ++;
|
if (opt->templ[sep] == '=') {
|
||||||
if (process_opt_param(var, opt->templ + sep + 1,
|
param++;
|
||||||
param, arg) == -1)
|
}
|
||||||
return -1;
|
if (process_opt_param(var, opt->templ + sep + 1, param, arg) ==
|
||||||
} else
|
-1) {
|
||||||
*(int *)var = opt->value;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
} else {
|
||||||
|
*(int *)var = opt->value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int process_opt_sep_arg(struct fuse_opt_context *ctx,
|
static int process_opt_sep_arg(struct fuse_opt_context *ctx,
|
||||||
const struct fuse_opt *opt, unsigned sep,
|
const struct fuse_opt *opt, unsigned sep,
|
||||||
const char *arg, int iso)
|
const char *arg, int iso)
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
char *newarg;
|
char *newarg;
|
||||||
char *param;
|
char *param;
|
||||||
|
|
||||||
if (next_arg(ctx, arg) == -1)
|
if (next_arg(ctx, arg) == -1) {
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
param = ctx->argv[ctx->argctr];
|
param = ctx->argv[ctx->argctr];
|
||||||
newarg = malloc(sep + strlen(param) + 1);
|
newarg = malloc(sep + strlen(param) + 1);
|
||||||
if (!newarg)
|
if (!newarg) {
|
||||||
return alloc_failed();
|
return alloc_failed();
|
||||||
|
}
|
||||||
|
|
||||||
memcpy(newarg, arg, sep);
|
memcpy(newarg, arg, sep);
|
||||||
strcpy(newarg + sep, param);
|
strcpy(newarg + sep, param);
|
||||||
res = process_opt(ctx, opt, sep, newarg, iso);
|
res = process_opt(ctx, opt, sep, newarg, iso);
|
||||||
free(newarg);
|
free(newarg);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int process_gopt(struct fuse_opt_context *ctx, const char *arg, int iso)
|
static int process_gopt(struct fuse_opt_context *ctx, const char *arg, int iso)
|
||||||
{
|
{
|
||||||
unsigned sep;
|
unsigned sep;
|
||||||
const struct fuse_opt *opt = find_opt(ctx->opt, arg, &sep);
|
const struct fuse_opt *opt = find_opt(ctx->opt, arg, &sep);
|
||||||
if (opt) {
|
if (opt) {
|
||||||
for (; opt; opt = find_opt(opt + 1, arg, &sep)) {
|
for (; opt; opt = find_opt(opt + 1, arg, &sep)) {
|
||||||
int res;
|
int res;
|
||||||
if (sep && opt->templ[sep] == ' ' && !arg[sep])
|
if (sep && opt->templ[sep] == ' ' && !arg[sep]) {
|
||||||
res = process_opt_sep_arg(ctx, opt, sep, arg,
|
res = process_opt_sep_arg(ctx, opt, sep, arg, iso);
|
||||||
iso);
|
} else {
|
||||||
else
|
res = process_opt(ctx, opt, sep, arg, iso);
|
||||||
res = process_opt(ctx, opt, sep, arg, iso);
|
}
|
||||||
if (res == -1)
|
if (res == -1) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
}
|
||||||
} else
|
return 0;
|
||||||
return call_proc(ctx, arg, FUSE_OPT_KEY_OPT, iso);
|
} else {
|
||||||
|
return call_proc(ctx, arg, FUSE_OPT_KEY_OPT, iso);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int process_real_option_group(struct fuse_opt_context *ctx, char *opts)
|
static int process_real_option_group(struct fuse_opt_context *ctx, char *opts)
|
||||||
{
|
{
|
||||||
char *s = opts;
|
char *s = opts;
|
||||||
char *d = s;
|
char *d = s;
|
||||||
int end = 0;
|
int end = 0;
|
||||||
|
|
||||||
while (!end) {
|
while (!end) {
|
||||||
if (*s == '\0')
|
if (*s == '\0') {
|
||||||
end = 1;
|
end = 1;
|
||||||
if (*s == ',' || end) {
|
}
|
||||||
int res;
|
if (*s == ',' || end) {
|
||||||
|
int res;
|
||||||
|
|
||||||
*d = '\0';
|
*d = '\0';
|
||||||
res = process_gopt(ctx, opts, 1);
|
res = process_gopt(ctx, opts, 1);
|
||||||
if (res == -1)
|
if (res == -1) {
|
||||||
return -1;
|
return -1;
|
||||||
d = opts;
|
}
|
||||||
} else {
|
d = opts;
|
||||||
if (s[0] == '\\' && s[1] != '\0') {
|
} else {
|
||||||
s++;
|
if (s[0] == '\\' && s[1] != '\0') {
|
||||||
if (s[0] >= '0' && s[0] <= '3' &&
|
s++;
|
||||||
s[1] >= '0' && s[1] <= '7' &&
|
if (s[0] >= '0' && s[0] <= '3' && s[1] >= '0' && s[1] <= '7' &&
|
||||||
s[2] >= '0' && s[2] <= '7') {
|
s[2] >= '0' && s[2] <= '7') {
|
||||||
*d++ = (s[0] - '0') * 0100 +
|
*d++ = (s[0] - '0') * 0100 + (s[1] - '0') * 0010 +
|
||||||
(s[1] - '0') * 0010 +
|
(s[2] - '0');
|
||||||
(s[2] - '0');
|
s += 2;
|
||||||
s += 2;
|
} else {
|
||||||
} else {
|
*d++ = *s;
|
||||||
*d++ = *s;
|
}
|
||||||
}
|
} else {
|
||||||
} else {
|
*d++ = *s;
|
||||||
*d++ = *s;
|
}
|
||||||
}
|
}
|
||||||
}
|
s++;
|
||||||
s++;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int process_option_group(struct fuse_opt_context *ctx, const char *opts)
|
static int process_option_group(struct fuse_opt_context *ctx, const char *opts)
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
char *copy = strdup(opts);
|
char *copy = strdup(opts);
|
||||||
|
|
||||||
if (!copy) {
|
if (!copy) {
|
||||||
fuse_log(FUSE_LOG_ERR, "fuse: memory allocation failed\n");
|
fuse_log(FUSE_LOG_ERR, "fuse: memory allocation failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
res = process_real_option_group(ctx, copy);
|
res = process_real_option_group(ctx, copy);
|
||||||
free(copy);
|
free(copy);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int process_one(struct fuse_opt_context *ctx, const char *arg)
|
static int process_one(struct fuse_opt_context *ctx, const char *arg)
|
||||||
{
|
{
|
||||||
if (ctx->nonopt || arg[0] != '-')
|
if (ctx->nonopt || arg[0] != '-') {
|
||||||
return call_proc(ctx, arg, FUSE_OPT_KEY_NONOPT, 0);
|
return call_proc(ctx, arg, FUSE_OPT_KEY_NONOPT, 0);
|
||||||
else if (arg[1] == 'o') {
|
} else if (arg[1] == 'o') {
|
||||||
if (arg[2])
|
if (arg[2]) {
|
||||||
return process_option_group(ctx, arg + 2);
|
return process_option_group(ctx, arg + 2);
|
||||||
else {
|
} else {
|
||||||
if (next_arg(ctx, arg) == -1)
|
if (next_arg(ctx, arg) == -1) {
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
return process_option_group(ctx,
|
return process_option_group(ctx, ctx->argv[ctx->argctr]);
|
||||||
ctx->argv[ctx->argctr]);
|
}
|
||||||
}
|
} else if (arg[1] == '-' && !arg[2]) {
|
||||||
} else if (arg[1] == '-' && !arg[2]) {
|
if (add_arg(ctx, arg) == -1) {
|
||||||
if (add_arg(ctx, arg) == -1)
|
return -1;
|
||||||
return -1;
|
}
|
||||||
ctx->nonopt = ctx->outargs.argc;
|
ctx->nonopt = ctx->outargs.argc;
|
||||||
return 0;
|
return 0;
|
||||||
} else
|
} else {
|
||||||
return process_gopt(ctx, arg, 0);
|
return process_gopt(ctx, arg, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int opt_parse(struct fuse_opt_context *ctx)
|
static int opt_parse(struct fuse_opt_context *ctx)
|
||||||
{
|
{
|
||||||
if (ctx->argc) {
|
if (ctx->argc) {
|
||||||
if (add_arg(ctx, ctx->argv[0]) == -1)
|
if (add_arg(ctx, ctx->argv[0]) == -1) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (ctx->argctr = 1; ctx->argctr < ctx->argc; ctx->argctr++)
|
for (ctx->argctr = 1; ctx->argctr < ctx->argc; ctx->argctr++) {
|
||||||
if (process_one(ctx, ctx->argv[ctx->argctr]) == -1)
|
if (process_one(ctx, ctx->argv[ctx->argctr]) == -1) {
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (ctx->opts) {
|
if (ctx->opts) {
|
||||||
if (fuse_opt_insert_arg(&ctx->outargs, 1, "-o") == -1 ||
|
if (fuse_opt_insert_arg(&ctx->outargs, 1, "-o") == -1 ||
|
||||||
fuse_opt_insert_arg(&ctx->outargs, 2, ctx->opts) == -1)
|
fuse_opt_insert_arg(&ctx->outargs, 2, ctx->opts) == -1) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* If option separator ("--") is the last argument, remove it */
|
/* If option separator ("--") is the last argument, remove it */
|
||||||
if (ctx->nonopt && ctx->nonopt == ctx->outargs.argc &&
|
if (ctx->nonopt && ctx->nonopt == ctx->outargs.argc &&
|
||||||
strcmp(ctx->outargs.argv[ctx->outargs.argc - 1], "--") == 0) {
|
strcmp(ctx->outargs.argv[ctx->outargs.argc - 1], "--") == 0) {
|
||||||
free(ctx->outargs.argv[ctx->outargs.argc - 1]);
|
free(ctx->outargs.argv[ctx->outargs.argc - 1]);
|
||||||
ctx->outargs.argv[--ctx->outargs.argc] = NULL;
|
ctx->outargs.argv[--ctx->outargs.argc] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fuse_opt_parse(struct fuse_args *args, void *data,
|
int fuse_opt_parse(struct fuse_args *args, void *data,
|
||||||
const struct fuse_opt opts[], fuse_opt_proc_t proc)
|
const struct fuse_opt opts[], fuse_opt_proc_t proc)
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
struct fuse_opt_context ctx = {
|
struct fuse_opt_context ctx = {
|
||||||
.data = data,
|
.data = data,
|
||||||
.opt = opts,
|
.opt = opts,
|
||||||
.proc = proc,
|
.proc = proc,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!args || !args->argv || !args->argc)
|
if (!args || !args->argv || !args->argc) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
ctx.argc = args->argc;
|
ctx.argc = args->argc;
|
||||||
ctx.argv = args->argv;
|
ctx.argv = args->argv;
|
||||||
|
|
||||||
res = opt_parse(&ctx);
|
res = opt_parse(&ctx);
|
||||||
if (res != -1) {
|
if (res != -1) {
|
||||||
struct fuse_args tmp = *args;
|
struct fuse_args tmp = *args;
|
||||||
*args = ctx.outargs;
|
*args = ctx.outargs;
|
||||||
ctx.outargs = tmp;
|
ctx.outargs = tmp;
|
||||||
}
|
}
|
||||||
free(ctx.opts);
|
free(ctx.opts);
|
||||||
fuse_opt_free_args(&ctx.outargs);
|
fuse_opt_free_args(&ctx.outargs);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
/*
|
/*
|
||||||
FUSE: Filesystem in Userspace
|
* FUSE: Filesystem in Userspace
|
||||||
Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
|
* Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
|
||||||
|
*
|
||||||
This program can be distributed under the terms of the GNU LGPLv2.
|
* This program can be distributed under the terms of the GNU LGPLv2.
|
||||||
See the file COPYING.LIB.
|
* See the file COPYING.LIB.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef FUSE_OPT_H_
|
#ifndef FUSE_OPT_H_
|
||||||
#define FUSE_OPT_H_
|
#define FUSE_OPT_H_
|
||||||
|
@ -37,7 +37,7 @@
|
||||||
*
|
*
|
||||||
* - 'offsetof(struct foo, member)' actions i) and iii)
|
* - 'offsetof(struct foo, member)' actions i) and iii)
|
||||||
*
|
*
|
||||||
* - -1 action ii)
|
* - -1 action ii)
|
||||||
*
|
*
|
||||||
* The 'offsetof()' macro is defined in the <stddef.h> header.
|
* The 'offsetof()' macro is defined in the <stddef.h> header.
|
||||||
*
|
*
|
||||||
|
@ -48,7 +48,7 @@
|
||||||
*
|
*
|
||||||
* The types of templates are:
|
* The types of templates are:
|
||||||
*
|
*
|
||||||
* 1) "-x", "-foo", "--foo", "--foo-bar", etc. These match only
|
* 1) "-x", "-foo", "--foo", "--foo-bar", etc. These match only
|
||||||
* themselves. Invalid values are "--" and anything beginning
|
* themselves. Invalid values are "--" and anything beginning
|
||||||
* with "-o"
|
* with "-o"
|
||||||
*
|
*
|
||||||
|
@ -71,58 +71,67 @@
|
||||||
* freed.
|
* freed.
|
||||||
*/
|
*/
|
||||||
struct fuse_opt {
|
struct fuse_opt {
|
||||||
/** Matching template and optional parameter formatting */
|
/** Matching template and optional parameter formatting */
|
||||||
const char *templ;
|
const char *templ;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Offset of variable within 'data' parameter of fuse_opt_parse()
|
* Offset of variable within 'data' parameter of fuse_opt_parse()
|
||||||
* or -1
|
* or -1
|
||||||
*/
|
*/
|
||||||
unsigned long offset;
|
unsigned long offset;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Value to set the variable to, or to be passed as 'key' to the
|
* Value to set the variable to, or to be passed as 'key' to the
|
||||||
* processing function. Ignored if template has a format
|
* processing function. Ignored if template has a format
|
||||||
*/
|
*/
|
||||||
int value;
|
int value;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Key option. In case of a match, the processing function will be
|
* Key option. In case of a match, the processing function will be
|
||||||
* called with the specified key.
|
* called with the specified key.
|
||||||
*/
|
*/
|
||||||
#define FUSE_OPT_KEY(templ, key) { templ, -1U, key }
|
#define FUSE_OPT_KEY(templ, key) \
|
||||||
|
{ \
|
||||||
|
templ, -1U, key \
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Last option. An array of 'struct fuse_opt' must end with a NULL
|
* Last option. An array of 'struct fuse_opt' must end with a NULL
|
||||||
* template value
|
* template value
|
||||||
*/
|
*/
|
||||||
#define FUSE_OPT_END { NULL, 0, 0 }
|
#define FUSE_OPT_END \
|
||||||
|
{ \
|
||||||
|
NULL, 0, 0 \
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Argument list
|
* Argument list
|
||||||
*/
|
*/
|
||||||
struct fuse_args {
|
struct fuse_args {
|
||||||
/** Argument count */
|
/** Argument count */
|
||||||
int argc;
|
int argc;
|
||||||
|
|
||||||
/** Argument vector. NULL terminated */
|
/** Argument vector. NULL terminated */
|
||||||
char **argv;
|
char **argv;
|
||||||
|
|
||||||
/** Is 'argv' allocated? */
|
/** Is 'argv' allocated? */
|
||||||
int allocated;
|
int allocated;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializer for 'struct fuse_args'
|
* Initializer for 'struct fuse_args'
|
||||||
*/
|
*/
|
||||||
#define FUSE_ARGS_INIT(argc, argv) { argc, argv, 0 }
|
#define FUSE_ARGS_INIT(argc, argv) \
|
||||||
|
{ \
|
||||||
|
argc, argv, 0 \
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Key value passed to the processing function if an option did not
|
* Key value passed to the processing function if an option did not
|
||||||
* match any template
|
* match any template
|
||||||
*/
|
*/
|
||||||
#define FUSE_OPT_KEY_OPT -1
|
#define FUSE_OPT_KEY_OPT -1
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Key value passed to the processing function for all non-options
|
* Key value passed to the processing function for all non-options
|
||||||
|
@ -130,7 +139,7 @@ struct fuse_args {
|
||||||
* Non-options are the arguments beginning with a character other than
|
* Non-options are the arguments beginning with a character other than
|
||||||
* '-' or all arguments after the special '--' option
|
* '-' or all arguments after the special '--' option
|
||||||
*/
|
*/
|
||||||
#define FUSE_OPT_KEY_NONOPT -2
|
#define FUSE_OPT_KEY_NONOPT -2
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Special key value for options to keep
|
* Special key value for options to keep
|
||||||
|
@ -174,7 +183,7 @@ struct fuse_args {
|
||||||
* @return -1 on error, 0 if arg is to be discarded, 1 if arg should be kept
|
* @return -1 on error, 0 if arg is to be discarded, 1 if arg should be kept
|
||||||
*/
|
*/
|
||||||
typedef int (*fuse_opt_proc_t)(void *data, const char *arg, int key,
|
typedef int (*fuse_opt_proc_t)(void *data, const char *arg, int key,
|
||||||
struct fuse_args *outargs);
|
struct fuse_args *outargs);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Option parsing function
|
* Option parsing function
|
||||||
|
@ -197,7 +206,7 @@ typedef int (*fuse_opt_proc_t)(void *data, const char *arg, int key,
|
||||||
* @return -1 on error, 0 on success
|
* @return -1 on error, 0 on success
|
||||||
*/
|
*/
|
||||||
int fuse_opt_parse(struct fuse_args *args, void *data,
|
int fuse_opt_parse(struct fuse_args *args, void *data,
|
||||||
const struct fuse_opt opts[], fuse_opt_proc_t proc);
|
const struct fuse_opt opts[], fuse_opt_proc_t proc);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add an option to a comma separated option list
|
* Add an option to a comma separated option list
|
||||||
|
|
|
@ -1,91 +1,95 @@
|
||||||
/*
|
/*
|
||||||
FUSE: Filesystem in Userspace
|
* FUSE: Filesystem in Userspace
|
||||||
Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
|
* Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
|
||||||
|
*
|
||||||
Utility functions for setting signal handlers.
|
* Utility functions for setting signal handlers.
|
||||||
|
*
|
||||||
This program can be distributed under the terms of the GNU LGPLv2.
|
* This program can be distributed under the terms of the GNU LGPLv2.
|
||||||
See the file COPYING.LIB
|
* See the file COPYING.LIB
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "fuse_lowlevel.h"
|
|
||||||
#include "fuse_i.h"
|
#include "fuse_i.h"
|
||||||
|
#include "fuse_lowlevel.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
static struct fuse_session *fuse_instance;
|
static struct fuse_session *fuse_instance;
|
||||||
|
|
||||||
static void exit_handler(int sig)
|
static void exit_handler(int sig)
|
||||||
{
|
{
|
||||||
if (fuse_instance) {
|
if (fuse_instance) {
|
||||||
fuse_session_exit(fuse_instance);
|
fuse_session_exit(fuse_instance);
|
||||||
if(sig <= 0) {
|
if (sig <= 0) {
|
||||||
fuse_log(FUSE_LOG_ERR, "assertion error: signal value <= 0\n");
|
fuse_log(FUSE_LOG_ERR, "assertion error: signal value <= 0\n");
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
fuse_instance->error = sig;
|
fuse_instance->error = sig;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void do_nothing(int sig)
|
static void do_nothing(int sig)
|
||||||
{
|
{
|
||||||
(void) sig;
|
(void)sig;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int set_one_signal_handler(int sig, void (*handler)(int), int remove)
|
static int set_one_signal_handler(int sig, void (*handler)(int), int remove)
|
||||||
{
|
{
|
||||||
struct sigaction sa;
|
struct sigaction sa;
|
||||||
struct sigaction old_sa;
|
struct sigaction old_sa;
|
||||||
|
|
||||||
memset(&sa, 0, sizeof(struct sigaction));
|
memset(&sa, 0, sizeof(struct sigaction));
|
||||||
sa.sa_handler = remove ? SIG_DFL : handler;
|
sa.sa_handler = remove ? SIG_DFL : handler;
|
||||||
sigemptyset(&(sa.sa_mask));
|
sigemptyset(&(sa.sa_mask));
|
||||||
sa.sa_flags = 0;
|
sa.sa_flags = 0;
|
||||||
|
|
||||||
if (sigaction(sig, NULL, &old_sa) == -1) {
|
if (sigaction(sig, NULL, &old_sa) == -1) {
|
||||||
perror("fuse: cannot get old signal handler");
|
perror("fuse: cannot get old signal handler");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (old_sa.sa_handler == (remove ? handler : SIG_DFL) &&
|
if (old_sa.sa_handler == (remove ? handler : SIG_DFL) &&
|
||||||
sigaction(sig, &sa, NULL) == -1) {
|
sigaction(sig, &sa, NULL) == -1) {
|
||||||
perror("fuse: cannot set signal handler");
|
perror("fuse: cannot set signal handler");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fuse_set_signal_handlers(struct fuse_session *se)
|
int fuse_set_signal_handlers(struct fuse_session *se)
|
||||||
{
|
{
|
||||||
/* If we used SIG_IGN instead of the do_nothing function,
|
/*
|
||||||
then we would be unable to tell if we set SIG_IGN (and
|
* If we used SIG_IGN instead of the do_nothing function,
|
||||||
thus should reset to SIG_DFL in fuse_remove_signal_handlers)
|
* then we would be unable to tell if we set SIG_IGN (and
|
||||||
or if it was already set to SIG_IGN (and should be left
|
* thus should reset to SIG_DFL in fuse_remove_signal_handlers)
|
||||||
untouched. */
|
* or if it was already set to SIG_IGN (and should be left
|
||||||
if (set_one_signal_handler(SIGHUP, exit_handler, 0) == -1 ||
|
* untouched.
|
||||||
set_one_signal_handler(SIGINT, exit_handler, 0) == -1 ||
|
*/
|
||||||
set_one_signal_handler(SIGTERM, exit_handler, 0) == -1 ||
|
if (set_one_signal_handler(SIGHUP, exit_handler, 0) == -1 ||
|
||||||
set_one_signal_handler(SIGPIPE, do_nothing, 0) == -1)
|
set_one_signal_handler(SIGINT, exit_handler, 0) == -1 ||
|
||||||
return -1;
|
set_one_signal_handler(SIGTERM, exit_handler, 0) == -1 ||
|
||||||
|
set_one_signal_handler(SIGPIPE, do_nothing, 0) == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
fuse_instance = se;
|
fuse_instance = se;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void fuse_remove_signal_handlers(struct fuse_session *se)
|
void fuse_remove_signal_handlers(struct fuse_session *se)
|
||||||
{
|
{
|
||||||
if (fuse_instance != se)
|
if (fuse_instance != se) {
|
||||||
fuse_log(FUSE_LOG_ERR,
|
fuse_log(FUSE_LOG_ERR,
|
||||||
"fuse: fuse_remove_signal_handlers: unknown session\n");
|
"fuse: fuse_remove_signal_handlers: unknown session\n");
|
||||||
else
|
} else {
|
||||||
fuse_instance = NULL;
|
fuse_instance = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
set_one_signal_handler(SIGHUP, exit_handler, 1);
|
set_one_signal_handler(SIGHUP, exit_handler, 1);
|
||||||
set_one_signal_handler(SIGINT, exit_handler, 1);
|
set_one_signal_handler(SIGINT, exit_handler, 1);
|
||||||
set_one_signal_handler(SIGTERM, exit_handler, 1);
|
set_one_signal_handler(SIGTERM, exit_handler, 1);
|
||||||
set_one_signal_handler(SIGPIPE, do_nothing, 1);
|
set_one_signal_handler(SIGPIPE, do_nothing, 1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,297 +1,309 @@
|
||||||
/*
|
/*
|
||||||
FUSE: Filesystem in Userspace
|
* FUSE: Filesystem in Userspace
|
||||||
Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
|
* Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
|
||||||
|
*
|
||||||
|
* Helper functions to create (simple) standalone programs. With the
|
||||||
|
* aid of these functions it should be possible to create full FUSE
|
||||||
|
* file system by implementing nothing but the request handlers.
|
||||||
|
|
||||||
Helper functions to create (simple) standalone programs. With the
|
* This program can be distributed under the terms of the GNU LGPLv2.
|
||||||
aid of these functions it should be possible to create full FUSE
|
* See the file COPYING.LIB.
|
||||||
file system by implementing nothing but the request handlers.
|
*/
|
||||||
|
|
||||||
This program can be distributed under the terms of the GNU LGPLv2.
|
|
||||||
See the file COPYING.LIB.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "fuse_i.h"
|
#include "fuse_i.h"
|
||||||
|
#include "fuse_lowlevel.h"
|
||||||
#include "fuse_misc.h"
|
#include "fuse_misc.h"
|
||||||
#include "fuse_opt.h"
|
#include "fuse_opt.h"
|
||||||
#include "fuse_lowlevel.h"
|
|
||||||
#include "mount_util.h"
|
#include "mount_util.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stddef.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stddef.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <limits.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#define FUSE_HELPER_OPT(t, p) \
|
#define FUSE_HELPER_OPT(t, p) \
|
||||||
{ t, offsetof(struct fuse_cmdline_opts, p), 1 }
|
{ \
|
||||||
|
t, offsetof(struct fuse_cmdline_opts, p), 1 \
|
||||||
|
}
|
||||||
|
|
||||||
static const struct fuse_opt fuse_helper_opts[] = {
|
static const struct fuse_opt fuse_helper_opts[] = {
|
||||||
FUSE_HELPER_OPT("-h", show_help),
|
FUSE_HELPER_OPT("-h", show_help),
|
||||||
FUSE_HELPER_OPT("--help", show_help),
|
FUSE_HELPER_OPT("--help", show_help),
|
||||||
FUSE_HELPER_OPT("-V", show_version),
|
FUSE_HELPER_OPT("-V", show_version),
|
||||||
FUSE_HELPER_OPT("--version", show_version),
|
FUSE_HELPER_OPT("--version", show_version),
|
||||||
FUSE_HELPER_OPT("-d", debug),
|
FUSE_HELPER_OPT("-d", debug),
|
||||||
FUSE_HELPER_OPT("debug", debug),
|
FUSE_HELPER_OPT("debug", debug),
|
||||||
FUSE_HELPER_OPT("-d", foreground),
|
FUSE_HELPER_OPT("-d", foreground),
|
||||||
FUSE_HELPER_OPT("debug", foreground),
|
FUSE_HELPER_OPT("debug", foreground),
|
||||||
FUSE_OPT_KEY("-d", FUSE_OPT_KEY_KEEP),
|
FUSE_OPT_KEY("-d", FUSE_OPT_KEY_KEEP),
|
||||||
FUSE_OPT_KEY("debug", FUSE_OPT_KEY_KEEP),
|
FUSE_OPT_KEY("debug", FUSE_OPT_KEY_KEEP),
|
||||||
FUSE_HELPER_OPT("-f", foreground),
|
FUSE_HELPER_OPT("-f", foreground),
|
||||||
FUSE_HELPER_OPT("fsname=", nodefault_subtype),
|
FUSE_HELPER_OPT("fsname=", nodefault_subtype),
|
||||||
FUSE_OPT_KEY("fsname=", FUSE_OPT_KEY_KEEP),
|
FUSE_OPT_KEY("fsname=", FUSE_OPT_KEY_KEEP),
|
||||||
FUSE_HELPER_OPT("subtype=", nodefault_subtype),
|
FUSE_HELPER_OPT("subtype=", nodefault_subtype),
|
||||||
FUSE_OPT_KEY("subtype=", FUSE_OPT_KEY_KEEP),
|
FUSE_OPT_KEY("subtype=", FUSE_OPT_KEY_KEEP),
|
||||||
FUSE_HELPER_OPT("max_idle_threads=%u", max_idle_threads),
|
FUSE_HELPER_OPT("max_idle_threads=%u", max_idle_threads),
|
||||||
FUSE_OPT_END
|
FUSE_OPT_END
|
||||||
};
|
};
|
||||||
|
|
||||||
struct fuse_conn_info_opts {
|
struct fuse_conn_info_opts {
|
||||||
int atomic_o_trunc;
|
int atomic_o_trunc;
|
||||||
int no_remote_posix_lock;
|
int no_remote_posix_lock;
|
||||||
int no_remote_flock;
|
int no_remote_flock;
|
||||||
int splice_write;
|
int splice_write;
|
||||||
int splice_move;
|
int splice_move;
|
||||||
int splice_read;
|
int splice_read;
|
||||||
int no_splice_write;
|
int no_splice_write;
|
||||||
int no_splice_move;
|
int no_splice_move;
|
||||||
int no_splice_read;
|
int no_splice_read;
|
||||||
int auto_inval_data;
|
int auto_inval_data;
|
||||||
int no_auto_inval_data;
|
int no_auto_inval_data;
|
||||||
int no_readdirplus;
|
int no_readdirplus;
|
||||||
int no_readdirplus_auto;
|
int no_readdirplus_auto;
|
||||||
int async_dio;
|
int async_dio;
|
||||||
int no_async_dio;
|
int no_async_dio;
|
||||||
int writeback_cache;
|
int writeback_cache;
|
||||||
int no_writeback_cache;
|
int no_writeback_cache;
|
||||||
int async_read;
|
int async_read;
|
||||||
int sync_read;
|
int sync_read;
|
||||||
unsigned max_write;
|
unsigned max_write;
|
||||||
unsigned max_readahead;
|
unsigned max_readahead;
|
||||||
unsigned max_background;
|
unsigned max_background;
|
||||||
unsigned congestion_threshold;
|
unsigned congestion_threshold;
|
||||||
unsigned time_gran;
|
unsigned time_gran;
|
||||||
int set_max_write;
|
int set_max_write;
|
||||||
int set_max_readahead;
|
int set_max_readahead;
|
||||||
int set_max_background;
|
int set_max_background;
|
||||||
int set_congestion_threshold;
|
int set_congestion_threshold;
|
||||||
int set_time_gran;
|
int set_time_gran;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define CONN_OPTION(t, p, v) \
|
#define CONN_OPTION(t, p, v) \
|
||||||
{ t, offsetof(struct fuse_conn_info_opts, p), v }
|
{ \
|
||||||
|
t, offsetof(struct fuse_conn_info_opts, p), v \
|
||||||
|
}
|
||||||
static const struct fuse_opt conn_info_opt_spec[] = {
|
static const struct fuse_opt conn_info_opt_spec[] = {
|
||||||
CONN_OPTION("max_write=%u", max_write, 0),
|
CONN_OPTION("max_write=%u", max_write, 0),
|
||||||
CONN_OPTION("max_write=", set_max_write, 1),
|
CONN_OPTION("max_write=", set_max_write, 1),
|
||||||
CONN_OPTION("max_readahead=%u", max_readahead, 0),
|
CONN_OPTION("max_readahead=%u", max_readahead, 0),
|
||||||
CONN_OPTION("max_readahead=", set_max_readahead, 1),
|
CONN_OPTION("max_readahead=", set_max_readahead, 1),
|
||||||
CONN_OPTION("max_background=%u", max_background, 0),
|
CONN_OPTION("max_background=%u", max_background, 0),
|
||||||
CONN_OPTION("max_background=", set_max_background, 1),
|
CONN_OPTION("max_background=", set_max_background, 1),
|
||||||
CONN_OPTION("congestion_threshold=%u", congestion_threshold, 0),
|
CONN_OPTION("congestion_threshold=%u", congestion_threshold, 0),
|
||||||
CONN_OPTION("congestion_threshold=", set_congestion_threshold, 1),
|
CONN_OPTION("congestion_threshold=", set_congestion_threshold, 1),
|
||||||
CONN_OPTION("sync_read", sync_read, 1),
|
CONN_OPTION("sync_read", sync_read, 1),
|
||||||
CONN_OPTION("async_read", async_read, 1),
|
CONN_OPTION("async_read", async_read, 1),
|
||||||
CONN_OPTION("atomic_o_trunc", atomic_o_trunc, 1),
|
CONN_OPTION("atomic_o_trunc", atomic_o_trunc, 1),
|
||||||
CONN_OPTION("no_remote_lock", no_remote_posix_lock, 1),
|
CONN_OPTION("no_remote_lock", no_remote_posix_lock, 1),
|
||||||
CONN_OPTION("no_remote_lock", no_remote_flock, 1),
|
CONN_OPTION("no_remote_lock", no_remote_flock, 1),
|
||||||
CONN_OPTION("no_remote_flock", no_remote_flock, 1),
|
CONN_OPTION("no_remote_flock", no_remote_flock, 1),
|
||||||
CONN_OPTION("no_remote_posix_lock", no_remote_posix_lock, 1),
|
CONN_OPTION("no_remote_posix_lock", no_remote_posix_lock, 1),
|
||||||
CONN_OPTION("splice_write", splice_write, 1),
|
CONN_OPTION("splice_write", splice_write, 1),
|
||||||
CONN_OPTION("no_splice_write", no_splice_write, 1),
|
CONN_OPTION("no_splice_write", no_splice_write, 1),
|
||||||
CONN_OPTION("splice_move", splice_move, 1),
|
CONN_OPTION("splice_move", splice_move, 1),
|
||||||
CONN_OPTION("no_splice_move", no_splice_move, 1),
|
CONN_OPTION("no_splice_move", no_splice_move, 1),
|
||||||
CONN_OPTION("splice_read", splice_read, 1),
|
CONN_OPTION("splice_read", splice_read, 1),
|
||||||
CONN_OPTION("no_splice_read", no_splice_read, 1),
|
CONN_OPTION("no_splice_read", no_splice_read, 1),
|
||||||
CONN_OPTION("auto_inval_data", auto_inval_data, 1),
|
CONN_OPTION("auto_inval_data", auto_inval_data, 1),
|
||||||
CONN_OPTION("no_auto_inval_data", no_auto_inval_data, 1),
|
CONN_OPTION("no_auto_inval_data", no_auto_inval_data, 1),
|
||||||
CONN_OPTION("readdirplus=no", no_readdirplus, 1),
|
CONN_OPTION("readdirplus=no", no_readdirplus, 1),
|
||||||
CONN_OPTION("readdirplus=yes", no_readdirplus, 0),
|
CONN_OPTION("readdirplus=yes", no_readdirplus, 0),
|
||||||
CONN_OPTION("readdirplus=yes", no_readdirplus_auto, 1),
|
CONN_OPTION("readdirplus=yes", no_readdirplus_auto, 1),
|
||||||
CONN_OPTION("readdirplus=auto", no_readdirplus, 0),
|
CONN_OPTION("readdirplus=auto", no_readdirplus, 0),
|
||||||
CONN_OPTION("readdirplus=auto", no_readdirplus_auto, 0),
|
CONN_OPTION("readdirplus=auto", no_readdirplus_auto, 0),
|
||||||
CONN_OPTION("async_dio", async_dio, 1),
|
CONN_OPTION("async_dio", async_dio, 1),
|
||||||
CONN_OPTION("no_async_dio", no_async_dio, 1),
|
CONN_OPTION("no_async_dio", no_async_dio, 1),
|
||||||
CONN_OPTION("writeback_cache", writeback_cache, 1),
|
CONN_OPTION("writeback_cache", writeback_cache, 1),
|
||||||
CONN_OPTION("no_writeback_cache", no_writeback_cache, 1),
|
CONN_OPTION("no_writeback_cache", no_writeback_cache, 1),
|
||||||
CONN_OPTION("time_gran=%u", time_gran, 0),
|
CONN_OPTION("time_gran=%u", time_gran, 0),
|
||||||
CONN_OPTION("time_gran=", set_time_gran, 1),
|
CONN_OPTION("time_gran=", set_time_gran, 1),
|
||||||
FUSE_OPT_END
|
FUSE_OPT_END
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
void fuse_cmdline_help(void)
|
void fuse_cmdline_help(void)
|
||||||
{
|
{
|
||||||
printf(" -h --help print help\n"
|
printf(
|
||||||
" -V --version print version\n"
|
" -h --help print help\n"
|
||||||
" -d -o debug enable debug output (implies -f)\n"
|
" -V --version print version\n"
|
||||||
" -f foreground operation\n"
|
" -d -o debug enable debug output (implies -f)\n"
|
||||||
" -o max_idle_threads the maximum number of idle worker threads\n"
|
" -f foreground operation\n"
|
||||||
" allowed (default: 10)\n");
|
" -o max_idle_threads the maximum number of idle worker threads\n"
|
||||||
|
" allowed (default: 10)\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fuse_helper_opt_proc(void *data, const char *arg, int key,
|
static int fuse_helper_opt_proc(void *data, const char *arg, int key,
|
||||||
struct fuse_args *outargs)
|
struct fuse_args *outargs)
|
||||||
{
|
{
|
||||||
(void) outargs;
|
(void)outargs;
|
||||||
struct fuse_cmdline_opts *opts = data;
|
struct fuse_cmdline_opts *opts = data;
|
||||||
|
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case FUSE_OPT_KEY_NONOPT:
|
case FUSE_OPT_KEY_NONOPT:
|
||||||
if (!opts->mountpoint) {
|
if (!opts->mountpoint) {
|
||||||
if (fuse_mnt_parse_fuse_fd(arg) != -1) {
|
if (fuse_mnt_parse_fuse_fd(arg) != -1) {
|
||||||
return fuse_opt_add_opt(&opts->mountpoint, arg);
|
return fuse_opt_add_opt(&opts->mountpoint, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
char mountpoint[PATH_MAX] = "";
|
char mountpoint[PATH_MAX] = "";
|
||||||
if (realpath(arg, mountpoint) == NULL) {
|
if (realpath(arg, mountpoint) == NULL) {
|
||||||
fuse_log(FUSE_LOG_ERR,
|
fuse_log(FUSE_LOG_ERR, "fuse: bad mount point `%s': %s\n", arg,
|
||||||
"fuse: bad mount point `%s': %s\n",
|
strerror(errno));
|
||||||
arg, strerror(errno));
|
return -1;
|
||||||
return -1;
|
}
|
||||||
}
|
return fuse_opt_add_opt(&opts->mountpoint, mountpoint);
|
||||||
return fuse_opt_add_opt(&opts->mountpoint, mountpoint);
|
} else {
|
||||||
} else {
|
fuse_log(FUSE_LOG_ERR, "fuse: invalid argument `%s'\n", arg);
|
||||||
fuse_log(FUSE_LOG_ERR, "fuse: invalid argument `%s'\n", arg);
|
return -1;
|
||||||
return -1;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* Pass through unknown options */
|
/* Pass through unknown options */
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int fuse_parse_cmdline(struct fuse_args *args,
|
int fuse_parse_cmdline(struct fuse_args *args, struct fuse_cmdline_opts *opts)
|
||||||
struct fuse_cmdline_opts *opts)
|
|
||||||
{
|
{
|
||||||
memset(opts, 0, sizeof(struct fuse_cmdline_opts));
|
memset(opts, 0, sizeof(struct fuse_cmdline_opts));
|
||||||
|
|
||||||
opts->max_idle_threads = 10;
|
opts->max_idle_threads = 10;
|
||||||
|
|
||||||
if (fuse_opt_parse(args, opts, fuse_helper_opts,
|
if (fuse_opt_parse(args, opts, fuse_helper_opts, fuse_helper_opt_proc) ==
|
||||||
fuse_helper_opt_proc) == -1)
|
-1) {
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int fuse_daemonize(int foreground)
|
int fuse_daemonize(int foreground)
|
||||||
{
|
{
|
||||||
if (!foreground) {
|
if (!foreground) {
|
||||||
int nullfd;
|
int nullfd;
|
||||||
int waiter[2];
|
int waiter[2];
|
||||||
char completed;
|
char completed;
|
||||||
|
|
||||||
if (pipe(waiter)) {
|
if (pipe(waiter)) {
|
||||||
perror("fuse_daemonize: pipe");
|
perror("fuse_daemonize: pipe");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* demonize current process by forking it and killing the
|
* demonize current process by forking it and killing the
|
||||||
* parent. This makes current process as a child of 'init'.
|
* parent. This makes current process as a child of 'init'.
|
||||||
*/
|
*/
|
||||||
switch(fork()) {
|
switch (fork()) {
|
||||||
case -1:
|
case -1:
|
||||||
perror("fuse_daemonize: fork");
|
perror("fuse_daemonize: fork");
|
||||||
return -1;
|
return -1;
|
||||||
case 0:
|
case 0:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
(void) read(waiter[0], &completed, sizeof(completed));
|
(void)read(waiter[0], &completed, sizeof(completed));
|
||||||
_exit(0);
|
_exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (setsid() == -1) {
|
if (setsid() == -1) {
|
||||||
perror("fuse_daemonize: setsid");
|
perror("fuse_daemonize: setsid");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
(void) chdir("/");
|
(void)chdir("/");
|
||||||
|
|
||||||
nullfd = open("/dev/null", O_RDWR, 0);
|
nullfd = open("/dev/null", O_RDWR, 0);
|
||||||
if (nullfd != -1) {
|
if (nullfd != -1) {
|
||||||
(void) dup2(nullfd, 0);
|
(void)dup2(nullfd, 0);
|
||||||
(void) dup2(nullfd, 1);
|
(void)dup2(nullfd, 1);
|
||||||
(void) dup2(nullfd, 2);
|
(void)dup2(nullfd, 2);
|
||||||
if (nullfd > 2)
|
if (nullfd > 2) {
|
||||||
close(nullfd);
|
close(nullfd);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Propagate completion of daemon initialization */
|
/* Propagate completion of daemon initialization */
|
||||||
completed = 1;
|
completed = 1;
|
||||||
(void) write(waiter[1], &completed, sizeof(completed));
|
(void)write(waiter[1], &completed, sizeof(completed));
|
||||||
close(waiter[0]);
|
close(waiter[0]);
|
||||||
close(waiter[1]);
|
close(waiter[1]);
|
||||||
} else {
|
} else {
|
||||||
(void) chdir("/");
|
(void)chdir("/");
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void fuse_apply_conn_info_opts(struct fuse_conn_info_opts *opts,
|
void fuse_apply_conn_info_opts(struct fuse_conn_info_opts *opts,
|
||||||
struct fuse_conn_info *conn)
|
struct fuse_conn_info *conn)
|
||||||
{
|
{
|
||||||
if(opts->set_max_write)
|
if (opts->set_max_write) {
|
||||||
conn->max_write = opts->max_write;
|
conn->max_write = opts->max_write;
|
||||||
if(opts->set_max_background)
|
}
|
||||||
conn->max_background = opts->max_background;
|
if (opts->set_max_background) {
|
||||||
if(opts->set_congestion_threshold)
|
conn->max_background = opts->max_background;
|
||||||
conn->congestion_threshold = opts->congestion_threshold;
|
}
|
||||||
if(opts->set_time_gran)
|
if (opts->set_congestion_threshold) {
|
||||||
conn->time_gran = opts->time_gran;
|
conn->congestion_threshold = opts->congestion_threshold;
|
||||||
if(opts->set_max_readahead)
|
}
|
||||||
conn->max_readahead = opts->max_readahead;
|
if (opts->set_time_gran) {
|
||||||
|
conn->time_gran = opts->time_gran;
|
||||||
|
}
|
||||||
|
if (opts->set_max_readahead) {
|
||||||
|
conn->max_readahead = opts->max_readahead;
|
||||||
|
}
|
||||||
|
|
||||||
#define LL_ENABLE(cond,cap) \
|
#define LL_ENABLE(cond, cap) \
|
||||||
if (cond) conn->want |= (cap)
|
if (cond) \
|
||||||
#define LL_DISABLE(cond,cap) \
|
conn->want |= (cap)
|
||||||
if (cond) conn->want &= ~(cap)
|
#define LL_DISABLE(cond, cap) \
|
||||||
|
if (cond) \
|
||||||
|
conn->want &= ~(cap)
|
||||||
|
|
||||||
LL_ENABLE(opts->splice_read, FUSE_CAP_SPLICE_READ);
|
LL_ENABLE(opts->splice_read, FUSE_CAP_SPLICE_READ);
|
||||||
LL_DISABLE(opts->no_splice_read, FUSE_CAP_SPLICE_READ);
|
LL_DISABLE(opts->no_splice_read, FUSE_CAP_SPLICE_READ);
|
||||||
|
|
||||||
LL_ENABLE(opts->splice_write, FUSE_CAP_SPLICE_WRITE);
|
LL_ENABLE(opts->splice_write, FUSE_CAP_SPLICE_WRITE);
|
||||||
LL_DISABLE(opts->no_splice_write, FUSE_CAP_SPLICE_WRITE);
|
LL_DISABLE(opts->no_splice_write, FUSE_CAP_SPLICE_WRITE);
|
||||||
|
|
||||||
LL_ENABLE(opts->splice_move, FUSE_CAP_SPLICE_MOVE);
|
LL_ENABLE(opts->splice_move, FUSE_CAP_SPLICE_MOVE);
|
||||||
LL_DISABLE(opts->no_splice_move, FUSE_CAP_SPLICE_MOVE);
|
LL_DISABLE(opts->no_splice_move, FUSE_CAP_SPLICE_MOVE);
|
||||||
|
|
||||||
LL_ENABLE(opts->auto_inval_data, FUSE_CAP_AUTO_INVAL_DATA);
|
LL_ENABLE(opts->auto_inval_data, FUSE_CAP_AUTO_INVAL_DATA);
|
||||||
LL_DISABLE(opts->no_auto_inval_data, FUSE_CAP_AUTO_INVAL_DATA);
|
LL_DISABLE(opts->no_auto_inval_data, FUSE_CAP_AUTO_INVAL_DATA);
|
||||||
|
|
||||||
LL_DISABLE(opts->no_readdirplus, FUSE_CAP_READDIRPLUS);
|
LL_DISABLE(opts->no_readdirplus, FUSE_CAP_READDIRPLUS);
|
||||||
LL_DISABLE(opts->no_readdirplus_auto, FUSE_CAP_READDIRPLUS_AUTO);
|
LL_DISABLE(opts->no_readdirplus_auto, FUSE_CAP_READDIRPLUS_AUTO);
|
||||||
|
|
||||||
LL_ENABLE(opts->async_dio, FUSE_CAP_ASYNC_DIO);
|
LL_ENABLE(opts->async_dio, FUSE_CAP_ASYNC_DIO);
|
||||||
LL_DISABLE(opts->no_async_dio, FUSE_CAP_ASYNC_DIO);
|
LL_DISABLE(opts->no_async_dio, FUSE_CAP_ASYNC_DIO);
|
||||||
|
|
||||||
LL_ENABLE(opts->writeback_cache, FUSE_CAP_WRITEBACK_CACHE);
|
LL_ENABLE(opts->writeback_cache, FUSE_CAP_WRITEBACK_CACHE);
|
||||||
LL_DISABLE(opts->no_writeback_cache, FUSE_CAP_WRITEBACK_CACHE);
|
LL_DISABLE(opts->no_writeback_cache, FUSE_CAP_WRITEBACK_CACHE);
|
||||||
|
|
||||||
LL_ENABLE(opts->async_read, FUSE_CAP_ASYNC_READ);
|
LL_ENABLE(opts->async_read, FUSE_CAP_ASYNC_READ);
|
||||||
LL_DISABLE(opts->sync_read, FUSE_CAP_ASYNC_READ);
|
LL_DISABLE(opts->sync_read, FUSE_CAP_ASYNC_READ);
|
||||||
|
|
||||||
LL_DISABLE(opts->no_remote_posix_lock, FUSE_CAP_POSIX_LOCKS);
|
LL_DISABLE(opts->no_remote_posix_lock, FUSE_CAP_POSIX_LOCKS);
|
||||||
LL_DISABLE(opts->no_remote_flock, FUSE_CAP_FLOCK_LOCKS);
|
LL_DISABLE(opts->no_remote_flock, FUSE_CAP_FLOCK_LOCKS);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct fuse_conn_info_opts* fuse_parse_conn_info_opts(struct fuse_args *args)
|
struct fuse_conn_info_opts *fuse_parse_conn_info_opts(struct fuse_args *args)
|
||||||
{
|
{
|
||||||
struct fuse_conn_info_opts *opts;
|
struct fuse_conn_info_opts *opts;
|
||||||
|
|
||||||
opts = calloc(1, sizeof(struct fuse_conn_info_opts));
|
opts = calloc(1, sizeof(struct fuse_conn_info_opts));
|
||||||
if(opts == NULL) {
|
if (opts == NULL) {
|
||||||
fuse_log(FUSE_LOG_ERR, "calloc failed\n");
|
fuse_log(FUSE_LOG_ERR, "calloc failed\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if(fuse_opt_parse(args, opts, conn_info_opt_spec, NULL) == -1) {
|
if (fuse_opt_parse(args, opts, conn_info_opt_spec, NULL) == -1) {
|
||||||
free(opts);
|
free(opts);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return opts;
|
return opts;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,23 +28,24 @@
|
||||||
* operation
|
* operation
|
||||||
*/
|
*/
|
||||||
static int mknod_wrapper(int dirfd, const char *path, const char *link,
|
static int mknod_wrapper(int dirfd, const char *path, const char *link,
|
||||||
int mode, dev_t rdev)
|
int mode, dev_t rdev)
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
if (S_ISREG(mode)) {
|
if (S_ISREG(mode)) {
|
||||||
res = openat(dirfd, path, O_CREAT | O_EXCL | O_WRONLY, mode);
|
res = openat(dirfd, path, O_CREAT | O_EXCL | O_WRONLY, mode);
|
||||||
if (res >= 0)
|
if (res >= 0) {
|
||||||
res = close(res);
|
res = close(res);
|
||||||
} else if (S_ISDIR(mode)) {
|
}
|
||||||
res = mkdirat(dirfd, path, mode);
|
} else if (S_ISDIR(mode)) {
|
||||||
} else if (S_ISLNK(mode) && link != NULL) {
|
res = mkdirat(dirfd, path, mode);
|
||||||
res = symlinkat(link, dirfd, path);
|
} else if (S_ISLNK(mode) && link != NULL) {
|
||||||
} else if (S_ISFIFO(mode)) {
|
res = symlinkat(link, dirfd, path);
|
||||||
res = mkfifoat(dirfd, path, mode);
|
} else if (S_ISFIFO(mode)) {
|
||||||
} else {
|
res = mkfifoat(dirfd, path, mode);
|
||||||
res = mknodat(dirfd, path, mode, rdev);
|
} else {
|
||||||
}
|
res = mknodat(dirfd, path, mode, rdev);
|
||||||
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue