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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [rtems/] [c/] [src/] [lib/] [libc/] [imfs_eval.c] - Blame information for rev 228

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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