source: rtems/cpukit/libfs/src/imfs/imfs_eval.c @ efd6e8e

4.115
Last change on this file since efd6e8e was 983bfad, checked in by Joel Sherrill <joel.sherrill@…>, on 06/24/10 at 21:31:22

2010-06-24 Joel Sherrill <joel.sherrilL@…>

  • libfs/src/imfs/imfs_creat.c, libfs/src/imfs/imfs_debug.c, libfs/src/imfs/imfs_directory.c, libfs/src/imfs/imfs_eval.c, libfs/src/imfs/imfs_fsunmount.c, libfs/src/imfs/imfs_getchild.c, libfs/src/imfs/imfs_initsupp.c, libfs/src/imfs/ioman.c, libfs/src/imfs/memfile.c: Evaluate all assert calls in IMFS. Either made them conditional on RTEMS_DEBUG or eliminated them.
  • Property mode set to 100644
File size: 16.2 KB
Line 
1/*
2 *  Evaluation IMFS Node Support Routines
3 *
4 *  COPYRIGHT (c) 1989-1999.
5 *  On-Line Applications Research Corporation (OAR).
6 *
7 *  The license and distribution terms for this file may be
8 *  found in the file LICENSE in this distribution or at
9 *  http://www.rtems.com/license/LICENSE.
10 *
11 *  $Id$
12 */
13
14#if HAVE_CONFIG_H
15#include "config.h"
16#endif
17
18#include <sys/types.h>
19#include <sys/stat.h>
20#include <fcntl.h>
21#include <unistd.h>
22#include <errno.h>
23#include <stdlib.h>
24
25#include "imfs.h"
26#include <rtems/libio_.h>
27#include <rtems/seterr.h>
28
29#define RTEMS_LIBIO_PERMS_RX (RTEMS_LIBIO_PERMS_SEARCH | RTEMS_LIBIO_PERMS_READ)
30#define RTEMS_LIBIO_PERMS_WX (RTEMS_LIBIO_PERMS_SEARCH | RTEMS_LIBIO_PERMS_WRITE)
31
32#define MAXSYMLINK 5
33
34int IMFS_Set_handlers(
35  rtems_filesystem_location_info_t   *loc
36)
37{
38  IMFS_jnode_t    *node = loc->node_access;
39  IMFS_fs_info_t  *fs_info;
40
41  fs_info = loc->mt_entry->fs_info;
42  switch( node->type ) {
43    case IMFS_DIRECTORY:
44      loc->handlers = fs_info->directory_handlers;
45      break;
46    case IMFS_DEVICE:
47      loc->handlers = &IMFS_device_handlers;
48      break;
49    case IMFS_SYM_LINK:
50    case IMFS_HARD_LINK:
51      loc->handlers = &IMFS_link_handlers;
52      break;
53    case IMFS_LINEAR_FILE:
54      loc->handlers = fs_info->memfile_handlers;
55      break;
56    case IMFS_MEMORY_FILE:
57      loc->handlers = fs_info->memfile_handlers;
58      break;
59    case IMFS_FIFO:
60      loc->handlers = fs_info->fifo_handlers;
61      break;
62  }
63
64  return 0;
65}
66
67/*
68 *  IMFS_evaluate_permission
69 *
70 *  The following routine evaluates that we have permission
71 *  to do flags on the node.
72 */
73
74int IMFS_evaluate_permission(
75  rtems_filesystem_location_info_t  *node,
76  int                                flags
77)
78{
79  uid_t         st_uid;
80  gid_t         st_gid;
81  IMFS_jnode_t *jnode;
82  int           flags_to_test;
83
84  if ( !rtems_libio_is_valid_perms( flags ) ) {
85    rtems_set_errno_and_return_minus_one( EIO );
86  }
87
88  jnode = node->node_access;
89
90#if defined(RTEMS_POSIX_API)
91  st_uid = geteuid();
92  st_gid = getegid();
93#else
94  st_uid = jnode->st_uid;
95  st_gid = jnode->st_gid;
96#endif
97
98  /*
99   * Check if I am owner or a group member or someone else.
100   */
101
102  flags_to_test = flags;
103
104  if ( st_uid == jnode->st_uid )
105    flags_to_test <<= 6;
106  else if ( st_gid == jnode->st_gid )
107    flags_to_test <<= 3;
108  else {
109    /* must be other - do nothing */;
110  }
111
112  /*
113   * If all of the flags are set we have permission
114   * to do this.
115   */
116  if ( ( flags_to_test & jnode->st_mode) == flags_to_test )
117    return 1;
118
119  return 0;
120}
121
122/*
123 *  IMFS_evaluate_hard_link
124 *
125 *  The following routine evaluates a hardlink to the actual node.
126 */
127
128int IMFS_evaluate_hard_link(
129  rtems_filesystem_location_info_t  *node,   /* IN/OUT */
130  int                                flags   /* IN     */
131)
132{
133  IMFS_jnode_t                     *jnode  = node->node_access;
134  int                               result = 0;
135
136  /*
137   * Check for things that should never happen.
138   */
139
140  if ( jnode->type != IMFS_HARD_LINK )
141    rtems_fatal_error_occurred (0xABCD0000);
142
143  /*
144   * Set the hard link value and the handlers.
145   */
146
147  node->node_access = jnode->info.hard_link.link_node;
148
149  IMFS_Set_handlers( node );
150
151  /*
152   * Verify we have the correct permissions for this node.
153   */
154
155  if ( !IMFS_evaluate_permission( node, flags ) )
156    rtems_set_errno_and_return_minus_one( EACCES );
157
158  return result;
159}
160
161
162/*
163 *  IMFS_evaluate_sym_link
164 *
165 *  The following routine evaluates a symbolic link to the actual node.
166 */
167
168int IMFS_evaluate_sym_link(
169  rtems_filesystem_location_info_t  *node,   /* IN/OUT */
170  int                                flags   /* IN     */
171)
172{
173  IMFS_jnode_t                     *jnode  = node->node_access;
174  int                               result = 0;
175  int                               i;
176
177  /*
178   * Check for things that should never happen.
179   */
180
181  if ( jnode->type != IMFS_SYM_LINK )
182    rtems_fatal_error_occurred (0xABCD0000);
183
184  if ( !jnode->Parent )
185    rtems_fatal_error_occurred( 0xBAD00000 );
186
187
188  /*
189   * Move the node_access to either the symbolic links parent or
190   * root depending on the symbolic links path.
191   */
192
193  node->node_access = jnode->Parent;
194
195  rtems_filesystem_get_sym_start_loc(
196    jnode->info.sym_link.name,
197    &i,
198    node
199  );
200
201  /*
202   * Use eval path to evaluate the path of the symbolic link.
203   */
204
205  result = IMFS_eval_path(
206    &jnode->info.sym_link.name[i],
207    strlen( &jnode->info.sym_link.name[i] ),
208    flags,
209    node
210  );
211
212  IMFS_Set_handlers( node );
213
214  /*
215   * Verify we have the correct permissions for this node.
216   */
217
218  if ( !IMFS_evaluate_permission( node, flags ) )
219    rtems_set_errno_and_return_minus_one( EACCES );
220
221  return result;
222}
223
224/*
225 *  IMFS_evaluate_link
226 *
227 *  The following routine returns the real node pointed to by a link.
228 */
229
230int IMFS_evaluate_link(
231  rtems_filesystem_location_info_t  *node,   /* IN/OUT */
232  int                                flags   /* IN     */
233)
234{
235  IMFS_jnode_t                     *jnode;
236  int                               result = 0;
237
238  do {
239    jnode  = node->node_access;
240
241    /*
242     * Increment and check the link counter.
243     */
244
245    rtems_filesystem_link_counts ++;
246    if ( rtems_filesystem_link_counts > MAXSYMLINK ) {
247      rtems_filesystem_link_counts = 0;
248      rtems_set_errno_and_return_minus_one( ELOOP );
249    }
250
251    /*
252     *  Follow the Link node.
253     */
254
255    if ( jnode->type == IMFS_HARD_LINK )
256      result = IMFS_evaluate_hard_link( node, flags );
257
258    else if (jnode->type == IMFS_SYM_LINK )
259      result = IMFS_evaluate_sym_link( node, flags );
260
261  } while ( ( result == 0 ) && ( ( jnode->type == IMFS_SYM_LINK  ) ||
262                                 ( jnode->type == IMFS_HARD_LINK ) ) );
263
264  /*
265   * Clear link counter.
266   */
267
268  rtems_filesystem_link_counts = 0;
269
270  return result;
271}
272
273
274/*
275 *  IMFS_evaluate_for_make
276 *
277 *  The following routine evaluate path for a new node to be created.
278 *  pathloc is returned with a pointer to the parent of the new node.
279 *  name is returned with a pointer to the first character in the
280 *  new node name.  The parent node is verified to be a directory.
281 */
282
283int IMFS_evaluate_for_make(
284   const char                         *path,       /* IN     */
285   rtems_filesystem_location_info_t   *pathloc,    /* IN/OUT */
286   const char                        **name        /* OUT    */
287)
288{
289  int                                 i = 0;
290  int                                 len;
291  IMFS_token_types                    type;
292  char                                token[ IMFS_NAME_MAX + 1 ];
293  rtems_filesystem_location_info_t    newloc;
294  IMFS_jnode_t                       *node;
295  bool                                done = false;
296  int                                 pathlen;
297  int                                 result;
298
299  /*
300   * This was filled in by the caller and is valid in the
301   * mount table.
302   */
303  node = pathloc->node_access;
304
305  /*
306   * Get the path length.
307   */
308  pathlen = strlen( path );
309  /*
310   *  Evaluate all tokens until we are done or an error occurs.
311   */
312
313  while( !done ) {
314
315    type = IMFS_get_token( &path[i], pathlen, token, &len );
316    pathlen -= len;
317    i +=  len;
318
319    if ( !pathloc->node_access )
320      rtems_set_errno_and_return_minus_one( ENOENT );
321
322    /*
323     * I cannot move out of this directory without execute permission.
324     */
325
326    if ( type != IMFS_NO_MORE_PATH )
327      if ( node->type == IMFS_DIRECTORY )
328        if ( !IMFS_evaluate_permission( pathloc, RTEMS_LIBIO_PERMS_SEARCH ) )
329           rtems_set_errno_and_return_minus_one( EACCES );
330
331    node = pathloc->node_access;
332
333    switch( type ) {
334
335      case IMFS_UP_DIR:
336       /*
337        *  Am I at the root of all filesystems? (chroot'ed?)
338        */
339
340       if ( pathloc->node_access == rtems_filesystem_root.node_access )
341         break;       /* Throw out the .. in this case */
342
343
344        /*
345         * Am I at the root of this mounted filesystem?
346         */
347
348        if (pathloc->node_access == pathloc->mt_entry->mt_fs_root.node_access){
349
350          /*
351           *  Am I at the root of all filesystems?
352           */
353
354          if ( pathloc->node_access == rtems_filesystem_root.node_access ) {
355            break;
356
357          } else {
358            newloc = pathloc->mt_entry->mt_point_node;
359            *pathloc = newloc;
360            return (*pathloc->ops->evalformake_h)( &path[i-len], pathloc, name );
361          }
362        } else {
363
364          if ( !node->Parent )
365            rtems_set_errno_and_return_minus_one( ENOENT );
366
367          node = node->Parent;
368        }
369
370        pathloc->node_access = node;
371        break;
372
373      case IMFS_NAME:
374
375        if ( node->type == IMFS_HARD_LINK ) {
376
377          result = IMFS_evaluate_link( pathloc, 0 );
378          if ( result == -1 )
379            return -1;
380
381        } else if ( node->type == IMFS_SYM_LINK ) {
382
383          result = IMFS_evaluate_link( pathloc, 0 );
384
385          if ( result == -1 )
386            return -1;
387        }
388
389        node = pathloc->node_access;
390        if ( !node )
391          rtems_set_errno_and_return_minus_one( ENOTDIR );
392
393        /*
394         * Only a directory can be decended into.
395         */
396
397        if ( node->type != IMFS_DIRECTORY )
398          rtems_set_errno_and_return_minus_one( ENOTDIR );
399
400        /*
401         * If we are at a node that is a mount point. Set loc to the
402         * new fs root node and let them finish evaluating the path.
403         */
404
405        if ( node->info.directory.mt_fs != NULL ) {
406          newloc  = node->info.directory.mt_fs->mt_fs_root;
407          *pathloc = newloc;
408          return (*pathloc->ops->evalformake_h)( &path[i-len], pathloc, name );
409        }
410
411        /*
412         * Otherwise find the token name in the present location.
413         */
414
415        node = IMFS_find_match_in_dir( node, token );
416
417        /*
418         * If there is no node we have found the name of the node we
419         * wish to create.
420         */
421
422        if ( ! node )
423          done = true;
424        else
425          pathloc->node_access = node;
426
427        break;
428
429      case IMFS_NO_MORE_PATH:
430        rtems_set_errno_and_return_minus_one( EEXIST );
431        break;
432
433      case IMFS_INVALID_TOKEN:
434        rtems_set_errno_and_return_minus_one( ENAMETOOLONG );
435        break;
436
437      case IMFS_CURRENT_DIR:
438        break;
439    }
440  }
441
442  *name = &path[ i - len ];
443
444  /*
445   * We have evaluated the path as far as we can.
446   * Verify there is not any invalid stuff at the end of the name.
447   */
448
449  for( ; path[i] != '\0'; i++) {
450    if ( !IMFS_is_separator( path[ i ] ) )
451      rtems_set_errno_and_return_minus_one( ENOENT );
452  }
453
454  /*
455   * Verify we can execute and write to this directory.
456   */
457
458  result = IMFS_Set_handlers( pathloc );
459
460  /*
461   * The returned node must be a directory
462   */
463  node = pathloc->node_access;
464  if ( node->type != IMFS_DIRECTORY )
465    rtems_set_errno_and_return_minus_one( ENOTDIR );
466
467  /*
468   * We must have Write and execute permission on the returned node.
469   */
470
471  if ( !IMFS_evaluate_permission( pathloc, RTEMS_LIBIO_PERMS_WX ) )
472    rtems_set_errno_and_return_minus_one( EACCES );
473
474  return result;
475}
476
477
478/*
479 *  IMFS_eval_path
480 *
481 *  The following routine evaluate path for a node that wishes to be
482 *  accessed with mode.  pathloc is returned with a pointer to the
483 *  node to be accessed.
484 */
485
486int IMFS_eval_path(
487  const char                        *pathname,     /* IN     */
488  size_t                             pathnamelen,  /* IN     */
489  int                                flags,        /* IN     */
490  rtems_filesystem_location_info_t  *pathloc       /* IN/OUT */
491                   )
492{
493  int                                 i = 0;
494  int                                 len;
495  IMFS_token_types                    type = IMFS_CURRENT_DIR;
496  char                                token[ IMFS_NAME_MAX + 1 ];
497  rtems_filesystem_location_info_t    newloc;
498  IMFS_jnode_t                       *node;
499  int                                 result;
500
501  if ( !rtems_libio_is_valid_perms( flags ) ) {
502    rtems_set_errno_and_return_minus_one( EIO );
503  }
504
505  /*
506   *  This was filled in by the caller and is valid in the
507   *  mount table.
508   */
509
510  node = pathloc->node_access;
511
512  /*
513   *  Evaluate all tokens until we are done or an error occurs.
514   */
515
516  while( (type != IMFS_NO_MORE_PATH) && (type != IMFS_INVALID_TOKEN) ) {
517
518    type = IMFS_get_token( &pathname[i], pathnamelen, token, &len );
519    pathnamelen -= len;
520    i += len;
521
522    if ( !pathloc->node_access )
523      rtems_set_errno_and_return_minus_one( ENOENT );
524
525    /*
526     * I cannot move out of this directory without execute permission.
527     */
528    if ( type != IMFS_NO_MORE_PATH )
529      if ( node->type == IMFS_DIRECTORY )
530        if ( !IMFS_evaluate_permission( pathloc, RTEMS_LIBIO_PERMS_SEARCH ) )
531          rtems_set_errno_and_return_minus_one( EACCES );
532
533    node = pathloc->node_access;
534
535    switch( type ) {
536      case IMFS_UP_DIR:
537        /*
538         *  Am I at the root of all filesystems? (chroot'ed?)
539         */
540
541        if ( pathloc->node_access == rtems_filesystem_root.node_access )
542          break;       /* Throw out the .. in this case */
543
544        /*
545         *  Am I at the root of this mounted filesystem?
546         */
547
548        if (pathloc->node_access ==
549            pathloc->mt_entry->mt_fs_root.node_access) {
550
551          /*
552           *  Am I at the root of all filesystems?
553           */
554
555          if ( pathloc->node_access == rtems_filesystem_root.node_access ) {
556            break;       /* Throw out the .. in this case */
557          } else {
558            newloc = pathloc->mt_entry->mt_point_node;
559            *pathloc = newloc;
560            return (*pathloc->ops->evalpath_h)(&(pathname[i-len]),
561                                               pathnamelen+len,
562                                               flags,pathloc);
563          }
564        } else {
565
566          if ( !node->Parent )
567            rtems_set_errno_and_return_minus_one( ENOENT );
568
569          node = node->Parent;
570          pathloc->node_access = node;
571
572        }
573
574        pathloc->node_access = node;
575        break;
576
577      case IMFS_NAME:
578        /*
579         *  If we are at a link follow it.
580         */
581
582        if ( node->type == IMFS_HARD_LINK ) {
583
584          IMFS_evaluate_hard_link( pathloc, 0 );
585
586          node = pathloc->node_access;
587          if ( !node )
588            rtems_set_errno_and_return_minus_one( ENOTDIR );
589
590        } else if ( node->type == IMFS_SYM_LINK ) {
591
592          result = IMFS_evaluate_sym_link( pathloc, 0 );
593
594          node = pathloc->node_access;
595          if ( result == -1 )
596            return -1;
597        }
598
599        /*
600         *  Only a directory can be decended into.
601         */
602
603        if ( node->type != IMFS_DIRECTORY )
604          rtems_set_errno_and_return_minus_one( ENOTDIR );
605
606        /*
607         *  If we are at a node that is a mount point. Set loc to the
608         *  new fs root node and let them finish evaluating the path.
609         */
610
611        if ( node->info.directory.mt_fs != NULL ) {
612          newloc   = node->info.directory.mt_fs->mt_fs_root;
613          *pathloc = newloc;
614          return (*pathloc->ops->evalpath_h)( &pathname[i-len],
615                                              pathnamelen+len,
616                                              flags, pathloc );
617        }
618
619        /*
620         *  Otherwise find the token name in the present location.
621         */
622
623        node = IMFS_find_match_in_dir( node, token );
624        if ( !node )
625          rtems_set_errno_and_return_minus_one( ENOENT );
626
627        /*
628         *  Set the node access to the point we have found.
629         */
630
631        pathloc->node_access = node;
632        break;
633
634      case IMFS_NO_MORE_PATH:
635      case IMFS_CURRENT_DIR:
636        break;
637
638      case IMFS_INVALID_TOKEN:
639        rtems_set_errno_and_return_minus_one( ENAMETOOLONG );
640        break;
641
642    }
643  }
644
645  /*
646   *  Always return the root node.
647   *
648   *  If we are at a node that is a mount point. Set loc to the
649   *  new fs root node and let let the mounted filesystem set the handlers.
650   *
651   *  NOTE: The behavior of stat() on a mount point appears to be questionable.
652   */
653
654  if ( node->type == IMFS_DIRECTORY ) {
655    if ( node->info.directory.mt_fs != NULL ) {
656      newloc   = node->info.directory.mt_fs->mt_fs_root;
657      *pathloc = newloc;
658      return (*pathloc->ops->evalpath_h)( &pathname[i-len],
659                                          pathnamelen+len,
660                                          flags, pathloc );
661    } else {
662      result = IMFS_Set_handlers( pathloc );
663    }
664  } else {
665    result = IMFS_Set_handlers( pathloc );
666  }
667
668  /*
669   * Verify we have the correct permissions for this node.
670   */
671
672  if ( !IMFS_evaluate_permission( pathloc, flags ) )
673    rtems_set_errno_and_return_minus_one( EACCES );
674
675  return result;
676}
Note: See TracBrowser for help on using the repository browser.