mirror of https://github.com/minio/minio.git
				
				
				
			Remove go1.9 specific code for windows (#5033)
Following fix https://go-review.googlesource.com/#/c/41834/ has been merged upstream and released with go1.9.
This commit is contained in:
		
							parent
							
								
									ad53c5d859
								
							
						
					
					
						commit
						3d0dced23c
					
				|  | @ -176,10 +176,11 @@ function __init__() | |||
|     mkdir -p "$MINIO_CONFIG_DIR" | ||||
|     mkdir -p "$MINT_DATA_DIR" | ||||
| 
 | ||||
|     if ! wget -q -O "$WORK_DIR/mc" https://dl.minio.io/client/mc/release/linux-amd64/mc; then | ||||
|         echo "failed to download https://dl.minio.io/client/mc/release/linux-amd64/mc" | ||||
|     if ! go get -u github.com/minio/mc; then | ||||
|         echo "failed to download https://github.com/minio/mc" | ||||
|         exit 1 | ||||
|     fi | ||||
|     /bin/cp -a "$(go env GOPATH)"/bin/mc "$WORK_DIR/mc" | ||||
| 
 | ||||
|     chmod a+x "$WORK_DIR/mc" | ||||
| 
 | ||||
|  |  | |||
|  | @ -46,7 +46,7 @@ func TestServerConfigMigrateV1(t *testing.T) { | |||
| 		t.Fatal("Unexpected error: ", err) | ||||
| 	} | ||||
| 	// Check if config v1 is removed from filesystem
 | ||||
| 	if _, err := osStat(configPath); err == nil || !os.IsNotExist(err) { | ||||
| 	if _, err := os.Stat(configPath); err == nil || !os.IsNotExist(err) { | ||||
| 		t.Fatal("Config V1 file is not purged") | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
|  | @ -133,7 +133,7 @@ func fsStat(statLoc string) (os.FileInfo, error) { | |||
| 	if err := checkPathLength(statLoc); err != nil { | ||||
| 		return nil, traceError(err) | ||||
| 	} | ||||
| 	fi, err := osStat((statLoc)) | ||||
| 	fi, err := os.Stat((statLoc)) | ||||
| 	if err != nil { | ||||
| 		return nil, traceError(err) | ||||
| 	} | ||||
|  | @ -211,7 +211,7 @@ func fsOpenFile(readPath string, offset int64) (io.ReadCloser, int64, error) { | |||
| 	} | ||||
| 
 | ||||
| 	// Stat to get the size of the file at path.
 | ||||
| 	st, err := osStat((readPath)) | ||||
| 	st, err := os.Stat((readPath)) | ||||
| 	if err != nil { | ||||
| 		return nil, 0, traceError(err) | ||||
| 	} | ||||
|  |  | |||
|  | @ -538,11 +538,11 @@ func TestFSRemoveMeta(t *testing.T) { | |||
| 		t.Fatalf("Unable to remove file, %s", err) | ||||
| 	} | ||||
| 
 | ||||
| 	if _, err := osStat((filePath)); !os.IsNotExist(err) { | ||||
| 	if _, err := os.Stat((filePath)); !os.IsNotExist(err) { | ||||
| 		t.Fatalf("`%s` file found though it should have been deleted.", filePath) | ||||
| 	} | ||||
| 
 | ||||
| 	if _, err := osStat((path.Dir(filePath))); !os.IsNotExist(err) { | ||||
| 	if _, err := os.Stat((path.Dir(filePath))); !os.IsNotExist(err) { | ||||
| 		t.Fatalf("`%s` parent directory found though it should have been deleted.", filePath) | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -86,7 +86,7 @@ func newFSObjectLayer(fsPath string) (ObjectLayer, error) { | |||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	fi, err := osStat((fsPath)) | ||||
| 	fi, err := os.Stat((fsPath)) | ||||
| 	if err == nil { | ||||
| 		if !fi.IsDir() { | ||||
| 			return nil, syscall.ENOTDIR | ||||
|  | @ -230,7 +230,7 @@ func (fs fsObjects) GetBucketInfo(bucket string) (bi BucketInfo, e error) { | |||
| 		return bi, toObjectErr(err, bucket) | ||||
| 	} | ||||
| 
 | ||||
| 	// As osStat() doesn't carry other than ModTime(), use ModTime() as CreatedTime.
 | ||||
| 	// As os.Stat() doesn't carry other than ModTime(), use ModTime() as CreatedTime.
 | ||||
| 	createdTime := st.ModTime() | ||||
| 	return BucketInfo{ | ||||
| 		Name:    bucket, | ||||
|  | @ -266,7 +266,7 @@ func (fs fsObjects) ListBuckets() ([]BucketInfo, error) { | |||
| 		} | ||||
| 		bucketInfos = append(bucketInfos, BucketInfo{ | ||||
| 			Name: fi.Name(), | ||||
| 			// As osStat() doesnt carry CreatedTime, use ModTime() as CreatedTime.
 | ||||
| 			// As os.Stat() doesnt carry CreatedTime, use ModTime() as CreatedTime.
 | ||||
| 			Created: fi.ModTime(), | ||||
| 		}) | ||||
| 	} | ||||
|  |  | |||
|  | @ -22,9 +22,10 @@ import ( | |||
| 	"sync" | ||||
| 
 | ||||
| 	"fmt" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/minio/dsync" | ||||
| 	"github.com/minio/lsync" | ||||
| 	"time" | ||||
| ) | ||||
| 
 | ||||
| // Global name space lock.
 | ||||
|  |  | |||
|  | @ -75,12 +75,12 @@ func parseDirents(dirPath string, buf []byte) (entries []string, err error) { | |||
| 		case syscall.DT_REG: | ||||
| 			entries = append(entries, name) | ||||
| 		case syscall.DT_LNK, syscall.DT_UNKNOWN: | ||||
| 			// If its symbolic link, follow the link using osStat()
 | ||||
| 			// If its symbolic link, follow the link using os.Stat()
 | ||||
| 
 | ||||
| 			// On Linux XFS does not implement d_type for on disk
 | ||||
| 			// format << v5. Fall back to OsStat().
 | ||||
| 			var fi os.FileInfo | ||||
| 			fi, err = osStat(path.Join(dirPath, name)) | ||||
| 			fi, err = os.Stat(path.Join(dirPath, name)) | ||||
| 			if err != nil { | ||||
| 				// If file does not exist, we continue and skip it.
 | ||||
| 				// Could happen if it was deleted in the middle while
 | ||||
|  |  | |||
|  | @ -55,7 +55,7 @@ func readDir(dirPath string) (entries []string, err error) { | |||
| 			// Stat symbolic link and follow to get the final value.
 | ||||
| 			if fi.Mode()&os.ModeSymlink == os.ModeSymlink { | ||||
| 				var st os.FileInfo | ||||
| 				st, err = osStat((path.Join(dirPath, fi.Name()))) | ||||
| 				st, err = os.Stat((path.Join(dirPath, fi.Name()))) | ||||
| 				if err != nil { | ||||
| 					errorIf(err, "Unable to stat path %s", path.Join(dirPath, fi.Name())) | ||||
| 					continue | ||||
|  |  | |||
|  | @ -18,14 +18,6 @@ | |||
| 
 | ||||
| package cmd | ||||
| 
 | ||||
| import "os" | ||||
| 
 | ||||
| // osStat returns a FileInfo structure describing the named file.
 | ||||
| // If there is an error, it will be of type *PathError.
 | ||||
| func osStat(name string) (os.FileInfo, error) { | ||||
| 	return os.Stat(name) | ||||
| } | ||||
| 
 | ||||
| // isValidVolname verifies a volname name in accordance with object
 | ||||
| // layer requirements.
 | ||||
| func isValidVolname(volname string) bool { | ||||
|  |  | |||
|  | @ -62,7 +62,7 @@ func TestIsValidUmaskVol(t *testing.T) { | |||
| 	defer os.RemoveAll(tmpPath) | ||||
| 
 | ||||
| 	// Stat to get permissions bits.
 | ||||
| 	st, err := osStat(path.Join(tmpPath, testCase.volName)) | ||||
| 	st, err := os.Stat(path.Join(tmpPath, testCase.volName)) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("Stat failed with %s expected to pass.", err) | ||||
| 	} | ||||
|  |  | |||
|  | @ -19,17 +19,9 @@ | |||
| package cmd | ||||
| 
 | ||||
| import ( | ||||
| 	"os" | ||||
| 	"strings" | ||||
| 
 | ||||
| 	os2 "github.com/minio/minio/pkg/x/os" | ||||
| ) | ||||
| 
 | ||||
| // Wrapper around safe stat implementation to avoid windows bugs.
 | ||||
| func osStat(name string) (os.FileInfo, error) { | ||||
| 	return os2.Stat(name) | ||||
| } | ||||
| 
 | ||||
| // isValidVolname verifies a volname name in accordance with object
 | ||||
| // layer requirements.
 | ||||
| func isValidVolname(volname string) bool { | ||||
|  |  | |||
							
								
								
									
										34
									
								
								cmd/posix.go
								
								
								
								
							
							
						
						
									
										34
									
								
								cmd/posix.go
								
								
								
								
							|  | @ -113,7 +113,7 @@ func newPosix(path string) (StorageAPI, error) { | |||
| 			}, | ||||
| 		}, | ||||
| 	} | ||||
| 	fi, err := osStat((diskPath)) | ||||
| 	fi, err := os.Stat((diskPath)) | ||||
| 	if err == nil { | ||||
| 		if !fi.IsDir() { | ||||
| 			return nil, syscall.ENOTDIR | ||||
|  | @ -249,7 +249,7 @@ func (s *posix) getVolDir(volume string) (string, error) { | |||
| // checkDiskFound - validates if disk is available,
 | ||||
| // returns errDiskNotFound if not found.
 | ||||
| func (s *posix) checkDiskFound() (err error) { | ||||
| 	_, err = osStat((s.diskPath)) | ||||
| 	_, err = os.Stat((s.diskPath)) | ||||
| 	if err != nil { | ||||
| 		if os.IsNotExist(err) { | ||||
| 			return errDiskNotFound | ||||
|  | @ -340,7 +340,7 @@ func listVols(dirPath string) ([]VolInfo, error) { | |||
| 			continue | ||||
| 		} | ||||
| 		var fi os.FileInfo | ||||
| 		fi, err = osStat((pathJoin(dirPath, entry))) | ||||
| 		fi, err = os.Stat((pathJoin(dirPath, entry))) | ||||
| 		if err != nil { | ||||
| 			// If the file does not exist, skip the entry.
 | ||||
| 			if os.IsNotExist(err) { | ||||
|  | @ -350,7 +350,7 @@ func listVols(dirPath string) ([]VolInfo, error) { | |||
| 		} | ||||
| 		volsInfo = append(volsInfo, VolInfo{ | ||||
| 			Name: fi.Name(), | ||||
| 			// As osStat() doesn't carry other than ModTime(), use
 | ||||
| 			// As os.Stat() doesn't carry other than ModTime(), use
 | ||||
| 			// ModTime() as CreatedTime.
 | ||||
| 			Created: fi.ModTime(), | ||||
| 		}) | ||||
|  | @ -381,14 +381,14 @@ func (s *posix) StatVol(volume string) (volInfo VolInfo, err error) { | |||
| 	} | ||||
| 	// Stat a volume entry.
 | ||||
| 	var st os.FileInfo | ||||
| 	st, err = osStat((volumeDir)) | ||||
| 	st, err = os.Stat((volumeDir)) | ||||
| 	if err != nil { | ||||
| 		if os.IsNotExist(err) { | ||||
| 			return VolInfo{}, errVolumeNotFound | ||||
| 		} | ||||
| 		return VolInfo{}, err | ||||
| 	} | ||||
| 	// As osStat() doesn't carry other than ModTime(), use ModTime()
 | ||||
| 	// As os.Stat() doesn't carry other than ModTime(), use ModTime()
 | ||||
| 	// as CreatedTime.
 | ||||
| 	createdTime := st.ModTime() | ||||
| 	return VolInfo{ | ||||
|  | @ -453,7 +453,7 @@ func (s *posix) ListDir(volume, dirPath string) (entries []string, err error) { | |||
| 		return nil, err | ||||
| 	} | ||||
| 	// Stat a volume entry.
 | ||||
| 	_, err = osStat((volumeDir)) | ||||
| 	_, err = os.Stat((volumeDir)) | ||||
| 	if err != nil { | ||||
| 		if os.IsNotExist(err) { | ||||
| 			return nil, errVolumeNotFound | ||||
|  | @ -489,7 +489,7 @@ func (s *posix) ReadAll(volume, path string) (buf []byte, err error) { | |||
| 		return nil, err | ||||
| 	} | ||||
| 	// Stat a volume entry.
 | ||||
| 	_, err = osStat((volumeDir)) | ||||
| 	_, err = os.Stat((volumeDir)) | ||||
| 	if err != nil { | ||||
| 		if os.IsNotExist(err) { | ||||
| 			return nil, errVolumeNotFound | ||||
|  | @ -560,7 +560,7 @@ func (s *posix) ReadFile(volume, path string, offset int64, buffer []byte, verif | |||
| 		return 0, err | ||||
| 	} | ||||
| 	// Stat a volume entry.
 | ||||
| 	_, err = osStat((volumeDir)) | ||||
| 	_, err = os.Stat((volumeDir)) | ||||
| 	if err != nil { | ||||
| 		if os.IsNotExist(err) { | ||||
| 			return 0, errVolumeNotFound | ||||
|  | @ -652,7 +652,7 @@ func (s *posix) createFile(volume, path string) (f *os.File, err error) { | |||
| 		return nil, err | ||||
| 	} | ||||
| 	// Stat a volume entry.
 | ||||
| 	_, err = osStat((volumeDir)) | ||||
| 	_, err = os.Stat((volumeDir)) | ||||
| 	if err != nil { | ||||
| 		if os.IsNotExist(err) { | ||||
| 			return nil, errVolumeNotFound | ||||
|  | @ -667,7 +667,7 @@ func (s *posix) createFile(volume, path string) (f *os.File, err error) { | |||
| 
 | ||||
| 	// Verify if the file already exists and is not of regular type.
 | ||||
| 	var st os.FileInfo | ||||
| 	if st, err = osStat((filePath)); err == nil { | ||||
| 	if st, err = os.Stat((filePath)); err == nil { | ||||
| 		if !st.Mode().IsRegular() { | ||||
| 			return nil, errIsNotRegular | ||||
| 		} | ||||
|  | @ -794,7 +794,7 @@ func (s *posix) StatFile(volume, path string) (file FileInfo, err error) { | |||
| 		return FileInfo{}, err | ||||
| 	} | ||||
| 	// Stat a volume entry.
 | ||||
| 	_, err = osStat((volumeDir)) | ||||
| 	_, err = os.Stat((volumeDir)) | ||||
| 	if err != nil { | ||||
| 		if os.IsNotExist(err) { | ||||
| 			return FileInfo{}, errVolumeNotFound | ||||
|  | @ -806,7 +806,7 @@ func (s *posix) StatFile(volume, path string) (file FileInfo, err error) { | |||
| 	if err = checkPathLength((filePath)); err != nil { | ||||
| 		return FileInfo{}, err | ||||
| 	} | ||||
| 	st, err := osStat((filePath)) | ||||
| 	st, err := os.Stat((filePath)) | ||||
| 	if err != nil { | ||||
| 		// File is really not found.
 | ||||
| 		if os.IsNotExist(err) { | ||||
|  | @ -887,7 +887,7 @@ func (s *posix) DeleteFile(volume, path string) (err error) { | |||
| 		return err | ||||
| 	} | ||||
| 	// Stat a volume entry.
 | ||||
| 	_, err = osStat((volumeDir)) | ||||
| 	_, err = os.Stat((volumeDir)) | ||||
| 	if err != nil { | ||||
| 		if os.IsNotExist(err) { | ||||
| 			return errVolumeNotFound | ||||
|  | @ -931,14 +931,14 @@ func (s *posix) RenameFile(srcVolume, srcPath, dstVolume, dstPath string) (err e | |||
| 		return err | ||||
| 	} | ||||
| 	// Stat a volume entry.
 | ||||
| 	_, err = osStat((srcVolumeDir)) | ||||
| 	_, err = os.Stat((srcVolumeDir)) | ||||
| 	if err != nil { | ||||
| 		if os.IsNotExist(err) { | ||||
| 			return errVolumeNotFound | ||||
| 		} | ||||
| 		return err | ||||
| 	} | ||||
| 	_, err = osStat((dstVolumeDir)) | ||||
| 	_, err = os.Stat((dstVolumeDir)) | ||||
| 	if err != nil { | ||||
| 		if os.IsNotExist(err) { | ||||
| 			return errVolumeNotFound | ||||
|  | @ -961,7 +961,7 @@ func (s *posix) RenameFile(srcVolume, srcPath, dstVolume, dstPath string) (err e | |||
| 	} | ||||
| 	if srcIsDir { | ||||
| 		// If source is a directory we expect the destination to be non-existent always.
 | ||||
| 		_, err = osStat((dstFilePath)) | ||||
| 		_, err = os.Stat((dstFilePath)) | ||||
| 		if err == nil { | ||||
| 			return errFileAccessDenied | ||||
| 		} | ||||
|  |  | |||
|  | @ -110,8 +110,9 @@ func getModTime(path string) (t time.Time, err error) { | |||
| 		return t, fmt.Errorf("Unable to get absolute path of %s. %s", path, err) | ||||
| 	} | ||||
| 
 | ||||
| 	// Get Stat info
 | ||||
| 	fi, err := osStat(absPath) | ||||
| 	// Version is minio non-standard, we will use minio binary's
 | ||||
| 	// ModTime as release time.
 | ||||
| 	fi, err := os.Stat(absPath) | ||||
| 	if err != nil { | ||||
| 		return t, fmt.Errorf("Unable to get ModTime of %s. %s", absPath, err) | ||||
| 	} | ||||
|  | @ -141,7 +142,7 @@ func GetCurrentReleaseTime() (releaseTime time.Time, err error) { | |||
| //     "/.dockerenv":      "file",
 | ||||
| //
 | ||||
| func IsDocker() bool { | ||||
| 	_, err := osStat("/.dockerenv") | ||||
| 	_, err := os.Stat("/.dockerenv") | ||||
| 	if os.IsNotExist(err) { | ||||
| 		return false | ||||
| 	} | ||||
|  |  | |||
|  | @ -26,6 +26,7 @@ import ( | |||
| 	"io" | ||||
| 	"net/http" | ||||
| 	"net/url" | ||||
| 	"os" | ||||
| 	"strings" | ||||
| 	"time" | ||||
| 
 | ||||
|  | @ -187,7 +188,7 @@ func dumpRequest(r *http.Request) string { | |||
| 
 | ||||
| // isFile - returns whether given path is a file or not.
 | ||||
| func isFile(path string) bool { | ||||
| 	if fi, err := osStat(path); err == nil { | ||||
| 	if fi, err := os.Stat(path); err == nil { | ||||
| 		return fi.Mode().IsRegular() | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
|  | @ -19,10 +19,9 @@ | |||
| package disk | ||||
| 
 | ||||
| import ( | ||||
| 	"os" | ||||
| 	"syscall" | ||||
| 	"unsafe" | ||||
| 
 | ||||
| 	os2 "github.com/minio/minio/pkg/x/os" | ||||
| ) | ||||
| 
 | ||||
| var ( | ||||
|  | @ -44,7 +43,7 @@ var ( | |||
| // https://msdn.microsoft.com/en-us/library/windows/desktop/aa364937(v=vs.85).aspx
 | ||||
| func GetInfo(path string) (info Info, err error) { | ||||
| 	// Stat to know if the path exists.
 | ||||
| 	if _, err = os2.Stat(path); err != nil { | ||||
| 	if _, err = os.Stat(path); err != nil { | ||||
| 		return Info{}, err | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
|  | @ -24,8 +24,6 @@ import ( | |||
| 	"path/filepath" | ||||
| 	"syscall" | ||||
| 	"unsafe" | ||||
| 
 | ||||
| 	os2 "github.com/minio/minio/pkg/x/os" | ||||
| ) | ||||
| 
 | ||||
| var ( | ||||
|  | @ -54,7 +52,7 @@ func lockedOpenFile(path string, flag int, perm os.FileMode, lockType uint32) (* | |||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	st, err := os2.Stat(path) | ||||
| 	st, err := os.Stat(path) | ||||
| 	if err != nil { | ||||
| 		f.Close() | ||||
| 		return nil, err | ||||
|  |  | |||
|  | @ -23,11 +23,11 @@ import ( | |||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"io/ioutil" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
| 	"runtime" | ||||
| 	"strings" | ||||
| 
 | ||||
| 	os2 "github.com/minio/minio/pkg/x/os" | ||||
| 	yaml "gopkg.in/yaml.v2" | ||||
| ) | ||||
| 
 | ||||
|  | @ -126,7 +126,7 @@ func saveFileConfig(filename string, v interface{}) error { | |||
| // decoder format according to the filename extension. If no
 | ||||
| // extension is provided, json will be selected by default.
 | ||||
| func loadFileConfig(filename string, v interface{}) error { | ||||
| 	if _, err := os2.Stat(filename); err != nil { | ||||
| 	if _, err := os.Stat(filename); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	fileData, err := ioutil.ReadFile(filename) | ||||
|  |  | |||
|  | @ -21,8 +21,6 @@ import ( | |||
| 	"os" | ||||
| 	"path" | ||||
| 	"testing" | ||||
| 
 | ||||
| 	os2 "github.com/minio/minio/pkg/x/os" | ||||
| ) | ||||
| 
 | ||||
| type MySuite struct { | ||||
|  | @ -54,7 +52,7 @@ func TestSafeAbort(t *testing.T) { | |||
| 		t.Fatal(err) | ||||
| 	} | ||||
| 
 | ||||
| 	_, err = os2.Stat(path.Join(s.root, "testfile-abort")) | ||||
| 	_, err = os.Stat(path.Join(s.root, "testfile-abort")) | ||||
| 	if !os.IsNotExist(err) { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
|  | @ -80,7 +78,7 @@ func TestSafeClose(t *testing.T) { | |||
| 		t.Fatal(err) | ||||
| 	} | ||||
| 
 | ||||
| 	_, err = os2.Stat(path.Join(s.root, "testfile-close")) | ||||
| 	_, err = os.Stat(path.Join(s.root, "testfile-close")) | ||||
| 	if !os.IsNotExist(err) { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
|  | @ -90,7 +88,7 @@ func TestSafeClose(t *testing.T) { | |||
| 		t.Fatal(err) | ||||
| 	} | ||||
| 
 | ||||
| 	_, err = os2.Stat(path.Join(s.root, "testfile-close")) | ||||
| 	_, err = os.Stat(path.Join(s.root, "testfile-close")) | ||||
| 	if err != nil { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
|  | @ -118,7 +116,7 @@ func TestSafe(t *testing.T) { | |||
| 		t.Fatal(err) | ||||
| 	} | ||||
| 
 | ||||
| 	_, err = os2.Stat(path.Join(s.root, "testfile-safe")) | ||||
| 	_, err = os.Stat(path.Join(s.root, "testfile-safe")) | ||||
| 	if !os.IsNotExist(err) { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
|  | @ -142,7 +140,7 @@ func TestSafe(t *testing.T) { | |||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	_, err = os2.Stat(path.Join(s.root, "testfile-safe")) | ||||
| 	_, err = os.Stat(path.Join(s.root, "testfile-safe")) | ||||
| 	if err != nil { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
|  | @ -163,7 +161,7 @@ func TestSafeAbortWrite(t *testing.T) { | |||
| 		t.Fatal(err) | ||||
| 	} | ||||
| 
 | ||||
| 	_, err = os2.Stat(path.Join(s.root, "purgefile-abort")) | ||||
| 	_, err = os.Stat(path.Join(s.root, "purgefile-abort")) | ||||
| 	if !os.IsNotExist(err) { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
|  | @ -173,7 +171,7 @@ func TestSafeAbortWrite(t *testing.T) { | |||
| 		t.Fatal(err) | ||||
| 	} | ||||
| 
 | ||||
| 	_, err = os2.Stat(path.Join(s.root, "purgefile-abort")) | ||||
| 	_, err = os.Stat(path.Join(s.root, "purgefile-abort")) | ||||
| 	if !os.IsNotExist(err) { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
|  |  | |||
|  | @ -1,28 +0,0 @@ | |||
| // +build !windows
 | ||||
| 
 | ||||
| /* | ||||
|  * Minio Cloud Storage, (C) 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. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  *     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| package os | ||||
| 
 | ||||
| import os1 "os" | ||||
| 
 | ||||
| // Stat returns a FileInfo structure describing the
 | ||||
| // named file. If there is an error, it will be of type
 | ||||
| // *PathError.
 | ||||
| func Stat(name string) (os1.FileInfo, error) { | ||||
| 	return os1.Stat(name) | ||||
| } | ||||
|  | @ -1,268 +0,0 @@ | |||
| // +build windows
 | ||||
| 
 | ||||
| /* | ||||
|  * Minio Cloud Storage, (C) 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. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  *     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| // FIXME: Once we have a go version released with the
 | ||||
| // following fix https://go-review.googlesource.com/#/c/41834/.
 | ||||
| // We should actively purge this block.
 | ||||
| 
 | ||||
| // Copyright 2009 The Go Authors. All rights reserved.
 | ||||
| // Use of this source code is governed by a BSD-style
 | ||||
| // license that can be found in the LICENSE file.
 | ||||
| 
 | ||||
| // Package os implements extended safe functions
 | ||||
| // for stdlib "os".
 | ||||
| package os | ||||
| 
 | ||||
| import ( | ||||
| 	os1 "os" | ||||
| 	"path/filepath" | ||||
| 	"syscall" | ||||
| 	"time" | ||||
| ) | ||||
| 
 | ||||
| const errSharingViolation syscall.Errno = 32 | ||||
| 
 | ||||
| // fixLongPath returns the extended-length (\\?\-prefixed) form of
 | ||||
| // path when needed, in order to avoid the default 260 character file
 | ||||
| // path limit imposed by Windows. If path is not easily converted to
 | ||||
| // the extended-length form (for example, if path is a relative path
 | ||||
| // or contains .. elements), or is short enough, fixLongPath returns
 | ||||
| // path unmodified.
 | ||||
| //
 | ||||
| // See https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx#maxpath
 | ||||
| func fixLongPath(path string) string { | ||||
| 	// Do nothing (and don't allocate) if the path is "short".
 | ||||
| 	// Empirically (at least on the Windows Server 2013 builder),
 | ||||
| 	// the kernel is arbitrarily okay with < 248 bytes. That
 | ||||
| 	// matches what the docs above say:
 | ||||
| 	// "When using an API to create a directory, the specified
 | ||||
| 	// path cannot be so long that you cannot append an 8.3 file
 | ||||
| 	// name (that is, the directory name cannot exceed MAX_PATH
 | ||||
| 	// minus 12)." Since MAX_PATH is 260, 260 - 12 = 248.
 | ||||
| 	//
 | ||||
| 	// The MSDN docs appear to say that a normal path that is 248 bytes long
 | ||||
| 	// will work; empirically the path must be less then 248 bytes long.
 | ||||
| 	if len(path) < 248 { | ||||
| 		// Don't fix. (This is how Go 1.7 and earlier worked,
 | ||||
| 		// not automatically generating the \\?\ form)
 | ||||
| 		return path | ||||
| 	} | ||||
| 
 | ||||
| 	// The extended form begins with \\?\, as in
 | ||||
| 	// \\?\c:\windows\foo.txt or \\?\UNC\server\share\foo.txt.
 | ||||
| 	// The extended form disables evaluation of . and .. path
 | ||||
| 	// elements and disables the interpretation of / as equivalent
 | ||||
| 	// to \. The conversion here rewrites / to \ and elides
 | ||||
| 	// . elements as well as trailing or duplicate separators. For
 | ||||
| 	// simplicity it avoids the conversion entirely for relative
 | ||||
| 	// paths or paths containing .. elements. For now,
 | ||||
| 	// \\server\share paths are not converted to
 | ||||
| 	// \\?\UNC\server\share paths because the rules for doing so
 | ||||
| 	// are less well-specified.
 | ||||
| 	if len(path) >= 2 && path[:2] == `\\` { | ||||
| 		// Don't canonicalize UNC paths.
 | ||||
| 		return path | ||||
| 	} | ||||
| 	if !filepath.IsAbs(path) { | ||||
| 		// Relative path
 | ||||
| 		return path | ||||
| 	} | ||||
| 
 | ||||
| 	const prefix = `\\?` | ||||
| 
 | ||||
| 	pathbuf := make([]byte, len(prefix)+len(path)+len(`\`)) | ||||
| 	copy(pathbuf, prefix) | ||||
| 	n := len(path) | ||||
| 	r, w := 0, len(prefix) | ||||
| 	for r < n { | ||||
| 		switch { | ||||
| 		case os1.IsPathSeparator(path[r]): | ||||
| 			// empty block
 | ||||
| 			r++ | ||||
| 		case path[r] == '.' && (r+1 == n || os1.IsPathSeparator(path[r+1])): | ||||
| 			// /./
 | ||||
| 			r++ | ||||
| 		case r+1 < n && path[r] == '.' && path[r+1] == '.' && (r+2 == n || os1.IsPathSeparator(path[r+2])): | ||||
| 			// /../ is currently unhandled
 | ||||
| 			return path | ||||
| 		default: | ||||
| 			pathbuf[w] = '\\' | ||||
| 			w++ | ||||
| 			for ; r < n && !os1.IsPathSeparator(path[r]); r++ { | ||||
| 				pathbuf[w] = path[r] | ||||
| 				w++ | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	// A drive's root directory needs a trailing \
 | ||||
| 	if w == len(`\\?\c:`) { | ||||
| 		pathbuf[w] = '\\' | ||||
| 		w++ | ||||
| 	} | ||||
| 	return string(pathbuf[:w]) | ||||
| } | ||||
| 
 | ||||
| // Stat returns a FileInfo structure describing the
 | ||||
| // named file. If there is an error, it will be of type
 | ||||
| // *PathError.
 | ||||
| func Stat(name string) (os1.FileInfo, error) { | ||||
| 	if len(name) == 0 { | ||||
| 		return nil, &os1.PathError{ | ||||
| 			Op:   "Stat", | ||||
| 			Path: name, | ||||
| 			Err:  syscall.Errno(syscall.ERROR_PATH_NOT_FOUND), | ||||
| 		} | ||||
| 	} | ||||
| 	if name == os1.DevNull { | ||||
| 		return &devNullStat, nil | ||||
| 	} | ||||
| 	namep, err := syscall.UTF16PtrFromString(fixLongPath(name)) | ||||
| 	if err != nil { | ||||
| 		return nil, &os1.PathError{Op: "Stat", Path: name, Err: err} | ||||
| 	} | ||||
| 
 | ||||
| 	// Use Windows I/O manager to dereference the symbolic link, as per
 | ||||
| 	// https://blogs.msdn.microsoft.com/oldnewthing/20100212-00/?p=14963/
 | ||||
| 	h, err := syscall.CreateFile(namep, 0, 0, nil, | ||||
| 		syscall.OPEN_EXISTING, syscall.FILE_FLAG_BACKUP_SEMANTICS, 0) | ||||
| 	if err != nil { | ||||
| 		if err == errSharingViolation { | ||||
| 			// try FindFirstFile now that CreateFile failed
 | ||||
| 			return statWithFindFirstFile(name, namep) | ||||
| 		} | ||||
| 		return nil, &os1.PathError{Op: "CreateFile", Path: name, Err: err} | ||||
| 	} | ||||
| 	defer syscall.CloseHandle(h) | ||||
| 
 | ||||
| 	var d syscall.ByHandleFileInformation | ||||
| 	if err = syscall.GetFileInformationByHandle(h, &d); err != nil { | ||||
| 		return nil, &os1.PathError{ | ||||
| 			Op:   "GetFileInformationByHandle", | ||||
| 			Path: name, | ||||
| 			Err:  err, | ||||
| 		} | ||||
| 	} | ||||
| 	return &fileStat{ | ||||
| 		name: filepath.Base(name), | ||||
| 		sys: syscall.Win32FileAttributeData{ | ||||
| 			FileAttributes: d.FileAttributes, | ||||
| 			CreationTime:   d.CreationTime, | ||||
| 			LastAccessTime: d.LastAccessTime, | ||||
| 			LastWriteTime:  d.LastWriteTime, | ||||
| 			FileSizeHigh:   d.FileSizeHigh, | ||||
| 			FileSizeLow:    d.FileSizeLow, | ||||
| 		}, | ||||
| 		vol:   d.VolumeSerialNumber, | ||||
| 		idxhi: d.FileIndexHigh, | ||||
| 		idxlo: d.FileIndexLow, | ||||
| 		// fileStat.path is used by os1.SameFile to decide, if it needs
 | ||||
| 		// to fetch vol, idxhi and idxlo. But these are already set,
 | ||||
| 		// so set fileStat.path to "" to prevent os1.SameFile doing it again.
 | ||||
| 		// Also do not set fileStat.filetype, because it is only used for
 | ||||
| 		// console and stdin/stdout. But you cannot call os1.Stat for these.
 | ||||
| 	}, nil | ||||
| } | ||||
| 
 | ||||
| // statWithFindFirstFile is used by Stat to handle special case of stating
 | ||||
| // c:\pagefile.sys. We might discovered other files need similar treatment.
 | ||||
| func statWithFindFirstFile(name string, namep *uint16) (os1.FileInfo, error) { | ||||
| 	var fd syscall.Win32finddata | ||||
| 	h, err := syscall.FindFirstFile(namep, &fd) | ||||
| 	if err != nil { | ||||
| 		return nil, &os1.PathError{Op: "FindFirstFile", Path: name, Err: err} | ||||
| 	} | ||||
| 	syscall.FindClose(h) | ||||
| 
 | ||||
| 	fullpath := name | ||||
| 	if !filepath.IsAbs(fullpath) { | ||||
| 		fullpath, err = syscall.FullPath(fullpath) | ||||
| 		if err != nil { | ||||
| 			return nil, &os1.PathError{Op: "FullPath", Path: name, Err: err} | ||||
| 		} | ||||
| 	} | ||||
| 	return &fileStat{ | ||||
| 		name: filepath.Base(name), | ||||
| 		path: fullpath, | ||||
| 		sys: syscall.Win32FileAttributeData{ | ||||
| 			FileAttributes: fd.FileAttributes, | ||||
| 			CreationTime:   fd.CreationTime, | ||||
| 			LastAccessTime: fd.LastAccessTime, | ||||
| 			LastWriteTime:  fd.LastWriteTime, | ||||
| 			FileSizeHigh:   fd.FileSizeHigh, | ||||
| 			FileSizeLow:    fd.FileSizeLow, | ||||
| 		}, | ||||
| 	}, nil | ||||
| } | ||||
| 
 | ||||
| // A fileStat is the implementation of os1.FileInfo returned by stat.
 | ||||
| type fileStat struct { | ||||
| 	name     string | ||||
| 	sys      syscall.Win32FileAttributeData | ||||
| 	filetype uint32 // what syscall.GetFileType returns
 | ||||
| 
 | ||||
| 	path  string | ||||
| 	vol   uint32 | ||||
| 	idxhi uint32 | ||||
| 	idxlo uint32 | ||||
| } | ||||
| 
 | ||||
| func (fs *fileStat) Name() string { return fs.name } | ||||
| func (fs *fileStat) IsDir() bool  { return fs.Mode().IsDir() } | ||||
| 
 | ||||
| func (fs *fileStat) Size() int64 { | ||||
| 	return int64(fs.sys.FileSizeHigh)<<32 + int64(fs.sys.FileSizeLow) | ||||
| } | ||||
| 
 | ||||
| // devNullStat is fileStat structure describing DevNull file ("NUL").
 | ||||
| var devNullStat = fileStat{ | ||||
| 	name:  os1.DevNull, | ||||
| 	vol:   0, | ||||
| 	idxhi: 0, | ||||
| 	idxlo: 0, | ||||
| } | ||||
| 
 | ||||
| func (fs *fileStat) Mode() (m os1.FileMode) { | ||||
| 	if fs == &devNullStat { | ||||
| 		return os1.ModeDevice | os1.ModeCharDevice | 0666 | ||||
| 	} | ||||
| 	if fs.sys.FileAttributes&syscall.FILE_ATTRIBUTE_READONLY != 0 { | ||||
| 		m |= 0444 | ||||
| 	} else { | ||||
| 		m |= 0666 | ||||
| 	} | ||||
| 	if fs.sys.FileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT != 0 { | ||||
| 		return m | os1.ModeSymlink | ||||
| 	} | ||||
| 	if fs.sys.FileAttributes&syscall.FILE_ATTRIBUTE_DIRECTORY != 0 { | ||||
| 		m |= os1.ModeDir | 0111 | ||||
| 	} | ||||
| 	switch fs.filetype { | ||||
| 	case syscall.FILE_TYPE_PIPE: | ||||
| 		m |= os1.ModeNamedPipe | ||||
| 	case syscall.FILE_TYPE_CHAR: | ||||
| 		m |= os1.ModeCharDevice | ||||
| 	} | ||||
| 	return m | ||||
| } | ||||
| 
 | ||||
| func (fs *fileStat) ModTime() time.Time { | ||||
| 	return time.Unix(0, fs.sys.LastWriteTime.Nanoseconds()) | ||||
| } | ||||
| 
 | ||||
| // Sys returns syscall.Win32FileAttributeData for file fs.
 | ||||
| func (fs *fileStat) Sys() interface{} { return &fs.sys } | ||||
|  | @ -1,245 +0,0 @@ | |||
| // +build windows
 | ||||
| 
 | ||||
| /* | ||||
|  * Minio Cloud Storage, (C) 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. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  *     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| package os | ||||
| 
 | ||||
| import ( | ||||
| 	"io/ioutil" | ||||
| 	os1 "os" | ||||
| 	"path/filepath" | ||||
| 	"strings" | ||||
| 	"syscall" | ||||
| 	"testing" | ||||
| 	"unsafe" | ||||
| ) | ||||
| 
 | ||||
| var ( | ||||
| 	modnetapi32 = syscall.NewLazyDLL("netapi32.dll") | ||||
| 
 | ||||
| 	procNetShareAdd = modnetapi32.NewProc("NetShareAdd") | ||||
| 	procNetShareDel = modnetapi32.NewProc("NetShareDel") | ||||
| ) | ||||
| 
 | ||||
| func netShareAdd(serverName *uint16, level uint32, buf *byte, parmErr *uint16) (neterr error) { | ||||
| 	r0, _, _ := syscall.Syscall6(procNetShareAdd.Addr(), 4, uintptr(unsafe.Pointer(serverName)), uintptr(level), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(parmErr)), 0, 0) | ||||
| 	if r0 != 0 { | ||||
| 		neterr = syscall.Errno(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func netShareDel(serverName *uint16, netName *uint16, reserved uint32) (neterr error) { | ||||
| 	r0, _, _ := syscall.Syscall(procNetShareDel.Addr(), 3, uintptr(unsafe.Pointer(serverName)), uintptr(unsafe.Pointer(netName)), uintptr(reserved)) | ||||
| 	if r0 != 0 { | ||||
| 		neterr = syscall.Errno(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| type shareInfo2 struct { | ||||
| 	Netname     *uint16 | ||||
| 	Type        uint32 | ||||
| 	Remark      *uint16 | ||||
| 	Permissions uint32 | ||||
| 	MaxUses     uint32 | ||||
| 	CurrentUses uint32 | ||||
| 	Path        *uint16 | ||||
| 	Passwd      *uint16 | ||||
| } | ||||
| 
 | ||||
| func sameFile(fi1, fi2 os1.FileInfo) bool { | ||||
| 	fii1, ok1 := fi1.(*fileStat) | ||||
| 	fii2, ok2 := fi2.(*fileStat) | ||||
| 	if !ok1 || !ok2 { | ||||
| 		return false | ||||
| 	} | ||||
| 	return fii1.vol == fii2.vol && fii1.idxhi == fii2.idxhi && fii1.idxlo == fii2.idxlo | ||||
| } | ||||
| 
 | ||||
| func TestNetworkSymbolicLink(t *testing.T) { | ||||
| 	dir, err := ioutil.TempDir("", "TestNetworkSymbolicLink") | ||||
| 	if err != nil { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
| 	defer os1.RemoveAll(dir) | ||||
| 
 | ||||
| 	oldwd, err := os1.Getwd() | ||||
| 	if err != nil { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
| 	err = os1.Chdir(dir) | ||||
| 	if err != nil { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
| 	defer os1.Chdir(oldwd) | ||||
| 
 | ||||
| 	shareName := "GoSymbolicLinkTestShare" // hope no conflicts.
 | ||||
| 	sharePath := filepath.Join(dir, shareName) | ||||
| 	testDir := "TestDir" | ||||
| 
 | ||||
| 	err = os1.MkdirAll(filepath.Join(sharePath, testDir), 0777) | ||||
| 	if err != nil { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
| 
 | ||||
| 	wShareName, err := syscall.UTF16PtrFromString(shareName) | ||||
| 	if err != nil { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
| 	wSharePath, err := syscall.UTF16PtrFromString(sharePath) | ||||
| 	if err != nil { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
| 
 | ||||
| 	p := shareInfo2{ | ||||
| 		Netname:     wShareName, | ||||
| 		Type:        0x00, // STYPE_DISKTREE
 | ||||
| 		Remark:      nil, | ||||
| 		Permissions: 0, | ||||
| 		MaxUses:     1, | ||||
| 		CurrentUses: 0, | ||||
| 		Path:        wSharePath, | ||||
| 		Passwd:      nil, | ||||
| 	} | ||||
| 
 | ||||
| 	err = netShareAdd(nil, 2, (*byte)(unsafe.Pointer(&p)), nil) | ||||
| 	if err != nil { | ||||
| 		if err == syscall.ERROR_ACCESS_DENIED { | ||||
| 			t.Skip("you don't have enough privileges to add network share") | ||||
| 		} | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
| 	defer func() { | ||||
| 		err := netShareDel(nil, wShareName, 0) | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
| 	}() | ||||
| 
 | ||||
| 	UNCPath := `\\localhost\` + shareName + `\` | ||||
| 
 | ||||
| 	fi1, err := Stat(sharePath) | ||||
| 	if err != nil { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
| 	fi2, err := Stat(UNCPath) | ||||
| 	if err != nil { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
| 	if !sameFile(fi1, fi2) { | ||||
| 		t.Fatalf("%q and %q should be the same directory, but not", sharePath, UNCPath) | ||||
| 	} | ||||
| 
 | ||||
| 	target := filepath.Join(UNCPath, testDir) | ||||
| 	link := "link" | ||||
| 
 | ||||
| 	err = os1.Symlink(target, link) | ||||
| 	if err != nil { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
| 	defer os1.Remove(link) | ||||
| 
 | ||||
| 	got, err := os1.Readlink(link) | ||||
| 	if err != nil { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
| 
 | ||||
| 	if got != target { | ||||
| 		t.Errorf(`os1.Readlink("%s"): got %v, want %v`, link, got, target) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestShareNotExistError(t *testing.T) { | ||||
| 	if testing.Short() { | ||||
| 		t.Skip("slow test that uses network; skipping") | ||||
| 	} | ||||
| 	_, err := Stat(`\\no_such_server\no_such_share\no_such_file`) | ||||
| 	if err == nil { | ||||
| 		t.Fatal("Stat succeeded, but expected to fail") | ||||
| 	} | ||||
| 	if !os1.IsNotExist(err) { | ||||
| 		t.Fatalf("os1.Stat failed with %q, but os1.IsNotExist(err) is false", err) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestStatPagefile(t *testing.T) { | ||||
| 	_, err := Stat(`c:\pagefile.sys`) | ||||
| 	if err == nil { | ||||
| 		return | ||||
| 	} | ||||
| 	if os1.IsNotExist(err) { | ||||
| 		t.Skip(`skipping because c:\pagefile.sys is not found`) | ||||
| 	} | ||||
| 	t.Fatal(err) | ||||
| } | ||||
| 
 | ||||
| func TestStatSymlinkLoop(t *testing.T) { | ||||
| 	err := os1.Symlink("x", "y") | ||||
| 	if err != nil { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
| 	defer os1.Remove("y") | ||||
| 
 | ||||
| 	err = os1.Symlink("y", "x") | ||||
| 	if err != nil { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
| 	defer os1.Remove("x") | ||||
| 
 | ||||
| 	_, err = Stat("x") | ||||
| 	if err != nil { | ||||
| 		if _, ok := err.(*os1.PathError); !ok { | ||||
| 			t.Errorf("expected *PathError, got %T: %v\n", err, err) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestFixLongPath(t *testing.T) { | ||||
| 	// 248 is long enough to trigger the longer-than-248 checks in
 | ||||
| 	// fixLongPath, but short enough not to make a path component
 | ||||
| 	// longer than 255, which is illegal on Windows. (which
 | ||||
| 	// doesn't really matter anyway, since this is purely a string
 | ||||
| 	// function we're testing, and it's not actually being used to
 | ||||
| 	// do a system call)
 | ||||
| 	veryLong := "l" + strings.Repeat("o", 248) + "ng" | ||||
| 	for _, test := range []struct{ in, want string }{ | ||||
| 		// Short; unchanged:
 | ||||
| 		{`C:\short.txt`, `C:\short.txt`}, | ||||
| 		{`C:\`, `C:\`}, | ||||
| 		{`C:`, `C:`}, | ||||
| 		// The "long" substring is replaced by a looooooong
 | ||||
| 		// string which triggers the rewriting. Except in the
 | ||||
| 		// cases below where it doesn't.
 | ||||
| 		{`C:\long\foo.txt`, `\\?\C:\long\foo.txt`}, | ||||
| 		{`C:/long/foo.txt`, `\\?\C:\long\foo.txt`}, | ||||
| 		{`C:\long\foo\\bar\.\baz\\`, `\\?\C:\long\foo\bar\baz`}, | ||||
| 		{`\\unc\path`, `\\unc\path`}, | ||||
| 		{`long.txt`, `long.txt`}, | ||||
| 		{`C:long.txt`, `C:long.txt`}, | ||||
| 		{`c:\long\..\bar\baz`, `c:\long\..\bar\baz`}, | ||||
| 		{`\\?\c:\long\foo.txt`, `\\?\c:\long\foo.txt`}, | ||||
| 		{`\\?\c:\long/foo.txt`, `\\?\c:\long/foo.txt`}, | ||||
| 	} { | ||||
| 		in := strings.Replace(test.in, "long", veryLong, -1) | ||||
| 		want := strings.Replace(test.want, "long", veryLong, -1) | ||||
| 		if got := fixLongPath(in); got != want { | ||||
| 			got = strings.Replace(got, veryLong, "long", -1) | ||||
| 			t.Errorf("fixLongPath(%q) = %q; want %q", test.in, got, test.want) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
		Loading…
	
		Reference in New Issue