1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
13 // File represents an open file descriptor.
18 // file is the real representation of *File.
19 // The extra level of indirection ensures that no clients of os
20 // can overwrite this data, which could cause the finalizer
21 // to close the wrong file descriptor.
25 dirinfo
*dirInfo
// nil unless directory being read
28 // Fd returns the integer Unix file descriptor referencing the open file.
29 func (f
*File
) Fd() uintptr {
36 // NewFile returns a new File with the given file descriptor and name.
37 func NewFile(fd
uintptr, name
string) *File
{
42 f
:= &File
{&file
{fd
: fdi
, name
: name
}}
43 runtime
.SetFinalizer(f
.file
, (*file
).close)
47 // Auxiliary information if the File describes a directory
49 buf
[syscall
.STATMAX
]byte // buffer for directory I/O
50 nbuf
int // length of buf; return value from Read
51 bufp
int // location of next record in buf.
54 func epipecheck(file
*File
, e error
) {
57 // DevNull is the name of the operating system's ``null device.''
58 // On Unix-like systems, it is "/dev/null"; on Windows, "NUL".
59 const DevNull
= "/dev/null"
61 // syscallMode returns the syscall-specific mode bits from Go's portable mode bits.
62 func syscallMode(i FileMode
) (o
uint32) {
64 if i
&ModeAppend
!= 0 {
67 if i
&ModeExclusive
!= 0 {
70 if i
&ModeTemporary
!= 0 {
76 // OpenFile is the generalized open call; most users will use Open
77 // or Create instead. It opens the named file with specified flag
78 // (O_RDONLY etc.) and perm, (0666 etc.) if applicable. If successful,
79 // methods on the returned File can be used for I/O.
80 // If there is an error, it will be of type *PathError.
81 func OpenFile(name
string, flag
int, perm FileMode
) (file
*File
, err error
) {
91 if flag
&O_CREATE
== O_CREATE
{
92 flag
= flag
& ^O_CREATE
95 if flag
&O_EXCL
== O_EXCL
{
98 if flag
&O_TRUNC
== O_TRUNC
{
101 // O_APPEND is emulated on Plan 9
102 if flag
&O_APPEND
== O_APPEND
{
103 flag
= flag
&^ O_APPEND
107 if (create
&& trunc
) || excl
{
108 fd
, e
= syscall
.Create(name
, flag
, syscallMode(perm
))
110 fd
, e
= syscall
.Open(name
, flag
)
111 if e
!= nil && create
{
113 fd
, e1
= syscall
.Create(name
, flag
, syscallMode(perm
))
121 return nil, &PathError
{"open", name
, e
}
125 if _
, e
= syscall
.Seek(fd
, 0, SEEK_END
); e
!= nil {
126 return nil, &PathError
{"seek", name
, e
}
130 return NewFile(uintptr(fd
), name
), nil
133 // Close closes the File, rendering it unusable for I/O.
134 // It returns an error, if any.
135 func (f
*File
) Close() error
{
139 return f
.file
.close()
142 func (file
*file
) close() error
{
143 if file
== nil || file
.fd
< 0 {
147 syscall
.ForkLock
.RLock()
148 if e
:= syscall
.Close(file
.fd
); e
!= nil {
149 err
= &PathError
{"close", file
.name
, e
}
151 syscall
.ForkLock
.RUnlock()
152 file
.fd
= -1 // so it can't be closed again
154 // no need for a finalizer anymore
155 runtime
.SetFinalizer(file
, nil)
159 // Stat returns the FileInfo structure describing file.
160 // If there is an error, it will be of type *PathError.
161 func (f
*File
) Stat() (fi FileInfo
, err error
) {
163 return nil, ErrInvalid
169 return fileInfoFromStat(d
), nil
172 // Truncate changes the size of the file.
173 // It does not change the I/O offset.
174 // If there is an error, it will be of type *PathError.
175 func (f
*File
) Truncate(size
int64) error
{
184 var buf
[syscall
.STATFIXLEN
]byte
185 n
, err
:= d
.Marshal(buf
[:])
187 return &PathError
{"truncate", f
.name
, err
}
189 if err
= syscall
.Fwstat(f
.fd
, buf
[:n
]); err
!= nil {
190 return &PathError
{"truncate", f
.name
, err
}
195 const chmodMask
= uint32(syscall
.DMAPPEND | syscall
.DMEXCL | syscall
.DMTMP | ModePerm
)
197 // Chmod changes the mode of the file to mode.
198 // If there is an error, it will be of type *PathError.
199 func (f
*File
) Chmod(mode FileMode
) error
{
205 odir
, e
:= dirstat(f
)
207 return &PathError
{"chmod", f
.name
, e
}
210 d
.Mode
= odir
.Mode
&^chmodMask |
syscallMode(mode
)&chmodMask
212 var buf
[syscall
.STATFIXLEN
]byte
213 n
, err
:= d
.Marshal(buf
[:])
215 return &PathError
{"chmod", f
.name
, err
}
217 if err
= syscall
.Fwstat(f
.fd
, buf
[:n
]); err
!= nil {
218 return &PathError
{"chmod", f
.name
, err
}
223 // Sync commits the current contents of the file to stable storage.
224 // Typically, this means flushing the file system's in-memory copy
225 // of recently written data to disk.
226 func (f
*File
) Sync() (err error
) {
233 var buf
[syscall
.STATFIXLEN
]byte
234 n
, err
:= d
.Marshal(buf
[:])
236 return NewSyscallError("fsync", err
)
238 if err
= syscall
.Fwstat(f
.fd
, buf
[:n
]); err
!= nil {
239 return NewSyscallError("fsync", err
)
244 // read reads up to len(b) bytes from the File.
245 // It returns the number of bytes read and an error, if any.
246 func (f
*File
) read(b
[]byte) (n
int, err error
) {
247 return syscall
.Read(f
.fd
, b
)
250 // pread reads len(b) bytes from the File starting at byte offset off.
251 // It returns the number of bytes read and the error, if any.
252 // EOF is signaled by a zero count with err set to nil.
253 func (f
*File
) pread(b
[]byte, off
int64) (n
int, err error
) {
254 return syscall
.Pread(f
.fd
, b
, off
)
257 // write writes len(b) bytes to the File.
258 // It returns the number of bytes written and an error, if any.
259 // Since Plan 9 preserves message boundaries, never allow
260 // a zero-byte write.
261 func (f
*File
) write(b
[]byte) (n
int, err error
) {
265 return syscall
.Write(f
.fd
, b
)
268 // pwrite writes len(b) bytes to the File starting at byte offset off.
269 // It returns the number of bytes written and an error, if any.
270 // Since Plan 9 preserves message boundaries, never allow
271 // a zero-byte write.
272 func (f
*File
) pwrite(b
[]byte, off
int64) (n
int, err error
) {
276 return syscall
.Pwrite(f
.fd
, b
, off
)
279 // seek sets the offset for the next Read or Write on file to offset, interpreted
280 // according to whence: 0 means relative to the origin of the file, 1 means
281 // relative to the current offset, and 2 means relative to the end.
282 // It returns the new offset and an error, if any.
283 func (f
*File
) seek(offset
int64, whence
int) (ret
int64, err error
) {
284 return syscall
.Seek(f
.fd
, offset
, whence
)
287 // Truncate changes the size of the named file.
288 // If the file is a symbolic link, it changes the size of the link's target.
289 // If there is an error, it will be of type *PathError.
290 func Truncate(name
string, size
int64) error
{
296 var buf
[syscall
.STATFIXLEN
]byte
297 n
, err
:= d
.Marshal(buf
[:])
299 return &PathError
{"truncate", name
, err
}
301 if err
= syscall
.Wstat(name
, buf
[:n
]); err
!= nil {
302 return &PathError
{"truncate", name
, err
}
307 // Remove removes the named file or directory.
308 // If there is an error, it will be of type *PathError.
309 func Remove(name
string) error
{
310 if e
:= syscall
.Remove(name
); e
!= nil {
311 return &PathError
{"remove", name
, e
}
316 // Rename renames a file.
317 func Rename(oldname
, newname
string) error
{
323 buf
:= make([]byte, syscall
.STATFIXLEN
+len(d
.Name
))
324 n
, err
:= d
.Marshal(buf
[:])
326 return &PathError
{"rename", oldname
, err
}
328 if err
= syscall
.Wstat(oldname
, buf
[:n
]); err
!= nil {
329 return &PathError
{"rename", oldname
, err
}
334 // Chmod changes the mode of the named file to mode.
335 // If the file is a symbolic link, it changes the mode of the link's target.
336 // If there is an error, it will be of type *PathError.
337 func Chmod(name
string, mode FileMode
) error
{
340 odir
, e
:= dirstat(name
)
342 return &PathError
{"chmod", name
, e
}
345 d
.Mode
= odir
.Mode
&^chmodMask |
syscallMode(mode
)&chmodMask
347 var buf
[syscall
.STATFIXLEN
]byte
348 n
, err
:= d
.Marshal(buf
[:])
350 return &PathError
{"chmod", name
, err
}
352 if err
= syscall
.Wstat(name
, buf
[:n
]); err
!= nil {
353 return &PathError
{"chmod", name
, err
}
358 // Chtimes changes the access and modification times of the named
359 // file, similar to the Unix utime() or utimes() functions.
361 // The underlying filesystem may truncate or round the values to a
362 // less precise time unit.
363 // If there is an error, it will be of type *PathError.
364 func Chtimes(name
string, atime time
.Time
, mtime time
.Time
) error
{
368 d
.Atime
= uint32(atime
.Unix())
369 d
.Mtime
= uint32(mtime
.Unix())
371 var buf
[syscall
.STATFIXLEN
]byte
372 n
, err
:= d
.Marshal(buf
[:])
374 return &PathError
{"chtimes", name
, err
}
376 if err
= syscall
.Wstat(name
, buf
[:n
]); err
!= nil {
377 return &PathError
{"chtimes", name
, err
}
382 // Pipe returns a connected pair of Files; reads from r return bytes
383 // written to w. It returns the files and an error, if any.
384 func Pipe() (r
*File
, w
*File
, err error
) {
387 syscall
.ForkLock
.RLock()
388 if e
:= syscall
.Pipe(p
[0:]); e
!= nil {
389 syscall
.ForkLock
.RUnlock()
390 return nil, nil, NewSyscallError("pipe", e
)
392 syscall
.ForkLock
.RUnlock()
394 return NewFile(uintptr(p
[0]), "|0"), NewFile(uintptr(p
[1]), "|1"), nil
397 // not supported on Plan 9
399 // Link creates newname as a hard link to the oldname file.
400 // If there is an error, it will be of type *LinkError.
401 func Link(oldname
, newname
string) error
{
402 return &LinkError
{"link", oldname
, newname
, syscall
.EPLAN9
}
405 // Symlink creates newname as a symbolic link to oldname.
406 // If there is an error, it will be of type *LinkError.
407 func Symlink(oldname
, newname
string) error
{
408 return &LinkError
{"symlink", oldname
, newname
, syscall
.EPLAN9
}
411 // Readlink returns the destination of the named symbolic link.
412 // If there is an error, it will be of type *PathError.
413 func Readlink(name
string) (string, error
) {
414 return "", &PathError
{"readlink", name
, syscall
.EPLAN9
}
417 // Chown changes the numeric uid and gid of the named file.
418 // If the file is a symbolic link, it changes the uid and gid of the link's target.
419 // If there is an error, it will be of type *PathError.
420 func Chown(name
string, uid
, gid
int) error
{
421 return &PathError
{"chown", name
, syscall
.EPLAN9
}
424 // Lchown changes the numeric uid and gid of the named file.
425 // If the file is a symbolic link, it changes the uid and gid of the link itself.
426 // If there is an error, it will be of type *PathError.
427 func Lchown(name
string, uid
, gid
int) error
{
428 return &PathError
{"lchown", name
, syscall
.EPLAN9
}
431 // Chown changes the numeric uid and gid of the named file.
432 // If there is an error, it will be of type *PathError.
433 func (f
*File
) Chown(uid
, gid
int) error
{
437 return &PathError
{"chown", f
.name
, syscall
.EPLAN9
}
440 // TempDir returns the default directory to use for temporary files.
441 func TempDir() string {