4.3 KiB
4.3 KiB
Replace genisoimage with go-diskfs (pure Go ISO creation)
Why
genisoimage is the only remaining external binary dependency after the dcmtk migration.
Replacing it with github.com/diskfs/go-diskfs (pure Go, MIT, 644⭐, v1.9.3) makes the
mkiso-server binary fully self-contained — zero external binaries beyond dcmtk storescp/movescu/storescu.
What
Replace pkg/dicom/command.go's RunGenISOImage() (which shells out to genisoimage)
with pure Go ISO creation using go-diskfs. This affects:
| Current | New |
|---|---|
service/iso.go calls dicom.RunGenISOImage() |
Calls isobuilder.BuildFromDirectory() |
pkg/dicom/command.go has RunGenISOImage() |
Remove it |
config.go has Tools.Genisoimage + validation |
Remove field + validation |
config.example.yaml has tools.genisoimage |
Remove |
handler/health.go checks genisoimage binary |
Remove check |
go-diskfs API reference
import (
diskfs "github.com/diskfs/go-diskfs"
"github.com/diskfs/go-diskfs/disk"
"github.com/diskfs/go-diskfs/filesystem"
"github.com/diskfs/go-diskfs/filesystem/iso9660"
)
type FinalizeOptions struct {
RockRidge bool // Rock Ridge extensions (long names, perms)
Joliet bool // Joliet (UCS-2 names for Windows)
DeepDirectories bool // Allow dirs deeper than 8 levels
ElTorito *ElTorito
VolumeIdentifier string // Volume label, default "ISOIMAGE"
PublisherIdentifier string
}
ISO creation pattern (from go-diskfs examples/create-iso-from-folder/)
// 1. Calculate total size of directory
folderSize := dirSize(srcDir)
// 2. Create disk image file
mydisk, err := diskfs.Create(isoPath, folderSize, 2048)
mydisk.LogicalBlocksize = 2048
// 3. Create ISO9660 filesystem
fs, err := mydisk.CreateFilesystem(disk.FilesystemSpec{
Partition: 0,
FSType: filesystem.TypeISO9660,
VolumeLabel: "DICOM",
})
// 4. Walk source dir, copy files
filepath.Walk(srcDir, func(path string, info os.FileInfo, err error) error {
relPath, _ := filepath.Rel(srcDir, path)
if info.IsDir() {
fs.Mkdir(relPath)
} else {
rw, _ := fs.OpenFile(relPath, os.O_CREATE|os.O_RDWR)
io.Copy(rw, file)
rw.Close()
}
})
// 5. Finalize with Rock Ridge + Joliet
iso := fs.(*iso9660.FileSystem)
iso.Finalize(iso9660.FinalizeOptions{
RockRidge: true,
Joliet: true,
DeepDirectories: true,
VolumeIdentifier: "DICOM",
})
fs.Close()
Equivalent genisoimage flags to go-diskfs options
| genisoimage flag | go-diskfs FinalizeOptions |
|---|---|
-iso-level 4 |
DeepDirectories: true |
-r (Rock Ridge) |
RockRidge: true |
-V DICOM |
VolumeIdentifier: "DICOM" |
-allow-multidot |
Implicit via Rock Ridge |
-allow-lowercase |
Implicit via Rock Ridge |
-allow-leading-dots |
Implicit via Rock Ridge |
-J (Joliet) |
Joliet: true |
Implementation order
- 1. Add go-diskfs dependency —
go get github.com/diskfs/go-diskfs@v1.9.3 - 2. Create
internal/isobuilder/builder.go—BuildFromDirectory(srcDir, isoPath, volumeLabel string) errordirSize()helper (walk dir, sum file sizes + 10% overhead margin)- Walk again to create dirs + copy files
- Finalize with RockRidge + Joliet + DeepDirectories + VolumeIdentifier
- 3. Update
internal/config/config.go- Remove
ToolsConfig.Genisoimagefield - Remove validation
c.Tools.Genisoimage == "" - Remove
Toolsfrom Config struct entirely if empty (keep struct, remove field)
- Remove
- 4. Update
config.example.yaml— removetools.genisoimagesection - 5. Update
internal/service/iso.go- Replace both
dicom.RunGenISOImage(...)calls withisobuilder.BuildFromDirectory(tempDir, isoPath, "DICOM") - Remove unused
dicomimport alias (if no longer needed in scope — it's still used forcountFileselsewhere)
- Replace both
- 6. Update
internal/handler/health.go- Remove genisoimage from the dependency check array
- 7. Remove
RunGenISOImagefrompkg/dicom/command.go- Delete the entire function
- 8. Build and test
go build ./...must passgo vet ./...must pass- Start server, verify
/api/healthno longer shows genisoimage - Verify ISO endpoint still returns proper errors (PACS unreachable)