mirror of
https://github.com/akuker/RASCSI.git
synced 2025-01-10 17:30:47 +00:00
Improve and fix bugs with saving&loading configuration files for rascsi-web (#218)
* Translate code commends into English, removing redundant ones * - Translated all remaining Japanese code comments in src/raspberrypi/ to English, with the exception of cfilesystem.cpp|h - Removed some redundant comments where the context is obvious from the code - Fixed a few typos and mistakes * - Store only file path and name to configuration csv - Strip known non-file path strings when reading configuration csv (backwards compatibility) - Validate SCSI ID before attempting to attach a device * Add comment and TODO * Partial translation of cfilesystem.h * Move csv read/write logic into file_cmd.py * Load default.csv on rascsi-web startup * Add rudimentary error handling to config loading/saving * Implement a delete configuration csv file feature. Also rename the delete_image method to delete_file and made it take the full file patch as argument to be consistent with other file operation methods. * Catch the exception when attempting to exclude SCSI id that is already in use from a list of valid SCSI ids * Fix error handling when failing to open a csv file for read or write
This commit is contained in:
parent
8fc8531b5b
commit
436e54d83c
@ -16,330 +16,321 @@
|
|||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// ステータスコード定義
|
// Status code definitions
|
||||||
//
|
//
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
#define FS_INVALIDFUNC 0xFFFFFFFF ///< 無効なファンクションコードを実行した
|
#define FS_INVALIDFUNC 0xFFFFFFFF ///< Executed an invalid function
|
||||||
#define FS_FILENOTFND 0xFFFFFFFE ///< 指定したファイルが見つからない
|
#define FS_FILENOTFND 0xFFFFFFFE ///< The selected file can not be found
|
||||||
#define FS_DIRNOTFND 0xFFFFFFFD ///< 指定したディレクトリが見つからない
|
#define FS_DIRNOTFND 0xFFFFFFFD ///< The selected directory can not be found
|
||||||
#define FS_OVEROPENED 0xFFFFFFFC ///< オープンしているファイルが多すぎる
|
#define FS_OVEROPENED 0xFFFFFFFC ///< There are too many files open
|
||||||
#define FS_CANTACCESS 0xFFFFFFFB ///< ディレクトリやボリュームラベルはアクセス不可
|
#define FS_CANTACCESS 0xFFFFFFFB ///< Can not access the direcory or volume
|
||||||
#define FS_NOTOPENED 0xFFFFFFFA ///< 指定したハンドルはオープンされていない
|
#define FS_NOTOPENED 0xFFFFFFFA ///< The selected handle is not opened
|
||||||
#define FS_INVALIDMEM 0xFFFFFFF9 ///< メモリ管理領域が破壊された
|
#define FS_INVALIDMEM 0xFFFFFFF9 ///< Memory management has been destroyed
|
||||||
#define FS_OUTOFMEM 0xFFFFFFF8 ///< 実行に必要なメモリがない
|
#define FS_OUTOFMEM 0xFFFFFFF8 ///< Insufficient memory for execution
|
||||||
#define FS_INVALIDPTR 0xFFFFFFF7 ///< 無効なメモリ管理ポインタを指定した
|
#define FS_INVALIDPTR 0xFFFFFFF7 ///< Selected an invalid memory management pointer
|
||||||
#define FS_INVALIDENV 0xFFFFFFF6 ///< 不正な環境を指定した
|
#define FS_INVALIDENV 0xFFFFFFF6 ///< Selected an invalid environment
|
||||||
#define FS_ILLEGALFMT 0xFFFFFFF5 ///< 実行ファイルのフォーマットが異常
|
#define FS_ILLEGALFMT 0xFFFFFFF5 ///< The exeucted file is in an invalid format
|
||||||
#define FS_ILLEGALMOD 0xFFFFFFF4 ///< オープンのアクセスモードが異常
|
#define FS_ILLEGALMOD 0xFFFFFFF4 ///< Invalid open access mode
|
||||||
#define FS_INVALIDPATH 0xFFFFFFF3 ///< ファイル名の指定に誤りがある
|
#define FS_INVALIDPATH 0xFFFFFFF3 ///< Mistake in selected file name
|
||||||
#define FS_INVALIDPRM 0xFFFFFFF2 ///< 無効なパラメータでコールした
|
#define FS_INVALIDPRM 0xFFFFFFF2 ///< Called with an invalid parameter
|
||||||
#define FS_INVALIDDRV 0xFFFFFFF1 ///< ドライブ指定に誤りがある
|
#define FS_INVALIDDRV 0xFFFFFFF1 ///< Mistake in selected drive
|
||||||
#define FS_DELCURDIR 0xFFFFFFF0 ///< カレントディレクトリは削除できない
|
#define FS_DELCURDIR 0xFFFFFFF0 ///< Unable to delete the current directory
|
||||||
#define FS_NOTIOCTRL 0xFFFFFFEF ///< IOCTRLできないデバイス
|
#define FS_NOTIOCTRL 0xFFFFFFEF ///< Unable to use IOCTRL with the device
|
||||||
#define FS_LASTFILE 0xFFFFFFEE ///< これ以上ファイルが見つからない
|
#define FS_LASTFILE 0xFFFFFFEE ///< Can not find any more files
|
||||||
#define FS_CANTWRITE 0xFFFFFFED ///< 指定のファイルは書き込みできない
|
#define FS_CANTWRITE 0xFFFFFFED ///< Selected file can not be written
|
||||||
#define FS_DIRALREADY 0xFFFFFFEC ///< 指定のディレクトリは既に登録されている
|
#define FS_DIRALREADY 0xFFFFFFEC ///< Selected directory is already registered
|
||||||
#define FS_CANTDELETE 0xFFFFFFEB ///< ファイルがあるので削除できない
|
#define FS_CANTDELETE 0xFFFFFFEB ///< Can not delete because of a file
|
||||||
#define FS_CANTRENAME 0xFFFFFFEA ///< ファイルがあるのでリネームできない
|
#define FS_CANTRENAME 0xFFFFFFEA ///< Can not rename because of a file
|
||||||
#define FS_DISKFULL 0xFFFFFFE9 ///< ディスクが一杯でファイルが作れない
|
#define FS_DISKFULL 0xFFFFFFE9 ///< Can not create a file because the disk is full
|
||||||
#define FS_DIRFULL 0xFFFFFFE8 ///< ディレクトリが一杯でファイルが作れない
|
#define FS_DIRFULL 0xFFFFFFE8 ///< Can not create a file because the directory is full
|
||||||
#define FS_CANTSEEK 0xFFFFFFE7 ///< 指定の位置にはシークできない
|
#define FS_CANTSEEK 0xFFFFFFE7 ///< Can not seek in the selected location
|
||||||
#define FS_SUPERVISOR 0xFFFFFFE6 ///< スーパーバイザ状態でスーパバイザ指定した
|
#define FS_SUPERVISOR 0xFFFFFFE6 ///< Selected supervisor in supervisor mode
|
||||||
#define FS_THREADNAME 0xFFFFFFE5 ///< 同じスレッド名が存在する
|
#define FS_THREADNAME 0xFFFFFFE5 ///< A thread with this name already exists
|
||||||
#define FS_BUFWRITE 0xFFFFFFE4 ///< プロセス間通信のバッファが書込み禁止
|
#define FS_BUFWRITE 0xFFFFFFE4 ///< Writing to inter-process communication buffers is disallowed
|
||||||
#define FS_BACKGROUND 0xFFFFFFE3 ///< バックグラウンドプロセスを起動できない
|
#define FS_BACKGROUND 0xFFFFFFE3 ///< Unable to start a background process
|
||||||
#define FS_OUTOFLOCK 0xFFFFFFE0 ///< ロック領域が足りない
|
#define FS_OUTOFLOCK 0xFFFFFFE0 ///< Insufficient lock space
|
||||||
#define FS_LOCKED 0xFFFFFFDF ///< ロックされていてアクセスできない
|
#define FS_LOCKED 0xFFFFFFDF ///< Can not access because it is locked
|
||||||
#define FS_DRIVEOPENED 0xFFFFFFDE ///< 指定のドライブはハンドラがオープンされている
|
#define FS_DRIVEOPENED 0xFFFFFFDE ///< Selected drive has an open handler
|
||||||
#define FS_LINKOVER 0xFFFFFFDD ///< シンボリックリンクネストが16回を超えた
|
#define FS_LINKOVER 0xFFFFFFDD ///< The symbolic link is nested over 16 times
|
||||||
#define FS_FILEEXIST 0xFFFFFFB0 ///< ファイルが存在する
|
#define FS_FILEEXIST 0xFFFFFFB0 ///< The file exists
|
||||||
|
|
||||||
#define FS_FATAL_MEDIAOFFLINE 0xFFFFFFA3 ///< メディアが入っていない
|
#define FS_FATAL_MEDIAOFFLINE 0xFFFFFFA3 ///< No media inserted
|
||||||
#define FS_FATAL_WRITEPROTECT 0xFFFFFFA2 ///< 書き込み禁止違反
|
#define FS_FATAL_WRITEPROTECT 0xFFFFFFA2 ///< Write protected
|
||||||
#define FS_FATAL_INVALIDCOMMAND 0xFFFFFFA1 ///< 不正なコマンド番号
|
#define FS_FATAL_INVALIDCOMMAND 0xFFFFFFA1 ///< Invalid command number
|
||||||
#define FS_FATAL_INVALIDUNIT 0xFFFFFFA0 ///< 不正なユニット番号
|
#define FS_FATAL_INVALIDUNIT 0xFFFFFFA0 ///< Invalid unit number
|
||||||
|
|
||||||
#define HUMAN68K_PATH_MAX 96 ///< Human68kのパス最大長
|
#define HUMAN68K_PATH_MAX 96 ///< Longest path allowed in Human68k
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
/// Human68k 名前空間
|
/// Human68k name space
|
||||||
//
|
//
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
namespace Human68k {
|
namespace Human68k {
|
||||||
/// ファイル属性ビット
|
/// File attribute bit
|
||||||
enum attribute_t {
|
enum attribute_t {
|
||||||
AT_READONLY = 0x01, ///< 読み込み専用属性
|
AT_READONLY = 0x01, ///< Read only attribute
|
||||||
AT_HIDDEN = 0x02, ///< 隠し属性
|
AT_HIDDEN = 0x02, ///< Hidden attribute
|
||||||
AT_SYSTEM = 0x04, ///< システム属性
|
AT_SYSTEM = 0x04, ///< System attribute
|
||||||
AT_VOLUME = 0x08, ///< ボリュームラベル属性
|
AT_VOLUME = 0x08, ///< Volume label attribute
|
||||||
AT_DIRECTORY = 0x10, ///< ディレクトリ属性
|
AT_DIRECTORY = 0x10, ///< Directory attribute
|
||||||
AT_ARCHIVE = 0x20, ///< アーカイブ属性
|
AT_ARCHIVE = 0x20, ///< Archive attribute
|
||||||
AT_ALL = 0xFF, ///< 全ての属性ビットが1
|
AT_ALL = 0xFF, ///< All attribute bits are 1
|
||||||
};
|
};
|
||||||
|
|
||||||
/// ファイルオープンモード
|
/// File open modes
|
||||||
enum open_t {
|
enum open_t {
|
||||||
OP_READ = 0, ///< 読み込み
|
OP_READ = 0, ///< Read
|
||||||
OP_WRITE = 1, ///< 書き込み
|
OP_WRITE = 1, ///< Write
|
||||||
OP_FULL = 2, ///< 読み書き
|
OP_FULL = 2, ///< Read/Write
|
||||||
OP_MASK = 0x0F, ///< 判定用マスク
|
OP_MASK = 0x0F, ///< Decision mask
|
||||||
OP_SHARE_NONE = 0x10, ///< 共有禁止
|
OP_SHARE_NONE = 0x10, ///< Sharing forbidden
|
||||||
OP_SHARE_READ = 0x20, ///< 読み込み共有
|
OP_SHARE_READ = 0x20, ///< Read sharing
|
||||||
OP_SHARE_WRITE = 0x30, ///< 書き込み共有
|
OP_SHARE_WRITE = 0x30, ///< Write sharing
|
||||||
OP_SHARE_FULL = 0x40, ///< 読み書き共有
|
OP_SHARE_FULL = 0x40, ///< Read/Write sharing
|
||||||
OP_SHARE_MASK = 0x70, ///< 共有判定用マスク
|
OP_SHARE_MASK = 0x70, ///< Sharing decision mask
|
||||||
OP_SPECIAL = 0x100, ///< 辞書アクセス
|
OP_SPECIAL = 0x100, ///< Dictionary access
|
||||||
};
|
};
|
||||||
|
|
||||||
/// シーク種類
|
/// Seek types
|
||||||
enum seek_t {
|
enum seek_t {
|
||||||
SK_BEGIN = 0, ///< ファイル先頭から
|
SK_BEGIN = 0, ///< From the beginning of a file
|
||||||
SK_CURRENT = 1, ///< 現在位置から
|
SK_CURRENT = 1, ///< From the current location
|
||||||
SK_END = 2, ///< ファイル末尾から
|
SK_END = 2, ///< From the end of the file
|
||||||
};
|
};
|
||||||
|
|
||||||
/// メディアバイト
|
/// Media byte
|
||||||
enum media_t {
|
enum media_t {
|
||||||
MEDIA_2DD_10 = 0xE0, ///< 2DD/10セクタ
|
MEDIA_2DD_10 = 0xE0, ///< 2DD/10 sector
|
||||||
MEDIA_1D_9 = 0xE5, ///< 1D/9セクタ
|
MEDIA_1D_9 = 0xE5, ///< 1D/9 sector
|
||||||
MEDIA_2D_9 = 0xE6, ///< 2D/9セクタ
|
MEDIA_2D_9 = 0xE6, ///< 2D/9 sector
|
||||||
MEDIA_1D_8 = 0xE7, ///< 1D/8セクタ
|
MEDIA_1D_8 = 0xE7, ///< 1D/8 sector
|
||||||
MEDIA_2D_8 = 0xE8, ///< 2D/8セクタ
|
MEDIA_2D_8 = 0xE8, ///< 2D/8 sector
|
||||||
MEDIA_2HT = 0xEA, ///< 2HT
|
MEDIA_2HT = 0xEA, ///< 2HT
|
||||||
MEDIA_2HS = 0xEB, ///< 2HS
|
MEDIA_2HS = 0xEB, ///< 2HS
|
||||||
MEDIA_2HDE = 0xEC, ///< 2DDE
|
MEDIA_2HDE = 0xEC, ///< 2DDE
|
||||||
MEDIA_1DD_9 = 0xEE, ///< 1DD/9セクタ
|
MEDIA_1DD_9 = 0xEE, ///< 1DD/9 sector
|
||||||
MEDIA_1DD_8 = 0xEF, ///< 1DD/8セクタ
|
MEDIA_1DD_8 = 0xEF, ///< 1DD/8 sector
|
||||||
MEDIA_MANUAL = 0xF1, ///< リモートドライブ (手動イジェクト)
|
MEDIA_MANUAL = 0xF1, ///< Remote drive (manual eject)
|
||||||
MEDIA_REMOVABLE = 0xF2, ///< リモートドライブ (リムーバブル)
|
MEDIA_REMOVABLE = 0xF2, ///< Remote drive (removable)
|
||||||
MEDIA_REMOTE = 0xF3, ///< リモートドライブ
|
MEDIA_REMOTE = 0xF3, ///< Remote drive
|
||||||
MEDIA_DAT = 0xF4, ///< SCSI-DAT
|
MEDIA_DAT = 0xF4, ///< SCSI-DAT
|
||||||
MEDIA_CDROM = 0xF5, ///< SCSI-CDROM
|
MEDIA_CDROM = 0xF5, ///< SCSI-CDROM
|
||||||
MEDIA_MO = 0xF6, ///< SCSI-MO
|
MEDIA_MO = 0xF6, ///< SCSI-MO
|
||||||
MEDIA_SCSI_HD = 0xF7, ///< SCSI-HD
|
MEDIA_SCSI_HD = 0xF7, ///< SCSI-HD
|
||||||
MEDIA_SASI_HD = 0xF8, ///< SASI-HD
|
MEDIA_SASI_HD = 0xF8, ///< SASI-HD
|
||||||
MEDIA_RAMDISK = 0xF9, ///< RAMディスク
|
MEDIA_RAMDISK = 0xF9, ///< RAM disk
|
||||||
MEDIA_2HQ = 0xFA, ///< 2HQ
|
MEDIA_2HQ = 0xFA, ///< 2HQ
|
||||||
MEDIA_2DD_8 = 0xFB, ///< 2DD/8セクタ
|
MEDIA_2DD_8 = 0xFB, ///< 2DD/8 sector
|
||||||
MEDIA_2DD_9 = 0xFC, ///< 2DD/9セクタ
|
MEDIA_2DD_9 = 0xFC, ///< 2DD/9 sector
|
||||||
MEDIA_2HC = 0xFD, ///< 2HC
|
MEDIA_2HC = 0xFD, ///< 2HC
|
||||||
MEDIA_2HD = 0xFE, ///< 2HD
|
MEDIA_2HD = 0xFE, ///< 2HD
|
||||||
};
|
};
|
||||||
|
|
||||||
/// namests構造体
|
|
||||||
struct namests_t {
|
struct namests_t {
|
||||||
BYTE wildcard; ///< ワイルドカード文字数
|
BYTE wildcard; ///< Wildcard array
|
||||||
BYTE drive; ///< ドライブ番号
|
BYTE drive; ///< Drive number
|
||||||
BYTE path[65]; ///< パス(サブディレクトリ+/)
|
BYTE path[65]; ///< Path (subdirectory +/)
|
||||||
BYTE name[8]; ///< ファイル名 (PADDING 0x20)
|
BYTE name[8]; ///< File name (PADDING 0x20)
|
||||||
BYTE ext[3]; ///< 拡張子 (PADDING 0x20)
|
BYTE ext[3]; ///< Extension (PADDING 0x20)
|
||||||
BYTE add[10]; ///< ファイル名追加 (PADDING 0x00)
|
BYTE add[10]; ///< File name addition (PADDING 0x00)
|
||||||
|
|
||||||
// 文字列取得
|
|
||||||
void GetCopyPath(BYTE* szPath) const;
|
void GetCopyPath(BYTE* szPath) const;
|
||||||
///< パス名取得
|
|
||||||
void GetCopyFilename(BYTE* szFilename) const;
|
void GetCopyFilename(BYTE* szFilename) const;
|
||||||
///< ファイル名取得
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// files構造体
|
|
||||||
struct files_t {
|
struct files_t {
|
||||||
BYTE fatr; ///< + 0 検索する属性 読込専用
|
BYTE fatr; ///< + 0 search attribute; read-only
|
||||||
// BYTE drive; ///< + 1 ドライブ番号 読込専用
|
// BYTE drive; ///< + 1 drive number; read-only
|
||||||
DWORD sector; ///< + 2 ディレクトリのセクタ DOS _FILES先頭アドレスで代用
|
DWORD sector; ///< + 2 directory sector; DOS _FILES first address substitute
|
||||||
// WORD cluster; ///< + 6 ディレクトリのクラスタ 詳細不明 (未使用)
|
// WORD cluster; ///< + 6 directory cluster; details unknown (unused)
|
||||||
WORD offset; ///< + 8 ディレクトリエントリ 書込専用
|
WORD offset; ///< + 8 directory entry; write-only
|
||||||
// BYTE name[8]; ///< +10 作業用ファイル名 読込専用 (未使用)
|
// BYTE name[8]; ///< +10 working file name; write-only (unused)
|
||||||
// BYTE ext[3]; ///< +18 作業用拡張子 読込専用 (未使用)
|
// BYTE ext[3]; ///< +18 working extension; write-only (unused)
|
||||||
BYTE attr; ///< +21 ファイル属性 書込専用
|
BYTE attr; ///< +21 file attribute; write-only
|
||||||
WORD time; ///< +22 最終変更時刻 書込専用
|
WORD time; ///< +22 last change time of day; write-only
|
||||||
WORD date; ///< +24 最終変更月日 書込専用
|
WORD date; ///< +24 last change date; write-only
|
||||||
DWORD size; ///< +26 ファイルサイズ 書込専用
|
DWORD size; ///< +26 file size; write-only
|
||||||
BYTE full[23]; ///< +30 フルファイル名 書込専用
|
BYTE full[23]; ///< +30 full name; write-only
|
||||||
};
|
};
|
||||||
|
|
||||||
/// FCB構造体
|
|
||||||
struct fcb_t {
|
struct fcb_t {
|
||||||
// BYTE pad00[6]; ///< + 0~+ 5 (未使用)
|
// BYTE pad00[6]; ///< + 0~+ 5 (unused)
|
||||||
DWORD fileptr; ///< + 6~+ 9 ファイルポインタ
|
DWORD fileptr; ///< + 6~+ 9 file pointer
|
||||||
// BYTE pad01[4]; ///< +10~+13 (未使用)
|
// BYTE pad01[4]; ///< +10~+13 (unused)
|
||||||
WORD mode; ///< +14~+15 オープンモード
|
WORD mode; ///< +14~+15 open mode
|
||||||
// BYTE pad02[16]; ///< +16~+31 (未使用)
|
// BYTE pad02[16]; ///< +16~+31 (unused)
|
||||||
// DWORD zero; ///< +32~+35 オープンのとき0が書き込まれている (未使用)
|
// DWORD zero; ///< +32~+35 zeros are written when opened (unused)
|
||||||
// BYTE name[8]; ///< +36~+43 ファイル名 (PADDING 0x20) (未使用)
|
// BYTE name[8]; ///< +36~+43 file name (PADDING 0x20) (unused)
|
||||||
// BYTE ext[3]; ///< +44~+46 拡張子 (PADDING 0x20) (未使用)
|
// BYTE ext[3]; ///< +44~+46 extension (PADDING 0x20) (unused)
|
||||||
BYTE attr; ///< +47 ファイル属性
|
BYTE attr; ///< +47 file attribute
|
||||||
// BYTE add[10]; ///< +48~+57 ファイル名追加 (PADDING 0x00) (未使用)
|
// BYTE add[10]; ///< +48~+57 file name addition (PADDING 0x00) (unused)
|
||||||
WORD time; ///< +58~+59 最終変更時刻
|
WORD time; ///< +58~+59 last change time of day
|
||||||
WORD date; ///< +60~+61 最終変更月日
|
WORD date; ///< +60~+61 last change date
|
||||||
// WORD cluster; ///< +62~+63 クラスタ番号 (未使用)
|
// WORD cluster; ///< +62~+63 cluster number (unused)
|
||||||
DWORD size; ///< +64~+67 ファイルサイズ
|
DWORD size; ///< +64~+67 file size
|
||||||
// BYTE pad03[28]; ///< +68~+95 FATキャッシュ (未使用)
|
// BYTE pad03[28]; ///< +68~+95 FAT cache (unused)
|
||||||
};
|
};
|
||||||
|
|
||||||
/// capacity構造体
|
|
||||||
struct capacity_t {
|
struct capacity_t {
|
||||||
WORD freearea; ///< + 0 使用可能なクラスタ数
|
WORD freearea; ///< + 0 Number of available clusters
|
||||||
WORD clusters; ///< + 2 総クラスタ数
|
WORD clusters; ///< + 2 Total number of clusters
|
||||||
WORD sectors; ///< + 4 クラスタあたりのセクタ数
|
WORD sectors; ///< + 4 Number of sectors per cluster
|
||||||
WORD bytes; ///< + 6 セクタ当たりのバイト数
|
WORD bytes; ///< + 6 Number of bytes per sector
|
||||||
};
|
};
|
||||||
|
|
||||||
/// ctrldrive構造体
|
|
||||||
struct ctrldrive_t {
|
struct ctrldrive_t {
|
||||||
BYTE status; ///< +13 状態
|
BYTE status; ///< +13 status
|
||||||
BYTE pad[3]; ///< Padding
|
BYTE pad[3]; ///< Padding
|
||||||
};
|
};
|
||||||
|
|
||||||
/// DPB構造体
|
|
||||||
struct dpb_t {
|
struct dpb_t {
|
||||||
WORD sector_size; ///< + 0 1セクタ当りのバイト数
|
WORD sector_size; ///< + 0 Number of bytes in one sector
|
||||||
BYTE cluster_size; ///< + 2 1クラスタ当りのセクタ数-1
|
BYTE cluster_size; ///< + 2 Number sectors in one cluster -1
|
||||||
BYTE shift; ///< + 3 クラスタ→セクタのシフト数
|
BYTE shift; ///< + 3 Number of cluster→sector shifts
|
||||||
WORD fat_sector; ///< + 4 FATの先頭セクタ番号
|
WORD fat_sector; ///< + 4 FAT first sector number
|
||||||
BYTE fat_max; ///< + 6 FAT領域の個数
|
BYTE fat_max; ///< + 6 FAT storage quantity
|
||||||
BYTE fat_size; ///< + 7 FATの占めるセクタ数(複写分を除く)
|
BYTE fat_size; ///< + 7 FAT controlled sector number (excluding duplicates)
|
||||||
WORD file_max; ///< + 8 ルートディレクトリに入るファイルの個数
|
WORD file_max; ///< + 8 Number of files in the root directory
|
||||||
WORD data_sector; ///< +10 データ領域の先頭セクタ番号
|
WORD data_sector; ///< +10 First sector number of data storage
|
||||||
WORD cluster_max; ///< +12 総クラスタ数+1
|
WORD cluster_max; ///< +12 Total number of clusters +1
|
||||||
WORD root_sector; ///< +14 ルートディレクトリの先頭セクタ番号
|
WORD root_sector; ///< +14 First sector number of root directory
|
||||||
// DWORD driverentry; ///< +16 デバイスドライバへのポインタ (未使用)
|
// DWORD driverentry; ///< +16 Device driver pointer (unused)
|
||||||
BYTE media; ///< +20 メディア識別子
|
BYTE media; ///< +20 Media identifier
|
||||||
// BYTE flag; ///< +21 DPB使用フラグ (未使用)
|
// BYTE flag; ///< +21 Flag used by DPB (unused)
|
||||||
};
|
};
|
||||||
|
|
||||||
/// ディレクトリエントリ構造体
|
/// Directory entry struct
|
||||||
struct dirent_t {
|
struct dirent_t {
|
||||||
BYTE name[8]; ///< + 0 ファイル名 (PADDING 0x20)
|
BYTE name[8]; ///< + 0 File name (PADDING 0x20)
|
||||||
BYTE ext[3]; ///< + 8 拡張子 (PADDING 0x20)
|
BYTE ext[3]; ///< + 8 Extension (PADDING 0x20)
|
||||||
BYTE attr; ///< +11 ファイル属性
|
BYTE attr; ///< +11 File attribute
|
||||||
BYTE add[10]; ///< +12 ファイル名追加 (PADDING 0x00)
|
BYTE add[10]; ///< +12 File name addition (PADDING 0x00)
|
||||||
WORD time; ///< +22 最終変更時刻
|
WORD time; ///< +22 Last change time of day
|
||||||
WORD date; ///< +24 最終変更月日
|
WORD date; ///< +24 Last change date
|
||||||
WORD cluster; ///< +26 クラスタ番号
|
WORD cluster; ///< +26 Cluster number
|
||||||
DWORD size; ///< +28 ファイルサイズ
|
DWORD size; ///< +28 File size
|
||||||
};
|
};
|
||||||
|
|
||||||
/// IOCTRLパラメータ共用体
|
/// IOCTRL parameter union
|
||||||
union ioctrl_t {
|
union ioctrl_t {
|
||||||
BYTE buffer[8]; ///< バイト単位でのアクセス
|
BYTE buffer[8]; ///< Access in byte units
|
||||||
DWORD param; ///< パラメータ(先頭4バイト)
|
DWORD param; ///< Parameter (First 4 bytes)
|
||||||
WORD media; ///< メディアバイト(先頭2バイト)
|
WORD media; ///< Media byte (First 2 bytes)
|
||||||
};
|
};
|
||||||
|
|
||||||
/// コマンドライン引数構造体
|
/// Command line parameter struct
|
||||||
/**
|
/**
|
||||||
先頭にドライバ自身のパスが含まれるためHUMAN68K_PATH_MAX以上のサイズにする。
|
The driver itself is included in the beginning of the argument,
|
||||||
|
so setting to a length longer than HUMAN68K_PATH_MAX
|
||||||
*/
|
*/
|
||||||
struct argument_t {
|
struct argument_t {
|
||||||
BYTE buf[256]; ///< コマンドライン引数
|
BYTE buf[256]; ///< Command line argument
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// FILES用バッファ個数
|
/// Number of FILES buffers
|
||||||
/**
|
/**
|
||||||
通常は数個で十分だが、Human68kの複数のプロセスがマルチタスクで同時に
|
Under normal circumstances it's enough with just a few buffers,
|
||||||
深い階層に渡って作業する時などはこの値を増やす必要がある。
|
but Human68k multitasking may lead to multiple threads working
|
||||||
|
deeply in the system, which is why this value is set this high.
|
||||||
|
|
||||||
デフォルトは20個。
|
Default is 20 buffers.
|
||||||
*/
|
*/
|
||||||
#define XM6_HOST_FILES_MAX 20
|
#define XM6_HOST_FILES_MAX 20
|
||||||
|
|
||||||
/// FCB用バッファ個数
|
/// Number of FCB buffers
|
||||||
/**
|
/**
|
||||||
同時にオープンできるファイル数はこれで決まる。
|
This decides how many files can be opened at the same time.
|
||||||
|
|
||||||
デフォルトは100ファイル。
|
Default is 100 files.
|
||||||
*/
|
*/
|
||||||
#define XM6_HOST_FCB_MAX 100
|
#define XM6_HOST_FCB_MAX 100
|
||||||
|
|
||||||
/// 仮想セクタ/クラスタ 最大個数
|
/// Max number of virtual clusters and sectors
|
||||||
/**
|
/**
|
||||||
ファイル実体の先頭セクタへのアクセスに対応するための仮想セクタの個数。
|
Number of virtual sectors used for accessing the first sector of a file entity.
|
||||||
lzdsysによるアクセスを行なうスレッドの数より多めに確保する。
|
Allocating a generous amount to exceed the number of threads lzdsys uses for access.
|
||||||
|
|
||||||
デフォルトは10セクタ。
|
Default is 10 sectors.
|
||||||
*/
|
*/
|
||||||
#define XM6_HOST_PSEUDO_CLUSTER_MAX 10
|
#define XM6_HOST_PSEUDO_CLUSTER_MAX 10
|
||||||
|
|
||||||
/// ディレクトリエントリ キャッシュ個数
|
/// Number of caches for directory entries
|
||||||
/**
|
/**
|
||||||
Human68kは、サブディレクトリ内で処理を行なう際にディレクトリエントリ
|
Human68k carries out a large number of checks of directory entries when doing an operation
|
||||||
のチェックを大量に発行する。この応答を高速化するための簡易キャッシュ
|
inside a subdirectory. This specifies the number of caches used to speed up this operation.
|
||||||
の個数を指定する。キャッシュは各ドライブ毎に確保される。
|
Cache is allocated per drive. The more you add the faster it gets, but use too many
|
||||||
多いほど高速になるが、増やしすぎるとホストOS側に負担がかかるので注意。
|
and the host OS gets under a heavy load, so be careful.
|
||||||
|
|
||||||
デフォルトは16個。
|
Default is 16.
|
||||||
*/
|
*/
|
||||||
#define XM6_HOST_DIRENTRY_CACHE_MAX 16
|
#define XM6_HOST_DIRENTRY_CACHE_MAX 16
|
||||||
|
|
||||||
/// 1ディレクトリに収納できるエントリの最大数
|
/// Max number of entries that can be stored per directory
|
||||||
/**
|
/**
|
||||||
ディレクトリ内にファイルが大量に存在すると、当時のアプリケーションが
|
When a large number of files are stored in a directory, a larger amount of data than
|
||||||
想定していない大量のデータを返してしまうことになる。アプリによっては
|
contemporanous applications can handle will be returned. This may lead to errors such as
|
||||||
一部しか認識されなかったり、速度が大幅に低下したり、メモリ不足で停止
|
partial data being recognized, performance dropping significantly, or OOM crashes.
|
||||||
するなどの危険性が存在する。このため上限を設定することで対処する。
|
To guard against this, an upper limit is defined here. In the case of a particular
|
||||||
例えばとあるファイラの場合、2560ファイルが上限となっている。この数を
|
file manager, the upper limit is 2560 files. This is one good example to use as reference.
|
||||||
一つの目安とするのが良い。
|
|
||||||
|
|
||||||
デフォルトは約6万エントリ。(FATのルートディレクトリでの上限値)
|
Default is around 60000 entries. (Upper limit of the FAT root directory)
|
||||||
*/
|
*/
|
||||||
#define XM6_HOST_DIRENTRY_FILE_MAX 65535
|
#define XM6_HOST_DIRENTRY_FILE_MAX 65535
|
||||||
|
|
||||||
/// ファイル名の重複除外パターンの最大数
|
/// Max number of patterns for file name deduplication
|
||||||
/**
|
/**
|
||||||
Human68k側のファイル名は、ホスト側のファイルシステムの名称をもとに自
|
The file names on the Human68k side are automatically created based on the file system on
|
||||||
動生成されるが、Human68k側のファイル名よりもホスト側のファイル名の名
|
the host side. However, Human68k have stricter file name length restrictions than the host has.
|
||||||
称のほうが長いため、同名のファイル名が生成されてしまう可能性がある。
|
Because of this, there is a risk that file name duplication will occur. When this happens,
|
||||||
その時、Human68k側からファイル名を区別できるようにするため、WindrvXM
|
WindrvXM will use a certain renaming heuristic to generate alternate file names to resolve
|
||||||
独自の命名規則に従って別名を生成して解決している。
|
the duplication. Theoretically, there are over 60 million (36^5) unique file names that
|
||||||
理論上は約6千万(36の5乗)通りの別名を生成できる方式を取っているが、実
|
can be generated by this method. However, in reality any more than a few hundred
|
||||||
際には数百パターン以上の重複判定が発生すると処理に時間がかかってしま
|
deduplications will take excessive processing time. So here an upper limit to deduplication
|
||||||
うため、重複の上限を設定することで速度を維持する。常識的な運用であれ
|
is set in order to maintain system performance. If a system is operated with common sense,
|
||||||
ば、代替名は数パターンもあれば十分運用できるはずであり、この値を可能
|
you should only need a few dozen deduplication patterns, so this value can be kept low
|
||||||
な限り小さい値にすることでパフォーマンスの改善が期待できる。
|
to further improce performance. In the case deduplication is not carried out, multiple files
|
||||||
この個数を超えるファイル名が重複してしまった場合は、同名のエントリが
|
with the same name will be created. When trying to access such files,
|
||||||
複数生成される。この場合、ファイル一覧では見えるがファイル名で指定す
|
only the first entry will ever be accessed.
|
||||||
ると最初のエントリのみ扱える状態となる。
|
|
||||||
|
|
||||||
デフォルトは36パターン。
|
Default is 36 patterns.
|
||||||
*/
|
*/
|
||||||
#define XM6_HOST_FILENAME_PATTERN_MAX 36
|
#define XM6_HOST_FILENAME_PATTERN_MAX 36
|
||||||
|
|
||||||
/// ファイル名重複防止マーク
|
/// Duplicate file identification mark
|
||||||
/**
|
/**
|
||||||
ホスト側のファイル名とHuman68k側ファイル名の名称の区別をつけるときに
|
A symbol used to distinguish between host and Human68k files.
|
||||||
使う文字。コマンドシェル等のエスケープ文字と重ならないものを選ぶと吉。
|
Do not use a command shell escape character, or similar protected symbol.
|
||||||
|
|
||||||
デフォルトは「@」。
|
Default is '@'.
|
||||||
*/
|
*/
|
||||||
#define XM6_HOST_FILENAME_MARK '@'
|
#define XM6_HOST_FILENAME_MARK '@'
|
||||||
|
|
||||||
/// WINDRV動作フラグ
|
/// WINDRV operational flags
|
||||||
/**
|
/**
|
||||||
通常は0にする。ファイル削除にOSのごみ箱機能を利用する場合は1にする。
|
Normally set to 0. When put in the OS trash can for deletion, it is set to 1.
|
||||||
それ以外の値は将来のための予約とする。
|
Other values are reserved for future use.
|
||||||
内部動作フラグとメディアバイト偽装などを見越した将来の拡張用。
|
Can be used for future extentions such as internal operational flags or mock media byte.
|
||||||
*/
|
*/
|
||||||
enum {
|
enum {
|
||||||
WINDRV_OPT_REMOVE = 0x00000001, ///< Bit 0: ファイル削除処理 0:直接 1:ごみ箱
|
WINDRV_OPT_REMOVE = 0x00000001, ///< Bit 0: File delete process 0:Directly 1:Trash can
|
||||||
WINDRV_OPT_ALPHABET = 0x00000020, ///< Bit 5: ファイル名比較 Alphabet区別 0:なし 1:あり 0:-C 1:+C
|
WINDRV_OPT_ALPHABET = 0x00000020, ///< Bit 5: File name comparison; Alphabet distinction 0:No 1:Yes 0:-C 1:+C
|
||||||
WINDRV_OPT_COMPARE_LENGTH = 0x00000040, ///< Bit 6: ファイル名比較 文字数(未実装) 0:18+3 1:8+3 0:+T 1:-T
|
WINDRV_OPT_COMPARE_LENGTH = 0x00000040, ///< Bit 6: File name comparison; String length (unimplemented) 0:18+3 1:8+3 0:+T 1:-T
|
||||||
WINDRV_OPT_CONVERT_LENGTH = 0x00000080, ///< Bit 7: ファイル名変換 文字数 0:18+3 1:8+3 0:-A 1:+A
|
WINDRV_OPT_CONVERT_LENGTH = 0x00000080, ///< Bit 7: File name conversion; String length 0:18+3 1:8+3 0:-A 1:+A
|
||||||
WINDRV_OPT_CONVERT_SPACE = 0x00000100, ///< Bit 8: ファイル名変換 スペース 0:なし 1:'_'
|
WINDRV_OPT_CONVERT_SPACE = 0x00000100, ///< Bit 8: File name conversion; Space 0:No 1:'_'
|
||||||
WINDRV_OPT_CONVERT_BADCHAR = 0x00000200, ///< Bit 9: ファイル名変換 無効な文字 0:なし 1:'_'
|
WINDRV_OPT_CONVERT_BADCHAR = 0x00000200, ///< Bit 9: File name conversion; Invalid char 0:No 1:'_'
|
||||||
WINDRV_OPT_CONVERT_HYPHENS = 0x00000400, ///< Bit10: ファイル名変換 中間のハイフン 0:なし 1:'_'
|
WINDRV_OPT_CONVERT_HYPHENS = 0x00000400, ///< Bit10: File name conversion; Middle hyphen 0:No 1:'_'
|
||||||
WINDRV_OPT_CONVERT_HYPHEN = 0x00000800, ///< Bit11: ファイル名変換 先頭のハイフン 0:なし 1:'_'
|
WINDRV_OPT_CONVERT_HYPHEN = 0x00000800, ///< Bit11: File name conversion; Initial hyphen 0:No 1:'_'
|
||||||
WINDRV_OPT_CONVERT_PERIODS = 0x00001000, ///< Bit12: ファイル名変換 中間のピリオド 0:なし 1:'_'
|
WINDRV_OPT_CONVERT_PERIODS = 0x00001000, ///< Bit12: File name conversion; Middle period 0:No 1:'_'
|
||||||
WINDRV_OPT_CONVERT_PERIOD = 0x00002000, ///< Bit13: ファイル名変換 先頭のピリオド 0:なし 1:'_'
|
WINDRV_OPT_CONVERT_PERIOD = 0x00002000, ///< Bit13: File name conversion; Initial period 0:No 1:'_'
|
||||||
WINDRV_OPT_REDUCED_SPACE = 0x00010000, ///< Bit16: ファイル名短縮 スペース 0:なし 1:短縮
|
WINDRV_OPT_REDUCED_SPACE = 0x00010000, ///< Bit16: File name reduction; Space 0:No 1:Reduced
|
||||||
WINDRV_OPT_REDUCED_BADCHAR = 0x00020000, ///< Bit17: ファイル名短縮 無効な文字 0:なし 1:短縮
|
WINDRV_OPT_REDUCED_BADCHAR = 0x00020000, ///< Bit17: File name reduction; Invalid char 0:No 1:Reduced
|
||||||
WINDRV_OPT_REDUCED_HYPHENS = 0x00040000, ///< Bit18: ファイル名短縮 中間のハイフン 0:なし 1:短縮
|
WINDRV_OPT_REDUCED_HYPHENS = 0x00040000, ///< Bit18: File name reduction Middle hyphen 0:No 1:Reduced
|
||||||
WINDRV_OPT_REDUCED_HYPHEN = 0x00080000, ///< Bit19: ファイル名短縮 先頭のハイフン 0:なし 1:短縮
|
WINDRV_OPT_REDUCED_HYPHEN = 0x00080000, ///< Bit19: File name reduction Initial hyphen 0:No 1:Reduced
|
||||||
WINDRV_OPT_REDUCED_PERIODS = 0x00100000, ///< Bit20: ファイル名短縮 中間のピリオド 0:なし 1:短縮
|
WINDRV_OPT_REDUCED_PERIODS = 0x00100000, ///< Bit20: File name reduction Middle period 0:No 1:Reduced
|
||||||
WINDRV_OPT_REDUCED_PERIOD = 0x00200000, ///< Bit21: ファイル名短縮 先頭のピリオド 0:なし 1:短縮
|
WINDRV_OPT_REDUCED_PERIOD = 0x00200000, ///< Bit21: File name reduction Initial period 0:No 1:Reduced
|
||||||
// Bit24~30 ファイル重複防止マーク 0:自動 1~127:文字
|
// Bit24~30 Duplicate file identification mark 0:Automatic 1~127:Chars
|
||||||
};
|
};
|
||||||
|
|
||||||
/// ファイルシステム動作フラグ
|
/// ファイルシステム動作フラグ
|
||||||
|
@ -2,8 +2,15 @@ import fnmatch
|
|||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import time
|
import time
|
||||||
|
import io
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
from ractl_cmds import attach_image
|
from ractl_cmds import (
|
||||||
|
attach_image,
|
||||||
|
detach_all,
|
||||||
|
list_devices,
|
||||||
|
)
|
||||||
from settings import *
|
from settings import *
|
||||||
|
|
||||||
|
|
||||||
@ -19,10 +26,9 @@ def create_new_image(file_name, type, size):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def delete_image(file_name):
|
def delete_file(file_name):
|
||||||
full_path = base_dir + file_name
|
if os.path.exists(file_name):
|
||||||
if os.path.exists(full_path):
|
os.remove(file_name)
|
||||||
os.remove(full_path)
|
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
@ -71,3 +77,49 @@ def download_image(url):
|
|||||||
full_path = base_dir + file_name
|
full_path = base_dir + file_name
|
||||||
|
|
||||||
urllib.request.urlretrieve(url, full_path)
|
urllib.request.urlretrieve(url, full_path)
|
||||||
|
|
||||||
|
def write_config_csv(file_name):
|
||||||
|
import csv
|
||||||
|
|
||||||
|
# This method takes the output of 'rasctl -l' and parses it into csv format:
|
||||||
|
# 0: ID
|
||||||
|
# 1: Unit Number (unused in rascsi-web)
|
||||||
|
# 2: Device Type
|
||||||
|
# 3: Device Status (includes the path to a loaded image file)
|
||||||
|
# TODO: Remove the dependence on rasctl; e.g. when implementing protobuf for rascsi-web
|
||||||
|
try:
|
||||||
|
with open(file_name, "w") as csv_file:
|
||||||
|
writer = csv.writer(csv_file)
|
||||||
|
for device in list_devices():
|
||||||
|
if device["type"] != "-":
|
||||||
|
device_info = list (device.values())
|
||||||
|
# Match a *nix file path inside column 3, cutting out the last chunk that starts with a space
|
||||||
|
filesearch = re.search("(^(/[^/ ]*)+)(\s.*)*$", device_info[3])
|
||||||
|
if filesearch is None:
|
||||||
|
device_info[3] = ""
|
||||||
|
else:
|
||||||
|
device_info[3] = filesearch.group(1)
|
||||||
|
writer.writerow(device_info)
|
||||||
|
return True
|
||||||
|
except:
|
||||||
|
print ("Could not open file for writing: ", file_name)
|
||||||
|
return False
|
||||||
|
|
||||||
|
def read_config_csv(file_name):
|
||||||
|
detach_all()
|
||||||
|
import csv
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(file_name) as csv_file:
|
||||||
|
config_reader = csv.reader(csv_file)
|
||||||
|
#TODO: Remove hard-coded string sanitation (e.g. after implementing protobuf)
|
||||||
|
exclude_list = ("X68000 HOST BRIDGE", "DaynaPort SCSI/Link", " (WRITEPROTECT)", "NO MEDIA")
|
||||||
|
for row in config_reader:
|
||||||
|
image_name = row[3]
|
||||||
|
for e in exclude_list:
|
||||||
|
image_name = image_name.replace(e, "")
|
||||||
|
attach_image(row[0], image_name, row[2])
|
||||||
|
return True
|
||||||
|
except:
|
||||||
|
print ("Could not access file: ", file_name)
|
||||||
|
return False
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import fnmatch
|
import fnmatch
|
||||||
import subprocess
|
import subprocess
|
||||||
import re
|
import re
|
||||||
|
import logging
|
||||||
|
|
||||||
from settings import *
|
from settings import *
|
||||||
|
|
||||||
@ -54,9 +55,12 @@ def get_valid_scsi_ids(devices):
|
|||||||
|
|
||||||
valid_list = list(range(8))
|
valid_list = list(range(8))
|
||||||
for id in invalid_list:
|
for id in invalid_list:
|
||||||
valid_list.remove(id)
|
try:
|
||||||
|
valid_list.remove(id)
|
||||||
|
except:
|
||||||
|
logging.warning("Reserved SCSI id " + str(id) + " is in use.")
|
||||||
valid_list.reverse()
|
valid_list.reverse()
|
||||||
|
|
||||||
return valid_list
|
return valid_list
|
||||||
|
|
||||||
|
|
||||||
|
@ -21,14 +21,19 @@
|
|||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h2>Current RaSCSI Configuration</h2>
|
<h2>Current RaSCSI Configuration</h2>
|
||||||
|
<p>The <em>default</em> configuration will be loaded when the Web UI starts up.</p>
|
||||||
|
<p>
|
||||||
<form action="/config/load" method="post">
|
<form action="/config/load" method="post">
|
||||||
<select name="name" >
|
<select name="name" >
|
||||||
{% for config in config_files %}
|
{% for config in config_files %}
|
||||||
<option value="{{config}}">{{config.replace(".csv", '')}}</option>
|
<option value="{{config}}">{{config.replace(".csv", '')}}</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
<input type="submit" value="Load" />
|
<input type="submit" name="load" value="Load" />
|
||||||
|
<input type="submit" name="delete" value="Delete" />
|
||||||
</form>
|
</form>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
<form action="/config/save" method="post">
|
<form action="/config/save" method="post">
|
||||||
<input name="name" placeholder="default">
|
<input name="name" placeholder="default">
|
||||||
<input type="submit" value="Save" />
|
<input type="submit" value="Save" />
|
||||||
@ -36,6 +41,7 @@
|
|||||||
<form action="/scsi/detach_all" method="post" onsubmit="return confirm('Detach all SCSI Devices?')">
|
<form action="/scsi/detach_all" method="post" onsubmit="return confirm('Detach all SCSI Devices?')">
|
||||||
<input type="submit" value="Detach All" />
|
<input type="submit" value="Detach All" />
|
||||||
</form>
|
</form>
|
||||||
|
</p>
|
||||||
|
|
||||||
<table cellpadding="3" border="black">
|
<table cellpadding="3" border="black">
|
||||||
<tbody>
|
<tbody>
|
||||||
|
@ -6,9 +6,11 @@ from flask import Flask, render_template, request, flash, url_for, redirect, sen
|
|||||||
from file_cmds import (
|
from file_cmds import (
|
||||||
create_new_image,
|
create_new_image,
|
||||||
download_file_to_iso,
|
download_file_to_iso,
|
||||||
delete_image,
|
delete_file,
|
||||||
unzip_file,
|
unzip_file,
|
||||||
download_image,
|
download_image,
|
||||||
|
write_config_csv,
|
||||||
|
read_config_csv,
|
||||||
)
|
)
|
||||||
from pi_cmds import shutdown_pi, reboot_pi, running_version, rascsi_service
|
from pi_cmds import shutdown_pi, reboot_pi, running_version, rascsi_service
|
||||||
from ractl_cmds import (
|
from ractl_cmds import (
|
||||||
@ -54,30 +56,28 @@ def index():
|
|||||||
def config_save():
|
def config_save():
|
||||||
file_name = request.form.get("name") or "default"
|
file_name = request.form.get("name") or "default"
|
||||||
file_name = f"{base_dir}{file_name}.csv"
|
file_name = f"{base_dir}{file_name}.csv"
|
||||||
import csv
|
|
||||||
|
|
||||||
with open(file_name, "w") as csv_file:
|
write_config_csv(file_name)
|
||||||
writer = csv.writer(csv_file)
|
|
||||||
for device in list_devices():
|
|
||||||
if device["type"] != "-":
|
|
||||||
writer.writerow(device.values())
|
|
||||||
flash(f"Saved config to {file_name}!")
|
flash(f"Saved config to {file_name}!")
|
||||||
return redirect(url_for("index"))
|
return redirect(url_for("index"))
|
||||||
|
|
||||||
|
|
||||||
@app.route("/config/load", methods=["POST"])
|
@app.route("/config/load", methods=["POST"])
|
||||||
def config_load():
|
def config_load():
|
||||||
file_name = request.form.get("name") or "default.csv"
|
file_name = request.form.get("name")
|
||||||
file_name = f"{base_dir}{file_name}"
|
file_name = f"{base_dir}{file_name}"
|
||||||
detach_all()
|
|
||||||
import csv
|
|
||||||
|
|
||||||
with open(file_name) as csv_file:
|
if "load" in request.form:
|
||||||
config_reader = csv.reader(csv_file)
|
if read_config_csv(file_name):
|
||||||
for row in config_reader:
|
flash(f"Loaded config from {file_name}!")
|
||||||
image_name = row[3].replace("(WRITEPROTECT)", "")
|
else:
|
||||||
attach_image(row[0], image_name, row[2])
|
flash(f"Failed to load {file_name}!", "error")
|
||||||
flash(f"Loaded config from {file_name}!")
|
elif "delete" in request.form:
|
||||||
|
if delete_file(file_name):
|
||||||
|
flash(f"Deleted config {file_name}!")
|
||||||
|
else:
|
||||||
|
flash(f"Failed to delete {file_name}!", "error")
|
||||||
|
|
||||||
return redirect(url_for("index"))
|
return redirect(url_for("index"))
|
||||||
|
|
||||||
|
|
||||||
@ -144,6 +144,11 @@ def attach():
|
|||||||
flash(f"Unknown file type. Valid files are: {', '.join(valid_file_suffix)}", "error")
|
flash(f"Unknown file type. Valid files are: {', '.join(valid_file_suffix)}", "error")
|
||||||
return redirect(url_for("index"))
|
return redirect(url_for("index"))
|
||||||
|
|
||||||
|
# Validate the SCSI ID
|
||||||
|
if re.match("[0-7]", str(scsi_id)) == None:
|
||||||
|
flash(f"Invalid SCSI ID. Should be a number between 0-7", "error")
|
||||||
|
return redirect(url_for("index"))
|
||||||
|
|
||||||
process = attach_image(scsi_id, file_name, image_type)
|
process = attach_image(scsi_id, file_name, image_type)
|
||||||
if process.returncode == 0:
|
if process.returncode == 0:
|
||||||
flash(f"Attached {file_name} to SCSI id {scsi_id}!")
|
flash(f"Attached {file_name} to SCSI id {scsi_id}!")
|
||||||
@ -283,7 +288,7 @@ def download():
|
|||||||
@app.route("/files/delete", methods=["POST"])
|
@app.route("/files/delete", methods=["POST"])
|
||||||
def delete():
|
def delete():
|
||||||
image = request.form.get("image")
|
image = request.form.get("image")
|
||||||
if delete_image(image):
|
if delete_file(base_dir + image):
|
||||||
flash("File " + image + " deleted")
|
flash("File " + image + " deleted")
|
||||||
return redirect(url_for("index"))
|
return redirect(url_for("index"))
|
||||||
else:
|
else:
|
||||||
@ -309,6 +314,8 @@ if __name__ == "__main__":
|
|||||||
app.config["UPLOAD_FOLDER"] = base_dir
|
app.config["UPLOAD_FOLDER"] = base_dir
|
||||||
os.makedirs(app.config["UPLOAD_FOLDER"], exist_ok=True)
|
os.makedirs(app.config["UPLOAD_FOLDER"], exist_ok=True)
|
||||||
app.config["MAX_CONTENT_LENGTH"] = MAX_FILE_SIZE
|
app.config["MAX_CONTENT_LENGTH"] = MAX_FILE_SIZE
|
||||||
|
|
||||||
|
read_config_csv(f"{base_dir}default.csv")
|
||||||
|
|
||||||
import bjoern
|
import bjoern
|
||||||
print("Serving rascsi-web...")
|
print("Serving rascsi-web...")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user