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; }
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; }
/* 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; }
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; }