155860Sbostic /*-
261433Sbostic * Copyright (c) 1992, 1993
361433Sbostic * The Regents of the University of California. All rights reserved.
455860Sbostic *
555860Sbostic * %sccs.include.redist.c%
655860Sbostic */
755860Sbostic
855860Sbostic #ifndef lint
9*69667Smargo static char sccsid[] = "@(#)library.c 8.3 (Berkeley) 05/24/95";
1055860Sbostic #endif /* not lint */
1155860Sbostic
1255491Sbostic #include <sys/param.h>
1355491Sbostic #include <sys/time.h>
1455491Sbostic #include <sys/stat.h>
1555491Sbostic #include <sys/mount.h>
1657201Smargo #include <sys/types.h>
1757201Smargo #include <sys/mman.h>
1855491Sbostic
1955491Sbostic #include <ufs/ufs/dinode.h>
2055491Sbostic #include <ufs/lfs/lfs.h>
2155491Sbostic
2255491Sbostic #include <fcntl.h>
2355491Sbostic #include <stdio.h>
2455856Sbostic #include <stdlib.h>
2555856Sbostic #include <string.h>
2660095Sbostic #include <unistd.h>
2760095Sbostic
2855491Sbostic #include "clean.h"
2955491Sbostic
3055856Sbostic void add_blocks __P((FS_INFO *, BLOCK_INFO *, int *, SEGSUM *, caddr_t,
3155856Sbostic daddr_t, daddr_t));
3255930Sbostic void add_inodes __P((FS_INFO *, BLOCK_INFO *, int *, SEGSUM *, caddr_t,
3355856Sbostic daddr_t));
3455856Sbostic int bi_compare __P((const void *, const void *));
3555856Sbostic int bi_toss __P((const void *, const void *, const void *));
3657201Smargo void get_ifile __P((FS_INFO *, int));
3755856Sbostic int get_superblock __P((FS_INFO *, struct lfs *));
3855856Sbostic int pseg_valid __P((FS_INFO *, SEGSUM *));
3955856Sbostic
4055491Sbostic /*
4161373Scgd * This function will get information on a a filesystem which matches
4261373Scgd * the name and type given. If a "name" is in a filesystem of the given
4361373Scgd * type, then buf is filled with that filesystem's info, and the
4461373Scgd * a non-zero value is returned.
4555491Sbostic */
4655491Sbostic int
fs_getmntinfo(buf,name,type)4761373Scgd fs_getmntinfo(buf, name, type)
4855491Sbostic struct statfs **buf;
4961373Scgd char *name;
5069256Smckusick char *type;
5155491Sbostic {
5261373Scgd /* allocate space for the filesystem info */
5361373Scgd *buf = (struct statfs *)malloc(sizeof(struct statfs));
5461373Scgd if (*buf == NULL)
5561373Scgd return 0;
5655491Sbostic
5761373Scgd /* grab the filesystem info */
5861373Scgd if (statfs(name, *buf) < 0) {
5961373Scgd free(*buf);
6061373Scgd return 0;
6161373Scgd }
6255491Sbostic
6361373Scgd /* check to see if it's the one we want */
6469256Smckusick if (strcmp((*buf)->f_fstypename, type) ||
6561373Scgd strncmp(name, (*buf)->f_mntonname, MNAMELEN)) {
6661373Scgd /* "this is not the filesystem you're looking for */
6761373Scgd free(*buf);
6861373Scgd return 0;
6955491Sbostic }
7055491Sbostic
7161373Scgd return 1;
7255491Sbostic }
7355491Sbostic
7455491Sbostic /*
7555856Sbostic * Get all the information available on an LFS file system.
7661373Scgd * Returns an pointer to an FS_INFO structure, NULL on error.
7755491Sbostic */
7855856Sbostic FS_INFO *
get_fs_info(lstatfsp,use_mmap)7961373Scgd get_fs_info (lstatfsp, use_mmap)
8061373Scgd struct statfs *lstatfsp; /* IN: pointer to statfs struct */
8157201Smargo int use_mmap; /* IN: mmap or read */
8255491Sbostic {
8361373Scgd FS_INFO *fsp;
8455491Sbostic int i;
8555491Sbostic
8661373Scgd fsp = (FS_INFO *)malloc(sizeof(FS_INFO));
8761373Scgd if (fsp == NULL)
8861373Scgd return NULL;
8961373Scgd bzero(fsp, sizeof(FS_INFO));
9055491Sbostic
9161373Scgd fsp->fi_statfsp = lstatfsp;
9261373Scgd if (get_superblock (fsp, &fsp->fi_lfs))
9361373Scgd err(1, "get_fs_info: get_superblock failed");
9461373Scgd fsp->fi_daddr_shift =
9561373Scgd fsp->fi_lfs.lfs_bshift - fsp->fi_lfs.lfs_fsbtodb;
9661373Scgd get_ifile (fsp, use_mmap);
9755856Sbostic return (fsp);
9855491Sbostic }
9955491Sbostic
10055856Sbostic /*
10155856Sbostic * If we are reading the ifile then we need to refresh it. Even if
10255856Sbostic * we are mmapping it, it might have grown. Finally, we need to
10355856Sbostic * refresh the file system information (statfs) info.
10455856Sbostic */
10555491Sbostic void
reread_fs_info(fsp,use_mmap)10661373Scgd reread_fs_info(fsp, use_mmap)
10761373Scgd FS_INFO *fsp; /* IN: prointer fs_infos to reread */
10860095Sbostic int use_mmap;
10955491Sbostic {
11055856Sbostic int i;
11155491Sbostic
11261373Scgd if (statfs(fsp->fi_statfsp->f_mntonname, fsp->fi_statfsp))
11361416Scgd err(1, "reread_fs_info: statfs failed");
11461373Scgd get_ifile (fsp, use_mmap);
11555491Sbostic }
11655491Sbostic
11755491Sbostic /*
11855856Sbostic * Gets the superblock from disk (possibly in face of errors)
11955491Sbostic */
12055491Sbostic int
get_superblock(fsp,sbp)12155491Sbostic get_superblock (fsp, sbp)
12255856Sbostic FS_INFO *fsp; /* local file system info structure */
12355856Sbostic struct lfs *sbp;
12455491Sbostic {
12555856Sbostic char mntfromname[MNAMELEN+1];
12655856Sbostic int fid;
12755491Sbostic
12855491Sbostic strcpy(mntfromname, "/dev/r");
12955856Sbostic strcat(mntfromname, fsp->fi_statfsp->f_mntfromname+5);
13055491Sbostic
13155491Sbostic if ((fid = open(mntfromname, O_RDONLY, (mode_t)0)) < 0) {
13255856Sbostic err(0, "get_superblock: bad open");
13355856Sbostic return (-1);
13455491Sbostic }
13555491Sbostic
13655856Sbostic get(fid, LFS_LABELPAD, sbp, sizeof(struct lfs));
13755491Sbostic close (fid);
13855491Sbostic
13955856Sbostic return (0);
14055491Sbostic }
14155491Sbostic
14255491Sbostic /*
14355856Sbostic * This function will map the ifile into memory. It causes a
14455856Sbostic * fatal error on failure.
14555491Sbostic */
14655856Sbostic void
get_ifile(fsp,use_mmap)14757201Smargo get_ifile (fsp, use_mmap)
14855491Sbostic FS_INFO *fsp;
14957201Smargo int use_mmap;
15057201Smargo
15155491Sbostic {
15255856Sbostic struct stat file_stat;
15355856Sbostic caddr_t ifp;
15455856Sbostic char *ifile_name;
15555856Sbostic int count, fid;
15655491Sbostic
15755856Sbostic ifp = NULL;
15855856Sbostic ifile_name = malloc(strlen(fsp->fi_statfsp->f_mntonname) +
15955856Sbostic strlen(IFILE_NAME)+2);
16055856Sbostic strcat(strcat(strcpy(ifile_name, fsp->fi_statfsp->f_mntonname), "/"),
16155856Sbostic IFILE_NAME);
16255491Sbostic
16355856Sbostic if ((fid = open(ifile_name, O_RDWR, (mode_t)0)) < 0)
16455856Sbostic err(1, "get_ifile: bad open");
16555491Sbostic
16655856Sbostic if (fstat (fid, &file_stat))
16755856Sbostic err(1, "get_ifile: fstat failed");
16855491Sbostic
16957201Smargo if (use_mmap && file_stat.st_size == fsp->fi_ifile_length) {
17057201Smargo (void) close(fid);
17157201Smargo return;
17257201Smargo }
17355856Sbostic
17455491Sbostic /* get the ifile */
17557201Smargo if (use_mmap) {
17657201Smargo if (fsp->fi_cip)
17757201Smargo munmap((caddr_t)fsp->fi_cip, fsp->fi_ifile_length);
17857201Smargo ifp = mmap ((caddr_t)0, file_stat.st_size,
17957201Smargo PROT_READ|PROT_WRITE, 0, fid, (off_t)0);
18057201Smargo if (ifp == (caddr_t)(-1))
18157201Smargo err(1, "get_ifile: mmap failed");
18257201Smargo } else {
18357201Smargo if (fsp->fi_cip)
18457201Smargo free(fsp->fi_cip);
18557201Smargo if (!(ifp = malloc (file_stat.st_size)))
18657201Smargo err (1, "get_ifile: malloc failed");
18755856Sbostic redo_read:
18857201Smargo count = read (fid, ifp, (size_t) file_stat.st_size);
18955491Sbostic
19057201Smargo if (count < 0)
19157201Smargo err(1, "get_ifile: bad ifile read");
19257201Smargo else if (count < file_stat.st_size) {
19357201Smargo err(0, "get_ifile");
19457201Smargo if (lseek(fid, 0, SEEK_SET) < 0)
19557201Smargo err(1, "get_ifile: bad ifile lseek");
19657201Smargo goto redo_read;
19757201Smargo }
19855491Sbostic }
19957201Smargo fsp->fi_ifile_length = file_stat.st_size;
20055491Sbostic close (fid);
20155491Sbostic
20255856Sbostic fsp->fi_cip = (CLEANERINFO *)ifp;
20355856Sbostic fsp->fi_segusep = (SEGUSE *)(ifp + CLEANSIZE(fsp));
20455856Sbostic fsp->fi_ifilep = (IFILE *)((caddr_t)fsp->fi_segusep + SEGTABSIZE(fsp));
20555856Sbostic
20655856Sbostic /*
20755856Sbostic * The number of ifile entries is equal to the number of blocks
20855856Sbostic * blocks in the ifile minus the ones allocated to cleaner info
20955856Sbostic * and segment usage table multiplied by the number of ifile
21055856Sbostic * entries per page.
21155856Sbostic */
21255856Sbostic fsp->fi_ifile_count = (fsp->fi_ifile_length >> fsp->fi_lfs.lfs_bshift -
21355856Sbostic fsp->fi_lfs.lfs_cleansz - fsp->fi_lfs.lfs_segtabsz) *
21455856Sbostic fsp->fi_lfs.lfs_ifpb;
21555856Sbostic
21655491Sbostic free (ifile_name);
21755491Sbostic }
21855491Sbostic
21955491Sbostic /*
22055856Sbostic * This function will scan a segment and return a list of
22155491Sbostic * <inode, blocknum> pairs which indicate which blocks were
22255856Sbostic * contained as live data within the segment when the segment
22355856Sbostic * summary was read (it may have "died" since then). Any given
22455856Sbostic * pair will be listed at most once.
22555491Sbostic */
22655491Sbostic int
lfs_segmapv(fsp,seg,seg_buf,blocks,bcount)22755930Sbostic lfs_segmapv(fsp, seg, seg_buf, blocks, bcount)
22855856Sbostic FS_INFO *fsp; /* pointer to local file system information */
22955856Sbostic int seg; /* the segment number */
23055856Sbostic caddr_t seg_buf; /* the buffer containing the segment's data */
23155856Sbostic BLOCK_INFO **blocks; /* OUT: array of block_info for live blocks */
23255856Sbostic int *bcount; /* OUT: number of active blocks in segment */
23355491Sbostic {
23455856Sbostic BLOCK_INFO *bip;
23555856Sbostic SEGSUM *sp;
23655856Sbostic SEGUSE *sup;
23756623Smargo FINFO *fip;
23855856Sbostic struct lfs *lfsp;
23955856Sbostic caddr_t s, segend;
24055856Sbostic daddr_t pseg_addr, seg_addr;
241*69667Smargo int i, nelem, nblocks, nsegs, sumsize;
24255856Sbostic time_t timestamp;
24355491Sbostic
24455856Sbostic lfsp = &fsp->fi_lfs;
24555930Sbostic nelem = 2 * lfsp->lfs_ssize;
24655930Sbostic if (!(bip = malloc(nelem * sizeof(BLOCK_INFO))))
24755856Sbostic goto err0;
24855491Sbostic
24955856Sbostic sup = SEGUSE_ENTRY(lfsp, fsp->fi_segusep, seg);
25055856Sbostic s = seg_buf + (sup->su_flags & SEGUSE_SUPERBLOCK ? LFS_SBPAD : 0);
25155856Sbostic seg_addr = sntoda(lfsp, seg);
25255856Sbostic pseg_addr = seg_addr + (sup->su_flags & SEGUSE_SUPERBLOCK ? btodb(LFS_SBPAD) : 0);
25355856Sbostic #ifdef VERBOSE
25455856Sbostic printf("\tsegment buffer at: 0x%x\tseg_addr 0x%x\n", s, seg_addr);
25555856Sbostic #endif /* VERBOSE */
25655491Sbostic
25755856Sbostic *bcount = 0;
258*69667Smargo for (nsegs = 0, timestamp = 0; nsegs < sup->su_nsums; nsegs++) {
25955856Sbostic sp = (SEGSUM *)s;
26056623Smargo
261*69667Smargo nblocks = pseg_valid(fsp, sp);
262*69667Smargo if (nblocks <= 0) {
263*69667Smargo printf("Warning: invalid segment summary at 0x%x\n",
264*69667Smargo pseg_addr);
265*69667Smargo break;
266*69667Smargo }
267*69667Smargo
26855491Sbostic #ifdef VERBOSE
26955856Sbostic printf("\tpartial at: 0x%x\n", pseg_addr);
27055856Sbostic print_SEGSUM(lfsp, sp);
27155491Sbostic fflush(stdout);
27255491Sbostic #endif /* VERBOSE */
27355491Sbostic
27455856Sbostic /* Check if we have hit old data */
27555856Sbostic if (timestamp > ((SEGSUM*)s)->ss_create)
27655856Sbostic break;
27755491Sbostic timestamp = ((SEGSUM*)s)->ss_create;
27855491Sbostic
27956623Smargo #ifdef DIAGNOSTIC
28056623Smargo /* Verfiy size of summary block */
28156623Smargo sumsize = sizeof(SEGSUM) +
28256623Smargo (sp->ss_ninos + INOPB(lfsp) - 1) / INOPB(lfsp);
283*69667Smargo for (i = 0, fip = (FINFO *)(sp + 1); i < sp->ss_nfinfo; ++i) {
28456623Smargo sumsize += sizeof(FINFO) +
28556623Smargo (fip->fi_nblocks - 1) * sizeof(daddr_t);
28656623Smargo fip = (FINFO *)(&fip->fi_blocks[fip->fi_nblocks]);
28756623Smargo }
28856623Smargo if (sumsize > LFS_SUMMARY_SIZE) {
28956623Smargo fprintf(stderr,
29056623Smargo "Segment %d summary block too big: %d\n",
29156623Smargo seg, sumsize);
29256623Smargo exit(1);
29356623Smargo }
29456623Smargo #endif
29556623Smargo
29655930Sbostic if (*bcount + nblocks + sp->ss_ninos > nelem) {
29755930Sbostic nelem = *bcount + nblocks + sp->ss_ninos;
29855930Sbostic bip = realloc (bip, nelem * sizeof(BLOCK_INFO));
29955930Sbostic if (!bip)
30055930Sbostic goto err0;
30155856Sbostic }
30255856Sbostic add_blocks(fsp, bip, bcount, sp, seg_buf, seg_addr, pseg_addr);
30355930Sbostic add_inodes(fsp, bip, bcount, sp, seg_buf, seg_addr);
30455856Sbostic pseg_addr += fsbtodb(lfsp, nblocks) +
30555856Sbostic bytetoda(fsp, LFS_SUMMARY_SIZE);
30655856Sbostic s += (nblocks << lfsp->lfs_bshift) + LFS_SUMMARY_SIZE;
30755856Sbostic }
30855856Sbostic qsort(bip, *bcount, sizeof(BLOCK_INFO), bi_compare);
30955856Sbostic toss(bip, bcount, sizeof(BLOCK_INFO), bi_toss, NULL);
31055856Sbostic #ifdef VERBOSE
31155856Sbostic {
31255856Sbostic BLOCK_INFO *_bip;
31355856Sbostic int i;
31455491Sbostic
31555856Sbostic printf("BLOCK INFOS\n");
31655856Sbostic for (_bip = bip, i=0; i < *bcount; ++_bip, ++i)
31755856Sbostic PRINT_BINFO(_bip);
31855491Sbostic }
31955856Sbostic #endif
32055856Sbostic *blocks = bip;
32155856Sbostic return (0);
32255856Sbostic
32355856Sbostic err0: *bcount = 0;
32455856Sbostic return (-1);
32555491Sbostic
32655491Sbostic }
32755491Sbostic
32855491Sbostic /*
32955856Sbostic * This will parse a partial segment and fill in BLOCK_INFO structures
33055856Sbostic * for each block described in the segment summary. It will not include
33155856Sbostic * blocks or inodes from files with new version numbers.
33255491Sbostic */
33355491Sbostic void
add_blocks(fsp,bip,countp,sp,seg_buf,segaddr,psegaddr)33455856Sbostic add_blocks (fsp, bip, countp, sp, seg_buf, segaddr, psegaddr)
33555491Sbostic FS_INFO *fsp; /* pointer to super block */
33655856Sbostic BLOCK_INFO *bip; /* Block info array */
33755856Sbostic int *countp; /* IN/OUT: number of blocks in array */
33855856Sbostic SEGSUM *sp; /* segment summmary pointer */
33955856Sbostic caddr_t seg_buf; /* buffer containing segment */
34055856Sbostic daddr_t segaddr; /* address of this segment */
34155856Sbostic daddr_t psegaddr; /* address of this partial segment */
34255491Sbostic {
34355856Sbostic IFILE *ifp;
34455856Sbostic FINFO *fip;
34555856Sbostic caddr_t bp;
34655930Sbostic daddr_t *dp, *iaddrp;
34755856Sbostic int db_per_block, i, j;
348*69667Smargo int db_frag;
34955856Sbostic u_long page_size;
350*69667Smargo long *lp;
35155491Sbostic
35255491Sbostic #ifdef VERBOSE
35355856Sbostic printf("FILE INFOS\n");
35455491Sbostic #endif
35555856Sbostic db_per_block = fsbtodb(&fsp->fi_lfs, 1);
35655856Sbostic page_size = fsp->fi_lfs.lfs_bsize;
35755856Sbostic bp = seg_buf + datobyte(fsp, psegaddr - segaddr) + LFS_SUMMARY_SIZE;
35855856Sbostic bip += *countp;
35955856Sbostic psegaddr += bytetoda(fsp, LFS_SUMMARY_SIZE);
36055856Sbostic iaddrp = (daddr_t *)((caddr_t)sp + LFS_SUMMARY_SIZE);
36155856Sbostic --iaddrp;
36255856Sbostic for (fip = (FINFO *)(sp + 1), i = 0; i < sp->ss_nfinfo;
36355856Sbostic ++i, fip = (FINFO *)(&fip->fi_blocks[fip->fi_nblocks])) {
36455491Sbostic
36555856Sbostic ifp = IFILE_ENTRY(&fsp->fi_lfs, fsp->fi_ifilep, fip->fi_ino);
36655856Sbostic PRINT_FINFO(fip, ifp);
36755856Sbostic if (ifp->if_version > fip->fi_version)
36855491Sbostic continue;
36955856Sbostic dp = &(fip->fi_blocks[0]);
37055856Sbostic for (j = 0; j < fip->fi_nblocks; j++, dp++) {
37155856Sbostic while (psegaddr == *iaddrp) {
37255856Sbostic psegaddr += db_per_block;
37355856Sbostic bp += page_size;
37455856Sbostic --iaddrp;
37555491Sbostic }
37655856Sbostic bip->bi_inode = fip->fi_ino;
37755856Sbostic bip->bi_lbn = *dp;
37855856Sbostic bip->bi_daddr = psegaddr;
37955856Sbostic bip->bi_segcreate = (time_t)(sp->ss_create);
38055856Sbostic bip->bi_bp = bp;
38156193Smargo bip->bi_version = ifp->if_version;
382*69667Smargo if (fip->fi_lastlength == page_size) {
383*69667Smargo bip->bi_size = page_size;
384*69667Smargo psegaddr += db_per_block;
385*69667Smargo bp += page_size;
386*69667Smargo } else {
387*69667Smargo db_frag = fragstodb(&(fsp->fi_lfs),
388*69667Smargo numfrags(&(fsp->fi_lfs),
389*69667Smargo fip->fi_lastlength));
390*69667Smargo #ifdef VERBOSE
391*69667Smargo printf("lastlength, frags: %d, %d, %d\n",
392*69667Smargo fip->fi_lastlength, temp,
393*69667Smargo bytetoda(fsp, temp));
394*69667Smargo fflush(stdout);
395*69667Smargo #endif
396*69667Smargo bip->bi_size = fip->fi_lastlength;
397*69667Smargo bp += fip->fi_lastlength;
398*69667Smargo psegaddr += db_frag;
399*69667Smargo }
40055856Sbostic ++bip;
40155856Sbostic ++(*countp);
40255491Sbostic }
40355491Sbostic }
40455491Sbostic }
40555491Sbostic
40655856Sbostic /*
40755856Sbostic * For a particular segment summary, reads the inode blocks and adds
40855856Sbostic * INODE_INFO structures to the array. Returns the number of inodes
40955856Sbostic * actually added.
41055856Sbostic */
41155491Sbostic void
add_inodes(fsp,bip,countp,sp,seg_buf,seg_addr)41255930Sbostic add_inodes (fsp, bip, countp, sp, seg_buf, seg_addr)
41355491Sbostic FS_INFO *fsp; /* pointer to super block */
41455930Sbostic BLOCK_INFO *bip; /* block info array */
41555856Sbostic int *countp; /* pointer to current number of inodes */
41655856Sbostic SEGSUM *sp; /* segsum pointer */
41755491Sbostic caddr_t seg_buf; /* the buffer containing the segment's data */
41855856Sbostic daddr_t seg_addr; /* disk address of seg_buf */
41955491Sbostic {
42055856Sbostic struct dinode *di;
42155856Sbostic struct lfs *lfsp;
42255856Sbostic IFILE *ifp;
42355930Sbostic BLOCK_INFO *bp;
42455856Sbostic daddr_t *daddrp;
42555856Sbostic ino_t inum;
42655856Sbostic int i;
42755491Sbostic
42855856Sbostic if (sp->ss_ninos <= 0)
42955856Sbostic return;
43055491Sbostic
43155930Sbostic bp = bip + *countp;
43255856Sbostic lfsp = &fsp->fi_lfs;
43355491Sbostic #ifdef VERBOSE
43455930Sbostic (void) printf("INODES:\n");
43555491Sbostic #endif
43655856Sbostic daddrp = (daddr_t *)((caddr_t)sp + LFS_SUMMARY_SIZE);
43755856Sbostic for (i = 0; i < sp->ss_ninos; ++i) {
43855491Sbostic if (i % INOPB(lfsp) == 0) {
43955856Sbostic --daddrp;
44055856Sbostic di = (struct dinode *)(seg_buf +
44155856Sbostic ((*daddrp - seg_addr) << fsp->fi_daddr_shift));
44255491Sbostic } else
44355491Sbostic ++di;
44455491Sbostic
44557201Smargo inum = di->di_inumber;
44655930Sbostic bp->bi_lbn = LFS_UNUSED_LBN;
44755930Sbostic bp->bi_inode = inum;
44855930Sbostic bp->bi_daddr = *daddrp;
44955930Sbostic bp->bi_bp = di;
45055930Sbostic bp->bi_segcreate = sp->ss_create;
45155491Sbostic
45256036Sbostic if (inum == LFS_IFILE_INUM) {
45356193Smargo bp->bi_version = 1; /* Ifile version should be 1 */
45455930Sbostic bp++;
45555856Sbostic ++(*countp);
45656036Sbostic PRINT_INODE(1, bp);
45756036Sbostic } else {
45856036Sbostic ifp = IFILE_ENTRY(lfsp, fsp->fi_ifilep, inum);
45956036Sbostic PRINT_INODE(ifp->if_daddr == *daddrp, bp);
46056193Smargo bp->bi_version = ifp->if_version;
46156036Sbostic if (ifp->if_daddr == *daddrp) {
46256036Sbostic bp++;
46356036Sbostic ++(*countp);
46456036Sbostic }
46556036Sbostic }
46655491Sbostic }
46755491Sbostic }
46855491Sbostic
46955491Sbostic /*
47055856Sbostic * Checks the summary checksum and the data checksum to determine if the
47155856Sbostic * segment is valid or not. Returns the size of the partial segment if it
47255856Sbostic * is valid, * and 0 otherwise. Use dump_summary to figure out size of the
47355856Sbostic * the partial as well as whether or not the checksum is valid.
47455491Sbostic */
47555491Sbostic int
pseg_valid(fsp,ssp)47655491Sbostic pseg_valid (fsp, ssp)
47755491Sbostic FS_INFO *fsp; /* pointer to file system info */
47855856Sbostic SEGSUM *ssp; /* pointer to segment summary block */
47955491Sbostic {
48055491Sbostic caddr_t p;
48155856Sbostic int i, nblocks;
48255856Sbostic u_long *datap;
48355491Sbostic
484*69667Smargo if (ssp->ss_magic != SS_MAGIC)
485*69667Smargo return(0);
486*69667Smargo
48756655Sbostic if ((nblocks = dump_summary(&fsp->fi_lfs, ssp, 0, NULL)) <= 0 ||
48856655Sbostic nblocks > fsp->fi_lfs.lfs_ssize - 1)
48955856Sbostic return(0);
49055491Sbostic
49155856Sbostic /* check data/inode block(s) checksum too */
49255856Sbostic datap = (u_long *)malloc(nblocks * sizeof(u_long));
49355491Sbostic p = (caddr_t)ssp + LFS_SUMMARY_SIZE;
49455856Sbostic for (i = 0; i < nblocks; ++i) {
49555491Sbostic datap[i] = *((u_long *)p);
49655856Sbostic p += fsp->fi_lfs.lfs_bsize;
49755491Sbostic }
49855856Sbostic if (cksum ((void *)datap, nblocks * sizeof(u_long)) != ssp->ss_datasum)
49955856Sbostic return (0);
50055491Sbostic
50155856Sbostic return (nblocks);
50255491Sbostic }
50355491Sbostic
50455491Sbostic
50555491Sbostic /* #define MMAP_SEGMENT */
50655491Sbostic /*
50755491Sbostic * read a segment into a memory buffer
50855491Sbostic */
50955491Sbostic int
mmap_segment(fsp,segment,segbuf,use_mmap)51057201Smargo mmap_segment (fsp, segment, segbuf, use_mmap)
51155856Sbostic FS_INFO *fsp; /* file system information */
51255856Sbostic int segment; /* segment number */
51355856Sbostic caddr_t *segbuf; /* pointer to buffer area */
51457201Smargo int use_mmap; /* mmap instead of read */
51555491Sbostic {
51655856Sbostic struct lfs *lfsp;
51755856Sbostic int fid; /* fildes for file system device */
51855856Sbostic daddr_t seg_daddr; /* base disk address of segment */
51955856Sbostic off_t seg_byte;
52055856Sbostic size_t ssize;
52155856Sbostic char mntfromname[MNAMELEN+2];
52255491Sbostic
52355856Sbostic lfsp = &fsp->fi_lfs;
52455856Sbostic
52555491Sbostic /* get the disk address of the beginning of the segment */
52655491Sbostic seg_daddr = sntoda(lfsp, segment);
52755856Sbostic seg_byte = datobyte(fsp, seg_daddr);
52855856Sbostic ssize = seg_size(lfsp);
52955491Sbostic
53055491Sbostic strcpy(mntfromname, "/dev/r");
53155856Sbostic strcat(mntfromname, fsp->fi_statfsp->f_mntfromname+5);
53255491Sbostic
53355491Sbostic if ((fid = open(mntfromname, O_RDONLY, (mode_t)0)) < 0) {
53455856Sbostic err(0, "mmap_segment: bad open");
53555856Sbostic return (-1);
53655491Sbostic }
53755491Sbostic
53857201Smargo if (use_mmap) {
53957201Smargo *segbuf = mmap ((caddr_t)0, seg_size(lfsp), PROT_READ,
54057201Smargo 0, fid, seg_byte);
54157201Smargo if (*(long *)segbuf < 0) {
54257201Smargo err(0, "mmap_segment: mmap failed");
54357201Smargo return (NULL);
54457201Smargo }
54557201Smargo } else {
54655856Sbostic #ifdef VERBOSE
54757201Smargo printf("mmap_segment\tseg_daddr: %lu\tseg_size: %lu\tseg_offset: %qu\n",
54857201Smargo seg_daddr, ssize, seg_byte);
54955856Sbostic #endif
55057201Smargo /* malloc the space for the buffer */
55157201Smargo *segbuf = malloc(ssize);
55257201Smargo if (!*segbuf) {
55357201Smargo err(0, "mmap_segment: malloc failed");
55457201Smargo return(NULL);
55557201Smargo }
55655491Sbostic
55757201Smargo /* read the segment data into the buffer */
55857201Smargo if (lseek (fid, seg_byte, SEEK_SET) != seg_byte) {
55957201Smargo err (0, "mmap_segment: bad lseek");
56057201Smargo free(*segbuf);
56157201Smargo return (-1);
56257201Smargo }
56357201Smargo
56457201Smargo if (read (fid, *segbuf, ssize) != ssize) {
56557201Smargo err (0, "mmap_segment: bad read");
56657201Smargo free(*segbuf);
56757201Smargo return (-1);
56857201Smargo }
56955491Sbostic }
57055491Sbostic close (fid);
57155491Sbostic
57255856Sbostic return (0);
57355491Sbostic }
57455491Sbostic
57555491Sbostic void
munmap_segment(fsp,seg_buf,use_mmap)57657201Smargo munmap_segment (fsp, seg_buf, use_mmap)
57755856Sbostic FS_INFO *fsp; /* file system information */
57855856Sbostic caddr_t seg_buf; /* pointer to buffer area */
57957201Smargo int use_mmap; /* mmap instead of read/write */
58055491Sbostic {
58157201Smargo if (use_mmap)
58257201Smargo munmap (seg_buf, seg_size(&fsp->fi_lfs));
58357201Smargo else
58457201Smargo free (seg_buf);
58555491Sbostic }
58655491Sbostic
58755491Sbostic
58855491Sbostic /*
58955491Sbostic * USEFUL DEBUGGING TOOLS:
59055491Sbostic */
59155491Sbostic void
print_SEGSUM(lfsp,p)59255856Sbostic print_SEGSUM (lfsp, p)
59355856Sbostic struct lfs *lfsp;
59455856Sbostic SEGSUM *p;
59555491Sbostic {
59655856Sbostic if (p)
59755856Sbostic (void) dump_summary(lfsp, p, DUMP_ALL, NULL);
59855491Sbostic else printf("0x0");
59955491Sbostic fflush(stdout);
60055491Sbostic }
60155491Sbostic
60255856Sbostic int
bi_compare(a,b)60355856Sbostic bi_compare(a, b)
60455856Sbostic const void *a;
60555856Sbostic const void *b;
60655491Sbostic {
60755856Sbostic const BLOCK_INFO *ba, *bb;
60855856Sbostic int diff;
60955491Sbostic
61055856Sbostic ba = a;
61155856Sbostic bb = b;
61255491Sbostic
61355856Sbostic if (diff = (int)(ba->bi_inode - bb->bi_inode))
61455856Sbostic return (diff);
61555930Sbostic if (diff = (int)(ba->bi_lbn - bb->bi_lbn)) {
61655930Sbostic if (ba->bi_lbn == LFS_UNUSED_LBN)
61755930Sbostic return(-1);
61855930Sbostic else if (bb->bi_lbn == LFS_UNUSED_LBN)
61955930Sbostic return(1);
62056623Smargo else if (ba->bi_lbn < 0 && bb->bi_lbn >= 0)
62155930Sbostic return(1);
62256623Smargo else if (bb->bi_lbn < 0 && ba->bi_lbn >= 0)
62356623Smargo return(-1);
62455930Sbostic else
62555930Sbostic return (diff);
62655930Sbostic }
62755856Sbostic if (diff = (int)(ba->bi_segcreate - bb->bi_segcreate))
62855856Sbostic return (diff);
62955856Sbostic diff = (int)(ba->bi_daddr - bb->bi_daddr);
63055856Sbostic return (diff);
63155856Sbostic }
63255491Sbostic
63355856Sbostic int
bi_toss(dummy,a,b)63455856Sbostic bi_toss(dummy, a, b)
63555856Sbostic const void *dummy;
63655856Sbostic const void *a;
63755856Sbostic const void *b;
63855491Sbostic {
63955856Sbostic const BLOCK_INFO *ba, *bb;
64055491Sbostic
64155856Sbostic ba = a;
64255856Sbostic bb = b;
64355856Sbostic
64455856Sbostic return(ba->bi_inode == bb->bi_inode && ba->bi_lbn == bb->bi_lbn);
64555491Sbostic }
64655491Sbostic
64755491Sbostic void
toss(p,nump,size,dotoss,client)64855856Sbostic toss(p, nump, size, dotoss, client)
64955856Sbostic void *p;
65055856Sbostic int *nump;
65155856Sbostic size_t size;
65255856Sbostic int (*dotoss) __P((const void *, const void *, const void *));
65355856Sbostic void *client;
65455491Sbostic {
65555856Sbostic int i;
65655856Sbostic void *p1;
65755491Sbostic
65855856Sbostic if (*nump == 0)
65955856Sbostic return;
66055491Sbostic
66155856Sbostic for (i = *nump; --i > 0;) {
66255856Sbostic p1 = p + size;
66355856Sbostic if (dotoss(client, p, p1)) {
66460095Sbostic memmove(p, p1, i * size);
66555856Sbostic --(*nump);
66655856Sbostic } else
66755856Sbostic p += size;
66855491Sbostic }
66955491Sbostic }
670