11name : Continuous Integration
2+
23on :
34 push :
45 paths :
1819 - " **.build"
1920 - " **.in"
2021 - " **.yml"
22+
2123env :
2224 CMAKE_GENERATOR : Ninja
23- HOMEBREW_NO_ANALYTICS : " 1"
24- HOMEBREW_NO_AUTO_UPDATE : " 1"
25- HOMEBREW_NO_INSTALL_UPGRADE : " 1"
26- HOMEBREW_NO_INSTALL_CLEANUP : " 1"
2725 DEBIAN_FRONTEND : noninteractive
2826 TZ : Japan
27+
2928jobs :
3029 build-ubuntu :
3130 runs-on : ubuntu-latest
3433 image : ubuntu:20.04
3534 options : --user 0
3635 steps :
37- - name : Install build dependancies
36+ - name : Install build dependencies
3837 run : |
3938 apt-get -y update
4039 apt-get -y -o Dpkg::Options::='--force-confdef' -o Dpkg::Options::='--force-confold' install build-essential expect pkg-config fuse libfuse-dev git time p7zip-full e2fsprogs python3
@@ -63,59 +62,103 @@ jobs:
6362 - name : Run Test
6463 run : |
6564 cd test
66- # Запускаем Tcl скрипт (который теперь создает EXT2 раздел)
6765 time ./pfsshell_test.tcl
6866
6967 - name : Verify EXT2 partition validity
7068 run : |
71- # Этот скрипт ищет раздел EXT2 в образе и проверяет его целостность
7269 cd test
7370 python3 -c "
74- import sys, struct
71+ import sys, os
72+
73+ # Константы EXT2
74+ MAGIC = b'\x53\xEF' # 0xEF53 (Little Endian)
75+ SB_OFFSET = 1024 # Суперблок начинается с 1024 байта раздела
76+ MAGIC_OFFSET = 56 # Сигнатура находится на 56-м байте суперблока
77+ # Итого смещение сигнатуры от начала раздела = 1080 байт
7578
76- MAGIC = b'\x53\xEF' # 0xEF53 little endian
77- SB_OFFSET = 1024
78- MAGIC_OFFSET = 56
7979 IMG_FILE = 'test.img'
8080 OUT_FILE = 'ext2_dump.img'
81+ PARTITION_SIZE = 128 * 1024 * 1024 # 128 MB (как в тесте)
82+ CHUNK_SIZE = 10 * 1024 * 1024 # Читаем по 10 МБ
8183
8284 print(f'Scanning {IMG_FILE} for EXT2 magic signature...')
8385
86+ found = False
87+ if not os.path.exists(IMG_FILE):
88+ print(f'Error: {IMG_FILE} not found!')
89+ sys.exit(1)
90+
8491 with open(IMG_FILE, 'rb') as f:
85- # APA разделы обычно выровнены. Сканируем с шагом 1MB для скорости.
92+ offset = 0
8693 while True:
87- pos = f.tell()
88- # Проверяем сигнатуру
89- f.seek(pos + SB_OFFSET + MAGIC_OFFSET)
90- magic = f.read(2)
94+ # Читаем чанк + небольшой перехлест, чтобы не разрезать сигнатуру
95+ f.seek(offset)
96+ data = f.read(CHUNK_SIZE)
97+ if not data:
98+ break
99+
100+ # Ищем сигнатуру внутри чанка
101+ rel_pos = -1
102+ while True:
103+ try:
104+ rel_pos = data.index(MAGIC, rel_pos + 1)
105+ except ValueError:
106+ break
107+
108+ # Нашли сигнатуру по абсолютному смещению abs_magic_pos
109+ abs_magic_pos = offset + rel_pos
110+
111+ # Предполагаемое начало раздела
112+ part_start = abs_magic_pos - (SB_OFFSET + MAGIC_OFFSET)
113+
114+ if part_start < 0:
115+ continue
116+
117+ # Проверка выравнивания (опционально, но полезно)
118+ # Обычно разделы выровнены по секторам (512 байт)
119+ if part_start % 512 == 0:
120+ print(f'FOUND EXT2 signature at offset {abs_magic_pos}')
121+ print(f'-> Suspected partition start at {part_start}')
122+
123+ # Извлекаем раздел
124+ f.seek(part_start)
125+ part_data = f.read(PARTITION_SIZE)
126+
127+ # Дополнительная проверка: первые байты не должны быть пустыми (там APA заголовок или уже EXT2 SB)
128+ # Но EXT2 SB начинается с 1024. Первые 1024 байта могут быть Boot Code или APA.
129+ # Просто сохраняем.
91130
92- if magic == MAGIC:
93- print(f'FOUND EXT2 signature at partition offset {pos}')
94- # Извлекаем 128MB (размер, который мы задали в тесте)
95- f.seek(pos)
96- data = f.read(128 * 1024 * 1024)
97- with open(OUT_FILE, 'wb') as out:
98- out.write(data)
99- print(f'Dumped partition to {OUT_FILE}')
100- sys.exit(0)
131+ with open(OUT_FILE, 'wb') as out:
132+ out.write(part_data)
101133
102- # Переходим к следующему блоку (ищем дальше)
103- f.seek(pos + 1024*1024)
104- # Проверка конца файла
105- if not f.read(1):
134+ print(f'Dumped {len(part_data)} bytes to {OUT_FILE}')
135+ found = True
136+ break
137+
138+ if found:
106139 break
107140
108- print('EXT2 partition NOT found!')
109- sys.exit(1)
141+ offset += CHUNK_SIZE
142+ # Небольшой откат назад, чтобы не пропустить сигнатуру на границе чанков
143+ # (не обязательно, если ищем побайтово, но для надежности)
144+ if offset > 1024:
145+ offset -= 1024
146+
147+ if not found:
148+ print('EXT2 partition NOT found!')
149+ sys.exit(1)
110150 "
111151
112152 echo "Running e2fsck on extracted partition..."
113- # Запускаем проверку файловой системы (-f force, -n no changes/readonly)
153+ # Запускаем проверку файловой системы
154+ # -f: force checking even if clean
155+ # -n: open in read-only mode
114156 /sbin/e2fsck -f -n ext2_dump.img
157+
115158 if [ $? -eq 0 ]; then
116- echo "EXT2 Filesystem is VALID."
159+ echo "SUCCESS: EXT2 Filesystem is VALID."
117160 else
118- echo "EXT2 Filesystem is CORRUPT."
161+ echo "FAILURE: EXT2 Filesystem is CORRUPT."
119162 exit 1
120163 fi
121164
@@ -125,171 +168,3 @@ jobs:
125168 path : |
126169 build/pfsshell
127170 build/pfs2tar
128-
129- - name : Build pfsfuse
130- run : |
131- rm -rf build/
132- meson setup build/ -Denable_pfsfuse=true
133- meson compile -C build
134-
135- - uses : actions/upload-artifact@v4
136- with :
137- name : pfsfuse-ubuntu
138- path : build/pfsfuse
139-
140- # ... (Остальные jobs: build-win32, build-macos и т.д. остаются без изменений) ...
141- build-win32 :
142- runs-on : ubuntu-latest
143- timeout-minutes : 20
144- container :
145- image : ubuntu:20.04
146- options : --user 0
147- steps :
148- - run : |
149- apt-get -y update
150- apt-get -y -o Dpkg::Options::='--force-confdef' -o Dpkg::Options::='--force-confold' install build-essential mingw-w64 git p7zip-full
151- update-alternatives --set i686-w64-mingw32-gcc /usr/bin/i686-w64-mingw32-gcc-posix
152- update-alternatives --set i686-w64-mingw32-g++ /usr/bin/i686-w64-mingw32-g++-posix
153- - uses : actions/checkout@v6
154- with :
155- submodules : recursive
156- - uses : actions/setup-python@v3
157- with :
158- python-version : 3.13.3
159- - uses : actions/cache@v3
160- with :
161- path : ~/.cache/pip
162- key : ${{ runner.os }}-pip
163- restore-keys : ${{ runner.os }}-pip
164- - run : python -m pip install --upgrade meson ninja
165- - run : |
166- meson setup build/ -Denable_pfs2tar=true --cross-file ./external/meson_toolchains/mingw32_meson.ini
167- meson compile -C build archive
168- - uses : actions/upload-artifact@v4
169- with :
170- name : pfsshell-win32
171- path : build/*.7z
172-
173- build-pfsfuse-win32 :
174- runs-on : windows-latest
175- timeout-minutes : 20
176- defaults :
177- run :
178- shell : msys2 {0}
179- steps :
180- - name : Install MSYS2 packages
181- uses : msys2/setup-msys2@v2
182- with :
183- msystem : MINGW32
184- install : base-devel git make texinfo patch binutils mpc-devel p7zip mingw-w64-i686-gcc mingw-w64-i686-cmake mingw-w64-i686-make mingw-w64-i686-meson
185- update : true
186- shell : msys2 {0}
187- - uses : actions/checkout@v6
188- with :
189- submodules : recursive
190- - name : Enable git symlinks
191- run : |
192- git config core.symlinks true
193- git reset --hard
194- - name : Build pfsfuse
195- run : |
196- meson setup build/ -Denable_pfsfuse=true
197- meson compile -C build
198- cp -f external/dokany/license.lgpl.txt build/
199- - uses : actions/upload-artifact@v4
200- with :
201- name : pfsfuse-win32
202- path : |
203- build/pfsfuse.exe
204- build/libdokanfuse*.dll
205- build/license.lgpl.txt
206-
207- build-macos :
208- runs-on : macos-latest
209- timeout-minutes : 20
210- steps :
211- - uses : actions/checkout@v6
212- with :
213- submodules : recursive
214- - uses : actions/setup-python@v3
215- with :
216- python-version : 3.x
217- - uses : actions/cache@v3
218- with :
219- path : ~/.cache/pip
220- key : ${{ runner.os }}-pip
221- restore-keys : ${{ runner.os }}-pip
222- - run : python -m pip install --upgrade meson ninja
223- - run : brew install macfuse coreutils
224- - run : |
225- meson setup build/ -Denable_pfs2tar=true
226- meson compile -C build
227- - name : Run Test
228- run : |
229- cd test
230- time ./pfsshell_test.tcl
231- - uses : actions/upload-artifact@v4
232- with :
233- name : pfsshell-macos
234- path : |
235- build/pfsshell
236- build/pfs2tar
237- - run : |
238- rm -rf build/
239- meson setup build/ -Denable_pfsfuse=true
240- meson compile -C build
241- - uses : actions/upload-artifact@v4
242- with :
243- name : pfsfuse-macos
244- path : build/pfsfuse
245-
246- create-release :
247- needs : [build-ubuntu, build-win32, build-macos, build-pfsfuse-win32]
248- runs-on : ubuntu-latest
249- timeout-minutes : 20
250- container :
251- image : ubuntu:20.04
252- options : --user 0
253- if : startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/master'
254- steps :
255- - name : Download all artifact
256- uses : actions/download-artifact@v4
257- - name : Install build dependancies
258- run : |
259- apt-get -y update
260- apt-get -y -o Dpkg::Options::='--force-confdef' -o Dpkg::Options::='--force-confold' install p7zip-full
261- - name : Prepare artifacts for release
262- run : |
263- 7z a -tzip pfsshell-ubuntu.zip pfsshell-ubuntu/*
264- 7z a -tzip pfsshell-macos.zip pfsshell-macos/*
265- 7z a -tzip pfsfuse-ubuntu.zip pfsfuse-ubuntu/*
266- 7z a -tzip pfsfuse-macos.zip pfsfuse-macos/*
267- 7z a -tzip pfsfuse-win32.zip pfsfuse-win32/*
268- - name : Create prerelease
269- if : github.ref == 'refs/heads/master'
270- uses : marvinpinto/action-automatic-releases@latest
271- with :
272- repo_token : ${{ secrets.GITHUB_TOKEN }}
273- prerelease : true
274- automatic_release_tag : latest
275- title : Latest development builds
276- files : |
277- pfsshell-win32/*
278- pfsfuse-win32.zip
279- pfsshell-ubuntu.zip
280- pfsshell-macos.zip
281- pfsfuse-ubuntu.zip
282- pfsfuse-macos.zip
283- - name : Create release
284- if : startsWith(github.ref, 'refs/tags/v')
285- uses : marvinpinto/action-automatic-releases@latest
286- with :
287- repo_token : ${{ secrets.GITHUB_TOKEN }}
288- prerelease : ${{ contains(github.ref, '-rc') }}
289- files : |
290- pfsshell-win32/*
291- pfsfuse-win32.zip
292- pfsshell-ubuntu.zip
293- pfsshell-macos.zip
294- pfsfuse-ubuntu.zip
295- pfsfuse-macos.zip
0 commit comments