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  }