home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / CPM / UZI / UZI-UTIL.ARK / FSCK.C < prev    next >
C/C++ Source or Header  |  1988-12-22  |  17KB  |  860 lines

  1.  
  2. /**************************************************
  3. UZI (Unix Z80 Implementation) Utilities:  fsck.c
  4. ***************************************************/
  5.  
  6.  
  7. #include <stdio.h>
  8.  
  9. #include "unix.h"
  10. #include "extern.h"
  11.  
  12. #define MAXDEPTH 20   /* Maximum depth of directory tree to search */
  13.  
  14. /* This checks a filesystem */
  15.  
  16. int dev;
  17. struct filesys filsys;
  18.  
  19. char *bitmap;
  20. int16 *linkmap;
  21.  
  22.  
  23. char *strcpy(), *strcat(), *sprintf();
  24. char *daread();
  25. char *calloc();
  26. char *da_read();
  27.  
  28. main(argc,argv)
  29. int argc;
  30. char *argv[];
  31. {
  32.  
  33.     char *buf;
  34.  
  35.     if (argc != 2 || argv[1][0] < '0' || argv[1][0] > '9')
  36.     {
  37.     fprintf(stderr,"Usage: fsck device#\n");
  38.     exit(-1);
  39.     }
  40.  
  41.     dev = atoi(argv[1]);
  42.  
  43.     bufinit();
  44.     if (d_open(dev))
  45.     {
  46.     fprintf(stderr,"Can't open device number %d\n",dev);
  47.     exit(-1);
  48.     }
  49.  
  50.     /* Read in the super block. */
  51.  
  52.     buf = daread(1);
  53.     bcopy(buf, (char *)&filsys, sizeof(struct filesys));
  54.  
  55.     /* Verify the fsize and isize parameters */
  56.  
  57.     if (filsys.s_mounted != SMOUNTED)
  58.     {
  59.     printf("Device %d has invalid magic number %d. Fix? ",
  60.            dev, filsys.s_mounted);
  61.     if (!yes())
  62.         exit(-1);
  63.     filsys.s_mounted = SMOUNTED;
  64.     dwrite((blkno_t)1,(char *)&filsys);
  65.     }
  66.  
  67.     printf("Device %d has fsize = %d and isize = %d. Continue? ",
  68.         dev, filsys.s_fsize, filsys.s_isize);
  69.     if (!yes())
  70.     exit(-1);
  71.  
  72.     bitmap = calloc(filsys.s_fsize,sizeof(char));
  73.     linkmap = (int16 *)calloc(8 * filsys.s_isize, sizeof(int16));
  74.  
  75.     if (!bitmap || !linkmap)
  76.     {
  77.     fprintf(stderr,"Not enough memory.\n");
  78.     exit(-1);
  79.     }
  80.  
  81.     printf("Pass 1: Checking inodes.\n");
  82.     pass1();
  83.  
  84.     printf("Pass 2: Rebuilding free list.\n");
  85.     pass2();
  86.  
  87.     printf("Pass 3: Checking block allocation.\n");
  88.     pass3();
  89.  
  90.     printf("Pass 4: Checking directory entries.\n");
  91.     pass4();
  92.  
  93.     printf("Pass 5: Checking link counts.\n");
  94.     pass5();
  95.  
  96.     bufsync();
  97.     printf("Done.\n");
  98.  
  99.     exit(0);
  100. }
  101.  
  102.  
  103.  
  104. /* Pass 1 checks each inode independently for validity, zaps bad block
  105. numbers in the inodes, and builds the block allocation map. */
  106.  
  107. pass1()
  108. {
  109.     uint16 n;
  110.     struct dinode ino;
  111.     uint16 mode;
  112.     blkno_t b;
  113.     blkno_t bno;
  114.     uint16 icount;
  115.     blkno_t *buf;
  116.  
  117.     blkno_t getblkno();
  118.  
  119.     icount = 0;
  120.  
  121.     for (n = ROOTINODE; n < 8*(filsys.s_isize-2); ++n)
  122.     {
  123.     iread(n, &ino);
  124.     linkmap[n] = -1;
  125.  
  126.     if (ino.i_mode == 0)
  127.         continue;
  128.  
  129.     mode = ino.i_mode & F_MASK;
  130.  
  131.     /* Check mode */
  132.     if (mode != F_REG && mode != F_DIR && mode != F_BDEV && mode != F_CDEV)
  133.     {
  134.         printf("Inode %d with mode 0%o is not of correct type. Zap? ",
  135.             n, ino.i_mode);
  136.         if (yes())
  137.         {
  138.         ino.i_mode = 0;
  139.         ino.i_nlink = 0;
  140.         iwrite(n, &ino);
  141.         continue;
  142.         }
  143.     }
  144.  
  145.     linkmap[n] = 0;
  146.     ++icount;
  147.     /* Check size */
  148.  
  149.     if (ino.i_size.o_offset >= 512)
  150.     {
  151.         printf("Inode %d offset is too big with value of %d. Fix? ",
  152.             n,ino.i_size.o_offset);
  153.         if (yes())
  154.         {
  155.         while (ino.i_size.o_offset >= 512)
  156.         {
  157.             ino.i_size.o_offset -= 512;
  158.             ++ino.i_size.o_blkno;
  159.         }
  160.         iwrite(n,&ino);
  161.         }
  162.     }
  163.  
  164.  
  165.     if (ino.i_size.o_offset < 0)
  166.     {
  167.         printf("Inode %d offset is negative with value of %d. Fix? ",
  168.             n,ino.i_size.o_offset);
  169.         if (yes())
  170.         {
  171.         ino.i_size.o_offset = 0;
  172.         iwrite(n,&ino);
  173.         }
  174.     }
  175.  
  176.     
  177.     /* Check blocks and build free block map */
  178.     if (mode == F_REG || mode == F_DIR)
  179.     {
  180.         /* Check singly indirect blocks */
  181.  
  182.         for (b=18; b < 20; ++b)
  183.         {
  184.         if (ino.i_addr[b] != 0 && (ino.i_addr[b] < filsys.s_isize ||
  185.             ino.i_addr[b] >= filsys.s_fsize))
  186.         {
  187.             printf("Inode %d singly indirect block %d is out of range with value of %u. Zap? ",
  188.                 n, b, ino.i_addr[b]);
  189.             if (yes())
  190.             {
  191.             ino.i_addr[b] = 0;
  192.             iwrite(n, &ino);
  193.             }
  194.         }
  195.  
  196.         if (ino.i_addr[b] != 0 && ino.i_size.o_blkno < 18)
  197.         {
  198.             printf("Inode %d singly indirect block %d is past end of file with value of %u. Zap? ",
  199.                 n, b, ino.i_addr[b]);
  200.             if (yes())
  201.             {
  202.             ino.i_addr[b] = 0;
  203.             iwrite(n, &ino);
  204.             }
  205.         }
  206.         if (ino.i_addr[b] != 0)
  207.             bitmap[ino.i_addr[b]] = 1;
  208.         }
  209.  
  210.         /* Check the double indirect blocks */
  211.         if (ino.i_addr[19] != 0)
  212.         {
  213.         buf = (blkno_t *)daread(ino.i_addr[19]);
  214.         for (b=0; b < 256; ++b)
  215.         {
  216.             if (buf[b] != 0 && (buf[b] < filsys.s_isize ||
  217.                 buf[b] >= filsys.s_fsize))
  218.             {
  219.             printf("Inode %d doubly indirect block %d is out of range with value of %u. Zap? ",
  220.                 n, b, buf[b]);
  221.             if (yes())
  222.             {
  223.                 buf[b] = 0;
  224.                 dwrite(b, (char *)buf);
  225.             }
  226.             }
  227.             if (buf[b] != 0)
  228.             bitmap[buf[b]] = 1;
  229.             
  230.         }
  231.         }
  232.  
  233.  
  234.         /* Check the rest */
  235.         for (bno=0; bno <= ino.i_size.o_blkno; ++bno)
  236.         {
  237.         b = getblkno(&ino, bno);
  238.  
  239.             if (b != 0 && (b < filsys.s_isize ||
  240.             b >= filsys.s_fsize))
  241.         {
  242.             printf("Inode %d block %d is out of range with value of %u. Zap? ",
  243.                 n, bno, b);
  244.             if (yes())
  245.             {
  246.             setblkno(&ino, bno,0);
  247.             iwrite(n, &ino);
  248.             }
  249.         }
  250.  
  251.         if (b != 0)
  252.             bitmap[b] = 1;
  253.         }
  254.  
  255.     }
  256.     }
  257.  
  258.     /* Fix free inode count in super block */
  259.     if (filsys.s_tinode != 8*(filsys.s_isize-2) - ROOTINODE - icount)
  260.     {
  261.     printf("Free inode count in super block is %u should be %u. Fix? ",
  262.         filsys.s_tinode, 8*(filsys.s_isize-2) - ROOTINODE - icount);
  263.     
  264.     if (yes())
  265.     {
  266.         filsys.s_tinode = 8*(filsys.s_isize-2) - ROOTINODE - icount;
  267.         dwrite((blkno_t)1,(char *)&filsys);
  268.     }
  269.     }
  270. }
  271.             
  272.  
  273.  
  274. /* Clear inode free list, rebuild block free list using bit map. */
  275.  
  276. pass2()
  277. {
  278.     blkno_t j;
  279.     blkno_t oldtfree;
  280.  
  281.     printf("Rebuild free list? ");
  282.     if (!yes())
  283.     return;
  284.  
  285.     oldtfree = filsys.s_tfree;
  286.  
  287.     /* Initialize the super-block */
  288.  
  289.     filsys.s_ninode =  0;
  290.     filsys.s_nfree =  1;
  291.     filsys.s_free[0] =  0;
  292.     filsys.s_tfree =  0;
  293.  
  294.     /* Free each block, building the free list */
  295.  
  296.     for (j= filsys.s_fsize-1; j >= filsys.s_isize; --j)
  297.     {
  298.     if (bitmap[j] == 0)
  299.     {
  300.         if (filsys.s_nfree == 50)
  301.         {
  302.         dwrite(j, (char *)&filsys.s_nfree);
  303.         filsys.s_nfree = 0;
  304.         }
  305.  
  306.         ++filsys.s_tfree;
  307.         filsys.s_free[(filsys.s_nfree)++] = j;
  308.     }
  309.     }
  310.  
  311.     dwrite((blkno_t)1,(char *)&filsys);
  312.  
  313.     if (oldtfree != filsys.s_tfree)
  314.     printf("During free list regeneration s_tfree was changed to %d from %d.\n",
  315.         filsys.s_tfree, oldtfree);
  316.  
  317. }
  318.  
  319.  
  320.  
  321. /* Pass 3 finds and fixes multiply allocated blocks. */
  322. pass3()
  323. {
  324.     uint16 n;
  325.     struct dinode ino;
  326.     uint16 mode;
  327.     blkno_t b;
  328.     blkno_t bno;
  329.     blkno_t newno;
  330.     blkno_t blk_alloc();
  331.     blkno_t getblkno();
  332.  
  333.     for (b = filsys.s_isize; b < filsys.s_fsize; ++b)
  334.     bitmap[b] = 0;
  335.  
  336.     for (n = ROOTINODE; n < 8*(filsys.s_isize-2); ++n)
  337.     {
  338.     iread(n, &ino);
  339.  
  340.     mode = ino.i_mode & F_MASK;
  341.     if (mode != F_REG && mode != F_DIR)
  342.         continue;
  343.  
  344.     /* Check singly indirect blocks */
  345.  
  346.     for (b=18; b < 20; ++b)
  347.     {
  348.         if (ino.i_addr[b] != 0)
  349.         {
  350.         if (bitmap[ino.i_addr[b]] != 0)
  351.         {
  352.             printf("Indirect block %d in inode %u value %u multiply allocated. Fix? ", b, n, ino.i_addr[b]);
  353.             if (yes())
  354.             {
  355.             newno = blk_alloc(&filsys);
  356.             if (newno == 0)
  357.                 printf("Sorry... No more free blocks.\n");
  358.             else
  359.             {
  360.                 dwrite(newno,daread(ino.i_addr[b]));
  361.                 ino.i_addr[b] = newno;
  362.                 iwrite(n, &ino);
  363.             }
  364.             }
  365.         }
  366.         else
  367.             bitmap[ino.i_addr[b]] = 1;
  368.         }
  369.     }
  370.  
  371.     /* Check the rest */
  372.     for (bno=0; bno <= ino.i_size.o_blkno; ++bno)
  373.     {
  374.         b = getblkno(&ino, bno);
  375.  
  376.         if (b != 0)
  377.         {
  378.         if (bitmap[b] != 0)
  379.         {
  380.             printf("Block %d in inode %u value %u multiply allocated. Fix? ",
  381.                     bno, n, b);
  382.             if (yes())
  383.             {
  384.             newno = blk_alloc(&filsys);
  385.             if (newno == 0)
  386.                 printf("Sorry... No more free blocks.\n");
  387.             else
  388.             {
  389.                 dwrite(newno,daread(b));
  390.                 setblkno(&ino, bno, newno);
  391.                 iwrite(n, &ino);
  392.             }
  393.             }
  394.         }
  395.         else
  396.             bitmap[b] = 1;
  397.         }
  398.     }
  399.  
  400.     }
  401.  
  402. }
  403.  
  404. int depth;
  405.  
  406. /* Pass 4 traverses the directory tree, fixing bad directory entries
  407. and finding the actual number of references to each inode. */
  408.  
  409. pass4()
  410. {
  411.     depth = 0;
  412.     linkmap[ROOTINODE] = 1;
  413.     ckdir(ROOTINODE,ROOTINODE,"/");
  414.     if (depth != 0)
  415.     panic("Inconsistent depth");
  416. }
  417.  
  418.  
  419.  
  420. /* This recursively checks the directories */
  421. ckdir(inum, pnum, name)
  422. uint16 inum;
  423. uint16 pnum;
  424. char *name;
  425. {
  426.     struct dinode ino;
  427.     struct direct dentry;
  428.     uint16 j;
  429.     int c;
  430.     int nentries;
  431.     char ename[150];
  432.  
  433.     iread(inum, &ino);
  434.     if ((ino.i_mode & F_MASK) != F_DIR)
  435.     return;
  436.     ++depth;
  437.  
  438.     if (ino.i_size.o_offset % 16 != 0)
  439.     {
  440.     printf("Directory inode %d has improper length. Fix? ");
  441.     if (yes())
  442.     {
  443.         ino.i_size.o_offset &= (~0x0f);
  444.         ++ino.i_size.o_offset;
  445.         iwrite(inum, &ino);
  446.     }
  447.     }
  448.  
  449.     nentries = 8*ino.i_size.o_blkno + ino.i_size.o_offset/16;
  450.  
  451.     for (j=0; j < nentries; ++j)
  452.     {
  453.     dirread(&ino, j, &dentry);
  454.  
  455.     if (dentry.d_ino == 0)
  456.         continue;
  457.  
  458.     if (dentry.d_ino < ROOTINODE || dentry.d_ino >= 8*filsys.s_isize)
  459.     {
  460.         printf("Directory entry %s%-1.14s has out-of-range inode %u. Zap? ",
  461.            name, dentry.d_name, dentry.d_ino);
  462.         if (yes())
  463.         {
  464.         dentry.d_ino = 0;
  465.         dentry.d_name[0] = '\0';
  466.         dirwrite(&ino, j, &dentry);
  467.         continue;
  468.         }
  469.     }
  470.  
  471.     if (dentry.d_ino && linkmap[dentry.d_ino] == -1)
  472.     {
  473.         printf("Directory entry %s%-1.14s points to bogus inode %u. Zap? ",
  474.            name, dentry.d_name, dentry.d_ino);
  475.         if (yes())
  476.         {
  477.         dentry.d_ino = 0;
  478.         dentry.d_name[0] = '\0';
  479.         dirwrite(&ino, j, &dentry);
  480.         continue;
  481.         }
  482.     }
  483.  
  484.     ++linkmap[dentry.d_ino];
  485.  
  486.     for (c=0; c<14 && dentry.d_name[c]; ++c)
  487.     {
  488.         if (dentry.d_name[c] == '/')
  489.         {
  490.         printf("Directory entry %s%-1.14s contains slash. Fix? ",
  491.                name, dentry.d_name);
  492.         if (yes())
  493.         {
  494.             dentry.d_name[c] = 'X';
  495.             dirwrite(&ino, j, &dentry);
  496.         }
  497.         }
  498.     }
  499.  
  500.     if (strncmp(dentry.d_name,".",14) == 0 && dentry.d_ino != inum)
  501.     {
  502.         printf("Dot entry %s%-1.14s points to wrong place. Fix? ",
  503.            name, dentry.d_name);
  504.         if (yes())
  505.         {
  506.         dentry.d_ino = inum;
  507.         dirwrite(&ino, j, &dentry);
  508.         }
  509.     }
  510.  
  511.     if (strncmp(dentry.d_name,"..",14) == 0 && dentry.d_ino != pnum)
  512.     {
  513.         printf("DotDot entry %s%-1.14s points to wrong place. Fix? ",
  514.            name, dentry.d_name);
  515.         if (yes())
  516.         {
  517.         dentry.d_ino = pnum;
  518.         dirwrite(&ino, j, &dentry);
  519.         }
  520.     }
  521.  
  522.     if (dentry.d_ino != pnum && dentry.d_ino != inum && depth < MAXDEPTH) 
  523.     {
  524.         strcpy(ename,name);
  525.         strcat(ename,dentry.d_name);
  526.         strcat(ename,"/");
  527.         ckdir(dentry.d_ino,inum,ename);
  528.     }
  529.     }
  530.     --depth;
  531. }
  532.  
  533.  
  534. /* Pass 5 compares the link counts found in pass 4 with the inodes. */
  535.  
  536. pass5()
  537. {
  538.     uint16 n;
  539.     struct dinode ino;
  540.  
  541.     for (n = ROOTINODE; n < 8*(filsys.s_isize-2); ++n)
  542.     {
  543.     iread(n, &ino);
  544.  
  545.     if (ino.i_mode == 0)
  546.     {
  547.         if (linkmap[n] != -1)
  548.         panic("Inconsistent linkmap");
  549.         continue;
  550.     }
  551.  
  552.     if (linkmap[n] == -1 && ino.i_mode != 0)
  553.         panic("Inconsistent linkmap");
  554.  
  555.     if (linkmap[n] > 0 && ino.i_nlink != linkmap[n])
  556.     {
  557.         printf("Inode %d has link count %d should be %d. Fix? ",
  558.             n, ino.i_nlink, linkmap[n]);
  559.         if (yes())
  560.         {
  561.         ino.i_nlink = linkmap[n];
  562.         iwrite(n, &ino);
  563.         }
  564.     }
  565.  
  566.     if (linkmap[n] == 0)
  567.     {
  568.         if ((ino.i_mode&F_MASK) == F_BDEV ||
  569.             (ino.i_mode&F_MASK) == F_CDEV ||
  570.             (ino.i_size.o_blkno == 0 && ino.i_size.o_offset == 0))
  571.         {
  572.         printf("Useless inode %d with mode 0%o has become detached. Link count is %d. Zap? ",
  573.             n, ino.i_mode, ino.i_nlink);
  574.         if (yes())
  575.         {
  576.             ino.i_nlink = 0;
  577.             ino.i_mode = 0;
  578.             iwrite(n, &ino);
  579.             ++filsys.s_tinode;
  580.             dwrite((blkno_t)1,(char *)&filsys);
  581.         }
  582.         }
  583.         else
  584.         {
  585.         printf("Inode %d has become detached. Link count is %d. Fix? ",
  586.             n, ino.i_nlink);
  587.         if (yes())
  588.         {
  589.             ino.i_nlink = 1;
  590.             iwrite(n, &ino);
  591.             mkentry(n);
  592.         }
  593.         }
  594.     }
  595.     }
  596. }
  597.  
  598.  
  599. /* This makes an entry in "lost+found" for inode n */
  600.  
  601. mkentry(inum)
  602. uint16 inum;
  603. {
  604.     struct dinode rootino;
  605.     struct direct dentry;
  606.     uint16 d;
  607.  
  608.     iread(ROOTINODE,&rootino);
  609.     for (d=0; d < 32*rootino.i_size.o_blkno + rootino.i_size.o_offset/16; ++d)
  610.     {
  611.     dirread(&rootino,d,&dentry);
  612.     if (dentry.d_ino == 0 && dentry.d_name[0] == '\0')
  613.     {
  614.        dentry.d_ino = inum;
  615.        sprintf(dentry.d_name,"l+f%d",inum);
  616.        dirwrite(&rootino,d,&dentry);
  617.        return;
  618.     }
  619.     }
  620.     printf("Sorry... No empty slots in root directory.\n");
  621. }
  622.  
  623. /* Beginning of fsck1.c */
  624.  
  625. /* Getblkno gets a pointer index, and a number of a block in the file.
  626. It returns the number of the block on the disk.  A value of zero
  627. means an unallocated block. */
  628.  
  629. char *daread();
  630.  
  631. blkno_t 
  632. getblkno(ino,num)
  633. struct dinode *ino;
  634. blkno_t num;
  635. {
  636.  
  637.     blkno_t indb;
  638.     blkno_t dindb;
  639.     blkno_t *buf;
  640.  
  641.     if (num < 18) /* Direct block */
  642.     {
  643.     return(ino->i_addr[num]);
  644.     }
  645.  
  646.     if (num < 256+18)  /* Single indirect */
  647.     {
  648.     indb = ino->i_addr[18];
  649.     if (indb==0)
  650.         return(0);
  651.     buf = (blkno_t *)daread(indb);
  652.     return(buf[num - 18]);
  653.     }
  654.  
  655.     /* Double indirect */
  656.     indb = ino->i_addr[19];
  657.     if(indb==0)
  658.     return(0);
  659.  
  660.     buf = (blkno_t *)daread(indb);
  661.  
  662.     dindb = buf[ (num-(18+256)) >> 8];
  663.     buf = (blkno_t *)daread(dindb);
  664.  
  665.     return(buf[ (num-(18+256)) & 0x00ff]);
  666. }
  667.  
  668.  
  669. /* Setblkno sets the given block number of the given file to the given
  670. disk block number, possibly creating or modifiying the indirect blocks.
  671. A return of zero means there were no blocks available to create an 
  672. indirect block. This should never happen in fsck. */
  673.  
  674.  
  675. setblkno(ino,num,dnum)
  676. struct dinode *ino;
  677. blkno_t num;
  678. blkno_t dnum;
  679. {
  680.  
  681.     blkno_t indb;
  682.     blkno_t dindb;
  683.     blkno_t *buf;
  684.     char *zerobuf();
  685.  
  686.  
  687.     if (num < 18) /* Direct block */
  688.     {
  689.     ino->i_addr[num] = dnum;
  690.     }
  691.     else if (num < 256+18)  /* Single indirect */
  692.     {
  693.     indb = ino->i_addr[18];
  694.     if (indb==0)
  695.         panic("Missing indirect block");
  696.  
  697.     buf = (blkno_t *)daread(indb);
  698.     buf[num - 18] = dnum;
  699.     dwrite(indb,(char *)buf);
  700.     }
  701.     else /* Double indirect */
  702.     {
  703.     indb = ino->i_addr[19];
  704.     if (indb == 0)
  705.         panic("Missing indirect block");
  706.  
  707.     buf = (blkno_t *)daread(indb);
  708.     dindb = buf[ (num-(18+256)) >> 8];
  709.     if (dindb==0)
  710.         panic("Missing indirect block");
  711.  
  712.     buf = (blkno_t *)daread(dindb);
  713.     buf[ (num-(18+256)) & 0x00ff] = num;
  714.     dwrite(indb,(char *)buf);
  715.     }
  716.  
  717. }
  718.  
  719.  
  720. /* Blk_alloc allocates an unused block.
  721. A returned block number of zero means no more blocks. */
  722.  
  723. blkno_t
  724. blk_alloc(filsys)
  725. struct filesys *filsys;
  726. {
  727.  
  728.     blkno_t newno;
  729.     blkno_t *buf;
  730.     int16 j;
  731.  
  732.     newno = filsys->s_free[--filsys->s_nfree];
  733.     ifnot (newno)
  734.     {
  735.     ++filsys->s_nfree;
  736.     return(0);
  737.     }
  738.  
  739.     /* See if we must refill the s_free array */
  740.  
  741.     ifnot (filsys->s_nfree)
  742.     {
  743.     buf = (blkno_t *)daread(newno);
  744.     filsys->s_nfree = buf[0];
  745.     for (j=0; j < 50; j++)
  746.     {
  747.         filsys->s_free[j] = buf[j+1];
  748.     }
  749.     }
  750.  
  751.     --filsys->s_tfree;
  752.  
  753.     if (newno < filsys->s_isize || newno >= filsys->s_fsize)
  754.     {
  755.     printf("Free list is corrupt.  Did you rebuild it?\n");
  756.     return(0);
  757.     }
  758.  
  759.     dwrite((blkno_t)1,(char *)filsys);
  760.     return(newno);
  761. }
  762.  
  763.  
  764.  
  765. char *
  766. daread(blk)
  767. uint16 blk;
  768. {
  769.     char *buf;
  770.     if (da_read(dev,blk,&buf) != 512)
  771.     {
  772.         fprintf(stderr,"Read of block %d failed.\n",blk);
  773.         abort();
  774.     }
  775.     return(buf);
  776. }
  777.  
  778.  
  779.  
  780. dwrite(blk, addr)
  781. uint16 blk;
  782. char *addr;
  783. {
  784.     if (d_write(dev,blk,addr) != 512)
  785.     {
  786.         fprintf(stderr,"Write of block %d failed.\n",blk);
  787.         abort();
  788.     }
  789. }
  790.     
  791.     
  792.  
  793. iread(ino, buf)
  794. uint16 ino;
  795. struct dinode *buf;
  796. {
  797.     struct dinode *addr;
  798.  
  799.     addr = (struct dinode *) daread((ino>>3) + 2);
  800.     bcopy((char *)&addr[ino & 7], (char *)buf, sizeof(struct dinode));
  801. }
  802.  
  803.  
  804. iwrite(ino, buf)
  805. uint16 ino;
  806. struct dinode *buf;
  807. {
  808.     struct dinode *addr;
  809.  
  810.     addr = (struct dinode *) daread((ino>>3) + 2);
  811.     bcopy((char *)buf, (char *)&addr[ino & 7], sizeof(struct dinode));
  812.     dwrite((ino>>3) + 2,(char *)addr);
  813. }
  814.  
  815.  
  816. dirread(ino, j, dentry)
  817. struct dinode *ino;
  818. uint16 j;
  819. struct direct *dentry;
  820. {
  821.     blkno_t blkno;
  822.     char *buf;
  823.  
  824.     blkno = getblkno(ino,(blkno_t)j/32);
  825.     if (blkno == 0)
  826.     panic("Missing block in directory");
  827.     buf = daread(blkno);
  828.     bcopy(buf+(16*j), (char *)dentry, 16);
  829. }
  830.  
  831.  
  832. dirwrite(ino, j, dentry)
  833. struct dinode *ino;
  834. uint16 j;
  835. struct direct *dentry;
  836. {
  837.     blkno_t blkno;
  838.     char *buf;
  839.  
  840.     blkno = getblkno(ino,(blkno_t)j/32);
  841.     if (blkno == 0)
  842.     panic("Missing block in directory");
  843.     buf = daread(blkno);
  844.     bcopy((char *)dentry, buf+(16*j), 16);
  845.     dwrite(blkno,buf);
  846. }
  847.  
  848.  
  849. yes()
  850. {
  851.     char line[20];
  852.  
  853.     if (!fgets(line,sizeof(line),stdin) || (*line != 'y' && *line != 'Y'))
  854.     return(0);
  855.  
  856.     return(1);
  857. }
  858.  
  859.  
  860.