1package winio 2 3import ( 4 "io/ioutil" 5 "os" 6 "testing" 7 8 "golang.org/x/sys/windows" 9) 10 11// Checks if current matches expected. Note that AllocationSize is filesystem-specific, 12// so we check that the current.AllocationSize is >= expected.AllocationSize. 13// https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/5afa7f66-619c-48f3-955f-68c4ece704ae 14func checkFileStandardInfo(t *testing.T, current, expected *FileStandardInfo) { 15 if current.AllocationSize < expected.AllocationSize { 16 t.Fatalf("FileStandardInfo unexpectedly had AllocationSize %d, expecting >=%d", current.AllocationSize, expected.AllocationSize) 17 } 18 19 if current.EndOfFile != expected.EndOfFile { 20 t.Fatalf("FileStandardInfo unexpectedly had EndOfFile %d, expecting %d", current.EndOfFile, expected.EndOfFile) 21 } 22 23 if current.NumberOfLinks != expected.NumberOfLinks { 24 t.Fatalf("FileStandardInfo unexpectedly had NumberOfLinks %d, expecting %d", current.NumberOfLinks, expected.NumberOfLinks) 25 } 26 27 if current.DeletePending != expected.DeletePending { 28 if current.DeletePending { 29 t.Fatalf("FileStandardInfo unexpectedly DeletePending") 30 } else { 31 t.Fatalf("FileStandardInfo unexpectedly not DeletePending") 32 } 33 } 34 35 if current.Directory != expected.Directory { 36 if current.Directory { 37 t.Fatalf("FileStandardInfo unexpectedly Directory") 38 } else { 39 t.Fatalf("FileStandardInfo unexpectedly not Directory") 40 } 41 } 42} 43 44func TestGetFileStandardInfo_File(t *testing.T) { 45 f, err := ioutil.TempFile("", "tst") 46 if err != nil { 47 t.Fatal(err) 48 } 49 defer f.Close() 50 defer os.Remove(f.Name()) 51 52 expectedFileInfo := &FileStandardInfo{ 53 AllocationSize: 0, 54 EndOfFile: 0, 55 NumberOfLinks: 1, 56 DeletePending: false, 57 Directory: false, 58 } 59 60 info, err := GetFileStandardInfo(f) 61 if err != nil { 62 t.Fatal(err) 63 } 64 checkFileStandardInfo(t, info, expectedFileInfo) 65 66 bytesWritten, err := f.Write([]byte("0123456789")) 67 if err != nil { 68 t.Fatal(err) 69 } 70 71 expectedFileInfo.EndOfFile = int64(bytesWritten) 72 expectedFileInfo.AllocationSize = int64(bytesWritten) 73 74 info, err = GetFileStandardInfo(f) 75 if err != nil { 76 t.Fatal(err) 77 } 78 checkFileStandardInfo(t, info, expectedFileInfo) 79 80 linkName := f.Name() + ".link" 81 82 if err = os.Link(f.Name(), linkName); err != nil { 83 t.Fatal(err) 84 } 85 defer os.Remove(linkName) 86 87 expectedFileInfo.NumberOfLinks = 2 88 89 info, err = GetFileStandardInfo(f) 90 if err != nil { 91 t.Fatal(err) 92 } 93 checkFileStandardInfo(t, info, expectedFileInfo) 94 95 os.Remove(linkName) 96 97 expectedFileInfo.NumberOfLinks = 1 98 99 info, err = GetFileStandardInfo(f) 100 if err != nil { 101 t.Fatal(err) 102 } 103 checkFileStandardInfo(t, info, expectedFileInfo) 104} 105 106func TestGetFileStandardInfo_Directory(t *testing.T) { 107 tempDir, err := ioutil.TempDir("", "tst") 108 if err != nil { 109 t.Fatal(err) 110 } 111 defer os.RemoveAll(tempDir) 112 113 // os.Open returns the Search Handle, not the Directory Handle 114 // See https://github.com/golang/go/issues/13738 115 f, err := OpenForBackup(tempDir, windows.GENERIC_READ, 0, windows.OPEN_EXISTING) 116 if err != nil { 117 t.Fatal(err) 118 } 119 defer f.Close() 120 121 expectedFileInfo := &FileStandardInfo{ 122 AllocationSize: 0, 123 EndOfFile: 0, 124 NumberOfLinks: 1, 125 DeletePending: false, 126 Directory: true, 127 } 128 129 info, err := GetFileStandardInfo(f) 130 if err != nil { 131 t.Fatal(err) 132 } 133 checkFileStandardInfo(t, info, expectedFileInfo) 134} 135