OpenCores
URL https://opencores.org/ocsvn/eco32/eco32/trunk

Subversion Repositories eco32

[/] [eco32/] [tags/] [eco32-0.24/] [disk/] [tools/] [fs-EOS32/] [shfs/] [shfs.c] - Blame information for rev 211

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 17 hellwig
/*
2
 * shfs.c -- show an EOS32 file system
3
 */
4
 
5
 
6
#include <stdio.h>
7
#include <stdlib.h>
8
#include <string.h>
9
#include <stdarg.h>
10
#include <time.h>
11
 
12
 
13
#define SECTOR_SIZE     512     /* disk sector size in bytes */
14
#define BLOCK_SIZE      4096    /* disk block size in bytes */
15
#define SPB             (BLOCK_SIZE / SECTOR_SIZE)
16
#define LINE_SIZE       100     /* input line buffer size in bytes */
17
#define LINES_PER_BATCH 32      /* number of lines output in one batch */
18
 
19
#define NICINOD         500     /* number of free inodes in superblock */
20
#define NICFREE         500     /* number of free blocks in superblock */
21
#define INOPB           64      /* number of inodes per block */
22
#define DIRPB           64      /* number of directory entries per block */
23
#define DIRSIZ          60      /* max length of path name component */
24
 
25
#define IFMT            070000  /* type of file */
26
#define   IFREG         040000  /* regular file */
27
#define   IFDIR         030000  /* directory */
28
#define   IFCHR         020000  /* character special */
29
#define   IFBLK         010000  /* block special */
30
#define   IFFREE        000000  /* reserved (indicates free inode) */
31
#define ISUID           004000  /* set user id on execution */
32
#define ISGID           002000  /* set group id on execution */
33
#define ISVTX           001000  /* save swapped text even after use */
34
#define IUREAD          000400  /* user's read permission */
35
#define IUWRITE         000200  /* user's write permission */
36
#define IUEXEC          000100  /* user's execute permission */
37
#define IGREAD          000040  /* group's read permission */
38
#define IGWRITE         000020  /* group's write permission */
39
#define IGEXEC          000010  /* group's execute permission */
40
#define IOREAD          000004  /* other's read permission */
41
#define IOWRITE         000002  /* other's write permission */
42
#define IOEXEC          000001  /* other's execute permission */
43
 
44
 
45
typedef unsigned long EOS32_ino_t;
46
typedef unsigned long EOS32_daddr_t;
47
typedef unsigned long EOS32_off_t;
48
typedef long EOS32_time_t;
49
 
50
 
51
void error(char *fmt, ...) {
52
  va_list ap;
53
 
54
  va_start(ap, fmt);
55
  printf("Error: ");
56
  vprintf(fmt, ap);
57
  printf("\n");
58
  va_end(ap);
59
  exit(1);
60
}
61
 
62
 
63
unsigned long fsStart;          /* file system start sector */
64
 
65
 
66
void readBlock(FILE *disk,
67
               EOS32_daddr_t blockNum,
68
               unsigned char *blockBuffer) {
69
  fseek(disk, fsStart * SECTOR_SIZE + blockNum * BLOCK_SIZE, SEEK_SET);
70
  if (fread(blockBuffer, BLOCK_SIZE, 1, disk) != 1) {
71
    error("cannot read block %lu (0x%lX)", blockNum, blockNum);
72
  }
73
}
74
 
75
 
76
unsigned long get4Bytes(unsigned char *addr) {
77
  return (unsigned long) addr[0] << 24 |
78
         (unsigned long) addr[1] << 16 |
79
         (unsigned long) addr[2] <<  8 |
80
         (unsigned long) addr[3] <<  0;
81
}
82
 
83
 
84
int waitForReturn(void) {
85
  char line[LINE_SIZE];
86
 
87
  printf("press <enter> to continue, <esc> to break, q to quit: ");
88
  fflush(stdout);
89
  if (fgets(line, LINE_SIZE, stdin) == NULL) {
90
    printf("\n");
91
    exit(0);
92
  }
93
  if (line[0] == 'q') {
94
    exit(0);
95
  }
96
  if (line[0] == 0x1B) {
97
    return 1;
98
  }
99
  return 0;
100
}
101
 
