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:
Dr. David Alan Gilbert 2019-12-09 19:53:47 +00:00
parent a3e23f3254
commit 7387863d03
15 changed files with 5979 additions and 5658 deletions

View File

@ -1,252 +1,272 @@
/* /*
FUSE: Filesystem in Userspace * FUSE: Filesystem in Userspace
Copyright (C) 2010 Miklos Szeredi <miklos@szeredi.hu> * Copyright (C) 2010 Miklos Szeredi <miklos@szeredi.hu>
*
Functions for dealing with `struct fuse_buf` and `struct * Functions for dealing with `struct fuse_buf` and `struct
fuse_bufvec`. * fuse_bufvec`.
*
This program can be distributed under the terms of the GNU LGPLv2. * This program can be distributed under the terms of the GNU LGPLv2.
See the file COPYING.LIB * See the file COPYING.LIB
*/ */
#define _GNU_SOURCE #define _GNU_SOURCE
#include "config.h" #include "config.h"
#include "fuse_i.h" #include "fuse_i.h"
#include "fuse_lowlevel.h" #include "fuse_lowlevel.h"
#include <assert.h>
#include <errno.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <errno.h>
#include <assert.h>
size_t fuse_buf_size(const struct fuse_bufvec *bufv) size_t fuse_buf_size(const struct fuse_bufvec *bufv)
{ {
size_t i; size_t i;
size_t size = 0; size_t size = 0;
for (i = 0; i < bufv->count; i++) { for (i = 0; i < bufv->count; i++) {
if (bufv->buf[i].size == SIZE_MAX) if (bufv->buf[i].size == SIZE_MAX) {
size = SIZE_MAX; size = SIZE_MAX;
else } else {
size += bufv->buf[i].size; size += bufv->buf[i].size;
} }
}
return size; return size;
} }
static size_t min_size(size_t s1, size_t s2) static size_t min_size(size_t s1, size_t s2)
{ {
return s1 < s2 ? s1 : s2; return s1 < s2 ? s1 : s2;
} }
static ssize_t fuse_buf_write(const struct fuse_buf *dst, size_t dst_off, static ssize_t fuse_buf_write(const struct fuse_buf *dst, size_t dst_off,
const struct fuse_buf *src, size_t src_off, const struct fuse_buf *src, size_t src_off,
size_t len) size_t len)
{ {
ssize_t res = 0; ssize_t res = 0;
size_t copied = 0; size_t copied = 0;
while (len) { while (len) {
if (dst->flags & FUSE_BUF_FD_SEEK) { if (dst->flags & FUSE_BUF_FD_SEEK) {
res = pwrite(dst->fd, (char *)src->mem + src_off, len, res = pwrite(dst->fd, (char *)src->mem + src_off, len,
dst->pos + dst_off); dst->pos + dst_off);
} else { } else {
res = write(dst->fd, (char *)src->mem + src_off, len); res = write(dst->fd, (char *)src->mem + src_off, len);
} }
if (res == -1) { if (res == -1) {
if (!copied) if (!copied) {
return -errno; return -errno;
break; }
} break;
if (res == 0) }
break; if (res == 0) {
break;
}
copied += res; copied += res;
if (!(dst->flags & FUSE_BUF_FD_RETRY)) if (!(dst->flags & FUSE_BUF_FD_RETRY)) {
break; break;
}
src_off += res; src_off += res;
dst_off += res; dst_off += res;
len -= res; len -= res;
} }
return copied; return copied;
} }
static ssize_t fuse_buf_read(const struct fuse_buf *dst, size_t dst_off, static ssize_t fuse_buf_read(const struct fuse_buf *dst, size_t dst_off,
const struct fuse_buf *src, size_t src_off, const struct fuse_buf *src, size_t src_off,
size_t len) size_t len)
{ {
ssize_t res = 0; ssize_t res = 0;
size_t copied = 0; size_t copied = 0;
while (len) { while (len) {
if (src->flags & FUSE_BUF_FD_SEEK) { if (src->flags & FUSE_BUF_FD_SEEK) {
res = pread(src->fd, (char *)dst->mem + dst_off, len, res = pread(src->fd, (char *)dst->mem + dst_off, len,
src->pos + src_off); src->pos + src_off);
} else { } else {
res = read(src->fd, (char *)dst->mem + dst_off, len); res = read(src->fd, (char *)dst->mem + dst_off, len);
} }
if (res == -1) { if (res == -1) {
if (!copied) if (!copied) {
return -errno; return -errno;
break; }
} break;
if (res == 0) }
break; if (res == 0) {
break;
}
copied += res; copied += res;
if (!(src->flags & FUSE_BUF_FD_RETRY)) if (!(src->flags & FUSE_BUF_FD_RETRY)) {
break; break;
}
dst_off += res; dst_off += res;
src_off += res; src_off += res;
len -= res; len -= res;
} }
return copied; return copied;
} }
static ssize_t fuse_buf_fd_to_fd(const struct fuse_buf *dst, size_t dst_off, static ssize_t fuse_buf_fd_to_fd(const struct fuse_buf *dst, size_t dst_off,
const struct fuse_buf *src, size_t src_off, const struct fuse_buf *src, size_t src_off,
size_t len) size_t len)
{ {
char buf[4096]; char buf[4096];
struct fuse_buf tmp = { struct fuse_buf tmp = {
.size = sizeof(buf), .size = sizeof(buf),
.flags = 0, .flags = 0,
}; };
ssize_t res; ssize_t res;
size_t copied = 0; size_t copied = 0;
tmp.mem = buf; tmp.mem = buf;
while (len) { while (len) {
size_t this_len = min_size(tmp.size, len); size_t this_len = min_size(tmp.size, len);
size_t read_len; size_t read_len;
res = fuse_buf_read(&tmp, 0, src, src_off, this_len); res = fuse_buf_read(&tmp, 0, src, src_off, this_len);
if (res < 0) { if (res < 0) {
if (!copied) if (!copied) {
return res; return res;
break; }
} break;
if (res == 0) }
break; if (res == 0) {
break;
}
read_len = res; read_len = res;
res = fuse_buf_write(dst, dst_off, &tmp, 0, read_len); res = fuse_buf_write(dst, dst_off, &tmp, 0, read_len);
if (res < 0) { if (res < 0) {
if (!copied) if (!copied) {
return res; return res;
break; }
} break;
if (res == 0) }
break; if (res == 0) {
break;
}
copied += res; copied += res;
if (res < this_len) if (res < this_len) {
break; break;
}
dst_off += res; dst_off += res;
src_off += res; src_off += res;
len -= res; len -= res;
} }
return copied; return copied;
} }
static ssize_t fuse_buf_copy_one(const struct fuse_buf *dst, size_t dst_off, static ssize_t fuse_buf_copy_one(const struct fuse_buf *dst, size_t dst_off,
const struct fuse_buf *src, size_t src_off, const struct fuse_buf *src, size_t src_off,
size_t len, enum fuse_buf_copy_flags flags) size_t len, enum fuse_buf_copy_flags flags)
{ {
int src_is_fd = src->flags & FUSE_BUF_IS_FD; int src_is_fd = src->flags & FUSE_BUF_IS_FD;
int dst_is_fd = dst->flags & FUSE_BUF_IS_FD; int dst_is_fd = dst->flags & FUSE_BUF_IS_FD;
if (!src_is_fd && !dst_is_fd) { if (!src_is_fd && !dst_is_fd) {
char *dstmem = (char *)dst->mem + dst_off; char *dstmem = (char *)dst->mem + dst_off;
char *srcmem = (char *)src->mem + src_off; char *srcmem = (char *)src->mem + src_off;
if (dstmem != srcmem) { if (dstmem != srcmem) {
if (dstmem + len <= srcmem || srcmem + len <= dstmem) if (dstmem + len <= srcmem || srcmem + len <= dstmem) {
memcpy(dstmem, srcmem, len); memcpy(dstmem, srcmem, len);
else } else {
memmove(dstmem, srcmem, len); memmove(dstmem, srcmem, len);
} }
}
return len; return len;
} else if (!src_is_fd) { } else if (!src_is_fd) {
return fuse_buf_write(dst, dst_off, src, src_off, len); return fuse_buf_write(dst, dst_off, src, src_off, len);
} else if (!dst_is_fd) { } else if (!dst_is_fd) {
return fuse_buf_read(dst, dst_off, src, src_off, len); return fuse_buf_read(dst, dst_off, src, src_off, len);
} else { } else {
return fuse_buf_fd_to_fd(dst, dst_off, src, src_off, len); return fuse_buf_fd_to_fd(dst, dst_off, src, src_off, len);
} }
} }
static const struct fuse_buf *fuse_bufvec_current(struct fuse_bufvec *bufv) static const struct fuse_buf *fuse_bufvec_current(struct fuse_bufvec *bufv)
{ {
if (bufv->idx < bufv->count) if (bufv->idx < bufv->count) {
return &bufv->buf[bufv->idx]; return &bufv->buf[bufv->idx];
else } else {
return NULL; return NULL;
}
} }
static int fuse_bufvec_advance(struct fuse_bufvec *bufv, size_t len) static int fuse_bufvec_advance(struct fuse_bufvec *bufv, size_t len)
{ {
const struct fuse_buf *buf = fuse_bufvec_current(bufv); const struct fuse_buf *buf = fuse_bufvec_current(bufv);
bufv->off += len; bufv->off += len;
assert(bufv->off <= buf->size); assert(bufv->off <= buf->size);
if (bufv->off == buf->size) { if (bufv->off == buf->size) {
assert(bufv->idx < bufv->count); assert(bufv->idx < bufv->count);
bufv->idx++; bufv->idx++;
if (bufv->idx == bufv->count) if (bufv->idx == bufv->count) {
return 0; return 0;
bufv->off = 0; }
} bufv->off = 0;
return 1; }
return 1;
} }
ssize_t fuse_buf_copy(struct fuse_bufvec *dstv, struct fuse_bufvec *srcv, ssize_t fuse_buf_copy(struct fuse_bufvec *dstv, struct fuse_bufvec *srcv,
enum fuse_buf_copy_flags flags) enum fuse_buf_copy_flags flags)
{ {
size_t copied = 0; size_t copied = 0;
if (dstv == srcv) if (dstv == srcv) {
return fuse_buf_size(dstv); return fuse_buf_size(dstv);
}
for (;;) { for (;;) {
const struct fuse_buf *src = fuse_bufvec_current(srcv); const struct fuse_buf *src = fuse_bufvec_current(srcv);
const struct fuse_buf *dst = fuse_bufvec_current(dstv); const struct fuse_buf *dst = fuse_bufvec_current(dstv);
size_t src_len; size_t src_len;
size_t dst_len; size_t dst_len;
size_t len; size_t len;
ssize_t res; ssize_t res;
if (src == NULL || dst == NULL) if (src == NULL || dst == NULL) {
break; break;
}
src_len = src->size - srcv->off; src_len = src->size - srcv->off;
dst_len = dst->size - dstv->off; dst_len = dst->size - dstv->off;
len = min_size(src_len, dst_len); len = min_size(src_len, dst_len);
res = fuse_buf_copy_one(dst, dstv->off, src, srcv->off, len, flags); res = fuse_buf_copy_one(dst, dstv->off, src, srcv->off, len, flags);
if (res < 0) { if (res < 0) {
if (!copied) if (!copied) {
return res; return res;
break; }
} break;
copied += res; }
copied += res;
if (!fuse_bufvec_advance(srcv, res) || if (!fuse_bufvec_advance(srcv, res) ||
!fuse_bufvec_advance(dstv, res)) !fuse_bufvec_advance(dstv, res)) {
break; break;
}
if (res < len) if (res < len) {
break; break;
} }
}
return copied; return copied;
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,21 +1,23 @@
/* FUSE: Filesystem in Userspace /*
Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu> * FUSE: Filesystem in Userspace
* Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU LGPLv2. *
See the file COPYING.LIB. * This program can be distributed under the terms of the GNU LGPLv2.
*/ * See the file COPYING.LIB.
*/
/** @file */ /** @file */
#if !defined(FUSE_H_) && !defined(FUSE_LOWLEVEL_H_) #if !defined(FUSE_H_) && !defined(FUSE_LOWLEVEL_H_)
#error "Never include <fuse_common.h> directly; use <fuse.h> or <fuse_lowlevel.h> instead." #error \
"Never include <fuse_common.h> directly; use <fuse.h> or <fuse_lowlevel.h> instead."
#endif #endif
#ifndef FUSE_COMMON_H_ #ifndef FUSE_COMMON_H_
#define FUSE_COMMON_H_ #define FUSE_COMMON_H_
#include "fuse_opt.h"
#include "fuse_log.h" #include "fuse_log.h"
#include "fuse_opt.h"
#include <stdint.h> #include <stdint.h>
#include <sys/types.h> #include <sys/types.h>
@ -25,7 +27,7 @@
/** Minor version of FUSE library interface */ /** Minor version of FUSE library interface */
#define FUSE_MINOR_VERSION 2 #define FUSE_MINOR_VERSION 2
#define FUSE_MAKE_VERSION(maj, min) ((maj) * 10 + (min)) #define FUSE_MAKE_VERSION(maj, min) ((maj) * 10 + (min))
#define FUSE_VERSION FUSE_MAKE_VERSION(FUSE_MAJOR_VERSION, FUSE_MINOR_VERSION) #define FUSE_VERSION FUSE_MAKE_VERSION(FUSE_MAJOR_VERSION, FUSE_MINOR_VERSION)
/** /**
@ -38,67 +40,83 @@
* descriptors can share a single file handle. * descriptors can share a single file handle.
*/ */
struct fuse_file_info { struct fuse_file_info {
/** Open flags. Available in open() and release() */ /** Open flags. Available in open() and release() */
int flags; int flags;
/** In case of a write operation indicates if this was caused /*
by a delayed write from the page cache. If so, then the * In case of a write operation indicates if this was caused
context's pid, uid, and gid fields will not be valid, and * by a delayed write from the page cache. If so, then the
the *fh* value may not match the *fh* value that would * context's pid, uid, and gid fields will not be valid, and
have been sent with the corresponding individual write * the *fh* value may not match the *fh* value that would
requests if write caching had been disabled. */ * have been sent with the corresponding individual write
unsigned int writepage : 1; * requests if write caching had been disabled.
*/
unsigned int writepage:1;
/** Can be filled in by open, to use direct I/O on this file. */ /** Can be filled in by open, to use direct I/O on this file. */
unsigned int direct_io : 1; unsigned int direct_io:1;
/** Can be filled in by open. It signals the kernel that any /*
currently cached file data (ie., data that the filesystem * Can be filled in by open. It signals the kernel that any
provided the last time the file was open) need not be * currently cached file data (ie., data that the filesystem
invalidated. Has no effect when set in other contexts (in * provided the last time the file was open) need not be
particular it does nothing when set by opendir()). */ * invalidated. Has no effect when set in other contexts (in
unsigned int keep_cache : 1; * particular it does nothing when set by opendir()).
*/
unsigned int keep_cache:1;
/** Indicates a flush operation. Set in flush operation, also /*
maybe set in highlevel lock operation and lowlevel release * Indicates a flush operation. Set in flush operation, also
operation. */ * maybe set in highlevel lock operation and lowlevel release
unsigned int flush : 1; * operation.
*/
unsigned int flush:1;
/** Can be filled in by open, to indicate that the file is not /*
seekable. */ * Can be filled in by open, to indicate that the file is not
unsigned int nonseekable : 1; * seekable.
*/
unsigned int nonseekable:1;
/* Indicates that flock locks for this file should be /*
released. If set, lock_owner shall contain a valid value. * Indicates that flock locks for this file should be
May only be set in ->release(). */ * released. If set, lock_owner shall contain a valid value.
unsigned int flock_release : 1; * May only be set in ->release().
*/
unsigned int flock_release:1;
/** Can be filled in by opendir. It signals the kernel to /*
enable caching of entries returned by readdir(). Has no * Can be filled in by opendir. It signals the kernel to
effect when set in other contexts (in particular it does * enable caching of entries returned by readdir(). Has no
nothing when set by open()). */ * effect when set in other contexts (in particular it does
unsigned int cache_readdir : 1; * nothing when set by open()).
*/
unsigned int cache_readdir:1;
/** Padding. Reserved for future use*/ /** Padding. Reserved for future use*/
unsigned int padding : 25; unsigned int padding:25;
unsigned int padding2 : 32; unsigned int padding2:32;
/** File handle id. May be filled in by filesystem in create, /*
* open, and opendir(). Available in most other file operations on the * File handle id. May be filled in by filesystem in create,
* same file handle. */ * open, and opendir(). Available in most other file operations on the
uint64_t fh; * same file handle.
*/
uint64_t fh;
/** Lock owner id. Available in locking operations and flush */ /** Lock owner id. Available in locking operations and flush */
uint64_t lock_owner; uint64_t lock_owner;
/** Requested poll events. Available in ->poll. Only set on kernels /*
which support it. If unsupported, this field is set to zero. */ * Requested poll events. Available in ->poll. Only set on kernels
uint32_t poll_events; * which support it. If unsupported, this field is set to zero.
*/
uint32_t poll_events;
}; };
/************************************************************************** /*
* Capability bits for 'fuse_conn_info.capable' and 'fuse_conn_info.want' * * Capability bits for 'fuse_conn_info.capable' and 'fuse_conn_info.want'
**************************************************************************/ */
/** /**
* Indicates that the filesystem supports asynchronous read requests. * Indicates that the filesystem supports asynchronous read requests.
@ -110,7 +128,7 @@ struct fuse_file_info {
* *
* This feature is enabled by default when supported by the kernel. * This feature is enabled by default when supported by the kernel.
*/ */
#define FUSE_CAP_ASYNC_READ (1 << 0) #define FUSE_CAP_ASYNC_READ (1 << 0)
/** /**
* Indicates that the filesystem supports "remote" locking. * Indicates that the filesystem supports "remote" locking.
@ -118,7 +136,7 @@ struct fuse_file_info {
* This feature is enabled by default when supported by the kernel, * This feature is enabled by default when supported by the kernel,
* and if getlk() and setlk() handlers are implemented. * and if getlk() and setlk() handlers are implemented.
*/ */
#define FUSE_CAP_POSIX_LOCKS (1 << 1) #define FUSE_CAP_POSIX_LOCKS (1 << 1)
/** /**
* Indicates that the filesystem supports the O_TRUNC open flag. If * Indicates that the filesystem supports the O_TRUNC open flag. If
@ -127,14 +145,14 @@ struct fuse_file_info {
* *
* This feature is enabled by default when supported by the kernel. * This feature is enabled by default when supported by the kernel.
*/ */
#define FUSE_CAP_ATOMIC_O_TRUNC (1 << 3) #define FUSE_CAP_ATOMIC_O_TRUNC (1 << 3)
/** /**
* Indicates that the filesystem supports lookups of "." and "..". * Indicates that the filesystem supports lookups of "." and "..".
* *
* This feature is disabled by default. * This feature is disabled by default.
*/ */
#define FUSE_CAP_EXPORT_SUPPORT (1 << 4) #define FUSE_CAP_EXPORT_SUPPORT (1 << 4)
/** /**
* Indicates that the kernel should not apply the umask to the * Indicates that the kernel should not apply the umask to the
@ -142,7 +160,7 @@ struct fuse_file_info {
* *
* This feature is disabled by default. * This feature is disabled by default.
*/ */
#define FUSE_CAP_DONT_MASK (1 << 6) #define FUSE_CAP_DONT_MASK (1 << 6)
/** /**
* Indicates that libfuse should try to use splice() when writing to * Indicates that libfuse should try to use splice() when writing to
@ -150,7 +168,7 @@ struct fuse_file_info {
* *
* This feature is disabled by default. * This feature is disabled by default.
*/ */
#define FUSE_CAP_SPLICE_WRITE (1 << 7) #define FUSE_CAP_SPLICE_WRITE (1 << 7)
/** /**
* Indicates that libfuse should try to move pages instead of copying when * Indicates that libfuse should try to move pages instead of copying when
@ -158,7 +176,7 @@ struct fuse_file_info {
* *
* This feature is disabled by default. * This feature is disabled by default.
*/ */
#define FUSE_CAP_SPLICE_MOVE (1 << 8) #define FUSE_CAP_SPLICE_MOVE (1 << 8)
/** /**
* Indicates that libfuse should try to use splice() when reading from * Indicates that libfuse should try to use splice() when reading from
@ -167,7 +185,7 @@ struct fuse_file_info {
* This feature is enabled by default when supported by the kernel and * This feature is enabled by default when supported by the kernel and
* if the filesystem implements a write_buf() handler. * if the filesystem implements a write_buf() handler.
*/ */
#define FUSE_CAP_SPLICE_READ (1 << 9) #define FUSE_CAP_SPLICE_READ (1 << 9)
/** /**
* If set, the calls to flock(2) will be emulated using POSIX locks and must * If set, the calls to flock(2) will be emulated using POSIX locks and must
@ -180,14 +198,14 @@ struct fuse_file_info {
* This feature is enabled by default when supported by the kernel and * This feature is enabled by default when supported by the kernel and
* if the filesystem implements a flock() handler. * if the filesystem implements a flock() handler.
*/ */
#define FUSE_CAP_FLOCK_LOCKS (1 << 10) #define FUSE_CAP_FLOCK_LOCKS (1 << 10)
/** /**
* Indicates that the filesystem supports ioctl's on directories. * Indicates that the filesystem supports ioctl's on directories.
* *
* This feature is enabled by default when supported by the kernel. * This feature is enabled by default when supported by the kernel.
*/ */
#define FUSE_CAP_IOCTL_DIR (1 << 11) #define FUSE_CAP_IOCTL_DIR (1 << 11)
/** /**
* Traditionally, while a file is open the FUSE kernel module only * Traditionally, while a file is open the FUSE kernel module only
@ -209,7 +227,7 @@ struct fuse_file_info {
* *
* This feature is enabled by default when supported by the kernel. * This feature is enabled by default when supported by the kernel.
*/ */
#define FUSE_CAP_AUTO_INVAL_DATA (1 << 12) #define FUSE_CAP_AUTO_INVAL_DATA (1 << 12)
/** /**
* Indicates that the filesystem supports readdirplus. * Indicates that the filesystem supports readdirplus.
@ -217,7 +235,7 @@ struct fuse_file_info {
* This feature is enabled by default when supported by the kernel and if the * This feature is enabled by default when supported by the kernel and if the
* filesystem implements a readdirplus() handler. * filesystem implements a readdirplus() handler.
*/ */
#define FUSE_CAP_READDIRPLUS (1 << 13) #define FUSE_CAP_READDIRPLUS (1 << 13)
/** /**
* Indicates that the filesystem supports adaptive readdirplus. * Indicates that the filesystem supports adaptive readdirplus.
@ -245,7 +263,7 @@ struct fuse_file_info {
* if the filesystem implements both a readdirplus() and a readdir() * if the filesystem implements both a readdirplus() and a readdir()
* handler. * handler.
*/ */
#define FUSE_CAP_READDIRPLUS_AUTO (1 << 14) #define FUSE_CAP_READDIRPLUS_AUTO (1 << 14)
/** /**
* Indicates that the filesystem supports asynchronous direct I/O submission. * Indicates that the filesystem supports asynchronous direct I/O submission.
@ -256,7 +274,7 @@ struct fuse_file_info {
* *
* This feature is enabled by default when supported by the kernel. * This feature is enabled by default when supported by the kernel.
*/ */
#define FUSE_CAP_ASYNC_DIO (1 << 15) #define FUSE_CAP_ASYNC_DIO (1 << 15)
/** /**
* Indicates that writeback caching should be enabled. This means that * Indicates that writeback caching should be enabled. This means that
@ -265,7 +283,7 @@ struct fuse_file_info {
* *
* This feature is disabled by default. * This feature is disabled by default.
*/ */
#define FUSE_CAP_WRITEBACK_CACHE (1 << 16) #define FUSE_CAP_WRITEBACK_CACHE (1 << 16)
/** /**
* Indicates support for zero-message opens. If this flag is set in * Indicates support for zero-message opens. If this flag is set in
@ -278,7 +296,7 @@ struct fuse_file_info {
* Setting (or unsetting) this flag in the `want` field has *no * Setting (or unsetting) this flag in the `want` field has *no
* effect*. * effect*.
*/ */
#define FUSE_CAP_NO_OPEN_SUPPORT (1 << 17) #define FUSE_CAP_NO_OPEN_SUPPORT (1 << 17)
/** /**
* Indicates support for parallel directory operations. If this flag * Indicates support for parallel directory operations. If this flag
@ -288,7 +306,7 @@ struct fuse_file_info {
* *
* This feature is enabled by default when supported by the kernel. * This feature is enabled by default when supported by the kernel.
*/ */
#define FUSE_CAP_PARALLEL_DIROPS (1 << 18) #define FUSE_CAP_PARALLEL_DIROPS (1 << 18)
/** /**
* Indicates support for POSIX ACLs. * Indicates support for POSIX ACLs.
@ -307,7 +325,7 @@ struct fuse_file_info {
* *
* This feature is disabled by default. * This feature is disabled by default.
*/ */
#define FUSE_CAP_POSIX_ACL (1 << 19) #define FUSE_CAP_POSIX_ACL (1 << 19)
/** /**
* Indicates that the filesystem is responsible for unsetting * Indicates that the filesystem is responsible for unsetting
@ -316,7 +334,7 @@ struct fuse_file_info {
* *
* This feature is enabled by default when supported by the kernel. * This feature is enabled by default when supported by the kernel.
*/ */
#define FUSE_CAP_HANDLE_KILLPRIV (1 << 20) #define FUSE_CAP_HANDLE_KILLPRIV (1 << 20)
/** /**
* Indicates support for zero-message opendirs. If this flag is set in * Indicates support for zero-message opendirs. If this flag is set in
@ -328,7 +346,7 @@ struct fuse_file_info {
* *
* Setting (or unsetting) this flag in the `want` field has *no effect*. * Setting (or unsetting) this flag in the `want` field has *no effect*.
*/ */
#define FUSE_CAP_NO_OPENDIR_SUPPORT (1 << 24) #define FUSE_CAP_NO_OPENDIR_SUPPORT (1 << 24)
/** /**
* Ioctl flags * Ioctl flags
@ -340,12 +358,12 @@ struct fuse_file_info {
* *
* FUSE_IOCTL_MAX_IOV: maximum of in_iovecs + out_iovecs * FUSE_IOCTL_MAX_IOV: maximum of in_iovecs + out_iovecs
*/ */
#define FUSE_IOCTL_COMPAT (1 << 0) #define FUSE_IOCTL_COMPAT (1 << 0)
#define FUSE_IOCTL_UNRESTRICTED (1 << 1) #define FUSE_IOCTL_UNRESTRICTED (1 << 1)
#define FUSE_IOCTL_RETRY (1 << 2) #define FUSE_IOCTL_RETRY (1 << 2)
#define FUSE_IOCTL_DIR (1 << 4) #define FUSE_IOCTL_DIR (1 << 4)
#define FUSE_IOCTL_MAX_IOV 256 #define FUSE_IOCTL_MAX_IOV 256
/** /**
* Connection information, passed to the ->init() method * Connection information, passed to the ->init() method
@ -355,114 +373,114 @@ struct fuse_file_info {
* value must usually be smaller than the indicated value. * value must usually be smaller than the indicated value.
*/ */
struct fuse_conn_info { struct fuse_conn_info {
/** /**
* Major version of the protocol (read-only) * Major version of the protocol (read-only)
*/ */
unsigned proto_major; unsigned proto_major;
/** /**
* Minor version of the protocol (read-only) * Minor version of the protocol (read-only)
*/ */
unsigned proto_minor; unsigned proto_minor;
/** /**
* Maximum size of the write buffer * Maximum size of the write buffer
*/ */
unsigned max_write; unsigned max_write;
/** /**
* Maximum size of read requests. A value of zero indicates no * Maximum size of read requests. A value of zero indicates no
* limit. However, even if the filesystem does not specify a * limit. However, even if the filesystem does not specify a
* limit, the maximum size of read requests will still be * limit, the maximum size of read requests will still be
* limited by the kernel. * limited by the kernel.
* *
* NOTE: For the time being, the maximum size of read requests * NOTE: For the time being, the maximum size of read requests
* must be set both here *and* passed to fuse_session_new() * must be set both here *and* passed to fuse_session_new()
* using the ``-o max_read=<n>`` mount option. At some point * using the ``-o max_read=<n>`` mount option. At some point
* in the future, specifying the mount option will no longer * in the future, specifying the mount option will no longer
* be necessary. * be necessary.
*/ */
unsigned max_read; unsigned max_read;
/** /**
* Maximum readahead * Maximum readahead
*/ */
unsigned max_readahead; unsigned max_readahead;
/** /**
* Capability flags that the kernel supports (read-only) * Capability flags that the kernel supports (read-only)
*/ */
unsigned capable; unsigned capable;
/** /**
* Capability flags that the filesystem wants to enable. * Capability flags that the filesystem wants to enable.
* *
* libfuse attempts to initialize this field with * libfuse attempts to initialize this field with
* reasonable default values before calling the init() handler. * reasonable default values before calling the init() handler.
*/ */
unsigned want; unsigned want;
/** /**
* Maximum number of pending "background" requests. A * Maximum number of pending "background" requests. A
* background request is any type of request for which the * background request is any type of request for which the
* total number is not limited by other means. As of kernel * total number is not limited by other means. As of kernel
* 4.8, only two types of requests fall into this category: * 4.8, only two types of requests fall into this category:
* *
* 1. Read-ahead requests * 1. Read-ahead requests
* 2. Asynchronous direct I/O requests * 2. Asynchronous direct I/O requests
* *
* Read-ahead requests are generated (if max_readahead is * Read-ahead requests are generated (if max_readahead is
* non-zero) by the kernel to preemptively fill its caches * non-zero) by the kernel to preemptively fill its caches
* when it anticipates that userspace will soon read more * when it anticipates that userspace will soon read more
* data. * data.
* *
* Asynchronous direct I/O requests are generated if * Asynchronous direct I/O requests are generated if
* FUSE_CAP_ASYNC_DIO is enabled and userspace submits a large * FUSE_CAP_ASYNC_DIO is enabled and userspace submits a large
* direct I/O request. In this case the kernel will internally * direct I/O request. In this case the kernel will internally
* split it up into multiple smaller requests and submit them * split it up into multiple smaller requests and submit them
* to the filesystem concurrently. * to the filesystem concurrently.
* *
* Note that the following requests are *not* background * Note that the following requests are *not* background
* requests: writeback requests (limited by the kernel's * requests: writeback requests (limited by the kernel's
* flusher algorithm), regular (i.e., synchronous and * flusher algorithm), regular (i.e., synchronous and
* buffered) userspace read/write requests (limited to one per * buffered) userspace read/write requests (limited to one per
* thread), asynchronous read requests (Linux's io_submit(2) * thread), asynchronous read requests (Linux's io_submit(2)
* call actually blocks, so these are also limited to one per * call actually blocks, so these are also limited to one per
* thread). * thread).
*/ */
unsigned max_background; unsigned max_background;
/** /**
* Kernel congestion threshold parameter. If the number of pending * Kernel congestion threshold parameter. If the number of pending
* background requests exceeds this number, the FUSE kernel module will * background requests exceeds this number, the FUSE kernel module will
* mark the filesystem as "congested". This instructs the kernel to * mark the filesystem as "congested". This instructs the kernel to
* expect that queued requests will take some time to complete, and to * expect that queued requests will take some time to complete, and to
* adjust its algorithms accordingly (e.g. by putting a waiting thread * adjust its algorithms accordingly (e.g. by putting a waiting thread
* to sleep instead of using a busy-loop). * to sleep instead of using a busy-loop).
*/ */
unsigned congestion_threshold; unsigned congestion_threshold;
/** /**
* When FUSE_CAP_WRITEBACK_CACHE is enabled, the kernel is responsible * When FUSE_CAP_WRITEBACK_CACHE is enabled, the kernel is responsible
* for updating mtime and ctime when write requests are received. The * for updating mtime and ctime when write requests are received. The
* updated values are passed to the filesystem with setattr() requests. * updated values are passed to the filesystem with setattr() requests.
* However, if the filesystem does not support the full resolution of * However, if the filesystem does not support the full resolution of
* the kernel timestamps (nanoseconds), the mtime and ctime values used * the kernel timestamps (nanoseconds), the mtime and ctime values used
* by kernel and filesystem will differ (and result in an apparent * by kernel and filesystem will differ (and result in an apparent
* change of times after a cache flush). * change of times after a cache flush).
* *
* To prevent this problem, this variable can be used to inform the * To prevent this problem, this variable can be used to inform the
* kernel about the timestamp granularity supported by the file-system. * kernel about the timestamp granularity supported by the file-system.
* The value should be power of 10. The default is 1, i.e. full * The value should be power of 10. The default is 1, i.e. full
* nano-second resolution. Filesystems supporting only second resolution * nano-second resolution. Filesystems supporting only second resolution
* should set this to 1000000000. * should set this to 1000000000.
*/ */
unsigned time_gran; unsigned time_gran;
/** /**
* For future use. * For future use.
*/ */
unsigned reserved[22]; unsigned reserved[22];
}; };
struct fuse_session; struct fuse_session;
@ -489,21 +507,20 @@ struct fuse_conn_info_opts;
* -o async_read sets FUSE_CAP_ASYNC_READ in conn->want * -o async_read sets FUSE_CAP_ASYNC_READ in conn->want
* -o sync_read unsets FUSE_CAP_ASYNC_READ in conn->want * -o sync_read unsets FUSE_CAP_ASYNC_READ in conn->want
* -o atomic_o_trunc sets FUSE_CAP_ATOMIC_O_TRUNC in conn->want * -o atomic_o_trunc sets FUSE_CAP_ATOMIC_O_TRUNC in conn->want
* -o no_remote_lock Equivalent to -o no_remote_flock,no_remote_posix_lock * -o no_remote_lock Equivalent to -o
* -o no_remote_flock Unsets FUSE_CAP_FLOCK_LOCKS in conn->want *no_remote_flock,no_remote_posix_lock -o no_remote_flock Unsets
* -o no_remote_posix_lock Unsets FUSE_CAP_POSIX_LOCKS in conn->want *FUSE_CAP_FLOCK_LOCKS in conn->want -o no_remote_posix_lock Unsets
* -o [no_]splice_write (un-)sets FUSE_CAP_SPLICE_WRITE in conn->want *FUSE_CAP_POSIX_LOCKS in conn->want -o [no_]splice_write (un-)sets
* -o [no_]splice_move (un-)sets FUSE_CAP_SPLICE_MOVE in conn->want *FUSE_CAP_SPLICE_WRITE in conn->want -o [no_]splice_move (un-)sets
* -o [no_]splice_read (un-)sets FUSE_CAP_SPLICE_READ in conn->want *FUSE_CAP_SPLICE_MOVE in conn->want -o [no_]splice_read (un-)sets
* -o [no_]auto_inval_data (un-)sets FUSE_CAP_AUTO_INVAL_DATA in conn->want *FUSE_CAP_SPLICE_READ in conn->want -o [no_]auto_inval_data (un-)sets
* -o readdirplus=no unsets FUSE_CAP_READDIRPLUS in conn->want *FUSE_CAP_AUTO_INVAL_DATA in conn->want -o readdirplus=no unsets
* -o readdirplus=yes sets FUSE_CAP_READDIRPLUS and unsets *FUSE_CAP_READDIRPLUS in conn->want -o readdirplus=yes sets
* FUSE_CAP_READDIRPLUS_AUTO in conn->want *FUSE_CAP_READDIRPLUS and unsets FUSE_CAP_READDIRPLUS_AUTO in conn->want -o
* -o readdirplus=auto sets FUSE_CAP_READDIRPLUS and *readdirplus=auto sets FUSE_CAP_READDIRPLUS and FUSE_CAP_READDIRPLUS_AUTO
* FUSE_CAP_READDIRPLUS_AUTO in conn->want *in conn->want -o [no_]async_dio (un-)sets FUSE_CAP_ASYNC_DIO in
* -o [no_]async_dio (un-)sets FUSE_CAP_ASYNC_DIO in conn->want *conn->want -o [no_]writeback_cache (un-)sets FUSE_CAP_WRITEBACK_CACHE in
* -o [no_]writeback_cache (un-)sets FUSE_CAP_WRITEBACK_CACHE in conn->want *conn->want -o time_gran=N sets conn->time_gran
* -o time_gran=N sets conn->time_gran
* *
* Known options will be removed from *args*, unknown options will be * Known options will be removed from *args*, unknown options will be
* passed through unchanged. * passed through unchanged.
@ -511,7 +528,7 @@ struct fuse_conn_info_opts;
* @param args argument vector (input+output) * @param args argument vector (input+output)
* @return parsed options * @return parsed options
**/ **/
struct fuse_conn_info_opts* fuse_parse_conn_info_opts(struct fuse_args *args); struct fuse_conn_info_opts *fuse_parse_conn_info_opts(struct fuse_args *args);
/** /**
* This function applies the (parsed) parameters in *opts* to the * This function applies the (parsed) parameters in *opts* to the
@ -521,7 +538,7 @@ struct fuse_conn_info_opts* fuse_parse_conn_info_opts(struct fuse_args *args);
* option has been explicitly set. * option has been explicitly set.
*/ */
void fuse_apply_conn_info_opts(struct fuse_conn_info_opts *opts, void fuse_apply_conn_info_opts(struct fuse_conn_info_opts *opts,
struct fuse_conn_info *conn); struct fuse_conn_info *conn);
/** /**
* Go into the background * Go into the background
@ -552,81 +569,81 @@ const char *fuse_pkgversion(void);
*/ */
void fuse_pollhandle_destroy(struct fuse_pollhandle *ph); void fuse_pollhandle_destroy(struct fuse_pollhandle *ph);
/* ----------------------------------------------------------- * /*
* Data buffer * * Data buffer
* ----------------------------------------------------------- */ */
/** /**
* Buffer flags * Buffer flags
*/ */
enum fuse_buf_flags { enum fuse_buf_flags {
/** /**
* Buffer contains a file descriptor * Buffer contains a file descriptor
* *
* If this flag is set, the .fd field is valid, otherwise the * If this flag is set, the .fd field is valid, otherwise the
* .mem fields is valid. * .mem fields is valid.
*/ */
FUSE_BUF_IS_FD = (1 << 1), FUSE_BUF_IS_FD = (1 << 1),
/** /**
* Seek on the file descriptor * Seek on the file descriptor
* *
* If this flag is set then the .pos field is valid and is * If this flag is set then the .pos field is valid and is
* used to seek to the given offset before performing * used to seek to the given offset before performing
* operation on file descriptor. * operation on file descriptor.
*/ */
FUSE_BUF_FD_SEEK = (1 << 2), FUSE_BUF_FD_SEEK = (1 << 2),
/** /**
* Retry operation on file descriptor * Retry operation on file descriptor
* *
* If this flag is set then retry operation on file descriptor * If this flag is set then retry operation on file descriptor
* until .size bytes have been copied or an error or EOF is * until .size bytes have been copied or an error or EOF is
* detected. * detected.
*/ */
FUSE_BUF_FD_RETRY = (1 << 3), FUSE_BUF_FD_RETRY = (1 << 3),
}; };
/** /**
* Buffer copy flags * Buffer copy flags
*/ */
enum fuse_buf_copy_flags { enum fuse_buf_copy_flags {
/** /**
* Don't use splice(2) * Don't use splice(2)
* *
* Always fall back to using read and write instead of * Always fall back to using read and write instead of
* splice(2) to copy data from one file descriptor to another. * splice(2) to copy data from one file descriptor to another.
* *
* If this flag is not set, then only fall back if splice is * If this flag is not set, then only fall back if splice is
* unavailable. * unavailable.
*/ */
FUSE_BUF_NO_SPLICE = (1 << 1), FUSE_BUF_NO_SPLICE = (1 << 1),
/** /**
* Force splice * Force splice
* *
* Always use splice(2) to copy data from one file descriptor * Always use splice(2) to copy data from one file descriptor
* to another. If splice is not available, return -EINVAL. * to another. If splice is not available, return -EINVAL.
*/ */
FUSE_BUF_FORCE_SPLICE = (1 << 2), FUSE_BUF_FORCE_SPLICE = (1 << 2),
/** /**
* Try to move data with splice. * Try to move data with splice.
* *
* If splice is used, try to move pages from the source to the * If splice is used, try to move pages from the source to the
* destination instead of copying. See documentation of * destination instead of copying. See documentation of
* SPLICE_F_MOVE in splice(2) man page. * SPLICE_F_MOVE in splice(2) man page.
*/ */
FUSE_BUF_SPLICE_MOVE = (1 << 3), FUSE_BUF_SPLICE_MOVE = (1 << 3),
/** /**
* Don't block on the pipe when copying data with splice * Don't block on the pipe when copying data with splice
* *
* Makes the operations on the pipe non-blocking (if the pipe * Makes the operations on the pipe non-blocking (if the pipe
* is full or empty). See SPLICE_F_NONBLOCK in the splice(2) * is full or empty). See SPLICE_F_NONBLOCK in the splice(2)
* man page. * man page.
*/ */
FUSE_BUF_SPLICE_NONBLOCK= (1 << 4), FUSE_BUF_SPLICE_NONBLOCK = (1 << 4),
}; };
/** /**
@ -636,36 +653,36 @@ enum fuse_buf_copy_flags {
* be supplied as a memory pointer or as a file descriptor * be supplied as a memory pointer or as a file descriptor
*/ */
struct fuse_buf { struct fuse_buf {
/** /**
* Size of data in bytes * Size of data in bytes
*/ */
size_t size; size_t size;
/** /**
* Buffer flags * Buffer flags
*/ */
enum fuse_buf_flags flags; enum fuse_buf_flags flags;
/** /**
* Memory pointer * Memory pointer
* *
* Used unless FUSE_BUF_IS_FD flag is set. * Used unless FUSE_BUF_IS_FD flag is set.
*/ */
void *mem; void *mem;
/** /**
* File descriptor * File descriptor
* *
* Used if FUSE_BUF_IS_FD flag is set. * Used if FUSE_BUF_IS_FD flag is set.
*/ */
int fd; int fd;
/** /**
* File position * File position
* *
* Used if FUSE_BUF_FD_SEEK flag is set. * Used if FUSE_BUF_FD_SEEK flag is set.
*/ */
off_t pos; off_t pos;
}; };
/** /**
@ -677,41 +694,39 @@ struct fuse_buf {
* Allocate dynamically to add more than one buffer. * Allocate dynamically to add more than one buffer.
*/ */
struct fuse_bufvec { struct fuse_bufvec {
/** /**
* Number of buffers in the array * Number of buffers in the array
*/ */
size_t count; size_t count;
/** /**
* Index of current buffer within the array * Index of current buffer within the array
*/ */
size_t idx; size_t idx;
/** /**
* Current offset within the current buffer * Current offset within the current buffer
*/ */
size_t off; size_t off;
/** /**
* Array of buffers * Array of buffers
*/ */
struct fuse_buf buf[1]; struct fuse_buf buf[1];
}; };
/* Initialize bufvec with a single buffer of given size */ /* Initialize bufvec with a single buffer of given size */
#define FUSE_BUFVEC_INIT(size__) \ #define FUSE_BUFVEC_INIT(size__) \
((struct fuse_bufvec) { \ ((struct fuse_bufvec){ /* .count= */ 1, \
/* .count= */ 1, \ /* .idx = */ 0, \
/* .idx = */ 0, \ /* .off = */ 0, /* .buf = */ \
/* .off = */ 0, \ { /* [0] = */ { \
/* .buf = */ { /* [0] = */ { \ /* .size = */ (size__), \
/* .size = */ (size__), \ /* .flags = */ (enum fuse_buf_flags)0, \
/* .flags = */ (enum fuse_buf_flags) 0, \ /* .mem = */ NULL, \
/* .mem = */ NULL, \ /* .fd = */ -1, \
/* .fd = */ -1, \ /* .pos = */ 0, \
/* .pos = */ 0, \ } } })
} } \
} )
/** /**
* Get total size of data in a fuse buffer vector * Get total size of data in a fuse buffer vector
@ -730,16 +745,16 @@ size_t fuse_buf_size(const struct fuse_bufvec *bufv);
* @return actual number of bytes copied or -errno on error * @return actual number of bytes copied or -errno on error
*/ */
ssize_t fuse_buf_copy(struct fuse_bufvec *dst, struct fuse_bufvec *src, ssize_t fuse_buf_copy(struct fuse_bufvec *dst, struct fuse_bufvec *src,
enum fuse_buf_copy_flags flags); enum fuse_buf_copy_flags flags);
/* ----------------------------------------------------------- * /*
* Signal handling * * Signal handling
* ----------------------------------------------------------- */ */
/** /**
* Exit session on HUP, TERM and INT signals and ignore PIPE signal * Exit session on HUP, TERM and INT signals and ignore PIPE signal
* *
* Stores session in a global variable. May only be called once per * Stores session in a global variable. May only be called once per
* process until fuse_remove_signal_handlers() is called. * process until fuse_remove_signal_handlers() is called.
* *
* Once either of the POSIX signals arrives, the signal handler calls * Once either of the POSIX signals arrives, the signal handler calls
@ -766,12 +781,12 @@ int fuse_set_signal_handlers(struct fuse_session *se);
*/ */
void fuse_remove_signal_handlers(struct fuse_session *se); void fuse_remove_signal_handlers(struct fuse_session *se);
/* ----------------------------------------------------------- * /*
* Compatibility stuff * * Compatibility stuff
* ----------------------------------------------------------- */ */
#if !defined(FUSE_USE_VERSION) || FUSE_USE_VERSION < 30 #if !defined(FUSE_USE_VERSION) || FUSE_USE_VERSION < 30
# error only API version 30 or greater is supported #error only API version 30 or greater is supported
#endif #endif
@ -781,11 +796,14 @@ void fuse_remove_signal_handlers(struct fuse_session *se);
* On 32bit systems please add -D_FILE_OFFSET_BITS=64 to your compile flags! * On 32bit systems please add -D_FILE_OFFSET_BITS=64 to your compile flags!
*/ */
#if defined(__GNUC__) && (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 6) && !defined __cplusplus #if defined(__GNUC__) && \
(__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 6) && \
!defined __cplusplus
_Static_assert(sizeof(off_t) == 8, "fuse: off_t must be 64bit"); _Static_assert(sizeof(off_t) == 8, "fuse: off_t must be 64bit");
#else #else
struct _fuse_off_t_must_be_64bit_dummy_struct \ struct _fuse_off_t_must_be_64bit_dummy_struct {
{ unsigned _fuse_off_t_must_be_64bit:((sizeof(off_t) == 8) ? 1 : -1); }; unsigned _fuse_off_t_must_be_64bit:((sizeof(off_t) == 8) ? 1 : -1);
};
#endif #endif
#endif /* FUSE_COMMON_H_ */ #endif /* FUSE_COMMON_H_ */

View File

@ -1,71 +1,71 @@
/* /*
FUSE: Filesystem in Userspace * FUSE: Filesystem in Userspace
Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu> * Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
*
This program can be distributed under the terms of the GNU LGPLv2. * This program can be distributed under the terms of the GNU LGPLv2.
See the file COPYING.LIB * See the file COPYING.LIB
*/ */
#include "fuse.h" #include "fuse.h"
#include "fuse_lowlevel.h" #include "fuse_lowlevel.h"
struct fuse_req { struct fuse_req {
struct fuse_session *se; struct fuse_session *se;
uint64_t unique; uint64_t unique;
int ctr; int ctr;
pthread_mutex_t lock; pthread_mutex_t lock;
struct fuse_ctx ctx; struct fuse_ctx ctx;
struct fuse_chan *ch; struct fuse_chan *ch;
int interrupted; int interrupted;
unsigned int ioctl_64bit : 1; unsigned int ioctl_64bit:1;
union { union {
struct { struct {
uint64_t unique; uint64_t unique;
} i; } i;
struct { struct {
fuse_interrupt_func_t func; fuse_interrupt_func_t func;
void *data; void *data;
} ni; } ni;
} u; } u;
struct fuse_req *next; struct fuse_req *next;
struct fuse_req *prev; struct fuse_req *prev;
}; };
struct fuse_notify_req { struct fuse_notify_req {
uint64_t unique; uint64_t unique;
void (*reply)(struct fuse_notify_req *, fuse_req_t, fuse_ino_t, void (*reply)(struct fuse_notify_req *, fuse_req_t, fuse_ino_t,
const void *, const struct fuse_buf *); const void *, const struct fuse_buf *);
struct fuse_notify_req *next; struct fuse_notify_req *next;
struct fuse_notify_req *prev; struct fuse_notify_req *prev;
}; };
struct fuse_session { struct fuse_session {
char *mountpoint; char *mountpoint;
volatile int exited; volatile int exited;
int fd; int fd;
int debug; int debug;
int deny_others; int deny_others;
struct fuse_lowlevel_ops op; struct fuse_lowlevel_ops op;
int got_init; int got_init;
struct cuse_data *cuse_data; struct cuse_data *cuse_data;
void *userdata; void *userdata;
uid_t owner; uid_t owner;
struct fuse_conn_info conn; struct fuse_conn_info conn;
struct fuse_req list; struct fuse_req list;
struct fuse_req interrupts; struct fuse_req interrupts;
pthread_mutex_t lock; pthread_mutex_t lock;
int got_destroy; int got_destroy;
int broken_splice_nonblock; int broken_splice_nonblock;
uint64_t notify_ctr; uint64_t notify_ctr;
struct fuse_notify_req notify_list; struct fuse_notify_req notify_list;
size_t bufsize; size_t bufsize;
int error; int error;
}; };
struct fuse_chan { struct fuse_chan {
pthread_mutex_t lock; pthread_mutex_t lock;
int ctr; int ctr;
int fd; int fd;
}; };
/** /**
@ -76,19 +76,20 @@ struct fuse_chan {
* *
*/ */
struct fuse_module { struct fuse_module {
char *name; char *name;
fuse_module_factory_t factory; fuse_module_factory_t factory;
struct fuse_module *next; struct fuse_module *next;
struct fusemod_so *so; struct fusemod_so *so;
int ctr; int ctr;
}; };
int fuse_send_reply_iov_nofree(fuse_req_t req, int error, struct iovec *iov, int fuse_send_reply_iov_nofree(fuse_req_t req, int error, struct iovec *iov,
int count); int count);
void fuse_free_req(fuse_req_t req); void fuse_free_req(fuse_req_t req);
void fuse_session_process_buf_int(struct fuse_session *se, void fuse_session_process_buf_int(struct fuse_session *se,
const struct fuse_buf *buf, struct fuse_chan *ch); const struct fuse_buf *buf,
struct fuse_chan *ch);
#define FUSE_MAX_MAX_PAGES 256 #define FUSE_MAX_MAX_PAGES 256

View File

@ -1,40 +1,40 @@
/* /*
FUSE: Filesystem in Userspace * FUSE: Filesystem in Userspace
Copyright (C) 2019 Red Hat, Inc. * Copyright (C) 2019 Red Hat, Inc.
*
Logging API. * Logging API.
*
This program can be distributed under the terms of the GNU LGPLv2. * This program can be distributed under the terms of the GNU LGPLv2.
See the file COPYING.LIB * See the file COPYING.LIB
*/ */
#include "fuse_log.h" #include "fuse_log.h"
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdio.h>
static void default_log_func( static void default_log_func(__attribute__((unused)) enum fuse_log_level level,
__attribute__(( unused )) enum fuse_log_level level, const char *fmt, va_list ap)
const char *fmt, va_list ap)
{ {
vfprintf(stderr, fmt, ap); vfprintf(stderr, fmt, ap);
} }
static fuse_log_func_t log_func = default_log_func; static fuse_log_func_t log_func = default_log_func;
void fuse_set_log_func(fuse_log_func_t func) void fuse_set_log_func(fuse_log_func_t func)
{ {
if (!func) if (!func) {
func = default_log_func; func = default_log_func;
}
log_func = func; log_func = func;
} }
void fuse_log(enum fuse_log_level level, const char *fmt, ...) void fuse_log(enum fuse_log_level level, const char *fmt, ...)
{ {
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
log_func(level, fmt, ap); log_func(level, fmt, ap);
va_end(ap); va_end(ap);
} }

View File

@ -1,10 +1,10 @@
/* /*
FUSE: Filesystem in Userspace * FUSE: Filesystem in Userspace
Copyright (C) 2019 Red Hat, Inc. * Copyright (C) 2019 Red Hat, Inc.
*
This program can be distributed under the terms of the GNU LGPLv2. * This program can be distributed under the terms of the GNU LGPLv2.
See the file COPYING.LIB. * See the file COPYING.LIB.
*/ */
#ifndef FUSE_LOG_H_ #ifndef FUSE_LOG_H_
#define FUSE_LOG_H_ #define FUSE_LOG_H_
@ -22,14 +22,14 @@
* These levels correspond to syslog(2) log levels since they are widely used. * These levels correspond to syslog(2) log levels since they are widely used.
*/ */
enum fuse_log_level { enum fuse_log_level {
FUSE_LOG_EMERG, FUSE_LOG_EMERG,
FUSE_LOG_ALERT, FUSE_LOG_ALERT,
FUSE_LOG_CRIT, FUSE_LOG_CRIT,
FUSE_LOG_ERR, FUSE_LOG_ERR,
FUSE_LOG_WARNING, FUSE_LOG_WARNING,
FUSE_LOG_NOTICE, FUSE_LOG_NOTICE,
FUSE_LOG_INFO, FUSE_LOG_INFO,
FUSE_LOG_DEBUG FUSE_LOG_DEBUG
}; };
/** /**
@ -45,8 +45,8 @@ enum fuse_log_level {
* @param fmt sprintf-style format string including newline * @param fmt sprintf-style format string including newline
* @param ap format string arguments * @param ap format string arguments
*/ */
typedef void (*fuse_log_func_t)(enum fuse_log_level level, typedef void (*fuse_log_func_t)(enum fuse_log_level level, const char *fmt,
const char *fmt, va_list ap); va_list ap);
/** /**
* Install a custom log handler function. * Install a custom log handler function.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,18 +1,18 @@
/* /*
FUSE: Filesystem in Userspace * FUSE: Filesystem in Userspace
Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu> * Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
*
This program can be distributed under the terms of the GNU LGPLv2. * This program can be distributed under the terms of the GNU LGPLv2.
See the file COPYING.LIB * See the file COPYING.LIB
*/ */
#include <pthread.h> #include <pthread.h>
/* /*
Versioned symbols cannot be used in some cases because it * Versioned symbols cannot be used in some cases because it
- confuse the dynamic linker in uClibc * - confuse the dynamic linker in uClibc
- not supported on MacOSX (in MachO binary format) * - not supported on MacOSX (in MachO binary format)
*/ */
#if (!defined(__UCLIBC__) && !defined(__APPLE__)) #if (!defined(__UCLIBC__) && !defined(__APPLE__))
#define FUSE_SYMVER(x) __asm__(x) #define FUSE_SYMVER(x) __asm__(x)
#else #else
@ -25,11 +25,11 @@
/* Is this hack still needed? */ /* Is this hack still needed? */
static inline void fuse_mutex_init(pthread_mutex_t *mut) static inline void fuse_mutex_init(pthread_mutex_t *mut)
{ {
pthread_mutexattr_t attr; pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr); pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ADAPTIVE_NP); pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ADAPTIVE_NP);
pthread_mutex_init(mut, &attr); pthread_mutex_init(mut, &attr);
pthread_mutexattr_destroy(&attr); pthread_mutexattr_destroy(&attr);
} }
#endif #endif

