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

4.104.114.84.95
Last change on this file since 657e1bf6 was 657e1bf6, checked in by Joel Sherrill <joel.sherrill@…>, on 10/26/99 at 20:17:13

Added initial cut at miniIMFS which leaves out memfile and directory
readdir support. The next step is to add a mount table and configure
either the miniIMFS or the full IMFS at the application level.

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