packer-cn/vendor/github.com/mitchellh/go-fs/fat/short_name.go

167 lines
3.3 KiB
Go

package fat
import (
"bytes"
"fmt"
"strings"
)
// checksumShortName returns the checksum for the shortname that is used
// for the long name entries.
func checksumShortName(name string) uint8 {
var sum uint8 = name[0]
for i := uint8(1); i < 11; i++ {
sum = name[i] + (((sum & 1) << 7) + ((sum & 0xFE) >> 1))
}
return sum
}
// generateShortName takes a list of existing short names and a long
// name and generates the next valid short name. This process is done
// according to the MS specification.
func generateShortName(longName string, used []string) (string, error) {
longName = strings.ToUpper(longName)
// Split the string at the final "."
dotIdx := strings.LastIndex(longName, ".")
var ext string
if dotIdx == -1 {
dotIdx = len(longName)
} else {
ext = longName[dotIdx+1 : len(longName)]
}
ext = cleanShortString(ext)
ext = ext[0:len(ext)]
rawName := longName[0:dotIdx]
name := cleanShortString(rawName)
simpleName := fmt.Sprintf("%s.%s", name, ext)
if ext == "" {
simpleName = simpleName[0 : len(simpleName)-1]
}
doSuffix := name != rawName || len(name) > 8
if !doSuffix {
for _, usedSingle := range used {
if strings.ToUpper(usedSingle) == simpleName {
doSuffix = true
break
}
}
}
if doSuffix {
found := false
for i := 1; i < 99999; i++ {
serial := fmt.Sprintf("~%d", i)
nameOffset := 8 - len(serial)
if len(name) < nameOffset {
nameOffset = len(name)
}
serialName := fmt.Sprintf("%s%s", name[0:nameOffset], serial)
simpleName = fmt.Sprintf("%s.%s", serialName, ext)
exists := false
for _, usedSingle := range used {
if strings.ToUpper(usedSingle) == simpleName {
exists = true
break
}
}
if !exists {
found = true
break
}
}
if !found {
return "", fmt.Errorf("could not generate short name for %s", longName)
}
}
return simpleName, nil
}
// shortNameEntryValue returns the proper formatted short name value
// for the directory cluster entry.
func shortNameEntryValue(name string) string {
var shortParts []string
if name == "." || name == ".." {
shortParts = []string{name, ""}
} else {
shortParts = strings.Split(name, ".")
}
if len(shortParts) == 1 {
shortParts = append(shortParts, "")
}
if len(shortParts[0]) < 8 {
var temp bytes.Buffer
temp.WriteString(shortParts[0])
for i := 0; i < 8-len(shortParts[0]); i++ {
temp.WriteRune(' ')
}
shortParts[0] = temp.String()
}
if len(shortParts[1]) < 3 {
var temp bytes.Buffer
temp.WriteString(shortParts[1])
for i := 0; i < 3-len(shortParts[1]); i++ {
temp.WriteRune(' ')
}
shortParts[1] = temp.String()
}
return fmt.Sprintf("%s%s", shortParts[0], shortParts[1])
}
func cleanShortString(v string) string {
var result bytes.Buffer
for _, char := range v {
// We skip these chars
if char == '.' || char == ' ' {
continue
}
if !validShortChar(char) {
char = '_'
}
result.WriteRune(char)
}
return result.String()
}
func validShortChar(char rune) bool {
if char >= 'A' && char <= 'Z' {
return true
}
if char >= '0' && char <= '9' {
return true
}
validShortSymbols := []rune{
'_', '^', '$', '~', '!', '#', '%', '&', '-', '{', '}', '(',
')', '@', '\'', '`',
}
for _, valid := range validShortSymbols {
if char == valid {
return true
}
}
return false
}