Skip to content

Commit 2722aa3

Browse files
committed
Fix file mode bit handling
fs.FileMode specifies a number of bits that do not match the file mode bits defined in the inode, so constructing a valid fs.FileMode requires translating bits 9-16 into the equivalent flags defined in fs package vs just casting the filemode bits from the inode. In addition, the IsDir method in inode was incorrect - a block device has the value 0x6000, which means IsDir will return true for block device nodes.
1 parent 1b22259 commit 2722aa3

File tree

3 files changed

+43
-12
lines changed

3 files changed

+43
-12
lines changed

xfs/inode.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -834,19 +834,19 @@ func parseEntry(r io.Reader, i8count bool) (*Dir2SfEntry, error) {
834834
}
835835

836836
func (ic InodeCore) IsDir() bool {
837-
return ic.Mode&0x4000 != 0 && ic.Mode&0x8000 == 0
837+
return ic.Mode&0xF000 == 0x4000
838838
}
839839

840840
func (ic InodeCore) IsRegular() bool {
841-
return ic.Mode&0x8000 != 0 && ic.Mode&0x4000 == 0
841+
return ic.Mode&0xF000 == 0x8000
842842
}
843843

844844
func (ic InodeCore) IsSocket() bool {
845-
return ic.Mode&0xC000 != 0
845+
return ic.Mode&0xF000 == 0xC000
846846
}
847847

848848
func (ic InodeCore) IsSymlink() bool {
849-
return ic.Mode&0xA000 != 0
849+
return ic.Mode&0xF000 == 0xA000
850850
}
851851

852852
func (ic InodeCore) isSupported() bool {

xfs/xfs.go

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,6 @@ func (xfs *FileSystem) ReadDirInfo(name string) (fs.FileInfo, error) {
148148
return FileInfo{
149149
name: "/",
150150
inode: inode,
151-
mode: fs.FileMode(inode.inodeCore.Mode),
152151
}, nil
153152
}
154153
name = strings.TrimRight(name, string(filepath.Separator))
@@ -334,7 +333,6 @@ func (xfs *FileSystem) listFileInfo(ino uint64) ([]FileInfo, error) {
334333
FileInfo{
335334
name: entry.Name(),
336335
inode: inode,
337-
mode: fs.FileMode(inode.inodeCore.Mode),
338336
},
339337
)
340338
}
@@ -399,8 +397,6 @@ func (xfs *FileSystem) listEntries(ino uint64) ([]Entry, error) {
399397
type FileInfo struct {
400398
name string
401399
inode *Inode
402-
403-
mode fs.FileMode
404400
}
405401

406402
func (i FileInfo) IsDir() bool {
@@ -424,7 +420,42 @@ func (i FileInfo) Sys() interface{} {
424420
}
425421

426422
func (i FileInfo) Mode() fs.FileMode {
427-
return i.mode
423+
m := i.inode.inodeCore.Mode
424+
// Bottom 9 bits are same in fs.FileMode and XFS inode (unix permission bits)
425+
translatedMode := fs.FileMode(m & 0o777)
426+
427+
// Bits 9-12 in the inode are sticky, setuid, and setgid bits
428+
if m&0o1000 != 0 {
429+
translatedMode |= fs.ModeSticky
430+
}
431+
if m&0o2000 != 0 {
432+
translatedMode |= fs.ModeSetuid
433+
}
434+
if m&0o4000 != 0 {
435+
translatedMode |= fs.ModeSetgid
436+
}
437+
438+
// bits 13-16 are file type bits, defined in stat.h
439+
switch m & 0xF000 {
440+
case 0xC000:
441+
translatedMode |= fs.ModeSocket
442+
case 0xA000:
443+
translatedMode |= fs.ModeSymlink
444+
case 0x8000:
445+
// Regular file, no flags to set
446+
case 0x6000:
447+
translatedMode |= fs.ModeDevice
448+
case 0x4000:
449+
translatedMode |= fs.ModeDir
450+
case 0x2000:
451+
translatedMode |= fs.ModeCharDevice
452+
case 0x1000:
453+
translatedMode |= fs.ModeNamedPipe
454+
default:
455+
translatedMode |= fs.ModeIrregular
456+
}
457+
458+
return translatedMode
428459
}
429460

430461
// dirEntry is implemented io/fs DirEntry interface

xfs/xfs_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,19 +25,19 @@ func TestFileSystemCheckFileExtents(t *testing.T) {
2525
filesystem: "testdata/image.xfs",
2626
name: "fmt_extents_file_1024",
2727
expectedSize: 1024,
28-
mode: 33188,
28+
mode: 0o644,
2929
},
3030
{
3131
filesystem: "testdata/image.xfs",
3232
name: "fmt_extents_file_4096",
3333
expectedSize: 4096,
34-
mode: 33188,
34+
mode: 0o644,
3535
},
3636
{
3737
filesystem: "testdata/image.xfs",
3838
name: "fmt_extents_file_16384",
3939
expectedSize: 16384,
40-
mode: 33188,
40+
mode: 0o644,
4141
},
4242
{
4343
filesystem: "testdata/image.xfs",

0 commit comments

Comments
 (0)