View File

@ -1,423 +1,450 @@
/* /*
FUSE: Filesystem in Userspace * FUSE: Filesystem in Userspace
Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu> * Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
*
Implementation of option parsing routines (dealing with `struct * Implementation of option parsing routines (dealing with `struct
fuse_args`). * fuse_args`).
*
This program can be distributed under the terms of the GNU LGPLv2. * This program can be distributed under the terms of the GNU LGPLv2.
See the file COPYING.LIB * See the file COPYING.LIB
*/ */
#include "fuse_opt.h"
#include "config.h" #include "config.h"
#include "fuse_i.h" #include "fuse_i.h"
#include "fuse_opt.h"
#include "fuse_misc.h" #include "fuse_misc.h"
#include <assert.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <assert.h>
struct fuse_opt_context { struct fuse_opt_context {
void *data; void *data;
const struct fuse_opt *opt; const struct fuse_opt *opt;
fuse_opt_proc_t proc; fuse_opt_proc_t proc;
int argctr; int argctr;
int argc; int argc;
char **argv; char **argv;
struct fuse_args outargs; struct fuse_args outargs;
char *opts; char *opts;
int nonopt; int nonopt;
}; };
void fuse_opt_free_args(struct fuse_args *args) void fuse_opt_free_args(struct fuse_args *args)
{ {
if (args) { if (args) {
if (args->argv && args->allocated) { if (args->argv && args->allocated) {
int i; int i;
for (i = 0; i < args->argc; i++) for (i = 0; i < args->argc; i++) {
free(args->argv[i]); free(args->argv[i]);
free(args->argv); }
} free(args->argv);
args->argc = 0; }
args->argv = NULL; args->argc = 0;
args->allocated = 0; args->argv = NULL;
} args->allocated = 0;
}
} }
static int alloc_failed(void) static int alloc_failed(void)
{ {
fuse_log(FUSE_LOG_ERR, "fuse: memory allocation failed\n"); fuse_log(FUSE_LOG_ERR, "fuse: memory allocation failed\n");
return -1; return -1;
} }
int fuse_opt_add_arg(struct fuse_args *args, const char *arg) int fuse_opt_add_arg(struct fuse_args *args, const char *arg)
{ {
char **newargv; char **newargv;
char *newarg; char *newarg;
assert(!args->argv || args->allocated); assert(!args->argv || args->allocated);
newarg = strdup(arg); newarg = strdup(arg);
if (!newarg) if (!newarg) {
return alloc_failed(); return alloc_failed();
}
newargv = realloc(args->argv, (args->argc + 2) * sizeof(char *)); newargv = realloc(args->argv, (args->argc + 2) * sizeof(char *));
if (!newargv) { if (!newargv) {
free(newarg); free(newarg);
return alloc_failed(); return alloc_failed();
} }
args->argv = newargv; args->argv = newargv;
args->allocated = 1; args->allocated = 1;
args->argv[args->argc++] = newarg; args->argv[args->argc++] = newarg;
args->argv[args->argc] = NULL; args->argv[args->argc] = NULL;
return 0; return 0;
} }
static int fuse_opt_insert_arg_common(struct fuse_args *args, int pos, static int fuse_opt_insert_arg_common(struct fuse_args *args, int pos,
const char *arg) const char *arg)
{ {
assert(pos <= args->argc); assert(pos <= args->argc);
if (fuse_opt_add_arg(args, arg) == -1) if (fuse_opt_add_arg(args, arg) == -1) {
return -1; return -1;
}
if (pos != args->argc - 1) { if (pos != args->argc - 1) {
char *newarg = args->argv[args->argc - 1]; char *newarg = args->argv[args->argc - 1];
memmove(&args->argv[pos + 1], &args->argv[pos], memmove(&args->argv[pos + 1], &args->argv[pos],
sizeof(char *) * (args->argc - pos - 1)); sizeof(char *) * (args->argc - pos - 1));
args->argv[pos] = newarg; args->argv[pos] = newarg;
} }
return 0; return 0;
} }
int fuse_opt_insert_arg(struct fuse_args *args, int pos, const char *arg) int fuse_opt_insert_arg(struct fuse_args *args, int pos, const char *arg)
{ {
return fuse_opt_insert_arg_common(args, pos, arg); return fuse_opt_insert_arg_common(args, pos, arg);
} }
static int next_arg(struct fuse_opt_context *ctx, const char *opt) static int next_arg(struct fuse_opt_context *ctx, const char *opt)
{ {
if (ctx->argctr + 1 >= ctx->argc) { if (ctx->argctr + 1 >= ctx->argc) {
fuse_log(FUSE_LOG_ERR, "fuse: missing argument after `%s'\n", opt); fuse_log(FUSE_LOG_ERR, "fuse: missing argument after `%s'\n", opt);
return -1; return -1;
} }
ctx->argctr++; ctx->argctr++;
return 0; return 0;
} }
static int add_arg(struct fuse_opt_context *ctx, const char *arg) static int add_arg(struct fuse_opt_context *ctx, const char *arg)
{ {
return fuse_opt_add_arg(&ctx->outargs, arg); return fuse_opt_add_arg(&ctx->outargs, arg);
} }
static int add_opt_common(char **opts, const char *opt, int esc) static int add_opt_common(char **opts, const char *opt, int esc)
{ {
unsigned oldlen = *opts ? strlen(*opts) : 0; unsigned oldlen = *opts ? strlen(*opts) : 0;
char *d = realloc(*opts, oldlen + 1 + strlen(opt) * 2 + 1); char *d = realloc(*opts, oldlen + 1 + strlen(opt) * 2 + 1);
if (!d) if (!d) {
return alloc_failed(); return alloc_failed();
}
*opts = d; *opts = d;
if (oldlen) { if (oldlen) {
d += oldlen; d += oldlen;
*d++ = ','; *d++ = ',';
} }
for (; *opt; opt++) { for (; *opt; opt++) {
if (esc && (*opt == ',' || *opt == '\\')) if (esc && (*opt == ',' || *opt == '\\')) {
*d++ = '\\'; *d++ = '\\';
*d++ = *opt; }
} *d++ = *opt;
*d = '\0'; }
*d = '\0';
return 0; return 0;
} }
int fuse_opt_add_opt(char **opts, const char *opt) int fuse_opt_add_opt(char **opts, const char *opt)
{ {
return add_opt_common(opts, opt, 0); return add_opt_common(opts, opt, 0);
} }
int fuse_opt_add_opt_escaped(char **opts, const char *opt) int fuse_opt_add_opt_escaped(char **opts, const char *opt)
{ {
return add_opt_common(opts, opt, 1); return add_opt_common(opts, opt, 1);
} }
static int add_opt(struct fuse_opt_context *ctx, const char *opt) static int add_opt(struct fuse_opt_context *ctx, const char *opt)
{ {
return add_opt_common(&ctx->opts, opt, 1); return add_opt_common(&ctx->opts, opt, 1);
} }
static int call_proc(struct fuse_opt_context *ctx, const char *arg, int key, static int call_proc(struct fuse_opt_context *ctx, const char *arg, int key,
int iso) int iso)
{ {
if (key == FUSE_OPT_KEY_DISCARD) if (key == FUSE_OPT_KEY_DISCARD) {
return 0; return 0;
}
if (key != FUSE_OPT_KEY_KEEP && ctx->proc) { if (key != FUSE_OPT_KEY_KEEP && ctx->proc) {
int res = ctx->proc(ctx->data, arg, key, &ctx->outargs); int res = ctx->proc(ctx->data, arg, key, &ctx->outargs);
if (res == -1 || !res) if (res == -1 || !res) {
return res; return res;
} }
if (iso) }
return add_opt(ctx, arg); if (iso) {
else return add_opt(ctx, arg);
return add_arg(ctx, arg); } else {
return add_arg(ctx, arg);
}
} }
static int match_template(const char *t, const char *arg, unsigned *sepp) static int match_template(const char *t, const char *arg, unsigned *sepp)
{ {
int arglen = strlen(arg); int arglen = strlen(arg);
const char *sep = strchr(t, '='); const char *sep = strchr(t, '=');
sep = sep ? sep : strchr(t, ' '); sep = sep ? sep : strchr(t, ' ');
if (sep && (!sep[1] || sep[1] == '%')) { if (sep && (!sep[1] || sep[1] == '%')) {
int tlen = sep - t; int tlen = sep - t;
if (sep[0] == '=') if (sep[0] == '=') {
tlen ++; tlen++;
if (arglen >= tlen && strncmp(arg, t, tlen) == 0) { }
*sepp = sep - t; if (arglen >= tlen && strncmp(arg, t, tlen) == 0) {
return 1; *sepp = sep - t;
} return 1;
} }
if (strcmp(t, arg) == 0) { }
*sepp = 0; if (strcmp(t, arg) == 0) {
return 1; *sepp = 0;
} return 1;
return 0; }
return 0;
} }
static const struct fuse_opt *find_opt(const struct fuse_opt *opt, static const struct fuse_opt *find_opt(const struct fuse_opt *opt,
const char *arg, unsigned *sepp) const char *arg, unsigned *sepp)
{ {
for (; opt && opt->templ; opt++) for (; opt && opt->templ; opt++) {
if (match_template(opt->templ, arg, sepp)) if (match_template(opt->templ, arg, sepp)) {
return opt; return opt;
return NULL; }
}
return NULL;
} }
int fuse_opt_match(const struct fuse_opt *opts, const char *opt) int fuse_opt_match(const struct fuse_opt *opts, const char *opt)
{ {
unsigned dummy; unsigned dummy;
return find_opt(opts, opt, &dummy) ? 1 : 0; return find_opt(opts, opt, &dummy) ? 1 : 0;
} }
static int process_opt_param(void *var, const char *format, const char *param, static int process_opt_param(void *var, const char *format, const char *param,
const char *arg) const char *arg)
{ {
assert(format[0] == '%'); assert(format[0] == '%');
if (format[1] == 's') { if (format[1] == 's') {
char **s = var; char **s = var;
char *copy = strdup(param); char *copy = strdup(param);
if (!copy) if (!copy) {
return alloc_failed(); return alloc_failed();
}
free(*s); free(*s);
*s = copy; *s = copy;
} else { } else {
if (sscanf(param, format, var) != 1) { if (sscanf(param, format, var) != 1) {
fuse_log(FUSE_LOG_ERR, "fuse: invalid parameter in option `%s'\n", arg); fuse_log(FUSE_LOG_ERR, "fuse: invalid parameter in option `%s'\n",
return -1; arg);
} return -1;
} }
return 0; }
return 0;
} }
static int process_opt(struct fuse_opt_context *ctx, static int process_opt(struct fuse_opt_context *ctx, const struct fuse_opt *opt,
const struct fuse_opt *opt, unsigned sep, unsigned sep, const char *arg, int iso)
const char *arg, int iso)
{ {
if (opt->offset == -1U) { if (opt->offset == -1U) {
if (call_proc(ctx, arg, opt->value, iso) == -1) if (call_proc(ctx, arg, opt->value, iso) == -1) {
return -1; return -1;
} else { }
void *var = (char *)ctx->data + opt->offset; } else {
if (sep && opt->templ[sep + 1]) { void *var = (char *)ctx->data + opt->offset;
const char *param = arg + sep; if (sep && opt->templ[sep + 1]) {
if (opt->templ[sep] == '=') const char *param = arg + sep;
param ++; if (opt->templ[sep] == '=') {
if (process_opt_param(var, opt->templ + sep + 1, param++;
param, arg) == -1) }
return -1; if (process_opt_param(var, opt->templ + sep + 1, param, arg) ==
} else -1) {
*(int *)var = opt->value; return -1;
} }
return 0; } else {
*(int *)var = opt->value;
}
}
return 0;
} }
static int process_opt_sep_arg(struct fuse_opt_context *ctx, static int process_opt_sep_arg(struct fuse_opt_context *ctx,
const struct fuse_opt *opt, unsigned sep, const struct fuse_opt *opt, unsigned sep,
const char *arg, int iso) const char *arg, int iso)
{ {
int res; int res;
char *newarg; char *newarg;
char *param; char *param;
if (next_arg(ctx, arg) == -1) if (next_arg(ctx, arg) == -1) {
return -1; return -1;
}
param = ctx->argv[ctx->argctr]; param = ctx->argv[ctx->argctr];
newarg = malloc(sep + strlen(param) + 1); newarg = malloc(sep + strlen(param) + 1);
if (!newarg) if (!newarg) {
return alloc_failed(); return alloc_failed();
}
memcpy(newarg, arg, sep); memcpy(newarg, arg, sep);
strcpy(newarg + sep, param); strcpy(newarg + sep, param);
res = process_opt(ctx, opt, sep, newarg, iso); res = process_opt(ctx, opt, sep, newarg, iso);
free(newarg); free(newarg);
return res; return res;
} }
static int process_gopt(struct fuse_opt_context *ctx, const char *arg, int iso) static int process_gopt(struct fuse_opt_context *ctx, const char *arg, int iso)
{ {
unsigned sep; unsigned sep;
const struct fuse_opt *opt = find_opt(ctx->opt, arg, &sep); const struct fuse_opt *opt = find_opt(ctx->opt, arg, &sep);
if (opt) { if (opt) {
for (; opt; opt = find_opt(opt + 1, arg, &sep)) { for (; opt; opt = find_opt(opt + 1, arg, &sep)) {
int res; int res;
if (sep && opt->templ[sep] == ' ' && !arg[sep]) if (sep && opt->templ[sep] == ' ' && !arg[sep]) {
res = process_opt_sep_arg(ctx, opt, sep, arg, res = process_opt_sep_arg(ctx, opt, sep, arg, iso);
iso); } else {
else res = process_opt(ctx, opt, sep, arg, iso);
res = process_opt(ctx, opt, sep, arg, iso); }
if (res == -1) if (res == -1) {
return -1; return -1;
} }
return 0; }
} else return 0;
return call_proc(ctx, arg, FUSE_OPT_KEY_OPT, iso); } else {
return call_proc(ctx, arg, FUSE_OPT_KEY_OPT, iso);
}
} }
static int process_real_option_group(struct fuse_opt_context *ctx, char *opts) static int process_real_option_group(struct fuse_opt_context *ctx, char *opts)
{ {
char *s = opts; char *s = opts;
char *d = s; char *d = s;
int end = 0; int end = 0;
while (!end) { while (!end) {
if (*s == '\0') if (*s == '\0') {
end = 1; end = 1;
if (*s == ',' || end) { }
int res; if (*s == ',' || end) {
int res;
*d = '\0'; *d = '\0';
res = process_gopt(ctx, opts, 1); res = process_gopt(ctx, opts, 1);
if (res == -1) if (res == -1) {
return -1; return -1;
d = opts; }
} else { d = opts;
if (s[0] == '\\' && s[1] != '\0') { } else {
s++; if (s[0] == '\\' && s[1] != '\0') {
if (s[0] >= '0' && s[0] <= '3' && s++;
s[1] >= '0' && s[1] <= '7' && if (s[0] >= '0' && s[0] <= '3' && s[1] >= '0' && s[1] <= '7' &&
s[2] >= '0' && s[2] <= '7') { s[2] >= '0' && s[2] <= '7') {
*d++ = (s[0] - '0') * 0100 + *d++ = (s[0] - '0') * 0100 + (s[1] - '0') * 0010 +
(s[1] - '0') * 0010 + (s[2] - '0');
(s[2] - '0'); s += 2;
s += 2; } else {
} else { *d++ = *s;
*d++ = *s; }
} } else {
} else { *d++ = *s;
*d++ = *s; }
} }
} s++;
s++; }
}
return 0; return 0;
} }
static int process_option_group(struct fuse_opt_context *ctx, const char *opts) static int process_option_group(struct fuse_opt_context *ctx, const char *opts)
{ {
int res; int res;
char *copy = strdup(opts); char *copy = strdup(opts);
if (!copy) { if (!copy) {
fuse_log(FUSE_LOG_ERR, "fuse: memory allocation failed\n"); fuse_log(FUSE_LOG_ERR, "fuse: memory allocation failed\n");
return -1; return -1;
} }
res = process_real_option_group(ctx, copy); res = process_real_option_group(ctx, copy);
free(copy); free(copy);
return res; return res;
} }
static int process_one(struct fuse_opt_context *ctx, const char *arg) static int process_one(struct fuse_opt_context *ctx, const char *arg)
{ {
if (ctx->nonopt || arg[0] != '-') if (ctx->nonopt || arg[0] != '-') {
return call_proc(ctx, arg, FUSE_OPT_KEY_NONOPT, 0); return call_proc(ctx, arg, FUSE_OPT_KEY_NONOPT, 0);
else if (arg[1] == 'o') { } else if (arg[1] == 'o') {
if (arg[2]) if (arg[2]) {
return process_option_group(ctx, arg + 2); return process_option_group(ctx, arg + 2);
else { } else {
if (next_arg(ctx, arg) == -1) if (next_arg(ctx, arg) == -1) {
return -1; return -1;
}
return process_option_group(ctx, return process_option_group(ctx, ctx->argv[ctx->argctr]);
ctx->argv[ctx->argctr]); }
} } else if (arg[1] == '-' && !arg[2]) {
} else if (arg[1] == '-' && !arg[2]) { if (add_arg(ctx, arg) == -1) {
if (add_arg(ctx, arg) == -1) return -1;
return -1; }
ctx->nonopt = ctx->outargs.argc; ctx->nonopt = ctx->outargs.argc;
return 0; return 0;
} else } else {
return process_gopt(ctx, arg, 0); return process_gopt(ctx, arg, 0);
}
} }
static int opt_parse(struct fuse_opt_context *ctx) static int opt_parse(struct fuse_opt_context *ctx)
{ {
if (ctx->argc) { if (ctx->argc) {
if (add_arg(ctx, ctx->argv[0]) == -1) if (add_arg(ctx, ctx->argv[0]) == -1) {
return -1; return -1;
} }
}
for (ctx->argctr = 1; ctx->argctr < ctx->argc; ctx->argctr++) for (ctx->argctr = 1; ctx->argctr < ctx->argc; ctx->argctr++) {
if (process_one(ctx, ctx->argv[ctx->argctr]) == -1) if (process_one(ctx, ctx->argv[ctx->argctr]) == -1) {
return -1; return -1;
}
}
if (ctx->opts) { if (ctx->opts) {
if (fuse_opt_insert_arg(&ctx->outargs, 1, "-o") == -1 || if (fuse_opt_insert_arg(&ctx->outargs, 1, "-o") == -1 ||
fuse_opt_insert_arg(&ctx->outargs, 2, ctx->opts) == -1) fuse_opt_insert_arg(&ctx->outargs, 2, ctx->opts) == -1) {
return -1; return -1;
} }
}
/* If option separator ("--") is the last argument, remove it */ /* If option separator ("--") is the last argument, remove it */
if (ctx->nonopt && ctx->nonopt == ctx->outargs.argc && if (ctx->nonopt && ctx->nonopt == ctx->outargs.argc &&
strcmp(ctx->outargs.argv[ctx->outargs.argc - 1], "--") == 0) { strcmp(ctx->outargs.argv[ctx->outargs.argc - 1], "--") == 0) {
free(ctx->outargs.argv[ctx->outargs.argc - 1]); free(ctx->outargs.argv[ctx->outargs.argc - 1]);
ctx->outargs.argv[--ctx->outargs.argc] = NULL; ctx->outargs.argv[--ctx->outargs.argc] = NULL;
} }
return 0; return 0;
} }
int fuse_opt_parse(struct fuse_args *args, void *data, int fuse_opt_parse(struct fuse_args *args, void *data,
const struct fuse_opt opts[], fuse_opt_proc_t proc) const struct fuse_opt opts[], fuse_opt_proc_t proc)
{ {
int res; int res;
struct fuse_opt_context ctx = { struct fuse_opt_context ctx = {
.data = data, .data = data,
.opt = opts, .opt = opts,
.proc = proc, .proc = proc,
}; };
if (!args || !args->argv || !args->argc) if (!args || !args->argv || !args->argc) {
return 0; return 0;
}
ctx.argc = args->argc; ctx.argc = args->argc;
ctx.argv = args->argv; ctx.argv = args->argv;
res = opt_parse(&ctx); res = opt_parse(&ctx);
if (res != -1) { if (res != -1) {
struct fuse_args tmp = *args; struct fuse_args tmp = *args;
*args = ctx.outargs; *args = ctx.outargs;
ctx.outargs = tmp; ctx.outargs = tmp;
} }
free(ctx.opts); free(ctx.opts);
fuse_opt_free_args(&ctx.outargs); fuse_opt_free_args(&ctx.outargs);
return res; return res;
} }

