home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sbin / restore / utilities.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-01  |  8.5 KB  |  393 lines

  1. /*
  2.  * Copyright (c) 1983 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[] = "@(#)utilities.c    5.10 (Berkeley) 12/2/92";
  36. #endif /* not lint */
  37.  
  38. #include <sys/param.h>
  39. #include <sys/stat.h>
  40.  
  41. #include <ufs/ufs/dinode.h>
  42. #include <ufs/ufs/dir.h>
  43.  
  44. #include <errno.h>
  45. #include <stdio.h>
  46. #include <stdlib.h>
  47. #include <string.h>
  48. #include <unistd.h>
  49.  
  50. #include "restore.h"
  51. #include "extern.h"
  52.  
  53. /*
  54.  * Insure that all the components of a pathname exist.
  55.  */
  56. void
  57. pathcheck(name)
  58.     char *name;
  59. {
  60.     register char *cp;
  61.     struct entry *ep;
  62.     char *start;
  63.  
  64.     start = index(name, '/');
  65.     if (start == 0)
  66.         return;
  67.     for (cp = start; *cp != '\0'; cp++) {
  68.         if (*cp != '/')
  69.             continue;
  70.         *cp = '\0';
  71.         ep = lookupname(name);
  72.         if (ep == NULL) {
  73.             ep = addentry(name, pathsearch(name)->d_ino, NODE);
  74.             newnode(ep);
  75.         }
  76.         ep->e_flags |= NEW|KEEP;
  77.         *cp = '/';
  78.     }
  79. }
  80.  
  81. /*
  82.  * Change a name to a unique temporary name.
  83.  */
  84. void
  85. mktempname(ep)
  86.     register struct entry *ep;
  87. {
  88.     char oldname[MAXPATHLEN];
  89.  
  90.     if (ep->e_flags & TMPNAME)
  91.         badentry(ep, "mktempname: called with TMPNAME");
  92.     ep->e_flags |= TMPNAME;
  93.     (void) strcpy(oldname, myname(ep));
  94.     freename(ep->e_name);
  95.     ep->e_name = savename(gentempname(ep));
  96.     ep->e_namlen = strlen(ep->e_name);
  97.     renameit(oldname, myname(ep));
  98. }
  99.  
  100. /*
  101.  * Generate a temporary name for an entry.
  102.  */
  103. char *
  104. gentempname(ep)
  105.     struct entry *ep;
  106. {
  107.     static char name[MAXPATHLEN];
  108.     struct entry *np;
  109.     long i = 0;
  110.  
  111.     for (np = lookupino(ep->e_ino);
  112.         np != NULL && np != ep; np = np->e_links)
  113.         i++;
  114.     if (np == NULL)
  115.         badentry(ep, "not on ino list");
  116.     (void) sprintf(name, "%s%d%d", TMPHDR, i, ep->e_ino);
  117.     return (name);
  118. }
  119.  
  120. /*
  121.  * Rename a file or directory.
  122.  */
  123. void
  124. renameit(from, to)
  125.     char *from, *to;
  126. {
  127.     if (!Nflag && rename(from, to) < 0) {
  128.         fprintf(stderr, "warning: cannot rename %s to %s: %s\n",
  129.             from, to, strerror(errno));
  130.         return;
  131.     }
  132.     vprintf(stdout, "rename %s to %s\n", from, to);
  133. }
  134.  
  135. /*
  136.  * Create a new node (directory).
  137.  */
  138. void
  139. newnode(np)
  140.     struct entry *np;
  141. {
  142.     char *cp;
  143.  
  144.     if (np->e_type != NODE)
  145.         badentry(np, "newnode: not a node");
  146.     cp = myname(np);
  147.     if (!Nflag && mkdir(cp, 0777) < 0) {
  148.         np->e_flags |= EXISTED;
  149.         fprintf(stderr, "warning: %s: %s\n", cp, strerror(errno));
  150.         return;
  151.     }
  152.     vprintf(stdout, "Make node %s\n", cp);
  153. }
  154.  
  155. /*
  156.  * Remove an old node (directory).
  157.  */
  158. void
  159. removenode(ep)
  160.     register struct entry *ep;
  161. {
  162.     char *cp;
  163.  
  164.     if (ep->e_type != NODE)
  165.         badentry(ep, "removenode: not a node");
  166.     if (ep->e_entries != NULL)
  167.         badentry(ep, "removenode: non-empty directory");
  168.     ep->e_flags |= REMOVED;
  169.     ep->e_flags &= ~TMPNAME;
  170.     cp = myname(ep);
  171.     if (!Nflag && rmdir(cp) < 0) {
  172.         fprintf(stderr, "warning: %s: %s\n", cp, strerror(errno));
  173.         return;
  174.     }
  175.     vprintf(stdout, "Remove node %s\n", cp);
  176. }
  177.  
  178. /*
  179.  * Remove a leaf.
  180.  */
  181. void
  182. removeleaf(ep)
  183.     register struct entry *ep;
  184. {
  185.     char *cp;
  186.  
  187.     if (ep->e_type != LEAF)
  188.         badentry(ep, "removeleaf: not a leaf");
  189.     ep->e_flags |= REMOVED;
  190.     ep->e_flags &= ~TMPNAME;
  191.     cp = myname(ep);
  192.     if (!Nflag && unlink(cp) < 0) {
  193.         fprintf(stderr, "warning: %s: %s\n", cp, strerror(errno));
  194.         return;
  195.     }
  196.     vprintf(stdout, "Remove leaf %s\n", cp);
  197. }
  198.  
  199. /*
  200.  * Create a link.
  201.  */
  202. int
  203. linkit(existing, new, type)
  204.     char *existing, *new;
  205.     int type;
  206. {
  207.  
  208.     if (type == SYMLINK) {
  209.         if (!Nflag && symlink(existing, new) < 0) {
  210.             fprintf(stderr,
  211.                 "warning: cannot create symbolic link %s->%s: %s\n",
  212.                 new, existing, strerror(errno));
  213.             return (FAIL);
  214.         }
  215.     } else if (type == HARDLINK) {
  216.         if (!Nflag && link(existing, new) < 0) {
  217.             fprintf(stderr,
  218.                 "warning: cannot create hard link %s->%s: %s\n",
  219.                 new, existing, strerror(errno));
  220.             return (FAIL);
  221.         }
  222.     } else {
  223.         panic("linkit: unknown type %d\n", type);
  224.         return (FAIL);
  225.     }
  226.     vprintf(stdout, "Create %s link %s->%s\n",
  227.         type == SYMLINK ? "symbolic" : "hard", new, existing);
  228.     return (GOOD);
  229. }
  230.  
  231. /*
  232.  * find lowest number file (above "start") that needs to be extracted
  233.  */
  234. ino_t
  235. lowerbnd(start)
  236.     ino_t start;
  237. {
  238.     register struct entry *ep;
  239.  
  240.     for ( ; start < maxino; start++) {
  241.         ep = lookupino(start);
  242.         if (ep == NULL || ep->e_type == NODE)
  243.             continue;
  244.         if (ep->e_flags & (NEW|EXTRACT))
  245.             return (start);
  246.     }
  247.     return (start);
  248. }
  249.  
  250. /*
  251.  * find highest number file (below "start") that needs to be extracted
  252.  */
  253. ino_t
  254. upperbnd(start)
  255.     ino_t start;
  256. {
  257.     register struct entry *ep;
  258.  
  259.     for ( ; start > ROOTINO; start--) {
  260.         ep = lookupino(start);
  261.         if (ep == NULL || ep->e_type == NODE)
  262.             continue;
  263.         if (ep->e_flags & (NEW|EXTRACT))
  264.             return (start);
  265.     }
  266.     return (start);
  267. }
  268.  
  269. /*
  270.  * report on a badly formed entry
  271.  */
  272. void
  273. badentry(ep, msg)
  274.     register struct entry *ep;
  275.     char *msg;
  276. {
  277.  
  278.     fprintf(stderr, "bad entry: %s\n", msg);
  279.     fprintf(stderr, "name: %s\n", myname(ep));
  280.     fprintf(stderr, "parent name %s\n", myname(ep->e_parent));
  281.     if (ep->e_sibling != NULL)
  282.         fprintf(stderr, "sibling name: %s\n", myname(ep->e_sibling));
  283.     if (ep->e_entries != NULL)
  284.         fprintf(stderr, "next entry name: %s\n", myname(ep->e_entries));
  285.     if (ep->e_links != NULL)
  286.         fprintf(stderr, "next link name: %s\n", myname(ep->e_links));
  287.     if (ep->e_next != NULL)
  288.         fprintf(stderr,
  289.             "next hashchain name: %s\n", myname(ep->e_next));
  290.     fprintf(stderr, "entry type: %s\n",
  291.         ep->e_type == NODE ? "NODE" : "LEAF");
  292.     fprintf(stderr, "inode number: %ld\n", ep->e_ino);
  293.     panic("flags: %s\n", flagvalues(ep));
  294. }
  295.  
  296. /*
  297.  * Construct a string indicating the active flag bits of an entry.
  298.  */
  299. char *
  300. flagvalues(ep)
  301.     register struct entry *ep;
  302. {
  303.     static char flagbuf[BUFSIZ];
  304.  
  305.     (void) strcpy(flagbuf, "|NIL");
  306.     flagbuf[0] = '\0';
  307.     if (ep->e_flags & REMOVED)
  308.         (void) strcat(flagbuf, "|REMOVED");
  309.     if (ep->e_flags & TMPNAME)
  310.         (void) strcat(flagbuf, "|TMPNAME");
  311.     if (ep->e_flags & EXTRACT)
  312.         (void) strcat(flagbuf, "|EXTRACT");
  313.     if (ep->e_flags & NEW)
  314.         (void) strcat(flagbuf, "|NEW");
  315.     if (ep->e_flags & KEEP)
  316.         (void) strcat(flagbuf, "|KEEP");
  317.     if (ep->e_flags & EXISTED)
  318.         (void) strcat(flagbuf, "|EXISTED");
  319.     return (&flagbuf[1]);
  320. }
  321.  
  322. /*
  323.  * Check to see if a name is on a dump tape.
  324.  */
  325. ino_t
  326. dirlookup(name)
  327.     char *name;
  328. {
  329.     ino_t ino;
  330.  
  331.     ino = pathsearch(name)->d_ino;
  332.     if (ino == 0 || TSTINO(ino, dumpmap) == 0)
  333.         fprintf(stderr, "%s is not on tape\n", name);
  334.     return (ino);
  335. }
  336.  
  337. /*
  338.  * Elicit a reply.
  339.  */
  340. int
  341. reply(question)
  342.     char *question;
  343. {
  344.     char c;
  345.  
  346.     do    {
  347.         fprintf(stderr, "%s? [yn] ", question);
  348.         (void) fflush(stderr);
  349.         c = getc(terminal);
  350.         while (c != '\n' && getc(terminal) != '\n')
  351.             if (feof(terminal))
  352.                 return (FAIL);
  353.     } while (c != 'y' && c != 'n');
  354.     if (c == 'y')
  355.         return (GOOD);
  356.     return (FAIL);
  357. }
  358.  
  359. /*
  360.  * handle unexpected inconsistencies
  361.  */
  362. #if __STDC__
  363. #include <stdarg.h>
  364. #else
  365. #include <varargs.h>
  366. #endif
  367.  
  368. void
  369. #if __STDC__
  370. panic(const char *fmt, ...)
  371. #else
  372. panic(fmt, va_alist)
  373.     char *fmt;
  374.     va_dcl
  375. #endif
  376. {
  377.     va_list ap;
  378. #if __STDC__
  379.     va_start(ap, fmt);
  380. #else
  381.     va_start(ap);
  382. #endif
  383.  
  384.     vfprintf(stderr, fmt, ap);
  385.     if (yflag)
  386.         return;
  387.     if (reply("abort") == GOOD) {
  388.         if (reply("dump core") == GOOD)
  389.             abort();
  390.         done(1);
  391.     }
  392. }
  393.