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
b1deb3be
Commit
b1deb3be
authored
Apr 26, 2011
by
Alex Brainman
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
os: fix race in ReadAt/WriteAt on Windows
R=bradfitzgo, rsc, peterGo CC=golang-dev
https://golang.org/cl/4441051
parent
2d99974e
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
147 additions
and
46 deletions
+147
-46
src/pkg/os/file.go
src/pkg/os/file.go
+10
-8
src/pkg/os/file_plan9.go
src/pkg/os/file_plan9.go
+33
-0
src/pkg/os/file_unix.go
src/pkg/os/file_unix.go
+33
-0
src/pkg/os/file_windows.go
src/pkg/os/file_windows.go
+71
-0
src/pkg/syscall/syscall_windows.go
src/pkg/syscall/syscall_windows.go
+0
-38
No files found.
src/pkg/os/file.go
View file @
b1deb3be
...
...
@@ -8,6 +8,7 @@ package os
import
(
"runtime"
"sync"
"syscall"
)
...
...
@@ -15,8 +16,9 @@ import (
type
File
struct
{
fd
int
name
string
dirinfo
*
dirInfo
// nil unless directory being read
nepipe
int
// number of consecutive EPIPE in Write
dirinfo
*
dirInfo
// nil unless directory being read
nepipe
int
// number of consecutive EPIPE in Write
l
sync
.
Mutex
// used to implement windows pread/pwrite
}
// Fd returns the integer Unix file descriptor referencing the open file.
...
...
@@ -30,7 +32,7 @@ func NewFile(fd int, name string) *File {
if
fd
<
0
{
return
nil
}
f
:=
&
File
{
fd
,
name
,
nil
,
0
}
f
:=
&
File
{
fd
:
fd
,
name
:
name
}
runtime
.
SetFinalizer
(
f
,
(
*
File
)
.
Close
)
return
f
}
...
...
@@ -85,7 +87,7 @@ func (file *File) Read(b []byte) (n int, err Error) {
if
file
==
nil
{
return
0
,
EINVAL
}
n
,
e
:=
syscall
.
Read
(
file
.
fd
,
b
)
n
,
e
:=
file
.
read
(
b
)
if
n
<
0
{
n
=
0
}
...
...
@@ -107,7 +109,7 @@ func (file *File) ReadAt(b []byte, off int64) (n int, err Error) {
return
0
,
EINVAL
}
for
len
(
b
)
>
0
{
m
,
e
:=
syscall
.
Pread
(
file
.
fd
,
b
,
off
)
m
,
e
:=
file
.
pread
(
b
,
off
)
if
m
==
0
&&
!
iserror
(
e
)
{
return
n
,
EOF
}
...
...
@@ -129,7 +131,7 @@ func (file *File) Write(b []byte) (n int, err Error) {
if
file
==
nil
{
return
0
,
EINVAL
}
n
,
e
:=
syscall
.
Write
(
file
.
fd
,
b
)
n
,
e
:=
file
.
write
(
b
)
if
n
<
0
{
n
=
0
}
...
...
@@ -150,7 +152,7 @@ func (file *File) WriteAt(b []byte, off int64) (n int, err Error) {
return
0
,
EINVAL
}
for
len
(
b
)
>
0
{
m
,
e
:=
syscall
.
Pwrite
(
file
.
fd
,
b
,
off
)
m
,
e
:=
file
.
pwrite
(
b
,
off
)
if
iserror
(
e
)
{
err
=
&
PathError
{
"write"
,
file
.
name
,
Errno
(
e
)}
break
...
...
@@ -167,7 +169,7 @@ func (file *File) WriteAt(b []byte, off int64) (n int, err Error) {
// relative to the current offset, and 2 means relative to the end.
// It returns the new offset and an Error, if any.
func
(
file
*
File
)
Seek
(
offset
int64
,
whence
int
)
(
ret
int64
,
err
Error
)
{
r
,
e
:=
syscall
.
Seek
(
file
.
fd
,
offset
,
whence
)
r
,
e
:=
file
.
seek
(
offset
,
whence
)
if
!
iserror
(
e
)
&&
file
.
dirinfo
!=
nil
&&
r
!=
0
{
e
=
syscall
.
EISDIR
}
...
...
src/pkg/os/file_plan9.go
View file @
b1deb3be
...
...
@@ -117,6 +117,39 @@ func (f *File) Sync() (err Error) {
return
nil
}
// read reads up to len(b) bytes from the File.
// It returns the number of bytes read and an error, if any.
func
(
f
*
File
)
read
(
b
[]
byte
)
(
n
int
,
err
syscall
.
Error
)
{
return
syscall
.
Read
(
f
.
fd
,
b
)
}
// pread reads len(b) bytes from the File starting at byte offset off.
// It returns the number of bytes read and the error, if any.
// EOF is signaled by a zero count with err set to nil.
func
(
f
*
File
)
pread
(
b
[]
byte
,
off
int64
)
(
n
int
,
err
syscall
.
Error
)
{
return
syscall
.
Pread
(
f
.
fd
,
b
,
off
)
}
// write writes len(b) bytes to the File.
// It returns the number of bytes written and an error, if any.
func
(
f
*
File
)
write
(
b
[]
byte
)
(
n
int
,
err
syscall
.
Error
)
{
return
syscall
.
Write
(
f
.
fd
,
b
)
}
// pwrite writes len(b) bytes to the File starting at byte offset off.
// It returns the number of bytes written and an error, if any.
func
(
f
*
File
)
pwrite
(
b
[]
byte
,
off
int64
)
(
n
int
,
err
syscall
.
Error
)
{
return
syscall
.
Pwrite
(
f
.
fd
,
b
,
off
)
}
// seek sets the offset for the next Read or Write on file to offset, interpreted
// according to whence: 0 means relative to the origin of the file, 1 means
// relative to the current offset, and 2 means relative to the end.
// It returns the new offset and an error, if any.
func
(
f
*
File
)
seek
(
offset
int64
,
whence
int
)
(
ret
int64
,
err
syscall
.
Error
)
{
return
syscall
.
Seek
(
f
.
fd
,
offset
,
whence
)
}
// Truncate changes the size of the named file.
// If the file is a symbolic link, it changes the size of the link's target.
func
Truncate
(
name
string
,
size
int64
)
Error
{
...
...
src/pkg/os/file_unix.go
View file @
b1deb3be
...
...
@@ -96,6 +96,39 @@ func (file *File) Readdir(count int) (fi []FileInfo, err Error) {
return
}
// read reads up to len(b) bytes from the File.
// It returns the number of bytes read and an error, if any.
func
(
f
*
File
)
read
(
b
[]
byte
)
(
n
int
,
err
int
)
{
return
syscall
.
Read
(
f
.
fd
,
b
)
}
// pread reads len(b) bytes from the File starting at byte offset off.
// It returns the number of bytes read and the error, if any.
// EOF is signaled by a zero count with err set to 0.
func
(
f
*
File
)
pread
(
b
[]
byte
,
off
int64
)
(
n
int
,
err
int
)
{
return
syscall
.
Pread
(
f
.
fd
,
b
,
off
)
}
// write writes len(b) bytes to the File.
// It returns the number of bytes written and an error, if any.
func
(
f
*
File
)
write
(
b
[]
byte
)
(
n
int
,
err
int
)
{
return
syscall
.
Write
(
f
.
fd
,
b
)
}
// pwrite writes len(b) bytes to the File starting at byte offset off.
// It returns the number of bytes written and an error, if any.
func
(
f
*
File
)
pwrite
(
b
[]
byte
,
off
int64
)
(
n
int
,
err
int
)
{
return
syscall
.
Pwrite
(
f
.
fd
,
b
,
off
)
}
// seek sets the offset for the next Read or Write on file to offset, interpreted
// according to whence: 0 means relative to the origin of the file, 1 means
// relative to the current offset, and 2 means relative to the end.
// It returns the new offset and an error, if any.
func
(
f
*
File
)
seek
(
offset
int64
,
whence
int
)
(
ret
int64
,
err
int
)
{
return
syscall
.
Seek
(
f
.
fd
,
offset
,
whence
)
}
// Truncate changes the size of the named file.
// If the file is a symbolic link, it changes the size of the link's target.
func
Truncate
(
name
string
,
size
int64
)
Error
{
...
...
src/pkg/os/file_windows.go
View file @
b1deb3be
...
...
@@ -165,6 +165,77 @@ func (file *File) Readdir(count int) (fi []FileInfo, err Error) {
return
fi
,
nil
}
// read reads up to len(b) bytes from the File.
// It returns the number of bytes read and an error, if any.
func
(
f
*
File
)
read
(
b
[]
byte
)
(
n
int
,
err
int
)
{
f
.
l
.
Lock
()
defer
f
.
l
.
Unlock
()
return
syscall
.
Read
(
f
.
fd
,
b
)
}
// pread reads len(b) bytes from the File starting at byte offset off.
// It returns the number of bytes read and the error, if any.
// EOF is signaled by a zero count with err set to 0.
func
(
f
*
File
)
pread
(
b
[]
byte
,
off
int64
)
(
n
int
,
err
int
)
{
f
.
l
.
Lock
()
defer
f
.
l
.
Unlock
()
curoffset
,
e
:=
syscall
.
Seek
(
f
.
fd
,
0
,
1
)
if
e
!=
0
{
return
0
,
e
}
defer
syscall
.
Seek
(
f
.
fd
,
curoffset
,
0
)
o
:=
syscall
.
Overlapped
{
OffsetHigh
:
uint32
(
off
>>
32
),
Offset
:
uint32
(
off
),
}
var
done
uint32
e
=
syscall
.
ReadFile
(
int32
(
f
.
fd
),
b
,
&
done
,
&
o
)
if
e
!=
0
{
return
0
,
e
}
return
int
(
done
),
0
}
// write writes len(b) bytes to the File.
// It returns the number of bytes written and an error, if any.
func
(
f
*
File
)
write
(
b
[]
byte
)
(
n
int
,
err
int
)
{
f
.
l
.
Lock
()
defer
f
.
l
.
Unlock
()
return
syscall
.
Write
(
f
.
fd
,
b
)
}
// pwrite writes len(b) bytes to the File starting at byte offset off.
// It returns the number of bytes written and an error, if any.
func
(
f
*
File
)
pwrite
(
b
[]
byte
,
off
int64
)
(
n
int
,
err
int
)
{
f
.
l
.
Lock
()
defer
f
.
l
.
Unlock
()
curoffset
,
e
:=
syscall
.
Seek
(
f
.
fd
,
0
,
1
)
if
e
!=
0
{
return
0
,
e
}
defer
syscall
.
Seek
(
f
.
fd
,
curoffset
,
0
)
o
:=
syscall
.
Overlapped
{
OffsetHigh
:
uint32
(
off
>>
32
),
Offset
:
uint32
(
off
),
}
var
done
uint32
e
=
syscall
.
WriteFile
(
int32
(
f
.
fd
),
b
,
&
done
,
&
o
)
if
e
!=
0
{
return
0
,
e
}
return
int
(
done
),
0
}
// seek sets the offset for the next Read or Write on file to offset, interpreted
// according to whence: 0 means relative to the origin of the file, 1 means
// relative to the current offset, and 2 means relative to the end.
// It returns the new offset and an error, if any.
func
(
f
*
File
)
seek
(
offset
int64
,
whence
int
)
(
ret
int64
,
err
int
)
{
f
.
l
.
Lock
()
defer
f
.
l
.
Unlock
()
return
syscall
.
Seek
(
f
.
fd
,
offset
,
whence
)
}
// Truncate changes the size of the named file.
// If the file is a symbolic link, it changes the size of the link's target.
func
Truncate
(
name
string
,
size
int64
)
Error
{
...
...
src/pkg/syscall/syscall_windows.go
View file @
b1deb3be
...
...
@@ -250,27 +250,6 @@ func Read(fd int, p []byte) (n int, errno int) {
return
int
(
done
),
0
}
// TODO(brainman): ReadFile/WriteFile change file offset, therefore
// i use Seek here to preserve semantics of unix pread/pwrite,
// not sure if I should do that
func
Pread
(
fd
int
,
p
[]
byte
,
offset
int64
)
(
n
int
,
errno
int
)
{
curoffset
,
e
:=
Seek
(
fd
,
0
,
1
)
if
e
!=
0
{
return
0
,
e
}
defer
Seek
(
fd
,
curoffset
,
0
)
var
o
Overlapped
o
.
OffsetHigh
=
uint32
(
offset
>>
32
)
o
.
Offset
=
uint32
(
offset
)
var
done
uint32
e
=
ReadFile
(
int32
(
fd
),
p
,
&
done
,
&
o
)
if
e
!=
0
{
return
0
,
e
}
return
int
(
done
),
0
}
func
Write
(
fd
int
,
p
[]
byte
)
(
n
int
,
errno
int
)
{
var
done
uint32
e
:=
WriteFile
(
int32
(
fd
),
p
,
&
done
,
nil
)
...
...
@@ -280,23 +259,6 @@ func Write(fd int, p []byte) (n int, errno int) {
return
int
(
done
),
0
}
func
Pwrite
(
fd
int
,
p
[]
byte
,
offset
int64
)
(
n
int
,
errno
int
)
{
curoffset
,
e
:=
Seek
(
fd
,
0
,
1
)
if
e
!=
0
{
return
0
,
e
}
defer
Seek
(
fd
,
curoffset
,
0
)
var
o
Overlapped
o
.
OffsetHigh
=
uint32
(
offset
>>
32
)
o
.
Offset
=
uint32
(
offset
)
var
done
uint32
e
=
WriteFile
(
int32
(
fd
),
p
,
&
done
,
&
o
)
if
e
!=
0
{
return
0
,
e
}
return
int
(
done
),
0
}
func
Seek
(
fd
int
,
offset
int64
,
whence
int
)
(
newoffset
int64
,
errno
int
)
{
var
w
uint32
switch
whence
{
...
...
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