diskfs / go-diskfs

MIT License
518 stars 117 forks source link

Create ISO from existing image files with Rock Ridge enabled still errors on filenames longer than 30 characters #189

Closed j-deng closed 11 months ago

j-deng commented 12 months ago
  1. Create ISO from existing image files with error: file name must be at most 30 characters
  2. All files' name are transftered to Uppercase

The print is panic: unable to calculate size of directory for spforbmc\spschema: could not calculate child * entry size : could not convert dirEntry to bytes: invalid filename ****: file name must be at most 30 characters, not including the separator '.'

deitch commented 12 months ago

Can you give a more specific case to reproduce?

j-deng commented 12 months ago

OK, thank you! @deitch

The error code of at most 30 characters is here: image

And the code to make iso is from example, the output iso filename is in Uppercase, and the origin name is in lower:

create-iso-from-folder

bootable_iso.go

image

deitch commented 12 months ago

I continue to be confused. I don't know what you actually are trying to do. You linked to 2 separate examples. Are you running on of them? Which one, and how? Ans are you seeing an error, or asking about the 30-character limit here?

j-deng commented 12 months ago

@deitch i was seeing the error, and the code is combine the two example, the original files is unzip from a x86 linux OS:

package main

import (
    "fmt"
    "io"
    "log"
    "os"
    "path/filepath"

    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"
)

func check(err error) {
    if err != nil {
        log.Panic(err)
    }
}

func FolderSize(path string) (int64, error) {
    var size int64
    err := filepath.Walk(path, func(_ string, info os.FileInfo, err error) error {
        if err != nil {
            return err
        }
        if !info.IsDir() {
            size += info.Size()
        }
        return err
    })
    return size, err
}

func CreateIsoFromFolder(srcFolder string, outputFileName string) {
    // We need to know the size of the folder before we can create a disk image
    // TODO: Are we able to create a disk image with a dynamic size?
    folderSize, err := FolderSize(srcFolder)
    check(err)

    // TODO: Explain why we need to set the logical block size and which values should be used
    var LogicalBlocksize diskfs.SectorSize = 2048
    // var LogicalBlocksize diskfs.SectorSize = 4096

    // Create the disk image
    // TODO: Explain why we need to use Raw here
    mydisk, err := diskfs.Create(outputFileName, folderSize, diskfs.Raw, LogicalBlocksize)
    check(err)

    // Create the ISO filesystem on the disk image
    fspec := disk.FilesystemSpec{
        Partition:   0,
        FSType:      filesystem.TypeISO9660,
        VolumeLabel: "label",
    }
    fs, err := mydisk.CreateFilesystem(fspec)
    check(err)

    // Walk the source folder to copy all files and folders to the ISO filesystem
    err = filepath.Walk(srcFolder, func(path string, info os.FileInfo, err error) error {
        check(err)

        relPath, err := filepath.Rel(srcFolder, path)
        check(err)

        // If the current path is a folder, create the folder in the ISO filesystem
        if info.IsDir() {
            // Create the directory in the ISO file
            err = fs.Mkdir(relPath)
            check(err)
            return nil
        }

        // If the current path is a file, copy the file to the ISO filesystem
        if !info.IsDir() {
            // Open the file in the ISO file for writing
            rw, err := fs.OpenFile(relPath, os.O_CREATE|os.O_RDWR)
            check(err)

            // Open the source file for reading
            in, errorOpeningFile := os.Open(path)
            if errorOpeningFile != nil {
                return errorOpeningFile
            }
            defer in.Close()

            // Copy the contents of the source file to the ISO file
            _, err = io.Copy(rw, in)
            check(err)
        }

        return nil
    })
    check(err)

    iso, ok := fs.(*iso9660.FileSystem)
    if !ok {
        check(fmt.Errorf("not an iso9660 filesystem"))
    }

    options := iso9660.FinalizeOptions{
        VolumeIdentifier: "my-volume",
        RockRidge: true,
        DeepDirectories: true,
        ElTorito: &iso9660.ElTorito{
            BootCatalog: "isolinux/boot.cat",
            Entries: []*iso9660.ElToritoEntry{
                {
                    Platform:  iso9660.BIOS,
                    Emulation: iso9660.NoEmulation,
                    BootFile:  "isolinux/isolinux.bin",
                    BootTable: true,
                    LoadSize:  4,
                },
                {
                    Platform:  iso9660.EFI,
                    Emulation: iso9660.NoEmulation,
                    BootFile:  "images/efiboot.img",
                },
            },
        },
    }

    err = iso.Finalize(options)
    check(err)
}

func main() {
    CreateIsoFromFolder("./dist", "./iso/test.iso")
}

--- updated 12.02 --- LogicalBlocksize diskfs.SectorSize = 2048

deitch commented 12 months ago

That is quite helpful, thanks.

What is in dist/? I see the screen capture, but what are the sources?

j-deng commented 12 months ago

The files in dist

dist   
├── EFI
│   ├── BOOT
│   │   ├── BOOTX64.EFI
│   │   ├── fonts
│   │   │   └── unicode.pf2
│   │   ├── grub.cfg
│   │   ├── grub.cfg.usb
│   │   ├── grubx64.efi
│   │   └── mmx64.efi
├── LiveOS
│   └── squashfs.img
├── Project
│   ├── app
│   │   ├── at-spi2-atk-2.34.2-1.eulerosv2r10.x86_64.rpm
│   │   ├── at-spi2-core-2.36.0-1.h1.eulerosv2r10.x86_64.rpm  # file length > 30
...
├── images
│   ├── efiboot.img
│   └── pxeboot
│       ├── initrd.img
│       └── vmlinuz
├── isolinux
│   ├── boot.cat
│   ├── boot.msg
│   ├── grub.conf
│   ├── initrd.img
│   ├── isolinux.bin
│   ├── isolinux.cfg
│   ├── ldlinux.c32
│   ├── libcom32.c32
│   ├── libutil.c32
│   ├── syslinux.cfg
│   ├── vesamenu.c32
│   └── vmlinuz

If ignore the error of 30 length, the output iso file names are on Uppercase

image

deitch commented 11 months ago

Are you saying the content doesn't matter, just having a file - any file - with a filename > 30 chars?

j-deng commented 11 months ago

Are you saying the content doesn't matter, just having a file - any file - with a filename > 30 chars?

Yes, I need to remove all the files length > 30 to make iso.

deitch commented 11 months ago

That isn't too surprising; iso9660 only supports filenames up to 30 characters (in levels 2 and 3; level 1 was only old DOS-style 8.3). Rock Ridge adds support for more POSIX-style filenames, up to 255 chars.

deitch commented 11 months ago

The issue is that you have RockRidge: true enabled, and it still errors on it. Now it is clear. I changed the issue title.

j-deng commented 11 months ago

@deitch 👍