package filepath_test
import (
+ "flag"
+ "fmt"
"io/ioutil"
"os"
"os/exec"
}
}
}
+
+// checkVolume8dot3Setting runs "fsutil 8dot3name query c:" command
+// (where c: is vol parameter) to discover "8dot3 name creation state".
+// The state is combination of 2 flags. The global flag controls if it
+// is per volume or global setting:
+// 0 - Enable 8dot3 name creation on all volumes on the system
+// 1 - Disable 8dot3 name creation on all volumes on the system
+// 2 - Set 8dot3 name creation on a per volume basis
+// 3 - Disable 8dot3 name creation on all volumes except the system volume
+// If global flag is set to 2, then per-volume flag needs to be examined:
+// 0 - Enable 8dot3 name creation on this volume
+// 1 - Disable 8dot3 name creation on this volume
+// checkVolume8dot3Setting verifies that "8dot3 name creation" flags
+// are set to 2 and 0, if enabled parameter is true, or 2 and 1, if enabled
+// is false. Otherwise checkVolume8dot3Setting returns error.
+func checkVolume8dot3Setting(vol string, enabled bool) error {
+ // It appears, on some systems "fsutil 8dot3name query ..." command always
+ // exits with error. Ignore exit code, and look at fsutil output instead.
+ out, _ := exec.Command("fsutil", "8dot3name", "query", vol).CombinedOutput()
+ // Check that system has "Volume level setting" set.
+ expected := "The registry state of NtfsDisable8dot3NameCreation is 2, the default (Volume level setting)"
+ if !strings.Contains(string(out), expected) {
+ // Windows 10 version of fsutil has different output message.
+ expectedWindow10 := "The registry state is: 2 (Per volume setting - the default)"
+ if !strings.Contains(string(out), expectedWindow10) {
+ return fmt.Errorf("fsutil output should contain %q, but is %q", expected, string(out))
+ }
+ }
+ // Now check the volume setting.
+ expected = "Based on the above two settings, 8dot3 name creation is %s on %s"
+ if enabled {
+ expected = fmt.Sprintf(expected, "enabled", vol)
+ } else {
+ expected = fmt.Sprintf(expected, "disabled", vol)
+ }
+ if !strings.Contains(string(out), expected) {
+ return fmt.Errorf("unexpected fsutil output: %q", string(out))
+ }
+ return nil
+}
+
+func setVolume8dot3Setting(vol string, enabled bool) error {
+ cmd := []string{"fsutil", "8dot3name", "set", vol}
+ if enabled {
+ cmd = append(cmd, "0")
+ } else {
+ cmd = append(cmd, "1")
+ }
+ // It appears, on some systems "fsutil 8dot3name set ..." command always
+ // exits with error. Ignore exit code, and look at fsutil output instead.
+ out, _ := exec.Command(cmd[0], cmd[1:]...).CombinedOutput()
+ if string(out) != "\r\nSuccessfully set 8dot3name behavior.\r\n" {
+ // Windows 10 version of fsutil has different output message.
+ expectedWindow10 := "Successfully %s 8dot3name generation on %s\r\n"
+ if enabled {
+ expectedWindow10 = fmt.Sprintf(expectedWindow10, "enabled", vol)
+ } else {
+ expectedWindow10 = fmt.Sprintf(expectedWindow10, "disabled", vol)
+ }
+ if string(out) != expectedWindow10 {
+ return fmt.Errorf("%v command failed: %q", cmd, string(out))
+ }
+ }
+ return nil
+}
+
+var runFSModifyTests = flag.Bool("run_fs_modify_tests", false, "run tests which modify filesystem parameters")
+
+// This test assumes registry state of NtfsDisable8dot3NameCreation is 2,
+// the default (Volume level setting).
+func TestEvalSymlinksCanonicalNamesWith8dot3Disabled(t *testing.T) {
+ if !*runFSModifyTests {
+ t.Skip("skipping test that modifies file system setting; enable with -run_fs_modify_tests")
+ }
+ tempVol := filepath.VolumeName(os.TempDir())
+ if len(tempVol) != 2 {
+ t.Fatalf("unexpected temp volume name %q", tempVol)
+ }
+
+ err := checkVolume8dot3Setting(tempVol, true)
+ if err != nil {
+ t.Fatal(err)
+ }
+ err = setVolume8dot3Setting(tempVol, false)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer func() {
+ err := setVolume8dot3Setting(tempVol, true)
+ if err != nil {
+ t.Fatal(err)
+ }
+ err = checkVolume8dot3Setting(tempVol, true)
+ if err != nil {
+ t.Fatal(err)
+ }
+ }()
+ err = checkVolume8dot3Setting(tempVol, false)
+ if err != nil {
+ t.Fatal(err)
+ }
+ TestEvalSymlinksCanonicalNames(t)
+}