source: rtems/c/src/lib/libc/memfile.c @ b568ccb

4.104.114.84.95
Last change on this file since b568ccb was b568ccb, checked in by Joel Sherrill <joel.sherrill@…>, on 11/02/99 at 20:20:13

The object memfile.o was being included in the miniIMFS even though it
should not have been. This required that IMFS_rmnod be split into
three separate (per file type) routines to avoid dependencies.
In the end, a miniIMFS application is 6K smaller than one using the
full IMFS.

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