OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rtems-20020807/] [cpukit/] [libfs/] [src/] [imfs/] [memfile.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1026 ivang
/*
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
 *  memfile.c,v 1.17 2002/04/08 18:28:59 joel Exp
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
 
41
MEMFILE_STATIC int IMFS_memfile_extend(
42
   IMFS_jnode_t  *the_jnode,
43
   off_t          new_length
44
);
45
 
46
MEMFILE_STATIC int IMFS_memfile_addblock(
47
   IMFS_jnode_t  *the_jnode,
48
   unsigned int   block
49
);
50
 
51
MEMFILE_STATIC int IMFS_memfile_remove_block(
52
   IMFS_jnode_t  *the_jnode,
53
   unsigned int   block
54
);
55
 
56
MEMFILE_STATIC block_p *IMFS_memfile_get_block_pointer(
57
   IMFS_jnode_t   *the_jnode,
58
   unsigned int    block,
59
   int             malloc_it
60
);
61
 
62
MEMFILE_STATIC int IMFS_memfile_read(
63
   IMFS_jnode_t    *the_jnode,
64
   off_t            start,
65
   unsigned char   *destination,
66
   unsigned int     length
67
);
68
 
69
MEMFILE_STATIC int IMFS_memfile_write(
70
   IMFS_jnode_t          *the_jnode,
71
   off_t                  start,
72
   const unsigned char   *source,
73
   unsigned int           length
74
);
75
 
76
void *memfile_alloc_block(void);
77
 
78
void 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
 
89
int 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
 
114
int 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
 
134
int 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
 
153
int memfile_write(
154
  rtems_libio_t *iop,
155
  const void    *buffer,
156
  unsigned32     count
157
)
158
{
159
  IMFS_jnode_t   *the_jnode;
160
  int             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
 
178
int 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
 
197
int 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
 
232
int 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
 
272
MEMFILE_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
 
333
MEMFILE_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
 
377
MEMFILE_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
 
401
void 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
 
458
int 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
 
544
MEMFILE_STATIC int 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
 
694
MEMFILE_STATIC int 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
778
printf( "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
798
printf( "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
820
printf( "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
841
block_p *IMFS_memfile_get_block_pointer_DEBUG(
842
   IMFS_jnode_t   *the_jnode,
843
   unsigned int    block,
844
   int             malloc_it
845
);
846
 
847
block_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
 
860
block_p *IMFS_memfile_get_block_pointer_DEBUG(
861
#else
862
block_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
900
printf( "(s %d) ", block );
901
fflush(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
928
printf( "(d %d) ", block );
929
fflush(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
966
printf( "(d %d %d %d %d %p %p) ", block, my_block, doubly,
967
                                       singly, p, &p[singly] );
968
fflush(stdout);
969
#endif
970
    return (block_p *)&p[ singly ];
971
  }
972
 
973
#if 0
974
printf( "(t %d) ", block );
975
fflush(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
1021
printf( "(t %d %d %d %d %d) ", block, my_block, triply, doubly, singly );
1022
fflush(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
 
1048
int memfile_blocks_allocated = 0;
1049
 
1050
void *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
 
1067
void memfile_free_block(
1068
  void *memory
1069
)
1070
{
1071
#if 0
1072
printf( "(d %p) ", memory );
1073
fflush(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
 
1087
int 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
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.