Home | History | Annotate | Download | only in progs
      1 /*
      2  * test_rel.c
      3  *
      4  * Copyright (C) 1997 Theodore Ts'o.
      5  *
      6  * %Begin-Header%
      7  * This file may be redistributed under the terms of the GNU Public
      8  * License.
      9  * %End-Header%
     10  */
     11 
     12 #include "config.h"
     13 #include <stdio.h>
     14 #include <stdlib.h>
     15 #include <string.h>
     16 #include <unistd.h>
     17 #ifdef HAVE_GETOPT_H
     18 #include <getopt.h>
     19 #endif
     20 #include <fcntl.h>
     21 
     22 #include <et/com_err.h>
     23 #include <ss/ss.h>
     24 #include <ext2fs/ext2_fs.h>
     25 #include <ext2fs/ext2fs.h>
     26 #include <ext2fs/irel.h>
     27 #include <ext2fs/brel.h>
     28 
     29 #include "test_rel.h"
     30 
     31 extern ss_request_table test_cmds;
     32 
     33 ext2_irel irel = NULL;
     34 ext2_brel brel = NULL;
     35 
     36 /*
     37  * Helper function which parses an inode number.
     38  */
     39 static int parse_inode(const char *request, const char *desc,
     40 		       const char *str, ext2_ino_t *ino)
     41 {
     42 	char *tmp;
     43 
     44 	*ino = strtoul(str, &tmp, 0);
     45 	if (*tmp) {
     46 		com_err(request, 0, "Bad %s - %s", desc, str);
     47 		return 1;
     48 	}
     49 	return 0;
     50 }
     51 
     52 /*
     53  * Helper function which parses a block number.
     54  */
     55 static int parse_block(const char *request, const char *desc,
     56 		       const char *str, blk_t *blk)
     57 {
     58 	char *tmp;
     59 
     60 	*blk = strtoul(str, &tmp, 0);
     61 	if (*tmp) {
     62 		com_err(request, 0, "Bad %s - %s", desc, str);
     63 		return 1;
     64 	}
     65 	return 0;
     66 }
     67 
     68 /*
     69  * Helper function which assures that a brel table is open
     70  */
     71 static int check_brel(char *request)
     72 {
     73 	if (brel)
     74 		return 0;
     75 	com_err(request, 0, "A block relocation table must be open.");
     76 	return 1;
     77 }
     78 
     79 /*
     80  * Helper function which assures that an irel table is open
     81  */
     82 static int check_irel(char *request)
     83 {
     84 	if (irel)
     85 		return 0;
     86 	com_err(request, 0, "An inode relocation table must be open.");
     87 	return 1;
     88 }
     89 
     90 /*
     91  * Helper function which displays a brel entry
     92  */
     93 static void display_brel_entry(blk_t old,
     94 			       struct ext2_block_relocate_entry *ent)
     95 {
     96 	printf("Old= %u, New= %u, Owner= %u:%u\n", old, ent->new,
     97 	       ent->owner.block_ref, ent->offset);
     98 }
     99 
    100 /*
    101  * Helper function which displays an irel entry
    102  */
    103 static void display_irel_entry(ext2_ino_t old,
    104 			       struct ext2_inode_relocate_entry *ent,
    105 			       int do_refs)
    106 {
    107 	struct ext2_inode_reference ref;
    108 	errcode_t	retval;
    109 	int		first = 1;
    110 
    111 	printf("Old= %lu, New= %lu, Original=%lu, Max_refs=%u\n", old,
    112 	       ent->new, ent->orig, ent->max_refs);
    113 	if (!do_refs)
    114 		return;
    115 
    116 	retval = ext2fs_irel_start_iter_ref(irel, old);
    117 	if (retval) {
    118 		printf("\tCouldn't get references: %s\n",
    119 		       error_message(retval));
    120 		return;
    121 	}
    122 	while (1) {
    123 		retval = ext2fs_irel_next_ref(irel, &ref);
    124 		if (retval) {
    125 			printf("(%s) ", error_message(retval));
    126 			break;
    127 		}
    128 		if (ref.block == 0)
    129 			break;
    130 		if (first) {
    131 			fputc('\t', stdout);
    132 			first = 0;
    133 		} else
    134 			printf(", ");
    135 		printf("%u:%u", ref.block, ref.offset);
    136 	}
    137 	if (!first)
    138 		fputc('\n', stdout);
    139 }
    140 
    141 /*
    142  * These are the actual command table procedures
    143  */
    144 void do_brel_ma_create(int argc, char **argv)
    145 {
    146 	const char *usage = "Usage: %s name max_blocks\n";
    147 	errcode_t	retval;
    148 	blk_t		max_blk;
    149 
    150 	if (argc < 3) {
    151 		printf(usage, argv[0]);
    152 		return;
    153 	}
    154 	if (parse_block(argv[0], "max_blocks", argv[2], &max_blk))
    155 		return;
    156 	retval = ext2fs_brel_memarray_create(argv[1], max_blk, &brel);
    157 	if (retval) {
    158 		com_err(argv[0], retval, "while opening memarray brel");
    159 		return;
    160 	}
    161 	return;
    162 }
    163 
    164 void do_brel_free(int argc, char **argv)
    165 {
    166 	if (check_brel(argv[0]))
    167 		return;
    168 	ext2fs_brel_free(brel);
    169 	brel = NULL;
    170 	return;
    171 }
    172 
    173 void do_brel_put(int argc, char **argv)
    174 {
    175 	const char *usage = "usage: %s old_block new_block [owner] [offset]";
    176 	errcode_t retval;
    177 	struct ext2_block_relocate_entry ent;
    178 	blk_t	old, new, offset=0, owner=0;
    179 
    180 	if (check_brel(argv[0]))
    181 		return;
    182 
    183 	if (argc < 3) {
    184 		printf(usage, argv[0]);
    185 		return;
    186 	}
    187 	if (parse_block(argv[0], "old block", argv[1], &old))
    188 		return;
    189 	if (parse_block(argv[0], "new block", argv[2], &new))
    190 		return;
    191 	if (argc > 3 &&
    192 	    parse_block(argv[0], "owner block", argv[3], &owner))
    193 		return;
    194 	if (argc > 4 &&
    195 	    parse_block(argv[0], "offset", argv[4], &offset))
    196 		return;
    197 	if (offset > 65535) {
    198 		printf("Offset too large.\n");
    199 		return;
    200 	}
    201 	ent.new = new;
    202 	ent.offset = (__u16) offset;
    203 	ent.flags = 0;
    204 	ent.owner.block_ref = owner;
    205 
    206 	retval = ext2fs_brel_put(brel, old, &ent);
    207 	if (retval) {
    208 		com_err(argv[0], retval, "while calling ext2fs_brel_put");
    209 		return;
    210 	}
    211 	return;
    212 }
    213 
    214 void do_brel_get(int argc, char **argv)
    215 {
    216 	const char *usage = "%s block";
    217 	errcode_t retval;
    218 	struct ext2_block_relocate_entry ent;
    219 	blk_t	blk;
    220 
    221 	if (check_brel(argv[0]))
    222 		return;
    223 	if (argc < 2) {
    224 		printf(usage, argv[0]);
    225 		return;
    226 	}
    227 	if (parse_block(argv[0], "block", argv[1], &blk))
    228 		return;
    229 	retval = ext2fs_brel_get(brel, blk, &ent);
    230 	if (retval) {
    231 		com_err(argv[0], retval, "while calling ext2fs_brel_get");
    232 		return;
    233 	}
    234 	display_brel_entry(blk, &ent);
    235 	return;
    236 }
    237 
    238 void do_brel_start_iter(int argc, char **argv)
    239 {
    240 	errcode_t retval;
    241 
    242 	if (check_brel(argv[0]))
    243 		return;
    244 
    245 	retval = ext2fs_brel_start_iter(brel);
    246 	if (retval) {
    247 		com_err(argv[0], retval, "while calling ext2fs_brel_start_iter");
    248 		return;
    249 	}
    250 	return;
    251 }
    252 
    253 void do_brel_next(int argc, char **argv)
    254 {
    255 	errcode_t retval;
    256 	struct ext2_block_relocate_entry ent;
    257 	blk_t	blk;
    258 
    259 	if (check_brel(argv[0]))
    260 		return;
    261 
    262 	retval = ext2fs_brel_next(brel, &blk, &ent);
    263 	if (retval) {
    264 		com_err(argv[0], retval, "while calling ext2fs_brel_next");
    265 		return;
    266 	}
    267 	if (blk == 0) {
    268 		printf("No more entries!\n");
    269 		return;
    270 	}
    271 	display_brel_entry(blk, &ent);
    272 	return;
    273 }
    274 
    275 void do_brel_dump(int argc, char **argv)
    276 {
    277 	errcode_t retval;
    278 	struct ext2_block_relocate_entry ent;
    279 	blk_t	blk;
    280 
    281 	if (check_brel(argv[0]))
    282 		return;
    283 
    284 	retval = ext2fs_brel_start_iter(brel);
    285 	if (retval) {
    286 		com_err(argv[0], retval, "while calling ext2fs_brel_start_iter");
    287 		return;
    288 	}
    289 
    290 	while (1) {
    291 		retval = ext2fs_brel_next(brel, &blk, &ent);
    292 		if (retval) {
    293 			com_err(argv[0], retval, "while calling ext2fs_brel_next");
    294 			return;
    295 		}
    296 		if (blk == 0)
    297 			break;
    298 
    299 		display_brel_entry(blk, &ent);
    300 	}
    301 	return;
    302 }
    303 
    304 void do_brel_move(int argc, char **argv)
    305 {
    306 	const char *usage = "%s old_block new_block";
    307 	errcode_t retval;
    308 	blk_t	old, new;
    309 
    310 	if (check_brel(argv[0]))
    311 		return;
    312 	if (argc < 2) {
    313 		printf(usage, argv[0]);
    314 		return;
    315 	}
    316 	if (parse_block(argv[0], "old block", argv[1], &old))
    317 		return;
    318 	if (parse_block(argv[0], "new block", argv[2], &new))
    319 		return;
    320 
    321 	retval = ext2fs_brel_move(brel, old, new);
    322 	if (retval) {
    323 		com_err(argv[0], retval, "while calling ext2fs_brel_move");
    324 		return;
    325 	}
    326 	return;
    327 }
    328 
    329 void do_brel_delete(int argc, char **argv)
    330 {
    331 	const char *usage = "%s block";
    332 	errcode_t retval;
    333 	blk_t	blk;
    334 
    335 	if (check_brel(argv[0]))
    336 		return;
    337 	if (argc < 2) {
    338 		printf(usage, argv[0]);
    339 		return;
    340 	}
    341 	if (parse_block(argv[0], "block", argv[1], &blk))
    342 		return;
    343 
    344 	retval = ext2fs_brel_delete(brel, blk);
    345 	if (retval) {
    346 		com_err(argv[0], retval, "while calling ext2fs_brel_delete");
    347 		return;
    348 	}
    349 }
    350 
    351 void do_irel_ma_create(int argc, char **argv)
    352 {
    353 	const char	*usage = "Usage: %s name max_inode\n";
    354 	errcode_t	retval;
    355 	ext2_ino_t	max_ino;
    356 
    357 	if (argc < 3) {
    358 		printf(usage, argv[0]);
    359 		return;
    360 	}
    361 	if (parse_inode(argv[0], "max_inodes", argv[2], &max_ino))
    362 		return;
    363 	retval = ext2fs_irel_memarray_create(argv[1], max_ino, &irel);
    364 	if (retval) {
    365 		com_err(argv[0], retval, "while opening memarray irel");
    366 		return;
    367 	}
    368 	return;
    369 }
    370 
    371 void do_irel_free(int argc, char **argv)
    372 {
    373 	if (check_irel(argv[0]))
    374 		return;
    375 
    376 	ext2fs_irel_free(irel);
    377 	irel = NULL;
    378 	return;
    379 }
    380 
    381 void do_irel_put(int argc, char **argv)
    382 {
    383 	const char	*usage = "%s old new max_refs";
    384 	errcode_t	retval;
    385 	ext2_ino_t	old, new, max_refs;
    386 	struct ext2_inode_relocate_entry ent;
    387 
    388 	if (check_irel(argv[0]))
    389 		return;
    390 
    391 	if (argc < 4) {
    392 		printf(usage, argv[0]);
    393 		return;
    394 	}
    395 	if (parse_inode(argv[0], "old inode", argv[1], &old))
    396 		return;
    397 	if (parse_inode(argv[0], "new inode", argv[2], &new))
    398 		return;
    399 	if (parse_inode(argv[0], "max_refs", argv[3], &max_refs))
    400 		return;
    401 	if (max_refs > 65535) {
    402 		printf("max_refs too big\n");
    403 		return;
    404 	}
    405 	ent.new = new;
    406 	ent.max_refs = (__u16) max_refs;
    407 	ent.flags = 0;
    408 
    409 	retval = ext2fs_irel_put(irel, old, &ent);
    410 	if (retval) {
    411 		com_err(argv[0], retval, "while calling ext2fs_irel_put");
    412 		return;
    413 	}
    414 	return;
    415 }
    416 
    417 void do_irel_get(int argc, char **argv)
    418 {
    419 	const char	*usage = "%s inode";
    420 	errcode_t	retval;
    421 	ext2_ino_t	old;
    422 	struct ext2_inode_relocate_entry ent;
    423 
    424 	if (check_irel(argv[0]))
    425 		return;
    426 
    427 	if (argc < 2) {
    428 		printf(usage, argv[0]);
    429 		return;
    430 	}
    431 	if (parse_inode(argv[0], "inode", argv[1], &old))
    432 		return;
    433 
    434 	retval = ext2fs_irel_get(irel, old, &ent);
    435 	if (retval) {
    436 		com_err(argv[0], retval, "while calling ext2fs_irel_get");
    437 		return;
    438 	}
    439 	display_irel_entry(old, &ent, 1);
    440 	return;
    441 }
    442 
    443 void do_irel_get_by_orig(int argc, char **argv)
    444 {
    445 	const char	*usage = "%s orig_inode";
    446 	errcode_t	retval;
    447 	ext2_ino_t	orig, old;
    448 	struct ext2_inode_relocate_entry ent;
    449 
    450 	if (check_irel(argv[0]))
    451 		return;
    452 
    453 	if (argc < 2) {
    454 		printf(usage, argv[0]);
    455 		return;
    456 	}
    457 	if (parse_inode(argv[0], "original inode", argv[1], &orig))
    458 		return;
    459 
    460 	retval = ext2fs_irel_get_by_orig(irel, orig, &old, &ent);
    461 	if (retval) {
    462 		com_err(argv[0], retval, "while calling ext2fs_irel_get_by_orig");
    463 		return;
    464 	}
    465 	display_irel_entry(old, &ent, 1);
    466 	return;
    467 }
    468 
    469 void do_irel_start_iter(int argc, char **argv)
    470 {
    471 	errcode_t retval;
    472 
    473 	if (check_irel(argv[0]))
    474 		return;
    475 
    476 	retval = ext2fs_irel_start_iter(irel);
    477 	if (retval) {
    478 		com_err(argv[0], retval, "while calling ext2fs_irel_start_iter");
    479 		return;
    480 	}
    481 	return;
    482 }
    483 
    484 void do_irel_next(int argc, char **argv)
    485 {
    486 	errcode_t	retval;
    487 	ext2_ino_t	old;
    488 	struct ext2_inode_relocate_entry ent;
    489 
    490 	if (check_irel(argv[0]))
    491 		return;
    492 
    493 	retval = ext2fs_irel_next(irel, &old, &ent);
    494 	if (retval) {
    495 		com_err(argv[0], retval, "while calling ext2fs_irel_next");
    496 		return;
    497 	}
    498 	if (old == 0) {
    499 		printf("No more entries!\n");
    500 		return;
    501 	}
    502 	display_irel_entry(old, &ent, 1);
    503 	return;
    504 }
    505 
    506 void do_irel_dump(int argc, char **argv)
    507 {
    508 	errcode_t	retval;
    509 	ext2_ino_t	ino;
    510 	struct ext2_inode_relocate_entry ent;
    511 
    512 	if (check_irel(argv[0]))
    513 		return;
    514 
    515 	retval = ext2fs_irel_start_iter(irel);
    516 	if (retval) {
    517 		com_err(argv[0], retval, "while calling ext2fs_irel_start_iter");
    518 		return;
    519 	}
    520 
    521 	while (1) {
    522 		retval = ext2fs_irel_next(irel, &ino, &ent);
    523 		if (retval) {
    524 			com_err(argv[0], retval, "while calling ext2fs_irel_next");
    525 			return;
    526 		}
    527 		if (ino == 0)
    528 			break;
    529 
    530 		display_irel_entry(ino, &ent, 1);
    531 	}
    532 	return;
    533 }
    534 
    535 void do_irel_add_ref(int argc, char **argv)
    536 {
    537 	const char	*usage = "%s inode block offset";
    538 	errcode_t	retval;
    539 	blk_t		block, offset;
    540 	ext2_ino_t	ino;
    541 	struct ext2_inode_reference ref;
    542 
    543 
    544 	if (check_irel(argv[0]))
    545 		return;
    546 
    547 	if (argc < 4) {
    548 		printf(usage, argv[0]);
    549 		return;
    550 	}
    551 	if (parse_inode(argv[0], "inode", argv[1], &ino))
    552 		return;
    553 	if (parse_block(argv[0], "block", argv[2], &block))
    554 		return;
    555 	if (parse_block(argv[0], "offset", argv[3], &offset))
    556 		return;
    557 	if (offset > 65535) {
    558 		printf("Offset too big.\n");
    559 		return;
    560 	}
    561 	ref.block = block;
    562 	ref.offset = offset;
    563 
    564 	retval = ext2fs_irel_add_ref(irel, ino, &ref);
    565 	if (retval) {
    566 		com_err(argv[0], retval, "while calling ext2fs_irel_add_ref");
    567 		return;
    568 	}
    569 	return;
    570 }
    571 
    572 void do_irel_start_iter_ref(int argc, char **argv)
    573 {
    574 	const char	*usage = "%s inode";
    575 	errcode_t	retval;
    576 	ext2_ino_t	ino;
    577 
    578 	if (check_irel(argv[0]))
    579 		return;
    580 
    581 	if (argc < 2) {
    582 		printf(usage, argv[0]);
    583 		return;
    584 	}
    585 
    586 	if (parse_inode(argv[0], "inode", argv[1], &ino))
    587 		return;
    588 	retval = ext2fs_irel_start_iter_ref(irel, ino);
    589 	if (retval) {
    590 		com_err(argv[0], retval, "while calling ext2fs_irel_start_iter_ref");
    591 		return;
    592 	}
    593 	return;
    594 }
    595 
    596 void do_irel_next_ref(int argc, char **argv)
    597 {
    598 	struct ext2_inode_reference ref;
    599 	errcode_t retval;
    600 
    601 	if (check_irel(argv[0]))
    602 		return;
    603 
    604 	retval = ext2fs_irel_next_ref(irel, &ref);
    605 	if (retval) {
    606 		com_err(argv[0], retval, "while calling ext2fs_irel_next_ref");
    607 		return;
    608 	}
    609 	printf("Inode reference: %u:%u\n", ref.block, ref.offset);
    610 	return;
    611 }
    612 
    613 void do_irel_move(int argc, char **argv)
    614 {
    615 	const char	*usage = "%s old new";
    616 	errcode_t	retval;
    617 	ext2_ino_t	old, new;
    618 
    619 	if (check_irel(argv[0]))
    620 		return;
    621 
    622 	if (argc < 3) {
    623 		printf(usage, argv[0]);
    624 		return;
    625 	}
    626 	if (parse_inode(argv[0], "old inode", argv[1], &old))
    627 		return;
    628 	if (parse_inode(argv[0], "new inode", argv[2], &new))
    629 		return;
    630 
    631 	retval = ext2fs_irel_move(irel, old, new);
    632 	if (retval) {
    633 		com_err(argv[0], retval, "while calling ext2fs_irel_move");
    634 		return;
    635 	}
    636 	return;
    637 }
    638 
    639 void do_irel_delete(int argc, char **argv)
    640 {
    641 	const char	*usage = "%s inode";
    642 	errcode_t	retval;
    643 	ext2_ino_t	ino;
    644 
    645 	if (check_irel(argv[0]))
    646 		return;
    647 
    648 	if (argc < 2) {
    649 		printf(usage, argv[0]);
    650 		return;
    651 	}
    652 	if (parse_inode(argv[0], "inode", argv[1], &ino))
    653 		return;
    654 
    655 	retval = ext2fs_irel_delete(irel, ino);
    656 	if (retval) {
    657 		com_err(argv[0], retval, "while calling ext2fs_irel_delete");
    658 		return;
    659 	}
    660 	return;
    661 }
    662 
    663 static int source_file(const char *cmd_file, int sci_idx)
    664 {
    665 	FILE		*f;
    666 	char		buf[256];
    667 	char		*cp;
    668 	int		exit_status = 0;
    669 	int		retval;
    670 	int 		noecho;
    671 
    672 	if (strcmp(cmd_file, "-") == 0)
    673 		f = stdin;
    674 	else {
    675 		f = fopen(cmd_file, "r");
    676 		if (!f) {
    677 			perror(cmd_file);
    678 			exit(1);
    679 		}
    680 	}
    681 	fflush(stdout);
    682 	fflush(stderr);
    683 	setbuf(stdout, NULL);
    684 	setbuf(stderr, NULL);
    685 	while (!feof(f)) {
    686 		if (fgets(buf, sizeof(buf), f) == NULL)
    687 			break;
    688 		if (buf[0] == '#')
    689 			continue;
    690 		noecho = 0;
    691 		if (buf[0] == '-') {
    692 			noecho = 1;
    693 			buf[0] = ' ';
    694 		}
    695 		cp = strchr(buf, '\n');
    696 		if (cp)
    697 			*cp = 0;
    698 		cp = strchr(buf, '\r');
    699 		if (cp)
    700 			*cp = 0;
    701 		if (!noecho)
    702 			printf("test_rel: %s\n", buf);
    703 		retval = ss_execute_line(sci_idx, buf);
    704 		if (retval) {
    705 			ss_perror(sci_idx, retval, buf);
    706 			exit_status++;
    707 		}
    708 	}
    709 	return exit_status;
    710 }
    711 
    712 void main(int argc, char **argv)
    713 {
    714 	int		retval;
    715 	int		sci_idx;
    716 	const char	*usage = "Usage: test_rel [-R request] [-f cmd_file]";
    717 	int		c;
    718 	char		*request = 0;
    719 	int		exit_status = 0;
    720 	char		*cmd_file = 0;
    721 
    722 	initialize_ext2_error_table();
    723 
    724 	while ((c = getopt (argc, argv, "wR:f:")) != EOF) {
    725 		switch (c) {
    726 		case 'R':
    727 			request = optarg;
    728 			break;
    729 		case 'f':
    730 			cmd_file = optarg;
    731 			break;
    732 		default:
    733 			com_err(argv[0], 0, usage);
    734 			return;
    735 		}
    736 	}
    737 	sci_idx = ss_create_invocation("test_rel", "0.0", (char *) NULL,
    738 				       &test_cmds, &retval);
    739 	if (retval) {
    740 		ss_perror(sci_idx, retval, "creating invocation");
    741 		exit(1);
    742 	}
    743 
    744 	(void) ss_add_request_table (sci_idx, &ss_std_requests, 1, &retval);
    745 	if (retval) {
    746 		ss_perror(sci_idx, retval, "adding standard requests");
    747 		exit (1);
    748 	}
    749 	if (request) {
    750 		retval = 0;
    751 		retval = ss_execute_line(sci_idx, request);
    752 		if (retval) {
    753 			ss_perror(sci_idx, retval, request);
    754 			exit_status++;
    755 		}
    756 	} else if (cmd_file) {
    757 		exit_status = source_file(cmd_file, sci_idx);
    758 	} else {
    759 		ss_listen(sci_idx);
    760 	}
    761 
    762 	exit(exit_status);
    763 }
    764 
    765