github.com/mvdan/u-root-coreutils@v0.0.0-20230122170626-c2eef2898555/pkg/ldd/ldd_darwin.go (about) 1 // Copyright 2021 the u-root Authors. All rights reserved 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 //go:build darwin 6 // +build darwin 7 8 // ldd returns none of the library dependencies of an executable. 9 // 10 // On many Unix kernels, the kernel ABI is stable. On OSX, the stability 11 // is held in the library interface; the kernel ABI is explicitly not 12 // stable. The ldd package on OSX will only return the files passed to it. 13 // It will continue to resolve symbolic links. 14 package ldd 15 16 import ( 17 "fmt" 18 "os" 19 "path/filepath" 20 ) 21 22 // Follow starts at a pathname and adds it 23 // to a map if it is not there. 24 // If the pathname is a symlink, indicated by the Readlink 25 // succeeding, links repeats and continues 26 // for as long as the name is not found in the map. 27 func follow(l string, names map[string]*FileInfo) error { 28 for { 29 if names[l] != nil { 30 return nil 31 } 32 i, err := os.Lstat(l) 33 if err != nil { 34 return fmt.Errorf("%v", err) 35 } 36 37 names[l] = &FileInfo{FullName: l, FileInfo: i} 38 if i.Mode().IsRegular() { 39 return nil 40 } 41 // If it's a symlink, the read works; if not, it fails. 42 // we can skip testing the type, since we still have to 43 // handle any error if it's a link. 44 next, err := os.Readlink(l) 45 if err != nil { 46 return err 47 } 48 // It may be a relative link, so we need to 49 // make it abs. 50 if filepath.IsAbs(next) { 51 l = next 52 continue 53 } 54 l = filepath.Join(filepath.Dir(l), next) 55 } 56 } 57 58 // Ldd returns the list of files passed to it, and resolves all symbolic 59 // links, returning them as well. 60 // 61 // It's not an error for a file to not be an ELF. 62 func Ldd(names []string) ([]*FileInfo, error) { 63 var ( 64 list = make(map[string]*FileInfo) 65 libs []*FileInfo 66 ) 67 for _, n := range names { 68 if err := follow(n, list); err != nil { 69 return nil, err 70 } 71 } 72 for i := range list { 73 libs = append(libs, list[i]) 74 } 75 76 return libs, nil 77 } 78 79 type FileInfo struct { 80 FullName string 81 os.FileInfo 82 } 83 84 // List returns the dependency file paths of files in names. 85 func List(names []string) ([]string, error) { 86 var list []string 87 l, err := Ldd(names) 88 if err != nil { 89 return nil, err 90 } 91 for i := range l { 92 list = append(list, l[i].FullName) 93 } 94 return list, nil 95 }