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

4.115
Last change on this file since da154e14 was da154e14, checked in by Sebastian Huber <sebastian.huber@…>, on 05/14/12 at 14:55:41

Filesystem: Move operations to mount table entry

The scope of the file system operations is the file system instance.
The scope of the file system node handlers is the file location. The
benefit of moving the operations to the mount table entry is a size
reduction of the file location (rtems_filesystem_location_info_t). The
code size is slightly increased due to additional load instructions.

Restructure rtems_filesystem_mount_table_entry_t to improve cache
efficiency.

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