10 #ifndef OPENDDS_SAFETY_PROFILE 31 const size_t FSS_MAX_FILE_NAME = 150, FSS_MAX_FILE_NAME_ENCODED = 240,
32 FSS_MAX_OVERFLOW_DIR = 9999;
38 if (str.
length() == 0)
return;
51 for (
size_t i = logical.
length() - 1; i >= 1; --i) {
54 if (logical[i] < 0x7F) {
71 #if defined ACE_WIN32 && !defined ACE_HAS_WINCE 76 idx = str.
find(L
'/', idx + 1)) {
92 fwd_slash_to_back_slash(wpath);
95 if (is_relative(path)) {
96 DWORD sz = ::GetCurrentDirectoryW(0, 0);
99 ::GetCurrentDirectoryW(sz, &cur[0]);
102 if (dir[dir.
length() - 1] != L
'\\') dir += L
'\\';
105 if (dir.
substr(0, 4) != L
"\\\\?\\" && wpath.
substr(0, 4) != L
"\\\\?\\")
106 dir = L
"\\\\?\\" + dir;
116 ace_result_), int, -1);
124 wchar_t spath[MAX_PATH];
126 if (0 == ::GetShortPathNameW(wpath.
c_str(), spath, MAX_PATH)) {
127 throw std::runtime_error(
"GetShortPathNameW failed.");
130 return ::_wchdir(spath);
136 DWORD attrib = ::GetFileAttributesW(wpath.
c_str());
138 if (attrib != INVALID_FILE_ATTRIBUTES) {
139 return attrib & FILE_ATTRIBUTE_DIRECTORY;
149 ace_result_), int, -1);
154 inline int dds_mkdir(
const ACE_TCHAR* path)
159 inline int dds_chdir(
const ACE_TCHAR* path)
164 inline bool is_dir(
const ACE_TCHAR* path)
167 return ACE_OS::stat(path, &st) != -1 && (st.st_mode & S_IFDIR);
170 inline int dds_rmdir(
const ACE_TCHAR* path)
179 const size_t buf_size=32;
193 if (errno == ERANGE) {
199 if (cwd_buf[0]) cwd_ = &cwd_buf[0];
201 dds_chdir(dir.
c_str());
205 dds_chdir(cwd_.
c_str());
214 CwdGuard cg(dirname);
216 for (
DDS_DIRENT* ent = dir.read(); ent; ent = dir.read()) {
217 if (ent->d_name[0] ==
ACE_TEXT(
'.') && (!ent->d_name[1] ||
218 (ent->d_name[1] ==
ACE_TEXT(
'.') && !ent->d_name[2]))) {
222 if (is_dir(ent->d_name)) {
223 recursive_remove(ent->d_name);
230 dds_rmdir(dirname.
c_str());
238 namespace FileSystemStorage {
246 wchar_t* directory_name_;
249 HANDLE current_handle_;
255 WIN32_FIND_DATAW fdata_;
258 int started_reading_;
266 if (path)
open(path);
269 int DDS_Dirent::open(
const ACE_TCHAR* path)
276 to_win32_long_path(path);
281 wchar_t extra[3] = {0, 0, 0};
282 const wchar_t* filename = wpath.
c_str();
285 DWORD fileAttribute = ::GetFileAttributesW(filename);
287 if (fileAttribute == INVALID_FILE_ATTRIBUTES) {
292 if (!(fileAttribute & FILE_ATTRIBUTE_DIRECTORY)) {
300 if (filename[lastchar-1] != L
'*') {
301 if (filename[lastchar-1] != L
'/' && filename[lastchar-1] != L
'\\')
318 dirp_->current_handle_ = INVALID_HANDLE_VALUE;
319 dirp_->started_reading_ = 0;
326 if (!dirp_)
return 0;
332 if (dirp_->dirent_ != 0) {
333 #ifdef ACE_HAS_TCHAR_DIRENT 340 if (!dirp_->started_reading_) {
341 dirp_->current_handle_ = ::FindFirstFileW(dirp_->directory_name_,
343 dirp_->started_reading_ = 1;
346 int retval = ::FindNextFileW(dirp_->current_handle_, &dirp_->fdata_);
350 ::FindClose(dirp_->current_handle_);
351 dirp_->current_handle_ = INVALID_HANDLE_VALUE;
355 if (dirp_->current_handle_ != INVALID_HANDLE_VALUE) {
358 if (dirp_->dirent_ != 0) {
359 #ifdef ACE_HAS_TCHAR_DIRENT 360 dirp_->dirent_->d_name =
365 #else // MinGW: d_name is a fixed-size char array 368 sizeof(dirp_->dirent_->d_name));
370 dirp_->dirent_->d_reclen =
sizeof(
DDS_DIRENT);
373 return dirp_->dirent_;
379 void DDS_Dirent::close()
382 if (dirp_->current_handle_ != INVALID_HANDLE_VALUE)
383 ::FindClose(dirp_->current_handle_);
385 dirp_->current_handle_ = INVALID_HANDLE_VALUE;
386 dirp_->started_reading_ = 0;
388 if (dirp_->dirent_ != 0) {
389 #ifdef ACE_HAS_TCHAR_DIRENT 399 DDS_Dirent::~DDS_Dirent()
404 #elif defined ACE_USES_WCHAR // non-Win32 uses-WChar 410 DDS_DIR() : real_dir_(), ent_() {}
416 if (path)
open(path);
419 int DDS_Dirent::open(
const ACE_TCHAR* path)
427 if (!dirp_->real_dir_)
return 0;
431 if (!dirp_->ent_.real_dirent_)
return 0;
439 void DDS_Dirent::close()
441 if (dirp_->real_dir_) {
446 dirp_->real_dir_ = 0;
449 DDS_Dirent::~DDS_Dirent()
463 , logical_relative_(logical)
482 ios::binary | ios::out);
483 return !stream.bad() && !stream.fail();
490 ios::binary | ios::in);
491 return !stream.bad() && !stream.fail();
496 int unlink_result = -1;
502 if (unlink_result != -1) {
524 return physical_dirname_ + relative;
539 if (std::strlen(name) >= FSS_MAX_FILE_NAME) {
540 throw std::runtime_error(
"file name too long");
544 Map::iterator it = files_.find(t_name);
546 if (it == files_.end()) {
547 return make_new_file(t_name);
550 return DCPS::make_rch<File>(full_path(it->second), it->first,
rchandle_from(
this));
556 if (dirs_.find(t_name) != dirs_.end()) {
557 throw std::runtime_error(
"Can't create a file with the same name as " 558 "an existing directory.");
562 files_[t_name] = phys;
564 CwdGuard cg(physical_dirname_);
568 if (!fh)
throw std::runtime_error(
"Can't create the file");
571 return DCPS::make_rch<File>(physical_dirname_ + phys, t_name,
rchandle_from(
this));
578 if (files_.empty()) {
579 logical = FSS_DEFAULT_FILE_NAME;
582 Map::iterator last = --files_.
end();
583 logical = last->first;
585 if (!increment(logical)) {
586 throw std::runtime_error(
"out of range for create_next_file");
590 return make_new_file(logical);
608 for (iterator iter = path.begin(), end = path.end(); iter != end; ++iter) {
609 dir = dir->get_subdir(iter->c_str());
618 Map::iterator it = dirs_.find(t_name);
620 if (it == dirs_.end()) {
621 return make_new_subdir(t_name);
624 return DCPS::make_rch<Directory>(full_path(it->second), it->first,
rchandle_from(
this));
633 logical = FSS_DEFAULT_DIR_NAME;
636 Map::iterator last = --dirs_.
end();
637 logical = last->first;
639 if (!increment(logical)) {
640 throw std::runtime_error(
"out of range for create_next_dir");
644 return make_new_subdir(logical);
649 if (files_.find(t_name) != files_.end()) {
650 throw std::runtime_error(
"Can't create a directory with the same " 651 "name as an existing file.");
655 (std::min)(FSS_MAX_FILE_NAME, t_name.
length()));
659 if (t_name.
length() >= FSS_MAX_FILE_NAME) {
660 unsigned int& counter = long_names_[phys_prefix + phys_base];
662 if (counter == 99999) {
663 throw std::runtime_error(
"Long directory name out of range");
669 phys_base = phys_base.
substr(0, phys_base.
length() - 1);
673 dirs_[t_name] = phys;
675 CwdGuard cg(physical_dirname_);
677 if (dds_mkdir(phys.
c_str()) == -1) {
678 throw std::runtime_error(
"Can't create directory");
681 if ((phys_prefix.
length() > 0 && dds_chdir(phys_prefix.
c_str()) == -1)
682 || dds_chdir(phys_base.c_str()) == -1) {
683 dds_rmdir(phys.
c_str());
684 throw std::runtime_error(
"Can't change to newly created directory");
687 std::ofstream fn(
"_fullname");
688 fn << t_name <<
'\n';
690 return DCPS::make_rch<Directory>(physical_dirname_ + phys, t_name,
rchandle_from(
this));
695 if (overflow_.empty()) {
700 typedef OPENDDS_MAP(
unsigned int,
unsigned int)::iterator iterator;
702 bool found_gap(
false);
703 unsigned int last_seen(0), unused_bucket(0);
705 for (iterator iter = overflow_.begin(), end = overflow_.end();
706 iter != end; ++iter) {
710 if (iter->first == 0)
return ACE_TEXT(
"");
712 return overflow_dir_name(iter->first);
715 if (!found_gap && iter->first > last_seen + 1) {
717 unused_bucket = last_seen + 1;
720 last_seen = iter->first;
724 if (last_seen == FSS_MAX_OVERFLOW_DIR) {
725 throw std::runtime_error(
"Overflow serial # out of range.");
728 unused_bucket = last_seen + 1;
731 overflow_[unused_bucket] = 1;
732 ACE_TString dir_name = overflow_dir_name(unused_bucket);
733 CwdGuard cg(physical_dirname_);
735 if (dds_mkdir(dir_name.
c_str()) == -1) {
736 throw std::runtime_error(
"Can't create overflow directory");
747 recursive_remove(physical_dirname_);
762 , physical_dirname_(dirname)
763 , logical_dirname_(logical)
779 if (!ok)
throw std::runtime_error(
"Can't open or create directory");
785 unsigned int overflow_index)
791 if (ent->d_name[0] ==
ACE_TEXT(
'.') && (!ent->d_name[1] ||
792 (ent->d_name[1] ==
ACE_TEXT(
'.') && !ent->d_name[2]))) {
798 if (is_dir(file.
c_str())) {
808 }
else if (
ACE_OS::strlen(ent->d_name) <= FSS_MAX_FILE_NAME_ENCODED) {
810 ++overflow_[overflow_index];
814 std::ifstream fn(
"_fullname");
817 if (!std::getline(fn, fullname)) {
818 throw std::runtime_error(
"Can't read .../_fullname");
822 dirs_[full_t] = phys;
823 ++overflow_[overflow_index];
828 throw std::runtime_error(
"Badly formatted long dir name");
833 unsigned int& counter = long_names_[prefix];
835 if (serial >= counter) counter = serial + 1;
839 if (ent->d_name[0] !=
ACE_TEXT(
'_')) {
841 ++overflow_[overflow_index];
850 Map::iterator iter = m.find(child);
852 if (iter == m.end())
return;
856 unsigned int bucket = (idx == 0 ?
ACE_OS::atoi(&phys[idx + 10]) : 0);
858 if (--overflow_[bucket] == 0 && bucket > 0) {
859 overflow_.erase(bucket);
862 dds_rmdir(ov_dir.
c_str());
873 ACE_TEXT(
"0123456789ABCDEFGHIJKLMNOPQRSTUV");
875 static const size_t enc[] = {0, 2, 4, 5, 7};
878 for (
size_t len =
ACE_OS::strlen(decoded); *decoded; decoded += 5, len -= 5) {
881 for (
size_t i(0); i < 5 && i < len; ++i) {
882 chunk |=
static_cast<ACE_UINT64>(decoded[i] & 0xFF) << ((4 - i) * 8);
885 size_t limit = (len < 5) ? enc[len] : 8;
887 for (
size_t i(0); i < limit; ++i) {
889 static_cast<unsigned char>(chunk >>((7 - i) * 5)) & 0x1F;
890 encoded += lookup[val];
894 encoded.
append(padding, 8 - enc[len]);
905 static const size_t dec[] = {0, 0, 1, 0, 2, 3, 0, 4, 0};
908 for (; *
encoded; encoded += 8) {
912 for (; i < 8 && encoded[i] !=
ACE_TEXT(
'='); ++i) {
913 char idx = (encoded[i] <=
ACE_TEXT(
'9'))
915 : (10 + encoded[i] -
ACE_TEXT(
'A'));
916 chunk |=
static_cast<ACE_UINT64>(idx) << ((7 - i) * 5);
919 size_t limit = (encoded[i] ==
ACE_TEXT(
'=')) ? dec[i] : 5;
921 for (
size_t j(0); j < limit; ++j) {
922 decoded +=
static_cast<ACE_TCHAR>(chunk >>((4 - j) * 8)) & 0xFF;
RcHandle< T > rchandle_from(T *pointer)
RcHandle< File > get_file(const char *name)
RcHandle< File > create_next_file()
assumes all files in this dir are created with this API
const ACE_CHAR_T * c_str(void) const
FileIterator begin_files()
int chdir(const char *path)
Directory::Ptr make_new_subdir(const ACE_TString &logical)
#define ACE_TEXT_ALWAYS_WCHAR(STRING)
Directory::Ptr get_subdir(const char *name)
ACE_TString b32h_encode(const ACE_TCHAR *decoded)
int snprintf(char *buf, size_t maxlen, const char *format,...) ACE_GCC_FORMAT_ATTRIBUTE(printf
int strncmp(const char *s, const char *t, size_t len)
void scan_dir(const ACE_TString &relative, DDS_Dirent &dir, unsigned int overflow_index)
#define ACE_TEXT_ALWAYS_CHAR(STRING)
static Ptr create(const char *root_path)
static FilterEvaluator::AstNodeWrapper child(const FilterEvaluator::AstNodeWrapper &node, size_t idx)
OPENDDS_STRING name() const
int stat(const char *file, ACE_stat *)
DirectoryIterator begin_dirs()
size_type rfind(char c, size_type pos=npos) const
size_t strlen(const char *s)
ACE_TString physical_dirname_
int close(ACE_HANDLE handle)
static size_type const npos
void removing(const ACE_TString &logical_child, bool file)
int unlink(const char *path)
struct ACE_DIRENT * readdir(ACE_DIR *)
char * getcwd(char *, size_t)
Directory(const ACE_TString &root_path, const ACE_TString &logical, const Directory::Ptr &parent)
ACE_HANDLE open(const char *filename, int mode, mode_t perms=ACE_DEFAULT_OPEN_PERMS, LPSECURITY_ATTRIBUTES sa=0)
void set(const char *s, bool release=true)
int mkdir(const char *path, mode_t mode=ACE_DEFAULT_DIR_PERMS)
#define OPENDDS_FILESYSTEMSTORAGE_MAX_FILES_PER_DIR
ACE_String_Base< char > & append(const char *s, size_type slen)
const ACE_TCHAR * dirname(const ACE_TCHAR *pathname, ACE_TCHAR delim=ACE_DIRECTORY_SEPARATOR_CHAR)
static ACE_Allocator * instance(void)
ACE_TString physical_file_
ACE_TString physical_dir_
ACE_TString full_path(const ACE_TString &relative) const
RcHandle< Directory > Ptr
#define ACE_ADAPT_RETVAL(OP, RESULT)
#define ACE_TEXT_CHAR_TO_TCHAR(STRING)
Directory::Ptr create_next_dir()
assumes all subdirectories in this dir are created with this API
Directory::Ptr parent() const
DirectoryIterator end_dirs()
RcHandle< File > make_new_file(const ACE_TString &t_name)
ACE_DIR * opendir(const ACE_TCHAR *filename)
#define OPENDDS_MAP(K, V)
int set_errno_to_last_error(void)
unsigned long long ACE_UINT64
Directory::Ptr get_dir(const OPENDDS_VECTOR(OPENDDS_STRING)&path)
#define OPENDDS_VECTOR(T)
size_type find(const ACE_String_Base< ACE_CHAR_T > &str, size_type pos=0) const
ACE_TString b32h_decode(const ACE_TCHAR *encoded)
ACE_String_Base< ACE_CHAR_T > substr(size_type offset, size_type length=npos) const
#define OPENDDS_END_VERSIONED_NAMESPACE_DECL
char * strcat(char *s, const char *t)
int rmdir(const char *path)
char * strdup(const char *s)
#define ACE_NEW_RETURN(POINTER, CONSTRUCTOR, RET_VAL)
size_type length(void) const
sequence<<%SCOPED%><%TYPE%><%SEQ%> local interface<%TYPE%> out string encoded
bool read(std::ifstream &stream)
void resize(const size_t new_size, const T &t)
OPENDDS_STRING name() const
The Internal API and Implementation of OpenDDS.
char * strcpy(char *s, const char *t)
#define ACE_TEXT_WCHAR_TO_TCHAR(STRING)
ACE_TString logical_relative_
virtual void * malloc(size_type nbytes)=0
char * strncpy(char *s, const char *t, size_t len)
bool write(std::ofstream &stream)