home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume2 / mdump < prev    next >
Internet Message Format  |  1986-11-30  |  40KB

  1. From: ihnp4!uiucdcs!uiucuxc.Uiuc.ARPA!paul
  2. Subject: mdump - multiple dump per tape utility
  3. Newsgroups: mod.sources
  4. Approved: john@genrad.UUCP
  5.  
  6. Mod.sources:  Volume 2, Issue 36
  7. Submitted by: ihnp4!uiucdcs!uiucuxc!paul (Paul Pomes)
  8.  
  9. Mdump and st were written to ease the pain of UNIX backups for our
  10. operations staff.  It's compressed the clock time needed to run a
  11. daily set of backups by almost two thirds.  The time savings are due
  12. to eliminating most of the tape mounts and waiting for tape rewinds.
  13. Listings are generated automatically though they can be suppressed.
  14. It's been in use here for about two months in its present form.
  15. VAX backups are done on local drives, the Pyramid 90x goes over an
  16. Ethernet to the VAX drives.  Most of the error recovery code was
  17. added because mt commands over the network would sometimes mysteriously
  18. disappear.  I've thought about alarm() timeouts but haven't come up
  19. with a reasonable implementation that wouldn't blow long rewinds out
  20. of the water by accident.  There's also the fact that it's working
  21. reasonably well and six other projects are on the fire.  Anyway I
  22. think this will be extremely useful for some sites, handy at others,
  23. and pretty window dressing at the rest.
  24.  
  25.          Paul Pomes
  26.  
  27. UUCP:     {ihnp4,pur-ee,convex}!uiucdcs!uiucuxc!paul
  28. ARPANET: paul%uiucuxc@uiuc.arpa
  29. CSNET:     paul%uiucuxc@uiuc.csnet
  30. ICBM:     40 07 N / 88 13 W
  31. US Mail: Univ of Illinois, CSO, 1304 W Springfield Ave, Urbana, IL  61801
  32.  
  33. #!/bin/sh
  34. # shar:    Shell Archiver
  35. #    Run the following text with /bin/sh to create:
  36. #    README
  37. #    Makefile
  38. #    dumptab.5
  39. #    dumptab.c
  40. #    dumptab.h
  41. #    etc.dumptab
  42. #    getdtent.3
  43. #    mdump.8
  44. #    mdump.c
  45. #    st.8
  46. #    st.c
  47. sed 's/^X//' << 'SHAR_EOF' > README
  48. XMdump and st together provide a coherent method for organizing multiple
  49. Xinstances of dump(8) onto a single magnetic tape volume.
  50. X
  51. XSeveral assumptions have been made: 1) filesystems are backed up on a
  52. Xdaily basis capturing changes made in the last 24 hours or since the
  53. Xlast weekly.  Weekly tapes capture all changes made since the last 
  54. Xlevel 0 dump.
  55. X
  56. XTo install, edit the #defines's in mdump.c to properly reflect the
  57. Xdesired commands.  The dump command issued via a system() call is
  58. Xbuilt in the wrt_dmp() procedure.
  59. X
  60. XCopy dumptab.h to /usr/include.
  61. X
  62. XEdit etc.dumptab to reflect the order desired in dumping filesystems
  63. Xand the day-of-week for the weekly dump.  I recommend putting the
  64. Xsmaller filesystems first on the tape.  Should the tape volume overflow,
  65. Xa smaller number of individual tapes will be needed to dump the
  66. Xremaining filesystems.
  67. X
  68. XCopy etc.dumptab to /etc/dumptab.
  69. X
  70. XRun "make", then "make install".
  71. X
  72. X         Paul Pomes
  73. X
  74. XUUCP:     {ihnp4,pur-ee,convex}!uiucdcs!uiucuxc!paul
  75. XARPANET: paul%uiucuxc@uiuc.arpa
  76. XCSNET:     paul%uiucuxc@uiuc.csnet
  77. XICBM:     40 07 N / 88 13 W
  78. XUS Mail: Univ of Illinois, CSO, 1304 W Springfield Ave, Urbana, IL  61801
  79. SHAR_EOF
  80. sed 's/^X//' << 'SHAR_EOF' > Makefile
  81. X# Makefile for mdump, a utility for putting multiple dump files onto a
  82. X# single tape volume.
  83. X#
  84. X# Written by Paul Pomes, University of Illinois, Computing Services Office
  85. X# Copyright 1985 by Paul Pomes and University of Illinois Board of Trustees
  86. X#
  87. X# This program may be freely reproduced and distributed provided the 
  88. X# copyright above is included in all copies.  It may not be included
  89. X# in any software product or distribution sold for profit without the
  90. X# permission of the author.
  91. X#
  92. X# UUCP:        {ihnp4,pur-ee,convex}!uiucdcs!uiucuxc!paul
  93. X# ARPANET:    paul%uiucuxc@uiuc.arpa
  94. X# CSNET:    paul%uiucuxc@uiuc.csnet
  95. X# US Mail:    Univ of Illinois, CSO, 1304 W Springfield Ave, Urbana, IL  61801
  96. X#
  97. X# $Header: Makefile,v 1.1 85/07/02 13:47:16 root Exp $
  98. X
  99. XCFLAGS=    -O
  100. XLDFLAGS=
  101. X
  102. Xall:    mdump st
  103. X
  104. Xmdump:    mdump.o dumptab.o
  105. X    cc mdump.o dumptab.o -o mdump ${LDFLAGS}
  106. X
  107. Xst:    st.o dumptab.o
  108. X    cc st.o dumptab.o -o st
  109. X
  110. Xclean:
  111. X    rm -f *.o mdump st make.log lint.out a.out
  112. X
  113. Xlint:
  114. X    lint -habcx mdump.c dumptab.c
  115. X    lint -habcx st.c dumptab.c
  116. X
  117. Xinstall: mdump st
  118. X    install -s mdump /etc
  119. X    install -s st /etc
  120. X    cp mdump.8 /usr/man/manl/mdump.l
  121. X    cp dumptab.5 /usr/man/manl/dumptab.l
  122. X    cp getdtent.3 /usr/man/manl/getdtent.l
  123. X    cp st.8 /usr/man/manl/st.l
  124. X
  125. Xdumptab.o:    dumptab.c dumptab.h
  126. X    cc ${CFLAGS} -c dumptab.c
  127. X
  128. Xmdump.o:    mdump.c dumptab.h
  129. X    cc ${CFLAGS} -c mdump.c
  130. X
  131. Xst.o:    st.c dumptab.h
  132. X    cc ${CFLAGS} -c st.c
  133. SHAR_EOF
  134. sed 's/^X//' << 'SHAR_EOF' > dumptab.5
  135. X.TH DUMPTAB 5 "UofI CSO"
  136. X.SH NAME
  137. Xdumptab \- multiple dump per tape description file
  138. X.SH DESCRIPTION
  139. X.I Dumptab
  140. Xcontains for each filesystem the
  141. Xfollowing information:
  142. X.HP 10
  143. Xname (filesystem name, contains no upper case)
  144. X.br
  145. X.ns
  146. X.HP 10
  147. Xtape file position (1 to n)
  148. X.br
  149. X.ns
  150. X.HP 10
  151. Xday of weekly backup (Sunday = 0)
  152. X.br
  153. X.ns
  154. Xdescriptive comment
  155. X.PP
  156. XThis is an ASCII file.  Each field within each filesystem's entry
  157. Xis separated from the next by a colon.
  158. XEach filesystem is separated from the next by a new-line.
  159. X.PP
  160. X.I Dumptab
  161. Xis used by
  162. X.IR mdump (8)
  163. Xand
  164. X.IR st (8)
  165. Xto define the order and backup schedule of filesystems.
  166. X.SH FILES
  167. X/etc/dumptab
  168. X.SH "SEE ALSO"
  169. Xgetdtent(3), mdump(8), st(8)
  170. X.SH BUGS
  171. XIt's not clear this is the best approach, however it was the fastest to
  172. Ximplement.
  173. SHAR_EOF
  174. sed 's/^X//' << 'SHAR_EOF' > dumptab.c
  175. X/*
  176. X * dumptab -- read the dumptab file
  177. X *
  178. X * Dumptab provides a set of routines similar in spirit to getpwent(3).
  179. X * getdtent() returns a pointer to a dumptab entry, getdtnam(name) returns
  180. X * a dumptab entry pointer for the named filesystem, getdtpos(position)
  181. X * returns a dumptab entry pointer for the filesystem at the indicated
  182. X * tape position, setdtent opens the dumptab file, and enddtent closes it.
  183. X *
  184. X * Written by Paul Pomes, University of Illinois, Computing Services Office
  185. X * Copyright 1985 by Paul Pomes and University of Illinois Board of Trustees
  186. X *
  187. X * This program may be freely reproduced and distributed provided the
  188. X * copyright above is included in all copies.  It may not be included
  189. X * in any software product or distribution sold for profit without the
  190. X * permission of the author.
  191. X *
  192. X * UUCP:    {ihnp4,pur-ee,convex}!uiucdcs!uiucuxc!paul
  193. X * ARPANET:    paul%uiucuxc@uiuc.arpa
  194. X * CSNET:    paul%uiucuxc@uiuc.csnet
  195. X * US Mail:    Univ of Illinois, CSO, 1304 W Springfield Ave, Urbana, IL  61801
  196. X *
  197. X * $Log:    dumptab.c,v $
  198. X * Revision 1.1  85/07/02  13:47:31  root
  199. X * Initial revision
  200. X * 
  201. X */
  202. X
  203. X#ifndef lint
  204. Xstatic char    RcsId[] = "$Header: dumptab.c,v 1.1 85/07/02 13:47:31 root Exp $";
  205. X#endif
  206. X
  207. X#include    <stdio.h>
  208. X#include    <dumptab.h>
  209. X
  210. Xstatic char *DUMPTAB = "/etc/dumptab";
  211. Xstatic FILE *dtf = NULL;
  212. Xstatic char line[BUFSIZ+1];
  213. Xstatic struct dumptab dumptab;
  214. X
  215. Xsetdtent()
  216. X{
  217. X    if (dtf == NULL)
  218. X        dtf = fopen(DUMPTAB, "r");
  219. X    else
  220. X        rewind(dtf);
  221. X}
  222. X
  223. Xenddtent()
  224. X{
  225. X    if (dtf != NULL) {
  226. X        (void) fclose(dtf);
  227. X        dtf = NULL;
  228. X    }
  229. X}
  230. X
  231. Xstatic char *
  232. Xdtskip(p)
  233. Xregister char *p;
  234. X{
  235. X    while (*p && *p != ':' && *p != '\n')
  236. X        p++;
  237. X    if (*p)
  238. X        *p++ = 0;
  239. X    return(p);
  240. X}
  241. X
  242. Xstruct dumptab *
  243. Xgetdtent()
  244. X{
  245. X    register char *p;
  246. X
  247. X    if (dtf == NULL) {
  248. X        if ((dtf = fopen( DUMPTAB, "r" )) == NULL)
  249. X            return(0);
  250. X    }
  251. X    p = fgets(line, BUFSIZ, dtf);
  252. X    if (p == NULL)
  253. X        return(0);
  254. X    dumptab.dt_name = p;
  255. X    p = dtskip(p);
  256. X    dumptab.dt_position = atoi(p);
  257. X    p = dtskip(p);
  258. X    dumptab.dt_weekly = atoi(p);
  259. X    p = dtskip(p);
  260. X    dumptab.dt_comment = p;
  261. X    while (*p && *p != '\n')
  262. X        p++;
  263. X    *p = '\0';
  264. X    return(&dumptab);
  265. X}
  266. X
  267. Xstruct dumptab *
  268. Xgetdtpos(num)
  269. Xregister num;
  270. X{
  271. X    register struct dumptab *p;
  272. X
  273. X    setdtent();
  274. X    while ((p = getdtent()) && p->dt_position != num)
  275. X        ;
  276. X    enddtent();
  277. X    return(p);
  278. X}
  279. X
  280. Xsetdtfile(file)
  281. Xchar *file;
  282. X{
  283. X    DUMPTAB = file;
  284. X}
  285. X
  286. Xstruct dumptab *
  287. Xgetdtnam(name)
  288. Xchar *name;
  289. X{
  290. X    register struct dumptab *p;
  291. X
  292. X    setdtent();
  293. X    while ((p = getdtent()) && strcmp(name, p->dt_name))
  294. X        ;
  295. X    enddtent();
  296. X    return(p);
  297. X}
  298. SHAR_EOF
  299. sed 's/^X//' << 'SHAR_EOF' > dumptab.h
  300. X/* $Header: dumptab.h,v 1.1 85/07/02 13:48:41 root Exp $ */
  301. X
  302. Xstruct    dumptab {
  303. X    char    *dt_name;
  304. X    int    dt_position;    /* 1 to n */
  305. X    int    dt_weekly;    /* Sunday = 0, Saturday = 6 */
  306. X    char    *dt_comment;    /* other information */
  307. X};
  308. X
  309. Xstruct dumptab *getdtent(), *getdtnam(), *getdtpos();
  310. SHAR_EOF
  311. sed 's/^X//' << 'SHAR_EOF' > etc.dumptab
  312. X/etc/dumptab:0:0:This file must be at position 0 as tape catalogue
  313. X/:1:2:The root filesystem, weekly dumped on Tuesday
  314. X/mnt:2:2:
  315. X/pub:3:5:
  316. X/cerlsys:4:1:
  317. X/cerl:5:3:
  318. X/acct:6:4:acct weekly dumped on Thursday, uses a new tape every month
  319. X/misc:7:4:
  320. X/srl:8:4:
  321. X/usr/spool:9:2:
  322. X/usr/src:10:3:
  323. X/irm:11:5:
  324. SHAR_EOF
  325. sed 's/^X//' << 'SHAR_EOF' > getdtent.3
  326. X.TH GETTDENT 3  "UofI CSO"
  327. X.SH NAME
  328. Xgetdtent, getdtnam, setdtent, enddtent \- get dumptab file entry
  329. X.SH SYNOPSIS
  330. X.nf
  331. X.B #include <dumptab.h>
  332. X.PP
  333. X.B struct passwd *getdtent()
  334. X.PP
  335. X.B struct passwd *getdtnam(name)
  336. X.B char *name;
  337. X.PP
  338. X.B struct passwd *getdtpos(position)
  339. X.B int position;
  340. X.PP
  341. X.B int setdtent()
  342. X.PP
  343. X.B int enddtent()
  344. X.fi
  345. X.SH DESCRIPTION
  346. X.IR Getdtent ,
  347. X.IR getdtnam ,
  348. Xand
  349. X.I getdtpos
  350. Xeach return a pointer to an object with the following structure
  351. Xcontaining the broken-out fields of a line in the dumptab file.
  352. X.RS
  353. X.PP
  354. X.nf
  355. X.so /usr/include/dumptab.h
  356. X.ft R
  357. X.ad
  358. X.fi
  359. X.RE
  360. X.PP
  361. X.I Getdtent
  362. Xreads the next line (opening the file if necessary);
  363. X.I setdtent
  364. Xrewinds the file;
  365. X.I enddtent
  366. Xcloses it.
  367. X.PP
  368. X.I Getdtnam
  369. Xsearches from the beginning until a matching
  370. X.I name
  371. Xis found (or until EOF is encountered).
  372. X.PP
  373. X.I Getdtpos
  374. Xsearches from the beginning until a matching
  375. X.I position
  376. X(file number on a tape volume) is found (or until EOF is encountered).
  377. X.SH FILES
  378. X/etc/dumptab
  379. X.SH "SEE ALSO"
  380. Xdumptab(5)
  381. X.SH DIAGNOSTICS
  382. XNull pointer
  383. X(0) returned on EOF or error.
  384. X.SH BUGS
  385. XAll information is contained in a static area so it must be copied if it is
  386. Xto be saved.
  387. SHAR_EOF
  388. sed 's/^X//' << 'SHAR_EOF' > mdump.8
  389. X.TH MDUMP 8 "UofI CSO"
  390. X.SH NAME
  391. Xmdump \- multiple dump per tape utility
  392. X.SH SYNOPSIS
  393. X.B mdump
  394. X[
  395. X.B \-w
  396. X] [
  397. X.B \-d
  398. X] [
  399. X.B \-l
  400. X] [
  401. X.B \-e
  402. X] [
  403. X\fB\-t \fIday-of-week\fR
  404. X] [
  405. X\fB\-f \fI[host:]/dev/rmtx\fR
  406. X]
  407. X.SH DESCRIPTION
  408. X.I Mdump
  409. Xsimplifies the backup procedure for systems with multiple filesystems
  410. Xby putting all daily and/or weekly backups onto a single tape.
  411. X.PP
  412. XThe order and selection of filesystems to be dumped is determined by
  413. X.I /etc/dumptab 
  414. Xand by the options
  415. X.B \-w
  416. Xand
  417. X.BR \-d .
  418. X.B \-w
  419. Xselects filesystems scheduled for weekly backup today while
  420. X.B \-d
  421. Xselects filesystems scheduled for daily backup.
  422. XSpecifying both switches causes daily and weekly backups to be selected.
  423. XA null file is inserted on the tape for non-selected filesystems
  424. Xto preserve file ordering.
  425. XThe
  426. X.IR st (8)
  427. Xcommand (set tape) will position the backup tape to the correct tape
  428. Xfile for restores.
  429. X.PP
  430. XThe backup device is selected with the
  431. X.B \-f
  432. Xoption.
  433. XRemote backup over the network is accomplished by specifying the device
  434. Xname in the same manner as
  435. X.IR rdump (8),
  436. Xe.g., uiucuxc:/dev/rmt0.
  437. X.PP
  438. XAfter
  439. X.I mdump
  440. Xhas finished writing the dump files,
  441. Xa listing of each dump will be created and sent to the \s-1IBM\s0 printers
  442. Xunless the
  443. X.B \-l
  444. Xoption is given to suppress the listings.
  445. X.PP
  446. XIn the case of positioning errors during the listing phase of
  447. X.IR mdump ,
  448. Xhanging rsh commands are the usual cause,
  449. X.B \-e
  450. Xwill execute the listing phase of
  451. X.I mdump
  452. Xonly.
  453. XAt least one of the flags
  454. X.B \-d
  455. Xand/or
  456. X.B \-w
  457. Xmust be specified in addition to the
  458. X.B \-e
  459. Xflag.
  460. X.PP
  461. XTo run
  462. X.I mdump
  463. Xas though it were a different day of the week, e.g.,
  464. Xcreate or list a Monday tape on Wednesday, the 
  465. X\fB\-t \fIday-of-week\fR
  466. Xflag is supplied where
  467. X.I day-of-week
  468. Xis one of mon, tue, wed, etc.
  469. X.SH NOTES
  470. XIn the case where
  471. X.I mdump
  472. Xfound no files to dump,
  473. Xthe subsequent listing phase will complain that
  474. Xit "Cannot find file dump list".
  475. X.I Mdump
  476. Xwill print a message saying that the list command exitted abnormally
  477. Xand ask whether to continue.
  478. XEntering 'y' directs
  479. X.I mdump
  480. Xto continue listing the other filesystems.
  481. XAny other response causes an exit.
  482. X.SH FILES
  483. X/etc/dumptab, /etc/dump
  484. X.SH "SEE ALSO"
  485. Xdumptab(5), dump(8), rdump(8), st(8)
  486. X.SH BUGS
  487. XIt's not clear this is the best approach, however it was the fastest to
  488. Ximplement.
  489. X.PP
  490. XNo provision is made for tape overflow.  This is an incentive to use 6250
  491. Xbpi drives.
  492. X.PP
  493. XAny tape error means restarting
  494. X.I mdump
  495. Xfrom the beginning.
  496. SHAR_EOF
  497. sed 's/^X//' << 'SHAR_EOF' > mdump.c
  498. X/*
  499. X * mdump -- put daily/weekly backups onto a single tape
  500. X *
  501. X * Mdump simplifies the tedious process of daily and weekly backups by
  502. X * putting all daily backups onto a single tape.  Weekly backups are
  503. X * performed the same way.  The /etc/dumptab file defines the file
  504. X * position on the tape each filesystem is written at and the day of
  505. X * the week the weekly backup is done.  Filesystems that are scheduled
  506. X * for a weekly backup are marked with an empty file on the daily tape
  507. X * so that file numbering remains constant.
  508. X *
  509. X * usage: mdump [-d] [-w] [-l] [-e] [-t day] [-f [host:]/dev/rmtx] [-db]
  510. X *
  511. X * -d    write a daily backup tape
  512. X *
  513. X * -w    write a weekly backup tape
  514. X *
  515. X * -l    suppress generation of the listing file
  516. X *
  517. X * -e    run listing code after an error exit
  518. X *
  519. X * -t day    run mdump for day (sun - sat) instead of today
  520. X *
  521. X * -f [host:]/dev/rmtx    tape device name.  If the host: prefix
  522. X *    is used, the backup tape will be written over the network to
  523. X *    the tape drive on the named host.
  524. X *
  525. X * -db    Write debug information to stderr
  526. X *
  527. X * Written by Paul Pomes, University of Illinois, Computing Services Office.
  528. X * Copyright 1985 by Paul Pomes and University of Illinois Board of Trustees
  529. X *
  530. X * This program may be freely reproduced and distributed provided the
  531. X * copyright notice above is included in all copies.  It may not be
  532. X * included in any software product or distribution sold for profit
  533. X * without the permission of the author.
  534. X *
  535. X * UUCP:    {ihnp4,pur-ee,convex}!uiucdcs!uiucuxc!paul
  536. X * ARPANET:    paul%uiucuxc@uiuc.arpa
  537. X * CSNET:    paul%uiucuxc@uiuc.csnet
  538. X * ICBM:    40 07 N / 88 13 W
  539. X * US Mail:    Univ of Illinois, CSO, 1304 W Springfield Ave, Urbana, IL  61801
  540. X *
  541. X * $Log:    mdump.c,v $
  542. X * Revision 1.7  85/08/07  16:30:08  paul
  543. X * Added bare-bones System 5 defines (index -> strchr, etc).  Large hacks
  544. X * needed to do the same for the mag tape ioctls.  Another day, far away.
  545. X * 
  546. X * Revision 1.6  85/08/07  16:03:57  root
  547. X * Added n switch to dump command so that operators are notified.
  548. X * Extremely effective annoyance feature.   -pbp
  549. X * 
  550. X * Revision 1.5  85/07/11  14:44:07  paul
  551. X * Added recovery question for restore listings of filesystems with no files.
  552. X * pbp
  553. X * 
  554. X * Revision 1.4  85/07/09  21:18:09  root
  555. X * *** empty log message ***
  556. X * 
  557. X * Revision 1.3  85/07/05  17:13:39  root
  558. X * Added -t day-of-week flag for enhanced error recovery.   -pbp
  559. X * 
  560. X * Revision 1.2  85/07/03  23:23:04  root
  561. X * Added -e flag to force listings after "rsh mt" errors.   -pbp
  562. X * 
  563. X * Revision 1.1  85/07/02  13:47:46  root
  564. X * Initial revision
  565. X */
  566. X
  567. X#ifndef lint
  568. Xstatic char    RcsId[] = "$Header: mdump.c,v 1.7 85/08/07 16:30:08 paul Exp $";
  569. X#endif
  570. X
  571. X#include    <stdio.h>
  572. X#ifdef    SYS5
  573. X#include    <string.h>
  574. X#define        index        strchr
  575. X#define        rindex        strrchr
  576. X#else
  577. X#include    <strings.h>
  578. X#endif
  579. X#include    <ctype.h>
  580. X#include    <sys/time.h>
  581. X#include    <sys/file.h>
  582. X#include    <sys/types.h>
  583. X#include    <sys/mtio.h>
  584. X#include    <sys/ioctl.h>
  585. X#include    <dumptab.h>
  586. X
  587. X#define        equal(s1, s2)    (strcmp(s1, s2) == 0)
  588. X
  589. X/* default output devices */
  590. X#define        DEF_DEV        "/dev/rmt0"
  591. X#define        DEF_NRDEV    "/dev/nrmt0"
  592. X
  593. X/* dumptab file.  must be the same as referenced by getdtent() functions */
  594. X#define        DUMPTAB        "/etc/dumptab"
  595. X
  596. X/* temp file for listings */
  597. X#define        DLIST        "/tmp/mdumpXXXXXX"
  598. X
  599. X/* maximum number of filesystems */
  600. X#define        MAX_FS        30
  601. X
  602. X/* size of shorter strings, e.g., host[] */
  603. X#define        SSTR_SIZE    12
  604. X
  605. X/* size of longer strings, e.g., command[] */
  606. X#define        LSTR_SIZE    160
  607. X
  608. X/* command for generating and formatting listings.
  609. X * arguments in order are: host, ':' (if host defined, ' ' otherwise),
  610. X * nrdevice, myname, dt->dt_name, list_file.  don't delete the leading
  611. X * blank as a remote restore replaces that with an 'r'.
  612. X */
  613. X#define        LST_CMD        " restore tf %s%c%s | sort +1 | pr -3 -w132 -f -h \"%s Dump Listing of %s\" >> %s"
  614. X
  615. X/* listing file print command.  arguments are myname and list_file */
  616. X#define        PRT_CMD        "ibmprint -f -h \"%s Dlist\" %s"   /* vax */
  617. X/* #define        PRT_CMD        "lpr -r -s -J %s_Dlist %s" /* pyramid */
  618. X
  619. X/* command to copy the /etc/dumptab file to the tape device.  arguments
  620. X * to DD_CMD are DUMPTAB and nrdevice.  for the remote command an rcp and
  621. X * rsh command are used.  arguments to RDD_CMD are DUMPTAB, host, host,
  622. X * nrdevice.
  623. X */
  624. X#define        DD_CMD        "dd if=%s of=%s bs=512"
  625. X#define        RDD_CMD        "rcp %s %s:/tmp/xyzzy.mdump; rsh %s \"dd if=/tmp/xyzzy.mdump of=%s bs=512; rm /tmp/xyzzy.mdump\""
  626. X
  627. X/* copy of argv[0] for error messages */
  628. Xchar        *self;
  629. X
  630. X/* resident host name */
  631. Xchar        myname[SSTR_SIZE];
  632. X
  633. X/* debug messages printed if set */
  634. Xint        debug;
  635. X
  636. X/* run listing code only */
  637. Xint        elist;
  638. X
  639. X/* state table of tape files.  if dump_state[0] is set, then there's a dump
  640. X * file there.  If zero, there's a tape mark on the tape instead.  If -1
  641. X * then EOT has been reached or some other dump(8) error.  Typical usage
  642. X * would be dump_state[dt->dt_position].
  643. X */
  644. Xint        dump_state[MAX_FS];
  645. X
  646. X/* mag tape stuff */
  647. Xstruct mt_cmds {
  648. X    char    *c_name;
  649. X    int    c_code;
  650. X    int    c_ronly;
  651. X} com[] = {
  652. X    { "eof",    MTWEOF,    0 },
  653. X    { "fsf",    MTFSF,    1 },
  654. X    { "bsf",    MTBSF,    1 },
  655. X    { "rew",    MTREW,    1 },
  656. X    { 0 }
  657. X};
  658. X
  659. Xextern time_t    time();
  660. X
  661. Xmain(argc, argv)
  662. Xint    argc;
  663. Xchar    **argv;
  664. X{
  665. X    /* a useful counter */
  666. X    int        i;
  667. X
  668. X    /* weekly or daily backups (can be both) */
  669. X    int        weekly, daily;
  670. X
  671. X    /* create a compact listing if set */
  672. X    int        dlist;
  673. X
  674. X    /* run mdump for day argument instead of today of set */
  675. X    char        newday[4];
  676. X
  677. X    /* listing file */
  678. X    char        *list_file = DLIST;
  679. X
  680. X    /* backup device */
  681. X    char        *device, *nrdevice;
  682. X
  683. X    /* host machine */
  684. X    char        host[SSTR_SIZE];
  685. X
  686. X    /* time stuff */
  687. X    struct tm    *tm;
  688. X    time_t        clock;
  689. X
  690. X    /* dumptab info */
  691. X    struct dumptab    *dt;
  692. X
  693. X    /* library routines */
  694. X    char        *malloc(), *mktemp();
  695. X
  696. X    /* routine to set new tm->tm_wday value for -t argument */
  697. X    struct tm    *setday();
  698. X
  699. X    /* squirrel a copy of *argv[0] away for use in error messages */
  700. X    self = malloc((unsigned) (strlen(*argv) + 1));
  701. X    (void) strcpy(self, *argv);
  702. X
  703. X    dlist = 1;
  704. X    weekly = daily = 0;
  705. X    newday[0] = host[0] = '\0';
  706. X    device = DEF_DEV;
  707. X    nrdevice = DEF_NRDEV;
  708. X    (void) gethostname(myname, SSTR_SIZE-1);
  709. X    /*
  710. X     * parse arguments
  711. X     */
  712. X    i = 1;
  713. X    while (i < argc && *argv[i] == '-') {
  714. X        if (equal(argv[i]+1, "db")) {
  715. X            /* db - set debug level */
  716. X            debug++;
  717. X            i++;
  718. X            fprintf(stderr, "%s: debug option enabled\n", self);
  719. X        }
  720. X        else if (equal(argv[i]+1, "d")) {
  721. X            /* d - daily backups */
  722. X            daily++;
  723. X            i++;
  724. X        }
  725. X        else if (equal(argv[i]+1, "w")) {
  726. X            /* w - weekly backups */
  727. X            weekly++;
  728. X            i++;
  729. X        }
  730. X        else if (equal(argv[i]+1, "l")) {
  731. X            /* l - suppress listings of files */
  732. X            dlist = 0;
  733. X            i++;
  734. X        }
  735. X        else if (equal(argv[i]+1, "e")) {
  736. X            /* e - run listing code only */
  737. X            printf("Listings only - nothing will be written to tape\n");
  738. X            elist++;
  739. X            i++;
  740. X        }
  741. X        else if (equal(argv[i]+1, "t")) {
  742. X            /* t - read new dump day-of-week from next argument */
  743. X            i++;
  744. X            (void) strncpy(newday, argv[i], 3);
  745. X            i++;
  746. X        }
  747. X        else if (equal(argv[i]+1, "f"))
  748. X        {
  749. X            /*
  750. X             * f - read backup device from next argument
  751. X             * turn /dev/rmt names into /dev/nrmt
  752. X             */
  753. X            char    temp[40], *p1, *p2;
  754. X
  755. X            i++;
  756. X            p2 = (char *) NULL;
  757. X            if ((p1 = index(argv[i], ':')) != 0) {
  758. X                (void) strncpy(host, argv[i], p1-argv[i]+1);
  759. X                *(index(host, ':')) = '\0';
  760. X                p1++;
  761. X            }
  762. X            if (p1 == 0)
  763. X                p1 = argv[i];
  764. X            device = malloc((unsigned) (strlen(p1) + 1));
  765. X            (void) strcpy(device, p1);
  766. X            if ((p2 = rindex(argv[i], '/')) == 0) {
  767. X                fprintf(stderr, "%s: Output device must be a tape drive, e.g., /dev/rmt1, uxc:/dev/rmt2\n", self);
  768. X                exit(1);
  769. X            }
  770. X            p2++;
  771. X            (void) strncpy(temp, p1, p2-p1);
  772. X            *(temp + (p2-p1)) = '\0';
  773. X            nrdevice = malloc((unsigned) (strlen(argv[i])+2));
  774. X            if (*p2 == 'n')
  775. X                (void) sprintf(nrdevice, "%s%s", temp, p2);
  776. X            else
  777. X                (void) sprintf(nrdevice, "%sn%s", temp, p2);
  778. X            if (debug)
  779. X                fprintf(stderr, "host %s, device %s, nrdevice %s\n", host, device, nrdevice);
  780. X            i++;
  781. X        }
  782. X        else
  783. X        {
  784. X            /* command line errors */
  785. X            fprintf(stderr, "%s: %s - bad flag\n", self, argv[i]+1);
  786. X            fprintf(stderr, "Usage: %s [-d] [-w] [-e] [-l] [-f [host:]/dev/rmtx] [-db]\n", self);
  787. X            exit(1);
  788. X        }
  789. X    }
  790. X    if (! (weekly || daily)) {
  791. X        fprintf(stderr, "%s: No action specified.\n\tInvoke %s with at least one of the following: -w, -d\n", self, self);
  792. X        exit(1);
  793. X    }
  794. X    clock = time((time_t *) 0);
  795. X    if (*newday)
  796. X        tm = setday(newday);
  797. X    else
  798. X        tm = localtime(&clock);
  799. X    mtio(host, device, "rew");
  800. X    wrt_dtinfo(host, nrdevice);
  801. X    setdtent();
  802. X    for (i = 1; (dt = getdtpos(i)); i++) {
  803. X        if (dt->dt_weekly == tm->tm_wday) {
  804. X            if (weekly) {
  805. X                if (wrt_dmp(host, nrdevice, dt, 'w'))
  806. X                    break;
  807. X            }
  808. X            else
  809. X                wrt_dummy(host, nrdevice, dt);
  810. X        }
  811. X        else {
  812. X            if (daily) {
  813. X                if (wrt_dmp(host, nrdevice, dt, 'd'))
  814. X                    break;
  815. X            }
  816. X            else
  817. X                wrt_dummy(host, nrdevice, dt);
  818. X        }
  819. X    }
  820. X    /* write the last EOF to form EOT and rewind the tape
  821. X     * by using the rewind-on-close device.
  822. X     */
  823. X    if (! elist) {
  824. X        printf("Really rewinding tape\n");
  825. X        mtio(host, device, "eof");
  826. X    }
  827. X    if (dlist) {
  828. X        char    command[LSTR_SIZE];
  829. X
  830. X        (void) mktemp(list_file);
  831. X        mtio(host, device, "rew");
  832. X
  833. X        /* skip over the zero'th file of /etc/dumptab */
  834. X        mtio(host, nrdevice, "fsf");
  835. X        setdtent();
  836. X        for (i = 1; (dt = getdtpos(i)); i++)
  837. X            if (list_tape(host, nrdevice, dt, list_file))
  838. X                break;
  839. X        (void) sprintf(command, PRT_CMD, myname, list_file);
  840. X        if (debug)
  841. X            fprintf(stderr, "print command: %s\n", command);
  842. X        if (i = (system(command) >> 8))
  843. X            fprintf(stderr, "%s: %s exitted abnormally (%d).\n", self, command, i);
  844. X        printf("Last rewind of tape\n");
  845. X        mtio(host, device, "rew");
  846. X    }
  847. X    exit(0);
  848. X}
  849. X
  850. X/*
  851. X * mtio -- perform a local/remote tape operation
  852. X *
  853. X *    for local tapes (host[0] == '\0') use the ioctl calls.
  854. X *    remote tapes use an rsh command.
  855. X *
  856. X *    parameters:
  857. X *        host (IN) -- name of remote host, if host[0] != '\0'
  858. X *        dev (IN) -- tape drive name
  859. X *        cp (IN) -- tape opcode
  860. X *    returns:
  861. X *        none
  862. X *    side effects:
  863. X *        none
  864. X *    deficiencies:
  865. X *        any error causes an error exit from the program
  866. X */
  867. Xmtio(host, dev, cp)
  868. Xchar    *host, *dev, *cp;
  869. X{
  870. X    struct mt_cmds    *comp;
  871. X
  872. X    /* tape file descriptor */
  873. X    int        mtfd;
  874. X
  875. X    /* return code from system() call */
  876. X    int        status;
  877. X
  878. X    /* from sys/mtio.h */
  879. X    struct mtop    mt_com;
  880. X
  881. X    /* buffer for rsh command */
  882. X    char        command[LSTR_SIZE];
  883. X
  884. X    if (*host == '\0') {
  885. X        for (comp = com; comp->c_name != NULL; comp++)
  886. X            if (strncmp(cp, comp->c_name, strlen(cp)) == 0)
  887. X                break;
  888. X        if (comp->c_name == NULL) {
  889. X            fprintf(stderr, "%s: mtio: don't grok \"%s\"\n", self, cp);
  890. X            exit(1);
  891. X        }
  892. X        if ((mtfd = open(dev, comp->c_ronly ? 0 : 2)) < 0) {
  893. X            fprintf(stderr, "%s: mtio: open of ", self);
  894. X            perror(dev);
  895. X            exit(1);
  896. X        }
  897. X        mt_com.mt_op = comp->c_code;
  898. X        mt_com.mt_count = 1;
  899. X        if (ioctl(mtfd, MTIOCTOP, &mt_com) < 0) {
  900. X            fprintf(stderr, "%s: mtio: %s %s %d ", self, dev,
  901. X                comp->c_name, mt_com.mt_count);
  902. X            perror("failed");
  903. X            exit(1);
  904. X        }
  905. X        (void) close(mtfd);
  906. X    }
  907. X    else {
  908. X        (void) strcpy(command, "rsh ");
  909. X        (void) strcat(command, host);
  910. X        (void) strcat(command, " mt -t ");
  911. X        (void) strcat(command, dev);
  912. X        (void) strcat(command, " ");
  913. X        (void) strcat(command, cp);
  914. X        if (debug)
  915. X            fprintf(stderr, "tape command %s\n", command);
  916. X        if (status = (system(command) >> 8)) {
  917. X            fprintf(stderr, "%s: %s exitted abnormally (%d).  Restart %s\n", self, command, status, self);
  918. X            exit(1);
  919. X        }
  920. X    }
  921. X}
  922. X
  923. X/*
  924. X * wrt_dmp -- write a filesystem dump on the dump tape
  925. X *
  926. X *    for local tapes (host[0] == '\0') use dump
  927. X *    remote tapes use rdump
  928. X *
  929. X *    parameters:
  930. X *        host (IN) -- name of remote host, if host[0] != '\0'
  931. X *        dev (IN) -- tape drive name
  932. X *        dt (IN) -- dumptab pointer
  933. X *        type (IN) -- weekly or daily dump
  934. X *    returns:
  935. X *        0 if dump command successful, 1 if not
  936. X *    side effects:
  937. X *        alters dump_state table
  938. X *    deficiencies:
  939. X *        any error causes an error exit from the program
  940. X */
  941. Xwrt_dmp(host, dev, dt, type)
  942. Xchar        *host, *dev, type;
  943. Xstruct dumptab    *dt;
  944. X{
  945. X    char    command[LSTR_SIZE];
  946. X    int    status;
  947. X
  948. X    if (elist) {
  949. X        dump_state[dt->dt_position] = 1;
  950. X        return(0);
  951. X    }
  952. X    (void) strcpy(command, " dump nu");
  953. X    switch (type) {
  954. X        case 'd':
  955. X        (void) strcat(command, "5");
  956. X        break;
  957. X        case 'w':
  958. X        (void) strcat(command, "4");
  959. X        break;
  960. X        default:
  961. X        fprintf(stderr, "%s: unknown dump type %c\n", self, type);
  962. X        exit(1);
  963. X    }
  964. X    (void) strcat(command, "f ");
  965. X    if (*host != '\0') {
  966. X        command[0] = 'r';
  967. X        (void) strcat(command, host);
  968. X        (void) strcat(command, ":");
  969. X    }
  970. X    (void) strcat(command, dev);
  971. X    (void) strcat(command, " ");
  972. X    (void) strcat(command, dt->dt_name);
  973. X    if (debug)
  974. X        fprintf(stderr, "dump command %s\n", command);
  975. X    printf("Dumping %s\n", dt->dt_name);
  976. X
  977. X    /* dump(8) exits with 1 if all is well */
  978. X    if ((status = (system(command) >> 8)) != 1) {
  979. X        fprintf(stderr, "%s: %s exitted abnormally (%d).\n", self, command, status);
  980. X        fprintf(stderr, "\tTape will rewind and create listings of the successful dumps.\n");
  981. X        dump_state[dt->dt_position] = -1;
  982. X        mtio(host, dev, "bsf");
  983. X        return(1);
  984. X    }
  985. X    dump_state[dt->dt_position] = 1;
  986. X    return(0);
  987. X}
  988. X
  989. X/*
  990. X * list_tape -- generate a "restore tf" listing for the current tape file
  991. X *
  992. X *    list_tape creates a command line to be executed by system() and
  993. X *    re-directs the output to a listing file.
  994. X *
  995. X *    parameters:
  996. X *        host (IN) -- name of remote host, if host[0] != '\0'
  997. X *        dev (IN) -- tape drive name
  998. X *        dt (IN) -- dumptab pointer
  999. X *        lfile (IN) -- name of listing file
  1000. X *    returns:
  1001. X *        0 for normal results, 1 if at end of tape
  1002. X *    side effects:
  1003. X *        none
  1004. X *    deficiencies:
  1005. X *        any error causes an error exit from the program
  1006. X */
  1007. Xlist_tape(host, dev, dt, lfile)
  1008. Xchar        *host, *dev, *lfile;
  1009. Xstruct dumptab    *dt;
  1010. X{
  1011. X    FILE        *fp;
  1012. X    int        status;
  1013. X    char        command[LSTR_SIZE];
  1014. X
  1015. X    if (dump_state[dt->dt_position] == 0) {
  1016. X        /* no file here so write a message on the dump listing */
  1017. X        if ((fp = fopen(lfile, "a")) == NULL) {
  1018. X            fprintf(stderr, "%s: list_tape ", self);
  1019. X            perror(lfile);
  1020. X            exit(1);
  1021. X        }
  1022. X        fprintf(fp, "\n\n\tNo dump file for %s on this tape.\n\f",
  1023. X            dt->dt_name);
  1024. X        (void) fclose(fp);
  1025. X        /* advance the tape by one tape mark */
  1026. X        printf("Skipping dummy file for %s\n", dt->dt_name);
  1027. X        mtio(host, dev, "fsf");
  1028. X        return(0);
  1029. X    }
  1030. X    else if (dump_state[dt->dt_position] == 1) {
  1031. X        /* build the appropriate restore tf command and execute it */
  1032. X        (void) sprintf(command, LST_CMD, host, (*host ? ':' : ' '),
  1033. X            dev, myname, dt->dt_name, lfile);
  1034. X        if (*host != '\0')
  1035. X            command[0] = 'r';
  1036. X        if (debug)
  1037. X            fprintf(stderr, "list command %s\n", command);
  1038. X        printf("Listing %s\n", dt->dt_name);
  1039. X        if (status = (system(command) >> 8)) {
  1040. X            char    c,d;
  1041. X
  1042. X            fprintf(stderr, "%s: %s exitted abnormally (%d).  Continue? [yn] ", self, command, status);
  1043. X            while ((d = getc(stdin)) != '\n')
  1044. X                c = d;
  1045. X            if (c != 'y')
  1046. X                exit(1);
  1047. X        }
  1048. X        /* advance the tape to end of file */
  1049. X        mtio(host, dev, "fsf");
  1050. X        return(0);
  1051. X    }
  1052. X    return(1);
  1053. X}
  1054. X
  1055. X/*
  1056. X * wrt_dtinfo -- write /etc/dumptab onto the tape
  1057. X *
  1058. X *    writing a copy of /etc/dumptab onto the tape as file #0 provides
  1059. X *    a catalogue of the tape files and insulates backup volumes from
  1060. X *    changes in /etc/dumptab.  Elsewhere on the tape it acts as a 
  1061. X *    place holder for a non-selected dump, e.g., daily on a weekly-only
  1062. X *    tape.
  1063. X *
  1064. X *    parameters:
  1065. X *        host (IN) -- name of remote host
  1066. X *        dev (IN) -- tape drive name
  1067. X *    returns:
  1068. X *        none
  1069. X *    side effects:
  1070. X *        none
  1071. X *    deficiencies:
  1072. X *        any error causes an error exit from the program
  1073. X */
  1074. Xwrt_dtinfo(host, dev)
  1075. Xchar    *host, *dev;
  1076. X{
  1077. X    char    command[LSTR_SIZE];
  1078. X    int    status;
  1079. X
  1080. X    if (elist)
  1081. X        return;
  1082. X    if (*host)
  1083. X        (void) sprintf(command, RDD_CMD, DUMPTAB, host, host, dev);
  1084. X    else
  1085. X        (void) sprintf(command, DD_CMD, DUMPTAB, dev);
  1086. X    printf("Copying %s to tape\n", DUMPTAB);
  1087. X    if (status = (system(command) >> 8)) {
  1088. X        fprintf(stderr, "%s: %s exitted abnormally (%d).  Restart %s\n", self, command, status, self);
  1089. X        exit(1);
  1090. X    }
  1091. X}
  1092. X
  1093. X/*
  1094. X * wrt_dummy -- write a dummy file onto the tape
  1095. X *
  1096. X *    write a dummy file onto the tape to take the place of a non-
  1097. X *    scheduled backup.  this preserves tape order.
  1098. X *
  1099. X *    parameters:
  1100. X *        host (IN) -- name of remote host
  1101. X *        dev (IN) -- tape drive name
  1102. X *        dt (IN) -- dumptab pointer
  1103. X *    returns:
  1104. X *        none
  1105. X *    side effects:
  1106. X *        alters dump_state table
  1107. X *    deficiencies:
  1108. X *        any error causes an error exit from the program
  1109. X */
  1110. Xwrt_dummy(host, dev, dt)
  1111. Xchar        *host, *dev;
  1112. Xstruct dumptab    *dt;
  1113. X{
  1114. X    char    command[LSTR_SIZE];
  1115. X    int    status;
  1116. X
  1117. X    if (elist)
  1118. X        return;
  1119. X    if (*host)
  1120. X        (void) sprintf(command, RDD_CMD, DUMPTAB, host, host, dev);
  1121. X    else
  1122. X        (void) sprintf(command, DD_CMD, DUMPTAB, dev);
  1123. X    printf("Writing place holder file for %s to tape\n", dt->dt_name);
  1124. X    if (status = (system(command) >> 8)) {
  1125. X        fprintf(stderr, "%s: %s exitted abnormally (%d).  Restart %s\n", self, command, status, self);
  1126. X        exit(1);
  1127. X    }
  1128. X}
  1129. X
  1130. X/*
  1131. X * setday -- set tm..tm_wday to value consistent with argument
  1132. X *
  1133. X *    tm.tm_wday has a legal range of 0 (for Sunday) to 6 (for Saturday).
  1134. X *    day is a three character string ("sun", "mon", etc) used to determine
  1135. X *    the value of tm.tm_wday.
  1136. X *
  1137. X *    parameters:
  1138. X *        day (IN/OUT) -- day of week string
  1139. X *    returns:
  1140. X *        pointer to static tm struct
  1141. X *    side effects:
  1142. X *        changes day string to all lower case
  1143. X *    deficiencies:
  1144. X *        any error causes an error exit from the program
  1145. X */
  1146. Xstruct tm *
  1147. Xsetday(day)
  1148. Xchar    *day;
  1149. X{
  1150. X    static struct tm    mtm;
  1151. X    char            *p;
  1152. X
  1153. X    for (p = day; *p; p++)
  1154. X        if (isupper(*p))
  1155. X            *p += ('a' - 'A');
  1156. X    if (equal(day, "sun"))
  1157. X        mtm.tm_wday = 0;
  1158. X    else if (equal(day, "mon"))
  1159. X        mtm.tm_wday = 1;
  1160. X    else if (equal(day, "tue"))
  1161. X        mtm.tm_wday = 2;
  1162. X    else if (equal(day, "wed"))
  1163. X        mtm.tm_wday = 3;
  1164. X    else if (equal(day, "thu"))
  1165. X        mtm.tm_wday = 4;
  1166. X    else if (equal(day, "fri"))
  1167. X        mtm.tm_wday = 5;
  1168. X    else if (equal(day, "sat"))
  1169. X        mtm.tm_wday = 6;
  1170. X    else {
  1171. X        fprintf(stderr, "%s: setday: illegal day of week (%s)\n", self, day);
  1172. X        fprintf(stderr, "\tLegal values are sun, mon, tue, etc.\n");
  1173. X        exit(1);
  1174. X    }
  1175. X    return(&mtm);
  1176. X}
  1177. SHAR_EOF
  1178. sed 's/^X//' << 'SHAR_EOF' > st.8
  1179. X.TH ST 8 "UofI CSO"
  1180. X.SH NAME
  1181. Xst \- set mdump tapes to correct file for restores
  1182. X.SH SYNOPSIS
  1183. X.B st
  1184. X[
  1185. X\fB\-f \fI[host:]/dev/rmtx\fR
  1186. X]
  1187. X.I filesystem
  1188. X.SH DESCRIPTION
  1189. X.I St
  1190. Xpositions tapes created by
  1191. X.IR mdump (8)
  1192. Xto the tape file corresponding to
  1193. X.IR filesystem .
  1194. XFrom there ordinary commands like
  1195. X.IR restore (8)
  1196. Xcan be used to retrieve files, etc.
  1197. X.PP
  1198. XThe tape device is selected with the
  1199. X.B \-f
  1200. Xoption.
  1201. XRemote tape reads over the network is accomplished by specifying the device
  1202. Xname in the same manner as
  1203. X.IR rdump (8),
  1204. Xe.g., uiucuxc:/dev/rmt0.
  1205. X.PP
  1206. XThe order of filesystems on
  1207. X.I mdump
  1208. Xtapes is determined by a copy of
  1209. X.I /etc/dumptab
  1210. Xwritten as the first tape file.
  1211. X.SH FILES
  1212. X/etc/dumptab
  1213. X.SH "SEE ALSO"
  1214. Xdumptab(5), dump(8), mdump(8), rdump(8)
  1215. X.SH BUGS
  1216. XIt's not clear this is the best approach, however it was the fastest to
  1217. Ximplement.
  1218. SHAR_EOF
  1219. sed 's/^X//' << 'SHAR_EOF' > st.c
  1220. X/*
  1221. X * st -- set tape position on a multi-file dump volume to that of
  1222. X *     the specified filesystem
  1223. X *
  1224. X * usage: st [-f [host:]/dev/rmtx] [-db] filesystem
  1225. X *
  1226. X * -f [host:]/dev/rmtx    tape device name.  If the host: prefix
  1227. X *    is used, the backup tape will be addressed over the network to
  1228. X *    the tape drive on the named host.
  1229. X *
  1230. X * -db    Write debug information to stderr
  1231. X *
  1232. X * Written by Paul Pomes, University of Illinois, Computing Services Office
  1233. X * Copyright 1985 by Paul Pomes and University of Illinois Board of Trustees
  1234. X *
  1235. X * This program may be freely reproduced and distributed provided the
  1236. X * copyright notice above is included in all copies.  It may not be
  1237. X * included in any software product or distribution sold for profit
  1238. X * without the permission of the author.
  1239. X *
  1240. X * UUCP:    {ihnp4,pur-ee,convex}!uiucdcs!uiucuxc!paul
  1241. X * ARPANET:    paul%uiucuxc@uiuc.arpa
  1242. X * CSNET:    paul%uiucuxc@uiuc.csnet
  1243. X * ICBM:    40 07 N / 88 13 W
  1244. X * US Mail:    Univ of Illinois, CSO, 1304 W Springfield Ave, Urbana, IL  61801
  1245. X *
  1246. X * $Log:    st.c,v $
  1247. X * Revision 1.2  85/07/11  13:27:51  paul
  1248. X * Updated author information.   -pbp
  1249. X * 
  1250. X * Revision 1.1  85/07/02  13:48:08  root
  1251. X * Initial revision
  1252. X * 
  1253. X */
  1254. X
  1255. X#ifndef lint
  1256. Xstatic char    RcsId[] = "$Header: st.c,v 1.2 85/07/11 13:27:51 paul Exp $";
  1257. X#endif
  1258. X
  1259. X#include    <stdio.h>
  1260. X#include    <strings.h>
  1261. X#include    <sys/file.h>
  1262. X#include    <sys/types.h>
  1263. X#include    <sys/mtio.h>
  1264. X#include    <sys/ioctl.h>
  1265. X#include    <dumptab.h>
  1266. X
  1267. X#define    equal(s1, s2)    (strcmp(s1, s2) == 0)
  1268. X
  1269. X/* default tape devices */
  1270. X#define        DEF_DEV        "/dev/rmt0"
  1271. X#define        DEF_NRDEV    "/dev/nrmt0"
  1272. X
  1273. X/* size of shorter strings, e.g., host[] */
  1274. X#define        SSTR_SIZE    12
  1275. X
  1276. X/* size of longer strings, e.g., command[] */
  1277. X#define        LSTR_SIZE    160
  1278. X
  1279. X/* commands to read the /etc/dumptab file in tape file #0.
  1280. X * argument to DD_CMD is nrdevice; arguments to RDD_CMD are host, nrdevice,
  1281. X * and host again.
  1282. X */
  1283. X#define        DD_CMD        "dd if=%s of=/tmp/xyzzy.mdump bs=512"
  1284. X#define        RDD_CMD        "rsh %s dd if=%s of=/tmp/xyzzy.mdump bs=512; rcp %s:/tmp/xyzzy.mdump /tmp/xyzzy.mdump"
  1285. X
  1286. X/* copy of argv[0] for error messages */
  1287. Xchar        *self;
  1288. X
  1289. X/* debug messages printed if set */
  1290. Xint        debug;
  1291. X
  1292. X/* mag tape stuff */
  1293. Xstruct mt_cmds {
  1294. X    char    *c_name;
  1295. X    int    c_code;
  1296. X    int    c_ronly;
  1297. X} com[] = {
  1298. X    { "eof",    MTWEOF,    0 },
  1299. X    { "fsf",    MTFSF,    1 },
  1300. X    { "rew",    MTREW,    1 },
  1301. X    { "status",    MTNOP,    1 },
  1302. X    { 0 }
  1303. X};
  1304. X
  1305. Xmain(argc, argv)
  1306. Xint    argc;
  1307. Xchar    **argv;
  1308. X{
  1309. X    /* a useful counter */
  1310. X    int        i;
  1311. X
  1312. X    /* tape device */
  1313. X    char        *device, *nrdevice;
  1314. X
  1315. X    /* filesystem to position to */
  1316. X    char        *filesys;
  1317. X
  1318. X    /* host machine */
  1319. X    char        host[SSTR_SIZE];
  1320. X
  1321. X    /* dumptab info */
  1322. X    struct dumptab    *dt;
  1323. X
  1324. X    /* library routines */
  1325. X    char        *malloc();
  1326. X
  1327. X    /* squirrel a copy of *argv[0] away for use in error messages */
  1328. X    self = malloc((unsigned) (strlen(*argv) + 1));
  1329. X    (void) strcpy(self, *argv);
  1330. X
  1331. X    host[0] = '\0';
  1332. X    device = DEF_DEV;
  1333. X    nrdevice = DEF_NRDEV;
  1334. X    /*
  1335. X     * parse arguments
  1336. X     */
  1337. X    i = 1;
  1338. X    while (i < argc && *argv[i] == '-') {
  1339. X        if (equal(argv[i]+1, "db")) {
  1340. X            /* db - set debug level */
  1341. X            debug++;
  1342. X            i++;
  1343. X            fprintf(stderr, "%s: debug option enabled\n", self);
  1344. X        }
  1345. X        else if (equal(argv[i]+1, "f"))
  1346. X        {
  1347. X            /*
  1348. X             * f - read tape device from next argument
  1349. X             * turn /dev/rmt names into /dev/nrmt
  1350. X             */
  1351. X            char    temp[40], *p1, *p2;
  1352. X
  1353. X            i++;
  1354. X            p2 = (char *) NULL;
  1355. X            if ((p1 = index(argv[i], ':')) != 0) {
  1356. X                (void) strncpy(host, argv[i], p1-argv[i]+1);
  1357. X                *(index(host, ':')) = '\0';
  1358. X                p1++;
  1359. X            }
  1360. X            if (p1 == 0)
  1361. X                p1 = argv[i];
  1362. X            device = malloc((unsigned) (strlen(p1) + 1));
  1363. X            (void) strcpy(device, p1);
  1364. X            if ((p2 = rindex(argv[i], '/')) == 0) {
  1365. X                fprintf(stderr, "%s: Device must be a tape drive, e.g., /dev/rmt1, uxc:/dev/rmt2\n", self);
  1366. X                exit(1);
  1367. X            }
  1368. X            p2++;
  1369. X            (void) strncpy(temp, p1, p2-p1);
  1370. X            *(temp + (p2-p1)) = '\0';
  1371. X            nrdevice = malloc((unsigned) (strlen(argv[i])+2));
  1372. X            if (*p2 == 'n')
  1373. X                (void) sprintf(nrdevice, "%s%s", temp, p2);
  1374. X            else
  1375. X                (void) sprintf(nrdevice, "%sn%s", temp, p2);
  1376. X            if (debug)
  1377. X                fprintf(stderr, "host %s, device %s, nrdevice %s\n", host, device, nrdevice);
  1378. X            i++;
  1379. X        }
  1380. X        else
  1381. X        {
  1382. X            /* command line errors */
  1383. X            fprintf(stderr, "%s: %s - bad flag\n", self, argv[i]+1);
  1384. X            Usage:
  1385. X            fprintf(stderr, "Usage: %s [-f [host:]/dev/rmtx] [-db] filesystem\n", self);
  1386. X            exit(1);
  1387. X        }
  1388. X    }
  1389. X    /* last argument is filesystem name */
  1390. X    if (argv[i] == NULL) {
  1391. X        fprintf(stderr, "%s: No filesystem specified\n", self);
  1392. X        goto Usage;
  1393. X    }
  1394. X    else {
  1395. X        filesys = malloc((unsigned) (strlen(argv[i]) + 1));
  1396. X        (void) strcpy(filesys, argv[i]);
  1397. X        if (debug)
  1398. X            fprintf(stderr, "filesys %s\n", filesys);
  1399. X    }
  1400. X    read_dtinfo(host, device);
  1401. X    setdtfile("/tmp/xyzzy.mdump");
  1402. X    setdtent();
  1403. X    if (dt = getdtnam(filesys)) {
  1404. X        printf("Skipping %d tape files...", dt->dt_position);
  1405. X        (void) fflush(stdout);
  1406. X        for (i = 0; i < dt->dt_position; i++) {
  1407. X            mtio(host, nrdevice, "fsf");
  1408. X            printf("%d ", i+1);
  1409. X            (void) fflush(stdout);
  1410. X        }
  1411. X        printf("done.\n");
  1412. X        (void) unlink("/tmp/xyzzy.mdump");
  1413. X        exit(0);
  1414. X    }
  1415. X    fprintf(stderr, "%s: %s not in tape file #0 (and thus not on tape)\n",
  1416. X        self, filesys);
  1417. X    fprintf(stderr, "\tCopy of tape file #0 in /tmp/xyzzy.mdump\n");
  1418. X    exit(1);
  1419. X}
  1420. X
  1421. X/*
  1422. X * mtio -- perform a local/remote tape operation
  1423. X *
  1424. X *    for local tapes (host[0] == '\0') use the ioctl calls.
  1425. X *    remote tapes use an rsh command.
  1426. X *
  1427. X *    parameters:
  1428. X *        host (IN) -- name of remote host
  1429. X *        dev (IN) -- tape drive name
  1430. X *        cp (IN) -- tape opcode
  1431. X *    returns:
  1432. X *        none
  1433. X *    side effects:
  1434. X *        none
  1435. X *    deficiencies:
  1436. X *        any error causes an error exit from the program
  1437. X */
  1438. Xmtio(host, dev, cp)
  1439. Xchar    *host, *dev, *cp;
  1440. X{
  1441. X    struct mt_cmds    *comp;
  1442. X
  1443. X    /* tape file descriptor */
  1444. X    int        mtfd;
  1445. X
  1446. X    /* return code from system() call */
  1447. X    int        status;
  1448. X
  1449. X    /* from sys/mtio.h */
  1450. X    struct mtop    mt_com;
  1451. X
  1452. X    /* buffer for rsh command */
  1453. X    char        command[LSTR_SIZE];
  1454. X
  1455. X    if (*host == '\0') {
  1456. X        for (comp = com; comp->c_name != NULL; comp++)
  1457. X            if (strncmp(cp, comp->c_name, strlen(cp)) == 0)
  1458. X                break;
  1459. X        if (comp->c_name == NULL) {
  1460. X            fprintf(stderr, "%s: mtio: don't grok \"%s\"\n", self, cp);
  1461. X            exit(1);
  1462. X        }
  1463. X        if ((mtfd = open(dev, comp->c_ronly ? 0 : 2)) < 0) {
  1464. X            fprintf(stderr, "%s: mtio: open of ", self);
  1465. X            perror(dev);
  1466. X            exit(1);
  1467. X        }
  1468. X        mt_com.mt_op = comp->c_code;
  1469. X        mt_com.mt_count = 1;
  1470. X        if (ioctl(mtfd, MTIOCTOP, &mt_com) < 0) {
  1471. X            fprintf(stderr, "%s: mtio: %s %s %d ", self, dev,
  1472. X                comp->c_name, mt_com.mt_count);
  1473. X            perror("failed");
  1474. X            exit(1);
  1475. X        }
  1476. X        (void) close(mtfd);
  1477. X    }
  1478. X    else {
  1479. X        (void) strcpy(command, "rsh ");
  1480. X        (void) strcat(command, host);
  1481. X        (void) strcat(command, " mt -t ");
  1482. X        (void) strcat(command, dev);
  1483. X        (void) strcat(command, " ");
  1484. X        (void) strcat(command, cp);
  1485. X        if (debug)
  1486. X            fprintf(stderr, "tape command %s\n", command);
  1487. X        if (status = (system(command) >> 8)) {
  1488. X            fprintf(stderr, "%s: %s exitted abnormally (%d).  Restart %s\n", self, command, status, self);
  1489. X            exit(1);
  1490. X        }
  1491. X    }
  1492. X}
  1493. X
  1494. X/*
  1495. X * read_dtinfo -- copy the dumptab file contained within tape file #0
  1496. X *
  1497. X *    the /etc/dumptab file used to create the backup tape volume
  1498. X *    is contained within the first tape file.  this routine copies
  1499. X *    it to the magic name of /tmp/xyzzy.mdump on the current host.
  1500. X *
  1501. X *    parameters:
  1502. X *        host (IN) -- name of remote host
  1503. X *        dev (IN) -- tape drive name
  1504. X *    returns:
  1505. X *        none
  1506. X *    side effects:
  1507. X *        none
  1508. X *    deficiencies:
  1509. X *        any error causes an error exit from the program
  1510. X */
  1511. Xread_dtinfo(host, dev)
  1512. Xchar    *host, *dev;
  1513. X{
  1514. X    char    command[LSTR_SIZE];
  1515. X    int    status;
  1516. X
  1517. X    mtio(host, dev, "rew");
  1518. X    if (*host)
  1519. X        (void) sprintf(command, RDD_CMD, host, dev, host);
  1520. X    else
  1521. X        (void) sprintf(command, DD_CMD, dev);
  1522. X    printf("Reading /etc/dumptab info from first tape file.\n");
  1523. X    if (status = (system(command) >> 8)) {
  1524. X        fprintf(stderr, "%s: %s exitted abnormally (%d).  Restart %s\n", self, command, status, self);
  1525. X        exit(1);
  1526. X    }
  1527. X}
  1528. SHAR_EOF
  1529. exit 0
  1530.  
  1531.