OSDN Git Service

Remove the types float and complex.
[pf3gnuchains/gcc-fork.git] / libgo / go / os / file.go
1 // Copyright 2009 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.
4
5 // The os package provides a platform-independent interface to operating
6 // system functionality.  The design is Unix-like.
7 package os
8
9 import (
10         "runtime"
11         "syscall"
12 )
13
14 // File represents an open file descriptor.
15 type File struct {
16         fd      int
17         name    string
18         dirinfo *dirInfo // nil unless directory being read
19         nepipe  int      // number of consecutive EPIPE in Write
20 }
21
22 // Fd returns the integer Unix file descriptor referencing the open file.
23 func (file *File) Fd() int { return file.fd }
24
25 // Name returns the name of the file as presented to Open.
26 func (file *File) Name() string { return file.name }
27
28 // NewFile returns a new File with the given file descriptor and name.
29 func NewFile(fd int, name string) *File {
30         if fd < 0 {
31                 return nil
32         }
33         f := &File{fd, name, nil, 0}
34         runtime.SetFinalizer(f, (*File).Close)
35         return f
36 }
37
38 // Stdin, Stdout, and Stderr are open Files pointing to the standard input,
39 // standard output, and standard error file descriptors.
40 var (
41         Stdin  = NewFile(syscall.Stdin, "/dev/stdin")
42         Stdout = NewFile(syscall.Stdout, "/dev/stdout")
43         Stderr = NewFile(syscall.Stderr, "/dev/stderr")
44 )
45
46 // Flags to Open wrapping those of the underlying system. Not all flags
47 // may be implemented on a given system.
48 const (
49         O_RDONLY   int = syscall.O_RDONLY   // open the file read-only.
50         O_WRONLY   int = syscall.O_WRONLY   // open the file write-only.
51         O_RDWR     int = syscall.O_RDWR     // open the file read-write.
52         O_APPEND   int = syscall.O_APPEND   // append data to the file when writing.
53         O_ASYNC    int = syscall.O_ASYNC    // generate a signal when I/O is available.
54         O_CREAT    int = syscall.O_CREAT    // create a new file if none exists.
55         O_EXCL     int = syscall.O_EXCL     // used with O_CREAT, file must not exist
56         O_NOCTTY   int = syscall.O_NOCTTY   // do not make file the controlling tty.
57         O_NONBLOCK int = syscall.O_NONBLOCK // open in non-blocking mode.
58         O_NDELAY   int = O_NONBLOCK         // synonym for O_NONBLOCK
59         O_SYNC     int = syscall.O_SYNC     // open for synchronous I/O.
60         O_TRUNC    int = syscall.O_TRUNC    // if possible, truncate file when opened.
61         O_CREATE   int = O_CREAT            // create a new file if none exists.
62 )
63
64 type eofError int
65
66 func (eofError) String() string { return "EOF" }
67
68 // EOF is the Error returned by Read when no more input is available.
69 // Functions should return EOF only to signal a graceful end of input.
70 // If the EOF occurs unexpectedly in a structured data stream,
71 // the appropriate error is either io.ErrUnexpectedEOF or some other error
72 // giving more detail.
73 var EOF Error = eofError(0)
74
75 // Read reads up to len(b) bytes from the File.
76 // It returns the number of bytes read and an Error, if any.
77 // EOF is signaled by a zero count with err set to EOF.
78 func (file *File) Read(b []byte) (n int, err Error) {
79         if file == nil {
80                 return 0, EINVAL
81         }
82         n, e := syscall.Read(file.fd, b)
83         if n < 0 {
84                 n = 0
85         }
86         if n == 0 && e == 0 {
87                 return 0, EOF
88         }
89         if e != 0 {
90                 err = &PathError{"read", file.name, Errno(e)}
91         }
92         return n, err
93 }
94
95 // ReadAt reads len(b) bytes from the File starting at byte offset off.
96 // It returns the number of bytes read and the Error, if any.
97 // EOF is signaled by a zero count with err set to EOF.
98 // ReadAt always returns a non-nil Error when n != len(b).
99 func (file *File) ReadAt(b []byte, off int64) (n int, err Error) {
100         if file == nil {
101                 return 0, EINVAL
102         }
103         for len(b) > 0 {
104                 m, e := syscall.Pread(file.fd, b, off)
105                 if m == 0 && e == 0 {
106                         return n, EOF
107                 }
108                 if e != 0 {
109                         err = &PathError{"read", file.name, Errno(e)}
110                         break
111                 }
112                 n += m
113                 b = b[m:]
114                 off += int64(m)
115         }
116         return
117 }
118
119 // Write writes len(b) bytes to the File.
120 // It returns the number of bytes written and an Error, if any.
121 // Write returns a non-nil Error when n != len(b).
122 func (file *File) Write(b []byte) (n int, err Error) {
123         if file == nil {
124                 return 0, EINVAL
125         }
126         n, e := syscall.Write(file.fd, b)
127         if n < 0 {
128                 n = 0
129         }
130         if e == syscall.EPIPE {
131                 file.nepipe++
132                 if file.nepipe >= 10 {
133                         Exit(syscall.EPIPE)
134                 }
135         } else {
136                 file.nepipe = 0
137         }
138         if e != 0 {
139                 err = &PathError{"write", file.name, Errno(e)}
140         }
141         return n, err
142 }
143
144 // WriteAt writes len(b) bytes to the File starting at byte offset off.
145 // It returns the number of bytes written and an Error, if any.
146 // WriteAt returns a non-nil Error when n != len(b).
147 func (file *File) WriteAt(b []byte, off int64) (n int, err Error) {
148         if file == nil {
149                 return 0, EINVAL
150         }
151         for len(b) > 0 {
152                 m, e := syscall.Pwrite(file.fd, b, off)
153                 if e != 0 {
154                         err = &PathError{"write", file.name, Errno(e)}
155                         break
156                 }
157                 n += m
158                 b = b[m:]
159                 off += int64(m)
160         }
161         return
162 }
163
164 // Seek sets the offset for the next Read or Write on file to offset, interpreted
165 // according to whence: 0 means relative to the origin of the file, 1 means
166 // relative to the current offset, and 2 means relative to the end.
167 // It returns the new offset and an Error, if any.
168 func (file *File) Seek(offset int64, whence int) (ret int64, err Error) {
169         r, e := syscall.Seek(file.fd, offset, whence)
170         if e == 0 && file.dirinfo != nil && r != 0 {
171                 e = syscall.EISDIR
172         }
173         if e != 0 {
174                 return 0, &PathError{"seek", file.name, Errno(e)}
175         }
176         return r, nil
177 }
178
179 // WriteString is like Write, but writes the contents of string s rather than
180 // an array of bytes.
181 func (file *File) WriteString(s string) (ret int, err Error) {
182         if file == nil {
183                 return 0, EINVAL
184         }
185         b := syscall.StringByteSlice(s)
186         b = b[0 : len(b)-1]
187         return file.Write(b)
188 }
189
190 // Pipe returns a connected pair of Files; reads from r return bytes written to w.
191 // It returns the files and an Error, if any.
192 func Pipe() (r *File, w *File, err Error) {
193         var p [2]int
194
195         // See ../syscall/exec.go for description of lock.
196         syscall.ForkLock.RLock()
197         e := syscall.Pipe(p[0:])
198         if e != 0 {
199                 syscall.ForkLock.RUnlock()
200                 return nil, nil, NewSyscallError("pipe", e)
201         }
202         syscall.CloseOnExec(p[0])
203         syscall.CloseOnExec(p[1])
204         syscall.ForkLock.RUnlock()
205
206         return NewFile(p[0], "|0"), NewFile(p[1], "|1"), nil
207 }
208
209 // Mkdir creates a new directory with the specified name and permission bits.
210 // It returns an error, if any.
211 func Mkdir(name string, perm uint32) Error {
212         e := syscall.Mkdir(name, perm)
213         if e != 0 {
214                 return &PathError{"mkdir", name, Errno(e)}
215         }
216         return nil
217 }
218
219 // Stat returns a FileInfo structure describing the named file and an error, if any.
220 // If name names a valid symbolic link, the returned FileInfo describes
221 // the file pointed at by the link and has fi.FollowedSymlink set to true.
222 // If name names an invalid symbolic link, the returned FileInfo describes
223 // the link itself and has fi.FollowedSymlink set to false.
224 func Stat(name string) (fi *FileInfo, err Error) {
225         var lstat, stat syscall.Stat_t
226         e := syscall.Lstat(name, &lstat)
227         if e != 0 {
228                 return nil, &PathError{"stat", name, Errno(e)}
229         }
230         statp := &lstat
231         if lstat.Mode&syscall.S_IFMT == syscall.S_IFLNK {
232                 e := syscall.Stat(name, &stat)
233                 if e == 0 {
234                         statp = &stat
235                 }
236         }
237         return fileInfoFromStat(name, new(FileInfo), &lstat, statp), nil
238 }
239
240 // Lstat returns the FileInfo structure describing the named file and an
241 // error, if any.  If the file is a symbolic link, the returned FileInfo
242 // describes the symbolic link.  Lstat makes no attempt to follow the link.
243 func Lstat(name string) (fi *FileInfo, err Error) {
244         var stat syscall.Stat_t
245         e := syscall.Lstat(name, &stat)
246         if e != 0 {
247                 return nil, &PathError{"lstat", name, Errno(e)}
248         }
249         return fileInfoFromStat(name, new(FileInfo), &stat, &stat), nil
250 }
251
252 // Chdir changes the current working directory to the named directory.
253 func Chdir(dir string) Error {
254         if e := syscall.Chdir(dir); e != 0 {
255                 return &PathError{"chdir", dir, Errno(e)}
256         }
257         return nil
258 }
259
260 // Chdir changes the current working directory to the file,
261 // which must be a directory.
262 func (f *File) Chdir() Error {
263         if e := syscall.Fchdir(f.fd); e != 0 {
264                 return &PathError{"chdir", f.name, Errno(e)}
265         }
266         return nil
267 }
268
269 // Remove removes the named file or directory.
270 func Remove(name string) Error {
271         // System call interface forces us to know
272         // whether name is a file or directory.
273         // Try both: it is cheaper on average than
274         // doing a Stat plus the right one.
275         e := syscall.Unlink(name)
276         if e == 0 {
277                 return nil
278         }
279         e1 := syscall.Rmdir(name)
280         if e1 == 0 {
281                 return nil
282         }
283
284         // Both failed: figure out which error to return.
285         // OS X and Linux differ on whether unlink(dir)
286         // returns EISDIR, so can't use that.  However,
287         // both agree that rmdir(file) returns ENOTDIR,
288         // so we can use that to decide which error is real.
289         // Rmdir might also return ENOTDIR if given a bad
290         // file path, like /etc/passwd/foo, but in that case,
291         // both errors will be ENOTDIR, so it's okay to
292         // use the error from unlink.
293         // For windows syscall.ENOTDIR is set
294         // to syscall.ERROR_DIRECTORY, hopefully it should
295         // do the trick.
296         if e1 != syscall.ENOTDIR {
297                 e = e1
298         }
299         return &PathError{"remove", name, Errno(e)}
300 }
301
302 // LinkError records an error during a link or symlink or rename
303 // system call and the paths that caused it.
304 type LinkError struct {
305         Op    string
306         Old   string
307         New   string
308         Error Error
309 }
310
311 func (e *LinkError) String() string {
312         return e.Op + " " + e.Old + " " + e.New + ": " + e.Error.String()
313 }
314
315 // Link creates a hard link.
316 func Link(oldname, newname string) Error {
317         e := syscall.Link(oldname, newname)
318         if e != 0 {
319                 return &LinkError{"link", oldname, newname, Errno(e)}
320         }
321         return nil
322 }
323
324 // Symlink creates a symbolic link.
325 func Symlink(oldname, newname string) Error {
326         e := syscall.Symlink(oldname, newname)
327         if e != 0 {
328                 return &LinkError{"symlink", oldname, newname, Errno(e)}
329         }
330         return nil
331 }
332
333 // Readlink reads the contents of a symbolic link: the destination of
334 // the link.  It returns the contents and an Error, if any.
335 func Readlink(name string) (string, Error) {
336         for len := 128; ; len *= 2 {
337                 b := make([]byte, len)
338                 n, e := syscall.Readlink(name, b)
339                 if e != 0 {
340                         return "", &PathError{"readlink", name, Errno(e)}
341                 }
342                 if n < len {
343                         return string(b[0:n]), nil
344                 }
345         }
346         // Silence 6g.
347         return "", nil
348 }
349
350 // Rename renames a file.
351 func Rename(oldname, newname string) Error {
352         e := syscall.Rename(oldname, newname)
353         if e != 0 {
354                 return &LinkError{"rename", oldname, newname, Errno(e)}
355         }
356         return nil
357 }
358
359 // Chmod changes the mode of the named file to mode.
360 // If the file is a symbolic link, it changes the mode of the link's target.
361 func Chmod(name string, mode uint32) Error {
362         if e := syscall.Chmod(name, mode); e != 0 {
363                 return &PathError{"chmod", name, Errno(e)}
364         }
365         return nil
366 }
367
368 // Chmod changes the mode of the file to mode.
369 func (f *File) Chmod(mode uint32) Error {
370         if e := syscall.Fchmod(f.fd, mode); e != 0 {
371                 return &PathError{"chmod", f.name, Errno(e)}
372         }
373         return nil
374 }
375
376 // Chown changes the numeric uid and gid of the named file.
377 // If the file is a symbolic link, it changes the uid and gid of the link's target.
378 func Chown(name string, uid, gid int) Error {
379         if e := syscall.Chown(name, uid, gid); e != 0 {
380                 return &PathError{"chown", name, Errno(e)}
381         }
382         return nil
383 }
384
385 // Lchown changes the numeric uid and gid of the named file.
386 // If the file is a symbolic link, it changes the uid and gid of the link itself.
387 func Lchown(name string, uid, gid int) Error {
388         if e := syscall.Lchown(name, uid, gid); e != 0 {
389                 return &PathError{"lchown", name, Errno(e)}
390         }
391         return nil
392 }
393
394 // Chown changes the numeric uid and gid of the named file.
395 func (f *File) Chown(uid, gid int) Error {
396         if e := syscall.Fchown(f.fd, uid, gid); e != 0 {
397                 return &PathError{"chown", f.name, Errno(e)}
398         }
399         return nil
400 }
401
402 // Truncate changes the size of the file.
403 // It does not change the I/O offset.
404 func (f *File) Truncate(size int64) Error {
405         if e := syscall.Ftruncate(f.fd, size); e != 0 {
406                 return &PathError{"truncate", f.name, Errno(e)}
407         }
408         return nil
409 }
410
411 // Sync commits the current contents of the file to stable storage.
412 // Typically, this means flushing the file system's in-memory copy
413 // of recently written data to disk.
414 func (file *File) Sync() (err Error) {
415         if file == nil {
416                 return EINVAL
417         }
418         if e := syscall.Fsync(file.fd); e != 0 {
419                 return NewSyscallError("fsync", e)
420         }
421         return nil
422 }
423
424 // Chtimes changes the access and modification times of the named
425 // file, similar to the Unix utime() or utimes() functions.
426 //
427 // The argument times are in nanoseconds, although the underlying
428 // filesystem may truncate or round the values to a more
429 // coarse time unit.
430 func Chtimes(name string, atime_ns int64, mtime_ns int64) Error {
431         var utimes [2]syscall.Timeval
432         utimes[0] = syscall.NsecToTimeval(atime_ns)
433         utimes[1] = syscall.NsecToTimeval(mtime_ns)
434         if e := syscall.Utimes(name, utimes[0:]); e != 0 {
435                 return &PathError{"chtimes", name, Errno(e)}
436         }
437         return nil
438 }