102
 
103
int checkBatch(int numLines) {
104
  static int lines;
105
  int r;
106
 
107
  r = 0;
108
  if (numLines == 0) {
109
    /* initialize */
110
    lines = 0;
111
  } else {
112
    /* output numLines lines */
113
    lines += numLines;
114
    if (lines >= LINES_PER_BATCH) {
115
      r = waitForReturn();
116
      lines = 0;
117
    }
118
  }
119
  return r;
120
}
121
 
122
 
123
void rawBlock(unsigned char *p) {
124
  int i, j;
125
  unsigned char c;
126
 
127
  checkBatch(0);
128
  for (i = 0; i < BLOCK_SIZE / 16; i++) {
129
    printf("%04X   ", i * 16);
130
    for (j = 0; j < 16; j++) {
131
      c = p[i * 16 + j];
132
      printf("%02X ", c);
133
    }
134
    printf("   ");
135
    for (j = 0; j < 16; j++) {
136
      c = p[i * 16 + j];
137
      if (c < 0x20 || c >= 0x7F) {
138
        printf(".");
139
      } else {
140
        printf("%c", c);
141
      }
142
    }
143
    printf("\n");
144
    if (checkBatch(1)) return;
145
  }
146
}
147
 
148
 
149
void superBlock(unsigned char *p) {
150
  unsigned int magic;
151
  EOS32_daddr_t fsize;
152
  EOS32_daddr_t isize;
153
  EOS32_daddr_t freeblks;
154
  EOS32_ino_t freeinos;
155
  unsigned int ninode;
156
  EOS32_ino_t ino;
157
  unsigned int nfree;
158
  EOS32_daddr_t free;
159
  EOS32_time_t tim;
160
  char *dat;
161
  unsigned char flag;
162
  int i;
163
 
164
  checkBatch(0);
165
  magic = get4Bytes(p);
166
  p += 4;
167
  printf("magic number = %u (0x%08X)\n", magic, magic);
168
  if (checkBatch(1)) return;
169
  fsize = get4Bytes(p);
170
  p += 4;
171
  printf("file system size = %lu (0x%lX) blocks\n", fsize, fsize);
172
  if (checkBatch(1)) return;
173
  isize = get4Bytes(p);
174
  p += 4;
175
  printf("inode list size  = %lu (0x%lX) blocks\n", isize, isize);
176
  if (checkBatch(1)) return;
177
  freeblks = get4Bytes(p);
178
  p += 4;
179
  printf("free blocks = %lu (0x%lX)\n", freeblks, freeblks);
180
  if (checkBatch(1)) return;
181
  freeinos = get4Bytes(p);
182
  p += 4;
183
  printf("free inodes = %lu (0x%lX)\n", freeinos, freeinos);
184
  if (checkBatch(1)) return;
185
  ninode = get4Bytes(p);
186
  p += 4;
187
  printf("number of entries in free inode list = %u (0x%X)\n", ninode, ninode);
188
  if (checkBatch(1)) return;
189
  for (i = 0; i < NICINOD; i++) {
190
    ino = get4Bytes(p);
191
    p += 4;
192
    if (i < ninode) {
193
      printf("  free inode[%3d] = %lu (0x%lX)\n", i, ino, ino);
194
      if (checkBatch(1)) return;
195
    }
196
  }
197
  nfree = get4Bytes(p);
198
  p += 4;
199
  printf("number of entries in free block list = %u (0x%X)\n", nfree, nfree);
200
  if (checkBatch(1)) return;
201
  for (i = 0; i < NICFREE; i++) {
202
    free = get4Bytes(p);
203
    p += 4;
204
    if (i < nfree) {
205
      printf("  %s block[%3d] = %lu (0x%lX)\n",
206
             i == 0 ? "link" : "free", i, free, free);
207
      if (checkBatch(1)) return;
208
    }
209
  }
210
  tim = get4Bytes(p);
211
  p += 4;
212
  dat = ctime((time_t *) &tim);
213
  dat[strlen(dat) - 1] = '\0';
214
  printf("last super block update = %ld (%s)\n", tim, dat);
215
  if (checkBatch(1)) return;
216
  flag = *p++;
217
  printf("free list locked flag = %d\n", (int) flag);
218
  if (checkBatch(1)) return;
219
  flag = *p++;
220
  printf("inode list locked flag = %d\n", (int) flag);
221
  if (checkBatch(1)) return;
222
  flag = *p++;
223
  printf("super block modified flag = %d\n", (int) flag);
224
  if (checkBatch(1)) return;
225
  flag = *p++;
226
  printf("fs mounted read-only flag = %d\n", (int) flag);
227
  if (checkBatch(1)) return;
228
}
229
 
