github.com/system-transparency/u-root@v6.0.1-0.20190919065413-ed07a650de4c+incompatible/pkg/uroot/util/symlink.go (about) 1 // Copyright 2014-2017 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 package util 6 7 import ( 8 "log" 9 "os" 10 "path/filepath" 11 ) 12 13 // AbsSymlink returns an absolute path for the link from a file to a target. 14 func AbsSymlink(originalFile, target string) string { 15 if !filepath.IsAbs(originalFile) { 16 var err error 17 originalFile, err = filepath.Abs(originalFile) 18 if err != nil { 19 // This should not happen on Unix systems, or you're 20 // already royally screwed. 21 log.Fatalf("could not determine absolute path for %v: %v", originalFile, err) 22 } 23 } 24 // Relative symlinks are resolved relative to the original file's 25 // parent directory. 26 // 27 // E.g. /bin/defaultsh -> ../bbin/elvish 28 if !filepath.IsAbs(target) { 29 return filepath.Join(filepath.Dir(originalFile), target) 30 } 31 return target 32 } 33 34 // IsTargetSymlink returns true if a target of a symlink is also a symlink. 35 func IsTargetSymlink(originalFile, target string) bool { 36 s, err := os.Lstat(AbsSymlink(originalFile, target)) 37 if err != nil { 38 return false 39 } 40 return (s.Mode() & os.ModeSymlink) == os.ModeSymlink 41 } 42 43 // ResolveUntilLastSymlink resolves until the last symlink. 44 // This is needed when we have a chain of symlinks and want the last 45 // symlink, not the file pointed to (which is why we don't use 46 // filepath.EvalSymlinks) 47 func ResolveUntilLastSymlink(p string) string { 48 for target, err := os.Readlink(p); err == nil && IsTargetSymlink(p, target); target, err = os.Readlink(p) { 49 p = AbsSymlink(p, target) 50 } 51 return p 52 }