diskfs / go-diskfs

MIT License
494 stars 112 forks source link

Missing "FILE SERIAL NUMBER" when creating rockridge iso9660 files? #223

Closed cmsj closed 2 months ago

cmsj commented 3 months ago

I'm currently trying to debug some code that uses libarchive to read iso9660 files, that is failing when reading an ISO created with go-diskfs.

The specific issue is that libarchive determines every file in the iso to be a hardlink, seemingly because the FILE SERIAL NUMBER portion of the rockridge PX header is unset.

Looking through the go-diskfs code (and I apologise in advance, I am not super familiar with Go), it looks to me like the relevant place where they would be added starts at toDirectoryEntry() in finalize.go. That function calls e.GetFileExtensions() which creates a rockRidgePosixAttributes struct for the mode/linkCount/uid/gid, but doesn't pass a value for the serial field, which I believe means that value will be written as zero.

This seems to be what confuses libarchive, because it then sees multiple files with the same serial (ie inode) and interprets that to mean they are hardlinks.

deitch commented 3 months ago

Rock Ridge 1.12 (1994) includes the longer PX field at 44 bytes. Available here., see pages 7-9, specifically page 9 for "serial".

"BP 37 to BP 44 - POSIX File Serial Number" shall have the same meaning as and may be used for the st_ino field of POSIX:5.6.1. This field shall be recorded according to ISO 9660:7.3.3. Directory Records which share the value of this field are defined as links (see POSIX:2.2.2.17) and, by definition, point to the same file or directory.

OK, so it is the same as st_ino, where stat.h includes:

dev_t     st_dev     Device ID of device containing file. 
ino_t     st_ino     File serial number. 

That basically means that when finalizing, each should have a unique number.

I see no reason we cannot add it.

deitch commented 3 months ago

@cmsj look at the branch in #224 , see if it works for you.