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

4.104.11
Last change on this file since 1d539c0 was 1d539c0, checked in by Chris Johns <chrisj@…>, on Apr 12, 2010 at 5:29:25 AM

2010-04-12 Chris Johns <chrisj@…>

libfs/src/rfs/rtems-rfs-buffer-bdbuf.c,
libfs/src/rfs/rtems-rfs-buffer.c, libfs/src/rfs/rtems-rfs-data.h,
libfs/src/rfs/rtems-rfs-dir.c,
libfs/src/rfs/rtems-rfs-file-system.c,
libfs/src/rfs/rtems-rfs-format.c, libfs/src/rfs/rtems-rfs-inode.h,
libfs/src/rfs/rtems-rfs-rtems.c, libfs/src/rfs/rtems-rfs-rtems.h,
libfs/src/rfs/rtems-rfs-shell.c: Fix for PR1502. Clean up problems
on 16bit targets.

  • Property mode set to 100644
File size: 35.9 KB
Line 
1/*
2 *  COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org>
3 *
4 *  The license and distribution terms for this file may be
5 *  found in the file LICENSE in this distribution or at
6 *  http://www.rtems.com/license/LICENSE.
7 *
8 *  $Id$
9 */
10/**
11 * @file
12 *
13 * @ingroup rtems-rfs
14 *
15 * RTEMS File System Interface for RTEMS.
16 */
17
18#if HAVE_CONFIG_H
19#include "config.h"
20#endif
21
22#include <stdlib.h>
23
24#include <rtems/rfs/rtems-rfs-file.h>
25#include <rtems/rfs/rtems-rfs-dir.h>
26#include <rtems/rfs/rtems-rfs-link.h>
27#include "rtems-rfs-rtems.h"
28
29/**
30 * The libio permissions for read/execute.
31 */
32#define RTEMS_LIBIO_PERMS_RX (RTEMS_LIBIO_PERMS_SEARCH | RTEMS_LIBIO_PERMS_READ)
33/**
34 * The libio permissions for write/execute.
35 */
36#define RTEMS_LIBIO_PERMS_WX (RTEMS_LIBIO_PERMS_SEARCH | RTEMS_LIBIO_PERMS_WRITE)
37
38/**
39 * Evaluate the path to a node that wishes to be accessed. The pathloc is
40 * returned with the ino to the node to be accessed.
41 *
42 * The routine starts from the root stripping away any leading path separators
43 * breaking the path up into the node names and checking an inode exists for
44 * that node name. Permissions are checked to insure access to the node is
45 * allowed. A path to a node must be accessable all the way even if the end
46 * result is directly accessable. As a user on Linux try "ls /root/../tmp" and
47 * you will see if fails.
48 *
49 * The whole process is complicated by crossmount paths where we head down into
50 * this file system only to return to the top and out to a another mounted file
51 * system. For example we are mounted on '/e' and the user enters "ls
52 * /e/a/b/../../dev". We need to head down then back up.
53 *
54 * @param path
55 * @param pathlen
56 * @param flags
57 * @param pathloc
58 */
59int
60rtems_rfs_rtems_eval_path (const char*                       path,
61                           int                               pathlen,
62                           int                               flags,
63                           rtems_filesystem_location_info_t* pathloc)
64{
65  rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc);
66  rtems_rfs_inode_handle inode;
67  rtems_rfs_ino          ino = rtems_rfs_rtems_get_pathloc_ino (pathloc);
68  uint32_t               doff = 0;
69  const char*            node;
70  int                    node_len;
71  int                    stripped;
72  int                    rc;
73
74  if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_EVAL_PATH))
75    printf ("rtems-rfs-rtems: eval-path: in: path:%s pathlen:%i ino:%ld\n",
76            path, pathlen, ino);
77 
78  /*
79   * Eat any separators at the start of the path.
80   */
81  stripped = rtems_filesystem_prefix_separators (path, pathlen);
82  path += stripped;
83  pathlen -= stripped;
84
85  rtems_rfs_rtems_lock (fs);
86 
87  while (true)
88  {
89    /*
90     * Open and load the inode.
91     */
92    rc = rtems_rfs_inode_open (fs, ino, &inode, true);
93    if (rc > 0)
94    {
95      rtems_rfs_rtems_unlock (fs);
96      return rtems_rfs_rtems_error ("eval_path: opening inode", rc);
97    }
98   
99    /*
100     * Is this the end of the pathname we where given ?
101     */
102    if ((*path == '\0') || (pathlen == 0))
103      break;
104
105    /*
106     * If a directory the execute bit must be set for us to enter.
107     */
108    if (RTEMS_RFS_S_ISDIR (rtems_rfs_inode_get_mode (&inode)) &&
109        !rtems_rfs_rtems_eval_perms (&inode, RTEMS_LIBIO_PERMS_SEARCH))
110    {
111      rtems_rfs_inode_close (fs, &inode);
112      rtems_rfs_rtems_unlock (fs);
113      return rtems_rfs_rtems_error ("eval_path: eval perms", EACCES);
114    }
115   
116    /*
117     * Extract the node name we will look for this time around.
118     */
119    node = path;
120    node_len = 0;
121    while (!rtems_filesystem_is_separator (*path) &&
122           (*path != '\0') && pathlen &&
123           (node_len < (rtems_rfs_fs_max_name (fs) - 1)))
124    {
125      path++;
126      pathlen--;
127      node_len++;
128    }
129
130    /*
131     * Eat any separators at start of the path.
132     */
133    stripped = rtems_filesystem_prefix_separators (path, pathlen);
134    path += stripped;
135    pathlen -= stripped;
136    node_len += stripped;
137
138    /*
139     * If the node is the current directory and there is more path to come move
140     * on it else we are at the inode we want.
141     */
142    if (rtems_rfs_current_dir (node))
143    {
144      if (*path)
145        continue;
146      break;
147    }
148
149    /*
150     * If the node is a parent we must move up one directory. If the location
151     * is on another file system we have a crossmount so we call that file
152     * system to handle the remainder of the path.
153     */
154    if (rtems_rfs_parent_dir (node))
155    {
156      /*
157       * If we are at root inode of the file system we have a crossmount path.
158       */
159      if (ino == RTEMS_RFS_ROOT_INO)
160      {
161        if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_EVAL_PATH))
162          printf("rtems-rfs-rtems: eval-path: crossmount: path:%s (%d)\n",
163                 path - node_len, pathlen + node_len);
164        rtems_rfs_inode_close (fs, &inode);
165        rtems_rfs_rtems_unlock (fs);
166        *pathloc = pathloc->mt_entry->mt_point_node;
167        return (*pathloc->ops->evalpath_h)(path - node_len, pathlen + node_len,
168                                           flags, pathloc);
169      }
170
171      /*
172       * We need to find the parent of this node.
173       */
174      rc = rtems_rfs_dir_lookup_ino (fs, &inode, "..", 2, &ino, &doff);
175      if (rc > 0)
176      {
177        rtems_rfs_inode_close (fs, &inode);
178        rtems_rfs_rtems_unlock (fs);
179        return rtems_rfs_rtems_error ("eval_path: read parent inode", rc);
180      }
181      if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_EVAL_PATH))
182        printf("rtems-rfs-rtems: eval-path: parent: ino:%ld\n", ino);
183    }
184    else
185    {
186      /*
187       * Look up the node name in this directory. If found drop through, close
188       * the current inode and let the loop open the inode so the mode can be
189       * read and handlers set.
190       */
191      rc = rtems_rfs_dir_lookup_ino (fs, &inode,
192                                     node, node_len - stripped, &ino, &doff);
193      if (rc > 0)
194      {
195        rtems_rfs_inode_close (fs, &inode);
196        rtems_rfs_rtems_unlock (fs);
197        return ((errno = rc) == 0) ? 0 : -1;
198      }   
199      if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_EVAL_PATH))
200        printf("rtems-rfs-rtems: eval-path: down: path:%s ino:%ld\n", node, ino);
201    }
202
203    rc = rtems_rfs_inode_close (fs, &inode);
204    if (rc > 0)
205    {
206      rtems_rfs_inode_close (fs, &inode);
207      rtems_rfs_rtems_unlock (fs);
208      return rtems_rfs_rtems_error ("eval_path: closing node", rc);
209    }   
210  }
211 
212  rtems_rfs_rtems_set_pathloc_ino (pathloc, ino);
213  rtems_rfs_rtems_set_pathloc_doff (pathloc, doff);
214
215  rc = rtems_rfs_rtems_set_handlers (pathloc, &inode) ? 0 : EIO;
216 
217  rtems_rfs_inode_close (fs, &inode);
218  rtems_rfs_rtems_unlock (fs);
219
220  if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_EVAL_PATH))
221    printf("rtems-rfs-rtems: eval-path: ino:%ld\n", ino);
222
223  return rc;
224}
225
226/**
227 * The following routine evaluates a path for a new node to be created. The
228 * pathloc is returned with a pointer to the parent of the new node. The name
229 * is returned with a pointer to the first character in the new node name. The
230 * parent node is verified to be a directory.
231 *
232 * @param path
233 * @param pathloc
234 * @param name
235 * @return int
236 */
237int
238rtems_rfs_rtems_eval_for_make (const char*                       path,
239                               rtems_filesystem_location_info_t* pathloc,
240                               const char**                      name)
241{
242  rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc);
243  rtems_rfs_inode_handle inode;
244  rtems_rfs_ino          ino = rtems_rfs_rtems_get_pathloc_ino (pathloc);
245  rtems_rfs_ino          node_ino;
246  uint32_t               doff = 0;
247  const char*            node;
248  int                    node_len;
249  int                    stripped;
250  int                    rc;
251
252  if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_EVAL_FOR_MAKE))
253    printf ("rtems-rfs-rtems: eval-for-make: path:%s ino:%ld\n", path, ino);
254 
255  *name = path + strlen (path);
256
257  while (*name != path)
258  {
259    (*name)--;
260    if (rtems_filesystem_is_separator (**name))
261    {
262      (*name)++;
263      break;
264    }
265  }
266     
267  /*
268   * Eat any separators at start of the path.
269   */
270  stripped = rtems_filesystem_prefix_separators (path, strlen(path));
271  path += stripped;
272
273  rtems_rfs_rtems_lock (fs);
274 
275  while (true)
276  {
277    /*
278     * Open and load the inode.
279     */
280    rc = rtems_rfs_inode_open (fs, ino, &inode, true);
281    if (rc > 0)
282    {
283      rtems_rfs_rtems_unlock (fs);
284      return rtems_rfs_rtems_error ("eval_for_make: read ino", rc);
285    }
286 
287    /*
288     * If a directory the execute bit must be set for us to enter.
289     */
290    if (RTEMS_RFS_S_ISDIR (rtems_rfs_inode_get_mode (&inode)) &&
291        !rtems_rfs_rtems_eval_perms (&inode, RTEMS_LIBIO_PERMS_SEARCH))
292    {
293      rtems_rfs_inode_close (fs, &inode);
294      rtems_rfs_rtems_unlock (fs);
295      return rtems_rfs_rtems_error ("eval_for_make: eval perms", EACCES);
296    }
297   
298    /*
299     * Is this the end of the pathname we where given ?
300     */
301    if (path == *name)
302      break;
303   
304    /*
305     * Extract the node name we will look for this time around.
306     */
307    node = path;
308    node_len = 0;
309    while (!rtems_filesystem_is_separator(*path) &&
310           (*path != '\0') &&
311           (node_len < (rtems_rfs_fs_max_name (fs) - 1)))
312    {
313      node_len++;
314      path++;
315    }
316
317    /*
318     * Eat any separators at start of the new path.
319     */
320    stripped = rtems_filesystem_prefix_separators (path, strlen (path));
321    path += stripped;
322    node_len += stripped;
323
324    /*
325     * If the node is the current directory and there is more path to come move
326     * on it else we are at the inode we want.
327     */
328    if (rtems_rfs_current_dir (node))
329    {
330      if (*path)
331        continue;
332      break;
333    }
334     
335    /*
336     * If the node is a parent we must move up one directory. If the location
337     * is on another file system we have a crossmount so we call that file
338     * system to handle the remainder of the path.
339     */
340    if (rtems_rfs_parent_dir (path))
341    {
342      /*
343       * If we are at the root inode of the file system we have a crossmount
344       * path.
345       */
346      if (ino == RTEMS_RFS_ROOT_INO)
347      {
348        if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_EVAL_FOR_MAKE))
349          printf("rtems-rfs-rtems: eval-for-make: crossmount: path:%s\n",
350                 path - node_len);
351
352        rtems_rfs_inode_close (fs, &inode);
353        rtems_rfs_rtems_unlock (fs);
354        *pathloc = pathloc->mt_entry->mt_point_node;
355        return (*pathloc->ops->evalformake_h)(path - node_len, pathloc, name);
356      }
357
358      /*
359       * If not a directory give and up return. We cannot change dir from a
360       * regular file or device node.
361       */
362      if (!RTEMS_RFS_S_ISDIR (rtems_rfs_inode_get_mode (&inode)))
363      {
364        rtems_rfs_inode_close (fs, &inode);
365        rtems_rfs_rtems_unlock (fs);
366        return rtems_rfs_rtems_error ("eval_for_make: not dir", ENOTSUP);
367      }
368     
369      /*
370       * We need to find the parent of this node.
371       */
372      rc = rtems_rfs_dir_lookup_ino (fs, &inode, "..", 2, &ino, &doff);
373      if (rc > 0)
374      {
375        rtems_rfs_inode_close (fs, &inode);
376        rtems_rfs_rtems_unlock (fs);
377        return rtems_rfs_rtems_error ("eval_for_make: read parent inode", rc);
378      }
379      if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_EVAL_FOR_MAKE))
380        printf ("rtems-rfs-rtems: eval-for-make: parent: ino:%ld\n", ino);
381    }
382    else
383    {
384      /*
385       * Read the inode so we know it exists and what type it is.
386       */
387      rc = rtems_rfs_dir_lookup_ino (fs, &inode,
388                                     node, node_len - stripped, &ino, &doff);
389      if (rc > 0)
390      {
391        rtems_rfs_inode_close (fs, &inode);
392        rtems_rfs_rtems_unlock (fs);
393        return rtems_rfs_rtems_error ("eval_for_make: reading inode", rc);
394      }
395      if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_EVAL_FOR_MAKE))
396        printf("rtems-rfs-rtems: eval-for-make: down: path:%s ino:%ld\n",
397               node, ino);
398    }
399
400    rc = rtems_rfs_inode_close (fs, &inode);
401    if (rc > 0)
402    {
403      rtems_rfs_rtems_unlock (fs);
404      return rtems_rfs_rtems_error ("eval_for_make: closing node", rc);
405    }   
406  }
407
408  if (!RTEMS_RFS_S_ISDIR (rtems_rfs_inode_get_mode (&inode)))
409  {
410    rtems_rfs_inode_close (fs, &inode);
411    rtems_rfs_rtems_unlock (fs);
412    return rtems_rfs_rtems_error ("eval_for_make: not dir", ENOTDIR);
413  }
414
415  if (!rtems_rfs_rtems_eval_perms (&inode, RTEMS_LIBIO_PERMS_WX))
416  {
417    rtems_rfs_inode_close (fs, &inode);
418    rtems_rfs_rtems_unlock (fs);
419    return rtems_rfs_rtems_error ("eval_for_make: cannot write", EACCES);
420  }
421 
422  /*
423   * Make sure the name does not already exists in the directory.
424   */
425  rc = rtems_rfs_dir_lookup_ino (fs, &inode, *name, strlen (*name),
426                                 &node_ino, &doff);
427  if (rc == 0)
428  {
429    rtems_rfs_inode_close (fs, &inode);
430    rtems_rfs_rtems_unlock (fs);
431    return rtems_rfs_rtems_error ("eval_for_make: found name", EEXIST);
432  }
433
434  if (rc != ENOENT)
435  {
436    rtems_rfs_inode_close (fs, &inode);
437    rtems_rfs_rtems_unlock (fs);
438    return rtems_rfs_rtems_error ("eval_for_make: look up", rc);
439  }
440 
441  /*
442   * Set the parent ino in the path location.
443   */
444
445  rtems_rfs_rtems_set_pathloc_ino (pathloc, ino);
446  rtems_rfs_rtems_set_pathloc_doff (pathloc, doff);
447
448  rc = rtems_rfs_rtems_set_handlers (pathloc, &inode) ? 0 : EIO;
449
450  if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_EVAL_FOR_MAKE))
451    printf("rtems-rfs-rtems: eval-for-make: parent ino:%ld name:%s\n",
452           ino, *name);
453
454  rtems_rfs_inode_close (fs, &inode);
455  rtems_rfs_rtems_unlock (fs);
456 
457  return rc;
458}
459
460/**
461 * The following rouine creates a new link node under parent with the name
462 * given in name. The link node is set to point to the node at to_loc.
463 *
464 * @param to_loc
465 * @param parent_loc
466 * @param name
467 * @return int
468 */
469int
470rtems_rfs_rtems_link (rtems_filesystem_location_info_t* to_loc,
471                      rtems_filesystem_location_info_t* parent_loc,
472                      const char*                       name)
473{
474  rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (to_loc);
475  rtems_rfs_ino          target = rtems_rfs_rtems_get_pathloc_ino (to_loc);
476  rtems_rfs_ino          parent = rtems_rfs_rtems_get_pathloc_ino (parent_loc);
477  int                    rc;
478
479  if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_LINK))
480    printf ("rtems-rfs-rtems: link: in: parent:%ld target:%ld\n",
481            parent, target);
482 
483  rtems_rfs_rtems_lock (fs);
484 
485  rc = rtems_rfs_link (fs, name, strlen (name), parent, target, false);
486  if (rc)
487  {
488    rtems_rfs_rtems_unlock (fs);
489    return rtems_rfs_rtems_error ("link: linking", rc);
490        }
491
492  rtems_rfs_rtems_unlock (fs);
493 
494        return 0;
495}
496
497/**
498 * Routine to remove a link node from the file system.
499 *
500 * @param parent_loc
501 * @param loc
502 * @return int
503 */
504
505int
506rtems_rfs_rtems_unlink (rtems_filesystem_location_info_t* parent_loc,
507                        rtems_filesystem_location_info_t* loc)
508{
509  rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (parent_loc);
510  rtems_rfs_ino          parent = rtems_rfs_rtems_get_pathloc_ino (parent_loc);
511  rtems_rfs_ino          ino = rtems_rfs_rtems_get_pathloc_ino (loc);
512  uint32_t               doff = rtems_rfs_rtems_get_pathloc_doff (loc);
513  int                    rc;
514
515  rtems_rfs_rtems_lock (fs);
516 
517  if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_UNLINK))
518    printf("rtems-rfs-rtems: unlink: parent:%ld doff:%lu ino:%ld\n",
519           parent, doff, ino);
520 
521  rc = rtems_rfs_unlink (fs, parent, ino, doff, rtems_rfs_unlink_dir_denied);
522  if (rc)
523  {
524    rtems_rfs_rtems_unlock (fs);
525    return rtems_rfs_rtems_error ("unlink: unlink inode", rc);
526  }
527 
528  rtems_rfs_rtems_unlock (fs);
529 
530  return 0;
531}
532
533/**
534 * The following verifies that and returns the type of node that the loc refers
535 * to.
536 *
537 * @param pathloc
538 * @return rtems_filesystem_node_types_t
539 */
540
541rtems_filesystem_node_types_t
542rtems_rfs_rtems_node_type (rtems_filesystem_location_info_t* pathloc)
543{
544  rtems_rfs_file_system*        fs = rtems_rfs_rtems_pathloc_dev (pathloc);
545  rtems_rfs_ino                 ino = rtems_rfs_rtems_get_pathloc_ino (pathloc);
546  rtems_filesystem_node_types_t type;
547  rtems_rfs_inode_handle        inode;
548  uint16_t                      mode;
549  int                           rc;
550
551  rtems_rfs_rtems_lock (fs);
552
553  rc = rtems_rfs_inode_open (fs, ino, &inode, true);
554  if (rc > 0)
555  {
556    rtems_rfs_rtems_unlock (fs);
557    return rtems_rfs_rtems_error ("node_type: opening inode", rc);
558  }
559 
560  /*
561   * Do not return RTEMS_FILESYSTEM_HARD_LINK because this would result in an
562   * eval link which does not make sense in the case of the RFS file
563   * system. All directory entries are links to an inode. A link such as a HARD
564   * link is actually the normal path to a regular file, directory, device
565   * etc's inode. Links to inodes can be considered "the real" one, yet they
566   * are all links.
567   */
568  mode = rtems_rfs_inode_get_mode (&inode);
569  if (RTEMS_RFS_S_ISDIR (mode))
570    type = RTEMS_FILESYSTEM_DIRECTORY;
571  else if (RTEMS_RFS_S_ISLNK (mode))
572    type = RTEMS_FILESYSTEM_SYM_LINK;
573  else if (RTEMS_RFS_S_ISBLK (mode) || RTEMS_RFS_S_ISCHR (mode))
574    type = RTEMS_FILESYSTEM_DEVICE;
575  else
576    type = RTEMS_FILESYSTEM_MEMORY_FILE;
577
578  rc = rtems_rfs_inode_close (fs, &inode);
579  if (rc > 0)
580  {
581    rtems_rfs_rtems_unlock (fs);
582    return rtems_rfs_rtems_error ("node_type: closing inode", rc);
583  }
584 
585  rtems_rfs_rtems_unlock (fs);
586 
587  return type;
588}
589
590/**
591 * This routine is the implementation of the chown() system call for the
592 * RFS.
593 *
594 * @param pathloc
595 * @param owner
596 * @param group
597 * return int
598 */
599
600static int
601rtems_rfs_rtems_chown (rtems_filesystem_location_info_t *pathloc,
602                       uid_t                             owner,
603                       gid_t                             group)
604{
605  rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc);
606  rtems_rfs_ino          ino = rtems_rfs_rtems_get_pathloc_ino (pathloc);
607  rtems_rfs_inode_handle inode;
608#if defined (RTEMS_POSIX_API)
609  uid_t                  uid;
610#endif
611  int                    rc;
612 
613  if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_CHOWN))
614    printf ("rtems-rfs-rtems: chown: in: ino:%ld uid:%d gid:%d\n",
615            ino, owner, group);
616 
617  rtems_rfs_rtems_lock (fs);
618 
619  rc = rtems_rfs_inode_open (fs, ino, &inode, true);
620  if (rc > 0)
621  {
622    rtems_rfs_rtems_unlock (fs);
623    return rtems_rfs_rtems_error ("chown: opening inode", rc);
624  }
625 
626  /*
627   *  Verify I am the owner of the node or the super user.
628   */
629
630#if defined (RTEMS_POSIX_API)
631  uid = geteuid();
632
633  if ((uid != rtems_rfs_inode_get_uid (&inode)) && (uid != 0))
634  {
635    rtems_rfs_inode_close (fs, &inode);
636    rtems_rfs_rtems_unlock (fs);
637    return rtems_rfs_rtems_error ("chown: not able", EPERM);
638  }
639#endif
640
641  rtems_rfs_inode_set_uid_gid (&inode, owner, group);
642
643  rc = rtems_rfs_inode_close (fs, &inode);
644  if (rc)
645  {
646    rtems_rfs_rtems_unlock (fs);
647    return rtems_rfs_rtems_error ("chown: closing inode", rc);
648  }
649
650  rtems_rfs_rtems_unlock (fs);
651 
652  return 0;
653}
654
655/**
656 * This routine is the RFS free node handler for the file system operations
657 * table. The RFS does not need to free anything.
658 *
659 * @param pathloc
660 * @retval 0 Always returned.
661 */
662
663int
664rtems_rfs_rtems_freenodinfo (rtems_filesystem_location_info_t* pathloc)
665{
666  return 0;
667}
668
669/**
670 * This routine is the implementation of the utime() system call for the
671 * RFS.
672 *
673 * @param pathloc
674 * @param atime
675 * @param mtime
676 * return int
677 */
678
679int
680rtems_rfs_rtems_utime(rtems_filesystem_location_info_t* pathloc,
681                      time_t                            atime,
682                      time_t                            mtime)
683{
684  rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc);
685  rtems_rfs_ino          ino = rtems_rfs_rtems_get_pathloc_ino (pathloc);
686  rtems_rfs_inode_handle inode;
687  int                    rc;
688
689  rtems_rfs_rtems_lock (fs);
690 
691  rc = rtems_rfs_inode_open (fs, ino, &inode, true);
692  if (rc)
693  {
694    rtems_rfs_rtems_unlock (fs);
695    return rtems_rfs_rtems_error ("utime: read inode", rc);
696  }
697
698  rtems_rfs_inode_set_atime (&inode, atime);
699  rtems_rfs_inode_set_mtime (&inode, mtime);
700
701  rc = rtems_rfs_inode_close (fs, &inode);
702  if (rc)
703  {
704    rtems_rfs_rtems_unlock (fs);
705    return rtems_rfs_rtems_error ("utime: closing inode", rc);
706  }
707 
708  rtems_rfs_rtems_unlock (fs);
709 
710  return 0;
711}
712
713/**
714 * The following rouine creates a new symbolic link node under parent with the
715 * name given in name. The node is set to point to the node at to_loc.
716 *
717 * @param parent_loc
718 * @param link_name
719 * @param node_name
720 * return int
721 */
722
723int
724rtems_rfs_rtems_symlink (rtems_filesystem_location_info_t* parent_loc,
725                         const char*                       link_name,
726                         const char*                       node_name)
727{
728  rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (parent_loc);
729  rtems_rfs_ino          parent = rtems_rfs_rtems_get_pathloc_ino (parent_loc);
730  uid_t                  uid;
731  gid_t                  gid;
732  int                    rc;
733
734#if defined(RTEMS_POSIX_API)
735  uid = geteuid ();
736  gid = getegid ();
737#else
738  uid = 0;
739  gid = 0;
740#endif
741
742  rtems_rfs_rtems_lock (fs);
743 
744  rc = rtems_rfs_symlink (fs, node_name, strlen (node_name),
745                          link_name, strlen (link_name),
746                          uid, gid, parent);
747  if (rc)
748  {
749    rtems_rfs_rtems_unlock (fs);
750    return rtems_rfs_rtems_error ("symlink: linking", rc);
751  }
752 
753  rtems_rfs_rtems_unlock (fs);
754 
755  return 0;
756}
757
758/**
759 * The following rouine puts the symblic links destination name into buf.
760 *
761 * @param loc
762 * @param buf
763 * @param bufsize
764 * @return int
765 */
766
767int
768rtems_rfs_rtems_readlink (rtems_filesystem_location_info_t* pathloc,
769                          char*                             buf,
770                          size_t                            bufsize)
771{
772  rtems_rfs_file_system*  fs = rtems_rfs_rtems_pathloc_dev (pathloc);
773  rtems_rfs_ino           ino = rtems_rfs_rtems_get_pathloc_ino (pathloc);
774  size_t                  length;
775  int                     rc;
776 
777  if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_READLINK))
778    printf ("rtems-rfs-rtems: readlink: in: ino:%ld\n", ino);
779 
780  rtems_rfs_rtems_lock (fs);
781 
782  rc = rtems_rfs_symlink_read (fs, ino, buf, bufsize, &length);
783  if (rc)
784  {
785    rtems_rfs_rtems_unlock (fs);
786    return rtems_rfs_rtems_error ("readlink: reading link", rc);
787  }
788
789  rtems_rfs_rtems_unlock (fs);
790
791  return (int) length;
792}
793
794/**
795 * File change mode routine.
796 *
797 * @param pathloc
798 * @param mode
799 * @return int
800 */
801int
802rtems_rfs_rtems_fchmod (rtems_filesystem_location_info_t* pathloc,
803                        mode_t                            mode)
804{
805  rtems_rfs_file_system*  fs = rtems_rfs_rtems_pathloc_dev (pathloc);
806  rtems_rfs_ino           ino = rtems_rfs_rtems_get_pathloc_ino (pathloc);
807  rtems_rfs_inode_handle  inode;
808  uint16_t                imode;
809#if defined (RTEMS_POSIX_API)
810  uid_t                   uid;
811#endif
812  int                     rc;
813
814  if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_FCHMOD))
815    printf ("rtems-rfs-rtems: fchmod: in: ino:%ld mode:%06o\n",
816            ino, (unsigned int) mode);
817 
818  rtems_rfs_rtems_lock (fs);
819 
820  rc = rtems_rfs_inode_open (fs, ino, &inode, true);
821  if (rc)
822  {
823    rtems_rfs_rtems_unlock (fs);
824    return rtems_rfs_rtems_error ("fchmod: opening inode", rc);
825  }
826
827  imode = rtems_rfs_inode_get_mode (&inode);
828 
829  /*
830   *  Verify I am the owner of the node or the super user.
831   */
832#if defined (RTEMS_POSIX_API)
833  uid = geteuid();
834
835  if ((uid != rtems_rfs_inode_get_uid (&inode)) && (uid != 0))
836  {
837    rtems_rfs_inode_close (fs, &inode);
838    rtems_rfs_rtems_unlock (fs);
839    return rtems_rfs_rtems_error ("fchmod: not owner", EPERM);
840  }
841#endif
842
843  imode &= ~(S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID | S_ISVTX);
844  imode |= mode & (S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID | S_ISVTX);
845
846  rtems_rfs_inode_set_mode (&inode, imode);
847 
848  rc = rtems_rfs_inode_close (fs, &inode);
849  if (rc > 0)
850  {
851    rtems_rfs_rtems_unlock (fs);
852    return rtems_rfs_rtems_error ("fchmod: closing inode", rc);
853  }
854 
855  rtems_rfs_rtems_unlock (fs);
856 
857  return 0;
858}
859
860/**
861 * The following routine does a fcntl on an node.
862 *
863 * @param cmd
864 * @param iop
865 * @return int
866 */
867
868int
869rtems_rfs_rtems_fcntl (int            cmd,
870                       rtems_libio_t* iop)
871{
872  return 0;
873}
874
875/**
876 * The following routine does a stat on a node.
877 *
878 * @param pathloc
879 * @param buf
880 * @return int
881 */
882
883int
884rtems_rfs_rtems_stat (rtems_filesystem_location_info_t* pathloc,
885                      struct stat*                      buf)
886{
887  rtems_rfs_file_system*  fs = rtems_rfs_rtems_pathloc_dev (pathloc);
888  rtems_rfs_ino           ino = rtems_rfs_rtems_get_pathloc_ino (pathloc);
889  rtems_rfs_inode_handle  inode;
890  rtems_rfs_file_shared*  shared;
891  uint16_t                mode;
892  int                     rc;
893
894  if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_STAT))
895    printf ("rtems-rfs-rtems: stat: in: ino:%ld\n", ino);
896
897  rtems_rfs_rtems_lock (fs);
898 
899  rc = rtems_rfs_inode_open (fs, ino, &inode, true);
900  if (rc)
901  {
902    rtems_rfs_rtems_unlock (fs);
903    return rtems_rfs_rtems_error ("stat: opening inode", rc);
904  }
905
906  mode = rtems_rfs_inode_get_mode (&inode);
907 
908  if (RTEMS_RFS_S_ISCHR (mode) || RTEMS_RFS_S_ISBLK (mode))
909  {
910    buf->st_rdev = 
911      rtems_filesystem_make_dev_t (rtems_rfs_inode_get_block (&inode, 0),
912                                   rtems_rfs_inode_get_block (&inode, 1));
913  }
914 
915  buf->st_dev     = rtems_rfs_fs_device (fs);
916  buf->st_ino     = ino;
917  buf->st_mode    = rtems_rfs_rtems_mode (mode);
918  buf->st_nlink   = rtems_rfs_inode_get_links (&inode);
919  buf->st_uid     = rtems_rfs_inode_get_uid (&inode);
920  buf->st_gid     = rtems_rfs_inode_get_gid (&inode);
921
922  /*
923   * Need to check is the ino is an open file. If so we take the values from
924   * the open file rather than the inode.
925   */
926  shared = rtems_rfs_file_get_shared (fs, ino);
927
928  if (shared)
929  {
930    buf->st_atime   = rtems_rfs_file_shared_get_atime (shared);
931    buf->st_mtime   = rtems_rfs_file_shared_get_mtime (shared);
932    buf->st_ctime   = rtems_rfs_file_shared_get_ctime (shared);
933    buf->st_blocks  = rtems_rfs_file_shared_get_block_count (shared);
934
935    if (S_ISLNK (buf->st_mode))
936      buf->st_size = rtems_rfs_file_shared_get_block_offset (shared);
937    else
938      buf->st_size = rtems_rfs_file_shared_get_size (fs, shared);
939  }
940  else
941  {
942    buf->st_atime   = rtems_rfs_inode_get_atime (&inode);
943    buf->st_mtime   = rtems_rfs_inode_get_mtime (&inode);
944    buf->st_ctime   = rtems_rfs_inode_get_ctime (&inode);
945    buf->st_blocks  = rtems_rfs_inode_get_block_count (&inode);
946
947    if (S_ISLNK (buf->st_mode))
948      buf->st_size = rtems_rfs_inode_get_block_offset (&inode);
949    else
950      buf->st_size = rtems_rfs_inode_get_size (fs, &inode);
951  }
952 
953  buf->st_blksize = rtems_rfs_fs_block_size (fs);
954 
955  rc = rtems_rfs_inode_close (fs, &inode);
956  if (rc > 0)
957  {
958    rtems_rfs_rtems_unlock (fs);
959    return rtems_rfs_rtems_error ("stat: closing inode", rc);
960  }
961 
962  rtems_rfs_rtems_unlock (fs);
963  return 0;
964}
965
966/**
967 * Routine to create a node in the RFS file system.
968 *
969 * @param name
970 * @param mode
971 * @param dev
972 * @param pathloc
973 * @return int
974 */
975
976int
977rtems_rfs_rtems_mknod (const char                       *name,
978                       mode_t                            mode,
979                       dev_t                             dev,
980                       rtems_filesystem_location_info_t *pathloc)
981{
982  rtems_rfs_file_system*  fs = rtems_rfs_rtems_pathloc_dev (pathloc);
983  rtems_rfs_ino           parent = rtems_rfs_rtems_get_pathloc_ino (pathloc);
984  rtems_rfs_ino           ino;
985  rtems_rfs_inode_handle  inode;
986  uid_t                   uid;
987  gid_t                   gid;
988  int                     rc;
989
990#if defined(RTEMS_POSIX_API)
991  uid = geteuid ();
992  gid = getegid ();
993#else
994  uid = 0;
995  gid = 0;
996#endif
997
998  rtems_rfs_rtems_lock (fs);
999 
1000  rc = rtems_rfs_inode_create (fs, parent, name, strlen (name),
1001                               rtems_rfs_rtems_imode (mode),
1002                               1, uid, gid, &ino);
1003  if (rc > 0)
1004  {
1005    rtems_rfs_rtems_unlock (fs);
1006    return rtems_rfs_rtems_error ("mknod: inode create", rc);
1007  }
1008
1009  rc = rtems_rfs_inode_open (fs, ino, &inode, true);
1010  if (rc > 0)
1011  {
1012    rtems_rfs_rtems_unlock (fs);
1013    return rtems_rfs_rtems_error ("mknod: inode open", rc);
1014  }
1015   
1016  if (S_ISDIR(mode) || S_ISREG(mode))
1017  {
1018  }
1019  else if (S_ISCHR (mode) || S_ISBLK (mode))
1020  {
1021    int major;
1022    int minor;
1023    rtems_filesystem_split_dev_t (dev, major, minor);
1024    rtems_rfs_inode_set_block (&inode, 0, major);
1025    rtems_rfs_inode_set_block (&inode, 1, minor);
1026  }
1027  else 
1028  {
1029    rtems_rfs_inode_close (fs, &inode);
1030    rtems_rfs_rtems_unlock (fs);
1031    return rtems_rfs_rtems_error ("mknod: bad mode", EINVAL);
1032  }
1033
1034  rc = rtems_rfs_inode_close (fs, &inode);
1035  if (rc > 0)
1036  {
1037    rtems_rfs_rtems_unlock (fs);
1038    return rtems_rfs_rtems_error ("mknod: closing inode", rc);
1039  }
1040 
1041  rtems_rfs_rtems_unlock (fs);
1042  return 0;
1043}
1044
1045/**
1046 * Routine to remove a node from the RFS file system.
1047 *
1048 * @param parent_pathloc
1049 * @param pathloc
1050 * @return int
1051 */
1052int
1053rtems_rfs_rtems_rmnod (rtems_filesystem_location_info_t* parent_pathloc,
1054                       rtems_filesystem_location_info_t* pathloc)
1055{
1056  rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc);
1057  rtems_rfs_ino          parent = rtems_rfs_rtems_get_pathloc_ino (parent_pathloc);
1058  rtems_rfs_ino          ino = rtems_rfs_rtems_get_pathloc_ino (pathloc);
1059  uint32_t               doff = rtems_rfs_rtems_get_pathloc_doff (pathloc);
1060  int                    rc;
1061
1062  if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_RMNOD))
1063    printf ("rtems-rfs: rmnod: parent:%ld doff:%lu, ino:%ld\n",
1064            parent, doff, ino);
1065
1066  rtems_rfs_rtems_lock (fs);
1067 
1068  rc = rtems_rfs_unlink (fs, parent, ino, doff, rtems_rfs_unlink_dir_denied);
1069  if (rc)
1070  {
1071    rtems_rfs_rtems_unlock (fs);
1072    return rtems_rfs_rtems_error ("rmnod: unlinking", rc);
1073  }
1074
1075  rtems_rfs_rtems_unlock (fs);
1076  return 0;
1077}
1078
1079/**
1080 * The following routine does a sync on an inode node. Currently it flushes
1081 * everything related to this device.
1082 *
1083 * @param iop
1084 * @return int
1085 */
1086int
1087rtems_rfs_rtems_fdatasync (rtems_libio_t* iop)
1088{
1089  int rc;
1090 
1091  rc = rtems_rfs_buffer_sync (rtems_rfs_rtems_pathloc_dev (&iop->pathinfo));
1092  if (rc)
1093    return rtems_rfs_rtems_error ("fdatasync: sync", rc);
1094
1095  return 0;
1096}
1097
1098/**
1099 * Rename the node.
1100 *
1101 * @param old_parent_loc The old name's parent location.
1102 * @param old_loc The old name's location.
1103 * @param new_parent_loc The new name's parent location.
1104 * @param new_name The new name.
1105 * @return int
1106 */
1107int
1108rtems_rfs_rtems_rename(rtems_filesystem_location_info_t* old_parent_loc,
1109                       rtems_filesystem_location_info_t* old_loc,
1110                       rtems_filesystem_location_info_t* new_parent_loc,
1111                       const char*                       new_name)
1112{
1113  rtems_rfs_file_system*  fs = rtems_rfs_rtems_pathloc_dev (old_loc);
1114  rtems_rfs_ino           old_parent;
1115  rtems_rfs_ino           new_parent;
1116  rtems_rfs_ino           ino;
1117  uint32_t                doff;
1118  int                     rc;
1119 
1120  old_parent = rtems_rfs_rtems_get_pathloc_ino (old_parent_loc);
1121  new_parent = rtems_rfs_rtems_get_pathloc_ino (new_parent_loc);
1122
1123  ino  = rtems_rfs_rtems_get_pathloc_ino (old_loc);
1124  doff = rtems_rfs_rtems_get_pathloc_doff (old_loc);
1125
1126  if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_RENAME))
1127    printf ("rtems-rfs: rename: ino:%ld doff:%lu, new parent:%ld new name:%s\n",
1128            ino, doff, new_parent, new_name);
1129
1130  rtems_rfs_rtems_lock (fs);
1131
1132  /*
1133   * Link to the inode before unlinking so the inode is not erased when
1134   * unlinked.
1135   */
1136  rc = rtems_rfs_link (fs, new_name, strlen (new_name), new_parent, ino, true);
1137  if (rc)
1138  {
1139    rtems_rfs_rtems_unlock (fs);
1140    return rtems_rfs_rtems_error ("rename: linking", rc);
1141  }
1142 
1143  /*
1144   * Unlink all inodes even directories with the dir option as false because a
1145   * directory may not be empty.
1146   */
1147  rc = rtems_rfs_unlink (fs, old_parent, ino, doff,
1148                         rtems_rfs_unlink_dir_allowed);
1149  if (rc)
1150  {
1151    rtems_rfs_rtems_unlock (fs);
1152    return rtems_rfs_rtems_error ("rename: unlinking", rc);
1153  }
1154
1155  rtems_rfs_rtems_unlock (fs);
1156
1157  return 0;
1158}
1159
1160/**
1161 * Return the file system stat data.
1162 *
1163 * @param pathloc
1164 * @param sb
1165 * @return int
1166 */
1167int
1168rtems_rfs_rtems_statvfs (rtems_filesystem_location_info_t* pathloc,
1169                         struct statvfs*                   sb)
1170{
1171  rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc);
1172  size_t                 blocks;
1173  size_t                 inodes;
1174
1175  rtems_rfs_group_usage (fs, &blocks, &inodes);
1176 
1177  sb->f_bsize   = rtems_rfs_fs_block_size (fs);
1178  sb->f_frsize  = rtems_rfs_fs_media_block_size (fs);
1179  sb->f_blocks  = rtems_rfs_fs_media_blocks (fs);
1180  sb->f_bfree   = rtems_rfs_fs_blocks (fs) - blocks;
1181  sb->f_bavail  = sb->f_bfree;
1182  sb->f_files   = rtems_rfs_fs_inodes (fs);
1183  sb->f_ffree   = rtems_rfs_fs_inodes (fs) - inodes;
1184  sb->f_favail  = sb->f_ffree;
1185  sb->f_fsid    = RTEMS_RFS_SB_MAGIC;
1186  sb->f_flag    = rtems_rfs_fs_flags (fs);
1187  sb->f_namemax = rtems_rfs_fs_max_name (fs);
1188 
1189  return 0;
1190}
1191
1192/**
1193 *  Handler table for RFS link nodes
1194 */
1195const rtems_filesystem_file_handlers_r rtems_rfs_rtems_link_handlers =
1196{
1197  .open_h      = NULL,
1198  .close_h     = NULL,
1199  .read_h      = NULL,
1200  .write_h     = NULL,
1201  .ioctl_h     = NULL,
1202  .lseek_h     = NULL,
1203  .fstat_h     = rtems_rfs_rtems_stat,
1204  .fchmod_h    = NULL,
1205  .ftruncate_h = NULL,
1206  .fpathconf_h = NULL,
1207  .fsync_h     = NULL,
1208  .fdatasync_h = NULL,
1209  .fcntl_h     = NULL,
1210  .rmnod_h     = rtems_rfs_rtems_rmnod
1211};
1212
1213/**
1214 * Forward decl for the ops table.
1215 */
1216
1217int rtems_rfs_rtems_initialise (rtems_filesystem_mount_table_entry_t *mt_entry);
1218int rtems_rfs_rtems_shutdown (rtems_filesystem_mount_table_entry_t *mt_entry);
1219
1220/**
1221 * RFS file system operations table.
1222 */
1223const rtems_filesystem_operations_table rtems_rfs_ops =
1224{
1225  .evalpath_h     = rtems_rfs_rtems_eval_path,
1226  .evalformake_h  = rtems_rfs_rtems_eval_for_make,
1227  .link_h         = rtems_rfs_rtems_link,
1228  .unlink_h       = rtems_rfs_rtems_unlink,
1229  .node_type_h    = rtems_rfs_rtems_node_type,
1230  .mknod_h        = rtems_rfs_rtems_mknod,
1231  .chown_h        = rtems_rfs_rtems_chown,
1232  .freenod_h      = rtems_rfs_rtems_freenodinfo,
1233  .mount_h        = NULL,
1234  .fsmount_me_h   = rtems_rfs_rtems_initialise,
1235  .unmount_h      = NULL,
1236  .fsunmount_me_h = rtems_rfs_rtems_shutdown,
1237  .utime_h        = rtems_rfs_rtems_utime,
1238  .eval_link_h    = NULL, /* never called cause we lie in the node type */
1239  .symlink_h      = rtems_rfs_rtems_symlink,
1240  .readlink_h     = rtems_rfs_rtems_readlink,
1241  .rename_h       = rtems_rfs_rtems_rename,
1242  .statvfs_h      = rtems_rfs_rtems_statvfs
1243};
1244
1245/**
1246 * Open the file system.
1247 */
1248
1249int
1250rtems_rfs_rtems_initialise (rtems_filesystem_mount_table_entry_t* mt_entry)
1251{
1252  rtems_rfs_rtems_private* rtems;
1253  rtems_rfs_file_system*   fs;
1254  int                      rc;
1255
1256  rtems = malloc (sizeof (rtems_rfs_rtems_private));
1257  if (!rtems)
1258    return rtems_rfs_rtems_error ("initialise: local data", ENOMEM);
1259
1260  memset (rtems, 0, sizeof (rtems_rfs_rtems_private));
1261 
1262  rc = rtems_rfs_mutex_create (&rtems->access);
1263  if (rc > 0)
1264  {
1265    free (rtems);
1266    return rtems_rfs_rtems_error ("initialise: cannot create mutex", rc);
1267  }
1268
1269  rc = rtems_rfs_mutex_lock (&rtems->access);
1270  if (rc > 0)
1271  {
1272    rtems_rfs_mutex_destroy (&rtems->access);
1273    free (rtems);
1274    return rtems_rfs_rtems_error ("initialise: cannot lock access  mutex", rc);
1275  }
1276 
1277  rc = rtems_rfs_fs_open (mt_entry->dev, rtems, 0, &fs);
1278  if (rc)
1279  {
1280    free (rtems);
1281    return rtems_rfs_rtems_error ("initialise: open", rc);
1282  }
1283 
1284  mt_entry->fs_info = fs;
1285
1286  mt_entry->mt_fs_root.node_access = (void*) RTEMS_RFS_ROOT_INO;
1287  mt_entry->mt_fs_root.handlers    = &rtems_rfs_rtems_dir_handlers;
1288  mt_entry->mt_fs_root.ops         = &rtems_rfs_ops;
1289
1290  rtems_rfs_rtems_unlock (fs);
1291 
1292  return 0;
1293}
1294
1295/**
1296 * Shutdown the file system.
1297 */
1298int
1299rtems_rfs_rtems_shutdown (rtems_filesystem_mount_table_entry_t* mt_entry)
1300{
1301  rtems_rfs_file_system*   fs = mt_entry->fs_info;
1302  rtems_rfs_rtems_private* rtems;
1303  int                      rc;
1304
1305  rtems = rtems_rfs_fs_user (fs);
1306 
1307  rc = rtems_rfs_fs_close(fs);
1308 
1309  rtems_rfs_mutex_destroy (&rtems->access);
1310  free (rtems);
1311 
1312  return rtems_rfs_rtems_error ("shutdown: close", rc);
1313}
Note: See TracBrowser for help on using the repository browser.