source: rtems/c/src/lib/libc/memfile.c @ 7c1a82f

Last change on this file since 7c1a82f was 7c1a82f, checked in by Joel Sherrill <joel.sherrill@…>, on May 23, 2000 at 3:41:04 PM

Patch from Jennifer Averett <jennifer.averett@…> to make
this C++ safe.

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