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

4.115
Last change on this file since f2a1ba5 was f2a1ba5, checked in by Sebastian Huber <sebastian.huber@…>, on 03/22/13 at 14:30:16

libfs: Always use geteuid() and getegid()

The two functions are independent of the POSIX API.

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