diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1997-01-07 02:33:00 +0000 |
---|---|---|
committer | <ralf@linux-mips.org> | 1997-01-07 02:33:00 +0000 |
commit | beb116954b9b7f3bb56412b2494b562f02b864b1 (patch) | |
tree | 120e997879884e1b9d93b265221b939d2ef1ade1 /fs/umsdos | |
parent | 908d4681a1dc3792ecafbe64265783a86c4cccb6 (diff) |
Import of Linux/MIPS 2.1.14
Diffstat (limited to 'fs/umsdos')
-rw-r--r-- | fs/umsdos/Makefile | 29 | ||||
-rw-r--r-- | fs/umsdos/README | 96 | ||||
-rw-r--r-- | fs/umsdos/check.c | 13 | ||||
-rw-r--r-- | fs/umsdos/dir.c | 286 | ||||
-rw-r--r-- | fs/umsdos/emd.c | 50 | ||||
-rw-r--r-- | fs/umsdos/file.c | 37 | ||||
-rw-r--r-- | fs/umsdos/inode.c | 33 | ||||
-rw-r--r-- | fs/umsdos/ioctl.c | 73 | ||||
-rw-r--r-- | fs/umsdos/mangle.c | 8 | ||||
-rw-r--r-- | fs/umsdos/namei.c | 16 | ||||
-rw-r--r-- | fs/umsdos/rdir.c | 83 | ||||
-rw-r--r-- | fs/umsdos/symlink.c | 16 |
12 files changed, 385 insertions, 355 deletions
diff --git a/fs/umsdos/Makefile b/fs/umsdos/Makefile index 8bdf98f97..79942b072 100644 --- a/fs/umsdos/Makefile +++ b/fs/umsdos/Makefile @@ -7,37 +7,18 @@ # # Note 2! The CFLAGS definitions are now in the main makefile... -.c.s: - $(CC) $(CFLAGS) -S $< -.c.o: - $(CC) $(CFLAGS) -c $< -.s.o: - $(AS) -o $*.o $< +O_TARGET := umsdos.o +O_OBJS := dir.o emd.o file.o inode.o ioctl.o mangle.o namei.o \ + rdir.o symlink.o #check.o +M_OBJS := $(O_TARGET) -OBJS= dir.o emd.o file.o inode.o ioctl.o mangle.o namei.o\ - rdir.o symlink.o #check.o - -umsdos.o: $(OBJS) - $(LD) -r -o umsdos.o $(OBJS) - -modules: umsdos.o - ln -sf ../fs/umsdos/umsdos.o $(TOPDIR)/modules +include $(TOPDIR)/Rules.make clean: rm -f core *.o *.a *.s -dep: - $(CPP) -M *.c > .depend - p: proto *.c >/usr/include/linux/umsdos_fs.p doc: nadoc -i -p umsdos.doc - /tmp/umsdos.mpg - -# -# include a dependency file if one exists -# -ifeq (.depend,$(wildcard .depend)) -include .depend -endif diff --git a/fs/umsdos/README b/fs/umsdos/README deleted file mode 100644 index 320dac6ca..000000000 --- a/fs/umsdos/README +++ /dev/null @@ -1,96 +0,0 @@ -Very short explanation for the impatient!!! - -Umsdos is a file system driver that run on top the MSDOS fs driver. -It is written by Jacques Gelinas (jacques@solucorp.qc.ca) - -Umsdos is not a file system per se, but a twist to make a boring -one into a useful one. - -It gives you: - - long file name - Permissions and owner - Links - Special files (devices, pipe...) - All is need to be a linux root fs. - -There is plenty of documentation on it in the source. A formated document -made from those comments is available from -sunsite.unc.edu:/pub/Linux/system/Filesystems/umsdos. - -Mostly... - -You mount a DOS partition like this - -mount -t umsdos /dev/hda3 /mnt - ^ ----------| - -All option are passed to the msdos drivers. Option like uid,gid etc are -given to msdos. - -The default behavior of Umsdos is to do the same thing as the msdos driver -mostly passing commands to it without much processing. Again, this is -the default. After doing the mount on a DOS partition, nothing special -happen. This is why all mount options are passed to the Msdos fs driver. - -Umsdos use a special DOS file --linux-.--- to store the information -which can't be handle by the normal MsDOS file system. This is the trick. - ---linux-.--- is optional. There is one per directory. - -**** If --linux-.--- is missing, then Umsdos process the directory the - same way the msdos driver do. Short file name, no goodies, default - owner and permissions. So each directory may have or not this - --linux-.--- - -Now, how to get those --linux-.---. - -\begin joke_section - - Well send me a directory content - and I will send you one customised for you. - $5 per directory. Add any applicable taxes. -\end joke_section - -A utility umssync creates those. The kernel maintain them. It is available -from the same directory above (sunsite) in the file umsdos_progs-0.7.tar.gz. -A compiled version is available in umsdos_progs-0.7.bin.tar.gz. - -So in our example, after mounting mnt, we do - -umssync . - -This will promote this directory (a recursive option is available) to full -umsdos capabilities (long name ...). A ls -l before and after won't show -much difference however. The file which were there are still there. But now -you can do all this: - - chmod 644 * - chown you.your_groupe * - ls >THIS_IS.A.VERY.LONG.NAME - ln -s toto tata - ls -l - -Once a directory is promoted, all subdirectory created will inherit that -promotion. - -What happen if you boot DOS and create files in those promoted directories ? -Umsdos won't notice new files, but will signal removed file (it won't crash). -Using umssync in /etc/rc will make sure the DOS directory is in sync with -the --linux-.---. - -It is a good idea to put the following command in your RC file just -after the "mount -a": - - mount -a - /sbin/umssync -i+ -c+ -r99 /umsdos_mount_point - - (You put one for each umsdos mount point in the fstab) - -This will insure nice operation. A umsdos.fsck is in the making, -so you will be allowed to managed umsdos partition in the same way -other filesystem are, using the generic fsck front end. - -Hope this helps! - diff --git a/fs/umsdos/check.c b/fs/umsdos/check.c index 7fb060c7a..67846925a 100644 --- a/fs/umsdos/check.c +++ b/fs/umsdos/check.c @@ -1,8 +1,8 @@ -#ifdef MODULE -#include <linux/module.h> -#endif - -#include <asm/system.h> +/* + * linux/fs/umsdos/check.c + * + * + */ #include <linux/signal.h> #include <linux/sched.h> @@ -13,8 +13,9 @@ #include <linux/types.h> #include <linux/ptrace.h> #include <linux/mman.h> +#include <linux/mm.h> -extern unsigned long high_memory; +#include <asm/system.h> static int check_one_table(struct pde * page_dir) { diff --git a/fs/umsdos/dir.c b/fs/umsdos/dir.c index 990260a92..9e0abf55a 100644 --- a/fs/umsdos/dir.c +++ b/fs/umsdos/dir.c @@ -7,12 +7,6 @@ * Extended MS-DOS directory handling functions */ -#ifdef MODULE -#include <linux/module.h> -#endif - -#include <asm/segment.h> - #include <linux/sched.h> #include <linux/string.h> #include <linux/fs.h> @@ -23,6 +17,8 @@ #include <linux/umsdos_fs.h> #include <linux/malloc.h> +#include <asm/uaccess.h> + #define PRINTK(x) #define Printk(x) printk x @@ -31,19 +27,50 @@ extern struct inode *pseudo_root; /* So grep * doesn't complain in the presence of directories. */ -int UMSDOS_dir_read(struct inode *inode,struct file *filp,char *buf, - int count) +long UMSDOS_dir_read(struct inode *inode,struct file *filp, + char *buf, unsigned long count) { return -EISDIR; } -#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de))) -#define ROUND_UP(x) (((x)+3) & ~3) + +struct UMSDOS_DIR_ONCE { + void *dirbuf; + filldir_t filldir; + int count; + int stop; +}; + +/* + Record a single entry the first call. + Return -EINVAL the next one. +*/ +static int umsdos_dir_once( + void * buf, + const char * name, + int name_len, + off_t offset, + ino_t ino) +{ + int ret = -EINVAL; + struct UMSDOS_DIR_ONCE *d = (struct UMSDOS_DIR_ONCE *)buf; + if (d->count == 0){ + #if 0 + char zname[100]; + memcpy (zname,name,name_len); + zname[name_len] = '\0'; + Printk (("dir_once :%s: offset %Ld\n",zname,offset)); + #endif + ret = d->filldir (d->dirbuf,name,name_len,offset,ino); + d->stop = ret < 0; + d->count = 1; + } + return ret; +} /* Read count directory entries from directory filp Return a negative value from linux/errno.h. - Return > 0 if success (The amount of byte written in - dirent round_up to a word size (32 bits). + Return > 0 if success (The amount of byte written by filldir). This function is used by the normal readdir VFS entry point and by some function who try to find out info on a file from a pure MSDOS @@ -52,19 +79,19 @@ int UMSDOS_dir_read(struct inode *inode,struct file *filp,char *buf, static int umsdos_readdir_x( struct inode *dir, /* Point to a description of the super block */ struct file *filp, /* Point to a directory which is read */ - struct dirent *dirent, /* Will hold count directory entry */ - int dirent_in_fs, /* dirent point in user's space ? */ - int count, + void *dirbuf, /* Will hold count directory entry */ + /* but filled by the filldir function */ + int internal_read, /* Called for internal purpose */ struct umsdos_dirent *u_entry, /* Optional umsdos entry */ int follow_hlink, - off_t *pt_f_pos) /* will hold the offset of the entry in EMD */ + filldir_t filldir) { int ret = 0; umsdos_startlookup(dir); if (filp->f_pos == UMSDOS_SPECIAL_DIRFPOS && dir == pseudo_root - && dirent_in_fs){ + && !internal_read){ /* We don't need to simulate this pseudo directory when umsdos_readdir_x is called for internal operation @@ -75,13 +102,10 @@ static int umsdos_readdir_x( linux root), it simulate a directory /DOS which points to the real root of the file system. */ - put_fs_long(dir->i_sb->s_mounted->i_ino,&dirent->d_ino); - memcpy_tofs (dirent->d_name,"DOS",3); - put_fs_byte(0,dirent->d_name+3); - put_fs_word (3,&dirent->d_reclen); - if (u_entry != NULL) u_entry->flags = 0; - ret = ROUND_UP(NAME_OFFSET(dirent) + 3 + 1); - filp->f_pos++; + if (filldir (dirbuf,"DOS",3,UMSDOS_SPECIAL_DIRFPOS + ,dir->i_sb->s_mounted->i_ino) == 0){ + filp->f_pos++; + } }else if (filp->f_pos < 2 || (dir != dir->i_sb->s_mounted && filp->f_pos == 32)){ /* #Specification: readdir / . and .. @@ -116,15 +140,27 @@ static int umsdos_readdir_x( EMD, we are back at offset 64. So we set the offset to UMSDOS_SPECIAL_DIRFPOS(3) as soon as we have read the .. entry from msdos. + + Now (linux 1.3), umsdos_readdir can read more than one + entry even if we limit (umsdos_dir_once) to only one: + It skips over hidden file. So we switch to + UMSDOS_SPECIAL_DIRFPOS as soon as we have read successfully + the .. entry. */ - ret = msdos_readdir(dir,filp,dirent,count); - if (filp->f_pos == 64) filp->f_pos = UMSDOS_SPECIAL_DIRFPOS; + int last_f_pos = filp->f_pos; + struct UMSDOS_DIR_ONCE bufk; + bufk.dirbuf = dirbuf; + bufk.filldir = filldir; + bufk.count = 0; + ret = fat_readdir(dir,filp,&bufk,umsdos_dir_once); + if (last_f_pos > 0 && filp->f_pos > last_f_pos) filp->f_pos = UMSDOS_SPECIAL_DIRFPOS; if (u_entry != NULL) u_entry->flags = 0; }else{ struct inode *emd_dir = umsdos_emd_dir_lookup(dir,0); if (emd_dir != NULL){ + off_t start_fpos = filp->f_pos; if (filp->f_pos <= UMSDOS_SPECIAL_DIRFPOS+1) filp->f_pos = 0; - PRINTK (("f_pos %ld i_size %d\n",filp->f_pos,emd_dir->i_size)); + PRINTK (("f_pos %lu i_size %ld\n",filp->f_pos,emd_dir->i_size)); ret = 0; while (filp->f_pos < emd_dir->i_size){ struct umsdos_dirent entry; @@ -156,7 +192,6 @@ static int umsdos_readdir_x( int lret; umsdos_parse (entry.name,entry.name_len,&info); info.f_pos = cur_f_pos; - *pt_f_pos = cur_f_pos; umsdos_manglename (&info); lret = umsdos_real_lookup (dir,info.fake.fname ,info.fake.len,&inode); @@ -177,29 +212,16 @@ static int umsdos_readdir_x( infinite recursion /DOS/linux/DOS/linux while walking the file system. */ - if (inode != pseudo_root){ - PRINTK (("Trouve ino %d ",inode->i_ino)); - if (dirent_in_fs){ - put_fs_long(inode->i_ino,&dirent->d_ino); - memcpy_tofs (dirent->d_name,entry.name - ,entry.name_len); - put_fs_byte(0,dirent->d_name+entry.name_len); - put_fs_word (entry.name_len - ,&dirent->d_reclen); - /* In this case, the caller only needs */ - /* flags */ - if (u_entry != NULL){ - u_entry->flags = entry.flags; - } - }else{ - dirent->d_ino = inode->i_ino; - memcpy (dirent->d_name,entry.name - ,entry.name_len); - dirent->d_name[entry.name_len] = '\0'; - dirent->d_reclen = entry.name_len; - if (u_entry != NULL) *u_entry = entry; + if (inode != pseudo_root + && (internal_read + || !(entry.flags & UMSDOS_HIDDEN))){ + if (filldir (dirbuf + ,entry.name,entry.name_len + ,cur_f_pos, inode->i_ino) < 0){ + filp->f_pos = cur_f_pos; } - ret = ROUND_UP(NAME_OFFSET(dirent) + entry.name_len + 1); + PRINTK (("Trouve ino %ld ",inode->i_ino)); + if (u_entry != NULL) *u_entry = entry; iput (inode); break; } @@ -217,32 +239,48 @@ static int umsdos_readdir_x( } } } + /* + If the fillbuf has failed, f_pos is back to 0. + To avoid getting back into the . and .. state + (see comments at the beginning), we put back + the special offset. + */ + if (filp->f_pos == 0) filp->f_pos = start_fpos; iput(emd_dir); } } umsdos_endlookup(dir); - PRINTK (("read dir %p pos %d ret %d\n",dir,filp->f_pos,ret)); + PRINTK (("read dir %p pos %Ld ret %d\n",dir,filp->f_pos,ret)); return ret; } /* Read count directory entries from directory filp Return a negative value from linux/errno.h. - Return > 0 if success (the amount of byte written to dirent) + Return 0 or positive if successful */ static int UMSDOS_readdir( struct inode *dir, /* Point to a description of the super block */ struct file *filp, /* Point to a directory which is read */ - struct dirent *dirent, /* Will hold count directory entry */ - int count) + void *dirbuf, /* Will hold directory entries */ + filldir_t filldir) { - int ret = -ENOENT; - while (1){ + int ret = 0; + int count = 0; + struct UMSDOS_DIR_ONCE bufk; + bufk.dirbuf = dirbuf; + bufk.filldir = filldir; + bufk.stop = 0; + PRINTK (("UMSDOS_readdir in\n")); + while (ret == 0 && bufk.stop == 0){ struct umsdos_dirent entry; - off_t f_pos; - ret = umsdos_readdir_x (dir,filp,dirent,1,count,&entry,1,&f_pos); - if (ret <= 0 || !(entry.flags & UMSDOS_HIDDEN)) break; + bufk.count = 0; + ret = umsdos_readdir_x (dir,filp,&bufk,0,&entry,1,umsdos_dir_once); + if (bufk.count == 0) break; + count += bufk.count; } - return ret; + PRINTK (("UMSDOS_readdir out %d count %d pos %Ld\n",ret,count + ,filp->f_pos)); + return count?:ret; } /* Complete the inode content with info from the EMD file @@ -304,12 +342,48 @@ void umsdos_lookup_patch ( */ if (S_ISREG(entry->mode)) entry->mtime = inode->i_mtime; inode->i_mode = entry->mode; - inode->i_rdev = entry->rdev; + inode->i_rdev = to_kdev_t(entry->rdev); inode->i_atime = entry->atime; inode->i_ctime = entry->ctime; inode->i_mtime = entry->mtime; inode->i_uid = entry->uid; inode->i_gid = entry->gid; + /* #Specification: umsdos / conversion mode + The msdos fs can do some inline conversion + of the data of a file. It can translate + silently from MsDOS text file format to Unix + one (crlf -> lf) while reading, and the reverse + while writing. This is activated using the mount + option conv=.... + + This is not useful for Linux file in promoted + directory. It can even be harmful. For this + reason, the binary (no conversion) mode is + always activated. + */ + /* #Specification: umsdos / conversion mode / todo + A flag could be added to file and directories + forcing an automatic conversion mode (as + done with the msdos fs). + + This flag could be setup on a directory basis + (instead of file) and all file in it would + logically inherited. If the conversion mode + is active (conv=) then the i_binary flag would + be left untouched in those directories. + + It was proposed that the sticky bit was used + to set this. The problem is that new file would + be written incorrectly. The other problem is that + the sticky bit has a meaning for directories. So + another bit should be used (there is some space + in the EMD file for it) and a special utilities + would be used to assign the flag to a directory). + I don't think it is useful to assign this flag + on a single file. + */ + + MSDOS_I(inode)->i_binary = 1; /* #Specification: umsdos / i_nlink The nlink field of an inode is maintain by the MSDOS file system for directory and by UMSDOS for other file. The logic is that @@ -331,6 +405,53 @@ void umsdos_lookup_patch ( if (inode->u.umsdos_i.i_emd_owner==0) printk ("emd_owner still 0 ???\n"); } } +struct UMSDOS_DIRENT_K{ + off_t f_pos; /* will hold the offset of the entry in EMD */ + ino_t ino; +}; + +/* + Just to record the offset of one entry. +*/ +static int umsdos_filldir_k( + void * buf, + const char * name, + int name_len, + off_t offset, + ino_t ino) +{ + struct UMSDOS_DIRENT_K *d = (struct UMSDOS_DIRENT_K *)buf; + d->f_pos = offset; + d->ino = ino; + return 0; +} + +struct UMSDOS_DIR_SEARCH{ + struct umsdos_dirent *entry; + int found; + ino_t search_ino; +}; + +static int umsdos_dir_search ( + void * buf, + const char * name, + int name_len, + off_t offset, + ino_t ino) +{ + int ret = 0; + struct UMSDOS_DIR_SEARCH *d = (struct UMSDOS_DIR_SEARCH *)buf; + if (d->search_ino == ino){ + d->found = 1; + memcpy (d->entry->name,name,name_len); + d->entry->name[name_len] = '\0'; + d->entry->name_len = name_len; + ret = 1; /* So fat_readdir will terminate */ + } + return ret; +} + + /* Locate entry of an inode in a directory. Return 0 or a negative error code. @@ -357,24 +478,18 @@ int umsdos_inode2entry ( iput (emddir); if (emddir == NULL){ /* This is a DOS directory */ + struct UMSDOS_DIR_SEARCH bufk; struct file filp; filp.f_reada = 1; filp.f_pos = 0; - while (1){ - struct dirent dirent; - if (umsdos_readdir_kmem (dir,&filp,&dirent,1) <= 0){ - printk ("UMSDOS: can't locate inode %ld in DOS directory???\n" - ,inode->i_ino); - }else if (dirent.d_ino == inode->i_ino){ - ret = 0; - memcpy (entry->name,dirent.d_name,dirent.d_reclen); - entry->name[dirent.d_reclen] = '\0'; - entry->name_len = dirent.d_reclen; - inode->u.umsdos_i.i_dir_owner = dir->i_ino; - inode->u.umsdos_i.i_emd_owner = 0; - umsdos_setup_dir_inode(inode); - break; - } + bufk.entry = entry; + bufk.search_ino = inode->i_ino; + fat_readdir (dir,&filp,&bufk,umsdos_dir_search); + if (bufk.found){ + ret = 0; + inode->u.umsdos_i.i_dir_owner = dir->i_ino; + inode->u.umsdos_i.i_emd_owner = 0; + umsdos_setup_dir_inode(inode); } }else{ /* skip . and .. see umsdos_readdir_x() */ @@ -382,16 +497,15 @@ int umsdos_inode2entry ( filp.f_reada = 1; filp.f_pos = UMSDOS_SPECIAL_DIRFPOS; while (1){ - struct dirent dirent; - off_t f_pos; - if (umsdos_readdir_x(dir,&filp,&dirent - ,0,1,entry,0,&f_pos) <= 0){ + struct UMSDOS_DIRENT_K bufk; + if (umsdos_readdir_x(dir,&filp,&bufk + ,1,entry,0,umsdos_filldir_k) < 0){ printk ("UMSDOS: can't locate inode %ld in EMD file???\n" ,inode->i_ino); break; - }else if (dirent.d_ino == inode->i_ino){ + }else if (bufk.ino == inode->i_ino){ ret = 0; - umsdos_lookup_patch (dir,inode,entry,f_pos); + umsdos_lookup_patch (dir,inode,entry,bufk.f_pos); break; } } @@ -411,7 +525,7 @@ static int umsdos_locate_ancestor ( int ret; umsdos_patch_inode (dir,NULL,0); ret = umsdos_real_lookup (dir,"..",2,result); - PRINTK (("result %d %x ",ret,*result)); + PRINTK (("result %d %p ",ret,*result)); if (ret == 0){ struct inode *adir = *result; ret = umsdos_inode2entry (adir,dir,entry); @@ -560,7 +674,7 @@ static int umsdos_lookup_x ( struct umsdos_info info; ret = umsdos_parse (name,len,&info); if (ret == 0) ret = umsdos_findentry (dir,&info,0); - PRINTK (("lookup %s pos %d ret %d len %d ",info.fake.fname,info.f_pos,ret + PRINTK (("lookup %s pos %lu ret %d len %d ",info.fake.fname,info.f_pos,ret ,info.fake.len)); if (ret == 0){ /* #Specification: umsdos / lookup @@ -581,7 +695,7 @@ static int umsdos_lookup_x ( umsdos_delentry (dir,&info,S_ISDIR(info.entry.mode)); }else{ umsdos_lookup_patch (dir,inode,&info.entry,info.f_pos); - PRINTK (("lookup ino %d flags %d\n",inode->i_ino + PRINTK (("lookup ino %ld flags %d\n",inode->i_ino ,info.entry.flags)); if (info.entry.flags & UMSDOS_HLINK){ ret = umsdos_hlink2inode (inode,result); @@ -698,6 +812,8 @@ struct inode_operations umsdos_dir_inode_operations = { UMSDOS_rename, /* rename */ NULL, /* readlink */ NULL, /* follow_link */ + NULL, /* readpage */ + NULL, /* writepage */ NULL, /* bmap */ NULL, /* truncate */ NULL /* permission */ diff --git a/fs/umsdos/emd.c b/fs/umsdos/emd.c index b1ec47bf6..6295d0a98 100644 --- a/fs/umsdos/emd.c +++ b/fs/umsdos/emd.c @@ -5,65 +5,48 @@ * * Extended MS-DOS directory handling functions */ -#ifdef MODULE -#include <linux/module.h> -#endif #include <linux/types.h> #include <linux/fcntl.h> #include <linux/kernel.h> -#include <asm/segment.h> #include <linux/sched.h> #include <linux/errno.h> #include <linux/string.h> #include <linux/msdos_fs.h> #include <linux/umsdos_fs.h> +#include <asm/uaccess.h> + #define PRINTK(x) #define Printk(x) printk x -int umsdos_readdir_kmem( - struct inode *inode, - struct file *filp, - struct dirent *dirent, - int count) -{ - int ret; - int old_fs = get_fs(); - set_fs (KERNEL_DS); - ret = msdos_readdir(inode,filp,dirent,count); - set_fs (old_fs); - return ret; -} /* Read a file into kernel space memory */ -int umsdos_file_read_kmem( - struct inode *inode, +long umsdos_file_read_kmem (struct inode *inode, struct file *filp, char *buf, - int count) + unsigned long count) { int ret; int old_fs = get_fs(); set_fs (KERNEL_DS); - ret = msdos_file_read(inode,filp,buf,count); + ret = fat_file_read(inode,filp,buf,count); set_fs (old_fs); return ret; } /* Write to a file from kernel space */ -int umsdos_file_write_kmem( - struct inode *inode, +long umsdos_file_write_kmem (struct inode *inode, struct file *filp, - char *buf, - int count) + const char *buf, + unsigned long count) { int ret; int old_fs = get_fs(); set_fs (KERNEL_DS); - ret = msdos_file_write(inode,filp,buf,count); + ret = fat_file_write(inode,filp,buf,count); set_fs (old_fs); return ret; } @@ -75,11 +58,10 @@ int umsdos_file_write_kmem( Return 0 if ok, a negative error code if not. */ -int umsdos_emd_dir_write ( - struct inode *emd_dir, +long umsdos_emd_dir_write (struct inode *emd_dir, struct file *filp, char *buf, /* buffer in kernel memory, not in user space */ - int count) + unsigned long count) { int written; filp->f_flags = 0; @@ -91,18 +73,18 @@ int umsdos_emd_dir_write ( The block of data is NOT in user space. Return 0 if ok, -EIO if any error. */ -int umsdos_emd_dir_read ( - struct inode *emd_dir, +long umsdos_emd_dir_read (struct inode *emd_dir, struct file *filp, char *buf, /* buffer in kernel memory, not in user space */ - int count) + unsigned long count) { - int ret = 0; + long int ret = 0; int sizeread; filp->f_flags = 0; sizeread = umsdos_file_read_kmem (emd_dir,filp,buf,count); if (sizeread != count){ - printk ("UMSDOS: problem with EMD file. Can't read\n"); + printk ("UMSDOS: problem with EMD file. Can't read pos = %Ld (%d != %ld)\n" + ,filp->f_pos,sizeread,count); ret = -EIO; } return ret; diff --git a/fs/umsdos/file.c b/fs/umsdos/file.c index 61eacaac6..d01ef6f87 100644 --- a/fs/umsdos/file.c +++ b/fs/umsdos/file.c @@ -7,13 +7,6 @@ * Extended MS-DOS regular file handling primitives */ -#ifdef MODULE -#include <linux/module.h> -#endif - -#include <asm/segment.h> -#include <asm/system.h> - #include <linux/sched.h> #include <linux/fs.h> #include <linux/msdos_fs.h> @@ -23,20 +16,22 @@ #include <linux/msdos_fs.h> #include <linux/umsdos_fs.h> +#include <asm/uaccess.h> +#include <asm/system.h> #define PRINTK(x) #define Printk(x) printk x /* Read a file into user space memory */ -static int UMSDOS_file_read( +static long UMSDOS_file_read( struct inode *inode, struct file *filp, char *buf, - int count) + unsigned long count) { /* We have to set the access time because msdos don't care */ - int ret = msdos_file_read(inode,filp,buf,count); + int ret = fat_file_read(inode,filp,buf,count); if (!IS_RDONLY(inode)){ inode->i_atime = CURRENT_TIME; inode->i_dirt = 1; @@ -46,13 +41,13 @@ static int UMSDOS_file_read( /* Write a file from user space memory */ -static int UMSDOS_file_write( +static long UMSDOS_file_write( struct inode *inode, struct file *filp, - char *buf, - int count) + const char *buf, + unsigned long count) { - return msdos_file_write(inode,filp,buf,count); + return fat_file_write(inode,filp,buf,count); } /* Truncate a file to 0 length. @@ -60,7 +55,7 @@ static int UMSDOS_file_write( static void UMSDOS_truncate(struct inode *inode) { PRINTK (("UMSDOS_truncate\n")); - msdos_truncate (inode); + fat_truncate (inode); inode->i_ctime = inode->i_mtime = CURRENT_TIME; inode->i_dirt = 1; } @@ -73,7 +68,7 @@ struct file_operations umsdos_file_operations = { NULL, /* readdir - bad */ NULL, /* select - default */ NULL, /* ioctl - default */ - generic_mmap, /* mmap */ + generic_file_mmap, /* mmap */ NULL, /* no special open is needed */ NULL, /* release */ file_fsync /* fsync */ @@ -92,10 +87,12 @@ struct inode_operations umsdos_file_inode_operations = { NULL, /* rename */ NULL, /* readlink */ NULL, /* follow_link */ - msdos_bmap, /* bmap */ + generic_readpage, /* readpage */ + NULL, /* writepage */ + fat_bmap, /* bmap */ UMSDOS_truncate,/* truncate */ NULL, /* permission */ - msdos_smap /* smap */ + fat_smap /* smap */ }; /* For other with larger and unaligned file system */ struct file_operations umsdos_file_operations_no_bmap = { @@ -105,7 +102,7 @@ struct file_operations umsdos_file_operations_no_bmap = { NULL, /* readdir - bad */ NULL, /* select - default */ NULL, /* ioctl - default */ - msdos_mmap, /* mmap */ + fat_mmap, /* mmap */ NULL, /* no special open is needed */ NULL, /* release */ file_fsync /* fsync */ @@ -124,6 +121,8 @@ struct inode_operations umsdos_file_inode_operations_no_bmap = { NULL, /* rename */ NULL, /* readlink */ NULL, /* follow_link */ + NULL, /* readpage */ + NULL, /* writepage */ NULL, /* bmap */ UMSDOS_truncate,/* truncate */ NULL, /* permission */ diff --git a/fs/umsdos/inode.c b/fs/umsdos/inode.c index 22be740cc..8157edca6 100644 --- a/fs/umsdos/inode.c +++ b/fs/umsdos/inode.c @@ -6,20 +6,14 @@ * */ -#ifdef MODULE #include <linux/module.h> -#include <linux/version.h> -#else -#define MOD_INC_USE_COUNT -#define MOD_DEC_USE_COUNT -#endif #include <linux/fs.h> #include <linux/msdos_fs.h> #include <linux/kernel.h> #include <linux/sched.h> #include <linux/errno.h> -#include <asm/segment.h> +#include <asm/uaccess.h> #include <linux/string.h> #include <linux/stat.h> #include <linux/umsdos_fs.h> @@ -50,7 +44,7 @@ void UMSDOS_put_inode(struct inode *inode) if (inode != NULL && inode == pseudo_root){ printk ("Umsdos: Oops releasing pseudo_root. Notify jacques@solucorp.qc.ca\n"); } - msdos_put_inode(inode); + fat_put_inode(inode); } @@ -63,7 +57,7 @@ void UMSDOS_put_super(struct super_block *sb) void UMSDOS_statfs(struct super_block *sb,struct statfs *buf, int bufsiz) { - msdos_statfs(sb,buf,bufsiz); + fat_statfs(sb,buf,bufsiz); } @@ -233,7 +227,7 @@ void UMSDOS_read_inode(struct inode *inode) if (S_ISDIR(inode->i_mode) && (inode->u.umsdos_i.u.dir_info.creating != 0 || inode->u.umsdos_i.u.dir_info.looking != 0 - || inode->u.umsdos_i.u.dir_info.p != NULL)){ + || waitqueue_active(&inode->u.umsdos_i.u.dir_info.p))){ Printk (("read inode %d %d %p\n" ,inode->u.umsdos_i.u.dir_info.creating ,inode->u.umsdos_i.u.dir_info.looking @@ -263,7 +257,7 @@ void UMSDOS_write_inode(struct inode *inode) struct iattr newattrs; PRINTK (("UMSDOS_write_inode emd %d\n",inode->u.umsdos_i.i_emd_owner)); - msdos_write_inode(inode); + fat_write_inode(inode); newattrs.ia_mtime = inode->i_mtime; newattrs.ia_atime = inode->i_atime; newattrs.ia_ctime = inode->i_ctime; @@ -410,6 +404,7 @@ struct super_block *UMSDOS_read_super( printk ("UMSDOS Beta 0.6 (compatibility level %d.%d, fast msdos)\n" ,UMSDOS_VERSION,UMSDOS_RELEASE); if (sb != NULL){ + MSDOS_SB(sb)->options.dotsOK = 0; /* disable hidden==dotfile */ sb->s_op = &umsdos_sops; PRINTK (("umsdos_read_super %p\n",sb->s_mounted)); umsdos_setup_dir_inode (sb->s_mounted); @@ -499,18 +494,24 @@ struct super_block *UMSDOS_read_super( } -#ifdef MODULE - -char kernel_version[] = UTS_RELEASE; static struct file_system_type umsdos_fs_type = { UMSDOS_read_super, "umsdos", 1, NULL }; +int init_umsdos_fs(void) +{ + return register_filesystem(&umsdos_fs_type); +} + +#ifdef MODULE int init_module(void) { - register_filesystem(&umsdos_fs_type); - return 0; + int status; + + if ((status = init_umsdos_fs()) == 0) + register_symtab(0); + return status; } void cleanup_module(void) diff --git a/fs/umsdos/ioctl.c b/fs/umsdos/ioctl.c index d766ef939..a4d4108b8 100644 --- a/fs/umsdos/ioctl.c +++ b/fs/umsdos/ioctl.c @@ -5,12 +5,10 @@ * * Extended MS-DOS ioctl directory handling functions */ -#ifdef MODULE -#include <linux/module.h> -#endif -#include <asm/segment.h> +#include <asm/uaccess.h> #include <linux/errno.h> +#include <linux/mm.h> #include <linux/kernel.h> #include <linux/sched.h> #include <linux/fs.h> @@ -20,6 +18,37 @@ #define PRINTK(x) #define Printk(x) printk x +struct UMSDOS_DIR_ONCE { + struct dirent *ent; + int count; +}; + +/* + Record a single entry the first call. + Return -EINVAL the next one. +*/ +static int umsdos_ioctl_fill( + void * buf, + const char * name, + int name_len, + off_t offset, + ino_t ino) +{ + int ret = -EINVAL; + struct UMSDOS_DIR_ONCE *d = (struct UMSDOS_DIR_ONCE *)buf; + if (d->count == 0){ + copy_to_user (d->ent->d_name,name,name_len); + put_user ('\0',d->ent->d_name+name_len); + put_user (name_len,&d->ent->d_reclen); + put_user (ino,&d->ent->d_ino); + put_user (offset,&d->ent->d_off); + d->count = 1; + ret = 0; + } + return ret; +} + + /* Perform special function on a directory */ @@ -30,11 +59,19 @@ int UMSDOS_ioctl_dir ( unsigned long data) { int ret = -EPERM; + int err; /* #Specification: ioctl / acces Only root (effective id) is allowed to do IOCTL on directory in UMSDOS. EPERM is returned for other user. */ - if (current->euid == 0 + /* + Well, not all cases require write access, but it simplifies + the code, and let's face it, there is only one client (umssync) + for all this. + */ + if ((err = verify_area(VERIFY_WRITE,(void*)data,sizeof(struct umsdos_ioctl))) < 0) { + ret = err; + }else if (current->euid == 0 || cmd == UMSDOS_GETVERSION){ struct umsdos_ioctl *idata = (struct umsdos_ioctl *)data; ret = -EINVAL; @@ -69,8 +106,8 @@ int UMSDOS_ioctl_dir ( Return always 0. */ - put_fs_byte (UMSDOS_VERSION,&idata->version); - put_fs_byte (UMSDOS_RELEASE,&idata->release); + put_user(UMSDOS_VERSION,&idata->version); + put_user(UMSDOS_RELEASE,&idata->release); ret = 0; }else if (cmd == UMSDOS_READDIR_DOS){ /* #Specification: ioctl / UMSDOS_READDIR_DOS @@ -80,7 +117,11 @@ int UMSDOS_ioctl_dir ( Return > 0 if success. */ - ret = msdos_readdir(dir,filp,&idata->dos_dirent,1); + struct UMSDOS_DIR_ONCE bufk; + bufk.count = 0; + bufk.ent = &idata->dos_dirent; + fat_readdir(dir,filp,&bufk,umsdos_ioctl_fill); + ret = bufk.count == 1 ? 1 : 0; }else if (cmd == UMSDOS_READDIR_EMD){ /* #Specification: ioctl / UMSDOS_READDIR_EMD One entry is read from the EMD at the current @@ -111,9 +152,9 @@ int UMSDOS_ioctl_dir ( umsdos_parse (entry.name,entry.name_len,&info); info.f_pos = f_pos; umsdos_manglename(&info); - memcpy_tofs(&idata->umsdos_dirent,&entry + copy_to_user(&idata->umsdos_dirent,&entry ,sizeof(entry)); - memcpy_tofs(&idata->dos_dirent.d_name + copy_to_user(&idata->dos_dirent.d_name ,info.fake.fname,info.fake.len+1); break; } @@ -146,7 +187,7 @@ int UMSDOS_ioctl_dir ( : &umsdos_rdir_inode_operations; }else{ struct umsdos_ioctl data; - memcpy_fromfs (&data,idata,sizeof(data)); + copy_from_user (&data,idata,sizeof(data)); if (cmd == UMSDOS_CREAT_EMD){ /* #Specification: ioctl / UMSDOS_CREAT_EMD The umsdos_dirent field of the struct umsdos_ioctl is used @@ -178,7 +219,7 @@ int UMSDOS_ioctl_dir ( ret = msdos_rename (dir ,data.dos_dirent.d_name,data.dos_dirent.d_reclen ,dir - ,data.umsdos_dirent.name,data.umsdos_dirent.name_len); + ,data.umsdos_dirent.name,data.umsdos_dirent.name_len,0); }else if (cmd == UMSDOS_UNLINK_EMD){ /* #Specification: ioctl / UMSDOS_UNLINK_EMD The umsdos_dirent field of the struct umsdos_ioctl is used @@ -240,7 +281,7 @@ int UMSDOS_ioctl_dir ( data.stat.st_atime = inode->i_atime; data.stat.st_ctime = inode->i_ctime; data.stat.st_mtime = inode->i_mtime; - memcpy_tofs (&idata->stat,&data.stat,sizeof(data.stat)); + copy_to_user (&idata->stat,&data.stat,sizeof(data.stat)); iput (inode); } }else if (cmd == UMSDOS_DOS_SETUP){ @@ -263,9 +304,9 @@ int UMSDOS_ioctl_dir ( umsdos_dirent.uid and gid sets the owner and group. umsdos_dirent.mode set the permissions flags. */ - dir->i_sb->u.msdos_sb.fs_uid = data.umsdos_dirent.uid; - dir->i_sb->u.msdos_sb.fs_gid = data.umsdos_dirent.gid; - dir->i_sb->u.msdos_sb.fs_umask = data.umsdos_dirent.mode; + dir->i_sb->u.msdos_sb.options.fs_uid = data.umsdos_dirent.uid; + dir->i_sb->u.msdos_sb.options.fs_gid = data.umsdos_dirent.gid; + dir->i_sb->u.msdos_sb.options.fs_umask = data.umsdos_dirent.mode; ret = 0; } } diff --git a/fs/umsdos/mangle.c b/fs/umsdos/mangle.c index a7649a39a..fb94b89c8 100644 --- a/fs/umsdos/mangle.c +++ b/fs/umsdos/mangle.c @@ -5,13 +5,9 @@ * * Control the mangling of file name to fit msdos name space. * Many optimisation by GLU == dglaude@is1.vub.ac.be (GLAUDE DAVID) -*/ -#ifdef MODULE -#include <linux/module.h> -#endif + */ #include <linux/errno.h> -#include <linux/ctype.h> #include <linux/string.h> #include <linux/kernel.h> #include <linux/umsdos_fs.h> @@ -175,7 +171,7 @@ int umsdos_parse ( like this. */ int i; - static char *spc = "\"*+,/:;<=>?[\\]|~"; + static const char *spc = "\"*+,/:;<=>?[\\]|~"; is_init = 1; for (i=0; i<=32; i++) lkp[i] = '#'; for (i=33; i<'A'; i++) lkp[i] = (char)i; diff --git a/fs/umsdos/namei.c b/fs/umsdos/namei.c index 42820bb98..51cfb0809 100644 --- a/fs/umsdos/namei.c +++ b/fs/umsdos/namei.c @@ -5,10 +5,7 @@ * Inspired from linux/fs/msdos/... by Werner Almesberger * * Maintain and access the --linux alternate directory file. -*/ -#ifdef MODULE -#include <linux/module.h> -#endif + */ #include <linux/errno.h> #include <linux/kernel.h> @@ -126,7 +123,6 @@ void umsdos_startlookup (struct inode *dir) while (umsdos_waitcreate (dir) != 0); dir->u.umsdos_i.u.dir_info.looking++; } -void check_page_tables(void); /* Unlock the directory. @@ -357,7 +353,8 @@ chkstk(); ret = msdos_rename (old_dir ,old_info.fake.fname,old_info.fake.len ,new_dir - ,new_info.fake.fname,new_info.fake.len); + ,new_info.fake.fname,new_info.fake.len + ,0); chkstk(); PRINTK (("after m_rename ret %d ",ret)); if (ret != 0){ @@ -437,7 +434,7 @@ static int umsdos_symlink_x( in unused entry of the EMD file. The other is to have a separate file dedicated to hold all symbolic links data. - Lets go for simplicity... + Let's go for simplicity... */ struct inode *inode; int ret; @@ -450,7 +447,7 @@ static int umsdos_symlink_x( struct file filp; filp.f_pos = 0; /* Make the inode acceptable to MSDOS */ - ret = umsdos_file_write_kmem (inode,&filp,(char*)symname,len); + ret = umsdos_file_write_kmem (inode,&filp,symname,len); iput (inode); if (ret >= 0){ if (ret != len){ @@ -1018,7 +1015,8 @@ int UMSDOS_rename( int old_len, struct inode * new_dir, const char * new_name, - int new_len) + int new_len, + int must_be_dir) { /* #Specification: weakness / rename There is a case where UMSDOS rename has a different behavior diff --git a/fs/umsdos/rdir.c b/fs/umsdos/rdir.c index d708709bd..da07c0d61 100644 --- a/fs/umsdos/rdir.c +++ b/fs/umsdos/rdir.c @@ -7,12 +7,6 @@ * (For directory without EMD file). */ -#ifdef MODULE -#include <linux/module.h> -#endif - -#include <asm/segment.h> - #include <linux/sched.h> #include <linux/fs.h> #include <linux/msdos_fs.h> @@ -22,50 +16,65 @@ #include <linux/umsdos_fs.h> #include <linux/malloc.h> +#include <asm/uaccess.h> + #define PRINTK(x) #define Printk(x) printk x extern struct inode *pseudo_root; -static int UMSDOS_rreaddir ( - struct inode *dir, - struct file *filp, - struct dirent *dirent, - int count) +struct RDIR_FILLDIR { + void *dirbuf; + filldir_t filldir; + int real_root; +}; + +static int rdir_filldir( + void * buf, + const char * name, + int name_len, + off_t offset, + ino_t ino) { int ret = 0; - while (1){ - int len = -1; - ret = msdos_readdir(dir,filp,dirent,count); - if (ret > 0) len = get_fs_word(&dirent->d_reclen); - if (len == 5 - && pseudo_root != NULL - && dir->i_sb->s_mounted == pseudo_root->i_sb->s_mounted){ - /* - In pseudo root mode, we must eliminate logically - the directory linux from the real root. - */ - char name[5]; - memcpy_fromfs (name,dirent->d_name,5); - if (memcmp(name,UMSDOS_PSDROOT_NAME,UMSDOS_PSDROOT_LEN)!=0) break; - }else{ - if (pseudo_root != NULL - && len == 2 - && dir == dir->i_sb->s_mounted - && dir == pseudo_root->i_sb->s_mounted){ - char name[2]; - memcpy_fromfs (name,dirent->d_name,2); - if (name[0] == '.' && name[1] == '.'){ - put_fs_long (pseudo_root->i_ino,&dirent->d_ino); - } + struct RDIR_FILLDIR *d = (struct RDIR_FILLDIR*) buf; + if (d->real_root){ + /* real root of a pseudo_rooted partition */ + if (name_len != UMSDOS_PSDROOT_LEN + || memcmp(name,UMSDOS_PSDROOT_NAME,UMSDOS_PSDROOT_LEN)!=0){ + /* So it is not the /linux directory */ + if (name_len == 2 + && name[0] == '.' + && name[1] == '.'){ + /* Make sure the .. entry points back to the pseudo_root */ + ino = pseudo_root->i_ino; } - break; + ret = d->filldir (d->dirbuf,name,name_len,offset,ino); } + }else{ + /* Any DOS directory */ + ret = d->filldir (d->dirbuf,name,name_len,offset,ino); } return ret; } + +static int UMSDOS_rreaddir ( + struct inode *dir, + struct file *filp, + void *dirbuf, + filldir_t filldir) +{ + struct RDIR_FILLDIR bufk; + bufk.filldir = filldir; + bufk.dirbuf = dirbuf; + bufk.real_root = pseudo_root != NULL + && dir == dir->i_sb->s_mounted + && dir == pseudo_root->i_sb->s_mounted; + return fat_readdir(dir,filp,&bufk,rdir_filldir); +} + /* Lookup into a non promoted directory. If the result is a directory, make sure we find out if it is @@ -252,6 +261,8 @@ struct inode_operations umsdos_rdir_inode_operations = { msdos_rename, /* rename */ NULL, /* readlink */ NULL, /* follow_link */ + NULL, /* readpage */ + NULL, /* writepage */ NULL, /* bmap */ NULL, /* truncate */ NULL /* permission */ diff --git a/fs/umsdos/symlink.c b/fs/umsdos/symlink.c index 6ab27c5dd..7bbcc0ef0 100644 --- a/fs/umsdos/symlink.c +++ b/fs/umsdos/symlink.c @@ -6,12 +6,6 @@ * * Extended MS-DOS regular file handling primitives */ -#ifdef MODULE -#include <linux/module.h> -#endif - -#include <asm/segment.h> -#include <asm/system.h> #include <linux/sched.h> #include <linux/fs.h> @@ -22,8 +16,12 @@ #include <linux/umsdos_fs.h> #include <linux/malloc.h> +#include <asm/uaccess.h> +#include <asm/system.h> + #define PRINTK(x) #define Printk(x) printk x + /* Read the data associate with the symlink. Return length read in buffer or a negative error code. @@ -31,7 +29,7 @@ static int umsdos_readlink_x ( struct inode *inode, char *buffer, - int (*msdos_read)(struct inode *, struct file *, char *, int), + long (*msdos_read)(struct inode *, struct file *, char *, unsigned long), int bufsiz) { int ret = inode->i_size; @@ -105,7 +103,7 @@ static int UMSDOS_readlink(struct inode * inode, char * buffer, int buflen) { int ret = -EINVAL; if (S_ISLNK(inode->i_mode)) { - ret = umsdos_readlink_x (inode,buffer,msdos_file_read,buflen); + ret = umsdos_readlink_x (inode,buffer,fat_file_read,buflen); } PRINTK (("readlink %d %x bufsiz %d\n",ret,inode->i_mode,buflen)); iput(inode); @@ -139,6 +137,8 @@ struct inode_operations umsdos_symlink_inode_operations = { NULL, /* rename */ UMSDOS_readlink, /* readlink */ UMSDOS_follow_link, /* follow_link */ + NULL, /* readpage */ + NULL, /* writepage */ NULL, /* bmap */ NULL, /* truncate */ NULL /* permission */ |