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

4.104.114.84.95
Last change on this file since d32359a7 was d32359a7, checked in by Joel Sherrill <joel.sherrill@…>, on 09/14/02 at 21:01:39

2002-09-14 Joel Sherrill <joel@…>

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