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

4.115
Last change on this file since c17d0b3 was c17d0b3, checked in by Sebastian Huber <sebastian.huber@…>, on 10/02/12 at 13:44:59

Filesystem: Reject removal of root nodes

Reject the removal of file system instance root nodes in rmdir() and
unlink() and return the EBUSY error status. File system instances can
be removed with unmount(). Remove root node special cases in IMFS,
DOSFS, and RFS.

  • 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  rc = rtems_rfs_unlink (fs, parent, ino, doff, rtems_rfs_unlink_dir_if_empty);
682  if (rc)
683  {
684    return rtems_rfs_rtems_error ("rmnod: unlinking", rc);
685  }
686
687  return 0;
688}
689
690/**
691 * The following routine does a sync on an inode node. Currently it flushes
692 * everything related to this device.
693 *
694 * @param iop
695 * @return int
696 */
697int
698rtems_rfs_rtems_fdatasync (rtems_libio_t* iop)
699{
700  int rc;
701
702  rc = rtems_rfs_buffer_sync (rtems_rfs_rtems_pathloc_dev (&iop->pathinfo));
703  if (rc)
704    return rtems_rfs_rtems_error ("fdatasync: sync", rc);
705
706  return 0;
707}
708
709/**
710 * Rename the node.
711 */
712static int
713rtems_rfs_rtems_rename(const rtems_filesystem_location_info_t* old_parent_loc,
714                       const rtems_filesystem_location_info_t* old_loc,
715                       const rtems_filesystem_location_info_t* new_parent_loc,
716                       const char*                             new_name,
717                       size_t                                  new_name_len)
718{
719  rtems_rfs_file_system*  fs = rtems_rfs_rtems_pathloc_dev (old_loc);
720  rtems_rfs_ino           old_parent;
721  rtems_rfs_ino           new_parent;
722  rtems_rfs_ino           ino;
723  uint32_t                doff;
724  int                     rc;
725
726  old_parent = rtems_rfs_rtems_get_pathloc_ino (old_parent_loc);
727  new_parent = rtems_rfs_rtems_get_pathloc_ino (new_parent_loc);
728
729  ino  = rtems_rfs_rtems_get_pathloc_ino (old_loc);
730  doff = rtems_rfs_rtems_get_pathloc_doff (old_loc);
731
732  if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_RENAME))
733    printf ("rtems-rfs: rename: ino:%" PRId32 " doff:%" PRIu32 ", new parent:%" PRId32 "\n",
734            ino, doff, new_parent);
735
736  /*
737   * Link to the inode before unlinking so the inode is not erased when
738   * unlinked.
739   */
740  rc = rtems_rfs_link (fs, new_name, new_name_len, new_parent, ino, true);
741  if (rc)
742  {
743    return rtems_rfs_rtems_error ("rename: linking", rc);
744  }
745
746  /*
747   * Unlink all inodes even directories with the dir option as false because a
748   * directory may not be empty.
749   */
750  rc = rtems_rfs_unlink (fs, old_parent, ino, doff,
751                         rtems_rfs_unlink_dir_allowed);
752  if (rc)
753  {
754    return rtems_rfs_rtems_error ("rename: unlinking", rc);
755  }
756
757  return 0;
758}
759
760/**
761 * Return the file system stat data.
762 *
763 * @param pathloc
764 * @param sb
765 * @return int
766 */
767static int
768rtems_rfs_rtems_statvfs (const rtems_filesystem_location_info_t* pathloc,
769                         struct statvfs*                         sb)
770{
771  rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc);
772  size_t                 blocks;
773  size_t                 inodes;
774
775  rtems_rfs_group_usage (fs, &blocks, &inodes);
776
777  sb->f_bsize   = rtems_rfs_fs_block_size (fs);
778  sb->f_frsize  = rtems_rfs_fs_media_block_size (fs);
779  sb->f_blocks  = rtems_rfs_fs_media_blocks (fs);
780  sb->f_bfree   = rtems_rfs_fs_blocks (fs) - blocks;
781  sb->f_bavail  = sb->f_bfree;
782  sb->f_files   = rtems_rfs_fs_inodes (fs);
783  sb->f_ffree   = rtems_rfs_fs_inodes (fs) - inodes;
784  sb->f_favail  = sb->f_ffree;
785  sb->f_fsid    = RTEMS_RFS_SB_MAGIC;
786  sb->f_flag    = rtems_rfs_fs_flags (fs);
787  sb->f_namemax = rtems_rfs_fs_max_name (fs);
788
789  return 0;
790}
791
792/**
793 *  Handler table for RFS link nodes
794 */
795const rtems_filesystem_file_handlers_r rtems_rfs_rtems_link_handlers =
796{
797  .open_h      = rtems_filesystem_default_open,
798  .close_h     = rtems_filesystem_default_close,
799  .read_h      = rtems_filesystem_default_read,
800  .write_h     = rtems_filesystem_default_write,
801  .ioctl_h     = rtems_filesystem_default_ioctl,
802  .lseek_h     = rtems_filesystem_default_lseek,
803  .fstat_h     = rtems_rfs_rtems_fstat,
804  .ftruncate_h = rtems_filesystem_default_ftruncate,
805  .fsync_h     = rtems_filesystem_default_fsync_or_fdatasync,
806  .fdatasync_h = rtems_filesystem_default_fsync_or_fdatasync,
807  .fcntl_h     = rtems_filesystem_default_fcntl
808};
809
810/**
811 * Forward decl for the ops table.
812 */
813
814int rtems_rfs_rtems_initialise (rtems_filesystem_mount_table_entry_t *mt_entry,
815                                const void                           *data);
816void rtems_rfs_rtems_shutdown (rtems_filesystem_mount_table_entry_t *mt_entry);
817
818/**
819 * RFS file system operations table.
820 */
821const rtems_filesystem_operations_table rtems_rfs_ops =
822{
823  .lock_h         = rtems_rfs_rtems_lock_by_mt_entry,
824  .unlock_h       = rtems_rfs_rtems_unlock_by_mt_entry,
825  .are_nodes_equal_h = rtems_filesystem_default_are_nodes_equal,
826  .eval_path_h    = rtems_rfs_rtems_eval_path,
827  .link_h         = rtems_rfs_rtems_link,
828  .node_type_h    = rtems_rfs_rtems_node_type,
829  .fchmod_h       = rtems_rfs_rtems_fchmod,
830  .mknod_h        = rtems_rfs_rtems_mknod,
831  .rmnod_h        = rtems_rfs_rtems_rmnod,
832  .chown_h        = rtems_rfs_rtems_chown,
833  .clonenod_h     = rtems_filesystem_default_clonenode,
834  .freenod_h      = rtems_filesystem_default_freenode,
835  .mount_h        = rtems_filesystem_default_mount,
836  .fsmount_me_h   = rtems_rfs_rtems_initialise,
837  .unmount_h      = rtems_filesystem_default_unmount,
838  .fsunmount_me_h = rtems_rfs_rtems_shutdown,
839  .utime_h        = rtems_rfs_rtems_utime,
840  .symlink_h      = rtems_rfs_rtems_symlink,
841  .readlink_h     = rtems_rfs_rtems_readlink,
842  .rename_h       = rtems_rfs_rtems_rename,
843  .statvfs_h      = rtems_rfs_rtems_statvfs
844};
845
846/**
847 * Open the file system.
848 */
849
850int
851rtems_rfs_rtems_initialise (rtems_filesystem_mount_table_entry_t* mt_entry,
852                            const void*                           data)
853{
854  rtems_rfs_rtems_private* rtems;
855  rtems_rfs_file_system*   fs;
856  uint32_t                 flags = 0;
857  uint32_t                 max_held_buffers = RTEMS_RFS_FS_MAX_HELD_BUFFERS;
858  const char*              options = data;
859  int                      rc;
860
861  /*
862   * Parse the options the user specifiies.
863   */
864  while (options)
865  {
866    printf ("options=%s\n", options);
867    if (strncmp (options, "hold-bitmaps",
868                 sizeof ("hold-bitmaps") - 1) == 0)
869      flags |= RTEMS_RFS_FS_BITMAPS_HOLD;
870    else if (strncmp (options, "no-local-cache",
871                      sizeof ("no-local-cache") - 1) == 0)
872      flags |= RTEMS_RFS_FS_NO_LOCAL_CACHE;
873    else if (strncmp (options, "max-held-bufs",
874                      sizeof ("max-held-bufs") - 1) == 0)
875    {
876      max_held_buffers = strtoul (options + sizeof ("max-held-bufs"), 0, 0);
877    }
878    else
879      return rtems_rfs_rtems_error ("initialise: invalid option", EINVAL);
880
881    options = strchr (options, ',');
882    if (options)
883    {
884      ++options;
885      if (*options == '\0')
886        options = NULL;
887    }
888  }
889
890  rtems = malloc (sizeof (rtems_rfs_rtems_private));
891  if (!rtems)
892    return rtems_rfs_rtems_error ("initialise: local data", ENOMEM);
893
894  memset (rtems, 0, sizeof (rtems_rfs_rtems_private));
895
896  rc = rtems_rfs_mutex_create (&rtems->access);
897  if (rc > 0)
898  {
899    free (rtems);
900    return rtems_rfs_rtems_error ("initialise: cannot create mutex", rc);
901  }
902
903  rc = rtems_rfs_mutex_lock (&rtems->access);
904  if (rc > 0)
905  {
906    rtems_rfs_mutex_destroy (&rtems->access);
907    free (rtems);
908    return rtems_rfs_rtems_error ("initialise: cannot lock access  mutex", rc);
909  }
910
911  rc = rtems_rfs_fs_open (mt_entry->dev, rtems, flags, max_held_buffers, &fs);
912  if (rc)
913  {
914    free (rtems);
915    return rtems_rfs_rtems_error ("initialise: open", rc);
916  }
917
918  mt_entry->fs_info                          = fs;
919  mt_entry->ops                              = &rtems_rfs_ops;
920  mt_entry->mt_fs_root->location.node_access = (void*) RTEMS_RFS_ROOT_INO;
921  mt_entry->mt_fs_root->location.handlers    = &rtems_rfs_rtems_dir_handlers;
922
923  rtems_rfs_rtems_unlock (fs);
924
925  return 0;
926}
927
928/**
929 * Shutdown the file system.
930 */
931void
932rtems_rfs_rtems_shutdown (rtems_filesystem_mount_table_entry_t* mt_entry)
933{
934  rtems_rfs_file_system*   fs = mt_entry->fs_info;
935  rtems_rfs_rtems_private* rtems;
936
937  rtems = rtems_rfs_fs_user (fs);
938
939  /* FIXME: Return value? */
940  rtems_rfs_fs_close(fs);
941
942  rtems_rfs_mutex_destroy (&rtems->access);
943  free (rtems);
944}
Note: See TracBrowser for help on using the repository browser.