Commit c0cf5000 authored by Linus Torvalds's avatar Linus Torvalds

[PATCH] Linux-0.98.6 (December 2, 1992)

Kai Makisara does the SCSI tape driver.  He's one of the few original
maintainers still around as such..

isofs introduced by Eric Youngdale, based on the minixfs code.  Eric was
a physicist, and you can tell he was new to C - he has been
Pascal-damaged, and has extra semi-colons at the end of block
statements.  But soon he ended up being one of the core maintainers
anyway, and took over SCSI maintenance.

More aggressive filesystem read-ahead introduced.

[Original announcement below]

Anyway, 0.98pl6 is hopefully the last release before 0.99: there are a
few known problems left in this release.  Most notable is the serial
code: it works for most people, but others still have problems with it.
I hope this will get fixed within a week (tytso is working on it).  It
also seems as if the PS/2 mouse code has some problems.

pl6 contains these fixes:

 - all the tcp/ip patches I've received (and I fixed one bug that
   gcc-2.3 seems to have found).
 - math-emu patch for the problem that resulted in FPU errors with some
   operations.
 - I fixed gcc-2.3 warnings as well as most of the old warnings.  You
   shouldn't get more than one or two warnings when recompiling the
   whole kernel.
 - /proc filesystem extensions.  Based on ideas (and some code) by
   Darren Senn, but mostly written by yours truly.  More about that
   later.
 - some tty_io fixes (there was a bug in the /dev/console handling when
   you changed VC's while using the general console device).
 - re-organization of the keyboard-driver internal data-structures.  The
   changes are mostly preliminary: they change the keyboard flags to be
   more easily adaptive to a reprogrammable keyboard driver.  No actual
   new features yet.
 - new SCSI drivers: reportedly much faster than the old ones (but not
   all drivers take advantage of it yet..)
 - various other fixes: pty's etc have minor changes.

I hope to make 0.99 in a week or so, and 1.0 after that has been tested
some.  I hope people will test out pl6 - 0.99 won't be much different,
and if you don't test pl6, any bugs relating to your particular hardware
may not be found in time for 0.99...

                Linus
parent a35eb8da
......@@ -92,7 +92,7 @@ LD86 =ld86 -0
AS =as
LD =ld
HOSTCC =gcc -static
HOSTCC =gcc
CC =gcc -DKERNEL
MAKE =make
CPP =$(CC) -E $(LIMIT_MEMORY)
......@@ -127,7 +127,7 @@ linuxsubdirs: dummy
Version:
@./makever.sh
@echo \#define UTS_RELEASE \"0.98.pl5-`cat .version`\" > tools/version.h
@echo \#define UTS_RELEASE \"0.98.pl6-`cat .version`\" > tools/version.h
@echo \#define UTS_VERSION \"`date +%D`\" >> tools/version.h
@echo \#define LINUX_COMPILE_TIME \"`date +%T`\" >> tools/version.h
@echo \#define LINUX_COMPILE_BY \"`whoami`\" >> tools/version.h
......@@ -170,11 +170,11 @@ boot/setup: boot/setup.s
$(AS86) -o boot/setup.o boot/setup.s
$(LD86) -s -o boot/setup boot/setup.o
boot/setup.s: boot/setup.S include/linux/config.h Makefile
$(CPP) -traditional $(SVGA_MODE) boot/setup.S -o boot/setup.s
boot/setup.s: boot/setup.S include/linux/config.h
$(CPP) -traditional boot/setup.S -o boot/setup.s
boot/bootsect.s: boot/bootsect.S include/linux/config.h
$(CPP) -traditional boot/bootsect.S -o boot/bootsect.s
boot/bootsect.s: boot/bootsect.S include/linux/config.h Makefile
$(CPP) -traditional $(SVGA_MODE) $(RAMDISK) boot/bootsect.S -o boot/bootsect.s
boot/bootsect: boot/bootsect.s
$(AS86) -o boot/bootsect.o boot/bootsect.s
......@@ -208,15 +208,16 @@ depend dep:
dummy:
### Dependencies:
init/main.o : init/main.c /usr/lib/gcc-lib/i386-linux/2.2.2d/include/stdarg.h /usr/include/asm/system.h \
init/main.o : init/main.c /usr/lib/gcc-lib/i386-linux/2.3.2/include/stdarg.h /usr/include/asm/system.h \
/usr/include/asm/io.h /usr/include/linux/mktime.h /usr/include/linux/types.h \
/usr/include/linux/fcntl.h /usr/include/linux/config.h /usr/include/linux/config.dist.h \
/usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \
/usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/dirent.h \
/usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \
/usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h \
/usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h \
/usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
/usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
/usr/include/linux/math_emu.h /usr/include/linux/tty.h /usr/include/linux/termios.h \
/usr/include/linux/unistd.h /usr/include/linux/string.h
/usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
/usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
/usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
/usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
/usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
/usr/include/linux/tty.h /usr/include/linux/termios.h /usr/include/linux/unistd.h \
/usr/include/linux/string.h
......@@ -40,6 +40,12 @@ ENDSEG = SYSSEG + SYSSIZE ! where to stop loading
! ROOT_DEV & SWAP_DEV are now written by "build".
ROOT_DEV = 0
SWAP_DEV = 0
#ifndef SVGA_MODE
#define SVGA_MODE ASK_VGA
#endif
#ifndef RAMDISK
#define RAMDISK 0
#endif
! ld86 requires an entry symbol. This may as well be the usual one.
.globl _main
......@@ -425,9 +431,13 @@ msg1:
.byte 13,10
.ascii "Loading"
.org 506
.org 502
swap_dev:
.word SWAP_DEV
ram_size:
.word RAMDISK
vid_mode:
.word SVGA_MODE
root_dev:
.word ROOT_DEV
boot_flag:
......
......@@ -265,7 +265,9 @@ getkey:
chsvga: cld
push ds
push cs
mov ax,[0x01fa]
pop ds
mov modesave,ax
mov ax,#0xc000
mov es,ax
mov ax,modesave
......
This diff is collapsed.
......@@ -7,6 +7,7 @@
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/locks.h>
#include <asm/segment.h>
#include <asm/system.h>
......@@ -56,40 +57,154 @@ int block_write(struct inode * inode, struct file * filp, char * buf, int count)
return written;
}
#define NBUF 16
int block_read(struct inode * inode, struct file * filp, char * buf, int count)
{
unsigned int block = filp->f_pos >> BLOCK_SIZE_BITS;
unsigned int offset = filp->f_pos & (BLOCK_SIZE-1);
int blocks, left;
int bhrequest;
int ra_blocks, max_block, nextblock;
struct buffer_head ** bhb, ** bhe;
struct buffer_head * buflist[NBUF];
struct buffer_head * bhreq[NBUF];
unsigned int chars;
unsigned int size;
unsigned int dev;
int read = 0;
struct buffer_head * bh;
register char * p;
dev = inode->i_rdev;
if (blk_size[MAJOR(dev)])
size = blk_size[MAJOR(dev)][MINOR(dev)];
size = blk_size[MAJOR(dev)][MINOR(dev)] << BLOCK_SIZE_BITS;
else
size = 0x7fffffff;
while (count>0) {
if (block >= size)
return read;
chars = BLOCK_SIZE-offset;
if (chars > count)
chars = count;
if (!(bh = breada(dev,block,block+1,block+2,-1)))
return read?read:-EIO;
block++;
p = offset + bh->b_data;
offset = 0;
filp->f_pos += chars;
read += chars;
count -= chars;
memcpy_tofs(buf,p,chars);
p += chars;
buf += chars;
brelse(bh);
}
if (filp->f_pos > size)
left = 0;
else
left = size - filp->f_pos;
if (left > count)
left = count;
if (left <= 0)
return 0;
blocks = (left + offset + BLOCK_SIZE - 1) / BLOCK_SIZE;
bhb = bhe = buflist;
ra_blocks = read_ahead[MAJOR(dev)] / (BLOCK_SIZE >> 9);
max_block = size;
nextblock = -1;
/* We do this in a two stage process. We first try and request
as many blocks as we can, then we wait for the first one to
complete, and then we try and wrap up as many as are actually
done. This routine is rather generic, in that it can be used
in a filesystem by substituting the appropriate function in
for getblk.
This routine is optimized to make maximum use of the various
buffers and caches. */
do {
bhrequest = 0;
while (blocks) {
int uptodate;
--blocks;
*bhb = getblk(dev, block++, BLOCK_SIZE);
uptodate = 1;
if (*bhb && !(*bhb)->b_uptodate) {
uptodate = 0;
bhreq[bhrequest++] = *bhb;
nextblock = (*bhb)->b_blocknr + 1;
};
if (++bhb == &buflist[NBUF])
bhb = buflist;
/* If the block we have on hand is uptodate, go ahead
and complete processing. */
if(bhrequest == 0 && uptodate) break;
if (bhb == bhe)
break;
}
if(blocks == 0 && bhrequest && filp->f_reada && bhb != bhe) {
/* If we are going to read something anyways, add in the
read-ahead blocks */
while(ra_blocks){
if (block >= max_block) break;
if(bhrequest == NBUF) break; /* Block full */
--ra_blocks;
*bhb = getblk(dev, block++, BLOCK_SIZE);
if (*bhb && !(*bhb)->b_uptodate) {
if((*bhb)->b_blocknr != nextblock) {
brelse(*bhb);
break;
};
nextblock = (*bhb)->b_blocknr + 1;
bhreq[bhrequest++] = *bhb;
};
if (++bhb == &buflist[NBUF])
bhb = buflist;
if (bhb == bhe)
break;
};
};
/* Now request them all */
if (bhrequest)
ll_rw_block(READ, bhrequest, bhreq);
do{ /* Finish off all I/O that has actually completed */
if (*bhe) {/* test for valid buffer */
wait_on_buffer(*bhe);
if (!(*bhe)->b_uptodate) {
do {
brelse(*bhe);
if (++bhe == &buflist[NBUF])
bhe = buflist;
} while (bhe != bhb);
break;
}
}
if (left < BLOCK_SIZE - offset)
chars = left;
else
chars = BLOCK_SIZE - offset;
filp->f_pos += chars;
left -= chars;
read += chars;
if (*bhe) {
memcpy_tofs(buf,offset+(*bhe)->b_data,chars);
brelse(*bhe);
buf += chars;
} else {
while (chars-->0)
put_fs_byte(0,buf++);
}
offset = 0;
if (++bhe == &buflist[NBUF])
bhe = buflist;
} while( bhe != bhb && (*bhe == 0 || !(*bhe)->b_lock) &&
(left > 0));
} while (left > 0);
/* Release the read-ahead blocks */
while (bhe != bhb) {
if (*bhe) brelse(*bhe);
if (++bhe == &buflist[NBUF])
bhe = buflist;
};
filp->f_reada = 1;
if (!read)
return -EIO;
return read;
}
......@@ -43,6 +43,7 @@ static struct buffer_head * unused_list = NULL;
static struct wait_queue * buffer_wait = NULL;
int nr_buffers = 0;
int buffermem = 0;
int nr_buffer_heads = 0;
/*
......@@ -306,7 +307,8 @@ struct buffer_head * getblk(dev_t dev, int block, int size)
int buffers;
repeat:
if (bh = get_hash_table(dev, block, size)) {
bh = get_hash_table(dev, block, size);
if (bh) {
if (bh->b_uptodate && !bh->b_dirt)
put_last_free(bh);
return bh;
......@@ -417,15 +419,21 @@ __asm__("cld\n\t" \
void bread_page(unsigned long address, dev_t dev, int b[4])
{
struct buffer_head * bh[4];
struct buffer_head * bhr[4];
int bhnum = 0;
int i;
for (i=0 ; i<4 ; i++)
if (b[i]) {
if (bh[i] = getblk(dev, b[i], 1024))
if (!bh[i]->b_uptodate)
ll_rw_block(READ, 1, &bh[i]);
bh[i] = getblk(dev, b[i], 1024);
if (bh[i] && !bh[i]->b_uptodate)
bhr[bhnum++] = bh[i];
} else
bh[i] = NULL;
if(bhnum)
ll_rw_block(READ, bhnum, bhr);
for (i=0 ; i<4 ; i++,address += BLOCK_SIZE)
if (bh[i]) {
wait_on_buffer(bh[i]);
......@@ -564,6 +572,7 @@ void grow_buffers(int size)
break;
}
tmp->b_this_page = bh;
buffermem += 4096;
return;
/*
* In case anything failed, we just free everything we got.
......@@ -605,6 +614,7 @@ static int try_to_free(struct buffer_head * bh)
remove_from_queues(p);
put_unused_buffer_head(p);
} while (tmp != bh);
buffermem -= 4096;
free_page(page);
return 1;
}
......
......@@ -128,7 +128,7 @@ int core_dump(long signr, struct pt_regs * regs)
/* Flag indicating the math stuff is valid. We don't support this for the
soft-float routines yet */
if (hard_math) {
if (dump.u_fpvalid = current->used_math) {
if ((dump.u_fpvalid = current->used_math) != 0) {
if (last_task_used_math == current)
__asm__("clts ; fnsave %0"::"m" (dump.i387));
else
......@@ -264,7 +264,7 @@ static int count(char ** argv)
int i=0;
char ** tmp;
if (tmp = argv)
if ((tmp = argv) != 0)
while (get_fs_long((unsigned long *) (tmp++)))
i++;
......@@ -481,7 +481,7 @@ int do_execve(unsigned long * eip,long tmp,char * filename,
brelse(bh);
iput(inode);
buf[127] = '\0';
if (cp = strchr(buf, '\n')) {
if ((cp = strchr(buf, '\n')) != NULL) {
*cp = '\0';
for (cp = buf; (*cp == ' ') || (*cp == '\t'); cp++);
}
......
This diff is collapsed.
......@@ -69,6 +69,8 @@ static int ext_readdir(struct inode * inode, struct file * filp,
if (!inode || !S_ISDIR(inode->i_mode))
return -EBADF;
if (filp->f_pos % 8 != 0)
return -EBADF;
while (filp->f_pos < inode->i_size) {
offset = filp->f_pos & 1023;
bh = ext_bread(inode,(filp->f_pos)>>BLOCK_SIZE_BITS,0);
......@@ -78,18 +80,22 @@ static int ext_readdir(struct inode * inode, struct file * filp,
}
de = (struct ext_dir_entry *) (offset + bh->b_data);
while (offset < 1024 && filp->f_pos < inode->i_size) {
offset += de->rec_len;
filp->f_pos += de->rec_len;
if (de->rec_len < 8 || de->rec_len % 4 != 0 ||
de->rec_len < de->name_len + 8) {
printk ("ext_readdir: bad directory entry\n");
if (de->rec_len < 8 || de->rec_len % 8 != 0 ||
de->rec_len < de->name_len + 8 ||
(de->rec_len + filp->f_pos - 1) / 1024 > (filp->f_pos / 1024)) {
printk ("ext_readdir: bad dir entry, skipping\n");
printk ("dev=%d, dir=%d, offset=%d, rec_len=%d, name_len=%d\n",
inode->i_dev, inode->i_ino, offset, de->rec_len, de->name_len);
return 0;
filp->f_pos += 1024-offset;
if (filp->f_pos > inode->i_size)
filp->f_pos = inode->i_size;
continue;
}
offset += de->rec_len;
filp->f_pos += de->rec_len;
if (de->inode) {
for (i = 0; i < de->name_len; i++)
if (c = de->name[i])
if ((c = de->name[i]) != 0)
put_fs_byte(c,i+dirent->d_name);
else
break;
......
......@@ -71,7 +71,10 @@ static int ext_file_read(struct inode * inode, struct file * filp, char * buf, i
{
int read,left,chars;
int block, blocks, offset;
int bhrequest;
int ra_blocks, max_block, nextblock;
struct buffer_head ** bhb, ** bhe;
struct buffer_head * bhreq[NBUF];
struct buffer_head * buflist[NBUF];
if (!inode) {
......@@ -95,50 +98,118 @@ static int ext_file_read(struct inode * inode, struct file * filp, char * buf, i
offset = filp->f_pos & (BLOCK_SIZE-1);
blocks = (left + offset + BLOCK_SIZE - 1) / BLOCK_SIZE;
bhb = bhe = buflist;
ra_blocks = read_ahead[MAJOR(inode->i_dev)] / (BLOCK_SIZE >> 9);
max_block = (inode->i_size + BLOCK_SIZE - 1)/BLOCK_SIZE;
nextblock = -1;
/* We do this in a two stage process. We first try and request
as many blocks as we can, then we wait for the first one to
complete, and then we try and wrap up as many as are actually
done. This routine is rather generic, in that it can be used
in a filesystem by substituting the appropriate function in
for getblk.
This routine is optimized to make maximum use of the various
buffers and caches. */
do {
if (blocks) {
bhrequest = 0;
while (blocks) {
int uptodate;
--blocks;
*bhb = ext_getblk(inode,block++,0);
if (*bhb && !(*bhb)->b_uptodate)
ll_rw_block(READ, 1, bhb);
*bhb = ext_getblk(inode, block++, 0);
uptodate = 1;
if (*bhb && !(*bhb)->b_uptodate) {
uptodate = 0;
bhreq[bhrequest++] = *bhb;
nextblock = (*bhb)->b_blocknr + 1;
};
if (++bhb == &buflist[NBUF])
bhb = buflist;
if (bhb != bhe)
continue;
}
if (*bhe) {
wait_on_buffer(*bhe);
if (!(*bhe)->b_uptodate) {
do {
brelse(*bhe);
if (++bhe == &buflist[NBUF])
bhe = buflist;
} while (bhe != bhb);
/* If the block we have on hand is uptodate, go ahead
and complete processing. */
if(bhrequest == 0 && uptodate) break;
if (bhb == bhe)
break;
}
}
}
if (left < BLOCK_SIZE - offset)
chars = left;
else
chars = BLOCK_SIZE - offset;
filp->f_pos += chars;
left -= chars;
read += chars;
if (*bhe) {
memcpy_tofs(buf,offset+(*bhe)->b_data,chars);
if(blocks == 0 && bhrequest && filp->f_reada && bhb != bhe) {
/* If we are going to read something anyways, add in the
read-ahead blocks */
while(ra_blocks){
if (block >= max_block) break;
if(bhrequest == NBUF) break; /* Block full */
--ra_blocks;
*bhb = ext_getblk(inode, block++, 0);
if (*bhb && !(*bhb)->b_uptodate) {
if((*bhb)->b_blocknr != nextblock) {
brelse(*bhb);
break;
};
nextblock = (*bhb)->b_blocknr + 1;
bhreq[bhrequest++] = *bhb;
};
if (++bhb == &buflist[NBUF])
bhb = buflist;
if (bhb == bhe)
break;
};
};
/* Now request them all */
if (bhrequest)
ll_rw_block(READ, bhrequest, bhreq);
do{ /* Finish off all I/O that has actually completed */
if (*bhe) {/* test for valid buffer */
wait_on_buffer(*bhe);
if (!(*bhe)->b_uptodate) {
do {
brelse(*bhe);
buf += chars;
} else {
while (chars-->0)
put_fs_byte(0,buf++);
}
offset = 0;
if (++bhe == &buflist[NBUF])
bhe = buflist;
if (++bhe == &buflist[NBUF])
bhe = buflist;
} while (bhe != bhb);
break;
}
}
if (left < BLOCK_SIZE - offset)
chars = left;
else
chars = BLOCK_SIZE - offset;
filp->f_pos += chars;
left -= chars;
read += chars;
if (*bhe) {
memcpy_tofs(buf,offset+(*bhe)->b_data,chars);
brelse(*bhe);
buf += chars;
} else {
while (chars-->0)
put_fs_byte(0,buf++);
}
offset = 0;
if (++bhe == &buflist[NBUF])
bhe = buflist;
} while( bhe != bhb && (*bhe == 0 || !(*bhe)->b_lock) &&
(left > 0));
} while (left > 0);
/* Release the read-ahead blocks */
while (bhe != bhb) {
if (*bhe) brelse(*bhe);
if (++bhe == &buflist[NBUF])
bhe = buflist;
};
filp->f_reada = 1;
if (!read)
return -EIO;
if (!IS_RDONLY(inode)) {
......
......@@ -32,6 +32,7 @@
#include <linux/sched.h>
#include <linux/ext_fs.h>
#include <linux/stat.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/locks.h>
......@@ -230,15 +231,17 @@ printk("ext_free_inode: inode full, skipping to %d\n", inode->i_ino);
clear_inode(inode);
}
struct inode * ext_new_inode(struct super_block * sb)
struct inode * ext_new_inode(const struct inode * dir)
{
struct super_block * sb;
struct inode * inode;
struct ext_free_inode * efi;
unsigned long block;
int j;
if (!sb || !(inode=get_empty_inode()))
if (!dir || !(inode=get_empty_inode()))
return NULL;
sb = dir->i_sb;
inode->i_sb = sb;
inode->i_flags = sb->s_flags;
if (!sb->u.ext_sb.s_firstfreeinodeblock)
......@@ -275,7 +278,7 @@ printk("ext_free_inode: inode empty, skipping to %d\n", efi->next);
inode->i_nlink = 1;
inode->i_dev = sb->s_dev;
inode->i_uid = current->euid;
inode->i_gid = current->egid;
inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->egid;
inode->i_dirt = 1;
inode->i_ino = j;
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
......
......@@ -122,18 +122,23 @@ static struct buffer_head * ext_find_entry(struct inode * dir,
if (prev_dir)
*prev_dir = NULL;
}
if (de->rec_len < 8 || de->rec_len % 4 != 0 ||
de->rec_len < de->name_len + 8) {
if (de->rec_len < 8 || de->rec_len % 8 != 0 ||
de->rec_len < de->name_len + 8 ||
(((char *) de) + de->rec_len-1 >= BLOCK_SIZE+bh->b_data)) {
printk ("ext_find_entry: bad dir entry\n");
printk ("dev=%d, dir=%d, offset=%d, rec_len=%d, name_len=%d\n",
dir->i_dev, dir->i_ino, offset, de->rec_len, de->name_len);
brelse (bh);
return NULL;
de = (struct ext_dir_entry *) (bh->b_data+BLOCK_SIZE);
offset = ((offset / BLOCK_SIZE) + 1) * BLOCK_SIZE;
continue;
/* brelse (bh);
return NULL; */
}
if (ext_match(namelen,name,de)) {
*res_dir = de;
if (next_dir)
if (offset + de->rec_len < dir->i_size)
if (offset + de->rec_len < dir->i_size &&
((char *)de) + de->rec_len < BLOCK_SIZE+bh->b_data)
*next_dir = (struct ext_dir_entry *)
((char *) de + de->rec_len);
else
......@@ -221,15 +226,15 @@ printk ("ext_add_entry: skipping to next block\n");
#endif
brelse(bh);
bh = NULL;
bh = ext_bread(dir,offset>>BLOCK_SIZE_BITS,1);
bh = ext_bread(dir,offset>>BLOCK_SIZE_BITS,0);
if (!bh)
return NULL;
de = (struct ext_dir_entry *) bh->b_data;
}
if (offset >= dir->i_size) {
/* Check that the directory entry fits in the block */
if (offset % BLOCK_SIZE == 0
|| (BLOCK_SIZE - (offset % BLOCK_SIZE)) < rec_len) {
if (offset % BLOCK_SIZE == 0 ||
(BLOCK_SIZE - (offset % BLOCK_SIZE)) < rec_len) {
if ((offset % BLOCK_SIZE) != 0) {
/* If the entry does not fit in the
block, the remainder of the block
......@@ -262,7 +267,8 @@ printk ("ext_add_entry : creating next block\n");
dir->i_ctime = CURRENT_TIME;
}
if (de->rec_len < 8 || de->rec_len % 4 != 0 ||
de->rec_len < de->name_len + 8) {
de->rec_len < de->name_len + 8 ||
(((char *) de) + de->rec_len-1 >= BLOCK_SIZE+bh->b_data)) {
printk ("ext_addr_entry: bad dir entry\n");
printk ("dev=%d, dir=%d, offset=%d, rec_len=%d, name_len=%d\n",
dir->i_dev, dir->i_ino, offset, de->rec_len, de->name_len);
......@@ -307,7 +313,7 @@ int ext_create(struct inode * dir,const char * name, int len, int mode,
*result = NULL;
if (!dir)
return -ENOENT;
inode = ext_new_inode(dir->i_sb);
inode = ext_new_inode(dir);
if (!inode) {
iput(dir);
return -ENOSPC;
......@@ -345,7 +351,7 @@ int ext_mknod(struct inode * dir, const char * name, int len, int mode, int rdev
iput(dir);
return -EEXIST;
}
inode = ext_new_inode(dir->i_sb);
inode = ext_new_inode(dir);
if (!inode) {
iput(dir);
return -ENOSPC;
......@@ -355,8 +361,11 @@ int ext_mknod(struct inode * dir, const char * name, int len, int mode, int rdev
inode->i_op = NULL;
if (S_ISREG(inode->i_mode))
inode->i_op = &ext_file_inode_operations;
else if (S_ISDIR(inode->i_mode))
else if (S_ISDIR(inode->i_mode)) {
inode->i_op = &ext_dir_inode_operations;
if (dir->i_mode & S_ISGID)
inode->i_mode |= S_ISGID;
}
else if (S_ISLNK(inode->i_mode))
inode->i_op = &ext_symlink_inode_operations;
else if (S_ISCHR(inode->i_mode))
......@@ -403,7 +412,7 @@ int ext_mkdir(struct inode * dir, const char * name, int len, int mode)
iput(dir);
return -EEXIST;
}
inode = ext_new_inode(dir->i_sb);
inode = ext_new_inode(dir);
if (!inode) {
iput(dir);
return -ENOSPC;
......@@ -437,6 +446,8 @@ int ext_mkdir(struct inode * dir, const char * name, int len, int mode)
dir_block->b_dirt = 1;
brelse(dir_block);
inode->i_mode = S_IFDIR | (mode & 0777 & ~current->umask);
if (dir->i_mode & S_ISGID)
inode->i_mode |= S_ISGID;
inode->i_dirt = 1;
bh = ext_add_entry(dir,name,len,&de);
if (!bh) {
......@@ -617,7 +628,7 @@ int ext_symlink(struct inode * dir, const char * name, int len, const char * sym
int i;
char c;
if (!(inode = ext_new_inode(dir->i_sb))) {
if (!(inode = ext_new_inode(dir))) {
iput(dir);
return -ENOSPC;
}
......
......@@ -93,6 +93,7 @@ static int fifo_open(struct inode * inode,struct file * filp)
}
if (!page)
return -ENOMEM;
PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0;
PIPE_BASE(*inode) = (char *) page;
return 0;
}
......
......@@ -23,6 +23,9 @@
#ifdef NFS_FS
#include <linux/nfs_fs.h>
#endif
#ifdef ISO9660_FS
#include <linux/iso_fs.h>
#endif
struct file_system_type file_systems[] = {
#ifdef MINIX_FS
......@@ -39,6 +42,9 @@ struct file_system_type file_systems[] = {
#endif
#ifdef NFS_FS
{nfs_read_super, "nfs", 0},
#endif
#ifdef ISO9660_FS
{isofs_read_super, "iso9660", 1},
#endif
{NULL, NULL, 0}
};
#
# Makefile for the linux isofs-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= namei.o inode.o file.o dir.o util.o rock.o symlink.o blkdev.o chrdev.o
isofs.o: $(OBJS)
$(LD) -r -o isofs.o $(OBJS)
clean:
rm -f core *.o *.a tmp_make
for i in *.c;do rm -f `basename $$i .c`.s;done
dep:
sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
for i in *.c;do $(CPP) -M $$i;done >> tmp_make
cp tmp_make Makefile
### Dependencies:
blkdev.o : blkdev.c /usr/include/linux/errno.h /usr/include/linux/sched.h /usr/include/linux/head.h \
/usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
/usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
/usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
/usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
/usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
/usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/iso_fs.h \
/usr/include/linux/tty.h /usr/include/linux/termios.h /usr/include/asm/system.h \
/usr/include/linux/stat.h /usr/include/linux/fcntl.h
chrdev.o : chrdev.c /usr/include/linux/errno.h /usr/include/linux/sched.h /usr/include/linux/head.h \
/usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
/usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
/usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
/usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
/usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
/usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/iso_fs.h \
/usr/include/linux/tty.h /usr/include/linux/termios.h /usr/include/asm/system.h \
/usr/include/linux/stat.h /usr/include/linux/fcntl.h
dir.o : dir.c /usr/include/linux/errno.h /usr/include/asm/segment.h /usr/include/linux/fs.h \
/usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \
/usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
/usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/iso_fs.h \
/usr/include/linux/kernel.h /usr/include/linux/stat.h /usr/include/linux/string.h \
/usr/include/linux/mm.h
file.o : file.c /usr/include/asm/segment.h /usr/include/asm/system.h /usr/include/linux/sched.h \
/usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \
/usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \
/usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \
/usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
/usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
/usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
/usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
/usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
/usr/include/linux/iso_fs.h /usr/include/linux/fcntl.h /usr/include/linux/errno.h \
/usr/include/linux/stat.h /usr/include/linux/locks.h
inode.o : inode.c /usr/include/linux/config.h /usr/include/linux/config.dist.h \
/usr/include/linux/stat.h /usr/include/linux/sched.h /usr/include/linux/head.h \
/usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
/usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
/usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
/usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
/usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
/usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/iso_fs.h \
/usr/include/linux/string.h /usr/include/linux/locks.h /usr/include/asm/system.h \
/usr/include/asm/segment.h /usr/include/linux/errno.h
namei.o : namei.c /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \
/usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \
/usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
/usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \
/usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
/usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
/usr/include/linux/math_emu.h /usr/include/linux/iso_fs.h /usr/include/linux/string.h \
/usr/include/linux/stat.h /usr/include/linux/fcntl.h /usr/include/asm/segment.h \
/usr/include/linux/errno.h
rock.o : rock.c /usr/include/linux/config.h /usr/include/linux/config.dist.h \
/usr/include/linux/stat.h /usr/include/linux/sched.h /usr/include/linux/head.h \
/usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
/usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
/usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
/usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
/usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
/usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/iso_fs.h \
/usr/include/linux/string.h rock.h
symlink.o : symlink.c /usr/include/asm/segment.h /usr/include/linux/errno.h \
/usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \
/usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \
/usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
/usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \
/usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
/usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
/usr/include/linux/math_emu.h /usr/include/linux/iso_fs.h /usr/include/linux/stat.h
util.o : util.c
/*
* linux/fs/isofs/blkdev.c
*
* (C) 1992 Eric Youngdale Modified for ISO9660 filesystem.
*
* Copyright (C) 1991, 1992 Linus Torvalds
*
* isofs blkdev handling code. This is only used with the Rock Ridge
* extensions to iso9660
*/
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/iso_fs.h>
#include <linux/tty.h>
#include <linux/stat.h>
#include <linux/fcntl.h>
/*
* Called every time a isofs block special file is opened
*/
static int blkdev_open(struct inode * inode, struct file * filp)
{
int i;
i = MAJOR(inode->i_rdev);
if (i < MAX_BLKDEV) {
filp->f_op = blkdev_fops[i];
if (filp->f_op && filp->f_op->open)
return filp->f_op->open(inode,filp);
}
return 0;
}
/*
* Dummy default file-operations: the only thing this does
* is contain the open that then fills in the correct operations
* depending on the special file...
*/
static struct file_operations def_blk_fops = {
NULL, /* lseek */
NULL, /* read */
NULL, /* write */
NULL, /* readdir */
NULL, /* select */
NULL, /* ioctl */
NULL, /* mmap */
blkdev_open, /* open */
NULL, /* release */
};
struct inode_operations isofs_blkdev_inode_operations = {
&def_blk_fops, /* 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 */
isofs_bmap, /* bmap */
NULL /* truncate */
};
/*
* linux/fs/isofs/chrdev.c
*
* (C) 1992 Eric Youngdale Modified for ISO9660 filesystem.
*
* Copyright (C) 1991, 1992 Linus Torvalds
*
* isofs chrdev handling code. This is only used with the Rock Ridge
* extensions to iso9660
*/
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/iso_fs.h>
#include <linux/tty.h>
#include <linux/stat.h>
#include <linux/fcntl.h>
/*
* Called every time a isofs character special file is opened
*/
static int chrdev_open(struct inode * inode, struct file * filp)
{
int i;
i = MAJOR(inode->i_rdev);
if (i < MAX_CHRDEV) {
filp->f_op = chrdev_fops[i];
if (filp->f_op && filp->f_op->open)
return filp->f_op->open(inode,filp);
}
return 0;
}
/*
* Dummy default file-operations: the only thing this does
* is contain the open that then fills in the correct operations
* depending on the special file...
*/
static struct file_operations def_chr_fops = {
NULL, /* lseek */
NULL, /* read */
NULL, /* write */
NULL, /* readdir */
NULL, /* select */
NULL, /* ioctl */
NULL, /* mmap */
chrdev_open, /* open */
NULL, /* release */
};
struct inode_operations isofs_chrdev_inode_operations = {
&def_chr_fops, /* 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 */
isofs_bmap, /* bmap */
NULL /* truncate */
};
/*
* linux/fs/isofs/dir.c
*
* (C) 1992 Eric Youngdale Modified for ISO9660 filesystem.
*
* (C) 1991 Linus Torvalds - minix filesystem
*
* isofs directory handling functions
*/
#include <linux/errno.h>
#include <asm/segment.h>
#include <linux/fs.h>
#include <linux/iso_fs.h>
#include <linux/kernel.h>
#include <linux/stat.h>
#include <linux/string.h>
#include <linux/mm.h>
static int isofs_readdir(struct inode *, struct file *, struct dirent *, int);
static struct file_operations isofs_dir_operations = {
NULL, /* lseek - default */
isofs_file_read, /* read */
NULL, /* write - bad */
isofs_readdir, /* readdir */
NULL, /* select - default */
NULL, /* ioctl - default */
NULL, /* no special open code */
NULL /* no special release code */
};
/*
* directories can handle most operations...
*/
struct inode_operations isofs_dir_inode_operations = {
&isofs_dir_operations, /* default directory file-ops */
NULL, /* create */
isofs_lookup, /* lookup */
NULL, /* link */
NULL, /* unlink */
NULL, /* symlink */
NULL, /* mkdir */
NULL, /* rmdir */
NULL, /* mknod */
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
isofs_bmap, /* bmap */
NULL /* truncate */
};
/* This is used to speed up lookup. Without this we would need to
make a linear search of the directory to find the file that the
directory read just returned. This is a single element cache. */
struct lookup_cache cache = {0,};
static int isofs_readdir(struct inode * inode, struct file * filp,
struct dirent * dirent, int count)
{
unsigned int block,offset,i, j;
char c = 0;
int inode_number;
struct buffer_head * bh;
char * cpnt = 0;
unsigned int old_offset;
int dlen, rrflag;
char * dpnt;
struct iso_directory_record * de;
if (!inode || !S_ISDIR(inode->i_mode))
return -EBADF;
offset = filp->f_pos & (BLOCK_SIZE - 1);
block = isofs_bmap(inode,(filp->f_pos)>>BLOCK_SIZE_BITS);
if (!block || !(bh = bread(inode->i_dev,block,ISOFS_BUFFER_SIZE)))
return 0;
while (filp->f_pos < inode->i_size) {
#ifdef DEBUG
printk("Block, offset: %x %x %x\n",block, offset, filp->f_pos);
#endif
de = (struct iso_directory_record *) (offset + bh->b_data);
inode_number = (block << BLOCK_SIZE_BITS)+(offset & (BLOCK_SIZE - 1));
/* If the length byte is zero, we should move on to the next CDROM sector.
If we are at the end of the directory, we kick out of the while loop. */
if (*((char*) de) == 0) {
brelse(bh);
offset = 0;
filp->f_pos =(filp->f_pos & ~(ISOFS_BLOCK_SIZE - 1))+ISOFS_BLOCK_SIZE;
block = isofs_bmap(inode,(filp->f_pos)>>BLOCK_SIZE_BITS);
if (!block || !(bh = bread(inode->i_dev,block,ISOFS_BUFFER_SIZE)))
return 0;
continue;
}
/* Make sure that the entire directory record is in the current bh block.
If not, we malloc a buffer, and put the two halves together, so that
we can cleanly read the block */
old_offset = offset;
offset += *((unsigned char*) de);
filp->f_pos += *((unsigned char*) de);
if (offset >= BLOCK_SIZE) {
cpnt = kmalloc(1 << ISOFS_BLOCK_BITS, GFP_KERNEL);
memcpy(cpnt, bh->b_data, BLOCK_SIZE);
de = (struct iso_directory_record *) (old_offset + cpnt);
brelse(bh);
offset = filp->f_pos & (BLOCK_SIZE - 1);
block = isofs_bmap(inode,(filp->f_pos)>>BLOCK_SIZE_BITS);
if (!block || !(bh = bread(inode->i_dev,block,ISOFS_BUFFER_SIZE)))
return 0;
memcpy(cpnt+BLOCK_SIZE, bh->b_data, BLOCK_SIZE);
}
/* Handle the case of the '.' directory */
rrflag = 0;
i = 1;
if (de->name_len[0] == 1 && de->name[0] == 0) {
put_fs_byte('.',dirent->d_name);
inode_number = inode->i_ino;
dpnt = ".";
}
/* Handle the case of the '..' directory */
else if (de->name_len[0] == 1 && de->name[0] == 1) {
put_fs_byte('.',dirent->d_name);
put_fs_byte('.',dirent->d_name+1);
i = 2;
dpnt = "..";
if((inode->i_sb->u.isofs_sb.s_firstdatazone << BLOCK_SIZE_BITS) != inode->i_ino)
inode_number = inode->u.isofs_i.i_backlink;
else
inode_number = inode->i_ino;
/* This should never happen, but who knows. Try to be forgiving */
if(inode_number == -1) {
inode_number =
isofs_lookup_grandparent(inode,
find_rock_ridge_relocation(de, inode));
if(inode_number == -1){ /* Should never happen */
printk("Backlink not properly set.\n");
goto out;
};
}
}
/* Handle everything else. Do name translation if there
is no Rock Ridge NM field. */
else {
dlen = de->name_len[0];
dpnt = de->name;
i = dlen;
rrflag = get_rock_ridge_filename(de, &dpnt, &dlen, inode);
if (rrflag) {
if (rrflag == -1) { /* This is a rock ridge reloc dir */
if (cpnt) {
kfree_s(cpnt, 1 << ISOFS_BLOCK_BITS);
cpnt = 0;
};
continue;
};
i = dlen;
}
else
if(inode->i_sb->u.isofs_sb.s_mapping == 'n')
for (i = 0; i < dlen && i < NAME_MAX; i++) {
if (!(c = dpnt[i])) break;
if (c >= 'A' && c <= 'Z') c |= 0x20; /* lower case */
if (c == ';' && i == dlen-2 && de->name[i+1] == '1')
break; /* Drop trailing ';1' */
if (c == ';') c = '.'; /* Convert remaining ';' to '.' */
dpnt[i] = c;
};
for(j=0; j<i; j++)
put_fs_byte(dpnt[j],j+dirent->d_name); /* And save it */
};
#if 0
printk("Nchar: %d\n",i);
#endif
if (i) {
while (cache.lock);
cache.lock = 1;
cache.ino = inode_number;
cache.dir = inode->i_ino;
cache.dev = inode->i_dev;
strncpy(cache.filename, dpnt, i);
cache.dlen = dlen;
cache.lock = 0;
};
if (rrflag) kfree(dpnt);
if (cpnt) {
kfree_s(cpnt, 1 << ISOFS_BLOCK_BITS);
cpnt = 0;
};
if (i) {
put_fs_long(inode_number, &dirent->d_ino);
put_fs_byte(0,i+dirent->d_name);
put_fs_word(i,&dirent->d_reclen);
brelse(bh);
return i;
}
}
/* We go here for any condition we cannot handle. We also drop through
to here at the end of the directory. */
out:
if (cpnt) kfree_s(cpnt, 1 << ISOFS_BLOCK_BITS);
brelse(bh);
return 0;
}
/*
* linux/fs/isofs/file.c
*
* (C) 1992 Eric Youngdale Modified for ISO9660 filesystem.
*
* (C) 1991 Linus Torvalds - minix filesystem
*
* isofs regular file handling primitives
*/
#include <asm/segment.h>
#include <asm/system.h>
#include <linux/sched.h>
#include <linux/iso_fs.h>
#include <linux/fcntl.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/stat.h>
#include <linux/locks.h>
#include <linux/dirent.h>
#define NBUF 16
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))
#include <linux/fs.h>
#include <linux/iso_fs.h>
int isofs_file_read(struct inode *, struct file *, char *, int);
/*
* We have mostly NULL's here: the current defaults are ok for
* the isofs filesystem.
*/
static struct file_operations isofs_file_operations = {
NULL, /* lseek - default */
isofs_file_read, /* read */
NULL, /* write */
NULL, /* readdir - bad */
NULL, /* select - default */
NULL, /* ioctl - default */
NULL, /* no special open is needed */
NULL /* release */
};
struct inode_operations isofs_file_inode_operations = {
&isofs_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 */
isofs_bmap, /* bmap */
NULL /* truncate */
};
/* This is a heuristic to determine if a file is text of binary. If it
* is text, then we translate all 0x0d characters to spaces. If the 0x0d
* character is not preceeded or followed by a 0x0a, then we turn it into
* a 0x0a. A control-Z is also turned into a linefeed.
*/
static inline void unixify_text_buffer(char * buffer, int chars, int mode)
{
while(chars--){
if(*buffer == 0x1a) *buffer = 0x0a;
if(*buffer == 0x0d){
if(mode == ISOFS_FILE_TEXT_M) *buffer = 0x0a;
if(mode == ISOFS_FILE_TEXT) *buffer = ' ';
}
buffer++;
}
}
/*This function determines if a given file has a DOS-like text format or not*/
static void isofs_determine_filetype(struct inode * inode)
{
int block;
int result, i;
struct buffer_head * bh;
unsigned char * pnt;
block = isofs_bmap(inode,0);
if (block && (bh = bread(inode->i_dev,block, ISOFS_BUFFER_SIZE))) {
pnt = (char*) bh->b_data;
result = ISOFS_FILE_TEXT_M;
for(i=0;i<(inode->i_size < ISOFS_BUFFER_SIZE ? inode->i_size : ISOFS_BUFFER_SIZE);
i++,pnt++){
if(*pnt & 0x80) {result = ISOFS_FILE_BINARY; break;};
if(*pnt >= 0x20 || *pnt == 0x1a) continue;
if(*pnt == 0x0a) {result = ISOFS_FILE_TEXT; continue;};
if(*pnt >= 0x9 && *pnt <= 0x0d) continue;
result = ISOFS_FILE_BINARY;
break;
}
brelse(bh);
inode->u.isofs_i.i_file_format = result;
}
}
/*
* isofs_file_read() is also needed by the directory read-routine,
* so it's not static. NOTE! reading directories directly is a bad idea,
* but has to be supported for now for compatability reasons with older
* versions.
*/
int isofs_file_read(struct inode * inode, struct file * filp, char * buf, int count)
{
int read,left,chars;
int block, blocks, offset;
int bhrequest;
int ra_blocks, max_block, nextblock;
struct buffer_head ** bhb, ** bhe;
struct buffer_head * bhreq[NBUF];
struct buffer_head * buflist[NBUF];
if (!inode) {
printk("isofs_file_read: inode = NULL\n");
return -EINVAL;
}
if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) {
printk("isofs_file_read: mode = %07o\n",inode->i_mode);
return -EINVAL;
}
if (inode->u.isofs_i.i_file_format == ISOFS_FILE_UNKNOWN)
isofs_determine_filetype(inode);
if (filp->f_pos > inode->i_size)
left = 0;
else
left = inode->i_size - filp->f_pos;
if (left > count)
left = count;
if (left <= 0)
return 0;
read = 0;
block = filp->f_pos >> ISOFS_BUFFER_BITS;
offset = filp->f_pos & (ISOFS_BUFFER_SIZE-1);
blocks = (left + offset + ISOFS_BUFFER_SIZE - 1) / ISOFS_BUFFER_SIZE;
bhb = bhe = buflist;
ra_blocks = read_ahead[MAJOR(inode->i_dev)] / (BLOCK_SIZE >> 9);
max_block = (inode->i_size + BLOCK_SIZE - 1)/BLOCK_SIZE;
nextblock = -1;
/* We do this in a two stage process. We first try and request
as many blocks as we can, then we wait for the first one to
complete, and then we try and wrap up as many as are actually
done. This routine is rather generic, in that it can be used
in a filesystem by substituting the appropriate function in
for getblk.
This routine is optimized to make maximum use of the various
buffers and caches. */
do {
bhrequest = 0;
while (blocks) {
int uptodate;
--blocks;
*bhb = getblk(inode->i_dev,isofs_bmap(inode, block++), ISOFS_BUFFER_SIZE);
uptodate = 1;
if (*bhb && !(*bhb)->b_uptodate) {
uptodate = 0;
bhreq[bhrequest++] = *bhb;
nextblock = (*bhb)->b_blocknr + 1;
};
if (++bhb == &buflist[NBUF])
bhb = buflist;
/* If the block we have on hand is uptodate, go ahead
and complete processing. */
if(bhrequest == 0 && uptodate) break;
if (bhb == bhe)
break;
}
if(blocks == 0 && bhrequest && filp->f_reada && bhb != bhe) {
/* If we are going to read something anyways, add in the
read-ahead blocks */
while(ra_blocks){
if (block >= max_block) break;
if(bhrequest == NBUF) break; /* Block full */
--ra_blocks;
*bhb = getblk(inode->i_dev,isofs_bmap(inode, block++), ISOFS_BUFFER_SIZE);
if (*bhb && !(*bhb)->b_uptodate) {
if((*bhb)->b_blocknr != nextblock) {
brelse(*bhb);
break;
};
nextblock = (*bhb)->b_blocknr + 1;
bhreq[bhrequest++] = *bhb;
};
if (++bhb == &buflist[NBUF])
bhb = buflist;
if (bhb == bhe)
break;
};
};
/* Now request them all */
if (bhrequest)
ll_rw_block(READ, bhrequest, bhreq);
do{ /* Finish off all I/O that has actually completed */
if (*bhe) {/* test for valid buffer */
wait_on_buffer(*bhe);
if (!(*bhe)->b_uptodate) {
do {
brelse(*bhe);
if (++bhe == &buflist[NBUF])
bhe = buflist;
} while (bhe != bhb);
break;
}
}
if (left < ISOFS_BUFFER_SIZE - offset)
chars = left;
else
chars = ISOFS_BUFFER_SIZE - offset;
filp->f_pos += chars;
left -= chars;
read += chars;
if (*bhe) {
if (inode->u.isofs_i.i_file_format == ISOFS_FILE_TEXT ||
inode->u.isofs_i.i_file_format == ISOFS_FILE_TEXT_M)
unixify_text_buffer(offset+(*bhe)->b_data,
chars, inode->u.isofs_i.i_file_format);
memcpy_tofs(buf,offset+(*bhe)->b_data,chars);
brelse(*bhe);
buf += chars;
} else {
while (chars-->0)
put_fs_byte(0,buf++);
}
offset = 0;
if (++bhe == &buflist[NBUF])
bhe = buflist;
} while( bhe != bhb && (*bhe == 0 || !(*bhe)->b_lock) &&
(left > 0));
} while (left > 0);
/* Release the read-ahead blocks */
while (bhe != bhb) {
if (*bhe) brelse(*bhe);
if (++bhe == &buflist[NBUF])
bhe = buflist;
};
filp->f_reada = 1;
if (!read)
return -EIO;
return read;
}
This diff is collapsed.
/*
* linux/fs/isofs/namei.c
*
* (C) 1992 Eric Youngdale Modified for ISO9660 filesystem.
*
* (C) 1991 Linus Torvalds - minix filesystem
*/
#include <linux/sched.h>
#include <linux/iso_fs.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/stat.h>
#include <linux/fcntl.h>
#include <asm/segment.h>
#include <linux/errno.h>
/*
* ok, we cannot use strncmp, as the name is not in our data space.
* Thus we'll have to use isofs_match. No big problem. Match also makes
* some sanity tests.
*
* NOTE! unlike strncmp, isofs_match returns 1 for success, 0 for failure.
*/
static int isofs_match(int len,const char * name, char * compare, int dlen)
{
register int same __asm__("ax");
if (!compare) return 0;
/* "" means "." ---> so paths like "/usr/lib//libc.a" work */
if (!len && (compare[0]==0) && (dlen==1))
return 1;
if (compare[0]==0 && dlen==1 && len == 1)
compare = ".";
if (compare[0]==1 && dlen==1 && len == 2) {
compare = "..";
dlen = 2;
};
#if 0
if (len <= 2) printk("Match: %d %d %s %d %d \n",len,dlen,compare,de->name[0], dlen);
#endif
if (dlen != len)
return 0;
__asm__("cld\n\t"
"fs ; repe ; cmpsb\n\t"
"setz %%al"
:"=a" (same)
:"0" (0),"S" ((long) name),"D" ((long) compare),"c" (len)
:"cx","di","si");
return same;
}
/*
* isofs_find_entry()
*
* finds an entry in the specified directory with the wanted name. It
* returns the cache buffer in which the entry was found, and the entry
* itself (as an inode number). It does NOT read the inode of the
* entry - you'll have to do that yourself if you want to.
*/
static struct buffer_head * isofs_find_entry(struct inode * dir,
const char * name, int namelen, int * ino, int * ino_back)
{
unsigned int block,i, f_pos, offset, inode_number;
struct buffer_head * bh;
char * cpnt = 0;
unsigned int old_offset;
unsigned int backlink;
int dlen, rrflag, match;
char * dpnt;
struct iso_directory_record * de;
char c;
*ino = 0;
if (!dir) return NULL;
if (!(block = dir->u.isofs_i.i_first_extent)) return NULL;
f_pos = 0;
offset = f_pos & (ISOFS_BUFFER_SIZE - 1);
block = isofs_bmap(dir,f_pos >> ISOFS_BUFFER_BITS);
if (!block || !(bh = bread(dir->i_dev,block,ISOFS_BUFFER_SIZE))) return NULL;
while (f_pos < dir->i_size) {
de = (struct iso_directory_record *) (offset + bh->b_data);
backlink = dir->i_ino;
inode_number = (block << ISOFS_BUFFER_BITS)+(offset & (ISOFS_BUFFER_SIZE - 1));
/* If byte is zero, this is the end of file, or time to move to
the next sector. Usually 2048 byte boundaries. */
if (*((unsigned char*) de) == 0) {
brelse(bh);
offset = 0;
f_pos =(f_pos & ~(ISOFS_BLOCK_SIZE - 1))+ISOFS_BLOCK_SIZE;
block = isofs_bmap(dir,(f_pos)>>ISOFS_BUFFER_BITS);
if (!block || !(bh = bread(dir->i_dev,block,ISOFS_BUFFER_SIZE)))
return 0;
continue; /* Will kick out if past end of directory */
};
old_offset = offset;
offset += *((unsigned char*) de);
f_pos += *((unsigned char*) de);
/* Handle case where the directory entry spans two blocks. Usually
1024 byte boundaries */
if (offset >= ISOFS_BUFFER_SIZE) {
cpnt = kmalloc(1 << ISOFS_BLOCK_BITS, GFP_KERNEL);
memcpy(cpnt, bh->b_data, ISOFS_BUFFER_SIZE);
de = (struct iso_directory_record *) (old_offset + cpnt);
brelse(bh);
offset = f_pos & (ISOFS_BUFFER_SIZE - 1);
block = isofs_bmap(dir,f_pos>>ISOFS_BUFFER_BITS);
if (!block || !(bh = bread(dir->i_dev,block,ISOFS_BUFFER_SIZE)))
return 0;
memcpy(cpnt+ISOFS_BUFFER_SIZE, bh->b_data, ISOFS_BUFFER_SIZE);
}
/* Handle the '.' case */
if (de->name[0]==0 && de->name_len[0]==1) {
inode_number = dir->i_ino;
backlink = 0;
}
/* Handle the '..' case */
if (de->name[0]==1 && de->name_len[0]==1) {
#if 0
printk("Doing .. (%d %d)",dir->i_sb->s_firstdatazone << ISOFS_BUFFER_BITS, dir->i_ino);
#endif
if((dir->i_sb->u.isofs_sb.s_firstdatazone << ISOFS_BUFFER_BITS) != dir->i_ino)
inode_number = dir->u.isofs_i.i_backlink;
else
inode_number = dir->i_ino;
backlink = 0;
}
dlen = de->name_len[0];
dpnt = de->name;
/* Now convert the filename in the buffer to lower case */
rrflag = get_rock_ridge_filename(de, &dpnt, &dlen, dir);
if (rrflag) {
if (rrflag == -1) goto out; /* Relocated deep directory */
} else {
if(dir->i_sb->u.isofs_sb.s_mapping == 'n') {
for (i = 0; i < dlen; i++) {
c = dpnt[i];
if (c >= 'A' && c <= 'Z') c |= 0x20; /* lower case */
if (c == ';' && i == dlen-2 && dpnt[i+1] == '1') {
dlen -= 2;
break;
};
if (c == ';') c = '.';
de->name[i] = c;
};
/* This allows us to match with and without a trailing period */
if(dpnt[dlen-1] == '.' && namelen == dlen-1)
dlen--;
};
};
match = isofs_match(namelen,name,dpnt, dlen);
if (cpnt) { kfree_s(cpnt, 1 << ISOFS_BLOCK_BITS); cpnt = 0;};
if(rrflag) kfree(dpnt);
if (match) {
if(inode_number == -1) { /* Should only happen for the '..' entry */
inode_number =
isofs_lookup_grandparent(dir,
find_rock_ridge_relocation(de,dir));
if(inode_number == -1){ /* Should never happen */
printk("Backlink not properly set.\n");
goto out;
};
};
*ino = inode_number;
*ino_back = backlink;
return bh;
}
}
out:
if (cpnt) kfree_s(cpnt, 1 << ISOFS_BLOCK_BITS);
brelse(bh);
return NULL;
}
int isofs_lookup(struct inode * dir,const char * name, int len,
struct inode ** result)
{
int ino, ino_back;
struct buffer_head * bh;
#ifdef DEBUG
printk("lookup: %x %d\n",dir->i_ino, len);
#endif
*result = NULL;
if (!dir)
return -ENOENT;
if (!S_ISDIR(dir->i_mode)) {
iput(dir);
return -ENOENT;
}
ino = 0;
while(cache.lock);
cache.lock = 1;
if (dir->i_dev == cache.dev &&
dir->i_ino == cache.dir &&
len == cache.dlen &&
isofs_match(len, name, cache.filename, cache.dlen))
{
ino = cache.ino;
ino_back = dir->i_ino;
/* These two cases are special, but since they are at the start
of the directory, we can just as easily search there */
if (cache.dlen == 1 && cache.filename[0] == '.') ino = 0;
if (cache.dlen == 2 && cache.filename[0] == '.' &&
cache.filename[1] == '.') ino = 0;
};
cache.lock = 0;
if (!ino) {
if (!(bh = isofs_find_entry(dir,name,len, &ino, &ino_back))) {
iput(dir);
return -ENOENT;
}
brelse(bh);
};
if (!(*result = iget(dir->i_sb,ino))) {
iput(dir);
return -EACCES;
}
/* We need this backlink for the .. entry */
if (ino_back) (*result)->u.isofs_i.i_backlink = ino_back;
iput(dir);
return 0;
}
This diff is collapsed.
/* These structs are used by the system-use-sharing protocol, in which the
Rock Ridge extensions are imbedded. It is quite possible that other
extensions are present on the disk, and this is fine as long as they
all use SUSP */
struct SU_SP{
unsigned char magic[2];
unsigned char skip;
};
struct SU_CE{
char extent[8];
char offset[8];
char size[8];
};
struct SU_ER{
unsigned char len_id;
unsigned char len_des;
unsigned char len_src;
unsigned char ext_ver;
char data[0];
};
struct RR_RR{
char flags[1];
};
struct RR_PX{
char mode[8];
char n_links[8];
char uid[8];
char gid[8];
};
struct RR_PN{
char dev_high[8];
char dev_low[8];
};
struct SL_component{
unsigned char flags;
unsigned char len;
char text[0];
};
struct RR_SL{
unsigned char flags;
struct SL_component link;
};
struct RR_NM{
unsigned char flags;
char name[0];
};
struct RR_CL{
char location[8];
};
struct RR_PL{
char location[8];
};
struct stamp{
char time[7];
};
struct RR_TF{
char flags;
struct stamp times[0]; /* Variable number of these beasts */
};
/* These are the bits and their meanings for flags in the TF structure. */
#define TF_CREATE 1
#define TF_MODIFY 2
#define TF_ACCESS 4
#define TF_ATTRIBUTES 8
#define TF_BACKUP 16
#define TF_EXPIRATION 32
#define TF_EFFECTIVE 64
#define TF_LONG_FORM 128
struct rock_ridge{
char signature[2];
unsigned char len;
unsigned char version;
union{
struct SU_SP SP;
struct SU_CE CE;
struct SU_ER ER;
struct RR_RR RR;
struct RR_PX PX;
struct RR_PN PN;
struct RR_SL SL;
struct RR_NM NM;
struct RR_CL CL;
struct RR_PL PL;
struct RR_TF TF;
} u;
};
#define RR_PX 1 /* POSIX attributes */
#define RR_PN 2 /* POSIX devices */
#define RR_SL 4 /* Symbolic link */
#define RR_NM 8 /* Alternate Name */
#define RR_CL 16 /* Child link */
#define RR_PL 32 /* Parent link */
#define RR_RE 64 /* Relocation directory */
#define RR_TF 128 /* Timestamps */
/*
* linux/fs/isofs/symlink.c
*
* (C) 1992 Eric Youngdale Modified for ISO9660 filesystem.
*
* Copyright (C) 1991, 1992 Linus Torvalds
*
* isofs symlink handling code. This is only used with the Rock Ridge
* extensions to iso9660
*/
#include <asm/segment.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/iso_fs.h>
#include <linux/stat.h>
static int isofs_readlink(struct inode *, char *, int);
static int isofs_follow_link(struct inode *, struct inode *, int, int, struct inode **);
/*
* symlinks can't do much...
*/
struct inode_operations isofs_symlink_inode_operations = {
NULL, /* no file-operations */
NULL, /* create */
NULL, /* lookup */
NULL, /* link */
NULL, /* unlink */
NULL, /* symlink */
NULL, /* mkdir */
NULL, /* rmdir */
NULL, /* mknod */
NULL, /* rename */
isofs_readlink, /* readlink */
isofs_follow_link, /* follow_link */
NULL, /* bmap */
NULL /* truncate */
};
static int isofs_follow_link(struct inode * dir, struct inode * inode,
int flag, int mode, struct inode ** res_inode)
{
int error;
unsigned short fs;
char * pnt;
if (!dir) {
dir = current->root;
dir->i_count++;
}
if (!inode) {
iput(dir);
*res_inode = NULL;
return -ENOENT;
}
if (!S_ISLNK(inode->i_mode)) {
iput(dir);
*res_inode = inode;
return 0;
}
__asm__("mov %%fs,%0":"=r" (fs));
if ((current->link_count > 5) ||
!(pnt = get_rock_ridge_symlink(inode))) {
iput(dir);
iput(inode);
*res_inode = NULL;
return -ELOOP;
}
iput(inode);
__asm__("mov %0,%%fs"::"r" ((unsigned short) 0x10));
current->link_count++;
error = open_namei(pnt,flag,mode,res_inode,dir);
current->link_count--;
__asm__("mov %0,%%fs"::"r" (fs));
kfree(pnt);
return error;
}
static int isofs_readlink(struct inode * inode, char * buffer, int buflen)
{
char * pnt;
int i;
char c;
if (!S_ISLNK(inode->i_mode)) {
iput(inode);
return -EINVAL;
}
if (buflen > 1023)
buflen = 1023;
pnt = get_rock_ridge_symlink(inode);
iput(inode);
if (!pnt)
return 0;
i = 0;
while (i<buflen && (c = pnt[i])) {
i++;
put_fs_byte(c,buffer++);
}
kfree(pnt);
return i;
}
/*
* linux/fs/isofs/util.c
*
* The special functions in the file are numbered according to the section
* of the iso 9660 standard in which they are described. isonum_733 will
* convert numbers according to section 7.3.3, etc.
*
* isofs special functions. This file was lifted in it's entirety from
* the bsd386 iso9660 filesystem, by Pace Williamson.
*/
int
isonum_711 (p)
char *p;
{
return (*p & 0xff);
}
int
isonum_712 (p)
char *p;
{
int val;
val = *p;
if (val & 0x80)
val |= 0xffffff00;
return (val);
}
int
isonum_721 (p)
char *p;
{
return ((p[0] & 0xff) | ((p[1] & 0xff) << 8));
}
int
isonum_722 (p)
char *p;
{
return (((p[0] & 0xff) << 8) | (p[1] & 0xff));
}
int
isonum_723 (p)
char *p;
{
#if 0
if (p[0] != p[3] || p[1] != p[2]) {
fprintf (stderr, "invalid format 7.2.3 number\n");
exit (1);
}
#endif
return (isonum_721 (p));
}
int
isonum_731 (p)
char *p;
{
return ((p[0] & 0xff)
| ((p[1] & 0xff) << 8)
| ((p[2] & 0xff) << 16)
| ((p[3] & 0xff) << 24));
}
int
isonum_732 (p)
char *p;
{
return (((p[0] & 0xff) << 24)
| ((p[1] & 0xff) << 16)
| ((p[2] & 0xff) << 8)
| (p[3] & 0xff));
}
int
isonum_733 (p)
char *p;
{
#if 0
int i;
for (i = 0; i < 4; i++) {
if (p[i] != p[7-i]) {
fprintf (stderr, "bad format 7.3.3 number\n");
exit (1);
}
}
#endif
return (isonum_731 (p));
}
int iso_date(p, flag)
char * p;
int flag;
{
int year, month, day, hour ,minute, second, tz;
int crtime, days, i;
year = p[0] - 70;
month = p[1];
day = p[2];
hour = p[3];
minute = p[4];
second = p[5];
if (flag == 0) tz = p[6]; /* High sierra has no time zone */
else tz = 0;
if (year < 0) {
crtime = 0;
} else {
int monlen[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
days = year * 365;
if (year > 2)
days += (year+2) / 4;
for (i = 1; i < month; i++)
days += monlen[i-1];
if (((year+2) % 4) == 0 && month > 2)
days++;
days += day - 1;
crtime = ((((days * 24) + hour) * 60 + minute) * 60)
+ second;
/* sign extend */
if (tz & 0x80)
tz |= (-1 << 8);
/* timezone offset is unreliable on some disks */
if (-48 <= tz && tz <= 52)
crtime += tz * 15 * 60;
}
return crtime;
}
This diff is collapsed.
......@@ -8,6 +8,7 @@
#include <linux/sched.h>
#include <linux/minix_fs.h>
#include <linux/stat.h>
#include <linux/kernel.h>
#include <linux/string.h>
......@@ -117,7 +118,7 @@ int minix_new_block(struct super_block * sb)
repeat:
j = 8192;
for (i=0 ; i<8 ; i++)
if (bh=sb->u.minix_sb.s_zmap[i])
if ((bh=sb->u.minix_sb.s_zmap[i]) != NULL)
if ((j=find_first_zero(bh->b_data))<8192)
break;
if (i>=8 || !bh || j>=8192)
......@@ -187,19 +188,21 @@ void minix_free_inode(struct inode * inode)
clear_inode(inode);
}
struct inode * minix_new_inode(struct super_block * sb)
struct inode * minix_new_inode(const struct inode * dir)
{
struct super_block * sb;
struct inode * inode;
struct buffer_head * bh;
int i,j;
if (!sb || !(inode = get_empty_inode()))
if (!dir || !(inode = get_empty_inode()))
return NULL;
sb = dir->i_sb;
inode->i_sb = sb;
inode->i_flags = inode->i_sb->s_flags;
j = 8192;
for (i=0 ; i<8 ; i++)
if (bh=inode->i_sb->u.minix_sb.s_imap[i])
if ((bh = inode->i_sb->u.minix_sb.s_imap[i]) != NULL)
if ((j=find_first_zero(bh->b_data))<8192)
break;
if (!bh || j >= 8192 || j+i*8192 > inode->i_sb->u.minix_sb.s_ninodes) {
......@@ -216,7 +219,7 @@ struct inode * minix_new_inode(struct super_block * sb)
inode->i_nlink = 1;
inode->i_dev = sb->s_dev;
inode->i_uid = current->euid;
inode->i_gid = current->egid;
inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->egid;
inode->i_dirt = 1;
inode->i_ino = j + i*8192;
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
......
......@@ -77,7 +77,7 @@ static int minix_readdir(struct inode * inode, struct file * filp,
filp->f_pos += sizeof (struct minix_dir_entry);
if (de->inode) {
for (i = 0; i < MINIX_NAME_LEN; i++)
if (c = de->name[i])
if ((c = de->name[i]) != 0)
put_fs_byte(c,i+dirent->d_name);
else
break;
......
......@@ -65,7 +65,10 @@ static int minix_file_read(struct inode * inode, struct file * filp, char * buf,
{
int read,left,chars;
int block, blocks, offset;
int bhrequest;
int ra_blocks, max_block, nextblock;
struct buffer_head ** bhb, ** bhe;
struct buffer_head * bhreq[NBUF];
struct buffer_head * buflist[NBUF];
if (!inode) {
......@@ -89,50 +92,118 @@ static int minix_file_read(struct inode * inode, struct file * filp, char * buf,
offset = filp->f_pos & (BLOCK_SIZE-1);
blocks = (left + offset + BLOCK_SIZE - 1) / BLOCK_SIZE;
bhb = bhe = buflist;
ra_blocks = read_ahead[MAJOR(inode->i_dev)] / (BLOCK_SIZE >> 9);
max_block = (inode->i_size + BLOCK_SIZE - 1)/BLOCK_SIZE;
nextblock = -1;
/* We do this in a two stage process. We first try and request
as many blocks as we can, then we wait for the first one to
complete, and then we try and wrap up as many as are actually
done. This routine is rather generic, in that it can be used
in a filesystem by substituting the appropriate function in
for getblk.
This routine is optimized to make maximum use of the various
buffers and caches. */
do {
if (blocks) {
bhrequest = 0;
while (blocks) {
int uptodate;
--blocks;
*bhb = minix_getblk(inode,block++,0);
if (*bhb && !(*bhb)->b_uptodate)
ll_rw_block(READ, 1, bhb);
*bhb = minix_getblk(inode, block++, 0);
uptodate = 1;
if (*bhb && !(*bhb)->b_uptodate) {
uptodate = 0;
bhreq[bhrequest++] = *bhb;
nextblock = (*bhb)->b_blocknr + 1;
};
if (++bhb == &buflist[NBUF])
bhb = buflist;
if (bhb != bhe)
continue;
}
if (*bhe) {
wait_on_buffer(*bhe);
if (!(*bhe)->b_uptodate) {
do {
brelse(*bhe);
if (++bhe == &buflist[NBUF])
bhe = buflist;
} while (bhe != bhb);
/* If the block we have on hand is uptodate, go ahead
and complete processing. */
if(bhrequest == 0 && uptodate) break;
if (bhb == bhe)
break;
}
}
}
if (left < BLOCK_SIZE - offset)
chars = left;
else
chars = BLOCK_SIZE - offset;
filp->f_pos += chars;
left -= chars;
read += chars;
if (*bhe) {
memcpy_tofs(buf,offset+(*bhe)->b_data,chars);
if(blocks == 0 && bhrequest && filp->f_reada && bhb != bhe) {
/* If we are going to read something anyways, add in the
read-ahead blocks */
while(ra_blocks){
if (block >= max_block) break;
if(bhrequest == NBUF) break; /* Block full */
--ra_blocks;
*bhb = minix_getblk(inode, block++, 0);
if (*bhb && !(*bhb)->b_uptodate) {
if((*bhb)->b_blocknr != nextblock) {
brelse(*bhb);
break;
};
nextblock = (*bhb)->b_blocknr + 1;
bhreq[bhrequest++] = *bhb;
};
if (++bhb == &buflist[NBUF])
bhb = buflist;
if (bhb == bhe)
break;
};
};
/* Now request them all */
if (bhrequest)
ll_rw_block(READ, bhrequest, bhreq);
do{ /* Finish off all I/O that has actually completed */
if (*bhe) {/* test for valid buffer */
wait_on_buffer(*bhe);
if (!(*bhe)->b_uptodate) {
do {
brelse(*bhe);
buf += chars;
} else {
while (chars-->0)
put_fs_byte(0,buf++);
}
offset = 0;
if (++bhe == &buflist[NBUF])
bhe = buflist;
if (++bhe == &buflist[NBUF])
bhe = buflist;
} while (bhe != bhb);
break;
}
}
if (left < BLOCK_SIZE - offset)
chars = left;
else
chars = BLOCK_SIZE - offset;
filp->f_pos += chars;
left -= chars;
read += chars;
if (*bhe) {
memcpy_tofs(buf,offset+(*bhe)->b_data,chars);
brelse(*bhe);
buf += chars;
} else {
while (chars-->0)
put_fs_byte(0,buf++);
}
offset = 0;
if (++bhe == &buflist[NBUF])
bhe = buflist;
} while( bhe != bhb && (*bhe == 0 || !(*bhe)->b_lock) &&
(left > 0));
} while (left > 0);
/* Release the read-ahead blocks */
while (bhe != bhb) {
if (*bhe) brelse(*bhe);
if (++bhe == &buflist[NBUF])
bhe = buflist;
};
filp->f_reada = 1;
if (!read)
return -EIO;
if (!IS_RDONLY(inode)) {
......
......@@ -86,12 +86,12 @@ struct super_block *minix_read_super(struct super_block *s,void *data)
s->u.minix_sb.s_zmap[i] = NULL;
block=2;
for (i=0 ; i < s->u.minix_sb.s_imap_blocks ; i++)
if (s->u.minix_sb.s_imap[i]=bread(dev,block,BLOCK_SIZE))
if ((s->u.minix_sb.s_imap[i]=bread(dev,block,BLOCK_SIZE)) != NULL)
block++;
else
break;
for (i=0 ; i < s->u.minix_sb.s_zmap_blocks ; i++)
if (s->u.minix_sb.s_zmap[i]=bread(dev,block,BLOCK_SIZE))
if ((s->u.minix_sb.s_zmap[i]=bread(dev,block,BLOCK_SIZE)) != NULL)
block++;
else
break;
......
......@@ -205,7 +205,7 @@ int minix_create(struct inode * dir,const char * name, int len, int mode,
*result = NULL;
if (!dir)
return -ENOENT;
inode = minix_new_inode(dir->i_sb);
inode = minix_new_inode(dir);
if (!inode) {
iput(dir);
return -ENOSPC;
......@@ -243,7 +243,7 @@ int minix_mknod(struct inode * dir, const char * name, int len, int mode, int rd
iput(dir);
return -EEXIST;
}
inode = minix_new_inode(dir->i_sb);
inode = minix_new_inode(dir);
if (!inode) {
iput(dir);
return -ENOSPC;
......@@ -253,8 +253,11 @@ int minix_mknod(struct inode * dir, const char * name, int len, int mode, int rd
inode->i_op = NULL;
if (S_ISREG(inode->i_mode))
inode->i_op = &minix_file_inode_operations;
else if (S_ISDIR(inode->i_mode))
else if (S_ISDIR(inode->i_mode)) {
inode->i_op = &minix_dir_inode_operations;
if (dir->i_mode & S_ISGID)
inode->i_mode |= S_ISGID;
}
else if (S_ISLNK(inode->i_mode))
inode->i_op = &minix_symlink_inode_operations;
else if (S_ISCHR(inode->i_mode))
......@@ -301,7 +304,7 @@ int minix_mkdir(struct inode * dir, const char * name, int len, int mode)
iput(dir);
return -EEXIST;
}
inode = minix_new_inode(dir->i_sb);
inode = minix_new_inode(dir);
if (!inode) {
iput(dir);
return -ENOSPC;
......@@ -327,6 +330,8 @@ int minix_mkdir(struct inode * dir, const char * name, int len, int mode)
dir_block->b_dirt = 1;
brelse(dir_block);
inode->i_mode = S_IFDIR | (mode & 0777 & ~current->umask);
if (dir->i_mode & S_ISGID)
inode->i_mode |= S_ISGID;
inode->i_dirt = 1;
bh = minix_add_entry(dir,name,len,&de);
if (!bh) {
......@@ -496,7 +501,7 @@ int minix_symlink(struct inode * dir, const char * name, int len, const char * s
int i;
char c;
if (!(inode = minix_new_inode(dir->i_sb))) {
if (!(inode = minix_new_inode(dir))) {
iput(dir);
return -ENOSPC;
}
......
......@@ -33,53 +33,58 @@ dir.o : dir.c /usr/include/asm/segment.h /usr/include/linux/sched.h /usr/include
/usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
/usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
/usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
/usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
/usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
/usr/include/linux/msdos_fs.h /usr/include/linux/errno.h /usr/include/linux/stat.h
/usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
/usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
/usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
/usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
/usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/msdos_fs.h \
/usr/include/linux/errno.h /usr/include/linux/stat.h
fat.o : fat.c /usr/include/linux/msdos_fs.h /usr/include/linux/fs.h /usr/include/linux/limits.h \
/usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \
/usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \
/usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h \
/usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/kernel.h \
/usr/include/linux/errno.h /usr/include/linux/stat.h
/usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
/usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
/usr/include/linux/iso_fs_sb.h /usr/include/linux/kernel.h /usr/include/linux/errno.h \
/usr/include/linux/stat.h
file.o : file.c /usr/include/asm/segment.h /usr/include/asm/system.h /usr/include/linux/sched.h \
/usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \
/usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \
/usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \
/usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h \
/usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h \
/usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
/usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
/usr/include/linux/math_emu.h /usr/include/linux/msdos_fs.h /usr/include/linux/errno.h \
/usr/include/linux/fcntl.h /usr/include/linux/stat.h
/usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
/usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
/usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
/usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
/usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
/usr/include/linux/msdos_fs.h /usr/include/linux/errno.h /usr/include/linux/fcntl.h \
/usr/include/linux/stat.h
inode.o : inode.c /usr/include/linux/msdos_fs.h /usr/include/linux/fs.h /usr/include/linux/limits.h \
/usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \
/usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \
/usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h \
/usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/kernel.h \
/usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/mm.h \
/usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
/usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
/usr/include/linux/errno.h /usr/include/linux/string.h /usr/include/linux/ctype.h \
/usr/include/linux/stat.h /usr/include/linux/locks.h /usr/include/asm/segment.h
/usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
/usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
/usr/include/linux/iso_fs_sb.h /usr/include/linux/kernel.h /usr/include/linux/sched.h \
/usr/include/linux/head.h /usr/include/linux/mm.h /usr/include/linux/signal.h \
/usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
/usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/errno.h \
/usr/include/linux/string.h /usr/include/linux/ctype.h /usr/include/linux/stat.h \
/usr/include/linux/locks.h /usr/include/asm/segment.h
misc.o : misc.c /usr/include/linux/msdos_fs.h /usr/include/linux/fs.h /usr/include/linux/limits.h \
/usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \
/usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \
/usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h \
/usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/sched.h \
/usr/include/linux/head.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
/usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
/usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
/usr/include/linux/errno.h /usr/include/linux/string.h /usr/include/linux/stat.h
/usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
/usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
/usr/include/linux/iso_fs_sb.h /usr/include/linux/sched.h /usr/include/linux/head.h \
/usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
/usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
/usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/errno.h \
/usr/include/linux/string.h /usr/include/linux/stat.h
namei.o : namei.c /usr/include/asm/segment.h /usr/include/linux/sched.h /usr/include/linux/head.h \
/usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
/usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
/usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
/usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
/usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
/usr/include/linux/msdos_fs.h /usr/include/linux/errno.h /usr/include/linux/string.h \
/usr/include/linux/stat.h
/usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
/usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
/usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
/usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
/usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/msdos_fs.h \
/usr/include/linux/errno.h /usr/include/linux/string.h /usr/include/linux/stat.h
......@@ -85,18 +85,16 @@ static int msdos_readdir(struct inode *inode,struct file *filp,
put_fs_byte(c,i+dirent->d_name);
}
i = last;
if (de->ext[0] && de->ext[0] != ' ') {
put_fs_byte('.',i+dirent->d_name);
put_fs_byte('.',i+dirent->d_name);
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);
i++;
for (i2 = 0; i2 < 3; i2++) {
if (!(c = de->ext[i2])) break;
if (c >= 'A' && c <= 'Z') c += 32;
put_fs_byte(c,i+dirent->d_name);
i++;
if (c != ' ') last = i;
}
}
if (i = last) {
if ((i = last) != 0) {
if (!strcmp(de->name,MSDOS_DOT))
ino = inode->i_ino;
else if (!strcmp(de->name,MSDOS_DOTDOT))
......
......@@ -282,7 +282,7 @@ int fat_free(struct inode *inode,int skip)
panic("fat_free: deleting beyond EOF");
if (MSDOS_SB(inode->i_sb)->free_clusters != -1)
MSDOS_SB(inode->i_sb)->free_clusters++;
inode->i_blocks--;
inode->i_blocks -= MSDOS_SB(inode->i_sb)->cluster_size;
}
unlock_fat(inode->i_sb);
cache_inval_inode(inode);
......
......@@ -94,7 +94,7 @@ static int msdos_file_read(struct inode *inode,struct file *filp,char *buf,
}
if (filp->f_pos >= inode->i_size || count <= 0) return 0;
start = buf;
while (left = MIN(inode->i_size-filp->f_pos,count-(buf-start))) {
while ((left = MIN(inode->i_size-filp->f_pos,count-(buf-start))) > 0){
if (!(sector = msdos_smap(inode,filp->f_pos >> SECTOR_BITS)))
break;
offset = filp->f_pos & (SECTOR_SIZE-1);
......
......@@ -70,7 +70,8 @@ static int parse_options(char *options,char *check,char *conversion,uid_t *uid,
*umask = current->umask;
if (!options) return 1;
for (this = strtok(options,","); this; this = strtok(NULL,",")) {
if (value = strchr(this,'=')) *value++ = 0;
if ((value = strchr(this,'=')) != NULL)
*value++ = 0;
if (!strcmp(this,"check") && value) {
if (value[0] && !value[1] && strchr("rns",*value))
*check = *value;
......@@ -254,7 +255,7 @@ void msdos_read_inode(struct inode *inode)
inode->i_blksize = MSDOS_SB(inode->i_sb)->cluster_size*
SECTOR_SIZE;
inode->i_blocks = (inode->i_size+inode->i_blksize-1)/
inode->i_blksize;
inode->i_blksize*MSDOS_SB(inode->i_sb)->cluster_size;
MSDOS_I(inode)->i_start = 0;
MSDOS_I(inode)->i_attrs = 0;
inode->i_mtime = inode->i_atime = inode->i_ctime = 0;
......@@ -279,7 +280,7 @@ void msdos_read_inode(struct inode *inode)
}
#endif
inode->i_size = 0;
if (this = raw_entry->start)
if ((this = raw_entry->start) != 0)
while (this != -1) {
inode->i_size += SECTOR_SIZE*MSDOS_SB(inode->
i_sb)->cluster_size;
......@@ -304,7 +305,7 @@ void msdos_read_inode(struct inode *inode)
/* this is as close to the truth as we can get ... */
inode->i_blksize = MSDOS_SB(inode->i_sb)->cluster_size*SECTOR_SIZE;
inode->i_blocks = (inode->i_size+inode->i_blksize-1)/
inode->i_blksize;
inode->i_blksize*MSDOS_SB(inode->i_sb)->cluster_size;
inode->i_mtime = inode->i_atime = inode->i_ctime =
date_dos2unix(raw_entry->time,raw_entry->date);
brelse(bh);
......
......@@ -118,7 +118,7 @@ printk("free cluster: %d\n",this);
printk("set to %x\n",fat_access(inode->i_sb,this,-1));
#endif
last = 0;
if (current = MSDOS_I(inode)->i_start) {
if ((current = MSDOS_I(inode)->i_start) != 0) {
cache_lookup(inode,0x7fffffff,&last,&current);
while (current && current != -1)
if (!(current = fat_access(inode->i_sb,
......@@ -163,7 +163,7 @@ printk("zeroing sector %d\n",sector);
brelse(bh);
}
}
inode->i_blocks++;
inode->i_blocks += MSDOS_SB(inode->i_sb)->cluster_size;
if (S_ISDIR(inode->i_mode)) {
if (inode->i_size & (SECTOR_SIZE-1))
panic("Odd directory size");
......
......@@ -24,7 +24,7 @@ static char *reserved_names[] = {
/* Characters that are undesirable in an MS-DOS file name */
static char bad_chars[] = "*?<>|\" ";
static char bad_chars[] = "*?<>|\"";
static char bad_if_strict[] = "+=,;";
......@@ -180,7 +180,8 @@ static int msdos_create_entry(struct inode *dir,char *name,int is_dir,
date_unix2dos(CURRENT_TIME,&de->time,&de->date);
de->size = 0;
bh->b_dirt = 1;
if (*result = iget(dir->i_sb,ino)) msdos_read_inode(*result);
if ((*result = iget(dir->i_sb,ino)) != NULL)
msdos_read_inode(*result);
brelse(bh);
if (!*result) return -EIO;
(*result)->i_mtime = (*result)->i_atime = (*result)->i_ctime =
......@@ -409,7 +410,7 @@ static int rename_same_dir(struct inode *old_dir,char *old_name,
memcpy(old_de->name,new_name,MSDOS_NAME);
old_bh->b_dirt = 1;
if (MSDOS_SB(old_dir->i_sb)->conversion == 'a') /* update binary info */
if (old_inode = iget(old_dir->i_sb,old_ino)) {
if ((old_inode = iget(old_dir->i_sb,old_ino)) != NULL) {
msdos_read_inode(old_inode);
iput(old_inode);
}
......
......@@ -65,7 +65,8 @@ int lookup(struct inode * dir,const char * name, int len,
else if ((sb = dir->i_sb) && (dir == sb->s_mounted)) {
sb = dir->i_sb;
iput(dir);
if (dir = sb->s_covered)
dir = sb->s_covered;
if (dir)
dir->i_count++;
}
}
......@@ -258,7 +259,8 @@ int open_namei(const char * pathname, int flag, int mode,
iput(inode);
return -EEXIST;
}
if (error = follow_link(dir,inode,flag,mode,&inode))
error = follow_link(dir,inode,flag,mode,&inode);
if (error)
return error;
if (S_ISDIR(inode->i_mode) && (flag & 2)) {
iput(inode);
......
......@@ -357,7 +357,8 @@ int sys_open(const char * filename,int flag,int mode)
return -ENFILE;
current->filp[fd] = f;
f->f_flags = flag;
if (f->f_mode = (flag+1) & O_ACCMODE)
f->f_mode = (flag+1) & O_ACCMODE;
if (f->f_mode)
flag++;
if (flag & (O_TRUNC | O_CREAT))
flag |= 2;
......@@ -388,13 +389,15 @@ int sys_open(const char * filename,int flag,int mode)
f->f_op = NULL;
if (inode->i_op)
f->f_op = inode->i_op->default_file_ops;
if (f->f_op && f->f_op->open)
if (i = f->f_op->open(inode,f)) {
if (f->f_op && f->f_op->open) {
i = f->f_op->open(inode,f);
if (i) {
iput(inode);
f->f_count--;
current->filp[fd]=NULL;
return i;
}
}
f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
return (fd);
}
......@@ -457,7 +460,7 @@ static void kill_wait(struct wait_queue **q, int sig)
do {
tmp = next;
next = tmp->next;
if (p = tmp->task)
if ((p = tmp->task) != NULL)
send_sig (sig, p , 1);
} while (next && next != *q);
}
......
......@@ -14,7 +14,7 @@
.s.o:
$(AS) -o $*.o $<
OBJS= inode.o root.o base.o mem.o link.o fd.o
OBJS= inode.o root.o base.o mem.o link.o fd.o array.o
proc.o: $(OBJS)
$(LD) -r -o proc.o $(OBJS)
......@@ -29,58 +29,74 @@ dep:
cp tmp_make Makefile
### Dependencies:
array.o : array.c /usr/include/linux/types.h /usr/include/linux/errno.h /usr/include/linux/sched.h \
/usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \
/usr/include/linux/wait.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
/usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
/usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
/usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
/usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
/usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/asm/segment.h \
/usr/include/asm/io.h
base.o : base.c /usr/include/asm/segment.h /usr/include/linux/errno.h /usr/include/linux/sched.h \
/usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \
/usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \
/usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \
/usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h \
/usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h \
/usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
/usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
/usr/include/linux/math_emu.h /usr/include/linux/proc_fs.h /usr/include/linux/stat.h
/usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
/usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
/usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
/usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
/usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
/usr/include/linux/proc_fs.h /usr/include/linux/stat.h
fd.o : fd.c /usr/include/asm/segment.h /usr/include/linux/errno.h /usr/include/linux/sched.h \
/usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \
/usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \
/usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \
/usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h \
/usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h \
/usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
/usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
/usr/include/linux/math_emu.h /usr/include/linux/proc_fs.h /usr/include/linux/stat.h
/usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
/usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
/usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
/usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
/usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
/usr/include/linux/proc_fs.h /usr/include/linux/stat.h
inode.o : inode.c /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \
/usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \
/usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
/usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
/usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
/usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/proc_fs.h \
/usr/include/linux/string.h /usr/include/linux/stat.h /usr/include/linux/locks.h \
/usr/include/asm/system.h /usr/include/asm/segment.h
/usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
/usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \
/usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
/usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
/usr/include/linux/math_emu.h /usr/include/linux/proc_fs.h /usr/include/linux/string.h \
/usr/include/linux/stat.h /usr/include/linux/locks.h /usr/include/asm/system.h \
/usr/include/asm/segment.h
link.o : link.c /usr/include/asm/segment.h /usr/include/linux/errno.h /usr/include/linux/sched.h \
/usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \
/usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \
/usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \
/usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h \
/usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h \
/usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
/usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
/usr/include/linux/math_emu.h /usr/include/linux/minix_fs.h /usr/include/linux/stat.h
/usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
/usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
/usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
/usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
/usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
/usr/include/linux/minix_fs.h /usr/include/linux/stat.h
mem.o : mem.c /usr/include/linux/types.h /usr/include/linux/errno.h /usr/include/linux/sched.h \
/usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \
/usr/include/linux/wait.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
/usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
/usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
/usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
/usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
/usr/include/asm/segment.h /usr/include/asm/io.h
/usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \
/usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
/usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
/usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
/usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/asm/segment.h \
/usr/include/asm/io.h
root.o : root.c /usr/include/asm/segment.h /usr/include/linux/errno.h /usr/include/linux/sched.h \
/usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \
/usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \
/usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \
/usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/minix_fs_sb.h \
/usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/mm.h \
/usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \
/usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \
/usr/include/linux/math_emu.h /usr/include/linux/proc_fs.h /usr/include/linux/stat.h
/usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
/usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
/usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \
/usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
/usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
/usr/include/linux/proc_fs.h /usr/include/linux/stat.h
/*
* linux/fs/proc/array.c
*
* Copyright (C) 1992 by Linus Torvalds
* based on ideas by Darren Senn
*/
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <asm/segment.h>
#include <asm/io.h>
static int get_loadavg(char * buffer)
{
return sprintf(buffer,"%d.%02d %d.%02d %d.%02d\n",
avenrun[0] >> FSHIFT,
(FIXED_1/2 + (avenrun[0] & (FIXED_1-1))*100) >> FSHIFT,
avenrun[1] >> FSHIFT,
(FIXED_1/2 + (avenrun[1] & (FIXED_1-1))*100) >> FSHIFT,
avenrun[2] >> FSHIFT,
(FIXED_1/2 + (avenrun[2] & (FIXED_1-1))*100) >> FSHIFT);
}
static int get_uptime(char * buffer)
{
return sprintf(buffer,"%d\n",(jiffies+jiffies_offset)/HZ);
}
static int get_meminfo(char * buffer)
{
struct sysinfo i;
si_meminfo(&i);
si_swapinfo(&i);
return sprintf(buffer, " total: used: free: shared: buffers:\n"
"Mem: %8d %8d %8d %8d %8d\n"
"Swap: %8d %8d %8d\n",
i.totalram, i.totalram-i.freeram, i.freeram, i.sharedram, i.bufferram,
i.totalswap, i.totalswap-i.freeswap, i.freeswap);
}
static struct task_struct ** get_task(pid_t pid)
{
struct task_struct ** p;
p = task;
while (++p < task+NR_TASKS) {
if (*p && (*p)->pid == pid)
return p;
}
return NULL;
}
static unsigned long get_phys_addr(struct task_struct ** p, unsigned long ptr)
{
unsigned long page;
if (!p || !*p || ptr >= TASK_SIZE)
return 0;
page = (*p)->tss.cr3;
page += (ptr >> 20) & 0xffc;
page = *(unsigned long *) page;
if (!(page & 1))
return 0;
page &= 0xfffff000;
page += (ptr >> 10) & 0xffc;
page = *(unsigned long *) page;
if (!(page & 1))
return 0;
page &= 0xfffff000;
page += ptr & 0xfff;
return page;
}
static unsigned long get_long(struct task_struct ** p, unsigned long ptr)
{
unsigned long addr;
if (ptr & 3)
return 0;
addr = get_phys_addr(p,ptr);
if (!addr)
return 0;
return *(unsigned long *) addr;
}
static int get_char(struct task_struct ** p, unsigned long ptr)
{
unsigned long addr;
addr = get_phys_addr(p,ptr);
if (!addr)
return -1;
return *(unsigned char *) addr;
}
static int get_array(struct task_struct ** p, unsigned long ptr, char * buffer)
{
unsigned long tmp;
int size = 0, result = 0;
unsigned long array;
char c;
array = get_long(p,ptr);
if (!ptr)
return 0;
for (;;) {
tmp = get_long(p,array);
if (!tmp)
return result;
array += 4;
while ((c = get_char(p,tmp++)) > 0) {
if (size < PAGE_SIZE)
buffer[size++] = c;
else
return result;
}
if (c < 0)
return result;
result = size;
if (size < PAGE_SIZE)
buffer[size++] = '\0';
}
}
static int get_env(int pid, char * buffer)
{
struct task_struct ** p = get_task(pid);
if (!p || !*p)
return 0;
return get_array(p, (*p)->start_stack+8, buffer);
}
static int get_arg(int pid, char * buffer)
{
struct task_struct ** p = get_task(pid);
if (!p || !*p)
return 0;
return get_array(p, (*p)->start_stack+4, buffer);
}
static int get_stat(int pid, char * buffer)
{
struct task_struct ** p = get_task(pid);
char state;
if (!p || !*p)
return 0;
if ((*p)->state < 0)
state = '.';
else
state = "RSDZTD"[(*p)->state];
return sprintf(buffer,"%d (%s) %c %d %d %d %d\n",
pid,
(*p)->comm,
state,
(*p)->p_pptr->pid,
(*p)->pgrp,
(*p)->session,
(*p)->tty);
}
static int array_read(struct inode * inode, struct file * file,char * buf, int count)
{
char * page;
int length;
int end;
int type, pid;
if (count < 0)
return -EINVAL;
page = (char *) get_free_page(GFP_KERNEL);
*page = 0;
if (!page)
return -ENOMEM;
type = inode->i_ino;
pid = type >> 16;
type &= 0x0000ffff;
switch (type) {
case 2:
length = get_loadavg(page);
break;
case 3:
length = get_uptime(page);
break;
case 4:
length = get_meminfo(page);
break;
case 9:
length = get_env(pid, page);
break;
case 10:
length = get_arg(pid, page);
break;
case 11:
length = get_stat(pid, page);
break;
default:
return -EBADF;
}
if (file->f_pos >= length)
return 0;
if (count + file->f_pos > length)
count = length - file->f_pos;
end = count + file->f_pos;
memcpy_tofs(buf, page + file->f_pos, count);
free_page((unsigned long) page);
file->f_pos = end;
return count;
}
static struct file_operations proc_array_operations = {
NULL, /* array_lseek */
array_read,
NULL, /* array_write */
NULL, /* array_readdir */
NULL, /* array_select */
NULL, /* array_ioctl */
NULL, /* mmap */
NULL, /* no special open code */
NULL /* no special release code */
};
struct inode_operations proc_array_inode_operations = {
&proc_array_operations, /* default base directory file-ops */
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 */
NULL /* truncate */
};
......@@ -48,12 +48,6 @@ struct inode_operations proc_base_inode_operations = {
NULL /* truncate */
};
struct proc_dir_entry {
unsigned short low_ino;
unsigned short namelen;
char * name;
};
static struct proc_dir_entry base_dir[] = {
{ 1,2,".." },
{ 2,1,"." },
......@@ -62,12 +56,15 @@ static struct proc_dir_entry base_dir[] = {
{ 5,4,"root" },
{ 6,3,"exe" },
{ 7,2,"fd" },
{ 8,3,"lib" }
{ 8,3,"lib" },
{ 9,7,"environ" },
{ 10,7,"cmdline" },
{ 11,4,"stat" }
};
#define NR_BASE_DIRENTRY ((sizeof (base_dir))/(sizeof (base_dir[0])))
static int proc_match(int len,const char * name,struct proc_dir_entry * de)
int proc_match(int len,const char * name,struct proc_dir_entry * de)
{
register int same __asm__("ax");
......
......@@ -11,6 +11,7 @@
#include <linux/string.h>
#include <linux/stat.h>
#include <linux/locks.h>
#include <linux/limits.h>
#include <asm/system.h>
#include <asm/segment.h>
......@@ -100,21 +101,25 @@ void proc_read_inode(struct inode * inode)
return;
if (ino == PROC_ROOT_INO) {
inode->i_mode = S_IFDIR | 0555;
inode->i_nlink = 2;
for (i = 1 ; i < NR_TASKS ; i++)
if (task[i])
inode->i_nlink++;
inode->i_op = &proc_root_inode_operations;
return;
}
if (!pid)
if (!pid) {
inode->i_mode = S_IFREG | 0444;
inode->i_op = &proc_array_inode_operations;
return;
}
ino &= 0x0000ffff;
inode->i_uid = p->euid;
inode->i_gid = p->egid;
switch (ino) {
case 2:
inode->i_nlink = 2;
for (i = 1 ; i < NR_TASKS ; i++)
if (task[i])
inode->i_nlink++;
inode->i_mode = S_IFDIR | 0500;
inode->i_nlink = 4;
inode->i_mode = S_IFDIR | 0555;
inode->i_op = &proc_base_inode_operations;
return;
case 3:
......@@ -135,6 +140,12 @@ void proc_read_inode(struct inode * inode)
inode->i_op = &proc_fd_inode_operations;
inode->i_nlink = 2;
return;
case 9:
case 10:
case 11:
inode->i_mode = S_IFREG | 0444;
inode->i_op = &proc_array_inode_operations;
return;
}
switch (ino >> 8) {
case 1:
......
......@@ -48,6 +48,16 @@ struct inode_operations proc_root_inode_operations = {
NULL /* truncate */
};
static struct proc_dir_entry root_dir[] = {
{ 1,1,"." },
{ 1,2,".." },
{ 2,7,"loadavg" },
{ 3,6,"uptime" },
{ 4,7,"meminfo" }
};
#define NR_ROOT_DIRENTRY ((sizeof (root_dir))/(sizeof (root_dir[0])))
static int proc_lookuproot(struct inode * dir,const char * name, int len,
struct inode ** result)
{
......@@ -61,34 +71,40 @@ static int proc_lookuproot(struct inode * dir,const char * name, int len,
iput(dir);
return -ENOENT;
}
pid = 0;
if (!len || (get_fs_byte(name) == '.' && (len == 1 ||
(get_fs_byte(name+1) == '.' && len == 2)))) {
*result = dir;
return 0;
}
while (len-- > 0) {
c = get_fs_byte(name) - '0';
name++;
if (c > 9) {
pid = 0;
break;
i = NR_ROOT_DIRENTRY;
while (i-- > 0 && !proc_match(len,name,root_dir+i))
/* nothing */;
if (i >= 0) {
ino = root_dir[i].low_ino;
if (ino == 1) {
*result = dir;
return 0;
}
pid *= 10;
pid += c;
if (pid & 0xffff0000) {
pid = 0;
break;
} else {
pid = 0;
while (len-- > 0) {
c = get_fs_byte(name) - '0';
name++;
if (c > 9) {
pid = 0;
break;
}
pid *= 10;
pid += c;
if (pid & 0xffff0000) {
pid = 0;
break;
}
}
for (i = 0 ; i < NR_TASKS ; i++)
if (task[i] && task[i]->pid == pid)
break;
if (!pid || i >= NR_TASKS) {
iput(dir);
return -ENOENT;
}
ino = (pid << 16) + 2;
}
for (i = 0 ; i < NR_TASKS ; i++)
if (task[i] && task[i]->pid == pid)
break;
if (!pid || i >= NR_TASKS) {
iput(dir);
return -ENOENT;
}
ino = (pid << 16) + 2;
if (!(*result = iget(dir->i_sb,ino))) {
iput(dir);
return -ENOENT;
......@@ -101,42 +117,48 @@ static int proc_readroot(struct inode * inode, struct file * filp,
struct dirent * dirent, int count)
{
struct task_struct * p;
unsigned int pid;
unsigned int nr,pid;
int i,j;
if (!inode || !S_ISDIR(inode->i_mode))
return -EBADF;
while ((pid = filp->f_pos) < NR_TASKS+2) {
repeat:
nr = filp->f_pos;
if (nr < NR_ROOT_DIRENTRY) {
struct proc_dir_entry * de = root_dir + nr;
filp->f_pos++;
if (pid < 2) {
i = j = pid+1;
put_fs_long(1, &dirent->d_ino);
put_fs_word(i, &dirent->d_reclen);
put_fs_byte(0, i+dirent->d_name);
while (i--)
put_fs_byte('.', i+dirent->d_name);
return j;
}
p = task[pid-2];
if (!p || !(pid = p->pid))
continue;
if (pid & 0xffff0000)
continue;
j = 10;
i = 1;
while (pid >= j) {
j *= 10;
i++;
}
i = de->namelen;
put_fs_long(de->low_ino, &dirent->d_ino);
put_fs_word(i,&dirent->d_reclen);
put_fs_byte(0,i+dirent->d_name);
j = i;
put_fs_long((pid << 16)+2, &dirent->d_ino);
put_fs_word(i, &dirent->d_reclen);
put_fs_byte(0, i+dirent->d_name);
while (i--) {
put_fs_byte('0'+(pid % 10), i+dirent->d_name);
pid /= 10;
}
while (i--)
put_fs_byte(de->name[i], i+dirent->d_name);
return j;
}
return 0;
nr -= NR_ROOT_DIRENTRY;
if (nr >= NR_TASKS)
return 0;
filp->f_pos++;
p = task[nr];
if (!p || !(pid = p->pid))
goto repeat;
if (pid & 0xffff0000)
goto repeat;
j = 10;
i = 1;
while (pid >= j) {
j *= 10;
i++;
}
j = i;
put_fs_long((pid << 16)+2, &dirent->d_ino);
put_fs_word(i, &dirent->d_reclen);
put_fs_byte(0, i+dirent->d_name);
while (i--) {
put_fs_byte('0'+(pid % 10), i+dirent->d_name);
pid /= 10;
}
return j;
}
......@@ -102,11 +102,11 @@ int do_select(int n, fd_set *in, fd_set *out, fd_set *ex,
FD_ZERO(res_out);
FD_ZERO(res_ex);
count = 0;
repeat:
wait_table.nr = 0;
wait_table.entry = entry;
current->state = TASK_INTERRUPTIBLE;
wait = &wait_table;
repeat:
current->state = TASK_INTERRUPTIBLE;
for (i = 0 ; i < n ; i++) {
if (FD_ISSET(i,in) && check(SEL_IN,wait,current->filp[i])) {
FD_SET(i, res_in);
......@@ -124,10 +124,9 @@ int do_select(int n, fd_set *in, fd_set *out, fd_set *ex,
wait = NULL;
}
}
if (!count && current->timeout
&& !(current->signal & ~current->blocked)) {
wait = NULL;
if (!count && current->timeout && !(current->signal & ~current->blocked)) {
schedule();
free_wait(&wait_table);
goto repeat;
}
free_wait(&wait_table);
......@@ -198,9 +197,11 @@ int sys_select( unsigned long *buffer )
get_fd_set(n, exp, &ex);
timeout = 0xffffffff;
if (tvp) {
timeout = get_fs_long((unsigned long *)&tvp->tv_usec)/(1000000/HZ);
timeout = jiffies;
timeout += get_fs_long((unsigned long *)&tvp->tv_usec)/(1000000/HZ);
timeout += get_fs_long((unsigned long *)&tvp->tv_sec) * HZ;
timeout += jiffies;
if (timeout <= jiffies)
timeout = 0;
}
current->timeout = timeout;
i = do_select(n, &in, &out, &ex, &res_in, &res_out, &res_ex);
......
......@@ -121,7 +121,8 @@ static struct super_block * read_super(dev_t dev,char *name,int flags,void *data
if (!dev)
return NULL;
check_disk_change(dev);
if (s = get_super(dev))
s = get_super(dev);
if (s)
return s;
if (!(type = get_fs_type(name))) {
printk("get fs type failed %s\n",name);
......@@ -304,7 +305,6 @@ static int do_mount(dev_t dev, const char * dir, char * type, int flags, void *
iput(dir_i);
return -EBUSY;
}
sb->s_flags = flags;
sb->s_covered = dir_i;
dir_i->i_mount = 1;
return 0; /* we don't iput(dir_i) - see umount */
......@@ -348,7 +348,8 @@ int sys_mount(char * dev_name, char * dir_name, char * type,
return -ENODEV;
t = fstype->name;
if (fstype->requires_dev) {
if (retval = namei(dev_name,&inode))
retval = namei(dev_name,&inode);
if (retval)
return retval;
if (!S_ISBLK(inode->i_mode)) {
iput(inode);
......@@ -371,7 +372,8 @@ int sys_mount(char * dev_name, char * dir_name, char * type,
}
fops = blkdev_fops[MAJOR(dev)];
if (fops && fops->open) {
if (retval = fops->open(inode,NULL)) {
retval = fops->open(inode,NULL);
if (retval) {
iput(inode);
return retval;
}
......
This diff is collapsed.
......@@ -24,13 +24,13 @@
#define SLOW_DOWN_IO __SLOW_DOWN_IO
#endif
extern void inline outb(char value, unsigned short port)
extern inline void outb(char value, unsigned short port)
{
__asm__ __volatile__ ("outb %%al,%%dx"
::"a" ((char) value),"d" ((unsigned short) port));
}
extern unsigned int inline inb(unsigned short port)
extern inline unsigned int inb(unsigned short port)
{
unsigned int _v;
__asm__ __volatile__ ("inb %%dx,%%al"
......@@ -38,14 +38,14 @@ __asm__ __volatile__ ("inb %%dx,%%al"
return _v;
}
extern void inline outb_p(char value, unsigned short port)
extern inline void outb_p(char value, unsigned short port)
{
__asm__ __volatile__ ("outb %%al,%%dx"
::"a" ((char) value),"d" ((unsigned short) port));
SLOW_DOWN_IO;
}
extern unsigned int inline inb_p(unsigned short port)
extern inline unsigned int inb_p(unsigned short port)
{
unsigned int _v;
__asm__ __volatile__ ("inb %%dx,%%al"
......
......@@ -119,8 +119,6 @@ __asm__( \
"pushl $" #nr "\n\t" \
"call _do_IRQ\n\t" \
"addl $8,%esp\n\t" \
"testl %eax,%eax\n\t" \
"jne ret_from_sys_call\n\t" \
"cli\n\t" \
UNBLK_##chip(mask) \
"jmp ret_from_sys_call\n" \
......@@ -131,11 +129,8 @@ __asm__( \
"pushl $" #nr "\n\t" \
"call _do_fast_IRQ\n\t" \
"addl $4,%esp\n\t" \
"testl %eax,%eax\n\t" \
"jne 2f\n\t" \
"cli\n\t" \
UNBLK_##chip(mask) \
"\n2:\t" \
RESTORE_MOST \
"\n\n.align 2\n" \
"_bad_IRQ" #nr "_interrupt:\n\t" \
......
extern inline unsigned char get_fs_byte(const char * addr)
{
unsigned register char _v;
register unsigned char _v;
__asm__ ("movb %%fs:%1,%0":"=q" (_v):"m" (*addr));
return _v;
......
......@@ -7,6 +7,8 @@
#undef CONFIG_SCSI_AHA1542
#define CONFIG_SCSI_AHA1542
#undef CONFIG_SCSI_AHA1740
#define CONFIG_SCSI_AHA1740
#undef CONFIG_SCSI_CSC
#define CONFIG_SCSI_CSC
#undef CONFIG_SCSI_DTC
......
......@@ -78,6 +78,7 @@
*/
#undef CONFIG_SCSI_AHA1542
#undef CONFIG_SCSI_AHA1740
#undef CONFIG_SCSI_ALWAYS
#undef CONFIG_SCSI_CSC
#undef CONFIG_SCSI_DTC
......@@ -92,7 +93,7 @@ defined(CONFIG_CHR_DEV_ST)
#define CONFIG_SCSI
#endif
#if !defined(CONFIG_SCSI_AHA1542) && !defined(CONFIG_SCSI_CSC) && !defined(CONFIG_SCSI_DTC) && \
#if !defined(CONFIG_SCSI_AHA1542) && !defined(CONFIG_SCSI_AHA1740) && !defined(CONFIG_SCSI_CSC) && !defined(CONFIG_SCSI_DTC) && \
!defined(CONFIG_SCSI_FUTURE_DOMAIN) && !defined(CONFIG_SCSI_SEAGATE) && !defined(CONFIG_SCSI_ULTRASTOR) && \
!defined(CONFIG_SCSI_7000FASST)
#error Error : SCSI devices enabled, but no low level drivers have been enabled.
......@@ -108,6 +109,7 @@ defined(CONFIG_CHR_DEV_ST)
#define MSDOS_FS
#define PROC_FS
#undef NFS_FS
#undef ISO9660_FS
#ifdef CONFIG_DISTRIBUTION
#include <linux/config.dist.h>
......
......@@ -74,7 +74,7 @@ extern int ext_link(struct inode * oldinode, struct inode * dir, const char * na
extern int ext_mknod(struct inode * dir, const char * name, int len, int mode, int rdev);
extern int ext_rename(struct inode * old_dir, const char * old_name, int old_len,
struct inode * new_dir, const char * new_name, int new_len);
extern struct inode * ext_new_inode(struct super_block * sb);
extern struct inode * ext_new_inode(const struct inode * dir);
extern void ext_free_inode(struct inode * inode);
extern unsigned long ext_count_free_inodes(struct super_block *sb);
extern int ext_new_block(struct super_block * sb);
......
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.
......@@ -57,7 +57,7 @@ extern int minix_link(struct inode * oldinode, struct inode * dir, const char *
extern int minix_mknod(struct inode * dir, const char * name, int len, int mode, int rdev);
extern int minix_rename(struct inode * old_dir, const char * old_name, int old_len,
struct inode * new_dir, const char * new_name, int new_len);
extern struct inode * minix_new_inode(struct super_block * sb);
extern struct inode * minix_new_inode(const struct inode * dir);
extern void minix_free_inode(struct inode * inode);
extern unsigned long minix_count_free_inodes(struct super_block *sb);
extern int minix_new_block(struct super_block * sb);
......
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.
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.
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.
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