• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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   */
parse_inode(const char * request,const char * desc,const char * str,ext2_ino_t * ino)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   */
parse_block(const char * request,const char * desc,const char * str,blk_t * blk)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   */
check_brel(char * request)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   */
check_irel(char * request)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   */
display_brel_entry(blk_t old,struct ext2_block_relocate_entry * ent)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   */
display_irel_entry(ext2_ino_t old,struct ext2_inode_relocate_entry * ent,int do_refs)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   */
do_brel_ma_create(int argc,char ** argv)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  
do_brel_free(int argc,char ** argv)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  
do_brel_put(int argc,char ** argv)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  
do_brel_get(int argc,char ** argv)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  
do_brel_start_iter(int argc,char ** argv)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  
do_brel_next(int argc,char ** argv)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  
do_brel_dump(int argc,char ** argv)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  
do_brel_move(int argc,char ** argv)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  
do_brel_delete(int argc,char ** argv)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  
do_irel_ma_create(int argc,char ** argv)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  
do_irel_free(int argc,char ** argv)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  
do_irel_put(int argc,char ** argv)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  
do_irel_get(int argc,char ** argv)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  
do_irel_get_by_orig(int argc,char ** argv)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  
do_irel_start_iter(int argc,char ** argv)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  
do_irel_next(int argc,char ** argv)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  
do_irel_dump(int argc,char ** argv)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  
do_irel_add_ref(int argc,char ** argv)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  
do_irel_start_iter_ref(int argc,char ** argv)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  
do_irel_next_ref(int argc,char ** argv)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  
do_irel_move(int argc,char ** argv)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  
do_irel_delete(int argc,char ** argv)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  
source_file(const char * cmd_file,int sci_idx)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  
main(int argc,char ** argv)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