src/pkg/path/filepath/symlink.go - The Go Programming Language

Golang

Source file src/pkg/path/filepath/symlink.go

     1	// Copyright 2012 The Go 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	// +build !windows
     6	
     7	package filepath
     8	
     9	import (
    10		"bytes"
    11		"errors"
    12		"os"
    13		"strings"
    14	)
    15	
    16	func evalSymlinks(path string) (string, error) {
    17		const maxIter = 255
    18		originalPath := path
    19		// consume path by taking each frontmost path element,
    20		// expanding it if it's a symlink, and appending it to b
    21		var b bytes.Buffer
    22		for n := 0; path != ""; n++ {
    23			if n > maxIter {
    24				return "", errors.New("EvalSymlinks: too many links in " + originalPath)
    25			}
    26	
    27			// find next path component, p
    28			i := strings.IndexRune(path, Separator)
    29			var p string
    30			if i == -1 {
    31				p, path = path, ""
    32			} else {
    33				p, path = path[:i], path[i+1:]
    34			}
    35	
    36			if p == "" {
    37				if b.Len() == 0 {
    38					// must be absolute path
    39					b.WriteRune(Separator)
    40				}
    41				continue
    42			}
    43	
    44			fi, err := os.Lstat(b.String() + p)
    45			if err != nil {
    46				return "", err
    47			}
    48			if fi.Mode()&os.ModeSymlink == 0 {
    49				b.WriteString(p)
    50				if path != "" {
    51					b.WriteRune(Separator)
    52				}
    53				continue
    54			}
    55	
    56			// it's a symlink, put it at the front of path
    57			dest, err := os.Readlink(b.String() + p)
    58			if err != nil {
    59				return "", err
    60			}
    61			if IsAbs(dest) {
    62				b.Reset()
    63			}
    64			path = dest + string(Separator) + path
    65		}
    66		return Clean(b.String()), nil
    67	}