source: rtems/cpukit/libfs/src/imfs/memfile.c @ 6b5519a

4.104.114.84.95
Last change on this file since 6b5519a was 6b5519a, checked in by Joel Sherrill <joel.sherrill@…>, on 11/28/00 at 21:53:48

2000-11-28 Joel Sherrill <joel@…>

  • src/imfs/memfile.c: Bug report from Sturniolo Jose <jsturnio@…> where NULL pointer was dereferenced.
  • Property mode set to 100644
File size: 23.3 KB
Line 
1/*
2 *  IMFS Device Node Handlers
3 *
4 *  This file contains the set of handlers used to process operations on
5 *  IMFS memory file nodes.  The memory files are created in memory using
6 *  malloc'ed memory.  Thus any data stored in one of these files is lost
7 *  at system shutdown unless special arrangements to copy the data to
8 *  some type of non-volailte storage are made by the application.
9 *
10 *  COPYRIGHT (c) 1989-1999.
11 *  On-Line Applications Research Corporation (OAR).
12 *
13 *  The license and distribution terms for this file may be
14 *  found in the file LICENSE in this distribution or at
15 *  http://www.OARcorp.com/rtems/license.html.
16 *
17 *  $Id$
18 */
19
20#include <stdlib.h>
21#include <assert.h>
22#include <errno.h>
23
24#include <rtems.h>
25#include <rtems/libio.h>
26#include "imfs.h"
27#include <rtems/libio_.h>
28
29#define MEMFILE_STATIC
30
31/*
32 *  Prototypes of private routines
33 */
34
35MEMFILE_STATIC int IMFS_memfile_extend(
36   IMFS_jnode_t  *the_jnode,
37   off_t          new_length
38);
39
40MEMFILE_STATIC int IMFS_memfile_addblock(
41   IMFS_jnode_t  *the_jnode,
42   unsigned int   block
43);
44
45MEMFILE_STATIC int IMFS_memfile_remove_block(
46   IMFS_jnode_t  *the_jnode,
47   unsigned int   block
48);
49
50MEMFILE_STATIC block_p *IMFS_memfile_get_block_pointer(
51   IMFS_jnode_t   *the_jnode,
52   unsigned int    block,
53   int             malloc_it
54);
55
56MEMFILE_STATIC int IMFS_memfile_read(
57   IMFS_jnode_t    *the_jnode,
58   off_t            start,
59   unsigned char   *destination,
60   unsigned int     length
61);
62
63MEMFILE_STATIC int IMFS_memfile_write(
64   IMFS_jnode_t          *the_jnode,
65   off_t                  start,
66   const unsigned char   *source,
67   unsigned int           length
68);
69
70void *memfile_alloc_block(void);
71
72void memfile_free_block(
73  void *memory
74);
75
76/*
77 *  memfile_open
78 *
79 *  This routine processes the open() system call.  Note that there is
80 *  nothing special to be done at open() time.
81 */
82
83int memfile_open(
84  rtems_libio_t *iop,
85  const char    *pathname,
86  unsigned32     flag,
87  unsigned32     mode
88)
89{
90  IMFS_jnode_t  *the_jnode;
91
92  the_jnode = iop->file_info;
93
94  if (iop->flags & LIBIO_FLAGS_APPEND)
95    iop->offset = the_jnode->info.file.size;
96
97  return 0;
98}
99
100/*
101 *  memfile_close
102 *
103 *  This routine processes the close() system call.  Note that there is
104 *  nothing to flush or memory to free at this point.
105 */
106
107int memfile_close(
108  rtems_libio_t *iop
109)
110{
111  IMFS_jnode_t   *the_jnode;
112
113  the_jnode = iop->file_info;
114
115  if (iop->flags & LIBIO_FLAGS_APPEND)
116    iop->offset = the_jnode->info.file.size;
117
118  return 0;
119}
120
121/*
122 *  memfile_read
123 *
124 *  This routine processes the read() system call.
125 */
126
127int memfile_read(
128  rtems_libio_t *iop,
129  void          *buffer,
130  unsigned32     count
131)
132{
133  IMFS_jnode_t   *the_jnode;
134
135  the_jnode = iop->file_info;
136
137  return IMFS_memfile_read( the_jnode, iop->offset, buffer, count );
138}
139
140/*
141 *  memfile_write
142 *
143 *  This routine processes the write() system call.
144 */
145
146int memfile_write(
147  rtems_libio_t *iop,
148  const void    *buffer,
149  unsigned32     count
150)
151{
152  IMFS_jnode_t   *the_jnode;
153  int             status;
154
155  the_jnode = iop->file_info;
156
157  status = IMFS_memfile_write( the_jnode, iop->offset, buffer, count );
158  iop->size = the_jnode->info.file.size;
159
160  return status;
161}
162
163/*
164 *  memfile_ioctl
165 *
166 *  This routine processes the ioctl() system call.
167 *
168 *  NOTE:  No ioctl()'s are supported for in-memory files.
169 */
170
171int memfile_ioctl(
172  rtems_libio_t *iop,
173  unsigned32     command,
174  void          *buffer
175)
176{
177  IMFS_jnode_t   *the_jnode;
178
179  the_jnode = iop->file_info;
180
181  return 0;
182}
183
184/*
185 *  memfile_lseek
186 *
187 *  This routine processes the lseek() system call.
188 */
189
190int memfile_lseek(
191  rtems_libio_t   *iop,
192  off_t            offset,
193  int              whence
194)
195{
196  IMFS_jnode_t   *the_jnode;
197
198  the_jnode = iop->file_info;
199
200  if (IMFS_memfile_extend( the_jnode, iop->offset ))
201    set_errno_and_return_minus_one( ENOSPC );
202
203  iop->size = the_jnode->info.file.size;
204  return iop->offset;
205}
206
207/*
208 *  memfile_stat
209 *
210 *  This IMFS_stat() can be used.
211 */
212
213/*
214 *  memfile_ftruncate
215 *
216 *  This routine processes the ftruncate() system call.
217 */
218
219int memfile_ftruncate(
220  rtems_libio_t        *iop,
221  off_t                 length
222)
223{
224  IMFS_jnode_t   *the_jnode;
225
226  the_jnode = iop->file_info;
227
228  /*
229   *  POSIX 1003.1b does not specify what happens if you truncate a file
230   *  and the new length is greater than the current size.  We treat this
231   *  as an extend operation.
232   */
233
234  if ( length > the_jnode->info.file.size )
235    return IMFS_memfile_extend( the_jnode, length );
236
237  /*
238   *  The in-memory files do not currently reclaim memory until the file is
239   *  deleted.  So we leave the previously allocated blocks in place for
240   *  future use and just set the length.
241   */
242
243  the_jnode->info.file.size = length;
244  iop->size = the_jnode->info.file.size;
245
246  IMFS_update_atime( the_jnode );
247
248  return 0;
249}
250
251/*
252 *  IMFS_memfile_extend
253 *
254 *  This routine insures that the in-memory file is of the length
255 *  specified.  If necessary, it will allocate memory blocks to
256 *  extend the file.
257 */
258
259MEMFILE_STATIC int IMFS_memfile_extend(
260   IMFS_jnode_t  *the_jnode,
261   off_t          new_length
262)
263{
264  unsigned int   block;
265  unsigned int   new_blocks;
266  unsigned int   old_blocks;
267
268  /*
269   *  Perform internal consistency checks
270   */
271
272  assert( the_jnode );
273  if ( !the_jnode )
274    set_errno_and_return_minus_one( EIO );
275
276  assert( the_jnode->type == IMFS_MEMORY_FILE );
277  if ( the_jnode->type != IMFS_MEMORY_FILE )
278    set_errno_and_return_minus_one( EIO );
279
280  if ( new_length >= IMFS_MEMFILE_MAXIMUM_SIZE )
281    set_errno_and_return_minus_one( EINVAL );
282
283  if ( new_length <= the_jnode->info.file.size )
284    return 0;
285
286  /*
287   *  Calculate the number of range of blocks to allocate
288   */
289
290  new_blocks = new_length / IMFS_MEMFILE_BYTES_PER_BLOCK;
291  old_blocks = the_jnode->info.file.size / IMFS_MEMFILE_BYTES_PER_BLOCK;
292
293  /*
294   *  Now allocate each of those blocks.
295   */
296
297  for ( block=old_blocks ; block<=new_blocks ; block++ ) {
298    if ( IMFS_memfile_addblock( the_jnode, block ) ) {
299       for ( ; block>=old_blocks ; block-- ) {
300          IMFS_memfile_remove_block( the_jnode, block );
301       }
302       set_errno_and_return_minus_one( ENOSPC );
303    }
304  }
305
306  /*
307   *  Set the new length of the file.
308   */
309
310  the_jnode->info.file.size = new_length;
311  return 0;
312}
313
314/*
315 *  IMFS_memfile_addblock
316 *
317 *  This routine adds a single block to the specified in-memory file.
318 */
319
320MEMFILE_STATIC int IMFS_memfile_addblock(
321   IMFS_jnode_t  *the_jnode,
322   unsigned int   block
323)
324{
325  block_p  memory;
326  block_p *block_entry_ptr;
327
328  assert( the_jnode );
329  if ( !the_jnode )
330    set_errno_and_return_minus_one( EIO );
331
332  assert( the_jnode->type == IMFS_MEMORY_FILE );
333  if ( the_jnode->type != IMFS_MEMORY_FILE )
334    set_errno_and_return_minus_one( EIO );
335
336  block_entry_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 1 );
337  if ( *block_entry_ptr )
338    return 0;
339
340#if 0
341  printf( "%d %p", block, block_entry_ptr );
342    fflush(stdout);
343#endif
344
345  memory = memfile_alloc_block();
346  if ( !memory )
347    return 1;
348  *block_entry_ptr = memory;
349
350  return 0;
351}
352
353/*
354 *  IMFS_memfile_remove_block
355 *
356 *  This routine removes the specified block from the in-memory file.
357 *
358 *  NOTE:  This is a support routine and is called only to remove
359 *         the last block or set of blocks in a file.  Removing a
360 *         block from the middle of a file would be exceptionally
361 *         dangerous and the results unpredictable.
362 */
363
364MEMFILE_STATIC int IMFS_memfile_remove_block(
365   IMFS_jnode_t  *the_jnode,
366   unsigned int   block
367)
368{
369  block_p *block_entry_ptr;
370  block_p  ptr;
371
372  block_entry_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
373  ptr = *block_entry_ptr;
374  *block_entry_ptr = 0;
375
376  memfile_free_block( ptr );
377
378  return 1;
379}
380
381/*
382 *  memfile_free_blocks_in_table
383 *
384 *  This is a support routine for IMFS_memfile_remove.  It frees all the
385 *  blocks in one of the indirection tables.
386 */
387
388void memfile_free_blocks_in_table(
389  block_p **block_table,
390  int       entries
391)
392{
393  int      i;
394  block_p *b;
395
396  /*
397   *  Perform internal consistency checks
398   */
399
400  assert( block_table );
401  if ( !block_table )
402    return;
403
404  /*
405   *  Now go through all the slots in the table and free the memory.
406   */
407
408  b = *block_table;
409
410  for ( i=0 ; i<entries ; i++ ) {
411    if ( b[i] ) {
412      memfile_free_block( b[i] );
413      b[i] = 0;
414    }
415  }
416
417  /*
418   *  Now that all the blocks in the block table are free, we can
419   *  free the block table itself.
420   */
421
422  memfile_free_block( *block_table );
423  *block_table = 0;
424}
425
426/*
427 *  IMFS_memfile_remove
428 *
429 *  This routine frees all memory associated with an in memory file.
430 *
431 *  NOTE:  This is an exceptionally conservative implementation. 
432 *         It will check EVERY pointer which is non-NULL and insure
433 *         any child non-NULL pointers are freed.  Optimistically, all that
434 *         is necessary is to scan until a NULL pointer is found.  There
435 *         should be no allocated data past that point.
436 *
437 *         In experimentation on the powerpc simulator, it was noted
438 *         that using blocks which held 128 slots versus 16 slots made
439 *         a significant difference in the performance of this routine.
440 *
441 *         Regardless until the IMFS implementation is proven, it
442 *         is better to stick to simple, easy to understand algorithms.
443 */
444
445int IMFS_memfile_remove(
446 IMFS_jnode_t  *the_jnode
447)
448{
449  IMFS_memfile_t  *info;
450  int              i;
451  int              j;
452  unsigned int     to_free;
453  block_p         *p;
454
455  /*
456   *  Perform internal consistency checks
457   */
458
459  assert( the_jnode );
460  if ( !the_jnode )
461    set_errno_and_return_minus_one( EIO );
462
463  assert( the_jnode->type == IMFS_MEMORY_FILE );
464  if ( the_jnode->type != IMFS_MEMORY_FILE )
465    set_errno_and_return_minus_one( EIO );
466
467  /*
468   *  Eventually this could be set smarter at each call to
469   *  memfile_free_blocks_in_table to greatly speed this up.
470   */
471
472  to_free = IMFS_MEMFILE_BLOCK_SLOTS;
473
474  /*
475   *  Now start freeing blocks in this order:
476   *    + indirect
477   *    + doubly indirect
478   *    + triply indirect
479   */
480
481  info = &the_jnode->info.file;
482
483  if ( info->indirect ) {
484    memfile_free_blocks_in_table( &info->indirect, to_free );
485  }
486
487  if ( info->doubly_indirect ) {
488
489    for ( i=0 ; i<IMFS_MEMFILE_BLOCK_SLOTS ; i++ ) {
490      if ( info->doubly_indirect[i] ) {
491        memfile_free_blocks_in_table(
492         (block_p **)&info->doubly_indirect[i], to_free );
493      }
494    }
495    memfile_free_blocks_in_table( &info->doubly_indirect, to_free );
496
497  }
498 
499  if ( info->triply_indirect ) {
500    for ( i=0 ; i<IMFS_MEMFILE_BLOCK_SLOTS ; i++ ) {
501      p = (block_p *) info->triply_indirect[i];
502      if (!p)  /* ensure we have a valid pointer */
503        break;
504      for ( j=0 ; j<IMFS_MEMFILE_BLOCK_SLOTS ; j++ ) {
505        if ( p[j] ) {
506          memfile_free_blocks_in_table( (block_p **)&p[j], to_free);
507        }
508      }
509      memfile_free_blocks_in_table(
510        (block_p **)&info->triply_indirect[i], to_free );
511    }
512    memfile_free_blocks_in_table(
513        (block_p **)&info->triply_indirect, to_free );
514  }
515
516  return 0;
517}
518
519/*
520 *  IMFS_memfile_read
521 *
522 *  This routine read from memory file pointed to by the_jnode into
523 *  the specified data buffer specified by destination.  The file
524 *  is NOT extended.  An offset greater than the length of the file
525 *  is considered an error.  Read from an offset for more bytes than
526 *  are between the offset and the end of the file will result in
527 *  reading the data between offset and the end of the file (truncated
528 *  read).
529 */
530
531MEMFILE_STATIC int IMFS_memfile_read(
532   IMFS_jnode_t    *the_jnode,
533   off_t            start,
534   unsigned char   *destination,
535   unsigned int     length
536)
537{
538  block_p             *block_ptr;
539  unsigned int         block;
540  unsigned int         my_length;
541  unsigned int         to_copy = 0;
542  unsigned int         last_byte;
543  unsigned int         copied;
544  unsigned int         start_offset;
545  unsigned char       *dest;
546
547  dest = destination;
548
549  /*
550   *  Perform internal consistency checks
551   */
552
553  assert( the_jnode );
554  if ( !the_jnode )
555    set_errno_and_return_minus_one( EIO );
556
557  assert( the_jnode->type == IMFS_MEMORY_FILE );
558  if ( the_jnode->type != IMFS_MEMORY_FILE )
559    set_errno_and_return_minus_one( EIO );
560
561  /*
562   *  Error checks on arguments
563   */
564
565  assert( dest );
566  if ( !dest )
567    set_errno_and_return_minus_one( EINVAL );
568
569  /*
570   *  If there is nothing to read, then quick exit.
571   */
572
573  my_length = length;
574  if ( !my_length )
575    set_errno_and_return_minus_one( EINVAL );
576
577  /*
578   *  If the last byte we are supposed to read is past the end of this
579   *  in memory file, then shorten the length to read.
580   */
581
582  last_byte = start + length;
583  if ( last_byte > the_jnode->info.file.size )
584    my_length = the_jnode->info.file.size - start;
585
586  copied = 0;
587
588  /*
589   *  Three phases to the read:
590   *    + possibly the last part of one block
591   *    + all of zero of more blocks
592   *    + possibly the first part of one block
593   */
594
595  /*
596   *  Phase 1: possibly the last part of one block
597   */
598
599  start_offset = start % IMFS_MEMFILE_BYTES_PER_BLOCK;
600  block = start / IMFS_MEMFILE_BYTES_PER_BLOCK;
601  if ( start_offset )  {
602    to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK - start_offset;
603    if ( to_copy > my_length )
604      to_copy = my_length;
605    block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
606    assert( block_ptr );
607    if ( !block_ptr )
608      return copied;
609    memcpy( dest, &(*block_ptr)[ start_offset ], to_copy );
610    dest += to_copy;
611    block++;
612    my_length -= to_copy;
613    copied += to_copy;
614  }
615
616  /*
617   *  Phase 2: all of zero of more blocks
618   */
619
620  to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK;
621  while ( my_length >= IMFS_MEMFILE_BYTES_PER_BLOCK ) {
622    block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
623    assert( block_ptr );
624    if ( !block_ptr )
625      return copied;
626    memcpy( dest, &(*block_ptr)[ 0 ], to_copy );
627    dest += to_copy;
628    block++;
629    my_length -= to_copy;
630    copied += to_copy;
631  }
632
633  /*
634   *  Phase 3: possibly the first part of one block
635   */
636
637  assert( my_length < IMFS_MEMFILE_BYTES_PER_BLOCK );
638
639  if ( my_length ) {
640    block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
641    assert( block_ptr );
642    if ( !block_ptr )
643      return copied;
644    memcpy( dest, &(*block_ptr)[ 0 ], my_length );
645    copied += my_length;
646  }
647
648  IMFS_update_atime( the_jnode );
649
650  return copied;
651}
652
653/*
654 *  IMFS_memfile_write
655 *
656 *  This routine writes the specified data buffer into the in memory
657 *  file pointed to by the_jnode.  The file is extended as needed.
658 */
659
660MEMFILE_STATIC int IMFS_memfile_write(
661   IMFS_jnode_t          *the_jnode,
662   off_t                  start,
663   const unsigned char   *source,
664   unsigned int           length
665)
666{
667  block_p             *block_ptr;
668  unsigned int         block;
669  int                  status;
670  unsigned int         my_length;
671  unsigned int         to_copy = 0;
672  unsigned int         last_byte;
673  unsigned int         start_offset;
674  int                  copied;
675  const unsigned char *src;
676
677  src = source;
678
679  /*
680   *  Perform internal consistency checks
681   */
682
683  assert( the_jnode );
684  if ( !the_jnode )
685    set_errno_and_return_minus_one( EIO );
686
687  assert( the_jnode->type == IMFS_MEMORY_FILE );
688  if ( the_jnode->type != IMFS_MEMORY_FILE )
689    set_errno_and_return_minus_one( EIO );
690
691  /*
692   *  Error check arguments
693   */
694
695  assert( source );
696  if ( !source )
697    set_errno_and_return_minus_one( EINVAL );
698
699
700  /*
701   *  If there is nothing to write, then quick exit.
702   */
703
704  my_length = length;
705  if ( !my_length )
706    set_errno_and_return_minus_one( EINVAL );
707
708  /*
709   *  If the last byte we are supposed to write is past the end of this
710   *  in memory file, then extend the length.
711   */
712
713  last_byte = start + length;
714  if ( last_byte > the_jnode->info.file.size ) {
715    status = IMFS_memfile_extend( the_jnode, last_byte );
716    if ( status )
717      set_errno_and_return_minus_one( ENOSPC );
718  }
719
720  copied = 0;
721
722  /*
723   *  Three phases to the write:
724   *    + possibly the last part of one block
725   *    + all of zero of more blocks
726   *    + possibly the first part of one block
727   */
728
729  /*
730   *  Phase 1: possibly the last part of one block
731   */
732
733  start_offset = start % IMFS_MEMFILE_BYTES_PER_BLOCK;
734  block = start / IMFS_MEMFILE_BYTES_PER_BLOCK;
735  if ( start_offset )  {
736    to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK - start_offset;
737    if ( to_copy > my_length )
738      to_copy = my_length;
739    block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
740    assert( block_ptr );
741    if ( !block_ptr )
742      return copied;
743#if 0
744printf( "write %d at %d in %d: %*s\n", to_copy, start_offset, block, to_copy, src );
745#endif
746    memcpy( &(*block_ptr)[ start_offset ], src, to_copy );
747    src += to_copy;
748    block++;
749    my_length -= to_copy;
750    copied += to_copy;
751  }
752
753  /*
754   *  Phase 2: all of zero of more blocks
755   */
756
757  to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK;
758  while ( my_length >= IMFS_MEMFILE_BYTES_PER_BLOCK ) {
759    block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
760    assert( block_ptr );
761    if ( !block_ptr )
762      return copied;
763#if 0
764printf( "write %d in %d: %*s\n", to_copy, block, to_copy, src );
765#endif
766    memcpy( &(*block_ptr)[ 0 ], src, to_copy );
767    src += to_copy;
768    block++;
769    my_length -= to_copy;
770    copied += to_copy;
771  }
772
773  /*
774   *  Phase 3: possibly the first part of one block
775   */
776
777  assert( my_length < IMFS_MEMFILE_BYTES_PER_BLOCK );
778
779  to_copy = my_length;
780  if ( my_length ) {
781    block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
782    assert( block_ptr );
783    if ( !block_ptr )
784      return copied;
785#if 0
786printf( "write %d in %d: %*s\n", to_copy, block, to_copy, src );
787#endif
788    memcpy( &(*block_ptr)[ 0 ], src, my_length );
789    my_length = 0;
790    copied += to_copy;
791  }
792
793  IMFS_atime_mtime_update( the_jnode );
794
795  return copied;
796}
797
798/*
799 *  IMFS_memfile_get_block_pointer
800 *
801 *  This routine looks up the block pointer associated with the given block
802 *  number.  If that block has not been allocated and "malloc_it" is
803 *  TRUE, then the block is allocated.  Otherwise, it is an error.
804 */
805
806#if 0
807block_p *IMFS_memfile_get_block_pointer_DEBUG(
808   IMFS_jnode_t   *the_jnode,
809   unsigned int    block,
810   int             malloc_it
811);
812
813block_p *IMFS_memfile_get_block_pointer(
814   IMFS_jnode_t   *the_jnode,
815   unsigned int    block,
816   int             malloc_it
817)
818{
819  block_p *p;
820
821  p = IMFS_memfile_get_block_pointer_DEBUG( the_jnode, block, malloc_it );
822  printf( "(%d -> %p) ", block, p );
823  return p;
824}
825
826block_p *IMFS_memfile_get_block_pointer_DEBUG(
827#else
828block_p *IMFS_memfile_get_block_pointer(
829#endif
830   IMFS_jnode_t   *the_jnode,
831   unsigned int    block,
832   int             malloc_it
833)
834{
835  unsigned int    my_block;
836  IMFS_memfile_t *info;
837  unsigned int    singly;
838  unsigned int    doubly;
839  unsigned int    triply;
840  block_p        *p;
841  block_p        *p1;
842  block_p        *p2;
843
844  /*
845   *  Perform internal consistency checks
846   */
847
848  assert( the_jnode );
849  if ( !the_jnode )
850    return NULL;
851
852  assert( the_jnode->type == IMFS_MEMORY_FILE );
853  if ( the_jnode->type != IMFS_MEMORY_FILE )
854    return NULL;
855
856  info = &the_jnode->info.file;
857
858  my_block = block;
859
860  /*
861   *  Is the block number in the simple indirect portion?
862   */
863
864  if ( my_block <= LAST_INDIRECT ) {
865#if 0
866printf( "(s %d) ", block );
867fflush(stdout);
868#endif
869    p = info->indirect;
870
871    if ( malloc_it ) {
872
873      if ( !p ) {
874        p = memfile_alloc_block();
875        if ( !p )
876           return 0;
877        info->indirect = p;
878      }
879      return &info->indirect[ my_block ];
880    }
881
882    if ( !p )
883      return 0;
884
885    return &info->indirect[ my_block ];
886  }
887
888  /*
889   *  Is the block number in the doubly indirect portion?
890   */
891
892  if ( my_block <= LAST_DOUBLY_INDIRECT ) {
893#if 0
894printf( "(d %d) ", block );
895fflush(stdout);
896#endif
897
898    my_block -= FIRST_DOUBLY_INDIRECT;
899
900    singly = my_block % IMFS_MEMFILE_BLOCK_SLOTS;
901    doubly = my_block / IMFS_MEMFILE_BLOCK_SLOTS;
902
903    p = info->doubly_indirect;
904    if ( malloc_it ) {
905
906      if ( !p ) {
907        p = memfile_alloc_block();
908        if ( !p )
909           return 0;
910        info->doubly_indirect = p;
911      }
912
913      p1 = (block_p *)p[ doubly ];
914      if ( !p1 ) {
915        p1 = memfile_alloc_block();
916        if ( !p1 )
917           return 0;
918        p[ doubly ] = (block_p) p1;
919      }
920
921      return (block_p *)&p1[ singly ];
922    }
923
924    if ( !p )
925      return 0;
926
927    p = (block_p *)p[ doubly ];
928    if ( !p )
929      return 0;
930
931#if 0
932printf( "(d %d %d %d %d %p %p) ", block, my_block, doubly,
933                                       singly, p, &p[singly] );
934fflush(stdout);
935#endif
936    return (block_p *)&p[ singly ];
937  }
938
939#if 0
940printf( "(t %d) ", block );
941fflush(stdout);
942#endif
943  /*
944   *  Is the block number in the triply indirect portion?
945   */
946
947  if ( my_block <= LAST_TRIPLY_INDIRECT ) {
948    my_block -= FIRST_TRIPLY_INDIRECT;
949
950    singly = my_block % IMFS_MEMFILE_BLOCK_SLOTS;
951    doubly = my_block / IMFS_MEMFILE_BLOCK_SLOTS;
952    triply = doubly / IMFS_MEMFILE_BLOCK_SLOTS;
953    doubly %= IMFS_MEMFILE_BLOCK_SLOTS;
954
955    p = info->triply_indirect;
956
957    if ( malloc_it ) {
958      if ( !p ) {
959        p = memfile_alloc_block();
960        if ( !p )
961           return 0;
962        info->triply_indirect = p;
963      }
964
965      p1 = (block_p *) p[ triply ];
966      if ( !p1 ) {
967        p1 = memfile_alloc_block();
968        if ( !p1 )
969           return 0;
970        p[ triply ] = (block_p) p1;
971      }
972
973      p2 = (block_p *)p1[ doubly ];
974      if ( !p2 ) {
975        p2 = memfile_alloc_block();
976        if ( !p2 )
977           return 0;
978        p1[ doubly ] = (block_p) p2;
979      }
980      return (block_p *)&p2[ singly ];
981    }
982
983    if ( !p )
984      return 0;
985
986#if 0
987printf( "(t %d %d %d %d %d) ", block, my_block, triply, doubly, singly );
988fflush(stdout);
989#endif
990    p1 = (block_p *) p[ triply ];
991    if ( !p1 )
992      return 0;
993
994    p2 = (block_p *)p1[ doubly ];
995    if ( !p )
996      return 0;
997
998    return (block_p *)&p2[ singly ];
999  }
1000
1001  /*
1002   *  This means the requested block number is out of range.
1003   */
1004
1005  return 0;
1006}
1007
1008/*
1009 *  memfile_alloc_block
1010 *
1011 *  Allocate a block for an in-memory file.
1012 */
1013
1014int memfile_blocks_allocated = 0;
1015
1016void *memfile_alloc_block(void)
1017{
1018  void *memory;
1019
1020  memory = (void *)calloc(1, IMFS_MEMFILE_BYTES_PER_BLOCK);
1021  if ( memory )
1022    memfile_blocks_allocated++;
1023
1024  return memory;
1025}
1026
1027/*
1028 *  memfile_free_block
1029 *
1030 *  Free a block from an in-memory file.
1031 */
1032
1033void memfile_free_block(
1034  void *memory
1035)
1036{
1037#if 0
1038printf( "(d %p) ", memory );
1039fflush(stdout);
1040#endif
1041  free(memory);
1042  memfile_blocks_allocated--;
1043}
1044
1045
1046/*
1047 *  memfile_rmnod
1048 *
1049 *  This routine is available from the optable to remove a node
1050 *  from the IMFS file system.
1051 */
1052
1053int memfile_rmnod(
1054  rtems_filesystem_location_info_t      *pathloc       /* IN */
1055)
1056{
1057  IMFS_jnode_t *the_jnode; 
1058
1059  the_jnode = (IMFS_jnode_t *) pathloc->node_access;
1060
1061  /*
1062   * Take the node out of the parent's chain that contains this node
1063   */
1064
1065  if ( the_jnode->Parent != NULL ) {
1066    Chain_Extract( (Chain_Node *) the_jnode );
1067    the_jnode->Parent = NULL;
1068  }
1069
1070  /*
1071   * Decrement the link counter and see if we can free the space.
1072   */
1073
1074  the_jnode->st_nlink--;
1075  IMFS_update_ctime( the_jnode );
1076
1077  /*
1078   * The file cannot be open and the link must be less than 1 to free.
1079   */
1080
1081  if ( !rtems_libio_is_file_open( the_jnode ) && (the_jnode->st_nlink < 1) ) {
1082
1083    /*
1084     * Is the rtems_filesystem_current is this node?
1085     */
1086
1087    if ( rtems_filesystem_current.node_access == pathloc->node_access )
1088       rtems_filesystem_current.node_access = NULL;
1089
1090    /*
1091     * Free memory associated with a memory file.
1092     */
1093
1094    IMFS_memfile_remove( the_jnode );
1095
1096    free( the_jnode );
1097  }
1098
1099  return 0;
1100
1101}
1102
1103
Note: See TracBrowser for help on using the repository browser.