source: rtems/c/src/libfs/src/imfs/imfs_eval.c @ 0ef748fb

4.104.114.84.95
Last change on this file since 0ef748fb was 0ef748fb, checked in by Joel Sherrill <joel.sherrill@…>, on 12/13/00 at 17:53:55

2000-12-12 Jake Janovetz <janovetz@…>

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