230
 
231
void inodeBlock(unsigned char *p) {
232
  unsigned int mode;
233
  unsigned int nlink;
234
  unsigned int uid;
235
  unsigned int gid;
236
  EOS32_time_t tim;
237
  char *dat;
238
  EOS32_off_t size;
239
  EOS32_daddr_t addr;
240
  int i, j;
241
 
242
  checkBatch(0);
243
  for (i = 0; i < INOPB; i++) {
244
    printf("inode %d:", i);
245
    mode = get4Bytes(p);
246
    p += 4;
247
    if (mode != 0) {
248
      printf("  type/mode = 0x%08X = ", mode);
249
      if ((mode & IFMT) == IFREG) {
250
        printf("-");
251
      } else
252
      if ((mode & IFMT) == IFDIR) {
253
        printf("d");
254
      } else
255
      if ((mode & IFMT) == IFCHR) {
256
        printf("c");
257
      } else
258
      if ((mode & IFMT) == IFBLK) {
259
        printf("b");
260
      } else {
261
        printf("?");
262
      }
263
      printf("%c", mode & IUREAD  ? 'r' : '-');
264
      printf("%c", mode & IUWRITE ? 'w' : '-');
265
      printf("%c", mode & IUEXEC  ? 'x' : '-');
266
      printf("%c", mode & IGREAD  ? 'r' : '-');
267
      printf("%c", mode & IGWRITE ? 'w' : '-');
268
      printf("%c", mode & IGEXEC  ? 'x' : '-');
269
      printf("%c", mode & IOREAD  ? 'r' : '-');
270
      printf("%c", mode & IOWRITE ? 'w' : '-');
271
      printf("%c", mode & IOEXEC  ? 'x' : '-');
272
      if (mode & ISUID) {
273
        printf(", set uid");
274
      }
275
      if (mode & ISGID) {
276
        printf(", set gid");
277
      }
278
      if (mode & ISVTX) {
279
        printf(", save text");
280
      }
281
    } else {
282
      printf("  <free>");
283
    }
284
    printf("\n");
285
    if (checkBatch(1)) return;
286
    nlink = get4Bytes(p);
287
    p += 4;
288
    if (mode != 0) {
289
      printf("  nlnk = %u (0x%08X)\n", nlink, nlink);
290
      if (checkBatch(1)) return;
291
    }
292
    uid = get4Bytes(p);
293
    p += 4;
294
    if (mode != 0) {
295
      printf("  uid  = %u (0x%08X)\n", uid, uid);
296
      if (checkBatch(1)) return;
297
    }
298
    gid = get4Bytes(p);
299
    p += 4;
300
    if (mode != 0) {
301
      printf("  gid  = %u (0x%08X)\n", gid, gid);
302
      if (checkBatch(1)) return;
303
    }
304
    tim = get4Bytes(p);
305
    p += 4;
306
    dat = ctime((time_t *) &tim);
307
    dat[strlen(dat) - 1] = '\0';
308
    if (mode != 0) {
309
      printf("  time inode created = %ld (%s)\n", tim, dat);
310
      if (checkBatch(1)) return;
311
    }
312
    tim = get4Bytes(p);
313
    p += 4;
314
    dat = ctime((time_t *) &tim);
315
    dat[strlen(dat) - 1] = '\0';
316
    if (mode != 0) {
317
      printf("  time last modified = %ld (%s)\n", tim, dat);
318
      if (checkBatch(1)) return;
319
    }
320
    tim = get4Bytes(p);
321
    p += 4;
322
    dat = ctime((time_t *) &tim);
323
    dat[strlen(dat) - 1] = '\0';
324
    if (mode != 0) {
325
      printf("  time last accessed = %ld (%s)\n", tim, dat);
326
      if (checkBatch(1)) return;
327
    }
328
    size = get4Bytes(p);
329
    p += 4;
330
    if (mode != 0) {
331
      printf("  size = %lu (0x%lX)\n", size, size);
332
      if (checkBatch(1)) return;
333
    }
334
    for (j = 0; j < 6; j++) {
335
      addr = get4Bytes(p);
336
      p += 4;
337
      if (mode != 0) {
338
        printf("  direct block[%1d] = %lu (0x%lX)\n", j, addr, addr);
339
        if (checkBatch(1)) return;
340
      }
341
    }
342
    addr = get4Bytes(p);
343
    p += 4;
344
    if (mode != 0) {
345
      printf("  single indirect = %lu (0x%lX)\n", addr, addr);
346
      if (checkBatch(1)) return;
347
    }
348
    addr = get4Bytes(p);
349
    p += 4;
350
    if (mode != 0) {
351
      printf("  double indirect = %lu (0x%lX)\n", addr, addr);
352
      if (checkBatch(1)) return;
353
    }
354
  }
355
}
356
 
