uint32_t flags);
+/* XXX (get|set)attr mask bits */
+#define RGW_SETATTR_MODE 1
+#define RGW_SETATTR_UID 2
+#define RGW_SETATTR_GID 4
+#define RGW_SETATTR_MTIME 8
+#define RGW_SETATTR_ATIME 16
+#define RGW_SETATTR_SIZE 32
+#define RGW_SETATTR_CTIME 64
+
/*
create file
*/
#define RGW_CREATE_FLAG_NONE 0x0000
-int rgw_create(struct rgw_fs *rgw_fs,
- struct rgw_file_handle *parent_fh,
- const char *name, mode_t mode, struct stat *st,
- struct rgw_file_handle **fh, uint32_t flags);
+int rgw_create(struct rgw_fs *rgw_fs, struct rgw_file_handle *parent_fh,
+ const char *name, struct stat *st, uint32_t mask,
+ struct rgw_file_handle **fh, uint32_t flags);
/*
create a new directory
int rgw_mkdir(struct rgw_fs *rgw_fs,
struct rgw_file_handle *parent_fh,
- const char *name, mode_t mode, struct stat *st,
+ const char *name, struct stat *st, uint32_t mask,
struct rgw_file_handle **fh, uint32_t flags);
/*
rgw_readdir_cb rcb, void *cb_arg, bool *eof,
uint32_t flags);
-/* XXX (get|set)attr mask bits */
-#define RGW_SETATTR_MODE 1
-#define RGW_SETATTR_UID 2
-#define RGW_SETATTR_GID 4
-#define RGW_SETATTR_MTIME 8
-#define RGW_SETATTR_ATIME 16
-#define RGW_SETATTR_SIZE 32
-#define RGW_SETATTR_CTIME 64
-
/*
get unix attributes for object
*/
return rc;
} /* RGWLibFS::rename */
+ MkObjResult RGWLibFS::mkdir(RGWFileHandle* parent, const char *name,
+ struct stat *st, uint32_t mask, uint32_t flags)
+ {
+ MkObjResult mkr{nullptr, -EINVAL};
+ int rc, rc2;
+
+ LookupFHResult fhr;
+ RGWFileHandle* rgw_fh = nullptr;
+
+ if (parent->is_root()) {
+ /* bucket */
+ string bname{name};
+ /* enforce S3 name restrictions */
+ rc = valid_s3_bucket_name(bname, false /* relaxed */);
+ if (rc != 0) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ string uri = "/" + bname; /* XXX get rid of URI some day soon */
+ RGWCreateBucketRequest req(get_context(), get_user(), uri);
+ rc = rgwlib.get_fe()->execute_req(&req);
+ rc2 = req.get_ret();
+ } else {
+ /* create an object representing the directory */
+ buffer::list bl;
+ string dir_name = /* XXX get rid of this some day soon, too */
+ parent->relative_object_name();
+ /* creating objects w/leading '/' makes a mess */
+ if ((dir_name.size() > 0) &&
+ (dir_name.back() != '/'))
+ dir_name += "/";
+ dir_name += name;
+ dir_name += "/";
+ RGWPutObjRequest req(get_context(), get_user(), parent->bucket_name(),
+ dir_name, bl);
+ rc = rgwlib.get_fe()->execute_req(&req);
+ rc2 = req.get_ret();
+ }
+
+ if ((rc == 0) &&
+ (rc2 == 0)) {
+ fhr = lookup_fh(parent, name,
+ RGWFileHandle::FLAG_CREATE|
+ RGWFileHandle::FLAG_DIRECTORY);
+ rgw_fh = get<0>(fhr);
+ if (rgw_fh) {
+ /* XXX unify timestamps */
+ rgw_fh->create_stat(st, mask);
+ rgw_fh->set_times(real_clock::now());
+ rgw_fh->stat(st);
+ get<0>(mkr) = rgw_fh;
+ } else
+ rc = -EIO;
+ }
+
+ out:
+ get<1>(mkr) = rc;
+
+ return mkr;
+ } /* RGWLibFS::mkdir */
+
+ MkObjResult RGWLibFS::create(RGWFileHandle* parent, const char *name,
+ struct stat *st, uint32_t mask, uint32_t flags)
+ {
+ int rc, rc2;
+
+ using std::get;
+
+ rgw_file_handle *lfh;
+ rc = rgw_lookup(get_fs(), parent->get_fh(), name, &lfh,
+ RGW_LOOKUP_FLAG_NONE);
+ if (! rc) {
+ /* conflict! */
+ rc = rgw_fh_rele(get_fs(), lfh, RGW_FH_RELE_FLAG_NONE);
+ return MkObjResult{nullptr, -EEXIST};
+ }
+
+ /* expand and check name */
+ std::string obj_name{parent->relative_object_name()};
+ if ((obj_name.size() > 0) &&
+ (obj_name.back() != '/'))
+ obj_name += "/";
+ obj_name += name;
+ if (! valid_s3_object_name(obj_name)) {
+ return MkObjResult{nullptr, -EINVAL};
+ }
+
+ /* create it */
+ buffer::list bl;
+ RGWPutObjRequest req(cct, get_user(), parent->bucket_name(), obj_name, bl);
+ MkObjResult mkr{nullptr, -EINVAL};
+
+ rc = rgwlib.get_fe()->execute_req(&req);
+ rc2 = req.get_ret();
+
+ if ((rc == 0) &&
+ (rc2 == 0)) {
+ /* XXX atomicity */
+ LookupFHResult fhr = lookup_fh(parent, name, RGWFileHandle::FLAG_CREATE);
+ RGWFileHandle* rgw_fh = get<0>(fhr);
+ if (rgw_fh) {
+ if (get<1>(fhr) & RGWFileHandle::FLAG_CREATE) {
+ /* fill in stat data */
+ rgw_fh->create_stat(st, mask);
+ rgw_fh->set_times(real_clock::now());
+ rgw_fh->open_for_create(); // XXX needed?
+ }
+ (void) rgw_fh->stat(st);
+ get<0>(mkr) = rgw_fh;
+ } else
+ rc = -EIO;
+ }
+
+ get<1>(mkr) = rc;
+
+ return mkr;
+ } /* RGWLibFS::create */
+
int RGWLibFS::getattr(RGWFileHandle* rgw_fh, struct stat* st)
{
switch(rgw_fh->fh.fh_type) {
generic create -- create an empty regular file
*/
int rgw_create(struct rgw_fs *rgw_fs,
- struct rgw_file_handle *parent_fh,
- const char *name, mode_t mode, struct stat *st,
- struct rgw_file_handle **fh, uint32_t flags)
+ struct rgw_file_handle *parent_fh,
+ const char *name, struct stat *st, uint32_t mask,
+ struct rgw_file_handle **fh, uint32_t flags)
{
- RGWLibFS *fs = static_cast<RGWLibFS*>(rgw_fs->fs_private);
- CephContext* cct = static_cast<CephContext*>(rgw_fs->rgw);
+ using std::get;
+ RGWLibFS *fs = static_cast<RGWLibFS*>(rgw_fs->fs_private);
RGWFileHandle* parent = get_rgwfh(parent_fh);
+
if ((! parent) ||
(parent->is_root()) ||
(parent->is_file())) {
return -EINVAL;
}
- using std::get;
+ MkObjResult fhr = fs->create(parent, name, st, mask, flags);
+ RGWFileHandle *nfh = get<0>(fhr); // nullptr if !success
- rgw_file_handle *lfh;
- int rc = rgw_lookup(rgw_fs, parent_fh, name, &lfh,
- RGW_LOOKUP_FLAG_NONE);
- if (! rc) {
- /* conflict! */
- rc = rgw_fh_rele(rgw_fs, lfh, RGW_FH_RELE_FLAG_NONE);
- return -EEXIST;
- } else {
- /* expand and check name */
- std::string obj_name{parent->relative_object_name()};
- if ((obj_name.size() > 0) &&
- (obj_name.back() != '/'))
- obj_name += "/";
- obj_name += name;
- if (! valid_s3_object_name(obj_name)) {
- return -EINVAL;
- } else {
- /* create it */
- buffer::list bl;
- RGWPutObjRequest req(cct, fs->get_user(), parent->bucket_name(),
- obj_name, bl);
- rc = rgwlib.get_fe()->execute_req(&req);
- int rc2 = req.get_ret();
-
- if ((rc == 0) &&
- (rc2 == 0)) {
- /* XXX atomicity */
- LookupFHResult fhr = fs->lookup_fh(parent, name,
- RGWFileHandle::FLAG_CREATE);
- RGWFileHandle* rgw_fh = get<0>(fhr);
- if (rgw_fh) {
- if (get<1>(fhr) & RGWFileHandle::FLAG_CREATE) {
- /* fill in stat data */
- rgw_fh->set_times(real_clock::now());
- rgw_fh->open_for_create(); // XXX needed?
- }
- (void) rgw_fh->stat(st);
- struct rgw_file_handle *rfh = rgw_fh->get_fh();
- *fh = rfh;
- } else
- rc = -EIO;
- }
- }
- }
+ if (nfh)
+ *fh = nfh->get_fh();
- return rc;
-}
+ return get<1>(fhr);
+} /* rgw_create */
/*
create a new directory
*/
int rgw_mkdir(struct rgw_fs *rgw_fs,
struct rgw_file_handle *parent_fh,
- const char *name, mode_t mode, struct stat *st,
+ const char *name, struct stat *st, uint32_t mask,
struct rgw_file_handle **fh, uint32_t flags)
{
- int rc, rc2;
+ using std::get;
RGWLibFS *fs = static_cast<RGWLibFS*>(rgw_fs->fs_private);
- CephContext* cct = static_cast<CephContext*>(rgw_fs->rgw);
-
RGWFileHandle* parent = get_rgwfh(parent_fh);
+
if (! parent) {
/* bad parent */
return -EINVAL;
}
- LookupFHResult fhr;
- RGWFileHandle* rgw_fh = nullptr;
+ MkObjResult fhr = fs->mkdir(parent, name, st, mask, flags);
+ RGWFileHandle *nfh = get<0>(fhr); // nullptr if !success
- if (parent->is_root()) {
- /* bucket */
- string bname{name};
- /* enforce S3 name restrictions */
- rc = valid_s3_bucket_name(bname, false /* relaxed */);
- if (rc != 0)
- return -EINVAL;
- string uri = "/" + bname; /* XXX get rid of URI some day soon */
- RGWCreateBucketRequest req(cct, fs->get_user(), uri);
- rc = rgwlib.get_fe()->execute_req(&req);
- rc2 = req.get_ret();
- } else {
- /* create an object representing the directory */
- buffer::list bl;
- string dir_name = /* XXX get rid of this some day soon, too */
- parent->relative_object_name();
- /* creating objects w/leading '/' makes a mess */
- if ((dir_name.size() > 0) &&
- (dir_name.back() != '/'))
- dir_name += "/";
- dir_name += name;
- dir_name += "/";
- RGWPutObjRequest req(cct, fs->get_user(), parent->bucket_name(),
- dir_name, bl);
- rc = rgwlib.get_fe()->execute_req(&req);
- rc2 = req.get_ret();
- }
-
- if ((rc == 0) &&
- (rc2 == 0)) {
- fhr = fs->lookup_fh(parent, name,
- RGWFileHandle::FLAG_CREATE|
- RGWFileHandle::FLAG_DIRECTORY);
- rgw_fh = get<0>(fhr);
- if (rgw_fh) {
- /* XXX unify timestamps */
- rgw_fh->set_times(real_clock::now());
- rgw_fh->stat(st);
- struct rgw_file_handle *rfh = rgw_fh->get_fh();
- *fh = rfh;
- } else
- rc = -EIO;
- }
+ if (nfh)
+ *fh = nfh->get_fh();
- return rc;
-}
+ return get<1>(fhr);
+} /* rgw_mkdir */
/*
rename object
if (! rgw_fh->is_open())
return -EPERM;
- std::cout << __func__ << " before write of "
- << length << " bytes at offset " << offset
- << std::endl;
-
rc = rgw_fh->write(offset, length, bytes_written, buffer);
- std::cout << __func__ << " after write of "
- << length << " bytes at offset " << offset
- << " wrote " << *bytes_written
- << " rc " << rc
- << std::endl;
-
return rc;
}
uint64_t dev;
size_t size;
uint64_t nlink;
+ uint32_t owner_uid; /* XXX need Unix attr */
+ uint32_t owner_gid; /* XXX need Unix attr */
+ mode_t unix_mode;
struct timespec ctime;
struct timespec mtime;
struct timespec atime;
- state() : dev(0), size(0), nlink(1), ctime{0,0}, mtime{0,0}, atime{0,0} {}
+ state() : dev(0), size(0), nlink(1), owner_uid(0), owner_gid(0),
+ ctime{0,0}, mtime{0,0}, atime{0,0} {}
} state;
struct file {
variant_type = directory();
/* stat */
state.dev = fs_inst;
+ state.unix_mode = RGW_RWXMODE|S_IFDIR;
/* pointer to self */
fh.fh_private = this;
}
-
+
void init_rootfs(std::string& fsid, const std::string& object_name) {
/* fh_key */
fh.fh_hk.bucket = XXH64(fsid.c_str(), fsid.length(), fh_key::seed);
/* save constant fhk */
fh.fh_hk = fhk.fh_hk; /* XXX redundant in fh_hk */
+ /* stat */
+ state.dev = fs_inst;
+
+ switch (fh.fh_type) {
+ case RGW_FS_TYPE_DIRECTORY:
+ state.unix_mode = RGW_RWXMODE|S_IFDIR;
+ break;
+ case RGW_FS_TYPE_FILE:
+ state.unix_mode = RGW_RWMODE|S_IFREG;
+ default:
+ break;
+ }
+
/* pointer to self */
fh.fh_private = this;
}
RGWFileHandle* get_parent() { return parent; }
+ uint32_t get_owner_uid() const { return state.owner_uid; }
+ uint32_t get_owner_gid() const { return state.owner_gid; }
+
struct timespec get_mtime() const { return state.mtime; }
- int stat(struct stat *st) {
+ void create_stat(struct stat* st, uint32_t mask) {
+ if (mask & RGW_SETATTR_UID)
+ state.owner_uid = st->st_uid;
+
+ if (mask & RGW_SETATTR_GID)
+ state.owner_gid = st->st_gid;
+
+ if (mask & RGW_SETATTR_MODE) {
+ switch (fh.fh_type) {
+ case RGW_FS_TYPE_DIRECTORY:
+ st->st_mode = state.unix_mode|S_IFDIR;
+ break;
+ case RGW_FS_TYPE_FILE:
+ st->st_mode = state.unix_mode|S_IFREG;
+ default:
+ break;
+ }
+ }
+ }
+
+ int stat(struct stat* st) {
/* partial Unix attrs */
memset(st, 0, sizeof(struct stat));
st->st_dev = state.dev;
st->st_ino = fh.fh_hk.object; // XXX
- st->st_uid = 0; // XXX
- st->st_gid = 0; // XXX
+ st->st_uid = state.owner_uid;
+ st->st_gid = state.owner_gid;
+
+ st->st_mode = state.unix_mode;
st->st_atim = state.atime;
st->st_mtim = state.mtime;
}
typedef std::tuple<RGWFileHandle*, uint32_t> LookupFHResult;
+ typedef std::tuple<RGWFileHandle*, int> MkObjResult;
class RGWLibFS
{
int rename(RGWFileHandle* old_fh, RGWFileHandle* new_fh,
const char *old_name, const char *new_name);
+ MkObjResult create(RGWFileHandle* parent, const char *name, struct stat *st,
+ uint32_t mask, uint32_t flags);
+
+ MkObjResult mkdir(RGWFileHandle* parent, const char *name, struct stat *st,
+ uint32_t mask, uint32_t flags);
+
int unlink(RGWFileHandle* parent, const char *name);
/* find existing RGWFileHandle */
string secret_key("");
struct rgw_fs *fs = nullptr;
+ uint32_t owner_uid = 867;
+ uint32_t owner_gid = 5309;
+ uint32_t create_mask = RGW_SETATTR_UID | RGW_SETATTR_GID | RGW_SETATTR_MODE;
+
bool do_create = false;
bool do_delete = false;
bool do_verify = false;
if (do_create) {
struct stat st;
struct rgw_file_handle *fh;
- int ret = rgw_mkdir(fs, fs->root_fh, bucket_name.c_str(), 755, &st, &fh,
- RGW_MKDIR_FLAG_NONE);
+
+ st.st_uid = owner_uid;
+ st.st_gid = owner_gid;
+ st.st_mode = 755;
+
+ int ret = rgw_mkdir(fs, fs->root_fh, bucket_name.c_str(), &st, create_mask,
+ &fh, RGW_MKDIR_FLAG_NONE);
ASSERT_EQ(ret, 0);
}
}
string secret_key("");
struct rgw_fs *fs = nullptr;
+ uint32_t owner_uid = 867;
+ uint32_t owner_gid = 5309;
+ uint32_t create_mask = RGW_SETATTR_UID | RGW_SETATTR_GID | RGW_SETATTR_MODE;
+
bool do_create = false;
bool do_delete = false;
bool do_multi = false;
if (do_create) {
struct stat st;
struct rgw_file_handle *fh;
- int ret = rgw_mkdir(fs, fs->root_fh, bucket_name.c_str(), 755, &st, &fh,
- RGW_MKDIR_FLAG_NONE);
+
+ st.st_uid = owner_uid;
+ st.st_gid = owner_gid;
+ st.st_mode = 755;
+
+ int ret = rgw_mkdir(fs, fs->root_fh, bucket_name.c_str(), &st, create_mask,
+ &fh, RGW_MKDIR_FLAG_NONE);
ASSERT_EQ(ret, 0);
}
}
int ret;
struct stat st;
struct rgw_file_handle *fh;
+
+ st.st_uid = owner_uid;
+ st.st_gid = owner_gid;
+ st.st_mode = 755;
+
for (int ix = 0; ix < multi_cnt; ++ix) {
string bn = bucket_name;
bn += to_string(ix);
- ret = rgw_mkdir(fs, fs->root_fh, bn.c_str(), 755, &st, &fh,
+ ret = rgw_mkdir(fs, fs->root_fh, bn.c_str(), &st, create_mask, &fh,
RGW_MKDIR_FLAG_NONE);
ASSERT_EQ(ret, 0);
std::cout << "created: " << bn << std::endl;
struct rgw_fs *fs = nullptr;
CephContext* cct = nullptr;
+ uint32_t owner_uid = 867;
+ uint32_t owner_gid = 5309;
+ uint32_t create_mask = RGW_SETATTR_UID | RGW_SETATTR_GID | RGW_SETATTR_MODE;
+
string bucket_name("nfsroot");
string dirs1_bucket_name("bdirs1");
string readf_name("toyland");
if (! bucket_fh) {
if (do_create) {
struct stat st;
- int rc = rgw_mkdir(fs, fs->root_fh, bucket_name.c_str(), 755, &st,
- &bucket_fh, RGW_MKDIR_FLAG_NONE);
+
+ st.st_uid = owner_uid;
+ st.st_gid = owner_gid;
+ st.st_mode = 755;
+
+ int rc = rgw_mkdir(fs, fs->root_fh, bucket_name.c_str(), &st,
+ create_mask, &bucket_fh, RGW_MKDIR_FLAG_NONE);
ASSERT_EQ(rc, 0);
}
}
int rc;
struct stat st;
+ st.st_uid = owner_uid;
+ st.st_gid = owner_gid;
+ st.st_mode = 755;
+
dirs1_b.parent_fh = fs->root_fh;
(void) rgw_lookup(fs, dirs1_b.parent_fh, dirs1_bucket_name.c_str(),
if (! dirs1_b.fh) {
if (do_create) {
- rc = rgw_mkdir(fs, dirs1_b.parent_fh, dirs1_b.name.c_str(), 755, &st,
- &dirs1_b.fh, RGW_MKDIR_FLAG_NONE);
+ rc = rgw_mkdir(fs, dirs1_b.parent_fh, dirs1_b.name.c_str(), &st,
+ create_mask, &dirs1_b.fh, RGW_MKDIR_FLAG_NONE);
ASSERT_EQ(rc, 0);
}
}
RGW_LOOKUP_FLAG_NONE);
if (! dir.fh) {
if (do_create) {
- rc = rgw_mkdir(fs, dir.parent_fh, dir.name.c_str(), 755, &st,
+ rc = rgw_mkdir(fs, dir.parent_fh, dir.name.c_str(), &st, create_mask,
&dir.fh, RGW_MKDIR_FLAG_NONE);
ASSERT_EQ(rc, 0);
}
if (! sdir.fh) {
if (do_create) {
- rc = rgw_mkdir(fs, sdir.parent_fh, sdir.name.c_str(), 755,
- &st, &sdir.fh, RGW_MKDIR_FLAG_NONE);
+ rc = rgw_mkdir(fs, sdir.parent_fh, sdir.name.c_str(), &st,
+ create_mask, &sdir.fh, RGW_MKDIR_FLAG_NONE);
ASSERT_EQ(rc, 0);
}
}
if (do_create) {
int rc;
struct stat st;
+
+ st.st_uid = owner_uid;
+ st.st_gid = owner_gid;
+ st.st_mode = 644;
+
for (auto& dirs_rec : dirs_vec) {
/* create 1 more file in each sdir */
obj_rec& dir = get<0>(dirs_rec);
(void) rgw_lookup(fs, sf.parent_fh, sf.name.c_str(), &sf.fh,
RGW_LOOKUP_FLAG_NONE);
if (! sf.fh) {
- rc = rgw_create(fs, sf.parent_fh, sf.name.c_str(), 644, &st, &sf.fh,
- RGW_CREATE_FLAG_NONE);
+ rc = rgw_create(fs, sf.parent_fh, sf.name.c_str(), &st, create_mask,
+ &sf.fh, RGW_CREATE_FLAG_NONE);
ASSERT_EQ(rc, 0);
}
sf.sync();
int rc;
struct stat st;
obj_vec ovec;
+
+ st.st_uid = owner_uid;
+ st.st_gid = owner_gid;
+ st.st_mode = 755;
+
for (int b_ix : {0, 1}) {
std::string bname{"brename_" + to_string(b_ix)};
obj_rec brec{bname, nullptr, nullptr, nullptr};
if (! brec.fh) {
if (do_create) {
struct stat st;
- int rc = rgw_mkdir(fs, fs->root_fh, brec.name.c_str(), 755, &st,
- &brec.fh, RGW_MKDIR_FLAG_NONE);
+ int rc = rgw_mkdir(fs, fs->root_fh, brec.name.c_str(), &st,
+ create_mask, &brec.fh, RGW_MKDIR_FLAG_NONE);
ASSERT_EQ(rc, 0);
}
}
ASSERT_NE(brec.fh, nullptr);
brec.sync();
+
+ st.st_mode = 644; /* file mask */
+
for (int f_ix : {0, 1}) {
std::string rfname{"rfile_"};
rfname += to_string(f_ix);
(void) rgw_lookup(fs, rf.parent_fh, rf.name.c_str(), &rf.fh,
RGW_LOOKUP_FLAG_NONE);
if (! rf.fh) {
- rc = rgw_create(fs, rf.parent_fh, rf.name.c_str(), 644, &st, &rf.fh,
- RGW_CREATE_FLAG_NONE);
+ rc = rgw_create(fs, rf.parent_fh, rf.name.c_str(), &st, create_mask,
+ &rf.fh, RGW_CREATE_FLAG_NONE);
ASSERT_EQ(rc, 0);
}
rf.sync();
struct stat st;
int ret;
+ st.st_uid = owner_uid;
+ st.st_gid = owner_gid;
+ st.st_mode = 755;
+
if (do_create) {
- ret = rgw_mkdir(fs, bucket_fh, marker_dir.c_str(), 755, &st, &marker_fh,
- RGW_MKDIR_FLAG_NONE);
+ ret = rgw_mkdir(fs, bucket_fh, marker_dir.c_str(), &st, create_mask,
+ &marker_fh, RGW_MKDIR_FLAG_NONE);
} else {
ret = rgw_lookup(fs, bucket_fh, marker_dir.c_str(), &marker_fh,
RGW_LOOKUP_FLAG_NONE);