00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <sys/types.h>
00023 #include <sys/stat.h>
00024 #include <minix/config.h>
00025 #include <minix/type.h>
00026 #include <fcntl.h>
00027 #include <unistd.h>
00028 #include <dirent.h>
00029 #include <stdlib.h>
00030
00031 #include "../../servers/fs/const.h"
00032 #undef printf
00033 #include "../../servers/fs/type.h"
00034
00035 #include <string.h>
00036 #include <stdio.h>
00037
00038 #define EXTERN extern
00039 #include "../../servers/fs/super.h"
00040
00041 _PROTOTYPE(int main, (int argc, char **argv));
00042 _PROTOTYPE(void rw_super, (int flag));
00043 _PROTOTYPE(void get_super, (void));
00044 _PROTOTYPE(void put_super, (void));
00045 _PROTOTYPE(void rw_inode, (struct stat * stat_ptr, int rw_mode));
00046 _PROTOTYPE(void get_inode, (struct stat * stat_ptr));
00047 _PROTOTYPE(void put_inode, (struct stat * stat_ptr));
00048 _PROTOTYPE(long rd_cmdline, (int argc, char *argv[]));
00049 _PROTOTYPE(void modify, (int nr_blocks));
00050 _PROTOTYPE(void save_blk, (block_t blk_num));
00051 _PROTOTYPE(void reset_blks, (void));
00052 _PROTOTYPE(void show_blks, (void));
00053 _PROTOTYPE(int blk_is_used, (block_t blk_num));
00054 _PROTOTYPE(int blk_ok, (block_t num));
00055 _PROTOTYPE(void set_bit, (zone_t num));
00056 _PROTOTYPE(long rd_num, (void));
00057 _PROTOTYPE(int ok, (char *str));
00058 _PROTOTYPE(void done, (int nr));
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075 #define OK 0
00076 #define NOT_OK 1
00077 #define QUIT 2
00078
00079 #define READ 0
00080 #define WRITE 1
00081
00082 #define HARMLESS 0
00083 #define DIR_CREATED 1
00084 #define DEV_MOUNTED 2
00085 #define FILE_EXISTS 3
00086 #define SUCCESS 4
00087
00088 #define BYTE 0377
00089 #define BLOCK_SIZE 1024
00090 #define SIZE_OF_INT (sizeof (int) )
00091
00092
00093 #if (V1_NR_DZONES > V2_NR_DZONES)
00094 #define V_NR_DZONES V1_NR_DZONES
00095 #define V_SMALLER V2_NR_DZONES
00096 #else
00097 #define V_NR_DZONES V2_NR_DZONES
00098 #define V_SMALLER V1_NR_DZONES
00099 #endif
00100
00101 #if 0
00102 struct super_block {
00103 ino_t s_ninodes;
00104 zone1_t s_nzones;
00105 short s_imap_blocks;
00106 short s_zmap_blocks;
00107 zone1_t s_firstdatazone;
00108 short s_log_zone_size;
00109 off_t s_max_size;
00110 short s_magic;
00111 short s_pad;
00112 zone_t s_zones;
00113 } super_block;
00114 #endif
00115
00116
00117
00118 char *dev_name;
00119 char f_name[] = ".Bad_XXXXXX";
00120 char file_name[50];
00121 char dir_name[] = "/tmpXXXXXX";
00122
00123 block_t block[V_NR_DZONES + 1];
00124 int interactive;
00125 int position = 2;
00126
00127 FILE *f;
00128 int fd;
00129 int eofseen;
00130 struct stat stat_buf;
00131 struct super_block *sp, sbs;
00132 int inodes_per_block;
00133 size_t inode_size;
00134 int v1fs = 0, v2fs = 0;
00135
00136 d1_inode d1inode;
00137 d1_inode *ip1;
00138 d2_inode d2inode;
00139 d2_inode *ip2;
00140
00141
00142
00143
00144 void rw_super(flag)
00145 int flag;
00146 {
00147 int rwd;
00148
00149 lseek(fd, 0L, SEEK_SET);
00150 lseek(fd, (long) BLOCK_SIZE, SEEK_SET);
00151
00152 if (flag == READ)
00153 rwd = read(fd, (char *) sp, SUPER_SIZE);
00154 else
00155 rwd = write(fd, (char *) sp, SUPER_SIZE);
00156 if (rwd != SUPER_SIZE) {
00157 printf("Bad %s in get_super() (should be %u is %d)\n",
00158 flag == READ ? "read" : "write",
00159 (unsigned) SUPER_SIZE, rwd);
00160 done(DIR_CREATED);
00161 }
00162 }
00163
00164 void get_super()
00165
00166 {
00167 rw_super(READ);
00168
00169 if (sp->s_magic == SUPER_MAGIC) {
00170
00171 v1fs = 1;
00172 } else if (sp->s_magic == SUPER_V2) {
00173
00174 v2fs = 1;
00175 } else if (sp->s_magic == SUPER_V3) {
00176 v1fs = v2fs = 0;
00177 } else {
00178
00179 printf("Bad magic number in super_block (0x%x)\n",
00180 (unsigned) sp->s_magic);
00181 done(DIR_CREATED);
00182 }
00183 }
00184
00185
00186 void put_super()
00187 {
00188 rw_super(WRITE);
00189 }
00190
00191
00192
00193 void rw_inode(stat_ptr, rw_mode)
00194 struct stat *stat_ptr;
00195 int rw_mode;
00196 {
00197 int rwd;
00198 ino_t i_num;
00199 block_t blk, offset;
00200
00201
00202 i_num = stat_ptr->st_ino;
00203
00204 blk = (block_t) (2 + sp->s_imap_blocks + sp->s_zmap_blocks);
00205 blk += (block_t) ((i_num - 1) / inodes_per_block);
00206 blk *= (block_t) (BLOCK_SIZE);
00207
00208 offset = (block_t) ((i_num - 1) % inodes_per_block);
00209 offset *= (block_t) (inode_size);
00210
00211 lseek(fd, (off_t) 0, SEEK_SET);
00212 lseek(fd, (off_t) (blk + offset), SEEK_SET);
00213
00214
00215 if (v1fs) {
00216
00217 if (rw_mode == READ) {
00218 rwd = read(fd, (char *) ip1, inode_size);
00219 } else {
00220 rwd = write(fd, (char *) ip1, inode_size);
00221 }
00222 } else {
00223
00224 if (rw_mode == READ) {
00225 rwd = read(fd, (char *) ip2, inode_size);
00226 } else {
00227 rwd = write(fd, (char *) ip2, inode_size);
00228 }
00229 }
00230
00231 if (rwd != inode_size) {
00232 printf("Bad %s in get_inode()\n", (rw_mode == READ) ? "read" :
00233 "write");
00234 done(DIR_CREATED);
00235 }
00236 }
00237
00238 void get_inode(stat_ptr)
00239 struct stat *stat_ptr;
00240 {
00241
00242 int cnt;
00243
00244 rw_inode(stat_ptr, READ);
00245
00246 if (v1fs) {
00247 for (cnt = 0; cnt < V1_NR_TZONES; cnt++)
00248 ip1->d1_zone[cnt] = 0;
00249 } else {
00250 for (cnt = 0; cnt < V2_NR_TZONES; cnt++)
00251 ip2->d2_zone[cnt] = 0;
00252 }
00253 }
00254
00255 void put_inode(stat_ptr)
00256 struct stat *stat_ptr;
00257 {
00258 rw_inode(stat_ptr, WRITE);
00259 }
00260
00261
00262
00263 int main(argc, argv)
00264 int argc;
00265 char *argv[];
00266 {
00267 int cnt, finished;
00268 block_t blk_nr;
00269 struct stat dev_stat;
00270 FILE *fp;
00271 int block_size;
00272
00273 sp = &sbs;
00274 ip1 = &d1inode;
00275 ip2 = &d2inode;
00276
00277 if (argc < 2 || argc > 9) {
00278 fprintf(stderr, "Usage: %s block_special [up_to_7_blocks]\n", argv[0]);
00279 done(HARMLESS);
00280 }
00281 interactive = (argc == 2 ? 1 : 0);
00282
00283
00284 if (geteuid()) {
00285 printf("Sorry, not in superuser mode \n");
00286 printf("Set_uid bit must be on or you must become super_user\n");
00287 done(HARMLESS);
00288 }
00289 dev_name = argv[1];
00290 mktemp(dir_name);
00291 if (mkdir(dir_name, 0777) == -1) {
00292 fprintf(stderr, "%s is already used in system\n", dir_name);
00293 done(HARMLESS);
00294 }
00295
00296
00297 mount(dev_name, dir_name, 0);
00298
00299
00300
00301
00302 if (umount(dev_name) == -1) {
00303 printf("Could not umount device %s.\n", dev_name);
00304 done(HARMLESS);
00305 }
00306 mktemp(f_name);
00307
00308 strcat(file_name, dir_name);
00309 strcat(file_name, "/");
00310 strcat(file_name, f_name);
00311
00312 if (mount(dev_name, dir_name, 0) == -1) {
00313 fprintf(stderr, "Could not mount device anymore\n");
00314 done(HARMLESS);
00315 }
00316 if (stat(file_name, &stat_buf) != -1) {
00317 printf("File %s already exists\n", file_name);
00318 done(DEV_MOUNTED);
00319 }
00320 if ((fp = fopen(file_name, "w")) == NULL) {
00321 printf("Cannot create file %s\n", file_name);
00322 done(DEV_MOUNTED);
00323 }
00324 chmod(file_name, 0);
00325 if (stat(file_name, &stat_buf) == -1) {
00326 printf("What? Second call from stat failed\n");
00327 done(FILE_EXISTS);
00328 }
00329
00330
00331 fclose(fp);
00332
00333
00334
00335 if (umount(dev_name) == -1) {
00336 printf("Can not umount device anymore??? \n");
00337 done(DIR_CREATED);
00338 }
00339 if ((fd = open(dev_name, O_RDWR)) == -1) {
00340 printf("Can not open device %s\n", dev_name);
00341 done(DEV_MOUNTED);
00342 }
00343 if (fstat(fd, &dev_stat) == -1) {
00344 printf("fstat on device %s failed\n", dev_name);
00345 done(DEV_MOUNTED);
00346 }
00347 if ((dev_stat.st_mode & S_IFMT) != S_IFBLK) {
00348 printf("Device \"%s\" is not a block_special.\n", dev_name);
00349 done(DEV_MOUNTED);
00350 }
00351 get_super();
00352 if (sp->s_log_zone_size) {
00353 printf("Block_size != zone_size.");
00354 printf("This program can not handle it\n");
00355 done(DIR_CREATED);
00356 }
00357 if(v1fs || v2fs) block_size = 1024;
00358 else block_size = sp->s_block_size;
00359
00360
00361 if (v1fs) {
00362 inodes_per_block = V1_INODES_PER_BLOCK;
00363 inode_size = V1_INODE_SIZE;
00364 } else {
00365 inodes_per_block = V2_INODES_PER_BLOCK(block_size);
00366 inode_size = V2_INODE_SIZE;
00367 }
00368
00369 get_inode(&stat_buf);
00370
00371 for (finished = 0; !finished;) {
00372 if (interactive)
00373 printf("Give up to %d bad block numbers separated by spaces\n",
00374 V_SMALLER);
00375 reset_blks();
00376 cnt = 0;
00377 while (cnt < V_SMALLER) {
00378 int tst;
00379
00380 if (interactive)
00381 blk_nr = rd_num();
00382 else
00383 blk_nr = rd_cmdline(argc, argv);
00384 if (blk_nr == -1) break;
00385 tst = blk_ok(blk_nr);
00386
00387
00388 if (tst == OK) {
00389 cnt++;
00390 save_blk(blk_nr);
00391 } else if (tst == QUIT)
00392 break;
00393 }
00394 if (interactive) show_blks();
00395 if (!cnt) done(FILE_EXISTS);
00396 if (interactive) {
00397 switch (ok("All these blocks ok <y/n/q> (y:Device will change) ")) {
00398 case OK: finished = 1; break;
00399 case NOT_OK:
00400 break;
00401 case QUIT: done(FILE_EXISTS);
00402 }
00403 } else {
00404 finished = 1;
00405 }
00406 }
00407
00408 modify(cnt);
00409 close(fd);
00410 done(SUCCESS);
00411 return(0);
00412 }
00413
00414 long rd_cmdline(argc, argv)
00415 int argc;
00416 char *argv[];
00417 {
00418 if (position == argc) return(-1);
00419 return(atol(argv[position++]));
00420 }
00421
00422
00423 void modify(nr_blocks)
00424 int nr_blocks;
00425 {
00426 int i;
00427
00428 if (nr_blocks == 0) return;
00429 if (v1fs) {
00430
00431 for (i = 0; i < nr_blocks; i++) {
00432 set_bit(block[i]);
00433 ip1->d1_zone[i] = block[i];
00434 }
00435 } else {
00436
00437 for (i = 0; i < nr_blocks; i++) {
00438 set_bit(block[i]);
00439 ip2->d2_zone[i] = block[i];
00440 }
00441 }
00442 if (v1fs) {
00443 ip1->d1_size = (long) (BLOCK_SIZE * nr_blocks);
00444 ip1->d1_mtime = 0;
00445 } else {
00446 ip2->d2_size = (long) (BLOCK_SIZE * nr_blocks);
00447 ip2->d2_atime = ip2->d2_mtime = ip2->d2_ctime = 0;
00448 }
00449
00450 put_inode(&stat_buf);
00451 put_super();
00452 }
00453
00454
00455 static blk_cnt = 0;
00456
00457 void save_blk(blk_num)
00458 block_t blk_num;
00459 {
00460 block[blk_cnt++] = blk_num;
00461 }
00462
00463 void reset_blks()
00464 {
00465 int i;
00466
00467 for (i = 0; i <= V_NR_DZONES; i++)
00468 block[i] = 0;
00469 blk_cnt = 0;
00470 }
00471
00472 void show_blks()
00473 {
00474 int i;
00475
00476 for (i = 0; i < blk_cnt; i++)
00477 printf("Block[%d] = %lu\n", i, (unsigned long) block[i]);
00478 }
00479
00480 int blk_is_used(blk_num)
00481 block_t blk_num;
00482 {
00483 int i;
00484
00485 for (i = 0; block[i] && block[i] != blk_num; i++);
00486 return(block[i] != 0) ? 1 : 0;
00487 }
00488
00489
00490
00491
00492 #define BIT_MAP_SHIFT 13
00493 #define INT_BITS (SIZE_OF_INT << 3)
00494
00495 int blk_ok(num)
00496 block_t num;
00497 {
00498 block_t blk_offset;
00499 int rd;
00500 int blk, offset, words, bit, tst_word;
00501 zone_t z_num;
00502
00503 if (blk_is_used(num)) {
00504 printf("Duplicate block (%lu) given\n", (unsigned long) num);
00505 return NOT_OK;
00506 }
00507
00508
00509
00510 z_num = num - (sp->s_firstdatazone - 1);
00511
00512
00513 blk = z_num >> BIT_MAP_SHIFT;
00514 offset = z_num - (blk << BIT_MAP_SHIFT);
00515 words = z_num / INT_BITS;
00516
00517 blk_offset = (block_t) (2 + sp->s_imap_blocks);
00518 blk_offset *= (block_t) BLOCK_SIZE;
00519 blk_offset += (block_t) (words * SIZE_OF_INT);
00520
00521
00522 lseek(fd, (off_t) 0, SEEK_SET);
00523 lseek(fd, (off_t) blk_offset, SEEK_SET);
00524
00525 rd = read(fd, (char *) &tst_word, SIZE_OF_INT);
00526 if (rd != SIZE_OF_INT) {
00527 printf("Read error in bitmap\n");
00528 done(DIR_CREATED);
00529 }
00530
00531
00532 bit = offset % INT_BITS;
00533
00534 if (((tst_word >> bit) & 01) == 0)
00535 return OK;
00536 else {
00537 printf("Bad number %lu. ", (unsigned long) num);
00538 printf("This zone (block) is marked in bitmap\n");
00539 return NOT_OK;
00540 }
00541 }
00542
00543 void set_bit(num)
00544 zone_t num;
00545 {
00546 int rwd;
00547 long blk_offset;
00548 int blk, offset, words, tst_word, bit;
00549 unsigned z_num;
00550
00551 z_num = num - (sp->s_firstdatazone - 1);
00552
00553 blk = z_num >> BIT_MAP_SHIFT;
00554 offset = z_num - (blk << BIT_MAP_SHIFT);
00555 words = z_num / INT_BITS;
00556
00557 blk_offset = (long) (2 + sp->s_imap_blocks);
00558 blk_offset *= (long) BLOCK_SIZE;
00559 blk_offset += (long) (words * SIZE_OF_INT);
00560
00561
00562 lseek(fd, (off_t) 0, SEEK_SET);
00563 lseek(fd, (off_t) blk_offset, SEEK_SET);
00564
00565 rwd = read(fd, (char *) &tst_word, SIZE_OF_INT);
00566 if (rwd != SIZE_OF_INT) {
00567 printf("Read error in bitmap\n");
00568 done(DEV_MOUNTED);
00569 }
00570 bit = offset % INT_BITS;
00571 if (((tst_word >> bit) & 01) == 0) {
00572 lseek(fd, 0L, SEEK_SET);
00573 lseek(fd, (off_t) blk_offset, SEEK_SET);
00574 tst_word |= (1 << bit);
00575 rwd = write(fd, (char *) &tst_word, SIZE_OF_INT);
00576 if (rwd != SIZE_OF_INT) {
00577 printf("Bad write in zone map\n");
00578 printf("Check file system \n");
00579 done(DIR_CREATED);
00580 }
00581 return;
00582 }
00583 printf("Bit map indicates that block %lu is in use. Not marked.\n",
00584 (unsigned long) num);
00585
00586 return;
00587 }
00588
00589
00590
00591 long rd_num()
00592 {
00593 long num;
00594 int c;
00595
00596 if (eofseen) return(-1);
00597 do {
00598 c = getchar();
00599 if (c == EOF || c == '\n') return(-1);
00600 } while (c != '-' && (c < '0' || c > '9'));
00601
00602 if (c == '-') {
00603 printf("Block numbers must be positive\n");
00604 exit(1);
00605 }
00606 num = 0;
00607 while (c >= '0' && c <= '9') {
00608 num *= 10;
00609 num += c - '0';
00610 c = getchar();
00611 if (c == '\n') eofseen = 1;
00612 }
00613 return num;
00614 }
00615
00616
00617
00618 int ok(str)
00619 char *str;
00620 {
00621 int c;
00622
00623 for (;;) {
00624 printf("%s", str);
00625 while ((c = getchar()) != EOF &&
00626 c != 'y' && c != 'n' && c != 'q')
00627 if (c != '\n') printf(" Bad character %c\n", (char) c);
00628 switch (c) {
00629 case EOF:
00630 return QUIT;
00631 case 'y':
00632 return OK;
00633 case 'n':
00634 return NOT_OK;
00635 case 'q': return QUIT;
00636 }
00637 printf("\n");
00638 }
00639 }
00640
00641
00642 void done(nr)
00643 int nr;
00644 {
00645 switch (nr) {
00646 case SUCCESS:
00647 case FILE_EXISTS:
00648 unlink(file_name);
00649 case DEV_MOUNTED:
00650 umount(dev_name);
00651 case DIR_CREATED:
00652 rmdir(dir_name);
00653 case HARMLESS:;
00654 }
00655 sync();
00656 exit(nr == SUCCESS ? 0 : 1);
00657 }