diff --git a/site/source/docs/tools_reference/settings_reference.rst b/site/source/docs/tools_reference/settings_reference.rst index 1554af79e3cf0..db8651d300e69 100644 --- a/site/source/docs/tools_reference/settings_reference.rst +++ b/site/source/docs/tools_reference/settings_reference.rst @@ -2322,6 +2322,30 @@ Alternate syntax: --use-port=libpng Default value: false +.. _use_libsquashfs: + +USE_LIBSQUASHFS +=============== + +1 = use libsquashfs from emscripten-ports +Alternate syntax: --use-port=libsquashfs + +.. note:: Applicable during both linking and compilation + +Default value: false + +.. _use_emscripten_wasmfs_squashfs: + +USE_EMSCRIPTEN_WASMFS_SQUASHFS +============================== + +1 = use emscripten_wasmfs_sqaushfs from emscripten-ports +Alternate syntax: --use-port=emscripten_wasmfs_sqaushfs + +.. note:: Applicable during both linking and compilation + +Default value: false + .. _use_regal: USE_REGAL diff --git a/src/settings.js b/src/settings.js index b21cc9ddc2454..da73ade3fdbcf 100644 --- a/src/settings.js +++ b/src/settings.js @@ -1560,6 +1560,16 @@ var USE_LIBJPEG = false; // [compile+link] var USE_LIBPNG = false; +// 1 = use libsquashfs from emscripten-ports +// Alternate syntax: --use-port=libsquashfs +// [compile+link] +var USE_LIBSQUASHFS = false; + +// 1 = use emscripten_wasmfs_sqaushfs from emscripten-ports +// Alternate syntax: --use-port=emscripten_wasmfs_sqaushfs +// [compile+link] +var USE_EMSCRIPTEN_WASMFS_SQUASHFS = false; + // 1 = use Regal from emscripten-ports // Alternate syntax: --use-port=regal // [compile+link] diff --git a/system/include/emscripten/wasmfs.h b/system/include/emscripten/wasmfs.h index f7025dc6eb6cb..080f9984d2250 100644 --- a/system/include/emscripten/wasmfs.h +++ b/system/include/emscripten/wasmfs.h @@ -96,6 +96,9 @@ backend_t wasmfs_create_jsimpl_backend(void); backend_t wasmfs_create_icase_backend(backend_t backend); +// creates a squashfs backend, backed by a squashfs file inside the filesystem +backend_t wasmfs_create_squashfs_backend(const char* squashFSFile __attribute__((nonnull))); + // Similar to fflush(0), but also flushes all internal buffers inside WasmFS. // This is necessary because in a Web environment we must buffer at an // additional level after libc, since console.log() prints entire lines, that diff --git a/test/test_other.py b/test/test_other.py index a42a2ba95c2cc..5ec4d875fa66b 100644 --- a/test/test_other.py +++ b/test/test_other.py @@ -14440,6 +14440,13 @@ def test_wasmfs_getdents(self): self.set_setting('FORCE_FILESYSTEM') self.do_run_in_out_file_test('wasmfs/wasmfs_getdents.c') + def test_wasmfs_squashfs(self): + self.set_setting('WASMFS') + self.set_setting('USE_EMSCRIPTEN_WASMFS_SQUASHFS') + shutil.copy(test_file('wasmfs/squashfs_example.sqshfs'), '.') + self.do_run_in_out_file_test('wasmfs/wasmfs_squashfs.c', + cflags=['--embed-file', 'squashfs_example.sqshfs']) + def test_wasmfs_jsfile(self): self.set_setting('WASMFS') self.do_run_in_out_file_test('wasmfs/wasmfs_jsfile.c') diff --git a/test/wasmfs/readme.squashfs b/test/wasmfs/readme.squashfs new file mode 100644 index 0000000000000..02766909338f7 --- /dev/null +++ b/test/wasmfs/readme.squashfs @@ -0,0 +1,6 @@ +The example squash fs file is generate with the following command from libsquashfs-ng: + +gensquashfs -b 4096 -c gzip -D squashfs_example squashfs_example.sqshfs + +The block size is chosen to be as small as possible to support multiple blocks with a small + example file. It is not a recommendation for usuage. diff --git a/test/wasmfs/squashfs_example.sqshfs b/test/wasmfs/squashfs_example.sqshfs new file mode 100644 index 0000000000000..c208a9bfb89c6 Binary files /dev/null and b/test/wasmfs/squashfs_example.sqshfs differ diff --git a/test/wasmfs/squashfs_example/Folder2/justanothertxtfile b/test/wasmfs/squashfs_example/Folder2/justanothertxtfile new file mode 100644 index 0000000000000..4c17a8a15ec4a --- /dev/null +++ b/test/wasmfs/squashfs_example/Folder2/justanothertxtfile @@ -0,0 +1,3 @@ +What comes to my mind? Nothing special about text files? +Maybe some latex: +$H=\hbar \omega a^\dagger a $ diff --git a/test/wasmfs/squashfs_example/Folder2/testfile.txt b/test/wasmfs/squashfs_example/Folder2/testfile.txt new file mode 100644 index 0000000000000..004c5b298a1ae --- /dev/null +++ b/test/wasmfs/squashfs_example/Folder2/testfile.txt @@ -0,0 +1,5 @@ +What should we write! + +More interesting text? +I just need to fill it. +Exotic characters ÖÄÜß?aêéáà diff --git a/test/wasmfs/squashfs_example/folder1/subfoldera/testmeagain b/test/wasmfs/squashfs_example/folder1/subfoldera/testmeagain new file mode 100644 index 0000000000000..b6e5b654ba0a7 --- /dev/null +++ b/test/wasmfs/squashfs_example/folder1/subfoldera/testmeagain @@ -0,0 +1 @@ +Lalala! diff --git a/test/wasmfs/squashfs_example/othertestfile2.txt b/test/wasmfs/squashfs_example/othertestfile2.txt new file mode 100644 index 0000000000000..e65680e88a17c --- /dev/null +++ b/test/wasmfs/squashfs_example/othertestfile2.txt @@ -0,0 +1 @@ +Just some text, nothing special! \ No newline at end of file diff --git a/test/wasmfs/squashfs_example/roottest1.txt b/test/wasmfs/squashfs_example/roottest1.txt new file mode 100644 index 0000000000000..54df3d02471ba --- /dev/null +++ b/test/wasmfs/squashfs_example/roottest1.txt @@ -0,0 +1,118 @@ +Traditional blind text exceeding 8Kbyte and thus two frames if frame size is 8KB +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. +Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, +dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper +congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est +eleifend mi, non fermentum diam nisl sit amet erat. +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. +Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, +dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper +congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est +eleifend mi, non fermentum diam nisl sit amet erat. +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. +Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, +dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper +congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est +eleifend mi, non fermentum diam nisl sit amet erat. +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. +Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, +dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper +congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est +eleifend mi, non fermentum diam nisl sit amet erat. +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. +Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, +dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper +congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est +eleifend mi, non fermentum diam nisl sit amet erat. +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. +Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, +dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper +congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est +eleifend mi, non fermentum diam nisl sit amet erat. +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. +Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, +dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper +congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est +eleifend mi, non fermentum diam nisl sit amet erat. +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. +Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, +dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper +congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est +eleifend mi, non fermentum diam nisl sit amet erat. +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. +Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, +dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper +congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est +eleifend mi, non fermentum diam nisl sit amet erat. +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. +Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, +dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper +congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est +eleifend mi, non fermentum diam nisl sit amet erat. +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. +Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, +dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper +congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est +eleifend mi, non fermentum diam nisl sit amet erat. +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. +Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, +dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper +congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est +eleifend mi, non fermentum diam nisl sit amet erat. +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. +Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, +dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper +congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est +eleifend mi, non fermentum diam nisl sit amet erat. +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. +Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, +dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper +congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est +eleifend mi, non fermentum diam nisl sit amet erat. +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. +Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, +dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper +congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est +eleifend mi, non fermentum diam nisl sit amet erat. +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. +Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, +dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper +congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est +eleifend mi, non fermentum diam nisl sit amet erat. +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. +Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, +dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper +congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est +eleifend mi, non fermentum diam nisl sit amet erat. +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. +Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, +dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper +congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est +eleifend mi, non fermentum diam nisl sit amet erat. +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. +Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, +dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper +congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est +eleifend mi, non fermentum diam nisl sit amet erat. +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. +Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, +dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper +congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est +eleifend mi, non fermentum diam nisl sit amet erat. +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. +Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, +dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper +congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est +eleifend mi, non fermentum diam nisl sit amet erat. +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. +Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, +dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper +congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est +eleifend mi, non fermentum diam nisl sit amet erat. +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. +Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, +dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper +congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est +eleifend mi, non fermentum diam nisl sit amet erat. +---- +End \ No newline at end of file diff --git a/test/wasmfs/squashfs_example/symtestfile.txt b/test/wasmfs/squashfs_example/symtestfile.txt new file mode 120000 index 0000000000000..62c74bcbe17c5 --- /dev/null +++ b/test/wasmfs/squashfs_example/symtestfile.txt @@ -0,0 +1 @@ +testfile.txt \ No newline at end of file diff --git a/test/wasmfs/squashfs_example/testfile.txt b/test/wasmfs/squashfs_example/testfile.txt new file mode 100644 index 0000000000000..004c5b298a1ae --- /dev/null +++ b/test/wasmfs/squashfs_example/testfile.txt @@ -0,0 +1,5 @@ +What should we write! + +More interesting text? +I just need to fill it. +Exotic characters ÖÄÜß?aêéáà diff --git a/test/wasmfs/wasmfs_squashfs.c b/test/wasmfs/wasmfs_squashfs.c new file mode 100644 index 0000000000000..7911c79a9cad2 --- /dev/null +++ b/test/wasmfs/wasmfs_squashfs.c @@ -0,0 +1,77 @@ +/* + * Copyright 2025 The Emscripten Authors. All rights reserved. + * Emscripten is available under two separate licenses, the MIT license and the + * University of Illinois/NCSA Open Source License. Both these licenses can be + * found in the LICENSE file. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void printFile(const char* path) { + FILE* file = fopen(path, "rb"); + printf("Print file: %s\n", path); + printf("------------\n"); + char buf[4096]; + size_t read = sizeof(buf); + while (read == sizeof(buf)) { + read = fread(buf, 1, sizeof(buf), file); + if (read > 0) + fwrite(buf, 1, read, stdout); + } + fclose(file); + printf("\n------------\n"); +} + +void iterateDirs(const char* oldPath) { + printf("Enter directory: %s\n", oldPath); + DIR* dir = opendir(oldPath); + assert(dir != NULL); + struct dirent* entry = readdir(dir); + char newPath[PATH_MAX + 1]; + while (entry) { + if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) { + printf("Process entry: %s\n", entry->d_name); + snprintf(newPath, sizeof(newPath), "%s/%s", oldPath, entry->d_name); + printf("New entry: %s\n", newPath); + struct stat st; + if (stat(newPath, &st) >= 0) { + if (S_ISDIR(st.st_mode)) + iterateDirs(newPath); + else if (S_ISREG(st.st_mode)) + printFile(newPath); + } + printf("Finish entry: %s\n", entry->d_name); + } + entry = readdir(dir); + } + closedir(dir); + printf("Exit directory: %s\n", oldPath); +} + +int main(int argc, char** argv) { + printf("Create backend from /squashfs_example.sqsh..."); + backend_t squashFSBackend = + wasmfs_create_squashfs_backend("/squashfs_example.sqshfs"); + assert(squashFSBackend != NULL); + printf("allocation success!\n"); + // now mount it in the file system + int ret = wasmfs_create_directory( + "/squashfs", S_IRUGO | S_IXUGO | S_IWUGO, squashFSBackend); + assert(ret == 0); + printf("mount done!\n"); + printf("Now iterate over all files and print their contents\n"); + iterateDirs("/squashfs"); + printf("Iteration finished!\n"); + return 0; +} diff --git a/test/wasmfs/wasmfs_squashfs.out b/test/wasmfs/wasmfs_squashfs.out new file mode 100644 index 0000000000000..e708666cba585 --- /dev/null +++ b/test/wasmfs/wasmfs_squashfs.out @@ -0,0 +1,211 @@ +Create backend from /squashfs_example.sqsh...allocation success! +mount done! +Now iterate over all files and print their contents +Enter directory: /squashfs +Process entry: Folder2 +New entry: /squashfs/Folder2 +Enter directory: /squashfs/Folder2 +Process entry: justanothertxtfile +New entry: /squashfs/Folder2/justanothertxtfile +Print file: /squashfs/Folder2/justanothertxtfile +------------ +What comes to my mind? Nothing special about text files? +Maybe some latex: +$H=\hbar \omega a^\dagger a $ + +------------ +Finish entry: justanothertxtfile +Process entry: testfile.txt +New entry: /squashfs/Folder2/testfile.txt +Print file: /squashfs/Folder2/testfile.txt +------------ +What should we write! + +More interesting text? +I just need to fill it. +Exotic characters ÖÄÜß?aêéáà + +------------ +Finish entry: testfile.txt +Exit directory: /squashfs/Folder2 +Finish entry: Folder2 +Process entry: folder1 +New entry: /squashfs/folder1 +Enter directory: /squashfs/folder1 +Process entry: subfoldera +New entry: /squashfs/folder1/subfoldera +Enter directory: /squashfs/folder1/subfoldera +Process entry: testmeagain +New entry: /squashfs/folder1/subfoldera/testmeagain +Print file: /squashfs/folder1/subfoldera/testmeagain +------------ +Lalala! + +------------ +Finish entry: testmeagain +Exit directory: /squashfs/folder1/subfoldera +Finish entry: subfoldera +Process entry: subfolderb +New entry: /squashfs/folder1/subfolderb +Enter directory: /squashfs/folder1/subfolderb +Exit directory: /squashfs/folder1/subfolderb +Finish entry: subfolderb +Exit directory: /squashfs/folder1 +Finish entry: folder1 +Process entry: othertestfile2.txt +New entry: /squashfs/othertestfile2.txt +Print file: /squashfs/othertestfile2.txt +------------ +Just some text, nothing special! +------------ +Finish entry: othertestfile2.txt +Process entry: roottest1.txt +New entry: /squashfs/roottest1.txt +Print file: /squashfs/roottest1.txt +------------ +Traditional blind text exceeding 8Kbyte and thus two frames if frame size is 8KB +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. +Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, +dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper +congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est +eleifend mi, non fermentum diam nisl sit amet erat. +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. +Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, +dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper +congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est +eleifend mi, non fermentum diam nisl sit amet erat. +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. +Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, +dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper +congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est +eleifend mi, non fermentum diam nisl sit amet erat. +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. +Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, +dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper +congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est +eleifend mi, non fermentum diam nisl sit amet erat. +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. +Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, +dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper +congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est +eleifend mi, non fermentum diam nisl sit amet erat. +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. +Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, +dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper +congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est +eleifend mi, non fermentum diam nisl sit amet erat. +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. +Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, +dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper +congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est +eleifend mi, non fermentum diam nisl sit amet erat. +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. +Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, +dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper +congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est +eleifend mi, non fermentum diam nisl sit amet erat. +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. +Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, +dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper +congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est +eleifend mi, non fermentum diam nisl sit amet erat. +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. +Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, +dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper +congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est +eleifend mi, non fermentum diam nisl sit amet erat. +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. +Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, +dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper +congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est +eleifend mi, non fermentum diam nisl sit amet erat. +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. +Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, +dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper +congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est +eleifend mi, non fermentum diam nisl sit amet erat. +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. +Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, +dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper +congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est +eleifend mi, non fermentum diam nisl sit amet erat. +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. +Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, +dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper +congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est +eleifend mi, non fermentum diam nisl sit amet erat. +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. +Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, +dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper +congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est +eleifend mi, non fermentum diam nisl sit amet erat. +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. +Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, +dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper +congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est +eleifend mi, non fermentum diam nisl sit amet erat. +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. +Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, +dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper +congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est +eleifend mi, non fermentum diam nisl sit amet erat. +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. +Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, +dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper +congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est +eleifend mi, non fermentum diam nisl sit amet erat. +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. +Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, +dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper +congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est +eleifend mi, non fermentum diam nisl sit amet erat. +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. +Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, +dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper +congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est +eleifend mi, non fermentum diam nisl sit amet erat. +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. +Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, +dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper +congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est +eleifend mi, non fermentum diam nisl sit amet erat. +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. +Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, +dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper +congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est +eleifend mi, non fermentum diam nisl sit amet erat. +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. +Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, +dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper +congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est +eleifend mi, non fermentum diam nisl sit amet erat. +---- +End +------------ +Finish entry: roottest1.txt +Process entry: symtestfile.txt +New entry: /squashfs/symtestfile.txt +Print file: /squashfs/symtestfile.txt +------------ +What should we write! + +More interesting text? +I just need to fill it. +Exotic characters ÖÄÜß?aêéáà + +------------ +Finish entry: symtestfile.txt +Process entry: testfile.txt +New entry: /squashfs/testfile.txt +Print file: /squashfs/testfile.txt +------------ +What should we write! + +More interesting text? +I just need to fill it. +Exotic characters ÖÄÜß?aêéáà + +------------ +Finish entry: testfile.txt +Exit directory: /squashfs +Iteration finished! diff --git a/tools/ports/emscripten_wasm_squashfs.py b/tools/ports/emscripten_wasm_squashfs.py new file mode 100644 index 0000000000000..8e07c4be6415b --- /dev/null +++ b/tools/ports/emscripten_wasm_squashfs.py @@ -0,0 +1,36 @@ +import os + +deps = ['libsquashfs'] + +port_name = 'emscripten_wasmfs_squashfs' + +root_path = os.path.dirname(os.path.realpath(__file__)) + + +def needed(settings): + return settings.USE_EMSCRIPTEN_WASMFS_SQUASHFS + + +def get_lib_name(settings): + return 'emscripten_wasmfs_squashfs.a' + + +def get(ports, settings, shared): + def create(final): + emscripten_root = shared.path_from_root() + source_path = os.path.join(root_path, 'emscripten_wasmfs_squashfs', 'src') + source_include_paths = [os.path.join(root_path, 'emscripten_wasmfs_squashfs', 'include'), os.path.join(emscripten_root, 'system', 'lib', 'wasmfs')] + srcs = [os.path.join(source_path, "backend.cpp")] + flags = ['-sUSE_LIBSQUASHFS'] + ports.build_port(source_path, final, port_name, includes=source_include_paths, srcs=srcs, flags=flags) + return [shared.cache.get_lib(get_lib_name(settings), create, what='port')] + + +def clear(ports, settings, shared): + shared.cache.erase_lib(get_lib_name(settings)) + + +def show(): + return 'emscripten_wasmfs_squashfs (-sUSE_EMSCRIPTEN_WASMFS_SQUASHFS or --use-port=emscripten-wasmfs-squashfs; some files emscripten original license but uses libsquashfs with LGPL-3.0-or-later license)' + + diff --git a/tools/ports/emscripten_wasmfs_squashfs/include/emscripten_squashfs.h b/tools/ports/emscripten_wasmfs_squashfs/include/emscripten_squashfs.h new file mode 100644 index 0000000000000..ea9a08f4fc249 --- /dev/null +++ b/tools/ports/emscripten_wasmfs_squashfs/include/emscripten_squashfs.h @@ -0,0 +1,4 @@ +#include "emscripten/wasmfs.h" + +// creates a squashfs backend, backed by a squashfs file inside the filesystem +backend_t wasmfs_create_squashfs_backend(const char* squashFSFile __attribute__((nonnull))); diff --git a/tools/ports/emscripten_wasmfs_squashfs/src/backend.cpp b/tools/ports/emscripten_wasmfs_squashfs/src/backend.cpp new file mode 100644 index 0000000000000..0c2e6223e88ab --- /dev/null +++ b/tools/ports/emscripten_wasmfs_squashfs/src/backend.cpp @@ -0,0 +1,357 @@ +// Copyright 2025 The Emscripten Authors. All rights reserved. +// Emscripten is available under two separate licenses, the MIT license and the +// University of Illinois/NCSA Open Source License. Both these licenses can be +// found in the LICENSE file. + +#include "backend.h" +#include "sqfs/compressor.h" +#include "sqfs/data_reader.h" +#include "sqfs/dir.h" +#include "sqfs/dir_reader.h" +#include "sqfs/id_table.h" +#include "sqfs/inode.h" +#include "sqfs/io.h" +#include "sqfs/super.h" +#include "wasmfs.h" + +using namespace wasmfs; + +namespace { + +class SquashFSFile; +class SquashFSDirectory; +class SquashFSSymlink; + +class SquashFSBackend : public Backend { + friend SquashFSFile; + friend SquashFSDirectory; + friend SquashFSSymlink; + +public: + SquashFSBackend(const std::string& squashFSFile) { + inited = false; + fsFile = nullptr; + compressor = nullptr; + idTable = nullptr; + dirReader = nullptr; + + fsFile = sqfs_open_file(squashFSFile.c_str(), SQFS_FILE_OPEN_READ_ONLY); + if (fsFile == nullptr) { + // TODO: How can I pass errors from the backend + return; // stop init we failed + } + + /* read super block*/ + if (sqfs_super_read(&superBlock, fsFile)) { + // TODO: How can I pass errors from the backend + return; + } + + sqfs_compressor_config_init( + &compressorCfg, + static_cast(superBlock.compression_id), + superBlock.block_size, + SQFS_COMP_FLAG_UNCOMPRESS); + + int ret = sqfs_compressor_create(&compressorCfg, &compressor); + if (ret != 0) { + // TODO: How can I pass errors from the backend + return; + } + idTable = sqfs_id_table_create(0); + if (idTable == nullptr) { + // TODO: How can I pass errors from the backend + return; + } + + if (sqfs_id_table_read(idTable, fsFile, &superBlock, compressor)) { + // TODO: How can I pass errors from the backend + return; + } + dirReader = sqfs_dir_reader_create(&superBlock, compressor, fsFile, 0); + if (dirReader == nullptr) { + // TODO: How can I pass errors from the backend + return; + } + dataReader = + sqfs_data_reader_create(fsFile, superBlock.block_size, compressor, 0); + if (dataReader == nullptr) { + // TODO: How can I pass errors from the backend + return; + } + + ret = sqfs_data_reader_load_fragment_table(dataReader, &superBlock); + if (ret != 0) { + // TODO: How can I pass errors from the backend + return; + } + inited = true; + } + + virtual ~SquashFSBackend() { + if (fsFile) + sqfs_destroy(fsFile); + if (compressor) + sqfs_destroy(compressor); + if (idTable) + sqfs_destroy(idTable); + if (dirReader) + sqfs_destroy(dirReader); + if (dataReader) + sqfs_destroy(dataReader); + } + + std::shared_ptr createFile(mode_t mode) override { + // honestly, this is readonly FS, and without a dir how should this work + return nullptr; + } + + std::shared_ptr createDirectory(mode_t mode) override; + + std::shared_ptr createSymlink(std::string target) override { + // Symlinks not supported. + return nullptr; + } + + bool isInited() { return inited; } + +private: + sqfs_file_t* fsFile; + sqfs_super_t superBlock; + sqfs_compressor_config_t compressorCfg; + sqfs_compressor_t* compressor; + sqfs_id_table_t* idTable; + sqfs_dir_reader_t* dirReader; + sqfs_data_reader_t* dataReader; + bool inited; +}; + +class SquashFSFile : public DataFile { +public: + SquashFSFile(mode_t mode, + SquashFSBackend* backend, + std::shared_ptr inode) + : DataFile(mode, backend), inodeGeneric(inode) {} + + int open(oflags_t flags) override { return 0; }; + int close() override { return 0; } + + ssize_t read(uint8_t* buf, size_t len, off_t offset) override { + SquashFSBackend* sbackend = static_cast(getBackend()); + sqfs_s32 res = sqfs_data_reader_read( + sbackend->dataReader, inodeGeneric.get(), offset, buf, len); + return res; + } + ssize_t write(const uint8_t* buf, size_t len, off_t offset) override { + return -EROFS; + } + + int setSize(off_t size) override { return -EROFS; } + + int flush() override { return 0; } + + off_t getSize() override { return inodeGeneric->data.file.file_size; } + +private: + std::shared_ptr inodeGeneric; +}; + +class SquashFSDirectory : public Directory { + // Use a vector instead of a map to save code size. + struct ChildEntry { + ChildEntry(std::string _name, std::shared_ptr _child) + : name(_name), child(_child) {}; + std::string name; + std::shared_ptr child; + }; + + std::vector entries; + +public: + SquashFSDirectory(mode_t mode, + SquashFSBackend* backend, + std::shared_ptr inode) + : Directory(mode, backend), dirRead(false), inodeGeneric(inode) {} + +protected: + // From memory backend + std::vector::iterator findEntry(const std::string& name) { + if (!dirRead) { + getEntries(); + } + return std::find_if(entries.begin(), entries.end(), [&](const auto& entry) { + return entry.name == name; + }); + } + // From memory backend + std::shared_ptr getChild(const std::string& name) override { + if (auto entry = findEntry(name); entry != entries.end()) { + return entry->child; + } + return nullptr; + } + + std::shared_ptr insertDataFile(const std::string& name, + mode_t mode) override { + // we are readonly + return nullptr; + } + std::shared_ptr insertDirectory(const std::string& name, + mode_t mode) override { + // we are readonly + return nullptr; + } + std::shared_ptr insertSymlink(const std::string& name, + const std::string& target) override { + // we are readonly + return nullptr; + } + + int insertMove(const std::string& name, std::shared_ptr file) override { + return -EROFS; // we are readonly + } + + int removeChild(const std::string& name) override { + return -EROFS; // we are readonly + } + + // The number of entries in this directory. Returns the number of entries or a + // negative error code. + ssize_t getNumEntries() override { + if (!dirRead) { + getEntries(); + } + return entries.size(); + } + + // The list of entries in this directory or a negative error code. + MaybeEntries getEntries() override { + if (!dirRead) { // dir was not read, so we read in know + SquashFSBackend* sbackend = static_cast(getBackend()); + + int result = + sqfs_dir_reader_open_dir(sbackend->dirReader, inodeGeneric.get(), 0); + if (result != 0) { + return {EIO}; + } + while (result == 0) { + sqfs_dir_entry_t* curEntry; + result = sqfs_dir_reader_read(sbackend->dirReader, &curEntry); + if (result != 0) + break; + sqfs_inode_generic_t* cinode; + result = sqfs_dir_reader_get_inode(sbackend->dirReader, &cinode); + if (result != 0) { + sqfs_destroy(&curEntry); + break; + } + + switch (curEntry->type) { + case SQFS_INODE_DIR: + entries.emplace_back( + std::string(reinterpret_cast(curEntry->name), + curEntry->size + 1), + std::make_shared( + cinode->base.mode, + sbackend, + std::shared_ptr(cinode, sqfs_free))); + break; + + case SQFS_INODE_FILE: + entries.emplace_back( + std::string(reinterpret_cast(curEntry->name), + curEntry->size + 1), + std::make_shared( + cinode->base.mode, + sbackend, + std::shared_ptr(cinode, sqfs_free))); + break; + + case SQFS_INODE_SLINK: + entries.emplace_back( + std::string(reinterpret_cast(curEntry->name), + curEntry->size + 1), + std::make_shared( + sbackend, + std::shared_ptr(cinode, sqfs_free))); + break; + default: + sqfs_free(cinode); + // do not add device file etc. + }; + sqfs_free(curEntry); + }; + if (result < 0) { + return {EIO}; + } + dirRead = true; + } + + // from MemoryDirectory + std::vector result; + result.reserve(entries.size()); + for (auto& [name, child] : entries) { + result.push_back({name, child->kind, child->getIno()}); + } + return {result}; + } + + // from MemoryDirectory + std::string getName(std::shared_ptr file) override { + auto it = + std::find_if(entries.begin(), entries.end(), [&](const auto& entry) { + return entry.child == file; + }); + if (it != entries.end()) { + return it->name; + } + return ""; + } + + bool maintainsFileIdentity() override { return true; } + +private: + bool dirRead; + std::shared_ptr inodeGeneric; +}; + +class SquashFSSymlink : public Symlink { +public: + SquashFSSymlink(SquashFSBackend* backend, + std::shared_ptr inode) + : Symlink(backend), inodeGeneric(inode) {} + + std::string getTarget() const override { + return std::string(reinterpret_cast(inodeGeneric->extra), + inodeGeneric->data.slink.target_size); + } + +private: + std::shared_ptr inodeGeneric; +}; + +std::shared_ptr SquashFSBackend::createDirectory(mode_t mode) { + sqfs_inode_generic_t* inode; + int result = sqfs_dir_reader_get_root_inode(dirReader, &inode); + if (result != 0) + return nullptr; + + return std::make_shared( + mode, this, std::shared_ptr(inode, sqfs_free)); +} + +} // anonymous namespace + +extern "C" { + +backend_t wasmfs_create_squashfs_backend(const char* squashFSFile) { + std::unique_ptr sqFSBackend = + std::make_unique(squashFSFile); + if (sqFSBackend->isInited()) { + return wasmFS.addBackend(std::move(sqFSBackend)); + } else { + return nullptr; + } +} + +} // extern "C" diff --git a/tools/ports/libsquashfs.py b/tools/ports/libsquashfs.py new file mode 100644 index 0000000000000..0a6ca226c32f4 --- /dev/null +++ b/tools/ports/libsquashfs.py @@ -0,0 +1,47 @@ +# Copyright 2015 The Emscripten Authors. All rights reserved. +# Emscripten is available under two separate licenses, the MIT license and the +# University of Illinois/NCSA Open Source License. Both these licenses can be +# found in the LICENSE file. + +import os +import shutil + +TAG = '1.3.2' +HASH = '4a3a194af80aa9ed689cf541106906945f546fa15a5b30feff9df95998105298aa919757b1f17bf8387da0bdb05b70857ce818ce8572411cd5ef25e2b93c2022' + +deps = ['zlib'] + + +def needed(settings): + return settings.USE_LIBSQUASHFS + + +def get(ports, settings, shared): + # TODO: This is an emscripten-hosted mirror of the libsquashfs repo from Sourceforge. + ports.fetch_project('libsquashfs', f'https://infraroot.at/pub/squashfs/squashfs-tools-ng-{TAG}.tar.gz', sha512hash=HASH) + + def create(final): + source_path = ports.get_dir('libsquashfs', 'squashfs-tools-ng-' + TAG) + squashfsconf_h = os.path.join(os.path.dirname(__file__), 'libsquashfs/config.h') + shutil.copyfile(squashfsconf_h, os.path.join(source_path, 'config.h')) + ports.install_headers(os.path.join(source_path,'include','sqfs'), target='sqfs') + flags = ['-sUSE_ZLIB', '-DWITH_GZIP', '-Wno-error=incompatible-pointer-types', '-Wno-error=format', '-D_GNU_SOURCE'] + ports.make_pkg_config('libsquashfs', TAG, flags) + includes = [os.path.join(source_path, 'include')] + exclude_dirs = ['bin', 'extras', 'common', 'compat', 'fstree', 'io', 'tar', 'win32', 'gensquashfs', 'libio', 'libtar'] + exclude_files = ['lz4.c', 'lzma.c', 'xz.c', 'zstd.c'] + ports.build_port(source_path, final, 'libsquashfs', flags=flags, includes=includes, exclude_dirs=exclude_dirs, exclude_files=exclude_files) + + return [shared.cache.get_lib('libsquashfs.a', create, what='port')] + + +def clear(ports, settings, shared): + shared.cache.erase_lib('libsquashfs.a') + + +def process_dependencies(settings): + settings.USE_ZLIB = 1 + + +def show(): + return 'libsquashfs (-sUSE_LIBSQUASHFS or --use-port=libsquashfs; LGPL-3.0-or-later license)' diff --git a/tools/ports/libsquashfs/config.h b/tools/ports/libsquashfs/config.h new file mode 100644 index 0000000000000..77bd5fdcfaa93 --- /dev/null +++ b/tools/ports/libsquashfs/config.h @@ -0,0 +1,116 @@ +/* config.h. Generated from config.h.in by configure. */ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if you have the header file. */ +#define HAVE_ALLOCA_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_BZLIB_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the `fnmatch' function. */ +#define HAVE_FNMATCH 1 + +/* Define to 1 if you have the `getopt' function. */ +#define HAVE_GETOPT 1 + +/* Define to 1 if you have the `getopt_long' function. */ +#define HAVE_GETOPT_LONG 1 + +/* Define to 1 if you have the `getsubopt' function. */ +#define HAVE_GETSUBOPT 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Have PTHREAD_PRIO_INHERIT. */ +#define HAVE_PTHREAD_PRIO_INHERIT 1 + +/* Define to 1 if you have the `sched_getaffinity' function. */ +/* #undef HAVE_SCHED_GETAFFINITY */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SELINUX_LABEL_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SELINUX_SELINUX_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `strchrnul' function. */ +#define HAVE_STRCHRNUL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strndup' function. */ +#define HAVE_STRNDUP 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_XATTR_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Does zstd support stream compression? */ +/* #undef HAVE_ZSTD_STREAM */ + +/* Define to the sub-directory where libtool stores uninstalled libraries. */ +#define LT_OBJDIR ".libs/" + +/* Name of package */ +#define PACKAGE "squashfs-tools-ng" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "goliath@infraroot.at" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "squashfs-tools-ng" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "squashfs-tools-ng 1.3.2" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "squashfs-tools-ng" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "1.3.2" + +/* Define to necessary symbol if this constant uses a non-standard name on + your system. */ +/* #undef PTHREAD_CREATE_JOINABLE */ + +/* Define to 1 if all of the C90 standard headers exist (not just the ones + required in a freestanding environment). This macro is provided for + backward compatibility; new code need not use it. */ +#define STDC_HEADERS 1 + +/* Version number of package */ +#define VERSION "1.3.2" + +/* Number of bits in a file offset, on hosts where this is settable. */ +/* #undef _FILE_OFFSET_BITS */ + +/* Define for large files, on AIX-style hosts. */ +/* #undef _LARGE_FILES */ diff --git a/tools/settings.py b/tools/settings.py index 8e640c6a5d41f..8f9351a2a1d7c 100644 --- a/tools/settings.py +++ b/tools/settings.py @@ -33,6 +33,8 @@ 'USE_LIBPNG', 'USE_BULLET', 'USE_ZLIB', + 'USE_LIBSQUASHFS', + 'USE_EMSCRIPTEN_WASMFS_SQUASHFS', 'USE_BZIP2', 'USE_VORBIS', 'USE_COCOS2D',