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

4.104.114.84.95
Last change on this file since b2709481 was b2709481, checked in by Joel Sherrill <joel.sherrill@…>, on 01/04/02 at 18:30:58

2002-01-04 Ralf Corsepius <corsepiu@…>

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