l sync.Mutex
// For console I/O.
- isConsole bool
lastbits []byte // first few bytes of the last incomplete rune in last write
readuint16 []uint16 // buffer to hold uint16s obtained with ReadConsole
readbyte []byte // buffer to hold decoding of readuint16 from utf16 to utf8
// message based socket connection.
ZeroReadIsEOF bool
- // Whether this is a normal file.
+ // Whether this is a file rather than a network socket.
isFile bool
- // Whether this is a directory.
- isDir bool
+ // The kind of this file.
+ kind fileKind
}
+// fileKind describes the kind of file.
+type fileKind byte
+
+const (
+ kindNet fileKind = iota
+ kindFile
+ kindConsole
+ kindDir
+)
+
// logInitFD is set by tests to enable file descriptor initialization logging.
var logInitFD func(net string, fd *FD, err error)
switch net {
case "file":
- fd.isFile = true
+ fd.kind = kindFile
case "console":
- fd.isConsole = true
+ fd.kind = kindConsole
case "dir":
- fd.isDir = true
- case "tcp", "tcp4", "tcp6":
- case "udp", "udp4", "udp6":
- case "ip", "ip4", "ip6":
- case "unix", "unixgram", "unixpacket":
+ fd.kind = kindDir
+ case "tcp", "tcp4", "tcp6",
+ "udp", "udp4", "udp6",
+ "ip", "ip4", "ip6",
+ "unix", "unixgram", "unixpacket":
+ fd.kind = kindNet
default:
return "", errors.New("internal error: unknown network type " + net)
}
+ fd.isFile = fd.kind != kindNet
var err error
if pollable {
// so this must be executed before fd.CloseFunc.
fd.pd.close()
var err error
- if fd.isFile || fd.isConsole {
- err = syscall.CloseHandle(fd.Sysfd)
- } else if fd.isDir {
- err = syscall.FindClose(fd.Sysfd)
- } else {
+ switch fd.kind {
+ case kindNet:
// The net package uses the CloseFunc variable for testing.
err = CloseFunc(fd.Sysfd)
+ case kindDir:
+ err = syscall.FindClose(fd.Sysfd)
+ default:
+ err = syscall.CloseHandle(fd.Sysfd)
}
fd.Sysfd = syscall.InvalidHandle
runtime_Semrelease(&fd.csema)
var n int
var err error
- if fd.isFile || fd.isDir || fd.isConsole {
+ if fd.isFile {
fd.l.Lock()
defer fd.l.Unlock()
- if fd.isConsole {
+ switch fd.kind {
+ case kindConsole:
n, err = fd.readConsole(buf)
- } else {
+ default:
n, err = syscall.Read(fd.Sysfd, buf)
}
if err != nil {
}
var n int
var err error
- if fd.isFile || fd.isDir || fd.isConsole {
+ if fd.isFile {
fd.l.Lock()
defer fd.l.Unlock()
- if fd.isConsole {
+ switch fd.kind {
+ case kindConsole:
n, err = fd.writeConsole(b)
- } else {
+ default:
n, err = syscall.Write(fd.Sysfd, b)
}
if err != nil {
}
}
-func TestDoubleCloseError(t *testing.T) {
- path := sfdir + "/" + sfname
+func testDoubleCloseError(t *testing.T, path string) {
file, err := Open(path)
if err != nil {
t.Fatal(err)
}
}
+func TestDoubleCloseError(t *testing.T) {
+ testDoubleCloseError(t, filepath.Join(sfdir, sfname))
+ testDoubleCloseError(t, sfdir)
+}
+
func TestUserHomeDir(t *testing.T) {
dir, err := UserHomeDir()
if dir == "" && err == nil {