source: rtems/c/src/lib/libc/memfile.c @ 74835d7

Last change on this file since 74835d7 was 74835d7, checked in by Joel Sherrill <joel.sherrill@…>, on 08/11/00 at 20:04:03

2000-08-11 Chris Johns <ccj@…>

  • libc/chmod.c: Return ENOTSUP if filesystem does not have handler.
  • libc/eval.c: Ditto.
  • libc/fcntl.c: Ditto.
  • libc/fsync.c: Ditto.
  • libc/ioctl.c: Ditto.
  • libc/ioman.c: Ditto.
  • libc/link.c: Ditto.
  • libc/memfile.c: Ditto.
  • libc/mknod.c: Ditto.
  • libc/symlink.c: Ditto.
  • libc/libio.h(rtems_filesystem_dev_major_t): New macro.
  • libc/libio.h(rtems_filesystem_dev_minor_t): New macro.
  • 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  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      for ( j=0 ; j<IMFS_MEMFILE_BLOCK_SLOTS ; j++ ) {
503        if ( p[j] ) {
504          memfile_free_blocks_in_table( (block_p **)&p[j], to_free);
505        }
506      }
507      memfile_free_blocks_in_table(
508        (block_p **)&info->triply_indirect[i], to_free );
509    }
510    memfile_free_blocks_in_table(
511        (block_p **)&info->triply_indirect, to_free );
512  }
513
514  return 0;
515}
516
517/*
518 *  IMFS_memfile_read
519 *
520 *  This routine read from memory file pointed to by the_jnode into
521 *  the specified data buffer specified by destination.  The file
522 *  is NOT extended.  An offset greater than the length of the file
523 *  is considered an error.  Read from an offset for more bytes than
524 *  are between the offset and the end of the file will result in
525 *  reading the data between offset and the end of the file (truncated
526 *  read).
527 */
528
529MEMFILE_STATIC int IMFS_memfile_read(
530   IMFS_jnode_t    *the_jnode,
531   off_t            start,
532   unsigned char   *destination,
533   unsigned int     length
534)
535{
536  block_p             *block_ptr;
537  unsigned int         block;
538  unsigned int         my_length;
539  unsigned int         to_copy = 0;
540  unsigned int         last_byte;
541  unsigned int         copied;
542  unsigned int         start_offset;
543  unsigned char       *dest;
544
545  dest = destination;
546
547  /*
548   *  Perform internal consistency checks
549   */
550
551  assert( the_jnode );
552  if ( !the_jnode )
553    set_errno_and_return_minus_one( EIO );
554
555  assert( the_jnode->type == IMFS_MEMORY_FILE );
556  if ( the_jnode->type != IMFS_MEMORY_FILE )
557    set_errno_and_return_minus_one( EIO );
558
559  /*
560   *  Error checks on arguments
561   */
562
563  assert( dest );
564  if ( !dest )
565    set_errno_and_return_minus_one( EINVAL );
566
567  /*
568   *  If there is nothing to read, then quick exit.
569   */
570
571  my_length = length;
572  if ( !my_length )
573    set_errno_and_return_minus_one( EINVAL );
574
575  /*
576   *  If the last byte we are supposed to read is past the end of this
577   *  in memory file, then shorten the length to read.
578   */
579
580  last_byte = start + length;
581  if ( last_byte > the_jnode->info.file.size )
582    my_length = the_jnode->info.file.size - start;
583
584  copied = 0;
585
586  /*
587   *  Three phases to the read:
588   *    + possibly the last part of one block
589   *    + all of zero of more blocks
590   *    + possibly the first part of one block
591   */
592
593  /*
594   *  Phase 1: possibly the last part of one block
595   */
596
597  start_offset = start % IMFS_MEMFILE_BYTES_PER_BLOCK;
598  block = start / IMFS_MEMFILE_BYTES_PER_BLOCK;
599  if ( start_offset )  {
600    to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK - start_offset;
601    if ( to_copy > my_length )
602      to_copy = my_length;
603    block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
604    assert( block_ptr );
605    if ( !block_ptr )
606      return copied;
607    memcpy( dest, &(*block_ptr)[ start_offset ], to_copy );
608    dest += to_copy;
609    block++;
610    my_length -= to_copy;
611    copied += to_copy;
612  }
613
614  /*
615   *  Phase 2: all of zero of more blocks
616   */
617
618  to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK;
619  while ( my_length >= IMFS_MEMFILE_BYTES_PER_BLOCK ) {
620    block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
621    assert( block_ptr );
622    if ( !block_ptr )
623      return copied;
624    memcpy( dest, &(*block_ptr)[ 0 ], to_copy );
625    dest += to_copy;
626    block++;
627    my_length -= to_copy;
628    copied += to_copy;
629  }
630
631  /*
632   *  Phase 3: possibly the first part of one block
633   */
634
635  assert( my_length < IMFS_MEMFILE_BYTES_PER_BLOCK );
636
637  if ( my_length ) {
638    block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
639    assert( block_ptr );
640    if ( !block_ptr )
641      return copied;
642    memcpy( dest, &(*block_ptr)[ 0 ], my_length );
643    copied += my_length;
644  }
645
646  IMFS_update_atime( the_jnode );
647
648  return copied;
649}
650
651/*
652 *  IMFS_memfile_write
653 *
654 *  This routine writes the specified data buffer into the in memory
655 *  file pointed to by the_jnode.  The file is extended as needed.
656 */
657
658MEMFILE_STATIC int IMFS_memfile_write(
659   IMFS_jnode_t          *the_jnode,
660   off_t                  start,
661   const unsigned char   *source,
662   unsigned int           length
663)
664{
665  block_p             *block_ptr;
666  unsigned int         block;
667  int                  status;
668  unsigned int         my_length;
669  unsigned int         to_copy = 0;
670  unsigned int         last_byte;
671  unsigned int         start_offset;
672  int                  copied;
673  const unsigned char *src;
674
675  src = source;
676
677  /*
678   *  Perform internal consistency checks
679   */
680
681  assert( the_jnode );
682  if ( !the_jnode )
683    set_errno_and_return_minus_one( EIO );
684
685  assert( the_jnode->type == IMFS_MEMORY_FILE );
686  if ( the_jnode->type != IMFS_MEMORY_FILE )
687    set_errno_and_return_minus_one( EIO );
688
689  /*
690   *  Error check arguments
691   */
692
693  assert( source );
694  if ( !source )
695    set_errno_and_return_minus_one( EINVAL );
696
697
698  /*
699   *  If there is nothing to write, then quick exit.
700   */
701
702  my_length = length;
703  if ( !my_length )
704    set_errno_and_return_minus_one( EINVAL );
705
706  /*
707   *  If the last byte we are supposed to write is past the end of this
708   *  in memory file, then extend the length.
709   */
710
711  last_byte = start + length;
712  if ( last_byte > the_jnode->info.file.size ) {
713    status = IMFS_memfile_extend( the_jnode, last_byte );
714    if ( status )
715      set_errno_and_return_minus_one( ENOSPC );
716  }
717
718  copied = 0;
719
720  /*
721   *  Three phases to the write:
722   *    + possibly the last part of one block
723   *    + all of zero of more blocks
724   *    + possibly the first part of one block
725   */
726
727  /*
728   *  Phase 1: possibly the last part of one block
729   */
730
731  start_offset = start % IMFS_MEMFILE_BYTES_PER_BLOCK;
732  block = start / IMFS_MEMFILE_BYTES_PER_BLOCK;
733  if ( start_offset )  {
734    to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK - start_offset;
735    if ( to_copy > my_length )
736      to_copy = my_length;
737    block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
738    assert( block_ptr );
739    if ( !block_ptr )
740      return copied;
741#if 0
742printf( "write %d at %d in %d: %*s\n", to_copy, start_offset, block, to_copy, src );
743#endif
744    memcpy( &(*block_ptr)[ start_offset ], src, to_copy );
745    src += to_copy;
746    block++;
747    my_length -= to_copy;
748    copied += to_copy;
749  }
750
751  /*
752   *  Phase 2: all of zero of more blocks
753   */
754
755  to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK;
756  while ( my_length >= IMFS_MEMFILE_BYTES_PER_BLOCK ) {
757    block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
758    assert( block_ptr );
759    if ( !block_ptr )
760      return copied;
761#if 0
762printf( "write %d in %d: %*s\n", to_copy, block, to_copy, src );
763#endif
764    memcpy( &(*block_ptr)[ 0 ], src, to_copy );
765    src += to_copy;
766    block++;
767    my_length -= to_copy;
768    copied += to_copy;
769  }
770
771  /*
772   *  Phase 3: possibly the first part of one block
773   */
774
775  assert( my_length < IMFS_MEMFILE_BYTES_PER_BLOCK );
776
777  to_copy = my_length;
778  if ( my_length ) {
779    block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
780    assert( block_ptr );
781    if ( !block_ptr )
782      return copied;
783#if 0
784printf( "write %d in %d: %*s\n", to_copy, block, to_copy, src );
785#endif
786    memcpy( &(*block_ptr)[ 0 ], src, my_length );
787    my_length = 0;
788    copied += to_copy;
789  }
790
791  IMFS_atime_mtime_update( the_jnode );
792
793  return copied;
794}
795
796/*
797 *  IMFS_memfile_get_block_pointer
798 *
799 *  This routine looks up the block pointer associated with the given block
800 *  number.  If that block has not been allocated and "malloc_it" is
801 *  TRUE, then the block is allocated.  Otherwise, it is an error.
802 */
803
804#if 0
805block_p *IMFS_memfile_get_block_pointer_DEBUG(
806   IMFS_jnode_t   *the_jnode,
807   unsigned int    block,
808   int             malloc_it
809);
810
811block_p *IMFS_memfile_get_block_pointer(
812   IMFS_jnode_t   *the_jnode,
813   unsigned int    block,
814   int             malloc_it
815)
816{
817  block_p *p;
818
819  p = IMFS_memfile_get_block_pointer_DEBUG( the_jnode, block, malloc_it );
820  printf( "(%d -> %p) ", block, p );
821  return p;
822}
823
824block_p *IMFS_memfile_get_block_pointer_DEBUG(
825#else
826block_p *IMFS_memfile_get_block_pointer(
827#endif
828   IMFS_jnode_t   *the_jnode,
829   unsigned int    block,
830   int             malloc_it
831)
832{
833  unsigned int    my_block;
834  IMFS_memfile_t *info;
835  unsigned int    singly;
836  unsigned int    doubly;
837  unsigned int    triply;
838  block_p        *p;
839  block_p        *p1;
840  block_p        *p2;
841
842  /*
843   *  Perform internal consistency checks
844   */
845
846  assert( the_jnode );
847  if ( !the_jnode )
848    return NULL;
849
850  assert( the_jnode->type == IMFS_MEMORY_FILE );
851  if ( the_jnode->type != IMFS_MEMORY_FILE )
852    return NULL;
853
854  info = &the_jnode->info.file;
855
856  my_block = block;
857
858  /*
859   *  Is the block number in the simple indirect portion?
860   */
861
862  if ( my_block <= LAST_INDIRECT ) {
863#if 0
864printf( "(s %d) ", block );
865fflush(stdout);
866#endif
867    p = info->indirect;
868
869    if ( malloc_it ) {
870
871      if ( !p ) {
872        p = memfile_alloc_block();
873        if ( !p )
874           return 0;
875        info->indirect = p;
876      }
877      return &info->indirect[ my_block ];
878    }
879
880    if ( !p )
881      return 0;
882
883    return &info->indirect[ my_block ];
884  }
885
886  /*
887   *  Is the block number in the doubly indirect portion?
888   */
889
890  if ( my_block <= LAST_DOUBLY_INDIRECT ) {
891#if 0
892printf( "(d %d) ", block );
893fflush(stdout);
894#endif
895
896    my_block -= FIRST_DOUBLY_INDIRECT;
897
898    singly = my_block % IMFS_MEMFILE_BLOCK_SLOTS;
899    doubly = my_block / IMFS_MEMFILE_BLOCK_SLOTS;
900
901    p = info->doubly_indirect;
902    if ( malloc_it ) {
903
904      if ( !p ) {
905        p = memfile_alloc_block();
906        if ( !p )
907           return 0;
908        info->doubly_indirect = p;
909      }
910
911      p1 = (block_p *)p[ doubly ];
912      if ( !p1 ) {
913        p1 = memfile_alloc_block();
914        if ( !p1 )
915           return 0;
916        p[ doubly ] = (block_p) p1;
917      }
918
919      return (block_p *)&p1[ singly ];
920    }
921
922    if ( !p )
923      return 0;
924
925    p = (block_p *)p[ doubly ];
926    if ( !p )
927      return 0;
928
929#if 0
930printf( "(d %d %d %d %d %p %p) ", block, my_block, doubly,
931                                       singly, p, &p[singly] );
932fflush(stdout);
933#endif
934    return (block_p *)&p[ singly ];
935  }
936
937#if 0
938printf( "(t %d) ", block );
939fflush(stdout);
940#endif
941  /*
942   *  Is the block number in the triply indirect portion?
943   */
944
945  if ( my_block <= LAST_TRIPLY_INDIRECT ) {
946    my_block -= FIRST_TRIPLY_INDIRECT;
947
948    singly = my_block % IMFS_MEMFILE_BLOCK_SLOTS;
949    doubly = my_block / IMFS_MEMFILE_BLOCK_SLOTS;
950    triply = doubly / IMFS_MEMFILE_BLOCK_SLOTS;
951    doubly %= IMFS_MEMFILE_BLOCK_SLOTS;
952
953    p = info->triply_indirect;
954
955    if ( malloc_it ) {
956      if ( !p ) {
957        p = memfile_alloc_block();
958        if ( !p )
959           return 0;
960        info->triply_indirect = p;
961      }
962
963      p1 = (block_p *) p[ triply ];
964      if ( !p1 ) {
965        p1 = memfile_alloc_block();
966        if ( !p1 )
967           return 0;
968        p[ triply ] = (block_p) p1;
969      }
970
971      p2 = (block_p *)p1[ doubly ];
972      if ( !p2 ) {
973        p2 = memfile_alloc_block();
974        if ( !p2 )
975           return 0;
976        p1[ doubly ] = (block_p) p2;
977      }
978      return (block_p *)&p2[ singly ];
979    }
980
981    if ( !p )
982      return 0;
983
984#if 0
985printf( "(t %d %d %d %d %d) ", block, my_block, triply, doubly, singly );
986fflush(stdout);
987#endif
988    p1 = (block_p *) p[ triply ];
989    if ( !p1 )
990      return 0;
991
992    p2 = (block_p *)p1[ doubly ];
993    if ( !p )
994      return 0;
995
996    return (block_p *)&p2[ singly ];
997  }
998
999  /*
1000   *  This means the requested block number is out of range.
1001   */
1002
1003  return 0;
1004}
1005
1006/*
1007 *  memfile_alloc_block
1008 *
1009 *  Allocate a block for an in-memory file.
1010 */
1011
1012int memfile_blocks_allocated = 0;
1013
1014void *memfile_alloc_block(void)
1015{
1016  void *memory;
1017
1018  memory = (void *)calloc(1, IMFS_MEMFILE_BYTES_PER_BLOCK);
1019  if ( memory )
1020    memfile_blocks_allocated++;
1021
1022  return memory;
1023}
1024
1025/*
1026 *  memfile_free_block
1027 *
1028 *  Free a block from an in-memory file.
1029 */
1030
1031void memfile_free_block(
1032  void *memory
1033)
1034{
1035#if 0
1036printf( "(d %p) ", memory );
1037fflush(stdout);
1038#endif
1039  free(memory);
1040  memfile_blocks_allocated--;
1041}
1042
1043
1044/*
1045 *  memfile_rmnod
1046 *
1047 *  This routine is available from the optable to remove a node
1048 *  from the IMFS file system.
1049 */
1050
1051int memfile_rmnod(
1052  rtems_filesystem_location_info_t      *pathloc       /* IN */
1053)
1054{
1055  IMFS_jnode_t *the_jnode; 
1056
1057  the_jnode = (IMFS_jnode_t *) pathloc->node_access;
1058
1059  /*
1060   * Take the node out of the parent's chain that contains this node
1061   */
1062
1063  if ( the_jnode->Parent != NULL ) {
1064    Chain_Extract( (Chain_Node *) the_jnode );
1065    the_jnode->Parent = NULL;
1066  }
1067
1068  /*
1069   * Decrement the link counter and see if we can free the space.
1070   */
1071
1072  the_jnode->st_nlink--;
1073  IMFS_update_ctime( the_jnode );
1074
1075  /*
1076   * The file cannot be open and the link must be less than 1 to free.
1077   */
1078
1079  if ( !rtems_libio_is_file_open( the_jnode ) && (the_jnode->st_nlink < 1) ) {
1080
1081    /*
1082     * Is the rtems_filesystem_current is this node?
1083     */
1084
1085    if ( rtems_filesystem_current.node_access == pathloc->node_access )
1086       rtems_filesystem_current.node_access = NULL;
1087
1088    /*
1089     * Free memory associated with a memory file.
1090     */
1091
1092    IMFS_memfile_remove( the_jnode );
1093
1094    free( the_jnode );
1095  }
1096
1097  return 0;
1098
1099}
1100
1101
Note: See TracBrowser for help on using the repository browser.