/** * Initializes the file based backend storage by passing a path to * the directory where the key named files will be stored. * The return value should be 0 on success. * If it is -ErrInvalidConfiguration then the the path name is too long to * accommodate the trailing slash and max key length. */ int init(const PathString& path) { using namespace std; int rv = -uavcan::ErrInvalidParam; if (path.size() > 0) { base_path = path.c_str(); if (base_path.back() == '/') { base_path.pop_back(); } rv = 0; struct stat sb; if (stat(base_path.c_str(), &sb) != 0 || !S_ISDIR(sb.st_mode)) { rv = mkdir(base_path.c_str(), S_IRWXU | S_IRWXG | S_IRWXO); } if (rv >= 0 ) { base_path.push_back('/'); if ((base_path.size() + MaxStringLength) > MaxPathLength) { rv = -uavcan::ErrInvalidConfiguration; } } } return rv; }
/** * 文字列が余分なセパレータで終わっているかどうかを返します。 */ bool isTerminatedByRedundantSeparator(const PathString &s) { // 完全修飾パス // \\Server\a\ => true? // \\Server\ => true? // \\?\C:\ => false // \\?\ => false // C:\a\ => true // C:\ => false // // 非完全修飾パス // \ => false // C:a\ => true // .\ => true // a\ => true std::size_t lastSepPos = s.size(); NativeChar prevChar = AUSH_NATIVE_L('\0'); NativeChar lastSepPrevChar = AUSH_NATIVE_L('\0'); for(std::size_t pos = 0; pos < s.size(); pos = next_char_pos(s, pos)){ NativeChar currChar = s[pos]; if(is_separator()(currChar)){ lastSepPos = pos; lastSepPrevChar = prevChar; } prevChar = currChar; } return (lastSepPos + 1 == s.size() && lastSepPrevChar != AUSH_NATIVE_L(':') && lastSepPrevChar != AUSH_NATIVE_L('?') && lastSepPrevChar != AUSH_NATIVE_L('\0')); }
/** * パス末尾の余分なセパレータを切り落とした文字列を返します。 * * 切り落とすのは余分なセパレータであり、切り落とすことによって意味が変わってしまう場合は切り落としません。 */ PathString chopLastRedundantSeparator(const PathString &s) { if(isTerminatedByRedundantSeparator(s)){ return PathString(s, 0, s.size() - 1); } else{ return s; } }
/** * ファイルの拡張子(ドットを含む)を返します。 */ PathString getFileExtension(const PathString &s) { const PathString filename = getLastFileName(s); if(filename.empty() || filename == AUSH_NATIVE_L(".") || filename == AUSH_NATIVE_L("..")){ return PathString(); } const std::size_t pos = find_last_char(filename, is_dot()); if(pos >= filename.size()){ return PathString(); } return filename.substr(pos); }
/** * Initializes the file based event tracer. */ int init(const PathString& path) { using namespace std; int rv = -uavcan::ErrInvalidParam; if (path.size() > 0) { rv = 0; path_ = path.c_str(); int fd = open(path_.c_str(), O_RDWR | O_CREAT | O_TRUNC, FilePermissions); if (fd >= 0) { (void)close(fd); } } return rv; }
/** * 最後のファイル名部分の先頭の位置を返します。 */ PathString::size_type getLastFileNamePos(const PathString &s) { // 完全修飾パス // \\Server\a\b => b // \\Server\a\ => (empty) // \\Server\a => a // \\Server\ => (empty) // \\Server => \\Server (*特殊) // // \\?\C:\a => a // \\?\C:\ => (empty) // \\?\C: => C: // \\?\ => (empty) // \\? => \\? (*特殊) // // (\\?\\\Server\aみたいなのはあるの?) // // C:\a\b => b // C:\a\ => (empty) // C:\a => a // C:\ => (empty) // // 非完全修飾パス // \\?\C:a => a (*特殊? 許可されていないっぽいけど) // // \a => a // \ => (empty) // // C:a\b => b // C:a\ => (empty) // C:a => a (*特殊) // C: => C: // // .\a => a // .\ =>(empty) // . => . // // a/b => b // a\ => (empty) // a => a // // => (empty) const std::size_t lastSep = find_last_char(s, is_separator()); const std::size_t afterSep = (lastSep == PathString::npos) ? 0 : lastSep + 1; if(afterSep >= s.size()){ return s.size(); //区切り文字で終わっている。または、文字列が空。 } // 特殊な物を処理する。 // ・ \\Server // ・ C:a // ・ C: if(lastSep == 1 && is_separator()(s[0])){ return 0; // \\で始まり以降区切りが無い場合、全体をひとまとまりとする。 } if(lastSep == PathString::npos && s.size() >= 3 && s[1] == AUSH_NATIVE_L(':')){ //PRN:とかのことを考えると微妙だけど、splitpathあたりもこれと等しい感じだし(_MAX_DRIVE=3)、まあいいか。 return 2; //コロン以降のみがファイル名。 } return afterSep; }