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 21#include <ext2fs/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 29extern ss_request_table test_cmds; 30 31#include "test_icount.h" 32 33ext2_filsys test_fs; 34ext2_icount_t test_icount; 35 36/* 37 * Helper function which assures that the icount structure is valid 38 */ 39static 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 */ 50static int parse_inode(const char *request, const char *desc, 51 const char *str, ext2_ino_t *ino) 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 63void do_create_icount(int argc, char **argv) 64{ 65 errcode_t retval; 66 char *progname; 67 int flags = 0; 68 ext2_ino_t size = 5; 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 93void 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 102void do_fetch(int argc, char **argv) 103{ 104 const char *usage = "usage: %s inode\n"; 105 errcode_t retval; 106 ext2_ino_t ino; 107 __u16 count; 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 125void do_increment(int argc, char **argv) 126{ 127 const char *usage = "usage: %s inode\n"; 128 errcode_t retval; 129 ext2_ino_t ino; 130 __u16 count; 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 149void do_decrement(int argc, char **argv) 150{ 151 const char *usage = "usage: %s inode\n"; 152 errcode_t retval; 153 ext2_ino_t ino; 154 __u16 count; 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_decrement"); 168 return; 169 } 170 printf("Count is now %u\n", count); 171} 172 173void do_store(int argc, char **argv) 174{ 175 const char *usage = "usage: %s inode count\n"; 176 errcode_t retval; 177 ext2_ino_t ino; 178 ext2_ino_t count; 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 202void do_dump(int argc, char **argv) 203{ 204 errcode_t retval; 205 ext2_ino_t i; 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", (unsigned long)i); 215 return; 216 } 217 if (count) 218 printf("%lu: %u\n", (unsigned long)i, count); 219 } 220} 221 222void do_validate(int argc, char **argv) 223{ 224 errcode_t retval; 225 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 236void do_get_size(int argc, char **argv) 237{ 238 ext2_ino_t size; 239 240 if (check_icount(argv[0])) 241 return; 242 size = ext2fs_get_icount_size(test_icount); 243 printf("Size of icount is: %lu\n", (unsigned long)size); 244} 245 246static 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 fflush(stdout); 265 fflush(stderr); 266 setbuf(stdout, NULL); 267 setbuf(stderr, NULL); 268 while (!feof(f)) { 269 if (fgets(buf, sizeof(buf), f) == NULL) 270 break; 271 if (buf[0] == '#') 272 continue; 273 noecho = 0; 274 if (buf[0] == '-') { 275 noecho = 1; 276 buf[0] = ' '; 277 } 278 cp = strchr(buf, '\n'); 279 if (cp) 280 *cp = 0; 281 cp = strchr(buf, '\r'); 282 if (cp) 283 *cp = 0; 284 if (!noecho) 285 printf("test_icount: %s\n", buf); 286 retval = ss_execute_line(sci_idx, buf); 287 if (retval) { 288 ss_perror(sci_idx, retval, buf); 289 exit_status++; 290 } 291 } 292 if (f != stdin) 293 fclose(f); 294 return exit_status; 295} 296 297int main(int argc, char **argv) 298{ 299 int retval; 300 int sci_idx; 301 int c; 302 char *request = 0; 303 int exit_status = 0; 304 char *cmd_file = 0; 305 struct ext2_super_block param; 306 307 initialize_ext2_error_table(); 308 309 /* 310 * Create a sample filesystem structure 311 */ 312 memset(¶m, 0, sizeof(struct ext2_super_block)); 313 ext2fs_blocks_count_set(¶m, 80000); 314 param.s_inodes_count = 20000; 315 retval = ext2fs_initialize("/dev/null", 0, ¶m, 316 unix_io_manager, &test_fs); 317 if (retval) { 318 com_err("/dev/null", retval, "while setting up test fs"); 319 exit(1); 320 } 321 322 while ((c = getopt (argc, argv, "wR:f:")) != EOF) { 323 switch (c) { 324 case 'R': 325 request = optarg; 326 break; 327 case 'f': 328 cmd_file = optarg; 329 break; 330 default: 331 com_err(argv[0], 0, "Usage: test_icount " 332 "[-R request] [-f cmd_file]"); 333 exit(1); 334 } 335 } 336 sci_idx = ss_create_invocation("test_icount", "0.0", (char *) NULL, 337 &test_cmds, &retval); 338 if (retval) { 339 ss_perror(sci_idx, retval, "creating invocation"); 340 exit(1); 341 } 342 343 (void) ss_add_request_table (sci_idx, &ss_std_requests, 1, &retval); 344 if (retval) { 345 ss_perror(sci_idx, retval, "adding standard requests"); 346 exit (1); 347 } 348 if (request) { 349 retval = 0; 350 retval = ss_execute_line(sci_idx, request); 351 if (retval) { 352 ss_perror(sci_idx, retval, request); 353 exit_status++; 354 } 355 } else if (cmd_file) { 356 exit_status = source_file(cmd_file, sci_idx); 357 } else { 358 ss_listen(sci_idx); 359 } 360 361 return(exit_status); 362} 363