Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
go
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
go
Commits
c7482b91
Commit
c7482b91
authored
Feb 27, 2012
by
Alex Brainman
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
os: implement sameFile on windows
Fixes #2511. R=golang-dev, rsc CC=golang-dev
https://golang.org/cl/5687072
parent
e4db4e9b
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
193 additions
and
21 deletions
+193
-21
src/pkg/os/file_windows.go
src/pkg/os/file_windows.go
+13
-1
src/pkg/os/os_test.go
src/pkg/os/os_test.go
+35
-0
src/pkg/os/stat_windows.go
src/pkg/os/stat_windows.go
+145
-20
No files found.
src/pkg/os/file_windows.go
View file @
c7482b91
...
...
@@ -52,6 +52,7 @@ func NewFile(fd uintptr, name string) *File {
type
dirInfo
struct
{
data
syscall
.
Win32finddata
needdata
bool
path
string
}
const
DevNull
=
"NUL"
...
...
@@ -79,6 +80,11 @@ func openDir(name string) (file *File, err error) {
if
e
!=
nil
{
return
nil
,
&
PathError
{
"open"
,
name
,
e
}
}
d
.
path
=
name
if
!
isAbs
(
d
.
path
)
{
cwd
,
_
:=
Getwd
()
d
.
path
=
cwd
+
`\`
+
d
.
path
}
f
:=
NewFile
(
uintptr
(
r
),
name
)
f
.
dirinfo
=
d
return
f
,
nil
...
...
@@ -171,7 +177,13 @@ func (file *File) readdir(n int) (fi []FileInfo, err error) {
if
name
==
"."
||
name
==
".."
{
// Useless names
continue
}
f
:=
toFileInfo
(
name
,
d
.
FileAttributes
,
d
.
FileSizeHigh
,
d
.
FileSizeLow
,
d
.
CreationTime
,
d
.
LastAccessTime
,
d
.
LastWriteTime
)
f
:=
&
fileStat
{
name
:
name
,
size
:
mkSize
(
d
.
FileSizeHigh
,
d
.
FileSizeLow
),
modTime
:
mkModTime
(
d
.
LastWriteTime
),
mode
:
mkMode
(
d
.
FileAttributes
),
sys
:
mkSys
(
file
.
dirinfo
.
path
+
`\`
+
name
,
d
.
LastAccessTime
,
d
.
CreationTime
),
}
n
--
fi
=
append
(
fi
,
f
)
}
...
...
src/pkg/os/os_test.go
View file @
c7482b91
...
...
@@ -1014,3 +1014,38 @@ func TestNilProcessStateString(t *testing.T) {
t
.
Errorf
(
"(*ProcessState)(nil).String() = %q, want %q"
,
s
,
"<nil>"
)
}
}
func
TestSameFile
(
t
*
testing
.
T
)
{
fa
,
err
:=
Create
(
"a"
)
if
err
!=
nil
{
t
.
Fatalf
(
"Create(a): %v"
,
err
)
}
defer
Remove
(
fa
.
Name
())
fa
.
Close
()
fb
,
err
:=
Create
(
"b"
)
if
err
!=
nil
{
t
.
Fatalf
(
"Create(b): %v"
,
err
)
}
defer
Remove
(
fb
.
Name
())
fb
.
Close
()
ia1
,
err
:=
Stat
(
"a"
)
if
err
!=
nil
{
t
.
Fatalf
(
"Stat(a): %v"
,
err
)
}
ia2
,
err
:=
Stat
(
"a"
)
if
err
!=
nil
{
t
.
Fatalf
(
"Stat(a): %v"
,
err
)
}
if
!
SameFile
(
ia1
,
ia2
)
{
t
.
Errorf
(
"files should be same"
)
}
ib
,
err
:=
Stat
(
"b"
)
if
err
!=
nil
{
t
.
Fatalf
(
"Stat(b): %v"
,
err
)
}
if
SameFile
(
ia1
,
ib
)
{
t
.
Errorf
(
"files should be different"
)
}
}
src/pkg/os/stat_windows.go
View file @
c7482b91
...
...
@@ -5,6 +5,7 @@
package
os
import
(
"sync"
"syscall"
"time"
"unsafe"
...
...
@@ -25,7 +26,13 @@ func (file *File) Stat() (fi FileInfo, err error) {
if
e
!=
nil
{
return
nil
,
&
PathError
{
"GetFileInformationByHandle"
,
file
.
name
,
e
}
}
return
toFileInfo
(
basename
(
file
.
name
),
d
.
FileAttributes
,
d
.
FileSizeHigh
,
d
.
FileSizeLow
,
d
.
CreationTime
,
d
.
LastAccessTime
,
d
.
LastWriteTime
),
nil
return
&
fileStat
{
name
:
basename
(
file
.
name
),
size
:
mkSize
(
d
.
FileSizeHigh
,
d
.
FileSizeLow
),
modTime
:
mkModTime
(
d
.
LastWriteTime
),
mode
:
mkMode
(
d
.
FileAttributes
),
sys
:
mkSysFromFI
(
&
d
),
},
nil
}
// Stat returns a FileInfo structure describing the named file.
...
...
@@ -39,7 +46,18 @@ func Stat(name string) (fi FileInfo, err error) {
if
e
!=
nil
{
return
nil
,
&
PathError
{
"GetFileAttributesEx"
,
name
,
e
}
}
return
toFileInfo
(
basename
(
name
),
d
.
FileAttributes
,
d
.
FileSizeHigh
,
d
.
FileSizeLow
,
d
.
CreationTime
,
d
.
LastAccessTime
,
d
.
LastWriteTime
),
nil
path
:=
name
if
!
isAbs
(
path
)
{
cwd
,
_
:=
Getwd
()
path
=
cwd
+
`\`
+
path
}
return
&
fileStat
{
name
:
basename
(
name
),
size
:
mkSize
(
d
.
FileSizeHigh
,
d
.
FileSizeLow
),
modTime
:
mkModTime
(
d
.
LastWriteTime
),
mode
:
mkMode
(
d
.
FileAttributes
),
sys
:
mkSys
(
path
,
d
.
LastAccessTime
,
d
.
CreationTime
),
},
nil
}
// Lstat returns the FileInfo structure describing the named file.
...
...
@@ -75,37 +93,144 @@ func basename(name string) string {
return
name
}
type
winTimes
struct
{
atime
,
ctime
syscall
.
Filetime
func
isSlash
(
c
uint8
)
bool
{
return
c
==
'\\'
||
c
==
'/'
}
func
isAbs
(
path
string
)
(
b
bool
)
{
v
:=
volumeName
(
path
)
if
v
==
""
{
return
false
}
path
=
path
[
len
(
v
)
:
]
if
path
==
""
{
return
false
}
return
isSlash
(
path
[
0
])
}
func
toFileInfo
(
name
string
,
fa
,
sizehi
,
sizelo
uint32
,
ctime
,
atime
,
mtime
syscall
.
Filetime
)
FileInfo
{
fs
:=
&
fileStat
{
name
:
name
,
size
:
int64
(
sizehi
)
<<
32
+
int64
(
sizelo
),
modTime
:
time
.
Unix
(
0
,
mtime
.
Nanoseconds
()),
sys
:
&
winTimes
{
atime
,
ctime
},
func
volumeName
(
path
string
)
(
v
string
)
{
if
len
(
path
)
<
2
{
return
""
}
// with drive letter
c
:=
path
[
0
]
if
path
[
1
]
==
':'
&&
(
'0'
<=
c
&&
c
<=
'9'
||
'a'
<=
c
&&
c
<=
'z'
||
'A'
<=
c
&&
c
<=
'Z'
)
{
return
path
[
:
2
]
}
// is it UNC
if
l
:=
len
(
path
);
l
>=
5
&&
isSlash
(
path
[
0
])
&&
isSlash
(
path
[
1
])
&&
!
isSlash
(
path
[
2
])
&&
path
[
2
]
!=
'.'
{
// first, leading `\\` and next shouldn't be `\`. its server name.
for
n
:=
3
;
n
<
l
-
1
;
n
++
{
// second, next '\' shouldn't be repeated.
if
isSlash
(
path
[
n
])
{
n
++
// third, following something characters. its share name.
if
!
isSlash
(
path
[
n
])
{
if
path
[
n
]
==
'.'
{
break
}
for
;
n
<
l
;
n
++
{
if
isSlash
(
path
[
n
])
{
break
}
}
return
path
[
:
n
]
}
break
}
}
}
return
""
}
type
winSys
struct
{
sync
.
Mutex
path
string
atime
,
ctime
syscall
.
Filetime
vol
,
idxhi
,
idxlo
uint32
}
func
mkSize
(
hi
,
lo
uint32
)
int64
{
return
int64
(
hi
)
<<
32
+
int64
(
lo
)
}
func
mkModTime
(
mtime
syscall
.
Filetime
)
time
.
Time
{
return
time
.
Unix
(
0
,
mtime
.
Nanoseconds
())
}
func
mkMode
(
fa
uint32
)
(
m
FileMode
)
{
if
fa
&
syscall
.
FILE_ATTRIBUTE_DIRECTORY
!=
0
{
fs
.
mode
|=
ModeDir
m
|=
ModeDir
}
if
fa
&
syscall
.
FILE_ATTRIBUTE_READONLY
!=
0
{
fs
.
mode
|=
0444
m
|=
0444
}
else
{
fs
.
mode
|=
0666
m
|=
0666
}
return
fs
return
m
}
func
mkSys
(
path
string
,
atime
,
ctime
syscall
.
Filetime
)
*
winSys
{
return
&
winSys
{
path
:
path
,
atime
:
atime
,
ctime
:
ctime
,
}
}
func
mkSysFromFI
(
i
*
syscall
.
ByHandleFileInformation
)
*
winSys
{
return
&
winSys
{
atime
:
i
.
LastAccessTime
,
ctime
:
i
.
CreationTime
,
vol
:
i
.
VolumeSerialNumber
,
idxhi
:
i
.
FileIndexHigh
,
idxlo
:
i
.
FileIndexLow
,
}
}
func
(
s
*
winSys
)
loadFileId
()
error
{
if
s
.
path
==
""
{
// already done
return
nil
}
s
.
Lock
()
defer
s
.
Unlock
()
h
,
e
:=
syscall
.
CreateFile
(
syscall
.
StringToUTF16Ptr
(
s
.
path
),
syscall
.
GENERIC_READ
,
syscall
.
FILE_SHARE_READ
,
nil
,
syscall
.
OPEN_EXISTING
,
0
,
0
)
if
e
!=
nil
{
return
e
}
defer
syscall
.
CloseHandle
(
h
)
var
i
syscall
.
ByHandleFileInformation
e
=
syscall
.
GetFileInformationByHandle
(
syscall
.
Handle
(
h
),
&
i
)
if
e
!=
nil
{
return
e
}
s
.
path
=
""
s
.
vol
=
i
.
VolumeSerialNumber
s
.
idxhi
=
i
.
FileIndexHigh
s
.
idxlo
=
i
.
FileIndexLow
return
nil
}
func
sameFile
(
sys1
,
sys2
interface
{})
bool
{
// TODO(rsc): Do better than this, but this matches what
// used to happen when code compared .Dev and .Ino,
// which were both always zero. Obviously not all files
// are the same.
return
true
s1
:=
sys1
.
(
*
winSys
)
s2
:=
sys2
.
(
*
winSys
)
e
:=
s1
.
loadFileId
()
if
e
!=
nil
{
panic
(
e
)
}
e
=
s2
.
loadFileId
()
if
e
!=
nil
{
panic
(
e
)
}
return
s1
.
vol
==
s2
.
vol
&&
s1
.
idxhi
==
s2
.
idxhi
&&
s1
.
idxlo
==
s2
.
idxlo
}
// For testing.
func
atime
(
fi
FileInfo
)
time
.
Time
{
return
time
.
Unix
(
0
,
fi
.
Sys
()
.
(
*
win
Time
s
)
.
atime
.
Nanoseconds
())
return
time
.
Unix
(
0
,
fi
.
Sys
()
.
(
*
win
Sy
s
)
.
atime
.
Nanoseconds
())
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment