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

Last change on this file was bcef89f2, checked in by Sebastian Huber <sebastian.huber@…>, on 05/19/23 at 06:18:25

Update company name

The embedded brains GmbH & Co. KG is the legal successor of embedded
brains GmbH.

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