357
 
358
void directoryBlock(unsigned char *p) {
359
  EOS32_ino_t ino;
360
  int i, j;
361
  unsigned char c;
362
 
363
  checkBatch(0);
364
  for (i = 0; i < DIRPB; i++) {
365
    printf("%02d:  ", i);
366
    ino = get4Bytes(p);
367
    p += 4;
368
    printf("inode = %lu (0x%lX)\n", ino, ino);
369
    if (checkBatch(1)) return;
370
    printf("     name  = ");
371
    if (*p == '\0') {
372
      printf("<empty>");
373
    } else {
374
      for (j = 0; j < DIRSIZ; j++) {
375
        c = *(p + j);
376
        if (c == '\0') {
377
          break;
378
        }
379
        if (c < 0x20 || c >= 0x7F) {
380
          printf(".");
381
        } else {
382
          printf("%c", c);
383
        }
384
      }
385
    }
386
    printf("\n");
387
    if (checkBatch(1)) return;
388
    p += DIRSIZ;
389
  }
390
}
391
 
392
 
393
void freeBlock(unsigned char *p) {
394
  unsigned int nfree;
395
  EOS32_daddr_t addr;
396
  int i;
397
 
398
  checkBatch(0);
399
  nfree = get4Bytes(p);
400
  p += 4;
401
  printf("nfree = %u (0x%X)\n", nfree, nfree);
402
  if (checkBatch(1)) return;
403
  for (i = 0; i < NICFREE; i++) {
404
    addr = get4Bytes(p);
405
    p += 4;
406
    if (i < nfree) {
407
      printf("  %s block[%3d] = %lu (0x%lX)\n",
408
             i == 0 ? "link" : "free", i, addr, addr);
409
      if (checkBatch(1)) return;
410
    }
411
  }
412
}
413
 
414
 
415
void indirectBlock(unsigned char *p) {
416
  EOS32_daddr_t addr;
417
  int i;
418
 
419
  checkBatch(0);
420
  for (i = 0; i < BLOCK_SIZE / sizeof(EOS32_daddr_t); i++) {
421
    addr = get4Bytes(p);
422
    p += 4;
423
    printf("block[%4d] = %lu (0x%lX)\n", i, addr, addr);
424
    if (checkBatch(1)) return;
425
  }
426
}
427
 
428
 
