source: rtems/c/src/lib/libc/memfile.c @ 5f3ad6a

Last change on this file since 5f3ad6a was 5f3ad6a, checked in by Joel Sherrill <joel.sherrill@…>, on Jun 26, 2000 at 2:50:00 PM

Patch from Chris Johns <cjohns@…> and
Jennifer Averett <jennifer.averett@…> to fix
appends (O_APPEND at open time) on in-memory files.

A call such as:

fd = open (file, O_APPEND | O_WRONLY);

did not append to the end of the file.

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