Added support for xattr as POSIX ACL (#2039)

This commit is contained in:
Takeshi Nakatani 2022-10-22 21:48:02 +09:00 committed by GitHub
parent 4a813aec42
commit 2e77920943
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 456 additions and 38 deletions

View File

@ -123,15 +123,20 @@ static int list_bucket(const char* path, S3ObjList& head, const char* delimiter,
static int directory_empty(const char* path);
static int rename_large_object(const char* from, const char* to);
static int create_file_object(const char* path, mode_t mode, uid_t uid, gid_t gid);
static int create_directory_object(const char* path, mode_t mode, const struct timespec& ts_atime, const struct timespec& ts_mtime, const struct timespec& ts_ctime, uid_t uid, gid_t gid);
static int create_directory_object(const char* path, mode_t mode, const struct timespec& ts_atime, const struct timespec& ts_mtime, const struct timespec& ts_ctime, uid_t uid, gid_t gid, const char* pxattrvalue);
static int rename_object(const char* from, const char* to, bool update_ctime);
static int rename_object_nocopy(const char* from, const char* to, bool update_ctime);
static int clone_directory_object(const char* from, const char* to, bool update_ctime);
static int clone_directory_object(const char* from, const char* to, bool update_ctime, const char* pxattrvalue);
static int rename_directory(const char* from, const char* to);
static int remote_mountpath_exists(const char* path);
static bool get_meta_xattr_value(const char* path, std::string& rawvalue);
static bool get_parent_meta_xattr_value(const char* path, std::string& rawvalue);
static bool get_xattr_posix_key_value(const char* path, std::string& xattrvalue, bool default_key);
static bool build_inherited_xattr_value(const char* path, std::string& xattrvalue);
static void free_xattrs(xattrs_t& xattrs);
static bool parse_xattr_keyval(const std::string& xattrpair, std::string& key, PXATTRVAL& pval);
static size_t parse_xattrs(const std::string& strxattrs, xattrs_t& xattrs);
static std::string raw_build_xattrs(const xattrs_t& xattrs);
static std::string build_xattrs(const xattrs_t& xattrs);
static int s3fs_check_service();
static bool set_mountpoint_attribute(struct stat& mpst);
@ -1029,6 +1034,12 @@ static int s3fs_create(const char* _path, mode_t mode, struct fuse_file_info* fi
meta["x-amz-meta-mtime"] = strnow;
meta["x-amz-meta-ctime"] = strnow;
std::string xattrvalue;
if(build_inherited_xattr_value(path, xattrvalue)){
S3FS_PRN_DBG("Set xattrs = %s", urlDecode(xattrvalue).c_str());
meta["x-amz-meta-xattr"] = xattrvalue;
}
// [NOTE] set no_truncate flag
// At this point, the file has not been created(uploaded) and
// the data is only present in the Stats cache.
@ -1055,7 +1066,7 @@ static int s3fs_create(const char* _path, mode_t mode, struct fuse_file_info* fi
return 0;
}
static int create_directory_object(const char* path, mode_t mode, const struct timespec& ts_atime, const struct timespec& ts_mtime, const struct timespec& ts_ctime, uid_t uid, gid_t gid)
static int create_directory_object(const char* path, mode_t mode, const struct timespec& ts_atime, const struct timespec& ts_mtime, const struct timespec& ts_ctime, uid_t uid, gid_t gid, const char* pxattrvalue)
{
S3FS_PRN_INFO1("[path=%s][mode=%04o][atime=%s][mtime=%s][ctime=%s][uid=%u][gid=%u]", path, mode, str(ts_atime).c_str(), str(ts_mtime).c_str(), str(ts_ctime).c_str(), (unsigned int)uid, (unsigned int)gid);
@ -1077,6 +1088,11 @@ static int create_directory_object(const char* path, mode_t mode, const struct t
meta["x-amz-meta-mtime"] = str(ts_mtime);
meta["x-amz-meta-ctime"] = str(ts_ctime);
if(pxattrvalue){
S3FS_PRN_DBG("Set xattrs = %s", urlDecode(std::string(pxattrvalue)).c_str());
meta["x-amz-meta-xattr"] = std::string(pxattrvalue);
}
S3fsCurl s3fscurl;
return s3fscurl.PutRequest(tpath.c_str(), meta, -1); // fd=-1 means for creating zero byte object.
}
@ -1104,9 +1120,17 @@ static int s3fs_mkdir(const char* _path, mode_t mode)
return result;
}
std::string xattrvalue;
const char* pxattrvalue;
if(get_parent_meta_xattr_value(path, xattrvalue)){
pxattrvalue = xattrvalue.c_str();
}else{
pxattrvalue = NULL;
}
struct timespec now;
s3fs_realtime(now);
result = create_directory_object(path, mode, now, now, now, pcxt->uid, pcxt->gid);
result = create_directory_object(path, mode, now, now, now, pcxt->uid, pcxt->gid, pxattrvalue);
StatCache::getStatCacheData()->DelStat(path);
S3FS_MALLOCTRIM(0);
@ -1238,6 +1262,9 @@ static int s3fs_symlink(const char* _from, const char* _to)
headers["x-amz-meta-uid"] = str(pcxt->uid);
headers["x-amz-meta-gid"] = str(pcxt->gid);
// [NOTE]
// Symbolic links do not set xattrs.
// open tmpfile
std::string strFrom;
{ // scope for AutoFdEntity
@ -1303,6 +1330,12 @@ static int rename_object(const char* from, const char* to, bool update_ctime)
meta["Content-Type"] = S3fsCurl::LookupMimeType(std::string(to));
meta["x-amz-metadata-directive"] = "REPLACE";
std::string xattrvalue;
if(get_meta_xattr_value(from, xattrvalue)){
S3FS_PRN_DBG("Set xattrs = %s", urlDecode(xattrvalue).c_str());
meta["x-amz-meta-xattr"] = xattrvalue;
}
// [NOTE]
// If it has a cache, open it first and leave it open until rename.
// The cache is renamed after put_header, because it must be open
@ -1444,7 +1477,7 @@ static int rename_large_object(const char* from, const char* to)
return result;
}
static int clone_directory_object(const char* from, const char* to, bool update_ctime)
static int clone_directory_object(const char* from, const char* to, bool update_ctime, const char* pxattrvalue)
{
int result = -1;
struct stat stbuf;
@ -1466,7 +1499,7 @@ static int clone_directory_object(const char* from, const char* to, bool update_
}else{
set_stat_to_timespec(stbuf, ST_TYPE_CTIME, ts_ctime);
}
result = create_directory_object(to, stbuf.st_mode, ts_atime, ts_mtime, ts_ctime, stbuf.st_uid, stbuf.st_gid);
result = create_directory_object(to, stbuf.st_mode, ts_atime, ts_mtime, ts_ctime, stbuf.st_uid, stbuf.st_gid, pxattrvalue);
StatCache::getStatCacheData()->DelStat(to);
@ -1565,11 +1598,19 @@ static int rename_directory(const char* from, const char* to)
// rename directory objects.
for(mn_cur = mn_head; mn_cur; mn_cur = mn_cur->next){
if(mn_cur->is_dir && mn_cur->old_path && '\0' != mn_cur->old_path[0]){
std::string xattrvalue;
const char* pxattrvalue;
if(get_meta_xattr_value(mn_cur->old_path, xattrvalue)){
pxattrvalue = xattrvalue.c_str();
}else{
pxattrvalue = NULL;
}
// [NOTE]
// The ctime is updated only for the top (from) directory.
// Other than that, it will not be updated.
//
if(0 != (result = clone_directory_object(mn_cur->old_path, mn_cur->new_path, (strfrom == mn_cur->old_path)))){
if(0 != (result = clone_directory_object(mn_cur->old_path, mn_cur->new_path, (strfrom == mn_cur->old_path), pxattrvalue))){
S3FS_PRN_ERR("clone_directory_object returned an error(%d)", result);
free_mvnodes(mn_head);
return result;
@ -1708,6 +1749,13 @@ static int s3fs_chmod(const char* _path, mode_t mode)
}
if(S_ISDIR(stbuf.st_mode) && (IS_REPLACEDIR(nDirType) || IS_CREATE_MP_STAT(path))){
std::string xattrvalue;
const char* pxattrvalue;
if(get_meta_xattr_value(path, xattrvalue)){
pxattrvalue = xattrvalue.c_str();
}else{
pxattrvalue = NULL;
}
if(IS_REPLACEDIR(nDirType)){
// Should rebuild directory object(except new type)
// Need to remove old dir("dir" etc) and make new dir("dir/")
@ -1727,7 +1775,7 @@ static int s3fs_chmod(const char* _path, mode_t mode)
set_stat_to_timespec(stbuf, ST_TYPE_MTIME, ts_mtime);
s3fs_realtime(ts_ctime);
if(0 != (result = create_directory_object(newpath.c_str(), mode, ts_atime, ts_mtime, ts_ctime, stbuf.st_uid, stbuf.st_gid))){
if(0 != (result = create_directory_object(newpath.c_str(), mode, ts_atime, ts_mtime, ts_ctime, stbuf.st_uid, stbuf.st_gid, pxattrvalue))){
return result;
}
}else{
@ -1807,6 +1855,14 @@ static int s3fs_chmod_nocopy(const char* _path, mode_t mode)
}
if(S_ISDIR(stbuf.st_mode)){
std::string xattrvalue;
const char* pxattrvalue;
if(get_meta_xattr_value(path, xattrvalue)){
pxattrvalue = xattrvalue.c_str();
}else{
pxattrvalue = NULL;
}
if(IS_REPLACEDIR(nDirType)){
// Should rebuild all directory object
// Need to remove old dir("dir" etc) and make new dir("dir/")
@ -1826,7 +1882,7 @@ static int s3fs_chmod_nocopy(const char* _path, mode_t mode)
set_stat_to_timespec(stbuf, ST_TYPE_MTIME, ts_mtime);
s3fs_realtime(ts_ctime);
if(0 != (result = create_directory_object(newpath.c_str(), mode, ts_atime, ts_mtime, ts_ctime, stbuf.st_uid, stbuf.st_gid))){
if(0 != (result = create_directory_object(newpath.c_str(), mode, ts_atime, ts_mtime, ts_ctime, stbuf.st_uid, stbuf.st_gid, pxattrvalue))){
return result;
}
}else{
@ -1897,6 +1953,14 @@ static int s3fs_chown(const char* _path, uid_t uid, gid_t gid)
}
if(S_ISDIR(stbuf.st_mode) && (IS_REPLACEDIR(nDirType) || IS_CREATE_MP_STAT(path))){
std::string xattrvalue;
const char* pxattrvalue;
if(get_meta_xattr_value(path, xattrvalue)){
pxattrvalue = xattrvalue.c_str();
}else{
pxattrvalue = NULL;
}
if(IS_REPLACEDIR(nDirType)){
// Should rebuild directory object(except new type)
// Need to remove old dir("dir" etc) and make new dir("dir/")
@ -1916,7 +1980,7 @@ static int s3fs_chown(const char* _path, uid_t uid, gid_t gid)
set_stat_to_timespec(stbuf, ST_TYPE_MTIME, ts_mtime);
s3fs_realtime(ts_ctime);
if(0 != (result = create_directory_object(newpath.c_str(), stbuf.st_mode, ts_atime, ts_mtime, ts_ctime, uid, gid))){
if(0 != (result = create_directory_object(newpath.c_str(), stbuf.st_mode, ts_atime, ts_mtime, ts_ctime, uid, gid, pxattrvalue))){
return result;
}
}else{
@ -2003,6 +2067,14 @@ static int s3fs_chown_nocopy(const char* _path, uid_t uid, gid_t gid)
}
if(S_ISDIR(stbuf.st_mode)){
std::string xattrvalue;
const char* pxattrvalue;
if(get_meta_xattr_value(path, xattrvalue)){
pxattrvalue = xattrvalue.c_str();
}else{
pxattrvalue = NULL;
}
if(IS_REPLACEDIR(nDirType)){
// Should rebuild all directory object
// Need to remove old dir("dir" etc) and make new dir("dir/")
@ -2022,7 +2094,7 @@ static int s3fs_chown_nocopy(const char* _path, uid_t uid, gid_t gid)
set_stat_to_timespec(stbuf, ST_TYPE_MTIME, ts_mtime);
s3fs_realtime(ts_ctime);
if(0 != (result = create_directory_object(newpath.c_str(), stbuf.st_mode, ts_atime, ts_mtime, ts_ctime, uid, gid))){
if(0 != (result = create_directory_object(newpath.c_str(), stbuf.st_mode, ts_atime, ts_mtime, ts_ctime, uid, gid, pxattrvalue))){
return result;
}
}else{
@ -2115,6 +2187,14 @@ static int s3fs_utimens(const char* _path, const struct timespec ts[2])
}
if(S_ISDIR(stbuf.st_mode) && (IS_REPLACEDIR(nDirType) || IS_CREATE_MP_STAT(path))){
std::string xattrvalue;
const char* pxattrvalue;
if(get_meta_xattr_value(path, xattrvalue)){
pxattrvalue = xattrvalue.c_str();
}else{
pxattrvalue = NULL;
}
if(IS_REPLACEDIR(nDirType)){
// Should rebuild directory object(except new type)
// Need to remove old dir("dir" etc) and make new dir("dir/")
@ -2127,7 +2207,7 @@ static int s3fs_utimens(const char* _path, const struct timespec ts[2])
StatCache::getStatCacheData()->DelStat(nowcache);
// Make new directory object("dir/")
if(0 != (result = create_directory_object(newpath.c_str(), stbuf.st_mode, atime, mtime, ctime, stbuf.st_uid, stbuf.st_gid))){
if(0 != (result = create_directory_object(newpath.c_str(), stbuf.st_mode, atime, mtime, ctime, stbuf.st_uid, stbuf.st_gid, pxattrvalue))){
return result;
}
}else{
@ -2239,6 +2319,14 @@ static int s3fs_utimens_nocopy(const char* _path, const struct timespec ts[2])
}
if(S_ISDIR(stbuf.st_mode)){
std::string xattrvalue;
const char* pxattrvalue;
if(get_meta_xattr_value(path, xattrvalue)){
pxattrvalue = xattrvalue.c_str();
}else{
pxattrvalue = NULL;
}
if(IS_REPLACEDIR(nDirType)){
// Should rebuild all directory object
// Need to remove old dir("dir" etc) and make new dir("dir/")
@ -2251,7 +2339,7 @@ static int s3fs_utimens_nocopy(const char* _path, const struct timespec ts[2])
StatCache::getStatCacheData()->DelStat(nowcache);
// Make new directory object("dir/")
if(0 != (result = create_directory_object(newpath.c_str(), stbuf.st_mode, atime, mtime, ctime, stbuf.st_uid, stbuf.st_gid))){
if(0 != (result = create_directory_object(newpath.c_str(), stbuf.st_mode, atime, mtime, ctime, stbuf.st_uid, stbuf.st_gid, pxattrvalue))){
return result;
}
}else{
@ -3094,6 +3182,123 @@ static int remote_mountpath_exists(const char* path)
return 0;
}
static bool get_meta_xattr_value(const char* path, std::string& rawvalue)
{
if(!path || '\0' == path[0]){
S3FS_PRN_ERR("path is empty.");
return false;
}
S3FS_PRN_DBG("[path=%s]", path);
rawvalue.erase();
headers_t meta;
if(0 != get_object_attribute(path, NULL, &meta)){
S3FS_PRN_ERR("Failed to get object(%s) headers", path);
return false;
}
headers_t::const_iterator iter;
if(meta.end() == (iter = meta.find("x-amz-meta-xattr"))){
return false;
}
rawvalue = iter->second;
return true;
}
static bool get_parent_meta_xattr_value(const char* path, std::string& rawvalue)
{
if(0 == strcmp(path, "/") || 0 == strcmp(path, ".")){
// path is mount point, thus does not have parent.
return false;
}
std::string parent = mydirname(path);
if(parent.empty()){
S3FS_PRN_ERR("Could not get parent path for %s.", path);
return false;
}
return get_meta_xattr_value(parent.c_str(), rawvalue);
}
static bool get_xattr_posix_key_value(const char* path, std::string& xattrvalue, bool default_key)
{
xattrvalue.erase();
std::string rawvalue;
if(!get_meta_xattr_value(path, rawvalue)){
return false;
}
xattrs_t xattrs;
if(0 == parse_xattrs(rawvalue, xattrs)){
return false;
}
std::string targetkey;
if(default_key){
targetkey = "system.posix_acl_default";
}else{
targetkey = "system.posix_acl_access";
}
xattrs_t::iterator iter;
if(xattrs.end() == (iter = xattrs.find(targetkey)) || !(iter->second)){
free_xattrs(xattrs);
return false;
}
// convert value by base64
char* base64val = s3fs_base64((iter->second)->pvalue, (iter->second)->length);
if(!base64val){
free_xattrs(xattrs);
return false;
}
free_xattrs(xattrs);
xattrvalue = base64val;
delete[] base64val;
return true;
}
// [NOTE]
// Converts and returns the POSIX ACL default(system.posix_acl_default) value of
// the parent directory as a POSIX ACL(system.posix_acl_access) value.
// Returns false if the parent directory has no POSIX ACL defaults.
//
static bool build_inherited_xattr_value(const char* path, std::string& xattrvalue)
{
S3FS_PRN_DBG("[path=%s]", path);
xattrvalue.erase();
if(0 == strcmp(path, "/") || 0 == strcmp(path, ".")){
// path is mount point, thus does not have parent.
return false;
}
std::string parent = mydirname(path);
if(parent.empty()){
S3FS_PRN_ERR("Could not get parent path for %s.", path);
return false;
}
// get parent's "system.posix_acl_default" value(base64'd).
std::string parent_default_value;
if(!get_xattr_posix_key_value(parent.c_str(), parent_default_value, true)){
return false;
}
// build "system.posix_acl_access" from parent's default value
std::string raw_xattr_value;
raw_xattr_value = "{\"system.posix_acl_access\":\"";
raw_xattr_value += parent_default_value;
raw_xattr_value += "\"}";
xattrvalue = urlEncode(raw_xattr_value);
return true;
}
static void free_xattrs(xattrs_t& xattrs)
{
@ -3163,16 +3368,16 @@ static size_t parse_xattrs(const std::string& strxattrs, xattrs_t& xattrs)
return xattrs.size();
}
static std::string build_xattrs(const xattrs_t& xattrs)
static std::string raw_build_xattrs(const xattrs_t& xattrs)
{
std::string strxattrs("{");
bool is_set = false;
std::string strxattrs;
bool is_set = false;
for(xattrs_t::const_iterator iter = xattrs.begin(); iter != xattrs.end(); ++iter){
if(is_set){
strxattrs += ',';
}else{
is_set = true;
is_set = true;
strxattrs = "{";
}
strxattrs += '\"';
strxattrs += iter->first;
@ -3187,8 +3392,18 @@ static std::string build_xattrs(const xattrs_t& xattrs)
}
strxattrs += '\"';
}
strxattrs += '}';
if(is_set){
strxattrs += "}";
}
return strxattrs;
}
static std::string build_xattrs(const xattrs_t& xattrs)
{
std::string strxattrs = raw_build_xattrs(xattrs);
if(strxattrs.empty()){
strxattrs = "{}";
}
strxattrs = urlEncode(strxattrs);
return strxattrs;
@ -3240,6 +3455,8 @@ static int set_xattrs_to_header(headers_t& meta, const char* name, const char* v
// build new strxattrs(not encoded) and set it to headers_t
meta["x-amz-meta-xattr"] = build_xattrs(xattrs);
S3FS_PRN_DBG("Set xattrs(after adding %s key) = %s", name, raw_build_xattrs(xattrs).c_str());
free_xattrs(xattrs);
return 0;
@ -3311,7 +3528,7 @@ static int s3fs_setxattr(const char* path, const char* name, const char* value,
set_stat_to_timespec(stbuf, ST_TYPE_MTIME, ts_mtime);
set_stat_to_timespec(stbuf, ST_TYPE_CTIME, ts_ctime);
if(0 != (result = create_directory_object(newpath.c_str(), stbuf.st_mode, ts_atime, ts_mtime, ts_ctime, stbuf.st_uid, stbuf.st_gid))){
if(0 != (result = create_directory_object(newpath.c_str(), stbuf.st_mode, ts_atime, ts_mtime, ts_ctime, stbuf.st_uid, stbuf.st_gid, NULL))){
return result;
}
@ -3421,6 +3638,8 @@ static int s3fs_getxattr(const char* path, const char* name, char* value, size_t
parse_xattrs(strxattrs, xattrs);
S3FS_PRN_DBG("Get xattrs = %s", raw_build_xattrs(xattrs).c_str());
// search name
std::string strname = name;
xattrs_t::iterator xiter = xattrs.find(strname);
@ -3485,6 +3704,8 @@ static int s3fs_listxattr(const char* path, char* list, size_t size)
parse_xattrs(strxattrs, xattrs);
S3FS_PRN_DBG("Get xattrs = %s", raw_build_xattrs(xattrs).c_str());
// calculate total name length
size_t total = 0;
for(xattrs_t::const_iterator xiter = xattrs.begin(); xiter != xattrs.end(); ++xiter){
@ -3582,6 +3803,8 @@ static int s3fs_removexattr(const char* path, const char* name)
delete xiter->second;
xattrs.erase(xiter);
S3FS_PRN_DBG("Reset xattrs(after delete %s key) = %s", name, raw_build_xattrs(xattrs).c_str());
if(S_ISDIR(stbuf.st_mode) && IS_REPLACEDIR(nDirType)){
// Should rebuild directory object(except new type)
// Need to remove old dir("dir" etc) and make new dir("dir/")
@ -3600,7 +3823,7 @@ static int s3fs_removexattr(const char* path, const char* name)
set_stat_to_timespec(stbuf, ST_TYPE_MTIME, ts_mtime);
set_stat_to_timespec(stbuf, ST_TYPE_CTIME, ts_ctime);
if(0 != (result = create_directory_object(newpath.c_str(), stbuf.st_mode, ts_atime, ts_mtime, ts_ctime, stbuf.st_uid, stbuf.st_gid))){
if(0 != (result = create_directory_object(newpath.c_str(), stbuf.st_mode, ts_atime, ts_mtime, ts_ctime, stbuf.st_uid, stbuf.st_gid, NULL))){
free_xattrs(xattrs);
return result;
}

View File

@ -1309,6 +1309,196 @@ function test_rm_rf_dir {
fi
}
function test_posix_acl {
describe "Testing posix acl function ..."
#------------------------------------------------------
# Directory
#------------------------------------------------------
local POSIX_ACL_TEST_DIR1="posix_acl_dir1"
local POSIX_ACL_TEST_DIR2="posix_acl_dir2"
mkdir "${POSIX_ACL_TEST_DIR1}"
#
# Set posix acl(not default)
#
setfacl -m "u:${USER}:rwx" "${POSIX_ACL_TEST_DIR1}"
if ! getfacl "${POSIX_ACL_TEST_DIR1}" | grep -q "^user:${USER}:rwx"; then
echo "Could not set posix acl(not default) to ${POSIX_ACL_TEST_DIR1} directory"
return 1
fi
#
# Set posix acl(default)
#
setfacl -d -m "u:${USER}:rwx" "${POSIX_ACL_TEST_DIR1}"
if ! getfacl "${POSIX_ACL_TEST_DIR1}" | grep -q "^default:user:${USER}:rwx"; then
echo "Could not set posix acl(default) to ${POSIX_ACL_TEST_DIR1} directory"
return 1
fi
#
# Rename
#
mv "${POSIX_ACL_TEST_DIR1}" "${POSIX_ACL_TEST_DIR2}"
if ! getfacl "${POSIX_ACL_TEST_DIR2}" | grep -q "^user:${USER}:rwx"; then
echo "Could not move with posix acl(not default) to ${POSIX_ACL_TEST_DIR2} directory"
return 1
fi
if ! getfacl "${POSIX_ACL_TEST_DIR2}" | grep -q "^default:user:${USER}:rwx"; then
echo "Could not move with posix acl(default) to ${POSIX_ACL_TEST_DIR2} directory"
return 1
fi
#
# Copy with permission
#
cp -rp "${POSIX_ACL_TEST_DIR2}" "${POSIX_ACL_TEST_DIR1}"
if ! getfacl "${POSIX_ACL_TEST_DIR1}" | grep -q "^user:${USER}:rwx"; then
echo "Could not copy with posix acl(not default) to ${POSIX_ACL_TEST_DIR1} directory"
return 1
fi
if ! getfacl "${POSIX_ACL_TEST_DIR1}" | grep -q "^default:user:${USER}:rwx"; then
echo "Could not copy with posix acl(default) to ${POSIX_ACL_TEST_DIR1} directory"
return 1
fi
#
# Overwrite posix acl(not default)
#
setfacl -m "u:${USER}:r-x" "${POSIX_ACL_TEST_DIR2}"
if ! getfacl "${POSIX_ACL_TEST_DIR2}" | grep -q "^user:${USER}:r-x"; then
echo "Could not set posix acl(not default) to ${POSIX_ACL_TEST_DIR2} directory"
return 1
fi
#
# Overwrite posix acl(default)
#
setfacl -d -m "u:${USER}:r-x" "${POSIX_ACL_TEST_DIR2}"
if ! getfacl "${POSIX_ACL_TEST_DIR2}" | grep -q "^default:user:${USER}:r-x"; then
echo "Could not set posix acl(default) to ${POSIX_ACL_TEST_DIR2} directory"
return 1
fi
#
# Remove posix acl(default)
#
setfacl -k "${POSIX_ACL_TEST_DIR2}"
if getfacl "${POSIX_ACL_TEST_DIR2}" | grep -q "^default:user:${USER}"; then
echo "Could not remove posix acl(default) to ${POSIX_ACL_TEST_DIR2} directory"
return 1
fi
#
# Remove posix acl(all)
#
setfacl -b "${POSIX_ACL_TEST_DIR2}"
if getfacl "${POSIX_ACL_TEST_DIR2}" | grep -q "^user:${USER}"; then
echo "Could not remove posix acl(all) to ${POSIX_ACL_TEST_DIR2} directory"
return 1
fi
#
# Copy without permission
#
rm -rf "${POSIX_ACL_TEST_DIR2}"
cp -r "${POSIX_ACL_TEST_DIR1}" "${POSIX_ACL_TEST_DIR2}"
if getfacl "${POSIX_ACL_TEST_DIR2}" | grep -q "^default:user:${USER}"; then
echo "Could not copy without posix acl(default) to ${POSIX_ACL_TEST_DIR2} directory"
return 1
fi
if getfacl "${POSIX_ACL_TEST_DIR2}" | grep -q "^user:${USER}"; then
echo "Could not copy without posix acl(all) to ${POSIX_ACL_TEST_DIR2} directory"
return 1
fi
#------------------------------------------------------
# File
#------------------------------------------------------
local POSIX_ACL_TEST_FILE1="posix_acl_dir1/posix_acl_file1"
local POSIX_ACL_TEST_FILE2="posix_acl_dir1/posix_acl_file2"
local POSIX_ACL_TEST_FILE3="posix_acl_dir2/posix_acl_file3"
local POSIX_ACL_TEST_FILE4="posix_acl_dir2/posix_acl_file4"
mkdir "${POSIX_ACL_TEST_DIR2}"
touch "${POSIX_ACL_TEST_FILE1}"
#
# Check default inherited posix acl
#
if ! getfacl "${POSIX_ACL_TEST_FILE1}" | grep -q "^user:${USER}:rwx"; then
echo "Could not set posix acl(inherited default) to ${POSIX_ACL_TEST_FILE1} file"
return 1
fi
#
# Overwrite posix acl
#
setfacl -m "u:${USER}:r-x" "${POSIX_ACL_TEST_FILE1}"
if ! getfacl "${POSIX_ACL_TEST_FILE1}" | grep -q "^user:${USER}:r-x"; then
echo "Could not overwrite posix acl to ${POSIX_ACL_TEST_FILE1} file"
return 1
fi
#
# Rename
#
mv "${POSIX_ACL_TEST_FILE1}" "${POSIX_ACL_TEST_FILE2}"
if ! getfacl "${POSIX_ACL_TEST_FILE2}" | grep -q "^user:${USER}:r-x"; then
echo "Could not move with posix acl to ${POSIX_ACL_TEST_FILE2} file"
return 1
fi
#
# Copy with permission
#
cp -p "${POSIX_ACL_TEST_FILE2}" "${POSIX_ACL_TEST_FILE1}"
if ! getfacl "${POSIX_ACL_TEST_FILE1}" | grep -q "^user:${USER}:r-x"; then
echo "Could not copy with posix acl to ${POSIX_ACL_TEST_FILE1} file"
return 1
fi
#
# Remove posix acl
#
setfacl -b "${POSIX_ACL_TEST_FILE2}"
if getfacl "${POSIX_ACL_TEST_FILE2}" | grep -q "^default:user:${USER}"; then
echo "Could not remove posix acl to ${POSIX_ACL_TEST_FILE2} file"
return 1
fi
#
# Copy without permission(set parent directory default acl)
#
rm -f "${POSIX_ACL_TEST_FILE2}"
cp "${POSIX_ACL_TEST_FILE1}" "${POSIX_ACL_TEST_FILE2}"
if ! getfacl "${POSIX_ACL_TEST_FILE2}" | grep -q "^user:${USER}:rwx"; then
echo "Could not copy without posix acl(inherited parent) to ${POSIX_ACL_TEST_FILE2} file"
return 1
fi
#
# Copy with permission(to no-acl directory)
#
cp -p "${POSIX_ACL_TEST_FILE1}" "${POSIX_ACL_TEST_FILE3}"
if ! getfacl "${POSIX_ACL_TEST_FILE3}" | grep -q "^user:${USER}:r-x"; then
echo "Could not copy with posix acl to ${POSIX_ACL_TEST_FILE3} file in no-acl directory"
return 1
fi
#
# Copy without permission(to no-acl directory)
#
cp "${POSIX_ACL_TEST_FILE1}" "${POSIX_ACL_TEST_FILE4}"
if getfacl "${POSIX_ACL_TEST_FILE4}" | grep -q "^user:${USER}"; then
echo "Could not copy without posix acl to ${POSIX_ACL_TEST_FILE4} file in no-acl directory"
return 1
fi
rm -rf "${POSIX_ACL_TEST_DIR1}"
rm -rf "${POSIX_ACL_TEST_DIR2}"
}
function test_copy_file {
describe "Test simple copy ..."
@ -1764,8 +1954,8 @@ function test_not_existed_dir_obj() {
# with "compat_dir", found directories and files
#
# Top directory
# shellcheck disable=SC2010
# Top directory
# shellcheck disable=SC2010
if ! ls -1 | grep -q '^not_existed_dir_single$'; then
echo "Expect to find \"not_existed_dir_single\" directory, but it is not found"
return 1;
@ -1776,8 +1966,8 @@ function test_not_existed_dir_obj() {
return 1;
fi
# Single nest directory
# shellcheck disable=SC2010
# Single nest directory
# shellcheck disable=SC2010
if ! ls -d not_existed_dir_single | grep -q '^not_existed_dir_single$'; then
echo "Expect to find \"not_existed_dir_single\" directory, but it is not found"
return 1;
@ -1793,8 +1983,8 @@ function test_not_existed_dir_obj() {
return 1;
fi
# Double nest directory
# shellcheck disable=SC2010
# Double nest directory
# shellcheck disable=SC2010
if ! ls -d not_existed_dir_parent | grep -q '^not_existed_dir_parent'; then
echo "Expect to find \"not_existed_dir_parent\" directory, but it is not found"
return 1;
@ -1820,8 +2010,8 @@ function test_not_existed_dir_obj() {
return 1;
fi
rm -rf not_existed_dir_single
rm -rf not_existed_dir_parent
rm -rf not_existed_dir_single
rm -rf not_existed_dir_parent
else
#
@ -1832,8 +2022,8 @@ function test_not_existed_dir_obj() {
# And if specify a file full path, it will be found.
#
# Top directory
# shellcheck disable=SC2010
# Top directory
# shellcheck disable=SC2010
if ls -1 | grep -q '^not_existed_dir_single$'; then
echo "Expect to not find \"not_existed_dir_single\" directory, but it is found"
return 1;
@ -1844,8 +2034,8 @@ function test_not_existed_dir_obj() {
return 1;
fi
# Single nest directory
# shellcheck disable=SC2010
# Single nest directory
# shellcheck disable=SC2010
if ! ls -d not_existed_dir_single | grep -q '^not_existed_dir_single$'; then
echo "Expect to find \"not_existed_dir_single\" directory, but it is not found"
return 1;
@ -1861,8 +2051,8 @@ function test_not_existed_dir_obj() {
return 1;
fi
# Double nest directory
# shellcheck disable=SC2010
# Double nest directory
# shellcheck disable=SC2010
if ! ls -d not_existed_dir_parent | grep -q '^not_existed_dir_parent'; then
echo "Expect to find \"not_existed_dir_parent\" directory, but it is not found"
return 1;
@ -1888,11 +2078,11 @@ function test_not_existed_dir_obj() {
return 1;
fi
rm -rf not_existed_dir_single
rm -rf not_existed_dir_single
# [NOTE]
# This case could not remove sub directory, then below command will be failed.
#rm -rf not_existed_dir_parent
#rm -rf not_existed_dir_parent
fi
}
@ -2190,6 +2380,11 @@ function add_all_tests {
add_tests test_update_directory_time_subdir
add_tests test_update_chmod_opened_file
# shellcheck disable=SC2009
if ! ps u -p "${S3FS_PID}" | grep -q use_xattr; then
add_tests test_posix_acl
fi
add_tests test_rm_rf_dir
add_tests test_copy_file
add_tests test_write_after_seek_ahead

View File

@ -42,7 +42,7 @@ export CACHE_DIR
export ENSURE_DISKFREE_SIZE
if [ -n "${ALL_TESTS}" ]; then
FLAGS=(
"use_cache=${CACHE_DIR} -o ensure_diskfree=${ENSURE_DISKFREE_SIZE} -o fake_diskfree=${FAKE_FREE_DISK_SIZE}"
"use_cache=${CACHE_DIR} -o ensure_diskfree=${ENSURE_DISKFREE_SIZE} -o fake_diskfree=${FAKE_FREE_DISK_SIZE} -o use_xattr"
enable_content_md5
disable_noobj_cache
"max_stat_cache_size=100"