429
void help(void) {
430
  printf("Commands are:\n");
431
  printf("  h        help\n");
432
  printf("  q        quit\n");
433
  printf("  r        show block as raw data\n");
434
  printf("  s        show block as super block\n");
435
  printf("  i        show block as inode block\n");
436
  printf("  d        show block as directory block\n");
437
  printf("  f        show block as block on the free list\n");
438
  printf("  *        show block as indirect block\n");
439
  printf("  b <num>  set current block to <num>\n");
440
  printf("  +        increment current block\n");
441
  printf("  -        decrement current block\n");
442
  printf("  t <num>  translate inode <num> to block number\n");
443
  printf("           and relative inode number within block\n");
444
}
445
 
446
 
447
int parseNumber(char **pc, unsigned long *pi) {
448
  char *p;
449
  unsigned int base, dval;
450
  unsigned long n;
451
 
452
  p = *pc;
453
  while (*p == ' ' || *p == '\t') {
454
    p++;
455
  }
456
  if (*p == '\0' || *p == '\n') {
457
    printf("Error: number is missing!\n");
458
    return 0;
459
  }
460
  base = 10;
461
  if (*p == '0') {
462
    p++;
463
    if (*p != '\0' && *p != '\n') {
464
      if (*p == 'x' || *p == 'X') {
465
        base = 16;
466
        p++;
467
      } else {
468
        base = 8;
469
      }
470
    }
471
  }
472
  n = 0;
473
  while ((*p >= '0' && *p <= '9') ||
474
         (*p >= 'a' && *p <= 'f') ||
475
         (*p >= 'A' && *p <= 'F')) {
476
    if (*p >= '0' && *p <= '9') {
477
      dval = (*p - '0');
478
    } else
479
    if (*p >= 'a' && *p <= 'f') {
480
      dval = (*p - 'a' + 10);
481
    } else
482
    if (*p >= 'A' && *p <= 'F') {
483
      dval = (*p - 'A' + 10);
484
    }
485
    if (dval >= base) {
486
      printf("Error: digit value %d is illegal in number base %d\n",
487
             dval, base);
488
      return 0;
489
    }
490
    n *= base;
491
    n += dval;
492
    p++;
493
  }
494
  while (*p == ' ' || *p == '\t') {
495
    p++;
496
  }
497
  *pc = p;
498
  *pi = n;
499
  return 1;
500
}
501
 
502
 
