diff --git a/app.py b/app.py index 7adbafd..13cad44 100644 --- a/app.py +++ b/app.py @@ -2023,6 +2023,84 @@ def r_update_check(): return jsonify(ok=True) +FORMAT_FILESYSTEMS = { + 'exfat': { + 'label': 'exFAT', + 'desc': 'Empfohlen – Mac & Windows, keine 4-GB-Dateigrößenbeschränkung', + 'cmd': lambda dev, name: ['mkfs.exfat', '-n', name, dev], + 'pkg': 'exfatprogs', + }, + 'fat32': { + 'label': 'FAT32', + 'desc': 'Mac & Windows, max. 4 GB pro Datei', + 'cmd': lambda dev, name: ['mkfs.vfat', '-F', '32', '-n', name[:11], dev], + 'pkg': 'dosfstools', + }, + 'ntfs': { + 'label': 'NTFS', + 'desc': 'Windows nativ, Mac nur lesen', + 'cmd': lambda dev, name: ['mkfs.ntfs', '-f', '-L', name[:32], dev], + 'pkg': 'ntfs-3g', + }, +} + +format_state = {'running': False, 'error': None, 'done': False, 'fs': '', 'device': ''} + +@app.route('/api/format/status') +def r_format_status(): + return jsonify(dict(format_state)) + +@app.route('/api/format', methods=['POST']) +def r_format(): + if format_state['running']: + return jsonify(error='Formatierung läuft bereits'), 409 + if copy_state.get('running'): + return jsonify(error='Kopiervorgang läuft – bitte warten'), 409 + + body = request.get_json(force=True) + fs = body.get('fs', '').lower() + name = (body.get('name') or 'PICOPY').upper() + dev = body.get('device', '') + + if fs not in FORMAT_FILESYSTEMS: + return jsonify(error=f'Unbekanntes Dateisystem: {fs}'), 400 + if not dev.startswith('/dev/'): + return jsonify(error='Ungültiges Gerät'), 400 + + # Sicherheitscheck: Gerät muss ein bekanntes USB-Gerät sein + known = [d['device'] for d in usb_devices()] + if dev not in known: + return jsonify(error='Gerät nicht als USB-Laufwerk erkannt'), 400 + + def do_format(): + format_state.update(running=True, error=None, done=False, fs=fs, device=dev) + try: + # Aushängen falls gemountet + subprocess.run(['umount', dev], capture_output=True) + + cmd = FORMAT_FILESYSTEMS[fs]['cmd'](dev, name) + r = subprocess.run(cmd, capture_output=True, text=True, timeout=120) + if r.returncode != 0: + err = r.stderr.strip() or r.stdout.strip() or 'Unbekannter Fehler' + # Hilfreiche Meldung wenn Paket fehlt + pkg = FORMAT_FILESYSTEMS[fs]['pkg'] + if 'not found' in err or r.returncode == 127: + err = f'Befehl nicht gefunden – bitte installieren: apt install {pkg}' + format_state.update(error=err) + return + format_state.update(done=True) + log.info(f'Formatierung {fs} auf {dev} abgeschlossen') + except subprocess.TimeoutExpired: + format_state.update(error='Timeout – Formatierung dauerte zu lange') + except Exception as e: + format_state.update(error=str(e)) + finally: + format_state['running'] = False + + threading.Thread(target=do_format, daemon=True).start() + return jsonify(ok=True) + + @app.route('/api/system/reboot', methods=['POST']) def r_system_reboot(): threading.Thread(target=lambda: ( @@ -2432,10 +2510,35 @@ body{background:var(--bg);color:var(--txt);font-family:-apple-system,BlinkMacSys - +
+ + +
Gerät in den gewünschten Port → aus Liste wählen → Speichern. Ab dann wird dieser Port immer als Ziel verwendet.
+ + +