source: rtems/c/src/lib/libc/imfs_eval.c @ 2f87c843

4.104.114.84.9
Last change on this file since 2f87c843 was 2f87c843, checked in by Joel Sherrill <joel.sherrill@…>, on Feb 5, 1999 at 12:28:43 AM

Corrected spacing and added some new error checks that were needed
to avoid dereferencing NULLs.

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