Files
MFTECmd-for-Linux/internal/cmd/cmd.go
Grigoryev Ilya Alekseevich 9df60aa41a rework args
2026-03-31 21:56:55 +05:00

277 lines
13 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package cmd
import (
"fmt"
"strings"
)
// Константы для значений по умолчанию
const (
DefaultTimeFormat = "yyyy-MM-dd HH:mm:ss.fffffff" // Формат временных меток
DefaultResidentMax = 1024 // Ограничение размера резидентных файлов
MaxResidentDataBytes = 1024000 // Максимальное ограничение размера резидентных файлов
)
// Корневая структура флагов.
// Используется для выбора типа файлов
type CLI struct {
Debug bool `help:"Show debug information during processing"`
Trace bool `help:"Show trace information during processing"`
MFT MFTGroup `name:"mft" cmd:"" help:"Processing with $MFT"`
J JournalGroup `name:"j" cmd:"" help:"Processing with $J (USN Journal)"`
Boot BootGroup `name:"boot" cmd:"" help:"Processing with $Boot"`
SDS SDSGroup `name:"sds" cmd:"" help:"Processing with $SDS"`
I30 I30Group `name:"i30" cmd:"" help:"Processing with $I30"`
LogFile LogFileGroup `name:"logfile" cmd:"" help:"Processing with $LogFile"`
}
// Операции с $MFT
type MFTGroup struct {
Parse MFTParseCmd `name:"parse" cmd:"" help:"Parse $MFT and write CSV, JSON, or bodyfile output"` // Парсинг $MFT записей
Show MFTShowCmd `name:"show" cmd:"" help:"Show full details for a specific $MFT entry or entry-sequence"` // Вывод информации о сущностях или последовательностях сущностей
ExportRecord MFTExportRecordCmd `name:"export-record" cmd:"" help:"Export one raw $MFT FILE record by offset"` // Извлечение конкретной $MFT записи
}
// Операции с $J (USN Journal)
type JournalGroup struct {
Parse JournalParseCmd `name:"parse" cmd:"" help:"Parse $J and write CSV or JSON output"` // Парсинг $J записей
}
// Операции с $Boot
type BootGroup struct {
Parse BootParseCmd `name:"parse" cmd:"" help:"Parse $Boot. CSV output is optional, matching MFTECmd behavior"` // Парсинг $Boot записей
}
// Операции с $SDS
type SDSGroup struct {
Parse SDSParseCmd `name:"parse" cmd:"" help:"Parse $SDS and write CSV output"` // Парсинг $SDS записей
Show SDSShowCmd `name:"show" cmd:"" help:"Show full details for a specific Security ID from $SDS"` // Вывод информации по конкретному идентификатору из $SDS
}
// Операции с $I30
type I30Group struct {
Parse I30ParseCmd `name:"parse" cmd:"" help:"Parse $I30 and write CSV output"` // Парсинг $I30 записей
}
// Операции с $LogFile
type LogFileGroup struct {
Parse LogFileParseCmd `name:"parse" cmd:"" help:"Recognize $LogFile input, but report that parsing is not supported yet"` // Парсинг $LogFile записей
}
// Переиспользуемые блоки флагов.
// Сохранение резульатов в CSV
type CSVOutput struct {
CSVPath string `name:"csv" short:"c" help:"Path to save CSV formatted results to" type:"path"` // Путь сохранения файла
}
// Проверка пути на пустое значение
func (o CSVOutput) Enabled() bool {
return strings.TrimSpace(o.CSVPath) != ""
}
// Сохранение резульатов в JSON
type JSONOutput struct {
JSONPath string `name:"json" short:"j" help:"Path to save CSV formatted results to" type:"path"` // Путь сохранения файла
}
// Проверка пути на пустое значение
func (o JSONOutput) Enabled() bool {
return strings.TrimSpace(o.JSONPath) != ""
}
// Сохранение резульатов в Bodyfile
type BodyOutput struct {
BodyPath string `name:"body" short:"b" help:"Path to save bodyfile formatted results to" type:"path"` // Путь сохранения файла
DriveLetter string `name:"drive-letter" short:"l" help:"Drive letter (C, D, etc.) to use with bodyfile. Only the drive letter itself should be provided"` //Буква диска
UseLF bool `name:"line-feed" default:"false" help:"When true, use LF vs CRLF for newlines. Default is FALSE"` // Окончание строки. false - CRLF, true - LF
}
// Проверка пути на пустое значение
func (o BodyOutput) Enabled() bool {
return strings.TrimSpace(o.BodyPath) != ""
}
// Флаги для работы с VSS
type VSSOptions struct {
VSS bool `name:"vss" default:"false" help:"Process all Volume Shadow Copies that exist on drive. Default is FALSE"` // Включает вывод VSC для диска
Dedupe bool `name:"dedupe" default:"false" help:"Deduplicate VSCs based on SHA-1. First file found wins. Default is FALSE"` // Включает удаление дубликатов VSS
}
// Флаги для работы с временными метками
type TimeFormatOption struct {
TimeFormat string `name:"time-format" short:"t" default:"yyyy-MM-dd HH:mm:ss.fffffff" help:"The custom date/time format to use when displaying time stamps. Default is: yyyy-MM-dd HH:mm:ss.fffffff"` // Задаёт формат временных меток
}
// Флаши для работы с резидентными файлами
type ResidentDataOptions struct {
DumpResidentFiles bool `name:"dump-resident-files" default:"false" help:"Dump resident files from $MFT into a Resident subdirectory under --csv or --json"` // Включает сбор резидентных файлов
IncludeResidentData bool `name:"include-resident-data" default:"false" help:"Include resident data directly in CSV or JSON output"` // Включает вывод резидентных файлов в файл вывода
ResidentExt string `name:"resident-ext" help:"Comma-separated extensions to include for resident data, for example .txt,.ps1,.bat. Empty means all extensions"` // Расширения резидентных файлов
ResidentMaxBytes int `name:"resident-max-bytes" default:"1024" help:"Maximum resident data size to include in bytes. Max 1024000"` // Максимальный размер резидентных файлов
}
// Флаги настройки отображения $MFT
type MFTDisplayOptions struct {
ShortNames bool `name:"short-names" help:"Include DOS 8.3 short names in $MFT output"` // Сокращённые имена файлов DOS
FileList bool `name:"file-list" help:"Generate condensed file listing output. Requires --csv"` // Сжатый листинг файлов
AllFNTimes bool `name:"all-fn-times" help:"Include all timestamps from the 0x30 FILE_NAME attribute, not only those that differ from 0x10"` // Включает все временные метки для 0x30 атрибутов
RecoverSlack bool `name:"recover-slack" help:"Recover slack space from FILE records when processing $MFT"` // Восстанавливает slack space из FILE
}
// Флаги для парсинга с $MFT
type MFTParseCmd struct {
Input string `arg name:"path" help:"Path to the $MFT file." type:"path"` // Путь к $MFT
CSVOutput
JSONOutput
BodyOutput
VSSOptions
TimeFormatOption
MFTDisplayOptions
ResidentDataOptions
}
// Валидация флагов
func (c *MFTParseCmd) Validate() error {
if !c.CSVOutput.Enabled() && !c.JSONOutput.Enabled() && !c.BodyOutput.Enabled() {
return fmt.Errorf("mft parse requires at least one output: --csv, --json, or --body") // Проверка на наличие флага формата файла вывода
}
if c.BodyOutput.Enabled() && strings.TrimSpace(c.DriveLetter) == "" {
return fmt.Errorf("--drive-letter is required when using --body") // Проверка наличия буквы диска в Bodyfile
}
if c.FileList && !c.CSVOutput.Enabled() {
return fmt.Errorf("--file-list requires --csv") // Проверка CSV вывода для листинга файлов
}
if (c.DumpResidentFiles || c.IncludeResidentData) && !c.CSVOutput.Enabled() && !c.JSONOutput.Enabled() {
return fmt.Errorf("--dump-resident-files and --include-resident-data require --csv or --json") // Проверка CSV или JSON вывода для резидентных файлов
}
if c.ResidentMaxBytes <= 0 || c.ResidentMaxBytes > MaxResidentDataBytes {
return fmt.Errorf("--resident-max-bytes must be between 1 and %d", MaxResidentDataBytes) // Проверка максимального значения размера резидентных файлов
}
return nil
}
// Флаги для просмотра информации из $MFT
type MFTShowCmd struct {
Input string `arg name:"path" help:"Path to the $MFT file" type:"path"` // Путь к $MFT
Entry string `arg name:"entry" help:"Entry or entry-sequence. Examples: 5, 624-5, 0x270-0x5"` // Идентификатор сущности
ListDir bool `name:"list-dir" help:"If the selected entry is a directory, list its contents"` // Листинг директори
TimeFormatOption
}
// Валидация флагов
func (c *MFTShowCmd) Validate() error {
return nil
}
// Флаги для извлечения записей из $MFT
type MFTExportRecordCmd struct {
Input string `arg name:"path" help:"Path to the $MFT file" type:"path"` // Путь к $MFT
Offset string `name:"offset" help:"FILE record offset in decimal or hex, for example 5120 or 0x1400" required` // Оффсет
OutDir string `name:"out" short:"o" help:"Directory to write the exported FILE record into" type:"path" required` // Директория для экспорта
}
// Валидация флагов
func (c *MFTExportRecordCmd) Validate() error {
return nil
}
// Флаги для парсинга $J
type JournalParseCmd struct {
Input string `arg:"" name:"path" help:"Path to the $J file." type:"path"` // Путь к $J
CSVOutput
JSONOutput
VSSOptions
TimeFormatOption
MFTPath string `name:"mft" short:"m" help:"Path to $MFT used to resolve parent paths in $J output." type:"path"` // Путь к $MFT
}
// Валидация флагов
func (c *JournalParseCmd) Validate() error {
if !c.CSVOutput.Enabled() && !c.JSONOutput.Enabled() {
return fmt.Errorf("j parse requires at least one output: --csv or --json") // Проверка вывода
}
return nil
}
// Флаги для парсинга $Boot
type BootParseCmd struct {
Input string `arg:"" name:"path" help:"Path to the $Boot file." type:"path"` // Путь к $Boot
CSVOutput
VSSOptions
}
// Валидация флагов
func (c *BootParseCmd) Validate() error {
return nil
}
// Флаги для парсинга $SDS
type SDSParseCmd struct {
Input string `arg:"" name:"path" help:"Path to the $SDS file." type:"path"` // Путь к $SDS
CSVOutput
VSSOptions
}
// Валидация флагов
func (c *SDSParseCmd) Validate() error {
if !c.CSVOutput.Enabled() {
return fmt.Errorf("sds parse requires --csv") // Проверка вывода в CSV
}
return nil
}
// Флаги для просмотра идентификаторов $SDS
type SDSShowCmd struct {
Input string `arg:"" name:"path" help:"Path to the $SDS file." type:"path"` // Путь к $SDS
SecurityID string `arg:"" name:"security-id" help:"Security ID in decimal or hex, for example 624 or 0x270."` // Идентификатор
}
// Валидация флагов
func (c *SDSShowCmd) Validate() error {
return nil
}
// Флаги для парсинга $I30
type I30ParseCmd struct {
Input string `arg:"" name:"path" help:"Path to the $I30 file." type:"path"` // Путь к $I30
CSVOutput
TimeFormatOption
}
// Валидация флагов
func (c *I30ParseCmd) Validate() error {
if !c.CSVOutput.Enabled() {
return fmt.Errorf("i30 parse requires --csv") // Проверка вывода в CSV
}
return nil
}
// Флаги для парсинга $LogFile
type LogFileParseCmd struct {
Input string `arg:"" name:"path" help:"Path to the $LogFile file." type:"path"` // Путь к $LogFile
}
// Валидация флагов
func (c *LogFileParseCmd) Validate() error {
return nil
}
// Валидация комманд
func ValidateLeaf(cmd any) error {
switch v := cmd.(type) {
case interface{ Validate() error }:
return v.Validate()
default:
return nil
}
}