home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sbin / dump / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-07-16  |  13.7 KB  |  545 lines

  1. /*-
  2.  * Copyright (c) 1980, 1991 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. char copyright[] =
  36. "@(#) Copyright (c) 1980, 1991 The Regents of the University of California.\n\
  37.  All rights reserved.\n";
  38. #endif /* not lint */
  39.  
  40. #ifndef lint
  41. static char sccsid[] = "@(#)main.c    5.24 (Berkeley) 7/16/92";
  42. #endif /* not lint */
  43.  
  44. #ifdef sunos
  45. #include <stdio.h>
  46. #include <errno.h>
  47. #include <ctype.h>
  48. #include <sys/param.h>
  49. #include <sys/stat.h>
  50. #include <ufs/fs.h>
  51. #else
  52. #include <sys/param.h>
  53. #include <sys/time.h>
  54. #include <ufs/ffs/fs.h>
  55. #endif
  56. #include <ufs/ufs/dinode.h>
  57. #include <protocols/dumprestore.h>
  58. #include <signal.h>
  59. #ifdef __STDC__
  60. #include <time.h>
  61. #endif
  62. #include <fcntl.h>
  63. #include <fstab.h>
  64. #include <stdio.h>
  65. #ifdef __STDC__
  66. #include <unistd.h>
  67. #include <stdlib.h>
  68. #include <string.h>
  69. #endif
  70. #include "dump.h"
  71. #include "pathnames.h"
  72.  
  73. int    notify = 0;    /* notify operator flag */
  74. int    blockswritten = 0;    /* number of blocks written on current tape */
  75. int    tapeno = 0;    /* current tape number */
  76. int    density = 0;    /* density in bytes/0.1" */
  77. int    ntrec = NTREC;    /* # tape blocks in each tape record */
  78. int    cartridge = 0;    /* Assume non-cartridge tape */
  79. long    dev_bsize = 1;    /* recalculated below */
  80. long    blocksperfile;    /* output blocks per file */
  81. char    *host = NULL;    /* remote host (if any) */
  82. #ifdef RDUMP
  83. int    rmthost();
  84. #endif
  85.  
  86. main(argc, argv)
  87.     int argc;
  88.     char **argv;
  89. {
  90.     register ino_t ino;
  91.     register int dirty; 
  92.     register struct dinode *dp;
  93.     register struct    fstab *dt;
  94.     register char *map;
  95.     register char *cp;
  96.     int i, anydirskipped, bflag = 0, Tflag = 0;
  97.     float fetapes;
  98.     ino_t maxino;
  99.  
  100.     spcl.c_date = 0;
  101.     (void) time((time_t *) &(spcl.c_date));
  102.  
  103.     tsize = 0;    /* Default later, based on 'c' option for cart tapes */
  104.     tape = _PATH_DEFTAPE;
  105.     dumpdates = _PATH_DUMPDATES;
  106.     temp = _PATH_DTMP;
  107.     if (TP_BSIZE / DEV_BSIZE == 0 || TP_BSIZE % DEV_BSIZE != 0)
  108.         quit("TP_BSIZE must be a multiple of DEV_BSIZE\n");
  109.     level = '0';
  110.     argv++;
  111.     argc -= 2;
  112.     for (cp = *argv++; *cp; cp++) {
  113.         switch (*cp) {
  114.         case '-':
  115.             continue;
  116.  
  117.         case 'w':
  118.             lastdump('w');    /* tell us only what has to be done */
  119.             (void) exit(0);
  120.  
  121.         case 'W':        /* what to do */
  122.             lastdump('W');    /* tell us state of what is done */
  123.             (void) exit(0);    /* do nothing else */
  124.  
  125.         case 'f':        /* output file */
  126.             if (argc < 1)
  127.                 break;
  128.             tape = *argv++;
  129.             argc--;
  130.             continue;
  131.  
  132.         case 'd':        /* density, in bits per inch */
  133.             if (argc < 1)
  134.                 break;
  135.             density = atoi(*argv) / 10;
  136.             if (density < 1) {
  137.                 (void) fprintf(stderr, "bad density \"%s\"\n",
  138.                     *argv);
  139.                 Exit(X_ABORT);
  140.             }
  141.             argc--;
  142.             argv++;
  143.             if (density >= 625 && !bflag)
  144.                 ntrec = HIGHDENSITYTREC;
  145.             continue;
  146.  
  147.         case 's':        /* tape size, feet */
  148.             if (argc < 1)
  149.                 break;
  150.             tsize = atol(*argv);
  151.             if (tsize < 1) {
  152.                 (void) fprintf(stderr, "bad size \"%s\"\n",
  153.                     *argv);
  154.                 Exit(X_ABORT);
  155.             }
  156.             argc--;
  157.             argv++;
  158.             tsize *= 12 * 10;
  159.             continue;
  160.  
  161.         case 'T':        /* time of last dump */
  162.             if (argc < 1)
  163.                 break;
  164.             spcl.c_ddate = unctime(*argv);
  165.             if (spcl.c_ddate < 0) {
  166.                 (void) fprintf(stderr, "bad time \"%s\"\n",
  167.                     *argv);
  168.                 Exit(X_ABORT);
  169.             }
  170.             Tflag++;
  171.             lastlevel = '?';
  172.             argc--;
  173.             argv++;
  174.             continue;
  175.  
  176.         case 'b':        /* blocks per tape write */
  177.             if (argc < 1)
  178.                 break;
  179.             bflag++;
  180.             ntrec = atoi(*argv);
  181.             if (ntrec < 1) {
  182.                 (void) fprintf(stderr, "%s \"%s\"\n",
  183.                     "bad number of blocks per write ", *argv);
  184.                 Exit(X_ABORT);
  185.             }
  186.             argc--;
  187.             argv++;
  188.             continue;
  189.  
  190.         case 'B':        /* blocks per output file */
  191.             if (argc < 1)
  192.                 break;
  193.             blocksperfile = atol(*argv);
  194.             if (blocksperfile < 1) {
  195.                 (void) fprintf(stderr, "%s \"%s\"\n",
  196.                     "bad number of blocks per file ", *argv);
  197.                 Exit(X_ABORT);
  198.             }
  199.             argc--;
  200.             argv++;
  201.             continue;
  202.  
  203.         case 'c':        /* Tape is cart. not 9-track */
  204.             cartridge++;
  205.             continue;
  206.  
  207.         case '0':        /* dump level */
  208.         case '1':
  209.         case '2':
  210.         case '3':
  211.         case '4':
  212.         case '5':
  213.         case '6':
  214.         case '7':
  215.         case '8':
  216.         case '9':
  217.             level = *cp;
  218.             continue;
  219.  
  220.         case 'u':        /* update /etc/dumpdates */
  221.             uflag++;
  222.             continue;
  223.  
  224.         case 'n':        /* notify operators */
  225.             notify++;
  226.             continue;
  227.  
  228.         default:
  229.             (void) fprintf(stderr, "bad key '%c'\n", *cp);
  230.             Exit(X_ABORT);
  231.         }
  232.         (void) fprintf(stderr, "missing argument to '%c'\n", *cp);
  233.         Exit(X_ABORT);
  234.     }
  235.     if (argc < 1) {
  236.         (void) fprintf(stderr, "Must specify disk or filesystem\n");
  237.         Exit(X_ABORT);
  238.     } else {
  239.         disk = *argv++;
  240.         argc--;
  241.     }
  242.     if (argc >= 1) {
  243.         (void) fprintf(stderr, "Unknown arguments to dump:");
  244.         while (argc--)
  245.             (void) fprintf(stderr, " %s", *argv++);
  246.         (void) fprintf(stderr, "\n");
  247.         Exit(X_ABORT);
  248.     }
  249.     if (Tflag && uflag) {
  250.             (void) fprintf(stderr,
  251.             "You cannot use the T and u flags together.\n");
  252.         Exit(X_ABORT);
  253.     }
  254.     if (strcmp(tape, "-") == 0) {
  255.         pipeout++;
  256.         tape = "standard output";
  257.     }
  258.  
  259.     if (blocksperfile)
  260.         blocksperfile = blocksperfile / ntrec * ntrec; /* round down */
  261.     else {
  262.         /*
  263.          * Determine how to default tape size and density
  264.          *
  265.          *             density                tape size
  266.          * 9-track    1600 bpi (160 bytes/.1")    2300 ft.
  267.          * 9-track    6250 bpi (625 bytes/.1")    2300 ft.
  268.          * cartridge    8000 bpi (100 bytes/.1")    1700 ft.
  269.          *                        (450*4 - slop)
  270.          */
  271.         if (density == 0)
  272.             density = cartridge ? 100 : 160;
  273.         if (tsize == 0)
  274.             tsize = cartridge ? 1700L*120L : 2300L*120L;
  275.     }
  276.  
  277.     if (index(tape, ':')) {
  278.         host = tape;
  279.         tape = index(host, ':');
  280.         *tape++ = 0;
  281. #ifdef RDUMP
  282.         if (rmthost(host) == 0)
  283.             (void) exit(X_ABORT);
  284. #else
  285.         (void) fprintf(stderr, "remote dump not enabled\n");
  286.         (void) exit(X_ABORT);
  287. #endif
  288.     }
  289.     (void) setuid(getuid()); /* rmthost() is the only reason to be setuid */
  290.  
  291.     if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
  292.         signal(SIGHUP, sig);
  293.     if (signal(SIGTRAP, SIG_IGN) != SIG_IGN)
  294.         signal(SIGTRAP, sig);
  295.     if (signal(SIGFPE, SIG_IGN) != SIG_IGN)
  296.         signal(SIGFPE, sig);
  297.     if (signal(SIGBUS, SIG_IGN) != SIG_IGN)
  298.         signal(SIGBUS, sig);
  299.     if (signal(SIGSEGV, SIG_IGN) != SIG_IGN)
  300.         signal(SIGSEGV, sig);
  301.     if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
  302.         signal(SIGTERM, sig);
  303.     if (signal(SIGINT, interrupt) == SIG_IGN)
  304.         signal(SIGINT, SIG_IGN);
  305.  
  306.     set_operators();    /* /etc/group snarfed */
  307.     getfstab();        /* /etc/fstab snarfed */
  308.     /*
  309.      *    disk can be either the full special file name,
  310.      *    the suffix of the special file name,
  311.      *    the special name missing the leading '/',
  312.      *    the file system name with or without the leading '/'.
  313.      */
  314.     dt = fstabsearch(disk);
  315.     if (dt != 0) {
  316.         disk = rawname(dt->fs_spec);
  317.         (void) strncpy(spcl.c_dev, dt->fs_spec, NAMELEN);
  318.         (void) strncpy(spcl.c_filesys, dt->fs_file, NAMELEN);
  319.     } else {
  320.         (void) strncpy(spcl.c_dev, disk, NAMELEN);
  321.         (void) strncpy(spcl.c_filesys, "an unlisted file system",
  322.             NAMELEN);
  323.     }
  324.     (void) strcpy(spcl.c_label, "none");
  325.     (void) gethostname(spcl.c_host, NAMELEN);
  326.     spcl.c_level = level - '0';
  327.     spcl.c_type = TS_TAPE;
  328.     if (!Tflag)
  329.             getdumptime();        /* /etc/dumpdates snarfed */
  330.  
  331.     msg("Date of this level %c dump: %s", level,
  332.         spcl.c_date == 0 ? "the epoch\n" : ctime(&spcl.c_date));
  333.      msg("Date of last level %c dump: %s", lastlevel,
  334.         spcl.c_ddate == 0 ? "the epoch\n" : ctime(&spcl.c_ddate));
  335.     msg("Dumping %s ", disk);
  336.     if (dt != 0)
  337.         msgtail("(%s) ", dt->fs_file);
  338.     if (host)
  339.         msgtail("to %s on host %s\n", tape, host);
  340.     else
  341.         msgtail("to %s\n", tape);
  342.  
  343.     if ((diskfd = open(disk, O_RDONLY)) < 0) {
  344.         msg("Cannot open %s\n", disk);
  345.         Exit(X_ABORT);
  346.     }
  347.     sync();
  348.     sblock = (struct fs *)sblock_buf;
  349.     bread(SBOFF, (char *) sblock, SBSIZE);
  350.     if (sblock->fs_magic != FS_MAGIC)
  351.         quit("bad sblock magic number\n");
  352.     dev_bsize = sblock->fs_fsize / fsbtodb(sblock, 1);
  353.     dev_bshift = ffs(dev_bsize) - 1;
  354.     if (dev_bsize != (1 << dev_bshift))
  355.         quit("dev_bsize (%d) is not a power of 2", dev_bsize);
  356.     tp_bshift = ffs(TP_BSIZE) - 1;
  357.     if (TP_BSIZE != (1 << tp_bshift))
  358.         quit("TP_BSIZE (%d) is not a power of 2", TP_BSIZE);
  359.     if (sblock->fs_inodefmt >= FS_44INODEFMT)
  360.         spcl.c_flags |= DR_NEWINODEFMT;
  361.     maxino = sblock->fs_ipg * sblock->fs_ncg - 1;
  362.     mapsize = roundup(howmany(sblock->fs_ipg * sblock->fs_ncg, NBBY),
  363.         TP_BSIZE);
  364.     usedinomap = (char *)calloc((unsigned) mapsize, sizeof(char));
  365.     dumpdirmap = (char *)calloc((unsigned) mapsize, sizeof(char));
  366.     dumpinomap = (char *)calloc((unsigned) mapsize, sizeof(char));
  367.     tapesize = 3 * (howmany(mapsize * sizeof(char), TP_BSIZE) + 1);
  368.  
  369.     msg("mapping (Pass I) [regular files]\n");
  370.     anydirskipped = mapfiles(maxino, &tapesize);
  371.  
  372.     msg("mapping (Pass II) [directories]\n");
  373.     while (anydirskipped) {
  374.         anydirskipped = mapdirs(maxino, &tapesize);
  375.     }
  376.  
  377.     if (pipeout)
  378.         tapesize += 10;    /* 10 trailer blocks */
  379.     else {
  380.         if (blocksperfile)
  381.             fetapes = (float) tapesize / blocksperfile;
  382.         else if (cartridge) {
  383.             /* Estimate number of tapes, assuming streaming stops at
  384.                the end of each block written, and not in mid-block.
  385.                Assume no erroneous blocks; this can be compensated
  386.                for with an artificially low tape size. */
  387.             fetapes = 
  388.             (      tapesize    /* blocks */
  389.                 * TP_BSIZE    /* bytes/block */
  390.                 * (1.0/density)    /* 0.1" / byte */
  391.               +
  392.                   tapesize    /* blocks */
  393.                 * (1.0/ntrec)    /* streaming-stops per block */
  394.                 * 15.48        /* 0.1" / streaming-stop */
  395.             ) * (1.0 / tsize );    /* tape / 0.1" */
  396.         } else {
  397.             /* Estimate number of tapes, for old fashioned 9-track
  398.                tape */
  399.             int tenthsperirg = (density == 625) ? 3 : 7;
  400.             fetapes =
  401.             (      tapesize    /* blocks */
  402.                 * TP_BSIZE    /* bytes / block */
  403.                 * (1.0/density)    /* 0.1" / byte */
  404.               +
  405.                   tapesize    /* blocks */
  406.                 * (1.0/ntrec)    /* IRG's / block */
  407.                 * tenthsperirg    /* 0.1" / IRG */
  408.             ) * (1.0 / tsize );    /* tape / 0.1" */
  409.         }
  410.         etapes = fetapes;        /* truncating assignment */
  411.         etapes++;
  412.         /* count the dumped inodes map on each additional tape */
  413.         tapesize += (etapes - 1) *
  414.             (howmany(mapsize * sizeof(char), TP_BSIZE) + 1);
  415.         tapesize += etapes + 10;    /* headers + 10 trailer blks */
  416.     }
  417.     if (pipeout)
  418.         msg("estimated %ld tape blocks.\n", tapesize);
  419.     else
  420.         msg("estimated %ld tape blocks on %3.2f tape(s).\n",
  421.             tapesize, fetapes);
  422.  
  423.     /*
  424.      * Allocate tape buffer
  425.      */
  426.     if (!alloctape())
  427.         quit("can't allocate tape buffers - try a smaller blocking factor.\n");
  428.  
  429.     startnewtape(1);
  430.     (void) time((time_t *)&(tstart_writing));
  431.     dumpmap(usedinomap, TS_CLRI, maxino);
  432.  
  433.     msg("dumping (Pass III) [directories]\n");
  434.     for (map = dumpdirmap, ino = 0; ino < maxino; ) {
  435.         if ((ino % NBBY) == 0)
  436.             dirty = *map++;
  437.         else
  438.             dirty >>= 1;
  439.         ino++;
  440.         if ((dirty & 1) == 0)
  441.             continue;
  442.         /*
  443.          * Skip directory inodes deleted and maybe reallocated
  444.          */
  445.         dp = getino(ino);
  446.         if ((dp->di_mode & IFMT) != IFDIR)
  447.             continue;
  448.         (void) dumpino(dp, ino);
  449.     }
  450.  
  451.     msg("dumping (Pass IV) [regular files]\n");
  452.     for (map = dumpinomap, ino = 0; ino < maxino; ) {
  453.         if ((ino % NBBY) == 0)
  454.             dirty = *map++;
  455.         else
  456.             dirty >>= 1;
  457.         ino++;
  458.         if ((dirty & 1) == 0)
  459.             continue;
  460.         /*
  461.          * Skip inodes deleted and reallocated as directories.
  462.          */
  463.         dp = getino(ino);
  464.         if ((dp->di_mode & IFMT) == IFDIR)
  465.             continue;
  466.         (void) dumpino(dp, ino);
  467.     }
  468.  
  469.     spcl.c_type = TS_END;
  470.     for (i = 0; i < ntrec; i++)
  471.         writeheader(maxino);
  472.     if (pipeout)
  473.         msg("DUMP: %ld tape blocks\n",spcl.c_tapea);
  474.     else
  475.         msg("DUMP: %ld tape blocks on %d volumes(s)\n",
  476.             spcl.c_tapea, spcl.c_volume);
  477.     putdumptime();
  478.     trewind();
  479.     broadcast("DUMP IS DONE!\7\7\n");
  480.     msg("DUMP IS DONE\n");
  481.     Exit(X_FINOK);
  482.     /* NOTREACHED */
  483. }
  484.  
  485. void
  486. sig(signo)
  487.     int signo;
  488. {
  489.     switch(signo) {
  490.     case SIGALRM:
  491.     case SIGBUS:
  492.     case SIGFPE:
  493.     case SIGHUP:
  494.     case SIGTERM:
  495.     case SIGTRAP:
  496.         if (pipeout)
  497.             quit("Signal on pipe: cannot recover\n");
  498.         msg("Rewriting attempted as response to unknown signal.\n");
  499.         (void) fflush(stderr);
  500.         (void) fflush(stdout);
  501.         close_rewind();
  502.         (void) exit(X_REWRITE);
  503.         /* NOTREACHED */
  504.     case SIGSEGV:
  505.         msg("SIGSEGV: ABORTING!\n");
  506.         (void) signal(SIGSEGV, SIG_DFL);
  507.         (void) kill(0, SIGSEGV);
  508.         /* NOTREACHED */
  509.     }
  510. }
  511.  
  512. char *
  513. rawname(cp)
  514.     char *cp;
  515. {
  516.     static char rawbuf[32];
  517.     char *rindex();
  518.     char *dp = rindex(cp, '/');
  519.  
  520.     if (dp == 0)
  521.         return (0);
  522.     *dp = 0;
  523.     (void) strcpy(rawbuf, cp);
  524.     *dp = '/';
  525.     (void) strcat(rawbuf, "/r");
  526.     (void) strcat(rawbuf, dp+1);
  527.     return (rawbuf);
  528. }
  529.  
  530. #ifdef sunos
  531. char *
  532. strerror(errnum)
  533.     int errnum;
  534. {
  535.     extern int sys_nerr;
  536.     extern char *sys_errlist[];
  537.  
  538.     if (errnum < sys_nerr) {
  539.         return(sys_errlist[errnum]);
  540.     } else {
  541.         return("bogus errno in strerror");
  542.     }
  543. }
  544. #endif
  545.