예제 #1
0
파일: sfsck.c 프로젝트: PhelanHarris/os161
static
void
check_root_dir(void)
{
	struct sfs_inode sfi;
	diskread(&sfi, SFS_ROOT_LOCATION);
	swapinode(&sfi);

	switch (sfi.sfi_type) {
	    case SFS_TYPE_DIR:
		break;
	    case SFS_TYPE_FILE:
		warnx("Root directory inode is a regular file (fixed)");
		goto fix;
	    default:
		warnx("Root directory inode has invalid type %lu (fixed)",
		      (unsigned long) sfi.sfi_type);
	    fix:
		setbadness(EXIT_RECOV);
		sfi.sfi_type = SFS_TYPE_DIR;
		swapinode(&sfi);
		diskwrite(&sfi, SFS_ROOT_LOCATION);
		break;
	}

	check_dir(SFS_ROOT_LOCATION, SFS_ROOT_LOCATION, "");
}
예제 #2
0
파일: sfsck.c 프로젝트: PhelanHarris/os161
static
void
adjust_filelinks(void)
{
	struct sfs_inode sfi;
	int i;

	for (i=0; i<ninodes; i++) {
		if (inodes[i].linkcount==0) {
			/* directory */
			continue;
		}
		diskread(&sfi, inodes[i].ino);
		swapinode(&sfi);
		assert(sfi.sfi_type == SFS_TYPE_FILE);
		if (sfi.sfi_linkcount != inodes[i].linkcount) {
			warnx("File %lu link count %lu should be %lu (fixed)",
			      (unsigned long) inodes[i].ino,
			      (unsigned long) sfi.sfi_linkcount,
			      (unsigned long) inodes[i].linkcount);
			sfi.sfi_linkcount = inodes[i].linkcount;
			setbadness(EXIT_RECOV);
			swapinode(&sfi);
			diskwrite(&sfi, inodes[i].ino);
		}
		count_files++;
	}
}
예제 #3
0
파일: sfsck.c 프로젝트: PhelanHarris/os161
static
void
dirwrite(const struct sfs_inode *sfi, struct sfs_dir *d, int nd)
{
	const unsigned atonce = SFS_BLOCKSIZE/sizeof(struct sfs_dir);
	unsigned nblocks = SFS_ROUNDUP(nd, atonce) / atonce;
	unsigned i, j, bad;

	for (i=0; i<nblocks; i++) {
		uint32_t block = dobmap(sfi, i);
		if (block!=0) {
			for (j=0; j<atonce; j++) {
				swapdir(&d[i*atonce+j]);
			}
			diskwrite(d + i*atonce, block);
		}
		else {
			for (j=bad=0; j<atonce; j++) {
				if (d[i*atonce+j].sfd_ino != SFS_NOINO ||
				    d[i*atonce+j].sfd_name[0] != 0) {
					bad = 1;
				}
			}
			if (bad) {
				warnx("Cannot write to missing block in "
				      "sparse directory (ERROR)");
				setbadness(EXIT_UNRECOV);
			}
		}
	}
}
예제 #4
0
파일: mksfs.c 프로젝트: Adam-Koza/A3
static
void
writebitmap(uint32_t fsblocks)
{

	uint32_t nbits = SFS_BITMAPSIZE(fsblocks);
	uint32_t nblocks = SFS_BITBLOCKS(fsblocks);
	char *ptr;
	uint32_t i;

	if (nblocks > MAXBITBLOCKS) {
		errx(1, "Filesystem too large "
		     "- increase MAXBITBLOCKS and recompile");
	}

	doallocbit(SFS_SB_LOCATION);
	doallocbit(SFS_ROOT_LOCATION);
	for (i=0; i<nblocks; i++) {
		doallocbit(SFS_MAP_LOCATION+i);
	}
	for (i=fsblocks; i<nbits; i++) {
		doallocbit(i);
	}

	for (i=0; i<nblocks; i++) {
		ptr = bitbuf + i*SFS_BLOCKSIZE;
		diskwrite(ptr, SFS_MAP_LOCATION+i);
	}
}
예제 #5
0
void do_multiboot(const char *filename) {
    uint8_t buf[SECTORSIZE];
    elf_header *elfh = (elf_header *) buf;
    off_t o;

    if ((diskfd = open(filename, O_RDWR)) < 0) {
	fprintf(stderr, "%s: %s\n", filename, strerror(errno));
	usage();
    }

    readsect(buf, 0);

    if (elfh->e_magic != ELF_MAGIC) {
	fprintf(stderr, "%s: not an ELF executable file\n", filename);
	usage();
    }

    o = elfh->e_phoff + sizeof(elf_program) * elfh->e_phnum;
    if (o >= 4096 - sizeof(multiboot_header)) {
	fprintf(stderr, "%s: ELF header too large to accommodate multiboot header\n", filename);
	usage();
    } else if (lseek(diskfd, o, SEEK_SET) != o) {
	perror("lseek");
	usage();
    }

    diskwrite(multiboot_header, sizeof(multiboot_header));
    exit(0);
}
예제 #6
0
파일: buff.c 프로젝트: AustenConrad/plan-9
static
void
flush(Buffer *b)
{
	if(b->cdirty || b->cnc==0){
		if(b->cnc == 0)
			delblock(b, b->cbi);
		else
			diskwrite(disk, &b->bl[b->cbi], b->c, b->cnc);
		b->cdirty = FALSE;
	}
}
예제 #7
0
파일: mksfs.c 프로젝트: Adam-Koza/A3
static
void
writerootdir(void)
{
	struct sfs_inode sfi;

	bzero((void *)&sfi, sizeof(sfi));

	sfi.sfi_size = SWAPL(0);
	sfi.sfi_type = SWAPS(SFS_TYPE_DIR);
	sfi.sfi_linkcount = SWAPS(1);

	diskwrite(&sfi, SFS_ROOT_LOCATION);
}
예제 #8
0
파일: mksfs.c 프로젝트: DianeRay/os161
/*
 * Write out the free block bitmap.
 */
