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

4.11
Last change on this file since 7666afc was 7666afc, checked in by Sebastian Huber <sebastian.huber@…>, on May 14, 2012 at 2:53:49 PM

Filesystem: Add const qualifier to lock/unlock

  • Property mode set to 100644
File size: 26.7 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
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  mt_entry->mt_fs_root->location.ops         = &rtems_rfs_ops;
926
927  rtems_rfs_rtems_unlock (fs);
928
929  return 0;
930}
931
932/**
933 * Shutdown the file system.
934 */
935void
936rtems_rfs_rtems_shutdown (rtems_filesystem_mount_table_entry_t* mt_entry)
937{
938  rtems_rfs_file_system*   fs = mt_entry->fs_info;
939  rtems_rfs_rtems_private* rtems;
940
941  rtems = rtems_rfs_fs_user (fs);
942
943  /* FIXME: Return value? */
944  rtems_rfs_fs_close(fs);
945
946  rtems_rfs_mutex_destroy (&rtems->access);
947  free (rtems);
948}
Note: See TracBrowser for help on using the repository browser.