mirror of
https://github.com/vgough/encfs.git
synced 2024-11-21 23:43:26 +01:00
add xattr translation
This commit is contained in:
parent
29c518d9d7
commit
a9975cd18d
124
encfs/encfs.cpp
124
encfs/encfs.cpp
@ -17,20 +17,25 @@
|
|||||||
|
|
||||||
#include "encfs.h"
|
#include "encfs.h"
|
||||||
|
|
||||||
|
#include <cerrno>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstring>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
#include <memory>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <string>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/statvfs.h>
|
#include <sys/statvfs.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <utility>
|
||||||
#include <utime.h>
|
#include <utime.h>
|
||||||
#include <cerrno>
|
#include <vector>
|
||||||
#include <cstddef>
|
|
||||||
#include <cstdio>
|
|
||||||
#include <cstring>
|
|
||||||
#include <memory>
|
|
||||||
#ifdef linux
|
#ifdef linux
|
||||||
#include <sys/fsuid.h>
|
#include <sys/fsuid.h>
|
||||||
#endif
|
#endif
|
||||||
@ -43,9 +48,6 @@
|
|||||||
|
|
||||||
#include <rlog/Error.h>
|
#include <rlog/Error.h>
|
||||||
#include <rlog/rlog.h>
|
#include <rlog/rlog.h>
|
||||||
#include <functional>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "Context.h"
|
#include "Context.h"
|
||||||
#include "DirNode.h"
|
#include "DirNode.h"
|
||||||
@ -60,10 +62,6 @@ namespace rlog {
|
|||||||
class RLogChannel;
|
class RLogChannel;
|
||||||
} // namespace rlog
|
} // namespace rlog
|
||||||
|
|
||||||
#ifndef MIN
|
|
||||||
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define ESUCCESS 0
|
#define ESUCCESS 0
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
@ -73,6 +71,13 @@ using rel::Lock;
|
|||||||
|
|
||||||
#define GET_FN(ctx, finfo) ctx->getNode((void *)(uintptr_t)finfo->fh)
|
#define GET_FN(ctx, finfo) ctx->getNode((void *)(uintptr_t)finfo->fh)
|
||||||
|
|
||||||
|
// XAttr prefix replacement.
|
||||||
|
// Replaces "com.apple." with "encfs_apl." when storing xattrs.
|
||||||
|
// TODO: future versions of encfs should encrypt xattrs, making this
|
||||||
|
// unnecessary.
|
||||||
|
static const char _attr_apple[] = "com.apple.";
|
||||||
|
static const char _attr_apple_internal[] = "encfs_apl.";
|
||||||
|
|
||||||
static RLogChannel *Info = DEF_CHANNEL("info", Log_Info);
|
static RLogChannel *Info = DEF_CHANNEL("info", Log_Info);
|
||||||
|
|
||||||
static EncFS_Context *context() {
|
static EncFS_Context *context() {
|
||||||
@ -634,77 +639,97 @@ int encfs_statfs(const char *path, struct statvfs *st) {
|
|||||||
|
|
||||||
#ifdef HAVE_XATTR
|
#ifdef HAVE_XATTR
|
||||||
|
|
||||||
#ifdef XATTR_ADD_OPT
|
typedef std::unique_ptr<const char[], std::function<void(const char *)>>
|
||||||
|
AttrPtr;
|
||||||
|
void NoFree(const char *) {}
|
||||||
|
|
||||||
|
AttrPtr extToInternalAttr(const char *attr) {
|
||||||
|
if (!strncmp(attr, _attr_apple, sizeof(_attr_apple) - 1)) {
|
||||||
|
char *out = strdup(attr);
|
||||||
|
memcpy(out, _attr_apple_internal, sizeof(_attr_apple_internal) - 1);
|
||||||
|
return AttrPtr(out, (void (*)(const char *))std::free);
|
||||||
|
} else {
|
||||||
|
return AttrPtr(attr, NoFree);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void internalToExtAttr(char *attr) {
|
||||||
|
if (!strncmp(attr, _attr_apple_internal, sizeof(_attr_apple_internal) - 1)) {
|
||||||
|
memcpy(attr, _attr_apple, sizeof(_attr_apple) - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int _do_setxattr(EncFS_Context *, const string &cyName, const char *name,
|
int _do_setxattr(EncFS_Context *, const string &cyName, const char *name,
|
||||||
const char *value, size_t size, uint32_t pos) {
|
const char *value, size_t size, uint32_t pos) {
|
||||||
int options = 0;
|
#ifdef XATTR_ADD_OPT
|
||||||
return ::setxattr(cyName.c_str(), name, value, size, pos, options);
|
return ::setxattr(cyName.c_str(), name, value, size, pos, XATTR_NOFOLLOW);
|
||||||
|
#else
|
||||||
|
return ::setxattr(cyName.c_str(), name, value, size, 0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
int encfs_setxattr(const char *path, const char *name, const char *value,
|
int encfs_setxattr(const char *path, const char *name, const char *value,
|
||||||
size_t size, int flags, uint32_t position) {
|
size_t size, int flags, uint32_t pos) {
|
||||||
if (isReadOnly(NULL)) return -EROFS;
|
if (isReadOnly(NULL)) return -EROFS;
|
||||||
(void)flags;
|
(void)flags;
|
||||||
return withCipherPath("setxattr", path, bind(_do_setxattr, _1, _2, name,
|
|
||||||
value, size, position));
|
AttrPtr attr = extToInternalAttr(name);
|
||||||
}
|
return withCipherPath("setxattr", path, bind(_do_setxattr, _1, _2, attr.get(),
|
||||||
#else
|
value, size, pos));
|
||||||
int _do_setxattr(EncFS_Context *, const string &cyName, const char *name,
|
|
||||||
const char *value, size_t size, int flags) {
|
|
||||||
return ::setxattr(cyName.c_str(), name, value, size, flags);
|
|
||||||
}
|
}
|
||||||
int encfs_setxattr(const char *path, const char *name, const char *value,
|
int encfs_setxattr(const char *path, const char *name, const char *value,
|
||||||
size_t size, int flags) {
|
size_t size, int flags) {
|
||||||
if (isReadOnly(NULL)) return -EROFS;
|
return encfs_setxattr(path, name, value, size, flags, uint32_t(0));
|
||||||
return withCipherPath("setxattr", path,
|
|
||||||
bind(_do_setxattr, _1, _2, name, value, size, flags));
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef XATTR_ADD_OPT
|
|
||||||
int _do_getxattr(EncFS_Context *, const string &cyName, const char *name,
|
int _do_getxattr(EncFS_Context *, const string &cyName, const char *name,
|
||||||
void *value, size_t size, uint32_t pos) {
|
void *value, size_t size, uint32_t pos) {
|
||||||
int options = 0;
|
#ifdef XATTR_ADD_OPT
|
||||||
return ::getxattr(cyName.c_str(), name, value, size, pos, options);
|
return ::getxattr(cyName.c_str(), name, value, size, pos, XATTR_NOFOLLOW);
|
||||||
|
#else
|
||||||
|
return ::getxattr(cyName.c_str(), name, value, size);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
int encfs_getxattr(const char *path, const char *name, char *value, size_t size,
|
int encfs_getxattr(const char *path, const char *name, char *value, size_t size,
|
||||||
uint32_t position) {
|
uint32_t pos) {
|
||||||
|
AttrPtr attr = extToInternalAttr(name);
|
||||||
return withCipherPath(
|
return withCipherPath(
|
||||||
"getxattr", path,
|
"getxattr", path,
|
||||||
bind(_do_getxattr, _1, _2, name, (void *)value, size, position), true);
|
bind(_do_getxattr, _1, _2, attr.get(), (void *)value, size, pos), true);
|
||||||
}
|
|
||||||
#else
|
|
||||||
int _do_getxattr(EncFS_Context *, const string &cyName, const char *name,
|
|
||||||
void *value, size_t size) {
|
|
||||||
return ::getxattr(cyName.c_str(), name, value, size);
|
|
||||||
}
|
}
|
||||||
int encfs_getxattr(const char *path, const char *name, char *value,
|
int encfs_getxattr(const char *path, const char *name, char *value,
|
||||||
size_t size) {
|
size_t size) {
|
||||||
return withCipherPath("getxattr", path,
|
return encfs_getxattr(path, name, value, size, uint32_t(0));
|
||||||
bind(_do_getxattr, _1, _2, name, (void *)value, size),
|
|
||||||
true);
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
int _do_listxattr(EncFS_Context *, const string &cyName, char *list,
|
int _do_listxattr(EncFS_Context *, const string &cyName, char *list,
|
||||||
size_t size) {
|
size_t size) {
|
||||||
#ifdef XATTR_ADD_OPT
|
#ifdef XATTR_ADD_OPT
|
||||||
int options = 0;
|
return ::listxattr(cyName.c_str(), list, size, XATTR_NOFOLLOW);
|
||||||
int res = ::listxattr(cyName.c_str(), list, size, options);
|
|
||||||
#else
|
#else
|
||||||
int res = ::listxattr(cyName.c_str(), list, size);
|
return ::listxattr(cyName.c_str(), list, size);
|
||||||
#endif
|
#endif
|
||||||
return (res == -1) ? -errno : res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int encfs_listxattr(const char *path, char *list, size_t size) {
|
int encfs_listxattr(const char *path, char *list, size_t size) {
|
||||||
return withCipherPath("listxattr", path,
|
int res = withCipherPath("listxattr", path,
|
||||||
bind(_do_listxattr, _1, _2, list, size), true);
|
bind(_do_listxattr, _1, _2, list, size), true);
|
||||||
|
if (list) {
|
||||||
|
size_t len = 0;
|
||||||
|
char *curr = list;
|
||||||
|
while (len < res) {
|
||||||
|
internalToExtAttr(curr);
|
||||||
|
size_t el_len = strlen(curr) + 1;
|
||||||
|
curr += el_len;
|
||||||
|
len += el_len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _do_removexattr(EncFS_Context *, const string &cyName, const char *name) {
|
int _do_removexattr(EncFS_Context *, const string &cyName, const char *name) {
|
||||||
#ifdef XATTR_ADD_OPT
|
#ifdef XATTR_ADD_OPT
|
||||||
int options = 0;
|
int res = ::removexattr(cyName.c_str(), name, XATTR_NOFOLLOW);
|
||||||
int res = ::removexattr(cyName.c_str(), name, options);
|
|
||||||
#else
|
#else
|
||||||
int res = ::removexattr(cyName.c_str(), name);
|
int res = ::removexattr(cyName.c_str(), name);
|
||||||
#endif
|
#endif
|
||||||
@ -714,8 +739,9 @@ int _do_removexattr(EncFS_Context *, const string &cyName, const char *name) {
|
|||||||
int encfs_removexattr(const char *path, const char *name) {
|
int encfs_removexattr(const char *path, const char *name) {
|
||||||
if (isReadOnly(NULL)) return -EROFS;
|
if (isReadOnly(NULL)) return -EROFS;
|
||||||
|
|
||||||
|
AttrPtr attr = extToInternalAttr(name);
|
||||||
return withCipherPath("removexattr", path,
|
return withCipherPath("removexattr", path,
|
||||||
bind(_do_removexattr, _1, _2, name));
|
bind(_do_removexattr, _1, _2, attr.get()));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // HAVE_XATTR
|
#endif // HAVE_XATTR
|
||||||
|
Loading…
Reference in New Issue
Block a user