Skip to content

Commit 3965e41

Browse files
author
mancausoft
committed
lookup: report VMS file number as inode
DIR/FILE_ID on VMS shows the (num, seq, rvn) tuple, and users identify a file header by the first component (the file number). Make ls -i match that: INDEXF.SYS is inode 1, BITMAP.SYS is 2, 000000.DIR (MFD) is 4, and so on. The previous packing put fid$w_seq into the low bits beyond num, so even small file numbers came out as five- or six-digit inodes that didn't line up with anything a VMS-savvy user would recognise. For a single-volume read-only mount the file number alone is already unique (slot reuse requires a deassign which we can't observe while mounted). rvn is still folded in above bit 24 so volume sets don't alias file 1 across RVNs.
1 parent df0bb15 commit 3965e41

1 file changed

Lines changed: 14 additions & 10 deletions

File tree

src/lookup.c

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -68,17 +68,21 @@ time_t ods2_vmstime_to_time_t( const VMSTIME t ) {
6868
/* ------------------------------------------------------ inode mapping */
6969

7070
ino_t ods2_fid_to_inode( const struct fiddef *fid ) {
71-
/* Pack FID into a 64-bit inode. Layout, low to high:
72-
* 16 bits fid$w_num | 16 bits fid$w_seq | 8 bits fid$b_rvn
73-
* | 8 bits fid$b_nmx | 16 bits reserved
74-
* The FID fields are stored little-endian on disk; we read them
75-
* via F11WORD() so they're in host byte order here.
71+
/* What a VMS user expects to see is the file number (the first
72+
* element of the (num,seq,rvn) tuple printed by DIR/FILE_ID), so
73+
* INDEXF.SYS comes out as inode 1, BITMAP.SYS as 2, the MFD as 4
74+
* and so on. fid$b_nmx extends fid$w_num to 24 bits on volumes
75+
* with more than 65535 file headers.
76+
*
77+
* For a single-volume read-only mount that's already a unique
78+
* inode: the sequence number can only change after the slot is
79+
* freed and reused, which can't happen while we're mounted. RVN
80+
* is folded in for safety on volume sets so file 1 of RVN 1 and
81+
* file 1 of RVN 2 don't collide.
7682
*/
77-
uint64_t v = 0;
78-
v |= (uint64_t)F11WORD(fid->fid$w_num);
79-
v |= (uint64_t)F11WORD(fid->fid$w_seq) << 16;
80-
v |= (uint64_t)fid->fid$b_rvn << 32;
81-
v |= (uint64_t)fid->fid$b_nmx << 40;
83+
uint64_t file_no = ((uint64_t)fid->fid$b_nmx << 16)
84+
| F11WORD(fid->fid$w_num);
85+
uint64_t v = file_no | ((uint64_t)fid->fid$b_rvn << 24);
8286
if( v == 0 )
8387
v = 1; /* 0 is reserved by some POSIX tools */
8488
return (ino_t)v;

0 commit comments

Comments
 (0)