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

4.115
Last change on this file since 7660e8b3 was 7660e8b3, checked in by Sebastian Huber <sebastian.huber@…>, on 07/23/13 at 11:32:58

Include missing <string.h>

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