#define MWORD(m,i) (m[(unsigned)(i-1)/MLEN])
#define MBIT(i) (1<<((unsigned)(i-1)%MLEN))
#define BIS(i,w) (MWORD(w,i) |= MBIT(i))
#define BIC(i,w) (MWORD(w,i) &= ~MBIT(i))
#define BIT(i,w) (MWORD(w,i) & MBIT(i))
char tapename
[] = "/dev/rmt1";
char *magtape
= tapename
;
char dirfile
[] = "rstXXXXXX";
struct dinode tino
, dino
;
printf("Usage: restor x file file..., restor r filesys, or restor t\n");
for (cp
= *argv
++; *cp
; cp
++) {
printf("Bad key character %c\n", *cp
);
if (signal(SIGINT
, done
) == SIG_IGN
)
if (signal(SIGTERM
, done
) == SIG_IGN
)
signal(SIGTERM
, SIG_IGN
);
df
= creat(dirfile
, 0666);
printf("restor: %s - cannot create directory temporary\n", dirfile
);
doit(command
, argc
, argv
);
doit(command
, argc
, argv
)
int rstrfile(), rstrskip();
if ((mt
= open(magtape
, 0)) < 0) {
printf("%s: cannot open tape\n", magtape
);
if (readhdr(&spcl
) == 0) {
printf("Tape is not a dump tape\n");
printf("Dump date: %s", ctime(&spcl
.c_date
));
printf("Dumped from: %s", ctime(&spcl
.c_ddate
));
if (readhdr(&spcl
) == 0) {
printf("Tape is not a dump tape\n");
if (checkvol(&spcl
, 1) == 0) {
printf("Tape is not volume 1 of the dump\n");
pass1(); /* This sets the various maps on the way by */
while (i
< MAXXTR
-1 && argc
--) {
if ((d
= psearch(*argv
)) == 0 || BIT(d
, dumpmap
) == 0) {
printf("%s: not on the tape\n", *argv
++);
xtrlist
[i
].x_flags
|= XINUSE
;
printf("%s: inode %u\n", *argv
, d
);
printf("Mount desired tape volume: Specify volume #: ");
printf("Volume numbers are positive numerics\n");
if (readhdr(&spcl
) == 0) {
printf("tape is not dump tape\n");
if (checkvol(&spcl
, volno
) == 0) {
printf("Wrong volume (%d)\n", spcl
.c_volume
);
while (gethead(&spcl
) == 0)
if (checktype(&spcl
, TS_INODE
) == 1) {
printf("Can't find inode mask!\n");
if (checktype(&spcl
, TS_BITS
) == 0)
for (k
= 0; xtrlist
[k
].x_flags
; k
++) {
if (BIT(xtrlist
[k
].x_ino
, dumpmap
)) {
xtrlist
[k
].x_flags
|= ONTAPE
;
while(gethead(&spcl
) == 0)
if (checktype(&spcl
, TS_END
) == 1) {
for (k
= 0; xtrlist
[k
].x_flags
; k
++)
if ((xtrlist
[k
].x_flags
&XTRACTD
) == 0)
if (checktype(&spcl
, TS_INODE
) == 0) {
for (k
= 0; xtrlist
[k
].x_flags
; k
++) {
if (d
== xtrlist
[k
].x_ino
) {
printf("extract file %u\n", xtrlist
[k
].x_ino
);
sprintf(name
, "%u", xtrlist
[k
].x_ino
);
if ((ofile
= creat(name
, 0666)) < 0) {
printf("%s: cannot create file\n", name
);
chown(name
, spcl
.c_dinode
.di_uid
, spcl
.c_dinode
.di_gid
);
getfile(ino
, xtrfile
, skip
, spcl
.c_dinode
.di_size
);
xtrlist
[k
].x_flags
|= XTRACTD
;
if ((fi
= open(*argv
, 2)) < 0) {
printf("%s: cannot open\n", *argv
);
printf("Enter starting volume number: ");
printf("Last chance before scribbling on %s. ",
while (getchar() != '\n');
dread((daddr_t
)1, (char *)&sblock
, sizeof(sblock
));
maxi
= (sblock
.s_isize
-2)*INOPB
;
if (readhdr(&spcl
) == 0) {
printf("Missing volume record\n");
if (checkvol(&spcl
, volno
) == 0) {
printf("Tape is not volume %d\n", volno
);
if (ishead(&spcl
) == 0) {
printf("Missing header block\n");
while (gethead(&spcl
) == 0)
if (checktype(&spcl
, TS_END
) == 1) {
dwrite( (daddr_t
) 1, (char *) &sblock
);
if (checktype(&spcl
, TS_CLRI
) == 1) {
for (ino
= 1; ino
<= maxi
; ino
++)
if (BIT(ino
, clrimap
) == 0) {
dwrite( (daddr_t
) 1, (char *) &sblock
);
if (checktype(&spcl
, TS_BITS
) == 1) {
if (checktype(&spcl
, TS_INODE
) == 0) {
printf("Unknown header type\n");
printf("Resynced at inode %u\n", ino
);
printf("%u: ilist too small\n", ino
);
for (i
= 0; i
< NADDR
; i
++)
l3tol(taddr
, dino
.di_addr
, 1);
getfile(d
, rstrfile
, rstrskip
, dino
.di_size
);
ltol3(ip
->di_addr
, taddr
, NADDR
);
ip
->di_mode
= ip1
->di_mode
;
ip
->di_nlink
= ip1
->di_nlink
;
ip
->di_uid
= ip1
->di_uid
;
ip
->di_gid
= ip1
->di_gid
;
ip
->di_size
= ip1
->di_size
;
ip
->di_atime
= ip1
->di_atime
;
ip
->di_mtime
= ip1
->di_mtime
;
ip
->di_ctime
= ip1
->di_ctime
;
* Read the tape, bulding up a directory structure for extraction
while (gethead(&spcl
) == 0) {
printf("Can't find directory header!\n");
if (checktype(&spcl
, TS_BITS
) == 1) {
if (checktype(&spcl
, TS_CLRI
) == 1) {
if (checktype(&spcl
, TS_INODE
) == 0) {
inotab
[ipos
].t_ino
= spcl
.c_inumber
;
inotab
[ipos
++].t_seekpt
= seekpt
;
getfile(spcl
.c_inumber
, putdir
, null
, spcl
.c_dinode
.di_size
);
* Do the file extraction, calling the supplied functions
if (gethead(&addrblock
) == 0) {
printf("Missing address (header) block\n");
if (checktype(&addrblock
, TS_ADDR
) == 0) {
for (i
= 0; i
< addrblock
.c_count
; i
++) {
if (addrblock
.c_addr
[i
]) {
(*f1
)(buf
, size
> BSIZE
? (long) BSIZE
: size
);
(*f2
)(buf
, size
> BSIZE
? (long) BSIZE
: size
);
if ((size
-= BSIZE
) <= 0) {
while (gethead(&spcl
) == 0)
if (checktype(&spcl
, TS_ADDR
) == 1)
* Do the tape i\/o, dealling with volume changes
for (i
= 0; i
< NTREC
; i
++)
((struct spcl
*)&tbf
[i
*BSIZE
])->c_magic
= 0;
if ((i
= read(mt
, tbf
, NTREC
*BSIZE
)) < 0) {
printf("Tape read error: inode %u\n", curino
);
printf("Mount volume %d\n", volno
);
while (getchar() != '\n')
if ((mt
= open(magtape
, 0)) == -1) {
printf("Cannot open tape!\n");
if (readhdr(&tmpbuf
) == 0) {
printf("Not a dump tape.Try again\n");
if (checkvol(&tmpbuf
, volno
) == 0) {
printf("Wrong tape. Try again\n");
copy(&tbf
[(bct
++*BSIZE
)], b
, BSIZE
);
* Put and get the directory entries from the compressed
for (i
= 0; i
< sizeof(ino_t
); i
++)
for (i
= 0; i
< DIRSIZ
; i
++) {
for (i
= 0; i
< sizeof(ino_t
); i
++)
for (i
= 0; i
< DIRSIZ
; i
++)
if ((*bf
++ = readc()) == 0)
* read/write te directory file
write(df
, drblock
, BSIZE
);
read(df
, drblock
, BSIZE
);
write(df
, drblock
, bpt
+1);
* search the directory inode ino
for (i
= 0; i
< MAXINO
; i
++)
if (inotab
[i
].t_ino
== inum
) {
mseek(inotab
[i
].t_seekpt
);
if (direq(dir
.d_name
, "/"))
} while (direq(dir
.d_name
, cp
) == 0);
* Search the directory tree rooted at inode 2
* for the path pointed at by n
while (*cp1
!= '/' && *cp1
)
for (i
= 0; i
< DIRSIZ
; i
++)
* read/write a disk block, be sure to update the buffer
for (i
= 0; i
< NCACHE
; i
++) {
if (cache
[i
].c_bno
== bno
) {
copy(b
, cache
[i
].c_block
, BSIZE
);
if(write(fi
, b
, BSIZE
) != BSIZE
) {
printf("disk write error %D\n", bno
);
fprintf(stderr
, "disk write error %ld\n", bno
);
for (i
= 0; i
< NCACHE
; i
++) {
if (++curcache
>= NCACHE
)
if (cache
[curcache
].c_bno
== bno
) {
copy(cache
[curcache
].c_block
, buf
, cnt
);
cache
[curcache
].c_time
= 0;
cache
[curcache
].c_time
++;
if (cache
[j
].c_time
< cache
[curcache
].c_time
)
if (read(fi
, cache
[j
].c_block
, BSIZE
) != BSIZE
) {
printf("read error %D\n", bno
);
printf("read error %ld\n", bno
);
copy(cache
[j
].c_block
, buf
, cnt
);
* the inode manpulation routines. Like the system.
i
= sizeof(struct dinode
)/sizeof(int);
* itrunc/tloop/bfree free all of the blocks pointed at by the inode
register struct dinode
*ip
;
daddr_t bn
, iaddr
[NADDR
];
if (i
!= IFDIR
&& i
!= IFREG
)
l3tol(iaddr
, ip
->di_addr
, NADDR
);
for(i
=NADDR
-1;i
>=0;i
--) {
dread(bn
, ibuf
.data
, BSIZE
);
for(i
=NINDIR
-1;i
>=0;i
--) {
if(sblock
.s_nfree
>= NICFREE
) {
fbuf
.df_nfree
= sblock
.s_nfree
;
fbuf
.df_free
[i
] = sblock
.s_free
[i
];
sblock
.s_free
[sblock
.s_nfree
++] = bn
;
* allocate a block off the free list.
static char zeroes
[BSIZE
];
if(sblock
.s_nfree
== 0 || (bno
=sblock
.s_free
[--sblock
.s_nfree
]) == 0) {
printf("Out of space\n");
fprintf(stderr
, "Out of space.\n");
if(sblock
.s_nfree
== 0) {
dread(bno
, fbuf
.data
, BSIZE
);
sblock
.s_nfree
= fbuf
.df_nfree
;
sblock
.s_free
[i
] = fbuf
.df_free
[i
];
* map a block number into a block address, ensuring
* all of the correct indirect blocks are around. Allocate
* blocks 0..NADDR-4 are direct blocks
iaddr
[bn
] = nb
= balloc();
* addresses NADDR-3, NADDR-2, and NADDR-1
* have single, double, triple indirect blocks.
* the first step is to determine
* how many levels of indirection.
* fetch the address from the inode
if((nb
= iaddr
[NADDR
-j
]) == 0) {
iaddr
[NADDR
-j
] = nb
= balloc();
* fetch through the indirect blocks
dread(nb
, (char *)indir
, BSIZE
);
dwrite(nb
, (char *)indir
);
* read the tape into buf, then return whether or
* or not it is a header block.
if (buf
->c_magic
!= MAGIC
|| checksum((int *) buf
) == 0)
* return whether or not the buffer contains a header block
if (buf
->c_magic
!= MAGIC
|| checksum((int *) buf
) == 0)
printf("Checksum error %o\n", i
);
if (checktype(b
, TS_TAPE
) == 0)
* The next routines are called during file extraction to
* put the data into the right form and place.
write(ofile
, b
, (int) size
);
lseek(ofile
, (long) BSIZE
, 1);
register struct direct
*dp
;
for (dp
= (struct direct
*) b
, i
= 0; i
< BSIZE
; dp
++, i
+= sizeof(*dp
)) {
* read/write an inode from the disk
copy(&buf
[((inum
-1)%INOPB
)*sizeof(struct dinode
)], (char *) b
, sizeof(struct dinode
));
bno
= ((ino
- 1)/INOPB
) + 2;
copy((char *) b
, &buf
[((inum
-1)%INOPB
)*sizeof(struct dinode
)], sizeof(struct dinode
));
* read a bit mask from the tape into m.
m
+= (BSIZE
/(MLEN
/BITS
));
while (gethead(&spcl
) == 0)