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 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 293int main(int argc, char **argv) 294{ 295 int retval; 296 int sci_idx; 297 const char *usage = "Usage: test_icount [-R request] [-f cmd_file]"; 298 int c; 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); 329 exit(1); 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 357 return(exit_status); 358} 359