155860Sbostic /*- 255860Sbostic * Copyright (c) 1992 The Regents of the University of California. 355860Sbostic * All rights reserved. 455860Sbostic * 555860Sbostic * %sccs.include.redist.c% 655860Sbostic */ 755860Sbostic 855860Sbostic #ifndef lint 9*56623Smargo static char sccsid[] = "@(#)library.c 5.6 (Berkeley) 10/24/92"; 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> 1655491Sbostic 1755491Sbostic #include <ufs/ufs/dinode.h> 1855491Sbostic #include <ufs/lfs/lfs.h> 1955491Sbostic 2055491Sbostic #include <fcntl.h> 2155491Sbostic #include <stdio.h> 2255491Sbostic #include <unistd.h> 2355856Sbostic #include <stdlib.h> 2455856Sbostic #include <string.h> 2555491Sbostic #include "clean.h" 2655491Sbostic 2755856Sbostic void add_blocks __P((FS_INFO *, BLOCK_INFO *, int *, SEGSUM *, caddr_t, 2855856Sbostic daddr_t, daddr_t)); 2955930Sbostic void add_inodes __P((FS_INFO *, BLOCK_INFO *, int *, SEGSUM *, caddr_t, 3055856Sbostic daddr_t)); 3155856Sbostic int bi_compare __P((const void *, const void *)); 3255856Sbostic int bi_toss __P((const void *, const void *, const void *)); 3355856Sbostic void get_ifile __P((FS_INFO *)); 3455856Sbostic int get_superblock __P((FS_INFO *, struct lfs *)); 3555856Sbostic int pseg_valid __P((FS_INFO *, SEGSUM *)); 3655856Sbostic 3755491Sbostic /* 3855856Sbostic * This function will get information on all mounted file systems 3955491Sbostic * of a given type. 4055491Sbostic */ 4155491Sbostic int 4255491Sbostic fs_getmntinfo(buf, type) 4355491Sbostic struct statfs **buf; 4455491Sbostic int type; 4555491Sbostic { 4655856Sbostic struct statfs *tstatfsp; 4755856Sbostic struct statfs *sbp; 4855856Sbostic int count, i, tcount; 4955491Sbostic 5055863Sbostic tcount = getmntinfo(&tstatfsp, MNT_NOWAIT); 5155491Sbostic 5255491Sbostic if (tcount < 0) { 5355856Sbostic err(0, "getmntinfo failed"); 5455856Sbostic return (-1); 5555491Sbostic } 5655491Sbostic 5755856Sbostic for (count = 0, i = 0; i < tcount ; ++i) 5855856Sbostic if (tstatfsp[i].f_type == type) 5955856Sbostic ++count; 6055491Sbostic 6155856Sbostic if (count) { 6255856Sbostic if (!(*buf = (struct statfs *) 6355856Sbostic malloc(count * sizeof(struct statfs)))) 6455856Sbostic err(1, "fs_getmntinfo: out of space"); 6555856Sbostic for (i = 0, sbp = *buf; i < tcount ; ++i) { 6655856Sbostic if (tstatfsp[i].f_type == type) { 6755856Sbostic *sbp = tstatfsp[i]; 6855856Sbostic ++sbp; 6955491Sbostic } 7055491Sbostic } 7155491Sbostic } 7255856Sbostic return (count); 7355491Sbostic } 7455491Sbostic 7555491Sbostic /* 7655856Sbostic * Get all the information available on an LFS file system. 7755856Sbostic * Returns an array of FS_INFO structures, NULL on error. 7855491Sbostic */ 7955856Sbostic FS_INFO * 8055856Sbostic get_fs_info (lstatfsp, count) 8155856Sbostic struct statfs *lstatfsp; /* IN: array of statfs structs */ 8255856Sbostic int count; /* IN: number of file systems */ 8355491Sbostic { 8455856Sbostic FS_INFO *fp, *fsp; 8555491Sbostic int i; 8655491Sbostic 8755856Sbostic fsp = (FS_INFO *)malloc(count * sizeof(FS_INFO)); 8855491Sbostic 8955856Sbostic for (fp = fsp, i = 0; i < count; ++i, ++fp) { 9055856Sbostic fp->fi_statfsp = lstatfsp++; 9155856Sbostic if (get_superblock (fp, &fp->fi_lfs)) 9255856Sbostic err(1, "get_fs_info: get_superblock failed"); 9355856Sbostic fp->fi_daddr_shift = 9455856Sbostic fp->fi_lfs.lfs_bshift - fp->fi_lfs.lfs_fsbtodb; 9555856Sbostic get_ifile (fp); 9655491Sbostic } 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 10655856Sbostic reread_fs_info(fsp, count) 10755856Sbostic FS_INFO *fsp; /* IN: array of fs_infos to free */ 10855856Sbostic int count; /* IN: number of file systems */ 10955491Sbostic { 11055856Sbostic int i; 11155491Sbostic 11255856Sbostic for (i = 0; i < count; ++i, ++fsp) { 11355856Sbostic if (statfs(fsp->fi_statfsp->f_mntonname, fsp->fi_statfsp)) 11455856Sbostic err(0, "reread_fs_info: statfs failed"); 11555856Sbostic #ifdef MMAP_WORKS 11655856Sbostic if (munmap(fsp->fi_cip, fsp->fi_ifile_length) < 0) 11755856Sbostic err(0, "reread_fs_info: munmap failed"); 11855491Sbostic #else 11955856Sbostic free (fsp->fi_cip); 12055491Sbostic #endif /* MMAP_WORKS */ 12155856Sbostic get_ifile (fsp); 12255491Sbostic } 12355491Sbostic } 12455491Sbostic 12555491Sbostic /* 12655856Sbostic * Gets the superblock from disk (possibly in face of errors) 12755491Sbostic */ 12855491Sbostic int 12955491Sbostic get_superblock (fsp, sbp) 13055856Sbostic FS_INFO *fsp; /* local file system info structure */ 13155856Sbostic struct lfs *sbp; 13255491Sbostic { 13355856Sbostic char mntfromname[MNAMELEN+1]; 13455856Sbostic int fid; 13555491Sbostic 13655491Sbostic strcpy(mntfromname, "/dev/r"); 13755856Sbostic strcat(mntfromname, fsp->fi_statfsp->f_mntfromname+5); 13855491Sbostic 13955491Sbostic if ((fid = open(mntfromname, O_RDONLY, (mode_t)0)) < 0) { 14055856Sbostic err(0, "get_superblock: bad open"); 14155856Sbostic return (-1); 14255491Sbostic } 14355491Sbostic 14455856Sbostic get(fid, LFS_LABELPAD, sbp, sizeof(struct lfs)); 14555491Sbostic close (fid); 14655491Sbostic 14755856Sbostic return (0); 14855491Sbostic } 14955491Sbostic 15055491Sbostic /* 15155856Sbostic * This function will map the ifile into memory. It causes a 15255856Sbostic * fatal error on failure. 15355491Sbostic */ 15455856Sbostic void 15555491Sbostic get_ifile (fsp) 15655491Sbostic FS_INFO *fsp; 15755491Sbostic { 15855856Sbostic struct stat file_stat; 15955856Sbostic caddr_t ifp; 16055856Sbostic char *ifile_name; 16155856Sbostic int count, fid; 16255491Sbostic 16355856Sbostic ifp = NULL; 16455856Sbostic ifile_name = malloc(strlen(fsp->fi_statfsp->f_mntonname) + 16555856Sbostic strlen(IFILE_NAME)+2); 16655856Sbostic strcat(strcat(strcpy(ifile_name, fsp->fi_statfsp->f_mntonname), "/"), 16755856Sbostic IFILE_NAME); 16855491Sbostic 16955856Sbostic if ((fid = open(ifile_name, O_RDWR, (mode_t)0)) < 0) 17055856Sbostic err(1, "get_ifile: bad open"); 17155491Sbostic 17255856Sbostic if (fstat (fid, &file_stat)) 17355856Sbostic err(1, "get_ifile: fstat failed"); 17455491Sbostic 17555856Sbostic fsp->fi_ifile_length = file_stat.st_size; 17655856Sbostic 17755491Sbostic /* get the ifile */ 17855491Sbostic #ifndef MMAP_WORKS 17955856Sbostic if (!(ifp = malloc ((size_t)fsp->fi_ifile_length))) 18055856Sbostic err (1, "get_ifile: malloc failed"); 18155856Sbostic redo_read: 18255856Sbostic count = read (fid, ifp, (size_t) fsp->fi_ifile_length); 18355491Sbostic 18455856Sbostic if (count < 0) 18555856Sbostic err(1, "get_ifile: bad ifile read"); 18655856Sbostic else if (count < (int)fsp->fi_ifile_length) { 18755856Sbostic err(0, "get_ifile"); 18855856Sbostic if (lseek(fid, 0, SEEK_SET) < 0) 18955856Sbostic err(1, "get_ifile: bad ifile lseek"); 19055856Sbostic goto redo_read; 19155491Sbostic } 19255491Sbostic #else /* MMAP_WORKS */ 19355856Sbostic ifp = mmap ((caddr_t)0, (size_t) fsp->fi_ifile_length, PROT_READ|PROT_WRITE, 19455491Sbostic MAP_FILE|MAP_SHARED, fid, (off_t)0); 19555856Sbostic if (ifp < 0) 19655856Sbostic err(1, "get_ifile: mmap failed"); 19755491Sbostic #endif /* MMAP_WORKS */ 19855491Sbostic 19955491Sbostic close (fid); 20055491Sbostic 20155856Sbostic fsp->fi_cip = (CLEANERINFO *)ifp; 20255856Sbostic fsp->fi_segusep = (SEGUSE *)(ifp + CLEANSIZE(fsp)); 20355856Sbostic fsp->fi_ifilep = (IFILE *)((caddr_t)fsp->fi_segusep + SEGTABSIZE(fsp)); 20455856Sbostic 20555856Sbostic /* 20655856Sbostic * The number of ifile entries is equal to the number of blocks 20755856Sbostic * blocks in the ifile minus the ones allocated to cleaner info 20855856Sbostic * and segment usage table multiplied by the number of ifile 20955856Sbostic * entries per page. 21055856Sbostic */ 21155856Sbostic fsp->fi_ifile_count = (fsp->fi_ifile_length >> fsp->fi_lfs.lfs_bshift - 21255856Sbostic fsp->fi_lfs.lfs_cleansz - fsp->fi_lfs.lfs_segtabsz) * 21355856Sbostic fsp->fi_lfs.lfs_ifpb; 21455856Sbostic 21555491Sbostic free (ifile_name); 21655491Sbostic } 21755491Sbostic 21855491Sbostic /* 21955856Sbostic * This function will scan a segment and return a list of 22055491Sbostic * <inode, blocknum> pairs which indicate which blocks were 22155856Sbostic * contained as live data within the segment when the segment 22255856Sbostic * summary was read (it may have "died" since then). Any given 22355856Sbostic * pair will be listed at most once. 22455491Sbostic */ 22555491Sbostic int 22655930Sbostic lfs_segmapv(fsp, seg, seg_buf, blocks, bcount) 22755856Sbostic FS_INFO *fsp; /* pointer to local file system information */ 22855856Sbostic int seg; /* the segment number */ 22955856Sbostic caddr_t seg_buf; /* the buffer containing the segment's data */ 23055856Sbostic BLOCK_INFO **blocks; /* OUT: array of block_info for live blocks */ 23155856Sbostic int *bcount; /* OUT: number of active blocks in segment */ 23255491Sbostic { 23355856Sbostic BLOCK_INFO *bip; 23455856Sbostic SEGSUM *sp; 23555856Sbostic SEGUSE *sup; 236*56623Smargo FINFO *fip; 23755856Sbostic struct lfs *lfsp; 23855856Sbostic caddr_t s, segend; 23955856Sbostic daddr_t pseg_addr, seg_addr; 240*56623Smargo int i, nelem, nblocks, sumsize; 24155856Sbostic time_t timestamp; 24255491Sbostic 24355856Sbostic lfsp = &fsp->fi_lfs; 24455930Sbostic nelem = 2 * lfsp->lfs_ssize; 24555930Sbostic if (!(bip = malloc(nelem * sizeof(BLOCK_INFO)))) 24655856Sbostic goto err0; 24755491Sbostic 24855856Sbostic sup = SEGUSE_ENTRY(lfsp, fsp->fi_segusep, seg); 24955856Sbostic s = seg_buf + (sup->su_flags & SEGUSE_SUPERBLOCK ? LFS_SBPAD : 0); 25055856Sbostic seg_addr = sntoda(lfsp, seg); 25155856Sbostic pseg_addr = seg_addr + (sup->su_flags & SEGUSE_SUPERBLOCK ? btodb(LFS_SBPAD) : 0); 25255856Sbostic #ifdef VERBOSE 25355856Sbostic printf("\tsegment buffer at: 0x%x\tseg_addr 0x%x\n", s, seg_addr); 25455856Sbostic #endif /* VERBOSE */ 25555491Sbostic 25655856Sbostic *bcount = 0; 25755856Sbostic for (segend = seg_buf + seg_size(lfsp), timestamp = 0; s < segend; ) { 25855856Sbostic sp = (SEGSUM *)s; 259*56623Smargo 26055491Sbostic #ifdef VERBOSE 26155856Sbostic printf("\tpartial at: 0x%x\n", pseg_addr); 26255856Sbostic print_SEGSUM(lfsp, sp); 26355491Sbostic fflush(stdout); 26455491Sbostic #endif /* VERBOSE */ 26555491Sbostic 26655856Sbostic nblocks = pseg_valid(fsp, sp); 26755856Sbostic if (nblocks <= 0) 26855856Sbostic break; 26955491Sbostic 27055856Sbostic /* Check if we have hit old data */ 27155856Sbostic if (timestamp > ((SEGSUM*)s)->ss_create) 27255856Sbostic break; 27355491Sbostic timestamp = ((SEGSUM*)s)->ss_create; 27455491Sbostic 275*56623Smargo #ifdef DIAGNOSTIC 276*56623Smargo /* Verfiy size of summary block */ 277*56623Smargo sumsize = sizeof(SEGSUM) + 278*56623Smargo (sp->ss_ninos + INOPB(lfsp) - 1) / INOPB(lfsp); 279*56623Smargo for (fip = (FINFO *)(sp + 1); i < sp->ss_nfinfo; ++i) { 280*56623Smargo sumsize += sizeof(FINFO) + 281*56623Smargo (fip->fi_nblocks - 1) * sizeof(daddr_t); 282*56623Smargo fip = (FINFO *)(&fip->fi_blocks[fip->fi_nblocks]); 283*56623Smargo } 284*56623Smargo if (sumsize > LFS_SUMMARY_SIZE) { 285*56623Smargo fprintf(stderr, 286*56623Smargo "Segment %d summary block too big: %d\n", 287*56623Smargo seg, sumsize); 288*56623Smargo exit(1); 289*56623Smargo } 290*56623Smargo #endif 291*56623Smargo 29255930Sbostic if (*bcount + nblocks + sp->ss_ninos > nelem) { 29355930Sbostic nelem = *bcount + nblocks + sp->ss_ninos; 29455930Sbostic bip = realloc (bip, nelem * sizeof(BLOCK_INFO)); 29555930Sbostic if (!bip) 29655930Sbostic goto err0; 29755856Sbostic } 29855856Sbostic add_blocks(fsp, bip, bcount, sp, seg_buf, seg_addr, pseg_addr); 29955930Sbostic add_inodes(fsp, bip, bcount, sp, seg_buf, seg_addr); 30055856Sbostic pseg_addr += fsbtodb(lfsp, nblocks) + 30155856Sbostic bytetoda(fsp, LFS_SUMMARY_SIZE); 30255856Sbostic s += (nblocks << lfsp->lfs_bshift) + LFS_SUMMARY_SIZE; 30355856Sbostic } 30455856Sbostic qsort(bip, *bcount, sizeof(BLOCK_INFO), bi_compare); 30555856Sbostic toss(bip, bcount, sizeof(BLOCK_INFO), bi_toss, NULL); 30655856Sbostic #ifdef VERBOSE 30755856Sbostic { 30855856Sbostic BLOCK_INFO *_bip; 30955856Sbostic int i; 31055491Sbostic 31155856Sbostic printf("BLOCK INFOS\n"); 31255856Sbostic for (_bip = bip, i=0; i < *bcount; ++_bip, ++i) 31355856Sbostic PRINT_BINFO(_bip); 31455491Sbostic } 31555856Sbostic #endif 31655856Sbostic *blocks = bip; 31755856Sbostic return (0); 31855856Sbostic 31955856Sbostic err0: *bcount = 0; 32055856Sbostic return (-1); 32155491Sbostic 32255491Sbostic } 32355491Sbostic 32455491Sbostic /* 32555856Sbostic * This will parse a partial segment and fill in BLOCK_INFO structures 32655856Sbostic * for each block described in the segment summary. It will not include 32755856Sbostic * blocks or inodes from files with new version numbers. 32855491Sbostic */ 32955491Sbostic void 33055856Sbostic add_blocks (fsp, bip, countp, sp, seg_buf, segaddr, psegaddr) 33155491Sbostic FS_INFO *fsp; /* pointer to super block */ 33255856Sbostic BLOCK_INFO *bip; /* Block info array */ 33355856Sbostic int *countp; /* IN/OUT: number of blocks in array */ 33455856Sbostic SEGSUM *sp; /* segment summmary pointer */ 33555856Sbostic caddr_t seg_buf; /* buffer containing segment */ 33655856Sbostic daddr_t segaddr; /* address of this segment */ 33755856Sbostic daddr_t psegaddr; /* address of this partial segment */ 33855491Sbostic { 33955856Sbostic IFILE *ifp; 34055856Sbostic FINFO *fip; 34155856Sbostic caddr_t bp; 34255930Sbostic daddr_t *dp, *iaddrp; 34355856Sbostic int db_per_block, i, j; 34455856Sbostic u_long page_size; 34555491Sbostic 34655491Sbostic #ifdef VERBOSE 34755856Sbostic printf("FILE INFOS\n"); 34855491Sbostic #endif 34955856Sbostic db_per_block = fsbtodb(&fsp->fi_lfs, 1); 35055856Sbostic page_size = fsp->fi_lfs.lfs_bsize; 35155856Sbostic bp = seg_buf + datobyte(fsp, psegaddr - segaddr) + LFS_SUMMARY_SIZE; 35255856Sbostic bip += *countp; 35355856Sbostic psegaddr += bytetoda(fsp, LFS_SUMMARY_SIZE); 35455856Sbostic iaddrp = (daddr_t *)((caddr_t)sp + LFS_SUMMARY_SIZE); 35555856Sbostic --iaddrp; 35655856Sbostic for (fip = (FINFO *)(sp + 1), i = 0; i < sp->ss_nfinfo; 35755856Sbostic ++i, fip = (FINFO *)(&fip->fi_blocks[fip->fi_nblocks])) { 35855491Sbostic 35955856Sbostic ifp = IFILE_ENTRY(&fsp->fi_lfs, fsp->fi_ifilep, fip->fi_ino); 36055856Sbostic PRINT_FINFO(fip, ifp); 36155856Sbostic if (ifp->if_version > fip->fi_version) 36255491Sbostic continue; 36355856Sbostic dp = &(fip->fi_blocks[0]); 36455856Sbostic for (j = 0; j < fip->fi_nblocks; j++, dp++) { 36555856Sbostic while (psegaddr == *iaddrp) { 36655856Sbostic psegaddr += db_per_block; 36755856Sbostic bp += page_size; 36855856Sbostic --iaddrp; 36955491Sbostic } 37055856Sbostic bip->bi_inode = fip->fi_ino; 37155856Sbostic bip->bi_lbn = *dp; 37255856Sbostic bip->bi_daddr = psegaddr; 37355856Sbostic bip->bi_segcreate = (time_t)(sp->ss_create); 37455856Sbostic bip->bi_bp = bp; 37556193Smargo bip->bi_version = ifp->if_version; 37655856Sbostic psegaddr += db_per_block; 37755856Sbostic bp += page_size; 37855856Sbostic ++bip; 37955856Sbostic ++(*countp); 38055491Sbostic } 38155491Sbostic } 38255491Sbostic } 38355491Sbostic 38455856Sbostic /* 38555856Sbostic * For a particular segment summary, reads the inode blocks and adds 38655856Sbostic * INODE_INFO structures to the array. Returns the number of inodes 38755856Sbostic * actually added. 38855856Sbostic */ 38955491Sbostic void 39055930Sbostic add_inodes (fsp, bip, countp, sp, seg_buf, seg_addr) 39155491Sbostic FS_INFO *fsp; /* pointer to super block */ 39255930Sbostic BLOCK_INFO *bip; /* block info array */ 39355856Sbostic int *countp; /* pointer to current number of inodes */ 39455856Sbostic SEGSUM *sp; /* segsum pointer */ 39555491Sbostic caddr_t seg_buf; /* the buffer containing the segment's data */ 39655856Sbostic daddr_t seg_addr; /* disk address of seg_buf */ 39755491Sbostic { 39855856Sbostic struct dinode *di; 39955856Sbostic struct lfs *lfsp; 40055856Sbostic IFILE *ifp; 40155930Sbostic BLOCK_INFO *bp; 40255856Sbostic daddr_t *daddrp; 40355856Sbostic ino_t inum; 40455856Sbostic int i; 40555491Sbostic 40655856Sbostic if (sp->ss_ninos <= 0) 40755856Sbostic return; 40855491Sbostic 40955930Sbostic bp = bip + *countp; 41055856Sbostic lfsp = &fsp->fi_lfs; 41155491Sbostic #ifdef VERBOSE 41255930Sbostic (void) printf("INODES:\n"); 41355491Sbostic #endif 41455856Sbostic daddrp = (daddr_t *)((caddr_t)sp + LFS_SUMMARY_SIZE); 41555856Sbostic for (i = 0; i < sp->ss_ninos; ++i) { 41655491Sbostic if (i % INOPB(lfsp) == 0) { 41755856Sbostic --daddrp; 41855856Sbostic di = (struct dinode *)(seg_buf + 41955856Sbostic ((*daddrp - seg_addr) << fsp->fi_daddr_shift)); 42055491Sbostic } else 42155491Sbostic ++di; 42255491Sbostic 42355491Sbostic inum = di->di_inum; 42455930Sbostic bp->bi_lbn = LFS_UNUSED_LBN; 42555930Sbostic bp->bi_inode = inum; 42655930Sbostic bp->bi_daddr = *daddrp; 42755930Sbostic bp->bi_bp = di; 42855930Sbostic bp->bi_segcreate = sp->ss_create; 42955491Sbostic 43056036Sbostic if (inum == LFS_IFILE_INUM) { 43156193Smargo bp->bi_version = 1; /* Ifile version should be 1 */ 43255930Sbostic bp++; 43355856Sbostic ++(*countp); 43456036Sbostic PRINT_INODE(1, bp); 43556036Sbostic } else { 43656036Sbostic ifp = IFILE_ENTRY(lfsp, fsp->fi_ifilep, inum); 43756036Sbostic PRINT_INODE(ifp->if_daddr == *daddrp, bp); 43856193Smargo bp->bi_version = ifp->if_version; 43956036Sbostic if (ifp->if_daddr == *daddrp) { 44056036Sbostic bp++; 44156036Sbostic ++(*countp); 44256036Sbostic } 44356036Sbostic } 44455491Sbostic } 44555491Sbostic } 44655491Sbostic 44755491Sbostic /* 44855856Sbostic * Checks the summary checksum and the data checksum to determine if the 44955856Sbostic * segment is valid or not. Returns the size of the partial segment if it 45055856Sbostic * is valid, * and 0 otherwise. Use dump_summary to figure out size of the 45155856Sbostic * the partial as well as whether or not the checksum is valid. 45255491Sbostic */ 45355491Sbostic int 45455491Sbostic pseg_valid (fsp, ssp) 45555491Sbostic FS_INFO *fsp; /* pointer to file system info */ 45655856Sbostic SEGSUM *ssp; /* pointer to segment summary block */ 45755491Sbostic { 45855491Sbostic caddr_t p; 45955856Sbostic int i, nblocks; 46055856Sbostic u_long *datap; 461*56623Smargo SEGUSE *sup; 46255491Sbostic 46355856Sbostic if ((nblocks = dump_summary(&fsp->fi_lfs, ssp, 0, NULL)) <= 0) 46455856Sbostic return(0); 46555491Sbostic 46655856Sbostic /* check data/inode block(s) checksum too */ 46755856Sbostic datap = (u_long *)malloc(nblocks * sizeof(u_long)); 46855491Sbostic p = (caddr_t)ssp + LFS_SUMMARY_SIZE; 46955856Sbostic for (i = 0; i < nblocks; ++i) { 47055491Sbostic datap[i] = *((u_long *)p); 47155856Sbostic p += fsp->fi_lfs.lfs_bsize; 47255491Sbostic } 47355856Sbostic if (cksum ((void *)datap, nblocks * sizeof(u_long)) != ssp->ss_datasum) 47455856Sbostic return (0); 47555491Sbostic 47655856Sbostic return (nblocks); 47755491Sbostic } 47855491Sbostic 47955491Sbostic 48055491Sbostic /* #define MMAP_SEGMENT */ 48155491Sbostic /* 48255491Sbostic * read a segment into a memory buffer 48355491Sbostic */ 48455491Sbostic int 48555856Sbostic mmap_segment (fsp, segment, segbuf) 48655856Sbostic FS_INFO *fsp; /* file system information */ 48755856Sbostic int segment; /* segment number */ 48855856Sbostic caddr_t *segbuf; /* pointer to buffer area */ 48955491Sbostic { 49055856Sbostic struct lfs *lfsp; 49155856Sbostic int fid; /* fildes for file system device */ 49255856Sbostic daddr_t seg_daddr; /* base disk address of segment */ 49355856Sbostic off_t seg_byte; 49455856Sbostic size_t ssize; 49555856Sbostic char mntfromname[MNAMELEN+2]; 49655491Sbostic 49755856Sbostic lfsp = &fsp->fi_lfs; 49855856Sbostic 49955491Sbostic /* get the disk address of the beginning of the segment */ 50055491Sbostic seg_daddr = sntoda(lfsp, segment); 50155856Sbostic seg_byte = datobyte(fsp, seg_daddr); 50255856Sbostic ssize = seg_size(lfsp); 50355491Sbostic 50455491Sbostic strcpy(mntfromname, "/dev/r"); 50555856Sbostic strcat(mntfromname, fsp->fi_statfsp->f_mntfromname+5); 50655491Sbostic 50755491Sbostic if ((fid = open(mntfromname, O_RDONLY, (mode_t)0)) < 0) { 50855856Sbostic err(0, "mmap_segment: bad open"); 50955856Sbostic return (-1); 51055491Sbostic } 51155491Sbostic 51255491Sbostic #ifdef MMAP_SEGMENT 51355856Sbostic *segbuf = mmap ((caddr_t)0, seg_size(lfsp), PROT_READ, 51455856Sbostic MAP_FILE, fid, seg_byte); 51555856Sbostic if (*(long *)segbuf < 0) { 51655856Sbostic err(0, "mmap_segment: mmap failed"); 51755856Sbostic return (NULL); 51855491Sbostic } 51955491Sbostic #else /* MMAP_SEGMENT */ 52055856Sbostic #ifdef VERBOSE 52155856Sbostic printf("mmap_segment\tseg_daddr: %lu\tseg_size: %lu\tseg_offset: %qu\n", 52255856Sbostic seg_daddr, ssize, seg_byte); 52355856Sbostic #endif 52455491Sbostic /* malloc the space for the buffer */ 52555856Sbostic *segbuf = malloc(ssize); 52655856Sbostic if (!*segbuf) { 52755856Sbostic err(0, "mmap_segment: malloc failed"); 52855856Sbostic return(NULL); 52955856Sbostic } 53055491Sbostic 53155491Sbostic /* read the segment data into the buffer */ 53255856Sbostic if (lseek (fid, seg_byte, SEEK_SET) != seg_byte) { 53355856Sbostic err (0, "mmap_segment: bad lseek"); 53455856Sbostic free(*segbuf); 53555856Sbostic return (-1); 53655491Sbostic } 53755491Sbostic 53855856Sbostic if (read (fid, *segbuf, ssize) != ssize) { 53955856Sbostic err (0, "mmap_segment: bad read"); 54055856Sbostic free(*segbuf); 54155856Sbostic return (-1); 54255491Sbostic } 54355491Sbostic #endif /* MMAP_SEGMENT */ 54455491Sbostic close (fid); 54555491Sbostic 54655856Sbostic return (0); 54755491Sbostic } 54855491Sbostic 54955491Sbostic void 55055491Sbostic munmap_segment (fsp, seg_buf) 55155856Sbostic FS_INFO *fsp; /* file system information */ 55255856Sbostic caddr_t seg_buf; /* pointer to buffer area */ 55355491Sbostic { 55455491Sbostic #ifdef MMAP_SEGMENT 55555856Sbostic munmap (seg_buf, seg_size(&fsp->fi_lfs)); 55655491Sbostic #else /* MMAP_SEGMENT */ 55755491Sbostic free (seg_buf); 55855491Sbostic #endif /* MMAP_SEGMENT */ 55955491Sbostic } 56055491Sbostic 56155491Sbostic 56255491Sbostic /* 56355491Sbostic * USEFUL DEBUGGING TOOLS: 56455491Sbostic */ 56555491Sbostic void 56655856Sbostic print_SEGSUM (lfsp, p) 56755856Sbostic struct lfs *lfsp; 56855856Sbostic SEGSUM *p; 56955491Sbostic { 57055856Sbostic if (p) 57155856Sbostic (void) dump_summary(lfsp, p, DUMP_ALL, NULL); 57255491Sbostic else printf("0x0"); 57355491Sbostic fflush(stdout); 57455491Sbostic } 57555491Sbostic 57655856Sbostic int 57755856Sbostic bi_compare(a, b) 57855856Sbostic const void *a; 57955856Sbostic const void *b; 58055491Sbostic { 58155856Sbostic const BLOCK_INFO *ba, *bb; 58255856Sbostic int diff; 58355491Sbostic 58455856Sbostic ba = a; 58555856Sbostic bb = b; 58655491Sbostic 58755856Sbostic if (diff = (int)(ba->bi_inode - bb->bi_inode)) 58855856Sbostic return (diff); 58955930Sbostic if (diff = (int)(ba->bi_lbn - bb->bi_lbn)) { 59055930Sbostic if (ba->bi_lbn == LFS_UNUSED_LBN) 59155930Sbostic return(-1); 59255930Sbostic else if (bb->bi_lbn == LFS_UNUSED_LBN) 59355930Sbostic return(1); 594*56623Smargo else if (ba->bi_lbn < 0 && bb->bi_lbn >= 0) 59555930Sbostic return(1); 596*56623Smargo else if (bb->bi_lbn < 0 && ba->bi_lbn >= 0) 597*56623Smargo return(-1); 59855930Sbostic else 59955930Sbostic return (diff); 60055930Sbostic } 60155856Sbostic if (diff = (int)(ba->bi_segcreate - bb->bi_segcreate)) 60255856Sbostic return (diff); 60355856Sbostic diff = (int)(ba->bi_daddr - bb->bi_daddr); 60455856Sbostic return (diff); 60555856Sbostic } 60655491Sbostic 60755856Sbostic int 60855856Sbostic bi_toss(dummy, a, b) 60955856Sbostic const void *dummy; 61055856Sbostic const void *a; 61155856Sbostic const void *b; 61255491Sbostic { 61355856Sbostic const BLOCK_INFO *ba, *bb; 61455491Sbostic 61555856Sbostic ba = a; 61655856Sbostic bb = b; 61755856Sbostic 61855856Sbostic return(ba->bi_inode == bb->bi_inode && ba->bi_lbn == bb->bi_lbn); 61955491Sbostic } 62055491Sbostic 62155491Sbostic void 62255856Sbostic toss(p, nump, size, dotoss, client) 62355856Sbostic void *p; 62455856Sbostic int *nump; 62555856Sbostic size_t size; 62655856Sbostic int (*dotoss) __P((const void *, const void *, const void *)); 62755856Sbostic void *client; 62855491Sbostic { 62955856Sbostic int i; 63055856Sbostic void *p1; 63155491Sbostic 63255856Sbostic if (*nump == 0) 63355856Sbostic return; 63455491Sbostic 63555856Sbostic for (i = *nump; --i > 0;) { 63655856Sbostic p1 = p + size; 63755856Sbostic if (dotoss(client, p, p1)) { 63855856Sbostic bcopy(p1, p, i * size); 63955856Sbostic --(*nump); 64055856Sbostic } else 64155856Sbostic p += size; 64255491Sbostic } 64355491Sbostic } 644