static
void
writefreemap(uint32_t fsblocks)
{
	uint32_t freemapblocks;
	char *ptr;
	uint32_t i;

	/* Write out each of the blocks in the free block bitmap. */
	freemapblocks = SFS_FREEMAPBLOCKS(fsblocks);
	for (i=0; i<freemapblocks; i++) {
		ptr = freemapbuf + i*SFS_BLOCKSIZE;
		diskwrite(ptr, SFS_FREEMAP_START+i);
	}
}
예제 #9
0
파일: mksfs.c 프로젝트: DianeRay/os161
/*
 * Write out the root directory inode.
 */
static
void
writerootdir(void)
{
	struct sfs_dinode sfi;

	/* Initialize the dinode */
	bzero((void *)&sfi, sizeof(sfi));
	sfi.sfi_size = SWAP32(0);
	sfi.sfi_type = SWAP16(SFS_TYPE_DIR);
	sfi.sfi_linkcount = SWAP16(1);

	/* Write it out */
	diskwrite(&sfi, SFS_ROOTDIR_INO);
}
예제 #10
0
파일: sfsck.c 프로젝트: PhelanHarris/os161
static
void
check_sb(void)
{
	struct sfs_super sp;
	uint32_t i;
	int schanged=0;

	diskread(&sp, SFS_SB_LOCATION);
	swapsb(&sp);
	if (sp.sp_magic != SFS_MAGIC) {
		errx(EXIT_UNRECOV, "Not an sfs filesystem");
	}

	assert(nblocks==0);
	assert(bitblocks==0);
	nblocks = sp.sp_nblocks;
	bitblocks = SFS_BITBLOCKS(nblocks);
	assert(nblocks>0);
	assert(bitblocks>0);

	bitmap_init(bitblocks);
	for (i=nblocks; i<bitblocks*SFS_BLOCKBITS; i++) {
		bitmap_mark(i, B_PASTEND, 0);
	}

	if (checknullstring(sp.sp_volname, sizeof(sp.sp_volname))) {
		warnx("Volume name not null-terminated (fixed)");
		setbadness(EXIT_RECOV);
		schanged = 1;
	}
	if (checkbadstring(sp.sp_volname)) {
		warnx("Volume name contains illegal characters (fixed)");
		setbadness(EXIT_RECOV);
		schanged = 1;
	}

	if (schanged) {
		swapsb(&sp);
		diskwrite(&sp, SFS_SB_LOCATION);
	}

	bitmap_mark(SFS_SB_LOCATION, B_SUPERBLOCK, 0);
	for (i=0; i<bitblocks; i++) {
		bitmap_mark(SFS_MAP_LOCATION+i, B_BITBLOCK, i);
	}
}
예제 #11
0
파일: mksfs.c 프로젝트: Adam-Koza/A3
static
void
writesuper(const char *volname, uint32_t nblocks)
{
	struct sfs_super sp;

	bzero((void *)&sp, sizeof(sp));

	if (strlen(volname) >= SFS_VOLNAME_SIZE) {
		errx(1, "Volume name %s too long", volname);
	}

	sp.sp_magic = SWAPL(SFS_MAGIC);
	sp.sp_nblocks = SWAPL(nblocks);
	strcpy(sp.sp_volname, volname);

	diskwrite(&sp, SFS_SB_LOCATION);
}
예제 #12
0
파일: mksfs.c 프로젝트: DianeRay/os161
/*
 * Initialize and write out the superblock.
 */
