syscall_plan9.go 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  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. // Plan 9 system calls.
  5. // This file is compiled as ordinary Go code,
  6. // but it is also input to mksyscall,
  7. // which parses the //sys lines and generates system call stubs.
  8. // Note that sometimes we use a lowercase //sys name and
  9. // wrap it in our own nicer implementation.
  10. package plan9
  11. import "unsafe"
  12. const ImplementsGetwd = true
  13. // ErrorString implements Error's String method by returning itself.
  14. type ErrorString string
  15. func (e ErrorString) Error() string { return string(e) }
  16. // NewError converts s to an ErrorString, which satisfies the Error interface.
  17. func NewError(s string) error { return ErrorString(s) }
  18. func (e ErrorString) Temporary() bool {
  19. return e == EINTR || e == EMFILE || e.Timeout()
  20. }
  21. func (e ErrorString) Timeout() bool {
  22. return e == EBUSY || e == ETIMEDOUT
  23. }
  24. // A Note is a string describing a process note.
  25. // It implements the os.Signal interface.
  26. type Note string
  27. func (n Note) Signal() {}
  28. func (n Note) String() string {
  29. return string(n)
  30. }
  31. var (
  32. Stdin = 0
  33. Stdout = 1
  34. Stderr = 2
  35. )
  36. // For testing: clients can set this flag to force
  37. // creation of IPv6 sockets to return EAFNOSUPPORT.
  38. var SocketDisableIPv6 bool
  39. func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err ErrorString)
  40. func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err ErrorString)
  41. func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr)
  42. func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
  43. func atoi(b []byte) (n uint) {
  44. n = 0
  45. for i := 0; i < len(b); i++ {
  46. n = n*10 + uint(b[i]-'0')
  47. }
  48. return
  49. }
  50. func cstring(s []byte) string {
  51. for i := range s {
  52. if s[i] == 0 {
  53. return string(s[0:i])
  54. }
  55. }
  56. return string(s)
  57. }
  58. func errstr() string {
  59. var buf [ERRMAX]byte
  60. RawSyscall(SYS_ERRSTR, uintptr(unsafe.Pointer(&buf[0])), uintptr(len(buf)), 0)
  61. buf[len(buf)-1] = 0
  62. return cstring(buf[:])
  63. }
  64. // Implemented in assembly to import from runtime.
  65. func exit(code int)
  66. func Exit(code int) { exit(code) }
  67. func readnum(path string) (uint, error) {
  68. var b [12]byte
  69. fd, e := Open(path, O_RDONLY)
  70. if e != nil {
  71. return 0, e
  72. }
  73. defer Close(fd)
  74. n, e := Pread(fd, b[:], 0)
  75. if e != nil {
  76. return 0, e
  77. }
  78. m := 0
  79. for ; m < n && b[m] == ' '; m++ {
  80. }
  81. return atoi(b[m : n-1]), nil
  82. }
  83. func Getpid() (pid int) {
  84. n, _ := readnum("#c/pid")
  85. return int(n)
  86. }
  87. func Getppid() (ppid int) {
  88. n, _ := readnum("#c/ppid")
  89. return int(n)
  90. }
  91. func Read(fd int, p []byte) (n int, err error) {
  92. return Pread(fd, p, -1)
  93. }
  94. func Write(fd int, p []byte) (n int, err error) {
  95. return Pwrite(fd, p, -1)
  96. }
  97. var ioSync int64
  98. func Getwd() (wd string, err error) {
  99. fd, e := Open(".", O_RDONLY)
  100. if e != nil {
  101. return "", e
  102. }
  103. defer Close(fd)
  104. return Fd2path(fd)
  105. }
  106. //sys fd2path(fd int, buf []byte) (err error)
  107. func Fd2path(fd int) (path string, err error) {
  108. var buf [512]byte
  109. e := fd2path(fd, buf[:])
  110. if e != nil {
  111. return "", e
  112. }
  113. return cstring(buf[:]), nil
  114. }
  115. //sys pipe(p *[2]_C_int) (err error)
  116. func Pipe(p []int) (err error) {
  117. if len(p) != 2 {
  118. return NewError("bad arg in system call")
  119. }
  120. var pp [2]_C_int
  121. err = pipe(&pp)
  122. p[0] = int(pp[0])
  123. p[1] = int(pp[1])
  124. return
  125. }
  126. // Underlying system call writes to newoffset via pointer.
  127. // Implemented in assembly to avoid allocation.
  128. func seek(placeholder uintptr, fd int, offset int64, whence int) (newoffset int64, err string)
  129. func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
  130. newoffset, e := seek(0, fd, offset, whence)
  131. if newoffset == -1 {
  132. err = NewError(e)
  133. }
  134. return
  135. }
  136. func Mkdir(path string, mode uint32) (err error) {
  137. fd, err := Create(path, O_RDONLY, DMDIR|mode)
  138. if fd != -1 {
  139. Close(fd)
  140. }
  141. return
  142. }
  143. type Waitmsg struct {
  144. Pid int
  145. Time [3]uint32
  146. Msg string
  147. }
  148. func (w Waitmsg) Exited() bool { return true }
  149. func (w Waitmsg) Signaled() bool { return false }
  150. func (w Waitmsg) ExitStatus() int {
  151. if len(w.Msg) == 0 {
  152. // a normal exit returns no message
  153. return 0
  154. }
  155. return 1
  156. }
  157. //sys await(s []byte) (n int, err error)
  158. func Await(w *Waitmsg) (err error) {
  159. var buf [512]byte
  160. var f [5][]byte
  161. n, err := await(buf[:])
  162. if err != nil || w == nil {
  163. return
  164. }
  165. nf := 0
  166. p := 0
  167. for i := 0; i < n && nf < len(f)-1; i++ {
  168. if buf[i] == ' ' {
  169. f[nf] = buf[p:i]
  170. p = i + 1
  171. nf++
  172. }
  173. }
  174. f[nf] = buf[p:]
  175. nf++
  176. if nf != len(f) {
  177. return NewError("invalid wait message")
  178. }
  179. w.Pid = int(atoi(f[0]))
  180. w.Time[0] = uint32(atoi(f[1]))
  181. w.Time[1] = uint32(atoi(f[2]))
  182. w.Time[2] = uint32(atoi(f[3]))
  183. w.Msg = cstring(f[4])
  184. if w.Msg == "''" {
  185. // await() returns '' for no error
  186. w.Msg = ""
  187. }
  188. return
  189. }
  190. func Unmount(name, old string) (err error) {
  191. oldp, err := BytePtrFromString(old)
  192. if err != nil {
  193. return err
  194. }
  195. oldptr := uintptr(unsafe.Pointer(oldp))
  196. var r0 uintptr
  197. var e ErrorString
  198. // bind(2) man page: If name is zero, everything bound or mounted upon old is unbound or unmounted.
  199. if name == "" {
  200. r0, _, e = Syscall(SYS_UNMOUNT, _zero, oldptr, 0)
  201. } else {
  202. namep, err := BytePtrFromString(name)
  203. if err != nil {
  204. return err
  205. }
  206. r0, _, e = Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(namep)), oldptr, 0)
  207. }
  208. if int32(r0) == -1 {
  209. err = e
  210. }
  211. return
  212. }
  213. func Fchdir(fd int) (err error) {
  214. path, err := Fd2path(fd)
  215. if err != nil {
  216. return
  217. }
  218. return Chdir(path)
  219. }
  220. type Timespec struct {
  221. Sec int32
  222. Nsec int32
  223. }
  224. type Timeval struct {
  225. Sec int32
  226. Usec int32
  227. }
  228. func NsecToTimeval(nsec int64) (tv Timeval) {
  229. nsec += 999 // round up to microsecond
  230. tv.Usec = int32(nsec % 1e9 / 1e3)
  231. tv.Sec = int32(nsec / 1e9)
  232. return
  233. }
  234. func nsec() int64 {
  235. var scratch int64
  236. r0, _, _ := Syscall(SYS_NSEC, uintptr(unsafe.Pointer(&scratch)), 0, 0)
  237. // TODO(aram): remove hack after I fix _nsec in the pc64 kernel.
  238. if r0 == 0 {
  239. return scratch
  240. }
  241. return int64(r0)
  242. }
  243. func Gettimeofday(tv *Timeval) error {
  244. nsec := nsec()
  245. *tv = NsecToTimeval(nsec)
  246. return nil
  247. }
  248. func Getpagesize() int { return 0x1000 }
  249. func Getegid() (egid int) { return -1 }
  250. func Geteuid() (euid int) { return -1 }
  251. func Getgid() (gid int) { return -1 }
  252. func Getuid() (uid int) { return -1 }
  253. func Getgroups() (gids []int, err error) {
  254. return make([]int, 0), nil
  255. }
  256. //sys Dup(oldfd int, newfd int) (fd int, err error)
  257. //sys Open(path string, mode int) (fd int, err error)
  258. //sys Create(path string, mode int, perm uint32) (fd int, err error)
  259. //sys Remove(path string) (err error)
  260. //sys Pread(fd int, p []byte, offset int64) (n int, err error)
  261. //sys Pwrite(fd int, p []byte, offset int64) (n int, err error)
  262. //sys Close(fd int) (err error)
  263. //sys Chdir(path string) (err error)
  264. //sys Bind(name string, old string, flag int) (err error)
  265. //sys Mount(fd int, afd int, old string, flag int, aname string) (err error)
  266. //sys Stat(path string, edir []byte) (n int, err error)
  267. //sys Fstat(fd int, edir []byte) (n int, err error)
  268. //sys Wstat(path string, edir []byte) (err error)
  269. //sys Fwstat(fd int, edir []byte) (err error)