Feature image padding (#269)

* Implement pad_image method

* Reintroduce list_files method, rename the other to list_images

* Add iso file padding UI

* HDD image UI

* Tweak label

* Store padded image in the right dir

* Show only images that need padding

* Support padding MO images

* Cleanup

* UI flow to show drive properites (#270)

* Adjust MO padding to align with current develop

* Add docstrings

* Fix image padding code

* Tweak labels
This commit is contained in:
Daniel Markstedt 2021-10-05 19:12:51 -07:00 committed by GitHub
parent 7717890b5f
commit 5727f3ba0f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 103 additions and 0 deletions

View File

@ -200,6 +200,22 @@ def download_image(url):
return {"status": False, "msg": "Error loading the URL"}
def pad_image(file_name, file_size):
"""
Adds a number of bytes to the end of a file up to a size
Takes str file_name, int file_size
Returns a dict with boolean status and str msg
"""
from subprocess import run
dd_proc = run(
["dd", "if=/dev/null", f"of={file_name}", "bs=1", "count=1", f"seek={file_size}" ], capture_output=True
)
if dd_proc.returncode != 0:
return {"status": False, "msg": str(dd_proc)}
return {"status": True, "msg": "File padding successful" }
def write_config(file_name):
"""
Takes str file_name

View File

@ -320,6 +320,53 @@
<hr/>
<details>
<summary>Pad Image File</summary>
<ul>
<li>If RaSCSI fails to attach an image with a size error, you can try to pad it here. This will create a "_padded" copy of the file.</li>
<li>Drive images are padded to the nearest multiple of 512 bytes, CD-ROM images to multiples of 2048 bytes.</li>
<li>The UI only lists image files that may need padding based on their file sizes.</li>
<li>For other usecases, pad your file manually using a tool like <tt>dd</tt> on Linux.</li>
</ul>
</details>
<table style="border: none">
<tr style="border: none">
<td style="border: none; vertical-align:top;">
<form action="/files/pad" method="post">
<label for="image">Drive images:</label>
<select name="image">
{% for f in drive_files %}
{% if f[1] % 512 %}
<option value="{{f[0]}},{{f[1]}}">{{f[0]}}</option>
{% endif %}
{% endfor %}
</select>
<input type="hidden" name="multiple" value="512" />
<input type="submit" value="Pad image" />
</form>
</td>
</tr>
<tr style="border: none">
<td style="border: none; vertical-align:top;">
<form action="/files/pad" method="post">
<label for="image">CD-ROM images:</label>
<select name="image">
{% for f in cdrom_files %}
{% if f[1] % 2048 %}
<option value="{{f[0]}},{{f[1]}}">{{f[0]}}</option>
{% endif %}
{% endfor %}
</select>
<input type="hidden" name="multiple" value="2048" />
<input type="submit" value="Pad image" />
</form>
</td>
</tr>
</table>
<hr/>
<details>
<summary>Logging</summary>
<ul>

View File

@ -13,6 +13,7 @@ from flask import (
from file_cmds import (
list_config_files,
list_files,
list_images,
create_new_image,
download_file_to_iso,
@ -20,6 +21,7 @@ from file_cmds import (
delete_file,
unzip_file,
download_image,
pad_image,
write_config,
read_config,
write_drive_properties,
@ -60,6 +62,9 @@ def index():
device_types=get_device_types()
files = list_images()
config_files = list_config_files()
drive_files = list_files(tuple(server_info["sahd"] + \
server_info["schd"] + server_info["scrm"] + server_info["scmo"]))
cdrom_files = list_files(tuple(server_info["sccd"]))
sorted_image_files = sorted(files["files"], key = lambda x: x["name"].lower())
sorted_config_files = sorted(config_files, key = lambda x: x.lower())
@ -84,6 +89,8 @@ def index():
devices=formatted_devices,
files=sorted_image_files,
config_files=sorted_config_files,
drive_files=drive_files,
cdrom_files=cdrom_files,
base_dir=base_dir,
cfg_dir=cfg_dir,
scsi_ids=scsi_ids,
@ -559,6 +566,39 @@ def create_file():
return redirect(url_for("index"))
@app.route("/files/pad", methods=["POST"])
def image_padding():
image = request.form.get("image")
multiple = request.form.get("multiple")
if not image:
flash(f"No file selected!", "error")
return redirect(url_for("index"))
file, size = image.split(",")
if not int(size) % int(multiple):
flash(f"{file} does not need to be padded!", "error")
return redirect(url_for("index"))
else:
target_size = int(size) - (int(size) % int(multiple)) + int(multiple)
from pathlib import PurePath
padded_image = base_dir + str(PurePath(file).stem) + "_padded" + str(PurePath(file).suffix)
from shutil import copyfile
copyfile(base_dir + file, padded_image)
process = pad_image(padded_image, target_size)
if process["status"] == True:
flash(f"Added " + str(target_size - int(size)) + " bytes to " + padded_image + "!")
flash(process["msg"])
return redirect(url_for("index"))
else:
flash(f"Failed to pad image!", "error")
flash(process["msg"], "error")
return redirect(url_for("index"))
@app.route("/files/download", methods=["POST"])
def download():
image = request.form.get("image")