Use chunked ISO search instead of reading entire 1.2GB file into memory
os.ReadFile on the ISO was OOM-killing the container. Switch to 8MB chunked reads with overlap to handle matches spanning chunk boundaries. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+44
-12
@@ -170,13 +170,16 @@ func rewriteGrubConfig(original, answerURL string) string {
|
|||||||
return strings.Join(collapsed, "\n")
|
return strings.Join(collapsed, "\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
// findAllOccurrences searches the entire ISO file for all locations where
|
|
||||||
// the grub.cfg content appears — this catches both the ISO9660 filesystem
|
|
||||||
// copy and any copy inside an embedded EFI boot partition image.
|
|
||||||
func findAllOccurrences(isoPath string, content []byte) ([]int64, error) {
|
func findAllOccurrences(isoPath string, content []byte) ([]int64, error) {
|
||||||
data, err := os.ReadFile(isoPath)
|
f, err := os.Open(isoPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("read ISO: %w", err)
|
return nil, fmt.Errorf("open ISO: %w", err)
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
stat, err := f.Stat()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
needle := content
|
needle := content
|
||||||
@@ -184,20 +187,49 @@ func findAllOccurrences(isoPath string, content []byte) ([]int64, error) {
|
|||||||
needle = needle[:256]
|
needle = needle[:256]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const chunkSize = 8 * 1024 * 1024
|
||||||
|
overlap := len(needle) - 1
|
||||||
|
buf := make([]byte, chunkSize+overlap)
|
||||||
|
|
||||||
var offsets []int64
|
var offsets []int64
|
||||||
start := 0
|
filePos := int64(0)
|
||||||
for {
|
|
||||||
idx := bytes.Index(data[start:], needle)
|
for filePos < stat.Size() {
|
||||||
if idx == -1 {
|
readStart := filePos
|
||||||
|
if filePos > 0 {
|
||||||
|
readStart -= int64(overlap)
|
||||||
|
}
|
||||||
|
|
||||||
|
n, err := f.ReadAt(buf, readStart)
|
||||||
|
if n == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
searchFrom := 0
|
||||||
|
if filePos > 0 {
|
||||||
|
searchFrom = overlap
|
||||||
|
}
|
||||||
|
|
||||||
|
chunk := buf[:n]
|
||||||
|
pos := searchFrom
|
||||||
|
for {
|
||||||
|
idx := bytes.Index(chunk[pos:], needle)
|
||||||
|
if idx == -1 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
offsets = append(offsets, readStart+int64(pos)+int64(idx))
|
||||||
|
pos += idx + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
filePos += chunkSize
|
||||||
|
if err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
offsets = append(offsets, int64(start+idx))
|
|
||||||
start += idx + 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(offsets) == 0 {
|
if len(offsets) == 0 {
|
||||||
return nil, fmt.Errorf("grub.cfg content not found in ISO raw data (searched %d bytes with %d-byte needle)",
|
return nil, fmt.Errorf("grub.cfg content not found in ISO raw data (searched %d bytes with %d-byte needle)",
|
||||||
len(data), len(needle))
|
stat.Size(), len(needle))
|
||||||
}
|
}
|
||||||
|
|
||||||
return offsets, nil
|
return offsets, nil
|
||||||
|
|||||||
Reference in New Issue
Block a user