Created
February 26, 2020 23:23
-
-
Save marwatk/4f9c59b112fd4dd5c360a5a29ddbfccf to your computer and use it in GitHub Desktop.
go-chmod with tests
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package chmod | |
import ( | |
"fmt" | |
"os" | |
"regexp" | |
"strconv" | |
"strings" | |
) | |
const setuid = 4 | |
const setgid = 2 | |
const sticky = 1 | |
const read = 4 | |
const write = 2 | |
const execute = 1 | |
const specialMask = 07000 | |
const ownerMask = 0700 | |
const groupMask = 070 | |
const otherMask = 07 | |
func applyNumericPerms(curMode uint32, modifier string, perms uint32) (uint32, error) { | |
if modifier == "" { | |
modifier = "=" | |
} | |
switch modifier { | |
case "=": | |
return perms, nil | |
case "+": | |
return curMode | perms, nil | |
case "-": | |
return curMode &^ perms, nil | |
default: | |
return curMode, fmt.Errorf("Unknown permissions modifier [%s]", modifier) | |
} | |
} | |
func applySymbolicPerms(curMode uint32, isFolder bool, appliesTo string, perms string) (uint32, error) { | |
if appliesTo == "" { | |
/* | |
This is the case where you `chmod +rw <file>` (emtpy specifier for where to apply) | |
I can't find a way to only fetch the umask in golang so am not going to implement | |
it (I can't imagine needing it, anyway). It's supposed to (from the man page): | |
If none of these are given, the effect is as if (a) were given, but bits that are | |
set in the umask are not affected | |
*/ | |
return 0, fmt.Errorf("Empty appliesTo is not supported") | |
} | |
appliesTo = strings.ReplaceAll(appliesTo, "a", "ugo") | |
//We put the ugo before the rwxXst so that it doesn't use the empty string instead of continuing to ugo | |
for _, parts := range regexp.MustCompile(`([+=-])([ugo]|[rwxXst]*)`).FindAllStringSubmatch(perms, -1) { | |
modifier := parts[1] | |
perms := parts[2] | |
for _, whoTo := range appliesTo { | |
switch perms { | |
case "u": | |
fallthrough | |
case "g": | |
fallthrough | |
case "o": | |
srcPerms, err := getPerms(curMode, perms) | |
if err != nil { | |
return 0, err | |
} | |
curMode, err = setPerms(curMode, modifier, string(whoTo), srcPerms) | |
if err != nil { | |
return 0, err | |
} | |
default: | |
specialBits, sectionBits, err := calculateBits(string(whoTo), isFolder, curMode, perms) | |
if err != nil { | |
return 0, err | |
} | |
curMode, err = setPerms(curMode, modifier, string(whoTo), sectionBits) | |
if err != nil { | |
return 0, fmt.Errorf("Error calling setPerms for %v in applySymbolicPerms default case: %v", whoTo, err) | |
} | |
curMode, err = setPerms(curMode, modifier, "s", specialBits) | |
if err != nil { | |
return 0, fmt.Errorf("Error calling setPerms for 's' section in applySymbolicPerms default case: %v", err) | |
} | |
} | |
} | |
} | |
return curMode, nil | |
} | |
func calculateBits(whoTo string, isFolder bool, curMode uint32, bits string) (uint8, uint8, error) { | |
specialBits := uint8(0) | |
sectionBits := uint8(0) | |
for _, bit := range bits { | |
switch string(bit) { | |
case "r": | |
sectionBits |= read | |
case "w": | |
sectionBits |= write | |
case "x": | |
sectionBits |= execute | |
case "X": | |
existingPerms, err := getPerms(curMode, string(whoTo)) | |
if err != nil { | |
return 0, 0, err | |
} | |
if isFolder || existingPerms&execute != 0 { | |
sectionBits |= execute | |
} | |
case "s": | |
if string(whoTo) == "g" { | |
specialBits |= setgid | |
} else if string(whoTo) == "u" { | |
specialBits |= setuid | |
} | |
case "t": | |
if string(whoTo) == "o" { // This filter is not document in chmod man page | |
specialBits |= sticky | |
} | |
} | |
} | |
return specialBits, sectionBits, nil | |
} | |
func calculateFileMode(curMode uint32, isFolder bool, applyMode string) (uint32, error) { | |
// From chmod man page: | |
// Each MODE is of the form '[ugoa]*([-+=]([rwxXst]*|[ugo]))+|[-+=][0-7]+'. | |
newMode := uint32(curMode) | |
numericRe := regexp.MustCompile(`^([+=-]?)([0-7]{1,4})$`) | |
//We put the ugo before the rwxXst so that it doesn't use the empty string instead of continuing to ugo | |
symbolicRe := regexp.MustCompile(`^([ugoa]*)(([+=-]([ugo]|[rwxXst]*))+)$`) | |
for _, mode := range strings.Split(applyMode, ",") { | |
if numericRe.MatchString(mode) { | |
parts := numericRe.FindStringSubmatch(mode) | |
thisMode, err := strconv.ParseInt(parts[2], 8, 32) | |
if err != nil { | |
return 0, err | |
} | |
modifier := parts[1] | |
newMode, err = applyNumericPerms(newMode, modifier, uint32(thisMode)) | |
if err != nil { | |
return 0, err | |
} | |
} else if symbolicRe.MatchString(mode) { | |
parts := symbolicRe.FindStringSubmatch(mode) | |
var err error | |
newMode, err = applySymbolicPerms(newMode, isFolder, parts[1], parts[2]) | |
if err != nil { | |
return 0, err | |
} | |
} else { | |
return curMode, fmt.Errorf("Mode %q is not valid", mode) | |
} | |
} | |
return newMode, nil | |
} | |
// Chmod allows for any mode specified in the linux chmod command. | |
func Chmod(name string, mode string) error { | |
curMode, isDir, err := getFileMode(name) | |
if err != nil { | |
return err | |
} | |
newMode, err := calculateFileMode(curMode, isDir, mode) | |
if err != nil { | |
return err | |
} | |
if newMode != curMode { | |
err = setFileMode(name, newMode) | |
} | |
return err | |
} | |
func getFileMode(name string) (uint32, bool, error) { | |
stat, err := os.Stat(name) | |
if err != nil { | |
return 0, false, err | |
} | |
goMode := stat.Mode() | |
unixMode := uint32(goMode & 0777) //Strip non permission metadata (like folder flag) | |
if goMode&os.ModeSetgid != 0 { | |
unixMode, err = setPerms(unixMode, "+", "s", setgid) | |
if err != nil { | |
return 0, false, err | |
} | |
} | |
if goMode&os.ModeSetuid != 0 { | |
unixMode, err = setPerms(unixMode, "+", "s", setuid) | |
if err != nil { | |
return 0, false, err | |
} | |
} | |
if goMode&os.ModeSticky != 0 { | |
unixMode, err = setPerms(unixMode, "+", "s", sticky) | |
if err != nil { | |
return 0, false, err | |
} | |
} | |
return unixMode, stat.IsDir(), nil | |
} | |
func getPerms(mode uint32, who string) (uint8, error) { | |
switch who { | |
case "s": | |
return uint8((mode & specialMask) >> 9), nil | |
case "u": | |
return uint8((mode & ownerMask) >> 6), nil | |
case "g": | |
return uint8((mode & groupMask) >> 3), nil | |
case "o": | |
return uint8(mode & otherMask), nil | |
default: | |
return 0, fmt.Errorf("Invalid source specification [%s]", who) | |
} | |
} | |
func setFileMode(name string, mode uint32) error { | |
fileMode, err := uint32ToFileMode(mode) | |
err = os.Chmod(name, fileMode) | |
if err != nil { | |
return err | |
} | |
return nil | |
} | |
func setPerms(mode uint32, modifier string, who string, perms uint8) (uint32, error) { | |
newMode := uint32(perms) | |
mask := uint32(0) | |
if who == "a" { | |
var err error | |
mode, err = setPerms(mode, modifier, "u", perms) | |
if err != nil { | |
return 0, err | |
} | |
mode, err = setPerms(mode, modifier, "g", perms) | |
if err != nil { | |
return 0, err | |
} | |
mode, err = setPerms(mode, modifier, "o", perms) | |
if err != nil { | |
return 0, err | |
} | |
return mode, nil | |
} | |
switch who { | |
case "s": | |
newMode <<= 9 | |
mask = specialMask | |
case "u": | |
newMode <<= 6 | |
mask = ownerMask | |
case "g": | |
newMode <<= 3 | |
mask = groupMask | |
case "o": | |
mask = otherMask | |
default: | |
return mode, fmt.Errorf("Invalid who specification on setPerms [%s]", who) | |
} | |
switch modifier { | |
case "+": | |
mode |= newMode | |
case "-": | |
mode &^= newMode | |
case "=": | |
mode &^= mask | |
mode |= newMode | |
} | |
return mode, nil | |
} | |
// UnixModeToFileMode converts a string representation of a unix file mode (755) | |
// to a golang os.FileMode. | |
func UnixModeToFileMode(unixMode string) (os.FileMode, error) { | |
intVal, err := strconv.ParseInt(unixMode, 8, 32) | |
if err != nil { | |
return 0, err | |
} | |
return uint32ToFileMode(uint32(intVal)) | |
} | |
func uint32ToFileMode(mode uint32) (os.FileMode, error) { | |
fileMode := os.FileMode(mode) | |
perms, err := getPerms(mode, "s") | |
if err != nil { | |
return 0, err | |
} | |
if perms&sticky != 0 { | |
fileMode |= os.ModeSticky | |
} | |
if perms&setgid != 0 { | |
fileMode |= os.ModeSetgid | |
} | |
if perms&setuid != 0 { | |
fileMode |= os.ModeSetuid | |
} | |
return fileMode, nil | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package chmod | |
import ( | |
"io/ioutil" | |
"os" | |
"os/exec" | |
"testing" | |
) | |
func testGetPerms(t *testing.T, mode uint32, who string, expected uint8, wantError bool) { | |
actual, err := getPerms(mode, who) | |
if wantError { | |
if err == nil { | |
t.Errorf("getPerms(%o, %q) should have errored but didn't", mode, who) | |
} | |
} else { | |
if err != nil { | |
t.Errorf("getPerms(%o, %q) errored %v", mode, who, err) | |
} | |
if actual != expected { | |
t.Errorf("getPerms(%o, %q) = %d; expected %d", mode, who, actual, expected) | |
} | |
} | |
} | |
func TestGetPerms(t *testing.T) { | |
testGetPerms(t, 01754, "o", 4, false) | |
testGetPerms(t, 01754, "g", 5, false) | |
testGetPerms(t, 01754, "u", 7, false) | |
testGetPerms(t, 01754, "s", 1, false) | |
testGetPerms(t, 01754, "p", 1, true) | |
} | |
func testSetPerms(t *testing.T, mode uint32, modifier string, who string, perms uint8, expected uint32, wantError bool) { | |
actual, err := setPerms(mode, modifier, who, perms) | |
if wantError { | |
if err == nil { | |
t.Errorf("setPerms(%o, %q, %q, %o) should have errored but didn't", mode, modifier, who, perms) | |
} | |
} else { | |
if err != nil { | |
t.Errorf("setPerms(%o, %q, %q, %o) errored %v", mode, modifier, who, perms, err) | |
} | |
if actual != expected { | |
t.Errorf("setPerms(%o, %q, %q, %o) = %o; expected %o", mode, modifier, who, perms, actual, expected) | |
} | |
} | |
} | |
func TestSetPerms(t *testing.T) { | |
testSetPerms(t, 0777, "-", "o", 1, 0776, false) | |
testSetPerms(t, 0777, "-", "o", 2, 0775, false) | |
testSetPerms(t, 0777, "-", "o", 7, 0770, false) | |
testSetPerms(t, 0770, "-", "o", 1, 0770, false) | |
testSetPerms(t, 0770, "-", "o", 2, 0770, false) | |
testSetPerms(t, 0770, "-", "o", 7, 0770, false) | |
testSetPerms(t, 0000, "-", "o", 1, 0000, false) | |
testSetPerms(t, 0000, "-", "o", 2, 0000, false) | |
testSetPerms(t, 0000, "-", "o", 7, 0000, false) | |
testSetPerms(t, 0777, "-", "g", 1, 0767, false) | |
testSetPerms(t, 0777, "-", "g", 2, 0757, false) | |
testSetPerms(t, 0777, "-", "g", 7, 0707, false) | |
testSetPerms(t, 0777, "-", "u", 1, 0677, false) | |
testSetPerms(t, 0777, "-", "u", 2, 0577, false) | |
testSetPerms(t, 0777, "-", "u", 7, 0077, false) | |
testSetPerms(t, 0777, "+", "o", 1, 0777, false) | |
testSetPerms(t, 0777, "+", "o", 2, 0777, false) | |
testSetPerms(t, 0777, "+", "o", 7, 0777, false) | |
testSetPerms(t, 0770, "+", "o", 1, 0771, false) | |
testSetPerms(t, 0770, "+", "o", 2, 0772, false) | |
testSetPerms(t, 0770, "+", "o", 7, 0777, false) | |
testSetPerms(t, 0000, "+", "o", 1, 0001, false) | |
testSetPerms(t, 0000, "+", "o", 2, 0002, false) | |
testSetPerms(t, 0000, "+", "o", 7, 0007, false) | |
testSetPerms(t, 0000, "+", "g", 1, 0010, false) | |
testSetPerms(t, 0000, "+", "g", 2, 0020, false) | |
testSetPerms(t, 0000, "+", "g", 7, 0070, false) | |
testSetPerms(t, 0000, "+", "u", 1, 0100, false) | |
testSetPerms(t, 0000, "+", "u", 2, 0200, false) | |
testSetPerms(t, 0000, "+", "u", 7, 0700, false) | |
testSetPerms(t, 0777, "=", "o", 1, 0771, false) | |
testSetPerms(t, 0777, "=", "o", 2, 0772, false) | |
testSetPerms(t, 0777, "=", "o", 7, 0777, false) | |
testSetPerms(t, 0770, "=", "o", 1, 0771, false) | |
testSetPerms(t, 0770, "=", "o", 2, 0772, false) | |
testSetPerms(t, 0770, "=", "o", 7, 0777, false) | |
testSetPerms(t, 0000, "=", "o", 1, 0001, false) | |
testSetPerms(t, 0000, "=", "o", 2, 0002, false) | |
testSetPerms(t, 0000, "=", "o", 7, 0007, false) | |
testSetPerms(t, 0000, "=", "g", 1, 0010, false) | |
testSetPerms(t, 0000, "=", "g", 2, 0020, false) | |
testSetPerms(t, 0000, "=", "g", 7, 0070, false) | |
testSetPerms(t, 0000, "=", "u", 1, 0100, false) | |
testSetPerms(t, 0000, "=", "u", 2, 0200, false) | |
testSetPerms(t, 0000, "=", "u", 7, 0700, false) | |
testSetPerms(t, 0000, "=", "s", 1, 01000, false) | |
testSetPerms(t, 0000, "=", "s", 2, 02000, false) | |
testSetPerms(t, 0000, "=", "s", 7, 07000, false) | |
testSetPerms(t, 0000, "+", "s", 1, 01000, false) | |
testSetPerms(t, 0000, "+", "s", 2, 02000, false) | |
testSetPerms(t, 0000, "+", "s", 7, 07000, false) | |
testSetPerms(t, 07777, "-", "s", 1, 06777, false) | |
testSetPerms(t, 07777, "-", "s", 2, 05777, false) | |
testSetPerms(t, 07777, "-", "s", 7, 00777, false) | |
testSetPerms(t, 0000, "+", "a", 1, 0111, false) | |
testSetPerms(t, 0000, "+", "a", 2, 0222, false) | |
testSetPerms(t, 0000, "+", "a", 7, 0777, false) | |
testSetPerms(t, 07777, "-", "a", 1, 07666, false) | |
testSetPerms(t, 07777, "-", "a", 2, 07555, false) | |
testSetPerms(t, 07777, "-", "a", 7, 07000, false) | |
testSetPerms(t, 07777, "-", "a", 0, 07777, false) | |
testSetPerms(t, 07777, "-", "a", 0, 07777, false) | |
testSetPerms(t, 07777, "-", "a", 0, 07777, false) | |
testSetPerms(t, 07777, "=", "a", 0, 07000, false) | |
testSetPerms(t, 07777, "=", "a", 0, 07000, false) | |
testSetPerms(t, 07777, "=", "a", 0, 07000, false) | |
testSetPerms(t, 07777, "+", "a", 0, 07777, false) | |
testSetPerms(t, 07777, "+", "a", 0, 07777, false) | |
testSetPerms(t, 07777, "+", "a", 0, 07777, false) | |
testSetPerms(t, 07777, "-", "o", 0, 07777, false) | |
testSetPerms(t, 07777, "-", "o", 0, 07777, false) | |
testSetPerms(t, 07777, "-", "o", 0, 07777, false) | |
testSetPerms(t, 07777, "=", "o", 0, 07770, false) | |
testSetPerms(t, 07777, "=", "o", 0, 07770, false) | |
testSetPerms(t, 07777, "=", "o", 0, 07770, false) | |
testSetPerms(t, 07777, "+", "o", 0, 07777, false) | |
testSetPerms(t, 07777, "+", "o", 0, 07777, false) | |
testSetPerms(t, 07777, "+", "o", 0, 07777, false) | |
testSetPerms(t, 0777, "-", "o", 0, 0777, false) | |
testSetPerms(t, 0777, "-", "o", 0, 0777, false) | |
testSetPerms(t, 0777, "-", "o", 0, 0777, false) | |
testSetPerms(t, 0777, "=", "o", 0, 0770, false) | |
testSetPerms(t, 0777, "=", "o", 0, 0770, false) | |
testSetPerms(t, 0777, "=", "o", 0, 0770, false) | |
testSetPerms(t, 0777, "+", "o", 0, 0777, false) | |
testSetPerms(t, 0777, "+", "o", 0, 0777, false) | |
testSetPerms(t, 0777, "+", "o", 0, 0777, false) | |
testSetPerms(t, 0777, "-", "p", 1, 0677, true) | |
} | |
func confirmRealChmodMatch(t *testing.T, curMode uint32, isFolder bool, applyMode string, expected uint32) { | |
path, err := exec.LookPath("chmod") | |
if err != nil { | |
//No chmod in path, can't do integration test | |
return | |
} | |
var temp string | |
if isFolder { | |
temp, err = ioutil.TempDir("", "") | |
if err != nil { | |
t.Errorf("Error making temp folder %v", err) | |
return | |
} | |
} else { | |
tempFile, err := ioutil.TempFile("", "") | |
if err != nil { | |
t.Errorf("Error making temp file %v", err) | |
return | |
} | |
temp = tempFile.Name() | |
tempFile.Close() | |
} | |
defer os.Remove(temp) | |
setFileMode(temp, curMode) | |
err = exec.Command(path, applyMode, temp).Run() | |
if err != nil { | |
t.Errorf("Error running [chmod %q %q] %v", applyMode, temp, err) | |
return | |
} | |
actual, _, err := getFileMode(temp) | |
if err != nil { | |
t.Errorf("Error `stat`ing file %q: %v", temp, err) | |
return | |
} | |
if actual != expected { | |
t.Errorf("The test is a lie! Real chmod says (folder: %t) starting with %o having [chmod %q] applied should end at %o, not %o as coded!", isFolder, curMode, applyMode, actual, expected) | |
} | |
} | |
func testCalculateFileMode(t *testing.T, curMode uint32, isFolder bool, applyMode string, expected uint32, wantError bool) { | |
if !wantError { | |
confirmRealChmodMatch(t, curMode, isFolder, applyMode, expected) | |
} | |
actual, err := calculateFileMode(curMode, isFolder, applyMode) | |
if wantError { | |
if err == nil { | |
t.Errorf("calculateFileMode(%o, %t, %q) should have errored but didn't", curMode, isFolder, applyMode) | |
} | |
} else { | |
if err != nil { | |
t.Errorf("calculateFileMode(%o, %t, %q) errored %v", curMode, isFolder, applyMode, err) | |
} | |
if actual != expected { | |
t.Errorf("calculateFileMode(%o, %t, %q) = %o; expected %o", curMode, isFolder, applyMode, actual, expected) | |
} | |
} | |
} | |
func TestCalculateFileMode(t *testing.T) { | |
testCalculateFileMode(t, 0755, false, "644", 0644, false) | |
testCalculateFileMode(t, 0755, false, "+020", 0775, false) | |
testCalculateFileMode(t, 0755, false, "-111", 0644, false) | |
testCalculateFileMode(t, 0666, false, "go+x", 0677, false) | |
testCalculateFileMode(t, 0666, false, "go=+x", 0611, false) | |
testCalculateFileMode(t, 0666, false, "go=+", 0600, false) | |
testCalculateFileMode(t, 0666, false, "go+x", 0677, false) | |
testCalculateFileMode(t, 0666, false, "go+", 0666, false) | |
testCalculateFileMode(t, 0666, false, "go=-w", 0600, false) | |
testCalculateFileMode(t, 0666, false, "a=-w", 0000, false) | |
testCalculateFileMode(t, 0666, false, "go-w", 0644, false) | |
testCalculateFileMode(t, 0666, false, "a-w", 0444, false) | |
testCalculateFileMode(t, 0666, false, "go=-w+x", 0611, false) | |
testCalculateFileMode(t, 0666, false, "go-w+x", 0655, false) | |
testCalculateFileMode(t, 0700, false, "g=u", 0770, false) | |
testCalculateFileMode(t, 0700, false, "a=u", 0777, false) | |
testCalculateFileMode(t, 0700, false, "go=u", 0777, false) | |
testCalculateFileMode(t, 0755, false, "go=u", 0777, false) | |
testCalculateFileMode(t, 0644, false, "g=u", 0664, false) | |
testCalculateFileMode(t, 0644, false, "a=u", 0666, false) | |
testCalculateFileMode(t, 0700, false, "go=u-w", 0755, false) | |
testCalculateFileMode(t, 0644, false, "ug+rwX", 0664, false) | |
testCalculateFileMode(t, 0644, true, "ug+rwX", 0774, false) | |
testCalculateFileMode(t, 0644, true, "ug+rwX,o+rX", 0775, false) | |
testCalculateFileMode(t, 0644, false, "a+rwX", 0666, false) | |
testCalculateFileMode(t, 0644, true, "a+rwX", 0777, false) | |
testCalculateFileMode(t, 0644, true, "a+X", 0755, false) | |
testCalculateFileMode(t, 0755, true, "a=X", 0111, false) | |
testCalculateFileMode(t, 0755, false, "a=X", 0111, false) | |
testCalculateFileMode(t, 0755, true, "go-X", 0744, false) | |
testCalculateFileMode(t, 0755, false, "go-X", 0744, false) | |
testCalculateFileMode(t, 0000, false, "+755,-111,g+w", 0664, false) | |
testCalculateFileMode(t, 0000, false, "+755,a-x,g+w", 0664, false) | |
testCalculateFileMode(t, 0000, false, "+755,,", 0664, true) | |
// Test various order of operations | |
testCalculateFileMode(t, 0751, false, "oa=g", 0555, false) | |
testCalculateFileMode(t, 0751, false, "ao=g", 0555, false) | |
testCalculateFileMode(t, 0751, false, "ao=g", 0555, false) | |
testCalculateFileMode(t, 0751, false, "ug=g", 0551, false) | |
testCalculateFileMode(t, 0751, false, "ug=g,o=u", 0555, false) | |
// special bits | |
testCalculateFileMode(t, 0751, false, "g+s", 02751, false) | |
testCalculateFileMode(t, 0751, false, "g-s", 0751, false) | |
testCalculateFileMode(t, 01751, false, "g-s", 01751, false) | |
testCalculateFileMode(t, 02751, false, "g-s", 0751, false) | |
testCalculateFileMode(t, 07751, false, "g-s", 05751, false) | |
testCalculateFileMode(t, 0751, false, "u+s", 04751, false) | |
testCalculateFileMode(t, 0751, false, "u-s", 0751, false) | |
testCalculateFileMode(t, 01751, false, "u-s", 01751, false) | |
testCalculateFileMode(t, 04751, false, "u-s", 0751, false) | |
testCalculateFileMode(t, 07751, false, "u-s", 03751, false) | |
testCalculateFileMode(t, 0751, false, "u+t", 0751, false) | |
testCalculateFileMode(t, 0751, false, "g+t", 0751, false) | |
testCalculateFileMode(t, 0751, false, "o+t", 01751, false) | |
testCalculateFileMode(t, 0751, false, "a+t", 01751, false) | |
testCalculateFileMode(t, 01751, false, "u-t", 01751, false) | |
testCalculateFileMode(t, 0751, false, "u-t", 0751, false) | |
testCalculateFileMode(t, 03751, false, "u-t", 03751, false) | |
testCalculateFileMode(t, 07751, false, "u-t", 07751, false) | |
testCalculateFileMode(t, 01751, false, "o-t", 0751, false) | |
testCalculateFileMode(t, 0751, false, "o-t", 0751, false) | |
testCalculateFileMode(t, 03751, false, "o-t", 02751, false) | |
testCalculateFileMode(t, 07751, false, "o-t", 06751, false) | |
testCalculateFileMode(t, 01751, false, "a-t", 0751, false) | |
testCalculateFileMode(t, 0751, false, "a-t", 0751, false) | |
testCalculateFileMode(t, 03751, false, "a-t", 02751, false) | |
testCalculateFileMode(t, 07751, false, "a-t", 06751, false) | |
testCalculateFileMode(t, 0751, true, "g+s", 02751, false) | |
testCalculateFileMode(t, 0751, true, "g-s", 0751, false) | |
testCalculateFileMode(t, 01751, true, "g-s", 01751, false) | |
testCalculateFileMode(t, 02751, true, "g-s", 0751, false) | |
testCalculateFileMode(t, 07751, true, "g-s", 05751, false) | |
testCalculateFileMode(t, 0751, true, "u+s", 04751, false) | |
testCalculateFileMode(t, 0751, true, "u-s", 0751, false) | |
testCalculateFileMode(t, 01751, true, "u-s", 01751, false) | |
testCalculateFileMode(t, 04751, true, "u-s", 0751, false) | |
testCalculateFileMode(t, 07751, true, "u-s", 03751, false) | |
testCalculateFileMode(t, 0751, true, "u+t", 0751, false) | |
testCalculateFileMode(t, 0751, true, "g+t", 0751, false) | |
testCalculateFileMode(t, 0751, true, "o+t", 01751, false) | |
testCalculateFileMode(t, 0751, true, "a+t", 01751, false) | |
testCalculateFileMode(t, 01751, true, "u-t", 01751, false) | |
testCalculateFileMode(t, 0751, true, "u-t", 0751, false) | |
testCalculateFileMode(t, 03751, true, "u-t", 03751, false) | |
testCalculateFileMode(t, 07751, true, "u-t", 07751, false) | |
testCalculateFileMode(t, 01751, true, "o-t", 0751, false) | |
testCalculateFileMode(t, 0751, true, "o-t", 0751, false) | |
testCalculateFileMode(t, 03751, true, "o-t", 02751, false) | |
testCalculateFileMode(t, 07751, true, "o-t", 06751, false) | |
testCalculateFileMode(t, 01751, true, "a-t", 0751, false) | |
testCalculateFileMode(t, 0751, true, "a-t", 0751, false) | |
testCalculateFileMode(t, 03751, true, "a-t", 02751, false) | |
testCalculateFileMode(t, 07751, true, "a-t", 06751, false) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment