Пример #1
0
int umsdos_emd_dir_readentry (struct file *filp, struct umsdos_dirent *entry)
{
	int ret;

	Printk ((KERN_DEBUG "umsdos_emd_dir_readentry /mn/: entering.\n"));

	ret = umsdos_emd_dir_read (filp, (char *) entry, UMSDOS_REC_SIZE);
	if (ret == 0) {	/* if no error */
		/* Variable size record. Maybe, we have to read some more */
		int recsize = umsdos_evalrecsize (entry->name_len);

		if (recsize > UMSDOS_REC_SIZE) {
Printk ((KERN_DEBUG "umsdos_emd_dir_readentry /mn/: %d > %d!\n",
recsize, UMSDOS_REC_SIZE));
			ret = umsdos_emd_dir_read (filp, 
					((char *) entry) + UMSDOS_REC_SIZE,
					recsize - UMSDOS_REC_SIZE);
		}
	}
	Printk (("umsdos_emd_dir_readentry /mn/: ret=%d.\n", ret));
	if (entry && ret == 0) {
Printk (("umsdos_emd_dir_readentry /mn/: returning len=%d,name=%.*s\n",
(int) entry->name_len, (int) entry->name_len, entry->name));
	}
	return ret;
}
Пример #2
0
/*
	Read an entry from the EMD file.
	Support variable length record.
	Return -EIO if error, 0 if ok.
*/
int umsdos_emd_dir_readentry (
	struct inode *emd_dir,
	struct file *filp,
	struct umsdos_dirent *entry)
{
	int ret = umsdos_emd_dir_read(emd_dir,filp,(char*)entry,UMSDOS_REC_SIZE);
	if (ret == 0){
		/* Variable size record. Maybe, we have to read some more */
		int recsize = umsdos_evalrecsize (entry->name_len);
		if (recsize > UMSDOS_REC_SIZE){
			ret = umsdos_emd_dir_read(emd_dir,filp
				,((char*)entry)+UMSDOS_REC_SIZE,recsize - UMSDOS_REC_SIZE);
			
		}
	}
	return ret;
}
Пример #3
0
static int umsdos_find (struct dentry *parent, struct umsdos_info *info)
{
	struct umsdos_dirent *entry = &info->entry;
	int recsize = info->recsize;
	struct dentry *demd;
	struct inode *emd_dir;
	int ret = -ENOENT;
	struct find_buffer buf;
	struct {
		off_t posok;	/* Position available to store the entry */
		int found;	/* A valid empty position has been found. */
		off_t one;	/* One empty position -> maybe <- large enough */
		int onesize;	/* size of empty region starting at one */
	} empty;

Printk (("umsdos_find: locating %s in %s/%s\n",
entry->name, parent->d_parent->d_name.name, parent->d_name.name));

	/*
	 * Lookup the EMD file in the parent directory.
	 */
	demd = umsdos_get_emd_dentry(parent);
	ret = PTR_ERR(demd);
	if (IS_ERR(demd))
		goto out;
	/* make sure there's an EMD file ... */
	ret = -ENOENT;
	emd_dir = demd->d_inode;
	if (!emd_dir)
		goto out_dput;

Printk(("umsdos_find: found EMD file %s/%s, ino=%p\n",
demd->d_parent->d_name.name, demd->d_name.name, emd_dir));

	fill_new_filp (&buf.filp, demd);

	buf.pos = 0;
	buf.size = 0;

	empty.found = 0;
	empty.posok = emd_dir->i_size;
	empty.onesize = 0;
	while (1) {
		struct umsdos_dirent *rentry = (struct umsdos_dirent *)
						(buf.buffer + buf.pos);
		int file_pos = buf.filp.f_pos - buf.size + buf.pos;

		if (buf.pos == buf.size) {
			ret = umsdos_fillbuf (&buf);
			if (ret < 0) {
				/* Not found, so note where it can be added */
				info->f_pos = empty.posok;
				break;
			}
		} else if (rentry->name_len == 0) {
			/* We are looking for an empty section at least */
			/* as large as recsize. */
			if (entry->name_len == 0) {
				info->f_pos = file_pos;
				ret = 0;
				break;
			} else if (!empty.found) {
				if (empty.onesize == 0) {
					/* This is the first empty record of a section. */
					empty.one = file_pos;
				}
				/* grow the empty section */
				empty.onesize += UMSDOS_REC_SIZE;
				if (empty.onesize == recsize) {
					/* Here is a large enough section. */
					empty.posok = empty.one;
					empty.found = 1;
				}
			}
			buf.pos += UMSDOS_REC_SIZE;
		} else {
			int entry_size = umsdos_evalrecsize (rentry->name_len);

			if (buf.pos + entry_size > buf.size) {
				ret = umsdos_fillbuf (&buf);
				if (ret < 0) {
					/* Not found, so note where it can be added */
					info->f_pos = empty.posok;
					break;
				}
			} else {
				empty.onesize = 0;	/* Reset the free slot search. */
				if (entry->name_len == rentry->name_len
				    && memcmp (entry->name, rentry->name, rentry->name_len) == 0) {
					info->f_pos = file_pos;
					*entry = *rentry;
					ret = 0;
					break;
				} else {
					buf.pos += entry_size;
				}
			}
		}
	}
Printk(("umsdos_find: ready to mangle %s, len=%d, pos=%ld\n",
entry->name, entry->name_len, (long)info->f_pos));
	umsdos_manglename (info);

out_dput:
	dput(demd);

out:
	Printk (("umsdos_find: returning %d\n", ret));
	return ret;
}
Пример #4
0
/*
	General search, locate a name in the EMD file or an empty slot to
	store it. if info->entry.name_len == 0, search the first empty
	slot (of the proper size).

	Caller must do iput on *pt_emd_dir.

	Return 0 if found, -ENOENT if not found, another error code if
	other problem.

	So this routine is used to either find an existing entry or to
	create a new one, while making sure it is a new one. After you
	get -ENOENT, you make sure the entry is stuffed correctly and
	call umsdos_writeentry().

	To delete an entry, you find it, zero out the entry (memset)
	and call umsdos_writeentry().

	All this to say that umsdos_writeentry must be call after this
	function since it rely on the f_pos field of info.
*/
static int umsdos_find (
	struct inode *dir,
	struct umsdos_info *info,		/* Hold name and name_len */
									/* Will hold the entry found */
	struct inode **pt_emd_dir)		/* Will hold the emd_dir inode */
									/* or NULL if not found */
{
	/* #Specification: EMD file structure
		The EMD file uses a fairly simple layout. It is made of records
		(UMSDOS_REC_SIZE == 64). When a name can't be written is a single
		record, multiple contiguous record are allocated.
	*/
	int ret = -ENOENT;
	struct inode *emd_dir = umsdos_emd_dir_lookup(dir,1);
	if (emd_dir != NULL){
		struct umsdos_dirent *entry = &info->entry;
		int recsize = info->recsize;
		struct {
			off_t posok;	/* Position available to store the entry */
			int found;		/* A valid empty position has been found */
			off_t one;		/* One empty position -> maybe <- large enough */
			int onesize;	/* size of empty region starting at one */
		}empty;
		/* Read several entries at a time to speed up the search */
		struct find_buffer buf;
		buf.pos = 0;
		buf.size = 0;
		buf.filp.f_pos = 0;
		buf.filp.f_reada = 1;
		empty.found = 0;
		empty.posok = emd_dir->i_size;
		empty.onesize = 0;
		while (1){
			struct umsdos_dirent *rentry = (struct umsdos_dirent*)
				(buf.buffer + buf.pos);
			int file_pos = buf.filp.f_pos - buf.size + buf.pos;
			if (buf.pos == buf.size){
				ret = umsdos_fillbuf (emd_dir,&buf);
				if (ret < 0){
					/* Not found, so note where it can be added */
					info->f_pos = empty.posok;
					break;
				}
			}else if (rentry->name_len == 0){
				/* We are looking for an empty section at least */
				/* recsize large */
				if (entry->name_len == 0){
					info->f_pos = file_pos;
					ret = 0;
					break;
				}else if (!empty.found){
					if (empty.onesize == 0){
						/* This is the first empty record of a section */
						empty.one = file_pos;
					}
					/* grow the empty section */
					empty.onesize += UMSDOS_REC_SIZE;
					if (empty.onesize == recsize){
						/* here is a large enough section */
						empty.posok = empty.one;
						empty.found = 1;
					}
				}
				buf.pos += UMSDOS_REC_SIZE;
			}else{
				int entry_size = umsdos_evalrecsize(rentry->name_len);
				if (buf.pos+entry_size > buf.size){
					ret = umsdos_fillbuf (emd_dir,&buf);
					if (ret < 0){
						/* Not found, so note where it can be added */
						info->f_pos = empty.posok;
						break;
					}
				}else{
					empty.onesize = 0;	/* Reset the free slot search */
					if (entry->name_len == rentry->name_len
						&& memcmp(entry->name,rentry->name,rentry->name_len)
							==0){
						info->f_pos = file_pos;
						*entry = *rentry;
						ret = 0;
						break;
					}else{
						buf.pos += entry_size;
					}
				}
			}	
		}
		umsdos_manglename(info);
	}
	*pt_emd_dir = emd_dir;
	return ret;
}