diff --git a/src/Makefile.am b/src/Makefile.am index 5741f1b..f102c42 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -24,7 +24,7 @@ if USE_GNUTLS_NETTLE AM_CPPFLAGS += -DUSE_GNUTLS_NETTLE endif -s3fs_SOURCES = s3fs.cpp s3fs.h curl.cpp curl.h cache.cpp cache.h string_util.cpp string_util.h s3fs_util.cpp s3fs_util.h fdcache.cpp fdcache.h common_auth.cpp s3fs_auth.h common.h +s3fs_SOURCES = s3fs.cpp s3fs.h curl.cpp curl.h cache.cpp cache.h string_util.cpp string_util.h s3fs_util.cpp s3fs_util.h fdcache.cpp fdcache.h common_auth.cpp s3fs_auth.h addhead.cpp addhead.h common.h if USE_SSL_OPENSSL s3fs_SOURCES += openssl_auth.cpp endif diff --git a/src/addhead.cpp b/src/addhead.cpp new file mode 100644 index 0000000..be4036f --- /dev/null +++ b/src/addhead.cpp @@ -0,0 +1,286 @@ +/* + * s3fs - FUSE-based file system backed by Amazon S3 + * + * Copyright 2007-2008 Randy Rizun + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "addhead.h" +#include "curl.h" +#include "s3fs.h" + +using namespace std; + +//------------------------------------------------------------------- +// Symbols +//------------------------------------------------------------------- +#define ADD_HEAD_REGEX "reg:" + +//------------------------------------------------------------------- +// Class AdditionalHeader +//------------------------------------------------------------------- +AdditionalHeader AdditionalHeader::singleton; + +//------------------------------------------------------------------- +// Class AdditionalHeader method +//------------------------------------------------------------------- +AdditionalHeader::AdditionalHeader() +{ + if(this == AdditionalHeader::get()){ + is_enable = false; + }else{ + assert(false); + } +} + +AdditionalHeader::~AdditionalHeader() +{ + if(this == AdditionalHeader::get()){ + Unload(); + }else{ + assert(false); + } +} + +bool AdditionalHeader::Load(const char* file) +{ + if(!file){ + S3FS_PRN_WARN("file is NULL."); + return false; + } + Unload(); + + ifstream AH(file); + if(!AH.good()){ + S3FS_PRN_WARN("Could not open file(%s).", file); + return false; + } + + // read file + string line; + PADDHEAD paddhead; + while(getline(AH, line)){ + if('#' == line[0]){ + continue; + } + if(0 == line.size()){ + continue; + } + // load a line + stringstream ss(line); + string key(""); // suffix(key) + string head; // additional HTTP header + string value; // header value + if(0 == isblank(line[0])){ + ss >> key; + } + if(ss){ + ss >> head; + if(ss && static_cast(ss.tellg()) < line.size()){ + value = line.substr(static_cast(ss.tellg()) + 1); + } + } + + // check it + if(0 == head.size()){ + if(0 == key.size()){ + continue; + } + S3FS_PRN_ERR("file format error: %s key(suffix) is no HTTP header value.", key.c_str()); + Unload(); + return false; + } + + paddhead = new ADDHEAD; + if(0 == strncasecmp(key.c_str(), ADD_HEAD_REGEX, strlen(ADD_HEAD_REGEX))){ + // regex + if(key.size() <= strlen(ADD_HEAD_REGEX)){ + S3FS_PRN_ERR("file format error: %s key(suffix) does not have key string.", key.c_str()); + continue; + } + key = key.substr(strlen(ADD_HEAD_REGEX)); + + // compile + regex_t* preg = new regex_t; + int result; + char errbuf[256]; + if(0 != (result = regcomp(preg, key.c_str(), REG_EXTENDED | REG_NOSUB))){ // we do not need matching info + regerror(result, preg, errbuf, sizeof(errbuf)); + S3FS_PRN_ERR("failed to compile regex from %s key by %s.", key.c_str(), errbuf); + delete preg; + delete paddhead; + continue; + } + + // set + paddhead->pregex = preg; + paddhead->basestring = key; + paddhead->headkey = head; + paddhead->headvalue = value; + + }else{ + // not regex, directly comparing + paddhead->pregex = NULL; + paddhead->basestring = key; + paddhead->headkey = head; + paddhead->headvalue = value; + } + + // add list + addheadlist.push_back(paddhead); + + // set flag + if(!is_enable){ + is_enable = true; + } + } + return true; +} + +void AdditionalHeader::Unload(void) +{ + is_enable = false; + + for(addheadlist_t::iterator iter = addheadlist.begin(); iter != addheadlist.end(); iter = addheadlist.erase(iter)){ + PADDHEAD paddhead = *iter; + if(paddhead){ + if(paddhead->pregex){ + regfree(paddhead->pregex); + delete paddhead->pregex; + } + delete paddhead; + } + } +} + +bool AdditionalHeader::AddHeader(headers_t& meta, const char* path) const +{ + if(!is_enable){ + return true; + } + if(!path){ + S3FS_PRN_WARN("path is NULL."); + return false; + } + + size_t pathlength = strlen(path); + + // loop + for(addheadlist_t::const_iterator iter = addheadlist.begin(); iter != addheadlist.end(); ++iter){ + const PADDHEAD paddhead = *iter; + if(!paddhead){ + continue; + } + + if(paddhead->pregex){ + // regex + int result; + regmatch_t match; // not use + + if(0 == (result = regexec(paddhead->pregex, path, 1, &match, 0))){ + // match -> adding header + meta[paddhead->headkey] = paddhead->headvalue; + break; + } + }else{ + // directly comparing + if(paddhead->basestring.length() < pathlength){ + if(0 == paddhead->basestring.length() || 0 == strcmp(&path[pathlength - paddhead->basestring.length()], paddhead->basestring.c_str())){ + // match -> adding header + meta[paddhead->headkey] = paddhead->headvalue; + break; + } + } + } + } + return true; +} + +struct curl_slist* AdditionalHeader::AddHeader(struct curl_slist* list, const char* path) const +{ + headers_t meta; + + if(!AddHeader(meta, path)){ + return list; + } + for(headers_t::iterator iter = meta.begin(); iter != meta.end(); ++iter){ + // Adding header + list = curl_slist_sort_insert(list, iter->first.c_str(), iter->second.c_str()); + } + meta.clear(); + S3FS_MALLOCTRIM(0); + return list; +} + +bool AdditionalHeader::Dump(void) const +{ + if(!IS_S3FS_LOG_DBG()){ + return true; + } + + stringstream ssdbg; + int cnt = 1; + + ssdbg << "Additional Header list[" << addheadlist.size() << "] = {" << endl; + + for(addheadlist_t::const_iterator iter = addheadlist.begin(); iter != addheadlist.end(); ++iter, ++cnt){ + const PADDHEAD paddhead = *iter; + + ssdbg << " [" << cnt << "] = {" << endl; + + if(paddhead){ + if(paddhead->pregex){ + ssdbg << " type\t\t--->\tregex" << endl; + }else{ + ssdbg << " type\t\t--->\tsuffix matching" << endl; + } + ssdbg << " base string\t--->\t" << paddhead->basestring << endl; + ssdbg << " add header\t--->\t" << paddhead->headkey << ": " << paddhead->headvalue << endl; + } + ssdbg << " }" << endl; + } + + + ssdbg << "}" << endl; + + // print all + S3FS_PRN_DBG("%s", ssdbg.str().c_str()); + + return true; +} + +/* +* Local variables: +* tab-width: 4 +* c-basic-offset: 4 +* End: +* vim600: noet sw=4 ts=4 fdm=marker +* vim<600: noet sw=4 ts=4 +*/ diff --git a/src/addhead.h b/src/addhead.h new file mode 100644 index 0000000..c2ef9b1 --- /dev/null +++ b/src/addhead.h @@ -0,0 +1,70 @@ +/* + * s3fs - FUSE-based file system backed by Amazon S3 + * + * Copyright 2007-2008 Randy Rizun + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef S3FS_ADDHEAD_H_ +#define S3FS_ADDHEAD_H_ + +#include + +//---------------------------------------------- +// class AdditionalHeader +//---------------------------------------------- +typedef struct add_header{ + regex_t* pregex; // not NULL means using regex, NULL means comparing suffix directly. + std::string basestring; + std::string headkey; + std::string headvalue; +}ADDHEAD, *PADDHEAD; + +typedef std::vector addheadlist_t; + +class AdditionalHeader +{ + private: + static AdditionalHeader singleton; + bool is_enable; + addheadlist_t addheadlist; + + protected: + AdditionalHeader(); + ~AdditionalHeader(); + + public: + // Reference singleton + static AdditionalHeader* get(void) { return &singleton; } + + bool Load(const char* file); + void Unload(void); + + bool AddHeader(headers_t& meta, const char* path) const; + struct curl_slist* AddHeader(struct curl_slist* list, const char* path) const; + bool Dump(void) const; +}; + +#endif // S3FS_ADDHEAD_H_ + +/* +* Local variables: +* tab-width: 4 +* c-basic-offset: 4 +* End: +* vim600: noet sw=4 ts=4 fdm=marker +* vim<600: noet sw=4 ts=4 +*/ diff --git a/src/curl.cpp b/src/curl.cpp index 91902af..942ca6a 100644 --- a/src/curl.cpp +++ b/src/curl.cpp @@ -48,6 +48,7 @@ #include "s3fs.h" #include "s3fs_util.h" #include "s3fs_auth.h" +#include "addhead.h" using namespace std; @@ -3780,244 +3781,6 @@ int S3fsMultiCurl::Request(void) return 0; } -//------------------------------------------------------------------- -// Symbols -//------------------------------------------------------------------- -#define ADD_HEAD_REGEX "reg:" - -//------------------------------------------------------------------- -// Class AdditionalHeader -//------------------------------------------------------------------- -AdditionalHeader AdditionalHeader::singleton; - -//------------------------------------------------------------------- -// Class AdditionalHeader method -//------------------------------------------------------------------- -AdditionalHeader::AdditionalHeader() -{ - if(this == AdditionalHeader::get()){ - is_enable = false; - }else{ - assert(false); - } -} - -AdditionalHeader::~AdditionalHeader() -{ - if(this == AdditionalHeader::get()){ - Unload(); - }else{ - assert(false); - } -} - -bool AdditionalHeader::Load(const char* file) -{ - if(!file){ - S3FS_PRN_WARN("file is NULL."); - return false; - } - Unload(); - - ifstream AH(file); - if(!AH.good()){ - S3FS_PRN_WARN("Could not open file(%s).", file); - return false; - } - - // read file - string line; - PADDHEAD paddhead; - while(getline(AH, line)){ - if('#' == line[0]){ - continue; - } - if(0 == line.size()){ - continue; - } - // load a line - stringstream ss(line); - string key(""); // suffix(key) - string head; // additional HTTP header - string value; // header value - if(0 == isblank(line[0])){ - ss >> key; - } - if(ss){ - ss >> head; - if(ss && static_cast(ss.tellg()) < line.size()){ - value = line.substr(static_cast(ss.tellg()) + 1); - } - } - - // check it - if(0 == head.size()){ - if(0 == key.size()){ - continue; - } - S3FS_PRN_ERR("file format error: %s key(suffix) is no HTTP header value.", key.c_str()); - Unload(); - return false; - } - - paddhead = new ADDHEAD; - if(0 == strncasecmp(key.c_str(), ADD_HEAD_REGEX, strlen(ADD_HEAD_REGEX))){ - // regex - if(key.size() <= strlen(ADD_HEAD_REGEX)){ - S3FS_PRN_ERR("file format error: %s key(suffix) does not have key string.", key.c_str()); - continue; - } - key = key.substr(strlen(ADD_HEAD_REGEX)); - - // compile - regex_t* preg = new regex_t; - int result; - char errbuf[256]; - if(0 != (result = regcomp(preg, key.c_str(), REG_EXTENDED | REG_NOSUB))){ // we do not need matching info - regerror(result, preg, errbuf, sizeof(errbuf)); - S3FS_PRN_ERR("failed to compile regex from %s key by %s.", key.c_str(), errbuf); - delete preg; - delete paddhead; - continue; - } - - // set - paddhead->pregex = preg; - paddhead->basestring = key; - paddhead->headkey = head; - paddhead->headvalue = value; - - }else{ - // not regex, directly comparing - paddhead->pregex = NULL; - paddhead->basestring = key; - paddhead->headkey = head; - paddhead->headvalue = value; - } - - // add list - addheadlist.push_back(paddhead); - - // set flag - if(!is_enable){ - is_enable = true; - } - } - return true; -} - -void AdditionalHeader::Unload(void) -{ - is_enable = false; - - for(addheadlist_t::iterator iter = addheadlist.begin(); iter != addheadlist.end(); iter = addheadlist.erase(iter)){ - PADDHEAD paddhead = *iter; - if(paddhead){ - if(paddhead->pregex){ - regfree(paddhead->pregex); - delete paddhead->pregex; - } - delete paddhead; - } - } -} - -bool AdditionalHeader::AddHeader(headers_t& meta, const char* path) const -{ - if(!is_enable){ - return true; - } - if(!path){ - S3FS_PRN_WARN("path is NULL."); - return false; - } - - size_t pathlength = strlen(path); - - // loop - for(addheadlist_t::const_iterator iter = addheadlist.begin(); iter != addheadlist.end(); ++iter){ - const PADDHEAD paddhead = *iter; - if(!paddhead){ - continue; - } - - if(paddhead->pregex){ - // regex - int result; - regmatch_t match; // not use - - if(0 == (result = regexec(paddhead->pregex, path, 1, &match, 0))){ - // match -> adding header - meta[paddhead->headkey] = paddhead->headvalue; - break; - } - }else{ - // directly comparing - if(paddhead->basestring.length() < pathlength){ - if(0 == paddhead->basestring.length() || 0 == strcmp(&path[pathlength - paddhead->basestring.length()], paddhead->basestring.c_str())){ - // match -> adding header - meta[paddhead->headkey] = paddhead->headvalue; - break; - } - } - } - } - return true; -} - -struct curl_slist* AdditionalHeader::AddHeader(struct curl_slist* list, const char* path) const -{ - headers_t meta; - - if(!AddHeader(meta, path)){ - return list; - } - for(headers_t::iterator iter = meta.begin(); iter != meta.end(); ++iter){ - // Adding header - list = curl_slist_sort_insert(list, iter->first.c_str(), iter->second.c_str()); - } - meta.clear(); - S3FS_MALLOCTRIM(0); - return list; -} - -bool AdditionalHeader::Dump(void) const -{ - if(!IS_S3FS_LOG_DBG()){ - return true; - } - - stringstream ssdbg; - int cnt = 1; - - ssdbg << "Additional Header list[" << addheadlist.size() << "] = {" << endl; - - for(addheadlist_t::const_iterator iter = addheadlist.begin(); iter != addheadlist.end(); ++iter, ++cnt){ - const PADDHEAD paddhead = *iter; - - ssdbg << " [" << cnt << "] = {" << endl; - - if(paddhead){ - if(paddhead->pregex){ - ssdbg << " type\t\t--->\tregex" << endl; - }else{ - ssdbg << " type\t\t--->\tsuffix matching" << endl; - } - ssdbg << " base string\t--->\t" << paddhead->basestring << endl; - ssdbg << " add header\t--->\t" << paddhead->headkey << ": " << paddhead->headvalue << endl; - } - ssdbg << " }" << endl; - } - - - ssdbg << "}" << endl; - - // print all - S3FS_PRN_DBG("%s", ssdbg.str().c_str()); - - return true; -} - //------------------------------------------------------------------- // Utility functions //------------------------------------------------------------------- diff --git a/src/curl.h b/src/curl.h index 5d0a989..92b5db0 100644 --- a/src/curl.h +++ b/src/curl.h @@ -17,6 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + #ifndef S3FS_CURL_H_ #define S3FS_CURL_H_ @@ -425,43 +426,6 @@ class S3fsMultiCurl int Request(void); }; -//---------------------------------------------- -// class AdditionalHeader -//---------------------------------------------- -#include - -typedef struct add_header{ - regex_t* pregex; // not NULL means using regex, NULL means comparing suffix directly. - std::string basestring; - std::string headkey; - std::string headvalue; -}ADDHEAD, *PADDHEAD; - -typedef std::vector addheadlist_t; - -class AdditionalHeader -{ - private: - static AdditionalHeader singleton; - bool is_enable; - addheadlist_t addheadlist; - - protected: - AdditionalHeader(); - ~AdditionalHeader(); - - public: - // Reference singleton - static AdditionalHeader* get(void) { return &singleton; } - - bool Load(const char* file); - void Unload(void); - - bool AddHeader(headers_t& meta, const char* path) const; - struct curl_slist* AddHeader(struct curl_slist* list, const char* path) const; - bool Dump(void) const; -}; - //---------------------------------------------- // Utility Functions //---------------------------------------------- diff --git a/src/s3fs.cpp b/src/s3fs.cpp index 8b3e2fc..c0c941b 100644 --- a/src/s3fs.cpp +++ b/src/s3fs.cpp @@ -52,6 +52,7 @@ #include "s3fs_util.h" #include "fdcache.h" #include "s3fs_auth.h" +#include "addhead.h" using namespace std;