Add Unraid diagnostics parser and fix zip upload support

Implements comprehensive parser for Unraid diagnostics archives with support for:
- System information (OS version, BIOS, motherboard)
- CPU details from lscpu (model, cores, threads, frequency)
- Memory information
- Storage devices with SMART data integration
- Temperature sensors from disk array
- System event logs

Parser intelligently merges data from multiple sources:
- SMART files provide detailed disk information (model, S/N, firmware)
- vars.txt provides disk configuration and filesystem types
- Deduplication ensures clean results

Also fixes critical bug where zip archives could not be uploaded via web interface
due to missing extractZipFromReader implementation.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-05 23:54:55 +03:00
parent 7d9135dc63
commit aa22034944
4 changed files with 919 additions and 0 deletions

View File

@@ -47,6 +47,8 @@ func ExtractArchiveFromReader(r io.Reader, filename string) ([]ExtractedFile, er
return extractTarGzFromReader(r, filename)
case ".tar":
return extractTarFromReader(r)
case ".zip":
return extractZipFromReader(r)
case ".txt", ".log":
return extractSingleFileFromReader(r, filename)
default:
@@ -219,6 +221,54 @@ func extractZip(archivePath string) ([]ExtractedFile, error) {
return files, nil
}
func extractZipFromReader(r io.Reader) ([]ExtractedFile, error) {
// Read all data into memory
data, err := io.ReadAll(r)
if err != nil {
return nil, fmt.Errorf("read zip data: %w", err)
}
// Create a ReaderAt from the byte slice
readerAt := bytes.NewReader(data)
// Open the zip archive
zipReader, err := zip.NewReader(readerAt, int64(len(data)))
if err != nil {
return nil, fmt.Errorf("open zip: %w", err)
}
var files []ExtractedFile
for _, f := range zipReader.File {
if f.FileInfo().IsDir() {
continue
}
// Skip large files (>10MB)
if f.FileInfo().Size() > 10*1024*1024 {
continue
}
rc, err := f.Open()
if err != nil {
return nil, fmt.Errorf("open file %s: %w", f.Name, err)
}
content, err := io.ReadAll(rc)
rc.Close()
if err != nil {
return nil, fmt.Errorf("read file %s: %w", f.Name, err)
}
files = append(files, ExtractedFile{
Path: f.Name,
Content: content,
})
}
return files, nil
}
func extractSingleFile(path string) ([]ExtractedFile, error) {
f, err := os.Open(path)
if err != nil {