503
int main(int argc, char *argv[]) {
504
  FILE *disk;
505
  unsigned long fsSize;
506
  int part;
507
  char *endptr;
508
  unsigned char partTable[SECTOR_SIZE];
509
  unsigned char *ptptr;
510
  unsigned long partType;
511
  EOS32_daddr_t numBlocks;
512
  EOS32_daddr_t currBlock;
513
  unsigned char blockBuffer[BLOCK_SIZE];
514
  char line[LINE_SIZE];
515
  int quit;
516
  char *p;
517
  unsigned long n;
518
 
519
  if (argc != 3) {
520
    printf("Usage: %s <disk> <partition>\n", argv[0]);
521
    printf("       <disk> is a disk image file name\n");
522
    printf("       <partition> is a partition number ");
523
    printf("(or '*' for the whole disk)\n");
524
    exit(1);
525
  }
526
  disk = fopen(argv[1], "rb");
527
  if (disk == NULL) {
528
    error("cannot open disk image file '%s'", argv[1]);
529
  }
530
  if (strcmp(argv[2], "*") == 0) {
531
    /* whole disk contains one single file system */
532
    fsStart = 0;
533
    fseek(disk, 0, SEEK_END);
534
    fsSize = ftell(disk) / SECTOR_SIZE;
535
  } else {
536
    /* argv[2] is partition number of file system */
537
    part = strtoul(argv[2], &endptr, 10);
538
    if (*endptr != '\0' || part < 0 || part > 15) {
539
      error("illegal partition number '%s'", argv[2]);
540
    }
541
    fseek(disk, 1 * SECTOR_SIZE, SEEK_SET);
542
    if (fread(partTable, 1, SECTOR_SIZE, disk) != SECTOR_SIZE) {
543
      error("cannot read partition table of disk '%s'", argv[1]);
544
    }
545
    ptptr = partTable + part * 32;
546
    partType = get4Bytes(ptptr + 0);
547
    if ((partType & 0x7FFFFFFF) != 0x00000058) {
548
      error("partition %d of disk '%s' does not contain an EOS32 file system",
549
            part, argv[1]);
550
    }
551
    fsStart = get4Bytes(ptptr + 4);
552
    fsSize = get4Bytes(ptptr + 8);
553
  }
554
  printf("File system has size %lu (0x%lX) sectors of %d bytes each.\n",
555
         fsSize, fsSize, SECTOR_SIZE);
556
  if (fsSize % SPB != 0) {
557
    printf("File system size is not a multiple of block size.\n");
558
  }
559
  numBlocks = fsSize / SPB;
560
  printf("This equals %lu (0x%lX) blocks of %d bytes each.\n",
561
         numBlocks, numBlocks, BLOCK_SIZE);
562
  if (numBlocks < 2) {
563
    error("file system has less than 2 blocks");
564
  }
565
  currBlock = 1;
566
  readBlock(disk, currBlock, blockBuffer);
567
  help();
568
  quit = 0;
569
  while (!quit) {
570
    printf("shfs [block %lu (0x%lX)] > ", currBlock, currBlock);
571
    fflush(stdout);
572
    if (fgets(line, LINE_SIZE, stdin) == NULL) {
573
      printf("\n");
574
      break;
575
    }
576
    if (line[0] == '\0' || line[0] == '\n') {
577
      continue;
578
    }
579
    switch (line[0]) {
580
      case 'h':
581
      case '?':
582
        help();
583
        break;
584
      case 'q':
585
        quit = 1;
586
        break;
587
      case 'r':
588
        rawBlock(blockBuffer);
589
        break;
590
      case 's':
591
        superBlock(blockBuffer);
592
        break;
593
      case 'i':
594
        inodeBlock(blockBuffer);
595
        break;
596
      case 'd':
597
        directoryBlock(blockBuffer);
598
        break;
599
      case 'f':
600
        freeBlock(blockBuffer);
601
        break;
602
      case '*':
603
        indirectBlock(blockBuffer);
604
        break;
605
      case 'b':
606
        p = line + 1;
607
        if (!parseNumber(&p, &n)) {
608
          break;
609
        }
610
        if (*p != '\0' && *p != '\n') {
611
          printf("Error: cannot parse block number!\n");
612
          break;
613
        }
614
        if (n >= numBlocks) {
615
          printf("Error: block number too big for file system!\n");
616
          break;
617
        }
618
        currBlock = n;
619
        readBlock(disk, currBlock, blockBuffer);
620
        break;
621
      case '+':
622
        n = currBlock + 1;
623
        if (n >= numBlocks) {
624
          printf("Error: block number too big for file system!\n");
625
          break;
626
        }
627
        currBlock = n;
628
        readBlock(disk, currBlock, blockBuffer);
629
        break;
630
      case '-':
631
        n = currBlock - 1;
632
        if (n >= numBlocks) {
633
          printf("Error: block number too big for file system!\n");
634
          break;
635
        }
636
        currBlock = n;
637
        readBlock(disk, currBlock, blockBuffer);
638
        break;
639
      case 't':
640
        p = line + 1;
641
        if (!parseNumber(&p, &n)) {
642
          break;
643
        }
644
        if (*p != '\0' && *p != '\n') {
645
          printf("Error: cannot parse inode number!\n");
646
          break;
647
        }
648
        printf("inode %lu (0x%lX) is in block %lu (0x%lX), inode %lu\n",
649
               n, n, n / INOPB + 2, n / INOPB + 2, n % INOPB);
650
        break;
651
      default:
652
        printf("Unknown command, type 'h' for help!\n");
653
        break;
654
    }
655
  }
656
  fclose(disk);
657
  return 0;
658
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.