{"id":27867588,"url":"https://github.com/eteran/resource-fs","last_synced_at":"2025-07-25T05:13:05.362Z","repository":{"id":283123130,"uuid":"950761733","full_name":"eteran/resource-fs","owner":"eteran","description":"Access your resources with ordinary FILE I/O","archived":false,"fork":false,"pushed_at":"2025-03-19T05:35:21.000Z","size":22,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-05-04T08:44:07.800Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/eteran.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-03-18T16:42:36.000Z","updated_at":"2025-03-19T05:35:25.000Z","dependencies_parsed_at":"2025-03-18T17:51:29.932Z","dependency_job_id":"69e5dbf7-f19c-41f5-8384-8ffd68749d50","html_url":"https://github.com/eteran/resource-fs","commit_stats":null,"previous_names":["eteran/resource-fs"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eteran%2Fresource-fs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eteran%2Fresource-fs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eteran%2Fresource-fs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eteran%2Fresource-fs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/eteran","download_url":"https://codeload.github.com/eteran/resource-fs/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252411804,"owners_count":21743604,"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","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":[],"created_at":"2025-05-04T22:50:16.767Z","updated_at":"2025-05-04T22:50:17.240Z","avatar_url":"https://github.com/eteran.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# resource-fs\nAccess your resources with ordinary FILE I/O\n\nThe upcoming `#embed` keyword is very exciting for embedding resources in C programs. But I feel it still falls short of what it could have been. Why not make it easy to embed resources and have them accessible with ordinary file operations? That's what this tool does!\n\n# Usage\n\nFirst just add the `resource_fs` script to your source tree, anywhere will do, but I tend to choose `scripts/`. Then add it to your build system. For `cmake`, it's as simple as this:\n\n```cmake\ncmake_minimum_required(VERSION 3.15)\nproject(example)\n\nadd_executable(example\n    main.c\n    ${CMAKE_CURRENT_BINARY_DIR}/resources.c\n)\n\n# The following is what generates the resources.c file\nadd_custom_command(\n    OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/resources.c\n    COMMAND python3 scripts/resource_fs --output ${CMAKE_CURRENT_BINARY_DIR}/resources.c\n    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}\n    DEPENDS res/example_resource.txt\n    DEPENDS res/another_resource.txt\n    DEPENDS config.yaml\n)\n```\n\nNext, create a config YAML file, which looks like this:\n\n```yaml\nresources:\n  - filename: ./res/example_resource.txt\n    description: This is an example resource file.\n    # description is optional\n    # if no name is specified, that's ok, we'll just use the basename of the filename\n  - filename: ./res/another_resource.txt\n    name: alternate_name.md\n    description: This is an example resource file.\noptions:\n    use_embed: false # i don't have a compiler that supports embed yet, but it *should* work\n```\n\nFinally, just do your FILE I/O like normal, except that you prefix the filename with `res:/`.\n\n```c\n#include \u003cstdio.h\u003e\n\nint main(void) {\n\n\tFILE *f = fopen(\"res:/example_resource.txt\", \"rb\");\n\tif (f) {\n\t\tchar buf[100];\n\t\tsize_t read = fread(buf, 1, sizeof(buf), f);\n\t\tif (read \u003e 0) {\n\t\t\tprintf(\"Read %zu bytes: %.*s\\n\", read, (int)read, buf);\n\t\t}\n\t\tfclose(f);\n\t} else {\n\t\tprintf(\"Failed to open file\\n\");\n\t}\n\n\treturn 0;\n}\n```\n\nYou can of course still use `fopen` like normal to access other files, only\nfilenames which match those of the resources get re-routed.\n\n# Notes\n\n* You may only open the resource files in read-only modes, `\"r\"` and `\"rb\"`.\n\n# Future work\n\n* I may add automatic compression support at some point in the future.\n\n# How does it work?\n\nGCC and Clang's libc exports its symbols as weak symbols. This is so things like `LD_PRELOAD`\ncan override features of the standard library for instrumentation and debugging purposes...\nBut, it's not only useful for that. You can override them in your own code too!\n\nSo, we simply generate a source file which exports an `fopen` function matching the signature\nof the original and add our special sauce there.\n\nIf we're trying to open a non-resource file, we just use `dlsym(RTLD_NEXT, \"fopen\");`\nto get the \"next\" implementation of `fopen`, AKA the original one so we can just call the original as needed.\n\nIf we're trying to open a resource file that was found, Linux offers a handy function called\n`fmemopen` which lets us wrap a `char *` with a `FILE*` object that can be used like normal.\n(For other systems, it can also emit code which uses `fopencookie`).\n\nSo, once we have `FILE*`, the experience is seamless.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feteran%2Fresource-fs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feteran%2Fresource-fs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feteran%2Fresource-fs/lists"}