Commit 4f8db550 authored by Linus Torvalds's avatar Linus Torvalds

Linux 2.4.0-test7-pre5

    - i2c-old compile fix.
    - sparc updates (pte_pagenr cleanups)
    - make ipv6 loadable as a module together with CONFIG_INET_ECN
    - get rid of bdf_prm.b_un.age_super - it just confused the buffer aging
    - smbfs knows about nls and ascii mount options
    - small joystick driver updates
    - make sure to mark inode dirty after having changed the size!
    - hgafb documentation update
parent 369c1bc4
......@@ -11305,6 +11305,21 @@ CONFIG_SMB_FS
want), say M here and read Documentation/modules.txt. The module
will be called smbfs.o. Most people say N, however.
nls support setting
CONFIG_SMB_NLS_REMOTE
This setting allows you to specify a default value for which
codepage the server uses. If this field is left blank no
translations will be done by default. The local codepage/charset
default to CONFIG_NLS_DEFAULT.
The nls settings can be changed at mount time, if your smbmount
supports that, using the codepage and iocharset parameters.
Currently no smbmount distributed with samba supports this, it is
assumed future versions will. In the meantime you can get an
unofficial patch for samba 2.0.7 from:
http://www.hojdpunkten.ac.se/054/samba/index.html
Coda file system support (advanced network fs)
CONFIG_CODA_FS
Coda is an advanced network file system, similar to NFS in that it
......
......@@ -450,6 +450,13 @@ M: asun@cobaltnet.com
L: linux-kernel@vger.rutgers.edu
S: Maintained
HGA FRAMEBUFFER DRIVER
P: Ferenc Bakonyi
M: fero@drama.obuda.kando.hu
L: linux-nvidia@lists.surfsouth.com
W: http://drama.obuda.kando.hu/~fero/cgi-bin/hgafb.shtml
S: Maintained
HIGH-SPEED SCC DRIVER FOR AX.25
P: Klaus Kudielka
M: klaus.kudielka@ieee.org
......
......@@ -7,6 +7,7 @@
*
* Modified for ARM by Russell King
*/
#include <linux/config.h>
#include <linux/sched.h>
#include <asm/semaphore.h>
......
/* $Id: srmmu.c,v 1.220 2000/08/09 00:00:15 davem Exp $
/* $Id: srmmu.c,v 1.221 2000/08/14 00:46:13 anton Exp $
* srmmu.c: SRMMU specific routines for memory management.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
......@@ -137,8 +137,8 @@ static inline unsigned long srmmu_pgd_page(pgd_t pgd)
static inline unsigned long srmmu_pmd_page(pmd_t pmd)
{ return srmmu_device_memory(pmd_val(pmd))?~0:(unsigned long)__nocache_va((pmd_val(pmd) & SRMMU_PTD_PMASK) << 4); }
static inline unsigned long srmmu_pte_pagenr(pte_t pte)
{ return srmmu_device_memory(pte_val(pte))?~0:(((pte_val(pte) & SRMMU_PTE_PMASK) << 4) >> PAGE_SHIFT); }
static inline struct page *srmmu_pte_page(pte_t pte)
{ return (mem_map + (unsigned long)(srmmu_device_memory(pte_val(pte))?~0:(((pte_val(pte) & SRMMU_PTE_PMASK) << 4) >> PAGE_SHIFT))); }
static inline int srmmu_pte_none(pte_t pte)
{ return !(pte_val(pte) & 0xFFFFFFF); }
......@@ -2153,7 +2153,7 @@ void __init ld_mmu_srmmu(void)
BTFIXUPSET_CALL(set_pte, srmmu_set_pte, BTFIXUPCALL_SWAPO0O1);
BTFIXUPSET_CALL(switch_mm, srmmu_switch_mm, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(sparc_pte_pagenr, srmmu_pte_pagenr, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(pte_page, srmmu_pte_page, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(pmd_page, srmmu_pmd_page, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(pgd_page, srmmu_pgd_page, BTFIXUPCALL_NORM);
......
/* $Id: sun4c.c,v 1.197 2000/08/09 00:00:15 davem Exp $
/* $Id: sun4c.c,v 1.198 2000/08/14 00:46:13 anton Exp $
* sun4c.c: Doing in software what should be done in hardware.
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
......@@ -2156,9 +2156,9 @@ static pte_t sun4c_mk_pte_io(unsigned long page, pgprot_t pgprot, int space)
return __pte(((page - PAGE_OFFSET) >> PAGE_SHIFT) | pgprot_val(pgprot));
}
static unsigned long sun4c_pte_pagenr(pte_t pte)
static struct page *sun4c_pte_page(pte_t pte)
{
return (pte_val(pte) & SUN4C_PFN_MASK);
return (mem_map + (unsigned long)(pte_val(pte) & SUN4C_PFN_MASK));
}
static inline unsigned long sun4c_pmd_page(pmd_t pmd)
......@@ -2650,7 +2650,7 @@ void __init ld_mmu_sun4c(void)
BTFIXUPSET_CALL(set_pte, sun4c_set_pte, BTFIXUPCALL_STO1O0);
BTFIXUPSET_CALL(sparc_pte_pagenr, sun4c_pte_pagenr, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(pte_page, sun4c_pte_page, BTFIXUPCALL_NORM);
#if PAGE_SHIFT <= 12
BTFIXUPSET_CALL(pmd_page, sun4c_pmd_page, BTFIXUPCALL_ANDNINT(PAGE_SIZE - 1));
#else
......
......@@ -36,10 +36,6 @@ static struct i2c_bus *busses[I2C_BUS_MAX];
static struct i2c_driver *drivers[I2C_DRIVER_MAX];
static int bus_count = 0, driver_count = 0;
#ifdef CONFIG_VIDEO_BT848
extern int i2c_tuner_init(void);
extern int msp3400c_init(void);
#endif
#ifdef CONFIG_VIDEO_BUZ
extern int saa7111_init(void);
extern int saa7185_init(void);
......@@ -54,10 +50,6 @@ int i2c_init(void)
printk(KERN_INFO "i2c: initialized%s\n",
scan ? " (i2c bus scan enabled)" : "");
/* anything to do here ? */
#ifdef CONFIG_VIDEO_BT848
i2c_tuner_init();
msp3400c_init();
#endif
#ifdef CONFIG_VIDEO_BUZ
saa7111_init();
saa7185_init();
......
/*
* $Id: amijoy.c,v 1.4 2000/05/29 10:39:54 vojtech Exp $
* $Id: amijoy.c,v 1.5 2000/07/21 22:52:24 vojtech Exp $
*
* Copyright (c) 1998-2000 Vojtech Pavlik
*
......@@ -77,7 +77,7 @@ static int amijoy_open(struct input_dev *dev)
return 0;
if (request_irq(IRQ_AMIGA_VERTB, amijoy_interrupt, 0, "amijoy", NULL)) {
amijoy_used--;
(*used)--;
printk(KERN_ERR "amijoy.c: Can't allocate irq %d\n", amijoy_irq);
return -EBUSY;
}
......@@ -89,7 +89,7 @@ static void amijoy_close(struct input_dev *dev)
{
int *used = dev->private;
if (!--(*port->used))
if (!--(*used))
free_irq(IRQ_AMIGA_VERTB, amijoy_interrupt);
}
......@@ -112,13 +112,21 @@ static int __init amijoy_init(void)
for (i = 0; i < 2; i++)
if (amijoy[i]) {
if (!request_mem_region(CUSTOM_PHYSADDR+10+i*2, 2,
amijoy [Denise]")) {
if (i == 1 && amijoy[0]) {
input_unregister_device(amijoy_dev);
release_mem_region(CUSTOM_PHYSADDR+10, 2);
}
return -EBUSY;
}
amijoy_dev[i].open = amijoy_open;
amijoy_dev[i].close = amijoy_close;
amijoy_dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
amijoy_dev[i].absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
amijoy_dev[i].keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
for (j = 0; j < 2; j++)
for (j = 0; j < 2; j++) {
amijoy_dev[i].absmin[ABS_X + j] = -1;
amijoy_dev[i].absmax[ABS_X + j] = 1;
}
......@@ -134,6 +142,7 @@ static int __init amijoy_init(void)
input_register_device(amijoy_dev + i);
printk(KERN_INFO "input%d: %s at joy%ddat\n", amijoy_dev[i].number, amijoy_name, i);
}
return 0;
}
static void _exit amijoy_exit(void)
......@@ -141,8 +150,10 @@ static void _exit amijoy_exit(void)
int i;
for (i = 0; i < 2; i++)
if (amijoy[i])
if (amijoy[i]) {
input_unregister_device(amijoy_dev + i);
release_mem_region(CUSTOM_PHYSADDR+10+i*2, 2);
}
}
module_init(amijoy_init);
......
/*
* $Id: db9.c,v 1.5 2000/05/29 20:39:38 vojtech Exp $
* $Id: db9.c,v 1.6 2000/06/25 10:57:50 vojtech Exp $
*
* Copyright (c) 1999 Vojtech Pavlik
*
......@@ -95,7 +95,7 @@ static short db9_genesis_btn[] = { BTN_START, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y,
static short db9_cd32_btn[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_START };
static char db9_buttons[DB9_MAX_PAD] = { 0, 1, 2, 4, 0, 6, 8, 8, 1, 1, 7 };
static short *db9_btn[DB9_MAX_PAD] = { db9_multi_btn, db9_multi_btn, db9_genesis_btn, NULL, db9_genesis_btn,
static short *db9_btn[DB9_MAX_PAD] = { NULL, db9_multi_btn, db9_multi_btn, db9_genesis_btn, NULL, db9_genesis_btn,
db9_genesis_btn, db9_cd32_btn, db9_multi_btn, db9_multi_btn, db9_cd32_btn };
static char *db9_name[DB9_MAX_PAD] = { NULL, "Multisystem joystick", "Multisystem joystick (2 fire)", "Genesis pad",
NULL, "Genesis 5 pad", "Genesis 6 pad", "Saturn pad", "Multisystem (0.8.0.2) joystick",
......@@ -113,36 +113,36 @@ static void db9_timer(unsigned long private)
data = parport_read_data(port) >> 3;
input_report_abs(dev + 1, ABS_X, (data&DB9_DOWN ?0:1) - (data&DB9_UP ?0:1));
input_report_abs(dev + 1, ABS_Y, (data&DB9_RIGHT?0:1) - (data&DB9_LEFT?0:1));
input_report_key(dev + 1, BTN_TRIGGER, ~data&DB9_FIRE1);
input_report_abs(dev + 1, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
input_report_abs(dev + 1, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1));
input_report_key(dev + 1, BTN_TRIGGER, ~data & DB9_FIRE1);
case DB9_MULTI_0802:
data = parport_read_status(port) >> 3;
input_report_abs(dev, ABS_X, (data&DB9_DOWN ?0:1) - (data&DB9_UP ?0:1));
input_report_abs(dev, ABS_Y, (data&DB9_RIGHT?0:1) - (data&DB9_LEFT?0:1));
input_report_key(dev, BTN_TRIGGER, data&DB9_FIRE1);
input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
input_report_abs(dev, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1));
input_report_key(dev, BTN_TRIGGER, data & DB9_FIRE1);
break;
case DB9_MULTI_STICK:
data = parport_read_data(port);
input_report_abs(dev, ABS_X, (data&DB9_DOWN ?0:1) - (data&DB9_UP ?0:1));
input_report_abs(dev, ABS_Y, (data&DB9_RIGHT?0:1) - (data&DB9_LEFT?0:1));
input_report_key(dev, BTN_TRIGGER, ~data&DB9_FIRE1);
input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
input_report_abs(dev, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1));
input_report_key(dev, BTN_TRIGGER, ~data & DB9_FIRE1);
break;
case DB9_MULTI2_STICK:
data = parport_read_data(port);
input_report_abs(dev, ABS_X, (data&DB9_DOWN ?0:1) - (data&DB9_UP ?0:1));
input_report_abs(dev, ABS_Y, (data&DB9_RIGHT?0:1) - (data&DB9_LEFT?0:1));
input_report_key(dev, BTN_TRIGGER, ~data&DB9_FIRE1);
input_report_key(dev, BTN_THUMB, ~data&DB9_FIRE2);
input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
input_report_abs(dev, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1));
input_report_key(dev, BTN_TRIGGER, ~data & DB9_FIRE1);
input_report_key(dev, BTN_THUMB, ~data & DB9_FIRE2);
break;
case DB9_GENESIS_PAD:
......@@ -150,16 +150,16 @@ static void db9_timer(unsigned long private)
parport_write_control(port, DB9_NOSELECT);
data = parport_read_data(port);
input_report_abs(dev, ABS_X, (data&DB9_DOWN ?0:1) - (data&DB9_UP ?0:1));
input_report_abs(dev, ABS_Y, (data&DB9_RIGHT?0:1) - (data&DB9_LEFT?0:1));
input_report_key(dev, BTN_B, ~data&DB9_FIRE1);
input_report_key(dev, BTN_C, ~data&DB9_FIRE2);
input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
input_report_abs(dev, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1));
input_report_key(dev, BTN_B, ~data & DB9_FIRE1);
input_report_key(dev, BTN_C, ~data & DB9_FIRE2);
parport_write_control(port, DB9_NORMAL);
data=parport_read_data(port);
input_report_key(dev, BTN_A, ~data&DB9_FIRE1);
input_report_key(dev, BTN_START, ~data&DB9_FIRE2);
input_report_key(dev, BTN_A, ~data & DB9_FIRE1);
input_report_key(dev, BTN_START, ~data & DB9_FIRE2);
break;
case DB9_GENESIS5_PAD:
......@@ -167,18 +167,18 @@ static void db9_timer(unsigned long private)
parport_write_control(port, DB9_NOSELECT);
data=parport_read_data(port);
input_report_abs(dev, ABS_X, (data&DB9_DOWN ?0:1) - (data&DB9_UP ?0:1));
input_report_abs(dev, ABS_Y, (data&DB9_RIGHT?0:1) - (data&DB9_LEFT?0:1));
input_report_key(dev, BTN_B, ~data&DB9_FIRE1);
input_report_key(dev, BTN_C, ~data&DB9_FIRE2);
input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
input_report_abs(dev, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1));
input_report_key(dev, BTN_B, ~data & DB9_FIRE1);
input_report_key(dev, BTN_C, ~data & DB9_FIRE2);
parport_write_control(port, DB9_NORMAL);
data=parport_read_data(port);
input_report_key(dev, BTN_A, ~data&DB9_FIRE1);
input_report_key(dev, BTN_X, ~data&DB9_FIRE2);
input_report_key(dev, BTN_Y, ~data&DB9_LEFT);
input_report_key(dev, BTN_START, ~data&DB9_RIGHT);
input_report_key(dev, BTN_A, ~data & DB9_FIRE1);
input_report_key(dev, BTN_X, ~data & DB9_FIRE2);
input_report_key(dev, BTN_Y, ~data & DB9_LEFT);
input_report_key(dev, BTN_START, ~data & DB9_RIGHT);
break;
case DB9_GENESIS6_PAD:
......@@ -187,17 +187,17 @@ static void db9_timer(unsigned long private)
udelay(DB9_GENESIS6_DELAY);
data=parport_read_data(port);
input_report_abs(dev, ABS_X, (data&DB9_DOWN ?0:1) - (data&DB9_UP ?0:1));
input_report_abs(dev, ABS_Y, (data&DB9_RIGHT?0:1) - (data&DB9_LEFT?0:1));
input_report_key(dev, BTN_B, ~data&DB9_FIRE1);
input_report_key(dev, BTN_C, ~data&DB9_FIRE2);
input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
input_report_abs(dev, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1));
input_report_key(dev, BTN_B, ~data & DB9_FIRE1);
input_report_key(dev, BTN_C, ~data & DB9_FIRE2);
parport_write_control(port, DB9_NORMAL);
udelay(DB9_GENESIS6_DELAY);
data=parport_read_data(port);
input_report_key(dev, BTN_A, ~data&DB9_FIRE1);
input_report_key(dev, BTN_X, ~data&DB9_FIRE2);
input_report_key(dev, BTN_A, ~data & DB9_FIRE1);
input_report_key(dev, BTN_X, ~data & DB9_FIRE2);
parport_write_control(port, DB9_NOSELECT); /* 2 */
udelay(DB9_GENESIS6_DELAY);
......@@ -207,10 +207,10 @@ static void db9_timer(unsigned long private)
udelay(DB9_GENESIS6_DELAY);
data=parport_read_data(port);
input_report_key(dev, BTN_Y, ~data&DB9_LEFT);
input_report_key(dev, BTN_Z, ~data&DB9_DOWN);
input_report_key(dev, BTN_MODE, ~data&DB9_UP);
input_report_key(dev, BTN_START, ~data&DB9_RIGHT);
input_report_key(dev, BTN_Y, ~data & DB9_LEFT);
input_report_key(dev, BTN_Z, ~data & DB9_DOWN);
input_report_key(dev, BTN_MODE, ~data & DB9_UP);
input_report_key(dev, BTN_START, ~data & DB9_RIGHT);
parport_write_control(port, DB9_NORMAL);
udelay(DB9_GENESIS6_DELAY);
......@@ -224,32 +224,32 @@ static void db9_timer(unsigned long private)
parport_write_control(port, DB9_SATURN0);
data = parport_read_data(port);
input_report_key(dev, BTN_Y, ~data&DB9_LEFT);
input_report_key(dev, BTN_Z, ~data&DB9_DOWN);
input_report_key(dev, BTN_TL,~data&DB9_UP);
input_report_key(dev, BTN_TR,~data&DB9_RIGHT);
input_report_key(dev, BTN_Y, ~data & DB9_LEFT);
input_report_key(dev, BTN_Z, ~data & DB9_DOWN);
input_report_key(dev, BTN_TL, ~data & DB9_UP);
input_report_key(dev, BTN_TR, ~data & DB9_RIGHT);
parport_write_control(port, DB9_SATURN2);
data = parport_read_data(port);
input_report_abs(dev, ABS_X, (data&DB9_DOWN ?0:1) - (data&DB9_UP ?0:1));
input_report_abs(dev, ABS_Y, (data&DB9_RIGHT?0:1) - (data&DB9_LEFT?0:1));
input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
input_report_abs(dev, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1));
parport_write_control(port, DB9_NORMAL);
data = parport_read_data(port);
input_report_key(dev, BTN_A, ~data&DB9_LEFT);
input_report_key(dev, BTN_B, ~data&DB9_UP);
input_report_key(dev, BTN_C, ~data&DB9_DOWN);
input_report_key(dev, BTN_X, ~data&DB9_RIGHT);
input_report_key(dev, BTN_A, ~data & DB9_LEFT);
input_report_key(dev, BTN_B, ~data & DB9_UP);
input_report_key(dev, BTN_C, ~data & DB9_DOWN);
input_report_key(dev, BTN_X, ~data & DB9_RIGHT);
break;
case DB9_CD32_PAD:
data=parport_read_data(port);
input_report_abs(dev, ABS_X, (data&DB9_DOWN ?0:1) - (data&DB9_UP ?0:1));
input_report_abs(dev, ABS_Y, (data&DB9_RIGHT?0:1) - (data&DB9_LEFT?0:1));
input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
input_report_abs(dev, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1));
parport_write_control(port, 0x0a);
......@@ -257,7 +257,7 @@ static void db9_timer(unsigned long private)
data = parport_read_data(port);
parport_write_control(port, 0x02);
parport_write_control(port, 0x0a);
input_report_key(dev, db9_cd32_btn[i], ~data&DB9_FIRE2);
input_report_key(dev, db9_cd32_btn[i], ~data & DB9_FIRE2);
}
parport_write_control(port, 0x00);
......
/*
* $Id: gamecon.c,v 1.4 2000/05/29 21:08:45 vojtech Exp $
* $Id: gamecon.c,v 1.5 2000/06/25 09:56:58 vojtech Exp $
*
* Copyright (c) 1999-2000 Vojtech Pavlik
*
......@@ -157,7 +157,7 @@ static void gc_n64_read_packet(struct gc *gc, unsigned char *data)
static unsigned char gc_nes_bytes[] = { 0, 1, 2, 3 };
static unsigned char gc_snes_bytes[] = { 8, 0, 2, 3, 9, 1, 10, 11 };
static short gc_snes_btn[] = { BTN_A, BTN_B, BTN_START, BTN_SELECT, BTN_X, BTN_Y, BTN_TL, BTN_TR };
static short gc_snes_btn[] = { BTN_A, BTN_B, BTN_SELECT, BTN_START, BTN_X, BTN_Y, BTN_TL, BTN_TR };
/*
* gc_nes_read_packet() reads a NES/SNES packet.
......@@ -515,7 +515,7 @@ static struct gc __init *gc_probe(int *config)
case GC_N64:
for (j = 0; j < 10; j++)
set_bit(gc_n64_btn[j], gc->dev[j].keybit);
set_bit(gc_n64_btn[j], gc->dev[i].keybit);
for (j = 0; j < 2; j++) {
set_bit(ABS_X + j, gc->dev[i].absbit);
......@@ -530,18 +530,15 @@ static struct gc __init *gc_probe(int *config)
break;
case GC_SNES:
for (j = 0; j < 8; j++)
set_bit(gc_snes_btn[j], gc->dev[j].keybit);
break;
for (j = 4; j < 8; j++)
set_bit(gc_snes_btn[j], gc->dev[i].keybit);
case GC_NES:
for (j = 0; j < 4; j++)
set_bit(gc_snes_btn[j], gc->dev[j].keybit);
set_bit(gc_snes_btn[j], gc->dev[i].keybit);
break;
case GC_MULTI2:
set_bit(BTN_THUMB, gc->dev[i].keybit);
case GC_MULTI:
set_bit(BTN_TRIGGER, gc->dev[i].keybit);
break;
......@@ -656,12 +653,13 @@ void __exit gc_exit(void)
{
int i, j;
for (i = 0; i < 3; i++) {
for (j = 0; j < 5; j++)
if (gc_base[i]->pads[0] & gc_status_bit[j])
input_unregister_device(gc_base[i]->dev + j);
parport_unregister_device(gc_base[i]->pd);
}
for (i = 0; i < 3; i++)
if (gc_base[i]) {
for (j = 0; j < 5; j++)
if (gc_base[i]->pads[0] & gc_status_bit[j])
input_unregister_device(gc_base[i]->dev + j);
parport_unregister_device(gc_base[i]->pd);
}
}
module_init(gc_init);
......
/*
* $Id: sidewinder.c,v 1.14 2000/05/29 11:27:55 vojtech Exp $
* $Id: sidewinder.c,v 1.16 2000/07/14 09:02:41 vojtech Exp $
*
* Copyright (c) 1998-2000 Vojtech Pavlik
*
......@@ -330,8 +330,8 @@ static int sw_parse(unsigned char *buf, struct sw *sw)
if (sw_parity(GB(i*15,15))) return -1;
input_report_key(dev + i, ABS_X, GB(i*15+3,1) - GB(i*15+2,1));
input_report_key(dev + i, ABS_Y, GB(i*15+0,1) - GB(i*15+1,1));
input_report_abs(dev + i, ABS_X, GB(i*15+3,1) - GB(i*15+2,1));
input_report_abs(dev + i, ABS_Y, GB(i*15+0,1) - GB(i*15+1,1));
for (j = 0; j < 10; j++)
input_report_key(dev, sw_btn[SW_ID_GP][j], !GB(i*15+j+4,1));
......
/*
* $Id: spaceball.c,v 1.6 2000/05/29 11:19:51 vojtech Exp $
* $Id: spaceball.c,v 1.7 2000/06/24 11:55:40 vojtech Exp $
*
* Copyright (c) 1999-2000 Vojtech Pavlik
*
......@@ -46,7 +46,7 @@
*/
#define JS_SBALL_MAX_LENGTH 128
static int spaceball_axes[] = { ABS_X, ABS_Y, ABS_Z, ABS_RX, ABS_RY, ABS_RZ };
static int spaceball_axes[] = { ABS_X, ABS_Z, ABS_Y, ABS_RX, ABS_RZ, ABS_RY };
static char *spaceball_name = "SpaceTec SpaceBall 4000 FLX";
/*
......@@ -70,10 +70,12 @@ static void spaceball_process_packet(struct spaceball* spaceball)
{
struct input_dev *dev = &spaceball->dev;
unsigned char *data = spaceball->data;
int i, d;
int i;
if (spaceball->idx < 2) return;
printk("%c %d\n", spaceball->data[0], spaceball->idx);
switch (spaceball->data[0]) {
case '@': /* Reset packet */
......@@ -84,17 +86,17 @@ static void spaceball_process_packet(struct spaceball* spaceball)
break;
case 'D': /* Ball data */
if (spaceball->idx != 16) return;
if (spaceball->idx != 15) return;
for (i = 0; i < 6; i++) {
d = ((data[2 * i + 3] << 8) | data[2 * i + 2]);
input_report_abs(dev, spaceball_axes[i], d - ((d & 0x8000) ? 0x10000 : 0));
input_report_abs(dev, spaceball_axes[i],
(__s16)((data[2 * i + 3] << 8) | data[2 * i + 2]));
}
break;
case '.': /* Button data, part2 */
if (spaceball->idx != 4) return;
input_report_key(dev, BTN_LEFT, data[2] & 1);
input_report_key(dev, BTN_RIGHT, data[2] & 2);
if (spaceball->idx != 3) return;
input_report_key(dev, BTN_0, data[2] & 1);
input_report_key(dev, BTN_1, data[2] & 2);
break;
case '?': /* Error packet */
......@@ -118,22 +120,27 @@ static void spaceball_interrupt(struct serio *serio, unsigned char data, unsigne
switch (data) {
case 0xd:
if (spaceball->idx)
spaceball_process_packet(spaceball);
spaceball_process_packet(spaceball);
spaceball->idx = 0;
spaceball->escape = 0;
return;
case '^':
if (!spaceball->escape) {
spaceball->escape ^= 1;
return;
}
spaceball->escape = 0;
case 'M':
case 'Q':
case 'S':
if (spaceball->escape)
if (spaceball->escape) {
spaceball->escape = 0;
data = 0xd;
case '^':
spaceball->escape ^= 1;
}
default:
if (spaceball->escape) {
printk(KERN_WARNING "spaceball.c: Unknown escaped character: %#x\n", data);
spaceball->escape = 0;
printk(KERN_WARNING "spaceball.c: Unknown escaped character: %#x (%c)\n", data, data);
}
if (spaceball->idx < JS_SBALL_MAX_LENGTH)
spaceball->data[spaceball->idx++] = data;
......@@ -172,15 +179,15 @@ static void spaceball_connect(struct serio *serio, struct serio_dev *dev)
memset(spaceball, 0, sizeof(struct spaceball));
spaceball->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
spaceball->dev.keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT);
spaceball->dev.keybit[LONG(BTN_0)] = BIT(BTN_0) | BIT(BTN_1);
for (i = 0; i < 6; i++) {
t = spaceball_axes[i];
set_bit(t, spaceball->dev.absbit);
spaceball->dev.absmin[t] = i < 3 ? -10000 : -2000;
spaceball->dev.absmax[t] = i < 3 ? 10000 : 2000;
spaceball->dev.absflat[t] = i < 3 ? 50 : 10;
spaceball->dev.absfuzz[t] = i < 3 ? 12 : 2;
spaceball->dev.absmin[t] = i < 3 ? -8000 : -1600;
spaceball->dev.absmax[t] = i < 3 ? 8000 : 1600;
spaceball->dev.absflat[t] = i < 3 ? 40 : 8;
spaceball->dev.absfuzz[t] = i < 3 ? 8 : 2;
}
spaceball->serio = serio;
......
......@@ -25,6 +25,7 @@
*/
#include <linux/config.h>
#include <linux/fs.h>
#undef N_DATA
......
......@@ -7,6 +7,8 @@
*
* History:
*
* - Revision 0.1.6 (17 Aug 2000): new style structs
* documentation
* - Revision 0.1.5 (13 Mar 2000): spinlocks instead of saveflags();cli();etc
* minor fixes
* - Revision 0.1.4 (24 Jan 2000): fixed a bug in hga_card_detect() for
......@@ -107,19 +109,23 @@ spinlock_t hga_reg_lock = SPIN_LOCK_UNLOCKED;
/* Framebuffer driver structures */
static struct fb_var_screeninfo hga_default_var = {
720, 348, /* xres, yres */
720, 348, /* xres_virtual, yres_virtual */
0, 0, /* xoffset, yoffset */
1, /* bits_per_pixel */
0, /* grayscale */
{0, 1, 0}, /* red */
{0, 1, 0}, /* green */
{0, 1, 0}, /* blue */
{0, 0, 0}, /* transp */
0, /* nonstd (FB_NONSTD_HGA ?) */
0, /* activate */
-1, -1, /* height, width */
0, /* accel_flags */
xres: 720,
yres: 348,
xres_virtual: 720,
yres_virtual: 348,
xoffset: 0,
yoffset: 0,
bits_per_pixel: 1,
grayscale: 0,
red: {0, 1, 0},
green: {0, 1, 0},
blue: {0, 1, 0},
transp: {0, 0, 0},
nonstd: 0, /* (FB_NONSTD_HGA ?) */
activate: 0,
height: -1,
width: -1,
accel_flags: 0,
/* pixclock */
/* left_margin, right_margin */
/* upper_margin, lower_margin */
......@@ -129,19 +135,19 @@ static struct fb_var_screeninfo hga_default_var = {
};
static struct fb_fix_screeninfo hga_fix = {
"HGA", /* id */
(unsigned long) NULL, /* smem_start */
0, /* smem_len */
FB_TYPE_PACKED_PIXELS, /* type (not sure) */
0, /* type_aux (not sure) */
FB_VISUAL_MONO10, /* visual */
8, /* xpanstep */
8, /* ypanstep */
0, /* ywrapstep */
90, /* line_length */
0, /* mmio_start */
0, /* mmio_len */
FB_ACCEL_NONE /* accel */
id: "HGA",
smem_start: (unsigned long) NULL,
smem_len: 0,
type: FB_TYPE_PACKED_PIXELS, /* (not sure) */
type_aux: 0, /* (not sure) */
visual: FB_VISUAL_MONO10,
xpanstep: 8,
ypanstep: 8,
ywrapstep: 0,
line_length: 90,
mmio_start: 0,
mmio_len: 0,
accel: FB_ACCEL_NONE
};
static struct fb_info fb_info;
......@@ -377,9 +383,15 @@ static int __init hga_card_detect(void)
*
* ------------------------------------------------------------------------- */
/*
* Get the Fixed Part of the Display
*/
/**
* hga_get_fix - get the fixed part of the display
* @fix:struct fb_fix_screeninfo to fill in
* @con:unused
* @info:pointer to fb_info object containing info for current hga board
*
* This wrapper function copies @info->fix to @fix.
* A zero is returned on success and %-EINVAL for failure.
*/
int hga_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
{
......@@ -390,10 +402,15 @@ int hga_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
return 0;
}
/*
* Get the User Defined Part of the Display
*/
/**
* hga_get_var - get the user defined part of the display
* @var:struct fb_var_screeninfo to fill in
* @con:unused
* @info:pointer to fb_info object containing info for current hga board
*
* This wrapper function copies @info->var to @var.
* A zero is returned on success and %-EINVAL for failure.
*/
int hga_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
{
......@@ -404,13 +421,23 @@ int hga_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
return 0;
}
/*
* Set the User Defined Part of the Display
* This is the most mystical function (at least for me).
* What is the exact specification of xxx_set_var?
* Should it handle xoffset, yoffset? Should it do pannig?
* What does vmode mean?
*/
/**
* hga_set_var - set the user defined part of the display
* @var:new video mode
* @con:unused
* @info:pointer to fb_info object containing info for current hga board
*
* This function is called for changing video modes. Since HGA cards have
* only one fixed mode we have not much to do. After checking input
* parameters @var is copied to @info->var and @info->changevar is called.
* A zero is returned on success and %-EINVAL for failure.
*
* FIXME:
* This is the most mystical function (at least for me).
* What is the exact specification of xxx_set_var()?
* Should it handle xoffset, yoffset? Should it do panning?
* What does vmode mean?
*/
int hga_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
{
......@@ -431,10 +458,20 @@ int hga_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
return 0;
}
/*
* Get the Colormap
*/
/**
* hga_getcolreg - read color registers
* @regno:register index to read out
* @red:red value
* @green:green value
* @blue:blue value
* @transp:transparency value
* @info:unused
*
* This callback function is used to read the color registers of a HGA
* board. Since we have only two fixed colors, RGB values are 0x0000
* for register0 and 0xaaaa for register1.
* A zero is returned on success and 1 for failure.
*/
static int hga_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
u_int *transp, struct fb_info *info)
......@@ -450,6 +487,17 @@ static int hga_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
return 0;
}
/**
* hga_get_cmap - get the colormap
* @cmap:struct fb_cmap to fill in
* @kspc:called from kernel space?
* @con:unused
* @info:pointer to fb_info object containing info for current hga board
*
* This wrapper function passes it's input parameters to fb_get_cmap().
* Callback function hga_getcolreg() is used to read the color registers.
*/
int hga_get_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
{
......@@ -458,9 +506,19 @@ int hga_get_cmap(struct fb_cmap *cmap, int kspc, int con,
return fb_get_cmap(cmap, kspc, hga_getcolreg, info);
}
/*
* Set the Colormap
*/
/**
* hga_setcolreg - set color registers
* @regno:register index to set
* @red:red value, unused
* @green:green value, unused
* @blue:blue value, unused
* @transp:transparency value, unused
* @info:unused
*
* This callback function is used to set the color registers of a HGA
* board. Since we have only two fixed colors only @regno is checked.
* A zero is returned on success and 1 for failure.
*/
static int hga_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info)
......@@ -470,6 +528,17 @@ static int hga_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
return 0;
}
/**
* hga_set_cmap - set the colormap
* @cmap:struct fb_cmap to set
* @kspc:called from kernel space?
* @con:unused
* @info:pointer to fb_info object containing info for current hga board
*
* This wrapper function passes it's input parameters to fb_set_cmap().
* Callback function hga_setcolreg() is used to set the color registers.
*/
int hga_set_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
{
......@@ -478,11 +547,17 @@ int hga_set_cmap(struct fb_cmap *cmap, int kspc, int con,
return fb_set_cmap(cmap, kspc, hga_setcolreg, info);
}
/*
* Pan or Wrap the Display
*
* This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
*/
/**
* hga_pan_display - pan or wrap the display
* @var:contains new xoffset, yoffset and vmode values
* @con:unused
* @info:pointer to fb_info object containing info for current hga board
*
* This function looks only at xoffset, yoffset and the %FB_VMODE_YWRAP
* flag in @var. If input parameters are correct it calls hga_pan() to
* program the hardware. @info->var is updated to the new values.
* A zero is returned on success and %-EINVAL for failure.
*/
int hga_pan_display(struct fb_var_screeninfo *var, int con,
struct fb_info *info)
......@@ -531,6 +606,18 @@ static struct fb_ops hgafb_ops = {
*
* ------------------------------------------------------------------------- */
/**
* hgafbcon_switch - switch console
* @con:new console to switch to
* @info:pointer to fb_info object containing info for current hga board
*
* This function should install a new colormap and change the video mode.
* Since we have fixed colors and only one video mode we have nothing to
* do.
* Only console administration is done but it should go to fbcon.c IMHO.
* A zero is returned on success and %-EINVAL for failure.
*/
static int hgafbcon_switch(int con, struct fb_info *info)
{
CHKINFO(-EINVAL);
......@@ -564,6 +651,17 @@ static int hgafbcon_switch(int con, struct fb_info *info)
return 0;
}
/**
* hgafbcon_updatevar - update the user defined part of the display
* @con:console to update or -1 when no consoles defined on this fb
* @info:pointer to fb_info object containing info for current hga board
*
* This function is called when @var is changed by fbcon.c without calling
* hga_set_var(). It usually means scrolling. hga_pan_display() is called
* to update the hardware and @info->var.
* A zero is returned on success and %-EINVAL for failure.
*/
static int hgafbcon_updatevar(int con, struct fb_info *info)
{
CHKINFO(-EINVAL);
......@@ -571,17 +669,21 @@ static int hgafbcon_updatevar(int con, struct fb_info *info)
return (con < 0) ? -EINVAL : hga_pan_display(&fb_display[con].var, con, info);
}
/**
* hgafbcon_blank - (un)blank the screen
* @blank_mode:blanking method to use
* @info:unused
*
* Blank the screen if blank_mode != 0, else unblank.
* Implements VESA suspend and powerdown modes on hardware that supports
* disabling hsync/vsync:
* @blank_mode == 2 means suspend vsync,
* @blank_mode == 3 means suspend hsync,
* @blank_mode == 4 means powerdown.
*/
static void hgafbcon_blank(int blank_mode, struct fb_info *info)
{
/*
* Blank the screen if blank_mode != 0, else unblank.
* Implements VESA suspend and powerdown modes on hardware
* that supports disabling hsync/vsync:
* blank_mode == 2: suspend vsync
* blank_mode == 3: suspend hsync
* blank_mode == 4: powerdown
*/
CHKINFO( );
DPRINTK("hga_blank: blank_mode:%d, info:%x, fb_info:%x\n", blank_mode, (unsigned)info, (unsigned)&fb_info);
......
......@@ -99,7 +99,9 @@ if [ "$CONFIG_NET" = "y" ]; then
fi
dep_tristate 'SMB file system support (to mount Windows shares etc.)' CONFIG_SMB_FS $CONFIG_INET
if [ "$CONFIG_SMB_FS" != "n" ]; then
string 'Default Remote NLS Option' CONFIG_SMB_NLS_REMOTE ""
fi
if [ "$CONFIG_IPX" != "n" -o "$CONFIG_INET" != "n" ]; then
tristate 'NCP file system support (to mount NetWare volumes)' CONFIG_NCP_FS
source fs/ncpfs/Config.in
......
......@@ -119,7 +119,7 @@ union bdflush_param {
when trying to refill buffers. */
int interval; /* jiffies delay between kupdate flushes */
int age_buffer; /* Time for normal buffer to age before we flush it */
int age_super; /* Time for superblock to age before we flush it */
int dummy1; /* unused, was age_super */
int dummy2; /* unused */
int dummy3; /* unused */
} b_un;
......@@ -894,7 +894,7 @@ void balance_dirty(kdev_t dev)
static __inline__ void __mark_dirty(struct buffer_head *bh, int flag)
{
bh->b_flushtime = jiffies + (flag ? bdf_prm.b_un.age_super : bdf_prm.b_un.age_buffer);
bh->b_flushtime = jiffies + bdf_prm.b_un.age_buffer;
refile_buffer(bh);
}
......@@ -1714,8 +1714,10 @@ int generic_commit_write(struct file *file, struct page *page,
loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
__block_commit_write(inode,page,from,to);
kunmap(page);
if (pos > inode->i_size)
if (pos > inode->i_size) {
inode->i_size = pos;
mark_inode_dirty(inode);
}
return 0;
}
......@@ -1837,6 +1839,7 @@ int brw_kiovec(int rw, int nr, struct kiobuf *iovec[],
int pageind;
int bhind;
int offset;
int sectors = size>>9;
unsigned long blocknr;
struct kiobuf * iobuf = NULL;
struct page * map;
......@@ -1888,9 +1891,10 @@ int brw_kiovec(int rw, int nr, struct kiobuf *iovec[],
tmp->b_this_page = tmp;
init_buffer(tmp, end_buffer_io_kiobuf, iobuf);
tmp->b_dev = dev;
tmp->b_rdev = tmp->b_dev = dev;
tmp->b_blocknr = blocknr;
tmp->b_state = 1 << BH_Mapped;
tmp->b_rsector = blocknr*sectors;
tmp->b_state = (1 << BH_Mapped) | (1 << BH_Lock) | (1 << BH_Req);
if (rw == WRITE) {
set_bit(BH_Uptodate, &tmp->b_state);
......
......@@ -771,6 +771,7 @@ void iput(struct inode *inode)
list_del(&inode->i_list);
INIT_LIST_HEAD(&inode->i_list);
inode->i_state|=I_FREEING;
inodes_stat.nr_inodes--;
spin_unlock(&inode_lock);
if (inode->i_data.nrpages)
......@@ -799,11 +800,11 @@ void iput(struct inode *inode)
list_del(&inode->i_list);
INIT_LIST_HEAD(&inode->i_list);
inode->i_state|=I_FREEING;
inodes_stat.nr_inodes--;
spin_unlock(&inode_lock);
clear_inode(inode);
}
}
inodes_stat.nr_inodes--;
destroy_inode(inode);
}
}
......
......@@ -4,7 +4,8 @@
# msdos and Joliet want NLS
if [ "$CONFIG_JOLIET" = "y" -o "$CONFIG_FAT_FS" != "n" \
-o "$CONFIG_NTFS_FS" != "n" -o "$CONFIG_NCPFS_NLS" = "y" ]; then
-o "$CONFIG_NTFS_FS" != "n" -o "$CONFIG_NCPFS_NLS" = "y" \
-o "$CONFIG_SMB_FS" != "n" ]; then
define_bool CONFIG_NLS y
else
define_bool CONFIG_NLS n
......
ChangeLog for smbfs.
2000-08-14 Urban Widmark <urban@svenskatest.se>
* dir.c: support case sensitive shares
* inode.c: ascii mount options
* proc.c: check length of paths to avoid buffer overflow
* proc.c: don't do interruptable_sleep in smb_retry to avoid signal
problem/race.
* proc.c: O_RDONLY & smb_revalidate_inode fix (tail -f)
* proc.c: add nls support
* sock.c: attempt to fix smb_data_callback (avoid infinite loop)
2000-07-25 Urban Widmark <urban@svenskatest.se>
* proc.c: fix 3 places where bad server responses could cause an Oops.
......
......@@ -8,7 +8,7 @@
# Note 2! The CFLAGS definitions are now in the main makefile...
O_TARGET := smbfs.o
O_OBJS := proc.o dir.o cache.o sock.o inode.o file.o ioctl.o
O_OBJS := proc.o dir.o cache.o sock.o inode.o file.o ioctl.o getopt.o
M_OBJS := $(O_TARGET)
# If you want debugging output, you may add these flags to the EXTRA_CFLAGS
......
......@@ -14,6 +14,7 @@
#include <linux/ctype.h>
#include <linux/smb_fs.h>
#include <linux/smb_mount.h>
#include <linux/smbno.h>
#include "smb_debug.h"
......@@ -142,7 +143,7 @@ smb_readdir(struct file *filp, void *dirent, filldir_t filldir)
}
/*
* Note: in order to allow the smbclient process to open the
* Note: in order to allow the smbmount process to open the
* mount point, we don't revalidate if conn_pid is NULL.
*/
static int
......@@ -190,6 +191,13 @@ static struct dentry_operations smbfs_dentry_operations =
d_delete: smb_delete_dentry,
};
static struct dentry_operations smbfs_dentry_operations_case =
{
d_revalidate: smb_lookup_validate,
d_delete: smb_delete_dentry,
};
/*
* This is the callback when the dcache has a lookup hit.
*/
......@@ -249,8 +257,7 @@ smb_compare_dentry(struct dentry *dir, struct qstr *a, struct qstr *b)
if (a->len != b->len)
goto out;
for (i=0; i < a->len; i++)
{
for (i=0; i < a->len; i++) {
if (tolower(a->name[i]) != tolower(b->name[i]))
goto out;
}
......@@ -300,6 +307,7 @@ smb_lookup(struct inode *dir, struct dentry *dentry)
struct smb_fattr finfo;
struct inode *inode;
int error;
struct smb_sb_info *server;
error = -ENAMETOOLONG;
if (dentry->d_name.len > SMB_MAXNAMELEN)
......@@ -315,15 +323,18 @@ smb_lookup(struct inode *dir, struct dentry *dentry)
inode = NULL;
if (error == -ENOENT)
goto add_entry;
if (!error)
{
if (!error) {
error = -EACCES;
finfo.f_ino = smb_invent_inos(1);
inode = smb_iget(dir->i_sb, &finfo);
if (inode)
{
if (inode) {
add_entry:
dentry->d_op = &smbfs_dentry_operations;
server = server_from_dentry(dentry);
if (server->mnt->flags & SMB_MOUNT_CASE)
dentry->d_op = &smbfs_dentry_operations_case;
else
dentry->d_op = &smbfs_dentry_operations;
d_add(dentry, inode);
smb_renew_times(dentry);
error = 0;
......
/*
* getopt.c
*/
#include <linux/kernel.h>
#include <linux/string.h>
#include "getopt.h"
/**
* smb_getopt - option parser
* @caller: name of the caller, for error messages
* @options: the options string
* @opts: an array of &struct option entries controlling parser operations
* @optopt: output; will contain the current option
* @optarg: output; will contain the value (if one exists)
* @flag: output; may be NULL; should point to a long for or'ing flags
* @value: output; may be NULL; will be overwritten with the integer value
* of the current argument.
*
* Helper to parse options on the format used by mount ("a=b,c=d,e,f").
* Returns opts->val if a matching entry in the 'opts' array is found,
* 0 when no more tokens are found, -1 if an error is encountered.
*/
int smb_getopt(char *caller, char **options, struct option *opts,
char **optopt, char **optarg, unsigned long *flag,
unsigned long *value)
{
char *token;
char *val;
int i;
if ( (token = strsep(options, ",")) == NULL)
return 0;
*optopt = token;
*optarg = NULL;
if ((val = strchr (token, '=')) != NULL) {
*val++ = 0;
if (value)
*value = simple_strtoul(val, NULL, 0);
*optarg = val;
}
for (i = 0; opts[i].name != NULL; i++) {
if (!strcmp(opts[i].name, token)) {
if (opts[i].has_arg && (!val || !*val)) {
printk("%s: the %s option requires an argument\n",
caller, token);
return -1;
}
if (flag && opts[i].flag)
*flag |= opts[i].flag;
return opts[i].val;
}
}
printk("%s: Unrecognized mount option %s\n", caller, token);
return -1;
}
#ifndef _LINUX_GETOPT_H
#define _LINUX_GETOPT_H
struct option {
const char *name;
int has_arg;
unsigned long flag;
int val;
};
extern int smb_getopt(char *caller, char **options, struct option *opts,
char **optopt, char **optarg, unsigned long *flag,
unsigned long *value);
#endif /* _LINUX_GETOPT_H */
......@@ -20,6 +20,7 @@
#include <linux/file.h>
#include <linux/dcache.h>
#include <linux/smp_lock.h>
#include <linux/nls.h>
#include <linux/smb_fs.h>
#include <linux/smbno.h>
......@@ -29,6 +30,7 @@
#include <asm/uaccess.h>
#include "smb_debug.h"
#include "getopt.h"
static void smb_delete_inode(struct inode *);
static void smb_put_super(struct super_block *);
......@@ -282,6 +284,82 @@ smb_delete_inode(struct inode *ino)
clear_inode(ino);
}
/* FIXME: flags and has_arg could probably be merged. */
struct option opts[] = {
{ "version", 1, 0, 'v' },
{ "win95", 0, SMB_MOUNT_WIN95, 1 },
{ "oldattr", 0, SMB_MOUNT_OLDATTR, 1 },
{ "dirattr", 0, SMB_MOUNT_DIRATTR, 1 },
{ "case", 0, SMB_MOUNT_CASE, 1 },
{ "uid", 1, 0, 'u' },
{ "gid", 1, 0, 'g' },
{ "file_mode", 1, 0, 'f' },
{ "dir_mode", 1, 0, 'd' },
{ "iocharset", 1, 0, 'i' },
{ "codepage", 1, 0, 'c' },
{ NULL, 0, 0, 0}
};
static int
parse_options(struct smb_mount_data_kernel *mnt, char *options)
{
int c;
unsigned long flags;
unsigned long value;
char *optarg;
char *optopt;
flags = 0;
while ( (c = smb_getopt("smbfs", &options, opts,
&optopt, &optarg, &flags, &value)) > 0) {
VERBOSE("'%s' -> '%s'\n", optopt, optarg ? optarg : "<none>");
switch (c) {
case 1:
/* got a "flag" option */
break;
case 'v':
if (value != SMB_MOUNT_VERSION) {
printk ("smbfs: Bad mount version %ld, expected %d\n",
value, SMB_MOUNT_VERSION);
return 0;
}
mnt->version = value;
break;
case 'u':
mnt->uid = value;
break;
case 'g':
mnt->gid = value;
break;
case 'f':
mnt->file_mode = value & (S_IRWXU | S_IRWXG | S_IRWXO);
mnt->file_mode |= S_IFREG;
break;
case 'd':
mnt->dir_mode = value & (S_IRWXU | S_IRWXG | S_IRWXO);
mnt->dir_mode |= S_IFDIR;
break;
case 'i':
strncpy(mnt->codepage.local_name, optarg,
SMB_NLS_MAXNAMELEN);
break;
case 'c':
strncpy(mnt->codepage.remote_name, optarg,
SMB_NLS_MAXNAMELEN);
break;
default:
printk ("smbfs: Unrecognized mount option %s\n",
optopt);
return -1;
}
}
mnt->flags = flags;
return c;
}
static void
smb_put_super(struct super_block *sb)
{
......@@ -300,18 +378,32 @@ smb_put_super(struct super_block *sb)
kfree(sb->u.smbfs_sb.temp_buf);
if (server->packet)
smb_vfree(server->packet);
if(sb->u.smbfs_sb.remote_nls) {
unload_nls(sb->u.smbfs_sb.remote_nls);
sb->u.smbfs_sb.remote_nls = NULL;
}
if(sb->u.smbfs_sb.local_nls) {
unload_nls(sb->u.smbfs_sb.local_nls);
sb->u.smbfs_sb.local_nls = NULL;
}
}
struct super_block *
smb_read_super(struct super_block *sb, void *raw_data, int silent)
{
struct smb_mount_data *mnt;
struct smb_mount_data_kernel *mnt;
struct smb_mount_data *oldmnt;
struct inode *root_inode;
struct smb_fattr root;
int ver;
if (!raw_data)
goto out_no_data;
if (((struct smb_mount_data *) raw_data)->version != SMB_MOUNT_VERSION)
oldmnt = (struct smb_mount_data *) raw_data;
ver = oldmnt->version;
if (ver != SMB_MOUNT_OLDVERSION && cpu_to_be32(ver) != SMB_MOUNT_ASCII)
goto out_wrong_data;
sb->s_blocksize = 1024; /* Eh... Is this correct? */
......@@ -320,6 +412,7 @@ smb_read_super(struct super_block *sb, void *raw_data, int silent)
sb->s_flags = 0;
sb->s_op = &smb_sops;
sb->u.smbfs_sb.mnt = NULL;
sb->u.smbfs_sb.sock_file = NULL;
init_MUTEX(&sb->u.smbfs_sb.sem);
init_waitqueue_head(&sb->u.smbfs_sb.wait);
......@@ -332,30 +425,61 @@ smb_read_super(struct super_block *sb, void *raw_data, int silent)
goto out_no_mem;
/* Allocate the global temp buffer */
sb->u.smbfs_sb.temp_buf = kmalloc(SMB_MAXPATHLEN + 20, GFP_KERNEL);
sb->u.smbfs_sb.temp_buf = kmalloc(2*SMB_MAXPATHLEN + 20, GFP_KERNEL);
if (!sb->u.smbfs_sb.temp_buf)
goto out_no_temp;
/* Setup NLS stuff */
sb->u.smbfs_sb.remote_nls = NULL;
sb->u.smbfs_sb.local_nls = NULL;
sb->u.smbfs_sb.name_buf = sb->u.smbfs_sb.temp_buf + SMB_MAXPATHLEN + 20;
/* Allocate the mount data structure */
mnt = kmalloc(sizeof(struct smb_mount_data), GFP_KERNEL);
/* FIXME: merge this with the other malloc and get a whole page? */
mnt = kmalloc(sizeof(struct smb_mount_data_kernel), GFP_KERNEL);
if (!mnt)
goto out_no_mount;
*mnt = *((struct smb_mount_data *) raw_data);
/* FIXME: passes config flags in high bits of file mode. Should be a
separate flags field. (but smbmount includes kernel headers ...) */
mnt->version = (mnt->file_mode >> 9);
mnt->file_mode &= (S_IRWXU | S_IRWXG | S_IRWXO);
mnt->file_mode |= S_IFREG;
mnt->dir_mode &= (S_IRWXU | S_IRWXG | S_IRWXO);
mnt->dir_mode |= S_IFDIR;
sb->u.smbfs_sb.mnt = mnt;
memset(mnt, 0, sizeof(struct smb_mount_data_kernel));
strncpy(mnt->codepage.local_name, CONFIG_NLS_DEFAULT,
SMB_NLS_MAXNAMELEN);
strncpy(mnt->codepage.local_name, CONFIG_SMB_NLS_REMOTE,
SMB_NLS_MAXNAMELEN);
if (ver == SMB_MOUNT_OLDVERSION) {
mnt->version = oldmnt->version;
/* FIXME: is this enough to convert uid/gid's ? */
mnt->mounted_uid = oldmnt->mounted_uid;
mnt->uid = oldmnt->uid;
mnt->gid = oldmnt->gid;
mnt->file_mode =
oldmnt->file_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
mnt->dir_mode =
oldmnt->dir_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
mnt->file_mode |= S_IFREG;
mnt->dir_mode |= S_IFDIR;
mnt->flags = (oldmnt->file_mode >> 9);
} else {
if (parse_options(mnt, raw_data))
goto out_bad_option;
mnt->mounted_uid = current->uid;
}
smb_setcodepage(&sb->u.smbfs_sb, &mnt->codepage);
if (!sb->u.smbfs_sb.convert)
PARANOIA("convert funcptr was NULL!\n");
/*
* Display the enabled options
* Note: smb_proc_getattr uses these in 2.4 (but was changed in 2.2)
*/
if (mnt->version & SMB_FIX_OLDATTR)
if (mnt->flags & SMB_MOUNT_OLDATTR)
printk("SMBFS: Using core getattr (Win 95 speedup)\n");
else if (mnt->version & SMB_FIX_DIRATTR)
else if (mnt->flags & SMB_MOUNT_DIRATTR)
printk("SMBFS: Using dir ff getattr\n");
/*
......@@ -374,16 +498,18 @@ smb_read_super(struct super_block *sb, void *raw_data, int silent)
out_no_root:
iput(root_inode);
out_bad_option:
kfree(sb->u.smbfs_sb.mnt);
out_no_mount:
kfree(sb->u.smbfs_sb.temp_buf);
out_no_temp:
smb_vfree(sb->u.smbfs_sb.packet);
out_no_mem:
printk(KERN_ERR "smb_read_super: allocation failure\n");
if (!sb->u.smbfs_sb.mnt)
printk(KERN_ERR "smb_read_super: allocation failure\n");
goto out_fail;
out_wrong_data:
printk(KERN_ERR "SMBFS: need mount version %d\n", SMB_MOUNT_VERSION);
printk(KERN_ERR "smbfs: mount_data version %d is not supported\n", ver);
goto out_fail;
out_no_data:
printk(KERN_ERR "smb_read_super: missing data argument\n");
......
......@@ -16,6 +16,7 @@
#include <linux/fcntl.h>
#include <linux/dcache.h>
#include <linux/dirent.h>
#include <linux/nls.h>
#include <linux/smb_fs.h>
#include <linux/smbno.h>
......@@ -25,10 +26,14 @@
#include "smb_debug.h"
/* Features. Undefine if they cause problems, this should perhaps be a
config option. */
#define SMBFS_POSIX_UNLINK 1
/* Allow smb_retry to be interrupted. Not sure of the benefit ... */
/* #define SMB_RETRY_INTR */
#define SMB_VWV(packet) ((packet) + SMB_HEADER_LEN)
#define SMB_CMD(packet) (*(packet+8))
#define SMB_WCT(packet) (*(packet+SMB_HEADER_LEN - 1))
......@@ -48,6 +53,20 @@ static int
smb_proc_do_getattr(struct smb_sb_info *server, struct dentry *dir,
struct smb_fattr *fattr);
static inline void
smb_lock_server(struct smb_sb_info *server)
{
down(&(server->sem));
}
static inline void
smb_unlock_server(struct smb_sb_info *server)
{
up(&(server->sem));
}
static void
str_upper(char *name, int len)
{
......@@ -83,6 +102,96 @@ static void reverse_string(char *buf, int len)
}
}
/* no conversion, just a wrapper for memcpy. */
static int convert_memcpy(char *output, int olen,
const char *input, int ilen,
struct nls_table *nls_from,
struct nls_table *nls_to)
{
memcpy(output, input, ilen);
return ilen;
}
/* convert from one "codepage" to another (possibly being utf8). */
static int convert_cp(char *output, int olen,
const char *input, int ilen,
struct nls_table *nls_from,
struct nls_table *nls_to)
{
int len = 0;
int n;
wchar_t ch;
if (!nls_from || !nls_to) {
PARANOIA("nls_from=%p, nls_to=%p\n", nls_from, nls_to);
return convert_memcpy(output, olen, input, ilen, NULL, NULL);
}
while (ilen > 0) {
/* convert by changing to unicode and back to the new cp */
n = nls_from->char2uni((unsigned char *)input, ilen, &ch);
if (n < 0)
goto out;
input += n;
ilen -= n;
n = nls_to->uni2char(ch, output, olen);
if (n < 0)
goto out;
output += n;
olen -= n;
len += n;
}
out:
return len;
}
static int setcodepage(struct smb_sb_info *server,
struct nls_table **p, char *name)
{
struct nls_table *nls;
if (!name || !*name) {
nls = NULL;
} else if ( (nls = load_nls(name)) == NULL) {
printk (KERN_ERR "smbfs: failed to load nls '%s'\n", name);
return -EINVAL;
}
/* if already set, unload the previous one. */
if (*p)
unload_nls(*p);
*p = nls;
return 0;
}
/* Handles all changes to codepage settings. */
int smb_setcodepage(struct smb_sb_info *server, struct smb_nls_codepage *cp)
{
int n;
smb_lock_server(server);
n = setcodepage(server, &server->local_nls, cp->local_name);
if (n != 0)
goto out;
n = setcodepage(server, &server->remote_nls, cp->remote_name);
if (n != 0)
setcodepage(server, &server->local_nls, NULL);
out:
if (server->local_nls != NULL && server->remote_nls != NULL)
server->convert = convert_cp;
else
server->convert = convert_memcpy;
smb_unlock_server(server);
return n;
}
/*****************************************************************************/
/* */
/* Encoding/Decoding section */
......@@ -107,9 +216,11 @@ smb_encode_smb_length(__u8 * p, __u32 len)
* smb_build_path: build the path to entry and name storing it in buf.
* The path returned will have the trailing '\0'.
*/
static int smb_build_path(struct dentry * entry, struct qstr * name, char * buf)
static int smb_build_path(struct smb_sb_info *server, char * buf,
struct dentry * entry, struct qstr * name)
{
char *path = buf;
int len;
if (entry == NULL)
goto test_name_and_out;
......@@ -129,9 +240,16 @@ static int smb_build_path(struct dentry * entry, struct qstr * name, char * buf)
* and store it in reversed order [see reverse_string()]
*/
for (;;) {
memcpy(path, entry->d_name.name, entry->d_name.len);
reverse_string(path, entry->d_name.len);
path += entry->d_name.len;
if (entry->d_name.len > SMB_MAXNAMELEN)
return -ENAMETOOLONG;
if (path - buf + entry->d_name.len > SMB_MAXPATHLEN)
return -ENAMETOOLONG;
len = server->convert(path, SMB_MAXNAMELEN,
entry->d_name.name, entry->d_name.len,
server->local_nls, server->remote_nls);
reverse_string(path, len);
path += len;
*(path++) = '\\';
......@@ -147,25 +265,28 @@ static int smb_build_path(struct dentry * entry, struct qstr * name, char * buf)
if (name != NULL) {
*(path++) = '\\';
name_and_out:
memcpy(path, name->name, name->len);
path += name->len;
len = server->convert(path, SMB_MAXNAMELEN,
name->name, name->len,
server->local_nls, server->remote_nls);
path += len;
}
out:
*(path++) = '\0';
return (path-buf);
}
static char *smb_encode_path(struct smb_sb_info *server, char *buf,
struct dentry *dir, struct qstr *name)
static int smb_encode_path(struct smb_sb_info *server, char *buf,
struct dentry *dir, struct qstr *name)
{
char *start = buf;
buf += smb_build_path(dir, name, buf);
int result;
result = smb_build_path(server, buf, dir, name);
if (result < 0)
goto out;
if (server->opt.protocol <= SMB_PROTOCOL_COREPLUS)
str_upper(start, buf - start);
return buf;
str_upper(buf, result);
out:
return result;
}
/* The following are taken directly from msdos-fs */
......@@ -464,18 +585,6 @@ smb_errno(struct smb_sb_info *server)
return EIO;
}
static inline void
smb_lock_server(struct smb_sb_info *server)
{
down(&(server->sem));
}
static inline void
smb_unlock_server(struct smb_sb_info *server)
{
up(&(server->sem));
}
/*
* smb_retry: This function should be called when smb_request_ok has
* indicated an error. If the error was indicated because the
......@@ -495,8 +604,7 @@ smb_retry(struct smb_sb_info *server)
smb_close_socket(server);
if (pid == 0)
{
if (pid == 0) {
printk(KERN_ERR "smb_retry: no connection process\n");
server->state = CONN_RETRIED;
goto out;
......@@ -511,26 +619,35 @@ smb_retry(struct smb_sb_info *server)
* Note: use the "priv" flag, as a user process may need to reconnect.
*/
error = kill_proc(pid, SIGUSR1, 1);
if (error)
{
if (error) {
printk(KERN_ERR "smb_retry: signal failed, error=%d\n", error);
goto out_restore;
}
VERBOSE("signalled pid %d, waiting for new connection\n",
server->conn_pid);
VERBOSE("signalled pid %d, waiting for new connection\n", pid);
/*
* Wait for the new connection.
*/
#ifdef SMB_RETRY_INTR
interruptible_sleep_on_timeout(&server->wait, 5*HZ);
if (signal_pending(current))
printk(KERN_INFO "smb_retry: caught signal\n");
#else
/*
* We don't want to be interrupted. For example, what if 'current'
* already has recieved a signal? sleep_on would terminate immediately
* and smbmount would not be able to re-establish connection.
*
* smbmount should be able to reconnect later, but it can't because
* it will get an -EIO on attempts to open the mountpoint!
*/
sleep_on_timeout(&server->wait, 5*HZ);
#endif
/*
* Check for a valid connection.
*/
if (server->state == CONN_VALID)
{
if (server->state == CONN_VALID) {
/* This should be changed to VERBOSE, except many smbfs
problems is with the userspace daemon not reconnecting. */
PARANOIA("sucessful, new pid=%d, generation=%d\n",
......@@ -656,7 +773,7 @@ smb_newconn(struct smb_sb_info *server, struct smb_conn_opt *opt)
if (server->opt.protocol == SMB_PROTOCOL_NT1 &&
(server->opt.max_xmit < 0x1000) &&
!(server->opt.capabilities & SMB_CAP_NT_SMBS)) {
server->mnt->version |= SMB_FIX_WIN95;
server->mnt->flags |= SMB_MOUNT_WIN95;
#ifdef SMBFS_DEBUG_VERBOSE
printk(KERN_NOTICE "smb_newconn: detected WIN95 server\n");
#endif
......@@ -667,7 +784,11 @@ smb_newconn(struct smb_sb_info *server, struct smb_conn_opt *opt)
server->opt.capabilities);
out:
#ifdef SMB_RETRY_INTR
wake_up_interruptible(&server->wait);
#else
wake_up(&server->wait);
#endif
return error;
out_putf:
......@@ -738,7 +859,7 @@ smb_proc_open(struct smb_sb_info *server, struct dentry *dentry, int wish)
{
struct inode *ino = dentry->d_inode;
int mode, read_write = 0x42, read_only = 0x40;
int error;
int res;
char *p;
/*
......@@ -748,6 +869,9 @@ smb_proc_open(struct smb_sb_info *server, struct dentry *dentry, int wish)
if (!(ino->i_mode & (S_IWUSR | S_IWGRP | S_IWOTH)))
mode = read_only;
#if 0
/* FIXME: why is this code not in? below we fix it so that a caller
wanting RO doesn't get RW. smb_revalidate_inode does some
optimization based on access mode. tail -f needs it to be correct. */
if (!(wish & (O_WRONLY | O_RDWR)))
mode = read_only;
#endif
......@@ -757,20 +881,23 @@ smb_proc_open(struct smb_sb_info *server, struct dentry *dentry, int wish)
WSET(server->packet, smb_vwv0, mode);
WSET(server->packet, smb_vwv1, aSYSTEM | aHIDDEN | aDIR);
*p++ = 4;
p = smb_encode_path(server, p, dentry, NULL);
res = smb_encode_path(server, p, dentry, NULL);
if (res < 0)
goto out;
p += res;
smb_setup_bcc(server, p);
error = smb_request_ok(server, SMBopen, 7, 0);
if (error != 0)
{
res = smb_request_ok(server, SMBopen, 7, 0);
if (res != 0) {
if (smb_retry(server))
goto retry;
if (mode == read_write &&
(error == -EACCES || error == -ETXTBSY || error == -EROFS))
(res == -EACCES || res == -ETXTBSY || res == -EROFS))
{
VERBOSE("%s/%s R/W failed, error=%d, retrying R/O\n",
DENTRY_PATH(dentry), error);
DENTRY_PATH(dentry), res);
mode = read_only;
goto retry;
}
......@@ -783,10 +910,12 @@ smb_proc_open(struct smb_sb_info *server, struct dentry *dentry, int wish)
/* smb_vwv2 has mtime */
/* smb_vwv4 has size */
ino->u.smbfs_i.access = (WVAL(server->packet, smb_vwv6) & SMB_ACCMASK);
if (!(wish & (O_WRONLY | O_RDWR)))
ino->u.smbfs_i.access = SMB_O_RDONLY;
ino->u.smbfs_i.open = server->generation;
out:
return error;
return res;
}
/*
......@@ -1025,7 +1154,7 @@ smb_proc_create(struct dentry *dentry, __u16 attr, time_t ctime, __u16 *fileid)
{
struct smb_sb_info *server = server_from_dentry(dentry);
char *p;
int error;
int result;
smb_lock_server(server);
......@@ -1034,22 +1163,24 @@ smb_proc_create(struct dentry *dentry, __u16 attr, time_t ctime, __u16 *fileid)
WSET(server->packet, smb_vwv0, attr);
DSET(server->packet, smb_vwv1, utc2local(server, ctime));
*p++ = 4;
p = smb_encode_path(server, p, dentry, NULL);
result = smb_encode_path(server, p, dentry, NULL);
if (result < 0)
goto out;
p += result;
smb_setup_bcc(server, p);
error = smb_request_ok(server, SMBcreate, 1, 0);
if (error < 0)
{
result = smb_request_ok(server, SMBcreate, 1, 0);
if (result < 0) {
if (smb_retry(server))
goto retry;
goto out;
}
*fileid = WVAL(server->packet, smb_vwv0);
error = 0;
result = 0;
out:
smb_unlock_server(server);
return error;
return result;
}
int
......@@ -1064,14 +1195,22 @@ smb_proc_mv(struct dentry *old_dentry, struct dentry *new_dentry)
retry:
p = smb_setup_header(server, SMBmv, 1, 0);
WSET(server->packet, smb_vwv0, aSYSTEM | aHIDDEN | aDIR);
*p++ = 4;
p = smb_encode_path(server, p, old_dentry, NULL);
result = smb_encode_path(server, p, old_dentry, NULL);
if (result < 0)
goto out;
p += result;
*p++ = 4;
p = smb_encode_path(server, p, new_dentry, NULL);
result = smb_encode_path(server, p, new_dentry, NULL);
if (result < 0)
goto out;
p += result;
smb_setup_bcc(server, p);
if ((result = smb_request_ok(server, SMBmv, 0, 0)) < 0)
{
if ((result = smb_request_ok(server, SMBmv, 0, 0)) < 0) {
if (smb_retry(server))
goto retry;
goto out;
......@@ -1097,12 +1236,14 @@ smb_proc_generic_command(struct dentry *dentry, __u8 command)
retry:
p = smb_setup_header(server, command, 0, 0);
*p++ = 4;
p = smb_encode_path(server, p, dentry, NULL);
result = smb_encode_path(server, p, dentry, NULL);
if (result < 0)
goto out;
p += result;
smb_setup_bcc(server, p);
result = smb_request_ok(server, command, 0, 0);
if (result < 0)
{
if (result < 0) {
if (smb_retry(server))
goto retry;
goto out;
......@@ -1165,11 +1306,13 @@ smb_proc_unlink(struct dentry *dentry)
p = smb_setup_header(server, SMBunlink, 1, 0);
WSET(server->packet, smb_vwv0, aSYSTEM | aHIDDEN);
*p++ = 4;
p = smb_encode_path(server, p, dentry, NULL);
result = smb_encode_path(server, p, dentry, NULL);
if (result < 0)
goto out;
p += result;
smb_setup_bcc(server, p);
if ((result = smb_request_ok(server, SMBunlink, 0, 0)) < 0)
{
if ((result = smb_request_ok(server, SMBunlink, 0, 0)) < 0) {
#if SMBFS_POSIX_UNLINK
if (result == -EACCES && !flag) {
/* Posix semantics is for the read-only state
......@@ -1220,8 +1363,7 @@ smb_proc_trunc(struct smb_sb_info *server, __u16 fid, __u32 length)
*p++ = 0;
smb_setup_bcc(server, p);
if ((result = smb_request_ok(server, SMBwrite, 1, 0)) < 0)
{
if ((result = smb_request_ok(server, SMBwrite, 1, 0)) < 0) {
if (smb_retry(server))
goto retry;
goto out;
......@@ -1306,6 +1448,8 @@ smb_decode_dirent(struct smb_sb_info *server, __u8 *p,
len--;
entry->len = len;
/* FIXME: These only work for ascii chars, and recent smbmount doesn't
allow the flag to be set anyway. Remove? */
switch (server->opt.case_handling) {
case SMB_CASE_UPPER:
str_upper(entry->name, len);
......@@ -1316,7 +1460,13 @@ smb_decode_dirent(struct smb_sb_info *server, __u8 *p,
default:
break;
}
DEBUG1("len=%d, name=%.*s\n", len, len, entry->name);
entry->len = server->convert(server->name_buf, SMB_MAXNAMELEN,
entry->name, len,
server->remote_nls, server->local_nls);
entry->name = server->name_buf;
DEBUG1("len=%d, name=%.*s\n", entry->len, entry->len, entry->name);
return p + 22;
}
......@@ -1355,7 +1505,10 @@ smb_proc_readdir_short(struct smb_sb_info *server, struct dentry *dir, int fpos,
WSET(server->packet, smb_vwv1, aDIR);
*p++ = 4;
if (first == 1) {
p = smb_encode_path(server, p, dir, &mask);
result = smb_encode_path(server, p, dir, &mask);
if (result < 0)
goto unlock_return;
p += result;
*p++ = 5;
WSET(p, 0, 0);
p += 2;
......@@ -1467,12 +1620,11 @@ smb_decode_long_dirent(struct smb_sb_info *server, char *p,
switch (level) {
case 1:
len = *((unsigned char *) p + 22);
entry->len = len;
entry->name = p + 23;
result = p + 24 + len;
VERBOSE("info 1 at %p, len=%d, name=%.*s\n",
p, entry->len, entry->len, entry->name);
p, len, len, entry->name);
break;
case 260:
result = p + WVAL(p, 0);
......@@ -1482,14 +1634,14 @@ smb_decode_long_dirent(struct smb_sb_info *server, char *p,
entry->name = p + 94;
if (len && entry->name[len-1] == '\0')
len--;
entry->len = len;
VERBOSE("info 260 at %p, len=%d, name=%.*s\n",
p, entry->len, entry->len, entry->name);
p, len, len, entry->name);
break;
default:
PARANOIA("Unknown info level %d\n", level);
result = p + WVAL(p, 0);
goto out;
}
switch (server->opt.case_handling) {
......@@ -1503,6 +1655,11 @@ smb_decode_long_dirent(struct smb_sb_info *server, char *p,
break;
}
entry->len = server->convert(server->name_buf, SMB_MAXNAMELEN,
entry->name, len,
server->remote_nls, server->local_nls);
entry->name = server->name_buf;
out:
return result;
}
......@@ -1561,7 +1718,12 @@ smb_proc_readdir_long(struct smb_sb_info *server, struct dentry *dir, int fpos,
* Encode the initial path
*/
mask = param + 12;
mask_len = smb_encode_path(server, mask, dir, &star) - mask;
mask_len = smb_encode_path(server, mask, dir, &star);
if (mask_len < 0) {
entries = mask_len;
goto unlock_return;
}
first = 1;
VERBOSE("starting fpos=%d, mask=%s\n", fpos, mask);
......@@ -1753,7 +1915,11 @@ smb_proc_getattr_ff(struct smb_sb_info *server, struct dentry *dentry,
int mask_len, result;
retry:
mask_len = smb_encode_path(server, mask, dentry, NULL) - mask;
mask_len = smb_encode_path(server, mask, dentry, NULL);
if (mask_len < 0) {
result = mask_len;
goto out;
}
VERBOSE("name=%s, len=%d\n", mask, mask_len);
WSET(param, 0, aSYSTEM | aHIDDEN | aDIR);
WSET(param, 2, 1); /* max count */
......@@ -1828,7 +1994,10 @@ smb_proc_getattr_core(struct smb_sb_info *server, struct dentry *dir,
retry:
p = smb_setup_header(server, SMBgetatr, 0, 0);
*p++ = 4;
p = smb_encode_path(server, p, dir, NULL);
result = smb_encode_path(server, p, dir, NULL);
if (result < 0)
goto out;
p += result;
smb_setup_bcc(server, p);
if ((result = smb_request_ok(server, SMBgetatr, 10, 0)) < 0)
......@@ -1874,7 +2043,10 @@ smb_proc_getattr_trans2(struct smb_sb_info *server, struct dentry *dir,
retry:
WSET(param, 0, 1); /* Info level SMB_INFO_STANDARD */
DSET(param, 2, 0);
p = smb_encode_path(server, param + 6, dir, NULL);
result = smb_encode_path(server, param + 6, dir, NULL);
if (result < 0)
goto out;
p = param + 6 + result;
result = smb_trans2_request(server, TRANSACT2_QPATHINFO,
0, NULL, p - param, param,
......@@ -1905,7 +2077,7 @@ smb_proc_getattr_trans2(struct smb_sb_info *server, struct dentry *dir,
* Kludge alert: Win 95 swaps the date and time field,
* contrary to the CIFS docs and Win NT practice.
*/
if (server->mnt->version & SMB_FIX_WIN95) {
if (server->mnt->flags & SMB_MOUNT_WIN95) {
off_date = 2;
off_time = 0;
}
......@@ -1945,21 +2117,16 @@ smb_proc_do_getattr(struct smb_sb_info *server, struct dentry *dir,
/*
* Select whether to use core or trans2 getattr.
* Win 95 appears to break with the trans2 getattr.
*/
if (server->opt.protocol >= SMB_PROTOCOL_LANMAN2) {
/*
* Win 95 appears to break with the trans2 getattr.
* Note: mnt->version options are set at mount time (inode.c)
*/
if (server->mnt->version & (SMB_FIX_OLDATTR|SMB_FIX_WIN95))
goto core_attr;
if (server->mnt->version & SMB_FIX_DIRATTR)
if (server->opt.protocol < SMB_PROTOCOL_LANMAN2 ||
(server->mnt->flags & (SMB_MOUNT_OLDATTR|SMB_MOUNT_WIN95)) ) {
result = smb_proc_getattr_core(server, dir, fattr);
} else {
if (server->mnt->flags & SMB_MOUNT_DIRATTR)
result = smb_proc_getattr_ff(server, dir, fattr);
else
result = smb_proc_getattr_trans2(server, dir, fattr);
} else {
core_attr:
result = smb_proc_getattr_core(server, dir, fattr);
}
smb_finish_dirent(server, fattr);
......@@ -2008,14 +2175,16 @@ smb_proc_setattr_core(struct smb_sb_info *server, struct dentry *dentry,
WSET(server->packet, smb_vwv6, 0);
WSET(server->packet, smb_vwv7, 0);
*p++ = 4;
p = smb_encode_path(server, p, dentry, NULL);
result = smb_encode_path(server, p, dentry, NULL);
if (result < 0)
goto out;
p += result;
*p++ = 4;
*p++ = 0;
smb_setup_bcc(server, p);
result = smb_request_ok(server, SMBsetatr, 0, 0);
if (result < 0)
{
if (result < 0) {
if (smb_retry(server))
goto retry;
goto out;
......@@ -2073,8 +2242,7 @@ smb_proc_setattr_ext(struct smb_sb_info *server,
#endif
result = smb_request_ok(server, SMBsetattrE, 0, 0);
if (result < 0)
{
if (result < 0) {
if (smb_retry(server))
goto retry;
goto out;
......@@ -2107,7 +2275,10 @@ smb_proc_setattr_trans2(struct smb_sb_info *server,
retry:
WSET(param, 0, 1); /* Info level SMB_INFO_STANDARD */
DSET(param, 2, 0);
p = smb_encode_path(server, param + 6, dir, NULL);
result = smb_encode_path(server, param + 6, dir, NULL);
if (result < 0)
goto out;
p = param + 6 + result;
WSET(data, 0, 0); /* creation time */
WSET(data, 2, 0);
......@@ -2170,8 +2341,7 @@ smb_proc_settime(struct dentry *dentry, struct smb_fattr *fattr)
smb_lock_server(server);
/* setting the time on a Win95 server fails (tridge) */
if (server->opt.protocol >= SMB_PROTOCOL_LANMAN2 &&
!(server->mnt->version & SMB_FIX_WIN95))
{
!(server->mnt->flags & SMB_MOUNT_WIN95)) {
if (smb_is_open(inode) &&
inode->u.smbfs_i.access != SMB_O_RDONLY)
result = smb_proc_setattr_ext(server, inode, fattr);
......@@ -2182,8 +2352,7 @@ smb_proc_settime(struct dentry *dentry, struct smb_fattr *fattr)
* Fail silently on directories ... timestamp can't be set?
*/
result = 0;
if (S_ISREG(inode->i_mode))
{
if (S_ISREG(inode->i_mode)) {
/*
* Set the mtime by opening and closing the file.
* Note that the file is opened read-only, but this
......@@ -2192,8 +2361,7 @@ smb_proc_settime(struct dentry *dentry, struct smb_fattr *fattr)
result = -EACCES;
if (!smb_is_open(inode))
smb_proc_open(server, dentry, SMB_O_RDONLY);
if (smb_is_open(inode))
{
if (smb_is_open(inode)) {
inode->i_mtime = fattr->f_mtime;
result = smb_proc_close_inode(server, inode);
}
......@@ -2208,7 +2376,7 @@ int
smb_proc_dskattr(struct super_block *sb, struct statfs *attr)
{
struct smb_sb_info *server = &(sb->u.smbfs_sb);
int error;
int result;
char *p;
smb_lock_server(server);
......@@ -2216,8 +2384,7 @@ smb_proc_dskattr(struct super_block *sb, struct statfs *attr)
retry:
smb_setup_header(server, SMBdskattr, 0, 0);
if ((error = smb_request_ok(server, SMBdskattr, 5, 0)) < 0)
{
if ((result = smb_request_ok(server, SMBdskattr, 5, 0)) < 0) {
if (smb_retry(server))
goto retry;
goto out;
......@@ -2226,11 +2393,11 @@ smb_proc_dskattr(struct super_block *sb, struct statfs *attr)
attr->f_blocks = WVAL(p, 0);
attr->f_bsize = WVAL(p, 2) * WVAL(p, 4);
attr->f_bavail = attr->f_bfree = WVAL(p, 6);
error = 0;
result = 0;
out:
smb_unlock_server(server);
return error;
return result;
}
int
......
......@@ -111,12 +111,16 @@ smb_data_callback(void* ptr)
unsigned char peek_buf[4];
int result;
mm_segment_t fs;
int count = 100; /* this is a lot, we should have some data waiting */
int found = 0;
fs = get_fs();
set_fs(get_ds());
lock_kernel();
while (1) {
while (count-- > 0) {
peek_buf[0] = 0;
result = -EIO;
if (job->sk->dead) {
PARANOIA("sock dead!\n");
......@@ -125,7 +129,7 @@ smb_data_callback(void* ptr)
result = _recvfrom(socket, (void *) peek_buf, 1,
MSG_PEEK | MSG_DONTWAIT);
if (result == -EAGAIN)
if (result < 0)
break;
if (peek_buf[0] != 0x85)
break;
......@@ -136,13 +140,15 @@ smb_data_callback(void* ptr)
DEBUG1("got SESSION KEEPALIVE\n");
if (result == -EAGAIN)
if (result < 0)
break;
found = 1;
}
unlock_kernel();
set_fs(fs);
if (result != -EAGAIN)
DEBUG1("found=%d, count=%d, result=%d\n", found, count, result);
if (found)
found_data(job->sk);
kfree(ptr);
}
......
......@@ -10,6 +10,7 @@
* 11-01-1998 RMK Added mask_and_ack_irq
* 22-08-1998 RMK Restructured IRQ routines
*/
#include <linux/config.h>
#include <asm/ioc.h>
#ifdef CONFIG_ARCH_ARC
......
......@@ -3,7 +3,6 @@
*
* Copyright (c) 1996-1999 Russell King and Dave Gilbert
*/
#include <linux/config.h>
static void arch_idle(void)
{
......
/* $Id: pgtable.h,v 1.101 2000/08/09 00:00:17 davem Exp $ */
/* $Id: pgtable.h,v 1.102 2000/08/14 00:46:13 anton Exp $ */
#ifndef _SPARC_PGTABLE_H
#define _SPARC_PGTABLE_H
......@@ -201,11 +201,9 @@ extern unsigned long empty_zero_page;
#define SIZEOF_PTR_LOG2 2
BTFIXUPDEF_CALL_CONST(unsigned long, sparc_pte_pagenr, pte_t)
BTFIXUPDEF_CALL_CONST(unsigned long, pmd_page, pmd_t)
BTFIXUPDEF_CALL_CONST(unsigned long, pgd_page, pgd_t)
#define sparc_pte_pagenr(pte) BTFIXUP_CALL(sparc_pte_pagenr)(pte)
#define pmd_page(pmd) BTFIXUP_CALL(pmd_page)(pmd)
#define pgd_page(pgd) BTFIXUP_CALL(pgd_page)(pgd)
......@@ -305,7 +303,9 @@ BTFIXUPDEF_CALL_CONST(pte_t, pte_mkyoung, pte_t)
/* Permanent address of a page. */
#define page_address(page) ((page)->virtual)
#define pte_page(x) (mem_map+sparc_pte_pagenr(x))
BTFIXUPDEF_CALL(struct page *, pte_page, pte_t)
#define pte_page(pte) BTFIXUP_CALL(pte_page)(pte)
/*
* Conversion functions: convert a page and protection to a page entry,
......
......@@ -16,7 +16,7 @@
* Define this to use the verbose/debugging versions in
* arch/sparc/lib/debuglocks.c
*
* Be sure to make check_asm whenever changing this option.
* Be sure to make dep whenever changing this option.
*/
#define SPIN_LOCK_DEBUG
......@@ -28,7 +28,7 @@ struct _spinlock_debug {
typedef struct _spinlock_debug spinlock_t;
#define SPIN_LOCK_UNLOCKED (spinlock_t) { 0, 0 }
#define spin_lock_init(lp) do { (lp)->owner_pc = 0; (lp)->lock = 0; } while(0)
#define spin_lock_init(lp) do { *(lp)= SPIN_LOCK_UNLOCKED; } while(0)
#define spin_is_locked(lp) (*((volatile unsigned char *)(&((lp)->lock))) != 0)
#define spin_unlock_wait(lp) do { barrier(); } while(*(volatile unsigned char *)(&(lp)->lock))
......@@ -49,6 +49,8 @@ typedef struct _rwlock_debug rwlock_t;
#define RW_LOCK_UNLOCKED (rwlock_t) { 0, 0, {0} }
#define rwlock_init(lp) do { *(lp)= RW_LOCK_UNLOCKED; } while(0)
extern void _do_read_lock(rwlock_t *rw, char *str);
extern void _do_read_unlock(rwlock_t *rw, char *str);
extern void _do_write_lock(rwlock_t *rw, char *str);
......@@ -144,6 +146,9 @@ typedef struct { volatile unsigned int lock; } rwlock_t;
#define RW_LOCK_UNLOCKED (rwlock_t) { 0 }
#define rwlock_init(lp) do { *(lp)= RW_LOCK_UNLOCKED; } while(0)
/* Sort of like atomic_t's on Sparc, but even more clever.
*
* ------------------------------------
......
/* $Id: unistd.h,v 1.68 2000/08/12 20:49:49 jj Exp $ */
/* $Id: unistd.h,v 1.70 2000/08/14 05:39:07 jj Exp $ */
#ifndef _SPARC_UNISTD_H
#define _SPARC_UNISTD_H
......@@ -170,7 +170,7 @@
/* #define __NR_putmsg 152 SunOS Specific */
#define __NR_poll 153 /* Common */
#define __NR_getdents64 154 /* Linux specific */
#define __NR_fstat64 155 /* Linux sparc32 Specific */
#define __NR_fcntl64 155 /* Linux sparc32 Specific */
/* #define __NR_getdirentries 156 SunOS Specific */
#define __NR_statfs 157 /* Common */
#define __NR_fstatfs 158 /* Common */
......
......@@ -109,6 +109,7 @@ extern int _spin_trylock (spinlock_t *lock);
typedef unsigned int rwlock_t;
#define RW_LOCK_UNLOCKED 0
#define rwlock_init(lp) do { *(lp) = RW_LOCK_UNLOCKED; } while(0)
extern void __read_lock(rwlock_t *);
extern void __read_unlock(rwlock_t *);
......@@ -128,6 +129,7 @@ typedef struct {
unsigned int reader_pc[4];
} rwlock_t;
#define RW_LOCK_UNLOCKED (rwlock_t) { 0, 0, 0xff, { 0, 0, 0, 0 } }
#define rwlock_init(lp) do { *(lp) = RW_LOCK_UNLOCKED; } while(0)
extern void _do_read_lock(rwlock_t *rw, char *str);
extern void _do_read_unlock(rwlock_t *rw, char *str);
......
/* $Id: unistd.h,v 1.46 2000/08/12 20:49:49 jj Exp $ */
/* $Id: unistd.h,v 1.47 2000/08/14 05:39:07 jj Exp $ */
#ifndef _SPARC64_UNISTD_H
#define _SPARC64_UNISTD_H
......@@ -170,7 +170,7 @@
/* #define __NR_putmsg 152 SunOS Specific */
#define __NR_poll 153 /* Common */
#define __NR_getdents64 154 /* Linux specific */
/* #define __NR_fstat64 155 Linux sparc32 Specific */
/* #define __NR_fcntl64 155 Linux sparc32 Specific */
/* #define __NR_getdirentries 156 SunOS Specific */
#define __NR_statfs 157 /* Common */
#define __NR_fstatfs 158 /* Common */
......
......@@ -62,6 +62,13 @@ struct smb_conn_opt {
#ifdef __KERNEL__
#define SMB_NLS_MAXNAMELEN 20
struct smb_nls_codepage {
char local_name[SMB_NLS_MAXNAMELEN];
char remote_name[SMB_NLS_MAXNAMELEN];
};
#define SMB_MAXNAMELEN 255
#define SMB_MAXPATHLEN 1024
......
......@@ -73,13 +73,6 @@ smb_vfree(void *obj)
#define SMB_F_CACHEVALID 0x01 /* directory cache valid */
#define SMB_F_LOCALWRITE 0x02 /* file modified locally */
/*
* Bug fix flags
*/
#define SMB_FIX_WIN95 0x0001 /* Win 95 server */
#define SMB_FIX_OLDATTR 0x0002 /* Use core getattr (Win 95 speedup) */
#define SMB_FIX_DIRATTR 0x0004 /* Use find_first for getattr */
/* NT1 protocol capability bits */
#define SMB_CAP_RAW_MODE 0x0001
......@@ -122,6 +115,7 @@ unsigned long smb_invent_inos(unsigned long);
struct inode *smb_iget(struct super_block *, struct smb_fattr *);
/* linux/fs/smbfs/proc.c */
int smb_setcodepage(struct smb_sb_info *server, struct smb_nls_codepage *cp);
__u32 smb_len(unsigned char *);
__u8 *smb_encode_smb_length(__u8 *, __u32);
__u8 *smb_setup_header(struct smb_sb_info *, __u8, __u16, __u16);
......
......@@ -23,7 +23,7 @@ struct smb_sb_info {
enum smb_conn_state state;
struct file * sock_file;
struct smb_mount_data *mnt;
struct smb_mount_data_kernel *mnt;
unsigned char *temp_buf;
/* Connections are counted. Each time a new socket arrives,
......@@ -41,8 +41,20 @@ struct smb_sb_info {
unsigned short rcls; /* The error codes we received */
unsigned short err;
/* We use our on data_ready callback, but need the original one */
/* We use our own data_ready callback, but need the original one */
void *data_ready;
/* nls pointers for codepage conversions */
struct nls_table *remote_nls;
struct nls_table *local_nls;
/* utf8 can make strings longer so we can't do in-place conversion.
This is a buffer for temporary stuff. We only need one so no need
to put it on the stack. This points to temp_buf space. */
char *name_buf;
int (*convert)(char *, int, const char *, int,
struct nls_table *, struct nls_table *);
};
#endif /* __KERNEL__ */
......
......@@ -11,7 +11,7 @@
#include <linux/types.h>
#define SMB_MOUNT_VERSION 6
#define SMB_MOUNT_VERSION 6
struct smb_mount_data {
int version;
......@@ -22,4 +22,37 @@ struct smb_mount_data {
__kernel_mode_t dir_mode;
};
#ifdef __KERNEL__
/* "vers" in big-endian */
#define SMB_MOUNT_ASCII 0x76657273
#define SMB_MOUNT_OLDVERSION 6
#undef SMB_MOUNT_VERSION
#define SMB_MOUNT_VERSION 7
/* flags */
#define SMB_MOUNT_WIN95 0x0001 /* Win 95 server */
#define SMB_MOUNT_OLDATTR 0x0002 /* Use core getattr (Win 95 speedup) */
#define SMB_MOUNT_DIRATTR 0x0004 /* Use find_first for getattr */
#define SMB_MOUNT_CASE 0x0008 /* Be case sensitive */
struct smb_mount_data_kernel {
int version;
__kernel_uid_t mounted_uid; /* Who may umount() this filesystem? */
__kernel_uid_t uid;
__kernel_gid_t gid;
__kernel_mode_t file_mode;
__kernel_mode_t dir_mode;
u32 flags;
struct smb_nls_codepage codepage;
};
#endif
#endif
......@@ -527,6 +527,7 @@ EXPORT_SYMBOL(get_fast_time);
/* library functions */
EXPORT_SYMBOL(strnicmp);
EXPORT_SYMBOL(strspn);
EXPORT_SYMBOL(strsep);
/* software interrupts */
EXPORT_SYMBOL(tasklet_hi_vec);
......
......@@ -414,7 +414,7 @@ static int writeout_one_page(struct page *page)
if (buffer_locked(bh) || !buffer_dirty(bh) || !buffer_uptodate(bh))
continue;
bh->b_flushtime = 0;
bh->b_flushtime = jiffies;
ll_rw_block(WRITE, 1, &bh);
} while ((bh = bh->b_this_page) != head);
return 0;
......
......@@ -339,7 +339,7 @@ struct buffer_head * create_bounce(int rw, struct buffer_head * bh_orig)
bh->b_count = bh_orig->b_count;
bh->b_rdev = bh_orig->b_rdev;
bh->b_state = bh_orig->b_state;
bh->b_flushtime = 0;
bh->b_flushtime = jiffies;
bh->b_next_free = NULL;
bh->b_prev_free = NULL;
/* bh->b_this_page */
......
......@@ -359,6 +359,7 @@ EXPORT_SYMBOL(tcp_sockets_allocated);
EXPORT_SYMBOL(sysctl_tcp_reordering);
EXPORT_SYMBOL(sysctl_tcp_rmem);
EXPORT_SYMBOL(sysctl_tcp_wmem);
EXPORT_SYMBOL(sysctl_tcp_ecn);
EXPORT_SYMBOL(tcp_cwnd_application_limited);
EXPORT_SYMBOL(xrlim_allow);
......
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