View File

@ -1,10 +1,10 @@
/* /*
FUSE: Filesystem in Userspace * FUSE: Filesystem in Userspace
Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu> * Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
*
This program can be distributed under the terms of the GNU LGPLv2. * This program can be distributed under the terms of the GNU LGPLv2.
See the file COPYING.LIB. * See the file COPYING.LIB.
*/ */
#ifndef FUSE_OPT_H_ #ifndef FUSE_OPT_H_
#define FUSE_OPT_H_ #define FUSE_OPT_H_
@ -37,7 +37,7 @@
* *
* - 'offsetof(struct foo, member)' actions i) and iii) * - 'offsetof(struct foo, member)' actions i) and iii)
* *
* - -1 action ii) * - -1 action ii)
* *
* The 'offsetof()' macro is defined in the <stddef.h> header. * The 'offsetof()' macro is defined in the <stddef.h> header.
* *
@ -48,7 +48,7 @@
* *
* The types of templates are: * The types of templates are:
* *
* 1) "-x", "-foo", "--foo", "--foo-bar", etc. These match only * 1) "-x", "-foo", "--foo", "--foo-bar", etc. These match only
* themselves. Invalid values are "--" and anything beginning * themselves. Invalid values are "--" and anything beginning
* with "-o" * with "-o"
* *
@ -71,58 +71,67 @@
* freed. * freed.
*/ */
struct fuse_opt { struct fuse_opt {
/** Matching template and optional parameter formatting */ /** Matching template and optional parameter formatting */
const char *templ; const char *templ;
/** /**
* Offset of variable within 'data' parameter of fuse_opt_parse() * Offset of variable within 'data' parameter of fuse_opt_parse()
* or -1 * or -1
*/ */
unsigned long offset; unsigned long offset;
/** /**
* Value to set the variable to, or to be passed as 'key' to the * Value to set the variable to, or to be passed as 'key' to the
* processing function. Ignored if template has a format * processing function. Ignored if template has a format
*/ */
int value; int value;
}; };
/** /**
* Key option. In case of a match, the processing function will be * Key option. In case of a match, the processing function will be
* called with the specified key. * called with the specified key.
*/ */
#define FUSE_OPT_KEY(templ, key) { templ, -1U, key } #define FUSE_OPT_KEY(templ, key) \
{ \
templ, -1U, key \
}
/** /**
* Last option. An array of 'struct fuse_opt' must end with a NULL * Last option. An array of 'struct fuse_opt' must end with a NULL
* template value * template value
*/ */
#define FUSE_OPT_END { NULL, 0, 0 } #define FUSE_OPT_END \
{ \
NULL, 0, 0 \
}
/** /**
* Argument list * Argument list
*/ */
struct fuse_args { struct fuse_args {
/** Argument count */ /** Argument count */
int argc; int argc;
/** Argument vector. NULL terminated */ /** Argument vector. NULL terminated */
char **argv; char **argv;
/** Is 'argv' allocated? */ /** Is 'argv' allocated? */
int allocated; int allocated;
}; };
/** /**
* Initializer for 'struct fuse_args' * Initializer for 'struct fuse_args'
*/ */
#define FUSE_ARGS_INIT(argc, argv) { argc, argv, 0 } #define FUSE_ARGS_INIT(argc, argv) \
{ \
argc, argv, 0 \
}
/** /**
* Key value passed to the processing function if an option did not * Key value passed to the processing function if an option did not
* match any template * match any template
*/ */
#define FUSE_OPT_KEY_OPT -1 #define FUSE_OPT_KEY_OPT -1
/** /**
* Key value passed to the processing function for all non-options * Key value passed to the processing function for all non-options
@ -130,7 +139,7 @@ struct fuse_args {
* Non-options are the arguments beginning with a character other than * Non-options are the arguments beginning with a character other than
* '-' or all arguments after the special '--' option * '-' or all arguments after the special '--' option
*/ */
#define FUSE_OPT_KEY_NONOPT -2 #define FUSE_OPT_KEY_NONOPT -2
/** /**
* Special key value for options to keep * Special key value for options to keep
@ -174,7 +183,7 @@ struct fuse_args {
* @return -1 on error, 0 if arg is to be discarded, 1 if arg should be kept * @return -1 on error, 0 if arg is to be discarded, 1 if arg should be kept
*/ */
typedef int (*fuse_opt_proc_t)(void *data, const char *arg, int key, typedef int (*fuse_opt_proc_t)(void *data, const char *arg, int key,
struct fuse_args *outargs); struct fuse_args *outargs);
/** /**
* Option parsing function * Option parsing function
@ -197,7 +206,7 @@ typedef int (*fuse_opt_proc_t)(void *data, const char *arg, int key,
* @return -1 on error, 0 on success * @return -1 on error, 0 on success
*/ */
int fuse_opt_parse(struct fuse_args *args, void *data, int fuse_opt_parse(struct fuse_args *args, void *data,
const struct fuse_opt opts[], fuse_opt_proc_t proc); const struct fuse_opt opts[], fuse_opt_proc_t proc);
/** /**
* Add an option to a comma separated option list * Add an option to a comma separated option list

View File

@ -1,91 +1,95 @@
/* /*
FUSE: Filesystem in Userspace * FUSE: Filesystem in Userspace
Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu> * Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
*
Utility functions for setting signal handlers. * Utility functions for setting signal handlers.
*
This program can be distributed under the terms of the GNU LGPLv2. * This program can be distributed under the terms of the GNU LGPLv2.
See the file COPYING.LIB * See the file COPYING.LIB
*/ */
#include "config.h" #include "config.h"
#include "fuse_lowlevel.h"
#include "fuse_i.h" #include "fuse_i.h"
#include "fuse_lowlevel.h"
#include <stdio.h>
#include <string.h>
#include <signal.h> #include <signal.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
static struct fuse_session *fuse_instance; static struct fuse_session *fuse_instance;
static void exit_handler(int sig) static void exit_handler(int sig)
{ {
if (fuse_instance) { if (fuse_instance) {
fuse_session_exit(fuse_instance); fuse_session_exit(fuse_instance);
if(sig <= 0) { if (sig <= 0) {
fuse_log(FUSE_LOG_ERR, "assertion error: signal value <= 0\n"); fuse_log(FUSE_LOG_ERR, "assertion error: signal value <= 0\n");
abort(); abort();
} }
fuse_instance->error = sig; fuse_instance->error = sig;
} }
} }
static void do_nothing(int sig) static void do_nothing(int sig)
{ {
(void) sig; (void)sig;
} }
static int set_one_signal_handler(int sig, void (*handler)(int), int remove) static int set_one_signal_handler(int sig, void (*handler)(int), int remove)
{ {
struct sigaction sa; struct sigaction sa;
struct sigaction old_sa; struct sigaction old_sa;
memset(&sa, 0, sizeof(struct sigaction)); memset(&sa, 0, sizeof(struct sigaction));
sa.sa_handler = remove ? SIG_DFL : handler; sa.sa_handler = remove ? SIG_DFL : handler;
sigemptyset(&(sa.sa_mask)); sigemptyset(&(sa.sa_mask));
sa.sa_flags = 0; sa.sa_flags = 0;
if (sigaction(sig, NULL, &old_sa) == -1) { if (sigaction(sig, NULL, &old_sa) == -1) {
perror("fuse: cannot get old signal handler"); perror("fuse: cannot get old signal handler");
return -1; return -1;
} }
if (old_sa.sa_handler == (remove ? handler : SIG_DFL) && if (old_sa.sa_handler == (remove ? handler : SIG_DFL) &&
sigaction(sig, &sa, NULL) == -1) { sigaction(sig, &sa, NULL) == -1) {
perror("fuse: cannot set signal handler"); perror("fuse: cannot set signal handler");
return -1; return -1;
} }
return 0; return 0;
} }
int fuse_set_signal_handlers(struct fuse_session *se) int fuse_set_signal_handlers(struct fuse_session *se)
{ {
/* If we used SIG_IGN instead of the do_nothing function, /*
then we would be unable to tell if we set SIG_IGN (and * If we used SIG_IGN instead of the do_nothing function,
thus should reset to SIG_DFL in fuse_remove_signal_handlers) * then we would be unable to tell if we set SIG_IGN (and
or if it was already set to SIG_IGN (and should be left * thus should reset to SIG_DFL in fuse_remove_signal_handlers)
untouched. */ * or if it was already set to SIG_IGN (and should be left
if (set_one_signal_handler(SIGHUP, exit_handler, 0) == -1 || * untouched.
set_one_signal_handler(SIGINT, exit_handler, 0) == -1 || */
set_one_signal_handler(SIGTERM, exit_handler, 0) == -1 || if (set_one_signal_handler(SIGHUP, exit_handler, 0) == -1 ||
set_one_signal_handler(SIGPIPE, do_nothing, 0) == -1) set_one_signal_handler(SIGINT, exit_handler, 0) == -1 ||
return -1; set_one_signal_handler(SIGTERM, exit_handler, 0) == -1 ||
set_one_signal_handler(SIGPIPE, do_nothing, 0) == -1) {
return -1;
}
fuse_instance = se; fuse_instance = se;
return 0; return 0;
} }
void fuse_remove_signal_handlers(struct fuse_session *se) void fuse_remove_signal_handlers(struct fuse_session *se)
{ {
if (fuse_instance != se) if (fuse_instance != se) {
fuse_log(FUSE_LOG_ERR, fuse_log(FUSE_LOG_ERR,
"fuse: fuse_remove_signal_handlers: unknown session\n"); "fuse: fuse_remove_signal_handlers: unknown session\n");
else } else {
fuse_instance = NULL; fuse_instance = NULL;
}
set_one_signal_handler(SIGHUP, exit_handler, 1); set_one_signal_handler(SIGHUP, exit_handler, 1);
set_one_signal_handler(SIGINT, exit_handler, 1); set_one_signal_handler(SIGINT, exit_handler, 1);
set_one_signal_handler(SIGTERM, exit_handler, 1); set_one_signal_handler(SIGTERM, exit_handler, 1);
set_one_signal_handler(SIGPIPE, do_nothing, 1); set_one_signal_handler(SIGPIPE, do_nothing, 1);
} }

View File

@ -1,297 +1,309 @@
/* /*
FUSE: Filesystem in Userspace * FUSE: Filesystem in Userspace
Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu> * Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
*
* Helper functions to create (simple) standalone programs. With the
* aid of these functions it should be possible to create full FUSE
* file system by implementing nothing but the request handlers.
Helper functions to create (simple) standalone programs. With the * This program can be distributed under the terms of the GNU LGPLv2.
aid of these functions it should be possible to create full FUSE * See the file COPYING.LIB.
file system by implementing nothing but the request handlers. */
This program can be distributed under the terms of the GNU LGPLv2.
See the file COPYING.LIB.
*/
#include "config.h" #include "config.h"
#include "fuse_i.h" #include "fuse_i.h"
#include "fuse_lowlevel.h"
#include "fuse_misc.h" #include "fuse_misc.h"
#include "fuse_opt.h" #include "fuse_opt.h"
#include "fuse_lowlevel.h"
#include "mount_util.h" #include "mount_util.h"
#include <errno.h>
#include <limits.h>
#include <stddef.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stddef.h>
#include <unistd.h>
#include <string.h> #include <string.h>
#include <limits.h>
#include <errno.h>
#include <sys/param.h> #include <sys/param.h>
#include <unistd.h>
#define FUSE_HELPER_OPT(t, p) \ #define FUSE_HELPER_OPT(t, p) \
{ t, offsetof(struct fuse_cmdline_opts, p), 1 } { \
t, offsetof(struct fuse_cmdline_opts, p), 1 \
}
static const struct fuse_opt fuse_helper_opts[] = { static const struct fuse_opt fuse_helper_opts[] = {
FUSE_HELPER_OPT("-h", show_help), FUSE_HELPER_OPT("-h", show_help),
FUSE_HELPER_OPT("--help", show_help), FUSE_HELPER_OPT("--help", show_help),
FUSE_HELPER_OPT("-V", show_version), FUSE_HELPER_OPT("-V", show_version),
FUSE_HELPER_OPT("--version", show_version), FUSE_HELPER_OPT("--version", show_version),
FUSE_HELPER_OPT("-d", debug), FUSE_HELPER_OPT("-d", debug),
FUSE_HELPER_OPT("debug", debug), FUSE_HELPER_OPT("debug", debug),
FUSE_HELPER_OPT("-d", foreground), FUSE_HELPER_OPT("-d", foreground),
FUSE_HELPER_OPT("debug", foreground), FUSE_HELPER_OPT("debug", foreground),
FUSE_OPT_KEY("-d", FUSE_OPT_KEY_KEEP), FUSE_OPT_KEY("-d", FUSE_OPT_KEY_KEEP),
FUSE_OPT_KEY("debug", FUSE_OPT_KEY_KEEP), FUSE_OPT_KEY("debug", FUSE_OPT_KEY_KEEP),
FUSE_HELPER_OPT("-f", foreground), FUSE_HELPER_OPT("-f", foreground),
FUSE_HELPER_OPT("fsname=", nodefault_subtype), FUSE_HELPER_OPT("fsname=", nodefault_subtype),
FUSE_OPT_KEY("fsname=", FUSE_OPT_KEY_KEEP), FUSE_OPT_KEY("fsname=", FUSE_OPT_KEY_KEEP),
FUSE_HELPER_OPT("subtype=", nodefault_subtype), FUSE_HELPER_OPT("subtype=", nodefault_subtype),
FUSE_OPT_KEY("subtype=", FUSE_OPT_KEY_KEEP), FUSE_OPT_KEY("subtype=", FUSE_OPT_KEY_KEEP),
FUSE_HELPER_OPT("max_idle_threads=%u", max_idle_threads), FUSE_HELPER_OPT("max_idle_threads=%u", max_idle_threads),
FUSE_OPT_END FUSE_OPT_END
}; };
struct fuse_conn_info_opts { struct fuse_conn_info_opts {
int atomic_o_trunc; int atomic_o_trunc;
int no_remote_posix_lock; int no_remote_posix_lock;
int no_remote_flock; int no_remote_flock;
int splice_write; int splice_write;
int splice_move; int splice_move;
int splice_read; int splice_read;
int no_splice_write; int no_splice_write;
int no_splice_move; int no_splice_move;
int no_splice_read; int no_splice_read;
int auto_inval_data; int auto_inval_data;
int no_auto_inval_data; int no_auto_inval_data;
int no_readdirplus; int no_readdirplus;
int no_readdirplus_auto; int no_readdirplus_auto;
int async_dio; int async_dio;
int no_async_dio; int no_async_dio;
int writeback_cache; int writeback_cache;
int no_writeback_cache; int no_writeback_cache;
int async_read; int async_read;
int sync_read; int sync_read;
unsigned max_write; unsigned max_write;
unsigned max_readahead; unsigned max_readahead;
unsigned max_background; unsigned max_background;
unsigned congestion_threshold; unsigned congestion_threshold;
unsigned time_gran; unsigned time_gran;
int set_max_write; int set_max_write;
int set_max_readahead; int set_max_readahead;
int set_max_background; int set_max_background;
int set_congestion_threshold; int set_congestion_threshold;
int set_time_gran; int set_time_gran;
}; };
#define CONN_OPTION(t, p, v) \ #define CONN_OPTION(t, p, v) \
{ t, offsetof(struct fuse_conn_info_opts, p), v } { \
t, offsetof(struct fuse_conn_info_opts, p), v \
}
static const struct fuse_opt conn_info_opt_spec[] = { static const struct fuse_opt conn_info_opt_spec[] = {
CONN_OPTION("max_write=%u", max_write, 0), CONN_OPTION("max_write=%u", max_write, 0),
CONN_OPTION("max_write=", set_max_write, 1), CONN_OPTION("max_write=", set_max_write, 1),
CONN_OPTION("max_readahead=%u", max_readahead, 0), CONN_OPTION("max_readahead=%u", max_readahead, 0),
CONN_OPTION("max_readahead=", set_max_readahead, 1), CONN_OPTION("max_readahead=", set_max_readahead, 1),
CONN_OPTION("max_background=%u", max_background, 0), CONN_OPTION("max_background=%u", max_background, 0),
CONN_OPTION("max_background=", set_max_background, 1), CONN_OPTION("max_background=", set_max_background, 1),
CONN_OPTION("congestion_threshold=%u", congestion_threshold, 0), CONN_OPTION("congestion_threshold=%u", congestion_threshold, 0),
CONN_OPTION("congestion_threshold=", set_congestion_threshold, 1), CONN_OPTION("congestion_threshold=", set_congestion_threshold, 1),
CONN_OPTION("sync_read", sync_read, 1), CONN_OPTION("sync_read", sync_read, 1),
CONN_OPTION("async_read", async_read, 1), CONN_OPTION("async_read", async_read, 1),
CONN_OPTION("atomic_o_trunc", atomic_o_trunc, 1), CONN_OPTION("atomic_o_trunc", atomic_o_trunc, 1),
CONN_OPTION("no_remote_lock", no_remote_posix_lock, 1), CONN_OPTION("no_remote_lock", no_remote_posix_lock, 1),
CONN_OPTION("no_remote_lock", no_remote_flock, 1), CONN_OPTION("no_remote_lock", no_remote_flock, 1),
CONN_OPTION("no_remote_flock", no_remote_flock, 1), CONN_OPTION("no_remote_flock", no_remote_flock, 1),
CONN_OPTION("no_remote_posix_lock", no_remote_posix_lock, 1), CONN_OPTION("no_remote_posix_lock", no_remote_posix_lock, 1),
CONN_OPTION("splice_write", splice_write, 1), CONN_OPTION("splice_write", splice_write, 1),
CONN_OPTION("no_splice_write", no_splice_write, 1), CONN_OPTION("no_splice_write", no_splice_write, 1),
CONN_OPTION("splice_move", splice_move, 1), CONN_OPTION("splice_move", splice_move, 1),
CONN_OPTION("no_splice_move", no_splice_move, 1), CONN_OPTION("no_splice_move", no_splice_move, 1),
CONN_OPTION("splice_read", splice_read, 1), CONN_OPTION("splice_read", splice_read, 1),
CONN_OPTION("no_splice_read", no_splice_read, 1), CONN_OPTION("no_splice_read", no_splice_read, 1),
CONN_OPTION("auto_inval_data", auto_inval_data, 1), CONN_OPTION("auto_inval_data", auto_inval_data, 1),
CONN_OPTION("no_auto_inval_data", no_auto_inval_data, 1), CONN_OPTION("no_auto_inval_data", no_auto_inval_data, 1),
CONN_OPTION("readdirplus=no", no_readdirplus, 1), CONN_OPTION("readdirplus=no", no_readdirplus, 1),
CONN_OPTION("readdirplus=yes", no_readdirplus, 0), CONN_OPTION("readdirplus=yes", no_readdirplus, 0),
CONN_OPTION("readdirplus=yes", no_readdirplus_auto, 1), CONN_OPTION("readdirplus=yes", no_readdirplus_auto, 1),
CONN_OPTION("readdirplus=auto", no_readdirplus, 0), CONN_OPTION("readdirplus=auto", no_readdirplus, 0),
CONN_OPTION("readdirplus=auto", no_readdirplus_auto, 0), CONN_OPTION("readdirplus=auto", no_readdirplus_auto, 0),
CONN_OPTION("async_dio", async_dio, 1), CONN_OPTION("async_dio", async_dio, 1),
CONN_OPTION("no_async_dio", no_async_dio, 1), CONN_OPTION("no_async_dio", no_async_dio, 1),
CONN_OPTION("writeback_cache", writeback_cache, 1), CONN_OPTION("writeback_cache", writeback_cache, 1),
CONN_OPTION("no_writeback_cache", no_writeback_cache, 1), CONN_OPTION("no_writeback_cache", no_writeback_cache, 1),
CONN_OPTION("time_gran=%u", time_gran, 0), CONN_OPTION("time_gran=%u", time_gran, 0),
CONN_OPTION("time_gran=", set_time_gran, 1), CONN_OPTION("time_gran=", set_time_gran, 1),
FUSE_OPT_END FUSE_OPT_END
}; };
void fuse_cmdline_help(void) void fuse_cmdline_help(void)
{ {
printf(" -h --help print help\n" printf(
" -V --version print version\n" " -h --help print help\n"
" -d -o debug enable debug output (implies -f)\n" " -V --version print version\n"
" -f foreground operation\n" " -d -o debug enable debug output (implies -f)\n"
" -o max_idle_threads the maximum number of idle worker threads\n" " -f foreground operation\n"
" allowed (default: 10)\n"); " -o max_idle_threads the maximum number of idle worker threads\n"
" allowed (default: 10)\n");
} }
static int fuse_helper_opt_proc(void *data, const char *arg, int key, static int fuse_helper_opt_proc(void *data, const char *arg, int key,
struct fuse_args *outargs) struct fuse_args *outargs)
{ {
(void) outargs; (void)outargs;
struct fuse_cmdline_opts *opts = data; struct fuse_cmdline_opts *opts = data;
switch (key) { switch (key) {
case FUSE_OPT_KEY_NONOPT: case FUSE_OPT_KEY_NONOPT:
if (!opts->mountpoint) { if (!opts->mountpoint) {
if (fuse_mnt_parse_fuse_fd(arg) != -1) { if (fuse_mnt_parse_fuse_fd(arg) != -1) {
return fuse_opt_add_opt(&opts->mountpoint, arg); return fuse_opt_add_opt(&opts->mountpoint, arg);
} }
char mountpoint[PATH_MAX] = ""; char mountpoint[PATH_MAX] = "";
if (realpath(arg, mountpoint) == NULL) { if (realpath(arg, mountpoint) == NULL) {
fuse_log(FUSE_LOG_ERR, fuse_log(FUSE_LOG_ERR, "fuse: bad mount point `%s': %s\n", arg,
"fuse: bad mount point `%s': %s\n", strerror(errno));
arg, strerror(errno)); return -1;
return -1; }
} return fuse_opt_add_opt(&opts->mountpoint, mountpoint);
return fuse_opt_add_opt(&opts->mountpoint, mountpoint); } else {
} else { fuse_log(FUSE_LOG_ERR, "fuse: invalid argument `%s'\n", arg);
fuse_log(FUSE_LOG_ERR, "fuse: invalid argument `%s'\n", arg); return -1;
return -1; }
}
default: default:
/* Pass through unknown options */ /* Pass through unknown options */
return 1; return 1;
} }
} }
int fuse_parse_cmdline(struct fuse_args *args, int fuse_parse_cmdline(struct fuse_args *args, struct fuse_cmdline_opts *opts)
struct fuse_cmdline_opts *opts)
{ {
memset(opts, 0, sizeof(struct fuse_cmdline_opts)); memset(opts, 0, sizeof(struct fuse_cmdline_opts));
opts->max_idle_threads = 10; opts->max_idle_threads = 10;
if (fuse_opt_parse(args, opts, fuse_helper_opts, if (fuse_opt_parse(args, opts, fuse_helper_opts, fuse_helper_opt_proc) ==
fuse_helper_opt_proc) == -1) -1) {
return -1; return -1;
}
return 0; return 0;
} }
int fuse_daemonize(int foreground) int fuse_daemonize(int foreground)
{ {
if (!foreground) { if (!foreground) {
int nullfd; int nullfd;
int waiter[2]; int waiter[2];
char completed; char completed;
if (pipe(waiter)) { if (pipe(waiter)) {
perror("fuse_daemonize: pipe"); perror("fuse_daemonize: pipe");
return -1; return -1;
} }
/* /*
* demonize current process by forking it and killing the * demonize current process by forking it and killing the
* parent. This makes current process as a child of 'init'. * parent. This makes current process as a child of 'init'.
*/ */
switch(fork()) { switch (fork()) {
case -1: case -1:
perror("fuse_daemonize: fork"); perror("fuse_daemonize: fork");
return -1; return -1;
case 0: case 0:
break; break;
default: default:
(void) read(waiter[0], &completed, sizeof(completed)); (void)read(waiter[0], &completed, sizeof(completed));
_exit(0); _exit(0);
} }
if (setsid() == -1) { if (setsid() == -1) {
perror("fuse_daemonize: setsid"); perror("fuse_daemonize: setsid");
return -1; return -1;
} }
(void) chdir("/"); (void)chdir("/");
nullfd = open("/dev/null", O_RDWR, 0); nullfd = open("/dev/null", O_RDWR, 0);
if (nullfd != -1) { if (nullfd != -1) {
(void) dup2(nullfd, 0); (void)dup2(nullfd, 0);
(void) dup2(nullfd, 1); (void)dup2(nullfd, 1);
(void) dup2(nullfd, 2); (void)dup2(nullfd, 2);
if (nullfd > 2) if (nullfd > 2) {
close(nullfd); close(nullfd);
} }
}
/* Propagate completion of daemon initialization */ /* Propagate completion of daemon initialization */
completed = 1; completed = 1;
(void) write(waiter[1], &completed, sizeof(completed)); (void)write(waiter[1], &completed, sizeof(completed));
close(waiter[0]); close(waiter[0]);
close(waiter[1]); close(waiter[1]);
} else { } else {
(void) chdir("/"); (void)chdir("/");
} }
return 0; return 0;
} }
void fuse_apply_conn_info_opts(struct fuse_conn_info_opts *opts, void fuse_apply_conn_info_opts(struct fuse_conn_info_opts *opts,
struct fuse_conn_info *conn) struct fuse_conn_info *conn)
{ {
if(opts->set_max_write) if (opts->set_max_write) {
conn->max_write = opts->max_write; conn->max_write = opts->max_write;
if(opts->set_max_background) }
conn->max_background = opts->max_background; if (opts->set_max_background) {
if(opts->set_congestion_threshold) conn->max_background = opts->max_background;
conn->congestion_threshold = opts->congestion_threshold; }
if(opts->set_time_gran) if (opts->set_congestion_threshold) {
conn->time_gran = opts->time_gran; conn->congestion_threshold = opts->congestion_threshold;
if(opts->set_max_readahead) }
conn->max_readahead = opts->max_readahead; if (opts->set_time_gran) {
conn->time_gran = opts->time_gran;
}
if (opts->set_max_readahead) {
conn->max_readahead = opts->max_readahead;
}
#define LL_ENABLE(cond,cap) \ #define LL_ENABLE(cond, cap) \
if (cond) conn->want |= (cap) if (cond) \
#define LL_DISABLE(cond,cap) \ conn->want |= (cap)
if (cond) conn->want &= ~(cap) #define LL_DISABLE(cond, cap) \
if (cond) \
conn->want &= ~(cap)
LL_ENABLE(opts->splice_read, FUSE_CAP_SPLICE_READ); LL_ENABLE(opts->splice_read, FUSE_CAP_SPLICE_READ);
LL_DISABLE(opts->no_splice_read, FUSE_CAP_SPLICE_READ); LL_DISABLE(opts->no_splice_read, FUSE_CAP_SPLICE_READ);
LL_ENABLE(opts->splice_write, FUSE_CAP_SPLICE_WRITE); LL_ENABLE(opts->splice_write, FUSE_CAP_SPLICE_WRITE);
LL_DISABLE(opts->no_splice_write, FUSE_CAP_SPLICE_WRITE); LL_DISABLE(opts->no_splice_write, FUSE_CAP_SPLICE_WRITE);
LL_ENABLE(opts->splice_move, FUSE_CAP_SPLICE_MOVE); LL_ENABLE(opts->splice_move, FUSE_CAP_SPLICE_MOVE);
LL_DISABLE(opts->no_splice_move, FUSE_CAP_SPLICE_MOVE); LL_DISABLE(opts->no_splice_move, FUSE_CAP_SPLICE_MOVE);
LL_ENABLE(opts->auto_inval_data, FUSE_CAP_AUTO_INVAL_DATA); LL_ENABLE(opts->auto_inval_data, FUSE_CAP_AUTO_INVAL_DATA);
LL_DISABLE(opts->no_auto_inval_data, FUSE_CAP_AUTO_INVAL_DATA); LL_DISABLE(opts->no_auto_inval_data, FUSE_CAP_AUTO_INVAL_DATA);
LL_DISABLE(opts->no_readdirplus, FUSE_CAP_READDIRPLUS); LL_DISABLE(opts->no_readdirplus, FUSE_CAP_READDIRPLUS);
LL_DISABLE(opts->no_readdirplus_auto, FUSE_CAP_READDIRPLUS_AUTO); LL_DISABLE(opts->no_readdirplus_auto, FUSE_CAP_READDIRPLUS_AUTO);
LL_ENABLE(opts->async_dio, FUSE_CAP_ASYNC_DIO); LL_ENABLE(opts->async_dio, FUSE_CAP_ASYNC_DIO);
LL_DISABLE(opts->no_async_dio, FUSE_CAP_ASYNC_DIO); LL_DISABLE(opts->no_async_dio, FUSE_CAP_ASYNC_DIO);
LL_ENABLE(opts->writeback_cache, FUSE_CAP_WRITEBACK_CACHE); LL_ENABLE(opts->writeback_cache, FUSE_CAP_WRITEBACK_CACHE);
LL_DISABLE(opts->no_writeback_cache, FUSE_CAP_WRITEBACK_CACHE); LL_DISABLE(opts->no_writeback_cache, FUSE_CAP_WRITEBACK_CACHE);
LL_ENABLE(opts->async_read, FUSE_CAP_ASYNC_READ); LL_ENABLE(opts->async_read, FUSE_CAP_ASYNC_READ);
LL_DISABLE(opts->sync_read, FUSE_CAP_ASYNC_READ); LL_DISABLE(opts->sync_read, FUSE_CAP_ASYNC_READ);
LL_DISABLE(opts->no_remote_posix_lock, FUSE_CAP_POSIX_LOCKS); LL_DISABLE(opts->no_remote_posix_lock, FUSE_CAP_POSIX_LOCKS);
LL_DISABLE(opts->no_remote_flock, FUSE_CAP_FLOCK_LOCKS); LL_DISABLE(opts->no_remote_flock, FUSE_CAP_FLOCK_LOCKS);
} }
struct fuse_conn_info_opts* fuse_parse_conn_info_opts(struct fuse_args *args) struct fuse_conn_info_opts *fuse_parse_conn_info_opts(struct fuse_args *args)
{ {
struct fuse_conn_info_opts *opts; struct fuse_conn_info_opts *opts;
opts = calloc(1, sizeof(struct fuse_conn_info_opts)); opts = calloc(1, sizeof(struct fuse_conn_info_opts));
if(opts == NULL) { if (opts == NULL) {
fuse_log(FUSE_LOG_ERR, "calloc failed\n"); fuse_log(FUSE_LOG_ERR, "calloc failed\n");
return NULL; return NULL;
} }
if(fuse_opt_parse(args, opts, conn_info_opt_spec, NULL) == -1) { if (fuse_opt_parse(args, opts, conn_info_opt_spec, NULL) == -1) {
free(opts); free(opts);
return NULL; return NULL;
} }
return opts; return opts;
} }

View File

@ -28,23 +28,24 @@
* operation * operation
*/ */
static int mknod_wrapper(int dirfd, const char *path, const char *link, static int mknod_wrapper(int dirfd, const char *path, const char *link,
int mode, dev_t rdev) int mode, dev_t rdev)
{ {
int res; int res;
if (S_ISREG(mode)) { if (S_ISREG(mode)) {
res = openat(dirfd, path, O_CREAT | O_EXCL | O_WRONLY, mode); res = openat(dirfd, path, O_CREAT | O_EXCL | O_WRONLY, mode);
if (res >= 0) if (res >= 0) {
res = close(res); res = close(res);
} else if (S_ISDIR(mode)) { }
res = mkdirat(dirfd, path, mode); } else if (S_ISDIR(mode)) {
} else if (S_ISLNK(mode) && link != NULL) { res = mkdirat(dirfd, path, mode);
res = symlinkat(link, dirfd, path); } else if (S_ISLNK(mode) && link != NULL) {
} else if (S_ISFIFO(mode)) { res = symlinkat(link, dirfd, path);
res = mkfifoat(dirfd, path, mode); } else if (S_ISFIFO(mode)) {
} else { res = mkfifoat(dirfd, path, mode);
res = mknodat(dirfd, path, mode, rdev); } else {
} res = mknodat(dirfd, path, mode, rdev);
}
return res; return res;
} }

File diff suppressed because it is too large Load Diff