[go]os.Open方法源码

file, err := os.Open("./buf.go")

func Open(name string) (*File, error) {
        return OpenFile(name, O_RDONLY, 0)
}


func OpenFile(name string, flag int, perm FileMode) (*File, error) {
        testlog.Open(name)
        f, err := openFileNolog(name, flag, perm)
        if err != nil {
                return nil, err
        }
        f.appendMode = flag&O_APPEND != 0

        return f, nil
}

func openFileNolog(name string, flag int, perm FileMode) (*File, error) {
        if name == "" {
                return nil, &PathError{"open", name, syscall.ENOENT}
        }
        r, errf := openFile(name, flag, perm)
        if errf == nil {
                return r, nil
        }
        r, errd := openDir(name)
        if errd == nil {
                if flag&O_WRONLY != 0 || flag&O_RDWR != 0 {
                        r.Close()
                        return nil, &PathError{"open", name, syscall.EISDIR}
                }
                return r, nil
        }
        return nil, &PathError{"open", name, errf}
}


func openFile(name string, flag int, perm FileMode) (file *File, err error) {
        r, e := syscall.Open(fixLongPath(name), flag|syscall.O_CLOEXEC, syscallMode(perm))
        if e != nil {
                return nil, e
        }
        return newFile(r, name, "file"), nil
}

func newFile(h syscall.Handle, name string, kind string) *File {
        if kind == "file" {
                var m uint32
                if syscall.GetConsoleMode(h, &m) == nil {
                        kind = "console"
                }
                if t, err := syscall.GetFileType(h); err == nil && t == syscall.FILE_TYPE_PIPE {
                        kind = "pipe"
                }
        }

        f := &File{&file{
                pfd: poll.FD{
                        Sysfd:         h,
                        IsStream:      true,
                        ZeroReadIsEOF: true,
                },
                name: name,
        }}
        runtime.SetFinalizer(f.file, (*file).close)

        // Ignore initialization errors.
        // Assume any problems will show up in later I/O.
        f.pfd.Init(kind, false)

        return f
}

type File struct {
        *file // os specific
}

type file struct {
        pfd        poll.FD
        name       string
        dirinfo    *dirInfo // nil unless directory being read
        appendMode bool     // whether file is opened for appending
}
func (f *File) write(b []byte) (n int, err error) {
        n, err = f.pfd.Write(b)
        runtime.KeepAlive(f)
        return n, err
}
  • 小结
os.Open("/etc/hosts") //只读模式
    OpenFile(name, O_RDONLY, 0)
        openFileNolog(name, flag, perm)
            newFile(uintptr(r), name, kindOpenFile)