00001
00002
00003
00004
00005 #define nil 0
00006 #define _POSIX_SOURCE 1
00007 #define _MINIX 1
00008 #include <sys/types.h>
00009 #include <sys/stat.h>
00010 #include <stdlib.h>
00011 #include <limits.h>
00012 #include <string.h>
00013 #include <errno.h>
00014 #include <minix/config.h>
00015 #include <minix/const.h>
00016 #include <minix/type.h>
00017 #include <servers/fs/const.h>
00018 #include <servers/fs/type.h>
00019 #include <servers/fs/buf.h>
00020 #include <servers/fs/super.h>
00021 #include <servers/fs/inode.h>
00022 #include "rawfs.h"
00023
00024 void readblock(off_t blockno, char *buf, int);
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 static unsigned nr_dzones;
00037 static unsigned nr_indirects;
00038 static unsigned inodes_per_block;
00039 static int block_size;
00040 #ifdef FLEX
00041 #include <dirent.h>
00042 #define direct _v7_direct
00043 #else
00044 #include <sys/dir.h>
00045 #endif
00046
00047 #if __minix_vmd
00048 static struct v12_super_block super;
00049 #define s_log_zone_size s_dummy
00050 #else
00051 static struct super_block super;
00052 #define SUPER_V1 SUPER_MAGIC
00053 #endif
00054
00055 static struct inode curfil;
00056 static char indir[_MAX_BLOCK_SIZE];
00057 static char dindir[_MAX_BLOCK_SIZE];
00058 static char dirbuf[_MAX_BLOCK_SIZE];
00059 #define scratch dirbuf
00060
00061 static block_t a_indir, a_dindir;
00062 static off_t dirpos;
00063
00064 #define fsbuf(b) (* (struct buf *) (b))
00065
00066 #define zone_shift (super.s_log_zone_size)
00067
00068 off_t r_super(int *bs)
00069
00070
00071
00072 {
00073
00074
00075
00076
00077 readblock(1, scratch, 1024);
00078
00079 memcpy(&super, scratch, sizeof(super));
00080
00081
00082 if (super.s_magic == SUPER_V2 || super.s_magic == SUPER_V3) {
00083 if(super.s_magic == SUPER_V2)
00084 super.s_block_size = 1024;
00085 *bs = block_size = super.s_block_size;
00086 if(block_size < _MIN_BLOCK_SIZE ||
00087 block_size > _MAX_BLOCK_SIZE) {
00088 return 0;
00089 }
00090 nr_dzones= V2_NR_DZONES;
00091 nr_indirects= V2_INDIRECTS(block_size);
00092 inodes_per_block= V2_INODES_PER_BLOCK(block_size);
00093 return (off_t) super.s_zones << zone_shift;
00094 } else
00095 if (super.s_magic == SUPER_V1) {
00096 *bs = block_size = 1024;
00097 nr_dzones= V1_NR_DZONES;
00098 nr_indirects= V1_INDIRECTS;
00099 inodes_per_block= V1_INODES_PER_BLOCK;
00100 return (off_t) super.s_nzones << zone_shift;
00101 } else {
00102
00103 return 0;
00104 }
00105 }
00106
00107 void r_stat(Ino_t inum, struct stat *stp)
00108
00109 {
00110 block_t block;
00111 block_t ino_block;
00112 ino_t ino_offset;
00113
00114
00115 block = START_BLOCK + super.s_imap_blocks + super.s_zmap_blocks;
00116
00117
00118 ino_block = ((inum - 1) / inodes_per_block);
00119 ino_offset = ((inum - 1) % inodes_per_block);
00120 block += ino_block;
00121
00122
00123 readblock(block, scratch, block_size);
00124
00125 if (super.s_magic == SUPER_V2 || super.s_magic == SUPER_V3) {
00126 d2_inode *dip;
00127 int i;
00128
00129 dip= &fsbuf(scratch).b_v2_ino[ino_offset];
00130
00131 curfil.i_mode= dip->d2_mode;
00132 curfil.i_nlinks= dip->d2_nlinks;
00133 curfil.i_uid= dip->d2_uid;
00134 curfil.i_gid= dip->d2_gid;
00135 curfil.i_size= dip->d2_size;
00136 curfil.i_atime= dip->d2_atime;
00137 curfil.i_mtime= dip->d2_mtime;
00138 curfil.i_ctime= dip->d2_ctime;
00139 for (i= 0; i < V2_NR_TZONES; i++)
00140 curfil.i_zone[i]= dip->d2_zone[i];
00141 } else {
00142 d1_inode *dip;
00143 int i;
00144
00145 dip= &fsbuf(scratch).b_v1_ino[ino_offset];
00146
00147 curfil.i_mode= dip->d1_mode;
00148 curfil.i_nlinks= dip->d1_nlinks;
00149 curfil.i_uid= dip->d1_uid;
00150 curfil.i_gid= dip->d1_gid;
00151 curfil.i_size= dip->d1_size;
00152 curfil.i_atime= dip->d1_mtime;
00153 curfil.i_mtime= dip->d1_mtime;
00154 curfil.i_ctime= dip->d1_mtime;
00155 for (i= 0; i < V1_NR_TZONES; i++)
00156 curfil.i_zone[i]= dip->d1_zone[i];
00157 }
00158 curfil.i_dev= -1;
00159 curfil.i_num= inum;
00160
00161 stp->st_dev= curfil.i_dev;
00162 stp->st_ino= curfil.i_num;
00163 stp->st_mode= curfil.i_mode;
00164 stp->st_nlink= curfil.i_nlinks;
00165 stp->st_uid= curfil.i_uid;
00166 stp->st_gid= curfil.i_gid;
00167 stp->st_rdev= (dev_t) curfil.i_zone[0];
00168 stp->st_size= curfil.i_size;
00169 stp->st_atime= curfil.i_atime;
00170 stp->st_mtime= curfil.i_mtime;
00171 stp->st_ctime= curfil.i_ctime;
00172
00173 a_indir= a_dindir= 0;
00174 dirpos= 0;
00175 }
00176
00177 ino_t r_readdir(char *name)
00178
00179 {
00180 ino_t inum= 0;
00181 int blkpos;
00182 struct direct *dp;
00183
00184 if (!S_ISDIR(curfil.i_mode)) { errno= ENOTDIR; return -1; }
00185
00186 if(!block_size) { errno = 0; return -1; }
00187
00188 while (inum == 0 && dirpos < curfil.i_size) {
00189 if ((blkpos= (int) (dirpos % block_size)) == 0) {
00190
00191
00192 readblock(r_vir2abs(dirpos / block_size), dirbuf, block_size);
00193 }
00194 #ifdef FLEX
00195 if (super.s_flags & S_FLEX) {
00196 struct _fl_direct *dp;
00197
00198 dp= (struct _fl_direct *) (dirbuf + blkpos);
00199 if ((inum= dp->d_ino) != 0) strcpy(name, dp->d_name);
00200
00201 dirpos+= (1 + dp->d_extent) * FL_DIR_ENTRY_SIZE;
00202 continue;
00203 }
00204 #endif
00205
00206 dp= (struct direct *) (dirbuf + blkpos);
00207
00208 if ((inum= dp->d_ino) != 0) {
00209
00210 strncpy(name, dp->d_name, sizeof(dp->d_name));
00211 name[sizeof(dp->d_name)]= 0;
00212 }
00213 dirpos+= DIR_ENTRY_SIZE;
00214 }
00215 return inum;
00216 }
00217
00218 off_t r_vir2abs(off_t virblk)
00219
00220
00221
00222 {
00223 block_t b= virblk;
00224 zone_t zone, ind_zone;
00225 block_t z, zone_index;
00226 int i;
00227
00228 if(!block_size) return -1;
00229
00230
00231 if (virblk * block_size >= curfil.i_size) return -1;
00232
00233
00234 zone = (zone_t) (b >> zone_shift);
00235
00236
00237 zone_index = b - ((block_t) zone << zone_shift);
00238
00239
00240 if (zone < (zone_t) nr_dzones) {
00241 zone = curfil.i_zone[(int) zone];
00242 z = ((block_t) zone << zone_shift) + zone_index;
00243 return z;
00244 }
00245
00246
00247 zone -= (zone_t) nr_dzones;
00248
00249
00250 if (zone < (zone_t) nr_indirects) {
00251 ind_zone = curfil.i_zone[nr_dzones];
00252 } else {
00253
00254 if ((ind_zone = curfil.i_zone[nr_dzones + 1]) == 0) return 0;
00255
00256 z = (block_t) ind_zone << zone_shift;
00257 if (a_dindir != z) {
00258 readblock(z, dindir, block_size);
00259 a_dindir= z;
00260 }
00261
00262 zone -= (zone_t) nr_indirects;
00263
00264 i = zone / (zone_t) nr_indirects;
00265 ind_zone = (super.s_magic == SUPER_V2 || super.s_magic == SUPER_V3)
00266 ? fsbuf(dindir).b_v2_ind[i]
00267 : fsbuf(dindir).b_v1_ind[i];
00268 zone %= (zone_t) nr_indirects;
00269 }
00270 if (ind_zone == 0) return 0;
00271
00272
00273 z = (block_t) ind_zone << zone_shift;
00274 if (a_indir != z) {
00275 readblock(z, indir, block_size);
00276 a_indir= z;
00277 }
00278 zone = (super.s_magic == SUPER_V2 || super.s_magic == SUPER_V3)
00279 ? fsbuf(indir).b_v2_ind[(int) zone]
00280 : fsbuf(indir).b_v1_ind[(int) zone];
00281
00282
00283 z = ((block_t) zone << zone_shift) + zone_index;
00284 return z;
00285 }
00286
00287 ino_t r_lookup(Ino_t cwd, char *path)
00288
00289
00290
00291 {
00292 char name[NAME_MAX+1], r_name[NAME_MAX+1];
00293 char *n;
00294 struct stat st;
00295 ino_t ino;
00296
00297 ino= path[0] == '/' ? ROOT_INO : cwd;
00298
00299 for (;;) {
00300 if (ino == 0) {
00301 errno= ENOENT;
00302 return 0;
00303 }
00304
00305 while (*path == '/') path++;
00306
00307 if (*path == 0) return ino;
00308
00309 r_stat(ino, &st);
00310
00311 if (!S_ISDIR(st.st_mode)) {
00312 errno= ENOTDIR;
00313 return 0;
00314 }
00315
00316 n= name;
00317 while (*path != 0 && *path != '/')
00318 if (n < name + NAME_MAX) *n++ = *path++;
00319 *n= 0;
00320
00321 while ((ino= r_readdir(r_name)) != 0
00322 && strcmp(name, r_name) != 0) {
00323 }
00324 }
00325 }
00326
00327
00328
00329