// dirs
int Client::do_mkdirat(int dirfd, const char *relpath, mode_t mode, const UserPerm& perm,
- std::string alternate_name)
+ std::string alternate_name, FSCrypt_Options fscrypt_options)
{
RWRef_t mref_reader(mount_state, CLIENT_MOUNTING);
if (!mref_reader.is_state_satisfied())
return rc;
}
- return _mkdir(wdr, mode, perm, 0, {}, std::move(alternate_name));
+ return _mkdir(wdr, mode, perm, 0, {}, std::move(alternate_name), fscrypt_options);
}
int Client::mkdirs(const char *relpath, mode_t mode, const UserPerm& perms)
// symlinks
int Client::do_symlinkat(const char *target, int dirfd, const char *relpath, const UserPerm& perms,
- std::string alternate_name)
+ std::string alternate_name, FSCrypt_Options fscrypt_options)
{
RWRef_t mref_reader(mount_state, CLIENT_MOUNTING);
if (!mref_reader.is_state_satisfied()) {
if (int rc = get_fd_inode(dirfd, &dirinode); rc < 0) {
return rc;
}
- return _symlink(dirinode.get(), relpath, target, perms, std::move(alternate_name));
+ return _symlink(dirinode.get(), relpath, target, perms, std::move(alternate_name), 0, fscrypt_options);
}
int Client::readlink(const char *relpath, char *buf, loff_t size, const UserPerm& perms)
int Client::create_and_open(int dirfd, const char *relpath, int flags,
const UserPerm& perms, mode_t mode, int stripe_unit,
int stripe_count, int object_size, const char *data_pool,
- std::string alternate_name) {
+ std::string alternate_name, FSCrypt_Options fscrypt_options) {
ceph_assert(ceph_mutex_is_locked_by_me(client_lock));
int cflags = ceph_flags_sys2wire(flags);
tout(cct) << cflags << std::endl;
}
r = _create(wdr, flags, mode, &in, &fh, stripe_unit,
stripe_count, object_size, data_pool, &created, perms,
- std::move(alternate_name));
+ std::move(alternate_name), fscrypt_options);
if (r < 0)
goto out;
}
int Client::do_openat(int dirfd, const char *relpath, int flags, const UserPerm& perms,
mode_t mode, int stripe_unit, int stripe_count, int object_size,
- const char *data_pool, std::string alternate_name) {
+ const char *data_pool, std::string alternate_name,
+ FSCrypt_Options fscrypt_options) {
RWRef_t mref_reader(mount_state, CLIENT_MOUNTING);
if (!mref_reader.is_state_satisfied()) {
return -ENOTCONN;
std::scoped_lock locker(client_lock);
// NEXT
int r = create_and_open(dirfd, relpath, flags, perms, mode, stripe_unit, stripe_count,
- object_size, data_pool, std::move(alternate_name));
+ object_size, data_pool, std::move(alternate_name), fscrypt_options);
tout(cct) << r << std::endl;
ldout(cct, 3) << "openat exit(" << relpath << ")" << dendl;
int Client::_create(const walk_dentry_result& wdr, int flags, mode_t mode,
InodeRef *inp, Fh **fhp, int stripe_unit, int stripe_count,
int object_size, const char *data_pool, bool *created,
- const UserPerm& perms, std::string alternate_name)
+ const UserPerm& perms, std::string alternate_name,
+ FSCrypt_Options fscrypt_options)
{
ldout(cct, 8) << "_create(" << *wdr.diri << " " << wdr.dname << ", 0" << oct <<
mode << dec << " " << perms << ")" << dendl;
req->set_filepath(wdr.getpath());
req->set_alternate_name(alternate_name.empty() ? wdr.alternate_name : alternate_name);
req->set_inode(wdr.diri);
- wdr.diri->gen_inherited_fscrypt_auth(&req->fscrypt_auth);
+ if (fscrypt_options.fscrypt_auth.size())
+ req->fscrypt_auth = fscrypt_options.fscrypt_auth;
+ else
+ wdr.diri->gen_inherited_fscrypt_auth(&req->fscrypt_auth);
+
+ if (fscrypt_options.fscrypt_file.size())
+ req->fscrypt_file = fscrypt_options.fscrypt_file;
+
req->head.args.open.flags = cflags | CEPH_O_CREAT;
req->head.args.open.stripe_unit = stripe_unit;
int Client::_mkdir(const walk_dentry_result& wdr, mode_t mode, const UserPerm& perm,
InodeRef *inp, const std::map<std::string, std::string> &metadata,
- std::string alternate_name)
+ std::string alternate_name, FSCrypt_Options fscrypt_options)
{
ldout(cct, 8) << "_mkdir(" << wdr << ", 0o" << std::oct << mode << std::dec
<< ", uid " << perm.uid()
req->dentry_drop = CEPH_CAP_FILE_SHARED;
req->dentry_unless = CEPH_CAP_FILE_EXCL;
req->set_alternate_name(alternate_name.empty() ? wdr.alternate_name : alternate_name);
- wdr.diri->gen_inherited_fscrypt_auth(&req->fscrypt_auth);
+ if (fscrypt_options.fscrypt_auth.size())
+ req->fscrypt_auth = fscrypt_options.fscrypt_auth;
+ else
+ wdr.diri->gen_inherited_fscrypt_auth(&req->fscrypt_auth);
+
+ if (fscrypt_options.fscrypt_file.size())
+ req->fscrypt_file = fscrypt_options.fscrypt_file;
mode |= S_IFDIR;
bufferlist bl;
}
int Client::_symlink(Inode *dir, const char *name, const char *target,
- const UserPerm& perms, std::string alternate_name, InodeRef *inp)
+ const UserPerm& perms, std::string alternate_name, InodeRef *inp,
+ FSCrypt_Options fscrypt_options)
{
ldout(cct, 8) << "_symlink(" << dir->ino << " " << name << ", " << target
<< ", uid " << perms.uid() << ", gid " << perms.gid() << ")"
MetaRequest *req = new MetaRequest(CEPH_MDS_OP_SYMLINK);
- wdr.diri->gen_inherited_fscrypt_auth(&req->fscrypt_auth);
+ if (fscrypt_options.fscrypt_auth.size())
+ req->fscrypt_auth = fscrypt_options.fscrypt_auth;
+ else
+ wdr.diri->gen_inherited_fscrypt_auth(&req->fscrypt_auth);
+
+ if (fscrypt_options.fscrypt_file.size())
+ req->fscrypt_file = fscrypt_options.fscrypt_file;
+
auto fscrypt_ctx = fscrypt->init_ctx(req->fscrypt_auth);
- if (fscrypt_ctx) {
+ if (fscrypt_ctx && cct->_conf.get_val<bool>("client_fscrypt_as")) {
auto fscrypt_denc = fscrypt->get_fname_denc(fscrypt_ctx, nullptr, true);
string enc_target;
}
int Client::fcopyfile(const char *spath, const char *dpath, UserPerm& perms, mode_t mode) {
- return 0;
+ ldout(cct, 10) << "fcopyfile spath=" << spath << " dpath=" << dpath << " mode=" << mode << dendl;
+
+ walk_dentry_result wdrsrc;
+ {
+ std::scoped_lock lock(client_lock);
+ if (int rc = path_walk(cwd, spath, &wdrsrc, perms, {.followsym = false}); rc < 0) {
+ return rc;
+ }
+ }
+
+ auto& srcin = wdrsrc.target;
+ std::string alt_name = wdrsrc.alternate_name;
+
+ FSCrypt_Options foptions;
+ foptions.fscrypt_auth = srcin->fscrypt_auth;
+ foptions.fscrypt_file = srcin->fscrypt_file;
+
+ if (srcin->is_symlink()){
+ char linkpath[4096];
+
+ int link_size = readlink(spath, linkpath, 4096, perms);
+ linkpath[link_size] = '\0';
+
+ int r = do_symlinkat(linkpath, CEPHFS_AT_FDCWD, dpath, perms, alt_name, foptions);
+ if (r < 0) {
+ ldout(cct, 10) << "fcopyfile could not create symlink=" << dpath << " r=" << r << dendl;
+ return r;
+ }
+ } else if(srcin->is_dir()) {
+ int r = do_mkdirat(CEPHFS_AT_FDCWD, dpath, mode, perms, alt_name, foptions);
+ if (r < 0) {
+ ldout(cct, 10) << "fcopyfile could not create dest dir=" << dpath << " r=" << r << dendl;
+ return r;
+ }
+ } else if(srcin->is_file()) {
+ int r = 0;
+ size_t size = srcin->size;
+
+ int dest = do_openat(CEPHFS_AT_FDCWD, dpath, O_CREAT | O_TRUNC | O_WRONLY, perms, mode, 0,0,0, NULL, alt_name, foptions);
+ if (dest < 0) {
+ ldout(cct, 10) << "fcopyfile could not open dest file=" << dpath << " ret=" << dest << dendl;
+ return dest;
+ }
+
+ bool need_read = true;
+ if (size == 0)
+ need_read = false;
+
+ int src;
+ if (need_read) {
+ src = open(spath, O_RDONLY, perms, mode);
+ if (src < 0) {
+ ldout(cct, 10) << "fcopyfile could not open source file=" << spath << " ret=" << src << dendl;
+ close(dest);
+ return src;
+ }
+
+ char in_buf[1048576];
+ size_t off = 0;
+ size_t len = sizeof(in_buf) / sizeof(in_buf[0]);
+
+ len = std::min(size, len);
+
+ while (true) {
+ // include fstat here to reverify size (statx)
+ r = read(src, in_buf, len, off);
+ if (r < 0) {
+ ldout(cct, 10) << "fcopyfile: error reading copy data, r=" << r << dendl;
+ goto out;
+ }
+
+ r = write(dest, in_buf, len, off);
+ if (r < 0) {
+ ldout(cct, 10) << "fcopyfile: error writing copy data, r=" << r << dendl;
+ goto out;
+ }
+ off = off + len;
+
+ if (off == size)
+ break;
+ }
+ }
+ out:
+ close(dest);
+ if (need_read)
+ close(src);
+ return r;
+ }
+ return 0;
}
StandaloneClient::StandaloneClient(Messenger *m, MonClient *mc,
protected:
+ struct FSCrypt_Options {
+ std::vector<uint8_t> fscrypt_auth;
+ std::vector<uint8_t> fscrypt_file;
+ };
+
struct walk_dentry_result {
DentryRef dn;
InodeRef target;
int create_and_open(int dirfd, const char *relpath, int flags, const UserPerm& perms,
mode_t mode, int stripe_unit, int stripe_count, int object_size,
- const char *data_pool, std::string alternate_name);
+ const char *data_pool, std::string alternate_name,
+ FSCrypt_Options fscrypt_options={});
- int do_mkdirat(int dirfd, const char *relpath, mode_t mode, const UserPerm& perm, std::string alternate_name="");
+ int do_mkdirat(int dirfd, const char *relpath, mode_t mode, const UserPerm& perm, std::string alternate_name="", FSCrypt_Options fscrypt_options={});
int do_rename(const char *from, const char *to, const UserPerm& perm, std::string alternate_name="");
int do_link(const char *existing, const char *newname, const UserPerm& perm, std::string alternate_name="");
- int do_symlinkat(const char *target, int dirfd, const char *linkpath, const UserPerm& perms, std::string alternate_name="");
- int do_openat(int dirfd, const char *path, int flags, const UserPerm& perms, mode_t mode, int stripe_unit, int stripe_count, int object_size, const char *data_pool, std::string alternate_name="");
+ int do_symlinkat(const char *target, int dirfd, const char *linkpath, const UserPerm& perms, std::string alternate_name="", FSCrypt_Options fscrypt_options={});
+ int do_openat(int dirfd, const char *path, int flags, const UserPerm& perms, mode_t mode, int stripe_unit, int stripe_count, int object_size, const char *data_pool, std::string alternate_name="", FSCrypt_Options fscrypt_options={});
struct PathWalk_ExtraOptions {
bool followsym = true;
bool is_rename = false;
bool require_target = true;
};
+
int path_walk(InodeRef dirinode, const filepath& fp, struct walk_dentry_result* result, const UserPerm& perms, const PathWalk_ExtraOptions& extra_options);
int path_walk(InodeRef dirinode, const filepath& fp, InodeRef *end, const UserPerm& perms, const PathWalk_ExtraOptions& extra_options);
int _rename(Inode *olddir, const char *oname, Inode *ndir, const char *nname, const UserPerm& perm, std::string alternate_name);
int _mkdir(const walk_dentry_result& wdr, mode_t mode, const UserPerm& perm,
InodeRef *inp = 0, const std::map<std::string, std::string> &metadata={},
- std::string alternate_name="");
+ std::string alternate_name="", FSCrypt_Options={});
int _rmdir(Inode *dir, const char *name, const UserPerm& perms, bool check_perms=true);
int _symlink(Inode *dir, const char *name, const char *target,
- const UserPerm& perms, std::string alternate_name, InodeRef *inp = 0);
+ const UserPerm& perms, std::string alternate_name, InodeRef *inp = 0, FSCrypt_Options fscrypt_options = {});
int _mknod(Inode *dir, const char *name, mode_t mode, dev_t rdev,
const UserPerm& perms, InodeRef *inp = 0);
bool make_absolute_path_string(const InodeRef& in, std::string& path);
int _create(const walk_dentry_result& wdr, int flags, mode_t mode, InodeRef *inp,
Fh **fhp, int stripe_unit, int stripe_count, int object_size,
const char *data_pool, bool *created, const UserPerm &perms,
- std::string alternate_name);
+ std::string alternate_name, FSCrypt_Options fscrypt_options={});
loff_t _lseek(Fh *fh, loff_t offset, int whence);
int64_t _read(Fh *fh, int64_t offset, uint64_t size, bufferlist *bl,