@@ -127,3 +127,119 @@ Terminal redirection and duplication
127127 the slot given by *index *.
128128
129129 The function returns the previous stream-like object in the given slot.
130+
131+ Filesystem mounting
132+ -------------------
133+
134+ Some ports provide a Virtual Filesystem (VFS) and the ability to mount multiple
135+ "real" filesystems within this VFS. Filesystem objects can be mounted at either
136+ the root of the VFS, or at a subdirectory that lives in the root. This allows
137+ dynamic and flexible configuration of the filesystem that is seen by Python
138+ programs. Ports that have this functionality provide the :func: `mount ` and
139+ :func: `umount ` functions, and possibly various filesystem implementations
140+ represented by VFS classes.
141+
142+ .. function :: mount(fsobj, mount_point, \*, readonly)
143+
144+ Mount the filesystem object *fsobj * at the location in the VFS given by the
145+ *mount_point * string. *fsobj * can be a a VFS object that has a ``mount() ``
146+ method, or a block device. If it's a block device then the filesystem type
147+ is automatically detected (an exception is raised if no filesystem was
148+ recognised). *mount_point * may be ``'/' `` to mount *fsobj * at the root,
149+ or ``'/<name>' `` to mount it at a subdirectory under the root.
150+
151+ If *readonly * is ``True `` then the filesystem is mounted read-only.
152+
153+ During the mount process the method ``mount() `` is called on the filesystem
154+ object.
155+
156+ Will raise ``OSError(EPERM) `` if *mount_point * is already mounted.
157+
158+ .. function :: umount(mount_point)
159+
160+ Unmount a filesystem. *mount_point * can be a string naming the mount location,
161+ or a previously-mounted filesystem object. During the unmount process the
162+ method ``umount() `` is called on the filesystem object.
163+
164+ Will raise ``OSError(EINVAL) `` if *mount_point * is not found.
165+
166+ .. class :: VfsFat(block_dev)
167+
168+ Create a filesystem object that uses the FAT filesystem format. Storage of
169+ the FAT filesystem is provided by *block_dev *.
170+ Objects created by this constructor can be mounted using :func: `mount `.
171+
172+ .. staticmethod :: mkfs(block_dev)
173+
174+ Build a FAT filesystem on *block_dev *.
175+
176+ Block devices
177+ -------------
178+
179+ A block device is an object which implements the block protocol, which is a set
180+ of methods described below by the :class: `AbstractBlockDev ` class. A concrete
181+ implementation of this class will usually allow access to the memory-like
182+ functionality a piece of hardware (like flash memory). A block device can be
183+ used by a particular filesystem driver to store the data for its filesystem.
184+
185+ .. class :: AbstractBlockDev(...)
186+
187+ Construct a block device object. The parameters to the constructor are
188+ dependent on the specific block device.
189+
190+ .. method :: readblocks(block_num, buf)
191+
192+ Starting at *block_num *, read blocks from the device into *buf * (an array
193+ of bytes). The number of blocks to read is given by the length of *buf *,
194+ which will be a multiple of the block size.
195+
196+ .. method :: writeblocks(block_num, buf)
197+
198+ Starting at *block_num *, write blocks from *buf * (an array of bytes) to
199+ the device. The number of blocks to write is given by the length of *buf *,
200+ which will be a multiple of the block size.
201+
202+ .. method :: ioctl(op, arg)
203+
204+ Control the block device and query its parameters. The operation to
205+ perform is given by *op * which is one of the following integers:
206+
207+ - 1 -- initialise the device (*arg * is unused)
208+ - 2 -- shutdown the device (*arg * is unused)
209+ - 3 -- sync the device (*arg * is unused)
210+ - 4 -- get a count of the number of blocks, should return an integer
211+ (*arg * is unused)
212+ - 5 -- get the number of bytes in a block, should return an integer,
213+ or ``None `` in which case the default value of 512 is used
214+ (*arg * is unused)
215+
216+ By way of example, the following class will implement a block device that stores
217+ its data in RAM using a ``bytearray ``::
218+
219+ class RAMBlockDev:
220+ def __init__(self, block_size, num_blocks):
221+ self.block_size = block_size
222+ self.data = bytearray(block_size * num_blocks)
223+
224+ def readblocks(self, block_num, buf):
225+ for i in range(len(buf)):
226+ buf[i] = self.data[block_num * self.block_size + i]
227+
228+ def writeblocks(self, block_num, buf):
229+ for i in range(len(buf)):
230+ self.data[block_num * self.block_size + i] = buf[i]
231+
232+ def ioctl(self, op, arg):
233+ if op == 4: # get number of blocks
234+ return len(self.data) // self.block_size
235+ if op == 5: # get block size
236+ return self.block_size
237+
238+ It can be used as follows::
239+
240+ import uos
241+
242+ bdev = RAMBlockDev(512, 50)
243+ uos.VfsFat.mkfs(bdev)
244+ vfs = uos.VfsFat(bdev)
245+ uos.mount(vfs, '/ramdisk')
0 commit comments