Whamcloud - gitweb
ChangeLog, random_exercise.c:
[tools/e2fsprogs.git] / tests / progs / test_rel.c
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 <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <unistd.h>
16 #ifdef HAVE_GETOPT_H
17 #include <getopt.h>
18 #endif
19 #include <fcntl.h>
20
21 #include <linux/ext2_fs.h>
22
23 #include <et/com_err.h>
24 #include <ss/ss.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, 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(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         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         struct ext2_inode_relocate_entry ent;
385         errcode_t retval;
386         ino_t   old, new, max_refs;
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         struct ext2_inode_relocate_entry ent;
421         errcode_t retval;
422         ino_t   old;
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         struct ext2_inode_relocate_entry ent;
448         ino_t   orig, old;
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         struct ext2_inode_relocate_entry ent;
488         ino_t   old;
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         struct ext2_inode_relocate_entry ent;
510         ino_t   ino;
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         struct ext2_inode_reference ref;
540         blk_t   block, offset;
541         ino_t   ino;
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         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         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         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         setbuf(stdout, NULL);
682         setbuf(stderr, NULL);
683         while (!feof(f)) {
684                 if (fgets(buf, sizeof(buf), f) == NULL)
685                         break;
686                 if (buf[0] == '#')
687                         continue;
688                 noecho = 0;
689                 if (buf[0] == '-') {
690                         noecho = 1;
691                         buf[0] = ' ';
692                 }
693                 cp = strchr(buf, '\n');
694                 if (cp)
695                         *cp = 0;
696                 cp = strchr(buf, '\r');
697                 if (cp)
698                         *cp = 0;
699                 if (!noecho)
700                         printf("test_rel: %s\n", buf);
701                 retval = ss_execute_line(sci_idx, buf);
702                 if (retval) {
703                         ss_perror(sci_idx, retval, buf);
704                         exit_status++;
705                 }
706         }
707         return exit_status;
708 }
709
710 void main(int argc, char **argv)
711 {
712         int             retval;
713         int             sci_idx;
714         const char      *usage = "Usage: test_rel [-R request] [-f cmd_file]";
715         char            c;
716         char            *request = 0;
717         int             exit_status = 0;
718         char            *cmd_file = 0;
719         
720         initialize_ext2_error_table();
721
722         while ((c = getopt (argc, argv, "wR:f:")) != EOF) {
723                 switch (c) {
724                 case 'R':
725                         request = optarg;
726                         break;
727                 case 'f':
728                         cmd_file = optarg;
729                         break;
730                 default:
731                         com_err(argv[0], 0, usage);
732                         return;
733                 }
734         }
735         sci_idx = ss_create_invocation("test_rel", "0.0", (char *) NULL,
736                                        &test_cmds, &retval);
737         if (retval) {
738                 ss_perror(sci_idx, retval, "creating invocation");
739                 exit(1);
740         }
741
742         (void) ss_add_request_table (sci_idx, &ss_std_requests, 1, &retval);
743         if (retval) {
744                 ss_perror(sci_idx, retval, "adding standard requests");
745                 exit (1);
746         }
747         if (request) {
748                 retval = 0;
749                 retval = ss_execute_line(sci_idx, request);
750                 if (retval) {
751                         ss_perror(sci_idx, retval, request);
752                         exit_status++;
753                 }
754         } else if (cmd_file) {
755                 exit_status = source_file(cmd_file, sci_idx);
756         } else {
757                 ss_listen(sci_idx);
758         }
759
760         exit(exit_status);
761 }
762