void rdfs(int u) { visited[u] = timestamp; if (match_x[u] != -1) { for (int v : rgraph[match_x[u]]) { if (visited[v] != timestamp) { parent[v] = u; via[v] = match_x[u]; rdfs(v); } } } }
void rdfs(int v, int k) { used[v] = true; cmp[v] = k; for(size_t index=0; index<rG[v].size(); index++) { if(!used[rG[v][index]]) { rdfs(rG[v][index]); } } }
int solve() { memset(used,0,sizeof(used)); vs.clear(); for(int v=1;v<=N;v++) if(!used[v]) dfs(v); memset(used,0,sizeof(used)); int k=0; for(int i=vs.size()-1;i>=0;i--) if(!used[vs[i]]) rdfs(vs[i],k++); return k; }
int scc() { memset(used,0,sizeof(used)); vs.clear(); for(int v = 0 ; v < V ; v++) { if(!used[v]) dfs(v); } memset(used,0,sizeof(used)); int k = 0; for(int i = vs.size() - 1 ; i >= 0 ; i--) { if(!used[vs[i]]) rdfs(vs[i],k++); } return k; }
void rdfs(int s, int c, int t) { int i; vis[s] = c; if (asg[s]!=0 && asg[s]!=t) { nosat = 1; } asg[s] = t; asg[s^1] = -t; for (i=0;i<2*n;i++) if (A[i][s] && !vis[i]) rdfs(i, c, t); }
/* * allocate a block or frag */ daddr64_t alloc(int size, int mode) { int i, frag; daddr64_t d, blkno; rdfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, (char *)&acg); if (acg.cg_magic != CG_MAGIC) { warnx("cg 0: bad magic number"); return (0); } if (acg.cg_cs.cs_nbfree == 0) { warnx("first cylinder group ran out of space"); return (0); } for (d = 0; d < acg.cg_ndblk; d += sblock.fs_frag) if (isblock(&sblock, cg_blksfree(&acg), d / sblock.fs_frag)) goto goth; warnx("internal error: can't find block in cyl 0"); return (0); goth: blkno = fragstoblks(&sblock, d); clrblock(&sblock, cg_blksfree(&acg), blkno); acg.cg_cs.cs_nbfree--; sblock.fs_cstotal.cs_nbfree--; fscs[0].cs_nbfree--; if (mode & IFDIR) { acg.cg_cs.cs_ndir++; sblock.fs_cstotal.cs_ndir++; fscs[0].cs_ndir++; } if (Oflag <= 1) { cg_blktot(&acg)[cbtocylno(&sblock, d)]--; cg_blks(&sblock, &acg, cbtocylno(&sblock, d)) [cbtorpos(&sblock, d)]--; } if (size != sblock.fs_bsize) { frag = howmany(size, sblock.fs_fsize); fscs[0].cs_nffree += sblock.fs_frag - frag; sblock.fs_cstotal.cs_nffree += sblock.fs_frag - frag; acg.cg_cs.cs_nffree += sblock.fs_frag - frag; acg.cg_frsum[sblock.fs_frag - frag]++; for (i = frag; i < sblock.fs_frag; i++) setbit(cg_blksfree(&acg), d + i); } wtfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, (char *)&acg); return (d); }
/* * Allocate an inode on the disk */ void iput(union dinode *ip, ino_t ino) { daddr64_t d; if (Oflag <= 1) ip->dp1.di_gen = (u_int32_t)arc4random(); else ip->dp2.di_gen = (u_int32_t)arc4random(); rdfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, (char *)&acg); if (acg.cg_magic != CG_MAGIC) errx(41, "cg 0: bad magic number"); acg.cg_cs.cs_nifree--; setbit(cg_inosused(&acg), ino); wtfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, (char *)&acg); sblock.fs_cstotal.cs_nifree--; fscs[0].cs_nifree--; if (ino >= sblock.fs_ipg * sblock.fs_ncg) errx(32, "fsinit: inode value %d out of range", ino); d = fsbtodb(&sblock, ino_to_fsba(&sblock, ino)); rdfs(d, sblock.fs_bsize, iobuf); if (Oflag <= 1) ((struct ufs1_dinode *)iobuf)[ino_to_fsbo(&sblock, ino)] = ip->dp1; else ((struct ufs2_dinode *)iobuf)[ino_to_fsbo(&sblock, ino)] = ip->dp2; wtfs(d, sblock.fs_bsize, iobuf); }
int solve2sat() { int i, cmpcol; nosat = 0; /* Forward */ dfsclear(); push = 0; for (i=0;i<2*n;i++) if (!vis[i]) dfs(i); /* Backward */ dfsclear(); cmpcol = 1; while (push && !nosat) { if (!vis[stack[push-1]]) { rdfs(stack[push-1], cmpcol, asg[stack[push-1]]!=0?asg[stack[push-1]]:-1); cmpcol++; } push--; } return !nosat; }
int scc() { memset(used, 0, sizeof(used)); vs.clear(); for(size_t v=0; v<V; v++) { if(!used[v]) { dfs[v]; } } memset(used, 0, sizeof(used)); int k = 0; for(size_t index=vs.size()-1; index>=0; i--) { if(!used[vs[i]]) { rdfs(vs[i], k++); } } return k; }
/* * Here we actually start growing the file system. We basically read the * cylinder summary from the first cylinder group as we want to update * this on the fly during our various operations. First we handle the * changes in the former last cylinder group. Afterwards we create all new * cylinder groups. Now we handle the cylinder group containing the * cylinder summary which might result in a relocation of the whole * structure. In the end we write back the updated cylinder summary, the * new superblock, and slightly patched versions of the super block * copies. */ static void growfs(int fsi, int fso, unsigned int Nflag) { DBG_FUNC("growfs") time_t modtime; uint cylno; int i, j, width; char tmpbuf[100]; DBG_ENTER; time(&modtime); /* * Get the cylinder summary into the memory. */ fscs = (struct csum *)calloc((size_t)1, (size_t)sblock.fs_cssize); if (fscs == NULL) errx(1, "calloc failed"); for (i = 0; i < osblock.fs_cssize; i += osblock.fs_bsize) { rdfs(fsbtodb(&osblock, osblock.fs_csaddr + numfrags(&osblock, i)), (size_t)MIN(osblock.fs_cssize - i, osblock.fs_bsize), (void *)(((char *)fscs) + i), fsi); } #ifdef FS_DEBUG { struct csum *dbg_csp; u_int32_t dbg_csc; char dbg_line[80]; dbg_csp = fscs; for (dbg_csc = 0; dbg_csc < osblock.fs_ncg; dbg_csc++) { snprintf(dbg_line, sizeof(dbg_line), "%d. old csum in old location", dbg_csc); DBG_DUMP_CSUM(&osblock, dbg_line, dbg_csp++); } } #endif /* FS_DEBUG */ DBG_PRINT0("fscs read\n"); /* * Do all needed changes in the former last cylinder group. */ updjcg(osblock.fs_ncg - 1, modtime, fsi, fso, Nflag); /* * Dump out summary information about file system. */ #ifdef FS_DEBUG #define B2MBFACTOR (1 / (1024.0 * 1024.0)) printf("growfs: %.1fMB (%jd sectors) block size %d, fragment size %d\n", (float)sblock.fs_size * sblock.fs_fsize * B2MBFACTOR, (intmax_t)fsbtodb(&sblock, sblock.fs_size), sblock.fs_bsize, sblock.fs_fsize); printf("\tusing %d cylinder groups of %.2fMB, %d blks, %d inodes.\n", sblock.fs_ncg, (float)sblock.fs_fpg * sblock.fs_fsize * B2MBFACTOR, sblock.fs_fpg / sblock.fs_frag, sblock.fs_ipg); if (sblock.fs_flags & FS_DOSOFTDEP) printf("\twith soft updates\n"); #undef B2MBFACTOR #endif /* FS_DEBUG */ /* * Now build the cylinders group blocks and * then print out indices of cylinder groups. */ printf("super-block backups (for fsck_ffs -b #) at:\n"); i = 0; width = charsperline(); /* * Iterate for only the new cylinder groups. */ for (cylno = osblock.fs_ncg; cylno < sblock.fs_ncg; cylno++) { initcg(cylno, modtime, fso, Nflag); j = sprintf(tmpbuf, " %jd%s", (intmax_t)fsbtodb(&sblock, cgsblock(&sblock, cylno)), cylno < (sblock.fs_ncg - 1) ? "," : "" ); if (i + j >= width) { printf("\n"); i = 0; } i += j; printf("%s", tmpbuf); fflush(stdout); } printf("\n"); /* * Do all needed changes in the first cylinder group. * allocate blocks in new location */ updcsloc(modtime, fsi, fso, Nflag); /* * Now write the cylinder summary back to disk. */ for (i = 0; i < sblock.fs_cssize; i += sblock.fs_bsize) { wtfs(fsbtodb(&sblock, sblock.fs_csaddr + numfrags(&sblock, i)), (size_t)MIN(sblock.fs_cssize - i, sblock.fs_bsize), (void *)(((char *)fscs) + i), fso, Nflag); } DBG_PRINT0("fscs written\n"); #ifdef FS_DEBUG { struct csum *dbg_csp; u_int32_t dbg_csc; char dbg_line[80]; dbg_csp = fscs; for (dbg_csc = 0; dbg_csc < sblock.fs_ncg; dbg_csc++) { snprintf(dbg_line, sizeof(dbg_line), "%d. new csum in new location", dbg_csc); DBG_DUMP_CSUM(&sblock, dbg_line, dbg_csp++); } } #endif /* FS_DEBUG */ /* * Now write the new superblock back to disk. */ sblock.fs_time = modtime; wtfs(sblockloc, (size_t)SBLOCKSIZE, (void *)&sblock, fso, Nflag); DBG_PRINT0("sblock written\n"); DBG_DUMP_FS(&sblock, "new initial sblock"); /* * Clean up the dynamic fields in our superblock copies. */ sblock.fs_fmod = 0; sblock.fs_clean = 1; sblock.fs_ronly = 0; sblock.fs_cgrotor = 0; sblock.fs_state = 0; memset((void *)&sblock.fs_fsmnt, 0, sizeof(sblock.fs_fsmnt)); sblock.fs_flags &= FS_DOSOFTDEP; /* * XXX * The following fields are currently distributed from the superblock * to the copies: * fs_minfree * fs_rotdelay * fs_maxcontig * fs_maxbpg * fs_minfree, * fs_optim * fs_flags regarding SOFTPDATES * * We probably should rather change the summary for the cylinder group * statistics here to the value of what would be in there, if the file * system were created initially with the new size. Therefor we still * need to find an easy way of calculating that. * Possibly we can try to read the first superblock copy and apply the * "diffed" stats between the old and new superblock by still copying * certain parameters onto that. */ /* * Write out the duplicate super blocks. */ for (cylno = 0; cylno < sblock.fs_ncg; cylno++) { wtfs(fsbtodb(&sblock, cgsblock(&sblock, cylno)), (size_t)SBLOCKSIZE, (void *)&sblock, fso, Nflag); } DBG_PRINT0("sblock copies written\n"); DBG_DUMP_FS(&sblock, "new other sblocks"); DBG_LEAVE; return; }
void mkfs(struct partition *pp, char *fsys, int fi, int fo, mode_t mfsmode, uid_t mfsuid, gid_t mfsgid) { time_t utime; quad_t sizepb; int i, j, width, origdensity, fragsperinode, minfpg, optimalfpg; int lastminfpg, mincylgrps; long cylno, csfrags; char tmpbuf[100]; /* XXX this will break in about 2,500 years */ if ((fsun = calloc(1, sizeof (union fs_u))) == NULL || (cgun = calloc(1, sizeof (union cg_u))) == NULL) err(1, "calloc"); #ifndef STANDALONE time(&utime); #endif if (mfs) { quad_t sz = (quad_t)fssize * sectorsize; if (sz > SIZE_T_MAX) { errno = ENOMEM; err(12, "mmap"); } membase = mmap(NULL, sz, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, (off_t)0); if (membase == MAP_FAILED) err(12, "mmap"); madvise(membase, sz, MADV_RANDOM); } fsi = fi; fso = fo; /* * Validate the given file system size. * Verify that its last block can actually be accessed. */ if (Oflag <= 1 && fssize > INT_MAX) errx(13, "preposterous size %lld, max is %d", fssize, INT_MAX); if (Oflag == 2 && fssize > MAXDISKSIZE) errx(13, "preposterous size %lld, max is %lld", fssize, MAXDISKSIZE); wtfs(fssize - 1, sectorsize, (char *)&sblock); sblock.fs_postblformat = FS_DYNAMICPOSTBLFMT; sblock.fs_avgfilesize = avgfilesize; sblock.fs_avgfpdir = avgfilesperdir; /* * Collect and verify the block and fragment sizes. */ if (!POWEROF2(bsize)) { errx(16, "block size must be a power of 2, not %d", bsize); } if (!POWEROF2(fsize)) { errx(17, "fragment size must be a power of 2, not %d", fsize); } if (fsize < sectorsize) { errx(18, "fragment size %d is too small, minimum is %d", fsize, sectorsize); } if (bsize < MINBSIZE) { errx(19, "block size %d is too small, minimum is %d", bsize, MINBSIZE); } if (bsize > MAXBSIZE) { errx(19, "block size %d is too large, maximum is %d", bsize, MAXBSIZE); } if (bsize < fsize) { errx(20, "block size (%d) cannot be smaller than fragment size (%d)", bsize, fsize); } sblock.fs_bsize = bsize; sblock.fs_fsize = fsize; /* * Calculate the superblock bitmasks and shifts. */ sblock.fs_bmask = ~(sblock.fs_bsize - 1); sblock.fs_fmask = ~(sblock.fs_fsize - 1); sblock.fs_qbmask = ~sblock.fs_bmask; sblock.fs_qfmask = ~sblock.fs_fmask; sblock.fs_bshift = ilog2(sblock.fs_bsize); sblock.fs_fshift = ilog2(sblock.fs_fsize); sblock.fs_frag = numfrags(&sblock, sblock.fs_bsize); if (sblock.fs_frag > MAXFRAG) { errx(21, "fragment size %d is too small, minimum with block " "size %d is %d", sblock.fs_fsize, sblock.fs_bsize, sblock.fs_bsize / MAXFRAG); } sblock.fs_fragshift = ilog2(sblock.fs_frag); sblock.fs_fsbtodb = ilog2(sblock.fs_fsize / sectorsize); sblock.fs_size = dbtofsb(&sblock, fssize); sblock.fs_nspf = sblock.fs_fsize / sectorsize; sblock.fs_maxcontig = 1; sblock.fs_nrpos = 1; sblock.fs_cpg = 1; /* * Before the file system is fully initialized, mark it as invalid. */ sblock.fs_magic = FS_BAD_MAGIC; /* * Set the remaining superblock fields. Note that for FFS1, media * geometry fields are set to fake values. This is for compatibility * with really ancient kernels that might still inspect these values. */ if (Oflag <= 1) { sblock.fs_sblockloc = SBLOCK_UFS1; sblock.fs_nindir = sblock.fs_bsize / sizeof(int32_t); sblock.fs_inopb = sblock.fs_bsize / sizeof(struct ufs1_dinode); if (Oflag == 0) { sblock.fs_maxsymlinklen = 0; sblock.fs_inodefmt = FS_42INODEFMT; } else { sblock.fs_maxsymlinklen = MAXSYMLINKLEN_UFS1; sblock.fs_inodefmt = FS_44INODEFMT; } sblock.fs_cgoffset = 0; sblock.fs_cgmask = 0xffffffff; sblock.fs_ffs1_size = sblock.fs_size; sblock.fs_rotdelay = 0; sblock.fs_rps = 60; sblock.fs_interleave = 1; sblock.fs_trackskew = 0; sblock.fs_cpc = 0; } else { sblock.fs_inodefmt = FS_44INODEFMT; sblock.fs_sblockloc = SBLOCK_UFS2; sblock.fs_nindir = sblock.fs_bsize / sizeof(int64_t); sblock.fs_inopb = sblock.fs_bsize / sizeof(struct ufs2_dinode); sblock.fs_maxsymlinklen = MAXSYMLINKLEN_UFS2; } sblock.fs_sblkno = roundup(howmany(sblock.fs_sblockloc + SBLOCKSIZE, sblock.fs_fsize), sblock.fs_frag); sblock.fs_cblkno = (int32_t)(sblock.fs_sblkno + roundup(howmany(SBSIZE, sblock.fs_fsize), sblock.fs_frag)); sblock.fs_iblkno = sblock.fs_cblkno + sblock.fs_frag; sblock.fs_maxfilesize = sblock.fs_bsize * NDADDR - 1; for (sizepb = sblock.fs_bsize, i = 0; i < NIADDR; i++) { sizepb *= NINDIR(&sblock); sblock.fs_maxfilesize += sizepb; } #ifdef notyet /* * It is impossible to create a snapshot in case fs_maxfilesize is * smaller than fssize. */ if (sblock.fs_maxfilesize < (u_quad_t)fssize) warnx("WARNING: You will be unable to create snapshots on this " "file system. Correct by using a larger blocksize."); #endif /* * Calculate the number of blocks to put into each cylinder group. The * first goal is to have at least enough data blocks in each cylinder * group to meet the density requirement. Once this goal is achieved * we try to expand to have at least mincylgrps cylinder groups. Once * this goal is achieved, we pack as many blocks into each cylinder * group map as will fit. * * We start by calculating the smallest number of blocks that we can * put into each cylinder group. If this is too big, we reduce the * density until it fits. */ origdensity = density; for (;;) { fragsperinode = MAX(numfrags(&sblock, density), 1); minfpg = fragsperinode * INOPB(&sblock); if (minfpg > sblock.fs_size) minfpg = sblock.fs_size; sblock.fs_ipg = INOPB(&sblock); sblock.fs_fpg = roundup(sblock.fs_iblkno + sblock.fs_ipg / INOPF(&sblock), sblock.fs_frag); if (sblock.fs_fpg < minfpg) sblock.fs_fpg = minfpg; sblock.fs_ipg = roundup(howmany(sblock.fs_fpg, fragsperinode), INOPB(&sblock)); sblock.fs_fpg = roundup(sblock.fs_iblkno + sblock.fs_ipg / INOPF(&sblock), sblock.fs_frag); if (sblock.fs_fpg < minfpg) sblock.fs_fpg = minfpg; sblock.fs_ipg = roundup(howmany(sblock.fs_fpg, fragsperinode), INOPB(&sblock)); if (CGSIZE(&sblock) < (unsigned long)sblock.fs_bsize) break; density -= sblock.fs_fsize; } if (density != origdensity) warnx("density reduced from %d to %d bytes per inode", origdensity, density); /* * Use a lower value for mincylgrps if the user specified a large * number of blocks per cylinder group. This is needed for, e.g. the * install media which needs to pack 2 files very tightly. */ mincylgrps = MINCYLGRPS; if (maxfrgspercg != INT_MAX) { i = sblock.fs_size / maxfrgspercg; if (i < MINCYLGRPS) mincylgrps = i <= 0 ? 1 : i; } /* * Start packing more blocks into the cylinder group until it cannot * grow any larger, the number of cylinder groups drops below * mincylgrps, or we reach the requested size. */ for (;;) { sblock.fs_fpg += sblock.fs_frag; sblock.fs_ipg = roundup(howmany(sblock.fs_fpg, fragsperinode), INOPB(&sblock)); if (sblock.fs_fpg > maxfrgspercg || sblock.fs_size / sblock.fs_fpg < mincylgrps || CGSIZE(&sblock) > (unsigned long)sblock.fs_bsize) break; } sblock.fs_fpg -= sblock.fs_frag; sblock.fs_ipg = roundup(howmany(sblock.fs_fpg, fragsperinode), INOPB(&sblock)); if (sblock.fs_fpg > maxfrgspercg) warnx("can't honour -c: minimum is %d", sblock.fs_fpg); /* * Check to be sure that the last cylinder group has enough blocks to * be viable. If it is too small, reduce the number of blocks per * cylinder group which will have the effect of moving more blocks into * the last cylinder group. */ optimalfpg = sblock.fs_fpg; for (;;) { sblock.fs_ncg = howmany(sblock.fs_size, sblock.fs_fpg); lastminfpg = roundup(sblock.fs_iblkno + sblock.fs_ipg / INOPF(&sblock), sblock.fs_frag); if (sblock.fs_size < lastminfpg) errx(28, "file system size %jd < minimum size of %d", (intmax_t)sblock.fs_size, lastminfpg); if (sblock.fs_size % sblock.fs_fpg >= lastminfpg || sblock.fs_size % sblock.fs_fpg == 0) break; sblock.fs_fpg -= sblock.fs_frag; sblock.fs_ipg = roundup(howmany(sblock.fs_fpg, fragsperinode), INOPB(&sblock)); } if (optimalfpg != sblock.fs_fpg) warnx("reduced number of fragments per cylinder group from %d" " to %d to enlarge last cylinder group", optimalfpg, sblock.fs_fpg); /* * Back to filling superblock fields. */ if (Oflag <= 1) { sblock.fs_spc = sblock.fs_fpg * sblock.fs_nspf; sblock.fs_nsect = sblock.fs_spc; sblock.fs_npsect = sblock.fs_spc; sblock.fs_ncyl = sblock.fs_ncg; } sblock.fs_cgsize = fragroundup(&sblock, CGSIZE(&sblock)); sblock.fs_dblkno = sblock.fs_iblkno + sblock.fs_ipg / INOPF(&sblock); sblock.fs_csaddr = cgdmin(&sblock, 0); sblock.fs_cssize = fragroundup(&sblock, sblock.fs_ncg * sizeof(struct csum)); fscs = (struct csum *)calloc(1, sblock.fs_cssize); if (fscs == NULL) errx(31, "calloc failed"); sblock.fs_sbsize = fragroundup(&sblock, sizeof(struct fs)); if (sblock.fs_sbsize > SBLOCKSIZE) sblock.fs_sbsize = SBLOCKSIZE; sblock.fs_minfree = minfree; sblock.fs_maxbpg = maxbpg; sblock.fs_optim = opt; sblock.fs_cgrotor = 0; sblock.fs_pendingblocks = 0; sblock.fs_pendinginodes = 0; sblock.fs_fmod = 0; sblock.fs_ronly = 0; sblock.fs_state = 0; sblock.fs_clean = 1; sblock.fs_id[0] = (u_int32_t)utime; sblock.fs_id[1] = (u_int32_t)arc4random(); sblock.fs_fsmnt[0] = '\0'; csfrags = howmany(sblock.fs_cssize, sblock.fs_fsize); sblock.fs_dsize = sblock.fs_size - sblock.fs_sblkno - sblock.fs_ncg * (sblock.fs_dblkno - sblock.fs_sblkno); sblock.fs_cstotal.cs_nbfree = fragstoblks(&sblock, sblock.fs_dsize) - howmany(csfrags, sblock.fs_frag); sblock.fs_cstotal.cs_nffree = fragnum(&sblock, sblock.fs_size) + (fragnum(&sblock, csfrags) > 0 ? sblock.fs_frag - fragnum(&sblock, csfrags) : 0); sblock.fs_cstotal.cs_nifree = sblock.fs_ncg * sblock.fs_ipg - ROOTINO; sblock.fs_cstotal.cs_ndir = 0; sblock.fs_dsize -= csfrags; sblock.fs_time = utime; if (Oflag <= 1) { sblock.fs_ffs1_time = sblock.fs_time; sblock.fs_ffs1_dsize = sblock.fs_dsize; sblock.fs_ffs1_csaddr = sblock.fs_csaddr; sblock.fs_ffs1_cstotal.cs_ndir = sblock.fs_cstotal.cs_ndir; sblock.fs_ffs1_cstotal.cs_nbfree = sblock.fs_cstotal.cs_nbfree; sblock.fs_ffs1_cstotal.cs_nifree = sblock.fs_cstotal.cs_nifree; sblock.fs_ffs1_cstotal.cs_nffree = sblock.fs_cstotal.cs_nffree; } /* * Dump out summary information about file system. */ if (!mfs) { #define B2MBFACTOR (1 / (1024.0 * 1024.0)) printf("%s: %.1fMB in %jd sectors of %d bytes\n", fsys, (float)sblock.fs_size * sblock.fs_fsize * B2MBFACTOR, (intmax_t)fsbtodb(&sblock, sblock.fs_size), sectorsize); printf("%d cylinder groups of %.2fMB, %d blocks, %d" " inodes each\n", sblock.fs_ncg, (float)sblock.fs_fpg * sblock.fs_fsize * B2MBFACTOR, sblock.fs_fpg / sblock.fs_frag, sblock.fs_ipg); #undef B2MBFACTOR } /* * Wipe out old FFS1 superblock if necessary. */ if (Oflag >= 2) { union fs_u *fsun1; struct fs *fs1; fsun1 = calloc(1, sizeof(union fs_u)); if (fsun1 == NULL) err(39, "calloc"); fs1 = &fsun1->fs; rdfs(SBLOCK_UFS1 / sectorsize, SBSIZE, (char *)fs1); if (fs1->fs_magic == FS_UFS1_MAGIC) { fs1->fs_magic = FS_BAD_MAGIC; wtfs(SBLOCK_UFS1 / sectorsize, SBSIZE, (char *)fs1); } free(fsun1); } wtfs((int)sblock.fs_sblockloc / sectorsize, SBSIZE, (char *)&sblock); sblock.fs_magic = (Oflag <= 1) ? FS_UFS1_MAGIC : FS_UFS2_MAGIC; /* * Now build the cylinders group blocks and * then print out indices of cylinder groups. */ if (!quiet) printf("super-block backups (for fsck -b #) at:\n"); #ifndef STANDALONE else if (!mfs && isatty(STDIN_FILENO)) { signal(SIGINFO, siginfo); cur_fsys = fsys; } #endif i = 0; width = charsperline(); /* * Allocate space for superblock, cylinder group map, and two sets of * inode blocks. */ if (sblock.fs_bsize < SBLOCKSIZE) iobufsize = SBLOCKSIZE + 3 * sblock.fs_bsize; else iobufsize = 4 * sblock.fs_bsize; if ((iobuf = malloc(iobufsize)) == 0) errx(38, "cannot allocate I/O buffer"); bzero(iobuf, iobufsize); /* * Make a copy of the superblock into the buffer that we will be * writing out in each cylinder group. */ bcopy((char *)&sblock, iobuf, SBLOCKSIZE); for (cylno = 0; cylno < sblock.fs_ncg; cylno++) { cur_cylno = (sig_atomic_t)cylno; initcg(cylno, utime); if (quiet) continue; j = snprintf(tmpbuf, sizeof tmpbuf, " %lld,", fsbtodb(&sblock, cgsblock(&sblock, cylno))); if (j >= sizeof tmpbuf) j = sizeof tmpbuf - 1; if (j == -1 || i+j >= width) { printf("\n"); i = 0; } i += j; printf("%s", tmpbuf); fflush(stdout); } if (!quiet) printf("\n"); if (Nflag && !mfs) exit(0); /* * Now construct the initial file system, then write out the superblock. */ if (Oflag <= 1) { if (fsinit1(utime, mfsmode, mfsuid, mfsgid)) errx(32, "fsinit1 failed"); sblock.fs_ffs1_cstotal.cs_ndir = sblock.fs_cstotal.cs_ndir; sblock.fs_ffs1_cstotal.cs_nbfree = sblock.fs_cstotal.cs_nbfree; sblock.fs_ffs1_cstotal.cs_nifree = sblock.fs_cstotal.cs_nifree; sblock.fs_ffs1_cstotal.cs_nffree = sblock.fs_cstotal.cs_nffree; } else { if (fsinit2(utime)) errx(32, "fsinit2 failed"); } wtfs((int)sblock.fs_sblockloc / sectorsize, SBSIZE, (char *)&sblock); for (i = 0; i < sblock.fs_cssize; i += sblock.fs_bsize) wtfs(fsbtodb(&sblock, sblock.fs_csaddr + numfrags(&sblock, i)), sblock.fs_cssize - i < sblock.fs_bsize ? sblock.fs_cssize - i : sblock.fs_bsize, ((char *)fscs) + i); /* * Update information about this partion in pack label, to that it may * be updated on disk. */ pp->p_fstype = FS_BSDFFS; pp->p_fragblock = DISKLABELV1_FFS_FRAGBLOCK(sblock.fs_fsize, sblock.fs_frag); pp->p_cpg = sblock.fs_cpg; }
/* * Here we dump a list of all blocks allocated by this inode. We follow * all indirect blocks. */ void dump_whole_inode(ino_t inode, int fsi, int level) { struct ufs1_dinode *ino; int rb; unsigned int ind2ctr, ind3ctr; ufs_daddr_t *ind2ptr, *ind3ptr; char comment[80]; DBG_ENTER; /* * Read the inode from disk/cache. */ ino=ginode(inode, fsi); if(ino->di_nlink==0) { DBG_LEAVE; return; /* inode not in use */ } /* * Dump the main inode structure. */ snprintf(comment, sizeof(comment), "Inode 0x%08jx", (uintmax_t)inode); if (level & 0x100) { DBG_DUMP_INO(&sblock, comment, ino); } if (!(level & 0x200)) { DBG_LEAVE; return; } /* * Ok, now prepare for dumping all direct and indirect pointers. */ rb=howmany(ino->di_size, sblock.fs_bsize)-UFS_NDADDR; if(rb>0) { /* * Dump single indirect block. */ rdfs(fsbtodb(&sblock, ino->di_ib[0]), (size_t)sblock.fs_bsize, &i1blk, fsi); snprintf(comment, sizeof(comment), "Inode 0x%08jx: indirect 0", (uintmax_t)inode); DBG_DUMP_IBLK(&sblock, comment, i1blk, (size_t)rb); rb-=howmany(sblock.fs_bsize, sizeof(ufs_daddr_t)); } if(rb>0) { /* * Dump double indirect blocks. */ rdfs(fsbtodb(&sblock, ino->di_ib[1]), (size_t)sblock.fs_bsize, &i2blk, fsi); snprintf(comment, sizeof(comment), "Inode 0x%08jx: indirect 1", (uintmax_t)inode); DBG_DUMP_IBLK(&sblock, comment, i2blk, howmany(rb, howmany(sblock.fs_bsize, sizeof(ufs_daddr_t)))); for(ind2ctr=0; ((ind2ctr < howmany(sblock.fs_bsize, sizeof(ufs_daddr_t)))&&(rb>0)); ind2ctr++) { ind2ptr=&((ufs_daddr_t *)(void *)&i2blk)[ind2ctr]; rdfs(fsbtodb(&sblock, *ind2ptr), (size_t)sblock.fs_bsize, &i1blk, fsi); snprintf(comment, sizeof(comment), "Inode 0x%08jx: indirect 1->%d", (uintmax_t)inode, ind2ctr); DBG_DUMP_IBLK(&sblock, comment, i1blk, (size_t)rb); rb-=howmany(sblock.fs_bsize, sizeof(ufs_daddr_t)); } } if(rb>0) { /* * Dump triple indirect blocks. */ rdfs(fsbtodb(&sblock, ino->di_ib[2]), (size_t)sblock.fs_bsize, &i3blk, fsi); snprintf(comment, sizeof(comment), "Inode 0x%08jx: indirect 2", (uintmax_t)inode); #define SQUARE(a) ((a)*(a)) DBG_DUMP_IBLK(&sblock, comment, i3blk, howmany(rb, SQUARE(howmany(sblock.fs_bsize, sizeof(ufs_daddr_t))))); #undef SQUARE for(ind3ctr=0; ((ind3ctr < howmany(sblock.fs_bsize, sizeof(ufs_daddr_t)))&&(rb>0)); ind3ctr ++) { ind3ptr=&((ufs_daddr_t *)(void *)&i3blk)[ind3ctr]; rdfs(fsbtodb(&sblock, *ind3ptr), (size_t)sblock.fs_bsize, &i2blk, fsi); snprintf(comment, sizeof(comment), "Inode 0x%08jx: indirect 2->%d", (uintmax_t)inode, ind3ctr); DBG_DUMP_IBLK(&sblock, comment, i2blk, howmany(rb, howmany(sblock.fs_bsize, sizeof(ufs_daddr_t)))); for(ind2ctr=0; ((ind2ctr < howmany(sblock.fs_bsize, sizeof(ufs_daddr_t)))&&(rb>0)); ind2ctr ++) { ind2ptr=&((ufs_daddr_t *)(void *)&i2blk) [ind2ctr]; rdfs(fsbtodb(&sblock, *ind2ptr), (size_t)sblock.fs_bsize, &i1blk, fsi); snprintf(comment, sizeof(comment), "Inode 0x%08jx: indirect 2->%d->%d", (uintmax_t)inode, ind3ctr, ind3ctr); DBG_DUMP_IBLK(&sblock, comment, i1blk, (size_t)rb); rb-=howmany(sblock.fs_bsize, sizeof(ufs_daddr_t)); } } } DBG_LEAVE; return; }
/* * ffsinfo(8) is a tool to dump all metadata of a filesystem. It helps to find * errors is the filesystem much easier. You can run ffsinfo before and after * an fsck(8), and compare the two ascii dumps easy with diff, and you see * directly where the problem is. You can control how much detail you want to * see with some command line arguments. You can also easy check the status * of a filesystem, like is there is enough space for growing a filesystem, * or how many active snapshots do we have. It provides much more detailed * information then dumpfs. Snapshots, as they are very new, are not really * supported. They are just mentioned currently, but it is planned to run * also over active snapshots, to even get that output. */ int main(int argc, char **argv) { char *device, *special; char ch; size_t len; struct stat st; struct partinfo pinfo; int fsi; struct csum *dbg_csp; int dbg_csc; char dbg_line[80]; int cylno,i; int cfg_cg, cfg_in, cfg_lv; int cg_start, cg_stop; ino_t in; char *out_file = NULL; int Lflag=0; DBG_ENTER; cfg_lv=0xff; cfg_in=-2; cfg_cg=-2; while ((ch=getopt(argc, argv, "Lg:i:l:o:")) != -1) { switch(ch) { case 'L': Lflag=1; break; case 'g': cfg_cg=atol(optarg); if(cfg_cg < -1) { usage(); } break; case 'i': cfg_in=atol(optarg); if(cfg_in < 0) { usage(); } break; case 'l': cfg_lv=atol(optarg); if(cfg_lv < 0x1||cfg_lv > 0x3ff) { usage(); } break; case 'o': if (out_file) free(out_file); out_file = strdup(optarg); break; case '?': /* FALLTHROUGH */ default: usage(); } } argc -= optind; argv += optind; if(argc != 1) { usage(); } device=*argv; /* * Now we try to guess the (raw)device name. */ if (0 == strrchr(device, '/') && (stat(device, &st) == -1)) { /* * No path prefix was given, so try in that order: * /dev/r%s * /dev/%s * /dev/vinum/r%s * /dev/vinum/%s. * * FreeBSD now doesn't distinguish between raw and block * devices any longer, but it should still work this way. */ len=strlen(device)+strlen(_PATH_DEV)+2+strlen("vinum/"); special=(char *)malloc(len); if(special == NULL) { errx(1, "malloc failed"); } snprintf(special, len, "%sr%s", _PATH_DEV, device); if (stat(special, &st) == -1) { snprintf(special, len, "%s%s", _PATH_DEV, device); if (stat(special, &st) == -1) { snprintf(special, len, "%svinum/r%s", _PATH_DEV, device); if (stat(special, &st) == -1) { /* * For now this is the 'last resort'. */ snprintf(special, len, "%svinum/%s", _PATH_DEV, device); } } } device = special; } /* * Open our device for reading. */ fsi = open(device, O_RDONLY); if (fsi < 0) { err(1, "%s", device); } stat(device, &st); if(S_ISREG(st.st_mode)) { /* label check not supported for files */ Lflag=1; } if(!Lflag) { /* * Try to read a label and gess the slice if not specified. * This code should guess the right thing and avaid to bother * the user user with the task of specifying the option -v on * vinum volumes. */ if (ioctl(fsi, DIOCGPART, &pinfo) < 0) { pinfo.media_size = st.st_size; pinfo.media_blksize = DEV_BSIZE; pinfo.media_blocks = pinfo.media_size / DEV_BSIZE; } /* * Check if that partition looks suited for dumping. */ if (pinfo.media_size == 0) { errx(1, "partition is unavailable"); } } /* * Read the current superblock. */ rdfs((daddr_t)(SBOFF/DEV_BSIZE), (size_t)SBSIZE, &sblock, fsi); if (sblock.fs_magic != FS_MAGIC) { errx(1, "superblock not recognized"); } DBG_OPEN(out_file); /* already here we need a superblock */ if(cfg_lv & 0x001) { DBG_DUMP_FS(&sblock, "primary sblock"); } /* * Determine here what cylinder groups to dump. */ if(cfg_cg==-2) { cg_start=0; cg_stop=sblock.fs_ncg; } else if (cfg_cg==-1) { cg_start=sblock.fs_ncg-1; cg_stop=sblock.fs_ncg; } else if (cfg_cg<sblock.fs_ncg) { cg_start=cfg_cg; cg_stop=cfg_cg+1; } else { cg_start=sblock.fs_ncg; cg_stop=sblock.fs_ncg; } if (cfg_lv & 0x004) { fscs = (struct csum *)calloc((size_t)1, (size_t)sblock.fs_cssize); if(fscs == NULL) { errx(1, "calloc failed"); } /* * Get the cylinder summary into the memory ... */ for (i = 0; i < sblock.fs_cssize; i += sblock.fs_bsize) { rdfs(fsbtodb(&sblock, sblock.fs_csaddr + numfrags(&sblock, i)), (size_t)(sblock.fs_cssize-i< sblock.fs_bsize ? sblock.fs_cssize - i : sblock.fs_bsize), (void *)(((char *)fscs)+i), fsi); } dbg_csp=fscs; /* * ... and dump it. */ for(dbg_csc=0; dbg_csc<sblock.fs_ncg; dbg_csc++) { snprintf(dbg_line, sizeof(dbg_line), "%d. csum in fscs", dbg_csc); DBG_DUMP_CSUM(&sblock, dbg_line, dbg_csp++); } } /* * For each requested cylinder group ... */ for(cylno=cg_start; cylno<cg_stop; cylno++) { snprintf(dbg_line, sizeof(dbg_line), "cgr %d", cylno); if(cfg_lv & 0x002) { /* * ... dump the superblock copies ... */ rdfs(fsbtodb(&sblock, cgsblock(&sblock, cylno)), (size_t)SBSIZE, &osblock, fsi); DBG_DUMP_FS(&osblock, dbg_line); } /* * ... read the cylinder group and dump whatever was requested. */ rdfs(fsbtodb(&sblock, cgtod(&sblock, cylno)), (size_t)sblock.fs_cgsize, &acg, fsi); if(cfg_lv & 0x008) { DBG_DUMP_CG(&sblock, dbg_line, &acg); } if(cfg_lv & 0x010) { DBG_DUMP_INMAP(&sblock, dbg_line, &acg); } if(cfg_lv & 0x020) { DBG_DUMP_FRMAP(&sblock, dbg_line, &acg); } if(cfg_lv & 0x040) { DBG_DUMP_CLMAP(&sblock, dbg_line, &acg); DBG_DUMP_CLSUM(&sblock, dbg_line, &acg); } if(cfg_lv & 0x080) { DBG_DUMP_SPTBL(&sblock, dbg_line, &acg); } } /* * Dump the requested inode(s). */ if(cfg_in != -2) { dump_whole_inode((ino_t)cfg_in, fsi, cfg_lv); } else { for(in=cg_start*sblock.fs_ipg; in<(ino_t)cg_stop*sblock.fs_ipg; in++) { dump_whole_inode(in, fsi, cfg_lv); } } DBG_CLOSE; close(fsi); DBG_LEAVE; return 0; }
// construct the prdf profile static PyObject *func_construct_prdf(PyObject *self, PyObject *args) { // local variables double cube_length; int nx, ny, nz; double x0, y0, z0; double prdf_spacing; int prdf_n; double cutoff_distance; size_t i; PyObject * item; // parse the argument list PyObject * py_solute_atom_types, * py_solvent_atom_types; PyObject * py_solute_atom_surf_mask; PyObject * py_solute_atom_coors, * py_solvent_atom_coors; if (!PyArg_ParseTuple(args, "O!O!O!O!O!ddddiiidid", &PyList_Type, &py_solute_atom_types, &PyArray_Type, &py_solute_atom_coors, &PyList_Type, &py_solvent_atom_types, &PyArray_Type, &py_solvent_atom_coors, &PyArray_Type, &py_solute_atom_surf_mask, &x0, &y0, &z0, &cube_length, &nx, &ny, &nz, &prdf_spacing, &prdf_n, &cutoff_distance)) return NULL; // define types typedef Atom::SoluteAtom::SoluteAtomType solute_atom_type_t; typedef Atom::SolventAtom::SolventAtomType solvent_atom_type_t; // get the number of frames, and solute/solvent atoms PyArrayObject * pyArray_solute_atom_coors = (PyArrayObject*)PyArray_ContiguousFromObject(py_solute_atom_coors,PyArray_DOUBLE, 2,2); PyArrayObject * pyArray_solvent_atom_coors = (PyArrayObject*)PyArray_ContiguousFromObject(py_solvent_atom_coors,PyArray_DOUBLE, 3,3); const size_t tot_frames=pyArray_solvent_atom_coors->dimensions[0]; const size_t n_solute_atoms = PyList_Size(py_solute_atom_types); const size_t n_solvent_atoms = PyList_Size(py_solvent_atom_types); std::cout<<__LINE__<<std::endl; // get the solute atom surface mask PyArrayObject * pyArray_solute_atom_surf_mask = (PyArrayObject*)PyArray_ContiguousFromObject(py_solute_atom_surf_mask,PyArray_INT, 1,1); std::cout<<__LINE__<<std::endl; // convert python types to C types solute_atom_type_t * solute_atom_types = new solute_atom_type_t[n_solute_atoms]; for (i=0; i<n_solute_atoms; i++) { item = PyList_GetItem(py_solute_atom_types, i); if (!PyString_Check(item)) prdf::utils::Error("solute atom type should be a string!"); solute_atom_types[i] = PyString_AsString(item); } solvent_atom_type_t * solvent_atom_types = new solvent_atom_type_t[n_solvent_atoms]; for (i=0; i<n_solvent_atoms; i++) { item = PyList_GetItem(py_solvent_atom_types, i); if (!PyString_Check(item)) prdf::utils::Error("solvent atom type should be a string!"); solvent_atom_types[i] = PyString_AsString(item); } double * solute_atom_coors = (double*)(pyArray_solute_atom_coors->data); double * solvent_atom_coors = (double*)(pyArray_solvent_atom_coors->data); int * solute_atom_surf_mask = (int*)(pyArray_solute_atom_surf_mask->data); std::cout<<__LINE__<<std::endl; /* std::cout<<"c0: "<<x0<<" "<<y0<<" "<<z0<<std::endl; std::cout<<"nx/y/z: "<<nx<<" "<<ny<<" "<<nz<<std::endl; std::cout<<"cube_l: "<<cube_length<<std::endl; std::cout<<"prfd_n/spacing: "<<prdf_n<<" "<<prdf_spacing<<std::endl; std::cout<<"n_slute: "<<n_solute_atoms<<" n_solv: "<<n_solvent_atoms<<std::endl; std::cout<<"c0 solute: "<<solute_atom_coors[0]<<" "<<solute_atom_coors[1]<<" "<<solute_atom_coors[2]<<std::endl; std::cout<<"c1 solute: "<<solute_atom_coors[3]<<" "<<solute_atom_coors[4]<<" "<<solute_atom_coors[5]<<std::endl; std::cout<<"c0 solvent: "<<solvent_atom_coors[0]<<" "<<solvent_atom_coors[1]<<" "<<solvent_atom_coors[2]<<std::endl; std::cout<<"c1 solvent: "<<solvent_atom_coors[3]<<" "<<solvent_atom_coors[4]<<" "<<solvent_atom_coors[5]<<std::endl; for (i=0; i<n_solute_atoms; i++) std::cout<<solute_atom_surf_mask[i]<<std::endl; */ // box parameters Coor coor_box_origin(x0, y0, z0); // set up the box Box box(coor_box_origin, nx, ny, nz, cube_length); std::cout<<__LINE__<<std::endl; // prdf parameters // set up prdf pRDF rdfs(prdf_n, prdf_spacing); std::cout<<__LINE__<<std::endl; // set up the cubes in box box.setupCube(n_solute_atoms, solute_atom_types, solute_atom_coors, solute_atom_surf_mask, cutoff_distance); // set up the _p_cube_type_distance from the passed solute atom set // print out the types and distances values of all the not-null cubes for debugging box.fprintfTypeDistancePDB("box_type_distance.pdb"); std::cout<<__LINE__<<std::endl; // accumulate the solvent density into cubes for (size_t frame = 0; frame<tot_frames; ++frame) { // accumulate the solvent density into cubes box.accumulateCubeDensity(n_solvent_atoms, solvent_atom_types, solvent_atom_coors+frame*n_solvent_atoms*3); } std::cout<<__LINE__<<std::endl; // finally update the pRDF based on the box rdfs.update(box); std::cout<<__LINE__<<std::endl; // output pRDF std::ofstream fout("pRDF.txt"); rdfs.print(fout,box,tot_frames); fout.close(); std::cout<<__LINE__<<std::endl; // clean up delete [] solute_atom_types; delete [] solvent_atom_types; std::cout<<__LINE__<<std::endl; // return Py_INCREF(Py_None); std::cout<<__LINE__<<std::endl; return Py_None; }
/// predict the prdf profile static PyObject *func_predict_prdf(PyObject *self, PyObject *args) { // local variables double cube_length; int nx, ny, nz; double x0, y0, z0; double cutoff_distance; size_t i; PyObject * item; // parse the argument list PyObject * py_solute_atom_types; PyObject * py_solute_atom_surf_mask; PyObject * py_solute_atom_coors; if (!PyArg_ParseTuple(args, "O!O!O!ddddiiid", &PyList_Type, &py_solute_atom_types, &PyArray_Type, &py_solute_atom_coors, &PyArray_Type, &py_solute_atom_surf_mask, &x0, &y0, &z0, &cube_length, &nx, &ny, &nz, &cutoff_distance)) return NULL; // define types typedef Atom::SoluteAtom::SoluteAtomType solute_atom_type_t; typedef Atom::SolventAtom::SolventAtomType solvent_atom_type_t; // get the number of frames, and solute/solvent atoms PyArrayObject * pyArray_solute_atom_coors = (PyArrayObject*)PyArray_ContiguousFromObject(py_solute_atom_coors,PyArray_DOUBLE, 2,2); const size_t n_solute_atoms = PyList_Size(py_solute_atom_types); // get the solute atom surface mask PyArrayObject * pyArray_solute_atom_surf_mask = (PyArrayObject*)PyArray_ContiguousFromObject(py_solute_atom_surf_mask,PyArray_INT, 1,1); // convert python types to C types solute_atom_type_t * solute_atom_types = new solute_atom_type_t[n_solute_atoms]; for (i=0; i<n_solute_atoms; i++) { item = PyList_GetItem(py_solute_atom_types, i); if (!PyString_Check(item)) prdf::utils::Error("solute atom type should be a string!"); solute_atom_types[i] = PyString_AsString(item); } double * solute_atom_coors = (double*)(pyArray_solute_atom_coors->data); int * solute_atom_surf_mask = (int*)(pyArray_solute_atom_surf_mask->data); // box parameters Coor coor_box_origin(x0, y0, z0); // set up the box Box box(coor_box_origin, nx, ny, nz, cube_length); // instantiate pRDF from the external file pRDF rdfs("pRDF.txt"); // set up the cubes in box box.setupCube(n_solute_atoms, solute_atom_types, solute_atom_coors, solute_atom_surf_mask, cutoff_distance); // set up the _p_cube_type_distance from the passed solute atom set // print out the types and distances values of all the not-null cubes for debugging box.fprintfTypeDistancePDB("box_type_distance.pdb"); // predict the solvent density in cubes box.predictCubeDensity(rdfs, cutoff_distance); // output box box.fprintfTypeDensityPDB("box_type_density.pdb"); // clean up delete [] solute_atom_types; // return Py_INCREF(Py_None); return Py_None; }
int main() { timestamp = 0; memset(visited, -1, sizeof(visited)); int n, m, q; scanf("%d%d%d", &n, &m, &q); for (int i = 0; i < n; ++ i) { scanf("%d", weight + i); } for (int i = 0; i < m; ++ i) { int a, b; scanf("%d%d", &a, &b); a --; b --; graph[a].push_back(b); rgraph[b].push_back(a); } memset(match_x, -1, sizeof(match_x)); memset(match_y, -1, sizeof(match_y)); int sum = 0; { std::vector<int> order(n); std::iota(ALL(order), 0); std::sort(ALL(order), by_weight); memset(match_x, -1, sizeof(match_x)); memset(match_y, -1, sizeof(match_y)); timestamp ++; for (int v : order) { if (weight[v] < 0) { break; } if (find(v)) { sum += weight[v]; timestamp ++; } } } while (q --) { int u, w; scanf("%d%d", &u, &w); u --; timestamp ++; do { if (match_x[u] == -1) { weight[u] = w; if (w < 0) { continue; } if (find(u)) { sum += weight[u]; } else { timestamp ++; dfs(u); int best = u; for (int v = 0; v < n; ++ v) { if (visited[v] == timestamp && weight[v] < weight[best]) { best = v; } } if (best != u) { match_x[best] = -1; } for (int p = best; p != u; p = parent[p]) { match_y[via[p]] = parent[p]; match_x[parent[p]] = via[p]; } sum += weight[u] - weight[best]; } } else { sum += w - weight[u]; weight[u] = w; rdfs(u); int best = u; for (int v = 0; v < n; ++ v) { if (visited[v] == timestamp && match_x[v] == -1 && weight[v] > weight[best]) { best = v; } } if (weight[best] <= 0) { sum -= weight[u]; match_y[match_x[u]] = -1; match_x[u] = -1; } else { for (int p = best; p != u; p = parent[p]) { match_x[p] = via[p]; match_y[via[p]] = p; } if (best != u) { match_x[u] = -1; } sum += weight[best] - weight[u]; } } } while (false); printf("%d\n", sum); } return 0; }
/* write the memory-inode out to the inode-block */ void iput(struct inode *ip, int *aibc, s4_daddr *ib) { struct s4_dinode *dp; s4_daddr d; int i,j,k; s4_daddr ib2[NIDIR]; /* a double indirect block */ filsys->s_tinode--; d = itod(ip->i_number); if(d >= filsys->s_isize) { if(error == 0) printf("ilist too small\n"); error = 1; return; } /* get the existing disk inode block to modify */ rdfs(d, buf, s4b_ino ); dp = (struct s4_dinode *)buf; /* skip to the right entry */ dp += itoo(ip->i_number); /* convert memory to disk format in buffer */ dp->di_mode = ip->i_ftype | ip->i_mode; dp->di_nlink = ip->i_nlink; dp->di_uid = ip->i_uid; dp->di_gid = ip->i_gid; dp->di_size = ip->i_size; dp->di_atime = utime; dp->di_mtime = utime; dp->di_ctime = utime; switch(ip->i_ftype) { case S_IFDIR: case S_IFREG: /* handle direct pointers */ for(i=0; i<*aibc && i<LADDR; i++) { ip->i_faddr[i] = ib[i]; ib[i] = 0; } /* handle single indirect block */ if(i < *aibc) { for(j=0; i<*aibc && j<NIDIR; j++, i++) ib[j] = ib[i]; for(; j<NIDIR; j++) ib[j] = 0; ip->i_faddr[LADDR] = alloc(); wtfs(ip->i_faddr[LADDR], (char *)ib, s4b_idx); } /* handle double indirect block */ if(i < *aibc) { for(k=0; k<NIDIR && i<*aibc; k++) { for(j=0; i<*aibc && j<NIDIR; j++, i++) ib[j] = ib[i]; for(; j<NIDIR; j++) ib[j] = 0; ib2[k] = alloc(); wtfs(ib2[k], (char *)ib, s4b_idx); } for(; k<NIDIR; k++) ib2[k] = 0; ip->i_faddr[LADDR+1] = alloc(); wtfs(ip->i_faddr[LADDR+1], (char *)ib2, s4b_idx ); } /* triple indirect block? Nope. */ if(i < *aibc) { printf("triple indirect blocks not handled\n"); } break; default: printf("bogus ftype %o\n", ip->i_ftype); exit(1); } /* convert the address list to correct disk format */ if( doswap ) s4ltol3r(dp->di_addr, ip->i_faddr, S4_NADDR); else s4ltol3(dp->di_addr, ip->i_faddr, S4_NADDR); wtfs(d, buf, s4b_ino); }