OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rtems-20020807/] [cpukit/] [libfs/] [src/] [imfs/] [imfs_eval.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1026 ivang
/*
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
 *  imfs_eval.c,v 1.16 2002/01/04 18:30:58 joel Exp
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
 
35
int 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
 
72
int 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
 
126
int 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
 
166
int 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
 
227
int 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
 
280
int 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
 
477
int 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
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.