• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /****************************************************************************
2  * rm/romfs/fs_romfs.h
3  *
4  *   Copyright (C) 2008-2009, 2011, 2017-2018 Gregory Nutt. All rights
5  *     reserved.
6  *   Author: Gregory Nutt <gnutt@nuttx.org>
7  *
8  * References: Linux/Documentation/filesystems/romfs.txt
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  *
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in
18  *    the documentation and/or other materials provided with the
19  *    distribution.
20  * 3. Neither the name NuttX nor the names of its contributors may be
21  *    used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
31  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
32  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35  * POSSIBILITY OF SUCH DAMAGE.
36  *
37  ****************************************************************************/
38 
39 /****************************************************************************
40  * Included Files
41  ****************************************************************************/
42 
43 #include <sys/types.h>
44 #include <sys/statfs.h>
45 #include <sys/stat.h>
46 
47 #include <stdint.h>
48 #include <stdbool.h>
49 #include <stdlib.h>
50 #include <unistd.h>
51 #include <string.h>
52 #include <fcntl.h>
53 #include <limits.h>
54 #include <assert.h>
55 #include <errno.h>
56 
57 #include "fs_romfs.h"
58 
59 #include "los_tables.h"
60 #include "user_copy.h"
61 #include "los_vm_filemap.h"
62 
63 #ifdef LOSCFG_FS_ROMFS
64 
65 /* forward define */
66 struct VnodeOps g_romfsVops;
67 struct file_operations_vfs g_romfsFops;
68 
69 /****************************************************************************
70  * Name: romfs_lookup
71  ****************************************************************************/
72 
romfs_lookup(struct Vnode * parentVnode,const char * path,int len,struct Vnode ** ppVnode)73 int romfs_lookup(struct Vnode *parentVnode, const char *path, int len, struct Vnode **ppVnode)
74 {
75   int ret;
76   struct Vnode *newVnode = NULL;
77   struct romfs_dirinfo_s *dirinfo = NULL;
78   struct romfs_dirinfo_s *parent_dirinfo = NULL;
79   struct romfs_mountpt_s *rm = NULL;
80   struct romfs_file_s    *rf = NULL;
81 
82   /* Get mountpoint private data from the inode reference from the file
83    * structure
84    */
85 
86   rm = (struct romfs_mountpt_s *)parentVnode->originMount->data;
87 
88   /* Check if the mount is still healthy */
89 
90   romfs_semtake(rm);
91   ret = romfs_checkmount(rm);
92   if (ret != OK)
93     {
94       PRINTK("ERROR: romfs_checkmount failed: %d\n", ret);
95       goto errout_with_semaphore;
96     }
97 
98   parent_dirinfo = (struct romfs_dirinfo_s *)parentVnode->data;
99   /* Initialize the directory info structure */
100 
101   dirinfo = (struct romfs_dirinfo_s *)zalloc(sizeof(struct romfs_dirinfo_s));
102   if (!dirinfo)
103     {
104       ret = -ENOMEM;
105       PRINTK("ERROR: Failed to allocate dirinfo structure, error: %d\n", -ret);
106       goto errout_with_semaphore;
107     }
108 
109   /* Locate the directory entry for this path */
110 
111   ret = romfs_searchdir(rm, path, len, parent_dirinfo->rd_dir.fr_firstoffset, dirinfo);
112   if (ret < 0)
113     {
114       goto errout_with_semaphore;
115     }
116 
117   /* The full path exists -- but is the final component a file
118    * or a directory?  Or some other Unix file type that is not
119    * appropriate in this contex.
120    *
121    * REVISIT: This logic should follow hard/soft link file
122    * types.  At present, it returns the ENXIO.
123    */
124 
125   if (!IS_DIRECTORY(dirinfo->rd_next) && !IS_FILE(dirinfo->rd_next))
126     {
127       /* ENXIO indicates "The named file is a character special or
128        * block special file, and the device associated with this
129        * special file does not exist."
130        *
131        * Here we also return ENXIO if the file is not a directory
132        * or a regular file.
133        */
134 
135       ret = -ENXIO;
136       PRINTK("ERROR: '%s' is a special file\n", path);
137       goto errout_with_semaphore;
138     }
139 
140   if (IS_DIRECTORY(dirinfo->rd_next))
141     {
142       ret = VnodeAlloc(&g_romfsVops, &newVnode);
143       if (ret != 0)
144         {
145           PRINTK("%s-%d: can't alloc vnode, error: %d\n", __FUNCTION__, __LINE__, ret);
146           goto errout_with_semaphore;
147         }
148       newVnode->type   = VNODE_TYPE_DIR;
149       newVnode->parent = parentVnode;
150       newVnode->fop    = &g_romfsFops;
151       newVnode->data   = dirinfo;
152       newVnode->originMount = parentVnode->originMount;
153       newVnode->uid    = parentVnode->uid;
154       newVnode->gid    = parentVnode->gid;
155       newVnode->mode   = parentVnode->mode | (S_IFDIR | S_IROTH | S_IXOTH | S_IRGRP | S_IXGRP |
156                      S_IRUSR | S_IXUSR);
157     }
158   else
159     {
160       rf = (struct romfs_file_s *)zalloc(sizeof(struct romfs_file_s));
161       if (!rf)
162         {
163           ret = -ENOMEM;
164           PRINTK("ERROR: Failed to allocate private data: %d\n", ret);
165           goto errout_with_semaphore;
166         }
167 
168       /* Initialize the file private data (only need to initialize
169       * non-zero elements)
170       */
171 
172       rf->rf_size = dirinfo->rd_size;
173       rf->rf_type = (uint8_t)(dirinfo->rd_next & RFNEXT_ALLMODEMASK);
174 
175       /* Get the start of the file data */
176 
177       ret = romfs_datastart(rm, dirinfo->rd_dir.fr_curroffset,
178                             &rf->rf_startoffset);
179       if (ret < 0)
180         {
181           PRINTK("ERROR: Failed to locate start of file data: %d\n", ret);
182           goto errout_with_mem;
183         }
184 
185       /* Then insert the new instance into the mountpoint structure.
186       * It needs to be there (1) to handle error conditions that effect
187       * all files, and (2) to inform the umount logic that we are busy
188       * (but a simple reference count could have done that).
189       */
190 
191       rf->rf_next = rm->rm_head;
192       rm->rm_head = rf->rf_next;
193 
194       ret = VnodeAlloc(&g_romfsVops, &newVnode);
195       if (ret != 0)
196         {
197           PRINTK("%s-%d: can't alloc vnode, error: %d\n", __FUNCTION__, __LINE__, ret);
198           goto errout_with_mem;
199         }
200 
201       newVnode->originMount = parentVnode->originMount;
202       newVnode->type   = VNODE_TYPE_REG;
203       newVnode->parent = parentVnode;
204       newVnode->fop    = &g_romfsFops;
205       newVnode->data   = rf;
206       newVnode->uid    = parentVnode->uid;
207       newVnode->gid    = parentVnode->gid;
208       newVnode->mode   = S_IFREG | S_IROTH | S_IXOTH | S_IRGRP | S_IXGRP | S_IRUSR | S_IXUSR;
209 
210       free(dirinfo);
211     }
212 
213   *ppVnode = newVnode;
214 
215   romfs_semgive(rm);
216   return OK;
217 
218   /* Error exits */
219 
220 errout_with_mem:
221   free(rf);
222 
223 errout_with_semaphore:
224   romfs_semgive(rm);
225   return ret;
226 }
227 
228 /****************************************************************************
229  * Name: romfs_close
230  ****************************************************************************/
231 
romfs_close(struct file * filep)232 int romfs_close(struct file *filep)
233 {
234   return 0;
235 }
236 
romfs_reclaim(struct Vnode * vp)237 int romfs_reclaim(struct Vnode *vp)
238 {
239   struct romfs_file_s *rf = vp->data;
240   if (rf->rf_buffer)
241     {
242       free(rf->rf_buffer);
243     }
244 
245   /* Then free the file structure itself. */
246 
247   free(rf);
248   vp->data = NULL;
249 
250   return 0;
251 }
252 
253 /****************************************************************************
254  * Name: romfs_read
255  ****************************************************************************/
256 
romfs_read(struct file * filep,char * buffer,size_t buflen)257 static ssize_t romfs_read(struct file *filep, char *buffer,
258                           size_t buflen)
259 {
260   struct romfs_mountpt_s *rm = NULL;
261   struct romfs_file_s    *rf = NULL;
262   uint32_t                    offset;
263   size_t                      bytesleft;
264   int                         ret;
265 
266   /* Recover our private data from the struct file instance */
267 
268   rf = (struct romfs_file_s *)filep->f_vnode->data;
269   rm = (struct romfs_mountpt_s *)filep->f_vnode->originMount->data;
270 
271   /* Make sure that the mount is still healthy */
272 
273   romfs_semtake(rm);
274   ret = romfs_checkmount(rm);
275   if (ret != OK)
276     {
277       PRINTK("ERROR: romfs_checkmount failed: %d\n", ret);
278       goto errout_with_semaphore;
279     }
280 
281   /* Get the number of bytes left in the file */
282 
283   bytesleft = rf->rf_size - filep->f_pos;
284 
285   /* Truncate read count so that it does not exceed the number
286    * of bytes left in the file.
287    */
288 
289   if (buflen > bytesleft)
290     {
291       buflen = bytesleft;
292     }
293 
294   offset = rf->rf_startoffset + filep->f_pos;
295   LOS_CopyFromKernel(buffer, buflen, &rm->rm_buffer[offset], buflen);
296   filep->f_pos += buflen;
297 
298   romfs_semgive(rm);
299   return buflen;
300 
301 errout_with_semaphore:
302   romfs_semgive(rm);
303   return ret;
304 }
305 
306 /****************************************************************************
307  * Name: romfs_readpage
308  ****************************************************************************/
309 
romfs_readpage(struct Vnode * vnode,char * buffer,off_t off)310 static ssize_t romfs_readpage(struct Vnode *vnode, char *buffer, off_t off)
311 {
312   size_t    bytesleft;
313   int       ret = 0;
314   int       buflen = PAGE_SIZE;
315   struct romfs_mountpt_s *rm = NULL;
316   struct romfs_file_s    *rf = NULL;
317 
318   /* Recover our private data from the struct file instance */
319 
320   rf = (struct romfs_file_s *)vnode->data;
321   rm = (struct romfs_mountpt_s *)vnode->originMount->data;
322 
323   /* Make sure that the mount is still healthy */
324 
325   romfs_semtake(rm);
326   ret = romfs_checkmount(rm);
327   if (ret != OK)
328     {
329       PRINTK("ERROR: romfs_checkmount failed: %d\n", ret);
330       goto errout_with_semaphore;
331     }
332 
333   if (off >= rf->rf_size)
334     {
335       ret = -ERANGE;
336       PRINTK("ERROR: readpage out of range, ret: %d.\n", ret);
337       goto errout_with_semaphore;
338     }
339 
340   /* Get the number of bytes left in the file */
341 
342   bytesleft = rf->rf_size - off;
343 
344   /* Truncate read count so that it does not exceed the number
345    * of bytes left in the file.
346    */
347 
348   if (buflen > bytesleft)
349     {
350       buflen = bytesleft;
351     }
352 
353   off = rf->rf_startoffset + off;
354   LOS_CopyFromKernel(buffer, buflen, &rm->rm_buffer[off], buflen);
355 
356   romfs_semgive(rm);
357   return buflen;
358 
359 errout_with_semaphore:
360   romfs_semgive(rm);
361   return ret;
362 }
363 
364 /****************************************************************************
365  * Name: romfs_seek
366  ****************************************************************************/
367 
romfs_seek(struct file * filep,off_t offset,int whence)368 off_t romfs_seek(struct file *filep, off_t offset, int whence)
369 {
370   struct romfs_file_s    *rf = NULL;
371   loff_t                 position;
372 
373   /* Recover our private data from the struct file instance */
374 
375   rf = (struct romfs_file_s *)filep->f_vnode->data;
376   position = filep->f_pos;
377 
378   /* Map the offset according to the whence option */
379 
380   switch (whence)
381     {
382     case SEEK_SET: /* The offset is set to offset bytes. */
383         position = offset;
384         break;
385 
386     case SEEK_CUR: /* The offset is set to its current location plus
387                     * offset bytes. */
388 
389         position += offset;
390         break;
391 
392     case SEEK_END: /* The offset is set to the size of the file plus
393                     * offset bytes. */
394 
395         position = offset + rf->rf_size;
396         break;
397 
398     default:
399         PRINTK("ERROR: Whence is invalid: %d\n", whence);
400         return -EINVAL;
401     }
402 
403   /* Limit positions to the end of the file. */
404 
405   if (position > rf->rf_size)
406     {
407       /* Otherwise, the position is limited to the file size */
408 
409       position = rf->rf_size;
410     }
411 
412   if (position < 0)
413     {
414       return -EINVAL;
415     }
416   return position;
417 }
418 
419 /****************************************************************************
420  * Name: romfs_seek64
421  ****************************************************************************/
422 
romfs_seek64(struct file * filep,loff_t offset,int whence)423 loff_t romfs_seek64(struct file *filep, loff_t offset, int whence)
424 {
425   return (loff_t)romfs_seek(filep, (off_t)offset, whence);
426 }
427 
428 /****************************************************************************
429  * Name: romfs_ioctl
430  ****************************************************************************/
431 
romfs_ioctl(struct file * filep,int cmd,unsigned long arg)432 static int romfs_ioctl(struct file *filep, int cmd, unsigned long arg)
433 {
434   return -ENOSYS;
435 }
436 
437 /****************************************************************************
438  * Name: romfs_opendir
439  *
440  * Description:
441  *   Open a directory for read access
442  *
443  ****************************************************************************/
444 
romfs_opendir(struct Vnode * vp,struct fs_dirent_s * dir)445 int romfs_opendir(struct Vnode *vp, struct fs_dirent_s *dir)
446 {
447   int ret;
448   struct romfs_mountpt_s *rm = NULL;
449   struct romfs_dirinfo_s *dirinfo = NULL;
450   struct fs_romfsdir_s   *ptr = NULL;
451 
452   /* Recover our private data from the vnode instance */
453 
454   rm = (struct romfs_mountpt_s *)vp->originMount->data;
455 
456   /* Make sure that the mount is still healthy */
457 
458   romfs_semtake(rm);
459   ret = romfs_checkmount(rm);
460   if (ret != OK)
461     {
462       PRINTK("ERROR: romfs_checkmount failed: %d\n", ret);
463       goto errout_with_semaphore;
464     }
465 
466   ptr = (struct fs_romfsdir_s *)zalloc(sizeof(struct fs_romfsdir_s));
467   if (ptr == NULL)
468     {
469       ret = -ENOMEM;
470       PRINTK("ERROR: zalloc error for romfsdir. error: %d\n", ret);
471       goto errout_with_semaphore;
472     }
473 
474   dirinfo = (struct romfs_dirinfo_s *)vp->data;
475   memcpy(ptr, &dirinfo->rd_dir, sizeof(struct fs_romfsdir_s));
476   dir->u.fs_dir = (fs_dir_s *)ptr;
477 
478   romfs_semgive(rm);
479   return OK;
480 
481 errout_with_semaphore:
482   romfs_semgive(rm);
483   return ret;
484 }
485 
486 /****************************************************************************
487  * Name: romfs_closedir
488  *
489  * Description:
490  *   Close a directory for read access
491  *
492  ****************************************************************************/
493 
romfs_closedir(struct Vnode * vp,struct fs_dirent_s * dir)494 int romfs_closedir(struct Vnode *vp, struct fs_dirent_s *dir)
495 {
496   struct fs_romfsdir_s *ptr = NULL;
497 
498   ptr = (struct fs_romfsdir_s *)dir->u.fs_dir;
499   if (ptr == NULL)
500     {
501       PRINTK("ERROR: romfs_closedir failed, fs_romfsdir_s is NULL.\n");
502       return -EINVAL;
503     }
504   free(ptr);
505   dir->u.fs_dir = NULL;
506   return 0;
507 }
508 
509 /****************************************************************************
510  * Name: romfs_readdir
511  *
512  * Description: Read the next directory entry
513  *
514  ****************************************************************************/
515 
romfs_readdir(struct Vnode * vp,struct fs_dirent_s * dir)516 static int romfs_readdir(struct Vnode *vp, struct fs_dirent_s *dir)
517 {
518   struct romfs_mountpt_s *rm = NULL;
519   struct fs_romfsdir_s   *romfsdir = NULL;
520   uint32_t                    linkoffset;
521   uint32_t                    next;
522   uint32_t                    info;
523   uint32_t                    size;
524   int                         ret;
525   int                         i = 0;
526 
527   /* Recover our private data from the vnode instance */
528 
529   rm = (struct romfs_mountpt_s *)vp->originMount->data;
530 
531   /* Make sure that the mount is still healthy */
532 
533   romfs_semtake(rm);
534   ret = romfs_checkmount(rm);
535   if (ret != OK)
536     {
537       PRINTK("ERROR: omfs_checkmount failed: %d\n", ret);
538       goto errout_with_semaphore;
539     }
540 
541   romfsdir = (struct fs_romfsdir_s *)dir->u.fs_dir;
542   /* Loop, skipping over unsupported items in the file system */
543 
544   while (i < dir->read_cnt)
545     {
546       /* Have we reached the end of the directory */
547 
548       if (!romfsdir->fr_curroffset)
549         {
550           /* We signal the end of the directory by returning the
551            * special error -ENOENT
552            */
553 
554           ret = -ENOENT;
555           break;
556         }
557 
558       /* Parse the directory entry */
559 
560       ret = romfs_parsedirentry(rm, romfsdir->fr_curroffset, &linkoffset,
561                                 &next, &info, &size);
562       if (ret < 0)
563         {
564           PRINTK("ERROR: romfs_parsedirentry failed: %d\n", ret);
565           goto errout_with_semaphore;
566         }
567 
568       /* Save the filename */
569 
570       ret = romfs_parsefilename(rm, (uint32_t)romfsdir->fr_curroffset, dir->fd_dir[i].d_name);
571       if (ret < 0)
572         {
573           PRINTK("ERROR: romfs_parsefilename failed: %d\n", ret);
574           goto errout_with_semaphore;
575         }
576 
577       /* Set up the next directory entry offset */
578 
579       romfsdir->fr_curroffset = (off_t)next & RFNEXT_OFFSETMASK;
580 
581       if (!strcmp(dir->fd_dir[i].d_name, ".") || !strcmp(dir->fd_dir[i].d_name, ".."))
582         {
583           continue;
584         }
585 
586       /* Check the file type */
587 
588       if (IS_DIRECTORY(next))
589         {
590           dir->fd_dir[i].d_type = DT_DIR;
591         }
592       else if (IS_FILE(next))
593         {
594           dir->fd_dir[i].d_type = DT_REG;
595         }
596 
597       dir->fd_position++;
598       dir->fd_dir[i].d_off = dir->fd_position;
599       dir->fd_dir[i].d_reclen = (uint16_t)sizeof(struct dirent);
600 
601       i++;
602     }
603   romfs_semgive(rm);
604   return i;
605 
606 errout_with_semaphore:
607   romfs_semgive(rm);
608   return ret;
609 }
610 
611 /****************************************************************************
612  * Name: romfs_rewindir
613  *
614  * Description: Reset directory read to the first entry
615  *
616  ****************************************************************************/
617 
romfs_rewinddir(struct Vnode * vp,struct fs_dirent_s * dir)618 static int romfs_rewinddir(struct Vnode *vp, struct fs_dirent_s *dir)
619 {
620   int ret;
621   struct romfs_mountpt_s *rm = NULL;
622   struct fs_romfsdir_s   *romfsdir = NULL;
623 
624   /* Recover our private data from the vnode instance */
625 
626   rm = (struct romfs_mountpt_s *)vp->originMount->data;
627 
628   /* Make sure that the mount is still healthy */
629 
630   romfs_semtake(rm);
631   ret = romfs_checkmount(rm);
632   if (ret == OK)
633     {
634       romfsdir = (struct fs_romfsdir_s *)dir->u.fs_dir;
635       romfsdir->fr_curroffset = romfsdir->fr_firstoffset;
636     }
637 
638   romfs_semgive(rm);
639   return ret;
640 }
641 
642 /****************************************************************************
643  * Name: romfs_bind
644  *
645  * Description: This implements a portion of the mount operation. This
646  *  function allocates and initializes the mountpoint private data and
647  *  binds the blockdriver inode to the filesystem private data.  The final
648  *  binding of the private data (containing the blockdriver) to the
649  *  mountpoint is performed by mount().
650  *
651  ****************************************************************************/
652 
romfs_bind(struct Mount * mnt,struct Vnode * blkDriver,const void * data)653 int romfs_bind(struct Mount *mnt, struct Vnode *blkDriver, const void *data)
654 {
655   struct romfs_mountpt_s *rm = NULL;
656   struct romfs_dirinfo_s *dirinfo = NULL;
657   struct Vnode *pv = NULL;
658   int ret;
659 
660   rm = (struct romfs_mountpt_s *)zalloc(sizeof(struct romfs_mountpt_s));
661   if (!rm)
662     {
663       PRINTK("ERROR: Failed to allocate mountpoint structure, error: %d\n", -ENOMEM);
664       return -ENOMEM;
665     }
666 
667   /* Initialize the allocated mountpt state structure.  The filesystem is
668    * responsible for one reference ont the blkdriver inode and does not
669    * have to addref() here (but does have to release in ubind().
670    */
671 
672   (void)sem_init(&rm->rm_sem, 0, 0);   /* Initialize the semaphore that controls access */
673 
674   /* Get the hardware configuration and setup buffering appropriately */
675 
676   rm->rm_buffer = (uint8_t *)data;
677   ret = romfs_hwconfigure(rm);
678   if (ret)
679     {
680       PRINTK("ERROR: romfs_hwconfigure failed: %d\n", ret);
681       goto errout_with_sem;
682     }
683 
684   /* Then complete the mount by getting the ROMFS configuratrion from
685    * the ROMF header
686    */
687 
688   ret = romfs_fsconfigure(rm);
689   if (ret < 0)
690     {
691       PRINTK("ERROR: romfs_fsconfigure failed: %d\n", ret);
692       goto errout_with_buffer;
693     }
694 
695   dirinfo = (struct romfs_dirinfo_s *)zalloc(sizeof(struct romfs_dirinfo_s));
696   if (!dirinfo)
697     {
698       PRINTK("ERROR: Failed to allocate dirinfo structure, error: %d\n", -ENOMEM);
699       goto errout_with_buffer;
700     }
701 
702   dirinfo->rd_dir.fr_firstoffset = rm->rm_rootoffset;
703   dirinfo->rd_dir.fr_curroffset  = rm->rm_rootoffset;
704   dirinfo->rd_next               = RFNEXT_DIRECTORY;
705   dirinfo->rd_size               = 0;
706 
707   /* Mounted! */
708 
709   ret = VnodeAlloc(&g_romfsVops, &pv);
710   if (ret)
711     {
712       goto errout_with_dirinfo;
713     }
714 
715   pv->type = VNODE_TYPE_DIR;
716   pv->data = dirinfo;
717   pv->originMount = mnt;
718   pv->fop = &g_romfsFops;
719   pv->uid = mnt->vnodeBeCovered->uid;
720   pv->gid = mnt->vnodeBeCovered->gid;
721   pv->mode = S_IFDIR | S_IROTH | S_IXOTH | S_IRGRP | S_IXGRP | S_IRUSR | S_IXUSR;
722   mnt->data = rm;
723   mnt->vnodeCovered = pv;
724 
725   romfs_semgive(rm);
726   return OK;
727 
728 errout_with_dirinfo:
729   free(dirinfo);
730 
731 errout_with_buffer:
732   free(rm->rm_buffer);
733 
734 errout_with_sem:
735   (void)sem_destroy(&rm->rm_sem);
736   free(rm);
737   return ret;
738 }
739 
740 /****************************************************************************
741  * Name: romfs_unbind
742  *
743  * Description: This implements the filesystem portion of the umount
744  *   operation.
745  *
746  ****************************************************************************/
747 
romfs_unbind(struct Mount * mnt,struct Vnode ** blkDriver)748 static int romfs_unbind(struct Mount *mnt, struct Vnode **blkDriver)
749 {
750   struct romfs_mountpt_s *rm = (struct romfs_mountpt_s *)mnt->data;
751 
752   if (!rm)
753     {
754       return -EINVAL;
755     }
756 
757   /* VFS can assure the mountpoint can be umounted. */
758 
759   romfs_semtake(rm);
760   /* Release the mountpoint private data */
761 
762   if (rm->rm_buffer)
763     {
764       free(rm->rm_buffer);
765     }
766 
767   (void)sem_destroy(&rm->rm_sem);
768   free(rm);
769   return OK;
770 }
771 
772 /****************************************************************************
773  * Name: romfs_statfs
774  *
775  * Description: Return filesystem statistics
776  *
777  ****************************************************************************/
778 
romfs_statfs(struct Mount * mnt,struct statfs * buf)779 static int romfs_statfs(struct Mount *mnt, struct statfs *buf)
780 {
781   struct romfs_mountpt_s *rm;
782   int ret;
783 
784   rm = (struct romfs_mountpt_s *)mnt->data;
785 
786   /* Check if the mount is still healthy */
787 
788   romfs_semtake(rm);
789   ret = romfs_checkmount(rm);
790   if (ret < 0)
791     {
792       PRINTK("ERROR: romfs_checkmount failed: %d\n", ret);
793       goto errout_with_semaphore;
794     }
795 
796   /* Fill in the statfs info */
797 
798   memset(buf, 0, sizeof(struct statfs));
799   buf->f_type    = ROMFS_MAGIC;
800 
801   /* We will claim that the optimal transfer size is the size of one sector */
802 
803   buf->f_bsize   = rm->rm_hwsectorsize;
804 
805   /* Everything else follows in units of sectors */
806 
807   buf->f_blocks  = SEC_NSECTORS(rm, rm->rm_volsize + SEC_NDXMASK(rm));
808   buf->f_bfree   = 0;
809   buf->f_bavail  = rm->rm_volsize;
810   buf->f_namelen = NAME_MAX;
811 
812   romfs_semgive(rm);
813   return OK;
814 
815 errout_with_semaphore:
816   romfs_semgive(rm);
817   return ret;
818 }
819 
820 /****************************************************************************
821  * Name: romfs_stat
822  *
823  * Description: Return information about a file or directory
824  *
825  ****************************************************************************/
826 
romfs_stat(struct Vnode * vp,struct stat * buf)827 static int romfs_stat(struct Vnode *vp, struct stat *buf)
828 {
829   struct romfs_mountpt_s *rm = NULL;
830   struct romfs_dirinfo_s *dirinfo = NULL;
831   struct romfs_file_s    *rf = NULL;
832   int ret;
833 
834   rm = (struct romfs_mountpt_s *)vp->originMount->data;
835 
836   /* Check if the mount is still healthy */
837 
838   romfs_semtake(rm);
839   ret = romfs_checkmount(rm);
840   if (ret != OK)
841     {
842       PRINTK("ERROR: romfs_checkmount failed: %d\n", ret);
843       goto errout_with_semaphore;
844     }
845 
846   if (vp->type == VNODE_TYPE_DIR)
847     {
848       dirinfo = (struct romfs_dirinfo_s *)vp->data;
849       buf->st_mode = vp->mode;
850       buf->st_size = dirinfo->rd_size;
851     }
852   else if (vp->type == VNODE_TYPE_REG)
853     {
854       rf = (struct romfs_file_s *)vp->data;
855       buf->st_mode = vp->mode;
856       buf->st_size = rf->rf_size;
857     }
858   else
859     {
860       PRINTK("ERROR: Unsupported file type: %d\n", vp->type);
861       ret = -EINVAL;
862       goto errout_with_semaphore;
863     }
864 
865   buf->st_blksize = rm->rm_hwsectorsize;
866   buf->st_dev     = 0;
867   buf->st_ino     = 0;
868   buf->st_nlink   = 0;
869   buf->st_uid     = vp->uid;
870   buf->st_gid     = vp->gid;
871   buf->st_atime   = 0;
872   buf->st_mtime   = 0;
873   buf->st_ctime   = 0;
874 
875 errout_with_semaphore:
876   romfs_semgive(rm);
877   return ret;
878 }
879 
880 const struct MountOps romfs_operations =
881 {
882   .Mount = romfs_bind,
883   .Unmount = romfs_unbind,
884   .Statfs = romfs_statfs,
885 };
886 
887 struct VnodeOps g_romfsVops =
888 {
889   .Lookup = romfs_lookup,
890   .Create = NULL,
891   .ReadPage = romfs_readpage,
892   .WritePage = NULL,
893   .Rename = NULL,
894   .Mkdir = NULL,
895   .Getattr = romfs_stat,
896   .Opendir = romfs_opendir,
897   .Readdir = romfs_readdir,
898   .Closedir = romfs_closedir,
899   .Rewinddir = romfs_rewinddir,
900   .Unlink = NULL,
901   .Rmdir = NULL,
902   .Chattr = NULL,
903   .Reclaim = romfs_reclaim,
904   .Truncate = NULL,
905   .Truncate64 = NULL,
906 };
907 
908 struct file_operations_vfs g_romfsFops =
909 {
910   .read = romfs_read,
911   .write = NULL,
912   .mmap = OsVfsFileMmap,
913   .seek = romfs_seek,
914   .ioctl = romfs_ioctl,
915   .close = romfs_close,
916   .fsync = NULL,
917 };
918 
919 FSMAP_ENTRY(romfs_fsmap, "romfs", romfs_operations, FALSE, FALSE);
920 
921 #endif
922