예제 #1
0
/* Modify atom refcount */
static int atomref(struct inode *atable, atom_t atom, int use)
{
	if(DEBUG_MODE_K==1)
	{
		printf("\t\t\t\t%25s[K]  %25s  %4d  #in\n",__FILE__,__func__,__LINE__);
	}
	struct sb *sb = tux_sb(atable->i_sb);
	unsigned shift = sb->blockbits - ATOMREF_BLKBITS;
	unsigned block = sb->atomref_base + ATOMREF_SIZE * (atom >> shift);
	unsigned offset = atom & ~(-1 << shift), kill = 0;
	struct buffer_head *buffer;
	__be16 *refcount;
	int err;

	buffer = blockread(mapping(atable), block);
	if (!buffer)
		return -EIO;

	refcount = bufdata(buffer);
	int low = be16_to_cpu(refcount[offset]) + use;
	trace("inc atom %x by %d, offset %x[%x], low = %d",
	      atom, use, block, offset, low);

	/* This releases buffer */
	err = update_refcount(sb, buffer, offset, low);
	if (err)
		return err;

	if (!low || (low & (-1 << 16))) {
		buffer = blockread(mapping(atable), block + 1);
		if (!buffer)
			return -EIO;

		refcount = bufdata(buffer);
		int high = be16_to_cpu(refcount[offset]);
		if (!low)
			blockput(buffer);
		else {
			trace("carry %d, offset %x[%x], high = %d",
			      (low >> 16), block, offset, high);
			high += (low >> 16);
			assert(high >= 0); /* paranoia check */

			/* This releases buffer */
			err = update_refcount(sb, buffer, offset, high);
			if (err) {
				/* FIXME: better set a flag that atomref broke
				 * or something! */
				return err;
			}
		}

		kill = !(low | high);
	}
예제 #2
0
파일: dir.c 프로젝트: Zkin/tux3
tux_dirent *tux_find_entry(struct inode *dir, const char *name, unsigned len,
			   struct buffer_head **result, loff_t size)
{
	struct sb *sb = tux_sb(dir->i_sb);
	unsigned reclen = TUX_REC_LEN(len);
	block_t block, blocks = size >> sb->blockbits;
	int err = -ENOENT;

	for (block = 0; block < blocks; block++) {
		struct buffer_head *buffer = blockread(mapping(dir), block);
		if (!buffer) {
			err = -EIO; // need ERR_PTR for blockread!!!
			goto error;
		}
		tux_dirent *entry = bufdata(buffer);
		tux_dirent *limit = (void *)entry + sb->blocksize - reclen;
		while (entry <= limit) {
			if (entry->rec_len == 0) {
				blockput(buffer);
				tux_zero_len_error(dir, block);
				err = -EIO;
				goto error;
			}
			if (tux_match(entry, name, len)) {
				*result = buffer;
				return entry;
			}
			entry = next_entry(entry);
		}
		blockput(buffer);
	}
error:
	*result = NULL;		/* for debug */
	return ERR_PTR(err);
}
예제 #3
0
파일: dir.c 프로젝트: Zkin/tux3
int tux_readdir(struct file *file, void *state, filldir_t filldir)
{
	loff_t pos = file->f_pos;
#ifdef __KERNEL__
	struct inode *dir = file->f_dentry->d_inode;
#else
	struct inode *dir = file->f_inode;
#endif
	int revalidate = file->f_version != dir->i_version;
	struct sb *sb = tux_sb(dir->i_sb);
	unsigned blockbits = sb->blockbits;
	block_t block, blocks = dir->i_size >> blockbits;
	unsigned offset = pos & sb->blockmask;

	assert(!(dir->i_size & sb->blockmask));

	for (block = pos >> blockbits ; block < blocks; block++) {
		struct buffer_head *buffer = blockread(mapping(dir), block);
		if (!buffer)
			return -EIO;
		void *base = bufdata(buffer);
		if (revalidate) {
			if (offset) {
				tux_dirent *entry = base + offset;
				tux_dirent *p = base + (offset & sb->blockmask);
				while (p < entry && p->rec_len)
					p = next_entry(p);
				offset = (void *)p - base;
				file->f_pos = (block << blockbits) + offset;
			}
			file->f_version = dir->i_version;
			revalidate = 0;
		}
		tux_dirent *limit = base + sb->blocksize - TUX_REC_LEN(1);
		for (tux_dirent *entry = base + offset; entry <= limit; entry = next_entry(entry)) {
			if (entry->rec_len == 0) {
				blockput(buffer);
				tux_zero_len_error(dir, block);
				return -EIO;
			}
			if (!is_deleted(entry)) {
				unsigned type = (entry->type < TUX_TYPES) ? filetype[entry->type] : DT_UNKNOWN;
				int lame = filldir(
					state, entry->name, entry->name_len,
					(block << blockbits) | ((void *)entry - base),
					be64_to_cpu(entry->inum), type);
				if (lame) {
					blockput(buffer);
					return 0;
				}
			}
			file->f_pos += tux_rec_len_from_disk(entry->rec_len);
		}
		blockput(buffer);
		offset = 0;
	}
	return 0;
}
예제 #4
0
int reader::mount()
{
	int i,ofs;

	if (!tmpsect) return 0;
	if (!blockread(0,1,tmpsect)) return 0;
	if (llei16(tmpsect+510) != 0xAA55) return 0;

	/* NEC MS-DOS 3.30 8-partition support */
	/* see http://www.geocities.com/thestarman3/asm/mbr/DOS33MBR.htm for details */
	if (llei16(tmpsect+0x17C) == 0xA55A) {
		entries = 8;
		ofs = 0x17E;
	}
	else {
		entries = 4;
		ofs = 0x1BE;
	}

	for (i=0;i < entries && i < MAX_ENTRIES;i++) {
		entry[i].flags =			 tmpsect[ofs+0x0];
		entry[i].start_head =			 tmpsect[ofs+0x1];
		entry[i].start_sector =			 tmpsect[ofs+0x2] & 0x3F;
		entry[i].start_cylinder =		 tmpsect[ofs+0x3] | ((tmpsect[ofs+0x2] & 0xC0) << 2);
		entry[i].system_id =			 tmpsect[ofs+0x4];
		entry[i].end_head =			 tmpsect[ofs+0x5];
		entry[i].end_sector =			 tmpsect[ofs+0x6] & 0x3F;
		entry[i].end_cylinder =			 tmpsect[ofs+0x7] | ((tmpsect[ofs+0x6] & 0xC0) << 2);
		entry[i].start =			 llei32(tmpsect+ofs+0x8);
		entry[i].size =				 llei32(tmpsect+ofs+0xC);
		entry[i].parent_ent =			-1;
		entry[i].partition_sector =		 0;
		entry[i].partition_sector_offset =	 ofs;
		ofs += 16;
	}

	/* look for extended DOS partitions */
	for (i=0;i < entries && i < MAX_ENTRIES;i++) {
		// TODO
	}

	return 1;
}
예제 #5
0
파일: dir.c 프로젝트: Zkin/tux3
int tux_dir_is_empty(struct inode *dir)
{
	struct sb *sb = tux_sb(dir->i_sb);
	block_t block, blocks = dir->i_size >> sb->blockbits;
	__be64 self = cpu_to_be64(tux_inode(dir)->inum);
	struct buffer_head *buffer;

	for (block = 0; block < blocks; block++) {
		buffer = blockread(mapping(dir), block);
		if (!buffer)
			return -EIO;

		tux_dirent *entry = bufdata(buffer);
		tux_dirent *limit = bufdata(buffer) + sb->blocksize - TUX_REC_LEN(1);
		for (; entry <= limit; entry = next_entry(entry)) {
			if (!entry->rec_len) {
				blockput(buffer);
				tux_zero_len_error(dir, block);
				return -EIO;
			}
			if (is_deleted(entry))
				continue;
			if (entry->name[0] != '.')
				goto not_empty;
			if (entry->name_len > 2)
				goto not_empty;
			if (entry->name_len < 2) {
				if (entry->inum != self)
					goto not_empty;
			} else if (entry->name[1] != '.')
				goto not_empty;
		}
		blockput(buffer);
	}
	return 0;
not_empty:
	blockput(buffer);
	return -ENOTEMPTY;
}
예제 #6
0
파일: dir.c 프로젝트: Zkin/tux3
loff_t tux_create_entry(struct inode *dir, const char *name, unsigned len,
			inum_t inum, umode_t mode, loff_t *size)
{
	unsigned delta = tux3_get_current_delta();
	struct sb *sb = tux_sb(dir->i_sb);
	tux_dirent *entry;
	struct buffer_head *buffer, *clone;
	unsigned reclen = TUX_REC_LEN(len), rec_len, name_len, offset;
	unsigned blocksize = sb->blocksize;
	block_t block, blocks = *size >> sb->blockbits;
	void *olddata;

	for (block = 0; block < blocks; block++) {
		buffer = blockread(mapping(dir), block);
		if (!buffer)
			return -EIO;
		entry = bufdata(buffer);
		tux_dirent *limit = bufdata(buffer) + blocksize - reclen;
		while (entry <= limit) {
			if (entry->rec_len == 0) {
				blockput(buffer);
				tux_zero_len_error(dir, block);
				return -EIO;
			}
			name_len = TUX_REC_LEN(entry->name_len);
			rec_len = tux_rec_len_from_disk(entry->rec_len);
			if (is_deleted(entry) && rec_len >= reclen)
				goto create;
			if (rec_len >= name_len + reclen)
				goto create;
			entry = (void *)entry + rec_len;
		}
		blockput(buffer);
	}
	entry = NULL;
	buffer = blockget(mapping(dir), block);
	assert(!buffer_dirty(buffer));

create:
	/*
	 * The directory is protected by i_mutex.
	 * blockdirty() should never return -EAGAIN.
	 */
	olddata = bufdata(buffer);
	clone = blockdirty(buffer, delta);
	if (IS_ERR(clone)) {
		assert(PTR_ERR(clone) != -EAGAIN);
		blockput(buffer);
		return PTR_ERR(clone);
	}
	if (!entry) {
		/* Expanding the directory size. Initialize block. */
		entry = bufdata(clone);
		memset(entry, 0, blocksize);
		entry->rec_len = tux_rec_len_to_disk(blocksize);
		assert(is_deleted(entry));

		*size += blocksize;
	} else {
		entry = ptr_redirect(entry, olddata, bufdata(clone));

		if (!is_deleted(entry)) {
			tux_dirent *newent = (void *)entry + name_len;
			unsigned rest_rec_len = rec_len - name_len;
			newent->rec_len = tux_rec_len_to_disk(rest_rec_len);
			entry->rec_len = tux_rec_len_to_disk(name_len);
			entry = newent;
		}
	}

	entry->name_len = len;
	memcpy(entry->name, name, len);
	offset = (void *)entry - bufdata(clone);
	/* this releases buffer */
	tux_update_entry(clone, entry, inum, mode);

	return (block << sb->blockbits) + offset; /* only for xattr create */
}
예제 #7
0
파일: mkext.c 프로젝트: aahud/harvey
void
main(int argc, char **argv)
{
	char *rargv[10];
	int rargc;
	char *fields[NFLDS], name[2*LEN], *p, *namep;
	char uid[NAMELEN], gid[NAMELEN];
	ulong mode, bytes, mtime;
	char *file;
	int i, n, stdin, fd, chatty;
	char blk[512];

	if(argc>1 && strcmp(argv[1], "RAMFS") == 0){
		argv[1] = argv[0];
		ramfsmain(argc-1, argv+1);
		exits(nil);
	}
	if(argc>1 && strcmp(argv[1], "BUNZIP") == 0){
		_unbzip(0, 1);
		exits(nil);
	}

	rfork(RFNOTEG);
	stdin = 0;
	file = nil;
	namep = name;
	mtpt = "/root";
	chatty = 0;
	ARGBEGIN{
	case 'd':
		chatty = !chatty;
		break;
	case 'f':
		file = ARGF();
		break;
	case 's':
		stdin++;
		break;
	case 'm':
		mtpt = ARGF();
		break;
	default:
		usage();
	}ARGEND

	if(argc != 0)
		usage();

	if(file == nil) {
		fprint(2, "must specify -f file\n");
		usage();
	}

	if((fd = open(file, OREAD)) < 0) {
		fprint(2, "cannot open \"%s\": %r\n", file);
		exits("open");
	}

	rargv[0] = "ramfs";
	rargc = 1;
	if(stdin)
		rargv[rargc++] = "-i";
	rargv[rargc++] = "-m";
	rargv[rargc++] = mtpt;
	rargv[rargc] = nil;
	ramfsmain(rargc, rargv);

	if(1 || strstr(file, "disk")) {	/* search for archive on block boundary */
if(chatty) fprint(2, "searching for bz\n");
		for(i=0;; i++){
			if((n = readn(fd, blk, sizeof blk)) != sizeof blk)
				sysfatal("read %d gets %d: %r\n", i, n);
			if(strncmp(blk, "bzfilesystem\n", 13) == 0)
				break;
		}
if(chatty) fprint(2, "found at %d\n", i);
	}

	if(chdir(mtpt) < 0)
		error("chdir %s: %r", mtpt);

	fd = unbflz(unbzip(blockread(fd, blk+13, sizeof(blk)-13)));

	Binits(&bin, fd, OREAD, binbuf, sizeof binbuf);
	while(p = Brdline(&bin, '\n')){
		p[Blinelen(&bin)-1] = '\0';
if(chatty) fprint(2, "%s\n", p);
		if(strcmp(p, "end of archive") == 0){
			_exits(0);
		}
		if(getfields(p, fields, NFLDS, 0, " \t") != NFLDS){
			warn("too few fields in file header");
			continue;
		}
		strcpy(namep, fields[0]);
		mode = strtoul(fields[1], 0, 8);
		mtime = strtoul(fields[4], 0, 10);
		bytes = strtoul(fields[5], 0, 10);
		strncpy(uid, fields[2], NAMELEN);
		strncpy(gid, fields[3], NAMELEN);
		if(mode & DMDIR)
			mkdir(name, mode, mtime, uid, gid);
		else
			extract(name, mode, mtime, uid, gid, bytes);
	}
	fprint(2, "premature end of archive\n");
	exits("premature end of archive");
}