source: trunk/minix/boot/rawfs.c@ 20

Last change on this file since 20 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

File size: 8.5 KB
Line 
1/* rawfs.c - Raw Minix file system support. Author: Kees J. Bot
2 * 23 Dec 1991
3 * Based on readfs by Paul Polderman
4 */
5#define nil 0
6#define _POSIX_SOURCE 1
7#define _MINIX 1
8#include <sys/types.h>
9#include <sys/stat.h>
10#include <stdlib.h>
11#include <limits.h>
12#include <string.h>
13#include <errno.h>
14#include <minix/config.h>
15#include <minix/const.h>
16#include <minix/type.h>
17#include <servers/fs/const.h>
18#include <servers/fs/type.h>
19#include <servers/fs/buf.h>
20#include <servers/fs/super.h>
21#include <servers/fs/inode.h>
22#include "rawfs.h"
23
24void readblock(off_t blockno, char *buf, int);
25
26/* The following code handles two file system types: Version 1 with small
27 * inodes and 16-bit disk addresses and Version 2 with big inodes and 32-bit
28 * disk addresses.
29#ifdef FLEX
30 * To make matters worse, Minix-vmd knows about the normal Unix Version 7
31 * directories and directories with flexible entries.
32#endif
33 */
34
35/* File system parameters. */
36static unsigned nr_dzones; /* Fill these in after reading superblock. */
37static unsigned nr_indirects;
38static unsigned inodes_per_block;
39static int block_size;
40#ifdef FLEX
41#include <dirent.h>
42#define direct _v7_direct
43#else
44#include <sys/dir.h>
45#endif
46
47#if __minix_vmd
48static struct v12_super_block super; /* Superblock of file system */
49#define s_log_zone_size s_dummy /* Zones are obsolete. */
50#else
51static struct super_block super; /* Superblock of file system */
52#define SUPER_V1 SUPER_MAGIC /* V1 magic has a weird name. */
53#endif
54
55static struct inode curfil; /* Inode of file under examination */
56static char indir[_MAX_BLOCK_SIZE]; /* Single indirect block. */
57static char dindir[_MAX_BLOCK_SIZE]; /* Double indirect block. */
58static char dirbuf[_MAX_BLOCK_SIZE]; /* Scratch/Directory block. */
59#define scratch dirbuf
60
61static block_t a_indir, a_dindir; /* Addresses of the indirects. */
62static off_t dirpos; /* Reading pos in a dir. */
63
64#define fsbuf(b) (* (struct buf *) (b))
65
66#define zone_shift (super.s_log_zone_size) /* zone to block ratio */
67
68off_t r_super(int *bs)
69/* Initialize variables, return size of file system in blocks,
70 * (zero on error).
71 */
72{
73 /* Read superblock. (The superblock is always at 1kB offset,
74 * that's why we lie to readblock and say the block size is 1024
75 * and we want block number 1 (the 'second block', at offset 1kB).)
76 */
77 readblock(1, scratch, 1024);
78
79 memcpy(&super, scratch, sizeof(super));
80
81 /* Is it really a MINIX file system ? */
82 if (super.s_magic == SUPER_V2 || super.s_magic == SUPER_V3) {
83 if(super.s_magic == SUPER_V2)
84 super.s_block_size = 1024;
85 *bs = block_size = super.s_block_size;
86 if(block_size < _MIN_BLOCK_SIZE ||
87 block_size > _MAX_BLOCK_SIZE) {
88 return 0;
89 }
90 nr_dzones= V2_NR_DZONES;
91 nr_indirects= V2_INDIRECTS(block_size);
92 inodes_per_block= V2_INODES_PER_BLOCK(block_size);
93 return (off_t) super.s_zones << zone_shift;
94 } else
95 if (super.s_magic == SUPER_V1) {
96 *bs = block_size = 1024;
97 nr_dzones= V1_NR_DZONES;
98 nr_indirects= V1_INDIRECTS;
99 inodes_per_block= V1_INODES_PER_BLOCK;
100 return (off_t) super.s_nzones << zone_shift;
101 } else {
102 /* Filesystem not recognized as Minix. */
103 return 0;
104 }
105}
106
107void r_stat(Ino_t inum, struct stat *stp)
108/* Return information about a file like stat(2) and remember it. */
109{
110 block_t block;
111 block_t ino_block;
112 ino_t ino_offset;
113
114 /* Calculate start of i-list */
115 block = START_BLOCK + super.s_imap_blocks + super.s_zmap_blocks;
116
117 /* Calculate block with inode inum */
118 ino_block = ((inum - 1) / inodes_per_block);
119 ino_offset = ((inum - 1) % inodes_per_block);
120 block += ino_block;
121
122 /* Fetch the block */
123 readblock(block, scratch, block_size);
124
125 if (super.s_magic == SUPER_V2 || super.s_magic == SUPER_V3) {
126 d2_inode *dip;
127 int i;
128
129 dip= &fsbuf(scratch).b_v2_ino[ino_offset];
130
131 curfil.i_mode= dip->d2_mode;
132 curfil.i_nlinks= dip->d2_nlinks;
133 curfil.i_uid= dip->d2_uid;
134 curfil.i_gid= dip->d2_gid;
135 curfil.i_size= dip->d2_size;
136 curfil.i_atime= dip->d2_atime;
137 curfil.i_mtime= dip->d2_mtime;
138 curfil.i_ctime= dip->d2_ctime;
139 for (i= 0; i < V2_NR_TZONES; i++)
140 curfil.i_zone[i]= dip->d2_zone[i];
141 } else {
142 d1_inode *dip;
143 int i;
144
145 dip= &fsbuf(scratch).b_v1_ino[ino_offset];
146
147 curfil.i_mode= dip->d1_mode;
148 curfil.i_nlinks= dip->d1_nlinks;
149 curfil.i_uid= dip->d1_uid;
150 curfil.i_gid= dip->d1_gid;
151 curfil.i_size= dip->d1_size;
152 curfil.i_atime= dip->d1_mtime;
153 curfil.i_mtime= dip->d1_mtime;
154 curfil.i_ctime= dip->d1_mtime;
155 for (i= 0; i < V1_NR_TZONES; i++)
156 curfil.i_zone[i]= dip->d1_zone[i];
157 }
158 curfil.i_dev= -1; /* Can't fill this in alas. */
159 curfil.i_num= inum;
160
161 stp->st_dev= curfil.i_dev;
162 stp->st_ino= curfil.i_num;
163 stp->st_mode= curfil.i_mode;
164 stp->st_nlink= curfil.i_nlinks;
165 stp->st_uid= curfil.i_uid;
166 stp->st_gid= curfil.i_gid;
167 stp->st_rdev= (dev_t) curfil.i_zone[0];
168 stp->st_size= curfil.i_size;
169 stp->st_atime= curfil.i_atime;
170 stp->st_mtime= curfil.i_mtime;
171 stp->st_ctime= curfil.i_ctime;
172
173 a_indir= a_dindir= 0;
174 dirpos= 0;
175}
176
177ino_t r_readdir(char *name)
178/* Read next directory entry at "dirpos" from file "curfil". */
179{
180 ino_t inum= 0;
181 int blkpos;
182 struct direct *dp;
183
184 if (!S_ISDIR(curfil.i_mode)) { errno= ENOTDIR; return -1; }
185
186 if(!block_size) { errno = 0; return -1; }
187
188 while (inum == 0 && dirpos < curfil.i_size) {
189 if ((blkpos= (int) (dirpos % block_size)) == 0) {
190 /* Need to fetch a new directory block. */
191
192 readblock(r_vir2abs(dirpos / block_size), dirbuf, block_size);
193 }
194#ifdef FLEX
195 if (super.s_flags & S_FLEX) {
196 struct _fl_direct *dp;
197
198 dp= (struct _fl_direct *) (dirbuf + blkpos);
199 if ((inum= dp->d_ino) != 0) strcpy(name, dp->d_name);
200
201 dirpos+= (1 + dp->d_extent) * FL_DIR_ENTRY_SIZE;
202 continue;
203 }
204#endif
205 /* Let dp point to the next entry. */
206 dp= (struct direct *) (dirbuf + blkpos);
207
208 if ((inum= dp->d_ino) != 0) {
209 /* This entry is occupied, return name. */
210 strncpy(name, dp->d_name, sizeof(dp->d_name));
211 name[sizeof(dp->d_name)]= 0;
212 }
213 dirpos+= DIR_ENTRY_SIZE;
214 }
215 return inum;
216}
217
218off_t r_vir2abs(off_t virblk)
219/* Translate a block number in a file to an absolute disk block number.
220 * Returns 0 for a hole and -1 if block is past end of file.
221 */
222{
223 block_t b= virblk;
224 zone_t zone, ind_zone;
225 block_t z, zone_index;
226 int i;
227
228 if(!block_size) return -1;
229
230 /* Check if virblk within file. */
231 if (virblk * block_size >= curfil.i_size) return -1;
232
233 /* Calculate zone in which the datablock number is contained */
234 zone = (zone_t) (b >> zone_shift);
235
236 /* Calculate index of the block number in the zone */
237 zone_index = b - ((block_t) zone << zone_shift);
238
239 /* Go get the zone */
240 if (zone < (zone_t) nr_dzones) { /* direct block */
241 zone = curfil.i_zone[(int) zone];
242 z = ((block_t) zone << zone_shift) + zone_index;
243 return z;
244 }
245
246 /* The zone is not a direct one */
247 zone -= (zone_t) nr_dzones;
248
249 /* Is it single indirect ? */
250 if (zone < (zone_t) nr_indirects) { /* single indirect block */
251 ind_zone = curfil.i_zone[nr_dzones];
252 } else { /* double indirect block */
253 /* Fetch the double indirect block */
254 if ((ind_zone = curfil.i_zone[nr_dzones + 1]) == 0) return 0;
255
256 z = (block_t) ind_zone << zone_shift;
257 if (a_dindir != z) {
258 readblock(z, dindir, block_size);
259 a_dindir= z;
260 }
261 /* Extract the indirect zone number from it */
262 zone -= (zone_t) nr_indirects;
263
264 i = zone / (zone_t) nr_indirects;
265 ind_zone = (super.s_magic == SUPER_V2 || super.s_magic == SUPER_V3)
266 ? fsbuf(dindir).b_v2_ind[i]
267 : fsbuf(dindir).b_v1_ind[i];
268 zone %= (zone_t) nr_indirects;
269 }
270 if (ind_zone == 0) return 0;
271
272 /* Extract the datablock number from the indirect zone */
273 z = (block_t) ind_zone << zone_shift;
274 if (a_indir != z) {
275 readblock(z, indir, block_size);
276 a_indir= z;
277 }
278 zone = (super.s_magic == SUPER_V2 || super.s_magic == SUPER_V3)
279 ? fsbuf(indir).b_v2_ind[(int) zone]
280 : fsbuf(indir).b_v1_ind[(int) zone];
281
282 /* Calculate absolute datablock number */
283 z = ((block_t) zone << zone_shift) + zone_index;
284 return z;
285}
286
287ino_t r_lookup(Ino_t cwd, char *path)
288/* Translates a pathname to an inode number. This is just a nice utility
289 * function, it only needs r_stat and r_readdir.
290 */
291{
292 char name[NAME_MAX+1], r_name[NAME_MAX+1];
293 char *n;
294 struct stat st;
295 ino_t ino;
296
297 ino= path[0] == '/' ? ROOT_INO : cwd;
298
299 for (;;) {
300 if (ino == 0) {
301 errno= ENOENT;
302 return 0;
303 }
304
305 while (*path == '/') path++;
306
307 if (*path == 0) return ino;
308
309 r_stat(ino, &st);
310
311 if (!S_ISDIR(st.st_mode)) {
312 errno= ENOTDIR;
313 return 0;
314 }
315
316 n= name;
317 while (*path != 0 && *path != '/')
318 if (n < name + NAME_MAX) *n++ = *path++;
319 *n= 0;
320
321 while ((ino= r_readdir(r_name)) != 0
322 && strcmp(name, r_name) != 0) {
323 }
324 }
325}
326
327/*
328 * $PchId: rawfs.c,v 1.8 1999/11/05 23:14:15 philip Exp $
329 */
Note: See TracBrowser for help on using the repository browser.