source: rtems/c/src/exec/libfs/src/imfs/imfs_eval.c @ b2709481

4.104.114.84.95
Last change on this file since b2709481 was b2709481, checked in by Joel Sherrill <joel.sherrill@…>, on 01/04/02 at 18:30:58

2002-01-04 Ralf Corsepius <corsepiu@…>

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