mirror of
https://github.com/s3fs-fuse/s3fs-fuse.git
synced 2025-04-11 02:51:52 +00:00
Fixed issue: 27
1) Feature Request: Compatability with other S3FS clients(Issue: 27) Supported the directory object which made by s3fox. Its name has "_$folder$" suffixes. On s3fs, that directory object is listed normal directory name without "_$folder$". You need careful when you change object attributes(rename, chmod, chown, touch), because the s3fs remakes the directory object after that object(which has "_$folder$" suffix) After changing the object attributes, the object name does not have "_$folder$" suffix. It means the object is remade by s3fs. 2) Other Fixes bugs which are found when this issue is fixed. git-svn-id: http://s3fs.googlecode.com/svn/trunk@413 df820570-a93a-0410-bd06-b72b767a4274
This commit is contained in:
parent
eaf43e6f59
commit
36447a23eb
@ -28,6 +28,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
#include "cache.h"
|
#include "cache.h"
|
||||||
#include "s3fs_util.h"
|
#include "s3fs_util.h"
|
||||||
|
522
src/s3fs.cpp
522
src/s3fs.cpp
File diff suppressed because it is too large
Load Diff
@ -31,6 +31,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "s3fs_util.h"
|
#include "s3fs_util.h"
|
||||||
@ -54,132 +55,190 @@ string get_realpath(const char *path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Utility for listing objects
|
// Class S3ObjList
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// [Change]
|
// New class S3ObjList is base on old s3_object struct.
|
||||||
// The s3_object's name member can be set "dir" or "dir/" as directory name.
|
// This class is for S3 compatible clients.
|
||||||
// Both of names are same directory s3_object.
|
|
||||||
// "dir/" is given priority to over "dir".
|
|
||||||
//
|
//
|
||||||
// [Notice]
|
// If name is terminated by "/", it is forced dir type.
|
||||||
// If there are "dir" and "dir/" object on S3, s3fs only recognizes "dir/".
|
// If name is terminated by "_$folder$", it is forced dir type.
|
||||||
// On this case, user can not know the "dir" object.
|
// If is_dir is true and name is not terminated by "/", the name is added "/".
|
||||||
//
|
//
|
||||||
int insert_object(const char* name, const char* etag, struct s3_object** head)
|
bool S3ObjList::insert(const char* name, const char* etag, bool is_dir)
|
||||||
{
|
{
|
||||||
struct s3_object *cur_object;
|
if(!name || '\0' == name[0]){
|
||||||
struct s3_object *new_object;
|
return false;
|
||||||
int nLen = name ? strlen(name) : 0;
|
|
||||||
int is_have_ndelimiter = 0;
|
|
||||||
|
|
||||||
// search same name object
|
|
||||||
if(nLen && '/' == name[nLen - 1]){
|
|
||||||
// case of "dir/"
|
|
||||||
nLen--;
|
|
||||||
is_have_ndelimiter = 1;
|
|
||||||
}
|
}
|
||||||
for(cur_object = *head; nLen && cur_object; cur_object = cur_object->next){
|
|
||||||
if(0 == strncmp(cur_object->name, name, nLen)){
|
|
||||||
int cLen = strlen(cur_object->name);
|
|
||||||
int is_have_cdelimiter = 0;
|
|
||||||
|
|
||||||
if('/' == cur_object->name[cLen - 1]){
|
s3obj_t::iterator iter;
|
||||||
cLen--;
|
string newname;
|
||||||
is_have_cdelimiter = 1;
|
string orgname = name;
|
||||||
}
|
|
||||||
if(cLen == nLen){
|
// Normalization
|
||||||
if(is_have_cdelimiter == is_have_ndelimiter){
|
string::size_type pos = orgname.find("_$folder$");
|
||||||
// perfect same object, replace only etag.
|
if(string::npos != pos){
|
||||||
}else if(is_have_cdelimiter){
|
newname = orgname.substr(0, pos);
|
||||||
// already set "dir/", so not need to add this.
|
is_dir = true;
|
||||||
return 0;
|
|
||||||
}else{
|
}else{
|
||||||
// new object is "dir/", replace name and etag
|
newname = orgname;
|
||||||
free(cur_object->name);
|
}
|
||||||
if(NULL == (cur_object->name = strdup(name))){
|
if(is_dir){
|
||||||
printf("insert_object: could not allocate memory\n");
|
if('/' != newname[newname.length() - 1]){
|
||||||
S3FS_FUSE_EXIT();
|
newname += "/";
|
||||||
return -1;
|
}
|
||||||
|
}else{
|
||||||
|
if('/' == newname[newname.length() - 1]){
|
||||||
|
is_dir = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// replace etag.
|
|
||||||
if(cur_object->etag){
|
// Check derived name object.
|
||||||
free(cur_object->etag);
|
if(is_dir){
|
||||||
cur_object->etag = NULL;
|
string chkname = newname.substr(0, newname.length() - 1);
|
||||||
|
if(objects.end() != (iter = objects.find(chkname))){
|
||||||
|
// found "dir" object --> remove it.
|
||||||
|
objects.erase(iter);
|
||||||
}
|
}
|
||||||
|
}else{
|
||||||
|
string chkname = newname + "/";
|
||||||
|
if(objects.end() != (iter = objects.find(chkname))){
|
||||||
|
// found "dir/" object --> not add new object.
|
||||||
|
// and add normalization
|
||||||
|
return insert_nomalized(orgname.c_str(), chkname.c_str(), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add object
|
||||||
|
if(objects.end() != (iter = objects.find(newname))){
|
||||||
|
// Found same object --> update information.
|
||||||
|
(*iter).second.normalname.erase();
|
||||||
|
(*iter).second.orgname = orgname;
|
||||||
|
(*iter).second.is_dir = is_dir;
|
||||||
if(etag){
|
if(etag){
|
||||||
if(NULL == (cur_object->etag = strdup(etag))){
|
(*iter).second.etag = string(etag); // over write
|
||||||
printf("insert_object: could not allocate memory\n");
|
|
||||||
S3FS_FUSE_EXIT();
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Not found same object.
|
|
||||||
new_object = (struct s3_object*)malloc(sizeof(struct s3_object));
|
|
||||||
if(new_object == NULL) {
|
|
||||||
printf("insert_object: could not allocate memory\n");
|
|
||||||
S3FS_FUSE_EXIT();
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(NULL == (new_object->name = strdup(name))){
|
|
||||||
free(new_object);
|
|
||||||
printf("insert_object: could not allocate memory\n");
|
|
||||||
S3FS_FUSE_EXIT();
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
}else{
|
||||||
|
// add new object
|
||||||
|
s3obj_entry newobject;
|
||||||
|
newobject.orgname = orgname;
|
||||||
|
newobject.is_dir = is_dir;
|
||||||
if(etag){
|
if(etag){
|
||||||
if(NULL == (new_object->etag = strdup(etag))){
|
newobject.etag = etag;
|
||||||
free(new_object->name);
|
|
||||||
free(new_object);
|
|
||||||
printf("insert_object: could not allocate memory\n");
|
|
||||||
S3FS_FUSE_EXIT();
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
}else{
|
objects[newname] = newobject;
|
||||||
new_object->etag = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if((*head) == NULL){
|
// add normalization
|
||||||
new_object->next = NULL;
|
return insert_nomalized(orgname.c_str(), newname.c_str(), is_dir);
|
||||||
}else{
|
|
||||||
new_object->next = (*head);
|
|
||||||
}
|
|
||||||
*head = new_object;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int free_object(struct s3_object *object)
|
bool S3ObjList::insert_nomalized(const char* name, const char* normalized, bool is_dir)
|
||||||
{
|
{
|
||||||
free(object->name);
|
if(!name || '\0' == name[0] || !normalized || '\0' == normalized[0]){
|
||||||
if(object->etag){
|
return false;
|
||||||
free(object->etag);
|
}
|
||||||
|
if(0 == strcmp(name, normalized)){
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
free(object);
|
|
||||||
object = NULL;
|
|
||||||
|
|
||||||
return 0;
|
s3obj_t::iterator iter;
|
||||||
|
if(objects.end() != (iter = objects.find(name))){
|
||||||
|
// found name --> over write
|
||||||
|
(*iter).second.orgname.erase();
|
||||||
|
(*iter).second.etag.erase();
|
||||||
|
(*iter).second.normalname = normalized;
|
||||||
|
(*iter).second.is_dir = is_dir;
|
||||||
|
}else{
|
||||||
|
// not found --> add new object
|
||||||
|
s3obj_entry newobject;
|
||||||
|
newobject.normalname = normalized;
|
||||||
|
newobject.is_dir = is_dir;
|
||||||
|
objects[name] = newobject;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int free_object_list(struct s3_object *head)
|
const s3obj_entry* S3ObjList::GetS3Obj(const char* name) const
|
||||||
{
|
{
|
||||||
struct s3_object *tmp = NULL;
|
s3obj_t::const_iterator iter;
|
||||||
struct s3_object *current = head;
|
|
||||||
|
|
||||||
current = head;
|
if(!name || '\0' == name[0]){
|
||||||
while(current != NULL) {
|
return NULL;
|
||||||
tmp = current;
|
|
||||||
current = current->next;
|
|
||||||
free_object(tmp);
|
|
||||||
}
|
}
|
||||||
|
if(objects.end() == (iter = objects.find(name))){
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return &((*iter).second);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
string S3ObjList::GetOrgName(const char* name) const
|
||||||
|
{
|
||||||
|
const s3obj_entry* ps3obj;
|
||||||
|
|
||||||
|
if(!name || '\0' == name[0]){
|
||||||
|
return string("");
|
||||||
|
}
|
||||||
|
if(NULL == (ps3obj = GetS3Obj(name))){
|
||||||
|
return string("");
|
||||||
|
}
|
||||||
|
return ps3obj->orgname;
|
||||||
|
}
|
||||||
|
|
||||||
|
string S3ObjList::GetNormalizedName(const char* name) const
|
||||||
|
{
|
||||||
|
const s3obj_entry* ps3obj;
|
||||||
|
|
||||||
|
if(!name || '\0' == name[0]){
|
||||||
|
return string("");
|
||||||
|
}
|
||||||
|
if(NULL == (ps3obj = GetS3Obj(name))){
|
||||||
|
return string("");
|
||||||
|
}
|
||||||
|
if(0 == (ps3obj->normalname).length()){
|
||||||
|
return string(name);
|
||||||
|
}
|
||||||
|
return ps3obj->normalname;
|
||||||
|
}
|
||||||
|
|
||||||
|
string S3ObjList::GetETag(const char* name) const
|
||||||
|
{
|
||||||
|
const s3obj_entry* ps3obj;
|
||||||
|
|
||||||
|
if(!name || '\0' == name[0]){
|
||||||
|
return string("");
|
||||||
|
}
|
||||||
|
if(NULL == (ps3obj = GetS3Obj(name))){
|
||||||
|
return string("");
|
||||||
|
}
|
||||||
|
return ps3obj->etag;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool S3ObjList::IsDir(const char* name) const
|
||||||
|
{
|
||||||
|
const s3obj_entry* ps3obj;
|
||||||
|
|
||||||
|
if(NULL == (ps3obj = GetS3Obj(name))){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return ps3obj->is_dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool S3ObjList::GetNameList(s3obj_list_t& list, bool OnlyNormalized, bool CutSlash) const
|
||||||
|
{
|
||||||
|
s3obj_t::const_iterator iter;
|
||||||
|
|
||||||
|
for(iter = objects.begin(); objects.end() != iter; iter++){
|
||||||
|
if(OnlyNormalized && 0 != (*iter).second.normalname.length()){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
string name = (*iter).first;
|
||||||
|
if(CutSlash && 1 < name.length() && '/' == name[name.length() - 1]){
|
||||||
|
// only "/" string is skio this.
|
||||||
|
name = name.substr(0, name.length() - 1);
|
||||||
|
}
|
||||||
|
list.push_back(name);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
|
@ -4,10 +4,53 @@
|
|||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Typedef
|
// Typedef
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
struct s3_object {
|
//
|
||||||
char* name;
|
// Struct
|
||||||
char* etag;
|
//
|
||||||
struct s3_object *next;
|
struct s3obj_entry{
|
||||||
|
std::string normalname; // normalized name: if empty, object is nomalized name.
|
||||||
|
std::string orgname; // original name: if empty, object is original name.
|
||||||
|
std::string etag;
|
||||||
|
bool is_dir;
|
||||||
|
|
||||||
|
s3obj_entry() : is_dir(false) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::map<std::string, struct s3obj_entry> s3obj_t;
|
||||||
|
typedef std::list<std::string> s3obj_list_t;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Class
|
||||||
|
//
|
||||||
|
class S3ObjList
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
s3obj_t objects;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool insert_nomalized(const char* name, const char* normalized, bool is_dir);
|
||||||
|
const s3obj_entry* GetS3Obj(const char* name) const;
|
||||||
|
|
||||||
|
s3obj_t::const_iterator begin(void) const {
|
||||||
|
return objects.begin();
|
||||||
|
}
|
||||||
|
s3obj_t::const_iterator end(void) const {
|
||||||
|
return objects.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
S3ObjList() {}
|
||||||
|
~S3ObjList() {}
|
||||||
|
|
||||||
|
bool IsEmpty(void) const {
|
||||||
|
return objects.empty();
|
||||||
|
}
|
||||||
|
bool insert(const char* name, const char* etag = NULL, bool is_dir = false);
|
||||||
|
std::string GetOrgName(const char* name) const;
|
||||||
|
std::string GetNormalizedName(const char* name) const;
|
||||||
|
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;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct mvnode {
|
typedef struct mvnode {
|
||||||
@ -18,16 +61,11 @@ typedef struct mvnode {
|
|||||||
struct mvnode *next;
|
struct mvnode *next;
|
||||||
} MVNODE;
|
} MVNODE;
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Functions
|
// Functions
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
std::string get_realpath(const char *path);
|
std::string get_realpath(const char *path);
|
||||||
|
|
||||||
int insert_object(const char* name, const char* etag, struct s3_object** head);
|
|
||||||
int free_object(struct s3_object *object);
|
|
||||||
int free_object_list(struct s3_object *head);
|
|
||||||
|
|
||||||
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);
|
||||||
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);
|
||||||
void free_mvnodes(MVNODE *head);
|
void free_mvnodes(MVNODE *head);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user