mirror of https://gitee.com/openkylin/qemu.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
|
||||
Copyright (C) 2010 Miklos Szeredi <miklos@szeredi.hu>
|
||||
|
||||
Functions for dealing with `struct fuse_buf` and `struct
|
||||
fuse_bufvec`.
|
||||
|
||||
This program can be distributed under the terms of the GNU LGPLv2.
|
||||
See the file COPYING.LIB
|
||||
*/
|
||||
* FUSE: Filesystem in Userspace
|
||||
* Copyright (C) 2010 Miklos Szeredi <miklos@szeredi.hu>
|
||||
*
|
||||
* Functions for dealing with `struct fuse_buf` and `struct
|
||||
* fuse_bufvec`.
|
||||
*
|
||||
* This program can be distributed under the terms of the GNU LGPLv2.
|
||||
* See the file COPYING.LIB
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include "config.h"
|
||||
#include "fuse_i.h"
|
||||
#include "fuse_lowlevel.h"
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
size_t fuse_buf_size(const struct fuse_bufvec *bufv)
|
||||
{
|
||||
size_t i;
|
||||
size_t size = 0;
|
||||
size_t i;
|
||||
size_t size = 0;
|
||||
|
||||
for (i = 0; i < bufv->count; i++) {
|
||||
if (bufv->buf[i].size == SIZE_MAX)
|
||||
size = SIZE_MAX;
|
||||
else
|
||||
size += bufv->buf[i].size;
|
||||
}
|
||||
for (i = 0; i < bufv->count; i++) {
|
||||
if (bufv->buf[i].size == SIZE_MAX) {
|
||||
size = SIZE_MAX;
|
||||
} else {
|
||||
size += bufv->buf[i].size;
|
||||
}
|
||||
}
|
||||
|
||||
return size;
|
||||
return size;
|
||||
}
|
||||
|
||||
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,
|
||||
const struct fuse_buf *src, size_t src_off,
|
||||
size_t len)
|
||||
const struct fuse_buf *src, size_t src_off,
|
||||
size_t len)
|
||||
{
|
||||
ssize_t res = 0;
|
||||
size_t copied = 0;
|
||||
ssize_t res = 0;
|
||||
size_t copied = 0;
|
||||
|
||||
while (len) {
|
||||
if (dst->flags & FUSE_BUF_FD_SEEK) {
|
||||
res = pwrite(dst->fd, (char *)src->mem + src_off, len,
|
||||
dst->pos + dst_off);
|
||||
} else {
|
||||
res = write(dst->fd, (char *)src->mem + src_off, len);
|
||||
}
|
||||
if (res == -1) {
|
||||
if (!copied)
|
||||
return -errno;
|
||||
break;
|
||||
}
|
||||
if (res == 0)
|
||||
break;
|
||||
while (len) {
|
||||
if (dst->flags & FUSE_BUF_FD_SEEK) {
|
||||
res = pwrite(dst->fd, (char *)src->mem + src_off, len,
|
||||
dst->pos + dst_off);
|
||||
} else {
|
||||
res = write(dst->fd, (char *)src->mem + src_off, len);
|
||||
}
|
||||
if (res == -1) {
|
||||
if (!copied) {
|
||||
return -errno;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (res == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
copied += res;
|
||||
if (!(dst->flags & FUSE_BUF_FD_RETRY))
|
||||
break;
|
||||
copied += res;
|
||||
if (!(dst->flags & FUSE_BUF_FD_RETRY)) {
|
||||
break;
|
||||
}
|
||||
|
||||
src_off += res;
|
||||
dst_off += res;
|
||||
len -= res;
|
||||
}
|
||||
src_off += res;
|
||||
dst_off += res;
|
||||
len -= res;
|
||||
}
|
||||
|
||||
return copied;
|
||||
return copied;
|
||||
}
|
||||
|
||||
static ssize_t fuse_buf_read(const struct fuse_buf *dst, size_t dst_off,
|
||||
const struct fuse_buf *src, size_t src_off,
|
||||
size_t len)
|
||||
const struct fuse_buf *src, size_t src_off,
|
||||
size_t len)
|
||||
{
|
||||
ssize_t res = 0;
|
||||
size_t copied = 0;
|
||||
ssize_t res = 0;
|
||||
size_t copied = 0;
|
||||
|
||||
while (len) {
|
||||
if (src->flags & FUSE_BUF_FD_SEEK) {
|
||||
res = pread(src->fd, (char *)dst->mem + dst_off, len,
|
||||
src->pos + src_off);
|
||||
} else {
|
||||
res = read(src->fd, (char *)dst->mem + dst_off, len);
|
||||
}
|
||||
if (res == -1) {
|
||||
if (!copied)
|
||||
return -errno;
|
||||
break;
|
||||
}
|
||||
if (res == 0)
|
||||
break;
|
||||
while (len) {
|
||||
if (src->flags & FUSE_BUF_FD_SEEK) {
|
||||
res = pread(src->fd, (char *)dst->mem + dst_off, len,
|
||||
src->pos + src_off);
|
||||
} else {
|
||||
res = read(src->fd, (char *)dst->mem + dst_off, len);
|
||||
}
|
||||
if (res == -1) {
|
||||
if (!copied) {
|
||||
return -errno;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (res == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
copied += res;
|
||||
if (!(src->flags & FUSE_BUF_FD_RETRY))
|
||||
break;
|
||||
copied += res;
|
||||
if (!(src->flags & FUSE_BUF_FD_RETRY)) {
|
||||
break;
|
||||
}
|
||||
|
||||
dst_off += res;
|
||||
src_off += res;
|
||||
len -= res;
|
||||
}
|
||||
dst_off += res;
|
||||
src_off += res;
|
||||
len -= res;
|
||||
}
|
||||
|
||||
return copied;
|
||||
return copied;
|
||||
}
|
||||
|
||||
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,
|
||||
size_t len)
|
||||
const struct fuse_buf *src, size_t src_off,
|
||||
size_t len)
|
||||
{
|
||||
char buf[4096];
|
||||
struct fuse_buf tmp = {
|
||||
.size = sizeof(buf),
|
||||
.flags = 0,
|
||||
};
|
||||
ssize_t res;
|
||||
size_t copied = 0;
|
||||
char buf[4096];
|
||||
struct fuse_buf tmp = {
|
||||
.size = sizeof(buf),
|
||||
.flags = 0,
|
||||
};
|
||||
ssize_t res;
|
||||
size_t copied = 0;
|
||||
|
||||
tmp.mem = buf;
|
||||
tmp.mem = buf;
|
||||
|
||||
while (len) {
|
||||
size_t this_len = min_size(tmp.size, len);
|
||||
size_t read_len;
|
||||
while (len) {
|
||||
size_t this_len = min_size(tmp.size, len);
|
||||
size_t read_len;
|
||||
|
||||
res = fuse_buf_read(&tmp, 0, src, src_off, this_len);
|
||||
if (res < 0) {
|
||||
if (!copied)
|
||||
return res;
|
||||
break;
|
||||
}
|
||||
if (res == 0)
|
||||
break;
|
||||
res = fuse_buf_read(&tmp, 0, src, src_off, this_len);
|
||||
if (res < 0) {
|
||||
if (!copied) {
|
||||
return res;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (res == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
read_len = res;
|
||||
res = fuse_buf_write(dst, dst_off, &tmp, 0, read_len);
|
||||
if (res < 0) {
|
||||
if (!copied)
|
||||
return res;
|
||||
break;
|
||||
}
|
||||
if (res == 0)
|
||||
break;
|
||||
read_len = res;
|
||||
res = fuse_buf_write(dst, dst_off, &tmp, 0, read_len);
|
||||
if (res < 0) {
|
||||
if (!copied) {
|
||||
return res;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (res == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
copied += res;
|
||||
copied += res;
|
||||
|
||||
if (res < this_len)
|
||||
break;
|
||||
if (res < this_len) {
|
||||
break;
|
||||
}
|
||||
|
||||
dst_off += res;
|
||||
src_off += res;
|
||||
len -= res;
|
||||
}
|
||||
dst_off += res;
|
||||
src_off += res;
|
||||
len -= res;
|
||||
}
|
||||
|
||||
return copied;
|
||||
return copied;
|
||||
}
|
||||
|
||||
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,
|
||||
size_t len, enum fuse_buf_copy_flags flags)
|
||||
const struct fuse_buf *src, size_t src_off,
|
||||
size_t len, enum fuse_buf_copy_flags flags)
|
||||
{
|
||||
int src_is_fd = src->flags & FUSE_BUF_IS_FD;
|
||||
int dst_is_fd = dst->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;
|
||||
|
||||
if (!src_is_fd && !dst_is_fd) {
|
||||
char *dstmem = (char *)dst->mem + dst_off;
|
||||
char *srcmem = (char *)src->mem + src_off;
|
||||
if (!src_is_fd && !dst_is_fd) {
|
||||
char *dstmem = (char *)dst->mem + dst_off;
|
||||
char *srcmem = (char *)src->mem + src_off;
|
||||
|
||||
if (dstmem != srcmem) {
|
||||
if (dstmem + len <= srcmem || srcmem + len <= dstmem)
|
||||
memcpy(dstmem, srcmem, len);
|
||||
else
|
||||
memmove(dstmem, srcmem, len);
|
||||
}
|
||||
if (dstmem != srcmem) {
|
||||
if (dstmem + len <= srcmem || srcmem + len <= dstmem) {
|
||||
memcpy(dstmem, srcmem, len);
|
||||
} else {
|
||||
memmove(dstmem, srcmem, len);
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
} else if (!src_is_fd) {
|
||||
return fuse_buf_write(dst, dst_off, src, src_off, len);
|
||||
} else if (!dst_is_fd) {
|
||||
return fuse_buf_read(dst, dst_off, src, src_off, len);
|
||||
} else {
|
||||
return fuse_buf_fd_to_fd(dst, dst_off, src, src_off, len);
|
||||
}
|
||||
return len;
|
||||
} else if (!src_is_fd) {
|
||||
return fuse_buf_write(dst, dst_off, src, src_off, len);
|
||||
} else if (!dst_is_fd) {
|
||||
return fuse_buf_read(dst, dst_off, src, src_off, len);
|
||||
} else {
|
||||
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)
|
||||
{
|
||||
if (bufv->idx < bufv->count)
|
||||
return &bufv->buf[bufv->idx];
|
||||
else
|
||||
return NULL;
|
||||
if (bufv->idx < bufv->count) {
|
||||
return &bufv->buf[bufv->idx];
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
assert(bufv->off <= buf->size);
|
||||
if (bufv->off == buf->size) {
|
||||
assert(bufv->idx < bufv->count);
|
||||
bufv->idx++;
|
||||
if (bufv->idx == bufv->count)
|
||||
return 0;
|
||||
bufv->off = 0;
|
||||
}
|
||||
return 1;
|
||||
bufv->off += len;
|
||||
assert(bufv->off <= buf->size);
|
||||
if (bufv->off == buf->size) {
|
||||
assert(bufv->idx < bufv->count);
|
||||
bufv->idx++;
|
||||
if (bufv->idx == bufv->count) {
|
||||
return 0;
|
||||
}
|
||||
bufv->off = 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
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)
|
||||
return fuse_buf_size(dstv);
|
||||
if (dstv == srcv) {
|
||||
return fuse_buf_size(dstv);
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
const struct fuse_buf *src = fuse_bufvec_current(srcv);
|
||||
const struct fuse_buf *dst = fuse_bufvec_current(dstv);
|
||||
size_t src_len;
|
||||
size_t dst_len;
|
||||
size_t len;
|
||||
ssize_t res;
|
||||
for (;;) {
|
||||
const struct fuse_buf *src = fuse_bufvec_current(srcv);
|
||||
const struct fuse_buf *dst = fuse_bufvec_current(dstv);
|
||||
size_t src_len;
|
||||
size_t dst_len;
|
||||
size_t len;
|
||||
ssize_t res;
|
||||
|
||||
if (src == NULL || dst == NULL)
|
||||
break;
|
||||
if (src == NULL || dst == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
src_len = src->size - srcv->off;
|
||||
dst_len = dst->size - dstv->off;
|
||||
len = min_size(src_len, dst_len);
|
||||
src_len = src->size - srcv->off;
|
||||
dst_len = dst->size - dstv->off;
|
||||
len = min_size(src_len, dst_len);
|
||||
|
||||
res = fuse_buf_copy_one(dst, dstv->off, src, srcv->off, len, flags);
|
||||
if (res < 0) {
|
||||
if (!copied)
|
||||
return res;
|
||||
break;
|
||||
}
|
||||
copied += res;
|
||||
res = fuse_buf_copy_one(dst, dstv->off, src, srcv->off, len, flags);
|
||||
if (res < 0) {
|
||||
if (!copied) {
|
||||
return res;
|
||||
}
|
||||
break;
|
||||
}
|
||||
copied += res;
|
||||
|
||||
if (!fuse_bufvec_advance(srcv, res) ||
|
||||
!fuse_bufvec_advance(dstv, res))
|
||||
break;
|
||||
if (!fuse_bufvec_advance(srcv, res) ||
|
||||
!fuse_bufvec_advance(dstv, res)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (res < len)
|
||||
break;
|
||||
}
|
||||
if (res < len) {
|
||||
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>
|
||||
|
||||
This program can be distributed under the terms of the GNU LGPLv2.
|
||||
See the file COPYING.LIB.
|
||||
*/
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/** @file */
|
||||
|
||||
#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
|
||||
|
||||
#ifndef FUSE_COMMON_H_
|
||||
#define FUSE_COMMON_H_
|
||||
|
||||
#include "fuse_opt.h"
|
||||
#include "fuse_log.h"
|
||||
#include "fuse_opt.h"
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
|
@ -25,7 +27,7 @@
|
|||
/** Minor version of FUSE library interface */
|
||||
#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)
|
||||
|
||||
/**
|
||||
|
@ -38,67 +40,83 @@
|
|||
* descriptors can share a single file handle.
|
||||
*/
|
||||
struct fuse_file_info {
|
||||
/** Open flags. Available in open() and release() */
|
||||
int flags;
|
||||
/** Open flags. Available in open() and release() */
|
||||
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
|
||||
context's pid, uid, and gid fields will not be valid, and
|
||||
the *fh* value may not match the *fh* value that would
|
||||
have been sent with the corresponding individual write
|
||||
requests if write caching had been disabled. */
|
||||
unsigned int writepage : 1;
|
||||
/*
|
||||
* In case of a write operation indicates if this was caused
|
||||
* by a delayed write from the page cache. If so, then the
|
||||
* context's pid, uid, and gid fields will not be valid, and
|
||||
* the *fh* value may not match the *fh* value that would
|
||||
* have been sent with the corresponding individual write
|
||||
* 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. */
|
||||
unsigned int direct_io : 1;
|
||||
/** Can be filled in by open, to use direct I/O on this file. */
|
||||
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
|
||||
provided the last time the file was open) need not be
|
||||
invalidated. Has no effect when set in other contexts (in
|
||||
particular it does nothing when set by opendir()). */
|
||||
unsigned int keep_cache : 1;
|
||||
/*
|
||||
* Can be filled in by open. It signals the kernel that any
|
||||
* currently cached file data (ie., data that the filesystem
|
||||
* provided the last time the file was open) need not be
|
||||
* invalidated. Has no effect when set in other contexts (in
|
||||
* 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
|
||||
operation. */
|
||||
unsigned int flush : 1;
|
||||
/*
|
||||
* Indicates a flush operation. Set in flush operation, also
|
||||
* maybe set in highlevel lock operation and lowlevel release
|
||||
* operation.
|
||||
*/
|
||||
unsigned int flush:1;
|
||||
|
||||
/** Can be filled in by open, to indicate that the file is not
|
||||
seekable. */
|
||||
unsigned int nonseekable : 1;
|
||||
/*
|
||||
* Can be filled in by open, to indicate that the file is not
|
||||
* seekable.
|
||||
*/
|
||||
unsigned int nonseekable:1;
|
||||
|
||||
/* Indicates that flock locks for this file should be
|
||||
released. If set, lock_owner shall contain a valid value.
|
||||
May only be set in ->release(). */
|
||||
unsigned int flock_release : 1;
|
||||
/*
|
||||
* Indicates that flock locks for this file should be
|
||||
* released. If set, lock_owner shall contain a valid value.
|
||||
* 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
|
||||
effect when set in other contexts (in particular it does
|
||||
nothing when set by open()). */
|
||||
unsigned int cache_readdir : 1;
|
||||
/*
|
||||
* Can be filled in by opendir. It signals the kernel to
|
||||
* enable caching of entries returned by readdir(). Has no
|
||||
* effect when set in other contexts (in particular it does
|
||||
* nothing when set by open()).
|
||||
*/
|
||||
unsigned int cache_readdir:1;
|
||||
|
||||
/** Padding. Reserved for future use*/
|
||||
unsigned int padding : 25;
|
||||
unsigned int padding2 : 32;
|
||||
/** Padding. Reserved for future use*/
|
||||
unsigned int padding:25;
|
||||
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
|
||||
* same file handle. */
|
||||
uint64_t fh;
|
||||
/*
|
||||
* File handle id. May be filled in by filesystem in create,
|
||||
* open, and opendir(). Available in most other file operations on the
|
||||
* same file handle.
|
||||
*/
|
||||
uint64_t fh;
|
||||
|
||||
/** Lock owner id. Available in locking operations and flush */
|
||||
uint64_t lock_owner;
|
||||
/** Lock owner id. Available in locking operations and flush */
|
||||
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. */
|
||||
uint32_t poll_events;
|
||||
/*
|
||||
* Requested poll events. Available in ->poll. Only set on kernels
|
||||
* 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.
|
||||
|
@ -110,7 +128,7 @@ struct fuse_file_info {
|
|||
*
|
||||
* 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.
|
||||
|
@ -118,7 +136,7 @@ struct fuse_file_info {
|
|||
* This feature is enabled by default when supported by the kernel,
|
||||
* 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
|
||||
|
@ -127,14 +145,14 @@ struct fuse_file_info {
|
|||
*
|
||||
* 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 "..".
|
||||
*
|
||||
* 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
|
||||
|
@ -142,7 +160,7 @@ struct fuse_file_info {
|
|||
*
|
||||
* 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
|
||||
|
@ -150,7 +168,7 @@ struct fuse_file_info {
|
|||
*
|
||||
* 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
|
||||
|
@ -158,7 +176,7 @@ struct fuse_file_info {
|
|||
*
|
||||
* 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
|
||||
|
@ -167,7 +185,7 @@ struct fuse_file_info {
|
|||
* This feature is enabled by default when supported by the kernel and
|
||||
* 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
|
||||
|
@ -180,14 +198,14 @@ struct fuse_file_info {
|
|||
* This feature is enabled by default when supported by the kernel and
|
||||
* 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.
|
||||
*
|
||||
* 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
|
||||
|
@ -209,7 +227,7 @@ struct fuse_file_info {
|
|||
*
|
||||
* 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.
|
||||
|
@ -217,7 +235,7 @@ struct fuse_file_info {
|
|||
* This feature is enabled by default when supported by the kernel and if the
|
||||
* filesystem implements a readdirplus() handler.
|
||||
*/
|
||||
#define FUSE_CAP_READDIRPLUS (1 << 13)
|
||||
#define FUSE_CAP_READDIRPLUS (1 << 13)
|
||||
|
||||
/**
|
||||
* 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()
|
||||
* 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.
|
||||
|
@ -256,7 +274,7 @@ struct fuse_file_info {
|
|||
*
|
||||
* 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
|
||||
|
@ -265,7 +283,7 @@ struct fuse_file_info {
|
|||
*
|
||||
* 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
|
||||
|
@ -278,7 +296,7 @@ struct fuse_file_info {
|
|||
* Setting (or unsetting) this flag in the `want` field has *no
|
||||
* 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
|
||||
|
@ -288,7 +306,7 @@ struct fuse_file_info {
|
|||
*
|
||||
* 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.
|
||||
|
@ -307,7 +325,7 @@ struct fuse_file_info {
|
|||
*
|
||||
* 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
|
||||
|
@ -316,7 +334,7 @@ struct fuse_file_info {
|
|||
*
|
||||
* 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
|
||||
|
@ -328,7 +346,7 @@ struct fuse_file_info {
|
|||
*
|
||||
* 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
|
||||
|
@ -340,12 +358,12 @@ struct fuse_file_info {
|
|||
*
|
||||
* FUSE_IOCTL_MAX_IOV: maximum of in_iovecs + out_iovecs
|
||||
*/
|
||||
#define FUSE_IOCTL_COMPAT (1 << 0)
|
||||
#define FUSE_IOCTL_UNRESTRICTED (1 << 1)
|
||||
#define FUSE_IOCTL_RETRY (1 << 2)
|
||||
#define FUSE_IOCTL_DIR (1 << 4)
|
||||
#define FUSE_IOCTL_COMPAT (1 << 0)
|
||||
#define FUSE_IOCTL_UNRESTRICTED (1 << 1)
|
||||
#define FUSE_IOCTL_RETRY (1 << 2)
|
||||
#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
|
||||
|
@ -355,114 +373,114 @@ struct fuse_file_info {
|
|||
* value must usually be smaller than the indicated value.
|
||||
*/
|
||||
struct fuse_conn_info {
|
||||
/**
|
||||
* Major version of the protocol (read-only)
|
||||
*/
|
||||
unsigned proto_major;
|
||||
/**
|
||||
* Major version of the protocol (read-only)
|
||||
*/
|
||||
unsigned proto_major;
|
||||
|
||||
/**
|
||||
* Minor version of the protocol (read-only)
|
||||
*/
|
||||
unsigned proto_minor;
|
||||
/**
|
||||
* Minor version of the protocol (read-only)
|
||||
*/
|
||||
unsigned proto_minor;
|
||||
|
||||
/**
|
||||
* Maximum size of the write buffer
|
||||
*/
|
||||
unsigned max_write;
|
||||
/**
|
||||
* Maximum size of the write buffer
|
||||
*/
|
||||
unsigned max_write;
|
||||
|
||||
/**
|
||||
* Maximum size of read requests. A value of zero indicates no
|
||||
* limit. However, even if the filesystem does not specify a
|
||||
* limit, the maximum size of read requests will still be
|
||||
* limited by the kernel.
|
||||
*
|
||||
* NOTE: For the time being, the maximum size of read requests
|
||||
* must be set both here *and* passed to fuse_session_new()
|
||||
* using the ``-o max_read=<n>`` mount option. At some point
|
||||
* in the future, specifying the mount option will no longer
|
||||
* be necessary.
|
||||
*/
|
||||
unsigned max_read;
|
||||
/**
|
||||
* Maximum size of read requests. A value of zero indicates no
|
||||
* limit. However, even if the filesystem does not specify a
|
||||
* limit, the maximum size of read requests will still be
|
||||
* limited by the kernel.
|
||||
*
|
||||
* NOTE: For the time being, the maximum size of read requests
|
||||
* must be set both here *and* passed to fuse_session_new()
|
||||
* using the ``-o max_read=<n>`` mount option. At some point
|
||||
* in the future, specifying the mount option will no longer
|
||||
* be necessary.
|
||||
*/
|
||||
unsigned max_read;
|
||||
|
||||
/**
|
||||
* Maximum readahead
|
||||
*/
|
||||
unsigned max_readahead;
|
||||
/**
|
||||
* Maximum readahead
|
||||
*/
|
||||
unsigned max_readahead;
|
||||
|
||||
/**
|
||||
* Capability flags that the kernel supports (read-only)
|
||||
*/
|
||||
unsigned capable;
|
||||
/**
|
||||
* Capability flags that the kernel supports (read-only)
|
||||
*/
|
||||
unsigned capable;
|
||||
|
||||
/**
|
||||
* Capability flags that the filesystem wants to enable.
|
||||
*
|
||||
* libfuse attempts to initialize this field with
|
||||
* reasonable default values before calling the init() handler.
|
||||
*/
|
||||
unsigned want;
|
||||
/**
|
||||
* Capability flags that the filesystem wants to enable.
|
||||
*
|
||||
* libfuse attempts to initialize this field with
|
||||
* reasonable default values before calling the init() handler.
|
||||
*/
|
||||
unsigned want;
|
||||
|
||||
/**
|
||||
* Maximum number of pending "background" requests. A
|
||||
* background request is any type of request for which the
|
||||
* total number is not limited by other means. As of kernel
|
||||
* 4.8, only two types of requests fall into this category:
|
||||
*
|
||||
* 1. Read-ahead requests
|
||||
* 2. Asynchronous direct I/O requests
|
||||
*
|
||||
* Read-ahead requests are generated (if max_readahead is
|
||||
* non-zero) by the kernel to preemptively fill its caches
|
||||
* when it anticipates that userspace will soon read more
|
||||
* data.
|
||||
*
|
||||
* Asynchronous direct I/O requests are generated if
|
||||
* FUSE_CAP_ASYNC_DIO is enabled and userspace submits a large
|
||||
* direct I/O request. In this case the kernel will internally
|
||||
* split it up into multiple smaller requests and submit them
|
||||
* to the filesystem concurrently.
|
||||
*
|
||||
* Note that the following requests are *not* background
|
||||
* requests: writeback requests (limited by the kernel's
|
||||
* flusher algorithm), regular (i.e., synchronous and
|
||||
* buffered) userspace read/write requests (limited to one per
|
||||
* thread), asynchronous read requests (Linux's io_submit(2)
|
||||
* call actually blocks, so these are also limited to one per
|
||||
* thread).
|
||||
*/
|
||||
unsigned max_background;
|
||||
/**
|
||||
* Maximum number of pending "background" requests. A
|
||||
* background request is any type of request for which the
|
||||
* total number is not limited by other means. As of kernel
|
||||
* 4.8, only two types of requests fall into this category:
|
||||
*
|
||||
* 1. Read-ahead requests
|
||||
* 2. Asynchronous direct I/O requests
|
||||
*
|
||||
* Read-ahead requests are generated (if max_readahead is
|
||||
* non-zero) by the kernel to preemptively fill its caches
|
||||
* when it anticipates that userspace will soon read more
|
||||
* data.
|
||||
*
|
||||
* Asynchronous direct I/O requests are generated if
|
||||
* FUSE_CAP_ASYNC_DIO is enabled and userspace submits a large
|
||||
* direct I/O request. In this case the kernel will internally
|
||||
* split it up into multiple smaller requests and submit them
|
||||
* to the filesystem concurrently.
|
||||
*
|
||||
* Note that the following requests are *not* background
|
||||
* requests: writeback requests (limited by the kernel's
|
||||
* flusher algorithm), regular (i.e., synchronous and
|
||||
* buffered) userspace read/write requests (limited to one per
|
||||
* thread), asynchronous read requests (Linux's io_submit(2)
|
||||
* call actually blocks, so these are also limited to one per
|
||||
* thread).
|
||||
*/
|
||||
unsigned max_background;
|
||||
|
||||
/**
|
||||
* Kernel congestion threshold parameter. If the number of pending
|
||||
* background requests exceeds this number, the FUSE kernel module will
|
||||
* mark the filesystem as "congested". This instructs the kernel to
|
||||
* expect that queued requests will take some time to complete, and to
|
||||
* adjust its algorithms accordingly (e.g. by putting a waiting thread
|
||||
* to sleep instead of using a busy-loop).
|
||||
*/
|
||||
unsigned congestion_threshold;
|
||||
/**
|
||||
* Kernel congestion threshold parameter. If the number of pending
|
||||
* background requests exceeds this number, the FUSE kernel module will
|
||||
* mark the filesystem as "congested". This instructs the kernel to
|
||||
* expect that queued requests will take some time to complete, and to
|
||||
* adjust its algorithms accordingly (e.g. by putting a waiting thread
|
||||
* to sleep instead of using a busy-loop).
|
||||
*/
|
||||
unsigned congestion_threshold;
|
||||
|
||||
/**
|
||||
* When FUSE_CAP_WRITEBACK_CACHE is enabled, the kernel is responsible
|
||||
* for updating mtime and ctime when write requests are received. The
|
||||
* updated values are passed to the filesystem with setattr() requests.
|
||||
* However, if the filesystem does not support the full resolution of
|
||||
* the kernel timestamps (nanoseconds), the mtime and ctime values used
|
||||
* by kernel and filesystem will differ (and result in an apparent
|
||||
* change of times after a cache flush).
|
||||
*
|
||||
* To prevent this problem, this variable can be used to inform the
|
||||
* kernel about the timestamp granularity supported by the file-system.
|
||||
* The value should be power of 10. The default is 1, i.e. full
|
||||
* nano-second resolution. Filesystems supporting only second resolution
|
||||
* should set this to 1000000000.
|
||||
*/
|
||||
unsigned time_gran;
|
||||
/**
|
||||
* When FUSE_CAP_WRITEBACK_CACHE is enabled, the kernel is responsible
|
||||
* for updating mtime and ctime when write requests are received. The
|
||||
* updated values are passed to the filesystem with setattr() requests.
|
||||
* However, if the filesystem does not support the full resolution of
|
||||
* the kernel timestamps (nanoseconds), the mtime and ctime values used
|
||||
* by kernel and filesystem will differ (and result in an apparent
|
||||
* change of times after a cache flush).
|
||||
*
|
||||
* To prevent this problem, this variable can be used to inform the
|
||||
* kernel about the timestamp granularity supported by the file-system.
|
||||
* The value should be power of 10. The default is 1, i.e. full
|
||||
* nano-second resolution. Filesystems supporting only second resolution
|
||||
* should set this to 1000000000.
|
||||
*/
|
||||
unsigned time_gran;
|
||||
|
||||
/**
|
||||
* For future use.
|
||||
*/
|
||||
unsigned reserved[22];
|
||||
/**
|
||||
* For future use.
|
||||
*/
|
||||
unsigned reserved[22];
|
||||
};
|
||||
|
||||
struct fuse_session;
|
||||
|
@ -489,21 +507,20 @@ struct fuse_conn_info_opts;
|
|||
* -o async_read sets 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 no_remote_lock Equivalent to -o no_remote_flock,no_remote_posix_lock
|
||||
* -o no_remote_flock Unsets FUSE_CAP_FLOCK_LOCKS in conn->want
|
||||
* -o no_remote_posix_lock Unsets FUSE_CAP_POSIX_LOCKS in conn->want
|
||||
* -o [no_]splice_write (un-)sets FUSE_CAP_SPLICE_WRITE in conn->want
|
||||
* -o [no_]splice_move (un-)sets FUSE_CAP_SPLICE_MOVE in conn->want
|
||||
* -o [no_]splice_read (un-)sets FUSE_CAP_SPLICE_READ in conn->want
|
||||
* -o [no_]auto_inval_data (un-)sets FUSE_CAP_AUTO_INVAL_DATA in conn->want
|
||||
* -o readdirplus=no unsets FUSE_CAP_READDIRPLUS in conn->want
|
||||
* -o readdirplus=yes sets FUSE_CAP_READDIRPLUS and unsets
|
||||
* FUSE_CAP_READDIRPLUS_AUTO in conn->want
|
||||
* -o readdirplus=auto sets FUSE_CAP_READDIRPLUS and
|
||||
* FUSE_CAP_READDIRPLUS_AUTO in conn->want
|
||||
* -o [no_]async_dio (un-)sets FUSE_CAP_ASYNC_DIO in conn->want
|
||||
* -o [no_]writeback_cache (un-)sets FUSE_CAP_WRITEBACK_CACHE in conn->want
|
||||
* -o time_gran=N sets conn->time_gran
|
||||
* -o no_remote_lock Equivalent to -o
|
||||
*no_remote_flock,no_remote_posix_lock -o no_remote_flock Unsets
|
||||
*FUSE_CAP_FLOCK_LOCKS in conn->want -o no_remote_posix_lock Unsets
|
||||
*FUSE_CAP_POSIX_LOCKS in conn->want -o [no_]splice_write (un-)sets
|
||||
*FUSE_CAP_SPLICE_WRITE in conn->want -o [no_]splice_move (un-)sets
|
||||
*FUSE_CAP_SPLICE_MOVE in conn->want -o [no_]splice_read (un-)sets
|
||||
*FUSE_CAP_SPLICE_READ in conn->want -o [no_]auto_inval_data (un-)sets
|
||||
*FUSE_CAP_AUTO_INVAL_DATA in conn->want -o readdirplus=no unsets
|
||||
*FUSE_CAP_READDIRPLUS in conn->want -o readdirplus=yes sets
|
||||
*FUSE_CAP_READDIRPLUS and unsets FUSE_CAP_READDIRPLUS_AUTO in conn->want -o
|
||||
*readdirplus=auto sets FUSE_CAP_READDIRPLUS and FUSE_CAP_READDIRPLUS_AUTO
|
||||
*in conn->want -o [no_]async_dio (un-)sets FUSE_CAP_ASYNC_DIO in
|
||||
*conn->want -o [no_]writeback_cache (un-)sets FUSE_CAP_WRITEBACK_CACHE in
|
||||
*conn->want -o time_gran=N sets conn->time_gran
|
||||
*
|
||||
* Known options will be removed from *args*, unknown options will be
|
||||
* passed through unchanged.
|
||||
|
@ -511,7 +528,7 @@ struct fuse_conn_info_opts;
|
|||
* @param args argument vector (input+output)
|
||||
* @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
|
||||
|
@ -521,7 +538,7 @@ struct fuse_conn_info_opts* fuse_parse_conn_info_opts(struct fuse_args *args);
|
|||
* option has been explicitly set.
|
||||
*/
|
||||
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
|
||||
|
@ -552,81 +569,81 @@ const char *fuse_pkgversion(void);
|
|||
*/
|
||||
void fuse_pollhandle_destroy(struct fuse_pollhandle *ph);
|
||||
|
||||
/* ----------------------------------------------------------- *
|
||||
* Data buffer *
|
||||
* ----------------------------------------------------------- */
|
||||
/*
|
||||
* Data buffer
|
||||
*/
|
||||
|
||||
/**
|
||||
* Buffer flags
|
||||
*/
|
||||
enum fuse_buf_flags {
|
||||
/**
|
||||
* Buffer contains a file descriptor
|
||||
*
|
||||
* If this flag is set, the .fd field is valid, otherwise the
|
||||
* .mem fields is valid.
|
||||
*/
|
||||
FUSE_BUF_IS_FD = (1 << 1),
|
||||
/**
|
||||
* Buffer contains a file descriptor
|
||||
*
|
||||
* If this flag is set, the .fd field is valid, otherwise the
|
||||
* .mem fields is valid.
|
||||
*/
|
||||
FUSE_BUF_IS_FD = (1 << 1),
|
||||
|
||||
/**
|
||||
* Seek on the file descriptor
|
||||
*
|
||||
* If this flag is set then the .pos field is valid and is
|
||||
* used to seek to the given offset before performing
|
||||
* operation on file descriptor.
|
||||
*/
|
||||
FUSE_BUF_FD_SEEK = (1 << 2),
|
||||
/**
|
||||
* Seek on the file descriptor
|
||||
*
|
||||
* If this flag is set then the .pos field is valid and is
|
||||
* used to seek to the given offset before performing
|
||||
* operation on file descriptor.
|
||||
*/
|
||||
FUSE_BUF_FD_SEEK = (1 << 2),
|
||||
|
||||
/**
|
||||
* 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
|
||||
* detected.
|
||||
*/
|
||||
FUSE_BUF_FD_RETRY = (1 << 3),
|
||||
/**
|
||||
* 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
|
||||
* detected.
|
||||
*/
|
||||
FUSE_BUF_FD_RETRY = (1 << 3),
|
||||
};
|
||||
|
||||
/**
|
||||
* Buffer copy flags
|
||||
*/
|
||||
enum fuse_buf_copy_flags {
|
||||
/**
|
||||
* Don't use splice(2)
|
||||
*
|
||||
* Always fall back to using read and write instead of
|
||||
* splice(2) to copy data from one file descriptor to another.
|
||||
*
|
||||
* If this flag is not set, then only fall back if splice is
|
||||
* unavailable.
|
||||
*/
|
||||
FUSE_BUF_NO_SPLICE = (1 << 1),
|
||||
/**
|
||||
* Don't use splice(2)
|
||||
*
|
||||
* Always fall back to using read and write instead of
|
||||
* splice(2) to copy data from one file descriptor to another.
|
||||
*
|
||||
* If this flag is not set, then only fall back if splice is
|
||||
* unavailable.
|
||||
*/
|
||||
FUSE_BUF_NO_SPLICE = (1 << 1),
|
||||
|
||||
/**
|
||||
* Force splice
|
||||
*
|
||||
* Always use splice(2) to copy data from one file descriptor
|
||||
* to another. If splice is not available, return -EINVAL.
|
||||
*/
|
||||
FUSE_BUF_FORCE_SPLICE = (1 << 2),
|
||||
/**
|
||||
* Force splice
|
||||
*
|
||||
* Always use splice(2) to copy data from one file descriptor
|
||||
* to another. If splice is not available, return -EINVAL.
|
||||
*/
|
||||
FUSE_BUF_FORCE_SPLICE = (1 << 2),
|
||||
|
||||
/**
|
||||
* Try to move data with splice.
|
||||
*
|
||||
* If splice is used, try to move pages from the source to the
|
||||
* destination instead of copying. See documentation of
|
||||
* SPLICE_F_MOVE in splice(2) man page.
|
||||
*/
|
||||
FUSE_BUF_SPLICE_MOVE = (1 << 3),
|
||||
/**
|
||||
* Try to move data with splice.
|
||||
*
|
||||
* If splice is used, try to move pages from the source to the
|
||||
* destination instead of copying. See documentation of
|
||||
* SPLICE_F_MOVE in splice(2) man page.
|
||||
*/
|
||||
FUSE_BUF_SPLICE_MOVE = (1 << 3),
|
||||
|
||||
/**
|
||||
* Don't block on the pipe when copying data with splice
|
||||
*
|
||||
* Makes the operations on the pipe non-blocking (if the pipe
|
||||
* is full or empty). See SPLICE_F_NONBLOCK in the splice(2)
|
||||
* man page.
|
||||
*/
|
||||
FUSE_BUF_SPLICE_NONBLOCK= (1 << 4),
|
||||
/**
|
||||
* Don't block on the pipe when copying data with splice
|
||||
*
|
||||
* Makes the operations on the pipe non-blocking (if the pipe
|
||||
* is full or empty). See SPLICE_F_NONBLOCK in the splice(2)
|
||||
* man page.
|
||||
*/
|
||||
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
|
||||
*/
|
||||
struct fuse_buf {
|
||||
/**
|
||||
* Size of data in bytes
|
||||
*/
|
||||
size_t size;
|
||||
/**
|
||||
* Size of data in bytes
|
||||
*/
|
||||
size_t size;
|
||||
|
||||
/**
|
||||
* Buffer flags
|
||||
*/
|
||||
enum fuse_buf_flags flags;
|
||||
/**
|
||||
* Buffer flags
|
||||
*/
|
||||
enum fuse_buf_flags flags;
|
||||
|
||||
/**
|
||||
* Memory pointer
|
||||
*
|
||||
* Used unless FUSE_BUF_IS_FD flag is set.
|
||||
*/
|
||||
void *mem;
|
||||
/**
|
||||
* Memory pointer
|
||||
*
|
||||
* Used unless FUSE_BUF_IS_FD flag is set.
|
||||
*/
|
||||
void *mem;
|
||||
|
||||
/**
|
||||
* File descriptor
|
||||
*
|
||||
* Used if FUSE_BUF_IS_FD flag is set.
|
||||
*/
|
||||
int fd;
|
||||
/**
|
||||
* File descriptor
|
||||
*
|
||||
* Used if FUSE_BUF_IS_FD flag is set.
|
||||
*/
|
||||
int fd;
|
||||
|
||||
/**
|
||||
* File position
|
||||
*
|
||||
* Used if FUSE_BUF_FD_SEEK flag is set.
|
||||
*/
|
||||
off_t pos;
|
||||
/**
|
||||
* File position
|
||||
*
|
||||
* Used if FUSE_BUF_FD_SEEK flag is set.
|
||||
*/
|
||||
off_t pos;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -677,41 +694,39 @@ struct fuse_buf {
|
|||
* Allocate dynamically to add more than one buffer.
|
||||
*/
|
||||
struct fuse_bufvec {
|
||||
/**
|
||||
* Number of buffers in the array
|
||||
*/
|
||||
size_t count;
|
||||
/**
|
||||
* Number of buffers in the array
|
||||
*/
|
||||
size_t count;
|
||||
|
||||
/**
|
||||
* Index of current buffer within the array
|
||||
*/
|
||||
size_t idx;
|
||||
/**
|
||||
* Index of current buffer within the array
|
||||
*/
|
||||
size_t idx;
|
||||
|
||||
/**
|
||||
* Current offset within the current buffer
|
||||
*/
|
||||
size_t off;
|
||||
/**
|
||||
* Current offset within the current buffer
|
||||
*/
|
||||
size_t off;
|
||||
|
||||
/**
|
||||
* Array of buffers
|
||||
*/
|
||||
struct fuse_buf buf[1];
|
||||
/**
|
||||
* Array of buffers
|
||||
*/
|
||||
struct fuse_buf buf[1];
|
||||
};
|
||||
|
||||
/* Initialize bufvec with a single buffer of given size */
|
||||
#define FUSE_BUFVEC_INIT(size__) \
|
||||
((struct fuse_bufvec) { \
|
||||
/* .count= */ 1, \
|
||||
/* .idx = */ 0, \
|
||||
/* .off = */ 0, \
|
||||
/* .buf = */ { /* [0] = */ { \
|
||||
/* .size = */ (size__), \
|
||||
/* .flags = */ (enum fuse_buf_flags) 0, \
|
||||
/* .mem = */ NULL, \
|
||||
/* .fd = */ -1, \
|
||||
/* .pos = */ 0, \
|
||||
} } \
|
||||
} )
|
||||
#define FUSE_BUFVEC_INIT(size__) \
|
||||
((struct fuse_bufvec){ /* .count= */ 1, \
|
||||
/* .idx = */ 0, \
|
||||
/* .off = */ 0, /* .buf = */ \
|
||||
{ /* [0] = */ { \
|
||||
/* .size = */ (size__), \
|
||||
/* .flags = */ (enum fuse_buf_flags)0, \
|
||||
/* .mem = */ NULL, \
|
||||
/* .fd = */ -1, \
|
||||
/* .pos = */ 0, \
|
||||
} } })
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
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
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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);
|
||||
|
||||
/* ----------------------------------------------------------- *
|
||||
* Compatibility stuff *
|
||||
* ----------------------------------------------------------- */
|
||||
/*
|
||||
* Compatibility stuff
|
||||
*/
|
||||
|
||||
#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
|
||||
|
||||
|
||||
|
@ -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!
|
||||
*/
|
||||
|
||||
#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");
|
||||
#else
|
||||
struct _fuse_off_t_must_be_64bit_dummy_struct \
|
||||
{ unsigned _fuse_off_t_must_be_64bit:((sizeof(off_t) == 8) ? 1 : -1); };
|
||||
struct _fuse_off_t_must_be_64bit_dummy_struct {
|
||||
unsigned _fuse_off_t_must_be_64bit:((sizeof(off_t) == 8) ? 1 : -1);
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* FUSE_COMMON_H_ */
|
||||
|
|
|
@ -1,71 +1,71 @@
|
|||
/*
|
||||
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
|
||||
*/
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include "fuse.h"
|
||||
#include "fuse_lowlevel.h"
|
||||
|
||||
struct fuse_req {
|
||||
struct fuse_session *se;
|
||||
uint64_t unique;
|
||||
int ctr;
|
||||
pthread_mutex_t lock;
|
||||
struct fuse_ctx ctx;
|
||||
struct fuse_chan *ch;
|
||||
int interrupted;
|
||||
unsigned int ioctl_64bit : 1;
|
||||
union {
|
||||
struct {
|
||||
uint64_t unique;
|
||||
} i;
|
||||
struct {
|
||||
fuse_interrupt_func_t func;
|
||||
void *data;
|
||||
} ni;
|
||||
} u;
|
||||
struct fuse_req *next;
|
||||
struct fuse_req *prev;
|
||||
struct fuse_session *se;
|
||||
uint64_t unique;
|
||||
int ctr;
|
||||
pthread_mutex_t lock;
|
||||
struct fuse_ctx ctx;
|
||||
struct fuse_chan *ch;
|
||||
int interrupted;
|
||||
unsigned int ioctl_64bit:1;
|
||||
union {
|
||||
struct {
|
||||
uint64_t unique;
|
||||
} i;
|
||||
struct {
|
||||
fuse_interrupt_func_t func;
|
||||
void *data;
|
||||
} ni;
|
||||
} u;
|
||||
struct fuse_req *next;
|
||||
struct fuse_req *prev;
|
||||
};
|
||||
|
||||
struct fuse_notify_req {
|
||||
uint64_t unique;
|
||||
void (*reply)(struct fuse_notify_req *, fuse_req_t, fuse_ino_t,
|
||||
const void *, const struct fuse_buf *);
|
||||
struct fuse_notify_req *next;
|
||||
struct fuse_notify_req *prev;
|
||||
uint64_t unique;
|
||||
void (*reply)(struct fuse_notify_req *, fuse_req_t, fuse_ino_t,
|
||||
const void *, const struct fuse_buf *);
|
||||
struct fuse_notify_req *next;
|
||||
struct fuse_notify_req *prev;
|
||||
};
|
||||
|
||||
struct fuse_session {
|
||||
char *mountpoint;
|
||||
volatile int exited;
|
||||
int fd;
|
||||
int debug;
|
||||
int deny_others;
|
||||
struct fuse_lowlevel_ops op;
|
||||
int got_init;
|
||||
struct cuse_data *cuse_data;
|
||||
void *userdata;
|
||||
uid_t owner;
|
||||
struct fuse_conn_info conn;
|
||||
struct fuse_req list;
|
||||
struct fuse_req interrupts;
|
||||
pthread_mutex_t lock;
|
||||
int got_destroy;
|
||||
int broken_splice_nonblock;
|
||||
uint64_t notify_ctr;
|
||||
struct fuse_notify_req notify_list;
|
||||
size_t bufsize;
|
||||
int error;
|
||||
char *mountpoint;
|
||||
volatile int exited;
|
||||
int fd;
|
||||
int debug;
|
||||
int deny_others;
|
||||
struct fuse_lowlevel_ops op;
|
||||
int got_init;
|
||||
struct cuse_data *cuse_data;
|
||||
void *userdata;
|
||||
uid_t owner;
|
||||
struct fuse_conn_info conn;
|
||||
struct fuse_req list;
|
||||
struct fuse_req interrupts;
|
||||
pthread_mutex_t lock;
|
||||
int got_destroy;
|
||||
int broken_splice_nonblock;
|
||||
uint64_t notify_ctr;
|
||||
struct fuse_notify_req notify_list;
|
||||
size_t bufsize;
|
||||
int error;
|
||||
};
|
||||
|
||||
struct fuse_chan {
|
||||
pthread_mutex_t lock;
|
||||
int ctr;
|
||||
int fd;
|
||||
pthread_mutex_t lock;
|
||||
int ctr;
|
||||
int fd;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -76,19 +76,20 @@ struct fuse_chan {
|
|||
*
|
||||
*/
|
||||
struct fuse_module {
|
||||
char *name;
|
||||
fuse_module_factory_t factory;
|
||||
struct fuse_module *next;
|
||||
struct fusemod_so *so;
|
||||
int ctr;
|
||||
char *name;
|
||||
fuse_module_factory_t factory;
|
||||
struct fuse_module *next;
|
||||
struct fusemod_so *so;
|
||||
int ctr;
|
||||
};
|
||||
|
||||
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_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
|
||||
|
|
|
@ -1,40 +1,40 @@
|
|||
/*
|
||||
FUSE: Filesystem in Userspace
|
||||
Copyright (C) 2019 Red Hat, Inc.
|
||||
|
||||
Logging API.
|
||||
|
||||
This program can be distributed under the terms of the GNU LGPLv2.
|
||||
See the file COPYING.LIB
|
||||
*/
|
||||
* FUSE: Filesystem in Userspace
|
||||
* Copyright (C) 2019 Red Hat, Inc.
|
||||
*
|
||||
* Logging API.
|
||||
*
|
||||
* This program can be distributed under the terms of the GNU LGPLv2.
|
||||
* See the file COPYING.LIB
|
||||
*/
|
||||
|
||||
#include "fuse_log.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static void default_log_func(
|
||||
__attribute__(( unused )) enum fuse_log_level level,
|
||||
const char *fmt, va_list ap)
|
||||
static void default_log_func(__attribute__((unused)) enum fuse_log_level level,
|
||||
const char *fmt, va_list ap)
|
||||
{
|
||||
vfprintf(stderr, fmt, ap);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
}
|
||||
|
||||
static fuse_log_func_t log_func = default_log_func;
|
||||
|
||||
void fuse_set_log_func(fuse_log_func_t func)
|
||||
{
|
||||
if (!func)
|
||||
func = default_log_func;
|
||||
if (!func) {
|
||||
func = default_log_func;
|
||||
}
|
||||
|
||||
log_func = func;
|
||||
log_func = func;
|
||||
}
|
||||
|
||||
void fuse_log(enum fuse_log_level level, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
log_func(level, fmt, ap);
|
||||
va_end(ap);
|
||||
va_start(ap, fmt);
|
||||
log_func(level, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
FUSE: Filesystem in Userspace
|
||||
Copyright (C) 2019 Red Hat, Inc.
|
||||
|
||||
This program can be distributed under the terms of the GNU LGPLv2.
|
||||
See the file COPYING.LIB.
|
||||
*/
|
||||
* FUSE: Filesystem in Userspace
|
||||
* Copyright (C) 2019 Red Hat, Inc.
|
||||
*
|
||||
* This program can be distributed under the terms of the GNU LGPLv2.
|
||||
* See the file COPYING.LIB.
|
||||
*/
|
||||
|
||||
#ifndef FUSE_LOG_H_
|
||||
#define FUSE_LOG_H_
|
||||
|
@ -22,14 +22,14 @@
|
|||
* These levels correspond to syslog(2) log levels since they are widely used.
|
||||
*/
|
||||
enum fuse_log_level {
|
||||
FUSE_LOG_EMERG,
|
||||
FUSE_LOG_ALERT,
|
||||
FUSE_LOG_CRIT,
|
||||
FUSE_LOG_ERR,
|
||||
FUSE_LOG_WARNING,
|
||||
FUSE_LOG_NOTICE,
|
||||
FUSE_LOG_INFO,
|
||||
FUSE_LOG_DEBUG
|
||||
FUSE_LOG_EMERG,
|
||||
FUSE_LOG_ALERT,
|
||||
FUSE_LOG_CRIT,
|
||||
FUSE_LOG_ERR,
|
||||
FUSE_LOG_WARNING,
|
||||
FUSE_LOG_NOTICE,
|
||||
FUSE_LOG_INFO,
|
||||
FUSE_LOG_DEBUG
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -45,8 +45,8 @@ enum fuse_log_level {
|
|||
* @param fmt sprintf-style format string including newline
|
||||
* @param ap format string arguments
|
||||
*/
|
||||
typedef void (*fuse_log_func_t)(enum fuse_log_level level,
|
||||
const char *fmt, va_list ap);
|
||||
typedef void (*fuse_log_func_t)(enum fuse_log_level level, const char *fmt,
|
||||
va_list ap);
|
||||
|
||||
/**
|
||||
* 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
|
||||
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
|
||||
*/
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
/*
|
||||
Versioned symbols cannot be used in some cases because it
|
||||
- confuse the dynamic linker in uClibc
|
||||
- not supported on MacOSX (in MachO binary format)
|
||||
*/
|
||||
* Versioned symbols cannot be used in some cases because it
|
||||
* - confuse the dynamic linker in uClibc
|
||||
* - not supported on MacOSX (in MachO binary format)
|
||||
*/
|
||||
#if (!defined(__UCLIBC__) && !defined(__APPLE__))
|
||||
#define FUSE_SYMVER(x) __asm__(x)
|
||||
#else
|
||||
|
@ -25,11 +25,11 @@
|
|||
/* Is this hack still needed? */
|
||||
static inline void fuse_mutex_init(pthread_mutex_t *mut)
|
||||
{
|
||||
pthread_mutexattr_t attr;
|
||||
pthread_mutexattr_init(&attr);
|
||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ADAPTIVE_NP);
|
||||
pthread_mutex_init(mut, &attr);
|
||||
pthread_mutexattr_destroy(&attr);
|
||||
pthread_mutexattr_t attr;
|
||||
pthread_mutexattr_init(&attr);
|
||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ADAPTIVE_NP);
|
||||
pthread_mutex_init(mut, &attr);
|
||||
pthread_mutexattr_destroy(&attr);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,423 +1,450 @@
|
|||
/*
|
||||
FUSE: Filesystem in Userspace
|
||||
Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
|
||||
|
||||
Implementation of option parsing routines (dealing with `struct
|
||||
fuse_args`).
|
||||
|
||||
This program can be distributed under the terms of the GNU LGPLv2.
|
||||
See the file COPYING.LIB
|
||||
*/
|
||||
* FUSE: Filesystem in Userspace
|
||||
* Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
|
||||
*
|
||||
* Implementation of option parsing routines (dealing with `struct
|
||||
* fuse_args`).
|
||||
*
|
||||
* This program can be distributed under the terms of the GNU LGPLv2.
|
||||
* See the file COPYING.LIB
|
||||
*/
|
||||
|
||||
#include "fuse_opt.h"
|
||||
#include "config.h"
|
||||
#include "fuse_i.h"
|
||||
#include "fuse_opt.h"
|
||||
#include "fuse_misc.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
struct fuse_opt_context {
|
||||
void *data;
|
||||
const struct fuse_opt *opt;
|
||||
fuse_opt_proc_t proc;
|
||||
int argctr;
|
||||
int argc;
|
||||
char **argv;
|
||||
struct fuse_args outargs;
|
||||
char *opts;
|
||||
int nonopt;
|
||||
void *data;
|
||||
const struct fuse_opt *opt;
|
||||
fuse_opt_proc_t proc;
|
||||
int argctr;
|
||||
int argc;
|
||||
char **argv;
|
||||
struct fuse_args outargs;
|
||||
char *opts;
|
||||
int nonopt;
|
||||
};
|
||||
|
||||
void fuse_opt_free_args(struct fuse_args *args)
|
||||
{
|
||||
if (args) {
|
||||
if (args->argv && args->allocated) {
|
||||
int i;
|
||||
for (i = 0; i < args->argc; i++)
|
||||
free(args->argv[i]);
|
||||
free(args->argv);
|
||||
}
|
||||
args->argc = 0;
|
||||
args->argv = NULL;
|
||||
args->allocated = 0;
|
||||
}
|
||||
if (args) {
|
||||
if (args->argv && args->allocated) {
|
||||
int i;
|
||||
for (i = 0; i < args->argc; i++) {
|
||||
free(args->argv[i]);
|
||||
}
|
||||
free(args->argv);
|
||||
}
|
||||
args->argc = 0;
|
||||
args->argv = NULL;
|
||||
args->allocated = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int alloc_failed(void)
|
||||
{
|
||||
fuse_log(FUSE_LOG_ERR, "fuse: memory allocation failed\n");
|
||||
return -1;
|
||||
fuse_log(FUSE_LOG_ERR, "fuse: memory allocation failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int fuse_opt_add_arg(struct fuse_args *args, const char *arg)
|
||||
{
|
||||
char **newargv;
|
||||
char *newarg;
|
||||
char **newargv;
|
||||
char *newarg;
|
||||
|
||||
assert(!args->argv || args->allocated);
|
||||
assert(!args->argv || args->allocated);
|
||||
|
||||
newarg = strdup(arg);
|
||||
if (!newarg)
|
||||
return alloc_failed();
|
||||
newarg = strdup(arg);
|
||||
if (!newarg) {
|
||||
return alloc_failed();
|
||||
}
|
||||
|
||||
newargv = realloc(args->argv, (args->argc + 2) * sizeof(char *));
|
||||
if (!newargv) {
|
||||
free(newarg);
|
||||
return alloc_failed();
|
||||
}
|
||||
newargv = realloc(args->argv, (args->argc + 2) * sizeof(char *));
|
||||
if (!newargv) {
|
||||
free(newarg);
|
||||
return alloc_failed();
|
||||
}
|
||||
|
||||
args->argv = newargv;
|
||||
args->allocated = 1;
|
||||
args->argv[args->argc++] = newarg;
|
||||
args->argv[args->argc] = NULL;
|
||||
return 0;
|
||||
args->argv = newargv;
|
||||
args->allocated = 1;
|
||||
args->argv[args->argc++] = newarg;
|
||||
args->argv[args->argc] = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fuse_opt_insert_arg_common(struct fuse_args *args, int pos,
|
||||
const char *arg)
|
||||
const char *arg)
|
||||
{
|
||||
assert(pos <= args->argc);
|
||||
if (fuse_opt_add_arg(args, arg) == -1)
|
||||
return -1;
|
||||
assert(pos <= args->argc);
|
||||
if (fuse_opt_add_arg(args, arg) == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pos != args->argc - 1) {
|
||||
char *newarg = args->argv[args->argc - 1];
|
||||
memmove(&args->argv[pos + 1], &args->argv[pos],
|
||||
sizeof(char *) * (args->argc - pos - 1));
|
||||
args->argv[pos] = newarg;
|
||||
}
|
||||
return 0;
|
||||
if (pos != args->argc - 1) {
|
||||
char *newarg = args->argv[args->argc - 1];
|
||||
memmove(&args->argv[pos + 1], &args->argv[pos],
|
||||
sizeof(char *) * (args->argc - pos - 1));
|
||||
args->argv[pos] = newarg;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if (ctx->argctr + 1 >= ctx->argc) {
|
||||
fuse_log(FUSE_LOG_ERR, "fuse: missing argument after `%s'\n", opt);
|
||||
return -1;
|
||||
}
|
||||
ctx->argctr++;
|
||||
return 0;
|
||||
if (ctx->argctr + 1 >= ctx->argc) {
|
||||
fuse_log(FUSE_LOG_ERR, "fuse: missing argument after `%s'\n", opt);
|
||||
return -1;
|
||||
}
|
||||
ctx->argctr++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
unsigned oldlen = *opts ? strlen(*opts) : 0;
|
||||
char *d = realloc(*opts, oldlen + 1 + strlen(opt) * 2 + 1);
|
||||
unsigned oldlen = *opts ? strlen(*opts) : 0;
|
||||
char *d = realloc(*opts, oldlen + 1 + strlen(opt) * 2 + 1);
|
||||
|
||||
if (!d)
|
||||
return alloc_failed();
|
||||
if (!d) {
|
||||
return alloc_failed();
|
||||
}
|
||||
|
||||
*opts = d;
|
||||
if (oldlen) {
|
||||
d += oldlen;
|
||||
*d++ = ',';
|
||||
}
|
||||
*opts = d;
|
||||
if (oldlen) {
|
||||
d += oldlen;
|
||||
*d++ = ',';
|
||||
}
|
||||
|
||||
for (; *opt; opt++) {
|
||||
if (esc && (*opt == ',' || *opt == '\\'))
|
||||
*d++ = '\\';
|
||||
*d++ = *opt;
|
||||
}
|
||||
*d = '\0';
|
||||
for (; *opt; opt++) {
|
||||
if (esc && (*opt == ',' || *opt == '\\')) {
|
||||
*d++ = '\\';
|
||||
}
|
||||
*d++ = *opt;
|
||||
}
|
||||
*d = '\0';
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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,
|
||||
int iso)
|
||||
int iso)
|
||||
{
|
||||
if (key == FUSE_OPT_KEY_DISCARD)
|
||||
return 0;
|
||||
if (key == FUSE_OPT_KEY_DISCARD) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (key != FUSE_OPT_KEY_KEEP && ctx->proc) {
|
||||
int res = ctx->proc(ctx->data, arg, key, &ctx->outargs);
|
||||
if (res == -1 || !res)
|
||||
return res;
|
||||
}
|
||||
if (iso)
|
||||
return add_opt(ctx, arg);
|
||||
else
|
||||
return add_arg(ctx, arg);
|
||||
if (key != FUSE_OPT_KEY_KEEP && ctx->proc) {
|
||||
int res = ctx->proc(ctx->data, arg, key, &ctx->outargs);
|
||||
if (res == -1 || !res) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
if (iso) {
|
||||
return add_opt(ctx, arg);
|
||||
} else {
|
||||
return add_arg(ctx, arg);
|
||||
}
|
||||
}
|
||||
|
||||
static int match_template(const char *t, const char *arg, unsigned *sepp)
|
||||
{
|
||||
int arglen = strlen(arg);
|
||||
const char *sep = strchr(t, '=');
|
||||
sep = sep ? sep : strchr(t, ' ');
|
||||
if (sep && (!sep[1] || sep[1] == '%')) {
|
||||
int tlen = sep - t;
|
||||
if (sep[0] == '=')
|
||||
tlen ++;
|
||||
if (arglen >= tlen && strncmp(arg, t, tlen) == 0) {
|
||||
*sepp = sep - t;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (strcmp(t, arg) == 0) {
|
||||
*sepp = 0;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
int arglen = strlen(arg);
|
||||
const char *sep = strchr(t, '=');
|
||||
sep = sep ? sep : strchr(t, ' ');
|
||||
if (sep && (!sep[1] || sep[1] == '%')) {
|
||||
int tlen = sep - t;
|
||||
if (sep[0] == '=') {
|
||||
tlen++;
|
||||
}
|
||||
if (arglen >= tlen && strncmp(arg, t, tlen) == 0) {
|
||||
*sepp = sep - t;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (strcmp(t, arg) == 0) {
|
||||
*sepp = 0;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
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++)
|
||||
if (match_template(opt->templ, arg, sepp))
|
||||
return opt;
|
||||
return NULL;
|
||||
for (; opt && opt->templ; opt++) {
|
||||
if (match_template(opt->templ, arg, sepp)) {
|
||||
return opt;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int fuse_opt_match(const struct fuse_opt *opts, const char *opt)
|
||||
{
|
||||
unsigned dummy;
|
||||
return find_opt(opts, opt, &dummy) ? 1 : 0;
|
||||
unsigned dummy;
|
||||
return find_opt(opts, opt, &dummy) ? 1 : 0;
|
||||
}
|
||||
|
||||
static int process_opt_param(void *var, const char *format, const char *param,
|
||||
const char *arg)
|
||||
const char *arg)
|
||||
{
|
||||
assert(format[0] == '%');
|
||||
if (format[1] == 's') {
|
||||
char **s = var;
|
||||
char *copy = strdup(param);
|
||||
if (!copy)
|
||||
return alloc_failed();
|
||||
assert(format[0] == '%');
|
||||
if (format[1] == 's') {
|
||||
char **s = var;
|
||||
char *copy = strdup(param);
|
||||
if (!copy) {
|
||||
return alloc_failed();
|
||||
}
|
||||
|
||||
free(*s);
|
||||
*s = copy;
|
||||
} else {
|
||||
if (sscanf(param, format, var) != 1) {
|
||||
fuse_log(FUSE_LOG_ERR, "fuse: invalid parameter in option `%s'\n", arg);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
free(*s);
|
||||
*s = copy;
|
||||
} else {
|
||||
if (sscanf(param, format, var) != 1) {
|
||||
fuse_log(FUSE_LOG_ERR, "fuse: invalid parameter in option `%s'\n",
|
||||
arg);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int process_opt(struct fuse_opt_context *ctx,
|
||||
const struct fuse_opt *opt, unsigned sep,
|
||||
const char *arg, int iso)
|
||||
static int process_opt(struct fuse_opt_context *ctx, const struct fuse_opt *opt,
|
||||
unsigned sep, const char *arg, int iso)
|
||||
{
|
||||
if (opt->offset == -1U) {
|
||||
if (call_proc(ctx, arg, opt->value, iso) == -1)
|
||||
return -1;
|
||||
} else {
|
||||
void *var = (char *)ctx->data + opt->offset;
|
||||
if (sep && opt->templ[sep + 1]) {
|
||||
const char *param = arg + sep;
|
||||
if (opt->templ[sep] == '=')
|
||||
param ++;
|
||||
if (process_opt_param(var, opt->templ + sep + 1,
|
||||
param, arg) == -1)
|
||||
return -1;
|
||||
} else
|
||||
*(int *)var = opt->value;
|
||||
}
|
||||
return 0;
|
||||
if (opt->offset == -1U) {
|
||||
if (call_proc(ctx, arg, opt->value, iso) == -1) {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
void *var = (char *)ctx->data + opt->offset;
|
||||
if (sep && opt->templ[sep + 1]) {
|
||||
const char *param = arg + sep;
|
||||
if (opt->templ[sep] == '=') {
|
||||
param++;
|
||||
}
|
||||
if (process_opt_param(var, opt->templ + sep + 1, param, arg) ==
|
||||
-1) {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
*(int *)var = opt->value;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int process_opt_sep_arg(struct fuse_opt_context *ctx,
|
||||
const struct fuse_opt *opt, unsigned sep,
|
||||
const char *arg, int iso)
|
||||
const struct fuse_opt *opt, unsigned sep,
|
||||
const char *arg, int iso)
|
||||
{
|
||||
int res;
|
||||
char *newarg;
|
||||
char *param;
|
||||
int res;
|
||||
char *newarg;
|
||||
char *param;
|
||||
|
||||
if (next_arg(ctx, arg) == -1)
|
||||
return -1;
|
||||
if (next_arg(ctx, arg) == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
param = ctx->argv[ctx->argctr];
|
||||
newarg = malloc(sep + strlen(param) + 1);
|
||||
if (!newarg)
|
||||
return alloc_failed();
|
||||
param = ctx->argv[ctx->argctr];
|
||||
newarg = malloc(sep + strlen(param) + 1);
|
||||
if (!newarg) {
|
||||
return alloc_failed();
|
||||
}
|
||||
|
||||
memcpy(newarg, arg, sep);
|
||||
strcpy(newarg + sep, param);
|
||||
res = process_opt(ctx, opt, sep, newarg, iso);
|
||||
free(newarg);
|
||||
memcpy(newarg, arg, sep);
|
||||
strcpy(newarg + sep, param);
|
||||
res = process_opt(ctx, opt, sep, newarg, iso);
|
||||
free(newarg);
|
||||
|
||||
return res;
|
||||
return res;
|
||||
}
|
||||
|
||||
static int process_gopt(struct fuse_opt_context *ctx, const char *arg, int iso)
|
||||
{
|
||||
unsigned sep;
|
||||
const struct fuse_opt *opt = find_opt(ctx->opt, arg, &sep);
|
||||
if (opt) {
|
||||
for (; opt; opt = find_opt(opt + 1, arg, &sep)) {
|
||||
int res;
|
||||
if (sep && opt->templ[sep] == ' ' && !arg[sep])
|
||||
res = process_opt_sep_arg(ctx, opt, sep, arg,
|
||||
iso);
|
||||
else
|
||||
res = process_opt(ctx, opt, sep, arg, iso);
|
||||
if (res == -1)
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
} else
|
||||
return call_proc(ctx, arg, FUSE_OPT_KEY_OPT, iso);
|
||||
unsigned sep;
|
||||
const struct fuse_opt *opt = find_opt(ctx->opt, arg, &sep);
|
||||
if (opt) {
|
||||
for (; opt; opt = find_opt(opt + 1, arg, &sep)) {
|
||||
int res;
|
||||
if (sep && opt->templ[sep] == ' ' && !arg[sep]) {
|
||||
res = process_opt_sep_arg(ctx, opt, sep, arg, iso);
|
||||
} else {
|
||||
res = process_opt(ctx, opt, sep, arg, iso);
|
||||
}
|
||||
if (res == -1) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
} else {
|
||||
return call_proc(ctx, arg, FUSE_OPT_KEY_OPT, iso);
|
||||
}
|
||||
}
|
||||
|
||||
static int process_real_option_group(struct fuse_opt_context *ctx, char *opts)
|
||||
{
|
||||
char *s = opts;
|
||||
char *d = s;
|
||||
int end = 0;
|
||||
char *s = opts;
|
||||
char *d = s;
|
||||
int end = 0;
|
||||
|
||||
while (!end) {
|
||||
if (*s == '\0')
|
||||
end = 1;
|
||||
if (*s == ',' || end) {
|
||||
int res;
|
||||
while (!end) {
|
||||
if (*s == '\0') {
|
||||
end = 1;
|
||||
}
|
||||
if (*s == ',' || end) {
|
||||
int res;
|
||||
|
||||
*d = '\0';
|
||||
res = process_gopt(ctx, opts, 1);
|
||||
if (res == -1)
|
||||
return -1;
|
||||
d = opts;
|
||||
} else {
|
||||
if (s[0] == '\\' && s[1] != '\0') {
|
||||
s++;
|
||||
if (s[0] >= '0' && s[0] <= '3' &&
|
||||
s[1] >= '0' && s[1] <= '7' &&
|
||||
s[2] >= '0' && s[2] <= '7') {
|
||||
*d++ = (s[0] - '0') * 0100 +
|
||||
(s[1] - '0') * 0010 +
|
||||
(s[2] - '0');
|
||||
s += 2;
|
||||
} else {
|
||||
*d++ = *s;
|
||||
}
|
||||
} else {
|
||||
*d++ = *s;
|
||||
}
|
||||
}
|
||||
s++;
|
||||
}
|
||||
*d = '\0';
|
||||
res = process_gopt(ctx, opts, 1);
|
||||
if (res == -1) {
|
||||
return -1;
|
||||
}
|
||||
d = opts;
|
||||
} else {
|
||||
if (s[0] == '\\' && s[1] != '\0') {
|
||||
s++;
|
||||
if (s[0] >= '0' && s[0] <= '3' && s[1] >= '0' && s[1] <= '7' &&
|
||||
s[2] >= '0' && s[2] <= '7') {
|
||||
*d++ = (s[0] - '0') * 0100 + (s[1] - '0') * 0010 +
|
||||
(s[2] - '0');
|
||||
s += 2;
|
||||
} else {
|
||||
*d++ = *s;
|
||||
}
|
||||
} else {
|
||||
*d++ = *s;
|
||||
}
|
||||
}
|
||||
s++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int process_option_group(struct fuse_opt_context *ctx, const char *opts)
|
||||
{
|
||||
int res;
|
||||
char *copy = strdup(opts);
|
||||
int res;
|
||||
char *copy = strdup(opts);
|
||||
|
||||
if (!copy) {
|
||||
fuse_log(FUSE_LOG_ERR, "fuse: memory allocation failed\n");
|
||||
return -1;
|
||||
}
|
||||
res = process_real_option_group(ctx, copy);
|
||||
free(copy);
|
||||
return res;
|
||||
if (!copy) {
|
||||
fuse_log(FUSE_LOG_ERR, "fuse: memory allocation failed\n");
|
||||
return -1;
|
||||
}
|
||||
res = process_real_option_group(ctx, copy);
|
||||
free(copy);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int process_one(struct fuse_opt_context *ctx, const char *arg)
|
||||
{
|
||||
if (ctx->nonopt || arg[0] != '-')
|
||||
return call_proc(ctx, arg, FUSE_OPT_KEY_NONOPT, 0);
|
||||
else if (arg[1] == 'o') {
|
||||
if (arg[2])
|
||||
return process_option_group(ctx, arg + 2);
|
||||
else {
|
||||
if (next_arg(ctx, arg) == -1)
|
||||
return -1;
|
||||
if (ctx->nonopt || arg[0] != '-') {
|
||||
return call_proc(ctx, arg, FUSE_OPT_KEY_NONOPT, 0);
|
||||
} else if (arg[1] == 'o') {
|
||||
if (arg[2]) {
|
||||
return process_option_group(ctx, arg + 2);
|
||||
} else {
|
||||
if (next_arg(ctx, arg) == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return process_option_group(ctx,
|
||||
ctx->argv[ctx->argctr]);
|
||||
}
|
||||
} else if (arg[1] == '-' && !arg[2]) {
|
||||
if (add_arg(ctx, arg) == -1)
|
||||
return -1;
|
||||
ctx->nonopt = ctx->outargs.argc;
|
||||
return 0;
|
||||
} else
|
||||
return process_gopt(ctx, arg, 0);
|
||||
return process_option_group(ctx, ctx->argv[ctx->argctr]);
|
||||
}
|
||||
} else if (arg[1] == '-' && !arg[2]) {
|
||||
if (add_arg(ctx, arg) == -1) {
|
||||
return -1;
|
||||
}
|
||||
ctx->nonopt = ctx->outargs.argc;
|
||||
return 0;
|
||||
} else {
|
||||
return process_gopt(ctx, arg, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static int opt_parse(struct fuse_opt_context *ctx)
|
||||
{
|
||||
if (ctx->argc) {
|
||||
if (add_arg(ctx, ctx->argv[0]) == -1)
|
||||
return -1;
|
||||
}
|
||||
if (ctx->argc) {
|
||||
if (add_arg(ctx, ctx->argv[0]) == -1) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
for (ctx->argctr = 1; ctx->argctr < ctx->argc; ctx->argctr++)
|
||||
if (process_one(ctx, ctx->argv[ctx->argctr]) == -1)
|
||||
return -1;
|
||||
for (ctx->argctr = 1; ctx->argctr < ctx->argc; ctx->argctr++) {
|
||||
if (process_one(ctx, ctx->argv[ctx->argctr]) == -1) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->opts) {
|
||||
if (fuse_opt_insert_arg(&ctx->outargs, 1, "-o") == -1 ||
|
||||
fuse_opt_insert_arg(&ctx->outargs, 2, ctx->opts) == -1)
|
||||
return -1;
|
||||
}
|
||||
if (ctx->opts) {
|
||||
if (fuse_opt_insert_arg(&ctx->outargs, 1, "-o") == -1 ||
|
||||
fuse_opt_insert_arg(&ctx->outargs, 2, ctx->opts) == -1) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* If option separator ("--") is the last argument, remove it */
|
||||
if (ctx->nonopt && ctx->nonopt == ctx->outargs.argc &&
|
||||
strcmp(ctx->outargs.argv[ctx->outargs.argc - 1], "--") == 0) {
|
||||
free(ctx->outargs.argv[ctx->outargs.argc - 1]);
|
||||
ctx->outargs.argv[--ctx->outargs.argc] = NULL;
|
||||
}
|
||||
/* If option separator ("--") is the last argument, remove it */
|
||||
if (ctx->nonopt && ctx->nonopt == ctx->outargs.argc &&
|
||||
strcmp(ctx->outargs.argv[ctx->outargs.argc - 1], "--") == 0) {
|
||||
free(ctx->outargs.argv[ctx->outargs.argc - 1]);
|
||||
ctx->outargs.argv[--ctx->outargs.argc] = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
struct fuse_opt_context ctx = {
|
||||
.data = data,
|
||||
.opt = opts,
|
||||
.proc = proc,
|
||||
};
|
||||
int res;
|
||||
struct fuse_opt_context ctx = {
|
||||
.data = data,
|
||||
.opt = opts,
|
||||
.proc = proc,
|
||||
};
|
||||
|
||||
if (!args || !args->argv || !args->argc)
|
||||
return 0;
|
||||
if (!args || !args->argv || !args->argc) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ctx.argc = args->argc;
|
||||
ctx.argv = args->argv;
|
||||
ctx.argc = args->argc;
|
||||
ctx.argv = args->argv;
|
||||
|
||||
res = opt_parse(&ctx);
|
||||
if (res != -1) {
|
||||
struct fuse_args tmp = *args;
|
||||
*args = ctx.outargs;
|
||||
ctx.outargs = tmp;
|
||||
}
|
||||
free(ctx.opts);
|
||||
fuse_opt_free_args(&ctx.outargs);
|
||||
return res;
|
||||
res = opt_parse(&ctx);
|
||||
if (res != -1) {
|
||||
struct fuse_args tmp = *args;
|
||||
*args = ctx.outargs;
|
||||
ctx.outargs = tmp;
|
||||
}
|
||||
free(ctx.opts);
|
||||
fuse_opt_free_args(&ctx.outargs);
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
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.
|
||||
*/
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef FUSE_OPT_H_
|
||||
#define FUSE_OPT_H_
|
||||
|
@ -37,7 +37,7 @@
|
|||
*
|
||||
* - 'offsetof(struct foo, member)' actions i) and iii)
|
||||
*
|
||||
* - -1 action ii)
|
||||
* - -1 action ii)
|
||||
*
|
||||
* The 'offsetof()' macro is defined in the <stddef.h> header.
|
||||
*
|
||||
|
@ -48,7 +48,7 @@
|
|||
*
|
||||
* 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
|
||||
* with "-o"
|
||||
*
|
||||
|
@ -71,58 +71,67 @@
|
|||
* freed.
|
||||
*/
|
||||
struct fuse_opt {
|
||||
/** Matching template and optional parameter formatting */
|
||||
const char *templ;
|
||||
/** Matching template and optional parameter formatting */
|
||||
const char *templ;
|
||||
|
||||
/**
|
||||
* Offset of variable within 'data' parameter of fuse_opt_parse()
|
||||
* or -1
|
||||
*/
|
||||
unsigned long offset;
|
||||
/**
|
||||
* Offset of variable within 'data' parameter of fuse_opt_parse()
|
||||
* or -1
|
||||
*/
|
||||
unsigned long offset;
|
||||
|
||||
/**
|
||||
* Value to set the variable to, or to be passed as 'key' to the
|
||||
* processing function. Ignored if template has a format
|
||||
*/
|
||||
int value;
|
||||
/**
|
||||
* Value to set the variable to, or to be passed as 'key' to the
|
||||
* processing function. Ignored if template has a format
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
#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
|
||||
*/
|
||||
#define FUSE_OPT_END { NULL, 0, 0 }
|
||||
#define FUSE_OPT_END \
|
||||
{ \
|
||||
NULL, 0, 0 \
|
||||
}
|
||||
|
||||
/**
|
||||
* Argument list
|
||||
*/
|
||||
struct fuse_args {
|
||||
/** Argument count */
|
||||
int argc;
|
||||
/** Argument count */
|
||||
int argc;
|
||||
|
||||
/** Argument vector. NULL terminated */
|
||||
char **argv;
|
||||
/** Argument vector. NULL terminated */
|
||||
char **argv;
|
||||
|
||||
/** Is 'argv' allocated? */
|
||||
int allocated;
|
||||
/** Is 'argv' allocated? */
|
||||
int allocated;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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
|
||||
* 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
|
||||
|
@ -130,7 +139,7 @@ struct fuse_args {
|
|||
* Non-options are the arguments beginning with a character other than
|
||||
* '-' 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
|
||||
|
@ -174,7 +183,7 @@ struct fuse_args {
|
|||
* @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,
|
||||
struct fuse_args *outargs);
|
||||
struct fuse_args *outargs);
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
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
|
||||
|
|
|
@ -1,91 +1,95 @@
|
|||
/*
|
||||
FUSE: Filesystem in Userspace
|
||||
Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
|
||||
|
||||
Utility functions for setting signal handlers.
|
||||
|
||||
This program can be distributed under the terms of the GNU LGPLv2.
|
||||
See the file COPYING.LIB
|
||||
*/
|
||||
* FUSE: Filesystem in Userspace
|
||||
* Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
|
||||
*
|
||||
* Utility functions for setting signal handlers.
|
||||
*
|
||||
* This program can be distributed under the terms of the GNU LGPLv2.
|
||||
* See the file COPYING.LIB
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "fuse_lowlevel.h"
|
||||
#include "fuse_i.h"
|
||||
#include "fuse_lowlevel.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static struct fuse_session *fuse_instance;
|
||||
|
||||
static void exit_handler(int sig)
|
||||
{
|
||||
if (fuse_instance) {
|
||||
fuse_session_exit(fuse_instance);
|
||||
if(sig <= 0) {
|
||||
fuse_log(FUSE_LOG_ERR, "assertion error: signal value <= 0\n");
|
||||
abort();
|
||||
}
|
||||
fuse_instance->error = sig;
|
||||
}
|
||||
if (fuse_instance) {
|
||||
fuse_session_exit(fuse_instance);
|
||||
if (sig <= 0) {
|
||||
fuse_log(FUSE_LOG_ERR, "assertion error: signal value <= 0\n");
|
||||
abort();
|
||||
}
|
||||
fuse_instance->error = sig;
|
||||
}
|
||||
}
|
||||
|
||||
static void do_nothing(int sig)
|
||||
{
|
||||
(void) sig;
|
||||
(void)sig;
|
||||
}
|
||||
|
||||
static int set_one_signal_handler(int sig, void (*handler)(int), int remove)
|
||||
{
|
||||
struct sigaction sa;
|
||||
struct sigaction old_sa;
|
||||
struct sigaction sa;
|
||||
struct sigaction old_sa;
|
||||
|
||||
memset(&sa, 0, sizeof(struct sigaction));
|
||||
sa.sa_handler = remove ? SIG_DFL : handler;
|
||||
sigemptyset(&(sa.sa_mask));
|
||||
sa.sa_flags = 0;
|
||||
memset(&sa, 0, sizeof(struct sigaction));
|
||||
sa.sa_handler = remove ? SIG_DFL : handler;
|
||||
sigemptyset(&(sa.sa_mask));
|
||||
sa.sa_flags = 0;
|
||||
|
||||
if (sigaction(sig, NULL, &old_sa) == -1) {
|
||||
perror("fuse: cannot get old signal handler");
|
||||
return -1;
|
||||
}
|
||||
if (sigaction(sig, NULL, &old_sa) == -1) {
|
||||
perror("fuse: cannot get old signal handler");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (old_sa.sa_handler == (remove ? handler : SIG_DFL) &&
|
||||
sigaction(sig, &sa, NULL) == -1) {
|
||||
perror("fuse: cannot set signal handler");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
if (old_sa.sa_handler == (remove ? handler : SIG_DFL) &&
|
||||
sigaction(sig, &sa, NULL) == -1) {
|
||||
perror("fuse: cannot set signal handler");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
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
|
||||
thus should reset to SIG_DFL in fuse_remove_signal_handlers)
|
||||
or if it was already set to SIG_IGN (and should be left
|
||||
untouched. */
|
||||
if (set_one_signal_handler(SIGHUP, exit_handler, 0) == -1 ||
|
||||
set_one_signal_handler(SIGINT, exit_handler, 0) == -1 ||
|
||||
set_one_signal_handler(SIGTERM, exit_handler, 0) == -1 ||
|
||||
set_one_signal_handler(SIGPIPE, do_nothing, 0) == -1)
|
||||
return -1;
|
||||
/*
|
||||
* If we used SIG_IGN instead of the do_nothing function,
|
||||
* then we would be unable to tell if we set SIG_IGN (and
|
||||
* thus should reset to SIG_DFL in fuse_remove_signal_handlers)
|
||||
* or if it was already set to SIG_IGN (and should be left
|
||||
* untouched.
|
||||
*/
|
||||
if (set_one_signal_handler(SIGHUP, exit_handler, 0) == -1 ||
|
||||
set_one_signal_handler(SIGINT, exit_handler, 0) == -1 ||
|
||||
set_one_signal_handler(SIGTERM, exit_handler, 0) == -1 ||
|
||||
set_one_signal_handler(SIGPIPE, do_nothing, 0) == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
fuse_instance = se;
|
||||
return 0;
|
||||
fuse_instance = se;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void fuse_remove_signal_handlers(struct fuse_session *se)
|
||||
{
|
||||
if (fuse_instance != se)
|
||||
fuse_log(FUSE_LOG_ERR,
|
||||
"fuse: fuse_remove_signal_handlers: unknown session\n");
|
||||
else
|
||||
fuse_instance = NULL;
|
||||
if (fuse_instance != se) {
|
||||
fuse_log(FUSE_LOG_ERR,
|
||||
"fuse: fuse_remove_signal_handlers: unknown session\n");
|
||||
} else {
|
||||
fuse_instance = NULL;
|
||||
}
|
||||
|
||||
set_one_signal_handler(SIGHUP, exit_handler, 1);
|
||||
set_one_signal_handler(SIGINT, exit_handler, 1);
|
||||
set_one_signal_handler(SIGTERM, exit_handler, 1);
|
||||
set_one_signal_handler(SIGPIPE, do_nothing, 1);
|
||||
set_one_signal_handler(SIGHUP, exit_handler, 1);
|
||||
set_one_signal_handler(SIGINT, exit_handler, 1);
|
||||
set_one_signal_handler(SIGTERM, exit_handler, 1);
|
||||
set_one_signal_handler(SIGPIPE, do_nothing, 1);
|
||||
}
|
||||
|
|
|
@ -1,297 +1,309 @@
|
|||
/*
|
||||
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>
|
||||
*
|
||||
* 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
|
||||
aid of these functions it should be possible to create full FUSE
|
||||
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.
|
||||
*/
|
||||
* This program can be distributed under the terms of the GNU LGPLv2.
|
||||
* See the file COPYING.LIB.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "fuse_i.h"
|
||||
#include "fuse_lowlevel.h"
|
||||
#include "fuse_misc.h"
|
||||
#include "fuse_opt.h"
|
||||
#include "fuse_lowlevel.h"
|
||||
#include "mount_util.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
#include <sys/param.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define FUSE_HELPER_OPT(t, p) \
|
||||
{ t, offsetof(struct fuse_cmdline_opts, p), 1 }
|
||||
#define FUSE_HELPER_OPT(t, p) \
|
||||
{ \
|
||||
t, offsetof(struct fuse_cmdline_opts, p), 1 \
|
||||
}
|
||||
|
||||
static const struct fuse_opt fuse_helper_opts[] = {
|
||||
FUSE_HELPER_OPT("-h", show_help),
|
||||
FUSE_HELPER_OPT("--help", show_help),
|
||||
FUSE_HELPER_OPT("-V", show_version),
|
||||
FUSE_HELPER_OPT("--version", show_version),
|
||||
FUSE_HELPER_OPT("-d", debug),
|
||||
FUSE_HELPER_OPT("debug", debug),
|
||||
FUSE_HELPER_OPT("-d", foreground),
|
||||
FUSE_HELPER_OPT("debug", foreground),
|
||||
FUSE_OPT_KEY("-d", FUSE_OPT_KEY_KEEP),
|
||||
FUSE_OPT_KEY("debug", FUSE_OPT_KEY_KEEP),
|
||||
FUSE_HELPER_OPT("-f", foreground),
|
||||
FUSE_HELPER_OPT("fsname=", nodefault_subtype),
|
||||
FUSE_OPT_KEY("fsname=", FUSE_OPT_KEY_KEEP),
|
||||
FUSE_HELPER_OPT("subtype=", nodefault_subtype),
|
||||
FUSE_OPT_KEY("subtype=", FUSE_OPT_KEY_KEEP),
|
||||
FUSE_HELPER_OPT("max_idle_threads=%u", max_idle_threads),
|
||||
FUSE_OPT_END
|
||||
FUSE_HELPER_OPT("-h", show_help),
|
||||
FUSE_HELPER_OPT("--help", show_help),
|
||||
FUSE_HELPER_OPT("-V", show_version),
|
||||
FUSE_HELPER_OPT("--version", show_version),
|
||||
FUSE_HELPER_OPT("-d", debug),
|
||||
FUSE_HELPER_OPT("debug", debug),
|
||||
FUSE_HELPER_OPT("-d", foreground),
|
||||
FUSE_HELPER_OPT("debug", foreground),
|
||||
FUSE_OPT_KEY("-d", FUSE_OPT_KEY_KEEP),
|
||||
FUSE_OPT_KEY("debug", FUSE_OPT_KEY_KEEP),
|
||||
FUSE_HELPER_OPT("-f", foreground),
|
||||
FUSE_HELPER_OPT("fsname=", nodefault_subtype),
|
||||
FUSE_OPT_KEY("fsname=", FUSE_OPT_KEY_KEEP),
|
||||
FUSE_HELPER_OPT("subtype=", nodefault_subtype),
|
||||
FUSE_OPT_KEY("subtype=", FUSE_OPT_KEY_KEEP),
|
||||
FUSE_HELPER_OPT("max_idle_threads=%u", max_idle_threads),
|
||||
FUSE_OPT_END
|
||||
};
|
||||
|
||||
struct fuse_conn_info_opts {
|
||||
int atomic_o_trunc;
|
||||
int no_remote_posix_lock;
|
||||
int no_remote_flock;
|
||||
int splice_write;
|
||||
int splice_move;
|
||||
int splice_read;
|
||||
int no_splice_write;
|
||||
int no_splice_move;
|
||||
int no_splice_read;
|
||||
int auto_inval_data;
|
||||
int no_auto_inval_data;
|
||||
int no_readdirplus;
|
||||
int no_readdirplus_auto;
|
||||
int async_dio;
|
||||
int no_async_dio;
|
||||
int writeback_cache;
|
||||
int no_writeback_cache;
|
||||
int async_read;
|
||||
int sync_read;
|
||||
unsigned max_write;
|
||||
unsigned max_readahead;
|
||||
unsigned max_background;
|
||||
unsigned congestion_threshold;
|
||||
unsigned time_gran;
|
||||
int set_max_write;
|
||||
int set_max_readahead;
|
||||
int set_max_background;
|
||||
int set_congestion_threshold;
|
||||
int set_time_gran;
|
||||
int atomic_o_trunc;
|
||||
int no_remote_posix_lock;
|
||||
int no_remote_flock;
|
||||
int splice_write;
|
||||
int splice_move;
|
||||
int splice_read;
|
||||
int no_splice_write;
|
||||
int no_splice_move;
|
||||
int no_splice_read;
|
||||
int auto_inval_data;
|
||||
int no_auto_inval_data;
|
||||
int no_readdirplus;
|
||||
int no_readdirplus_auto;
|
||||
int async_dio;
|
||||
int no_async_dio;
|
||||
int writeback_cache;
|
||||
int no_writeback_cache;
|
||||
int async_read;
|
||||
int sync_read;
|
||||
unsigned max_write;
|
||||
unsigned max_readahead;
|
||||
unsigned max_background;
|
||||
unsigned congestion_threshold;
|
||||
unsigned time_gran;
|
||||
int set_max_write;
|
||||
int set_max_readahead;
|
||||
int set_max_background;
|
||||
int set_congestion_threshold;
|
||||
int set_time_gran;
|
||||
};
|
||||
|
||||
#define CONN_OPTION(t, p, v) \
|
||||
{ t, offsetof(struct fuse_conn_info_opts, p), v }
|
||||
#define CONN_OPTION(t, p, v) \
|
||||
{ \
|
||||
t, offsetof(struct fuse_conn_info_opts, p), v \
|
||||
}
|
||||
static const struct fuse_opt conn_info_opt_spec[] = {
|
||||
CONN_OPTION("max_write=%u", max_write, 0),
|
||||
CONN_OPTION("max_write=", set_max_write, 1),
|
||||
CONN_OPTION("max_readahead=%u", max_readahead, 0),
|
||||
CONN_OPTION("max_readahead=", set_max_readahead, 1),
|
||||
CONN_OPTION("max_background=%u", max_background, 0),
|
||||
CONN_OPTION("max_background=", set_max_background, 1),
|
||||
CONN_OPTION("congestion_threshold=%u", congestion_threshold, 0),
|
||||
CONN_OPTION("congestion_threshold=", set_congestion_threshold, 1),
|
||||
CONN_OPTION("sync_read", sync_read, 1),
|
||||
CONN_OPTION("async_read", async_read, 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_flock, 1),
|
||||
CONN_OPTION("no_remote_flock", no_remote_flock, 1),
|
||||
CONN_OPTION("no_remote_posix_lock", no_remote_posix_lock, 1),
|
||||
CONN_OPTION("splice_write", splice_write, 1),
|
||||
CONN_OPTION("no_splice_write", no_splice_write, 1),
|
||||
CONN_OPTION("splice_move", splice_move, 1),
|
||||
CONN_OPTION("no_splice_move", no_splice_move, 1),
|
||||
CONN_OPTION("splice_read", splice_read, 1),
|
||||
CONN_OPTION("no_splice_read", no_splice_read, 1),
|
||||
CONN_OPTION("auto_inval_data", 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=yes", no_readdirplus, 0),
|
||||
CONN_OPTION("readdirplus=yes", no_readdirplus_auto, 1),
|
||||
CONN_OPTION("readdirplus=auto", no_readdirplus, 0),
|
||||
CONN_OPTION("readdirplus=auto", no_readdirplus_auto, 0),
|
||||
CONN_OPTION("async_dio", async_dio, 1),
|
||||
CONN_OPTION("no_async_dio", no_async_dio, 1),
|
||||
CONN_OPTION("writeback_cache", writeback_cache, 1),
|
||||
CONN_OPTION("no_writeback_cache", no_writeback_cache, 1),
|
||||
CONN_OPTION("time_gran=%u", time_gran, 0),
|
||||
CONN_OPTION("time_gran=", set_time_gran, 1),
|
||||
FUSE_OPT_END
|
||||
CONN_OPTION("max_write=%u", max_write, 0),
|
||||
CONN_OPTION("max_write=", set_max_write, 1),
|
||||
CONN_OPTION("max_readahead=%u", max_readahead, 0),
|
||||
CONN_OPTION("max_readahead=", set_max_readahead, 1),
|
||||
CONN_OPTION("max_background=%u", max_background, 0),
|
||||
CONN_OPTION("max_background=", set_max_background, 1),
|
||||
CONN_OPTION("congestion_threshold=%u", congestion_threshold, 0),
|
||||
CONN_OPTION("congestion_threshold=", set_congestion_threshold, 1),
|
||||
CONN_OPTION("sync_read", sync_read, 1),
|
||||
CONN_OPTION("async_read", async_read, 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_flock, 1),
|
||||
CONN_OPTION("no_remote_flock", no_remote_flock, 1),
|
||||
CONN_OPTION("no_remote_posix_lock", no_remote_posix_lock, 1),
|
||||
CONN_OPTION("splice_write", splice_write, 1),
|
||||
CONN_OPTION("no_splice_write", no_splice_write, 1),
|
||||
CONN_OPTION("splice_move", splice_move, 1),
|
||||
CONN_OPTION("no_splice_move", no_splice_move, 1),
|
||||
CONN_OPTION("splice_read", splice_read, 1),
|
||||
CONN_OPTION("no_splice_read", no_splice_read, 1),
|
||||
CONN_OPTION("auto_inval_data", 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=yes", no_readdirplus, 0),
|
||||
CONN_OPTION("readdirplus=yes", no_readdirplus_auto, 1),
|
||||
CONN_OPTION("readdirplus=auto", no_readdirplus, 0),
|
||||
CONN_OPTION("readdirplus=auto", no_readdirplus_auto, 0),
|
||||
CONN_OPTION("async_dio", async_dio, 1),
|
||||
CONN_OPTION("no_async_dio", no_async_dio, 1),
|
||||
CONN_OPTION("writeback_cache", writeback_cache, 1),
|
||||
CONN_OPTION("no_writeback_cache", no_writeback_cache, 1),
|
||||
CONN_OPTION("time_gran=%u", time_gran, 0),
|
||||
CONN_OPTION("time_gran=", set_time_gran, 1),
|
||||
FUSE_OPT_END
|
||||
};
|
||||
|
||||
|
||||
void fuse_cmdline_help(void)
|
||||
{
|
||||
printf(" -h --help print help\n"
|
||||
" -V --version print version\n"
|
||||
" -d -o debug enable debug output (implies -f)\n"
|
||||
" -f foreground operation\n"
|
||||
" -o max_idle_threads the maximum number of idle worker threads\n"
|
||||
" allowed (default: 10)\n");
|
||||
printf(
|
||||
" -h --help print help\n"
|
||||
" -V --version print version\n"
|
||||
" -d -o debug enable debug output (implies -f)\n"
|
||||
" -f foreground operation\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,
|
||||
struct fuse_args *outargs)
|
||||
struct fuse_args *outargs)
|
||||
{
|
||||
(void) outargs;
|
||||
struct fuse_cmdline_opts *opts = data;
|
||||
(void)outargs;
|
||||
struct fuse_cmdline_opts *opts = data;
|
||||
|
||||
switch (key) {
|
||||
case FUSE_OPT_KEY_NONOPT:
|
||||
if (!opts->mountpoint) {
|
||||
if (fuse_mnt_parse_fuse_fd(arg) != -1) {
|
||||
return fuse_opt_add_opt(&opts->mountpoint, arg);
|
||||
}
|
||||
switch (key) {
|
||||
case FUSE_OPT_KEY_NONOPT:
|
||||
if (!opts->mountpoint) {
|
||||
if (fuse_mnt_parse_fuse_fd(arg) != -1) {
|
||||
return fuse_opt_add_opt(&opts->mountpoint, arg);
|
||||
}
|
||||
|
||||
char mountpoint[PATH_MAX] = "";
|
||||
if (realpath(arg, mountpoint) == NULL) {
|
||||
fuse_log(FUSE_LOG_ERR,
|
||||
"fuse: bad mount point `%s': %s\n",
|
||||
arg, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
return fuse_opt_add_opt(&opts->mountpoint, mountpoint);
|
||||
} else {
|
||||
fuse_log(FUSE_LOG_ERR, "fuse: invalid argument `%s'\n", arg);
|
||||
return -1;
|
||||
}
|
||||
char mountpoint[PATH_MAX] = "";
|
||||
if (realpath(arg, mountpoint) == NULL) {
|
||||
fuse_log(FUSE_LOG_ERR, "fuse: bad mount point `%s': %s\n", arg,
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
return fuse_opt_add_opt(&opts->mountpoint, mountpoint);
|
||||
} else {
|
||||
fuse_log(FUSE_LOG_ERR, "fuse: invalid argument `%s'\n", arg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
default:
|
||||
/* Pass through unknown options */
|
||||
return 1;
|
||||
}
|
||||
default:
|
||||
/* Pass through unknown options */
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
int fuse_parse_cmdline(struct fuse_args *args,
|
||||
struct fuse_cmdline_opts *opts)
|
||||
int fuse_parse_cmdline(struct fuse_args *args, 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,
|
||||
fuse_helper_opt_proc) == -1)
|
||||
return -1;
|
||||
if (fuse_opt_parse(args, opts, fuse_helper_opts, fuse_helper_opt_proc) ==
|
||||
-1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int fuse_daemonize(int foreground)
|
||||
{
|
||||
if (!foreground) {
|
||||
int nullfd;
|
||||
int waiter[2];
|
||||
char completed;
|
||||
if (!foreground) {
|
||||
int nullfd;
|
||||
int waiter[2];
|
||||
char completed;
|
||||
|
||||
if (pipe(waiter)) {
|
||||
perror("fuse_daemonize: pipe");
|
||||
return -1;
|
||||
}
|
||||
if (pipe(waiter)) {
|
||||
perror("fuse_daemonize: pipe");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* demonize current process by forking it and killing the
|
||||
* parent. This makes current process as a child of 'init'.
|
||||
*/
|
||||
switch(fork()) {
|
||||
case -1:
|
||||
perror("fuse_daemonize: fork");
|
||||
return -1;
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
(void) read(waiter[0], &completed, sizeof(completed));
|
||||
_exit(0);
|
||||
}
|
||||
/*
|
||||
* demonize current process by forking it and killing the
|
||||
* parent. This makes current process as a child of 'init'.
|
||||
*/
|
||||
switch (fork()) {
|
||||
case -1:
|
||||
perror("fuse_daemonize: fork");
|
||||
return -1;
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
(void)read(waiter[0], &completed, sizeof(completed));
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
if (setsid() == -1) {
|
||||
perror("fuse_daemonize: setsid");
|
||||
return -1;
|
||||
}
|
||||
if (setsid() == -1) {
|
||||
perror("fuse_daemonize: setsid");
|
||||
return -1;
|
||||
}
|
||||
|
||||
(void) chdir("/");
|
||||
(void)chdir("/");
|
||||
|
||||
nullfd = open("/dev/null", O_RDWR, 0);
|
||||
if (nullfd != -1) {
|
||||
(void) dup2(nullfd, 0);
|
||||
(void) dup2(nullfd, 1);
|
||||
(void) dup2(nullfd, 2);
|
||||
if (nullfd > 2)
|
||||
close(nullfd);
|
||||
}
|
||||
nullfd = open("/dev/null", O_RDWR, 0);
|
||||
if (nullfd != -1) {
|
||||
(void)dup2(nullfd, 0);
|
||||
(void)dup2(nullfd, 1);
|
||||
(void)dup2(nullfd, 2);
|
||||
if (nullfd > 2) {
|
||||
close(nullfd);
|
||||
}
|
||||
}
|
||||
|
||||
/* Propagate completion of daemon initialization */
|
||||
completed = 1;
|
||||
(void) write(waiter[1], &completed, sizeof(completed));
|
||||
close(waiter[0]);
|
||||
close(waiter[1]);
|
||||
} else {
|
||||
(void) chdir("/");
|
||||
}
|
||||
return 0;
|
||||
/* Propagate completion of daemon initialization */
|
||||
completed = 1;
|
||||
(void)write(waiter[1], &completed, sizeof(completed));
|
||||
close(waiter[0]);
|
||||
close(waiter[1]);
|
||||
} else {
|
||||
(void)chdir("/");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
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)
|
||||
conn->max_write = opts->max_write;
|
||||
if(opts->set_max_background)
|
||||
conn->max_background = opts->max_background;
|
||||
if(opts->set_congestion_threshold)
|
||||
conn->congestion_threshold = opts->congestion_threshold;
|
||||
if(opts->set_time_gran)
|
||||
conn->time_gran = opts->time_gran;
|
||||
if(opts->set_max_readahead)
|
||||
conn->max_readahead = opts->max_readahead;
|
||||
if (opts->set_max_write) {
|
||||
conn->max_write = opts->max_write;
|
||||
}
|
||||
if (opts->set_max_background) {
|
||||
conn->max_background = opts->max_background;
|
||||
}
|
||||
if (opts->set_congestion_threshold) {
|
||||
conn->congestion_threshold = opts->congestion_threshold;
|
||||
}
|
||||
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) \
|
||||
if (cond) conn->want |= (cap)
|
||||
#define LL_DISABLE(cond,cap) \
|
||||
if (cond) conn->want &= ~(cap)
|
||||
#define LL_ENABLE(cond, 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_DISABLE(opts->no_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_ENABLE(opts->splice_write, FUSE_CAP_SPLICE_WRITE);
|
||||
LL_DISABLE(opts->no_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_ENABLE(opts->splice_move, FUSE_CAP_SPLICE_MOVE);
|
||||
LL_DISABLE(opts->no_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_ENABLE(opts->auto_inval_data, FUSE_CAP_AUTO_INVAL_DATA);
|
||||
LL_DISABLE(opts->no_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_readdirplus, FUSE_CAP_READDIRPLUS);
|
||||
LL_DISABLE(opts->no_readdirplus_auto, FUSE_CAP_READDIRPLUS_AUTO);
|
||||
LL_DISABLE(opts->no_readdirplus, FUSE_CAP_READDIRPLUS);
|
||||
LL_DISABLE(opts->no_readdirplus_auto, FUSE_CAP_READDIRPLUS_AUTO);
|
||||
|
||||
LL_ENABLE(opts->async_dio, FUSE_CAP_ASYNC_DIO);
|
||||
LL_DISABLE(opts->no_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_ENABLE(opts->writeback_cache, FUSE_CAP_WRITEBACK_CACHE);
|
||||
LL_DISABLE(opts->no_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_ENABLE(opts->async_read, FUSE_CAP_ASYNC_READ);
|
||||
LL_DISABLE(opts->sync_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->no_remote_posix_lock, FUSE_CAP_POSIX_LOCKS);
|
||||
LL_DISABLE(opts->no_remote_flock, FUSE_CAP_FLOCK_LOCKS);
|
||||
LL_DISABLE(opts->no_remote_posix_lock, FUSE_CAP_POSIX_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));
|
||||
if(opts == NULL) {
|
||||
fuse_log(FUSE_LOG_ERR, "calloc failed\n");
|
||||
return NULL;
|
||||
}
|
||||
if(fuse_opt_parse(args, opts, conn_info_opt_spec, NULL) == -1) {
|
||||
free(opts);
|
||||
return NULL;
|
||||
}
|
||||
return opts;
|
||||
opts = calloc(1, sizeof(struct fuse_conn_info_opts));
|
||||
if (opts == NULL) {
|
||||
fuse_log(FUSE_LOG_ERR, "calloc failed\n");
|
||||
return NULL;
|
||||
}
|
||||
if (fuse_opt_parse(args, opts, conn_info_opt_spec, NULL) == -1) {
|
||||
free(opts);
|
||||
return NULL;
|
||||
}
|
||||
return opts;
|
||||
}
|
||||
|
|
|
@ -28,23 +28,24 @@
|
|||
* operation
|
||||
*/
|
||||
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)) {
|
||||
res = openat(dirfd, path, O_CREAT | O_EXCL | O_WRONLY, mode);
|
||||
if (res >= 0)
|
||||
res = close(res);
|
||||
} else if (S_ISDIR(mode)) {
|
||||
res = mkdirat(dirfd, path, mode);
|
||||
} else if (S_ISLNK(mode) && link != NULL) {
|
||||
res = symlinkat(link, dirfd, path);
|
||||
} else if (S_ISFIFO(mode)) {
|
||||
res = mkfifoat(dirfd, path, mode);
|
||||
} else {
|
||||
res = mknodat(dirfd, path, mode, rdev);
|
||||
}
|
||||
if (S_ISREG(mode)) {
|
||||
res = openat(dirfd, path, O_CREAT | O_EXCL | O_WRONLY, mode);
|
||||
if (res >= 0) {
|
||||
res = close(res);
|
||||
}
|
||||
} else if (S_ISDIR(mode)) {
|
||||
res = mkdirat(dirfd, path, mode);
|
||||
} else if (S_ISLNK(mode) && link != NULL) {
|
||||
res = symlinkat(link, dirfd, path);
|
||||
} else if (S_ISFIFO(mode)) {
|
||||
res = mkfifoat(dirfd, path, mode);
|
||||
} 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