Theodore Ts'o | 521e368 | 1997-04-29 17:48:10 +0000 | [diff] [blame] | 1 | /* |
| 2 | * test_icount.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 | |
Theodore Ts'o | 54c637d | 2001-05-14 11:45:38 +0000 | [diff] [blame^] | 21 | #include <ext2fs/ext2_fs.h> |
Theodore Ts'o | 521e368 | 1997-04-29 17:48:10 +0000 | [diff] [blame] | 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 | extern ss_request_table test_cmds; |
| 30 | |
| 31 | #include "test_icount.h" |
| 32 | |
| 33 | ext2_filsys test_fs; |
| 34 | ext2_icount_t test_icount; |
| 35 | |
| 36 | /* |
| 37 | * Helper function which assures that the icount structure is valid |
| 38 | */ |
| 39 | static int check_icount(char *request) |
| 40 | { |
| 41 | if (test_icount) |
| 42 | return 0; |
| 43 | com_err(request, 0, "The icount structure must be allocated."); |
| 44 | return 1; |
| 45 | } |
| 46 | |
| 47 | /* |
| 48 | * Helper function which parses an inode number. |
| 49 | */ |
| 50 | static int parse_inode(const char *request, const char *desc, |
Theodore Ts'o | dfcdc32 | 2001-01-11 15:38:00 +0000 | [diff] [blame] | 51 | const char *str, ext2_ino_t *ino) |
Theodore Ts'o | 521e368 | 1997-04-29 17:48:10 +0000 | [diff] [blame] | 52 | { |
| 53 | char *tmp; |
| 54 | |
| 55 | *ino = strtoul(str, &tmp, 0); |
| 56 | if (*tmp) { |
| 57 | com_err(request, 0, "Bad %s - %s", desc, str); |
| 58 | return 1; |
| 59 | } |
| 60 | return 0; |
| 61 | } |
| 62 | |
| 63 | void do_create_icount(int argc, char **argv) |
| 64 | { |
Theodore Ts'o | dfcdc32 | 2001-01-11 15:38:00 +0000 | [diff] [blame] | 65 | errcode_t retval; |
| 66 | char *progname; |
| 67 | int flags = 0; |
| 68 | ext2_ino_t size = 5; |
Theodore Ts'o | 521e368 | 1997-04-29 17:48:10 +0000 | [diff] [blame] | 69 | |
| 70 | progname = *argv; |
| 71 | argv++; argc --; |
| 72 | |
| 73 | if (argc && !strcmp("-i", *argv)) { |
| 74 | flags |= EXT2_ICOUNT_OPT_INCREMENT; |
| 75 | argv++; argc--; |
| 76 | } |
| 77 | if (argc) { |
| 78 | if (parse_inode(progname, "icount size", argv[0], &size)) |
| 79 | return; |
| 80 | argv++; argc--; |
| 81 | } |
| 82 | #if 0 |
| 83 | printf("Creating icount... flags=%d, size=%d\n", flags, (int) size); |
| 84 | #endif |
| 85 | retval = ext2fs_create_icount(test_fs, flags, (int) size, |
| 86 | &test_icount); |
| 87 | if (retval) { |
| 88 | com_err(progname, retval, "while creating icount"); |
| 89 | return; |
| 90 | } |
| 91 | } |
| 92 | |
| 93 | void do_free_icount(int argc, char **argv) |
| 94 | { |
| 95 | if (check_icount(argv[0])) |
| 96 | return; |
| 97 | |
| 98 | ext2fs_free_icount(test_icount); |
| 99 | test_icount = 0; |
| 100 | } |
| 101 | |
| 102 | void do_fetch(int argc, char **argv) |
| 103 | { |
Theodore Ts'o | dfcdc32 | 2001-01-11 15:38:00 +0000 | [diff] [blame] | 104 | const char *usage = "usage: %s inode"; |
| 105 | errcode_t retval; |
| 106 | ext2_ino_t ino; |
| 107 | __u16 count; |
Theodore Ts'o | 521e368 | 1997-04-29 17:48:10 +0000 | [diff] [blame] | 108 | |
| 109 | if (argc < 2) { |
| 110 | printf(usage, argv[0]); |
| 111 | return; |
| 112 | } |
| 113 | if (check_icount(argv[0])) |
| 114 | return; |
| 115 | if (parse_inode(argv[0], "inode", argv[1], &ino)) |
| 116 | return; |
| 117 | retval = ext2fs_icount_fetch(test_icount, ino, &count); |
| 118 | if (retval) { |
| 119 | com_err(argv[0], retval, "while calling ext2fs_icount_fetch"); |
| 120 | return; |
| 121 | } |
| 122 | printf("Count is %u\n", count); |
| 123 | } |
| 124 | |
| 125 | void do_increment(int argc, char **argv) |
| 126 | { |
Theodore Ts'o | dfcdc32 | 2001-01-11 15:38:00 +0000 | [diff] [blame] | 127 | const char *usage = "usage: %s inode"; |
| 128 | errcode_t retval; |
| 129 | ext2_ino_t ino; |
| 130 | __u16 count; |
Theodore Ts'o | 521e368 | 1997-04-29 17:48:10 +0000 | [diff] [blame] | 131 | |
| 132 | if (argc < 2) { |
| 133 | printf(usage, argv[0]); |
| 134 | return; |
| 135 | } |
| 136 | if (check_icount(argv[0])) |
| 137 | return; |
| 138 | if (parse_inode(argv[0], "inode", argv[1], &ino)) |
| 139 | return; |
| 140 | retval = ext2fs_icount_increment(test_icount, ino, &count); |
| 141 | if (retval) { |
| 142 | com_err(argv[0], retval, |
| 143 | "while calling ext2fs_icount_increment"); |
| 144 | return; |
| 145 | } |
| 146 | printf("Count is now %u\n", count); |
| 147 | } |
| 148 | |
| 149 | void do_decrement(int argc, char **argv) |
| 150 | { |
Theodore Ts'o | dfcdc32 | 2001-01-11 15:38:00 +0000 | [diff] [blame] | 151 | const char *usage = "usage: %s inode"; |
| 152 | errcode_t retval; |
| 153 | ext2_ino_t ino; |
| 154 | __u16 count; |
Theodore Ts'o | 521e368 | 1997-04-29 17:48:10 +0000 | [diff] [blame] | 155 | |
| 156 | if (argc < 2) { |
| 157 | printf(usage, argv[0]); |
| 158 | return; |
| 159 | } |
| 160 | if (check_icount(argv[0])) |
| 161 | return; |
| 162 | if (parse_inode(argv[0], "inode", argv[1], &ino)) |
| 163 | return; |
| 164 | retval = ext2fs_icount_decrement(test_icount, ino, &count); |
| 165 | if (retval) { |
| 166 | com_err(argv[0], retval, |
| 167 | "while calling ext2fs_icount_increment"); |
| 168 | return; |
| 169 | } |
| 170 | printf("Count is now %u\n", count); |
| 171 | } |
| 172 | |
| 173 | void do_store(int argc, char **argv) |
| 174 | { |
Theodore Ts'o | dfcdc32 | 2001-01-11 15:38:00 +0000 | [diff] [blame] | 175 | const char *usage = "usage: %s inode count"; |
| 176 | errcode_t retval; |
| 177 | ext2_ino_t ino; |
| 178 | ext2_ino_t count; |
Theodore Ts'o | 521e368 | 1997-04-29 17:48:10 +0000 | [diff] [blame] | 179 | |
| 180 | if (argc < 3) { |
| 181 | printf(usage, argv[0]); |
| 182 | return; |
| 183 | } |
| 184 | if (check_icount(argv[0])) |
| 185 | return; |
| 186 | if (parse_inode(argv[0], "inode", argv[1], &ino)) |
| 187 | return; |
| 188 | if (parse_inode(argv[0], "count", argv[2], &count)) |
| 189 | return; |
| 190 | if (count > 65535) { |
| 191 | printf("Count too large.\n"); |
| 192 | return; |
| 193 | } |
| 194 | retval = ext2fs_icount_store(test_icount, ino, (__u16) count); |
| 195 | if (retval) { |
| 196 | com_err(argv[0], retval, |
| 197 | "while calling ext2fs_icount_store"); |
| 198 | return; |
| 199 | } |
| 200 | } |
| 201 | |
| 202 | void do_dump(int argc, char **argv) |
| 203 | { |
| 204 | errcode_t retval; |
Theodore Ts'o | dfcdc32 | 2001-01-11 15:38:00 +0000 | [diff] [blame] | 205 | ext2_ino_t i; |
Theodore Ts'o | 521e368 | 1997-04-29 17:48:10 +0000 | [diff] [blame] | 206 | __u16 count; |
| 207 | |
| 208 | if (check_icount(argv[0])) |
| 209 | return; |
| 210 | for (i=1; i <= test_fs->super->s_inodes_count; i++) { |
| 211 | retval = ext2fs_icount_fetch(test_icount, i, &count); |
| 212 | if (retval) { |
| 213 | com_err(argv[0], retval, |
| 214 | "while fetching icount for %lu", i); |
| 215 | return; |
| 216 | } |
| 217 | if (count) |
| 218 | printf("%lu: %u\n", i, count); |
| 219 | } |
| 220 | } |
| 221 | |
| 222 | void do_validate(int argc, char **argv) |
| 223 | { |
| 224 | errcode_t retval; |
Theodore Ts'o | 4e27d76 | 1997-10-25 23:50:09 +0000 | [diff] [blame] | 225 | |
Theodore Ts'o | 521e368 | 1997-04-29 17:48:10 +0000 | [diff] [blame] | 226 | if (check_icount(argv[0])) |
| 227 | return; |
| 228 | retval = ext2fs_icount_validate(test_icount, stdout); |
| 229 | if (retval) { |
| 230 | com_err(argv[0], retval, "while validating icount structure"); |
| 231 | return; |
| 232 | } |
| 233 | printf("Icount structure successfully validated\n"); |
| 234 | } |
| 235 | |
| 236 | void do_get_size(int argc, char **argv) |
| 237 | { |
Theodore Ts'o | dfcdc32 | 2001-01-11 15:38:00 +0000 | [diff] [blame] | 238 | ext2_ino_t size; |
Theodore Ts'o | 521e368 | 1997-04-29 17:48:10 +0000 | [diff] [blame] | 239 | |
| 240 | if (check_icount(argv[0])) |
| 241 | return; |
| 242 | size = ext2fs_get_icount_size(test_icount); |
Theodore Ts'o | 2a3013b | 1998-03-30 01:08:41 +0000 | [diff] [blame] | 243 | printf("Size of icount is: %lu\n", size); |
Theodore Ts'o | 521e368 | 1997-04-29 17:48:10 +0000 | [diff] [blame] | 244 | } |
| 245 | |
| 246 | static int source_file(const char *cmd_file, int sci_idx) |
| 247 | { |
| 248 | FILE *f; |
| 249 | char buf[256]; |
| 250 | char *cp; |
| 251 | int exit_status = 0; |
| 252 | int retval; |
| 253 | int noecho; |
| 254 | |
| 255 | if (strcmp(cmd_file, "-") == 0) |
| 256 | f = stdin; |
| 257 | else { |
| 258 | f = fopen(cmd_file, "r"); |
| 259 | if (!f) { |
| 260 | perror(cmd_file); |
| 261 | exit(1); |
| 262 | } |
| 263 | } |
| 264 | setbuf(stdout, NULL); |
| 265 | setbuf(stderr, NULL); |
| 266 | while (!feof(f)) { |
| 267 | if (fgets(buf, sizeof(buf), f) == NULL) |
| 268 | break; |
| 269 | if (buf[0] == '#') |
| 270 | continue; |
| 271 | noecho = 0; |
| 272 | if (buf[0] == '-') { |
| 273 | noecho = 1; |
| 274 | buf[0] = ' '; |
| 275 | } |
| 276 | cp = strchr(buf, '\n'); |
| 277 | if (cp) |
| 278 | *cp = 0; |
| 279 | cp = strchr(buf, '\r'); |
| 280 | if (cp) |
| 281 | *cp = 0; |
| 282 | if (!noecho) |
| 283 | printf("test_icount: %s\n", buf); |
| 284 | retval = ss_execute_line(sci_idx, buf); |
| 285 | if (retval) { |
| 286 | ss_perror(sci_idx, retval, buf); |
| 287 | exit_status++; |
| 288 | } |
| 289 | } |
| 290 | return exit_status; |
| 291 | } |
| 292 | |
Theodore Ts'o | 818180c | 1998-06-27 05:11:14 +0000 | [diff] [blame] | 293 | int main(int argc, char **argv) |
Theodore Ts'o | 521e368 | 1997-04-29 17:48:10 +0000 | [diff] [blame] | 294 | { |
| 295 | int retval; |
| 296 | int sci_idx; |
| 297 | const char *usage = "Usage: test_icount [-R request] [-f cmd_file]"; |
Theodore Ts'o | 018100f | 1998-06-27 05:20:20 +0000 | [diff] [blame] | 298 | int c; |
Theodore Ts'o | 521e368 | 1997-04-29 17:48:10 +0000 | [diff] [blame] | 299 | char *request = 0; |
| 300 | int exit_status = 0; |
| 301 | char *cmd_file = 0; |
| 302 | struct ext2_super_block param; |
| 303 | |
| 304 | initialize_ext2_error_table(); |
| 305 | |
| 306 | /* |
| 307 | * Create a sample filesystem structure |
| 308 | */ |
| 309 | memset(¶m, 0, sizeof(struct ext2_super_block)); |
| 310 | param.s_blocks_count = 80000; |
| 311 | param.s_inodes_count = 20000; |
| 312 | retval = ext2fs_initialize("/dev/null", 0, ¶m, |
| 313 | unix_io_manager, &test_fs); |
| 314 | if (retval) { |
| 315 | com_err("/dev/null", retval, "while setting up test fs"); |
| 316 | exit(1); |
| 317 | } |
| 318 | |
| 319 | while ((c = getopt (argc, argv, "wR:f:")) != EOF) { |
| 320 | switch (c) { |
| 321 | case 'R': |
| 322 | request = optarg; |
| 323 | break; |
| 324 | case 'f': |
| 325 | cmd_file = optarg; |
| 326 | break; |
| 327 | default: |
| 328 | com_err(argv[0], 0, usage); |
Theodore Ts'o | 818180c | 1998-06-27 05:11:14 +0000 | [diff] [blame] | 329 | exit(1); |
Theodore Ts'o | 521e368 | 1997-04-29 17:48:10 +0000 | [diff] [blame] | 330 | } |
| 331 | } |
| 332 | sci_idx = ss_create_invocation("test_icount", "0.0", (char *) NULL, |
| 333 | &test_cmds, &retval); |
| 334 | if (retval) { |
| 335 | ss_perror(sci_idx, retval, "creating invocation"); |
| 336 | exit(1); |
| 337 | } |
| 338 | |
| 339 | (void) ss_add_request_table (sci_idx, &ss_std_requests, 1, &retval); |
| 340 | if (retval) { |
| 341 | ss_perror(sci_idx, retval, "adding standard requests"); |
| 342 | exit (1); |
| 343 | } |
| 344 | if (request) { |
| 345 | retval = 0; |
| 346 | retval = ss_execute_line(sci_idx, request); |
| 347 | if (retval) { |
| 348 | ss_perror(sci_idx, retval, request); |
| 349 | exit_status++; |
| 350 | } |
| 351 | } else if (cmd_file) { |
| 352 | exit_status = source_file(cmd_file, sci_idx); |
| 353 | } else { |
| 354 | ss_listen(sci_idx); |
| 355 | } |
| 356 | |
Theodore Ts'o | 818180c | 1998-06-27 05:11:14 +0000 | [diff] [blame] | 357 | return(exit_status); |
Theodore Ts'o | 521e368 | 1997-04-29 17:48:10 +0000 | [diff] [blame] | 358 | } |