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

4.115
Last change on this file since 3c96bee was b6657c39, checked in by Sebastian Huber <sebastian.huber@…>, on 09/11/13 at 08:34:02

Filesystem: Add and use rtems_filesystem_chmod()

Implement POSIX requirements in the high-level file system layer.

  • Property mode set to 100644
File size: 26.0 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  int                     rc;
472
473  if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_FCHMOD))
474    printf ("rtems-rfs-rtems: fchmod: in: ino:%" PRId32 " mode:%06" PRIomode_t "\n",
475            ino, mode);
476
477  rc = rtems_rfs_inode_open (fs, ino, &inode, true);
478  if (rc)
479  {
480    return rtems_rfs_rtems_error ("fchmod: opening inode", rc);
481  }
482
483  rtems_rfs_inode_set_mode (&inode, mode);
484
485  rc = rtems_rfs_inode_close (fs, &inode);
486  if (rc > 0)
487  {
488    return rtems_rfs_rtems_error ("fchmod: closing inode", rc);
489  }
490
491  return 0;
492}
493
494int
495rtems_rfs_rtems_fstat (const rtems_filesystem_location_info_t* pathloc,
496                       struct stat*                            buf)
497{
498  rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc);
499  rtems_rfs_ino          ino = rtems_rfs_rtems_get_pathloc_ino (pathloc);
500  rtems_rfs_inode_handle inode;
501  rtems_rfs_file_shared* shared;
502  uint16_t               mode;
503  int                    rc;
504
505  if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_STAT))
506    printf ("rtems-rfs-rtems: stat: in: ino:%" PRId32 "\n", ino);
507
508  rc = rtems_rfs_inode_open (fs, ino, &inode, true);
509  if (rc)
510  {
511    return rtems_rfs_rtems_error ("stat: opening inode", rc);
512  }
513
514  mode = rtems_rfs_inode_get_mode (&inode);
515
516  if (RTEMS_RFS_S_ISCHR (mode) || RTEMS_RFS_S_ISBLK (mode))
517  {
518    buf->st_rdev =
519      rtems_filesystem_make_dev_t (rtems_rfs_inode_get_block (&inode, 0),
520                                   rtems_rfs_inode_get_block (&inode, 1));
521  }
522
523  buf->st_dev     = rtems_rfs_fs_device (fs);
524  buf->st_ino     = rtems_rfs_inode_ino (&inode);
525  buf->st_mode    = rtems_rfs_rtems_mode (mode);
526  buf->st_nlink   = rtems_rfs_inode_get_links (&inode);
527  buf->st_uid     = rtems_rfs_inode_get_uid (&inode);
528  buf->st_gid     = rtems_rfs_inode_get_gid (&inode);
529
530  /*
531   * Need to check is the ino is an open file. If so we take the values from
532   * the open file rather than the inode.
533   */
534  shared = rtems_rfs_file_get_shared (fs, rtems_rfs_inode_ino (&inode));
535
536  if (shared)
537  {
538    buf->st_atime   = rtems_rfs_file_shared_get_atime (shared);
539    buf->st_mtime   = rtems_rfs_file_shared_get_mtime (shared);
540    buf->st_ctime   = rtems_rfs_file_shared_get_ctime (shared);
541    buf->st_blocks  = rtems_rfs_file_shared_get_block_count (shared);
542
543    if (S_ISLNK (buf->st_mode))
544      buf->st_size = rtems_rfs_file_shared_get_block_offset (shared);
545    else
546      buf->st_size = rtems_rfs_file_shared_get_size (fs, shared);
547  }
548  else
549  {
550    buf->st_atime   = rtems_rfs_inode_get_atime (&inode);
551    buf->st_mtime   = rtems_rfs_inode_get_mtime (&inode);
552    buf->st_ctime   = rtems_rfs_inode_get_ctime (&inode);
553    buf->st_blocks  = rtems_rfs_inode_get_block_count (&inode);
554
555    if (S_ISLNK (buf->st_mode))
556      buf->st_size = rtems_rfs_inode_get_block_offset (&inode);
557    else
558      buf->st_size = rtems_rfs_inode_get_size (fs, &inode);
559  }
560
561  buf->st_blksize = rtems_rfs_fs_block_size (fs);
562
563  rc = rtems_rfs_inode_close (fs, &inode);
564  if (rc > 0)
565  {
566    return rtems_rfs_rtems_error ("stat: closing inode", rc);
567  }
568
569  return 0;
570}
571
572/**
573 * Routine to create a node in the RFS file system.
574 */
575
576static int
577rtems_rfs_rtems_mknod (const rtems_filesystem_location_info_t *parentloc,
578                       const char                             *name,
579                       size_t                                  namelen,
580                       mode_t                                  mode,
581                       dev_t                                   dev)
582{
583  rtems_rfs_file_system*  fs = rtems_rfs_rtems_pathloc_dev (parentloc);
584  rtems_rfs_ino           parent = rtems_rfs_rtems_get_pathloc_ino (parentloc);
585  rtems_rfs_ino           ino;
586  rtems_rfs_inode_handle  inode;
587  uid_t                   uid;
588  gid_t                   gid;
589  int                     rc;
590
591  uid = geteuid ();
592  gid = getegid ();
593
594  rc = rtems_rfs_inode_create (fs, parent, name, namelen,
595                               rtems_rfs_rtems_imode (mode),
596                               1, uid, gid, &ino);
597  if (rc > 0)
598  {
599    return rtems_rfs_rtems_error ("mknod: inode create", rc);
600  }
601
602  rc = rtems_rfs_inode_open (fs, ino, &inode, true);
603  if (rc > 0)
604  {
605    return rtems_rfs_rtems_error ("mknod: inode open", rc);
606  }
607
608  if (S_ISDIR(mode) || S_ISREG(mode))
609  {
610  }
611  else if (S_ISCHR (mode) || S_ISBLK (mode))
612  {
613    int major;
614    int minor;
615    rtems_filesystem_split_dev_t (dev, major, minor);
616    rtems_rfs_inode_set_block (&inode, 0, major);
617    rtems_rfs_inode_set_block (&inode, 1, minor);
618  }
619  else
620  {
621    rtems_rfs_inode_close (fs, &inode);
622    return rtems_rfs_rtems_error ("mknod: bad mode", EINVAL);
623  }
624
625  rc = rtems_rfs_inode_close (fs, &inode);
626  if (rc > 0)
627  {
628    return rtems_rfs_rtems_error ("mknod: closing inode", rc);
629  }
630
631  return 0;
632}
633
634/**
635 * Routine to remove a node from the RFS file system.
636 *
637 * @param parent_pathloc
638 * @param pathloc
639 * @return int
640 */
641int
642rtems_rfs_rtems_rmnod (const rtems_filesystem_location_info_t* parent_pathloc,
643                       const rtems_filesystem_location_info_t* pathloc)
644{
645  rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc);
646  rtems_rfs_ino          parent = rtems_rfs_rtems_get_pathloc_ino (parent_pathloc);
647  rtems_rfs_ino          ino = rtems_rfs_rtems_get_pathloc_ino (pathloc);
648  uint32_t               doff = rtems_rfs_rtems_get_pathloc_doff (pathloc);
649  int                    rc;
650
651  if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_RMNOD))
652    printf ("rtems-rfs: rmnod: parent:%" PRId32 " doff:%" PRIu32 ", ino:%" PRId32 "\n",
653            parent, doff, ino);
654
655  rc = rtems_rfs_unlink (fs, parent, ino, doff, rtems_rfs_unlink_dir_if_empty);
656  if (rc)
657  {
658    return rtems_rfs_rtems_error ("rmnod: unlinking", rc);
659  }
660
661  return 0;
662}
663
664/**
665 * The following routine does a sync on an inode node. Currently it flushes
666 * everything related to this device.
667 *
668 * @param iop
669 * @return int
670 */
671int
672rtems_rfs_rtems_fdatasync (rtems_libio_t* iop)
673{
674  int rc;
675
676  rc = rtems_rfs_buffer_sync (rtems_rfs_rtems_pathloc_dev (&iop->pathinfo));
677  if (rc)
678    return rtems_rfs_rtems_error ("fdatasync: sync", rc);
679
680  return 0;
681}
682
683/**
684 * Rename the node.
685 */
686static int
687rtems_rfs_rtems_rename(const rtems_filesystem_location_info_t* old_parent_loc,
688                       const rtems_filesystem_location_info_t* old_loc,
689                       const rtems_filesystem_location_info_t* new_parent_loc,
690                       const char*                             new_name,
691                       size_t                                  new_name_len)
692{
693  rtems_rfs_file_system*  fs = rtems_rfs_rtems_pathloc_dev (old_loc);
694  rtems_rfs_ino           old_parent;
695  rtems_rfs_ino           new_parent;
696  rtems_rfs_ino           ino;
697  uint32_t                doff;
698  int                     rc;
699
700  old_parent = rtems_rfs_rtems_get_pathloc_ino (old_parent_loc);
701  new_parent = rtems_rfs_rtems_get_pathloc_ino (new_parent_loc);
702
703  ino  = rtems_rfs_rtems_get_pathloc_ino (old_loc);
704  doff = rtems_rfs_rtems_get_pathloc_doff (old_loc);
705
706  if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_RENAME))
707    printf ("rtems-rfs: rename: ino:%" PRId32 " doff:%" PRIu32 ", new parent:%" PRId32 "\n",
708            ino, doff, new_parent);
709
710  /*
711   * Link to the inode before unlinking so the inode is not erased when
712   * unlinked.
713   */
714  rc = rtems_rfs_link (fs, new_name, new_name_len, new_parent, ino, true);
715  if (rc)
716  {
717    return rtems_rfs_rtems_error ("rename: linking", rc);
718  }
719
720  /*
721   * Unlink all inodes even directories with the dir option as false because a
722   * directory may not be empty.
723   */
724  rc = rtems_rfs_unlink (fs, old_parent, ino, doff,
725                         rtems_rfs_unlink_dir_allowed);
726  if (rc)
727  {
728    return rtems_rfs_rtems_error ("rename: unlinking", rc);
729  }
730
731  return 0;
732}
733
734/**
735 * Return the file system stat data.
736 *
737 * @param pathloc
738 * @param sb
739 * @return int
740 */
741static int
742rtems_rfs_rtems_statvfs (const rtems_filesystem_location_info_t* pathloc,
743                         struct statvfs*                         sb)
744{
745  rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc);
746  size_t                 blocks;
747  size_t                 inodes;
748
749  rtems_rfs_group_usage (fs, &blocks, &inodes);
750
751  sb->f_bsize   = rtems_rfs_fs_block_size (fs);
752  sb->f_frsize  = rtems_rfs_fs_media_block_size (fs);
753  sb->f_blocks  = rtems_rfs_fs_media_blocks (fs);
754  sb->f_bfree   = rtems_rfs_fs_blocks (fs) - blocks;
755  sb->f_bavail  = sb->f_bfree;
756  sb->f_files   = rtems_rfs_fs_inodes (fs);
757  sb->f_ffree   = rtems_rfs_fs_inodes (fs) - inodes;
758  sb->f_favail  = sb->f_ffree;
759  sb->f_fsid    = RTEMS_RFS_SB_MAGIC;
760  sb->f_flag    = rtems_rfs_fs_flags (fs);
761  sb->f_namemax = rtems_rfs_fs_max_name (fs);
762
763  return 0;
764}
765
766/**
767 *  Handler table for RFS link nodes
768 */
769const rtems_filesystem_file_handlers_r rtems_rfs_rtems_link_handlers =
770{
771  .open_h      = rtems_filesystem_default_open,
772  .close_h     = rtems_filesystem_default_close,
773  .read_h      = rtems_filesystem_default_read,
774  .write_h     = rtems_filesystem_default_write,
775  .ioctl_h     = rtems_filesystem_default_ioctl,
776  .lseek_h     = rtems_filesystem_default_lseek,
777  .fstat_h     = rtems_rfs_rtems_fstat,
778  .ftruncate_h = rtems_filesystem_default_ftruncate,
779  .fsync_h     = rtems_filesystem_default_fsync_or_fdatasync,
780  .fdatasync_h = rtems_filesystem_default_fsync_or_fdatasync,
781  .fcntl_h     = rtems_filesystem_default_fcntl
782};
783
784/**
785 * Forward decl for the ops table.
786 */
787
788int rtems_rfs_rtems_initialise (rtems_filesystem_mount_table_entry_t *mt_entry,
789                                const void                           *data);
790void rtems_rfs_rtems_shutdown (rtems_filesystem_mount_table_entry_t *mt_entry);
791
792/**
793 * RFS file system operations table.
794 */
795const rtems_filesystem_operations_table rtems_rfs_ops =
796{
797  .lock_h         = rtems_rfs_rtems_lock_by_mt_entry,
798  .unlock_h       = rtems_rfs_rtems_unlock_by_mt_entry,
799  .are_nodes_equal_h = rtems_filesystem_default_are_nodes_equal,
800  .eval_path_h    = rtems_rfs_rtems_eval_path,
801  .link_h         = rtems_rfs_rtems_link,
802  .node_type_h    = rtems_rfs_rtems_node_type,
803  .fchmod_h       = rtems_rfs_rtems_fchmod,
804  .mknod_h        = rtems_rfs_rtems_mknod,
805  .rmnod_h        = rtems_rfs_rtems_rmnod,
806  .chown_h        = rtems_rfs_rtems_chown,
807  .clonenod_h     = rtems_filesystem_default_clonenode,
808  .freenod_h      = rtems_filesystem_default_freenode,
809  .mount_h        = rtems_filesystem_default_mount,
810  .fsmount_me_h   = rtems_rfs_rtems_initialise,
811  .unmount_h      = rtems_filesystem_default_unmount,
812  .fsunmount_me_h = rtems_rfs_rtems_shutdown,
813  .utime_h        = rtems_rfs_rtems_utime,
814  .symlink_h      = rtems_rfs_rtems_symlink,
815  .readlink_h     = rtems_rfs_rtems_readlink,
816  .rename_h       = rtems_rfs_rtems_rename,
817  .statvfs_h      = rtems_rfs_rtems_statvfs
818};
819
820/**
821 * Open the file system.
822 */
823
824int
825rtems_rfs_rtems_initialise (rtems_filesystem_mount_table_entry_t* mt_entry,
826                            const void*                           data)
827{
828  rtems_rfs_rtems_private* rtems;
829  rtems_rfs_file_system*   fs;
830  uint32_t                 flags = 0;
831  uint32_t                 max_held_buffers = RTEMS_RFS_FS_MAX_HELD_BUFFERS;
832  const char*              options = data;
833  int                      rc;
834
835  /*
836   * Parse the options the user specifiies.
837   */
838  while (options)
839  {
840    printf ("options=%s\n", options);
841    if (strncmp (options, "hold-bitmaps",
842                 sizeof ("hold-bitmaps") - 1) == 0)
843      flags |= RTEMS_RFS_FS_BITMAPS_HOLD;
844    else if (strncmp (options, "no-local-cache",
845                      sizeof ("no-local-cache") - 1) == 0)
846      flags |= RTEMS_RFS_FS_NO_LOCAL_CACHE;
847    else if (strncmp (options, "max-held-bufs",
848                      sizeof ("max-held-bufs") - 1) == 0)
849    {
850      max_held_buffers = strtoul (options + sizeof ("max-held-bufs"), 0, 0);
851    }
852    else
853      return rtems_rfs_rtems_error ("initialise: invalid option", EINVAL);
854
855    options = strchr (options, ',');
856    if (options)
857    {
858      ++options;
859      if (*options == '\0')
860        options = NULL;
861    }
862  }
863
864  rtems = malloc (sizeof (rtems_rfs_rtems_private));
865  if (!rtems)
866    return rtems_rfs_rtems_error ("initialise: local data", ENOMEM);
867
868  memset (rtems, 0, sizeof (rtems_rfs_rtems_private));
869
870  rc = rtems_rfs_mutex_create (&rtems->access);
871  if (rc > 0)
872  {
873    free (rtems);
874    return rtems_rfs_rtems_error ("initialise: cannot create mutex", rc);
875  }
876
877  rc = rtems_rfs_mutex_lock (&rtems->access);
878  if (rc > 0)
879  {
880    rtems_rfs_mutex_destroy (&rtems->access);
881    free (rtems);
882    return rtems_rfs_rtems_error ("initialise: cannot lock access  mutex", rc);
883  }
884
885  rc = rtems_rfs_fs_open (mt_entry->dev, rtems, flags, max_held_buffers, &fs);
886  if (rc)
887  {
888    free (rtems);
889    return rtems_rfs_rtems_error ("initialise: open", rc);
890  }
891
892  mt_entry->fs_info                          = fs;
893  mt_entry->ops                              = &rtems_rfs_ops;
894  mt_entry->mt_fs_root->location.node_access = (void*) RTEMS_RFS_ROOT_INO;
895  mt_entry->mt_fs_root->location.handlers    = &rtems_rfs_rtems_dir_handlers;
896
897  rtems_rfs_rtems_unlock (fs);
898
899  return 0;
900}
901
902/**
903 * Shutdown the file system.
904 */
905void
906rtems_rfs_rtems_shutdown (rtems_filesystem_mount_table_entry_t* mt_entry)
907{
908  rtems_rfs_file_system*   fs = mt_entry->fs_info;
909  rtems_rfs_rtems_private* rtems;
910
911  rtems = rtems_rfs_fs_user (fs);
912
913  /* FIXME: Return value? */
914  rtems_rfs_fs_close(fs);
915
916  rtems_rfs_mutex_destroy (&rtems->access);
917  free (rtems);
918}
Note: See TracBrowser for help on using the repository browser.