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

4.104.115
Last change on this file since a9fa9b7 was a9fa9b7, checked in by Chris Johns <chrisj@…>, on 02/18/10 at 00:24:25

2010-02-18 Chris Johns <chrisj@…>

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