Commit 591f1652 authored by Linus Torvalds's avatar Linus Torvalds

Import 1.1.58

parent beadddbf
......@@ -97,6 +97,7 @@ S: United Kingdom
N: Remy Card
E: Remy.Card@masi.ibp.fr
E: Remy.Card@linux.org
D: Extended file system designer and developer
D: Second extended file system designer and developer
S: Institut Blaise Pascal
......
VERSION = 1
PATCHLEVEL = 1
SUBLEVEL = 57
SUBLEVEL = 58
ARCH = i386
......
......@@ -11,6 +11,7 @@
#include <linux/config.h>
#include <linux/sched.h>
#include <linux/minix_fs.h>
#include <linux/ext2_fs.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/string.h>
......@@ -98,7 +99,17 @@ long rd_init(long mem_start, int length)
static void do_load(void)
{
struct buffer_head *bh;
struct minix_super_block s;
struct super_block {
union
{
char minix [sizeof (struct minix_super_block)];
char ext2 [sizeof (struct ext2_super_block)];
} record;
} sb;
struct minix_super_block *minixsb =
(struct minix_super_block *)&sb;
struct ext2_super_block *ext2sb =
(struct ext2_super_block *)&sb;
int block, tries;
int i = 1;
int nblocks;
......@@ -121,12 +132,32 @@ static void do_load(void)
}
/* This is silly- why do we require it to be a MINIX FS? */
*((struct minix_super_block *) &s) =
*((struct minix_super_block *) bh->b_data);
*((struct super_block *) &sb) =
*((struct super_block *) bh->b_data);
brelse(bh);
nblocks = s.s_nzones << s.s_log_zone_size;
if (s.s_magic != MINIX_SUPER_MAGIC &&
s.s_magic != MINIX_SUPER_MAGIC2) {
/* Try Minix */
nblocks = -1;
if (minixsb->s_magic == MINIX_SUPER_MAGIC ||
minixsb->s_magic == MINIX_SUPER_MAGIC2) {
printk("RAMDISK: Minix filesystem found at block %d\n",
block);
nblocks = minixsb->s_nzones << minixsb->s_log_zone_size;
}
/* Try ext2 */
if (nblocks == -1 && (ext2sb->s_magic ==
EXT2_PRE_02B_MAGIC ||
ext2sb->s_magic == EXT2_SUPER_MAGIC))
{
printk("RAMDISK: Ext2 filesystem found at block %d\n",
block);
nblocks = ext2sb->s_blocks_count;
}
if (nblocks == -1)
{
printk("RAMDISK: trying old-style RAM image.\n");
continue;
}
......
Mon Oct 24 23:36:21 1994 Theodore Y. Ts'o (tytso@rt-11)
* serial.c (rs_close): Add a timeout to the transmitter flush
loop; this is just a sanity check in case we have flakey
(or non-existent-but-configured-by-the-user) hardware.
Fri Oct 21 09:37:23 1994 Theodore Y. Ts'o (tytso@rt-11)
* tty_io.c (tty_fasync): When asyncronous I/O is enabled, if the
process or process group has not be specified yet, set it
to be the tty's process group, or if that is not yet set,
to the current process's pid.
Thu Oct 20 23:17:28 1994 Theodore Y. Ts'o (tytso@rt-11)
* n_tty.c (n_tty_receive_room): If we are doing input
canonicalization, let as many characters through as
possible, so that the excess characters can be "beeped".
Tue Oct 18 10:02:43 1994 Theodore Y. Ts'o (tytso@rt-11)
* serial.c (rs_start): Removed an incorrect '!' that was
......
......@@ -584,6 +584,14 @@ static int n_tty_receive_room(struct tty_struct *tty)
{
int left = N_TTY_BUF_SIZE - tty->read_cnt - 1;
/*
* If we are doing input canonicalization, let as many
* characters through as possible, so that the excess
* characters can be "beeped".
*/
if (L_ICANON(tty))
return N_TTY_BUF_SIZE;
if (left > 0)
return left;
return 0;
......
......@@ -1735,6 +1735,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
{
struct async_struct * info = (struct async_struct *)tty->driver_data;
unsigned long flags;
unsigned long timeout;
if (!info || serial_paranoia_check(info, tty->device, "rs_close"))
return;
......@@ -1786,10 +1787,13 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
* has completely drained; this is especially
* important if there is a transmit FIFO!
*/
timeout = jiffies+HZ;
while (!(serial_inp(info, UART_LSR) & UART_LSR_TEMT)) {
current->state = TASK_INTERRUPTIBLE;
current->timeout = jiffies + info->timeout;
schedule();
if (jiffies > timeout)
break;
}
}
shutdown(info);
......
......@@ -1175,6 +1175,12 @@ static int tty_fasync(struct inode * inode, struct file * filp, int on)
tty->fasync = fa;
if (!tty->read_wait)
tty->minimum_to_wake = 1;
if (filp->f_owner == 0) {
if (tty->pgrp)
filp->f_owner = -tty->pgrp;
else
filp->f_owner = current->pid;
}
} else {
if (!fa)
return 0;
......
Mon Oct 24 23:27:42 1994 Theodore Y. Ts'o (tytso@rt-11)
* fcntl.c (sys_fcntl): Liberalize security checks which Alan Cox
put in.
Thu Oct 20 23:44:22 1994 Theodore Y. Ts'o (tytso@rt-11)
* fcntl.c (sys_fcntl): Add more of a security check to the
F_SETOWN fcntl().
Changes from version 0.5 to version 0.5a
========================================
- Some cleanups in the error messages (some versions of syslog contain
a bug which truncates an error message if it contains '\n').
- Check that no data can be written to a file past the 2GB limit.
- The famous readdir() bug has been fixed by Stephen Tweedie.
- Added a revision level in the superblock.
- Full support for O_SYNC flag of the open system call.
- New mount options: `bsddf' and `minixdf'. `bsddf' causes ext2fs
......
......@@ -44,7 +44,7 @@ static struct ext2_group_desc * get_group_desc (struct super_block * sb,
if (block_group >= sb->u.ext2_sb.s_groups_count)
ext2_panic (sb, "get_group_desc",
"block_group >= groups_count\n"
"block_group >= groups_count - "
"block_group = %d, groups_count = %lu",
block_group, sb->u.ext2_sb.s_groups_count);
......@@ -52,7 +52,7 @@ static struct ext2_group_desc * get_group_desc (struct super_block * sb,
desc = block_group % EXT2_DESC_PER_BLOCK(sb);
if (!sb->u.ext2_sb.s_group_desc[group_desc])
ext2_panic (sb, "get_group_desc",
"Group descriptor not loaded\n"
"Group descriptor not loaded - "
"block_group = %d, group_desc = %lu, desc = %lu",
block_group, group_desc, desc);
gdp = (struct ext2_group_desc *)
......@@ -73,7 +73,7 @@ static void read_block_bitmap (struct super_block * sb,
bh = bread (sb->s_dev, gdp->bg_block_bitmap, sb->s_blocksize);
if (!bh)
ext2_panic (sb, "read_block_bitmap",
"Cannot read block bitmap\n"
"Cannot read block bitmap - "
"block_group = %d, block_bitmap = %lu",
block_group, gdp->bg_block_bitmap);
sb->u.ext2_sb.s_block_bitmap_number[bitmap_nr] = block_group;
......@@ -100,7 +100,7 @@ static int load__block_bitmap (struct super_block * sb,
if (block_group >= sb->u.ext2_sb.s_groups_count)
ext2_panic (sb, "load_block_bitmap",
"block_group >= groups_count\n"
"block_group >= groups_count - "
"block_group = %d, groups_count = %lu",
block_group, sb->u.ext2_sb.s_groups_count);
......@@ -185,7 +185,7 @@ void ext2_free_blocks (struct super_block * sb, unsigned long block,
if (block < es->s_first_data_block ||
(block + count) > es->s_blocks_count) {
ext2_error (sb, "ext2_free_blocks",
"Freeing blocks not in datazone\n"
"Freeing blocks not in datazone - "
"block = %lu, count = %lu", block, count);
unlock_super (sb);
return;
......@@ -198,7 +198,7 @@ void ext2_free_blocks (struct super_block * sb, unsigned long block,
bit = (block - es->s_first_data_block) % EXT2_BLOCKS_PER_GROUP(sb);
if (bit + count > EXT2_BLOCKS_PER_GROUP(sb))
ext2_panic (sb, "ext2_free_blocks",
"Freeing blocks across group boundary\n"
"Freeing blocks across group boundary - "
"Block = %lu, count = %lu",
block, count);
bitmap_nr = load_block_bitmap (sb, block_group);
......@@ -213,7 +213,7 @@ void ext2_free_blocks (struct super_block * sb, unsigned long block,
in_range (block + count - 1, gdp->bg_inode_table,
sb->u.ext2_sb.s_itb_per_group)))
ext2_panic (sb, "ext2_free_blocks",
"Freeing blocks in system zones\n"
"Freeing blocks in system zones - "
"Block = %lu, count = %lu",
block, count);
......@@ -404,7 +404,7 @@ int ext2_new_block (struct super_block * sb, unsigned long goal,
tmp == gdp->bg_inode_bitmap ||
in_range (tmp, gdp->bg_inode_table, sb->u.ext2_sb.s_itb_per_group)))
ext2_panic (sb, "ext2_new_block",
"Allocating block in system zone\n"
"Allocating block in system zone - "
"block = %u", tmp);
if (set_bit (j, bh->b_data)) {
......@@ -445,7 +445,7 @@ int ext2_new_block (struct super_block * sb, unsigned long goal,
if (j >= es->s_blocks_count) {
ext2_error (sb, "ext2_new_block",
"block >= blocks count\n"
"block >= blocks count - "
"block_group = %d, block=%d", i, j);
unlock_super (sb);
return 0;
......
......@@ -230,7 +230,9 @@ static int ext2_file_read (struct inode * inode, struct file * filp,
static int ext2_file_write (struct inode * inode, struct file * filp,
char * buf, int count)
{
off_t pos;
const loff_t two_gb = 2147483647;
loff_t pos;
off_t pos2;
int written, c;
struct buffer_head * bh, *bufferlist[NBUF];
char * p;
......@@ -251,7 +253,7 @@ static int ext2_file_write (struct inode * inode, struct file * filp,
return -ENOSPC;
if (!S_ISREG(inode->i_mode)) {
ext2_warning (sb, "ext2_file_write", "mode = %07o\n",
ext2_warning (sb, "ext2_file_write", "mode = %07o",
inode->i_mode);
return -EINVAL;
}
......@@ -260,6 +262,7 @@ static int ext2_file_write (struct inode * inode, struct file * filp,
pos = inode->i_size;
else
pos = filp->f_pos;
pos2 = (off_t) pos;
/*
* If a file has been opened in synchronous mode, we have to ensure
* that meta-data will also be written synchronously. Thus, we
......@@ -270,13 +273,18 @@ static int ext2_file_write (struct inode * inode, struct file * filp,
inode->u.ext2_i.i_osync++;
written = 0;
while (written < count) {
bh = ext2_getblk (inode, pos / sb->s_blocksize, 1, &err);
if (pos > two_gb) {
if (!written)
written = -EFBIG;
break;
}
bh = ext2_getblk (inode, pos2 / sb->s_blocksize, 1, &err);
if (!bh) {
if (!written)
written = err;
break;
}
c = sb->s_blocksize - (pos % sb->s_blocksize);
c = sb->s_blocksize - (pos2 % sb->s_blocksize);
if (c > count-written)
c = count - written;
if (c != sb->s_blocksize && !bh->b_uptodate) {
......@@ -289,7 +297,8 @@ static int ext2_file_write (struct inode * inode, struct file * filp,
break;
}
}
p = (pos % sb->s_blocksize) + bh->b_data;
p = (pos2 % sb->s_blocksize) + bh->b_data;
pos2 += c;
pos += c;
written += c;
memcpy_fromfs (p, buf, c);
......
......@@ -43,7 +43,7 @@ static struct ext2_group_desc * get_group_desc (struct super_block * sb,
if (block_group >= sb->u.ext2_sb.s_groups_count)
ext2_panic (sb, "get_group_desc",
"block_group >= groups_count\n"
"block_group >= groups_count - "
"block_group = %d, groups_count = %lu",
block_group, sb->u.ext2_sb.s_groups_count);
......@@ -51,7 +51,7 @@ static struct ext2_group_desc * get_group_desc (struct super_block * sb,
desc = block_group % EXT2_DESC_PER_BLOCK(sb);
if (!sb->u.ext2_sb.s_group_desc[group_desc])
ext2_panic (sb, "get_group_desc",
"Group descriptor not loaded\n"
"Group descriptor not loaded - "
"block_group = %d, group_desc = %lu, desc = %lu",
block_group, group_desc, desc);
gdp = (struct ext2_group_desc *)
......@@ -71,7 +71,8 @@ static void read_inode_bitmap (struct super_block * sb,
gdp = get_group_desc (sb, block_group, NULL);
bh = bread (sb->s_dev, gdp->bg_inode_bitmap, sb->s_blocksize);
if (!bh)
ext2_panic (sb, "read_inode_bitmap", "Cannot read inode bitmap\n"
ext2_panic (sb, "read_inode_bitmap",
"Cannot read inode bitmap - "
"block_group = %lu, inode_bitmap = %lu",
block_group, gdp->bg_inode_bitmap);
sb->u.ext2_sb.s_inode_bitmap_number[bitmap_nr] = block_group;
......@@ -98,7 +99,7 @@ static int load_inode_bitmap (struct super_block * sb,
if (block_group >= sb->u.ext2_sb.s_groups_count)
ext2_panic (sb, "load_inode_bitmap",
"block_group >= groups_count\n"
"block_group >= groups_count - "
"block_group = %d, groups_count = %lu",
block_group, sb->u.ext2_sb.s_groups_count);
if (sb->u.ext2_sb.s_loaded_inode_bitmaps > 0 &&
......@@ -167,7 +168,7 @@ static void set_inode_dtime (struct inode * inode,
bh = bread (inode->i_sb->s_dev, inode_block, inode->i_sb->s_blocksize);
if (!bh)
ext2_panic (inode->i_sb, "set_inode_dtime",
"Cannot load inode table block\n"
"Cannot load inode table block - "
"inode=%lu, inode_block=%lu",
inode->i_ino, inode_block);
raw_inode = ((struct ext2_inode *) bh->b_data) +
......@@ -275,7 +276,7 @@ static void inc_inode_version (struct inode * inode,
bh = bread (inode->i_sb->s_dev, inode_block, inode->i_sb->s_blocksize);
if (!bh) {
ext2_error (inode->i_sb, "inc_inode_version",
"Cannot load inode table block"
"Cannot load inode table block - "
"inode=%lu, inode_block=%lu\n",
inode->i_ino, inode_block);
inode->u.ext2_i.i_version = 1;
......@@ -431,7 +432,7 @@ struct inode * ext2_new_inode (const struct inode * dir, int mode)
j += i * EXT2_INODES_PER_GROUP(sb) + 1;
if (j < EXT2_FIRST_INO || j > es->s_inodes_count) {
ext2_error (sb, "ext2_new_inode",
"reserved inode or inode > inodes count\n"
"reserved inode or inode > inodes count - "
"block_group = %d,inode=%d", i, j);
unlock_super (sb);
iput (inode);
......@@ -464,6 +465,8 @@ struct inode * ext2_new_inode (const struct inode * dir, int mode)
inode->i_blocks = 0;
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
inode->u.ext2_i.i_flags = dir->u.ext2_i.i_flags;
if (S_ISLNK(mode))
inode->u.ext2_i.i_flags &= ~(EXT2_IMMUTABLE_FL | EXT2_APPEND_FL);
inode->u.ext2_i.i_faddr = 0;
inode->u.ext2_i.i_frag_no = 0;
inode->u.ext2_i.i_frag_size = 0;
......
......@@ -515,7 +515,7 @@ void ext2_read_inode (struct inode * inode)
/ EXT2_INODES_PER_BLOCK(inode->i_sb));
if (!(bh = bread (inode->i_dev, block, inode->i_sb->s_blocksize)))
ext2_panic (inode->i_sb, "ext2_read_inode",
"unable to read i-node block\n"
"unable to read i-node block - "
"inode=%lu, block=%lu", inode->i_ino, block);
raw_inode = ((struct ext2_inode *) bh->b_data) +
(inode->i_ino - 1) % EXT2_INODES_PER_BLOCK(inode->i_sb);
......@@ -606,7 +606,7 @@ static struct buffer_head * ext2_update_inode (struct inode * inode)
/ EXT2_INODES_PER_BLOCK(inode->i_sb));
if (!(bh = bread (inode->i_dev, block, inode->i_sb->s_blocksize)))
ext2_panic (inode->i_sb, "ext2_write_inode",
"unable to read i-node block\n"
"unable to read i-node block - "
"inode=%lu, block=%lu", inode->i_ino, block);
raw_inode = ((struct ext2_inode *)bh->b_data) +
(inode->i_ino - 1) % EXT2_INODES_PER_BLOCK(inode->i_sb);
......
......@@ -33,10 +33,9 @@ int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
/*
* Only the super-user can change the IMMUTABLE flag
*/
if (((flags & EXT2_IMMUTABLE_FL) &&
!(inode->u.ext2_i.i_flags & EXT2_IMMUTABLE_FL)) ||
(!(flags & EXT2_IMMUTABLE_FL) &&
(inode->u.ext2_i.i_flags & EXT2_IMMUTABLE_FL))) {
if ((flags & EXT2_IMMUTABLE_FL) ^
(inode->u.ext2_i.i_flags & EXT2_IMMUTABLE_FL)) {
/* This test looks nicer. Thanks to Pauline Middelink */
if (!fsuser())
return -EPERM;
} else
......
......@@ -271,6 +271,11 @@ static int parse_options (char * options, unsigned long * sb_block,
static void ext2_setup_super (struct super_block * sb,
struct ext2_super_block * es)
{
if (es->s_rev_level > EXT2_CURRENT_REV) {
printk ("EXT2-fs warning: revision level too high, "
"forcing read/only mode\n");
sb->s_flags |= MS_RDONLY;
}
if (!(sb->s_flags & MS_RDONLY)) {
if (!(sb->u.ext2_sb.s_mount_state & EXT2_VALID_FS))
printk ("EXT2-fs warning: mounting unchecked fs, "
......
......@@ -66,6 +66,8 @@ asmlinkage int sys_dup(unsigned int fildes)
asmlinkage int sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
{
struct file * filp;
struct task_struct *p;
int task_found = 0;
if (fd >= NR_OPEN || !(filp = current->files->fd[fd]))
return -EBADF;
......@@ -116,22 +118,45 @@ asmlinkage int sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
return filp->f_owner;
case F_SETOWN:
/*
* Add the security checks - AC. Without this there is a massive
* Linux security hole here - consider what happens if you do
* something like
* Add the security checks - AC. Without
* this there is a massive Linux security
* hole here - consider what happens if
* you do something like
*
* fcntl(0,F_SETOWN,some_root_process);
* getchar();
*
* and input a line!
*
* BTW: Don't try this for fun. Several Unix
* systems I tried this on fall for the
* trick!
*
* I had to fix this botch job as Linux
* kill_fasync asserts priv making it a
* free all user process killer!
*
* BTW: Don't try this for fun. Several Unix systems I tried this on
* fall for the trick!
*
* I had to fix this botch job as Linux kill_fasync asserts
* priv making it a free all user process killer!
* Changed to make the security checks more
* liberal. -- TYT
*/
if(!suser() && current->pgrp != -arg &&
current->pid != arg)
return -EPERM;
if (current->pgrp == -arg || current->pid != arg)
goto fasync_ok;
for_each_task(p) {
if ((p->pid == arg) || (p->pid == -arg) ||
(p->pgrp == -arg)) {
task_found++;
if ((p->session != current->session) &&
(p->uid != current->uid) &&
(p->euid != current->euid) &&
!suser())
return -EPERM;
break;
}
}
if ((task_found == 0) && !suser())
return -EINVAL;
fasync_ok:
filp->f_owner = arg;
if (S_ISSOCK (filp->f_inode->i_mode))
sock_fcntl (filp, F_SETOWN, arg);
......
......@@ -32,7 +32,7 @@ static int isofs_match(int len,const char * name, char * compare, int dlen)
/* check special "." and ".." files */
if (dlen == 1) {
/* "." */
if (compare[0] = 0) {
if (compare[0] == 0) {
if (!len)
return 1;
compare = ".";
......
......@@ -78,7 +78,7 @@ struct file_operations umsdos_file_operations = {
msdos_mmap, /* mmap */
NULL, /* no special open is needed */
NULL, /* release */
NULL /* fsync */
file_fsync /* fsync */
};
struct inode_operations umsdos_file_inode_operations = {
......
......@@ -617,8 +617,10 @@ int UMSDOS_link (
iput (olddir);
}
if (ret == 0){
struct iattr newattrs;
oldinode->i_nlink++;
ret = UMSDOS_notify_change (0,NULL,oldinode);
newattrs.ia_valid = 0;
ret = UMSDOS_notify_change(oldinode, &newattrs);
}
iput (oldinode);
iput (dir);
......@@ -923,7 +925,9 @@ int UMSDOS_unlink (
iput (hdir);
}
}else{
ret = UMSDOS_notify_change (0,NULL,inode);
struct iattr newattrs;
newattrs.ia_valid = 0;
ret = UMSDOS_notify_change (inode, &newattrs);
}
iput (inode);
}
......
......@@ -79,7 +79,80 @@ extern __inline__ unsigned long change_bit(unsigned long nr, void * addr)
extern __inline__ unsigned long test_bit(int nr, void * addr)
{
return (1UL << (nr & 63)) & ((unsigned long *) addr)[nr >> 6];
return 1UL & (((unsigned long *) addr)[nr >> 6] >> (nr & 63));
}
/*
* ffz = Find First Zero in word. Undefined if no zero exists,
* so code should check agains ~0UL first..
*
* This uses the cmpbge insn to check which byte contains the zero.
* I don't know if that's actually a good idea, but it's fun and the
* resulting LBS tests should be natural on the alpha.. Besides, I'm
* just teaching myself the asm of the alpha anyway.
*/
extern inline unsigned long ffz(unsigned long word)
{
unsigned long result = 0;
unsigned long tmp;
__asm__("cmpbge %1,%0,%0"
:"=r" (tmp)
:"r" (word), "0" (~0UL));
while (tmp & 1) {
word >>= 8;
tmp >>= 1;
result += 8;
}
while (word & 1) {
result++;
word >>= 1;
}
return result;
}
/*
* Find next zero bit in a bitmap reasonably efficiently..
*/
extern inline unsigned long find_next_zero_bit(void * addr, unsigned long size, unsigned long offset)
{
unsigned long * p = ((unsigned long *) addr) + (offset >> 6);
unsigned long result = offset & ~63UL;
unsigned long tmp;
if (offset >= size)
return size;
size -= result;
offset &= 63UL;
if (offset) {
tmp = *(p++);
tmp |= ~0UL >> (64-offset);
if (size < 64)
goto found_first;
if (~tmp)
goto found_middle;
size -= 64;
result += 64;
}
while (size & ~63UL) {
if (~(tmp = *(p++)))
goto found_middle;
result += 64;
size -= 64;
}
if (!size)
return result;
tmp = *p;
found_first:
tmp |= ~0UL << size;
found_middle:
return result + ffz(tmp);
}
/*
* The optimizer actually does good code for this case..
*/
#define find_first_zero_bit(addr, size) \
find_next_zero_bit((addr), (size), 0)
#endif /* _ALPHA_BITOPS_H */
......@@ -47,7 +47,7 @@
/*
* The second extended file system version
*/
#define EXT2FS_DATE "94/08/24"
#define EXT2FS_DATE "94/10/23"
#define EXT2FS_VERSION "0.5a"
/*
......
......@@ -14,3 +14,8 @@ o Removed some surplus uncommented code from tcp.c
o Fixed protocol violation during closedown in tcp.c
[Still not got the window < MSS bug fix included]
Fixes for 1.1.58
o non blocking connect fail gets the error code right.
o select() not reporting read ok after an urgent read fixed.
......@@ -888,7 +888,11 @@ static int inet_connect(struct socket *sock, struct sockaddr * uaddr,
if (sk->state > TCP_FIN_WAIT2 && sock->state==SS_CONNECTING)
{
sock->state=SS_UNCONNECTED;
return -ETIMEDOUT;
cli();
err=sk->err;
sk->err=0;
sti();
return -err;
}
if (sk->state != TCP_ESTABLISHED &&(flags & O_NONBLOCK))
......
......@@ -85,6 +85,7 @@
* Alan Cox : BSD accept semantics.
* Alan Cox : Reset on closedown bug.
* Peter De Schrijver : ENOTCONN check missing in tcp_sendto().
* Michael Pall : Handle select() after URG properly in all cases.
*
*
* To Fix:
......@@ -1410,15 +1411,29 @@ static int tcp_read_urg(struct sock * sk, int nonblock,
{
if (sk->urginline || !sk->urg_data || sk->urg_data == URG_READ)
return -EINVAL;
sk->inuse=1;
if (sk->urg_data & URG_VALID)
{
char c = sk->urg_data;
if (!(flags & MSG_PEEK))
{
/* Skip over urgent data, so tcp_readable() returns
something again. This in turn makes tcp_select()
happy. Mike <pall@rz.uni-karlsruhe.de> */
if (sk->copied_seq + 1 == sk->urg_seq)
{
wake_up_interruptible(sk->sleep);
sk->copied_seq++;
}
sk->urg_data = URG_READ;
}
put_fs_byte(c, to);
release_sock(sk);
return 1;
}
release_sock(sk);
if (sk->err)
{
int tmp = -sk->err;
......
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