Example #1
0
static int
romfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
{
	struct inode *i = filp->f_path.dentry->d_inode;
	struct romfs_inode ri;
	unsigned long offset, maxoff;
	int j, ino, nextfh;
	int stored = 0;
	char fsname[ROMFS_MAXFN];	/* XXX dynamic? */

	lock_kernel();

	maxoff = romfs_maxsize(i->i_sb);

	offset = filp->f_pos;
	if (!offset) {
		offset = i->i_ino & ROMFH_MASK;
		if (romfs_copyfrom(i, &ri, offset, ROMFH_SIZE) <= 0)
			goto out;
		offset = be32_to_cpu(ri.spec) & ROMFH_MASK;
	}

	/* Not really failsafe, but we are read-only... */
	for(;;) {
		if (!offset || offset >= maxoff) {
			offset = maxoff;
			filp->f_pos = offset;
			goto out;
		}
		filp->f_pos = offset;

		/* Fetch inode info */
		if (romfs_copyfrom(i, &ri, offset, ROMFH_SIZE) <= 0)
			goto out;

		j = romfs_strnlen(i, offset+ROMFH_SIZE, sizeof(fsname)-1);
		if (j < 0)
			goto out;

		fsname[j]=0;
		romfs_copyfrom(i, fsname, offset+ROMFH_SIZE, j);

		ino = offset;
		nextfh = be32_to_cpu(ri.next);
		if ((nextfh & ROMFH_TYPE) == ROMFH_HRD)
			ino = be32_to_cpu(ri.spec);
		if (filldir(dirent, fsname, j, offset, ino,
			    romfs_dtype_table[nextfh & ROMFH_TYPE]) < 0) {
			goto out;
		}
		stored++;
		offset = nextfh & ROMFH_MASK;
	}
out:
	unlock_kernel();
	return stored;
}
Example #2
0
static int
romfs_readpage(struct file *file, struct page * page)
{
	struct inode *inode = page->mapping->host;
	loff_t offset, avail, readlen;
	void *buf;
	int result = -EIO;

	page_cache_get(page);
	lock_kernel();
	buf = kmap(page);
	if (!buf)
		goto err_out;

	/* 32 bit warning -- but not for us :) */
	offset = page_offset(page);
	if (offset < i_size_read(inode)) {
		avail = inode->i_size-offset;
		readlen = min_t(unsigned long, avail, PAGE_SIZE);
		if (romfs_copyfrom(inode, buf, ROMFS_I(inode)->i_dataoffset+offset, readlen) == readlen) {
			if (readlen < PAGE_SIZE) {
				memset(buf + readlen,0,PAGE_SIZE-readlen);
			}
			SetPageUptodate(page);
			result = 0;
		}
	}
Example #3
0
static struct dentry *
romfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
{
	unsigned long offset, maxoff;
	long res;
	int fslen;
	struct inode *inode = NULL;
	char fsname[ROMFS_MAXFN];	/* XXX dynamic? */
	struct romfs_inode ri;
	const char *name;		/* got from dentry */
	int len;

	res = -EACCES;			/* placeholder for "no data here" */
	offset = dir->i_ino & ROMFH_MASK;
	lock_kernel();
	if (romfs_copyfrom(dir, &ri, offset, ROMFH_SIZE) <= 0)
		goto error;

	maxoff = romfs_maxsize(dir->i_sb);
	offset = be32_to_cpu(ri.spec) & ROMFH_MASK;

	/* OK, now find the file whose name is in "dentry" in the
	 * directory specified by "dir".  */

	name = dentry->d_name.name;
	len = dentry->d_name.len;

	for(;;) {
		if (!offset || offset >= maxoff)
			goto success; /* negative success */
		if (romfs_copyfrom(dir, &ri, offset, ROMFH_SIZE) <= 0)
			goto error;

		/* try to match the first 16 bytes of name */
		fslen = romfs_strnlen(dir, offset+ROMFH_SIZE, ROMFH_SIZE);
		if (len < ROMFH_SIZE) {
			if (len == fslen) {
				/* both are shorter, and same size */
				romfs_copyfrom(dir, fsname, offset+ROMFH_SIZE, len+1);
				if (strncmp (name, fsname, len) == 0)
					break;
			}
		} else if (fslen >= ROMFH_SIZE) {
			/* both are longer; XXX optimize max size */
			fslen = romfs_strnlen(dir, offset+ROMFH_SIZE, sizeof(fsname)-1);
			if (len == fslen) {
				romfs_copyfrom(dir, fsname, offset+ROMFH_SIZE, len+1);
				if (strncmp(name, fsname, len) == 0)
					break;
			}
		}
		/* next entry */
		offset = be32_to_cpu(ri.next) & ROMFH_MASK;
	}

	/* Hard link handling */
	if ((be32_to_cpu(ri.next) & ROMFH_TYPE) == ROMFH_HRD)
		offset = be32_to_cpu(ri.spec) & ROMFH_MASK;

	inode = romfs_iget(dir->i_sb, offset);
	if (IS_ERR(inode)) {
		res = PTR_ERR(inode);
		goto error;
	}

success:
	d_add(dentry, inode);
	res = 0;
error:
	unlock_kernel();
	return ERR_PTR(res);
}
Example #4
0
static struct dentry *
romfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
{
	unsigned long offset, maxoff;
	int fslen, res;
	struct inode *inode;
	char fsname[ROMFS_MAXFN];	/* XXX dynamic? */
	struct romfs_inode ri;
	const char *name;		/* got from dentry */
	int len;

	res = -EACCES;			/* placeholder for "no data here" */
	offset = dir->i_ino & ROMFH_MASK;
	lock_kernel();
	if (romfs_copyfrom(dir, &ri, offset, ROMFH_SIZE) <= 0)
		goto out;

	maxoff = romfs_maxsize(dir->i_sb);
	offset = be32_to_cpu(ri.spec) & ROMFH_MASK;

	/* OK, now find the file whose name is in "dentry" in the
	 * directory specified by "dir".  */

	name = dentry->d_name.name;
	len = dentry->d_name.len;

	for(;;) {
		if (!offset || offset >= maxoff)
			goto out0;
		if (romfs_copyfrom(dir, &ri, offset, ROMFH_SIZE) <= 0)
			goto out;

		/* try to match the first 16 bytes of name */
		fslen = romfs_strnlen(dir, offset+ROMFH_SIZE, ROMFH_SIZE);
		if (len < ROMFH_SIZE) {
			if (len == fslen) {
				/* both are shorter, and same size */
				romfs_copyfrom(dir, fsname, offset+ROMFH_SIZE, len+1);
				if (strncmp (name, fsname, len) == 0)
					break;
			}
		} else if (fslen >= ROMFH_SIZE) {
			/* both are longer; XXX optimize max size */
			fslen = romfs_strnlen(dir, offset+ROMFH_SIZE, sizeof(fsname)-1);
			if (len == fslen) {
				romfs_copyfrom(dir, fsname, offset+ROMFH_SIZE, len+1);
				if (strncmp(name, fsname, len) == 0)
					break;
			}
		}
		/* next entry */
		offset = be32_to_cpu(ri.next) & ROMFH_MASK;
	}

	/* Hard link handling */
	if ((be32_to_cpu(ri.next) & ROMFH_TYPE) == ROMFH_HRD)
		offset = be32_to_cpu(ri.spec) & ROMFH_MASK;

	if ((inode = iget(dir->i_sb, offset)))
		goto outi;

	/*
	 * it's a bit funky, _lookup needs to return an error code
	 * (negative) or a NULL, both as a dentry.  ENOENT should not
	 * be returned, instead we need to create a negative dentry by
	 * d_add(dentry, NULL); and return 0 as no error.
	 * (Although as I see, it only matters on writable file
	 * systems).
	 */

out0:	inode = NULL;
outi:	res = 0;
	d_add (dentry, inode);

out:	unlock_kernel();
	return ERR_PTR(res);
}