windows: Support all REPARSE_POINT attrib files properly. (#4203)

This change adopts the upstream fix in this regard at
https://go-review.googlesource.com/#/c/41834/ for Minio's
purposes.

Go's current os.Stat() lacks support for lot of strange
windows files such as

 - share symlinks on SMB2
 - symlinks on docker nanoserver
 - de-duplicated files on NTFS de-duplicated volume.

This PR attempts to incorporate the change mentioned here

   https://blogs.msdn.microsoft.com/oldnewthing/20100212-00/?p=14963/

The article suggests to use Windows I/O manager to
dereference the symbolic link.

Fixes #4122
This commit is contained in:
Harshavardhana
2017-05-02 02:35:27 -07:00
committed by GitHub
parent 44d53c9c67
commit f0b5c0ec7c
20 changed files with 497 additions and 56 deletions

View File

@@ -1,5 +1,5 @@
/*
* Minio Client (C) 2015 Minio, Inc.
* Minio Client (C) 2015, 2016, 2017 Minio, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@ import (
"path"
"testing"
os2 "github.com/minio/minio/pkg/x/os"
. "gopkg.in/check.v1"
)
@@ -47,7 +48,7 @@ func (s *MySuite) TearDownSuite(c *C) {
func (s *MySuite) TestSafeAbort(c *C) {
f, err := CreateFile(path.Join(s.root, "testfile-abort"))
c.Assert(err, IsNil)
_, err = os.Stat(path.Join(s.root, "testfile-abort"))
_, err = os2.Stat(path.Join(s.root, "testfile-abort"))
c.Assert(err, Not(IsNil))
err = f.Abort()
c.Assert(err, IsNil)
@@ -58,11 +59,11 @@ func (s *MySuite) TestSafeAbort(c *C) {
func (s *MySuite) TestSafeClose(c *C) {
f, err := CreateFile(path.Join(s.root, "testfile-close"))
c.Assert(err, IsNil)
_, err = os.Stat(path.Join(s.root, "testfile-close"))
_, err = os2.Stat(path.Join(s.root, "testfile-close"))
c.Assert(err, Not(IsNil))
err = f.Close()
c.Assert(err, IsNil)
_, err = os.Stat(path.Join(s.root, "testfile-close"))
_, err = os2.Stat(path.Join(s.root, "testfile-close"))
c.Assert(err, IsNil)
err = os.Remove(path.Join(s.root, "testfile-close"))
c.Assert(err, IsNil)
@@ -73,7 +74,7 @@ func (s *MySuite) TestSafeClose(c *C) {
func (s *MySuite) TestSafe(c *C) {
f, err := CreateFile(path.Join(s.root, "testfile-safe"))
c.Assert(err, IsNil)
_, err = os.Stat(path.Join(s.root, "testfile-safe"))
_, err = os2.Stat(path.Join(s.root, "testfile-safe"))
c.Assert(err, Not(IsNil))
err = f.Close()
c.Assert(err, IsNil)
@@ -81,7 +82,7 @@ func (s *MySuite) TestSafe(c *C) {
c.Assert(err.Error(), Equals, "write on closed file")
err = f.Close()
c.Assert(err.Error(), Equals, "close on closed file")
_, err = os.Stat(path.Join(s.root, "testfile-safe"))
_, err = os2.Stat(path.Join(s.root, "testfile-safe"))
c.Assert(err, IsNil)
err = os.Remove(path.Join(s.root, "testfile-safe"))
c.Assert(err, IsNil)
@@ -90,11 +91,11 @@ func (s *MySuite) TestSafe(c *C) {
func (s *MySuite) TestSafeAbortWrite(c *C) {
f, err := CreateFile(path.Join(s.root, "purgefile-abort"))
c.Assert(err, IsNil)
_, err = os.Stat(path.Join(s.root, "purgefile-abort"))
_, err = os2.Stat(path.Join(s.root, "purgefile-abort"))
c.Assert(err, Not(IsNil))
err = f.Abort()
c.Assert(err, IsNil)
_, err = os.Stat(path.Join(s.root, "purgefile-abort"))
_, err = os2.Stat(path.Join(s.root, "purgefile-abort"))
c.Assert(err, Not(IsNil))
err = f.Abort()
c.Assert(err.Error(), Equals, "abort on aborted file")