source: rtems/c/src/exec/libfs/src/imfs/memfile.c @ d1941587

4.104.114.84.95
Last change on this file since d1941587 was d1941587, checked in by Joel Sherrill <joel.sherrill@…>, on 01/12/01 at 13:44:12

2001-01-12 Jake Janovetz <janovetz@…>

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