// -*- C++ -*- (c) 2015 Jiří Weiser #include #include #include #include #include #ifndef TOOLS_COMPILE_SNAPSHOT_H #define TOOLS_COMPILE_SNAPSHOT_H namespace divine { namespace compile { struct Snapshot { static void writeFile( std::ofstream &file, const std::string &dir, const std::string &stdin ) { file << "#include \n" << "namespace divine{ namespace fs {\n" << "VFS vfs{\n"; if ( !stdin.empty() ) { std::ifstream in( stdin, std::ios::binary ); in >> std::noskipws; std::string content = brick::fs::readFile( in ); file << '"' << _stringify( content ) << "\"," << content.size() << ",{\n"; } if ( !dir.empty() ) { brick::fs::traverseDirectoryTree( dir, [&]( std::string path ) { auto shrinked = brick::fs::distinctPaths( dir, path ); if ( !shrinked.empty() ) { auto st = brick::fs::stat( path ); file << "{\"" << _stringify( shrinked ) << "\", Type::Directory, " << st->st_mode << ", nullptr, 0 },\n"; } return true; }, []( std::string ){}, [&]( std::string path ) { auto st = brick::fs::lstat( path ); const char *type = _resolveType( st->st_mode ); file << "{\"" << _stringify( brick::fs::distinctPaths( dir, path ) ) << "\", Type::" << type << ", "<< st->st_mode << ", "; if ( _file == type ) { std::ifstream in( path, std::ios::binary ); in >> std::noskipws; std::string content = brick::fs::readFile( in ); file << '"' << _stringify( content ) << "\"," << content.size(); } else if ( _pipe == type ) { file << "\"\", 0"; } else if ( _symLink == type ) { std::string link( st->st_size, '-' ); ::readlink( path.c_str(), &link.front(), st->st_size ); file << "\"" << _stringify( link ) << "\", " << st->st_size; } else file << "nullptr, 0"; file << "},\n"; } ); } file << "{nullptr, Type::Nothing, 0, nullptr, 0}"; if ( !stdin.empty() ) file << "}"; file << "};}}" << std::endl; } private: static constexpr const char *_file = "File"; static constexpr const char *_symLink = "SymLink"; static constexpr const char *_pipe = "Pipe"; static const char *_resolveType( unsigned mode ) { if ( ( mode & S_IFLNK ) == S_IFLNK ) return _symLink; if ( ( mode & S_IFREG ) == S_IFREG ) return _file; if ( ( mode & S_IFIFO ) == S_IFIFO ) return _pipe; return nullptr; } using uchar = unsigned char; static std::string _encode( uchar c ) { std::string result = "\\x"; if ( ( (c >> 4) & 15 ) < 10 ) result += ( (c >> 4) & 15 ) + '0'; else result += ( (c >> 4) & 15 ) - 10 + 'a'; if ( ( c & 15 ) < 10 ) result += ( c & 15 ) + '0'; else result += ( c & 15 ) - 10 + 'a'; return result; } static std::string _stringify( const std::string &str ) { std::string result; for ( char c : str ) result += _encode( uchar( c ) ); return result; } }; } // namespace compile } // namespace divine #endif