home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sbin / newfs / mkfs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-07-03  |  31.9 KB  |  1,163 lines

  1. /*
  2.  * Copyright (c) 1980, 1989 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. static char sccsid[] = "@(#)mkfs.c    6.18 (Berkeley) 7/3/91";
  36. #endif /* not lint */
  37.  
  38. #ifndef STANDALONE
  39. #include <stdio.h>
  40. #include <a.out.h>
  41. #endif
  42.  
  43. #include <sys/param.h>
  44. #include <sys/time.h>
  45. #include <sys/wait.h>
  46. #include <sys/resource.h>
  47. #include <ufs/dinode.h>
  48. #include <ufs/fs.h>
  49. #include <ufs/dir.h>
  50. #include <sys/disklabel.h>
  51. #include <machine/endian.h>
  52.  
  53. /*
  54.  * make file system for cylinder-group style file systems
  55.  */
  56.  
  57. /*
  58.  * The size of a cylinder group is calculated by CGSIZE. The maximum size
  59.  * is limited by the fact that cylinder groups are at most one block.
  60.  * Its size is derived from the size of the maps maintained in the 
  61.  * cylinder group and the (struct cg) size.
  62.  */
  63. #define CGSIZE(fs) \
  64.     /* base cg */    (sizeof(struct cg) + \
  65.     /* blktot size */    (fs)->fs_cpg * sizeof(long) + \
  66.     /* blks size */    (fs)->fs_cpg * (fs)->fs_nrpos * sizeof(short) + \
  67.     /* inode map */    howmany((fs)->fs_ipg, NBBY) + \
  68.     /* block map */    howmany((fs)->fs_cpg * (fs)->fs_spc / NSPF(fs), NBBY))
  69.  
  70. /*
  71.  * We limit the size of the inode map to be no more than a
  72.  * third of the cylinder group space, since we must leave at
  73.  * least an equal amount of space for the block map.
  74.  *
  75.  * N.B.: MAXIPG must be a multiple of INOPB(fs).
  76.  */
  77. #define MAXIPG(fs)    roundup((fs)->fs_bsize * NBBY / 3, INOPB(fs))
  78.  
  79. #define UMASK        0755
  80. #define MAXINOPB    (MAXBSIZE / sizeof(struct dinode))
  81. #define POWEROF2(num)    (((num) & ((num) - 1)) == 0)
  82.  
  83. /*
  84.  * variables set up by front end.
  85.  */
  86. extern int    mfs;        /* run as the memory based filesystem */
  87. extern int    Nflag;        /* run mkfs without writing file system */
  88. extern int    fssize;        /* file system size */
  89. extern int    ntracks;    /* # tracks/cylinder */
  90. extern int    nsectors;    /* # sectors/track */
  91. extern int    nphyssectors;    /* # sectors/track including spares */
  92. extern int    secpercyl;    /* sectors per cylinder */
  93. extern int    sectorsize;    /* bytes/sector */
  94. extern int    rpm;        /* revolutions/minute of drive */
  95. extern int    interleave;    /* hardware sector interleave */
  96. extern int    trackskew;    /* sector 0 skew, per track */
  97. extern int    headswitch;    /* head switch time, usec */
  98. extern int    trackseek;    /* track-to-track seek, usec */
  99. extern int    fsize;        /* fragment size */
  100. extern int    bsize;        /* block size */
  101. extern int    cpg;        /* cylinders/cylinder group */
  102. extern int    cpgflg;        /* cylinders/cylinder group flag was given */
  103. extern int    minfree;    /* free space threshold */
  104. extern int    opt;        /* optimization preference (space or time) */
  105. extern int    density;    /* number of bytes per inode */
  106. extern int    maxcontig;    /* max contiguous blocks to allocate */
  107. extern int    rotdelay;    /* rotational delay between blocks */
  108. extern int    maxbpg;        /* maximum blocks per file in a cyl group */
  109. extern int    nrpos;        /* # of distinguished rotational positions */
  110. extern int    bbsize;        /* boot block size */
  111. extern int    sbsize;        /* superblock size */
  112. extern u_long    memleft;    /* virtual memory available */
  113. extern caddr_t    membase;    /* start address of memory based filesystem */
  114. extern caddr_t    malloc(), calloc();
  115.  
  116. union {
  117.     struct fs fs;
  118.     char pad[SBSIZE];
  119. } fsun;
  120. #define    sblock    fsun.fs
  121. struct    csum *fscs;
  122.  
  123. union {
  124.     struct cg cg;
  125.     char pad[MAXBSIZE];
  126. } cgun;
  127. #define    acg    cgun.cg
  128.  
  129. struct dinode zino[MAXBSIZE / sizeof(struct dinode)];
  130.  
  131. int    fsi, fso;
  132. daddr_t    alloc();
  133.  
  134. mkfs(pp, fsys, fi, fo)
  135.     struct partition *pp;
  136.     char *fsys;
  137.     int fi, fo;
  138. {
  139.     register long i, mincpc, mincpg, inospercg;
  140.     long cylno, rpos, blk, j, warn = 0;
  141.     long used, mincpgcnt, bpcg;
  142.     long mapcramped, inodecramped;
  143.     long postblsize, rotblsize, totalsbsize;
  144.     int ppid, status;
  145.     time_t utime;
  146.     void started();
  147.  
  148. #ifndef STANDALONE
  149.     time(&utime);
  150. #endif
  151.     if (mfs) {
  152.         ppid = getpid();
  153.         (void) signal(SIGUSR1, started);
  154.         if (i = fork()) {
  155.             if (i == -1) {
  156.                 perror("mfs");
  157.                 exit(10);
  158.             }
  159.             if (waitpid(i, &status, 0) != -1 && WIFEXITED(status))
  160.                 exit(WEXITSTATUS(status));
  161.             exit(11);
  162.             /* NOTREACHED */
  163.         }
  164.         (void)malloc(0);
  165.         if (fssize * sectorsize > memleft)
  166.             fssize = (memleft - 16384) / sectorsize;
  167.         if ((membase = malloc(fssize * sectorsize)) == 0)
  168.             exit(12);
  169.     }
  170.     fsi = fi;
  171.     fso = fo;
  172.     /*
  173.      * Validate the given file system size.
  174.      * Verify that its last block can actually be accessed.
  175.      */
  176.     if (fssize <= 0)
  177.         printf("preposterous size %d\n", fssize), exit(13);
  178.     wtfs(fssize - 1, sectorsize, (char *)&sblock);
  179.     /*
  180.      * collect and verify the sector and track info
  181.      */
  182.     sblock.fs_nsect = nsectors;
  183.     sblock.fs_ntrak = ntracks;
  184.     if (sblock.fs_ntrak <= 0)
  185.         printf("preposterous ntrak %d\n", sblock.fs_ntrak), exit(14);
  186.     if (sblock.fs_nsect <= 0)
  187.         printf("preposterous nsect %d\n", sblock.fs_nsect), exit(15);
  188.     /*
  189.      * collect and verify the block and fragment sizes
  190.      */
  191.     sblock.fs_bsize = bsize;
  192.     sblock.fs_fsize = fsize;
  193.     if (!POWEROF2(sblock.fs_bsize)) {
  194.         printf("block size must be a power of 2, not %d\n",
  195.             sblock.fs_bsize);
  196.         exit(16);
  197.     }
  198.     if (!POWEROF2(sblock.fs_fsize)) {
  199.         printf("fragment size must be a power of 2, not %d\n",
  200.             sblock.fs_fsize);
  201.         exit(17);
  202.     }
  203.     if (sblock.fs_fsize < sectorsize) {
  204.         printf("fragment size %d is too small, minimum is %d\n",
  205.             sblock.fs_fsize, sectorsize);
  206.         exit(18);
  207.     }
  208.     if (sblock.fs_bsize < MINBSIZE) {
  209.         printf("block size %d is too small, minimum is %d\n",
  210.             sblock.fs_bsize, MINBSIZE);
  211.         exit(19);
  212.     }
  213.     if (sblock.fs_bsize < sblock.fs_fsize) {
  214.         printf("block size (%d) cannot be smaller than fragment size (%d)\n",
  215.             sblock.fs_bsize, sblock.fs_fsize);
  216.         exit(20);
  217.     }
  218.     sblock.fs_bmask = ~(sblock.fs_bsize - 1);
  219.     sblock.fs_fmask = ~(sblock.fs_fsize - 1);
  220.     /*
  221.      * Planning now for future expansion.
  222.      */
  223. #    if (BYTE_ORDER == BIG_ENDIAN)
  224.         sblock.fs_qbmask.val[0] = 0;
  225.         sblock.fs_qbmask.val[1] = ~sblock.fs_bmask;
  226.         sblock.fs_qfmask.val[0] = 0;
  227.         sblock.fs_qfmask.val[1] = ~sblock.fs_fmask;
  228. #    endif /* BIG_ENDIAN */
  229. #    if (BYTE_ORDER == LITTLE_ENDIAN)
  230.         sblock.fs_qbmask.val[0] = ~sblock.fs_bmask;
  231.         sblock.fs_qbmask.val[1] = 0;
  232.         sblock.fs_qfmask.val[0] = ~sblock.fs_fmask;
  233.         sblock.fs_qfmask.val[1] = 0;
  234. #    endif /* LITTLE_ENDIAN */
  235.     for (sblock.fs_bshift = 0, i = sblock.fs_bsize; i > 1; i >>= 1)
  236.         sblock.fs_bshift++;
  237.     for (sblock.fs_fshift = 0, i = sblock.fs_fsize; i > 1; i >>= 1)
  238.         sblock.fs_fshift++;
  239.     sblock.fs_frag = numfrags(&sblock, sblock.fs_bsize);
  240.     for (sblock.fs_fragshift = 0, i = sblock.fs_frag; i > 1; i >>= 1)
  241.         sblock.fs_fragshift++;
  242.     if (sblock.fs_frag > MAXFRAG) {
  243.         printf("fragment size %d is too small, minimum with block size %d is %d\n",
  244.             sblock.fs_fsize, sblock.fs_bsize,
  245.             sblock.fs_bsize / MAXFRAG);
  246.         exit(21);
  247.     }
  248.     sblock.fs_nrpos = nrpos;
  249.     sblock.fs_nindir = sblock.fs_bsize / sizeof(daddr_t);
  250.     sblock.fs_inopb = sblock.fs_bsize / sizeof(struct dinode);
  251.     sblock.fs_nspf = sblock.fs_fsize / sectorsize;
  252.     for (sblock.fs_fsbtodb = 0, i = NSPF(&sblock); i > 1; i >>= 1)
  253.         sblock.fs_fsbtodb++;
  254.     sblock.fs_sblkno =
  255.         roundup(howmany(bbsize + sbsize, sblock.fs_fsize), sblock.fs_frag);
  256.     sblock.fs_cblkno = (daddr_t)(sblock.fs_sblkno +
  257.         roundup(howmany(sbsize, sblock.fs_fsize), sblock.fs_frag));
  258.     sblock.fs_iblkno = sblock.fs_cblkno + sblock.fs_frag;
  259.     sblock.fs_cgoffset = roundup(
  260.         howmany(sblock.fs_nsect, NSPF(&sblock)), sblock.fs_frag);
  261.     for (sblock.fs_cgmask = 0xffffffff, i = sblock.fs_ntrak; i > 1; i >>= 1)
  262.         sblock.fs_cgmask <<= 1;
  263.     if (!POWEROF2(sblock.fs_ntrak))
  264.         sblock.fs_cgmask <<= 1;
  265.     /*
  266.      * Validate specified/determined secpercyl
  267.      * and calculate minimum cylinders per group.
  268.      */
  269.     sblock.fs_spc = secpercyl;
  270.     for (sblock.fs_cpc = NSPB(&sblock), i = sblock.fs_spc;
  271.          sblock.fs_cpc > 1 && (i & 1) == 0;
  272.          sblock.fs_cpc >>= 1, i >>= 1)
  273.         /* void */;
  274.     mincpc = sblock.fs_cpc;
  275.     bpcg = sblock.fs_spc * sectorsize;
  276.     inospercg = roundup(bpcg / sizeof(struct dinode), INOPB(&sblock));
  277.     if (inospercg > MAXIPG(&sblock))
  278.         inospercg = MAXIPG(&sblock);
  279.     used = (sblock.fs_iblkno + inospercg / INOPF(&sblock)) * NSPF(&sblock);
  280.     mincpgcnt = howmany(sblock.fs_cgoffset * (~sblock.fs_cgmask) + used,
  281.         sblock.fs_spc);
  282.     mincpg = roundup(mincpgcnt, mincpc);
  283.     /*
  284.      * Insure that cylinder group with mincpg has enough space
  285.      * for block maps
  286.      */
  287.     sblock.fs_cpg = mincpg;
  288.     sblock.fs_ipg = inospercg;
  289.     mapcramped = 0;
  290.     while (CGSIZE(&sblock) > sblock.fs_bsize) {
  291.         mapcramped = 1;
  292.         if (sblock.fs_bsize < MAXBSIZE) {
  293.             sblock.fs_bsize <<= 1;
  294.             if ((i & 1) == 0) {
  295.                 i >>= 1;
  296.             } else {
  297.                 sblock.fs_cpc <<= 1;
  298.                 mincpc <<= 1;
  299.                 mincpg = roundup(mincpgcnt, mincpc);
  300.                 sblock.fs_cpg = mincpg;
  301.             }
  302.             sblock.fs_frag <<= 1;
  303.             sblock.fs_fragshift += 1;
  304.             if (sblock.fs_frag <= MAXFRAG)
  305.                 continue;
  306.         }
  307.         if (sblock.fs_fsize == sblock.fs_bsize) {
  308.             printf("There is no block size that");
  309.             printf(" can support this disk\n");
  310.             exit(22);
  311.         }
  312.         sblock.fs_frag >>= 1;
  313.         sblock.fs_fragshift -= 1;
  314.         sblock.fs_fsize <<= 1;
  315.         sblock.fs_nspf <<= 1;
  316.     }
  317.     /*
  318.      * Insure that cylinder group with mincpg has enough space for inodes
  319.      */
  320.     inodecramped = 0;
  321.     used *= sectorsize;
  322.     inospercg = roundup((mincpg * bpcg - used) / density, INOPB(&sblock));
  323.     sblock.fs_ipg = inospercg;
  324.     while (inospercg > MAXIPG(&sblock)) {
  325.         inodecramped = 1;
  326.         if (mincpc == 1 || sblock.fs_frag == 1 ||
  327.             sblock.fs_bsize == MINBSIZE)
  328.             break;
  329.         printf("With a block size of %d %s %d\n", sblock.fs_bsize,
  330.             "minimum bytes per inode is",
  331.             (mincpg * bpcg - used) / MAXIPG(&sblock) + 1);
  332.         sblock.fs_bsize >>= 1;
  333.         sblock.fs_frag >>= 1;
  334.         sblock.fs_fragshift -= 1;
  335.         mincpc >>= 1;
  336.         sblock.fs_cpg = roundup(mincpgcnt, mincpc);
  337.         if (CGSIZE(&sblock) > sblock.fs_bsize) {
  338.             sblock.fs_bsize <<= 1;
  339.             break;
  340.         }
  341.         mincpg = sblock.fs_cpg;
  342.         inospercg =
  343.             roundup((mincpg * bpcg - used) / density, INOPB(&sblock));
  344.         sblock.fs_ipg = inospercg;
  345.     }
  346.     if (inodecramped) {
  347.         if (inospercg > MAXIPG(&sblock)) {
  348.             printf("Minimum bytes per inode is %d\n",
  349.                 (mincpg * bpcg - used) / MAXIPG(&sblock) + 1);
  350.         } else if (!mapcramped) {
  351.             printf("With %d bytes per inode, ", density);
  352.             printf("minimum cylinders per group is %d\n", mincpg);
  353.         }
  354.     }
  355.     if (mapcramped) {
  356.         printf("With %d sectors per cylinder, ", sblock.fs_spc);
  357.         printf("minimum cylinders per group is %d\n", mincpg);
  358.     }
  359.     if (inodecramped || mapcramped) {
  360.         if (sblock.fs_bsize != bsize)
  361.             printf("%s to be changed from %d to %d\n",
  362.                 "This requires the block size",
  363.                 bsize, sblock.fs_bsize);
  364.         if (sblock.fs_fsize != fsize)
  365.             printf("\t%s to be changed from %d to %d\n",
  366.                 "and the fragment size",
  367.                 fsize, sblock.fs_fsize);
  368.         exit(23);
  369.     }
  370.     /* 
  371.      * Calculate the number of cylinders per group
  372.      */
  373.     sblock.fs_cpg = cpg;
  374.     if (sblock.fs_cpg % mincpc != 0) {
  375.         printf("%s groups must have a multiple of %d cylinders\n",
  376.             cpgflg ? "Cylinder" : "Warning: cylinder", mincpc);
  377.         sblock.fs_cpg = roundup(sblock.fs_cpg, mincpc);
  378.         if (!cpgflg)
  379.             cpg = sblock.fs_cpg;
  380.     }
  381.     /*
  382.      * Must insure there is enough space for inodes
  383.      */
  384.     sblock.fs_ipg = roundup((sblock.fs_cpg * bpcg - used) / density,
  385.         INOPB(&sblock));
  386.     while (sblock.fs_ipg > MAXIPG(&sblock)) {
  387.         inodecramped = 1;
  388.         sblock.fs_cpg -= mincpc;
  389.         sblock.fs_ipg = roundup((sblock.fs_cpg * bpcg - used) / density,
  390.             INOPB(&sblock));
  391.     }
  392.     /*
  393.      * Must insure there is enough space to hold block map
  394.      */
  395.     while (CGSIZE(&sblock) > sblock.fs_bsize) {
  396.         mapcramped = 1;
  397.         sblock.fs_cpg -= mincpc;
  398.         sblock.fs_ipg = roundup((sblock.fs_cpg * bpcg - used) / density,
  399.             INOPB(&sblock));
  400.     }
  401.     sblock.fs_fpg = (sblock.fs_cpg * sblock.fs_spc) / NSPF(&sblock);
  402.     if ((sblock.fs_cpg * sblock.fs_spc) % NSPB(&sblock) != 0) {
  403.         printf("panic (fs_cpg * fs_spc) % NSPF != 0");
  404.         exit(24);
  405.     }
  406.     if (sblock.fs_cpg < mincpg) {
  407.         printf("cylinder groups must have at least %d cylinders\n",
  408.             mincpg);
  409.         exit(25);
  410.     } else if (sblock.fs_cpg != cpg) {
  411.         if (!cpgflg)
  412.             printf("Warning: ");
  413.         else if (!mapcramped && !inodecramped)
  414.             exit(26);
  415.         if (mapcramped && inodecramped)
  416.             printf("Block size and bytes per inode restrict");
  417.         else if (mapcramped)
  418.             printf("Block size restricts");
  419.         else
  420.             printf("Bytes per inode restrict");
  421.         printf(" cylinders per group to %d.\n", sblock.fs_cpg);
  422.         if (cpgflg)
  423.             exit(27);
  424.     }
  425.     sblock.fs_cgsize = fragroundup(&sblock, CGSIZE(&sblock));
  426.     /*
  427.      * Now have size for file system and nsect and ntrak.
  428.      * Determine number of cylinders and blocks in the file system.
  429.      */
  430.     sblock.fs_size = fssize = dbtofsb(&sblock, fssize);
  431.     sblock.fs_ncyl = fssize * NSPF(&sblock) / sblock.fs_spc;
  432.     if (fssize * NSPF(&sblock) > sblock.fs_ncyl * sblock.fs_spc) {
  433.         sblock.fs_ncyl++;
  434.         warn = 1;
  435.     }
  436.     if (sblock.fs_ncyl < 1) {
  437.         printf("file systems must have at least one cylinder\n");
  438.         exit(28);
  439.     }
  440.     /*
  441.      * Determine feasability/values of rotational layout tables.
  442.      *
  443.      * The size of the rotational layout tables is limited by the
  444.      * size of the superblock, SBSIZE. The amount of space available
  445.      * for tables is calculated as (SBSIZE - sizeof (struct fs)).
  446.      * The size of these tables is inversely proportional to the block
  447.      * size of the file system. The size increases if sectors per track
  448.      * are not powers of two, because more cylinders must be described
  449.      * by the tables before the rotational pattern repeats (fs_cpc).
  450.      */
  451.     sblock.fs_interleave = interleave;
  452.     sblock.fs_trackskew = trackskew;
  453.     sblock.fs_npsect = nphyssectors;
  454.     sblock.fs_postblformat = FS_DYNAMICPOSTBLFMT;
  455.     sblock.fs_sbsize = fragroundup(&sblock, sizeof(struct fs));
  456.     if (sblock.fs_ntrak == 1) {
  457.         sblock.fs_cpc = 0;
  458.         goto next;
  459.     }
  460.     postblsize = sblock.fs_nrpos * sblock.fs_cpc * sizeof(short);
  461.     rotblsize = sblock.fs_cpc * sblock.fs_spc / NSPB(&sblock);
  462.     totalsbsize = sizeof(struct fs) + rotblsize;
  463.     if (sblock.fs_nrpos == 8 && sblock.fs_cpc <= 16) {
  464.         /* use old static table space */
  465.         sblock.fs_postbloff = (char *)(&sblock.fs_opostbl[0][0]) -
  466.             (char *)(&sblock.fs_link);
  467.         sblock.fs_rotbloff = &sblock.fs_space[0] -
  468.             (u_char *)(&sblock.fs_link);
  469.     } else {
  470.         /* use dynamic table space */
  471.         sblock.fs_postbloff = &sblock.fs_space[0] -
  472.             (u_char *)(&sblock.fs_link);
  473.         sblock.fs_rotbloff = sblock.fs_postbloff + postblsize;
  474.         totalsbsize += postblsize;
  475.     }
  476.     if (totalsbsize > SBSIZE ||
  477.         sblock.fs_nsect > (1 << NBBY) * NSPB(&sblock)) {
  478.         printf("%s %s %d %s %d.%s",
  479.             "Warning: insufficient space in super block for\n",
  480.             "rotational layout tables with nsect", sblock.fs_nsect,
  481.             "and ntrak", sblock.fs_ntrak,
  482.             "\nFile system performance may be impaired.\n");
  483.         sblock.fs_cpc = 0;
  484.         goto next;
  485.     }
  486.     sblock.fs_sbsize = fragroundup(&sblock, totalsbsize);
  487.     /*
  488.      * calculate the available blocks for each rotational position
  489.      */
  490.     for (cylno = 0; cylno < sblock.fs_cpc; cylno++)
  491.         for (rpos = 0; rpos < sblock.fs_nrpos; rpos++)
  492.             fs_postbl(&sblock, cylno)[rpos] = -1;
  493.     for (i = (rotblsize - 1) * sblock.fs_frag;
  494.          i >= 0; i -= sblock.fs_frag) {
  495.         cylno = cbtocylno(&sblock, i);
  496.         rpos = cbtorpos(&sblock, i);
  497.         blk = fragstoblks(&sblock, i);
  498.         if (fs_postbl(&sblock, cylno)[rpos] == -1)
  499.             fs_rotbl(&sblock)[blk] = 0;
  500.         else
  501.             fs_rotbl(&sblock)[blk] =
  502.                 fs_postbl(&sblock, cylno)[rpos] - blk;
  503.         fs_postbl(&sblock, cylno)[rpos] = blk;
  504.     }
  505. next:
  506.     /*
  507.      * Compute/validate number of cylinder groups.
  508.      */
  509.     sblock.fs_ncg = sblock.fs_ncyl / sblock.fs_cpg;
  510.     if (sblock.fs_ncyl % sblock.fs_cpg)
  511.         sblock.fs_ncg++;
  512.     sblock.fs_dblkno = sblock.fs_iblkno + sblock.fs_ipg / INOPF(&sblock);
  513.     i = MIN(~sblock.fs_cgmask, sblock.fs_ncg - 1);
  514.     if (cgdmin(&sblock, i) - cgbase(&sblock, i) >= sblock.fs_fpg) {
  515.         printf("inode blocks/cyl group (%d) >= data blocks (%d)\n",
  516.             cgdmin(&sblock, i) - cgbase(&sblock, i) / sblock.fs_frag,
  517.             sblock.fs_fpg / sblock.fs_frag);
  518.         printf("number of cylinders per cylinder group (%d) %s.\n",
  519.             sblock.fs_cpg, "must be increased");
  520.         exit(29);
  521.     }
  522.     j = sblock.fs_ncg - 1;
  523.     if ((i = fssize - j * sblock.fs_fpg) < sblock.fs_fpg &&
  524.         cgdmin(&sblock, j) - cgbase(&sblock, j) > i) {
  525.         if (j == 0) {
  526.             printf("Filesystem must have at least %d sectors\n",
  527.                 NSPF(&sblock) *
  528.                 (cgdmin(&sblock, 0) + 3 * sblock.fs_frag));
  529.             exit(30);
  530.         }
  531.         printf("Warning: inode blocks/cyl group (%d) >= data blocks (%d) in last\n",
  532.             (cgdmin(&sblock, j) - cgbase(&sblock, j)) / sblock.fs_frag,
  533.             i / sblock.fs_frag);
  534.         printf("    cylinder group. This implies %d sector(s) cannot be allocated.\n",
  535.             i * NSPF(&sblock));
  536.         sblock.fs_ncg--;
  537.         sblock.fs_ncyl -= sblock.fs_ncyl % sblock.fs_cpg;
  538.         sblock.fs_size = fssize = sblock.fs_ncyl * sblock.fs_spc /
  539.             NSPF(&sblock);
  540.         warn = 0;
  541.     }
  542.     if (warn && !mfs) {
  543.         printf("Warning: %d sector(s) in last cylinder unallocated\n",
  544.             sblock.fs_spc -
  545.             (fssize * NSPF(&sblock) - (sblock.fs_ncyl - 1)
  546.             * sblock.fs_spc));
  547.     }
  548.     /*
  549.      * fill in remaining fields of the super block
  550.      */
  551.     sblock.fs_csaddr = cgdmin(&sblock, 0);
  552.     sblock.fs_cssize =
  553.         fragroundup(&sblock, sblock.fs_ncg * sizeof(struct csum));
  554.     i = sblock.fs_bsize / sizeof(struct csum);
  555.     sblock.fs_csmask = ~(i - 1);
  556.     for (sblock.fs_csshift = 0; i > 1; i >>= 1)
  557.         sblock.fs_csshift++;
  558.     fscs = (struct csum *)calloc(1, sblock.fs_cssize);
  559.     sblock.fs_magic = FS_MAGIC;
  560.     sblock.fs_rotdelay = rotdelay;
  561.     sblock.fs_minfree = minfree;
  562.     sblock.fs_maxcontig = maxcontig;
  563.     sblock.fs_headswitch = headswitch;
  564.     sblock.fs_trkseek = trackseek;
  565.     sblock.fs_maxbpg = maxbpg;
  566.     sblock.fs_rps = rpm / 60;
  567.     sblock.fs_optim = opt;
  568.     sblock.fs_cgrotor = 0;
  569.     sblock.fs_cstotal.cs_ndir = 0;
  570.     sblock.fs_cstotal.cs_nbfree = 0;
  571.     sblock.fs_cstotal.cs_nifree = 0;
  572.     sblock.fs_cstotal.cs_nffree = 0;
  573.     sblock.fs_fmod = 0;
  574.     sblock.fs_ronly = 0;
  575.     /*
  576.      * Dump out summary information about file system.
  577.      */
  578.     if (!mfs) {
  579.         printf("%s:\t%d sectors in %d %s of %d tracks, %d sectors\n",
  580.             fsys, sblock.fs_size * NSPF(&sblock), sblock.fs_ncyl,
  581.             "cylinders", sblock.fs_ntrak, sblock.fs_nsect);
  582.         printf("\t%.1fMB in %d cyl groups (%d c/g, %.2fMB/g, %d i/g)\n",
  583.             (float)sblock.fs_size * sblock.fs_fsize * 1e-6,
  584.             sblock.fs_ncg, sblock.fs_cpg,
  585.             (float)sblock.fs_fpg * sblock.fs_fsize * 1e-6,
  586.             sblock.fs_ipg);
  587.     }
  588.     /*
  589.      * Now build the cylinders group blocks and
  590.      * then print out indices of cylinder groups.
  591.      */
  592.     if (!mfs)
  593.         printf("super-block backups (for fsck -b #) at:");
  594.     for (cylno = 0; cylno < sblock.fs_ncg; cylno++) {
  595.         initcg(cylno, utime);
  596.         if (mfs)
  597.             continue;
  598.         if (cylno % 9 == 0)
  599.             printf("\n");
  600.         printf(" %d,", fsbtodb(&sblock, cgsblock(&sblock, cylno)));
  601.     }
  602.     if (!mfs)
  603.         printf("\n");
  604.     if (Nflag && !mfs)
  605.         exit(0);
  606.     /*
  607.      * Now construct the initial file system,
  608.      * then write out the super-block.
  609.      */
  610.     fsinit(utime);
  611.     sblock.fs_time = utime;
  612.     wtfs(SBOFF / sectorsize, sbsize, (char *)&sblock);
  613.     for (i = 0; i < sblock.fs_cssize; i += sblock.fs_bsize)
  614.         wtfs(fsbtodb(&sblock, sblock.fs_csaddr + numfrags(&sblock, i)),
  615.             sblock.fs_cssize - i < sblock.fs_bsize ?
  616.                 sblock.fs_cssize - i : sblock.fs_bsize,
  617.             ((char *)fscs) + i);
  618.     /* 
  619.      * Write out the duplicate super blocks
  620.      */
  621.     for (cylno = 0; cylno < sblock.fs_ncg; cylno++)
  622.         wtfs(fsbtodb(&sblock, cgsblock(&sblock, cylno)),
  623.             sbsize, (char *)&sblock);
  624.     /*
  625.      * Update information about this partion in pack
  626.      * label, to that it may be updated on disk.
  627.      */
  628.     pp->p_fstype = FS_BSDFFS;
  629.     pp->p_fsize = sblock.fs_fsize;
  630.     pp->p_frag = sblock.fs_frag;
  631.     pp->p_cpg = sblock.fs_cpg;
  632.     /*
  633.      * Notify parent process of success.
  634.      * Dissociate from session and tty.
  635.      */
  636.     if (mfs) {
  637.         kill(ppid, SIGUSR1);
  638.         (void) setsid();
  639.         (void) close(0);
  640.         (void) close(1);
  641.         (void) close(2);
  642.         (void) chdir("/");
  643.     }
  644. }
  645.  
  646. /*
  647.  * Initialize a cylinder group.
  648.  */
  649. initcg(cylno, utime)
  650.     int cylno;
  651.     time_t utime;
  652. {
  653.     daddr_t cbase, d, dlower, dupper, dmax;
  654.     long i, j, s;
  655.     register struct csum *cs;
  656.  
  657.     /*
  658.      * Determine block bounds for cylinder group.
  659.      * Allow space for super block summary information in first
  660.      * cylinder group.
  661.      */
  662.     cbase = cgbase(&sblock, cylno);
  663.     dmax = cbase + sblock.fs_fpg;
  664.     if (dmax > sblock.fs_size)
  665.         dmax = sblock.fs_size;
  666.     dlower = cgsblock(&sblock, cylno) - cbase;
  667.     dupper = cgdmin(&sblock, cylno) - cbase;
  668.     if (cylno == 0)
  669.         dupper += howmany(sblock.fs_cssize, sblock.fs_fsize);
  670.     cs = fscs + cylno;
  671.     acg.cg_time = utime;
  672.     acg.cg_magic = CG_MAGIC;
  673.     acg.cg_cgx = cylno;
  674.     if (cylno == sblock.fs_ncg - 1)
  675.         acg.cg_ncyl = sblock.fs_ncyl % sblock.fs_cpg;
  676.     else
  677.         acg.cg_ncyl = sblock.fs_cpg;
  678.     acg.cg_niblk = sblock.fs_ipg;
  679.     acg.cg_ndblk = dmax - cbase;
  680.     acg.cg_cs.cs_ndir = 0;
  681.     acg.cg_cs.cs_nffree = 0;
  682.     acg.cg_cs.cs_nbfree = 0;
  683.     acg.cg_cs.cs_nifree = 0;
  684.     acg.cg_rotor = 0;
  685.     acg.cg_frotor = 0;
  686.     acg.cg_irotor = 0;
  687.     acg.cg_btotoff = &acg.cg_space[0] - (u_char *)(&acg.cg_link);
  688.     acg.cg_boff = acg.cg_btotoff + sblock.fs_cpg * sizeof(long);
  689.     acg.cg_iusedoff = acg.cg_boff + 
  690.         sblock.fs_cpg * sblock.fs_nrpos * sizeof(short);
  691.     acg.cg_freeoff = acg.cg_iusedoff + howmany(sblock.fs_ipg, NBBY);
  692.     acg.cg_nextfreeoff = acg.cg_freeoff +
  693.         howmany(sblock.fs_cpg * sblock.fs_spc / NSPF(&sblock), NBBY);
  694.     for (i = 0; i < sblock.fs_frag; i++) {
  695.         acg.cg_frsum[i] = 0;
  696.     }
  697.     bzero((caddr_t)cg_inosused(&acg), acg.cg_freeoff - acg.cg_iusedoff);
  698.     acg.cg_cs.cs_nifree += sblock.fs_ipg;
  699.     if (cylno == 0)
  700.         for (i = 0; i < ROOTINO; i++) {
  701.             setbit(cg_inosused(&acg), i);
  702.             acg.cg_cs.cs_nifree--;
  703.         }
  704.     for (i = 0; i < sblock.fs_ipg / INOPF(&sblock); i += sblock.fs_frag)
  705.         wtfs(fsbtodb(&sblock, cgimin(&sblock, cylno) + i),
  706.             sblock.fs_bsize, (char *)zino);
  707.     bzero((caddr_t)cg_blktot(&acg), acg.cg_boff - acg.cg_btotoff);
  708.     bzero((caddr_t)cg_blks(&sblock, &acg, 0),
  709.         acg.cg_iusedoff - acg.cg_boff);
  710.     bzero((caddr_t)cg_blksfree(&acg), acg.cg_nextfreeoff - acg.cg_freeoff);
  711.     if (cylno > 0) {
  712.         /*
  713.          * In cylno 0, beginning space is reserved
  714.          * for boot and super blocks.
  715.          */
  716.         for (d = 0; d < dlower; d += sblock.fs_frag) {
  717.             setblock(&sblock, cg_blksfree(&acg), d/sblock.fs_frag);
  718.             acg.cg_cs.cs_nbfree++;
  719.             cg_blktot(&acg)[cbtocylno(&sblock, d)]++;
  720.             cg_blks(&sblock, &acg, cbtocylno(&sblock, d))
  721.                 [cbtorpos(&sblock, d)]++;
  722.         }
  723.         sblock.fs_dsize += dlower;
  724.     }
  725.     sblock.fs_dsize += acg.cg_ndblk - dupper;
  726.     if (i = dupper % sblock.fs_frag) {
  727.         acg.cg_frsum[sblock.fs_frag - i]++;
  728.         for (d = dupper + sblock.fs_frag - i; dupper < d; dupper++) {
  729.             setbit(cg_blksfree(&acg), dupper);
  730.             acg.cg_cs.cs_nffree++;
  731.         }
  732.     }
  733.     for (d = dupper; d + sblock.fs_frag <= dmax - cbase; ) {
  734.         setblock(&sblock, cg_blksfree(&acg), d / sblock.fs_frag);
  735.         acg.cg_cs.cs_nbfree++;
  736.         cg_blktot(&acg)[cbtocylno(&sblock, d)]++;
  737.         cg_blks(&sblock, &acg, cbtocylno(&sblock, d))
  738.             [cbtorpos(&sblock, d)]++;
  739.         d += sblock.fs_frag;
  740.     }
  741.     if (d < dmax - cbase) {
  742.         acg.cg_frsum[dmax - cbase - d]++;
  743.         for (; d < dmax - cbase; d++) {
  744.             setbit(cg_blksfree(&acg), d);
  745.             acg.cg_cs.cs_nffree++;
  746.         }
  747.     }
  748.     sblock.fs_cstotal.cs_ndir += acg.cg_cs.cs_ndir;
  749.     sblock.fs_cstotal.cs_nffree += acg.cg_cs.cs_nffree;
  750.     sblock.fs_cstotal.cs_nbfree += acg.cg_cs.cs_nbfree;
  751.     sblock.fs_cstotal.cs_nifree += acg.cg_cs.cs_nifree;
  752.     *cs = acg.cg_cs;
  753.     wtfs(fsbtodb(&sblock, cgtod(&sblock, cylno)),
  754.         sblock.fs_bsize, (char *)&acg);
  755. }
  756.  
  757. /*
  758.  * initialize the file system
  759.  */
  760. struct dinode node;
  761.  
  762. #ifdef LOSTDIR
  763. #define PREDEFDIR 3
  764. #else
  765. #define PREDEFDIR 2
  766. #endif
  767.  
  768. struct direct root_dir[] = {
  769.     { ROOTINO, sizeof(struct direct), 1, "." },
  770.     { ROOTINO, sizeof(struct direct), 2, ".." },
  771. #ifdef LOSTDIR
  772.     { LOSTFOUNDINO, sizeof(struct direct), 10, "lost+found" },
  773. #endif
  774. };
  775. #ifdef LOSTDIR
  776. struct direct lost_found_dir[] = {
  777.     { LOSTFOUNDINO, sizeof(struct direct), 1, "." },
  778.     { ROOTINO, sizeof(struct direct), 2, ".." },
  779.     { 0, DIRBLKSIZ, 0, 0 },
  780. };
  781. #endif
  782. char buf[MAXBSIZE];
  783.  
  784. fsinit(utime)
  785.     time_t utime;
  786. {
  787.     int i;
  788.  
  789.     /*
  790.      * initialize the node
  791.      */
  792.     node.di_atime = utime;
  793.     node.di_mtime = utime;
  794.     node.di_ctime = utime;
  795. #ifdef LOSTDIR
  796.     /*
  797.      * create the lost+found directory
  798.      */
  799.     (void)makedir(lost_found_dir, 2);
  800.     for (i = DIRBLKSIZ; i < sblock.fs_bsize; i += DIRBLKSIZ)
  801.         bcopy(&lost_found_dir[2], &buf[i], DIRSIZ(&lost_found_dir[2]));
  802.     node.di_mode = IFDIR | UMASK;
  803.     node.di_nlink = 2;
  804.     node.di_size = sblock.fs_bsize;
  805.     node.di_db[0] = alloc(node.di_size, node.di_mode);
  806.     node.di_blocks = btodb(fragroundup(&sblock, node.di_size));
  807.     wtfs(fsbtodb(&sblock, node.di_db[0]), node.di_size, buf);
  808.     iput(&node, LOSTFOUNDINO);
  809. #endif
  810.     /*
  811.      * create the root directory
  812.      */
  813.     if (mfs)
  814.         node.di_mode = IFDIR | 01777;
  815.     else
  816.         node.di_mode = IFDIR | UMASK;
  817.     node.di_nlink = PREDEFDIR;
  818.     node.di_size = makedir(root_dir, PREDEFDIR);
  819.     node.di_db[0] = alloc(sblock.fs_fsize, node.di_mode);
  820.     node.di_blocks = btodb(fragroundup(&sblock, node.di_size));
  821.     wtfs(fsbtodb(&sblock, node.di_db[0]), sblock.fs_fsize, buf);
  822.     iput(&node, ROOTINO);
  823. }
  824.  
  825. /*
  826.  * construct a set of directory entries in "buf".
  827.  * return size of directory.
  828.  */
  829. makedir(protodir, entries)
  830.     register struct direct *protodir;
  831.     int entries;
  832. {
  833.     char *cp;
  834.     int i, spcleft;
  835.  
  836.     spcleft = DIRBLKSIZ;
  837.     for (cp = buf, i = 0; i < entries - 1; i++) {
  838.         protodir[i].d_reclen = DIRSIZ(&protodir[i]);
  839.         bcopy(&protodir[i], cp, protodir[i].d_reclen);
  840.         cp += protodir[i].d_reclen;
  841.         spcleft -= protodir[i].d_reclen;
  842.     }
  843.     protodir[i].d_reclen = spcleft;
  844.     bcopy(&protodir[i], cp, DIRSIZ(&protodir[i]));
  845.     return (DIRBLKSIZ);
  846. }
  847.  
  848. /*
  849.  * allocate a block or frag
  850.  */
  851. daddr_t
  852. alloc(size, mode)
  853.     int size;
  854.     int mode;
  855. {
  856.     int i, frag;
  857.     daddr_t d;
  858.  
  859.     rdfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize,
  860.         (char *)&acg);
  861.     if (acg.cg_magic != CG_MAGIC) {
  862.         printf("cg 0: bad magic number\n");
  863.         return (0);
  864.     }
  865.     if (acg.cg_cs.cs_nbfree == 0) {
  866.         printf("first cylinder group ran out of space\n");
  867.         return (0);
  868.     }
  869.     for (d = 0; d < acg.cg_ndblk; d += sblock.fs_frag)
  870.         if (isblock(&sblock, cg_blksfree(&acg), d / sblock.fs_frag))
  871.             goto goth;
  872.     printf("internal error: can't find block in cyl 0\n");
  873.     return (0);
  874. goth:
  875.     clrblock(&sblock, cg_blksfree(&acg), d / sblock.fs_frag);
  876.     acg.cg_cs.cs_nbfree--;
  877.     sblock.fs_cstotal.cs_nbfree--;
  878.     fscs[0].cs_nbfree--;
  879.     if (mode & IFDIR) {
  880.         acg.cg_cs.cs_ndir++;
  881.         sblock.fs_cstotal.cs_ndir++;
  882.         fscs[0].cs_ndir++;
  883.     }
  884.     cg_blktot(&acg)[cbtocylno(&sblock, d)]--;
  885.     cg_blks(&sblock, &acg, cbtocylno(&sblock, d))[cbtorpos(&sblock, d)]--;
  886.     if (size != sblock.fs_bsize) {
  887.         frag = howmany(size, sblock.fs_fsize);
  888.         fscs[0].cs_nffree += sblock.fs_frag - frag;
  889.         sblock.fs_cstotal.cs_nffree += sblock.fs_frag - frag;
  890.         acg.cg_cs.cs_nffree += sblock.fs_frag - frag;
  891.         acg.cg_frsum[sblock.fs_frag - frag]++;
  892.         for (i = frag; i < sblock.fs_frag; i++)
  893.             setbit(cg_blksfree(&acg), d + i);
  894.     }
  895.     wtfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize,
  896.         (char *)&acg);
  897.     return (d);
  898. }
  899.  
  900. /*
  901.  * Allocate an inode on the disk
  902.  */
  903. iput(ip, ino)
  904.     register struct dinode *ip;
  905.     register ino_t ino;
  906. {
  907.     struct dinode buf[MAXINOPB];
  908.     daddr_t d;
  909.     int c;
  910.  
  911.     c = itog(&sblock, ino);
  912.     rdfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize,
  913.         (char *)&acg);
  914.     if (acg.cg_magic != CG_MAGIC) {
  915.         printf("cg 0: bad magic number\n");
  916.         exit(31);
  917.     }
  918.     acg.cg_cs.cs_nifree--;
  919.     setbit(cg_inosused(&acg), ino);
  920.     wtfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize,
  921.         (char *)&acg);
  922.     sblock.fs_cstotal.cs_nifree--;
  923.     fscs[0].cs_nifree--;
  924.     if (ino >= sblock.fs_ipg * sblock.fs_ncg) {
  925.         printf("fsinit: inode value out of range (%d).\n", ino);
  926.         exit(32);
  927.     }
  928.     d = fsbtodb(&sblock, itod(&sblock, ino));
  929.     rdfs(d, sblock.fs_bsize, buf);
  930.     buf[itoo(&sblock, ino)] = *ip;
  931.     wtfs(d, sblock.fs_bsize, buf);
  932. }
  933.  
  934. /*
  935.  * Notify parent process that the filesystem has created itself successfully.
  936.  */
  937. void
  938. started()
  939. {
  940.  
  941.     exit(0);
  942. }
  943.  
  944. /*
  945.  * Replace libc function with one suited to our needs.
  946.  */
  947. caddr_t
  948. malloc(size)
  949.     register u_long size;
  950. {
  951.     u_long base, i;
  952.     static u_long pgsz;
  953.     struct rlimit rlp;
  954.  
  955.     if (pgsz == 0) {
  956.         base = sbrk(0);
  957.         pgsz = getpagesize() - 1;
  958.         i = (base + pgsz) &~ pgsz;
  959.         base = sbrk(i - base);
  960.         if (getrlimit(RLIMIT_DATA, &rlp) < 0)
  961.             perror("getrlimit");
  962.         rlp.rlim_cur = rlp.rlim_max;
  963.         if (setrlimit(RLIMIT_DATA, &rlp) < 0)
  964.             perror("setrlimit");
  965.         memleft = rlp.rlim_max - base;
  966.     }
  967.     size = (size + pgsz) &~ pgsz;
  968.     if (size > memleft)
  969.         size = memleft;
  970.     memleft -= size;
  971.     if (size == 0)
  972.         return (0);
  973.     return ((caddr_t)sbrk(size));
  974. }
  975.  
  976. /*
  977.  * Replace libc function with one suited to our needs.
  978.  */
  979. caddr_t
  980. realloc(ptr, size)
  981.     char *ptr;
  982.     u_long size;
  983. {
  984.  
  985.     /* always fail for now */
  986.     return ((caddr_t)0);
  987. }
  988.  
  989. /*
  990.  * Replace libc function with one suited to our needs.
  991.  */
  992. char *
  993. calloc(size, numelm)
  994.     u_long size, numelm;
  995. {
  996.     caddr_t base;
  997.  
  998.     size *= numelm;
  999.     base = malloc(size);
  1000.     bzero(base, size);
  1001.     return (base);
  1002. }
  1003.  
  1004. /*
  1005.  * Replace libc function with one suited to our needs.
  1006.  */
  1007. free(ptr)
  1008.     char *ptr;
  1009. {
  1010.     
  1011.     /* do not worry about it for now */
  1012. }
  1013.  
  1014. /*
  1015.  * read a block from the file system
  1016.  */
  1017. rdfs(bno, size, bf)
  1018.     daddr_t bno;
  1019.     int size;
  1020.     char *bf;
  1021. {
  1022.     int n;
  1023.  
  1024.     if (mfs) {
  1025.         bcopy(membase + bno * sectorsize, bf, size);
  1026.         return;
  1027.     }
  1028.     if (lseek(fsi, bno * sectorsize, 0) < 0) {
  1029.         printf("seek error: %ld\n", bno);
  1030.         perror("rdfs");
  1031.         exit(33);
  1032.     }
  1033.     n = read(fsi, bf, size);
  1034.     if(n != size) {
  1035.         printf("read error: %ld\n", bno);
  1036.         perror("rdfs");
  1037.         exit(34);
  1038.     }
  1039. }
  1040.  
  1041. /*
  1042.  * write a block to the file system
  1043.  */
  1044. wtfs(bno, size, bf)
  1045.     daddr_t bno;
  1046.     int size;
  1047.     char *bf;
  1048. {
  1049.     int n;
  1050.  
  1051.     if (mfs) {
  1052.         bcopy(bf, membase + bno * sectorsize, size);
  1053.         return;
  1054.     }
  1055.     if (Nflag)
  1056.         return;
  1057.     if (lseek(fso, bno * sectorsize, 0) < 0) {
  1058.         printf("seek error: %ld\n", bno);
  1059.         perror("wtfs");
  1060.         exit(35);
  1061.     }
  1062.     n = write(fso, bf, size);
  1063.     if(n != size) {
  1064.         printf("write error: %ld\n", bno);
  1065.         perror("wtfs");
  1066.         exit(36);
  1067.     }
  1068. }
  1069.  
  1070. /*
  1071.  * check if a block is available
  1072.  */
  1073. isblock(fs, cp, h)
  1074.     struct fs *fs;
  1075.     unsigned char *cp;
  1076.     int h;
  1077. {
  1078.     unsigned char mask;
  1079.  
  1080.     switch (fs->fs_frag) {
  1081.     case 8:
  1082.         return (cp[h] == 0xff);
  1083.     case 4:
  1084.         mask = 0x0f << ((h & 0x1) << 2);
  1085.         return ((cp[h >> 1] & mask) == mask);
  1086.     case 2:
  1087.         mask = 0x03 << ((h & 0x3) << 1);
  1088.         return ((cp[h >> 2] & mask) == mask);
  1089.     case 1:
  1090.         mask = 0x01 << (h & 0x7);
  1091.         return ((cp[h >> 3] & mask) == mask);
  1092.     default:
  1093. #ifdef STANDALONE
  1094.         printf("isblock bad fs_frag %d\n", fs->fs_frag);
  1095. #else
  1096.         fprintf(stderr, "isblock bad fs_frag %d\n", fs->fs_frag);
  1097. #endif
  1098.         return (0);
  1099.     }
  1100. }
  1101.  
  1102. /*
  1103.  * take a block out of the map
  1104.  */
  1105. clrblock(fs, cp, h)
  1106.     struct fs *fs;
  1107.     unsigned char *cp;
  1108.     int h;
  1109. {
  1110.     switch ((fs)->fs_frag) {
  1111.     case 8:
  1112.         cp[h] = 0;
  1113.         return;
  1114.     case 4:
  1115.         cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2));
  1116.         return;
  1117.     case 2:
  1118.         cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1));
  1119.         return;
  1120.     case 1:
  1121.         cp[h >> 3] &= ~(0x01 << (h & 0x7));
  1122.         return;
  1123.     default:
  1124. #ifdef STANDALONE
  1125.         printf("clrblock bad fs_frag %d\n", fs->fs_frag);
  1126. #else
  1127.         fprintf(stderr, "clrblock bad fs_frag %d\n", fs->fs_frag);
  1128. #endif
  1129.         return;
  1130.     }
  1131. }
  1132.  
  1133. /*
  1134.  * put a block into the map
  1135.  */
  1136. setblock(fs, cp, h)
  1137.     struct fs *fs;
  1138.     unsigned char *cp;
  1139.     int h;
  1140. {
  1141.     switch (fs->fs_frag) {
  1142.     case 8:
  1143.         cp[h] = 0xff;
  1144.         return;
  1145.     case 4:
  1146.         cp[h >> 1] |= (0x0f << ((h & 0x1) << 2));
  1147.         return;
  1148.     case 2:
  1149.         cp[h >> 2] |= (0x03 << ((h & 0x3) << 1));
  1150.         return;
  1151.     case 1:
  1152.         cp[h >> 3] |= (0x01 << (h & 0x7));
  1153.         return;
  1154.     default:
  1155. #ifdef STANDALONE
  1156.         printf("setblock bad fs_frag %d\n", fs->fs_frag);
  1157. #else
  1158.         fprintf(stderr, "setblock bad fs_frag %d\n", fs->fs_frag);
  1159. #endif
  1160.         return;
  1161.     }
  1162. }
  1163.