Esempio n. 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;
}
Esempio n. 2
0
static int umsdos_fillbuf (struct find_buffer *buf)
{
	struct inode *inode = buf->filp.f_dentry->d_inode;
	int mustmove = buf->size - buf->pos;
	int mustread, remain;
	int ret = -ENOENT;

	if (mustmove > 0) {
		memcpy (buf->buffer, buf->buffer + buf->pos, mustmove);
	}
	buf->pos = 0;
	mustread = CHUNK_SIZE - mustmove;
	remain = inode->i_size - buf->filp.f_pos;
	if (remain < mustread)
		mustread = remain;
	if (mustread > 0) {
		ret = umsdos_emd_dir_read (&buf->filp, buf->buffer + mustmove,
					 mustread);
		if (ret == 0)
			buf->size = mustmove + mustread;
	} else if (mustmove) {
		buf->size = mustmove;
		ret = 0;
	}
	return ret;
}
Esempio n. 3
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;
}
Esempio n. 4
0
int UMSDOS_notify_change(struct inode *inode, struct iattr *attr)
{
	int ret = 0;

	if ((ret = inode_change_ok(inode, attr)) != 0) 
		return ret;

	if (inode->i_nlink > 0){
		/* #Specification: notify_change / i_nlink > 0
			notify change is only done for inode with nlink > 0. An inode
			with nlink == 0 is no longer associated with any entry in
			the EMD file, so there is nothing to update.
		*/
		unsigned long i_emd_owner = inode->u.umsdos_i.i_emd_owner;
		if (inode == inode->i_sb->s_mounted){
			/* #Specification: root inode / attributes
				I don't know yet how this should work. Normally
				the attributes (permissions bits, owner, times) of
				a directory are stored in the EMD file of its parent.

				One thing we could do is store the attributes of the root
				inode in its own EMD file. A simple entry named "." could
				be used for this special case. It would be read once
				when the file system is mounted and update in
				UMSDOS_notify_change() (right here).

				I am not sure of the behavior of the root inode for
				a real UNIX file system. For now, this is a nop.
			*/
		}else if (i_emd_owner != 0xffffffff && i_emd_owner != 0){
			/* This inode is not a EMD file nor an inode used internally
				by MSDOS, so we can update its status.
				See emd.c
			*/
			struct inode *emd_owner = iget (inode->i_sb,i_emd_owner);
			PRINTK (("notify change %p ",inode));
			if (emd_owner == NULL){
				printk ("UMSDOS: emd_owner = NULL ???");
				ret = -EPERM;
			}else{
				struct file filp;
				struct umsdos_dirent entry;
				filp.f_pos = inode->u.umsdos_i.pos;
				filp.f_reada = 0;
				PRINTK (("pos = %d ",filp.f_pos));
				/* Read only the start of the entry since we don't touch */
				/* the name */
				ret = umsdos_emd_dir_read (emd_owner,&filp,(char*)&entry
					,UMSDOS_REC_SIZE);
				if (ret == 0){
					if (attr->ia_valid & ATTR_UID) 
						entry.uid = attr->ia_uid;
					if (attr->ia_valid & ATTR_GID) 
						entry.gid = attr->ia_gid;
					if (attr->ia_valid & ATTR_MODE) 
						entry.mode = attr->ia_mode;
					if (attr->ia_valid & ATTR_ATIME) 
						entry.atime = attr->ia_atime;
					if (attr->ia_valid & ATTR_MTIME) 
						entry.mtime = attr->ia_mtime;
					if (attr->ia_valid & ATTR_CTIME) 
						entry.ctime = attr->ia_ctime;

					entry.nlink = inode->i_nlink;
					filp.f_pos = inode->u.umsdos_i.pos;
					ret = umsdos_emd_dir_write (emd_owner,&filp,(char*)&entry
						,UMSDOS_REC_SIZE);

					PRINTK (("notify pos %d ret %d nlink %d "
						,inode->u.umsdos_i.pos
						,ret,entry.nlink));
					/* #Specification: notify_change / msdos fs
						notify_change operation are done only on the
						EMD file. The msdos fs is not even called.
					*/
				}
				iput (emd_owner);
			}
			PRINTK (("\n"));
		}
	}
	if (ret == 0) 
		inode_setattr(inode, attr);
	return ret;
}