Guest User

Untitled

a guest
Jul 16th, 2018
79
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.14 KB | None | 0 0
  1. module V6FS
  2.  
  3. open System
  4. open System.Collections.Generic
  5. open System.IO
  6. open System.Text
  7.  
  8. let right(s:string, len:int) = s.Substring(s.Length - len)
  9.  
  10. let NINODE = 100
  11. let ROOTINO = 1
  12. let ILOCK = 1uy
  13.  
  14. let IALLOC = 0o100000
  15. let IFMT = 0o60000
  16. let IFDIR = 0o40000
  17. let IFCHR = 0o20000
  18. let IFBLK = 0o60000
  19. let ILARG = 0o10000
  20. let ISUID = 0o4000
  21. let ISGID = 0o2000
  22. let ISVTX = 0o1000
  23. let IREAD = 0o400
  24. let IWRITE = 0o200
  25. let IEXEC = 0o100
  26.  
  27. let getMode(mode:int) =
  28. let list = new List<string>()
  29. list.Add(right("00" + Convert.ToString(mode &&& 0o777, 8), 3))
  30. if (mode &&& IALLOC) <> 0 then list.Add "IALLOC"
  31. if (mode &&& IFMT ) <> 0 then list.Add "IFMT"
  32. if (mode &&& IFDIR ) <> 0 then list.Add "IFDIR"
  33. if (mode &&& IFCHR ) <> 0 then list.Add "IFCHR"
  34. if (mode &&& IFBLK ) <> 0 then list.Add "IFBLK"
  35. if (mode &&& ILARG ) <> 0 then list.Add "ILARG"
  36. if (mode &&& ISUID ) <> 0 then list.Add "ISUID"
  37. if (mode &&& ISGID ) <> 0 then list.Add "ISGID"
  38. if (mode &&& ISVTX ) <> 0 then list.Add "ISVTX"
  39. // if (mode &&& IREAD ) <> 0 then list.Add "IREAD"
  40. // if (mode &&& IWRITE) <> 0 then list.Add "IWRITE"
  41. // if (mode &&& IEXEC ) <> 0 then list.Add "IEXEC"
  42. String.Join(",", list.ToArray())
  43.  
  44. let getBinaryReader(data:byte[], offset:int) =
  45. new BinaryReader(new MemoryStream(data, offset, 512))
  46.  
  47. let getUInt32(h:uint16, l:uint16) = (uint32(h) <<< 16) ||| uint32(l)
  48. let readUInt32(br:BinaryReader) =
  49. let h = br.ReadUInt16()
  50. let l = br.ReadUInt16()
  51. getUInt32(h, l)
  52.  
  53. let epoch = new DateTime(1970, 1, 1)
  54. let getTime(t:uint32) = epoch.AddSeconds(float(t))
  55.  
  56. let getString(buf:byte[]) =
  57. let sb = new StringBuilder()
  58. let mutable i = 0
  59. while i < buf.Length && buf.[i] <> 0uy do
  60. sb.Append((char)buf.[i]) |> ignore
  61. i <- i + 1
  62. sb.ToString()
  63.  
  64. let pathCombine(path:string, name:string) =
  65. if String.IsNullOrEmpty(path) || path.EndsWith("/") then
  66. path + name
  67. else
  68. path + "/" + name
  69.  
  70. let isCurOrParent(path:string) = path = "." || path = ".."
  71.  
  72. type dentry =
  73. { inode:int
  74. name:string }
  75.  
  76. static member Read(br:BinaryReader) =
  77. { inode = int <| br.ReadUInt16()
  78. name = getString(br.ReadBytes(14)) }
  79.  
  80. (*
  81. * inode structure as it appears on
  82. * the disk. Not used by the system,
  83. * but by things like check, df, dump.
  84. *)
  85.  
  86. type inode =
  87. { data:byte[]
  88. inode:int // i number, 1-to-1 with device address
  89. path:string
  90. name:string
  91. offset:int
  92. mutable mode:uint16
  93. mutable nlink:byte // directory entries
  94. mutable uid:byte // owner
  95. mutable gid:byte // group of owner
  96. mutable size0:byte // most significant of size
  97. mutable size1:uint16 // least sig
  98. mutable addr:uint16[] // device addresses constituting file
  99. mutable atime:uint32
  100. mutable mtime:uint32
  101. }
  102.  
  103. static member Read(data:byte[], ino:int, path:string, name:string) =
  104. let offset = 1024 + 32 * (ino - 1)
  105. use br = getBinaryReader(data, offset)
  106. { data = data
  107. inode = ino
  108. path = path
  109. name = name
  110. offset = offset
  111. mode = br.ReadUInt16()
  112. nlink = br.ReadByte()
  113. uid = br.ReadByte()
  114. gid = br.ReadByte()
  115. size0 = br.ReadByte()
  116. size1 = br.ReadUInt16()
  117. addr = [| for _ in 0..7 -> br.ReadUInt16() |]
  118. atime = readUInt32(br)
  119. mtime = readUInt32(br) }
  120.  
  121. member x.GetAddrs() =
  122. String.Join(",", [| for ad in x.addr -> ad.ToString() |])
  123.  
  124. member x.Length = (int(x.size0) <<< 16) ||| int(x.size1)
  125. member x.LastAccessTime = getTime x.atime
  126. member x.LastWriteTime = getTime x.mtime
  127. member x.FullName = pathCombine(x.path, x.name)
  128. member x.IsDir = (int(x.mode) &&& IFDIR ) <> 0
  129.  
  130. member x.Write(tw:TextWriter) =
  131. tw.WriteLine("[{0}]", x.FullName)
  132. tw.WriteLine("mode : {0}", getMode((int)x.mode))
  133. tw.WriteLine("nlink : {0}", x.nlink)
  134. tw.WriteLine("uid : {0}", x.uid)
  135. tw.WriteLine("gid : {0}", x.gid)
  136. tw.WriteLine("size : {0}", x.Length)
  137. tw.WriteLine("addr : {0}", x.GetAddrs())
  138. tw.WriteLine("atime : {0}", x.LastAccessTime)
  139. tw.WriteLine("mtime : {0}", x.LastWriteTime)
  140.  
  141. member x.ReadAllBytes() =
  142. let mutable i, pos, len = 0, 0, x.Length
  143. let ret = Array.zeroCreate<byte> len
  144. while i < 8 && len > 0 do
  145. let wlen =
  146. if i = 7 || x.addr.[i + 1] = 0us then len else 512
  147. array.Copy(x.data, int(x.addr.[i]) * 512, ret, pos, wlen)
  148. pos <- pos + wlen
  149. len <- len - wlen
  150. i <- i + 1
  151. ret
  152.  
  153. member x.OpenRead() =
  154. new MemoryStream(x.ReadAllBytes())
  155.  
  156. member x.ReadDir() =
  157. let list = new List<dentry>()
  158. if x.IsDir then
  159. use br = new BinaryReader(x.OpenRead())
  160. let count = x.Length / 16
  161. for i = 1 to count do
  162. let dent = dentry.Read(br)
  163. if dent.inode <> 0 && not(isCurOrParent dent.name) then
  164. list.Add dent
  165. list.Sort(new Comparison<dentry>(fun a b -> a.name.CompareTo(b.name)))
  166. list.ToArray()
  167.  
  168. (*
  169. * Definition of the unix super block.
  170. * The root super block is allocated and
  171. * read in iinit/alloc.c. Subsequently
  172. * a super block is allocated and read
  173. * with each mount (smount/sys3.c) and
  174. * released with unmount (sumount/sys3.c).
  175. * A disk block is ripped off for storage.
  176. * See alloc.c for general alloc/free
  177. * routines for free list and I list.
  178. *)
  179.  
  180. type filsys =
  181. { data:byte[]
  182. mutable isize :uint16 // size in blocks of I list
  183. mutable fsize :uint16 // size in blocks of entire volume
  184. mutable nfree :uint16 // number of in core free blocks (0-100)
  185. free :uint16[] // in core free blocks
  186. mutable ninode:uint16 // number of in core I nodes (0-100)
  187. inode :uint16[] // in core free I nodes
  188. mutable flock :byte // lock during free list manipulation
  189. mutable ilock :byte // lock during I list manipulation
  190. mutable fmod :byte // super block modified flag
  191. mutable ronly :byte // mounted read-only flag
  192. time :uint32 // current date of last update
  193. inodes :Dictionary<int, inode> }
  194.  
  195. static member Read(data:byte[], offset:int) =
  196. use br = getBinaryReader(data, offset)
  197. { data = data
  198. isize = br.ReadUInt16()
  199. fsize = br.ReadUInt16()
  200. nfree = br.ReadUInt16()
  201. free = [| for _ in 0..99 -> br.ReadUInt16() |]
  202. ninode = br.ReadUInt16()
  203. inode = [| for _ in 0..99 -> br.ReadUInt16() |]
  204. flock = br.ReadByte()
  205. ilock = br.ReadByte()
  206. fmod = br.ReadByte()
  207. ronly = br.ReadByte()
  208. time = readUInt32(br)
  209. inodes = new Dictionary<int, inode>() }
  210.  
  211. member x.Time = getTime x.time
  212.  
  213. member x.Write(tw:TextWriter) =
  214. tw.WriteLine("isize : {0}", x.isize)
  215. tw.WriteLine("fsize : {0}", x.fsize)
  216. tw.WriteLine("nfree : {0}", x.nfree)
  217. tw.WriteLine("ninode: {0}", x.ninode)
  218. tw.WriteLine("flock : {0}", x.flock)
  219. tw.WriteLine("ilock : {0}", x.ilock)
  220. tw.WriteLine("fmod : {0}", x.fmod)
  221. tw.WriteLine("ronly : {0}", x.ronly)
  222. tw.WriteLine("time : {0}", x.Time)
  223.  
  224. member x.GetINode(ino:int, path:string, name:string) =
  225. let ok, ret = x.inodes.TryGetValue(ino)
  226. if ok then ret else
  227. let ret = inode.Read(x.data, ino, path, name)
  228. x.inodes.Add(ino, ret)
  229. ret
  230.  
  231. member x.GetNodes(ino:inode) =
  232. let path = ino.FullName
  233. let dirs = ino.ReadDir()
  234. [| for dent in dirs ->
  235. x.GetINode(dent.inode, path, dent.name) |]
  236.  
  237. member x.Root = x.GetINode(1, "", "/")
  238.  
  239. let Open(fn:string) =
  240. let data = File.ReadAllBytes(fn)
  241. let fs = filsys.Read(data, 512)
  242.  
  243. use sw = new StringWriter()
  244. fs.Write sw
  245. let rec dir(inode:inode) =
  246. sw.WriteLine()
  247. inode.Write sw
  248. for inode in fs.GetNodes(inode) do
  249. dir inode
  250. dir fs.Root
  251.  
  252. sw.ToString()
Add Comment
Please, Sign In to add comment