patch-2.1.87 linux/fs/umsdos/emd.c
Next file: linux/fs/umsdos/file.c
Previous file: linux/fs/umsdos/dir.c
Back to the patch index
Back to the overall index
- Lines: 559
- Date:
Thu Feb 12 13:36:57 1998
- Orig file:
v2.1.86/linux/fs/umsdos/emd.c
- Orig date:
Mon Dec 1 10:34:11 1997
diff -u --recursive --new-file v2.1.86/linux/fs/umsdos/emd.c linux/fs/umsdos/emd.c
@@ -17,36 +17,141 @@
#include <asm/uaccess.h>
+#include <asm/delay.h>
+
#define PRINTK(x)
#define Printk(x) printk x
/*
- Read a file into kernel space memory
-*/
-long umsdos_file_read_kmem (struct inode *inode,
- struct file *filp,
- char *buf,
- unsigned long count)
-{
- int ret;
- mm_segment_t old_fs = get_fs();
- set_fs (KERNEL_DS);
- ret = fat_file_read(inode,filp,buf,count);
- set_fs (old_fs);
- return ret;
+ * makes dentry. for name name with length len. /mn/
+ * if inode is not NULL, puts it also.
+ *
+ */
+
+struct dentry *creat_dentry (const char *name, const int len, const struct inode *inode)
+{
+ struct dentry *ret, *parent=NULL; /* FIXME /mn/: whatis parent ?? */
+ struct qstr qname;
+
+ if (inode)
+ Printk (("/mn/ creat_dentry: creating dentry with inode=%d for %20s\n", inode->i_ino, name));
+ else
+ Printk (("/mn/ creat_dentry: creating empty dentry for %20s\n", name));
+
+ qname.name = name;
+ qname.len = len;
+ qname.hash = 0;
+
+ ret = d_alloc (parent,&qname); /* create new dentry */
+ ret->d_inode = inode;
+}
+
+
+
+/*
+ * Read a file into kernel space memory
+ * returns how many bytes read (from fat_file_read)
+ */
+
+ssize_t umsdos_file_read_kmem (struct inode *emd_dir,
+ struct file *filp,
+ char *buf,
+ size_t count,
+ loff_t *offs
+ )
+{
+ int ret;
+
+ struct dentry *old_dentry;
+ mm_segment_t old_fs = get_fs();
+
+ set_fs (KERNEL_DS);
+
+ old_dentry=filp->f_dentry; /* save it */
+ filp->f_dentry = creat_dentry (UMSDOS_EMD_FILE, UMSDOS_EMD_NAMELEN, emd_dir);
+ *offs = filp->f_pos;
+
+ Printk ((KERN_DEBUG "umsdos_file_read_kmem /mn/: Checkin: filp=%p, buf=%p, size=%ld, offs=%p\n", filp, buf, count, offs));
+ Printk ((KERN_DEBUG " using emd=%d\n", emd_dir->i_ino));
+ Printk ((KERN_DEBUG " inode=%d, i_size=%d\n", filp->f_dentry->d_inode->i_ino,filp->f_dentry->d_inode->i_size));
+ Printk ((KERN_DEBUG " ofs=%ld\n", *offs));
+ Printk ((KERN_DEBUG " f_pos=%ld\n", filp->f_pos));
+ Printk ((KERN_DEBUG " name=%12s\n", filp->f_dentry->d_name.name));
+ Printk ((KERN_DEBUG " i_binary(sb)=%d\n", MSDOS_I(filp->f_dentry->d_inode)->i_binary ));
+ Printk ((KERN_DEBUG " f_count=%d, f_flags=%d\n", filp->f_count, filp->f_flags));
+ Printk ((KERN_DEBUG " f_owner=%d\n", filp->f_owner));
+ Printk ((KERN_DEBUG " f_version=%ld\n", filp->f_version));
+ Printk ((KERN_DEBUG " f_reada=%ld, f_ramax=%ld, f_raend=%ld, f_ralen=%ld, f_rawin=%ld\n", filp->f_reada, filp->f_ramax, filp->f_raend, filp->f_ralen, filp->f_rawin));
+
+ ret = fat_file_read(filp,buf,count,offs);
+ Printk ((KERN_DEBUG "fat_file_read returned with %ld!\n", ret));
+
+ filp->f_pos = *offs; /* we needed *filp only for this? grrrr... /mn/ */
+ /* FIXME: I have no idea what f_pos is used for. It seems to be used this way before offs was introduced.
+ this probably needs fixing /mn/ */
+
+ filp->f_dentry=old_dentry; /* restore orig. dentry (it is dentry of file we need info about. Dunno why it gets passed to us
+ since we have no use for it, expect to store totally unrelated data of offset of EMD_FILE
+ end not directory in it. But what the hell now... fat_file_read requires it also, but prolly expects
+ it to be file* of EMD not file we want to read EMD entry about... ugh. complicated to explain :) /mn/ */
+
+ /* FIXME: we probably need to destroy originl filp->f_dentry first ? Do we ? And how ? this way we leave all sorts of dentries, inodes etc. lying around */
+ /* Also FIXME: all the same problems in umsdos_file_write_kmem */
+
+ Printk ((KERN_DEBUG " (ret) using emd=%d\n", emd_dir->i_ino));
+ Printk ((KERN_DEBUG " (ret) inode=%d, i_size=%d\n", filp->f_dentry->d_inode->i_ino,filp->f_dentry->d_inode->i_size));
+ Printk ((KERN_DEBUG " (ret) ofs=%ld\n", *offs));
+ Printk ((KERN_DEBUG " (ret) f_pos=%ld\n", filp->f_pos));
+ Printk ((KERN_DEBUG " (ret) name=%12s\n", filp->f_dentry->d_name.name));
+ Printk ((KERN_DEBUG " (ret) i_binary(sb)=%d\n", MSDOS_I(filp->f_dentry->d_inode)->i_binary ));
+ Printk ((KERN_DEBUG " (ret) f_count=%d, f_flags=%d\n", filp->f_count, filp->f_flags));
+ Printk ((KERN_DEBUG " (ret) f_owner=%d\n", filp->f_owner));
+ Printk ((KERN_DEBUG " (ret) f_version=%ld\n", filp->f_version));
+ Printk ((KERN_DEBUG " (ret) f_reada=%ld, f_ramax=%ld, f_raend=%ld, f_ralen=%ld, f_rawin=%ld\n", filp->f_reada, filp->f_ramax, filp->f_raend, filp->f_ralen, filp->f_rawin));
+
+#if 0
+ {
+ struct umsdos_dirent *mydirent=buf;
+
+ Printk ((KERN_DEBUG " (DDD) uid=%d\n",mydirent->uid));
+ Printk ((KERN_DEBUG " (DDD) gid=%d\n",mydirent->gid));
+ Printk ((KERN_DEBUG " (DDD) name=>%20s<\n",mydirent->name));
+ }
+#endif
+
+ set_fs (old_fs);
+ return ret;
}
+
+
/*
Write to a file from kernel space
*/
-long umsdos_file_write_kmem (struct inode *inode,
- struct file *filp,
- const char *buf,
- unsigned long count)
+ssize_t umsdos_file_write_kmem (struct inode *emd_dir,
+ struct file *filp,
+ const char *buf,
+ size_t count,
+ loff_t *offs
+ )
{
int ret;
mm_segment_t old_fs = get_fs();
+ struct dentry *old_dentry; /* FIXME /mn/: whatis parent ?? */
+
set_fs (KERNEL_DS);
- ret = fat_file_write(inode,filp,buf,count);
+ ret = fat_file_write(filp,buf,count,offs);
+
+ old_dentry=filp->f_dentry; /* save it */
+ filp->f_dentry = creat_dentry (UMSDOS_EMD_FILE, UMSDOS_EMD_NAMELEN, emd_dir);
+
+ *offs = filp->f_pos;
+
+ ret = fat_file_write (filp,buf,count,offs);
+ PRINTK ((KERN_DEBUG "fat_file_write returned with %ld!\n", ret));
+
+ filp->f_pos = *offs;
+ filp->f_dentry=old_dentry;
+
set_fs (old_fs);
return ret;
}
@@ -58,12 +163,16 @@
Return 0 if ok, a negative error code if not.
*/
-long umsdos_emd_dir_write (struct inode *emd_dir,
- struct file *filp,
- char *buf, /* buffer in kernel memory, not in user space */
- unsigned long count)
+ssize_t umsdos_emd_dir_write (struct inode *emd_dir,
+ struct file *filp,
+ char *buf, /* buffer in kernel memory, not in user space */
+ size_t count,
+ loff_t *offs
+ )
{
int written;
+ loff_t myofs=0;
+
#ifdef __BIG_ENDIAN
struct umsdos_dirent *d = (struct umsdos_dirent *)buf;
#endif
@@ -78,7 +187,11 @@
d->rdev = cpu_to_le16 (d->rdev);
d->mode = cpu_to_le16 (d->mode);
#endif
- written = umsdos_file_write_kmem (emd_dir,filp,buf,count);
+
+ if (offs) myofs=*offs; /* if offs is not NULL, read it */
+ written = umsdos_file_write_kmem (emd_dir, filp, buf, count, &myofs);
+ if (offs) *offs=myofs; /* if offs is not NULL, store myofs there */
+
#ifdef __BIG_ENDIAN
d->nlink = le16_to_cpu (d->nlink);
d->uid = le16_to_cpu (d->uid);
@@ -91,25 +204,36 @@
#endif
return written != count ? -EIO : 0;
}
+
+
+
/*
- Read a block of bytes from one EMD file.
- The block of data is NOT in user space.
- Return 0 if ok, -EIO if any error.
-*/
-long umsdos_emd_dir_read (struct inode *emd_dir,
+ * Read a block of bytes from one EMD file.
+ * The block of data is NOT in user space.
+ * Return 0 if ok, -EIO if any error.
+ */
+
+ssize_t umsdos_emd_dir_read (struct inode *emd_dir,
struct file *filp,
char *buf, /* buffer in kernel memory, not in user space */
- unsigned long count)
+ size_t count,
+ loff_t *offs
+ )
{
+ loff_t myofs=0;
long int ret = 0;
int sizeread;
+
+
#ifdef __BIG_ENDIAN
struct umsdos_dirent *d = (struct umsdos_dirent *)buf;
#endif
+
+ if (offs) myofs=*offs; /* if offs is not NULL, read it */
filp->f_flags = 0;
- sizeread = umsdos_file_read_kmem (emd_dir,filp,buf,count);
+ sizeread = umsdos_file_read_kmem (emd_dir, filp, buf, count, &myofs);
if (sizeread != count){
- printk ("UMSDOS: problem with EMD file. Can't read pos = %Ld (%d != %ld)\n"
+ printk ("UMSDOS: problem with EMD file. Can't read pos = %Ld (%d != %d)\n"
,filp->f_pos,sizeread,count);
ret = -EIO;
}
@@ -123,49 +247,105 @@
d->rdev = le16_to_cpu (d->rdev);
d->mode = le16_to_cpu (d->mode);
#endif
+ if (offs) *offs=myofs; /* if offs is not NULL, store myofs there */
return ret;
}
+
+
+
+
+/*
+ Locate the EMD file in a directory .
+
+ Return NULL if error. If ok, dir->u.umsdos_i.emd_inode
+*/
+struct inode *umsdos_emd_dir_lookup (struct inode *dir, int creat)
+{
+ struct inode *ret = NULL;
+ int res;
+ Printk (("Entering umsdos_emd_dir_lookup\n"));
+ if (dir->u.umsdos_i.i_emd_dir != 0){
+ ret = iget (dir->i_sb,dir->u.umsdos_i.i_emd_dir);
+ Printk (("umsdos_emd_dir_lookup: deja trouve %ld %p\n"
+ ,dir->u.umsdos_i.i_emd_dir,ret));
+ } else {
+ Printk ((KERN_DEBUG "umsdos /mn/: Looking for %20s -", UMSDOS_EMD_FILE));
+ res = compat_umsdos_real_lookup (dir, UMSDOS_EMD_FILE, UMSDOS_EMD_NAMELEN, &ret);
+ Printk ((KERN_DEBUG "-returned %d\n", res));
+ Printk ((KERN_DEBUG "emd_dir_lookup "));
+ if (ret != NULL){
+ Printk ((KERN_DEBUG "Found --linux "));
+ dir->u.umsdos_i.i_emd_dir = ret->i_ino;
+ } else if (creat) {
+ int code;
+ Printk ((KERN_ERR " * ERROR * /mn/: creat not yet implemented!!!!" ));
+ Printk ((KERN_DEBUG "avant create "));
+ atomic_inc(&dir->i_count);
+
+ code = compat_msdos_create (dir,UMSDOS_EMD_FILE,UMSDOS_EMD_NAMELEN
+ ,S_IFREG|0777,&ret);
+ Printk ((KERN_DEBUG "Creat EMD code %d ret %x ",code,ret));
+ if (ret != NULL){
+ dir->u.umsdos_i.i_emd_dir = ret->i_ino;
+ }else{
+ printk ("UMSDOS: Can't create EMD file\n");
+ }
+ }
+
+ if (ret != NULL){
+ /* Disable UMSDOS_notify_change() for EMD file */
+ ret->u.umsdos_i.i_emd_owner = 0xffffffff;
+ }
+
+ }
+
+ Printk ((KERN_DEBUG "umsdos_emd_dir_lookup returning %p /mn/\n", ret));
+ if (ret != NULL) Printk ((KERN_DEBUG " debug : returning ino=%d\n",ret->i_ino));
+ return ret;
+}
+
/*
- Locate the EMD file in a directory and optionally, creates it.
+ creates an EMD file
Return NULL if error. If ok, dir->u.umsdos_i.emd_inode
*/
-struct inode *umsdos_emd_dir_lookup(struct inode *dir, int creat)
+
+struct inode *umsdos_emd_dir_create(struct inode *dir, struct dentry *dentry,int mode)
{
struct inode *ret = NULL;
if (dir->u.umsdos_i.i_emd_dir != 0){
ret = iget (dir->i_sb,dir->u.umsdos_i.i_emd_dir);
- PRINTK (("deja trouve %d %x [%d] "
- ,dir->u.umsdos_i.i_emd_dir,ret,
- atomic_read(&ret->i_count)));
+ Printk (("deja trouve %d %x",dir->u.umsdos_i.i_emd_dir,ret));
}else{
- umsdos_real_lookup (dir,UMSDOS_EMD_FILE,UMSDOS_EMD_NAMELEN,&ret);
- PRINTK (("emd_dir_lookup "));
- if (ret != NULL){
- PRINTK (("Find --linux "));
- dir->u.umsdos_i.i_emd_dir = ret->i_ino;
- }else if (creat){
- int code;
- PRINTK (("avant create "));
- atomic_inc(&dir->i_count);
- code = msdos_create (dir,UMSDOS_EMD_FILE,UMSDOS_EMD_NAMELEN
- ,S_IFREG|0777,&ret);
- PRINTK (("Creat EMD code %d ret %x ",code,ret));
- if (ret != NULL){
- dir->u.umsdos_i.i_emd_dir = ret->i_ino;
- }else{
- printk ("UMSDOS: Can't create EMD file\n");
- }
- }
+
+ int code;
+ Printk (("avant create "));
+ dir->i_count++;
+ /*
+ code = msdos_create (dir,UMSDOS_EMD_FILE,UMSDOS_EMD_NAMELEN
+ ,S_IFREG|0777,&ret);
+
+ FIXME, I think I need a new dentry here
+ */
+ code = compat_msdos_create (dir,UMSDOS_EMD_FILE,UMSDOS_EMD_NAMELEN, S_IFREG|0777, &ret);
+ Printk (("Creat EMD code %d ret %x ",code,ret));
+ if (ret != NULL){
+ dir->u.umsdos_i.i_emd_dir = ret->i_ino;
+ }else{
+ printk ("UMSDOS: Can't create EMD file\n");
+ }
}
+
if (ret != NULL){
- /* Disable UMSDOS_notify_change() for EMD file */
- ret->u.umsdos_i.i_emd_owner = 0xffffffff;
+ /* Disable UMSDOS_notify_change() for EMD file */
+ ret->u.umsdos_i.i_emd_owner = 0xffffffff;
}
return ret;
}
+
+
/*
Read an entry from the EMD file.
Support variable length record.
@@ -176,18 +356,28 @@
struct file *filp,
struct umsdos_dirent *entry)
{
- int ret = umsdos_emd_dir_read(emd_dir,filp,(char*)entry,UMSDOS_REC_SIZE);
- if (ret == 0){
+ int ret;
+ Printk ((KERN_DEBUG "umsdos_emd_dir_readentry /mn/: entering.\n"));
+ Printk (("umsdos_emd_dir_readentry /mn/: trying to lookup %12s (ino=%d) using EMD %d\n", filp->f_dentry->d_name.name, filp->f_dentry->d_inode->i_ino, emd_dir->i_ino));
+
+ ret = umsdos_emd_dir_read(emd_dir, filp, (char*)entry, UMSDOS_REC_SIZE, NULL);
+ if (ret == 0){ /* note /mn/: is this wrong? ret is allways 0 or -EIO. but who knows. It used to work this way... */
/* Variable size record. Maybe, we have to read some more */
int recsize = umsdos_evalrecsize (entry->name_len);
+ Printk ((KERN_DEBUG "umsdos_emd_dir_readentry /mn/: FIXME if %d > %d?\n",recsize, UMSDOS_REC_SIZE));
if (recsize > UMSDOS_REC_SIZE){
- ret = umsdos_emd_dir_read(emd_dir,filp
- ,((char*)entry)+UMSDOS_REC_SIZE,recsize - UMSDOS_REC_SIZE);
+ ret = umsdos_emd_dir_read(emd_dir, filp
+ ,((char*)entry)+UMSDOS_REC_SIZE,recsize - UMSDOS_REC_SIZE,NULL);
}
}
+ Printk (("umsdos_emd_dir_readentry /mn/: returning %d.\n", ret));
return ret;
}
+
+
+
+
/*
Write an entry in the EMD file.
Return 0 if ok, -EIO if some error.
@@ -202,6 +392,12 @@
struct file filp;
struct umsdos_dirent *entry = &info->entry;
struct umsdos_dirent entry0;
+
+ Printk (("umsdos_writeentry /mn/: entering...\n"));
+
+ Printk ((KERN_ERR "umsdos_writeentry /mn/: FIXME! this is READ ONLY FOR NOW. RETURNING...\n"));
+ return -EIO;
+
if (free_entry){
/* #Specification: EMD file / empty entries
Unused entry in the EMD file are identify
@@ -222,15 +418,20 @@
*/
memset (entry->spare,0,sizeof(entry->spare));
}
+
+ Printk (("umsdos_writeentry /mn/: if passed...\n"));
+
filp.f_pos = info->f_pos;
filp.f_reada = 0;
- ret = umsdos_emd_dir_write(emd_dir,&filp,(char*)entry,info->recsize);
+ ret = umsdos_emd_dir_write(emd_dir, &filp,(char*)entry,info->recsize,NULL);
if (ret != 0){
printk ("UMSDOS: problem with EMD file. Can't write\n");
}else{
dir->i_ctime = dir->i_mtime = CURRENT_TIME;
- dir->i_dirt = 1;
+ /* dir->i_dirt = 1; FIXME iput/dput ??? */
}
+
+ Printk (("umsdos_writeentry /mn/: returning...\n"));
return ret;
}
@@ -242,6 +443,10 @@
struct file filp;
};
+
+
+
+
/*
Fill the read buffer and take care of the byte remaining inside.
Unread bytes are simply move to the beginning.
@@ -256,6 +461,9 @@
int mustmove = buf->size - buf->pos;
int mustread;
int remain;
+
+ Printk ((KERN_DEBUG "Entering umsdos_fillbuf, for inode %d, buf=%p\n",inode->i_ino, buf));
+
if (mustmove > 0){
memcpy (buf->buffer,buf->buffer+buf->pos,mustmove);
}
@@ -264,8 +472,8 @@
remain = inode->i_size - buf->filp.f_pos;
if (remain < mustread) mustread = remain;
if (mustread > 0){
- ret = umsdos_emd_dir_read (inode,&buf->filp,buf->buffer+mustmove
- ,mustread);
+ ret = umsdos_emd_dir_read (inode, &buf->filp,buf->buffer+mustmove
+ ,mustread,NULL);
if (ret == 0) buf->size = mustmove + mustread;
}else if (mustmove){
buf->size = mustmove;
@@ -274,6 +482,8 @@
return ret;
}
+
+
/*
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
@@ -308,6 +518,7 @@
record, multiple contiguous record are allocated.
*/
int ret = -ENOENT;
+ /* FIXME */
struct inode *emd_dir = umsdos_emd_dir_lookup(dir,1);
if (emd_dir != NULL){
struct umsdos_dirent *entry = &info->entry;
@@ -320,10 +531,21 @@
}empty;
/* Read several entries at a time to speed up the search */
struct find_buffer buf;
- buf.pos = 0;
- buf.size = 0;
+ struct dentry *dentry;
+
+ memset (&buf.filp, 0, sizeof (buf.filp));
+
+ dentry = creat_dentry ("umsfind-mn", 10, emd_dir);
+
buf.filp.f_pos = 0;
buf.filp.f_reada = 1;
+ buf.filp.f_flags = O_RDONLY;
+ buf.filp.f_dentry = dentry;
+ buf.filp.f_op = &umsdos_file_operations; /* /mn/ - we have to fill it with dummy values so we won't segfault */
+
+ buf.pos = 0;
+ buf.size = 0;
+
empty.found = 0;
empty.posok = emd_dir->i_size;
empty.onesize = 0;
@@ -388,6 +610,7 @@
*pt_emd_dir = emd_dir;
return ret;
}
+
/*
Add a new entry in the emd file
Return 0 if ok or a negative error code.
@@ -405,11 +628,12 @@
ret = -EEXIST;
}else if (ret == -ENOENT){
ret = umsdos_writeentry(dir,emd_dir,info,0);
- PRINTK (("umsdos_newentry EDM ret = %d\n",ret));
+ Printk (("umsdos_newentry EDM ret = %d\n",ret));
}
iput (emd_dir);
return ret;
}
+
/*
Create a new hidden link.
Return 0 if ok, an error code if not.
@@ -475,15 +699,24 @@
*/
int umsdos_isempty (struct inode *dir)
{
+ struct dentry *dentry;
+
int ret = 2;
struct inode *emd_dir = umsdos_emd_dir_lookup(dir,0);
/* If the EMD file does not exist, it is certainly empty :-) */
if (emd_dir != NULL){
struct file filp;
/* Find an empty slot */
+ memset (&filp, 0, sizeof (filp));
+
+ dentry = creat_dentry ("isempty-mn", 10, dir);
+
filp.f_pos = 0;
filp.f_reada = 1;
filp.f_flags = O_RDONLY;
+ filp.f_dentry = dentry;
+ filp.f_op = &umsdos_file_operations; /* /mn/ - we have to fill it with dummy values so we won't segfault */
+
ret = 1;
while (filp.f_pos < emd_dir->i_size){
struct umsdos_dirent entry;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov