github.com/YousefHaggyHeroku/pack@v1.5.5/internal/paths/paths.go (about)

     1  package paths
     2  
     3  import (
     4  	"net/url"
     5  	"os"
     6  	"path/filepath"
     7  	"regexp"
     8  	"runtime"
     9  	"strings"
    10  )
    11  
    12  var schemeRegexp = regexp.MustCompile(`^.+://.*`)
    13  
    14  func IsURI(ref string) bool {
    15  	return schemeRegexp.MatchString(ref)
    16  }
    17  
    18  func IsDir(p string) (bool, error) {
    19  	fileInfo, err := os.Stat(p)
    20  	if err != nil {
    21  		return false, err
    22  	}
    23  
    24  	return fileInfo.IsDir(), nil
    25  }
    26  
    27  func FilePathToURI(p string) (string, error) {
    28  	var err error
    29  	if !filepath.IsAbs(p) {
    30  		p, err = filepath.Abs(p)
    31  		if err != nil {
    32  			return "", err
    33  		}
    34  	}
    35  
    36  	if runtime.GOOS == "windows" {
    37  		if strings.HasPrefix(p, `\\`) {
    38  			return "file://" + filepath.ToSlash(strings.TrimPrefix(p, `\\`)), nil
    39  		}
    40  		return "file:///" + filepath.ToSlash(p), nil
    41  	}
    42  	return "file://" + p, nil
    43  }
    44  
    45  // examples:
    46  //
    47  // - unix file: file://laptop/some%20dir/file.tgz
    48  //
    49  // - windows drive: file:///C:/Documents%20and%20Settings/file.tgz
    50  //
    51  // - windows share: file://laptop/My%20Documents/file.tgz
    52  //
    53  func URIToFilePath(uri string) (string, error) {
    54  	var (
    55  		osPath string
    56  		err    error
    57  	)
    58  
    59  	osPath = filepath.FromSlash(strings.TrimPrefix(uri, "file://"))
    60  
    61  	if osPath, err = url.PathUnescape(osPath); err != nil {
    62  		return "", nil
    63  	}
    64  
    65  	if runtime.GOOS == "windows" {
    66  		if strings.HasPrefix(osPath, `\`) {
    67  			return strings.TrimPrefix(osPath, `\`), nil
    68  		}
    69  		return `\\` + osPath, nil
    70  	}
    71  	return osPath, nil
    72  }
    73  
    74  func ToAbsolute(uri, relativeTo string) (string, error) {
    75  	parsed, err := url.Parse(uri)
    76  	if err != nil {
    77  		return "", err
    78  	}
    79  
    80  	if parsed.Scheme == "" {
    81  		if !filepath.IsAbs(parsed.Path) {
    82  			absPath := filepath.Join(relativeTo, parsed.Path)
    83  			return FilePathToURI(absPath)
    84  		}
    85  	}
    86  
    87  	return uri, nil
    88  }
    89  
    90  func FilterReservedNames(p string) string {
    91  	// The following keys are reserved on Windows
    92  	// https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file?redirectedfrom=MSDN#win32-file-namespaces
    93  	reservedNameConversions := map[string]string{
    94  		"aux": "a_u_x",
    95  		"com": "c_o_m",
    96  		"con": "c_o_n",
    97  		"lpt": "l_p_t",
    98  		"nul": "n_u_l",
    99  		"prn": "p_r_n",
   100  	}
   101  	for k, v := range reservedNameConversions {
   102  		p = strings.Replace(p, k, v, -1)
   103  	}
   104  
   105  	return p
   106  }
   107  
   108  //WindowsDir is equivalent to path.Dir or filepath.Dir but always for Windows paths
   109  //reproduced because Windows implementation is not exported
   110  func WindowsDir(p string) string {
   111  	pathElements := strings.Split(p, `\`)
   112  
   113  	dirName := strings.Join(pathElements[:len(pathElements)-1], `\`)
   114  
   115  	return dirName
   116  }
   117  
   118  //WindowsBasename is equivalent to path.Basename or filepath.Basename but always for Windows paths
   119  //reproduced because Windows implementation is not exported
   120  func WindowsBasename(p string) string {
   121  	pathElements := strings.Split(p, `\`)
   122  
   123  	return pathElements[len(pathElements)-1]
   124  }
   125  
   126  //WindowsToSlash is equivalent to path.ToSlash or filepath.ToSlash but always for Windows paths
   127  //reproduced because Windows implementation is not exported
   128  func WindowsToSlash(p string) string {
   129  	slashPath := strings.ReplaceAll(p, `\`, "/") // convert slashes
   130  	if len(slashPath) < 2 {
   131  		return ""
   132  	}
   133  
   134  	return slashPath[2:] // strip volume
   135  }
   136  
   137  //WindowsPathSID returns the appropriate SID for a given UID and GID
   138  //This the basic logic for path permissions in Pack and Lifecycle
   139  func WindowsPathSID(uid, gid int) string {
   140  	if uid == 0 && gid == 0 {
   141  		return "S-1-5-32-544" // BUILTIN\Administrators
   142  	}
   143  	return "S-1-5-32-545" // BUILTIN\Users
   144  }