mirror of
https://github.com/s3fs-fuse/s3fs-fuse.git
synced 2024-12-23 01:08:54 +00:00
Changed codes for issue: 27(+)
1) Feature Request: Compatability with other S3FS clients(Issue: 27) Rechanges source code. 2) For other S3 clients Supports the directory which is no objects. If there is a object which has "/" charactor(ex. "<bucket>/dir/file"), the directory("dir") object is no object. Exsample, you can upload the object which name is "s3://bucket/dir/file" by the s3cmd. Then the "dir" is not object in bucket("dir"). This s3fs codes understands this case. git-svn-id: http://s3fs.googlecode.com/svn/trunk@414 df820570-a93a-0410-bd06-b72b767a4274
This commit is contained in:
parent
36447a23eb
commit
b973eaae44
@ -101,7 +101,7 @@ time_t StatCache::UnsetExpireTime(void)
|
||||
return old;
|
||||
}
|
||||
|
||||
bool StatCache::GetStat(string& key, struct stat* pst, headers_t* meta, bool overcheck, const char* petag)
|
||||
bool StatCache::GetStat(string& key, struct stat* pst, headers_t* meta, bool overcheck, const char* petag, bool* pisforce)
|
||||
{
|
||||
bool is_delete_cache = false;
|
||||
string strpath = key;
|
||||
@ -144,7 +144,9 @@ bool StatCache::GetStat(string& key, struct stat* pst, headers_t* meta, bool ove
|
||||
meta->clear();
|
||||
(*meta) = (*iter).second.meta;
|
||||
}
|
||||
|
||||
if(pisforce != NULL){
|
||||
(*pisforce) = (*iter).second.isforce;
|
||||
}
|
||||
(*iter).second.hit_count++;
|
||||
pthread_mutex_unlock(&StatCache::stat_cache_lock);
|
||||
return true;
|
||||
@ -163,7 +165,7 @@ bool StatCache::GetStat(string& key, struct stat* pst, headers_t* meta, bool ove
|
||||
return false;
|
||||
}
|
||||
|
||||
bool StatCache::AddStat(std::string& key, headers_t& meta)
|
||||
bool StatCache::AddStat(std::string& key, headers_t& meta, bool forcedir)
|
||||
{
|
||||
if(CacheSize< 1){
|
||||
return true;
|
||||
@ -177,7 +179,7 @@ bool StatCache::AddStat(std::string& key, headers_t& meta)
|
||||
}
|
||||
|
||||
struct stat st;
|
||||
if(!convert_header_to_stat(key.c_str(), meta, &st)){
|
||||
if(!convert_header_to_stat(key.c_str(), meta, &st, forcedir)){
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -185,6 +187,7 @@ bool StatCache::AddStat(std::string& key, headers_t& meta)
|
||||
stat_cache[key].stbuf = st;
|
||||
stat_cache[key].hit_count = 0;
|
||||
stat_cache[key].cache_date = time(NULL); // Set time.
|
||||
stat_cache[key].isforce = forcedir;
|
||||
|
||||
//copy only some keys
|
||||
for (headers_t::iterator iter = meta.begin(); iter != meta.end(); ++iter) {
|
||||
@ -272,7 +275,7 @@ bool StatCache::DelStat(const char* key)
|
||||
//-------------------------------------------------------------------
|
||||
// Functions
|
||||
//-------------------------------------------------------------------
|
||||
bool convert_header_to_stat(const char* path, headers_t& meta, struct stat* pst)
|
||||
bool convert_header_to_stat(const char* path, headers_t& meta, struct stat* pst, bool forcedir)
|
||||
{
|
||||
headers_t::const_iterator iter;
|
||||
|
||||
@ -295,16 +298,20 @@ bool convert_header_to_stat(const char* path, headers_t& meta, struct stat* pst)
|
||||
if(iter != meta.end()){
|
||||
strConType = (*iter).second;
|
||||
}
|
||||
if(strConType == "application/x-directory"){
|
||||
if(forcedir){
|
||||
pst->st_mode |= S_IFDIR;
|
||||
}else if(0 < strlen(path) && '/' == path[strlen(path) - 1]){
|
||||
if(strConType == "binary/octet-stream" || strConType == "application/octet-stream"){
|
||||
}else{
|
||||
if(strConType == "application/x-directory"){
|
||||
pst->st_mode |= S_IFDIR;
|
||||
}else if(0 < strlen(path) && '/' == path[strlen(path) - 1]){
|
||||
if(strConType == "binary/octet-stream" || strConType == "application/octet-stream"){
|
||||
pst->st_mode |= S_IFDIR;
|
||||
}else{
|
||||
pst->st_mode |= S_IFREG;
|
||||
}
|
||||
}else{
|
||||
pst->st_mode |= S_IFREG;
|
||||
}
|
||||
}else{
|
||||
pst->st_mode |= S_IFREG;
|
||||
}
|
||||
|
||||
// blocks
|
||||
|
21
src/cache.h
21
src/cache.h
@ -11,8 +11,9 @@ struct stat_cache_entry {
|
||||
unsigned long hit_count;
|
||||
time_t cache_date;
|
||||
headers_t meta;
|
||||
bool isforce;
|
||||
|
||||
stat_cache_entry() : hit_count(0), cache_date(0) {
|
||||
stat_cache_entry() : hit_count(0), cache_date(0), isforce(false) {
|
||||
memset(&stbuf, 0, sizeof(struct stat));
|
||||
meta.clear();
|
||||
}
|
||||
@ -34,7 +35,7 @@ class StatCache
|
||||
unsigned long CacheSize;
|
||||
|
||||
private:
|
||||
bool GetStat(std::string& key, struct stat* pst, headers_t* meta, bool overcheck, const char* petag);
|
||||
bool GetStat(std::string& key, struct stat* pst, headers_t* meta, bool overcheck, const char* petag, bool* pisforce);
|
||||
// Truncate stat cache
|
||||
bool TruncateCache(void);
|
||||
|
||||
@ -55,24 +56,24 @@ class StatCache
|
||||
time_t UnsetExpireTime(void);
|
||||
|
||||
// Get stat cache
|
||||
bool GetStat(std::string& key, struct stat* pst, headers_t* meta, bool overcheck = true) {
|
||||
return GetStat(key, pst, meta, overcheck, NULL);
|
||||
bool GetStat(std::string& key, struct stat* pst, headers_t* meta, bool overcheck = true, bool* pisforce = NULL) {
|
||||
return GetStat(key, pst, meta, overcheck, NULL, pisforce);
|
||||
}
|
||||
bool GetStat(std::string& key, struct stat* pst, bool overcheck = true) {
|
||||
return GetStat(key, pst, NULL, overcheck, NULL);
|
||||
return GetStat(key, pst, NULL, overcheck, NULL, NULL);
|
||||
}
|
||||
bool GetStat(std::string& key, headers_t* meta, bool overcheck = true) {
|
||||
return GetStat(key, NULL, meta, overcheck, NULL);
|
||||
return GetStat(key, NULL, meta, overcheck, NULL, NULL);
|
||||
}
|
||||
bool HasStat(std::string& key, bool overcheck = true) {
|
||||
return GetStat(key, NULL, NULL, overcheck, NULL);
|
||||
return GetStat(key, NULL, NULL, overcheck, NULL, NULL);
|
||||
}
|
||||
bool HasStat(std::string& key, const char* etag, bool overcheck = true) {
|
||||
return GetStat(key, NULL, NULL, overcheck, etag);
|
||||
return GetStat(key, NULL, NULL, overcheck, etag, NULL);
|
||||
}
|
||||
|
||||
// Add stat cache
|
||||
bool AddStat(std::string& key, headers_t& meta);
|
||||
bool AddStat(std::string& key, headers_t& meta, bool forcedir = false);
|
||||
|
||||
// Delete stat cache
|
||||
bool DelStat(const char* key);
|
||||
@ -84,6 +85,6 @@ class StatCache
|
||||
//
|
||||
// Functions
|
||||
//
|
||||
bool convert_header_to_stat(const char* path, headers_t& meta, struct stat* pst);
|
||||
bool convert_header_to_stat(const char* path, headers_t& meta, struct stat* pst, bool forcedir = false);
|
||||
|
||||
#endif // S3FS_CACHE_H_
|
||||
|
432
src/s3fs.cpp
432
src/s3fs.cpp
@ -56,6 +56,10 @@ using namespace std;
|
||||
#define DIRTYPE_NEW 0
|
||||
#define DIRTYPE_OLD 1
|
||||
#define DIRTYPE_FOLDER 2
|
||||
#define DIRTYPE_NOOBJ 3
|
||||
|
||||
#define IS_REPLACEDIR(type) (DIRTYPE_OLD == type || DIRTYPE_FOLDER == type || DIRTYPE_NOOBJ == type)
|
||||
#define IS_RMTYPEDIR(type) (DIRTYPE_OLD == type || DIRTYPE_FOLDER == type)
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Typedef
|
||||
@ -120,12 +124,13 @@ static s3fs_pathtofd_t s3fs_pathtofd; // path -> fd
|
||||
// Static functions : prototype
|
||||
//-------------------------------------------------------------------
|
||||
static bool is_special_name_folder_object(const char *path);
|
||||
static int chk_dir_object_type(const char *path, string& strpath, string& strdelpath, headers_t* pmeta = NULL, int* pDirType = NULL);
|
||||
static int get_object_attribute(const char *path, struct stat *pstbuf, headers_t* pmeta = NULL, bool overcheck = true);
|
||||
static int chk_dir_object_type(const char *path, string& newpath, string& nowpath, string& nowcache, headers_t* pmeta = NULL, int* pDirType = NULL);
|
||||
static int get_object_attribute(const char *path, struct stat *pstbuf, headers_t* pmeta = NULL, bool overcheck = true, bool* pisforce = NULL);
|
||||
static int check_object_access(const char *path, int mask, struct stat* pstbuf);
|
||||
static int check_object_owner(const char *path, struct stat* pstbuf);
|
||||
static int check_parent_object_access(const char *path, int mask);
|
||||
static int list_bucket(const char *path, S3ObjList& head, const char* delimiter);
|
||||
static int directory_empty(const char *path);
|
||||
static bool is_truncated(const char *xml);
|
||||
static int append_objects_from_xml_ex(const char* path, xmlDocPtr doc, xmlXPathContextPtr ctx,
|
||||
const char* ex_contents, const char* ex_key, const char* ex_etag, int isCPrefix, S3ObjList& head);
|
||||
@ -200,69 +205,92 @@ static bool is_special_name_folder_object(const char *path)
|
||||
return true;
|
||||
}
|
||||
|
||||
static int chk_dir_object_type(const char *path, string& strpath, string& strdelpath, headers_t* pmeta, int* pDirType)
|
||||
// [Detail]
|
||||
// This function is complicated for checking directory object type.
|
||||
// Arguments is used for deleting cache/path, and remake directory object.
|
||||
// Please see the codes which calls this function.
|
||||
//
|
||||
// path: target path
|
||||
// newpath: should be object path for making/putting/getting after checking
|
||||
// nowpath: now object name for deleting after checking
|
||||
// nowcache: now cache path for deleting after checking
|
||||
// pmeta: headers map
|
||||
// pDirType: directory object type
|
||||
//
|
||||
static int chk_dir_object_type(const char *path, string& newpath, string& nowpath, string& nowcache, headers_t* pmeta, int* pDirType)
|
||||
{
|
||||
int result = -1;
|
||||
strpath = path;
|
||||
if(pDirType){
|
||||
*pDirType= DIRTYPE_NEW;
|
||||
int TypeTmp;
|
||||
int result = -1;
|
||||
bool isforce = false;
|
||||
int* pType = pDirType ? pDirType : &TypeTmp;
|
||||
|
||||
// Normalize new path.
|
||||
newpath = path;
|
||||
if('/' != newpath[newpath.length() - 1]){
|
||||
string::size_type Pos;
|
||||
if(string::npos != (Pos = newpath.find("_$folder$", 0))){
|
||||
newpath = newpath.substr(0, Pos);
|
||||
}
|
||||
newpath += "/";
|
||||
}
|
||||
|
||||
// At first, if not have "/", check path with "/".
|
||||
if('/' != strpath[strpath.length() - 1]){
|
||||
strpath += "/";
|
||||
strdelpath = strpath;
|
||||
result = get_object_attribute(strpath.c_str(), NULL, pmeta, false);
|
||||
}
|
||||
if(0 == result){
|
||||
// Found "dir/" --> Check for "_$folder$"
|
||||
if(is_special_name_folder_object(strpath.c_str())){
|
||||
if(0 < strpath.length() && '/' == strpath[strpath.length() - 1]){
|
||||
strpath = strpath.substr(0, strpath.length() - 1);
|
||||
}
|
||||
strdelpath = strpath + "_$folder$";
|
||||
if(pDirType){
|
||||
*pDirType = DIRTYPE_FOLDER;
|
||||
// Alwayes check "dir/" at first.
|
||||
if(0 == (result = get_object_attribute(newpath.c_str(), NULL, pmeta, false, &isforce))){
|
||||
// Found "dir/" cache --> Check for "_$folder$", "no dir object"
|
||||
nowcache = newpath;
|
||||
if(is_special_name_folder_object(newpath.c_str())){
|
||||
// "_$folder$" type.
|
||||
(*pType) = DIRTYPE_FOLDER;
|
||||
nowpath = newpath.substr(0, newpath.length() - 1) + "_$folder$"; // cut and add
|
||||
}else if(isforce){
|
||||
// "no dir object" type.
|
||||
(*pType) = DIRTYPE_NOOBJ;
|
||||
nowpath = "";
|
||||
}else{
|
||||
nowpath = path;
|
||||
if(0 < nowpath.length() && '/' == nowpath[nowpath.length() - 1]){
|
||||
// "dir/" type
|
||||
(*pType) = DIRTYPE_NEW;
|
||||
}else{
|
||||
// "dir" type
|
||||
(*pType) = DIRTYPE_OLD;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
// Need to chack old type directory("dir").
|
||||
strpath = path;
|
||||
strdelpath = strpath;
|
||||
if(0 == (result = get_object_attribute(strpath.c_str(), NULL, pmeta, false))){
|
||||
if(0 < strpath.length() && '/' != strpath[strpath.length() - 1]){
|
||||
if(pDirType){
|
||||
*pDirType = DIRTYPE_OLD;
|
||||
}
|
||||
// Check "dir"
|
||||
nowpath = newpath.substr(0, newpath.length() - 1);
|
||||
if(0 == (result = get_object_attribute(nowpath.c_str(), NULL, pmeta, false, &isforce))){
|
||||
// Found "dir" cache --> this case is only "dir" type.
|
||||
// Because, if object is "_$folder$" or "no dir object", the cache is "dir/" type.
|
||||
// (But "no dir objet" is checked here.)
|
||||
nowcache = nowpath;
|
||||
if(isforce){
|
||||
(*pType) = DIRTYPE_NOOBJ;
|
||||
nowpath = "";
|
||||
}else{
|
||||
// Found "dir/" --> Check for "_$folder$"
|
||||
if(is_special_name_folder_object(strpath.c_str())){
|
||||
strpath = strpath.substr(0, strpath.length() - 1);
|
||||
strdelpath = strpath + "_$folder$";
|
||||
if(pDirType){
|
||||
*pDirType = DIRTYPE_FOLDER;
|
||||
}
|
||||
}
|
||||
(*pType) = DIRTYPE_OLD;
|
||||
}
|
||||
}else{
|
||||
// Check for "_$folder$"
|
||||
if(is_special_name_folder_object(strpath.c_str())){
|
||||
if(0 < strpath.length() && '/' == strpath[strpath.length() - 1]){
|
||||
strpath = strpath.substr(0, strpath.length() - 1);
|
||||
}
|
||||
strdelpath = strpath + "_$folder$";
|
||||
if(pDirType){
|
||||
*pDirType = DIRTYPE_FOLDER;
|
||||
}
|
||||
result = get_object_attribute(strpath.c_str(), NULL, pmeta, false);
|
||||
// Not found cache --> check for "_$folder$" and "no dir object".
|
||||
nowcache = ""; // This case is no cahce.
|
||||
nowpath += "_$folder$";
|
||||
if(is_special_name_folder_object(nowpath.c_str())){
|
||||
// "_$folder$" type.
|
||||
(*pType) = DIRTYPE_FOLDER;
|
||||
result = 0; // result is OK.
|
||||
}else if(-ENOTEMPTY == directory_empty(newpath.c_str())){
|
||||
// "no dir object" type.
|
||||
(*pType) = DIRTYPE_NOOBJ;
|
||||
nowpath = ""; // now path.
|
||||
result = 0; // result is OK.
|
||||
}else{
|
||||
// Error: Unknown type.
|
||||
(*pType) = DIRTYPE_UNKNOWN;
|
||||
newpath = "";
|
||||
nowpath = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
if(0 != result){
|
||||
if(pDirType){
|
||||
*pDirType = DIRTYPE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -270,7 +298,7 @@ static int chk_dir_object_type(const char *path, string& strpath, string& strdel
|
||||
// Get object attributes with stat cache.
|
||||
// This function is base for s3fs_getattr().
|
||||
//
|
||||
static int get_object_attribute(const char *path, struct stat *pstbuf, headers_t* pmeta, bool overcheck)
|
||||
static int get_object_attribute(const char *path, struct stat *pstbuf, headers_t* pmeta, bool overcheck, bool* pisforce)
|
||||
{
|
||||
int result = -1;
|
||||
struct stat tmpstbuf;
|
||||
@ -280,6 +308,7 @@ static int get_object_attribute(const char *path, struct stat *pstbuf, headers_t
|
||||
string strpath;
|
||||
string s3_realpath;
|
||||
string::size_type Pos;
|
||||
bool forcedir = false;
|
||||
|
||||
//FGPRINT(" get_object_attribute[path=%s]\n", path);
|
||||
|
||||
@ -299,7 +328,10 @@ static int get_object_attribute(const char *path, struct stat *pstbuf, headers_t
|
||||
strpath += "/";
|
||||
}
|
||||
}
|
||||
if(StatCache::getStatCacheData()->GetStat(strpath, pstat, pheader, overcheck)){
|
||||
if(pisforce){
|
||||
(*pisforce) = false;
|
||||
}
|
||||
if(StatCache::getStatCacheData()->GetStat(strpath, pstat, pheader, overcheck, pisforce)){
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -319,15 +351,32 @@ static int get_object_attribute(const char *path, struct stat *pstbuf, headers_t
|
||||
strpath = path;
|
||||
s3_realpath = get_realpath(strpath.c_str());
|
||||
if(0 != (result = curl_get_headers(s3_realpath.c_str(), (*pheader)))){
|
||||
if(overcheck && string::npos == strpath.find("_$folder$", 0)){
|
||||
// check for s3fox etc
|
||||
strpath += "_$folder$";
|
||||
s3_realpath = get_realpath(strpath.c_str());
|
||||
if(0 != (result = curl_get_headers(s3_realpath.c_str(), (*pheader)))){
|
||||
return result;
|
||||
// Not found --> check( if overcheck )
|
||||
if(overcheck){
|
||||
if(string::npos == strpath.find("_$folder$", 0)){
|
||||
// path doesn't have "_$folder$" --> check for s3fox etc
|
||||
strpath += "_$folder$";
|
||||
s3_realpath = get_realpath(strpath.c_str());
|
||||
result = curl_get_headers(s3_realpath.c_str(), (*pheader));
|
||||
}
|
||||
if(0 == result){
|
||||
// found "_$folder$" object.
|
||||
strpath = path; // reset original
|
||||
strpath += "/";
|
||||
}else{
|
||||
// path does not have "_$folder$" --> check "no dir obejct".
|
||||
if(-ENOTEMPTY == directory_empty(path)){
|
||||
// found "no dir obejct".
|
||||
forcedir = true;
|
||||
strpath = path; // reset original
|
||||
strpath += "/";
|
||||
if(pisforce){
|
||||
(*pisforce) = true;
|
||||
}
|
||||
}else{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
strpath = path; // reset original
|
||||
strpath += "/";
|
||||
}else{
|
||||
return result;
|
||||
}
|
||||
@ -342,11 +391,11 @@ static int get_object_attribute(const char *path, struct stat *pstbuf, headers_t
|
||||
}
|
||||
|
||||
// add into stat cache
|
||||
if(!StatCache::getStatCacheData()->AddStat(strpath, (*pheader))){
|
||||
if(!StatCache::getStatCacheData()->AddStat(strpath, (*pheader), forcedir)){
|
||||
FGPRINT(" get_object_attribute: failed adding stat cache [path=%s]\n", strpath.c_str());
|
||||
return -ENOENT;
|
||||
}
|
||||
if(!StatCache::getStatCacheData()->GetStat(strpath, pstat, pheader, overcheck)){
|
||||
if(!StatCache::getStatCacheData()->GetStat(strpath, pstat, pheader, overcheck, pisforce)){
|
||||
FGPRINT(" get_object_attribute: failed getting added stat cache [path=%s]\n", strpath.c_str());
|
||||
return -ENOENT;
|
||||
}
|
||||
@ -1821,6 +1870,8 @@ static int s3fs_rmdir(const char *path)
|
||||
StatCache::getStatCacheData()->DelStat(strpath.c_str());
|
||||
}
|
||||
}
|
||||
// If there is no "dir" and "dir/" object(this case is made by s3cmd/s3sync),
|
||||
// the cache key is "dir/". So we get error only onece(delete "dir/").
|
||||
|
||||
// check for "_$folder$" object.
|
||||
// This processing is necessary for other S3 clients compatibility.
|
||||
@ -2065,13 +2116,17 @@ static int clone_directory_object(const char *from, const char *to)
|
||||
return result;
|
||||
}
|
||||
|
||||
static int rename_directory(const char *from, const char *to) {
|
||||
static int rename_directory(const char *from, const char *to)
|
||||
{
|
||||
S3ObjList head;
|
||||
s3obj_list_t headlist;
|
||||
string strfrom = from ? from : ""; // from is without "/".
|
||||
string strto = to ? to : ""; // to is without "/" too.
|
||||
string basepath = strfrom + "/";
|
||||
string strdelpath;
|
||||
string newpath; // should be from name(not used)
|
||||
string nowcache; // now cache path(not used)
|
||||
int DirType;
|
||||
bool normdir;
|
||||
MVNODE* mn_head = NULL;
|
||||
MVNODE* mn_tail = NULL;
|
||||
MVNODE* mn_cur;
|
||||
@ -2086,12 +2141,18 @@ static int rename_directory(const char *from, const char *to) {
|
||||
// Initiate and Add base directory into MVNODE struct.
|
||||
//
|
||||
strto += "/";
|
||||
if(0 == chk_dir_object_type(from, strfrom, strdelpath)){
|
||||
if(NULL == (add_mvnode(&mn_head, &mn_tail, strdelpath.c_str(), strto.c_str(), true))){
|
||||
if(0 == chk_dir_object_type(from, newpath, strfrom, nowcache, NULL, &DirType) && DIRTYPE_UNKNOWN != DirType){
|
||||
if(DIRTYPE_NOOBJ != DirType){
|
||||
normdir = false;
|
||||
}else{
|
||||
normdir = true;
|
||||
strfrom = from; // from directory is not removed, but from directory attr is needed.
|
||||
}
|
||||
if(NULL == (add_mvnode(&mn_head, &mn_tail, strfrom.c_str(), strto.c_str(), true, normdir))){
|
||||
return -ENOMEM;
|
||||
}
|
||||
}else{
|
||||
// No base directory: maybe a case of made no directory by s3cmd.
|
||||
// Something wrong about "from" directory.
|
||||
}
|
||||
|
||||
//
|
||||
@ -2103,8 +2164,9 @@ static int rename_directory(const char *from, const char *to) {
|
||||
FGPRINT(" rename_directory list_bucket returns error.\n");
|
||||
return result;
|
||||
}
|
||||
head.GetNameList(headlist); // get name without "/".
|
||||
S3ObjList::MakeHierarchizedList(headlist, false); // add hierarchized dir.
|
||||
|
||||
head.GetNameList(headlist); // get name without "/".
|
||||
s3obj_list_t::const_iterator liter;
|
||||
for(liter = headlist.begin(); headlist.end() != liter; liter++){
|
||||
// make "from" and "to" object name.
|
||||
@ -2120,17 +2182,23 @@ static int rename_directory(const char *from, const char *to) {
|
||||
}
|
||||
if(S_ISDIR(stbuf.st_mode)){
|
||||
is_dir = true;
|
||||
if(0 != chk_dir_object_type(from_name.c_str(), from_name, strdelpath)){
|
||||
FGPRINT(" rename_directory - failed to get %s object directory type.\n", from_name.c_str());
|
||||
if(0 != chk_dir_object_type(from_name.c_str(), newpath, from_name, nowcache, NULL, &DirType) || DIRTYPE_UNKNOWN == DirType){
|
||||
FGPRINT(" rename_directory - failed to get %s%s object directory type.\n", basepath.c_str(), (*liter).c_str());
|
||||
continue;
|
||||
}
|
||||
if(DIRTYPE_NOOBJ != DirType){
|
||||
normdir = false;
|
||||
}else{
|
||||
normdir = true;
|
||||
from_name = basepath + (*liter); // from directory is not removed, but from directory attr is needed.
|
||||
}
|
||||
}else{
|
||||
is_dir = false;
|
||||
strdelpath = from_name;
|
||||
is_dir = false;
|
||||
normdir = false;
|
||||
}
|
||||
|
||||
// push this one onto the stack
|
||||
if(NULL == add_mvnode(&mn_head, &mn_tail, strdelpath.c_str(), to_name.c_str(), is_dir)){
|
||||
if(NULL == add_mvnode(&mn_head, &mn_tail, from_name.c_str(), to_name.c_str(), is_dir, normdir)){
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
@ -2140,7 +2208,7 @@ 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){
|
||||
if(mn_cur->is_dir && mn_cur->old_path && '\0' != mn_cur->old_path[0]){
|
||||
if(0 != (result = clone_directory_object(mn_cur->old_path, mn_cur->new_path))){
|
||||
FGPRINT(" rename_directory - failed(%d) to rename %s directory object to %s.\n", result, mn_cur->old_path, mn_cur->new_path);
|
||||
SYSLOGERR("clone_directory_object returned an error(%d)", result);
|
||||
@ -2170,12 +2238,17 @@ static int rename_directory(const char *from, const char *to) {
|
||||
|
||||
// Iterate over old the directories, bottoms up and remove
|
||||
for(mn_cur = mn_tail; mn_cur; mn_cur = mn_cur->prev){
|
||||
if(mn_cur->is_dir){
|
||||
if(0 != (result = s3fs_rmdir(mn_cur->old_path))){
|
||||
FGPRINT(" rename_directory - failed(%d) to remove %s directory object.\n", result, mn_cur->old_path);
|
||||
SYSLOGERR("s3fs_rmdir returned an error(%d)", result);
|
||||
free_mvnodes(mn_head);
|
||||
return -EIO;
|
||||
if(mn_cur->is_dir && mn_cur->old_path && '\0' != mn_cur->old_path[0]){
|
||||
if(!(mn_cur->is_normdir)){
|
||||
if(0 != (result = s3fs_rmdir(mn_cur->old_path))){
|
||||
FGPRINT(" rename_directory - failed(%d) to remove %s directory object.\n", result, mn_cur->old_path);
|
||||
SYSLOGERR("s3fs_rmdir returned an error(%d)", result);
|
||||
free_mvnodes(mn_head);
|
||||
return -EIO;
|
||||
}
|
||||
}else{
|
||||
// cache clear.
|
||||
StatCache::getStatCacheData()->DelStat(mn_cur->old_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2229,7 +2302,8 @@ static int s3fs_chmod(const char *path, mode_t mode)
|
||||
int result;
|
||||
string s3_realpath;
|
||||
string strpath;
|
||||
string strdel;
|
||||
string newpath;
|
||||
string nowcache;
|
||||
headers_t meta;
|
||||
struct stat stbuf;
|
||||
int nDirType = DIRTYPE_UNKNOWN;
|
||||
@ -2244,11 +2318,11 @@ static int s3fs_chmod(const char *path, mode_t mode)
|
||||
}
|
||||
|
||||
if(S_ISDIR(stbuf.st_mode)){
|
||||
result = chk_dir_object_type(path, strpath, strdel, &meta, &nDirType);
|
||||
s3_realpath = get_realpath(strdel.c_str());
|
||||
result = chk_dir_object_type(path, newpath, strpath, nowcache, &meta, &nDirType);
|
||||
s3_realpath = get_realpath(strpath.c_str());
|
||||
}else{
|
||||
strpath = path;
|
||||
strdel = strpath;
|
||||
nowcache = strpath;
|
||||
s3_realpath = get_realpath(strpath.c_str());
|
||||
result = get_object_attribute(strpath.c_str(), NULL, &meta);
|
||||
}
|
||||
@ -2256,21 +2330,22 @@ static int s3fs_chmod(const char *path, mode_t mode)
|
||||
return result;
|
||||
}
|
||||
|
||||
if(S_ISDIR(stbuf.st_mode) && DIRTYPE_NEW != nDirType){
|
||||
// directory object of old version
|
||||
// Need to remove old dir("dir") and make new dir("dir/")
|
||||
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/")
|
||||
|
||||
// At first, remove directory old object
|
||||
if(0 != (result = curl_delete(s3_realpath.c_str()))){
|
||||
return result;
|
||||
if(IS_RMTYPEDIR(nDirType)){
|
||||
if(0 != (result = curl_delete(s3_realpath.c_str()))){
|
||||
return result;
|
||||
}
|
||||
}
|
||||
StatCache::getStatCacheData()->DelStat(strdel);
|
||||
StatCache::getStatCacheData()->DelStat(nowcache);
|
||||
|
||||
// Make new directory object("dir/")
|
||||
if(0 != (result = create_directory_object(strpath.c_str(), mode, stbuf.st_mtime, stbuf.st_uid, stbuf.st_gid))){
|
||||
if(0 != (result = create_directory_object(newpath.c_str(), mode, stbuf.st_mtime, stbuf.st_uid, stbuf.st_gid))){
|
||||
return result;
|
||||
}
|
||||
|
||||
}else{
|
||||
// normal object or directory object of newer version
|
||||
meta["x-amz-meta-mode"] = str(mode);
|
||||
@ -2280,7 +2355,7 @@ static int s3fs_chmod(const char *path, mode_t mode)
|
||||
if(put_headers(strpath.c_str(), meta) != 0){
|
||||
return -EIO;
|
||||
}
|
||||
StatCache::getStatCacheData()->DelStat(strdel);
|
||||
StatCache::getStatCacheData()->DelStat(nowcache);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -2290,7 +2365,8 @@ static int s3fs_chmod_nocopy(const char *path, mode_t mode) {
|
||||
int result;
|
||||
string s3_realpath;
|
||||
string strpath;
|
||||
string strdel;
|
||||
string newpath;
|
||||
string nowcache;
|
||||
headers_t meta;
|
||||
struct stat stbuf;
|
||||
int nDirType = DIRTYPE_UNKNOWN;
|
||||
@ -2306,11 +2382,11 @@ static int s3fs_chmod_nocopy(const char *path, mode_t mode) {
|
||||
|
||||
// Get attributes
|
||||
if(S_ISDIR(stbuf.st_mode)){
|
||||
result = chk_dir_object_type(path, strpath, strdel, &meta, &nDirType);
|
||||
s3_realpath = get_realpath(strdel.c_str());
|
||||
result = chk_dir_object_type(path, newpath, strpath, nowcache, &meta, &nDirType);
|
||||
s3_realpath = get_realpath(strpath.c_str());
|
||||
}else{
|
||||
strpath = path;
|
||||
strdel = strpath;
|
||||
nowcache = strpath;
|
||||
s3_realpath = get_realpath(strpath.c_str());
|
||||
result = get_object_attribute(strpath.c_str(), NULL, &meta);
|
||||
}
|
||||
@ -2319,29 +2395,21 @@ static int s3fs_chmod_nocopy(const char *path, mode_t mode) {
|
||||
}
|
||||
|
||||
if(S_ISDIR(stbuf.st_mode)){
|
||||
if(DIRTYPE_NEW != nDirType){
|
||||
// directory object of old version
|
||||
// Need to remove old dir("dir") and make new dir("dir/")
|
||||
|
||||
// At first, remove directory old object
|
||||
// Should rebuild all directory object
|
||||
// Need to remove old dir("dir" etc) and make new dir("dir/")
|
||||
|
||||
// At first, remove directory old object
|
||||
if(IS_RMTYPEDIR(nDirType)){
|
||||
if(0 != (result = curl_delete(s3_realpath.c_str()))){
|
||||
return result;
|
||||
}
|
||||
StatCache::getStatCacheData()->DelStat(strdel);
|
||||
|
||||
// Make new directory object("dir/")
|
||||
if(0 != (result = create_directory_object(strpath.c_str(), mode, stbuf.st_mtime, stbuf.st_uid, stbuf.st_gid))){
|
||||
return result;
|
||||
}
|
||||
}else{
|
||||
// directory object of new version
|
||||
// Over put directory object.
|
||||
if(0 != (result = create_directory_object(strpath.c_str(), mode, stbuf.st_mtime, stbuf.st_uid, stbuf.st_gid))){
|
||||
return result;
|
||||
}
|
||||
StatCache::getStatCacheData()->DelStat(strdel);
|
||||
}
|
||||
StatCache::getStatCacheData()->DelStat(nowcache);
|
||||
|
||||
// Make new directory object("dir/")
|
||||
if(0 != (result = create_directory_object(newpath.c_str(), mode, stbuf.st_mtime, stbuf.st_uid, stbuf.st_gid))){
|
||||
return result;
|
||||
}
|
||||
}else{
|
||||
// normal object or directory object of newer version
|
||||
int fd;
|
||||
@ -2377,7 +2445,7 @@ static int s3fs_chmod_nocopy(const char *path, mode_t mode) {
|
||||
if(isclose){
|
||||
close(fd);
|
||||
}
|
||||
StatCache::getStatCacheData()->DelStat(strdel);
|
||||
StatCache::getStatCacheData()->DelStat(nowcache);
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -2387,7 +2455,8 @@ static int s3fs_chown(const char *path, uid_t uid, gid_t gid) {
|
||||
int result;
|
||||
string s3_realpath;
|
||||
string strpath;
|
||||
string strdel;
|
||||
string newpath;
|
||||
string nowcache;
|
||||
headers_t meta;
|
||||
struct stat stbuf;
|
||||
int nDirType = DIRTYPE_UNKNOWN;
|
||||
@ -2402,11 +2471,11 @@ static int s3fs_chown(const char *path, uid_t uid, gid_t gid) {
|
||||
}
|
||||
|
||||
if(S_ISDIR(stbuf.st_mode)){
|
||||
result = chk_dir_object_type(path, strpath, strdel, &meta, &nDirType);
|
||||
s3_realpath = get_realpath(strdel.c_str());
|
||||
result = chk_dir_object_type(path, newpath, strpath, nowcache, &meta, &nDirType);
|
||||
s3_realpath = get_realpath(strpath.c_str());
|
||||
}else{
|
||||
strpath = path;
|
||||
strdel = strpath;
|
||||
nowcache = strpath;
|
||||
s3_realpath = get_realpath(strpath.c_str());
|
||||
result = get_object_attribute(strpath.c_str(), NULL, &meta);
|
||||
}
|
||||
@ -2423,18 +2492,20 @@ static int s3fs_chown(const char *path, uid_t uid, gid_t gid) {
|
||||
gid = grdata->gr_gid;
|
||||
}
|
||||
|
||||
if(S_ISDIR(stbuf.st_mode) && DIRTYPE_NEW != nDirType){
|
||||
// directory object of old version
|
||||
// Need to remove old dir("dir") and make new dir("dir/")
|
||||
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/")
|
||||
|
||||
// At first, remove directory old object
|
||||
if(0 != (result = curl_delete(s3_realpath.c_str()))){
|
||||
return result;
|
||||
if(IS_RMTYPEDIR(nDirType)){
|
||||
if(0 != (result = curl_delete(s3_realpath.c_str()))){
|
||||
return result;
|
||||
}
|
||||
}
|
||||
StatCache::getStatCacheData()->DelStat(strdel);
|
||||
StatCache::getStatCacheData()->DelStat(nowcache);
|
||||
|
||||
// Make new directory object("dir/")
|
||||
if(0 != (result = create_directory_object(strpath.c_str(), stbuf.st_mode, stbuf.st_mtime, uid, gid))){
|
||||
if(0 != (result = create_directory_object(newpath.c_str(), stbuf.st_mode, stbuf.st_mtime, uid, gid))){
|
||||
return result;
|
||||
}
|
||||
}else{
|
||||
@ -2446,7 +2517,7 @@ static int s3fs_chown(const char *path, uid_t uid, gid_t gid) {
|
||||
if(put_headers(strpath.c_str(), meta) != 0){
|
||||
return -EIO;
|
||||
}
|
||||
StatCache::getStatCacheData()->DelStat(strdel);
|
||||
StatCache::getStatCacheData()->DelStat(nowcache);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -2456,7 +2527,8 @@ static int s3fs_chown_nocopy(const char *path, uid_t uid, gid_t gid) {
|
||||
int result;
|
||||
string s3_realpath;
|
||||
string strpath;
|
||||
string strdel;
|
||||
string newpath;
|
||||
string nowcache;
|
||||
headers_t meta;
|
||||
struct stat stbuf;
|
||||
int nDirType = DIRTYPE_UNKNOWN;
|
||||
@ -2472,11 +2544,11 @@ static int s3fs_chown_nocopy(const char *path, uid_t uid, gid_t gid) {
|
||||
|
||||
// Get attributes
|
||||
if(S_ISDIR(stbuf.st_mode)){
|
||||
result = chk_dir_object_type(path, strpath, strdel, &meta, &nDirType);
|
||||
s3_realpath = get_realpath(strdel.c_str());
|
||||
result = chk_dir_object_type(path, newpath, strpath, nowcache, &meta, &nDirType);
|
||||
s3_realpath = get_realpath(strpath.c_str());
|
||||
}else{
|
||||
strpath = path;
|
||||
strdel = strpath;
|
||||
nowcache = strpath;
|
||||
s3_realpath = get_realpath(strpath.c_str());
|
||||
result = get_object_attribute(strpath.c_str(), NULL, &meta);
|
||||
}
|
||||
@ -2494,27 +2566,20 @@ static int s3fs_chown_nocopy(const char *path, uid_t uid, gid_t gid) {
|
||||
}
|
||||
|
||||
if(S_ISDIR(stbuf.st_mode)){
|
||||
if(DIRTYPE_NEW != nDirType){
|
||||
// directory object of old version
|
||||
// Need to remove old dir("dir") and make new dir("dir/")
|
||||
// Should rebuild all directory object
|
||||
// Need to remove old dir("dir" etc) and make new dir("dir/")
|
||||
|
||||
// At first, remove directory old object
|
||||
// At first, remove directory old object
|
||||
if(IS_RMTYPEDIR(nDirType)){
|
||||
if(0 != (result = curl_delete(s3_realpath.c_str()))){
|
||||
return result;
|
||||
}
|
||||
StatCache::getStatCacheData()->DelStat(strdel);
|
||||
}
|
||||
StatCache::getStatCacheData()->DelStat(nowcache);
|
||||
|
||||
// Make new directory object("dir/")
|
||||
if(0 != (result = create_directory_object(strpath.c_str(), stbuf.st_mode, stbuf.st_mtime, uid, gid))){
|
||||
return result;
|
||||
}
|
||||
}else{
|
||||
// directory object of new version
|
||||
// Over put directory object.
|
||||
if(0 != (result = create_directory_object(strpath.c_str(), stbuf.st_mode, stbuf.st_mtime, uid, gid))){
|
||||
return result;
|
||||
}
|
||||
StatCache::getStatCacheData()->DelStat(strdel);
|
||||
// Make new directory object("dir/")
|
||||
if(0 != (result = create_directory_object(newpath.c_str(), stbuf.st_mode, stbuf.st_mtime, uid, gid))){
|
||||
return result;
|
||||
}
|
||||
}else{
|
||||
// normal object or directory object of newer version
|
||||
@ -2553,7 +2618,7 @@ static int s3fs_chown_nocopy(const char *path, uid_t uid, gid_t gid) {
|
||||
if(isclose){
|
||||
close(fd);
|
||||
}
|
||||
StatCache::getStatCacheData()->DelStat(strdel);
|
||||
StatCache::getStatCacheData()->DelStat(nowcache);
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -3380,7 +3445,8 @@ static int s3fs_utimens(const char *path, const struct timespec ts[2]) {
|
||||
int result;
|
||||
string s3_realpath;
|
||||
string strpath;
|
||||
string strdel;
|
||||
string newpath;
|
||||
string nowcache;
|
||||
headers_t meta;
|
||||
struct stat stbuf;
|
||||
int nDirType = DIRTYPE_UNKNOWN;
|
||||
@ -3395,11 +3461,11 @@ static int s3fs_utimens(const char *path, const struct timespec ts[2]) {
|
||||
}
|
||||
|
||||
if(S_ISDIR(stbuf.st_mode)){
|
||||
result = chk_dir_object_type(path, strpath, strdel, &meta, &nDirType);
|
||||
s3_realpath = get_realpath(strdel.c_str());
|
||||
result = chk_dir_object_type(path, newpath, strpath, nowcache, &meta, &nDirType);
|
||||
s3_realpath = get_realpath(strpath.c_str());
|
||||
}else{
|
||||
strpath = path;
|
||||
strdel = strpath;
|
||||
nowcache = strpath;
|
||||
s3_realpath = get_realpath(strpath.c_str());
|
||||
result = get_object_attribute(strpath.c_str(), NULL, &meta);
|
||||
}
|
||||
@ -3407,18 +3473,20 @@ static int s3fs_utimens(const char *path, const struct timespec ts[2]) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if(S_ISDIR(stbuf.st_mode) && DIRTYPE_NEW != nDirType){
|
||||
// directory object of old version
|
||||
// Need to remove old dir("dir") and make new dir("dir/")
|
||||
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/")
|
||||
|
||||
// At first, remove directory old object
|
||||
if(0 != (result = curl_delete(s3_realpath.c_str()))){
|
||||
return result;
|
||||
if(IS_RMTYPEDIR(nDirType)){
|
||||
if(0 != (result = curl_delete(s3_realpath.c_str()))){
|
||||
return result;
|
||||
}
|
||||
}
|
||||
StatCache::getStatCacheData()->DelStat(strdel);
|
||||
StatCache::getStatCacheData()->DelStat(nowcache);
|
||||
|
||||
// Make new directory object("dir/")
|
||||
if(0 != (result = create_directory_object(strpath.c_str(), stbuf.st_mode, ts[1].tv_sec, stbuf.st_uid, stbuf.st_gid))){
|
||||
if(0 != (result = create_directory_object(newpath.c_str(), stbuf.st_mode, ts[1].tv_sec, stbuf.st_uid, stbuf.st_gid))){
|
||||
return result;
|
||||
}
|
||||
}else{
|
||||
@ -3429,7 +3497,7 @@ static int s3fs_utimens(const char *path, const struct timespec ts[2]) {
|
||||
if(put_headers(strpath.c_str(), meta) != 0){
|
||||
return -EIO;
|
||||
}
|
||||
StatCache::getStatCacheData()->DelStat(strdel);
|
||||
StatCache::getStatCacheData()->DelStat(nowcache);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -3439,7 +3507,8 @@ static int s3fs_utimens_nocopy(const char *path, const struct timespec ts[2]) {
|
||||
int result;
|
||||
string s3_realpath;
|
||||
string strpath;
|
||||
string strdel;
|
||||
string newpath;
|
||||
string nowcache;
|
||||
headers_t meta;
|
||||
struct stat stbuf;
|
||||
int nDirType = DIRTYPE_UNKNOWN;
|
||||
@ -3455,11 +3524,11 @@ static int s3fs_utimens_nocopy(const char *path, const struct timespec ts[2]) {
|
||||
|
||||
// Get attributes
|
||||
if(S_ISDIR(stbuf.st_mode)){
|
||||
result = chk_dir_object_type(path, strpath, strdel, &meta, &nDirType);
|
||||
s3_realpath = get_realpath(strdel.c_str());
|
||||
result = chk_dir_object_type(path, newpath, strpath, nowcache, &meta, &nDirType);
|
||||
s3_realpath = get_realpath(strpath.c_str());
|
||||
}else{
|
||||
strpath = path;
|
||||
strdel = strpath;
|
||||
nowcache = strpath;
|
||||
s3_realpath = get_realpath(strpath.c_str());
|
||||
result = get_object_attribute(strpath.c_str(), NULL, &meta);
|
||||
}
|
||||
@ -3468,27 +3537,20 @@ static int s3fs_utimens_nocopy(const char *path, const struct timespec ts[2]) {
|
||||
}
|
||||
|
||||
if(S_ISDIR(stbuf.st_mode)){
|
||||
if(DIRTYPE_NEW != nDirType){
|
||||
// directory object of old version
|
||||
// Need to remove old dir("dir") and make new dir("dir/")
|
||||
// Should rebuild all directory object
|
||||
// Need to remove old dir("dir" etc) and make new dir("dir/")
|
||||
|
||||
// At first, remove directory old object
|
||||
// At first, remove directory old object
|
||||
if(IS_RMTYPEDIR(nDirType)){
|
||||
if(0 != (result = curl_delete(s3_realpath.c_str()))){
|
||||
return result;
|
||||
}
|
||||
StatCache::getStatCacheData()->DelStat(strdel);
|
||||
}
|
||||
StatCache::getStatCacheData()->DelStat(nowcache);
|
||||
|
||||
// Make new directory object("dir/")
|
||||
if(0 != (result = create_directory_object(strpath.c_str(), stbuf.st_mode, ts[1].tv_sec, stbuf.st_uid, stbuf.st_gid))){
|
||||
return result;
|
||||
}
|
||||
}else{
|
||||
// directory object of new version
|
||||
// Over put directory object.
|
||||
if(0 != (result = create_directory_object(strpath.c_str(), stbuf.st_mode, ts[1].tv_sec, stbuf.st_uid, stbuf.st_gid))){
|
||||
return result;
|
||||
}
|
||||
StatCache::getStatCacheData()->DelStat(strdel);
|
||||
// Make new directory object("dir/")
|
||||
if(0 != (result = create_directory_object(newpath.c_str(), stbuf.st_mode, ts[1].tv_sec, stbuf.st_uid, stbuf.st_gid))){
|
||||
return result;
|
||||
}
|
||||
}else{
|
||||
// normal object or directory object of newer version
|
||||
@ -3529,7 +3591,7 @@ static int s3fs_utimens_nocopy(const char *path, const struct timespec ts[2]) {
|
||||
if(isclose){
|
||||
close(fd);
|
||||
}
|
||||
StatCache::getStatCacheData()->DelStat(strdel);
|
||||
StatCache::getStatCacheData()->DelStat(nowcache);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -241,10 +241,52 @@ bool S3ObjList::GetNameList(s3obj_list_t& list, bool OnlyNormalized, bool CutSla
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef std::map<std::string, bool> s3obj_h_t;
|
||||
|
||||
bool S3ObjList::MakeHierarchizedList(s3obj_list_t& list, bool haveSlash)
|
||||
{
|
||||
s3obj_h_t h_map;
|
||||
s3obj_h_t::iterator hiter;
|
||||
s3obj_list_t::const_iterator liter;
|
||||
|
||||
for(liter = list.begin(); list.end() != liter; liter++){
|
||||
string strtmp = (*liter);
|
||||
if(1 < strtmp.length() && '/' == strtmp[strtmp.length() - 1]){
|
||||
strtmp = strtmp.substr(0, strtmp.length() - 1);
|
||||
}
|
||||
h_map[strtmp] = true;
|
||||
|
||||
// check hierarchized directory
|
||||
for(string::size_type pos = strtmp.find_last_of("/"); string::npos != pos; pos = strtmp.find_last_of("/")){
|
||||
strtmp = strtmp.substr(0, pos);
|
||||
if(0 == strtmp.length() || "/" == strtmp){
|
||||
break;
|
||||
}
|
||||
if(h_map.end() == h_map.find(strtmp)){
|
||||
// not found
|
||||
h_map[strtmp] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check map and add lost hierarchized directory.
|
||||
for(hiter = h_map.begin(); hiter != h_map.end(); ++hiter){
|
||||
if(false == (*hiter).second){
|
||||
// add hierarchized directory.
|
||||
string strtmp = (*hiter).first;
|
||||
if(haveSlash){
|
||||
strtmp += "/";
|
||||
}
|
||||
list.push_back(strtmp);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Utility functions for moving objects
|
||||
//-------------------------------------------------------------------
|
||||
MVNODE *create_mvnode(const char *old_path, const char *new_path, bool is_dir)
|
||||
MVNODE *create_mvnode(const char *old_path, const char *new_path, bool is_dir, bool normdir)
|
||||
{
|
||||
MVNODE *p;
|
||||
char *p_old_path;
|
||||
@ -272,9 +314,10 @@ MVNODE *create_mvnode(const char *old_path, const char *new_path, bool is_dir)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
p->old_path = p_old_path;
|
||||
p->new_path = p_new_path;
|
||||
p->is_dir = is_dir;
|
||||
p->old_path = p_old_path;
|
||||
p->new_path = p_new_path;
|
||||
p->is_dir = is_dir;
|
||||
p->is_normdir = normdir;
|
||||
p->prev = NULL;
|
||||
p->next = NULL;
|
||||
return p;
|
||||
@ -283,7 +326,7 @@ MVNODE *create_mvnode(const char *old_path, const char *new_path, bool is_dir)
|
||||
//
|
||||
// Add sorted MVNODE data(Ascending order)
|
||||
//
|
||||
MVNODE *add_mvnode(MVNODE** head, MVNODE** tail, const char *old_path, const char *new_path, bool is_dir)
|
||||
MVNODE *add_mvnode(MVNODE** head, MVNODE** tail, const char *old_path, const char *new_path, bool is_dir, bool normdir)
|
||||
{
|
||||
if(!head || !tail){
|
||||
return NULL;
|
||||
@ -308,7 +351,7 @@ MVNODE *add_mvnode(MVNODE** head, MVNODE** tail, const char *old_path, const cha
|
||||
// Add into before cur-pos.
|
||||
// ex: cur("abc"), mvnew("ab")
|
||||
// ex: cur("abc"), mvnew("abb")
|
||||
if(NULL == (mvnew = create_mvnode(old_path, new_path, is_dir))){
|
||||
if(NULL == (mvnew = create_mvnode(old_path, new_path, is_dir, normdir))){
|
||||
return NULL;
|
||||
}
|
||||
if(cur->prev){
|
||||
@ -325,7 +368,7 @@ MVNODE *add_mvnode(MVNODE** head, MVNODE** tail, const char *old_path, const cha
|
||||
}
|
||||
}
|
||||
// Add into tail.
|
||||
if(NULL == (mvnew = create_mvnode(old_path, new_path, is_dir))){
|
||||
if(NULL == (mvnew = create_mvnode(old_path, new_path, is_dir, normdir))){
|
||||
return NULL;
|
||||
}
|
||||
mvnew->prev = (*tail);
|
||||
|
@ -51,12 +51,15 @@ class S3ObjList
|
||||
std::string GetETag(const char* name) const;
|
||||
bool IsDir(const char* name) const;
|
||||
bool GetNameList(s3obj_list_t& list, bool OnlyNormalized = true, bool CutSlash = true) const;
|
||||
|
||||
static bool MakeHierarchizedList(s3obj_list_t& list, bool haveSlash);
|
||||
};
|
||||
|
||||
typedef struct mvnode {
|
||||
char *old_path;
|
||||
char *new_path;
|
||||
bool is_dir;
|
||||
bool is_normdir;
|
||||
struct mvnode *prev;
|
||||
struct mvnode *next;
|
||||
} MVNODE;
|
||||
@ -66,8 +69,8 @@ typedef struct mvnode {
|
||||
//-------------------------------------------------------------------
|
||||
std::string get_realpath(const char *path);
|
||||
|
||||
MVNODE *create_mvnode(const char *old_path, const char *new_path, bool is_dir);
|
||||
MVNODE *add_mvnode(MVNODE** head, MVNODE** tail, const char *old_path, const char *new_path, bool is_dir);
|
||||
MVNODE *create_mvnode(const char *old_path, const char *new_path, bool is_dir, bool normdir = false);
|
||||
MVNODE *add_mvnode(MVNODE** head, MVNODE** tail, const char *old_path, const char *new_path, bool is_dir, bool normdir = false);
|
||||
void free_mvnodes(MVNODE *head);
|
||||
|
||||
std::string get_username(uid_t uid);
|
||||
|
Loading…
Reference in New Issue
Block a user