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

4.115
Last change on this file since 56bea43 was 56bea43, checked in by Sebastian Huber <sebastian.huber@…>, on 12/16/13 at 13:26:29

Filesystem: Use default kqfilter and poll handler

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