static
void
writesuper(const char *volname, uint32_t nblocks)
{
	struct sfs_superblock sb;

	/* The cast is required on some outdated host systems. */
	bzero((void *)&sb, sizeof(sb));

	if (strlen(volname) >= SFS_VOLNAME_SIZE) {
		errx(1, "Volume name %s too long", volname);
	}

	/* Initialize the superblock structure */
	sb.sb_magic = SWAP32(SFS_MAGIC);
	sb.sb_nblocks = SWAP32(nblocks);
	strcpy(sb.sb_volname, volname);

	/* and write it out. */
	diskwrite(&sb, SFS_SUPER_BLOCK);
}
예제 #13
0
파일: sfsck.c 프로젝트: PhelanHarris/os161
static
void
check_bitmap(void)
{
	uint8_t bits[SFS_BLOCKSIZE], *found, *tofree, tmp;
	uint32_t alloccount=0, freecount=0, i, j;
	int bchanged;

	for (i=0; i<bitblocks; i++) {
		diskread(bits, SFS_MAP_LOCATION+i);
		swapbits(bits);
		found = bitmapdata + i*SFS_BLOCKSIZE;
		tofree = tofreedata + i*SFS_BLOCKSIZE;
		bchanged = 0;

		for (j=0; j<SFS_BLOCKSIZE; j++) {
			/* we shouldn't have blocks marked both ways */
			assert((found[j] & tofree[j])==0);

			if (bits[j]==found[j]) {
				continue;
			}

			if (bits[j]==(found[j] | tofree[j])) {
				bits[j] = found[j];
				bchanged = 1;
				continue;
			}

			/* free the ones we're freeing */
			bits[j] &= ~tofree[j];

			/* are we short any? */
			if ((bits[j] & found[j]) != found[j]) {
				tmp = found[j] & ~bits[j];
				alloccount += countbits(tmp);
				if (tmp != 0) {
					reportbits(i, j, tmp, "free");
				}
			}

			/* do we have any extra? */
			if ((bits[j] & found[j]) != bits[j]) {
				tmp = bits[j] & ~found[j];
				freecount += countbits(tmp);
				if (tmp != 0) {
					reportbits(i, j, tmp, "allocated");
				}
			}

			bits[j] = found[j];
			bchanged = 1;
		}

		if (bchanged) {
			swapbits(bits);
			diskwrite(bits, SFS_MAP_LOCATION+i);
		}
	}

	if (alloccount > 0) {
		warnx("%lu blocks erroneously shown free in bitmap (fixed)",
		      (unsigned long) alloccount);
		setbadness(EXIT_RECOV);
	}
	if (freecount > 0) {
		warnx("%lu blocks erroneously shown used in bitmap (fixed)",
		      (unsigned long) freecount);
		setbadness(EXIT_RECOV);
	}
}
예제 #14
0
파일: sfsck.c 프로젝트: PhelanHarris/os161
static
int
check_dir(uint32_t ino, uint32_t parentino, const char *pathsofar)
{
	struct sfs_inode sfi;
	struct sfs_dir *direntries;
	int *sortvector;
	uint32_t dirsize, ndirentries, maxdirentries, subdircount, i;
	int ichanged=0, dchanged=0, dotseen=0, dotdotseen=0;

	diskread(&sfi, ino);
	swapinode(&sfi);

	if (remember_dir(ino, pathsofar)) {
		/* crosslinked dir */
		return 1;
	}

	bitmap_mark(ino, B_INODE, ino);
	count_dirs++;

	if (sfi.sfi_size % sizeof(struct sfs_dir) != 0) {
		setbadness(EXIT_RECOV);
		warnx("Directory /%s has illegal size %lu (fixed)",
		      pathsofar, (unsigned long) sfi.sfi_size);
		sfi.sfi_size = SFS_ROUNDUP(sfi.sfi_size,
					   sizeof(struct sfs_dir));
		ichanged = 1;
	}

	if (check_inode_blocks(ino, &sfi, 1)) {
		ichanged = 1;
	}

	ndirentries = sfi.sfi_size/sizeof(struct sfs_dir);
	maxdirentries = SFS_ROUNDUP(ndirentries,
				    SFS_BLOCKSIZE/sizeof(struct sfs_dir));
	dirsize = maxdirentries * sizeof(struct sfs_dir);
	direntries = domalloc(dirsize);
	sortvector = domalloc(ndirentries * sizeof(int));

	dirread(&sfi, direntries, ndirentries);
	for (i=ndirentries; i<maxdirentries; i++) {
		direntries[i].sfd_ino = SFS_NOINO;
		bzero(direntries[i].sfd_name, sizeof(direntries[i].sfd_name));
	}

	for (i=0; i<ndirentries; i++) {
		if (check_dir_entry(pathsofar, i, &direntries[i])) {
			dchanged = 1;
		}
		sortvector[i] = i;
	}

	sortdir(sortvector, direntries, ndirentries);

	/* don't use ndirentries-1 here in case ndirentries == 0 */
	for (i=0; i+1<ndirentries; i++) {
		struct sfs_dir *d1 = &direntries[sortvector[i]];
		struct sfs_dir *d2 = &direntries[sortvector[i+1]];
		assert(d1 != d2);

		if (d1->sfd_ino == SFS_NOINO) {
			continue;
		}

		if (!strcmp(d1->sfd_name, d2->sfd_name)) {
			if (d1->sfd_ino == d2->sfd_ino) {
				setbadness(EXIT_RECOV);
				warnx("Directory /%s: Duplicate entries for "
				      "%s (merged)",
				      pathsofar, d1->sfd_name);
				d1->sfd_ino = SFS_NOINO;
				d1->sfd_name[0] = 0;
			}
			else {
				snprintf(d1->sfd_name, sizeof(d1->sfd_name),
					 "FSCK.%lu.%lu",
					 (unsigned long) d1->sfd_ino,
					 (unsigned long) uniquecounter++);
				setbadness(EXIT_RECOV);
				warnx("Directory /%s: Duplicate names %s "
				      "(one renamed: %s)",
				      pathsofar, d2->sfd_name, d1->sfd_name);
			}
			dchanged = 1;
		}
	}

	for (i=0; i<ndirentries; i++) {
		if (!strcmp(direntries[i].sfd_name, ".")) {
			if (direntries[i].sfd_ino != ino) {
				setbadness(EXIT_RECOV);
				warnx("Directory /%s: Incorrect `.' entry "
				      "(fixed)", pathsofar);
				direntries[i].sfd_ino = ino;
				dchanged = 1;
			}
			assert(dotseen==0); /* due to duplicate checking */
			dotseen = 1;
		}
		else if (!strcmp(direntries[i].sfd_name, "..")) {
			if (direntries[i].sfd_ino != parentino) {
				setbadness(EXIT_RECOV);
				warnx("Directory /%s: Incorrect `..' entry "
				      "(fixed)", pathsofar);
				direntries[i].sfd_ino = parentino;
				dchanged = 1;
			}
			assert(dotdotseen==0); /* due to duplicate checking */
			dotdotseen = 1;
		}
	}

	if (!dotseen) {
		if (dir_tryadd(direntries, ndirentries, ".", ino)==0) {
			setbadness(EXIT_RECOV);
			warnx("Directory /%s: No `.' entry (added)",
			      pathsofar);
			dchanged = 1;
		}
		else if (dir_tryadd(direntries, maxdirentries, ".", ino)==0) {
			setbadness(EXIT_RECOV);
			warnx("Directory /%s: No `.' entry (added)",
			      pathsofar);
			ndirentries++;
			dchanged = 1;
			sfi.sfi_size += sizeof(struct sfs_dir);
			ichanged = 1;
		}
		else {
			setbadness(EXIT_UNRECOV);
			warnx("Directory /%s: No `.' entry (NOT FIXED)",
			      pathsofar);
		}
	}

	if (!dotdotseen) {
		if (dir_tryadd(direntries, ndirentries, "..", parentino)==0) {
			setbadness(EXIT_RECOV);
			warnx("Directory /%s: No `..' entry (added)",
			      pathsofar);
			dchanged = 1;
		}
		else if (dir_tryadd(direntries, maxdirentries, "..",
				    parentino)==0) {
			setbadness(EXIT_RECOV);
			warnx("Directory /%s: No `..' entry (added)",
			      pathsofar);
			ndirentries++;
			dchanged = 1;
			sfi.sfi_size += sizeof(struct sfs_dir);
			ichanged = 1;
		}
		else {
			setbadness(EXIT_UNRECOV);
			warnx("Directory /%s: No `..' entry (NOT FIXED)",
			      pathsofar);
		}
	}

	subdircount=0;
	for (i=0; i<ndirentries; i++) {
		if (!strcmp(direntries[i].sfd_name, ".")) {
			/* nothing */
		}
		else if (!strcmp(direntries[i].sfd_name, "..")) {
			/* nothing */
		}
		else if (direntries[i].sfd_ino == SFS_NOINO) {
			/* nothing */
		}
		else {
			char path[strlen(pathsofar)+SFS_NAMELEN+1];
			struct sfs_inode subsfi;

			diskread(&subsfi, direntries[i].sfd_ino);
			swapinode(&subsfi);
			snprintf(path, sizeof(path), "%s/%s",
				 pathsofar, direntries[i].sfd_name);

			switch (subsfi.sfi_type) {
			    case SFS_TYPE_FILE:
				if (check_inode_blocks(direntries[i].sfd_ino,
						       &subsfi, 0)) {
					swapinode(&subsfi);
					diskwrite(&subsfi,
						  direntries[i].sfd_ino);
				}
				observe_filelink(direntries[i].sfd_ino);
				break;
			    case SFS_TYPE_DIR:
				if (check_dir(direntries[i].sfd_ino,
					      ino,
					      path)) {
					setbadness(EXIT_RECOV);
					warnx("Directory /%s: Crosslink to "
					      "other directory (removed)",
					      path);
					direntries[i].sfd_ino = SFS_NOINO;
					direntries[i].sfd_name[0] = 0;
					dchanged = 1;
				}
				else {
					subdircount++;
				}
				break;
			    default:
				setbadness(EXIT_RECOV);
				warnx("Object /%s: Invalid inode type "
				      "(removed)", path);
				direntries[i].sfd_ino = SFS_NOINO;
				direntries[i].sfd_name[0] = 0;
				dchanged = 1;
				break;
			}
		}
	}

	if (sfi.sfi_linkcount != subdircount+2) {
		setbadness(EXIT_RECOV);
		warnx("Directory /%s: Link count %lu should be %lu (fixed)",
		      pathsofar, (unsigned long) sfi.sfi_linkcount,
		      (unsigned long) subdircount+2);
		sfi.sfi_linkcount = subdircount+2;
		ichanged = 1;
	}

	if (dchanged) {
		dirwrite(&sfi, direntries, ndirentries);
	}

	if (ichanged) {
		swapinode(&sfi);
		diskwrite(&sfi, ino);
	}

	free(direntries);
	free(sortvector);

	return 0;
}
예제 #15
0
파일: sfsck.c 프로젝트: PhelanHarris/os161
static
void
check_indirect_block(uint32_t ino, uint32_t *ientry, uint32_t *blockp,
		     uint32_t nblocks, uint32_t *badcountp,
		     int isdir, int indirection)
{
	uint32_t entries[SFS_DBPERIDB];
	uint32_t i, ct;

	if (*ientry !=0) {
		diskread(entries, *ientry);
		swapindir(entries);
		bitmap_mark(*ientry, B_IBLOCK, ino);
	}
	else {
		for (i=0; i<SFS_DBPERIDB; i++) {
			entries[i] = 0;
		}
	}

	if (indirection > 1) {
		for (i=0; i<SFS_DBPERIDB; i++) {
			check_indirect_block(ino, &entries[i],
					     blockp, nblocks,
					     badcountp,
					     isdir,
					     indirection-1);
		}
	}
	else {
		assert(indirection==1);

		for (i=0; i<SFS_DBPERIDB; i++) {
			if (*blockp < nblocks) {
				if (entries[i] != 0) {
					bitmap_mark(entries[i],
						    isdir ? B_DIRDATA : B_DATA,
						    ino);
				}
			}
			else {
				if (entries[i] != 0) {
					(*badcountp)++;
					bitmap_mark(entries[i],
						    isdir ? B_DIRDATA : B_DATA,
						    ino);
					entries[i] = 0;
				}
			}
			(*blockp)++;
		}
	}

	ct=0;
	for (i=ct=0; i<SFS_DBPERIDB; i++) {
		if (entries[i]!=0) ct++;
	}
	if (ct==0) {
		if (*ientry != 0) {
			(*badcountp)++;
			bitmap_mark(*ientry, B_TOFREE, 0);
			*ientry = 0;
		}
	}
	else {
		assert(*ientry != 0);
		if (*badcountp > 0) {
			swapindir(entries);
			diskwrite(entries, *ientry);
		}
	}
}
예제 #16
0
int main(int argc, char *argv[]) {
    char buf[4096];
    char zerobuf[512];
    FILE *f;
    size_t n;
    size_t nsectors;
    int i;
    int bootsector_special = 1;

#if defined(_MSDOS) || defined(_WIN32)
    // As our output file is binary, we must set its file mode to binary.
    diskfd = _fileno(stdout);
    _setmode(diskfd, _O_BINARY);
#else
    diskfd = fileno(stdout);
#endif

    // Check for a partition
    if (argc >= 2 && strcmp(argv[1], "-p") == 0) {
	if (argc < 3)
	    usage();
	if ((diskfd = open(argv[2], O_RDWR)) < 0) {
	    fprintf(stderr, "%s: %s\n", argv[2], strerror(errno));
	    usage();
	}
	if (find_partition(0, 0, 0) <= 0) {
	    fprintf(stderr, "%s: no JOS partition (type 0x27) found!\n", argv[2]);
	    usage();
	}
	argc -= 2;
	argv += 2;
	bootsector_special = 0;
    }

    // Check for multiboot option
    if (argc >= 2 && strcmp(argv[1], "-m") == 0) {
	if (argc < 3)
	    usage();
	do_multiboot(argv[2]);
    }

    // Read files
    if (argc < 2)
	usage();

    // Read boot sector
    if (bootsector_special) {
	f = fopencheck(argv[1]);
	n = fread(buf, 1, 4096, f);
	if (n > 510) {
	    fprintf(stderr, "%s: boot block too large: %s%u bytes (max 510)\n", argv[1], (n == 4096 ? ">= " : ""), (unsigned) n);
	    usage();
	}
	fclose(f);

	// Append signature and write modified boot sector
	memset(buf + n, 0, 510 - n);
	buf[510] = 0x55;
	buf[511] = 0xAA;
	diskwrite(buf, 512);
	nsectors = 1;

	argc--;
	argv++;
    } else
	nsectors = 0;

    // Read any succeeding files, then write them out
    memset(zerobuf, 0, 512);
    for (i = 1; i < argc; i++) {
	size_t pos;
	char *str;
	unsigned long skipto_sector;

	// An argument like "@X" means "skip to sector X".
	if (argv[i][0] == '@' && isdigit(argv[i][1])
	    && ((skipto_sector = strtoul(argv[i] + 1, &str, 0)), *str == 0)) {
	    if (nsectors > skipto_sector) {
		fprintf(stderr, "mkbootdisk: can't skip to sector %u, already at sector %u\n", (unsigned) skipto_sector, (unsigned) nsectors);
		usage();
	    }
	    while (nsectors < skipto_sector) {
		diskwrite(zerobuf, 512);
		nsectors++;
	    }
	    continue;
	}

	// Otherwise, read the file.
	f = fopencheck(argv[i]);
	pos = 0;
	while ((n = fread(buf, 1, 4096, f)) > 0) {
	    diskwrite(buf, n);
	    pos += n;
	}
	if (pos % 512 != 0) {
	    diskwrite(zerobuf, 512 - (pos % 512));
	    pos += 512 - (pos % 512);
	}
	nsectors += pos / 512;
	fclose(f);
    }

    // Fill out to 1024 sectors with 0 blocks
    while (nsectors < 1024) {
	diskwrite(zerobuf, 512);
	nsectors++;
    }

    return 0;
}
예제 #17
0
파일: buff.c 프로젝트: AustenConrad/plan-9
void
bufinsert(Buffer *b, uint q0, Rune *s, uint n)
{
	uint i, m, t, off;

	if(q0 > b->nc)
		panic("internal error: bufinsert");

	while(n > 0){
		setcache(b, q0);
		off = q0-b->cq;
		if(b->cnc+n <= Maxblock){
			/* Everything fits in one block. */
			t = b->cnc+n;
			m = n;
			if(b->bl == nil){	/* allocate */
				if(b->cnc != 0)
					panic("internal error: bufinsert1 cnc!=0");
				addblock(b, 0, t);
				b->cbi = 0;
			}
			sizecache(b, t);
			runemove(b->c+off+m, b->c+off, b->cnc-off);
			runemove(b->c+off, s, m);
			b->cnc = t;
			goto Tail;
		}
		/*
		 * We must make a new block.  If q0 is at
		 * the very beginning or end of this block,
		 * just make a new block and fill it.
		 */
		if(q0==b->cq || q0==b->cq+b->cnc){
			if(b->cdirty)
				flush(b);
			m = min(n, Maxblock);
			if(b->bl == nil){	/* allocate */
				if(b->cnc != 0)
					panic("internal error: bufinsert2 cnc!=0");
				i = 0;
			}else{
				i = b->cbi;
				if(q0 > b->cq)
					i++;
			}
			addblock(b, i, m);
			sizecache(b, m);
			runemove(b->c, s, m);
			b->cq = q0;
			b->cbi = i;
			b->cnc = m;
			goto Tail;
		}
		/*
		 * Split the block; cut off the right side and
		 * let go of it.
		 */
		m = b->cnc-off;
		if(m > 0){
			i = b->cbi+1;
			addblock(b, i, m);
			diskwrite(disk, &b->bl[i], b->c+off, m);
			b->cnc -= m;
		}
		/*
		 * Now at end of block.  Take as much input
		 * as possible and tack it on end of block.
		 */
		m = min(n, Maxblock-b->cnc);
		sizecache(b, b->cnc+m);
		runemove(b->c+b->cnc, s, m);
		b->cnc += m;
  Tail:
		b->nc += m;
		q0 += m;
		s += m;
		n -= m;
		b->cdirty = TRUE;
	}
}