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

4.11
Last change on this file since ad659ff8 was ad659ff8, checked in by Sebastian Huber <sebastian.huber@…>, on 10/21/15 at 07:52:36

RFS: Fix resource leak

Update #2433.

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