diff --git a/cmd/go-unsquashfs/main.go b/cmd/go-unsquashfs/main.go index fe4ce13..1b6a530 100644 --- a/cmd/go-unsquashfs/main.go +++ b/cmd/go-unsquashfs/main.go @@ -5,19 +5,43 @@ import ( "fmt" "io/fs" "os" + "os/user" "path/filepath" + "strconv" "strings" "time" "github.com/CalebQ42/squashfs" ) -func printEntry(root, path string, d fs.DirEntry) { +func userName(uid int, numeric bool) string { + us := strconv.Itoa(uid) + if numeric { + return us + } + if u, err := user.LookupId(us); err == nil { + return u.Username + } + return us +} + +func groupName(gid int, numeric bool) string { + gs := strconv.Itoa(gid) + if numeric { + return gs + } + if g, err := user.LookupGroupId(gs); err == nil { + return g.Name + } + return gs +} + +func printEntry(root, path string, d fs.DirEntry, numeric bool) { fi, _ := d.Info() sfi := fi.(squashfs.FileInfo) - owner := fmt.Sprintf("%d/%d", - sfi.Uid(), - sfi.Gid()) + owner := fmt.Sprintf("%s/%s", + userName(sfi.Uid(), numeric), + groupName(sfi.Gid(), numeric)) link := "" if sfi.IsSymlink() { link = " -> " + sfi.SymlinkPath() @@ -33,6 +57,7 @@ func main() { verbose := flag.Bool("v", false, "Verbose") list := flag.Bool("l", false, "List") long := flag.Bool("ll", false, "List with attributes") + numeric := flag.Bool("lln", false, "List with attributes and numeric ids") ignore := flag.Bool("ip", false, "Ignore Permissions and extract all files/folders with 0755") flag.Parse() if len(flag.Args()) < 2 { @@ -47,14 +72,14 @@ func main() { if err != nil { panic(err) } - if *list || *long { + if *list || *long || *numeric { root := flag.Arg(1) fs.WalkDir(r, ".", func(path string, d fs.DirEntry, err error) error { if err != nil { panic(err) } - if *long { - printEntry(root, path, d) + if *long || *numeric { + printEntry(root, path, d, *numeric) } else { fmt.Println(filepath.Join(root, path)) } diff --git a/file.go b/file.go index 1024fa1..c3ebf6f 100644 --- a/file.go +++ b/file.go @@ -142,7 +142,15 @@ func (f *File) ReadDir(n int) ([]fs.DirEntry, error) { // Returns the file's fs.FileInfo func (f *File) Stat() (fs.FileInfo, error) { - return newFileInfo(f.b.Name, &f.b.Inode), nil + uid, err := f.b.Uid(&f.r.Low) + if err != nil { + return nil, err + } + gid, err := f.b.Gid(&f.r.Low) + if err != nil { + return nil, err + } + return newFileInfo(f.b.Name, uid, gid, &f.b.Inode), nil } // SymlinkPath returns the symlink's target path. Is the File isn't a symlink, returns an empty string. diff --git a/file_info.go b/file_info.go index 6c00017..20ddfc7 100644 --- a/file_info.go +++ b/file_info.go @@ -10,6 +10,8 @@ import ( type FileInfo struct { name string + uid uint32 + gid uint32 size int64 target string perm uint32 @@ -18,14 +20,22 @@ type FileInfo struct { } func (r Reader) newFileInfo(e directory.Entry) (FileInfo, error) { - i, err := r.Low.InodeFromEntry(e) + b, err := r.Low.BaseFromEntry(e) if err != nil { return FileInfo{}, err } - return newFileInfo(e.Name, &i), nil + uid, err := b.Uid(&r.Low) + if err != nil { + return FileInfo{}, err + } + gid, err := b.Gid(&r.Low) + if err != nil { + return FileInfo{}, err + } + return newFileInfo(e.Name, uid, gid, &b.Inode), nil } -func newFileInfo(name string, i *inode.Inode) FileInfo { +func newFileInfo(name string, uid, gid uint32, i *inode.Inode) FileInfo { var size int64 var target string switch i.Type { @@ -40,6 +50,8 @@ func newFileInfo(name string, i *inode.Inode) FileInfo { } return FileInfo{ name: name, + uid: uid, + gid: gid, size: size, target: target, perm: uint32(i.Perm), @@ -52,6 +64,14 @@ func (f FileInfo) Name() string { return f.name } +func (f FileInfo) Uid() int { + return int(f.uid) +} + +func (f FileInfo) Gid() int { + return int(f.gid) +} + func (f FileInfo) Size() int64 { return f.size }