{"id":19797874,"url":"https://github.com/podgorskiy/fsal","last_synced_at":"2025-08-04T06:39:08.398Z","repository":{"id":60657821,"uuid":"141553188","full_name":"podgorskiy/fsal","owner":"podgorskiy","description":"File System Abstraction Layer","archived":false,"fork":false,"pushed_at":"2020-05-05T09:12:21.000Z","size":516,"stargazers_count":5,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-05-01T03:36:34.245Z","etag":null,"topics":["filesystem","memory-file","vpk","zip"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/podgorskiy.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-07-19T09:05:51.000Z","updated_at":"2024-07-26T14:34:33.000Z","dependencies_parsed_at":"2022-10-02T19:40:14.679Z","dependency_job_id":null,"html_url":"https://github.com/podgorskiy/fsal","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/podgorskiy/fsal","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/podgorskiy%2Ffsal","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/podgorskiy%2Ffsal/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/podgorskiy%2Ffsal/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/podgorskiy%2Ffsal/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/podgorskiy","download_url":"https://codeload.github.com/podgorskiy/fsal/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/podgorskiy%2Ffsal/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":268658385,"owners_count":24285665,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-04T02:00:09.867Z","response_time":79,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["filesystem","memory-file","vpk","zip"],"created_at":"2024-11-12T07:27:11.846Z","updated_at":"2025-08-04T06:39:08.332Z","avatar_url":"https://github.com/podgorskiy.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# File System Abstraction Layer\n[![Build Status](https://travis-ci.org/podgorskiy/fsal.svg?branch=master)](https://travis-ci.org/github/podgorskiy/fsal)\n\n\n![Banner](https://repository-images.githubusercontent.com/141553188/8d423700-7ace-11ea-97a3-d1ab9deb0700)\n\nFSAL is a C++ library that provides an abstract layer over a filesystem.\n\n * Standard API for file acces (read, write, tell, seek, etc.)\n * Access to last modification time\n * UTF8 for filenames on all platforms\n * Mounting ZIP and VPK archives (content is accessible in read-only mode as if they were unpacked)\n * In-memory files-like objects. Can be mutable, immutable, growable, and views (no-copy from user data pointer)\n  \n## Examples \n \n### Basic file API\n```cpp\n\tfsal::FileSystem fs;\n\tfs.PushSearchPath(\"some_path/\"); // Adding search path\n\tfs.PushSearchPath(\"../\"); // Adding another search path\n\n\tfs.CreateDirectory(\"some_path\"); // Creating directory\n  \n\t// Writing std::string to a file\n\tfs.Open(\"some_path/test.txt\", fsal::kWrite) = std::string(\"test content\"); \n\n\t// Reading file to std::string (we can open it because of the search path)\n\tstd::string content = fs.Open(\"test.txt\"); \n\tCHECK(content == \"test content\");\n\n\tauto file = fs.Open(\"somefile.bin\"); // Open file for reading\n\n\tsize_t size = file.GetSize(); // Getting size\n\tCHECK(size == 128);\n\tfsal::path path = file.GetPath(); // Get path of the file\n\tCHECK(path.filename() == \"somefile.bin\");\n\n\tfile.Seek(110, fsal::File::Beginning); // Seek file\n\n\tuint32_t some_int;\n\tfile.Read(some_int); // Reading 4-byte unsigned int\n\n\tint16_t some_short;\n\tfile.Read(some_short); // Reading 2-byte signed int\n\n\tuint8_t buff[200];\n\tauto status = file.Read(buff, 10); // Reading 10 bytes to buff\n\tbool is_eof = status.is_eof(); // is EOF?\n\tCHECK(status.ok());\n\tCHECK(!is_eof);\n\n\t// Reading one more time 2-byte signed int to reach end\n\t// (no EOF yet, it's generated only when reading beyond end of file)\n\tstatus = file.Read(some_short); \n\tCHECK(status.ok());\n\tCHECK(!status.is_eof());\n\n\tstatus = file.Read(some_short); // Reading again and getting EOF\n\tCHECK(status.ok());\n\tCHECK(status.is_eof());\n```\n\n### Path normalization:\n```cpp\n\tCHECK(fsal::NormalizePath(\"./test_folder/folder_inside/../folder_inside/./\") == \"test_folder/folder_inside/\");\n\tCHECK(fsal::NormalizePath(\"test_folder/folder_inside/../folder_inside/\") == \"test_folder/folder_inside/\");\n\tCHECK(fsal::NormalizePath(\"test_folder/../test_folder/./folder_inside/../folder_inside/\") == \"test_folder/folder_inside/\");\n\tCHECK(fsal::NormalizePath(\"test_folder/folder_inside/../folder_inside/.\") == \"test_folder/folder_inside\");\n```\n\n### Getting system locations:\n```cpp\n\tusing fs = fsal::FileSystem;\n\tusing loc = fsal::Location;\n\tprintf(\"RoamingAppData: %s\\n\", fs::GetSystemPath(loc::kStorageSynced).string().c_str());\n\tprintf(\"LocalAppData: %s\\n\", fs::GetSystemPath(loc::kStorageLocal).string().c_str());\n\tprintf(\"UserPictures: %s\\n\", fs::GetSystemPath(loc::kPictures).string().c_str());\n\tprintf(\"UserMusic: %s\\n\", fs::GetSystemPath(loc::kMusic).string().c_str());\n\tprintf(\"ProgramData: %s\\n\", fs::GetSystemPath(loc::kWin_ProgramData).string().c_str());\n\tprintf(\"ProgramFiles: %s\\n\", fs::GetSystemPath(loc::kWin_ProgramFiles).string().c_str());\n\tprintf(\"Temp: %s\\n\", fs::GetSystemPath(loc::kTemp).string().c_str());\n```\n\n### Reading ZIP archive:\n```cpp\n\tfsal::ZipReader zip;\n\tauto zipfile = fs.Open(\"test_archive.zip\");\n\tCHECK(zipfile);\n\n\tfsal::Status r = zip.OpenArchive(zipfile);\n\tCHECK(r.ok());\n\n\tauto file = zip.OpenFile(\"test_folder/folder_inside/../folder_inside/./test_file.txt\");\n\tCHECK(file);\n\n\tstd::string str = file;\n\tCHECK(str == \"test\");\n\n\tauto l1 = zip.ListDirectory(\"./test_folder/folder_inside/../folder_inside/./\");\n\tprintf(\"\\nListDirectory ./test_folder/folder_inside/../folder_inside/./\\n\");\n\tfor (const auto\u0026 l: l1)\n\t{\n\t\tprintf(\"%s\\n\", l.c_str());\n\t}\n\tauto l2 = zip.ListDirectory(\".\");\n\tprintf(\"\\nListDirectory .\\n\");\n\tfor (const auto\u0026 l: l2)\n\t{\n\t\tprintf(\"%s\\n\", l.c_str());\n\t}\n```\n\n### Creating ZIP archive:\n```cpp\n\tauto zipfile = fs.Open(\"out_archive.zip\", fsal::kWrite);\n\tfsal::ZipWriter zip(zipfile);\n\tCHECK(zipfile);\n\n\tzip.AddFile(\"CMakeLists.txt\", fs.Open(\"CMakeLists.txt\"));\n\tzip.CreateDirectory(\"tests\");\n\tzip.AddFile(\"tests/main.cpp\", fs.Open(\"tests/main.cpp\"));\n\tzip.CreateDirectory(\"tests2\");\n```\n\n### Mounting ZIP archive:\n```cpp\n\tauto zipfile = fs.Open(\"test_archive.zip\", fsal::kRead, true);\n\tCHECK(zipfile);\n\n\tauto zip = fsal::OpenZipArchive(zipfile);\n\tfs.MountArchive(zip);\n\n\tfsal::File file = fs.Open(\"test_folder/folder_inside/test_file.txt\", fsal::kRead);\n\tCHECK(file);\n\tstd::string str = file;\n\tCHECK(str == \"test\");\n\n\tfile = fs.Open(\"test_folder/folder_inside/123.png\", fsal::kRead);\n\tstd::string content = file;\n\tfs.Open(\"123.png\", fsal::Mode::kWrite) = content;\n\t\n\tprintf(\"\\nListDirectory test_folder/folder_inside\\\"\\n\");\n\tauto list = zip.ListDirectory(\"test_folder/folder_inside\");\n\tfor(auto s: list)\n\t{\n\t\tprintf(\"%s\\n\", s.c_str());\n\t}\n```\n\n### Mounting VPK archive:\n```cpp\n\tauto archive = fsal::OpenVpkArchive(fs, \"/mnt/StorageExt4/SteamLibrary/steamapps/common/Counter-Strike Global Offensive/csgo\");\n\tfs.MountArchive(archive);\n\tfsal::File file = fs.Open(\"materials/panorama/images/map_icons/map_icon_de_dust2.svg\", fsal::kRead);\n\tstd::string content = file;\n\tfs.Open(\"map_icon_de_dust2.svg\", fsal::Mode::kWrite) = content;\n\n\tauto list = archive.ListDirectory(\".\");\n\tprintf(\"\\nListDirectory .\\n\");\n\tfor(auto s: list)\n\t{\n\t\tprintf(\"%s\\n\", s.c_str());\n\t}\n\tlist = archive.ListDirectory(\"models\");\n\tprintf(\"\\nListDirectory models\\n\");\n\tfor(auto s: list)\n\t{\n\t\tprintf(\"%s\\n\", s.c_str());\n\t}\n```\n  \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpodgorskiy%2Ffsal","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpodgorskiy%2Ffsal","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpodgorskiy%2Ffsal/lists"}