1 /****************************************************************/
5 /* Reading and writing to a file system device. */
7 /****************************************************************/
8 /* origination 1989-Jan-15 Terrence W. Holm */
9 /****************************************************************/
12 #include <minix/config.h>
13 #include <sys/types.h>
19 #include <minix/const.h>
20 #include <minix/type.h>
21 #include "mfs/const.h"
23 #include "mfs/super.h"
24 #include "mfs/inode.h"
25 #include <minix/fslib.h>
32 /****************************************************************/
34 /* Read_Disk( state, block_addr, buffer ) */
36 /* Reads a 1k block at "block_addr" into "buffer". */
38 /****************************************************************/
41 void Read_Disk( s
, block_addr
, buffer
)
47 if ( lseek( s
->device_d
, block_addr
, SEEK_SET
) == -1 )
48 Error( "Error seeking %s", s
->device_name
);
50 if ( read( s
->device_d
, buffer
, s
->block_size
) != s
->block_size
)
51 Error( "Error reading %s", s
->device_name
);
59 /****************************************************************/
61 /* Read_Block( state, buffer ) */
63 /* Reads a 1k block from "state->address" into */
64 /* "buffer". Checks "address", and updates */
65 /* "block" and "offset". */
67 /****************************************************************/
70 void Read_Block( s
, buffer
)
77 end_addr
= (long) s
->device_size
* s
->block_size
- 1;
82 if ( s
->address
> end_addr
)
83 s
->address
= end_addr
;
85 /* The address must be rounded off for */
86 /* certain visual display modes. */
88 if ( s
->mode
== WORD
)
90 else if ( s
->mode
== MAP
)
94 block_addr
= s
->address
& K_MASK
;
96 s
->block
= (zone_t
) (block_addr
>> K_SHIFT
);
97 s
->offset
= (unsigned) (s
->address
- block_addr
);
99 Read_Disk( s
, block_addr
, buffer
);
107 /****************************************************************/
109 /* Read_Super_Block( state ) */
111 /* Read and check the super block. */
113 /****************************************************************/
116 void Read_Super_Block( s
)
120 struct super_block
*super
= (struct super_block
*) s
->buffer
;
121 unsigned inodes_per_block
;
125 Read_Disk( s
, (long) SUPER_BLOCK_BYTES
, s
->buffer
);
127 s
->magic
= super
->s_magic
;
128 if ( s
->magic
== SUPER_MAGIC
)
132 s
->inode_size
= V1_INODE_SIZE
;
133 inodes_per_block
= V1_INODES_PER_BLOCK
;
134 s
->nr_indirects
= V1_INDIRECTS
;
135 s
->zone_num_size
= V1_ZONE_NUM_SIZE
;
136 s
->zones
= super
->s_nzones
;
137 s
->ndzones
= V1_NR_DZONES
;
138 s
->block_size
= _STATIC_BLOCK_SIZE
;
140 else if ( s
->magic
== SUPER_V2
|| s
->magic
== SUPER_V3
)
142 if(s
->magic
== SUPER_V3
)
143 s
->block_size
= super
->s_block_size
;
145 s
->block_size
= _STATIC_BLOCK_SIZE
;
148 s
->inode_size
= V2_INODE_SIZE
;
149 inodes_per_block
= V2_INODES_PER_BLOCK(s
->block_size
);
150 s
->nr_indirects
= V2_INDIRECTS(s
->block_size
);
151 s
->zone_num_size
= V2_ZONE_NUM_SIZE
;
152 s
->zones
= super
->s_zones
;
153 s
->ndzones
= V2_NR_DZONES
;
157 if ( super
->s_magic
== SUPER_REV
)
158 Warning( "V1-bytes-swapped file system (?)" );
159 else if ( super
->s_magic
== SUPER_V2_REV
)
160 Warning( "V2-bytes-swapped file system (?)" );
162 Warning( "Not a Minix file system" );
163 Warning( "The file system features will not be available" );
168 s
->inodes
= super
->s_ninodes
;
169 s
->inode_maps
= bitmapsize( (bit_t
) s
->inodes
+ 1 , s
->block_size
);
170 if ( s
->inode_maps
!= super
->s_imap_blocks
)
172 if ( s
->inode_maps
> super
->s_imap_blocks
)
173 Error( "Corrupted inode map count or inode count in super block" );
175 Warning( "Count of inode map blocks in super block suspiciously high" );
176 s
->inode_maps
= super
->s_imap_blocks
;
179 s
->zone_maps
= bitmapsize( (bit_t
) s
->zones
, s
->block_size
);
180 if ( s
->zone_maps
!= super
->s_zmap_blocks
)
182 if ( s
->zone_maps
> super
->s_zmap_blocks
)
183 Error( "Corrupted zone map count or zone count in super block" );
185 Warning( "Count of zone map blocks in super block suspiciously high" );
186 s
->zone_maps
= super
->s_zmap_blocks
;
189 s
->inode_blocks
= (s
->inodes
+ inodes_per_block
- 1) / inodes_per_block
;
190 s
->first_data
= 2 + s
->inode_maps
+ s
->zone_maps
+ s
->inode_blocks
;
191 if ( super
->s_firstdatazone_old
!= 0 &&
192 s
->first_data
!= super
->s_firstdatazone_old
)
194 if ( s
->first_data
> super
->s_firstdatazone_old
)
195 Error( "Corrupted first data zone offset or inode count in super block" );
197 Warning( "First data zone in super block suspiciously high" );
198 s
->first_data
= super
->s_firstdatazone_old
;
201 s
->inodes_in_map
= s
->inodes
+ 1;
202 s
->zones_in_map
= s
->zones
+ 1 - s
->first_data
;
205 if ( s->zones != s->device_size )
206 Warning( "Zone count does not equal device size" );
209 s
->device_size
= s
->zones
;
211 if ( super
->s_log_zone_size
!= 0 )
212 Error( "Can not handle multiple blocks per zone" );
220 /****************************************************************/
222 /* Read_Bit_Maps( state ) */
224 /* Read in the i-node and zone bit maps from the */
225 /* specified file system device. */
227 /****************************************************************/
230 void Read_Bit_Maps( s
)
236 if ( s
->inode_maps
> I_MAP_SLOTS
|| s
->zone_maps
> Z_MAP_SLOTS
)
238 Warning( "Super block specifies too many bit map blocks" );
242 for ( i
= 0; i
< s
->inode_maps
; ++i
)
244 Read_Disk( s
, (long) (2 + i
) * K
,
245 (char *) &s
->inode_map
[ i
* K
/ sizeof (bitchunk_t
) ] );
248 for ( i
= 0; i
< s
->zone_maps
; ++i
)
250 Read_Disk( s
, (long) (2 + s
->inode_maps
+ i
) * K
,
251 (char *) &s
->zone_map
[ i
* K
/ sizeof (bitchunk_t
) ] );
260 /****************************************************************/
262 /* Search( state, string ) */
264 /* Search from the current address for the ASCII */
265 /* "string" on the device. */
267 /****************************************************************/
270 off_t
Search( s
, string
)
275 off_t address
= s
->address
+ 1;
276 off_t last_addr
= address
;
277 char buffer
[ SEARCH_BUFFER
];
279 int tail_length
= strlen( string
) - 1;
280 int count
= SEARCH_BUFFER
;
284 for ( ; count
== SEARCH_BUFFER
; address
+= SEARCH_BUFFER
- tail_length
)
286 if ( lseek( s
->device_d
, address
, SEEK_SET
) == -1 )
287 Error( "Error seeking %s", s
->device_name
);
289 if ( (count
= read( s
->device_d
, buffer
, SEARCH_BUFFER
)) == -1 )
290 Error( "Error reading %s", s
->device_name
);
293 if ( address
- last_addr
>= 500L * K
)
298 last_addr
+= 500L * K
;
302 last_offset
= count
- tail_length
;
304 for ( offset
= 0; offset
< last_offset
; ++offset
)
306 register char c
= buffer
[ offset
];
310 char *tail_buffer
= &buffer
[ offset
+ 1 ];
311 char *tail_string
= string
+ 1;
315 if ( *tail_string
== '\0' )
316 return( address
+ offset
);
318 while ( *tail_buffer
++ == *tail_string
++ );
320 } /* end for ( offset ) */
321 } /* end for ( address ) */
331 /****************************************************************/
333 /* Write_Word( state, word ) */
335 /* Write a word at address. */
337 /****************************************************************/
340 void Write_Word( s
, word
)
345 if ( s
->address
& 01 )
346 Error( "Internal fault (unaligned address)" );
348 if ( lseek( s
->device_d
, s
->address
, SEEK_SET
) == -1 )
349 Error( "Error seeking %s", s
->device_name
);
351 if ( write( s
->device_d
, (char *) &word
, sizeof word
) != sizeof word
)
352 Error( "Error writing %s", s
->device_name
);