fs_nacl.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832
  1. // Copyright 2013 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. // A simulated Unix-like file system for use within NaCl.
  5. //
  6. // The simulation is not particularly tied to NaCl other than the reuse
  7. // of NaCl's definition for the Stat_t structure.
  8. //
  9. // The file system need never be written to disk, so it is represented as
  10. // in-memory Go data structures, never in a serialized form.
  11. //
  12. // TODO: Perhaps support symlinks, although they muck everything up.
  13. package unix
  14. import (
  15. "sync"
  16. "unsafe"
  17. )
  18. // Provided by package runtime.
  19. func now() (sec int64, nsec int32)
  20. // An fsys is a file system.
  21. // Since there is no I/O (everything is in memory),
  22. // the global lock mu protects the whole file system state,
  23. // and that's okay.
  24. type fsys struct {
  25. mu sync.Mutex
  26. root *inode // root directory
  27. cwd *inode // process current directory
  28. inum uint64 // number of inodes created
  29. dev []func() (devFile, error) // table for opening devices
  30. }
  31. // A devFile is the implementation required of device files
  32. // like /dev/null or /dev/random.
  33. type devFile interface {
  34. pread([]byte, int64) (int, error)
  35. pwrite([]byte, int64) (int, error)
  36. }
  37. // An inode is a (possibly special) file in the file system.
  38. type inode struct {
  39. Stat_t
  40. data []byte
  41. dir []dirent
  42. }
  43. // A dirent describes a single directory entry.
  44. type dirent struct {
  45. name string
  46. inode *inode
  47. }
  48. // An fsysFile is the fileImpl implementation backed by the file system.
  49. type fsysFile struct {
  50. defaultFileImpl
  51. fsys *fsys
  52. inode *inode
  53. openmode int
  54. offset int64
  55. dev devFile
  56. }
  57. // newFsys creates a new file system.
  58. func newFsys() *fsys {
  59. fs := &fsys{}
  60. fs.mu.Lock()
  61. defer fs.mu.Unlock()
  62. ip := fs.newInode()
  63. ip.Mode = 0555 | S_IFDIR
  64. fs.dirlink(ip, ".", ip)
  65. fs.dirlink(ip, "..", ip)
  66. fs.cwd = ip
  67. fs.root = ip
  68. return fs
  69. }
  70. var fs = newFsys()
  71. var fsinit = func() {}
  72. func init() {
  73. // do not trigger loading of zipped file system here
  74. oldFsinit := fsinit
  75. defer func() { fsinit = oldFsinit }()
  76. fsinit = func() {}
  77. Mkdir("/dev", 0555)
  78. Mkdir("/tmp", 0777)
  79. mkdev("/dev/null", 0666, openNull)
  80. mkdev("/dev/random", 0444, openRandom)
  81. mkdev("/dev/urandom", 0444, openRandom)
  82. mkdev("/dev/zero", 0666, openZero)
  83. chdirEnv()
  84. }
  85. func chdirEnv() {
  86. pwd, ok := Getenv("NACLPWD")
  87. if ok {
  88. chdir(pwd)
  89. }
  90. }
  91. // Except where indicated otherwise, unexported methods on fsys
  92. // expect fs.mu to have been locked by the caller.
  93. // newInode creates a new inode.
  94. func (fs *fsys) newInode() *inode {
  95. fs.inum++
  96. ip := &inode{
  97. Stat_t: Stat_t{
  98. Ino: fs.inum,
  99. Blksize: 512,
  100. },
  101. }
  102. return ip
  103. }
  104. // atime sets ip.Atime to the current time.
  105. func (fs *fsys) atime(ip *inode) {
  106. sec, nsec := now()
  107. ip.Atime, ip.AtimeNsec = sec, int64(nsec)
  108. }
  109. // mtime sets ip.Mtime to the current time.
  110. func (fs *fsys) mtime(ip *inode) {
  111. sec, nsec := now()
  112. ip.Mtime, ip.MtimeNsec = sec, int64(nsec)
  113. }
  114. // dirlookup looks for an entry in the directory dp with the given name.
  115. // It returns the directory entry and its index within the directory.
  116. func (fs *fsys) dirlookup(dp *inode, name string) (de *dirent, index int, err error) {
  117. fs.atime(dp)
  118. for i := range dp.dir {
  119. de := &dp.dir[i]
  120. if de.name == name {
  121. fs.atime(de.inode)
  122. return de, i, nil
  123. }
  124. }
  125. return nil, 0, ENOENT
  126. }
  127. // dirlink adds to the directory dp an entry for name pointing at the inode ip.
  128. // If dp already contains an entry for name, that entry is overwritten.
  129. func (fs *fsys) dirlink(dp *inode, name string, ip *inode) {
  130. fs.mtime(dp)
  131. fs.atime(ip)
  132. ip.Nlink++
  133. for i := range dp.dir {
  134. if dp.dir[i].name == name {
  135. dp.dir[i] = dirent{name, ip}
  136. return
  137. }
  138. }
  139. dp.dir = append(dp.dir, dirent{name, ip})
  140. dp.dirSize()
  141. }
  142. func (dp *inode) dirSize() {
  143. dp.Size = int64(len(dp.dir)) * (8 + 8 + 2 + 256) // Dirent
  144. }
  145. // skipelem splits path into the first element and the remainder.
  146. // the returned first element contains no slashes, and the returned
  147. // remainder does not begin with a slash.
  148. func skipelem(path string) (elem, rest string) {
  149. for len(path) > 0 && path[0] == '/' {
  150. path = path[1:]
  151. }
  152. if len(path) == 0 {
  153. return "", ""
  154. }
  155. i := 0
  156. for i < len(path) && path[i] != '/' {
  157. i++
  158. }
  159. elem, path = path[:i], path[i:]
  160. for len(path) > 0 && path[0] == '/' {
  161. path = path[1:]
  162. }
  163. return elem, path
  164. }
  165. // namei translates a file system path name into an inode.
  166. // If parent is false, the returned ip corresponds to the given name, and elem is the empty string.
  167. // If parent is true, the walk stops at the next-to-last element in the name,
  168. // so that ip is the parent directory and elem is the final element in the path.
  169. func (fs *fsys) namei(path string, parent bool) (ip *inode, elem string, err error) {
  170. // Reject NUL in name.
  171. for i := 0; i < len(path); i++ {
  172. if path[i] == '\x00' {
  173. return nil, "", EINVAL
  174. }
  175. }
  176. // Reject empty name.
  177. if path == "" {
  178. return nil, "", EINVAL
  179. }
  180. if path[0] == '/' {
  181. ip = fs.root
  182. } else {
  183. ip = fs.cwd
  184. }
  185. for len(path) > 0 && path[len(path)-1] == '/' {
  186. path = path[:len(path)-1]
  187. }
  188. for {
  189. elem, rest := skipelem(path)
  190. if elem == "" {
  191. if parent && ip.Mode&S_IFMT == S_IFDIR {
  192. return ip, ".", nil
  193. }
  194. break
  195. }
  196. if ip.Mode&S_IFMT != S_IFDIR {
  197. return nil, "", ENOTDIR
  198. }
  199. if len(elem) >= 256 {
  200. return nil, "", ENAMETOOLONG
  201. }
  202. if parent && rest == "" {
  203. // Stop one level early.
  204. return ip, elem, nil
  205. }
  206. de, _, err := fs.dirlookup(ip, elem)
  207. if err != nil {
  208. return nil, "", err
  209. }
  210. ip = de.inode
  211. path = rest
  212. }
  213. if parent {
  214. return nil, "", ENOTDIR
  215. }
  216. return ip, "", nil
  217. }
  218. // open opens or creates a file with the given name, open mode,
  219. // and permission mode bits.
  220. func (fs *fsys) open(name string, openmode int, mode uint32) (fileImpl, error) {
  221. dp, elem, err := fs.namei(name, true)
  222. if err != nil {
  223. return nil, err
  224. }
  225. var (
  226. ip *inode
  227. dev devFile
  228. )
  229. de, _, err := fs.dirlookup(dp, elem)
  230. if err != nil {
  231. if openmode&O_CREATE == 0 {
  232. return nil, err
  233. }
  234. ip = fs.newInode()
  235. ip.Mode = mode
  236. fs.dirlink(dp, elem, ip)
  237. if ip.Mode&S_IFMT == S_IFDIR {
  238. fs.dirlink(ip, ".", ip)
  239. fs.dirlink(ip, "..", dp)
  240. }
  241. } else {
  242. ip = de.inode
  243. if openmode&(O_CREATE|O_EXCL) == O_CREATE|O_EXCL {
  244. return nil, EEXIST
  245. }
  246. if openmode&O_TRUNC != 0 {
  247. if ip.Mode&S_IFMT == S_IFDIR {
  248. return nil, EISDIR
  249. }
  250. ip.data = nil
  251. }
  252. if ip.Mode&S_IFMT == S_IFCHR {
  253. if ip.Rdev < 0 || ip.Rdev >= int64(len(fs.dev)) || fs.dev[ip.Rdev] == nil {
  254. return nil, ENODEV
  255. }
  256. dev, err = fs.dev[ip.Rdev]()
  257. if err != nil {
  258. return nil, err
  259. }
  260. }
  261. }
  262. switch openmode & O_ACCMODE {
  263. case O_WRONLY, O_RDWR:
  264. if ip.Mode&S_IFMT == S_IFDIR {
  265. return nil, EISDIR
  266. }
  267. }
  268. switch ip.Mode & S_IFMT {
  269. case S_IFDIR:
  270. if openmode&O_ACCMODE != O_RDONLY {
  271. return nil, EISDIR
  272. }
  273. case S_IFREG:
  274. // ok
  275. case S_IFCHR:
  276. // handled above
  277. default:
  278. // TODO: some kind of special file
  279. return nil, EPERM
  280. }
  281. f := &fsysFile{
  282. fsys: fs,
  283. inode: ip,
  284. openmode: openmode,
  285. dev: dev,
  286. }
  287. if openmode&O_APPEND != 0 {
  288. f.offset = ip.Size
  289. }
  290. return f, nil
  291. }
  292. // fsysFile methods to implement fileImpl.
  293. func (f *fsysFile) stat(st *Stat_t) error {
  294. f.fsys.mu.Lock()
  295. defer f.fsys.mu.Unlock()
  296. *st = f.inode.Stat_t
  297. return nil
  298. }
  299. func (f *fsysFile) read(b []byte) (int, error) {
  300. f.fsys.mu.Lock()
  301. defer f.fsys.mu.Unlock()
  302. n, err := f.preadLocked(b, f.offset)
  303. f.offset += int64(n)
  304. return n, err
  305. }
  306. func ReadDirent(fd int, buf []byte) (int, error) {
  307. f, err := fdToFsysFile(fd)
  308. if err != nil {
  309. return 0, err
  310. }
  311. f.fsys.mu.Lock()
  312. defer f.fsys.mu.Unlock()
  313. if f.inode.Mode&S_IFMT != S_IFDIR {
  314. return 0, EINVAL
  315. }
  316. n, err := f.preadLocked(buf, f.offset)
  317. f.offset += int64(n)
  318. return n, err
  319. }
  320. func (f *fsysFile) write(b []byte) (int, error) {
  321. f.fsys.mu.Lock()
  322. defer f.fsys.mu.Unlock()
  323. n, err := f.pwriteLocked(b, f.offset)
  324. f.offset += int64(n)
  325. return n, err
  326. }
  327. func (f *fsysFile) seek(offset int64, whence int) (int64, error) {
  328. f.fsys.mu.Lock()
  329. defer f.fsys.mu.Unlock()
  330. switch whence {
  331. case 1:
  332. offset += f.offset
  333. case 2:
  334. offset += f.inode.Size
  335. }
  336. if offset < 0 {
  337. return 0, EINVAL
  338. }
  339. if offset > f.inode.Size {
  340. return 0, EINVAL
  341. }
  342. f.offset = offset
  343. return offset, nil
  344. }
  345. func (f *fsysFile) pread(b []byte, offset int64) (int, error) {
  346. f.fsys.mu.Lock()
  347. defer f.fsys.mu.Unlock()
  348. return f.preadLocked(b, offset)
  349. }
  350. func (f *fsysFile) pwrite(b []byte, offset int64) (int, error) {
  351. f.fsys.mu.Lock()
  352. defer f.fsys.mu.Unlock()
  353. return f.pwriteLocked(b, offset)
  354. }
  355. func (f *fsysFile) preadLocked(b []byte, offset int64) (int, error) {
  356. if f.openmode&O_ACCMODE == O_WRONLY {
  357. return 0, EINVAL
  358. }
  359. if offset < 0 {
  360. return 0, EINVAL
  361. }
  362. if f.dev != nil {
  363. f.fsys.atime(f.inode)
  364. f.fsys.mu.Unlock()
  365. defer f.fsys.mu.Lock()
  366. return f.dev.pread(b, offset)
  367. }
  368. if offset > f.inode.Size {
  369. return 0, nil
  370. }
  371. if int64(len(b)) > f.inode.Size-offset {
  372. b = b[:f.inode.Size-offset]
  373. }
  374. if f.inode.Mode&S_IFMT == S_IFDIR {
  375. if offset%direntSize != 0 || len(b) != 0 && len(b) < direntSize {
  376. return 0, EINVAL
  377. }
  378. fs.atime(f.inode)
  379. n := 0
  380. for len(b) >= direntSize {
  381. src := f.inode.dir[int(offset/direntSize)]
  382. dst := (*Dirent)(unsafe.Pointer(&b[0]))
  383. dst.Ino = int64(src.inode.Ino)
  384. dst.Off = offset
  385. dst.Reclen = direntSize
  386. for i := range dst.Name {
  387. dst.Name[i] = 0
  388. }
  389. copy(dst.Name[:], src.name)
  390. n += direntSize
  391. offset += direntSize
  392. b = b[direntSize:]
  393. }
  394. return n, nil
  395. }
  396. fs.atime(f.inode)
  397. n := copy(b, f.inode.data[offset:])
  398. return n, nil
  399. }
  400. func (f *fsysFile) pwriteLocked(b []byte, offset int64) (int, error) {
  401. if f.openmode&O_ACCMODE == O_RDONLY {
  402. return 0, EINVAL
  403. }
  404. if offset < 0 {
  405. return 0, EINVAL
  406. }
  407. if f.dev != nil {
  408. f.fsys.atime(f.inode)
  409. f.fsys.mu.Unlock()
  410. defer f.fsys.mu.Lock()
  411. return f.dev.pwrite(b, offset)
  412. }
  413. if offset > f.inode.Size {
  414. return 0, EINVAL
  415. }
  416. f.fsys.mtime(f.inode)
  417. n := copy(f.inode.data[offset:], b)
  418. if n < len(b) {
  419. f.inode.data = append(f.inode.data, b[n:]...)
  420. f.inode.Size = int64(len(f.inode.data))
  421. }
  422. return len(b), nil
  423. }
  424. // Standard Unix system calls.
  425. func Open(path string, openmode int, perm uint32) (fd int, err error) {
  426. fsinit()
  427. fs.mu.Lock()
  428. defer fs.mu.Unlock()
  429. f, err := fs.open(path, openmode, perm&0777|S_IFREG)
  430. if err != nil {
  431. return -1, err
  432. }
  433. return newFD(f), nil
  434. }
  435. func Mkdir(path string, perm uint32) error {
  436. fs.mu.Lock()
  437. defer fs.mu.Unlock()
  438. _, err := fs.open(path, O_CREATE|O_EXCL, perm&0777|S_IFDIR)
  439. return err
  440. }
  441. func Getcwd(buf []byte) (n int, err error) {
  442. // Force package os to default to the old algorithm using .. and directory reads.
  443. return 0, ENOSYS
  444. }
  445. func Stat(path string, st *Stat_t) error {
  446. fsinit()
  447. fs.mu.Lock()
  448. defer fs.mu.Unlock()
  449. ip, _, err := fs.namei(path, false)
  450. if err != nil {
  451. return err
  452. }
  453. *st = ip.Stat_t
  454. return nil
  455. }
  456. func Lstat(path string, st *Stat_t) error {
  457. return Stat(path, st)
  458. }
  459. func unlink(path string, isdir bool) error {
  460. fsinit()
  461. fs.mu.Lock()
  462. defer fs.mu.Unlock()
  463. dp, elem, err := fs.namei(path, true)
  464. if err != nil {
  465. return err
  466. }
  467. if elem == "." || elem == ".." {
  468. return EINVAL
  469. }
  470. de, _, err := fs.dirlookup(dp, elem)
  471. if err != nil {
  472. return err
  473. }
  474. if isdir {
  475. if de.inode.Mode&S_IFMT != S_IFDIR {
  476. return ENOTDIR
  477. }
  478. if len(de.inode.dir) != 2 {
  479. return ENOTEMPTY
  480. }
  481. } else {
  482. if de.inode.Mode&S_IFMT == S_IFDIR {
  483. return EISDIR
  484. }
  485. }
  486. de.inode.Nlink--
  487. *de = dp.dir[len(dp.dir)-1]
  488. dp.dir = dp.dir[:len(dp.dir)-1]
  489. dp.dirSize()
  490. return nil
  491. }
  492. func Unlink(path string) error {
  493. return unlink(path, false)
  494. }
  495. func Rmdir(path string) error {
  496. return unlink(path, true)
  497. }
  498. func Chmod(path string, mode uint32) error {
  499. fsinit()
  500. fs.mu.Lock()
  501. defer fs.mu.Unlock()
  502. ip, _, err := fs.namei(path, false)
  503. if err != nil {
  504. return err
  505. }
  506. ip.Mode = ip.Mode&^0777 | mode&0777
  507. return nil
  508. }
  509. func Fchmod(fd int, mode uint32) error {
  510. f, err := fdToFsysFile(fd)
  511. if err != nil {
  512. return err
  513. }
  514. f.fsys.mu.Lock()
  515. defer f.fsys.mu.Unlock()
  516. f.inode.Mode = f.inode.Mode&^0777 | mode&0777
  517. return nil
  518. }
  519. func Chown(path string, uid, gid int) error {
  520. fsinit()
  521. fs.mu.Lock()
  522. defer fs.mu.Unlock()
  523. ip, _, err := fs.namei(path, false)
  524. if err != nil {
  525. return err
  526. }
  527. ip.Uid = uint32(uid)
  528. ip.Gid = uint32(gid)
  529. return nil
  530. }
  531. func Fchown(fd int, uid, gid int) error {
  532. fs.mu.Lock()
  533. defer fs.mu.Unlock()
  534. f, err := fdToFsysFile(fd)
  535. if err != nil {
  536. return err
  537. }
  538. f.fsys.mu.Lock()
  539. defer f.fsys.mu.Unlock()
  540. f.inode.Uid = uint32(uid)
  541. f.inode.Gid = uint32(gid)
  542. return nil
  543. }
  544. func Lchown(path string, uid, gid int) error {
  545. return Chown(path, uid, gid)
  546. }
  547. func UtimesNano(path string, ts []Timespec) error {
  548. if len(ts) != 2 {
  549. return EINVAL
  550. }
  551. fsinit()
  552. fs.mu.Lock()
  553. defer fs.mu.Unlock()
  554. ip, _, err := fs.namei(path, false)
  555. if err != nil {
  556. return err
  557. }
  558. ip.Atime = ts[0].Sec
  559. ip.AtimeNsec = int64(ts[0].Nsec)
  560. ip.Mtime = ts[1].Sec
  561. ip.MtimeNsec = int64(ts[1].Nsec)
  562. return nil
  563. }
  564. func Link(path, link string) error {
  565. fsinit()
  566. ip, _, err := fs.namei(path, false)
  567. if err != nil {
  568. return err
  569. }
  570. dp, elem, err := fs.namei(link, true)
  571. if err != nil {
  572. return err
  573. }
  574. if ip.Mode&S_IFMT == S_IFDIR {
  575. return EPERM
  576. }
  577. fs.dirlink(dp, elem, ip)
  578. return nil
  579. }
  580. func Rename(from, to string) error {
  581. fsinit()
  582. fdp, felem, err := fs.namei(from, true)
  583. if err != nil {
  584. return err
  585. }
  586. fde, _, err := fs.dirlookup(fdp, felem)
  587. if err != nil {
  588. return err
  589. }
  590. tdp, telem, err := fs.namei(to, true)
  591. if err != nil {
  592. return err
  593. }
  594. fs.dirlink(tdp, telem, fde.inode)
  595. fde.inode.Nlink--
  596. *fde = fdp.dir[len(fdp.dir)-1]
  597. fdp.dir = fdp.dir[:len(fdp.dir)-1]
  598. fdp.dirSize()
  599. return nil
  600. }
  601. func (fs *fsys) truncate(ip *inode, length int64) error {
  602. if length > 1e9 || ip.Mode&S_IFMT != S_IFREG {
  603. return EINVAL
  604. }
  605. if length < int64(len(ip.data)) {
  606. ip.data = ip.data[:length]
  607. } else {
  608. data := make([]byte, length)
  609. copy(data, ip.data)
  610. ip.data = data
  611. }
  612. ip.Size = int64(len(ip.data))
  613. return nil
  614. }
  615. func Truncate(path string, length int64) error {
  616. fsinit()
  617. fs.mu.Lock()
  618. defer fs.mu.Unlock()
  619. ip, _, err := fs.namei(path, false)
  620. if err != nil {
  621. return err
  622. }
  623. return fs.truncate(ip, length)
  624. }
  625. func Ftruncate(fd int, length int64) error {
  626. f, err := fdToFsysFile(fd)
  627. if err != nil {
  628. return err
  629. }
  630. f.fsys.mu.Lock()
  631. defer f.fsys.mu.Unlock()
  632. return f.fsys.truncate(f.inode, length)
  633. }
  634. func Chdir(path string) error {
  635. fsinit()
  636. return chdir(path)
  637. }
  638. func chdir(path string) error {
  639. fs.mu.Lock()
  640. defer fs.mu.Unlock()
  641. ip, _, err := fs.namei(path, false)
  642. if err != nil {
  643. return err
  644. }
  645. fs.cwd = ip
  646. return nil
  647. }
  648. func Fchdir(fd int) error {
  649. f, err := fdToFsysFile(fd)
  650. if err != nil {
  651. return err
  652. }
  653. f.fsys.mu.Lock()
  654. defer f.fsys.mu.Unlock()
  655. if f.inode.Mode&S_IFMT != S_IFDIR {
  656. return ENOTDIR
  657. }
  658. fs.cwd = f.inode
  659. return nil
  660. }
  661. func Readlink(path string, buf []byte) (n int, err error) {
  662. return 0, ENOSYS
  663. }
  664. func Symlink(path, link string) error {
  665. return ENOSYS
  666. }
  667. func Fsync(fd int) error {
  668. return nil
  669. }
  670. // Special devices.
  671. func mkdev(path string, mode uint32, open func() (devFile, error)) error {
  672. f, err := fs.open(path, O_CREATE|O_RDONLY|O_EXCL, S_IFCHR|mode)
  673. if err != nil {
  674. return err
  675. }
  676. ip := f.(*fsysFile).inode
  677. ip.Rdev = int64(len(fs.dev))
  678. fs.dev = append(fs.dev, open)
  679. return nil
  680. }
  681. type nullFile struct{}
  682. func openNull() (devFile, error) { return &nullFile{}, nil }
  683. func (f *nullFile) close() error { return nil }
  684. func (f *nullFile) pread(b []byte, offset int64) (int, error) { return 0, nil }
  685. func (f *nullFile) pwrite(b []byte, offset int64) (int, error) { return len(b), nil }
  686. type zeroFile struct{}
  687. func openZero() (devFile, error) { return &zeroFile{}, nil }
  688. func (f *zeroFile) close() error { return nil }
  689. func (f *zeroFile) pwrite(b []byte, offset int64) (int, error) { return len(b), nil }
  690. func (f *zeroFile) pread(b []byte, offset int64) (int, error) {
  691. for i := range b {
  692. b[i] = 0
  693. }
  694. return len(b), nil
  695. }
  696. type randomFile struct {
  697. naclFD int
  698. }
  699. func openRandom() (devFile, error) {
  700. fd, err := openNamedService("SecureRandom", O_RDONLY)
  701. if err != nil {
  702. return nil, err
  703. }
  704. return &randomFile{naclFD: fd}, nil
  705. }
  706. func (f *randomFile) close() error {
  707. naclClose(f.naclFD)
  708. f.naclFD = -1
  709. return nil
  710. }
  711. func (f *randomFile) pread(b []byte, offset int64) (int, error) {
  712. return naclRead(f.naclFD, b)
  713. }
  714. func (f *randomFile) pwrite(b []byte, offset int64) (int, error) {
  715. return 0, EPERM
  716. }
  717. func fdToFsysFile(fd int) (*fsysFile, error) {
  718. f, err := fdToFile(fd)
  719. if err != nil {
  720. return nil, err
  721. }
  722. impl := f.impl
  723. fsysf, ok := impl.(*fsysFile)
  724. if !ok {
  725. return nil, EINVAL
  726. }
  727. return fsysf, nil
  728. }
  729. // create creates a file in the file system with the given name, mode, time, and data.
  730. // It is meant to be called when initializing the file system image.
  731. func create(name string, mode uint32, sec int64, data []byte) error {
  732. fs.mu.Lock()
  733. fs.mu.Unlock()
  734. f, err := fs.open(name, O_CREATE|O_EXCL, mode)
  735. if err != nil {
  736. return err
  737. }
  738. ip := f.(*fsysFile).inode
  739. ip.Atime = sec
  740. ip.Mtime = sec
  741. ip.Ctime = sec
  742. if len(data) > 0 {
  743. ip.Size = int64(len(data))
  744. ip.data = data
  745. }
  746. return nil
  747. }