source: rtems/cpukit/libfs/src/rfs/rtems-rfs-rtems.c @ c6bb1c33

5
Last change on this file since c6bb1c33 was c6bb1c33, checked in by Kevin Kirspel <kevin-kirspel@…>, on 06/29/17 at 14:36:43

posix/mmap: Add support for file handler and MAP_ANON

Added a mmap file handler to struct _rtems_filesystem_file_handlers_r.
Updated each file handler object to support the default mmap handler.
Updated mmap() to call the mmap handler for MAP_SHARED.
Added a mmap file handler for shm

Added support for MAP_ANON in mmap().

Updates #2859

  • Property mode set to 100644
File size: 24.1 KB
Line 
1/**
2 * @file
3 *
4 * @brief RTEMS File System Interface for RTEMS
5 * @ingroup rtems_rfs
6 */
7
8/*
9 *  COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org>
10 *
11 *  Modifications to support reference counting in the file system are
12 *  Copyright (c) 2012 embedded brains GmbH.
13 *
14 *  The license and distribution terms for this file may be
15 *  found in the file LICENSE in this distribution or at
16 *  http://www.rtems.org/license/LICENSE.
17 */
18
19#if HAVE_CONFIG_H
20#include "config.h"
21#endif
22
23#include <sys/param.h>
24#include <inttypes.h>
25#include <string.h>
26#include <stdlib.h>
27
28#include <rtems/inttypes.h>
29
30#include <rtems/rfs/rtems-rfs-file.h>
31#include <rtems/rfs/rtems-rfs-dir.h>
32#include <rtems/rfs/rtems-rfs-link.h>
33#include "rtems-rfs-rtems.h"
34
35static bool
36rtems_rfs_rtems_eval_perms (rtems_filesystem_eval_path_context_t *ctx,
37                            int eval_flags,
38                            rtems_rfs_inode_handle* inode)
39{
40  return rtems_filesystem_eval_path_check_access(
41    ctx,
42    eval_flags,
43    rtems_rfs_inode_get_mode (inode),
44    rtems_rfs_inode_get_uid (inode),
45    rtems_rfs_inode_get_gid (inode)
46  );
47}
48
49static void
50rtems_rfs_rtems_lock_by_mt_entry (
51  const rtems_filesystem_mount_table_entry_t *mt_entry
52)
53{
54  rtems_rfs_file_system* fs = mt_entry->fs_info;
55
56  rtems_rfs_rtems_lock (fs);
57}
58
59static void
60rtems_rfs_rtems_unlock_by_mt_entry (
61  const rtems_filesystem_mount_table_entry_t *mt_entry
62)
63{
64  rtems_rfs_file_system* fs = mt_entry->fs_info;
65
66  rtems_rfs_rtems_unlock (fs);
67}
68
69static bool
70rtems_rfs_rtems_is_directory(
71  rtems_filesystem_eval_path_context_t *ctx,
72  void *arg
73)
74{
75  rtems_rfs_inode_handle* inode = arg;
76
77  return S_ISDIR (rtems_rfs_inode_get_mode (inode));
78}
79
80static void rtems_rfs_rtems_follow_link(
81  rtems_filesystem_eval_path_context_t* ctx,
82  rtems_rfs_file_system* fs,
83  rtems_rfs_ino ino
84)
85{
86  size_t len = MAXPATHLEN;
87  char *link = malloc(len + 1);
88
89  if (link != NULL) {
90    int rc = rtems_rfs_symlink_read (fs, ino, link, len, &len);
91
92    if (rc == 0) {
93      rtems_filesystem_eval_path_recursive (ctx, link, len);
94    } else {
95      rtems_filesystem_eval_path_error (ctx, 0);
96    }
97
98    free(link);
99  } else {
100    rtems_filesystem_eval_path_error (ctx, ENOMEM);
101  }
102}
103
104static rtems_filesystem_eval_path_generic_status
105rtems_rfs_rtems_eval_token(
106  rtems_filesystem_eval_path_context_t *ctx,
107  void *arg,
108  const char *token,
109  size_t tokenlen
110)
111{
112  rtems_filesystem_eval_path_generic_status status =
113    RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_DONE;
114  rtems_rfs_inode_handle* inode = arg;
115  bool access_ok = rtems_rfs_rtems_eval_perms (ctx, RTEMS_FS_PERMS_EXEC, inode);
116
117  if (access_ok) {
118    if (rtems_filesystem_is_current_directory (token, tokenlen)) {
119      rtems_filesystem_eval_path_clear_token (ctx);
120    } else {
121      rtems_filesystem_location_info_t *currentloc =
122        rtems_filesystem_eval_path_get_currentloc( ctx );
123      rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (currentloc);
124      rtems_rfs_ino entry_ino;
125      uint32_t entry_doff;
126      int rc = rtems_rfs_dir_lookup_ino (
127        fs,
128        inode,
129        token,
130        tokenlen,
131        &entry_ino,
132        &entry_doff
133      );
134
135      if (rc == 0) {
136        rc = rtems_rfs_inode_close (fs, inode);
137        if (rc == 0) {
138          rc = rtems_rfs_inode_open (fs, entry_ino, inode, true);
139        }
140
141        if (rc != 0) {
142          /*
143           * This prevents the rtems_rfs_inode_close() from doing something in
144           * rtems_rfs_rtems_eval_path().
145           */
146          memset (inode, 0, sizeof(*inode));
147        }
148      } else {
149        status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_NO_ENTRY;
150        rc = -1;
151      }
152
153      if (rc == 0) {
154        bool is_sym_link = S_ISLNK (rtems_rfs_inode_get_mode (inode));
155        int eval_flags = rtems_filesystem_eval_path_get_flags (ctx);
156        bool follow_sym_link = (eval_flags & RTEMS_FS_FOLLOW_SYM_LINK) != 0;
157        bool terminal = !rtems_filesystem_eval_path_has_path (ctx);
158
159        rtems_filesystem_eval_path_clear_token (ctx);
160
161        if (is_sym_link && (follow_sym_link || !terminal)) {
162          rtems_rfs_rtems_follow_link (ctx, fs, entry_ino);
163        } else {
164          rc = rtems_rfs_rtems_set_handlers (currentloc, inode) ? 0 : EIO;
165          if (rc == 0) {
166            rtems_rfs_rtems_set_pathloc_ino (currentloc, entry_ino);
167            rtems_rfs_rtems_set_pathloc_doff (currentloc, entry_doff);
168
169            if (!terminal) {
170              status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_CONTINUE;
171            }
172          } else {
173            rtems_filesystem_eval_path_error (
174              ctx,
175              rtems_rfs_rtems_error ("eval_path: set handlers", rc)
176            );
177          }
178        }
179      }
180    }
181  }
182
183  return status;
184}
185
186static const rtems_filesystem_eval_path_generic_config
187rtems_rfs_rtems_eval_config = {
188  .is_directory = rtems_rfs_rtems_is_directory,
189  .eval_token = rtems_rfs_rtems_eval_token
190};
191
192static void
193rtems_rfs_rtems_eval_path (rtems_filesystem_eval_path_context_t *ctx)
194{
195  rtems_filesystem_location_info_t *currentloc =
196    rtems_filesystem_eval_path_get_currentloc (ctx);
197  rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (currentloc);
198  rtems_rfs_ino ino = rtems_rfs_rtems_get_pathloc_ino (currentloc);
199  rtems_rfs_inode_handle inode;
200  int rc;
201
202  rc = rtems_rfs_inode_open (fs, ino, &inode, true);
203  if (rc == 0) {
204    rtems_filesystem_eval_path_generic (
205      ctx,
206      &inode,
207      &rtems_rfs_rtems_eval_config
208    );
209    rc = rtems_rfs_inode_close (fs, &inode);
210    if (rc != 0) {
211      rtems_filesystem_eval_path_error (
212        ctx,
213        rtems_rfs_rtems_error ("eval_path: closing inode", rc)
214      );
215    }
216  } else {
217    rtems_filesystem_eval_path_error (
218      ctx,
219      rtems_rfs_rtems_error ("eval_path: opening inode", rc)
220    );
221  }
222}
223
224/**
225 * The following rouine creates a new link node under parent with the name
226 * given in name. The link node is set to point to the node at targetloc.
227 */
228static int
229rtems_rfs_rtems_link (const rtems_filesystem_location_info_t *parentloc,
230                      const rtems_filesystem_location_info_t *targetloc,
231                      const char *name,
232                      size_t namelen)
233{
234  rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (targetloc);
235  rtems_rfs_ino          target = rtems_rfs_rtems_get_pathloc_ino (targetloc);
236  rtems_rfs_ino          parent = rtems_rfs_rtems_get_pathloc_ino (parentloc);
237  int                    rc;
238
239  if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_LINK))
240    printf ("rtems-rfs-rtems: link: in: parent:%" PRId32 " target:%" PRId32 "\n",
241            parent, target);
242
243  rc = rtems_rfs_link (fs, name, namelen, parent, target, false);
244  if (rc)
245  {
246    return rtems_rfs_rtems_error ("link: linking", rc);
247        }
248
249
250        return 0;
251}
252
253/**
254 * This routine is the implementation of the chown() system call for the
255 * RFS.
256 *
257 * @param pathloc
258 * @param owner
259 * @param group
260 * return int
261 */
262
263static int
264rtems_rfs_rtems_chown (const rtems_filesystem_location_info_t *pathloc,
265                       uid_t                                   owner,
266                       gid_t                                   group)
267{
268  rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc);
269  rtems_rfs_ino          ino = rtems_rfs_rtems_get_pathloc_ino (pathloc);
270  rtems_rfs_inode_handle inode;
271  int                    rc;
272
273  if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_CHOWN))
274    printf ("rtems-rfs-rtems: chown: in: ino:%" PRId32 " uid:%d gid:%d\n",
275            ino, owner, group);
276
277  rc = rtems_rfs_inode_open (fs, ino, &inode, true);
278  if (rc > 0)
279  {
280    return rtems_rfs_rtems_error ("chown: opening inode", rc);
281  }
282
283  rtems_rfs_inode_set_uid_gid (&inode, owner, group);
284
285  rc = rtems_rfs_inode_close (fs, &inode);
286  if (rc)
287  {
288    return rtems_rfs_rtems_error ("chown: closing inode", rc);
289  }
290
291  return 0;
292}
293
294/**
295 * This routine is the implementation of the utime() system call for the
296 * RFS.
297 *
298 * @param pathloc
299 * @param atime
300 * @param mtime
301 * return int
302 */
303
304static int
305rtems_rfs_rtems_utime(const rtems_filesystem_location_info_t* pathloc,
306                      time_t                                  atime,
307                      time_t                                  mtime)
308{
309  rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc);
310  rtems_rfs_ino          ino = rtems_rfs_rtems_get_pathloc_ino (pathloc);
311  rtems_rfs_inode_handle inode;
312  int                    rc;
313
314  rc = rtems_rfs_inode_open (fs, ino, &inode, true);
315  if (rc)
316  {
317    return rtems_rfs_rtems_error ("utime: read inode", rc);
318  }
319
320  rtems_rfs_inode_set_atime (&inode, atime);
321  rtems_rfs_inode_set_mtime (&inode, mtime);
322
323  rc = rtems_rfs_inode_close (fs, &inode);
324  if (rc)
325  {
326    return rtems_rfs_rtems_error ("utime: closing inode", rc);
327  }
328
329  return 0;
330}
331
332/**
333 * The following routine creates a new symbolic link node under parent with the
334 * name given in node_name.
335 */
336
337static int
338rtems_rfs_rtems_symlink (const rtems_filesystem_location_info_t* parent_loc,
339                         const char*                             node_name,
340                         size_t                                  node_name_len,
341                         const char*                             target)
342{
343  rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (parent_loc);
344  rtems_rfs_ino          parent = rtems_rfs_rtems_get_pathloc_ino (parent_loc);
345  int                    rc;
346
347  rc = rtems_rfs_symlink (fs, node_name, node_name_len,
348                          target, strlen (target),
349                          geteuid(), getegid(), parent);
350  if (rc)
351  {
352    return rtems_rfs_rtems_error ("symlink: linking", rc);
353  }
354
355  return 0;
356}
357
358/**
359 * The following rouine puts the symblic links destination name into buf.
360 */
361
362static ssize_t
363rtems_rfs_rtems_readlink (const rtems_filesystem_location_info_t* pathloc,
364                          char*                                   buf,
365                          size_t                                  bufsize)
366{
367  rtems_rfs_file_system*  fs = rtems_rfs_rtems_pathloc_dev (pathloc);
368  rtems_rfs_ino           ino = rtems_rfs_rtems_get_pathloc_ino (pathloc);
369  size_t                  length;
370  int                     rc;
371
372  if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_READLINK))
373    printf ("rtems-rfs-rtems: readlink: in: ino:%" PRId32 "\n", ino);
374
375  rc = rtems_rfs_symlink_read (fs, ino, buf, bufsize, &length);
376  if (rc)
377  {
378    return rtems_rfs_rtems_error ("readlink: reading link", rc);
379  }
380
381  return (ssize_t) length;
382}
383
384static int
385rtems_rfs_rtems_fchmod (const rtems_filesystem_location_info_t* pathloc,
386                        mode_t                                  mode)
387{
388  rtems_rfs_file_system*  fs = rtems_rfs_rtems_pathloc_dev (pathloc);
389  rtems_rfs_ino           ino = rtems_rfs_rtems_get_pathloc_ino (pathloc);
390  rtems_rfs_inode_handle  inode;
391  int                     rc;
392
393  if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_FCHMOD))
394    printf ("rtems-rfs-rtems: fchmod: in: ino:%" PRId32 " mode:%06" PRIomode_t "\n",
395            ino, mode);
396
397  rc = rtems_rfs_inode_open (fs, ino, &inode, true);
398  if (rc)
399  {
400    return rtems_rfs_rtems_error ("fchmod: opening inode", rc);
401  }
402
403  rtems_rfs_inode_set_mode (&inode, mode);
404
405  rc = rtems_rfs_inode_close (fs, &inode);
406  if (rc > 0)
407  {
408    return rtems_rfs_rtems_error ("fchmod: closing inode", rc);
409  }
410
411  return 0;
412}
413
414int
415rtems_rfs_rtems_fstat (const rtems_filesystem_location_info_t* pathloc,
416                       struct stat*                            buf)
417{
418  rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc);
419  rtems_rfs_ino          ino = rtems_rfs_rtems_get_pathloc_ino (pathloc);
420  rtems_rfs_inode_handle inode;
421  rtems_rfs_file_shared* shared;
422  uint16_t               mode;
423  int                    rc;
424
425  if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_STAT))
426    printf ("rtems-rfs-rtems: stat: in: ino:%" PRId32 "\n", ino);
427
428  rc = rtems_rfs_inode_open (fs, ino, &inode, true);
429  if (rc)
430  {
431    return rtems_rfs_rtems_error ("stat: opening inode", rc);
432  }
433
434  mode = rtems_rfs_inode_get_mode (&inode);
435
436  if (RTEMS_RFS_S_ISCHR (mode) || RTEMS_RFS_S_ISBLK (mode))
437  {
438    buf->st_rdev =
439      rtems_filesystem_make_dev_t (rtems_rfs_inode_get_block (&inode, 0),
440                                   rtems_rfs_inode_get_block (&inode, 1));
441  }
442
443  buf->st_dev     = (dev_t) (uintptr_t)rtems_rfs_fs_device (fs);
444  buf->st_ino     = rtems_rfs_inode_ino (&inode);
445  buf->st_mode    = rtems_rfs_rtems_mode (mode);
446  buf->st_nlink   = rtems_rfs_inode_get_links (&inode);
447  buf->st_uid     = rtems_rfs_inode_get_uid (&inode);
448  buf->st_gid     = rtems_rfs_inode_get_gid (&inode);
449
450  /*
451   * Need to check is the ino is an open file. If so we take the values from
452   * the open file rather than the inode.
453   */
454  shared = rtems_rfs_file_get_shared (fs, rtems_rfs_inode_ino (&inode));
455
456  if (shared)
457  {
458    buf->st_atime   = rtems_rfs_file_shared_get_atime (shared);
459    buf->st_mtime   = rtems_rfs_file_shared_get_mtime (shared);
460    buf->st_ctime   = rtems_rfs_file_shared_get_ctime (shared);
461    buf->st_blocks  = rtems_rfs_file_shared_get_block_count (shared);
462
463    if (S_ISLNK (buf->st_mode))
464      buf->st_size = rtems_rfs_file_shared_get_block_offset (shared);
465    else
466      buf->st_size = rtems_rfs_file_shared_get_size (fs, shared);
467  }
468  else
469  {
470    buf->st_atime   = rtems_rfs_inode_get_atime (&inode);
471    buf->st_mtime   = rtems_rfs_inode_get_mtime (&inode);
472    buf->st_ctime   = rtems_rfs_inode_get_ctime (&inode);
473    buf->st_blocks  = rtems_rfs_inode_get_block_count (&inode);
474
475    if (S_ISLNK (buf->st_mode))
476      buf->st_size = rtems_rfs_inode_get_block_offset (&inode);
477    else
478      buf->st_size = rtems_rfs_inode_get_size (fs, &inode);
479  }
480
481  buf->st_blksize = rtems_rfs_fs_block_size (fs);
482
483  rc = rtems_rfs_inode_close (fs, &inode);
484  if (rc > 0)
485  {
486    return rtems_rfs_rtems_error ("stat: closing inode", rc);
487  }
488
489  return 0;
490}
491
492/**
493 * Routine to create a node in the RFS file system.
494 */
495
496static int
497rtems_rfs_rtems_mknod (const rtems_filesystem_location_info_t *parentloc,
498                       const char                             *name,
499                       size_t                                  namelen,
500                       mode_t                                  mode,
501                       dev_t                                   dev)
502{
503  rtems_rfs_file_system*  fs = rtems_rfs_rtems_pathloc_dev (parentloc);
504  rtems_rfs_ino           parent = rtems_rfs_rtems_get_pathloc_ino (parentloc);
505  rtems_rfs_ino           ino;
506  rtems_rfs_inode_handle  inode;
507  uid_t                   uid;
508  gid_t                   gid;
509  int                     rc;
510
511  uid = geteuid ();
512  gid = getegid ();
513
514  rc = rtems_rfs_inode_create (fs, parent, name, namelen,
515                               rtems_rfs_rtems_imode (mode),
516                               1, uid, gid, &ino);
517  if (rc > 0)
518  {
519    return rtems_rfs_rtems_error ("mknod: inode create", rc);
520  }
521
522  rc = rtems_rfs_inode_open (fs, ino, &inode, true);
523  if (rc > 0)
524  {
525    return rtems_rfs_rtems_error ("mknod: inode open", rc);
526  }
527
528  if (S_ISDIR(mode) || S_ISREG(mode))
529  {
530  }
531  else if (S_ISCHR (mode) || S_ISBLK (mode))
532  {
533    int major;
534    int minor;
535    rtems_filesystem_split_dev_t (dev, major, minor);
536    rtems_rfs_inode_set_block (&inode, 0, major);
537    rtems_rfs_inode_set_block (&inode, 1, minor);
538  }
539  else
540  {
541    rtems_rfs_inode_close (fs, &inode);
542    return rtems_rfs_rtems_error ("mknod: bad mode", EINVAL);
543  }
544
545  rc = rtems_rfs_inode_close (fs, &inode);
546  if (rc > 0)
547  {
548    return rtems_rfs_rtems_error ("mknod: closing inode", rc);
549  }
550
551  return 0;
552}
553
554/**
555 * Routine to remove a node from the RFS file system.
556 *
557 * @param parent_pathloc
558 * @param pathloc
559 * @return int
560 */
561int
562rtems_rfs_rtems_rmnod (const rtems_filesystem_location_info_t* parent_pathloc,
563                       const rtems_filesystem_location_info_t* pathloc)
564{
565  rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc);
566  rtems_rfs_ino          parent = rtems_rfs_rtems_get_pathloc_ino (parent_pathloc);
567  rtems_rfs_ino          ino = rtems_rfs_rtems_get_pathloc_ino (pathloc);
568  uint32_t               doff = rtems_rfs_rtems_get_pathloc_doff (pathloc);
569  int                    rc;
570
571  if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_RMNOD))
572    printf ("rtems-rfs: rmnod: parent:%" PRId32 " doff:%" PRIu32 ", ino:%" PRId32 "\n",
573            parent, doff, ino);
574
575  rc = rtems_rfs_unlink (fs, parent, ino, doff, rtems_rfs_unlink_dir_if_empty);
576  if (rc)
577  {
578    return rtems_rfs_rtems_error ("rmnod: unlinking", rc);
579  }
580
581  return 0;
582}
583
584/**
585 * The following routine does a sync on an inode node. Currently it flushes
586 * everything related to this device.
587 *
588 * @param iop
589 * @return int
590 */
591int
592rtems_rfs_rtems_fdatasync (rtems_libio_t* iop)
593{
594  int rc;
595
596  rc = rtems_rfs_buffer_sync (rtems_rfs_rtems_pathloc_dev (&iop->pathinfo));
597  if (rc)
598    return rtems_rfs_rtems_error ("fdatasync: sync", rc);
599
600  return 0;
601}
602
603/**
604 * Rename the node.
605 */
606static int
607rtems_rfs_rtems_rename(const rtems_filesystem_location_info_t* old_parent_loc,
608                       const rtems_filesystem_location_info_t* old_loc,
609                       const rtems_filesystem_location_info_t* new_parent_loc,
610                       const char*                             new_name,
611                       size_t                                  new_name_len)
612{
613  rtems_rfs_file_system*  fs = rtems_rfs_rtems_pathloc_dev (old_loc);
614  rtems_rfs_ino           old_parent;
615  rtems_rfs_ino           new_parent;
616  rtems_rfs_ino           ino;
617  uint32_t                doff;
618  int                     rc;
619
620  old_parent = rtems_rfs_rtems_get_pathloc_ino (old_parent_loc);
621  new_parent = rtems_rfs_rtems_get_pathloc_ino (new_parent_loc);
622
623  ino  = rtems_rfs_rtems_get_pathloc_ino (old_loc);
624  doff = rtems_rfs_rtems_get_pathloc_doff (old_loc);
625
626  if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_RENAME))
627    printf ("rtems-rfs: rename: ino:%" PRId32 " doff:%" PRIu32 ", new parent:%" PRId32 "\n",
628            ino, doff, new_parent);
629
630  /*
631   * Link to the inode before unlinking so the inode is not erased when
632   * unlinked.
633   */
634  rc = rtems_rfs_link (fs, new_name, new_name_len, new_parent, ino, true);
635  if (rc)
636  {
637    return rtems_rfs_rtems_error ("rename: linking", rc);
638  }
639
640  /*
641   * Unlink all inodes even directories with the dir option as false because a
642   * directory may not be empty.
643   */
644  rc = rtems_rfs_unlink (fs, old_parent, ino, doff,
645                         rtems_rfs_unlink_dir_allowed);
646  if (rc)
647  {
648    return rtems_rfs_rtems_error ("rename: unlinking", rc);
649  }
650
651  return 0;
652}
653
654/**
655 * Return the file system stat data.
656 *
657 * @param pathloc
658 * @param sb
659 * @return int
660 */
661static int
662rtems_rfs_rtems_statvfs (
663  const rtems_filesystem_location_info_t *__restrict pathloc,
664  struct statvfs *__restrict                         sb)
665{
666  rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc);
667  size_t                 blocks;
668  size_t                 inodes;
669
670  rtems_rfs_group_usage (fs, &blocks, &inodes);
671
672  sb->f_bsize   = rtems_rfs_fs_block_size (fs);
673  sb->f_frsize  = rtems_rfs_fs_media_block_size (fs);
674  sb->f_blocks  = rtems_rfs_fs_media_blocks (fs);
675  sb->f_bfree   = rtems_rfs_fs_blocks (fs) - blocks - 1; /* do not count the superblock */
676  sb->f_bavail  = sb->f_bfree;
677  sb->f_files   = rtems_rfs_fs_inodes (fs);
678  sb->f_ffree   = rtems_rfs_fs_inodes (fs) - inodes;
679  sb->f_favail  = sb->f_ffree;
680  sb->f_fsid    = RTEMS_RFS_SB_MAGIC;
681  sb->f_flag    = rtems_rfs_fs_flags (fs);
682  sb->f_namemax = rtems_rfs_fs_max_name (fs);
683
684  return 0;
685}
686
687/**
688 *  Handler table for RFS link nodes
689 */
690const rtems_filesystem_file_handlers_r rtems_rfs_rtems_link_handlers =
691{
692  .open_h      = rtems_filesystem_default_open,
693  .close_h     = rtems_filesystem_default_close,
694  .read_h      = rtems_filesystem_default_read,
695  .write_h     = rtems_filesystem_default_write,
696  .ioctl_h     = rtems_filesystem_default_ioctl,
697  .lseek_h     = rtems_filesystem_default_lseek,
698  .fstat_h     = rtems_rfs_rtems_fstat,
699  .ftruncate_h = rtems_filesystem_default_ftruncate,
700  .fsync_h     = rtems_filesystem_default_fsync_or_fdatasync,
701  .fdatasync_h = rtems_filesystem_default_fsync_or_fdatasync,
702  .fcntl_h     = rtems_filesystem_default_fcntl,
703  .kqfilter_h  = rtems_filesystem_default_kqfilter,
704  .mmap_h      = rtems_filesystem_default_mmap,
705  .poll_h      = rtems_filesystem_default_poll,
706  .readv_h     = rtems_filesystem_default_readv,
707  .writev_h    = rtems_filesystem_default_writev
708};
709
710/**
711 * Forward decl for the ops table.
712 */
713
714int rtems_rfs_rtems_initialise (rtems_filesystem_mount_table_entry_t *mt_entry,
715                                const void                           *data);
716void rtems_rfs_rtems_shutdown (rtems_filesystem_mount_table_entry_t *mt_entry);
717
718/**
719 * RFS file system operations table.
720 */
721const rtems_filesystem_operations_table rtems_rfs_ops =
722{
723  .lock_h         = rtems_rfs_rtems_lock_by_mt_entry,
724  .unlock_h       = rtems_rfs_rtems_unlock_by_mt_entry,
725  .are_nodes_equal_h = rtems_filesystem_default_are_nodes_equal,
726  .eval_path_h    = rtems_rfs_rtems_eval_path,
727  .link_h         = rtems_rfs_rtems_link,
728  .fchmod_h       = rtems_rfs_rtems_fchmod,
729  .mknod_h        = rtems_rfs_rtems_mknod,
730  .rmnod_h        = rtems_rfs_rtems_rmnod,
731  .chown_h        = rtems_rfs_rtems_chown,
732  .clonenod_h     = rtems_filesystem_default_clonenode,
733  .freenod_h      = rtems_filesystem_default_freenode,
734  .mount_h        = rtems_filesystem_default_mount,
735  .unmount_h      = rtems_filesystem_default_unmount,
736  .fsunmount_me_h = rtems_rfs_rtems_shutdown,
737  .utime_h        = rtems_rfs_rtems_utime,
738  .symlink_h      = rtems_rfs_rtems_symlink,
739  .readlink_h     = rtems_rfs_rtems_readlink,
740  .rename_h       = rtems_rfs_rtems_rename,
741  .statvfs_h      = rtems_rfs_rtems_statvfs
742};
743
744/**
745 * Open the file system.
746 */
747
748int
749rtems_rfs_rtems_initialise (rtems_filesystem_mount_table_entry_t* mt_entry,
750                            const void*                           data)
751{
752  rtems_rfs_rtems_private* rtems;
753  rtems_rfs_file_system*   fs;
754  uint32_t                 flags = 0;
755  uint32_t                 max_held_buffers = RTEMS_RFS_FS_MAX_HELD_BUFFERS;
756  const char*              options = data;
757  int                      rc;
758
759  /*
760   * Parse the options the user specifiies.
761   */
762  while (options)
763  {
764    printf ("options=%s\n", options);
765    if (strncmp (options, "hold-bitmaps",
766                 sizeof ("hold-bitmaps") - 1) == 0)
767      flags |= RTEMS_RFS_FS_BITMAPS_HOLD;
768    else if (strncmp (options, "no-local-cache",
769                      sizeof ("no-local-cache") - 1) == 0)
770      flags |= RTEMS_RFS_FS_NO_LOCAL_CACHE;
771    else if (strncmp (options, "max-held-bufs",
772                      sizeof ("max-held-bufs") - 1) == 0)
773    {
774      max_held_buffers = strtoul (options + sizeof ("max-held-bufs"), 0, 0);
775    }
776    else
777      return rtems_rfs_rtems_error ("initialise: invalid option", EINVAL);
778
779    options = strchr (options, ',');
780    if (options)
781    {
782      ++options;
783      if (*options == '\0')
784        options = NULL;
785    }
786  }
787
788  rtems = malloc (sizeof (rtems_rfs_rtems_private));
789  if (!rtems)
790    return rtems_rfs_rtems_error ("initialise: local data", ENOMEM);
791
792  memset (rtems, 0, sizeof (rtems_rfs_rtems_private));
793
794  rc = rtems_rfs_mutex_create (&rtems->access);
795  if (rc > 0)
796  {
797    free (rtems);
798    return rtems_rfs_rtems_error ("initialise: cannot create mutex", rc);
799  }
800
801  rc = rtems_rfs_mutex_lock (&rtems->access);
802  if (rc > 0)
803  {
804    rtems_rfs_mutex_destroy (&rtems->access);
805    free (rtems);
806    return rtems_rfs_rtems_error ("initialise: cannot lock access  mutex", rc);
807  }
808
809  rc = rtems_rfs_fs_open (mt_entry->dev, rtems, flags, max_held_buffers, &fs);
810  if (rc)
811  {
812    rtems_rfs_mutex_unlock (&rtems->access);
813    rtems_rfs_mutex_destroy (&rtems->access);
814    free (rtems);
815    return rtems_rfs_rtems_error ("initialise: open", errno);
816  }
817
818  mt_entry->fs_info                          = fs;
819  mt_entry->ops                              = &rtems_rfs_ops;
820  mt_entry->mt_fs_root->location.node_access = (void*) RTEMS_RFS_ROOT_INO;
821  mt_entry->mt_fs_root->location.handlers    = &rtems_rfs_rtems_dir_handlers;
822
823  rtems_rfs_rtems_unlock (fs);
824
825  return 0;
826}
827
828/**
829 * Shutdown the file system.
830 */
831void
832rtems_rfs_rtems_shutdown (rtems_filesystem_mount_table_entry_t* mt_entry)
833{
834  rtems_rfs_file_system*   fs = mt_entry->fs_info;
835  rtems_rfs_rtems_private* rtems;
836
837  rtems = rtems_rfs_fs_user (fs);
838
839  /* FIXME: Return value? */
840  rtems_rfs_fs_close(fs);
841
842  rtems_rfs_mutex_destroy (&rtems->access);
843  free (rtems);
844}
Note: See TracBrowser for help on using the repository browser.