- 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
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
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
*
* 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)
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); }
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)
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)
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
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);
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
*
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;
}
{
int *used = dev->private;
- if (!--(*port->used))
+ if (!--(*used))
free_irq(IRQ_AMIGA_VERTB, amijoy_interrupt);
}
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;
}
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)
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
*
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",
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:
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:
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:
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);
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);
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);
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
*
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.
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);
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;
{
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
*
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
*
*/
#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";
/*
{
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 */
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 */
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;
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;
*/
+#include <linux/config.h>
#include <linux/fs.h>
#undef N_DATA
*
* 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
/* 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 */
};
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;
*
* ------------------------------------------------------------------------- */
- /*
- * 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)
{
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)
{
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)
{
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)
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)
{
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)
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)
{
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)
*
* ------------------------------------------------------------------------- */
+/**
+ * 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);
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);
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);
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
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;
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);
}
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;
}
int pageind;
int bhind;
int offset;
+ int sectors = size>>9;
unsigned long blocknr;
struct kiobuf * iobuf = NULL;
struct page * map;
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);
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)
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);
}
}
# 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.
# 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
#include <linux/ctype.h>
#include <linux/smb_fs.h>
+#include <linux/smb_mount.h>
#include <linux/smbno.h>
#include "smb_debug.h"
}
/*
- * 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
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.
*/
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;
}
struct smb_fattr finfo;
struct inode *inode;
int error;
+ struct smb_sb_info *server;
error = -ENAMETOOLONG;
if (dentry->d_name.len > SMB_MAXNAMELEN)
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;
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+#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 */
#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>
#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 *);
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)
{
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? */
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);
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");
/*
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");
#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>
#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))
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)
{
}
}
+/* 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 */
* 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;
* 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++) = '\\';
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 */
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
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;
* 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",
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
server->opt.capabilities);
out:
+#ifdef SMB_RETRY_INTR
wake_up_interruptible(&server->wait);
+#else
+ wake_up(&server->wait);
+#endif
return error;
out_putf:
{
struct inode *ino = dentry->d_inode;
int mode, read_write = 0x42, read_only = 0x40;
- int error;
+ int res;
char *p;
/*
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
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;
}
/* 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;
}
/*
{
struct smb_sb_info *server = server_from_dentry(dentry);
char *p;
- int error;
+ int result;
smb_lock_server(server);
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
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;
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;
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
*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;
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);
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;
}
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;
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);
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) {
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;
}
* 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);
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 */
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)
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,
* 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;
}
/*
* 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);
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;
#endif
result = smb_request_ok(server, SMBsetattrE, 0, 0);
- if (result < 0)
- {
+ if (result < 0) {
if (smb_retry(server))
goto retry;
goto out;
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);
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);
* 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
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);
}
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);
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;
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
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");
result = _recvfrom(socket, (void *) peek_buf, 1,
MSG_PEEK | MSG_DONTWAIT);
- if (result == -EAGAIN)
+ if (result < 0)
break;
if (peek_buf[0] != 0x85)
break;
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);
}
* 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
*
* 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
#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)
/* 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,
* 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
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))
#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);
#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
/* #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 */
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 *);
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
/* #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 */
#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
#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
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);
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,
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__ */
#include <linux/types.h>
-#define SMB_MOUNT_VERSION 6
+#define SMB_MOUNT_VERSION 6
struct smb_mount_data {
int version;
__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
/* library functions */
EXPORT_SYMBOL(strnicmp);
EXPORT_SYMBOL(strspn);
+EXPORT_SYMBOL(strsep);
/* software interrupts */
EXPORT_SYMBOL(tasklet_hi_vec);
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;
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 */
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);