home *** CD-ROM | disk | FTP | other *** search
- Subject: v13i040: Derez, remove stale files from system, Part01/02
- Newsgroups: comp.sources.unix
- Sender: sources
- Approved: rsalz@uunet.UU.NET
-
- Submitted-by: A. Nonymous
- Posting-number: Volume 13, Issue 40
- Archive-name: derez3/part01
-
- [ This is kind of a fun program, in a sick sort of way. Consider it a
- tool in the war between system administrators who believe disks should
- be kept empty, and system users, who believe they should be kept full.
- Sorry, but no summary can do the vilification in the documentation
- true justice; you will have to read the manpage and README yourself.
- --r$ ]
-
- This is version 3.0 of Derez, the stale file archiver.
-
- This version is an upgraded version of the earlier
- usenet posting, from the very same anonymous source.
- Several tools to spot anti-social uses have been added,
- and the context diff to create a custom version of
- 4.2 BSD "tar", called rerez, that remembers access dates
- in the tape archive has been added. This version,
- as was the earlier version, is in the public domain
- and the author will deny being the author of this program.
-
- This is part 1 of two parts.
-
- : Run this shell script with "sh" not "csh"
- PATH=:/bin:/usr/bin:/usr/ucb
- export PATH
- all=FALSE
- if [ x$1 = x-a ]; then
- all=TRUE
- fi
- /bin/echo 'Extracting README'
- sed 's/^X//' <<'//go.sysin dd *' >README
- This code is explicitly placed in the public domain by the author and may be
- used for fun or profit (the author really enjoys running it). It is not
- copyrighted and contains no references to the author's true name. This is
- by design as the author does not what to become "known" as the author of Derez.
-
- This is version 3.0. It contains several useful options for derez, a special
- version of tar (rerez) to allow archives to restore time last accessed and some
- useful tooling to help spot antisocial users. Derez always wins in the
- derez/rerez wars. What! You think files should remain on disk forever????
-
- XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-
- Caution! Rerez.c is a munged version of 4.2BSD tar and therefore can't
- be transmitted to sites without a suitable license. Any public distributions
- of rerez.c should only contain the differences in "patch" format from 4.2BSD
- tar to protect AT&T's or UCB's interests. This distribution contains a file
- rerez.c.diff which a context diff to create rerez.c from 4.2BSD tar using
- "patch". Get patch from the USENET archive, or make the changes by hand.
- Rerez is simply a version of tar which remembers and restores time last
- accessed dates. If you can't manage to create rerez.c from 4.2BSD tar
- send a note to maddog.uucp!root or root@lll-maddog.arpa and we will try
- to help you out.
-
- The remote tape library patches appearing in rerez are the public
- domain rmtlib patches published in the USENET mod.sources. These
- are needed only to access a remote drive.
-
- XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-
- This version of Derez has a Makefile that conforms to the /usr/local
- standard for locally developed software (local rules for MadDog). All binaries
- are installed in the /usr/local/{bin,etc,lib,...} directory tree, with the
- exception of the man pages due to reservations in munging man (we recently
- munged it). Each installed item can have its owner and group set though the
- OWNER and GROUP parameters on the make comand line. It must be installed once
- by root, but there after the owner of the files can maintain them and install
- the new versions.
-
- Anyone having problems with derez should send a mail request to
- maddog!root for possible help or suggestions, arpa sites can use
- root@lll-maddog.arpa. Anyone who fixes some of derez's bugs or inadequacies
- is invited to send maddog!root a copy of the patches. We can always use a
- better, but not necessarily less Draconian, derez on our system.
-
- Derez does not contain a mechanism to warn users about the impending
- removal of stale files. We have found that doing this only invites the
- users to go and defeat the effects of derez totally without archiving
- their stale files to tape and removing them from disk. On systems with
- cooperative users, perhaps a separate program that sends users mail about
- their stale files, listing their path names might be helpful.
-
-
- DIRECTIONS TO SYSTEM ADMINISTRATORS FOR INSTALLATION:
- Derez, Readbyte, Rerez, and Agehist have man pages which describe their use
- and abuse. These man pages contain local system rules on MadDog
- and you will probably have your own you want to use. If so, modify
- the man pages to reflect these rules.
-
- The default definition for staleness is compiled into derez. You
- may want to change this. In any event the -t option can set the
- stale date to anything you want.
-
- 1) Modify the man pages, derez.c and the Makefile to reflect
- system rules, default stale interval and installation targets
- for your system.
-
- 2) Type "make install" to compile and install all programs and
- manual pages.
-
- 3) If you take out the #define of RIPEM in derez.c, derez
- will create the appropriate directory tree in MORGUE, including
- hard links to the target files, but will not rip off the
- originals. You can use this to first check that derez properly
- preserves all modes and ownerships before enabling the RIPEM code.
- A debug run of derez with the RIPEM code out is highly suggested
- to make sure that some system dependency in the code does not bite
- you. Your users expect and deserve absolute reliability when it comes
- to archiving their files.
-
-
- DIRECTIONS TO SYSTEM ADMINISTRATORS FOR STANDARD USAGE:
-
- 1) You must be root to derez another users files.
-
- 2) Cd to the directory where the directories you want to run
- derez on reside. Usually this would be the directory where the
- login directories of users reside but does not have to be.
- example: cd /u0
-
- 2) If the directory MORGUE does not exist, create it.
- example: mkdir MORGUE
-
- 3) Suppose you want to search the entire tree under /u0 for stale
- files not accessed in a year and move them to MORGUE. Type the
- command:
- derez -t 360
- If on the other hand you want to search only the subdirectories
- foo and bar and archive their stale files type the command:
- derez -t 360 foo bar
- Foo and bar must reside in the current directory.
-
- Derez will search the directories for stale files and create
- a list of them with the name MORGUE/DEREZ. It will then
- create a link to each file in MORGUE, and if RIPEM is defined
- in derez remove the original link one at a time. Doing this one
- files at a time limits the possibility of overrunning the disk.
- Using links makes it fast, and does not change the access dates
- of the stale files.
-
- An entire directory tree of the stale files will eventually be
- built in MORGUE. All of the directories created in MORGUE should
- match the originals with respect to ownership and permissions.
- Once the process is complete you can archive the directory
- tree in MORGUE onto tape using tar, or rerez, and remove the
- directory tree.
- cd MORGUE
- rerez c *
- "remove the tape, remove the write ring, then check the
- tape with rerez t to be sure its okay"
- rm -rf *
- "optionally remove the MORGUE directory"
-
- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- !MAKE TWO COPIES OF THE TAR OR REREZ ARCHIVE, AND CHECK EACH FOR!
- !ABSOLUTE FLAWLESSNESS BEFORE BLOWING THOSE FILES AWAY !
- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-
- On a system that has never been derez'ed, there may be more than
- one tape full of files that are stale by the desired definition of
- staleness. Derez can incrementally be used to build up stale files
- until a tar image of the the MORGUE subdirectory will just fill a tape.
- First run derez with say, a 3 year definitition of staleness, and
- them check the size of MORGUE using:
- du -s MORGUE
- Repeat the derez operations with successively smaller intervals until
- du reports that a tar image of MORGUE will fill a tape. When this
- happens archive the enmorgued files using tar or rerez and remove the
- files in MORGUE. Repeat this operation until the desired staleness
- interval of say a year or less has been reached.
-
-
- Remember to create a listing of the files on each archive tape
- in a suitable system directory so users can locate any stale files
- they need later. The location of these files and their naming
- convention must be duly recorded in the derez man page.
- When incrementally building the MORGE as above,
- MORGUE/DEREZ will only contain a list of the last set of files
- that were enmorgued with derez. Use "tar t" or "rerez t" to get the
- complete archive list from the tape.
-
- The rest of this message is the "sh archive format" of the
- derez source.
- XXXXXXXXXXXXXXXXXXXXX Cut here and feed to /bin/sh XXXXXXXXXXXXXXXXXXX
- //go.sysin dd *
- if [ `wc -c < README` != 7387 ]; then
- made=FALSE
- /bin/echo 'error transmitting "README" --'
- /bin/echo 'length should be 7387, not' `wc -c < README`
- else
- made=TRUE
- fi
- if [ $made = TRUE ]; then
- /bin/chmod 644 README
- /bin/echo -n ' '; /bin/ls -ld README
- fi
- /bin/echo 'Extracting Makefile'
- sed 's/^X//' <<'//go.sysin dd *' >Makefile
- CFLAGS = -O
- PROGSRC = derez.c readbyte.c agehist.c
- PROGS = derez readbyte agehist rerez
- MANS = derez.1 readbyte.1 agehist.1 rerez.1
- MANDIR=/usr/local/man
-
- OWNER=root
- GROUP=daemon
-
- all : $P $(PROGS)
-
- install : all $(MANS)
- install -c -o $(OWNER) -g $(GROUP) -m 755 derez /usr/local/bin
- install -c -o $(OWNER) -g $(GROUP) -m 644 derez.1 $(MANDIR)/manl/derez.l
- install -c -o $(OWNER) -g $(GROUP) -m 755 readbyte /usr/local/bin
- install -c -o $(OWNER) -g $(GROUP) -m 644 readbyte.1 $(MANDIR)/manl/readbyte.l
- install -c -o $(OWNER) -g $(GROUP) -m 755 agehist /usr/local/bin
- install -c -o $(OWNER) -g $(GROUP) -m 644 agehist.1 $(MANDIR)/manl/agehist.l
- install -c -o $(OWNER) -g $(GROUP) -m 755 rerez /usr/local/bin
- install -c -o $(OWNER) -g $(GROUP) -m 644 rerez.1 $(MANDIR)/manl/rerez.l
-
- clean :
- rm -f *.o
-
- clobber : clean
- rm -f $(PROGS) scriptfile
-
- derez : derez.c
- cc -o derez derez.c
- lintderez :
- lint derez.c
-
- readbyte : readbyte.c
- cc -o readbyte readbyte.c
-
- agehist : agehist.c
- cc -o agehist agehist.c
-
- rerez.o : rmt.h
- cc -c -O -I. rerez.c
- rerez : rerez.o rmtlib.o
- cc -o rerez rerez.o rmtlib.o
-
- scriptfile : README Makefile $(PROGSRC) rerez.c $(MANS)
- touch scriptfile
- rcsdiff -c -r1.1 rerez.c > rerez.c.diff
- cp README scriptfile
- makescript README Makefile $(PROGSRC) rerez.c.diff rmtlib.c rmt.h $(MANS) >> scriptfile
- cp PART1 usenet1
- makescript README Makefile rerez.c.diff rmtlib.c rmt.h >> usenet1
- cp PART2 usenet2
- makescript $(PROGSRC) $(MANS) >> usenet2
- //go.sysin dd *
- if [ `wc -c < Makefile` != 1478 ]; then
- made=FALSE
- /bin/echo 'error transmitting "Makefile" --'
- /bin/echo 'length should be 1478, not' `wc -c < Makefile`
- else
- made=TRUE
- fi
- if [ $made = TRUE ]; then
- /bin/chmod 644 Makefile
- /bin/echo -n ' '; /bin/ls -ld Makefile
- fi
- /bin/echo 'Extracting rerez.c.diff'
- sed 's/^X//' <<'//go.sysin dd *' >rerez.c.diff
- *** /tmp/,RCSt1012366 Sun Dec 6 11:25:29 1987
- --- rerez.c Tue Jun 9 12:52:33 1987
- ***************
- *** 6,11
- * Tape Archival Program
- */
- #include <stdio.h>
- #include <sys/param.h>
- #include <sys/stat.h>
- #include <sys/dir.h>
-
- --- 6,12 -----
- * Tape Archival Program
- */
- #include <stdio.h>
- + #include <rmt.h> /* remote tape, must come before <sys/stat.h> */
- #include <sys/param.h>
- #include <sys/stat.h>
- #include <sys/dir.h>
- ***************
- *** 28,33
- char gid[8];
- char size[12];
- char mtime[12];
- char chksum[8];
- char linkflag;
- char linkname[NAMSIZ];
-
- --- 29,35 -----
- char gid[8];
- char size[12];
- char mtime[12];
- + char atime[12];
- char chksum[8];
- char linkflag;
- char linkname[NAMSIZ];
- ***************
- *** 82,88
- FILE *tfile;
- char tname[] = "/tmp/tarXXXXXX";
- char *usefile;
- ! char magtape[] = "/dev/rmt8";
- char *malloc();
- char *sprintf();
- char *strcat();
-
- --- 84,94 -----
- FILE *tfile;
- char tname[] = "/tmp/tarXXXXXX";
- char *usefile;
- ! #ifdef sun
- ! char magtape[] = "/dev/rmt0";
- ! #else
- ! char magtape[] = "/dev/rts0";
- ! #endif
- char *malloc();
- char *sprintf();
- char *strcat();
- ***************
- *** 161,166
- break;
-
- case 'm':
- mflag++;
- break;
-
-
- --- 167,174 -----
- break;
-
- case 'm':
- + fprintf(stderr, "You must be joking!\n");
- + exit(1);
- mflag++;
- break;
-
- ***************
- *** 267,272
- doxtract(argv);
- else
- dotable();
- done(0);
- }
-
-
- --- 275,281 -----
- doxtract(argv);
- else
- dotable();
- + close (mt);
- done(0);
- }
-
- ***************
- *** 373,378
- sp->st_gid = i;
- sscanf(dblock.dbuf.size, "%lo", &sp->st_size);
- sscanf(dblock.dbuf.mtime, "%lo", &sp->st_mtime);
- sscanf(dblock.dbuf.chksum, "%o", &chksum);
- if (chksum != (i = checksum())) {
- fprintf(stderr, "tar: directory checksum error (%d != %d)\n",
-
- --- 382,388 -----
- sp->st_gid = i;
- sscanf(dblock.dbuf.size, "%lo", &sp->st_size);
- sscanf(dblock.dbuf.mtime, "%lo", &sp->st_mtime);
- + sscanf(dblock.dbuf.atime, "%lo", &sp->st_atime);
- sscanf(dblock.dbuf.chksum, "%o", &chksum);
- if (chksum != (i = checksum())) {
- fprintf(stderr, "tar: directory checksum error (%d != %d)\n",
- ***************
- *** 557,562
- }
- lp->count--;
- close(infile);
- return;
- }
- lp = (struct linkbuf *) malloc(sizeof(*lp));
-
- --- 567,581 -----
- }
- lp->count--;
- close(infile);
- + {
- + struct timeval tv[2];
- +
- + tv[0].tv_sec = stbuf.st_atime;
- + tv[0].tv_usec = 0;
- + tv[1].tv_sec = stbuf.st_mtime;
- + tv[1].tv_usec = 0;
- + utimes(shortname, tv);
- + }
- return;
- }
- lp = (struct linkbuf *) malloc(sizeof(*lp));
- ***************
- *** 588,593
- blocks--;
- }
- close(infile);
- if (blocks != 0 || i != 0)
- fprintf(stderr, "tar: %s: file changed size\n",
- longname);
-
- --- 607,621 -----
- blocks--;
- }
- close(infile);
- + {
- + struct timeval tv[2];
- +
- + tv[0].tv_sec = stbuf.st_atime;
- + tv[0].tv_usec = 0;
- + tv[1].tv_sec = stbuf.st_mtime;
- + tv[1].tv_usec = 0;
- + utimes(shortname, tv);
- + }
- if (blocks != 0 || i != 0)
- fprintf(stderr, "tar: %s: file changed size\n",
- longname);
- ***************
- *** 642,648
- if (checkdir(dblock.dbuf.name))
- continue;
- if (dblock.dbuf.linkflag == '2') {
- ! unlink(dblock.dbuf.name);
- if (symlink(dblock.dbuf.linkname, dblock.dbuf.name)<0) {
- fprintf(stderr, "tar: %s: symbolic link failed\n",
- dblock.dbuf.name);
-
- --- 670,682 -----
- if (checkdir(dblock.dbuf.name))
- continue;
- if (dblock.dbuf.linkflag == '2') {
- ! /*
- ! * only unlink non-directories or empty directories
- ! */
- ! if (rmdir (dblock.dbuf.name) < 0) {
- ! if (errno == ENOTDIR)
- ! unlink(dblock.dbuf.name);
- ! }
- if (symlink(dblock.dbuf.linkname, dblock.dbuf.name)<0) {
- fprintf(stderr, "tar: %s: symbolic link failed\n",
- dblock.dbuf.name);
- ***************
- *** 657,663
- if (mflag == 0) {
- struct timeval tv[2];
-
- ! tv[0].tv_sec = time(0);
- tv[0].tv_usec = 0;
- tv[1].tv_sec = stbuf.st_mtime;
- tv[1].tv_usec = 0;
-
- --- 691,697 -----
- if (mflag == 0) {
- struct timeval tv[2];
-
- ! tv[0].tv_sec = stbuf.st_mtime;
- tv[0].tv_usec = 0;
- tv[1].tv_sec = stbuf.st_mtime;
- tv[1].tv_usec = 0;
- ***************
- *** 669,675
- continue;
- }
- if (dblock.dbuf.linkflag == '1') {
- ! unlink(dblock.dbuf.name);
- if (link(dblock.dbuf.linkname, dblock.dbuf.name) < 0) {
- fprintf(stderr, "tar: %s: cannot link\n",
- dblock.dbuf.name);
-
- --- 703,715 -----
- continue;
- }
- if (dblock.dbuf.linkflag == '1') {
- ! /*
- ! * only unlink non-directories or empty directories
- ! */
- ! if (rmdir (dblock.dbuf.name) < 0) {
- ! if (errno == ENOTDIR)
- ! unlink(dblock.dbuf.name);
- ! }
- if (link(dblock.dbuf.linkname, dblock.dbuf.name) < 0) {
- fprintf(stderr, "tar: %s: cannot link\n",
- dblock.dbuf.name);
- ***************
- *** 713,719
- if (mflag == 0) {
- struct timeval tv[2];
-
- ! tv[0].tv_sec = time(0);
- tv[0].tv_usec = 0;
- tv[1].tv_sec = stbuf.st_mtime;
- tv[1].tv_usec = 0;
-
- --- 753,759 -----
- if (mflag == 0) {
- struct timeval tv[2];
-
- ! tv[0].tv_sec = stbuf.st_atime;
- tv[0].tv_usec = 0;
- tv[1].tv_sec = stbuf.st_mtime;
- tv[1].tv_usec = 0;
- ***************
- *** 761,766
- printf("%7D", st->st_size);
- cp = ctime(&st->st_mtime);
- printf(" %-12.12s %-4.4s ", cp+4, cp+20);
- }
-
- #define SUID 04000
-
- --- 801,808 -----
- printf("%7D", st->st_size);
- cp = ctime(&st->st_mtime);
- printf(" %-12.12s %-4.4s ", cp+4, cp+20);
- + cp = ctime(&st->st_atime);
- + printf(" %-12.12s %-4.4s ", cp+4, cp+20);
- }
-
- #define SUID 04000
- ***************
- *** 884,889
- sprintf(dblock.dbuf.gid, "%6o ", sp->st_gid);
- sprintf(dblock.dbuf.size, "%11lo ", sp->st_size);
- sprintf(dblock.dbuf.mtime, "%11lo ", sp->st_mtime);
- }
-
- checksum()
-
- --- 926,932 -----
- sprintf(dblock.dbuf.gid, "%6o ", sp->st_gid);
- sprintf(dblock.dbuf.size, "%11lo ", sp->st_size);
- sprintf(dblock.dbuf.mtime, "%11lo ", sp->st_mtime);
- + sprintf(dblock.dbuf.atime, "%11lo ", sp->st_atime);
- }
-
- checksum()
- //go.sysin dd *
- if [ `wc -c < rerez.c.diff` != 6250 ]; then
- made=FALSE
- /bin/echo 'error transmitting "rerez.c.diff" --'
- /bin/echo 'length should be 6250, not' `wc -c < rerez.c.diff`
- else
- made=TRUE
- fi
- if [ $made = TRUE ]; then
- /bin/chmod 644 rerez.c.diff
- /bin/echo -n ' '; /bin/ls -ld rerez.c.diff
- fi
- /bin/echo 'Extracting rmtlib.c'
- sed 's/^X//' <<'//go.sysin dd *' >rmtlib.c
- X/*
- * rmt --- remote tape emulator subroutines
- *
- * Originally written by Jeff Lee, modified some by Arnold Robbins
- *
- * WARNING: The man page rmt(8) for /etc/rmt documents the remote mag
- * tape protocol which rdump and rrestore use. Unfortunately, the man
- * page is *WRONG*. The author of the routines I'm including originally
- * wrote his code just based on the man page, and it didn't work, so he
- * went to the rdump source to figure out why. The only thing he had to
- * change was to check for the 'F' return code in addition to the 'E',
- * and to separate the various arguments with \n instead of a space. I
- * personally don't think that this is much of a problem, but I wanted to
- * point it out.
- * -- Arnold Robbins
- *
- * Redone as a library that can replace open, read, write, etc, by
- * Fred Fish, with some additional work by Arnold Robbins.
- */
-
- X/*
- * MAXUNIT --- Maximum number of remote tape file units
- *
- * READ --- Return the number of the read side file descriptor
- * WRITE --- Return the number of the write side file descriptor
- */
-
- #define RMTIOCTL 1
-
- #include <stdio.h>
- #include <signal.h>
- #include <sys/types.h>
-
- #ifdef RMTIOCTL
- #include <sys/ioctl.h>
- #include <sys/mtio.h>
- #endif
-
- #include <errno.h>
- #include <setjmp.h>
- #include <sys/stat.h>
-
- #define BUFMAGIC 64 /* a magic number for buffer sizes */
- #define MAXUNIT 4
-
- #define READ(fd) (Ctp[fd][0])
- #define WRITE(fd) (Ptc[fd][1])
-
- static int Ctp[MAXUNIT][2] = { -1, -1, -1, -1, -1, -1, -1, -1 };
- static int Ptc[MAXUNIT][2] = { -1, -1, -1, -1, -1, -1, -1, -1 };
-
- static jmp_buf Jmpbuf;
- extern int errno;
-
- X/*
- * abort --- close off a remote tape connection
- */
-
- static void abort(fildes)
- int fildes;
- {
- close(READ(fildes));
- close(WRITE(fildes));
- READ(fildes) = -1;
- WRITE(fildes) = -1;
- }
-
-
-
- X/*
- * command --- attempt to perform a remote tape command
- */
-
- static int command(fildes, buf)
- int fildes;
- char *buf;
- {
- register int blen;
- int (*pstat)();
-
- X/*
- * save current pipe status and try to make the request
- */
-
- blen = strlen(buf);
- pstat = signal(SIGPIPE, SIG_IGN);
- if (write(WRITE(fildes), buf, blen) == blen)
- {
- signal(SIGPIPE, pstat);
- return(0);
- }
-
- X/*
- * something went wrong. close down and go home
- */
-
- signal(SIGPIPE, pstat);
- abort(fildes);
-
- errno = EIO;
- return(-1);
- }
-
-
-
- X/*
- * status --- retrieve the status from the pipe
- */
-
- static int status(fildes)
- int fildes;
- {
- int i;
- char c, *cp;
- char buffer[BUFMAGIC];
-
- X/*
- * read the reply command line
- */
-
- for (i = 0, cp = buffer; i < BUFMAGIC; i++, cp++)
- {
- if (read(READ(fildes), cp, 1) != 1)
- {
- abort(fildes);
- errno = EIO;
- return(-1);
- }
- if (*cp == '\n')
- {
- *cp = 0;
- break;
- }
- }
-
- if (i == BUFMAGIC)
- {
- abort(fildes);
- errno = EIO;
- return(-1);
- }
-
- X/*
- * check the return status
- */
-
- for (cp = buffer; *cp; cp++)
- if (*cp != ' ')
- break;
-
- if (*cp == 'E' || *cp == 'F')
- {
- errno = atoi(cp + 1);
- while (read(READ(fildes), &c, 1) == 1)
- if (c == '\n')
- break;
-
- if (*cp == 'F')
- abort(fildes);
-
- return(-1);
- }
-
- X/*
- * check for mis-synced pipes
- */
-
- if (*cp != 'A')
- {
- abort(fildes);
- errno = EIO;
- return(-1);
- }
-
- return(atoi(cp + 1));
- }
-
-
-
- X/*
- * _rmt_open --- open a magtape device on system specified, as given user
- *
- * file name has the form system[.user]:/dev/????
- */
-
- #define MAXHOSTLEN 257 /* BSD allows very long host names... */
-
- static int _rmt_open (path, oflag, mode)
- char *path;
- int oflag;
- int mode;
- {
- int i, rc;
- char buffer[BUFMAGIC];
- char system[MAXHOSTLEN];
- char device[BUFMAGIC];
- char login[BUFMAGIC];
- char *sys, *dev, *user;
-
- sys = system;
- dev = device;
- user = login;
-
- X/*
- * first, find an open pair of file descriptors
- */
-
- for (i = 0; i < MAXUNIT; i++)
- if (READ(i) == -1 && WRITE(i) == -1)
- break;
-
- if (i == MAXUNIT)
- {
- errno = EMFILE;
- return(-1);
- }
-
- X/*
- * pull apart system and device, and optional user
- * don't munge original string
- */
- while (*path != '.' && *path != ':') {
- *sys++ = *path++;
- }
- *sys = '\0';
- path++;
-
- if (*(path - 1) == '.')
- {
- while (*path != ':') {
- *user++ = *path++;
- }
- *user = '\0';
- path++;
- }
- else
- *user = '\0';
-
- while (*path) {
- *dev++ = *path++;
- }
- *dev = '\0';
-
- X/*
- * setup the pipes for the 'rsh' command and fork
- */
-
- if (pipe(Ptc[i]) == -1 || pipe(Ctp[i]) == -1)
- return(-1);
-
- if ((rc = fork()) == -1)
- return(-1);
-
- if (rc == 0)
- {
- close(0);
- dup(Ptc[i][0]);
- close(Ptc[i][0]); close(Ptc[i][1]);
- close(1);
- dup(Ctp[i][1]);
- close(Ctp[i][0]); close(Ctp[i][1]);
- (void) setuid (getuid ());
- (void) setgid (getgid ());
- if (*user)
- {
- execl("/usr/ucb/rsh", "rsh", system, "-l", login,
- "/etc/rmt", (char *) 0);
- execl("/usr/bin/remsh", "remsh", system, "-l", login,
- "/etc/rmt", (char *) 0);
- }
- else
- {
- execl("/usr/ucb/rsh", "rsh", system,
- "/etc/rmt", (char *) 0);
- execl("/usr/bin/remsh", "remsh", system,
- "/etc/rmt", (char *) 0);
- }
-
- X/*
- * bad problems if we get here
- */
-
- perror("exec");
- exit(1);
- }
-
- close(Ptc[i][0]); close(Ctp[i][1]);
-
- X/*
- * now attempt to open the tape device
- */
-
- sprintf(buffer, "O%s\n%d\n", device, oflag);
- if (command(i, buffer) == -1 || status(i) == -1)
- return(-1);
-
- return(i);
- }
-
-
-
- X/*
- * _rmt_close --- close a remote magtape unit and shut down
- */
-
- static int _rmt_close(fildes)
- int fildes;
- {
- int rc;
-
- if (command(fildes, "C\n") != -1)
- {
- rc = status(fildes);
-
- abort(fildes);
- return(rc);
- }
-
- return(-1);
- }
-
-
-
- X/*
- * _rmt_read --- read a buffer from a remote tape
- */
-
- static int _rmt_read(fildes, buf, nbyte)
- int fildes;
- char *buf;
- unsigned int nbyte;
- {
- int rc, i;
- char buffer[BUFMAGIC];
-
- sprintf(buffer, "R%d\n", nbyte);
- if (command(fildes, buffer) == -1 || (rc = status(fildes)) == -1)
- return(-1);
-
- for (i = 0; i < rc; i += nbyte, buf += nbyte)
- {
- nbyte = read(READ(fildes), buf, rc);
- if (nbyte <= 0)
- {
- abort(fildes);
- errno = EIO;
- return(-1);
- }
- }
-
- return(rc);
- }
-
-
-
- X/*
- * _rmt_write --- write a buffer to the remote tape
- */
-
- static int _rmt_write(fildes, buf, nbyte)
- int fildes;
- char *buf;
- unsigned int nbyte;
- {
- int rc;
- char buffer[BUFMAGIC];
- int (*pstat)();
-
- sprintf(buffer, "W%d\n", nbyte);
- if (command(fildes, buffer) == -1)
- return(-1);
-
- pstat = signal(SIGPIPE, SIG_IGN);
- if (write(WRITE(fildes), buf, nbyte) == nbyte)
- {
- signal (SIGPIPE, pstat);
- return(status(fildes));
- }
-
- signal (SIGPIPE, pstat);
- abort(fildes);
- errno = EIO;
- return(-1);
- }
-
-
-
- X/*
- * _rmt_lseek --- perform an imitation lseek operation remotely
- */
-
- static long _rmt_lseek(fildes, offset, whence)
- int fildes;
- long offset;
- int whence;
- {
- char buffer[BUFMAGIC];
-
- sprintf(buffer, "L%d\n%d\n", offset, whence);
- if (command(fildes, buffer) == -1)
- return(-1);
-
- return(status(fildes));
- }
-
-
- X/*
- * _rmt_ioctl --- perform raw tape operations remotely
- */
-
- #ifdef RMTIOCTL
- static _rmt_ioctl(fildes, op, arg)
- int fildes, op;
- char *arg;
- {
- char c;
- int rc, cnt;
- char buffer[BUFMAGIC];
-
- X/*
- * MTIOCOP is the easy one. nothing is transfered in binary
- */
-
- if (op == MTIOCTOP)
- {
- sprintf(buffer, "I%d\n%d\n", ((struct mtop *) arg)->mt_op,
- ((struct mtop *) arg)->mt_count);
- if (command(fildes, buffer) == -1)
- return(-1);
- return(status(fildes));
- }
-
- X/*
- * we can only handle 2 ops, if not the other one, punt
- */
-
- if (op != MTIOCGET)
- {
- errno = EINVAL;
- return(-1);
- }
-
- X/*
- * grab the status and read it directly into the structure
- * this assumes that the status buffer is (hopefully) not
- * padded and that 2 shorts fit in a long without any word
- * alignment problems, ie - the whole struct is contiguous
- * NOTE - this is probably NOT a good assumption.
- */
-
- if (command(fildes, "S\n") == -1 || (rc = status(fildes)) == -1)
- return(-1);
-
- for (; rc > 0; rc -= cnt, arg += cnt)
- {
- cnt = read(READ(fildes), arg, rc);
- if (cnt <= 0)
- {
- abort(fildes);
- errno = EIO;
- return(-1);
- }
- }
-
- X/*
- * now we check for byte position. mt_type is a small integer field
- * (normally) so we will check its magnitude. if it is larger than
- * 256, we will assume that the bytes are swapped and go through
- * and reverse all the bytes
- */
-
- if (((struct mtget *) arg)->mt_type < 256)
- return(0);
-
- for (cnt = 0; cnt < rc; cnt += 2)
- {
- c = arg[cnt];
- arg[cnt] = arg[cnt+1];
- arg[cnt+1] = c;
- }
-
- return(0);
- }
- #endif /* RMTIOCTL */
-
- X/*
- * Added routines to replace open(), close(), lseek(), ioctl(), etc.
- * The preprocessor can be used to remap these the rmtopen(), etc
- * thus minimizing source changes:
- *
- * #ifdef <something>
- * # define access rmtaccess
- * # define close rmtclose
- * # define creat rmtcreat
- * # define dup rmtdup
- * # define fcntl rmtfcntl
- * # define fstat rmtfstat
- * # define ioctl rmtioctl
- * # define isatty rmtisatty
- * # define lseek rmtlseek
- * # define lstat rmtlstat
- * # define open rmtopen
- * # define read rmtread
- * # define stat rmtstat
- * # define write rmtwrite
- * # define access rmtaccess
- * # define close rmtclose
- * # define creat rmtcreat
- * # define dup rmtdup
- * # define fcntl rmtfcntl
- * # define fstat rmtfstat
- * # define ioctl rmtioctl
- * # define lseek rmtlseek
- * # define open rmtopen
- * # define read rmtread
- * # define stat rmtstat
- * # define write rmtwrite
- * #endif
- *
- * -- Fred Fish
- *
- * ADR --- I set up a <rmt.h> include file for this
- *
- */
-
- X/*
- * Note that local vs remote file descriptors are distinquished
- * by adding a bias to the remote descriptors. This is a quick
- * and dirty trick that may not be portable to some systems.
- */
-
- #define REM_BIAS 128
-
-
- X/*
- * Test pathname to see if it is local or remote. A remote device
- * is any string that contains ":/dev/". Returns 1 if remote,
- * 0 otherwise.
- */
-
- static int remdev (path)
- register char *path;
- {
- #define strchr index
- extern char *strchr ();
-
- if ((path = strchr (path, ':')) != NULL)
- {
- if (strncmp (path + 1, "/dev/", 5) == 0)
- {
- return (1);
- }
- }
- return (0);
- }
-
-
- X/*
- * Open a local or remote file. Looks just like open(2) to
- * caller.
- */
-
- int rmtopen (path, oflag, mode)
- char *path;
- int oflag;
- int mode;
- {
- if (remdev (path))
- {
- return (_rmt_open (path, oflag, mode) + REM_BIAS);
- }
- else
- {
- return (open (path, oflag, mode));
- }
- }
-
- X/*
- * Test pathname for specified access. Looks just like access(2)
- * to caller.
- */
-
- int rmtaccess (path, amode)
- char *path;
- int amode;
- {
- if (remdev (path))
- {
- return (0); /* Let /etc/rmt find out */
- }
- else
- {
- return (access (path, amode));
- }
- }
-
-
- X/*
- * Read from stream. Looks just like read(2) to caller.
- */
-
- int rmtread (fildes, buf, nbyte)
- int fildes;
- char *buf;
- unsigned int nbyte;
- {
- if (isrmt (fildes))
- {
- return (_rmt_read (fildes - REM_BIAS, buf, nbyte));
- }
- else
- {
- return (read (fildes, buf, nbyte));
- }
- }
-
-
- X/*
- * Write to stream. Looks just like write(2) to caller.
- */
-
- int rmtwrite (fildes, buf, nbyte)
- int fildes;
- char *buf;
- unsigned int nbyte;
- {
- if (isrmt (fildes))
- {
- return (_rmt_write (fildes - REM_BIAS, buf, nbyte));
- }
- else
- {
- return (write (fildes, buf, nbyte));
- }
- }
-
- X/*
- * Perform lseek on file. Looks just like lseek(2) to caller.
- */
-
- long rmtlseek (fildes, offset, whence)
- int fildes;
- long offset;
- int whence;
- {
- if (isrmt (fildes))
- {
- return (_rmt_lseek (fildes - REM_BIAS, offset, whence));
- }
- else
- {
- return (lseek (fildes, offset, whence));
- }
- }
-
-
- X/*
- * Close a file. Looks just like close(2) to caller.
- */
-
- int rmtclose (fildes)
- int fildes;
- {
- if (isrmt (fildes))
- {
- return (_rmt_close (fildes - REM_BIAS));
- }
- else
- {
- return (close (fildes));
- }
- }
-
- X/*
- * Do ioctl on file. Looks just like ioctl(2) to caller.
- */
-
- int rmtioctl (fildes, request, arg)
- int fildes, request, arg;
- {
- if (isrmt (fildes))
- {
- #ifdef RMTIOCTL
- return (_rmt_ioctl (fildes, request, arg));
- #else
- errno = EOPNOTSUPP;
- return (-1); /* For now (fnf) */
- #endif
- }
- else
- {
- return (ioctl (fildes, request, arg));
- }
- }
-
-
- X/*
- * Duplicate an open file descriptor. Looks just like dup(2)
- * to caller.
- */
-
- int rmtdup (fildes)
- int fildes;
- {
- if (isrmt (fildes))
- {
- errno = EOPNOTSUPP;
- return (-1); /* For now (fnf) */
- }
- else
- {
- return (dup (fildes));
- }
- }
-
- X/*
- * Get file status. Looks just like fstat(2) to caller.
- */
-
- int rmtfstat (fildes, buf)
- int fildes;
- struct stat *buf;
- {
- if (isrmt (fildes))
- {
- errno = EOPNOTSUPP;
- return (-1); /* For now (fnf) */
- }
- else
- {
- return (fstat (fildes, buf));
- }
- }
-
-
- X/*
- * Get file status. Looks just like stat(2) to caller.
- */
-
- int rmtstat (path, buf)
- char *path;
- struct stat *buf;
- {
- if (remdev (path))
- {
- errno = EOPNOTSUPP;
- return (-1); /* For now (fnf) */
- }
- else
- {
- return (stat (path, buf));
- }
- }
-
-
-
- X/*
- * Create a file from scratch. Looks just like creat(2) to the caller.
- */
-
- #include <sys/file.h> /* BSD DEPENDANT!!! */
- X/* #include <fcntl.h> /* use this one for S5 with remote stuff */
-
- int rmtcreat (path, mode)
- char *path;
- int mode;
- {
- if (remdev (path))
- {
- return (rmtopen (path, 1 | O_CREAT, mode));
- }
- else
- {
- return (creat (path, mode));
- }
- }
-
- X/*
- * Isrmt. Let a programmer know he has a remote device.
- */
-
- int isrmt (fd)
- int fd;
- {
- return (fd >= REM_BIAS);
- }
-
- X/*
- * Rmtfcntl. Do a remote fcntl operation.
- */
-
- int rmtfcntl (fd, cmd, arg)
- int fd, cmd, arg;
- {
- if (isrmt (fd))
- {
- errno = EOPNOTSUPP;
- return (-1);
- }
- else
- {
- return (fcntl (fd, cmd, arg));
- }
- }
-
- X/*
- * Rmtisatty. Do the isatty function.
- */
-
- int rmtisatty (fd)
- int fd;
- {
- if (isrmt (fd))
- return (0);
- else
- return (isatty (fd));
- }
-
-
- X/*
- * Get file status, even if symlink. Looks just like lstat(2) to caller.
- */
-
- int rmtlstat (path, buf)
- char *path;
- struct stat *buf;
- {
- if (remdev (path))
- {
- errno = EOPNOTSUPP;
- return (-1); /* For now (fnf) */
- }
- else
- {
- return (lstat (path, buf));
- }
- }
- //go.sysin dd *
- if [ `wc -c < rmtlib.c` != 13684 ]; then
- made=FALSE
- /bin/echo 'error transmitting "rmtlib.c" --'
- /bin/echo 'length should be 13684, not' `wc -c < rmtlib.c`
- else
- made=TRUE
- fi
- if [ $made = TRUE ]; then
- /bin/chmod 440 rmtlib.c
- /bin/echo -n ' '; /bin/ls -ld rmtlib.c
- fi
- /bin/echo 'Extracting rmt.h'
- sed 's/^X//' <<'//go.sysin dd *' >rmt.h
- X/*
- * rmt.h
- *
- * Added routines to replace open(), close(), lseek(), ioctl(), etc.
- * The preprocessor can be used to remap these the rmtopen(), etc
- * thus minimizing source changes.
- *
- * This file must be included before <sys/stat.h>, since it redefines
- * stat to be rmtstat, so that struct stat xyzzy; declarations work
- * properly.
- *
- * -- Fred Fish (w/some changes by Arnold Robbins)
- */
-
-
- #ifndef access /* avoid multiple redefinition */
- #ifndef lint /* in this case what lint doesn't know won't hurt it */
- #define access rmtaccess
- #define close rmtclose
- #define creat rmtcreat
- #define dup rmtdup
- #define fcntl rmtfcntl
- #define fstat rmtfstat
- #define ioctl rmtioctl
- #define isatty rmtisatty
- #define lseek rmtlseek
- #define lstat rmtlstat
- #define open rmtopen
- #define read rmtread
- #define stat rmtstat
- #define write rmtwrite
-
- extern long rmtlseek (); /* all the rest are int's */
- #endif
- #endif
- //go.sysin dd *
- if [ `wc -c < rmt.h` != 904 ]; then
- made=FALSE
- /bin/echo 'error transmitting "rmt.h" --'
- /bin/echo 'length should be 904, not' `wc -c < rmt.h`
- else
- made=TRUE
- fi
- if [ $made = TRUE ]; then
- /bin/chmod 440 rmt.h
- /bin/echo -n ' '; /bin/ls -ld rmt.h
- fi
-
-