conversions.go 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890
  1. // Copyright 2015 Google Inc. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package fuse
  15. import (
  16. "bytes"
  17. "errors"
  18. "fmt"
  19. "os"
  20. "reflect"
  21. "syscall"
  22. "time"
  23. "unsafe"
  24. "github.com/jacobsa/fuse/fuseops"
  25. "github.com/jacobsa/fuse/internal/buffer"
  26. "github.com/jacobsa/fuse/internal/fusekernel"
  27. )
  28. ////////////////////////////////////////////////////////////////////////
  29. // Incoming messages
  30. ////////////////////////////////////////////////////////////////////////
  31. // Convert a kernel message to an appropriate op. If the op is unknown, a
  32. // special unexported type will be used.
  33. //
  34. // The caller is responsible for arranging for the message to be destroyed.
  35. func convertInMessage(
  36. inMsg *buffer.InMessage,
  37. outMsg *buffer.OutMessage,
  38. protocol fusekernel.Protocol) (o interface{}, err error) {
  39. switch inMsg.Header().Opcode {
  40. case fusekernel.OpLookup:
  41. buf := inMsg.ConsumeBytes(inMsg.Len())
  42. n := len(buf)
  43. if n == 0 || buf[n-1] != '\x00' {
  44. err = errors.New("Corrupt OpLookup")
  45. return
  46. }
  47. o = &fuseops.LookUpInodeOp{
  48. Parent: fuseops.InodeID(inMsg.Header().Nodeid),
  49. Name: string(buf[:n-1]),
  50. }
  51. case fusekernel.OpGetattr:
  52. o = &fuseops.GetInodeAttributesOp{
  53. Inode: fuseops.InodeID(inMsg.Header().Nodeid),
  54. }
  55. case fusekernel.OpSetattr:
  56. type input fusekernel.SetattrIn
  57. in := (*input)(inMsg.Consume(unsafe.Sizeof(input{})))
  58. if in == nil {
  59. err = errors.New("Corrupt OpSetattr")
  60. return
  61. }
  62. to := &fuseops.SetInodeAttributesOp{
  63. Inode: fuseops.InodeID(inMsg.Header().Nodeid),
  64. }
  65. o = to
  66. valid := fusekernel.SetattrValid(in.Valid)
  67. if valid&fusekernel.SetattrSize != 0 {
  68. to.Size = &in.Size
  69. }
  70. if valid&fusekernel.SetattrMode != 0 {
  71. mode := convertFileMode(in.Mode)
  72. to.Mode = &mode
  73. }
  74. if valid&fusekernel.SetattrAtime != 0 {
  75. t := time.Unix(int64(in.Atime), int64(in.AtimeNsec))
  76. to.Atime = &t
  77. }
  78. if valid&fusekernel.SetattrMtime != 0 {
  79. t := time.Unix(int64(in.Mtime), int64(in.MtimeNsec))
  80. to.Mtime = &t
  81. }
  82. case fusekernel.OpForget:
  83. type input fusekernel.ForgetIn
  84. in := (*input)(inMsg.Consume(unsafe.Sizeof(input{})))
  85. if in == nil {
  86. err = errors.New("Corrupt OpForget")
  87. return
  88. }
  89. o = &fuseops.ForgetInodeOp{
  90. Inode: fuseops.InodeID(inMsg.Header().Nodeid),
  91. N: in.Nlookup,
  92. }
  93. case fusekernel.OpMkdir:
  94. in := (*fusekernel.MkdirIn)(inMsg.Consume(fusekernel.MkdirInSize(protocol)))
  95. if in == nil {
  96. err = errors.New("Corrupt OpMkdir")
  97. return
  98. }
  99. name := inMsg.ConsumeBytes(inMsg.Len())
  100. i := bytes.IndexByte(name, '\x00')
  101. if i < 0 {
  102. err = errors.New("Corrupt OpMkdir")
  103. return
  104. }
  105. name = name[:i]
  106. o = &fuseops.MkDirOp{
  107. Parent: fuseops.InodeID(inMsg.Header().Nodeid),
  108. Name: string(name),
  109. // On Linux, vfs_mkdir calls through to the inode with at most
  110. // permissions and sticky bits set (cf. https://goo.gl/WxgQXk), and fuse
  111. // passes that on directly (cf. https://goo.gl/f31aMo). In other words,
  112. // the fact that this is a directory is implicit in the fact that the
  113. // opcode is mkdir. But we want the correct mode to go through, so ensure
  114. // that os.ModeDir is set.
  115. Mode: convertFileMode(in.Mode) | os.ModeDir,
  116. }
  117. case fusekernel.OpMknod:
  118. in := (*fusekernel.MknodIn)(inMsg.Consume(fusekernel.MknodInSize(protocol)))
  119. if in == nil {
  120. err = errors.New("Corrupt OpMknod")
  121. return
  122. }
  123. name := inMsg.ConsumeBytes(inMsg.Len())
  124. i := bytes.IndexByte(name, '\x00')
  125. if i < 0 {
  126. err = errors.New("Corrupt OpMknod")
  127. return
  128. }
  129. name = name[:i]
  130. o = &fuseops.MkNodeOp{
  131. Parent: fuseops.InodeID(inMsg.Header().Nodeid),
  132. Name: string(name),
  133. Mode: convertFileMode(in.Mode),
  134. }
  135. case fusekernel.OpCreate:
  136. in := (*fusekernel.CreateIn)(inMsg.Consume(fusekernel.CreateInSize(protocol)))
  137. if in == nil {
  138. err = errors.New("Corrupt OpCreate")
  139. return
  140. }
  141. name := inMsg.ConsumeBytes(inMsg.Len())
  142. i := bytes.IndexByte(name, '\x00')
  143. if i < 0 {
  144. err = errors.New("Corrupt OpCreate")
  145. return
  146. }
  147. name = name[:i]
  148. o = &fuseops.CreateFileOp{
  149. Parent: fuseops.InodeID(inMsg.Header().Nodeid),
  150. Name: string(name),
  151. Mode: convertFileMode(in.Mode),
  152. }
  153. case fusekernel.OpSymlink:
  154. // The message is "newName\0target\0".
  155. names := inMsg.ConsumeBytes(inMsg.Len())
  156. if len(names) == 0 || names[len(names)-1] != 0 {
  157. err = errors.New("Corrupt OpSymlink")
  158. return
  159. }
  160. i := bytes.IndexByte(names, '\x00')
  161. if i < 0 {
  162. err = errors.New("Corrupt OpSymlink")
  163. return
  164. }
  165. newName, target := names[0:i], names[i+1:len(names)-1]
  166. o = &fuseops.CreateSymlinkOp{
  167. Parent: fuseops.InodeID(inMsg.Header().Nodeid),
  168. Name: string(newName),
  169. Target: string(target),
  170. }
  171. case fusekernel.OpRename:
  172. type input fusekernel.RenameIn
  173. in := (*input)(inMsg.Consume(unsafe.Sizeof(input{})))
  174. if in == nil {
  175. err = errors.New("Corrupt OpRename")
  176. return
  177. }
  178. names := inMsg.ConsumeBytes(inMsg.Len())
  179. // names should be "old\x00new\x00"
  180. if len(names) < 4 {
  181. err = errors.New("Corrupt OpRename")
  182. return
  183. }
  184. if names[len(names)-1] != '\x00' {
  185. err = errors.New("Corrupt OpRename")
  186. return
  187. }
  188. i := bytes.IndexByte(names, '\x00')
  189. if i < 0 {
  190. err = errors.New("Corrupt OpRename")
  191. return
  192. }
  193. oldName, newName := names[:i], names[i+1:len(names)-1]
  194. o = &fuseops.RenameOp{
  195. OldParent: fuseops.InodeID(inMsg.Header().Nodeid),
  196. OldName: string(oldName),
  197. NewParent: fuseops.InodeID(in.Newdir),
  198. NewName: string(newName),
  199. }
  200. case fusekernel.OpUnlink:
  201. buf := inMsg.ConsumeBytes(inMsg.Len())
  202. n := len(buf)
  203. if n == 0 || buf[n-1] != '\x00' {
  204. err = errors.New("Corrupt OpUnlink")
  205. return
  206. }
  207. o = &fuseops.UnlinkOp{
  208. Parent: fuseops.InodeID(inMsg.Header().Nodeid),
  209. Name: string(buf[:n-1]),
  210. }
  211. case fusekernel.OpRmdir:
  212. buf := inMsg.ConsumeBytes(inMsg.Len())
  213. n := len(buf)
  214. if n == 0 || buf[n-1] != '\x00' {
  215. err = errors.New("Corrupt OpRmdir")
  216. return
  217. }
  218. o = &fuseops.RmDirOp{
  219. Parent: fuseops.InodeID(inMsg.Header().Nodeid),
  220. Name: string(buf[:n-1]),
  221. }
  222. case fusekernel.OpOpen:
  223. o = &fuseops.OpenFileOp{
  224. Inode: fuseops.InodeID(inMsg.Header().Nodeid),
  225. }
  226. case fusekernel.OpOpendir:
  227. o = &fuseops.OpenDirOp{
  228. Inode: fuseops.InodeID(inMsg.Header().Nodeid),
  229. }
  230. case fusekernel.OpRead:
  231. in := (*fusekernel.ReadIn)(inMsg.Consume(fusekernel.ReadInSize(protocol)))
  232. if in == nil {
  233. err = errors.New("Corrupt OpRead")
  234. return
  235. }
  236. to := &fuseops.ReadFileOp{
  237. Inode: fuseops.InodeID(inMsg.Header().Nodeid),
  238. Handle: fuseops.HandleID(in.Fh),
  239. Offset: int64(in.Offset),
  240. }
  241. o = to
  242. readSize := int(in.Size)
  243. p := outMsg.GrowNoZero(readSize)
  244. if p == nil {
  245. err = fmt.Errorf("Can't grow for %d-byte read", readSize)
  246. return
  247. }
  248. sh := (*reflect.SliceHeader)(unsafe.Pointer(&to.Dst))
  249. sh.Data = uintptr(p)
  250. sh.Len = readSize
  251. sh.Cap = readSize
  252. case fusekernel.OpReaddir:
  253. in := (*fusekernel.ReadIn)(inMsg.Consume(fusekernel.ReadInSize(protocol)))
  254. if in == nil {
  255. err = errors.New("Corrupt OpReaddir")
  256. return
  257. }
  258. to := &fuseops.ReadDirOp{
  259. Inode: fuseops.InodeID(inMsg.Header().Nodeid),
  260. Handle: fuseops.HandleID(in.Fh),
  261. Offset: fuseops.DirOffset(in.Offset),
  262. }
  263. o = to
  264. readSize := int(in.Size)
  265. p := outMsg.GrowNoZero(readSize)
  266. if p == nil {
  267. err = fmt.Errorf("Can't grow for %d-byte read", readSize)
  268. return
  269. }
  270. sh := (*reflect.SliceHeader)(unsafe.Pointer(&to.Dst))
  271. sh.Data = uintptr(p)
  272. sh.Len = readSize
  273. sh.Cap = readSize
  274. case fusekernel.OpRelease:
  275. type input fusekernel.ReleaseIn
  276. in := (*input)(inMsg.Consume(unsafe.Sizeof(input{})))
  277. if in == nil {
  278. err = errors.New("Corrupt OpRelease")
  279. return
  280. }
  281. o = &fuseops.ReleaseFileHandleOp{
  282. Handle: fuseops.HandleID(in.Fh),
  283. }
  284. case fusekernel.OpReleasedir:
  285. type input fusekernel.ReleaseIn
  286. in := (*input)(inMsg.Consume(unsafe.Sizeof(input{})))
  287. if in == nil {
  288. err = errors.New("Corrupt OpReleasedir")
  289. return
  290. }
  291. o = &fuseops.ReleaseDirHandleOp{
  292. Handle: fuseops.HandleID(in.Fh),
  293. }
  294. case fusekernel.OpWrite:
  295. in := (*fusekernel.WriteIn)(inMsg.Consume(fusekernel.WriteInSize(protocol)))
  296. if in == nil {
  297. err = errors.New("Corrupt OpWrite")
  298. return
  299. }
  300. buf := inMsg.ConsumeBytes(inMsg.Len())
  301. if len(buf) < int(in.Size) {
  302. err = errors.New("Corrupt OpWrite")
  303. return
  304. }
  305. o = &fuseops.WriteFileOp{
  306. Inode: fuseops.InodeID(inMsg.Header().Nodeid),
  307. Handle: fuseops.HandleID(in.Fh),
  308. Data: buf,
  309. Offset: int64(in.Offset),
  310. }
  311. case fusekernel.OpFsync:
  312. type input fusekernel.FsyncIn
  313. in := (*input)(inMsg.Consume(unsafe.Sizeof(input{})))
  314. if in == nil {
  315. err = errors.New("Corrupt OpFsync")
  316. return
  317. }
  318. o = &fuseops.SyncFileOp{
  319. Inode: fuseops.InodeID(inMsg.Header().Nodeid),
  320. Handle: fuseops.HandleID(in.Fh),
  321. }
  322. case fusekernel.OpFlush:
  323. type input fusekernel.FlushIn
  324. in := (*input)(inMsg.Consume(unsafe.Sizeof(input{})))
  325. if in == nil {
  326. err = errors.New("Corrupt OpFlush")
  327. return
  328. }
  329. o = &fuseops.FlushFileOp{
  330. Inode: fuseops.InodeID(inMsg.Header().Nodeid),
  331. Handle: fuseops.HandleID(in.Fh),
  332. }
  333. case fusekernel.OpReadlink:
  334. o = &fuseops.ReadSymlinkOp{
  335. Inode: fuseops.InodeID(inMsg.Header().Nodeid),
  336. }
  337. case fusekernel.OpStatfs:
  338. o = &fuseops.StatFSOp{}
  339. case fusekernel.OpInterrupt:
  340. type input fusekernel.InterruptIn
  341. in := (*input)(inMsg.Consume(unsafe.Sizeof(input{})))
  342. if in == nil {
  343. err = errors.New("Corrupt OpInterrupt")
  344. return
  345. }
  346. o = &interruptOp{
  347. FuseID: in.Unique,
  348. }
  349. case fusekernel.OpInit:
  350. type input fusekernel.InitIn
  351. in := (*input)(inMsg.Consume(unsafe.Sizeof(input{})))
  352. if in == nil {
  353. err = errors.New("Corrupt OpInit")
  354. return
  355. }
  356. o = &initOp{
  357. Kernel: fusekernel.Protocol{in.Major, in.Minor},
  358. MaxReadahead: in.MaxReadahead,
  359. Flags: fusekernel.InitFlags(in.Flags),
  360. }
  361. case fusekernel.OpRemovexattr:
  362. buf := inMsg.ConsumeBytes(inMsg.Len())
  363. n := len(buf)
  364. if n == 0 || buf[n-1] != '\x00' {
  365. err = errors.New("Corrupt OpRemovexattr")
  366. return
  367. }
  368. o = &fuseops.RemoveXattrOp{
  369. Inode: fuseops.InodeID(inMsg.Header().Nodeid),
  370. Name: string(buf[:n-1]),
  371. }
  372. case fusekernel.OpGetxattr:
  373. type input fusekernel.GetxattrIn
  374. in := (*input)(inMsg.Consume(unsafe.Sizeof(input{})))
  375. if in == nil {
  376. err = errors.New("Corrupt OpGetxattr")
  377. return
  378. }
  379. name := inMsg.ConsumeBytes(inMsg.Len())
  380. i := bytes.IndexByte(name, '\x00')
  381. if i < 0 {
  382. err = errors.New("Corrupt OpGetxattr")
  383. return
  384. }
  385. name = name[:i]
  386. to := &fuseops.GetXattrOp{
  387. Inode: fuseops.InodeID(inMsg.Header().Nodeid),
  388. Name: string(name),
  389. }
  390. o = to
  391. readSize := int(in.Size)
  392. p := outMsg.GrowNoZero(readSize)
  393. if p == nil {
  394. err = fmt.Errorf("Can't grow for %d-byte read", readSize)
  395. return
  396. }
  397. sh := (*reflect.SliceHeader)(unsafe.Pointer(&to.Dst))
  398. sh.Data = uintptr(p)
  399. sh.Len = readSize
  400. sh.Cap = readSize
  401. case fusekernel.OpListxattr:
  402. type input fusekernel.ListxattrIn
  403. in := (*input)(inMsg.Consume(unsafe.Sizeof(input{})))
  404. if in == nil {
  405. err = errors.New("Corrupt OpListxattr")
  406. return
  407. }
  408. to := &fuseops.ListXattrOp{
  409. Inode: fuseops.InodeID(inMsg.Header().Nodeid),
  410. }
  411. o = to
  412. readSize := int(in.Size)
  413. if readSize != 0 {
  414. p := outMsg.GrowNoZero(readSize)
  415. if p == nil {
  416. err = fmt.Errorf("Can't grow for %d-byte read", readSize)
  417. return
  418. }
  419. sh := (*reflect.SliceHeader)(unsafe.Pointer(&to.Dst))
  420. sh.Data = uintptr(p)
  421. sh.Len = readSize
  422. sh.Cap = readSize
  423. }
  424. case fusekernel.OpSetxattr:
  425. type input fusekernel.SetxattrIn
  426. in := (*input)(inMsg.Consume(unsafe.Sizeof(input{})))
  427. if in == nil {
  428. err = errors.New("Corrupt OpSetxattr")
  429. return
  430. }
  431. payload := inMsg.ConsumeBytes(inMsg.Len())
  432. // payload should be "name\x00value"
  433. if len(payload) < 3 {
  434. err = errors.New("Corrupt OpSetxattr")
  435. return
  436. }
  437. i := bytes.IndexByte(payload, '\x00')
  438. if i < 0 {
  439. err = errors.New("Corrupt OpSetxattr")
  440. return
  441. }
  442. name, value := payload[:i], payload[i+1:len(payload)]
  443. o = &fuseops.SetXattrOp{
  444. Inode: fuseops.InodeID(inMsg.Header().Nodeid),
  445. Name: string(name),
  446. Value: value,
  447. Flags: in.Flags,
  448. }
  449. default:
  450. o = &unknownOp{
  451. OpCode: inMsg.Header().Opcode,
  452. Inode: fuseops.InodeID(inMsg.Header().Nodeid),
  453. }
  454. }
  455. return
  456. }
  457. ////////////////////////////////////////////////////////////////////////
  458. // Outgoing messages
  459. ////////////////////////////////////////////////////////////////////////
  460. // Fill in the response that should be sent to the kernel, or set noResponse if
  461. // the op requires no response.
  462. func (c *Connection) kernelResponse(
  463. m *buffer.OutMessage,
  464. fuseID uint64,
  465. op interface{},
  466. opErr error) (noResponse bool) {
  467. h := m.OutHeader()
  468. h.Unique = fuseID
  469. // Special case: handle the ops for which the kernel expects no response.
  470. // interruptOp .
  471. switch op.(type) {
  472. case *fuseops.ForgetInodeOp:
  473. noResponse = true
  474. return
  475. case *interruptOp:
  476. noResponse = true
  477. return
  478. }
  479. // If the user returned the error, fill in the error field of the outgoing
  480. // message header.
  481. if opErr != nil {
  482. handled := false
  483. if opErr == syscall.ERANGE {
  484. switch o := op.(type) {
  485. case *fuseops.GetXattrOp:
  486. writeXattrSize(m, uint32(o.BytesRead))
  487. handled = true
  488. case *fuseops.ListXattrOp:
  489. writeXattrSize(m, uint32(o.BytesRead))
  490. handled = true
  491. }
  492. }
  493. if !handled {
  494. m.OutHeader().Error = -int32(syscall.EIO)
  495. if errno, ok := opErr.(syscall.Errno); ok {
  496. m.OutHeader().Error = -int32(errno)
  497. }
  498. // Special case: for some types, convertInMessage grew the message in order
  499. // to obtain a destination buffer. Make sure that we shrink back to just
  500. // the header, because on OS X the kernel otherwise returns EINVAL when we
  501. // attempt to write an error response with a length that extends beyond the
  502. // header.
  503. m.ShrinkTo(buffer.OutMessageHeaderSize)
  504. }
  505. }
  506. // Otherwise, fill in the rest of the response.
  507. if opErr == nil {
  508. c.kernelResponseForOp(m, op)
  509. }
  510. h.Len = uint32(m.Len())
  511. return
  512. }
  513. // Like kernelResponse, but assumes the user replied with a nil error to the
  514. // op.
  515. func (c *Connection) kernelResponseForOp(
  516. m *buffer.OutMessage,
  517. op interface{}) {
  518. // Create the appropriate output message
  519. switch o := op.(type) {
  520. case *fuseops.LookUpInodeOp:
  521. size := int(fusekernel.EntryOutSize(c.protocol))
  522. out := (*fusekernel.EntryOut)(m.Grow(size))
  523. convertChildInodeEntry(&o.Entry, out)
  524. case *fuseops.GetInodeAttributesOp:
  525. size := int(fusekernel.AttrOutSize(c.protocol))
  526. out := (*fusekernel.AttrOut)(m.Grow(size))
  527. out.AttrValid, out.AttrValidNsec = convertExpirationTime(
  528. o.AttributesExpiration)
  529. convertAttributes(o.Inode, &o.Attributes, &out.Attr)
  530. case *fuseops.SetInodeAttributesOp:
  531. size := int(fusekernel.AttrOutSize(c.protocol))
  532. out := (*fusekernel.AttrOut)(m.Grow(size))
  533. out.AttrValid, out.AttrValidNsec = convertExpirationTime(
  534. o.AttributesExpiration)
  535. convertAttributes(o.Inode, &o.Attributes, &out.Attr)
  536. case *fuseops.MkDirOp:
  537. size := int(fusekernel.EntryOutSize(c.protocol))
  538. out := (*fusekernel.EntryOut)(m.Grow(size))
  539. convertChildInodeEntry(&o.Entry, out)
  540. case *fuseops.MkNodeOp:
  541. size := int(fusekernel.EntryOutSize(c.protocol))
  542. out := (*fusekernel.EntryOut)(m.Grow(size))
  543. convertChildInodeEntry(&o.Entry, out)
  544. case *fuseops.CreateFileOp:
  545. eSize := int(fusekernel.EntryOutSize(c.protocol))
  546. e := (*fusekernel.EntryOut)(m.Grow(eSize))
  547. convertChildInodeEntry(&o.Entry, e)
  548. oo := (*fusekernel.OpenOut)(m.Grow(int(unsafe.Sizeof(fusekernel.OpenOut{}))))
  549. oo.Fh = uint64(o.Handle)
  550. case *fuseops.CreateSymlinkOp:
  551. size := int(fusekernel.EntryOutSize(c.protocol))
  552. out := (*fusekernel.EntryOut)(m.Grow(size))
  553. convertChildInodeEntry(&o.Entry, out)
  554. case *fuseops.RenameOp:
  555. // Empty response
  556. case *fuseops.RmDirOp:
  557. // Empty response
  558. case *fuseops.UnlinkOp:
  559. // Empty response
  560. case *fuseops.OpenDirOp:
  561. out := (*fusekernel.OpenOut)(m.Grow(int(unsafe.Sizeof(fusekernel.OpenOut{}))))
  562. out.Fh = uint64(o.Handle)
  563. case *fuseops.ReadDirOp:
  564. // convertInMessage already set up the destination buffer to be at the end
  565. // of the out message. We need only shrink to the right size based on how
  566. // much the user read.
  567. m.ShrinkTo(buffer.OutMessageHeaderSize + o.BytesRead)
  568. case *fuseops.ReleaseDirHandleOp:
  569. // Empty response
  570. case *fuseops.OpenFileOp:
  571. out := (*fusekernel.OpenOut)(m.Grow(int(unsafe.Sizeof(fusekernel.OpenOut{}))))
  572. out.Fh = uint64(o.Handle)
  573. if o.KeepPageCache {
  574. out.OpenFlags |= uint32(fusekernel.OpenKeepCache)
  575. }
  576. if o.UseDirectIO {
  577. out.OpenFlags |= uint32(fusekernel.OpenDirectIO)
  578. }
  579. case *fuseops.ReadFileOp:
  580. // convertInMessage already set up the destination buffer to be at the end
  581. // of the out message. We need only shrink to the right size based on how
  582. // much the user read.
  583. m.ShrinkTo(buffer.OutMessageHeaderSize + o.BytesRead)
  584. case *fuseops.WriteFileOp:
  585. out := (*fusekernel.WriteOut)(m.Grow(int(unsafe.Sizeof(fusekernel.WriteOut{}))))
  586. out.Size = uint32(len(o.Data))
  587. case *fuseops.SyncFileOp:
  588. // Empty response
  589. case *fuseops.FlushFileOp:
  590. // Empty response
  591. case *fuseops.ReleaseFileHandleOp:
  592. // Empty response
  593. case *fuseops.ReadSymlinkOp:
  594. m.AppendString(o.Target)
  595. case *fuseops.StatFSOp:
  596. out := (*fusekernel.StatfsOut)(m.Grow(int(unsafe.Sizeof(fusekernel.StatfsOut{}))))
  597. out.St.Blocks = o.Blocks
  598. out.St.Bfree = o.BlocksFree
  599. out.St.Bavail = o.BlocksAvailable
  600. out.St.Files = o.Inodes
  601. out.St.Ffree = o.InodesFree
  602. // The posix spec for sys/statvfs.h (http://goo.gl/LktgrF) defines the
  603. // following fields of statvfs, among others:
  604. //
  605. // f_bsize File system block size.
  606. // f_frsize Fundamental file system block size.
  607. // f_blocks Total number of blocks on file system in units of f_frsize.
  608. //
  609. // It appears as though f_bsize was the only thing supported by most unixes
  610. // originally, but then f_frsize was added when new sorts of file systems
  611. // came about. Quoth The Linux Programming Interface by Michael Kerrisk
  612. // (https://goo.gl/5LZMxQ):
  613. //
  614. // For most Linux file systems, the values of f_bsize and f_frsize are
  615. // the same. However, some file systems support the notion of block
  616. // fragments, which can be used to allocate a smaller unit of storage
  617. // at the end of the file if if a full block is not required. This
  618. // avoids the waste of space that would otherwise occur if a full block
  619. // was allocated. On such file systems, f_frsize is the size of a
  620. // fragment, and f_bsize is the size of a whole block. (The notion of
  621. // fragments in UNIX file systems first appeared in the early 1980s
  622. // with the 4.2BSD Fast File System.)
  623. //
  624. // Confusingly, it appears as though osxfuse surfaces fuse_kstatfs::bsize
  625. // as statfs::f_iosize (of advisory use only), and fuse_kstatfs::frsize as
  626. // statfs::f_bsize (which affects free space display in the Finder).
  627. out.St.Bsize = o.IoSize
  628. out.St.Frsize = o.BlockSize
  629. case *fuseops.RemoveXattrOp:
  630. // Empty response
  631. case *fuseops.GetXattrOp:
  632. // convertInMessage already set up the destination buffer to be at the end
  633. // of the out message. We need only shrink to the right size based on how
  634. // much the user read.
  635. if o.BytesRead == 0 {
  636. writeXattrSize(m, uint32(o.BytesRead))
  637. } else {
  638. m.ShrinkTo(buffer.OutMessageHeaderSize + o.BytesRead)
  639. }
  640. case *fuseops.ListXattrOp:
  641. if o.BytesRead == 0 {
  642. writeXattrSize(m, uint32(o.BytesRead))
  643. } else {
  644. m.ShrinkTo(buffer.OutMessageHeaderSize + o.BytesRead)
  645. }
  646. case *fuseops.SetXattrOp:
  647. // Empty response
  648. case *initOp:
  649. out := (*fusekernel.InitOut)(m.Grow(int(unsafe.Sizeof(fusekernel.InitOut{}))))
  650. out.Major = o.Library.Major
  651. out.Minor = o.Library.Minor
  652. out.MaxReadahead = o.MaxReadahead
  653. out.Flags = uint32(o.Flags)
  654. out.MaxWrite = o.MaxWrite
  655. default:
  656. panic(fmt.Sprintf("Unexpected op: %#v", op))
  657. }
  658. return
  659. }
  660. ////////////////////////////////////////////////////////////////////////
  661. // General conversions
  662. ////////////////////////////////////////////////////////////////////////
  663. func convertTime(t time.Time) (secs uint64, nsec uint32) {
  664. totalNano := t.UnixNano()
  665. secs = uint64(totalNano / 1e9)
  666. nsec = uint32(totalNano % 1e9)
  667. return
  668. }
  669. func convertAttributes(
  670. inodeID fuseops.InodeID,
  671. in *fuseops.InodeAttributes,
  672. out *fusekernel.Attr) {
  673. out.Ino = uint64(inodeID)
  674. out.Size = in.Size
  675. out.Atime, out.AtimeNsec = convertTime(in.Atime)
  676. out.Mtime, out.MtimeNsec = convertTime(in.Mtime)
  677. out.Ctime, out.CtimeNsec = convertTime(in.Ctime)
  678. out.SetCrtime(convertTime(in.Crtime))
  679. out.Nlink = in.Nlink
  680. out.Uid = in.Uid
  681. out.Gid = in.Gid
  682. // round up to the nearest 512 boundary
  683. out.Blocks = (in.Size + 512 - 1) / 512
  684. // Set the mode.
  685. out.Mode = uint32(in.Mode) & 0777
  686. switch {
  687. default:
  688. out.Mode |= syscall.S_IFREG
  689. case in.Mode&os.ModeDir != 0:
  690. out.Mode |= syscall.S_IFDIR
  691. case in.Mode&os.ModeDevice != 0:
  692. if in.Mode&os.ModeCharDevice != 0 {
  693. out.Mode |= syscall.S_IFCHR
  694. } else {
  695. out.Mode |= syscall.S_IFBLK
  696. }
  697. case in.Mode&os.ModeNamedPipe != 0:
  698. out.Mode |= syscall.S_IFIFO
  699. case in.Mode&os.ModeSymlink != 0:
  700. out.Mode |= syscall.S_IFLNK
  701. case in.Mode&os.ModeSocket != 0:
  702. out.Mode |= syscall.S_IFSOCK
  703. }
  704. }
  705. // Convert an absolute cache expiration time to a relative time from now for
  706. // consumption by the fuse kernel module.
  707. func convertExpirationTime(t time.Time) (secs uint64, nsecs uint32) {
  708. // Fuse represents durations as unsigned 64-bit counts of seconds and 32-bit
  709. // counts of nanoseconds (cf. http://goo.gl/EJupJV). So negative durations
  710. // are right out. There is no need to cap the positive magnitude, because
  711. // 2^64 seconds is well longer than the 2^63 ns range of time.Duration.
  712. d := t.Sub(time.Now())
  713. if d > 0 {
  714. secs = uint64(d / time.Second)
  715. nsecs = uint32((d % time.Second) / time.Nanosecond)
  716. }
  717. return
  718. }
  719. func convertChildInodeEntry(
  720. in *fuseops.ChildInodeEntry,
  721. out *fusekernel.EntryOut) {
  722. out.Nodeid = uint64(in.Child)
  723. out.Generation = uint64(in.Generation)
  724. out.EntryValid, out.EntryValidNsec = convertExpirationTime(in.EntryExpiration)
  725. out.AttrValid, out.AttrValidNsec = convertExpirationTime(in.AttributesExpiration)
  726. convertAttributes(in.Child, &in.Attributes, &out.Attr)
  727. }
  728. func convertFileMode(unixMode uint32) os.FileMode {
  729. mode := os.FileMode(unixMode & 0777)
  730. switch unixMode & syscall.S_IFMT {
  731. case syscall.S_IFREG:
  732. // nothing
  733. case syscall.S_IFDIR:
  734. mode |= os.ModeDir
  735. case syscall.S_IFCHR:
  736. mode |= os.ModeCharDevice | os.ModeDevice
  737. case syscall.S_IFBLK:
  738. mode |= os.ModeDevice
  739. case syscall.S_IFIFO:
  740. mode |= os.ModeNamedPipe
  741. case syscall.S_IFLNK:
  742. mode |= os.ModeSymlink
  743. case syscall.S_IFSOCK:
  744. mode |= os.ModeSocket
  745. default:
  746. // no idea
  747. mode |= os.ModeDevice
  748. }
  749. if unixMode&syscall.S_ISUID != 0 {
  750. mode |= os.ModeSetuid
  751. }
  752. if unixMode&syscall.S_ISGID != 0 {
  753. mode |= os.ModeSetgid
  754. }
  755. return mode
  756. }
  757. func writeXattrSize(m *buffer.OutMessage, size uint32) {
  758. out := (*fusekernel.GetxattrOut)(m.Grow(int(unsafe.Sizeof(fusekernel.GetxattrOut{}))))
  759. out.Size = size
  760. }