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;
......@@ -80,20 +84,26 @@ static int msdos_readdir(struct inode *inode,struct file *filp,
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,11 +69,18 @@ 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,
/*
Read a file into user space
*/
int msdos_file_read(
struct inode *inode,
struct file *filp,
char *buf,
int count)
{
char *start;
......@@ -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,8 +135,13 @@ 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,
/*
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;
......@@ -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.
/*
* linux/fs/umsdos/ioctl.c
*
* Written 1993 by Jacques Gelinas
*
* Extended MS-DOS ioctl directory handling functions
*/
#include <asm/segment.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/msdos_fs.h>
#include <linux/umsdos_fs.h>
#define PRINTK(x)
#define Printk(x) printk x
/*
Perform special function on a directory
*/
int UMSDOS_ioctl_dir (
struct inode *dir,
struct file *filp,
unsigned int cmd,
unsigned long data)
{
int ret = -EPERM;
/* #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
|| cmd == UMSDOS_GETVERSION){
struct umsdos_ioctl *idata = (struct umsdos_ioctl *)data;
ret = -EINVAL;
/* #Specification: ioctl / prototypes
The official prototype for the umsdos ioctl on directory
is:
int ioctl (
int fd, // File handle of the directory
int cmd, // command
struct umsdos_ioctl *data)
The struct and the commands are defined in linux/umsdos_fs.h.
umsdos_progs/umsdosio.c provide an interface in C++ to all
these ioctl. umsdos_progs/udosctl is a small utility showing
all this.
These ioctl generally allow one to work on the EMD or the
DOS directory independantly. These are essential to implement
the synchroniser.
*/
PRINTK (("ioctl %d ",cmd));
if (cmd == UMSDOS_GETVERSION){
/* #Specification: ioctl / UMSDOS_GETVERSION
The field version and release of the structure
umsdos_ioctl are filled with the version and release
number of the fs code in the kernel. This will allow
some form of checking. Users won't be able to run
incompatible utility such as the synchroniser (umssync).
umsdos_progs/umsdosio.c enforce this checking.
Return always 0.
*/
put_fs_byte (UMSDOS_VERSION,&idata->version);
put_fs_byte (UMSDOS_RELEASE,&idata->release);
ret = 0;
}else if (cmd == UMSDOS_READDIR_DOS){
/* #Specification: ioctl / UMSDOS_READDIR_DOS
One entry is read from the DOS directory at the current
file position. The entry is put as is in the dos_dirent
field of struct umsdos_ioctl.
Return > 0 if success.
*/
ret = msdos_readdir(dir,filp,&idata->dos_dirent,1);
}else if (cmd == UMSDOS_READDIR_EMD){
/* #Specification: ioctl / UMSDOS_READDIR_EMD
One entry is read from the EMD at the current
file position. The entry is put as is in the umsdos_dirent
field of struct umsdos_ioctl. The corresponding mangled
DOS entry name is put in the dos_dirent field.
All entries are read including hidden links. Blank
entries are skipped.
Return > 0 if success.
*/
struct inode *emd_dir = umsdos_emd_dir_lookup (dir,0);
if (emd_dir != NULL){
while (1){
if (filp->f_pos >= emd_dir->i_size){
ret = 0;
break;
}else{
struct umsdos_dirent entry;
off_t f_pos = filp->f_pos;
ret = umsdos_emd_dir_readentry (emd_dir,filp,&entry);
if (ret < 0){
break;
}else if (entry.name_len > 0){
struct umsdos_info info;
ret = entry.name_len;
umsdos_parse (entry.name,entry.name_len,&info);
info.f_pos = f_pos;
umsdos_manglename(&info);
memcpy_tofs(&idata->umsdos_dirent,&entry
,sizeof(entry));
memcpy_tofs(&idata->dos_dirent.d_name
,info.fake.fname,info.fake.len+1);
break;
}
}
}
iput (emd_dir);
}else{
/* The absence of the EMD is simply seen as an EOF */
ret = 0;
}
}else if (cmd == UMSDOS_INIT_EMD){
/* #Specification: ioctl / UMSDOS_INIT_EMD
The UMSDOS_INIT_EMD command make sure the EMD
exist for a directory. If it does not, it is
created. Also, it makes sure the directory functions
table (struct inode_operations) is set to the UMSDOS
semantic. This mean that umssync may be applied to
an "opened" msdos directory, and it will change behavior
on the fly.
Return 0 if success.
*/
extern struct inode_operations umsdos_rdir_inode_operations;
struct inode *emd_dir = umsdos_emd_dir_lookup (dir,1);
ret = emd_dir != NULL;
iput (emd_dir);
dir->i_op = ret
? &umsdos_dir_inode_operations
: &umsdos_rdir_inode_operations;
}else{
struct umsdos_ioctl data;
memcpy_fromfs (&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
as is to create a new entry in the EMD of the directory.
The DOS directory is not modified.
No validation is done (yet).
Return 0 if success.
*/
struct umsdos_info info;
/* This makes sure info.entry and info in general is correctly */
/* initialised */
memcpy (&info.entry,&data.umsdos_dirent
,sizeof(data.umsdos_dirent));
umsdos_parse (data.umsdos_dirent.name
,data.umsdos_dirent.name_len,&info);
ret = umsdos_newentry (dir,&info);
}else if (cmd == UMSDOS_UNLINK_EMD){
/* #Specification: ioctl / UMSDOS_UNLINK_EMD
The umsdos_dirent field of the struct umsdos_ioctl is used
as is to remove an entry from the EMD of the directory.
No validation is done (yet). The mode field is used
to validate S_ISDIR or S_ISREG.
Return 0 if success.
*/
struct umsdos_info info;
/* This makes sure info.entry and info in general is correctly */
/* initialised */
memcpy (&info.entry,&data.umsdos_dirent
,sizeof(data.umsdos_dirent));
umsdos_parse (data.umsdos_dirent.name
,data.umsdos_dirent.name_len,&info);
ret = umsdos_delentry (dir,&info
,S_ISDIR(data.umsdos_dirent.mode));
}else if (cmd == UMSDOS_UNLINK_DOS){
/* #Specification: ioctl / UMSDOS_UNLINK_DOS
The dos_dirent field of the struct umsdos_ioctl is used to
execute a msdos_unlink operation. The d_name and d_reclen
fields are used.
Return 0 if success.
*/
dir->i_count++;
ret = msdos_unlink (dir,data.dos_dirent.d_name
,data.dos_dirent.d_reclen);
}else if (cmd == UMSDOS_RMDIR_DOS){
/* #Specification: ioctl / UMSDOS_RMDIR_DOS
The dos_dirent field of the struct umsdos_ioctl is used to
execute a msdos_unlink operation. The d_name and d_reclen
fields are used.
Return 0 if success.
*/
dir->i_count++;
ret = msdos_rmdir (dir,data.dos_dirent.d_name
,data.dos_dirent.d_reclen);
}else if (cmd == UMSDOS_STAT_DOS){
/* #Specification: ioctl / UMSDOS_STAT_DOS
The dos_dirent field of the struct umsdos_ioctl is
used to execute a stat operation in the DOS directory.
The d_name and d_reclen fields are used.
The following field of umsdos_ioctl.stat are filled.
st_ino,st_mode,st_size,st_atime,st_mtime,st_ctime,
Return 0 if success.
*/
struct inode *inode;
ret = umsdos_real_lookup (dir,data.dos_dirent.d_name
,data.dos_dirent.d_reclen,&inode);
if (ret == 0){
data.stat.st_ino = inode->i_ino;
data.stat.st_mode = inode->i_mode;
data.stat.st_size = inode->i_size;
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));
iput (inode);
}
}else if (cmd == UMSDOS_DOS_SETUP){
/* #Specification: ioctl / UMSDOS_DOS_SETUP
The UMSDOS_DOS_SETUP ioctl allow changing the
default permission of the MsDOS file system driver
on the fly. The MsDOS driver apply global permission
to every file and directory. Normally these permissions
are controlled by a mount option. This is not
available for root partition, so a special utility
(umssetup) is provided to do this, normally in
/etc/rc.local.
Be aware that this apply ONLY to MsDOS directory
(those without EMD --linux-.---). Umsdos directory
have independant (standard) permission for each
and every file.
The field umsdos_dirent provide the information needed.
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;
ret = 0;
}
}
}
PRINTK (("ioctl return %d\n",ret));
return ret;
}
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.
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