Commit f48455d2 authored by Linus Torvalds's avatar Linus Torvalds

Import 1.1.35

parent 57dabd37
......@@ -53,7 +53,6 @@ S: The Netherlands
N: Hennus Bergman
E: hennus@sky.nl.mugnet.org [My uucp-fed Linux box at home]
E: csg279@wing.rug.nl [Alternate address]
D: Author and maintainer of the QIC-02 tape driver
S: The Netherlands
......
VERSION = 1
PATCHLEVEL = 1
SUBLEVEL = 34
SUBLEVEL = 35
all: Version zImage
......
......@@ -150,6 +150,7 @@ bool 'Extended fs support' CONFIG_EXT_FS n
bool 'Second extended fs support' CONFIG_EXT2_FS y
bool 'xiafs filesystem support' CONFIG_XIA_FS n
bool 'msdos fs support' CONFIG_MSDOS_FS y
bool 'umsdos: Unix like fs on top of std MSDOS FAT fs' CONFIG_UMSDOS_FS n
bool '/proc filesystem support' CONFIG_PROC_FS y
if [ "$CONFIG_INET" = "y" ]; then
bool 'NFS filesystem support' CONFIG_NFS_FS y
......@@ -169,7 +170,22 @@ fi
bool 'Microsoft busmouse support' CONFIG_MS_BUSMOUSE n
bool 'ATIXL busmouse support' CONFIG_ATIXL_BUSMOUSE n
bool 'Selection (cut and paste for virtual consoles)' CONFIG_SELECTION n
bool 'QIC-02 tape support' CONFIG_TAPE_QIC02 n
bool 'QIC-02 tape support' CONFIG_QIC02_TAPE n
if [ "$CONFIG_QIC02_TAPE" = "y" ]; then
bool 'Do you want runtime configuration for QIC-02' CONFIG_QIC02_DYNCONF y
if [ "$CONFIG_QIC02_DYNCONF" != "y" ]; then
comment '>>> Edit configuration parameters in ./include/linux/tpqic02.h!'
else
comment '>>> Setting runtime QIC-02 configuration is done with qic02conf'
comment '>>> Which is available from ftp://ftp.funet.fi/pub/OS/Linux/BETA/QIC-02/'
fi
fi
bool 'QIC-117 tape support' CONFIG_FTAPE n
if [ "$CONFIG_FTAPE" = "y" ]; then
int ' number of ftape buffers' NR_FTAPE_BUFFERS 3
......
......@@ -58,7 +58,7 @@ OBJS := $(OBJS) psaux.o
SRCS := $(SRCS) psaux.c
endif
ifdef CONFIG_TAPE_QIC02
ifdef CONFIG_QIC02_TAPE
OBJS := $(OBJS) tpqic02.o
SRCS := $(SRCS) tpqic02.c
endif
......
......@@ -156,7 +156,7 @@ static struct {
/* misc */
unsigned long vc_ques : 1;
unsigned long vc_need_wrap : 1;
unsigned long vc_report_mouse : 1;
unsigned long vc_report_mouse : 2;
unsigned long vc_tab_stop[5]; /* Tab stops. 160 columns. */
unsigned char * vc_translate;
unsigned char * vc_G0_charset;
......@@ -848,12 +848,15 @@ static void set_mode(int currcons, int on_off)
clr_kbd(decarm);
break;
case 9:
report_mouse = on_off;
report_mouse = on_off ? 1 : 0;
break;
case 25: /* Cursor on/off */
deccm = on_off;
set_cursor(currcons);
break;
case 1000:
report_mouse = on_off ? 2 : 0;
break;
} else switch(par[i]) { /* ANSI modes set/reset */
case 4: /* Insert Mode on/off */
decim = on_off;
......@@ -1858,11 +1861,11 @@ static inline short limit(const int v, const int l, const int u)
}
/* invoked via ioctl(TIOCLINUX) */
int mouse_reporting_p(void)
int mouse_reporting(void)
{
int currcons = fg_console;
return ((report_mouse) ? 0 : -EINVAL);
return report_mouse;
}
/* set the current selection. Invoked by ioctl(). */
......
......@@ -411,8 +411,8 @@ long chr_dev_init(long mem_start, long mem_end)
#ifdef CONFIG_SOUND
mem_start = soundcard_init(mem_start);
#endif
#if CONFIG_TAPE_QIC02
mem_start = tape_qic02_init(mem_start);
#if CONFIG_QIC02_TAPE
mem_start = qic02_tape_init(mem_start);
#endif
/*
* Rude way to allocate kernel memory buffer for tape device
......
This diff is collapsed.
......@@ -69,7 +69,7 @@
extern int set_selection(const int arg, struct tty_struct *tty);
extern int paste_selection(struct tty_struct *tty);
extern int sel_loadlut(const int arg);
extern int mouse_reporting_p(void);
extern int mouse_reporting(void);
extern int shift_state;
#endif /* CONFIG_SELECTION */
extern int do_screendump(int arg);
......@@ -1394,7 +1394,8 @@ static int tty_ioctl(struct inode * inode, struct file * file,
put_fs_byte(shift_state,arg);
return 0;
case 7:
return mouse_reporting_p();
put_fs_byte(mouse_reporting(),arg);
return 0;
#endif /* CONFIG_SELECTION */
default:
return -EINVAL;
......
......@@ -62,8 +62,6 @@ int autoirq_setup(int waittime)
int i, mask;
int timeout = jiffies+waittime;
irq_number = 0;
irq_bitmap = 0;
irq_handled = 0;
for (i = 0; i < 16; i++) {
if (!irqaction(i, &autoirq_sigaction))
......@@ -71,6 +69,8 @@ int autoirq_setup(int waittime)
}
/* Update our USED lists. */
irqs_used |= ~irq_handled;
irq_number = 0;
irq_bitmap = 0;
/* Hang out at least <waittime> jiffies waiting for bogus IRQ hits. */
while (timeout > jiffies)
......
......@@ -305,7 +305,7 @@ static inline unsigned char xchgb(unsigned char reg,
volatile unsigned char *mem)
{
asm("xchgb %0,%1" :
"=r" (reg), "=m" (*(unsigned char *)mem) :
"=q" (reg), "=m" (*(unsigned char *)mem) :
"0" (reg), "1" (*(unsigned char *)mem));
return reg;
}
......
......@@ -33,6 +33,9 @@ endif
ifdef CONFIG_XIA_FS
FS_SUBDIRS := $(FS_SUBDIRS) xiafs
endif
ifdef CONFIG_UMSDOS_FS
FS_SUBDIRS := $(FS_SUBDIRS) umsdos
endif
ifdef CONFIG_SYSV_FS
FS_SUBDIRS := $(FS_SUBDIRS) sysv
endif
......
......@@ -14,6 +14,7 @@
#include <linux/ext2_fs.h>
#include <linux/xia_fs.h>
#include <linux/msdos_fs.h>
#include <linux/umsdos_fs.h>
#include <linux/proc_fs.h>
#include <linux/nfs_fs.h>
#include <linux/iso_fs.h>
......@@ -52,6 +53,10 @@ asmlinkage int sys_setup(void)
register_filesystem(&(struct file_system_type)
{xiafs_read_super, "xiafs", 1, NULL});
#endif
#ifdef CONFIG_UMSDOS_FS
register_filesystem(&(struct file_system_type)
{UMSDOS_read_super, "umsdos", 1, NULL});
#endif
#ifdef CONFIG_MSDOS_FS
register_filesystem(&(struct file_system_type)
......
......@@ -14,7 +14,7 @@
.s.o:
$(AS) -o $*.o $<
OBJS= namei.o inode.o file.o dir.o misc.o fat.o
OBJS= namei.o inode.o file.o dir.o misc.o fat.o mmap.o
msdos.o: $(OBJS)
$(LD) -r -o msdos.o $(OBJS)
......
......@@ -12,6 +12,7 @@
#include <linux/msdos_fs.h>
#include <linux/errno.h>
#include <linux/stat.h>
#include <linux/string.h>
static int msdos_dir_read(struct inode * inode,struct file * filp, char * buf,int count)
......@@ -19,7 +20,7 @@ static int msdos_dir_read(struct inode * inode,struct file * filp, char * buf,in
return -EISDIR;
}
static int msdos_readdir(struct inode *inode,struct file *filp,
int msdos_readdir(struct inode *inode,struct file *filp,
struct dirent *dirent,int count);
......@@ -54,8 +55,11 @@ struct inode_operations msdos_dir_inode_operations = {
NULL /* permission */
};
static int msdos_readdir(struct inode *inode,struct file *filp,
struct dirent *dirent,int count)
int msdos_readdir(
struct inode *inode,
struct file *filp,
struct dirent *dirent, /* dirent in user space */
int count)
{
int ino,i,i2,last;
char c,*walk;
......@@ -67,33 +71,39 @@ static int msdos_readdir(struct inode *inode,struct file *filp,
/* Fake . and .. for the root directory. */
if (filp->f_pos == 2) filp->f_pos = 0;
else if (filp->f_pos < 2) {
walk = filp->f_pos++ ? ".." : ".";
for (i = 0; *walk; walk++)
put_fs_byte(*walk,dirent->d_name+i++);
put_fs_long(MSDOS_ROOT_INO,&dirent->d_ino);
put_fs_byte(0,dirent->d_name+i);
put_fs_word(i,&dirent->d_reclen);
return i;
}
walk = filp->f_pos++ ? ".." : ".";
for (i = 0; *walk; walk++)
put_fs_byte(*walk,dirent->d_name+i++);
put_fs_long(MSDOS_ROOT_INO,&dirent->d_ino);
put_fs_byte(0,dirent->d_name+i);
put_fs_word(i,&dirent->d_reclen);
return i;
}
}
if (filp->f_pos & (sizeof(struct msdos_dir_entry)-1)) return -ENOENT;
bh = NULL;
while ((ino = msdos_get_entry(inode,&filp->f_pos,&bh,&de)) > -1) {
if (!IS_FREE(de->name) && !(de->attr & ATTR_VOLUME)) {
char bufname[13];
char *ptname = bufname;
for (i = last = 0; i < 8; i++) {
if (!(c = de->name[i])) break;
if (c >= 'A' && c <= 'Z') c += 32;
if (c != ' ') last = i+1;
put_fs_byte(c,i+dirent->d_name);
if (c != ' '){
last = i+1;
*ptname++ = c;
}
}
i = last;
put_fs_byte('.',i+dirent->d_name);
*ptname++ = '.';
i++;
for (i2 = 0; i2 < 3; i2++) {
if (!(c = de->ext[i2])) break;
if (c >= 'A' && c <= 'Z') c += 32;
if (c != ' ') last = i+1;
put_fs_byte(c,i+dirent->d_name);
if (c != ' '){
last = i+1;
*ptname++ = c;
}
i++;
}
if ((i = last) != 0) {
......@@ -101,8 +111,9 @@ static int msdos_readdir(struct inode *inode,struct file *filp,
ino = inode->i_ino;
else if (!strcmp(de->name,MSDOS_DOTDOT))
ino = msdos_parent_ino(inode,0);
bufname[i] = '\0';
put_fs_long(ino,&dirent->d_ino);
put_fs_byte(0,i+dirent->d_name);
memcpy_tofs(dirent->d_name,bufname,i+1);
put_fs_word(i,&dirent->d_reclen);
brelse(bh);
return i;
......
......@@ -15,16 +15,11 @@
#include <linux/errno.h>
#include <linux/fcntl.h>
#include <linux/stat.h>
#include <linux/string.h>
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
static int msdos_file_read(struct inode *inode,struct file *filp,char *buf,
int count);
static int msdos_file_write(struct inode *inode,struct file *filp,char *buf,
int count);
static struct file_operations msdos_file_operations = {
NULL, /* lseek - default */
msdos_file_read, /* read */
......@@ -32,7 +27,7 @@ static struct file_operations msdos_file_operations = {
NULL, /* readdir - bad */
NULL, /* select - default */
NULL, /* ioctl - default */
NULL, /* mmap */
msdos_mmap, /* mmap */
NULL, /* no special open is needed */
NULL, /* release */
file_fsync /* fsync */
......@@ -53,7 +48,8 @@ struct inode_operations msdos_file_inode_operations = {
NULL, /* follow_link */
msdos_bmap, /* bmap */
msdos_truncate, /* truncate */
NULL /* permission */
NULL, /* permission */
msdos_smap /* smap */
};
/* No bmap for MS-DOS FS' that don't align data at kByte boundaries. */
......@@ -73,12 +69,19 @@ struct inode_operations msdos_file_inode_operations_no_bmap = {
NULL, /* follow_link */
NULL, /* bmap */
msdos_truncate, /* truncate */
NULL /* permission */
NULL, /* permission */
msdos_smap /* smap */
};
static int msdos_file_read(struct inode *inode,struct file *filp,char *buf,
int count)
/*
Read a file into user space
*/
int msdos_file_read(
struct inode *inode,
struct file *filp,
char *buf,
int count)
{
char *start;
int left,offset,size,sector,cnt;
......@@ -91,7 +94,8 @@ static int msdos_file_read(struct inode *inode,struct file *filp,char *buf,
printk("msdos_file_read: inode = NULL\n");
return -EINVAL;
}
if (!S_ISREG(inode->i_mode)) {
/* S_ISLNK allows for UMSDOS. Should never happen for normal MSDOS */
if (!S_ISREG(inode->i_mode) && !S_ISLNK(inode->i_mode)) {
printk("msdos_file_read: mode = %07o\n",inode->i_mode);
return -EINVAL;
}
......@@ -131,9 +135,14 @@ static int msdos_file_read(struct inode *inode,struct file *filp,char *buf,
return buf-start;
}
static int msdos_file_write(struct inode *inode,struct file *filp,char *buf,
int count)
/*
Write to a file either from user space
*/
int msdos_file_write(
struct inode *inode,
struct file *filp,
char *buf,
int count)
{
int sector,offset,size,left,written;
int error,carry;
......@@ -145,7 +154,8 @@ static int msdos_file_write(struct inode *inode,struct file *filp,char *buf,
printk("msdos_file_write: inode = NULL\n");
return -EINVAL;
}
if (!S_ISREG(inode->i_mode)) {
/* S_ISLNK allows for UMSDOS. Should never happen for normal MSDOS */
if (!S_ISREG(inode->i_mode) && !S_ISLNK(inode->i_mode)) {
printk("msdos_file_write: mode = %07o\n",inode->i_mode);
return -EINVAL;
}
......@@ -211,7 +221,6 @@ static int msdos_file_write(struct inode *inode,struct file *filp,char *buf,
return buf-start;
}
void msdos_truncate(struct inode *inode)
{
int cluster;
......
/*
* fs/msdos/mmap.c
*
* Written by Jacques Gelinas (jacques@solucorp.qc.ca)
* Inspired by fs/nfs/mmap.c (Jaon Tombs 15 Aug 1993)
*
* msdos mmap handling
*/
#include <linux/stat.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/shm.h>
#include <linux/errno.h>
#include <linux/mman.h>
#include <linux/string.h>
#include <linux/malloc.h>
#include <asm/segment.h>
#include <asm/system.h>
#include <linux/msdos_fs.h>
/*
* Fill in the supplied page for mmap
*/
static unsigned long msdos_file_mmap_nopage(
struct vm_area_struct * area,
unsigned long address,
unsigned long page,
int error_code)
{
struct inode * inode = area->vm_inode;
unsigned int clear;
int pos;
long gap; /* distance from eof to pos */
address &= PAGE_MASK;
pos = address - area->vm_start + area->vm_offset;
clear = 0;
gap = inode->i_size - pos;
if (gap <= 0){
/* mmaping beyong end of file */
clear = PAGE_SIZE;
}else{
int cur_read;
int need_read;
struct file filp;
if (gap < PAGE_SIZE){
clear = PAGE_SIZE - gap;
}
filp.f_pos = pos;
need_read = PAGE_SIZE - clear;
{
unsigned long cur_fs = get_fs();
set_fs (KERNEL_DS);
cur_read = msdos_file_read (inode,&filp,(char*)page
,need_read);
set_fs (cur_fs);
}
if (cur_read != need_read){
printk ("MSDOS: Error while reading an mmap file %d <> %d\n"
,cur_read,need_read);
}
}
if (clear > 0){
memset ((char*)page+PAGE_SIZE-clear,0,clear);
}
return page;
}
struct vm_operations_struct msdos_file_mmap = {
NULL, /* open */
NULL, /* close */
msdos_file_mmap_nopage, /* nopage */
NULL, /* wppage */
NULL, /* share */
NULL, /* unmap */
};
/*
* This is used for a general mmap of an msdos file
* Returns 0 if ok, or a negative error code if not.
*/
int msdos_mmap(
struct inode * inode,
struct file * file,
unsigned long addr,
size_t len,
int prot,
unsigned long off)
{
struct vm_area_struct * mpnt;
if (prot & PAGE_RW) /* only PAGE_COW or read-only supported now */
return -EINVAL;
if (off & (inode->i_sb->s_blocksize - 1))
return -EINVAL;
if (!inode->i_sb || !S_ISREG(inode->i_mode))
return -EACCES;
if (!IS_RDONLY(inode)) {
inode->i_atime = CURRENT_TIME;
inode->i_dirt = 1;
}
mpnt = (struct vm_area_struct * ) kmalloc(sizeof(struct vm_area_struct), GFP_KERNEL);
if (!mpnt)
return -ENOMEM;
unmap_page_range(addr, len);
mpnt->vm_task = current;
mpnt->vm_start = addr;
mpnt->vm_end = addr + len;
mpnt->vm_page_prot = prot;
mpnt->vm_share = NULL;
mpnt->vm_inode = inode;
inode->i_count++;
mpnt->vm_offset = off;
mpnt->vm_ops = &msdos_file_mmap;
insert_vm_struct (current,mpnt);
merge_segments (current->mm->mmap,NULL,NULL);
return 0;
}
......@@ -360,7 +360,11 @@ int msdos_rmdir(struct inode *dir,const char *name,int len)
}
int msdos_unlink(struct inode *dir,const char *name,int len)
static int msdos_unlinkx(
struct inode *dir,
const char *name,
int len,
int nospc) /* Flag special file ? */
{
int res,ino;
struct buffer_head *bh;
......@@ -375,7 +379,7 @@ int msdos_unlink(struct inode *dir,const char *name,int len)
res = -ENOENT;
goto unlink_done;
}
if (!S_ISREG(inode->i_mode)) {
if (!S_ISREG(inode->i_mode) && nospc){
res = -EPERM;
goto unlink_done;
}
......@@ -392,6 +396,17 @@ int msdos_unlink(struct inode *dir,const char *name,int len)
return res;
}
int msdos_unlink(struct inode *dir,const char *name,int len)
{
return msdos_unlinkx (dir,name,len,1);
}
/*
Special entry for umsdos
*/
int msdos_unlink_umsdos(struct inode *dir,const char *name,int len)
{
return msdos_unlinkx (dir,name,len,0);
}
static int rename_same_dir(struct inode *old_dir,char *old_name,
struct inode *new_dir,char *new_name,struct buffer_head *old_bh,
......
#
# Makefile for the umsdos unix-like filesystem routines.
#
# Note! Dependencies are done automagically by 'make dep', which also
# removes any old dependencies. DON'T put your own dependencies here
# unless it's something special (ie not a .c file).
#
# 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 $<
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)
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
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
Permisssions 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/ALPHA/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 optionnal. 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 and maintain them. It is available
from the same directory above (sunsite) in the file umsdos_progs-0.3.tar.gz.
A compiled version is available in umsdos-0.3a.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-.---.
Hope this helps!
#include <asm/system.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/head.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/ptrace.h>
#include <linux/mman.h>
extern unsigned long high_memory;
static int check_one_table(unsigned long * page_dir)
{
unsigned long pg_table = *page_dir;
if (!pg_table)
return 0;
if (pg_table >= high_memory || !(pg_table & PAGE_PRESENT)) {
return 1;
}
return 0;
}
/*
* This function frees up all page tables of a process when it exits.
*/
void check_page_tables(void)
{
unsigned long pg_dir;
static int err = 0;
int stack_level = (long)(&pg_dir)-current->kernel_stack_page;
if (stack_level < 1500) printk ("** %d ** ",stack_level);
pg_dir = current->tss.cr3;
if (mem_map[MAP_NR(pg_dir)] > 1) {
return;
}
if (err == 0){
unsigned long *page_dir = (unsigned long *) pg_dir;
unsigned long *base = page_dir;
int i;
for (i = 0 ; i < PTRS_PER_PAGE ; i++,page_dir++){
int notok = check_one_table(page_dir);
if (notok){
err++;
printk ("|%d| ",page_dir-base);
}
}
if (err) printk ("Erreur MM %d\n",err);
}
}
This diff is collapsed.
This diff is collapsed.
/*
* linux/fs/umsdos/file.c
*
* Written 1993 by Jacques Gelinas
* inpired from linux/fs/msdos/file.c Werner Almesberger
*
* Extended MS-DOS regular file handling primitives
*/
#include <asm/segment.h>
#include <asm/system.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/msdos_fs.h>
#include <linux/errno.h>
#include <linux/fcntl.h>
#include <linux/stat.h>
#include <linux/msdos_fs.h>
#include <linux/umsdos_fs.h>
#define PRINTK(x)
#define Printk(x) printk x
/*
Read a file into user space memory
*/
static int UMSDOS_file_read(
struct inode *inode,
struct file *filp,
char *buf,
int count)
{
/* We have to set the access time because msdos don't care */
int ret = msdos_file_read(inode,filp,buf,count);
inode->i_atime = CURRENT_TIME;
inode->i_dirt = 1;
return ret;
}
/*
Write a file from user space memory
*/
static int UMSDOS_file_write(
struct inode *inode,
struct file *filp,
char *buf,
int count)
{
return msdos_file_write(inode,filp,buf,count);
}
/*
Truncate a file to 0 length.
*/
static void UMSDOS_truncate(struct inode *inode)
{
PRINTK (("UMSDOS_truncate\n"));
msdos_truncate (inode);
inode->i_ctime = inode->i_mtime = CURRENT_TIME;
inode->i_dirt = 1;
}
/*
See inode.c
Some entry point are filled dynamicly with function pointers
from the msdos file_operations and file_inode_operations.
The idea is to have the code as independant as possible from
the msdos file system.
*/
struct file_operations umsdos_file_operations = {
NULL, /* lseek - default */
UMSDOS_file_read, /* read */
UMSDOS_file_write, /* write */
NULL, /* readdir - bad */
NULL, /* select - default */
NULL, /* ioctl - default */
msdos_mmap, /* mmap */
NULL, /* no special open is needed */
NULL, /* release */
NULL /* fsync */
};
struct inode_operations umsdos_file_inode_operations = {
&umsdos_file_operations, /* default file operations */
NULL, /* create */
NULL, /* lookup */
NULL, /* link */
NULL, /* unlink */
NULL, /* symlink */
NULL, /* mkdir */
NULL, /* rmdir */
NULL, /* mknod */
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
NULL, /* bmap */
UMSDOS_truncate,/* truncate */
NULL, /* permission */
msdos_smap /* smap */
};
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This file contain idea and things I don't want to forget
Possible bug in fs/read_write.c
Function sys_readdir()
There is a call the verify_area that does not take in account
the count parameter. I guess it should read
error = verify_area(VERIFY_WRITE, dirent, count*sizeof (*dirent));
instead of
error = verify_area(VERIFY_WRITE, dirent, sizeof (*dirent));
Of course, now , count is always 1
This diff is collapsed.
/*
* linux/fs/umsdos/file.c
*
* Written 1992 by Jacques Gelinas
* inpired from linux/fs/msdos/file.c Werner Almesberger
*
* Extended MS-DOS regular file handling primitives
*/
#include <asm/segment.h>
#include <asm/system.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/msdos_fs.h>
#include <linux/errno.h>
#include <linux/fcntl.h>
#include <linux/stat.h>
#include <linux/umsdos_fs.h>
#include <linux/malloc.h>
#define PRINTK(x)
#define Printk(x) printk x
/*
Read the data associate with the symlink.
Return lenght read in buffer or a negative error code.
*/
static int umsdos_readlink_x (
struct inode *inode,
char *buffer,
int (*msdos_read)(struct inode *, struct file *, char *, int),
int bufsiz)
{
int ret = inode->i_size;
struct file filp;
filp.f_pos = 0;
if (ret > bufsiz) ret = bufsiz;
if ((*msdos_read) (inode, &filp, buffer,ret) != ret){
ret = -EIO;
}
return ret;
}
/*
Follow a symbolic link chain by calling open_namei recursivly
until an inode is found.
Return 0 if ok, or a negative error code if not.
*/
static int UMSDOS_follow_link(
struct inode * dir,
struct inode * inode,
int flag,
int mode,
struct inode ** res_inode)
{
int ret = -ELOOP;
*res_inode = NULL;
if (current->link_count < 5) {
char *path = (char*)kmalloc(PATH_MAX,GFP_KERNEL);
if (path == NULL){
ret = -ENOMEM;
}else{
if (!dir) {
dir = current->fs[1].root;
dir->i_count++;
}
if (!inode){
PRINTK (("symlink: inode = NULL\n"));
ret = -ENOENT;
}else if (!S_ISLNK(inode->i_mode)){
PRINTK (("symlink: Not ISLNK\n"));
*res_inode = inode;
inode = NULL;
ret = 0;
}else{
ret = umsdos_readlink_x (inode,path
,umsdos_file_read_kmem,PATH_MAX-1);
if (ret > 0){
path[ret] = '\0';
PRINTK (("follow :%s: %d ",path,ret));
iput(inode);
inode = NULL;
current->link_count++;
ret = open_namei(path,flag,mode,res_inode,dir);
current->link_count--;
dir = NULL;
}else{
ret = -EIO;
}
}
kfree (path);
}
}
iput(inode);
iput(dir);
PRINTK (("follow_link ret %d\n",ret));
return ret;
}
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);
}
PRINTK (("readlink %d %x bufsiz %d\n",ret,inode->i_mode,buflen));
iput(inode);
return ret;
}
static struct file_operations umsdos_symlink_operations = {
NULL, /* lseek - default */
NULL, /* read */
NULL, /* write */
NULL, /* readdir - bad */
NULL, /* select - default */
NULL, /* ioctl - default */
NULL, /* mmap */
NULL, /* no special open is needed */
NULL, /* release */
NULL /* fsync */
};
struct inode_operations umsdos_symlink_inode_operations = {
&umsdos_symlink_operations, /* default file operations */
NULL, /* create */
NULL, /* lookup */
NULL, /* link */
NULL, /* unlink */
NULL, /* symlink */
NULL, /* mkdir */
NULL, /* rmdir */
NULL, /* mknod */
NULL, /* rename */
UMSDOS_readlink, /* readlink */
UMSDOS_follow_link, /* follow_link */
NULL, /* bmap */
NULL, /* truncate */
NULL /* permission */
};
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment