...

Source file src/pkg/os/stat_plan9.go

     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.
     4	
     5	package os
     6	
     7	import (
     8		"syscall"
     9		"time"
    10	)
    11	
    12	const bitSize16 = 2
    13	
    14	func fileInfoFromStat(d *syscall.Dir) FileInfo {
    15		fs := &fileStat{
    16			name:    d.Name,
    17			size:    d.Length,
    18			modTime: time.Unix(int64(d.Mtime), 0),
    19			sys:     d,
    20		}
    21		fs.mode = FileMode(d.Mode & 0777)
    22		if d.Mode&syscall.DMDIR != 0 {
    23			fs.mode |= ModeDir
    24		}
    25		if d.Mode&syscall.DMAPPEND != 0 {
    26			fs.mode |= ModeAppend
    27		}
    28		if d.Mode&syscall.DMEXCL != 0 {
    29			fs.mode |= ModeExclusive
    30		}
    31		if d.Mode&syscall.DMTMP != 0 {
    32			fs.mode |= ModeTemporary
    33		}
    34		// Consider all files not served by #M as device files.
    35		if d.Type != 'M' {
    36			fs.mode |= ModeDevice
    37		}
    38		// Consider all files served by #c as character device files.
    39		if d.Type == 'c' {
    40			fs.mode |= ModeCharDevice
    41		}
    42		return fs
    43	}
    44	
    45	// arg is an open *File or a path string.
    46	func dirstat(arg interface{}) (*syscall.Dir, error) {
    47		var name string
    48		var err error
    49	
    50		size := syscall.STATFIXLEN + 16*4
    51	
    52		for i := 0; i < 2; i++ {
    53			buf := make([]byte, bitSize16+size)
    54	
    55			var n int
    56			switch a := arg.(type) {
    57			case *File:
    58				name = a.name
    59				n, err = syscall.Fstat(a.fd, buf)
    60			case string:
    61				name = a
    62				n, err = syscall.Stat(a, buf)
    63			default:
    64				panic("phase error in dirstat")
    65			}
    66	
    67			if n < bitSize16 {
    68				return nil, &PathError{"stat", name, err}
    69			}
    70	
    71			// Pull the real size out of the stat message.
    72			size = int(uint16(buf[0]) | uint16(buf[1])<<8)
    73	
    74			// If the stat message is larger than our buffer we will
    75			// go around the loop and allocate one that is big enough.
    76			if size <= n {
    77				d, err := syscall.UnmarshalDir(buf[:n])
    78				if err != nil {
    79					return nil, &PathError{"stat", name, err}
    80				}
    81				return d, nil
    82			}
    83	
    84		}
    85	
    86		if err == nil {
    87			err = syscall.ErrBadStat
    88		}
    89	
    90		return nil, &PathError{"stat", name, err}
    91	}
    92	
    93	// statNolog implements Stat for Plan 9.
    94	func statNolog(name string) (FileInfo, error) {
    95		d, err := dirstat(name)
    96		if err != nil {
    97			return nil, err
    98		}
    99		return fileInfoFromStat(d), nil
   100	}
   101	
   102	// lstatNolog implements Lstat for Plan 9.
   103	func lstatNolog(name string) (FileInfo, error) {
   104		return statNolog(name)
   105	}
   106	
   107	// For testing.
   108	func atime(fi FileInfo) time.Time {
   109		return time.Unix(int64(fi.Sys().(*syscall.Dir).Atime), 0)
   110	}
   111	

View as plain text