diff -u --recursive --new-file v2.0.26/linux/CREDITS linux/CREDITS --- v2.0.26/linux/CREDITS Fri Nov 22 16:25:53 1996 +++ linux/CREDITS Fri Nov 29 12:10:18 1996 @@ -108,8 +108,8 @@ N: Randolph Bentson E: bentson@grieg.seaslug.org D: author of driver for Cyclades Cyclom-Y async mux -S: 2500 Gilman Dr W, #404 -S: Seattle, Washington 98119-2102 +S: 2322 37th Ave SW +S: Seattle, Washington 98126-2010 S: USA N: Stephen R. van den Berg (AKA BuGless) @@ -960,7 +960,7 @@ S: USA N: Rick Miller -E: rdmiller@execpc.com +E: rick@digalogsys.com D: Original Linux Device Registrar (Major/minor numbers), au-play, bwBASIC S: S78 W16203 Woods Road S: Muskego, Wisconsin 53150 diff -u --recursive --new-file v2.0.26/linux/Documentation/Configure.help linux/Documentation/Configure.help --- v2.0.26/linux/Documentation/Configure.help Fri Nov 22 16:25:54 1996 +++ linux/Documentation/Configure.help Sun Dec 1 15:58:05 1996 @@ -1641,10 +1641,10 @@ EATA ISA/EISA/PCI (DPT and generic EATA/DMA-compliant boards) support CONFIG_SCSI_EATA This driver supports all the EATA/DMA-compliant SCSI host adapters - and does not need any BIOS32 or PCI BIOS service. - Only ISA (0x1F0, 0x170, 0x230, 0x330) and EISA (0x1C88 through 0xFC88) - addresses are probed. In order to detect a generic EATA PCI board you - can force on it any unused EISA address. + and does not need any BIOS32 service. + DPT ISA and all EISA i/o addresses are probed looking for the "EATA" + signature. If "PCI bios support" is enabled, the addresses of all the + PCI SCSI controllers reported by BIOS32 are probed as well. Note that there is also another driver for the same hardware: "EATA-DMA support". You should enable only one of them. You want to read the start of drivers/scsi/eata.c and the @@ -3121,15 +3121,12 @@ removed from the running kernel whenever you want), say M here and read Documentation/modules.txt. Most people say N, however. -SMB long filename support (EXPERIMENTAL) -CONFIG_SMB_LONG - SMBFS was designed to support long filenames using the LanManager - 2.0 protocol. I had to find out that the support for long filenames - sometimes causes problems, which can even result in kernel OOPSes. I - did not yet find out what the problem is, but hopefully I will find - this bug eventually. As many people seem to run long filenames with - no problems, I leave this support in the kernel as an option. The - careful among you should say N here. +SMB Win95 bug work-around +CONFIG_SMB_WIN95 + If you want to connect to a share exported by Windows 95, you should + say Y here. The Windows 95 server contains a bug that makes listing + directories unreliable. This option slows down the listing of + directories. This makes the Windows 95 server a bit more stable. NCP filesystem support (to mount NetWare volumes) CONFIG_NCP_FS diff -u --recursive --new-file v2.0.26/linux/Makefile linux/Makefile --- v2.0.26/linux/Makefile Fri Nov 22 16:25:55 1996 +++ linux/Makefile Fri Nov 22 16:25:41 1996 @@ -1,6 +1,6 @@ VERSION = 2 PATCHLEVEL = 0 -SUBLEVEL = 26 +SUBLEVEL = 27 ARCH = i386 diff -u --recursive --new-file v2.0.26/linux/arch/alpha/kernel/bios32.c linux/arch/alpha/kernel/bios32.c --- v2.0.26/linux/arch/alpha/kernel/bios32.c Fri Nov 22 16:25:55 1996 +++ linux/arch/alpha/kernel/bios32.c Sat Nov 30 11:14:51 1996 @@ -693,6 +693,7 @@ static inline void alphapc164_fixup(void) { + extern int SMCInit(void); char irq_tab[7][5] = { /* * int intA intB intC intD @@ -708,6 +709,8 @@ }; common_fixup(5, 11, 5, irq_tab, 0); + + SMCInit(); } /* @@ -1279,4 +1282,262 @@ } return err; } +#ifdef CONFIG_ALPHA_PC164 + +/* device "activate" register contents */ +#define DEVICE_ON 1 +#define DEVICE_OFF 0 + +/* configuration on/off keys */ +#define CONFIG_ON_KEY 0x55 +#define CONFIG_OFF_KEY 0xaa + +/* configuration space device definitions */ +#define FDC 0 +#define IDE1 1 +#define IDE2 2 +#define PARP 3 +#define SER1 4 +#define SER2 5 +#define RTCL 6 +#define KYBD 7 +#define AUXIO 8 + +/* Chip register offsets from base */ +#define CONFIG_CONTROL 0x02 +#define INDEX_ADDRESS 0x03 +#define LOGICAL_DEVICE_NUMBER 0x07 +#define DEVICE_ID 0x20 +#define DEVICE_REV 0x21 +#define POWER_CONTROL 0x22 +#define POWER_MGMT 0x23 +#define OSC 0x24 + +#define ACTIVATE 0x30 +#define ADDR_HI 0x60 +#define ADDR_LO 0x61 +#define INTERRUPT_SEL 0x70 +#define INTERRUPT_SEL_2 0x72 /* KYBD/MOUS only */ +#define DMA_CHANNEL_SEL 0x74 /* FDC/PARP only */ + +#define FDD_MODE_REGISTER 0x90 +#define FDD_OPTION_REGISTER 0x91 + +/* values that we read back that are expected ... */ +#define VALID_DEVICE_ID 2 + +/* default device addresses */ +#define KYBD_INTERRUPT 1 +#define MOUS_INTERRUPT 12 +#define COM2_BASE 0x2f8 +#define COM2_INTERRUPT 3 +#define COM1_BASE 0x3f8 +#define COM1_INTERRUPT 4 +#define PARP_BASE 0x3bc +#define PARP_INTERRUPT 7 + +#define SMC_DEBUG 0 + +unsigned long SMCConfigState( unsigned long baseAddr ) +{ + unsigned char devId; + unsigned char devRev; + + unsigned long configPort; + unsigned long indexPort; + unsigned long dataPort; + + configPort = indexPort = baseAddr; + dataPort = ( unsigned long )( ( char * )configPort + 1 ); + + outb(CONFIG_ON_KEY, configPort); + outb(CONFIG_ON_KEY, configPort); + outb(DEVICE_ID, indexPort); + devId = inb(dataPort); + if ( devId == VALID_DEVICE_ID ) { + outb(DEVICE_REV, indexPort); + devRev = inb(dataPort); + } + else { + baseAddr = 0; + } + return( baseAddr ); +} + +void SMCRunState( unsigned long baseAddr ) +{ + outb(CONFIG_OFF_KEY, baseAddr); +} + +unsigned long SMCDetectUltraIO(void) +{ + unsigned long baseAddr; + + baseAddr = 0x3F0; + if ( ( baseAddr = SMCConfigState( baseAddr ) ) == 0x3F0 ) { + return( baseAddr ); + } + baseAddr = 0x370; + if ( ( baseAddr = SMCConfigState( baseAddr ) ) == 0x370 ) { + return( baseAddr ); + } + return( ( unsigned long )0 ); +} + +void SMCEnableDevice( unsigned long baseAddr, + unsigned long device, + unsigned long portaddr, + unsigned long interrupt) +{ + unsigned long indexPort; + unsigned long dataPort; + + indexPort = baseAddr; + dataPort = ( unsigned long )( ( char * )baseAddr + 1 ); + + outb(LOGICAL_DEVICE_NUMBER, indexPort); + outb(device, dataPort); + + outb(ADDR_LO, indexPort); + outb(( portaddr & 0xFF ), dataPort); + + outb(ADDR_HI, indexPort); + outb(( ( portaddr >> 8 ) & 0xFF ), dataPort); + + outb(INTERRUPT_SEL, indexPort); + outb(interrupt, dataPort); + + outb(ACTIVATE, indexPort); + outb(DEVICE_ON, dataPort); +} + +void SMCEnableKYBD( unsigned long baseAddr ) +{ + unsigned long indexPort; + unsigned long dataPort; + + indexPort = baseAddr; + dataPort = ( unsigned long )( ( char * )baseAddr + 1 ); + + outb(LOGICAL_DEVICE_NUMBER, indexPort); + outb(KYBD, dataPort); + + outb(INTERRUPT_SEL, indexPort); /* Primary interrupt select */ + outb(KYBD_INTERRUPT, dataPort); + + outb(INTERRUPT_SEL_2, indexPort);/* Secondary interrupt select */ + outb(MOUS_INTERRUPT, dataPort); + + outb(ACTIVATE, indexPort); + outb(DEVICE_ON, dataPort); +} + +void SMCEnableFDC( unsigned long baseAddr ) +{ + unsigned long indexPort; + unsigned long dataPort; + + unsigned char oldValue; + + indexPort = baseAddr; + dataPort = ( unsigned long )( ( char * )baseAddr + 1 ); + + outb(LOGICAL_DEVICE_NUMBER, indexPort); + outb(FDC, dataPort); + + outb(FDD_MODE_REGISTER, indexPort); + oldValue = inb(dataPort); + + oldValue |= 0x0E; /* Enable burst mode */ + outb(oldValue, dataPort); + + outb(INTERRUPT_SEL, indexPort); /* Primary interrupt select */ + outb(0x06, dataPort ); + + outb(DMA_CHANNEL_SEL, indexPort); /* DMA channel select */ + outb(0x02, dataPort); + + outb(ACTIVATE, indexPort); + outb(DEVICE_ON, dataPort); +} + +#if SMC_DEBUG +void SMCReportDeviceStatus( unsigned long baseAddr ) +{ + unsigned long indexPort; + unsigned long dataPort; + unsigned char currentControl; + + indexPort = baseAddr; + dataPort = ( unsigned long )( ( char * )baseAddr + 1 ); + + outb(POWER_CONTROL, indexPort); + currentControl = inb(dataPort); + + if ( currentControl & ( 1 << FDC ) ) + printk( "\t+FDC Enabled\n" ); + else + printk( "\t-FDC Disabled\n" ); + + if ( currentControl & ( 1 << IDE1 ) ) + printk( "\t+IDE1 Enabled\n" ); + else + printk( "\t-IDE1 Disabled\n" ); + + if ( currentControl & ( 1 << IDE2 ) ) + printk( "\t+IDE2 Enabled\n" ); + else + printk( "\t-IDE2 Disabled\n" ); + + if ( currentControl & ( 1 << PARP ) ) + printk( "\t+PARP Enabled\n" ); + else + printk( "\t-PARP Disabled\n" ); + + if ( currentControl & ( 1 << SER1 ) ) + printk( "\t+SER1 Enabled\n" ); + else + printk( "\t-SER1 Disabled\n" ); + + if ( currentControl & ( 1 << SER2 ) ) + printk( "\t+SER2 Enabled\n" ); + else + printk( "\t-SER2 Disabled\n" ); + + printk( "\n" ); +} +#endif + +int SMCInit(void) +{ + unsigned long SMCUltraBase; + + if ( ( SMCUltraBase = SMCDetectUltraIO( ) ) != ( unsigned long )0 ) { + printk( "SMC FDC37C93X Ultra I/O Controller found @ 0x%lx\n", + SMCUltraBase ); +#if SMC_DEBUG + SMCReportDeviceStatus( SMCUltraBase ); +#endif + SMCEnableDevice( SMCUltraBase, SER1, COM1_BASE, COM1_INTERRUPT ); + SMCEnableDevice( SMCUltraBase, SER2, COM2_BASE, COM2_INTERRUPT ); + SMCEnableDevice( SMCUltraBase, PARP, PARP_BASE, PARP_INTERRUPT ); + /* on PC164, IDE on the SMC is not enabled; CMD646 (PCI) on MB */ + SMCEnableKYBD( SMCUltraBase ); + SMCEnableFDC( SMCUltraBase ); +#if SMC_DEBUG + SMCReportDeviceStatus( SMCUltraBase ); +#endif + SMCRunState( SMCUltraBase ); + return( 1 ); + } + else { +#if SMC_DEBUG + printk( "No SMC FDC37C93X Ultra I/O Controller found\n" ); +#endif + return( 0 ); + } +} + +#endif /* CONFIG_ALPHA_PC164 */ + #endif /* CONFIG_PCI */ diff -u --recursive --new-file v2.0.26/linux/drivers/isdn/teles/proto.h linux/drivers/isdn/teles/proto.h --- v2.0.26/linux/drivers/isdn/teles/proto.h Thu Jan 1 02:00:00 1970 +++ linux/drivers/isdn/teles/proto.h Fri Nov 29 11:10:13 1996 @@ -0,0 +1,18 @@ +/* $Id: proto.h,v 1.1 1996/09/23 01:53:52 fritz Exp $ + * + * not much now - just the l3 proto discriminator + * + * $Log: proto.h,v $ + * Revision 1.1 1996/09/23 01:53:52 fritz + * Bugfix: discard unknown frames (non-EDSS1 and non-1TR6). + * + */ + +#ifndef PROTO_H +#define PROTO_H + +#define PROTO_EURO 0x08 +#define PROTO_DIS_N0 0x40 +#define PROTO_DIS_N1 0x41 + +#endif diff -u --recursive --new-file v2.0.26/linux/drivers/net/wavelan.c linux/drivers/net/wavelan.c --- v2.0.26/linux/drivers/net/wavelan.c Wed Aug 21 09:18:08 1996 +++ linux/drivers/net/wavelan.c Fri Nov 29 12:00:05 1996 @@ -69,7 +69,7 @@ extern int wavelan_probe(device *); /* See Space.c */ -static const char *version = "wavelan.c:v8 96/8/18\n"; +static const char *version = "wavelan.c:v9 96/11/17\n"; /* * Entry point forward declarations. @@ -881,7 +881,11 @@ || psa.psa_univ_mac_addr[1] != SA_ADDR1 || - psa.psa_univ_mac_addr[2] != SA_ADDR2 + ( + psa.psa_univ_mac_addr[2] != SA_ADDR2 + && + psa.psa_univ_mac_addr[2] != SA_ALT_ADDR2 + ) ) { if (wavelan_debug > 0) diff -u --recursive --new-file v2.0.26/linux/drivers/net/wavelan.h linux/drivers/net/wavelan.h --- v2.0.26/linux/drivers/net/wavelan.h Sun Jul 2 10:30:38 1995 +++ linux/drivers/net/wavelan.h Fri Nov 29 12:00:05 1996 @@ -2,6 +2,7 @@ #define SA_ADDR0 0x08 /* First octet of WaveLAN MAC addresses */ #define SA_ADDR1 0x00 /* Second octet of WaveLAN MAC addresses */ #define SA_ADDR2 0x0E /* Third octet of WaveLAN MAC addresses */ +#define SA_ALT_ADDR2 0x6A /* Alternate third octet of WaveLAN MAC addresses */ #define WAVELAN_MTU 1500 /* Maximum size of WaveLAN packet */ /* diff -u --recursive --new-file v2.0.26/linux/drivers/scsi/BusLogic.c linux/drivers/scsi/BusLogic.c --- v2.0.26/linux/drivers/scsi/BusLogic.c Thu Oct 31 12:08:52 1996 +++ linux/drivers/scsi/BusLogic.c Sun Dec 1 09:43:49 1996 @@ -25,7 +25,7 @@ #define BusLogic_DriverVersion "2.0.6" -#define BusLogic_DriverDate "19 October 1996" +#define BusLogic_DriverDate "1 December 1996" #include @@ -763,7 +763,7 @@ *HostAdapter) { boolean TraceHardReset = (BusLogic_GlobalOptions & BusLogic_TraceHardReset); - int TimeoutCounter = loops_per_sec >> 2; + int TimeoutCounter = loops_per_sec; unsigned char StatusRegister = 0; /* Issue a Hard Reset Command to the Host Adapter. The Host Adapter should diff -u --recursive --new-file v2.0.26/linux/drivers/scsi/eata.c linux/drivers/scsi/eata.c --- v2.0.26/linux/drivers/scsi/eata.c Fri Nov 22 16:26:03 1996 +++ linux/drivers/scsi/eata.c Sat Nov 23 15:28:23 1996 @@ -1,6 +1,14 @@ /* * eata.c - Low-level driver for EATA/DMA SCSI host adapters. * + * 22 Nov 1996 rev. 2.30 for linux 2.1.12 and 2.0.26 + * When CONFIG_PCI is defined, BIOS32 is used to include in the + * list of i/o ports to be probed all the PCI SCSI controllers. + * The list of i/o ports to be probed can be overwritten by the + * "eata=port0, port1,...." boot command line option. + * Scatter/gather lists are now allocated by a number of kmalloc + * calls, in order to avoid the previous size limit of 64Kb. + * * 16 Nov 1996 rev. 2.20 for linux 2.1.10 and 2.0.25 * Added support for EATA 2.0C, PCI, multichannel and wide SCSI. * @@ -79,6 +87,11 @@ * * Copyright (C) 1994, 1995, 1996 Dario Ballabio (dario@milano.europe.dg.com) * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that redistributions of source + * code retain the above copyright notice and this comment without + * modification. + * */ /* @@ -103,9 +116,10 @@ * supported by this driver. * * This code has been tested with up to 3 Distributed Processing Technology - * PM2122A/9X (DPT SCSI BIOS v002.D1, firmware v05E.0) eisa controllers, + * PM2122A/9X (DPT SCSI BIOS v002.D1, firmware v05E.0) EISA controllers, * in any combination of private and shared IRQ. - * PCI support has been tested using a DPT PM3224W (firmware v07G.0). + * PCI support has been tested using up to 2 DPT PM3224W (DPT SCSI BIOS + * v003.D0, firmware v07G.0). * * Multiple ISA, EISA and PCI boards can be configured in the same system. * It is suggested to put all the EISA boards on the same IRQ level, all @@ -116,16 +130,32 @@ * be _level_ triggered (not _edge_ triggered). * * This driver detects EATA boards by probes at fixed port addresses, - * so no BIOS32 or PCI BIOS support is used or required. + * so no BIOS32 or PCI BIOS support is required. * The suggested way to detect a generic EATA PCI board is to force on it * any unused EISA address, even if there are other controllers on the EISA * bus, or even if you system has no EISA bus at all. * Do not force any ISA address on EATA PCI boards. * + * If PCI bios support is configured into the kernel, BIOS32 is used to + * include in the list of i/o ports to be probed all the PCI SCSI controllers. + * + * Due to a DPT BIOS "feature", it might not be possible to force an EISA + * address on more then a single DPT PCI board, so in this case you have to + * let the PCI BIOS assign the addresses. + * * The sequence of detection probes is: + * * - ISA 0x1F0; + * - PCI SCSI controllers (only if BIOS32 is available); * - EISA/PCI 0x1C88 through 0xFC88 (corresponding to EISA slots 1 to 15); * - ISA 0x170, 0x230, 0x330. + * + * The above list of detection probes can be totally replaced by the + * boot command line option: "eata=port0, port1, port2,...", where the + * port0, port1... arguments are ISA/EISA/PCI addresses to be probed. + * For example using "eata=0x7410, 0x7450, 0x230", the driver probes + * only the two PCI addresses 0x7410 and 0x7450 and the ISA address 0x230, + * in this order; "eata=0" totally disables this driver. * * The boards are named EATA0, EATA1,... according to the detection order. * @@ -152,9 +182,11 @@ #include "sd.h" #include #include -#include "linux/in.h" #include "eata.h" #include +#include +#include +#include struct proc_dir_entry proc_scsi_eata2x = { PROC_SCSI_EATA2X, 6, "eata2x", @@ -172,17 +204,22 @@ #undef DEBUG_STATISTICS #undef DEBUG_RESET +#define MAX_ISA 4 +#define MAX_VESA 0 +#define MAX_EISA 15 +#define MAX_PCI 16 +#define MAX_BOARDS (MAX_ISA + MAX_VESA + MAX_EISA + MAX_PCI) #define MAX_CHANNEL 4 #define MAX_LUN 32 #define MAX_TARGET 32 #define MAX_IRQ 16 -#define MAX_BOARDS 18 #define MAX_MAILBOXES 64 #define MAX_SGLIST 64 #define MAX_LARGE_SGLIST 252 #define MAX_INTERNAL_RETRIES 64 #define MAX_CMD_PER_LUN 2 +#define SKIP 1 #define FALSE 0 #define TRUE 1 #define FREE 0 @@ -190,7 +227,6 @@ #define LOCKED 2 #define IN_RESET 3 #define IGNORE 4 -#define NO_IRQ 0xff #define NO_DMA 0xff #define MAXLOOP 200000 @@ -205,7 +241,8 @@ #define REG_MID 4 #define REG_MSB 5 #define REGION_SIZE 9 -#define EISA_RANGE 0x1000 +#define ISA_RANGE 0x0fff +#define EISA_RANGE 0xfc88 #define BSY_ASSERTED 0x80 #define DRQ_ASSERTED 0x08 #define ABSY_ASSERTED 0x01 @@ -261,13 +298,18 @@ /* Structure extension defined in EATA 2.0B */ unchar isaena:1, /* ISA i/o addressing is disabled/enabled */ forcaddr:1, /* Port address has been forced */ - :6; + large_sg:1, /* 1 if large SG lists are supported */ + res1:1, + :4; unchar max_id:5, /* Max SCSI target ID number */ max_chan:3; /* Max SCSI channel number on this board */ /* Structure extension defined in EATA 2.0C */ unchar max_lun; /* Max SCSI LUN number */ - unchar notused[3]; + unchar :6, + pci:1, /* This board is PCI */ + eisa:1; /* This board is EISA */ + unchar notused[2]; ushort ipad[247]; }; @@ -294,6 +336,11 @@ char mess[12]; }; +struct sg_list { + unsigned int address; /* Segment Address */ + unsigned int num_bytes; /* Segment Length */ + }; + /* MailBox SCSI Command Packet */ struct mscp { unchar sreset:1, /* SCSI Bus Reset Signal should be asserted */ @@ -317,17 +364,12 @@ unchar mess[3]; /* Massage to/from Target */ unchar cdb[12]; /* Command Descriptor Block */ ulong data_len; /* If sg=0 Data Length, if sg=1 sglist length */ - Scsi_Cmnd *SCpnt; /* Address to be returned is sp */ + Scsi_Cmnd *SCpnt; /* Address to be returned in sp */ ulong data_address; /* If sg=0 Data Address, if sg=1 sglist address */ ulong sp_addr; /* Address where sp is DMA'ed when cp completes */ ulong sense_addr; /* Address where Sense Data is DMA'ed on error */ - - struct sg_list { - unsigned int address; /* Segment Address */ - unsigned int num_bytes; /* Segment Length */ - } sglist[MAX_SGLIST]; - unsigned int index; /* cp index */ + struct sg_list *sglist; }; struct hostdata { @@ -353,6 +395,26 @@ static const char *driver_name = "EATA"; static unsigned int irqlist[MAX_IRQ], calls[MAX_IRQ]; +static unsigned int io_port[MAX_BOARDS + 1] = { + + /* First ISA */ + 0x1f0, + + /* Space for MAX_PCI ports possibly reported by PCI_BIOS */ + SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, + SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, + + /* MAX_EISA ports */ + 0x1c88, 0x2c88, 0x3c88, 0x4c88, 0x5c88, 0x6c88, 0x7c88, 0x8c88, + 0x9c88, 0xac88, 0xbc88, 0xcc88, 0xdc88, 0xec88, 0xfc88, + + /* Other (MAX_ISA - 1) ports */ + 0x170, 0x230, 0x330, + + /* End of list */ + 0x0 + }; + #define HD(board) ((struct hostdata *) &sh[board]->hostdata) #define BN(board) (HD(board)->board_name) @@ -363,6 +425,7 @@ static void eata2x_interrupt_handler(int, void *, struct pt_regs *); static int do_trace = FALSE; +static int setup_done = FALSE; static inline int wait_on_busy(unsigned int iobase) { unsigned int loop = MAXLOOP; @@ -404,11 +467,12 @@ return FALSE; } -static inline int port_detect(unsigned int *port_base, unsigned int j, +static inline int port_detect(unsigned int port_base, unsigned int j, Scsi_Host_Template *tpnt) { - unsigned char irq, dma_channel, subversion, c; + unsigned char irq, dma_channel, subversion, i; unsigned char protocol_rev; struct eata_info info; + char *bus_type; /* Allowed DMA channels for ISA (0 indicates reserved) */ unsigned char dma_channel_table[4] = { 5, 6, 7, 0 }; @@ -417,16 +481,15 @@ sprintf(name, "%s%d", driver_name, j); - if(check_region(*port_base, REGION_SIZE)) { - printk("%s: address 0x%03x in use, skipping probe.\n", - name, *port_base); + if(check_region(port_base, REGION_SIZE)) { + printk("%s: address 0x%03x in use, skipping probe.\n", name, port_base); return FALSE; } - if (do_dma(*port_base, 0, READ_CONFIG_PIO)) return FALSE; + if (do_dma(port_base, 0, READ_CONFIG_PIO)) return FALSE; /* Read the info structure */ - if (read_pio(*port_base, (ushort *)&info, (ushort *)&info.ipad[0])) + if (read_pio(port_base, (ushort *)&info, (ushort *)&info.ipad[0])) return FALSE; /* Check the controller "EATA" signature */ @@ -446,7 +509,7 @@ irq = info.irq; - if (*port_base >= EISA_RANGE) { + if (port_base > ISA_RANGE) { if (!info.haaval || info.ata || info.drqvld) { printk("%s: unusable EISA/PCI board found (%d%d%d), detaching.\n", @@ -477,8 +540,8 @@ name, irq); /* Board detected, allocate its IRQ if not already done */ - if ((irq >= MAX_IRQ) || ((irqlist[irq] == NO_IRQ) && request_irq - (irq, eata2x_interrupt_handler, SA_INTERRUPT, driver_name, NULL))) { + if ((irq >= MAX_IRQ) || (!irqlist[irq] && request_irq(irq, + eata2x_interrupt_handler, SA_INTERRUPT, driver_name, NULL))) { printk("%s: unable to allocate IRQ %u, detaching.\n", name, irq); return FALSE; } @@ -499,7 +562,7 @@ config.len = (ushort) htons((ushort)510); config.ocena = TRUE; - if (do_dma(*port_base, (unsigned int)&config, SET_CONFIG_DMA)) { + if (do_dma(port_base, (unsigned int)&config, SET_CONFIG_DMA)) { printk("%s: busy timeout sending configuration, detaching.\n", name); return FALSE; } @@ -511,15 +574,15 @@ if (sh[j] == NULL) { printk("%s: unable to register host, detaching.\n", name); - if (irqlist[irq] == NO_IRQ) free_irq(irq, NULL); + if (!irqlist[irq]) free_irq(irq, NULL); if (subversion == ISA) free_dma(dma_channel); return FALSE; } - sh[j]->io_port = *port_base; - sh[j]->unique_id = *port_base; + sh[j]->io_port = port_base; + sh[j]->unique_id = port_base; sh[j]->n_io_port = REGION_SIZE; sh[j]->dma_channel = dma_channel; sh[j]->irq = irq; @@ -529,13 +592,13 @@ sh[j]->cmd_per_lun = MAX_CMD_PER_LUN; /* Register the I/O space that we use */ - request_region(sh[j]->io_port, REGION_SIZE, driver_name); + request_region(sh[j]->io_port, sh[j]->n_io_port, driver_name); memset(HD(j), 0, sizeof(struct hostdata)); HD(j)->subversion = subversion; HD(j)->protocol_rev = protocol_rev; HD(j)->board_number = j; - irqlist[irq] = j; + irqlist[irq]++; if (HD(j)->subversion == ESA) sh[j]->unchecked_isa_dma = FALSE; @@ -548,66 +611,138 @@ enable_dma(dma_channel); } - if (protocol_rev != 'A' && info.max_chan > 0 && info.max_chan < MAX_CHANNEL) - sh[j]->max_channel = info.max_chan; - - if (protocol_rev != 'A' && info.max_id > 7 && info.max_id < MAX_TARGET) - sh[j]->max_id = info.max_id + 1; - - if (protocol_rev == 'C' && info.max_lun > 7 && info.max_lun < MAX_LUN) - sh[j]->max_lun = info.max_lun + 1; - strcpy(BN(j), name); - printk("%s: rev. 2.0%c, PORT 0x%03x, IRQ %u, DMA %u, SG %d, "\ - "Mbox %d, CmdLun %d.\n", BN(j), HD(j)->protocol_rev, - sh[j]->io_port, sh[j]->irq, sh[j]->dma_channel, - sh[j]->sg_tablesize, sh[j]->can_queue, sh[j]->cmd_per_lun); - /* DPT PM2012 does not allow to detect sg_tablesize correctly */ if (sh[j]->sg_tablesize > MAX_SGLIST || sh[j]->sg_tablesize < 2) { - printk("%s: detect, forcing to use %d SG lists.\n", BN(j), MAX_SGLIST); + printk("%s: detect, wrong n. of SG lists %d, fixed.\n", + BN(j), sh[j]->sg_tablesize); sh[j]->sg_tablesize = MAX_SGLIST; } /* DPT PM2012 does not allow to detect can_queue correctly */ if (sh[j]->can_queue > MAX_MAILBOXES || sh[j]->can_queue < 2) { - printk("%s: detect, forcing to use %d Mbox.\n", BN(j), MAX_MAILBOXES); + printk("%s: detect, wrong n. of Mbox %d, fixed.\n", + BN(j), sh[j]->can_queue); sh[j]->can_queue = MAX_MAILBOXES; } + if (protocol_rev != 'A') { + + if (info.max_chan > 0 && info.max_chan < MAX_CHANNEL) + sh[j]->max_channel = info.max_chan; + + if (info.max_id > 7 && info.max_id < MAX_TARGET) + sh[j]->max_id = info.max_id + 1; + + if (info.large_sg && sh[j]->sg_tablesize == MAX_SGLIST) + sh[j]->sg_tablesize = MAX_LARGE_SGLIST; + } + + if (protocol_rev == 'C') { + + if (info.max_lun > 7 && info.max_lun < MAX_LUN) + sh[j]->max_lun = info.max_lun + 1; + } + + if (subversion == ESA && protocol_rev == 'C' && info.pci) bus_type = "PCI"; + else if (sh[j]->io_port > EISA_RANGE) bus_type = "PCI"; + else if (subversion == ESA) bus_type = "EISA"; + else bus_type = "ISA"; + + for (i = 0; i < sh[j]->can_queue; i++) + if (! ((&HD(j)->cp[i])->sglist = kmalloc( + sh[j]->sg_tablesize * sizeof(struct sg_list), + (sh[j]->unchecked_isa_dma ? GFP_DMA : 0) | GFP_ATOMIC))) { + printk("%s: kmalloc SGlist failed, mbox %d, detaching.\n", BN(j), i); + eata2x_release(sh[j]); + return FALSE; + } + + printk("%s: rev. 2.0%c, %s, PORT 0x%03x, IRQ %u, DMA %u, SG %d, "\ + "Mbox %d, CmdLun %d.\n", BN(j), HD(j)->protocol_rev, bus_type, + sh[j]->io_port, sh[j]->irq, sh[j]->dma_channel, + sh[j]->sg_tablesize, sh[j]->can_queue, sh[j]->cmd_per_lun); + if (sh[j]->max_id > 8 || sh[j]->max_lun > 8) printk("%s: wide SCSI support enabled, max_id %u, max_lun %u.\n", BN(j), sh[j]->max_id, sh[j]->max_lun); - for (c = 0; c <= sh[j]->max_channel; c++) + for (i = 0; i <= sh[j]->max_channel; i++) printk("%s: SCSI channel %u enabled, host target ID %u.\n", - BN(j), c, info.host_addr[3 - c]); + BN(j), i, info.host_addr[3 - i]); #if defined (DEBUG_DETECT) - if (protocol_rev != 'A') - printk("%s: EATA 2.0%c, isaena %u, forcaddr %u, max_id %u,"\ - " max_chan %u, max_lun %u.\n", name, protocol_rev, info.isaena, - info.forcaddr, info.max_id, info.max_chan, info.max_lun); - - printk("%s: Vers. 0x%x, SYNC 0x%x, sec. %u, infol %ld, cpl %ld spl %ld.\n", - name, info.version, info.sync, info.second, DEV2H(info.data_len), - DEV2H(info.cp_len), DEV2H(info.sp_len)); + printk("%s: Vers. 0x%x, ocs %u, tar %u, SYNC 0x%x, sec. %u, "\ + "infol %ld, cpl %ld spl %ld.\n", name, info.version, + info.ocsena, info.tarsup, info.sync, info.second, + DEV2H(info.data_len), DEV2H(info.cp_len), DEV2H(info.sp_len)); + + if (protocol_rev == 'B' || protocol_rev == 'C') + printk("%s: isaena %u, forcaddr %u, max_id %u, max_chan %u, "\ + "large_sg %u, res1 %u.\n", name, info.isaena, info.forcaddr, + info.max_id, info.max_chan, info.large_sg, info.res1); + + if (protocol_rev == 'C') + printk("%s: max_lun %u, pci %u, eisa %u.\n", name, + info.max_lun, info.pci, info.eisa); #endif return TRUE; } -int eata2x_detect(Scsi_Host_Template *tpnt) { - unsigned int j = 0, k, flags; +void eata2x_setup(char *str, int *ints) { + int i, argc = ints[0]; - unsigned int io_port[] = { - 0x1f0, 0x1c88, 0x2c88, 0x3c88, 0x4c88, 0x5c88, 0x6c88, 0x7c88, - 0x8c88, 0x9c88, 0xac88, 0xbc88, 0xcc88, 0xdc88, 0xec88, 0xfc88, - 0x170, 0x230, 0x330, 0x0 - }; + if (argc <= 0) return; - unsigned int *port_base = io_port; + if (argc > MAX_BOARDS) argc = MAX_BOARDS; + + for (i = 0; i < argc; i++) io_port[i] = ints[i + 1]; + + io_port[i] = 0; + setup_done = TRUE; + return; +} + +static void add_pci_ports(void) { + +#if defined(CONFIG_PCI) + + unsigned short i = 0; + unsigned char bus, devfn; + unsigned int addr, k; + + if (!pcibios_present()) return; + + for (k = 0; k < MAX_PCI; k++) { + + if (pcibios_find_class(PCI_CLASS_STORAGE_SCSI << 8, i++, &bus, &devfn) + != PCIBIOS_SUCCESSFUL) break; + + if (pcibios_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, &addr) + != PCIBIOS_SUCCESSFUL) continue; + +#if defined(DEBUG_DETECT) + printk("%s: detect, seq. %d, bus %d, devfn 0x%x, addr 0x%x.\n", + driver_name, k, bus, devfn, addr); +#endif + + if ((addr & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_IO) + continue; + + /* Reverse the returned address order */ + io_port[MAX_PCI - k] = + (addr & PCI_BASE_ADDRESS_IO_MASK) + PCI_BASE_ADDRESS_0; + } +#endif + + return; +} + +int eata2x_detect(Scsi_Host_Template *tpnt) { + unsigned long flags; + unsigned int j = 0, k; tpnt->proc_dir = &proc_scsi_eata2x; @@ -615,17 +750,19 @@ cli(); for (k = 0; k < MAX_IRQ; k++) { - irqlist[k] = NO_IRQ; + irqlist[k] = 0; calls[k] = 0; } for (k = 0; k < MAX_BOARDS + 1; k++) sh[k] = NULL; - while (*port_base) { + if (!setup_done) add_pci_ports(); - if (j < MAX_BOARDS && port_detect(port_base, j, tpnt)) j++; + for (k = 0; io_port[k]; k++) { - port_base++; + if (io_port[k] == SKIP) continue; + + if (j < MAX_BOARDS && port_detect(io_port[k], j, tpnt)) j++; } if (j > 0) @@ -651,7 +788,8 @@ } int eata2x_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { - unsigned int i, j, k, flags; + unsigned long flags; + unsigned int i, j, k; struct mscp *cpp; struct mssp *spp; @@ -702,7 +840,7 @@ /* Set pointer to control packet structure */ cpp = &HD(j)->cp[i]; - memset(cpp, 0, sizeof(struct mscp)); + memset(cpp, 0, sizeof(struct mscp) - sizeof(struct sg_list *)); /* Set pointer to status packet structure */ spp = &HD(j)->sp[i]; @@ -766,7 +904,8 @@ } int eata2x_abort(Scsi_Cmnd *SCarg) { - unsigned int i, j, flags; + unsigned long flags; + unsigned int i, j; save_flags(flags); cli(); @@ -805,6 +944,9 @@ panic("%s: abort, mbox %d, SCarg %p, cp SCpnt %p.\n", BN(j), i, SCarg, HD(j)->cp[i].SCpnt); + if (inb(sh[j]->io_port + REG_AUX_STATUS) & IRQ_ASSERTED) + printk("%s: abort, mbox %d, interrupt pending.\n", BN(j), i); + restore_flags(flags); return SCSI_ABORT_SNOOZE; } @@ -825,7 +967,8 @@ } int eata2x_reset(Scsi_Cmnd *SCarg, unsigned int reset_flags) { - unsigned int i, j, flags, time, k, c, limit = 0; + unsigned long flags; + unsigned int i, j, time, k, c, limit = 0; int arg_done = FALSE; Scsi_Cmnd *SCpnt; @@ -944,14 +1087,15 @@ static void eata2x_interrupt_handler(int irq, void *dev_id, struct pt_regs *regs) { Scsi_Cmnd *SCpnt; - unsigned int i, j, k, c, flags, status, tstatus, loops, total_loops = 0; + unsigned long flags; + unsigned int i, j, k, c, status, tstatus, loops, total_loops = 0; struct mssp *spp; struct mscp *cpp; save_flags(flags); cli(); - if (irqlist[irq] == NO_IRQ) { + if (!irqlist[irq]) { printk("%s, ihdlr, irq %d, unexpected interrupt.\n", driver_name, irq); restore_flags(flags); return; @@ -1158,6 +1302,31 @@ restore_flags(flags); return; +} + +int eata2x_release(struct Scsi_Host *shpnt) { + unsigned long flags; + unsigned int i, j; + + save_flags(flags); + cli(); + + for (j = 0; sh[j] != NULL && sh[j] != shpnt; j++); + + if (sh[j] == NULL) panic("%s: release, invalid Scsi_Host pointer.\n", + driver_name); + + for (i = 0; i < sh[j]->can_queue; i++) + if ((&HD(j)->cp[i])->sglist) kfree((&HD(j)->cp[i])->sglist); + + if (! --irqlist[sh[j]->irq]) free_irq(sh[j]->irq, NULL); + + if (sh[j]->dma_channel != NO_DMA) free_dma(sh[j]->dma_channel); + + release_region(sh[j]->io_port, sh[j]->n_io_port); + scsi_unregister(sh[j]); + restore_flags(flags); + return FALSE; } #if defined(MODULE) diff -u --recursive --new-file v2.0.26/linux/drivers/scsi/eata.h linux/drivers/scsi/eata.h --- v2.0.26/linux/drivers/scsi/eata.h Fri Nov 22 16:26:03 1996 +++ linux/drivers/scsi/eata.h Sat Nov 23 15:28:23 1996 @@ -7,11 +7,12 @@ #include int eata2x_detect(Scsi_Host_Template *); +int eata2x_release(struct Scsi_Host *); int eata2x_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); int eata2x_abort(Scsi_Cmnd *); int eata2x_reset(Scsi_Cmnd *, unsigned int); -#define EATA_VERSION "2.20.00" +#define EATA_VERSION "2.30.00" #define EATA { \ @@ -21,7 +22,7 @@ NULL, \ "EATA/DMA 2.0x rev. " EATA_VERSION " ", \ eata2x_detect, \ - NULL, /* Release */ \ + eata2x_release, \ NULL, \ NULL, \ eata2x_queuecommand, \ diff -u --recursive --new-file v2.0.26/linux/drivers/scsi/u14-34f.c linux/drivers/scsi/u14-34f.c --- v2.0.26/linux/drivers/scsi/u14-34f.c Fri Nov 22 16:26:04 1996 +++ linux/drivers/scsi/u14-34f.c Sat Nov 23 15:28:23 1996 @@ -1,6 +1,12 @@ /* * u14-34f.c - Low-level driver for UltraStor 14F/34F SCSI host adapters. * + * 21 Nov 1996 rev. 2.30 for linux 2.1.11 and 2.0.25 + * The list of i/o ports to be probed can be overwritten by the + * "u14-34f=port0, port1,...." boot command line option. + * Scatter/gather lists are now allocated by a number of kmalloc + * calls, in order to avoid the previous size limit of 64Kb. + * * 16 Nov 1996 rev. 2.20 for linux 2.1.10 and 2.0.25 * Added multichannel support. * @@ -74,6 +80,11 @@ * * Copyright (C) 1994, 1995, 1996 Dario Ballabio (dario@milano.europe.dg.com) * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that redistributions of source + * code retain the above copyright notice and this comment without + * modification. + * * WARNING: if your 14/34F board has an old firmware revision (see below) * you must change "#undef" into "#define" in the following * statement. @@ -149,6 +160,15 @@ * the latest firmware prom is 28008-006. Older firmware 28008-005 has * problems when using more then 16 scatter/gather lists. * + * The list of i/o ports to be probed can be totally replaced by the + * boot command line option: "u14-34f=port0, port1, port2,...", where the + * port0, port1... arguments are ISA/VESA addresses to be probed. + * For example using "u14-34f=0x230, 0x340", the driver probes only the two + * addresses 0x230 and 0x340 in this order; "u14-34f=0" totally disables + * this driver. + * + * The boards are named Ux4F0, Ux4F1,... according to the detection order. + * * In order to support multiple ISA boards in a reliable way, * the driver sets host->wish_block = TRUE for all ISA boards. */ @@ -205,11 +225,15 @@ #undef DEBUG_STATISTICS #undef DEBUG_RESET +#define MAX_ISA 3 +#define MAX_VESA 1 +#define MAX_EISA 0 +#define MAX_PCI 0 +#define MAX_BOARDS (MAX_ISA + MAX_VESA + MAX_EISA + MAX_PCI) #define MAX_CHANNEL 1 #define MAX_LUN 8 #define MAX_TARGET 8 #define MAX_IRQ 16 -#define MAX_BOARDS 4 #define MAX_MAILBOXES 16 #define MAX_SGLIST 32 #define MAX_SAFE_SGLIST 16 @@ -223,7 +247,6 @@ #define LOCKED 2 #define IN_RESET 3 #define IGNORE 4 -#define NO_IRQ 0xff #define NO_DMA 0xff #define MAXLOOP 200000 @@ -251,6 +274,11 @@ #define PACKED __attribute__((packed)) +struct sg_list { + unsigned int address; /* Segment Address */ + unsigned int num_bytes; /* Segment Length */ + }; + /* MailBox SCSI Command Packet */ struct mscp { unsigned char opcode: 3; /* type of command */ @@ -272,15 +300,9 @@ unsigned char adapter_status; /* non-zero indicates HA error */ unsigned char target_status; /* non-zero indicates target error */ unsigned int sense_addr PACKED; - Scsi_Cmnd *SCpnt; - - struct sg_list { - unsigned int address; /* Segment Address */ - unsigned int num_bytes; /* Segment Length */ - } sglist[MAX_SGLIST]; - - unsigned int index; /* cp index */ + unsigned int index; /* cp index */ + struct sg_list *sglist; }; struct hostdata { @@ -309,6 +331,13 @@ static const char *driver_name = "Ux4F"; static unsigned int irqlist[MAX_IRQ], calls[MAX_IRQ]; +static unsigned int io_port[] = { + 0x330, 0x340, 0x230, 0x240, 0x210, 0x130, 0x140, + + /* End of list */ + 0x0 + }; + #define HD(board) ((struct hostdata *) &sh[board]->hostdata) #define BN(board) (HD(board)->board_name) @@ -328,6 +357,7 @@ static void u14_34f_interrupt_handler(int, void *, struct pt_regs *); static int do_trace = FALSE; +static int setup_done = FALSE; static inline int wait_on_busy(unsigned int iobase) { unsigned int loop = MAXLOOP; @@ -381,9 +411,9 @@ return FALSE; } -static inline int port_detect(unsigned int *port_base, unsigned int j, - Scsi_Host_Template *tpnt) { - unsigned char irq, dma_channel, subversion, c; +static inline int port_detect(unsigned int port_base, unsigned int j, + Scsi_Host_Template *tpnt) { + unsigned char irq, dma_channel, subversion, i; unsigned char in_byte; /* Allowed BIOS base addresses (NULL indicates reserved) */ @@ -425,28 +455,27 @@ sprintf(name, "%s%d", driver_name, j); - if(check_region(*port_base, REGION_SIZE)) { - printk("%s: address 0x%03x in use, skipping probe.\n", - name, *port_base); + if(check_region(port_base, REGION_SIZE)) { + printk("%s: address 0x%03x in use, skipping probe.\n", name, port_base); return FALSE; } - if (inb(*port_base + REG_PRODUCT_ID1) != PRODUCT_ID1) return FALSE; + if (inb(port_base + REG_PRODUCT_ID1) != PRODUCT_ID1) return FALSE; - in_byte = inb(*port_base + REG_PRODUCT_ID2); + in_byte = inb(port_base + REG_PRODUCT_ID2); if ((in_byte & 0xf0) != PRODUCT_ID2) return FALSE; - *(char *)&config_1 = inb(*port_base + REG_CONFIG1); - *(char *)&config_2 = inb(*port_base + REG_CONFIG2); + *(char *)&config_1 = inb(port_base + REG_CONFIG1); + *(char *)&config_2 = inb(port_base + REG_CONFIG2); irq = interrupt_table[config_1.interrupt]; dma_channel = dma_channel_table[config_1.dma_channel]; subversion = (in_byte & 0x0f); /* Board detected, allocate its IRQ if not already done */ - if ((irq >= MAX_IRQ) || ((irqlist[irq] == NO_IRQ) && request_irq - (irq, u14_34f_interrupt_handler, SA_INTERRUPT, driver_name, NULL))) { + if ((irq >= MAX_IRQ) || (!irqlist[irq] && request_irq(irq, + u14_34f_interrupt_handler, SA_INTERRUPT, driver_name, NULL))) { printk("%s: unable to allocate IRQ %u, detaching.\n", name, irq); return FALSE; } @@ -463,15 +492,15 @@ if (sh[j] == NULL) { printk("%s: unable to register host, detaching.\n", name); - if (irqlist[irq] == NO_IRQ) free_irq(irq, NULL); + if (!irqlist[irq]) free_irq(irq, NULL); if (subversion == ISA) free_dma(dma_channel); return FALSE; } - sh[j]->io_port = *port_base; - sh[j]->unique_id = *port_base; + sh[j]->io_port = port_base; + sh[j]->unique_id = port_base; sh[j]->n_io_port = REGION_SIZE; sh[j]->base = bios_segment_table[config_1.bios_segment]; sh[j]->irq = irq; @@ -494,14 +523,14 @@ if (sh[j]->base == 0) outb(CMD_ENA_INTR, sh[j]->io_port + REG_SYS_MASK); /* Register the I/O space that we use */ - request_region(sh[j]->io_port, REGION_SIZE, driver_name); + request_region(sh[j]->io_port, sh[j]->n_io_port, driver_name); memset(HD(j), 0, sizeof(struct hostdata)); HD(j)->heads = mapping_table[config_2.mapping_mode].heads; HD(j)->sectors = mapping_table[config_2.mapping_mode].sectors; HD(j)->subversion = subversion; HD(j)->board_number = j; - irqlist[irq] = j; + irqlist[irq]++; if (HD(j)->subversion == ESA) { @@ -546,6 +575,15 @@ } } + for (i = 0; i < sh[j]->can_queue; i++) + if (! ((&HD(j)->cp[i])->sglist = kmalloc( + sh[j]->sg_tablesize * sizeof(struct sg_list), + (sh[j]->unchecked_isa_dma ? GFP_DMA : 0) | GFP_ATOMIC))) { + printk("%s: kmalloc SGlist failed, mbox %d, detaching.\n", BN(j), i); + u14_34f_release(sh[j]); + return FALSE; + } + printk("%s: PORT 0x%03x, BIOS 0x%05x, IRQ %u, DMA %u, SG %d, "\ "Mbox %d, CmdLun %d, C%d.\n", BN(j), sh[j]->io_port, (int)sh[j]->base, sh[j]->irq, sh[j]->dma_channel, @@ -556,21 +594,30 @@ printk("%s: wide SCSI support enabled, max_id %u, max_lun %u.\n", BN(j), sh[j]->max_id, sh[j]->max_lun); - for (c = 0; c <= sh[j]->max_channel; c++) + for (i = 0; i <= sh[j]->max_channel; i++) printk("%s: SCSI channel %u enabled, host target ID %u.\n", - BN(j), c, sh[j]->this_id); + BN(j), i, sh[j]->this_id); return TRUE; } -int u14_34f_detect(Scsi_Host_Template *tpnt) { - unsigned int j = 0, k, flags; +void u14_34f_setup(char *str, int *ints) { + int i, argc = ints[0]; - unsigned int io_port[] = { - 0x330, 0x340, 0x230, 0x240, 0x210, 0x130, 0x140, 0x0 - }; + if (argc <= 0) return; - unsigned int *port_base = io_port; + if (argc > MAX_BOARDS) argc = MAX_BOARDS; + + for (i = 0; i < argc; i++) io_port[i] = ints[i + 1]; + + io_port[i] = 0; + setup_done = TRUE; + return; +} + +int u14_34f_detect(Scsi_Host_Template *tpnt) { + unsigned long flags; + unsigned int j = 0, k; tpnt->proc_dir = &proc_scsi_u14_34f; @@ -578,18 +625,14 @@ cli(); for (k = 0; k < MAX_IRQ; k++) { - irqlist[k] = NO_IRQ; + irqlist[k] = 0; calls[k] = 0; } for (k = 0; k < MAX_BOARDS + 1; k++) sh[k] = NULL; - while (*port_base) { - - if (j < MAX_BOARDS && port_detect(port_base, j, tpnt)) j++; - - port_base++; - } + for (k = 0; io_port[k]; k++) + if (j < MAX_BOARDS && port_detect(io_port[k], j, tpnt)) j++; if (j > 0) printk("UltraStor 14F/34F: Copyright (C) 1994, 1995, 1996 Dario Ballabio.\n"); @@ -616,7 +659,8 @@ } int u14_34f_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { - unsigned int i, j, k, flags; + unsigned long flags; + unsigned int i, j, k; struct mscp *cpp; static const unsigned char data_out_cmds[] = { @@ -666,7 +710,7 @@ /* Set pointer to control packet structure */ cpp = &HD(j)->cp[i]; - memset(cpp, 0, sizeof(struct mscp)); + memset(cpp, 0, sizeof(struct mscp) - sizeof(struct sg_list *)); SCpnt->scsi_done = done; cpp->index = i; SCpnt->host_scribble = (unsigned char *) &cpp->index; @@ -726,7 +770,8 @@ } int u14_34f_abort(Scsi_Cmnd *SCarg) { - unsigned int i, j, flags; + unsigned long flags; + unsigned int i, j; save_flags(flags); cli(); @@ -765,6 +810,9 @@ panic("%s: abort, mbox %d, SCarg %p, cp SCpnt %p.\n", BN(j), i, SCarg, HD(j)->cp[i].SCpnt); + if (inb(sh[j]->io_port + REG_SYS_INTR) & IRQ_ASSERTED) + printk("%s: abort, mbox %d, interrupt pending.\n", BN(j), i); + restore_flags(flags); return SCSI_ABORT_SNOOZE; } @@ -785,7 +833,8 @@ } int u14_34f_reset(Scsi_Cmnd *SCarg, unsigned int reset_flags) { - unsigned int i, j, flags, time, k, c, limit = 0; + unsigned long flags; + unsigned int i, j, time, k, c, limit = 0; int arg_done = FALSE; Scsi_Cmnd *SCpnt; @@ -909,19 +958,20 @@ dkinfo[0] = HD(j)->heads; dkinfo[1] = HD(j)->sectors; dkinfo[2] = size / (HD(j)->heads * HD(j)->sectors); - return 0; + return FALSE; } static void u14_34f_interrupt_handler(int irq, void *dev_id, struct pt_regs *regs) { Scsi_Cmnd *SCpnt; - unsigned int i, j, k, c, flags, status, tstatus, loops, total_loops = 0; + unsigned long flags; + unsigned int i, j, k, c, status, tstatus, loops, total_loops = 0; struct mscp *spp; save_flags(flags); cli(); - if (irqlist[irq] == NO_IRQ) { + if (!irqlist[irq]) { printk("%s, ihdlr, irq %d, unexpected interrupt.\n", driver_name, irq); restore_flags(flags); return; @@ -1122,6 +1172,31 @@ restore_flags(flags); return; +} + +int u14_34f_release(struct Scsi_Host *shpnt) { + unsigned long flags; + unsigned int i, j; + + save_flags(flags); + cli(); + + for (j = 0; sh[j] != NULL && sh[j] != shpnt; j++); + + if (sh[j] == NULL) panic("%s: release, invalid Scsi_Host pointer.\n", + driver_name); + + for (i = 0; i < sh[j]->can_queue; i++) + if ((&HD(j)->cp[i])->sglist) kfree((&HD(j)->cp[i])->sglist); + + if (! --irqlist[sh[j]->irq]) free_irq(sh[j]->irq, NULL); + + if (sh[j]->dma_channel != NO_DMA) free_dma(sh[j]->dma_channel); + + release_region(sh[j]->io_port, sh[j]->n_io_port); + scsi_unregister(sh[j]); + restore_flags(flags); + return FALSE; } #if defined(MODULE) diff -u --recursive --new-file v2.0.26/linux/drivers/scsi/u14-34f.h linux/drivers/scsi/u14-34f.h --- v2.0.26/linux/drivers/scsi/u14-34f.h Fri Nov 22 16:26:05 1996 +++ linux/drivers/scsi/u14-34f.h Sat Nov 23 15:28:23 1996 @@ -5,12 +5,13 @@ #define _U14_34F_H int u14_34f_detect(Scsi_Host_Template *); +int u14_34f_release(struct Scsi_Host *); int u14_34f_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); int u14_34f_abort(Scsi_Cmnd *); int u14_34f_reset(Scsi_Cmnd *, unsigned int); int u14_34f_biosparam(Disk *, kdev_t, int *); -#define U14_34F_VERSION "2.20.00" +#define U14_34F_VERSION "2.30.00" #define ULTRASTOR_14_34F { \ NULL, /* Ptr for modules */ \ @@ -19,7 +20,7 @@ NULL, \ "UltraStor 14F/34F rev. " U14_34F_VERSION " ", \ u14_34f_detect, \ - NULL, /* Release */ \ + u14_34f_release, \ NULL, \ NULL, \ u14_34f_queuecommand, \ diff -u --recursive --new-file v2.0.26/linux/fs/Config.in linux/fs/Config.in --- v2.0.26/linux/fs/Config.in Wed Jun 5 13:24:45 1996 +++ linux/fs/Config.in Sun Dec 1 15:58:05 1996 @@ -28,8 +28,8 @@ fi fi tristate 'SMB filesystem support (to mount WfW shares etc..)' CONFIG_SMB_FS - if [ "$CONFIG_SMB_FS" != "n" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then - bool 'SMB long filename support (EXPERIMENTAL)' CONFIG_SMB_LONG + if [ "$CONFIG_SMB_FS" != "n" ]; then + bool 'SMB Win95 bug work-around' CONFIG_SMB_WIN95 fi fi if [ "$CONFIG_IPX" != "n" ]; then diff -u --recursive --new-file v2.0.26/linux/fs/fat/inode.c linux/fs/fat/inode.c --- v2.0.26/linux/fs/fat/inode.c Mon Aug 5 10:13:54 1996 +++ linux/fs/fat/inode.c Sat Nov 30 12:27:38 1996 @@ -48,13 +48,12 @@ } inode->i_size = 0; fat_truncate(inode); - clear_inode(inode); if (depend) { if (MSDOS_I(depend)->i_old != inode) { printk("Invalid link (0x%p): expected 0x%p, got 0x%p\n", depend, inode, MSDOS_I(depend)->i_old); fat_fs_panic(sb,"..."); - return; + goto done; } MSDOS_I(depend)->i_old = NULL; iput(depend); @@ -64,11 +63,13 @@ printk("Invalid link (0x%p): expected 0x%p, got 0x%p\n", linked, inode, MSDOS_I(linked)->i_oldlink); fat_fs_panic(sb,"..."); - return; + goto done; } MSDOS_I(linked)->i_oldlink = NULL; iput(linked); } +done: + clear_inode(inode); } diff -u --recursive --new-file v2.0.26/linux/fs/smbfs/dir.c linux/fs/smbfs/dir.c --- v2.0.26/linux/fs/smbfs/dir.c Wed Sep 11 17:57:16 1996 +++ linux/fs/smbfs/dir.c Sun Dec 1 15:58:05 1996 @@ -1,7 +1,7 @@ /* * dir.c * - * Copyright (C) 1995 by Paal-Kr. Engstad and Volker Lendecke + * Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke * */ @@ -12,98 +12,69 @@ #include #include #include +#include #include +#include #include -#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de))) -#define ROUND_UP(x) (((x)+3) & ~3) - -static int -smb_dir_read(struct inode *inode, struct file *filp, char *buf, int count); - -static int -smb_readdir(struct inode *inode, struct file *filp, - void *dirent, filldir_t filldir); - -static int -get_pname(struct inode *dir, const char *name, int len, - char **res_path, int *res_len); - static int -get_pname_static(struct inode *dir, const char *name, int len, - char *path, int *res_len); + smb_dir_read(struct inode *inode, struct file *filp, char *buf, int count); -static void -put_pname(char *path); +static int + smb_readdir(struct inode *inode, struct file *filp, + void *dirent, filldir_t filldir); static struct smb_inode_info * -smb_find_inode(struct smb_server *server, const char *path); + smb_find_dir_inode(struct inode *parent, const char *name, int len); static int -smb_lookup(struct inode *dir, const char *__name, - int len, struct inode **result); + smb_lookup(struct inode *dir, const char *__name, + int len, struct inode **result); -static int -smb_create(struct inode *dir, const char *name, int len, int mode, - struct inode **result); - -static int -smb_mkdir(struct inode *dir, const char *name, int len, int mode); +static int + smb_create(struct inode *dir, const char *name, int len, int mode, + struct inode **result); -static int -smb_rmdir(struct inode *dir, const char *name, int len); +static int + smb_mkdir(struct inode *dir, const char *name, int len, int mode); static int -smb_unlink(struct inode *dir, const char *name, int len); + smb_rmdir(struct inode *dir, const char *name, int len); static int -smb_rename(struct inode *old_dir, const char *old_name, int old_len, - struct inode *new_dir, const char *new_name, int new_len, - int must_be_dir); + smb_unlink(struct inode *dir, const char *name, int len); -static inline void str_upper(char *name) -{ - while (*name) { - if (*name >= 'a' && *name <= 'z') - *name -= ('a' - 'A'); - name++; - } -} +static int + smb_rename(struct inode *old_dir, const char *old_name, int old_len, + struct inode *new_dir, const char *new_name, int new_len, + int must_be_dir); -static inline void str_lower(char *name) +static struct file_operations smb_dir_operations = { - while (*name) { - if (*name >= 'A' && *name <= 'Z') - *name += ('a' - 'A'); - name ++; - } -} - -static struct file_operations smb_dir_operations = { - NULL, /* lseek - default */ + NULL, /* lseek - default */ smb_dir_read, /* read - bad */ NULL, /* write - bad */ smb_readdir, /* readdir */ NULL, /* select - default */ smb_ioctl, /* ioctl - default */ - NULL, /* mmap */ + NULL, /* mmap */ NULL, /* no special open code */ NULL, /* no special release code */ NULL /* fsync */ }; -struct inode_operations smb_dir_inode_operations = +struct inode_operations smb_dir_inode_operations = { &smb_dir_operations, /* default directory file ops */ smb_create, /* create */ - smb_lookup, /* lookup */ + smb_lookup, /* lookup */ NULL, /* link */ - smb_unlink, /* unlink */ + smb_unlink, /* unlink */ NULL, /* symlink */ - smb_mkdir, /* mkdir */ - smb_rmdir, /* rmdir */ + smb_mkdir, /* mkdir */ + smb_rmdir, /* rmdir */ NULL, /* mknod */ - smb_rename, /* rename */ + smb_rename, /* rename */ NULL, /* readlink */ NULL, /* follow_link */ NULL, /* readpage */ @@ -111,336 +82,301 @@ NULL, /* bmap */ NULL, /* truncate */ NULL, /* permission */ - NULL /* smap */ + NULL /* smap */ }; - -static int -smb_dir_read(struct inode *inode, struct file *filp, char *buf, int count) +static int +strncasecmp(const char *s1, const char *s2, int len) { - return -EISDIR; -} + int result = 0; -/* - * Description: - * smb_readdir provides a listing in the form of filling the dirent structure. - * Note that dirent resides in the user space. This is to support reading of a - * directory "stream". - * Notes: - * Since we want to reduce directory lookups we revert into a - * dircache. It is taken rather directly out of the nfs_readdir. - */ + for (; len > 0; len -= 1) + { + char c1, c2; -/* In smbfs, we have unique inodes across all mounted filesystems, for - all inodes that are in memory. That's why it's enough to index the - directory cache by the inode number. */ - -static unsigned long c_ino = 0; -static int c_size; -static int c_seen_eof; -static int c_last_returned_index; -static struct smb_dirent* c_entry = NULL; + c1 = (*s1 >= 'a' && *s1 <= 'z') ? *s1 - ('a' - 'A') : *s1; + c2 = (*s2 >= 'a' && *s2 <= 'z') ? *s2 - ('a' - 'A') : *s2; + s1 += 1; + s2 += 1; + + if ((result = c1 - c2) != 0 || c1 == 0) + { + return result; + } + } + return result; +} static int -smb_readdir(struct inode *inode, struct file *filp, - void *dirent, filldir_t filldir) +compare_filename(const struct smb_server *server, + const char *s1, int len, struct smb_dirent *entry) { - int result, i = 0; - int index = 0; - struct smb_dirent *entry = NULL; - struct smb_server *server = SMB_SERVER(inode); - - DDPRINTK("smb_readdir: filp->f_pos = %d\n", (int)filp->f_pos); - DDPRINTK("smb_readdir: inode->i_ino = %ld, c_ino = %ld\n", - inode->i_ino, c_ino); - - if (!inode || !S_ISDIR(inode->i_mode)) { - printk("smb_readdir: inode is NULL or not a directory\n"); - return -EBADF; + if (len != entry->len) + { + return 1; } + if (server->case_handling == CASE_DEFAULT) + { + return strncasecmp(s1, entry->name, len); + } + return strncmp(s1, entry->name, len); +} + +struct smb_inode_info * +smb_find_inode(struct smb_server *server, ino_t ino) +{ + struct smb_inode_info *root = &(server->root); + struct smb_inode_info *this = root; - if (c_entry == NULL) + do { - i = sizeof (struct smb_dirent) * SMB_READDIR_CACHE_SIZE; - c_entry = (struct smb_dirent *) smb_kmalloc(i, GFP_KERNEL); - if (c_entry == NULL) { - printk("smb_readdir: no MEMORY for cache\n"); - return -ENOMEM; - } - for (i = 0; i < SMB_READDIR_CACHE_SIZE; i++) { - c_entry[i].path = - (char *) smb_kmalloc(SMB_MAXNAMELEN + 1, - GFP_KERNEL); - if (c_entry[i].path == NULL) { - DPRINTK("smb_readdir: could not alloc path\n"); - while (--i>=0) - kfree(c_entry[i].path); - kfree(c_entry); - c_entry = NULL; - return -ENOMEM; - } - } - } - - if (filp->f_pos == 0) { - smb_invalid_dir_cache(inode->i_ino); - } - - if (inode->i_ino == c_ino) { - for (i = 0; i < c_size; i++) { - if (filp->f_pos == c_entry[i].f_pos) { - entry = &c_entry[i]; - c_last_returned_index = i; - index = i; - break; - } + if (ino == smb_info_ino(this)) + { + return this; } - if ((entry == NULL) && c_seen_eof) - return 0; + this = this->next; } + while (this != root); - if (entry == NULL) { - DPRINTK("smb_readdir: Not found in cache.\n"); - result = smb_proc_readdir(server, inode, - filp->f_pos, SMB_READDIR_CACHE_SIZE, - c_entry); + return NULL; +} - if (result < 0) { - c_ino = 0; - return result; - } +static ino_t +smb_fresh_inodes(struct smb_server *server, int no) +{ + static ino_t seed = 1; + struct smb_inode_info *root = &(server->root); + struct smb_inode_info *this; - if (result > 0) { - c_seen_eof = (result < SMB_READDIR_CACHE_SIZE); - c_ino = inode->i_ino; - c_size = result; - entry = c_entry; - c_last_returned_index = 0; - index = 0; - for (i = 0; i < c_size; i++) { - - switch (server->case_handling) - { - case CASE_UPPER: - str_upper(c_entry[i].path); break; - case CASE_LOWER: - str_lower(c_entry[i].path); break; - case CASE_DEFAULT: - break; - } - } + retry: + if (seed + no <= no) + { + /* avoid inode number of 0 at wrap-around */ + seed += no; + } + this = root; + do + { + /* We assume that ino_t is unsigned! */ + if (this->finfo.f_ino - seed < no) + { + seed += no; + goto retry; } + this = this->next; } + while (this != root); - if (entry == NULL) { - /* Nothing found, even from a smb call */ - return 0; - } - - while (index < c_size) { - - /* We found it. For getwd(), we have to return the - correct inode in d_ino if the inode is currently in - use. Otherwise the inode number does not - matter. (You can argue a lot about this..) */ - - int path_len; - int len; - struct smb_inode_info *ino_info; - char complete_path[SMB_MAXPATHLEN]; - - len = strlen(entry->path); - if ((result = get_pname_static(inode, entry->path, len, - complete_path, - &path_len)) < 0) - return result; - - ino_info = smb_find_inode(server, complete_path); - - /* Some programs seem to be confused about a zero - inode number, so we set it to one. Thanks to - Gordon Chaffee for this one. */ - if (ino_info == NULL) { - ino_info = (struct smb_inode_info *) 1; - } - - DDPRINTK("smb_readdir: entry->path = %s\n", entry->path); - DDPRINTK("smb_readdir: entry->f_pos = %ld\n", entry->f_pos); + seed += no; - if (filldir(dirent, entry->path, len, - entry->f_pos, (ino_t)ino_info) < 0) { - break; - } - - if ( (inode->i_ino != c_ino) - || (entry->f_pos != filp->f_pos)) { - /* Someone has destroyed the cache while we slept - in filldir */ - break; - } - filp->f_pos += 1; - index += 1; - entry += 1; - } - return 0; + return seed - no; } -void -smb_init_dir_cache(void) +static int +smb_dir_read(struct inode *inode, struct file *filp, char *buf, int count) { - c_ino = 0; - c_entry = NULL; + return -EISDIR; } -void -smb_invalid_dir_cache(unsigned long ino) + +static unsigned long c_ino = 0; +static kdev_t c_dev; +static int c_size; +static int c_seen_eof; +static int c_last_returned_index; +static struct smb_dirent *c_entry = NULL; + +static struct smb_dirent * +smb_search_in_cache(struct inode *dir, unsigned long f_pos) { - if (ino == c_ino) { - c_ino = 0; - c_seen_eof = 0; - } + int i; + + if ((dir->i_dev != c_dev) || (dir->i_ino != c_ino)) + { + return NULL; + } + for (i = 0; i < c_size; i++) + { + if (f_pos == c_entry[i].f_pos) + { + c_last_returned_index = i; + return &(c_entry[i]); + } + } + return NULL; } -void -smb_free_dir_cache(void) +static int +smb_refill_dir_cache(struct smb_server *server, struct inode *dir, + unsigned long f_pos) { - int i; + int result; + static struct semaphore sem = MUTEX; + int i; + ino_t ino; - DPRINTK("smb_free_dir_cache: enter\n"); - - if (c_entry == NULL) - return; + do + { + down(&sem); + result = smb_proc_readdir(server, dir, f_pos, + SMB_READDIR_CACHE_SIZE, c_entry); - for (i = 0; i < SMB_READDIR_CACHE_SIZE; i++) { - smb_kfree_s(c_entry[i].path, NAME_MAX + 1); - } + if (result <= 0) + { + smb_invalid_dir_cache(dir->i_ino); + up(&sem); + return result; + } + c_seen_eof = (result < SMB_READDIR_CACHE_SIZE); + c_dev = dir->i_dev; + c_ino = dir->i_ino; + c_size = result; + c_last_returned_index = 0; - smb_kfree_s(c_entry, - sizeof(struct smb_dirent) * SMB_READDIR_CACHE_SIZE); - c_entry = NULL; + ino = smb_fresh_inodes(server, c_size); + for (i = 0; i < c_size; i++) + { + c_entry[i].f_ino = ino; + ino += 1; + } - DPRINTK("smb_free_dir_cache: exit\n"); -} + up(&sem); + } + while ((c_dev != dir->i_dev) || (c_ino != dir->i_ino)); -/* get_pname_static: it expects the res_path to be a preallocated - string of len SMB_MAXPATHLEN. */ + return result; +} static int -get_pname_static(struct inode *dir, const char *name, int len, - char *path, int *res_len) +smb_readdir(struct inode *dir, struct file *filp, + void *dirent, filldir_t filldir) { - char *parentname = SMB_INOP(dir)->finfo.path; - int parentlen = SMB_INOP(dir)->finfo.len; - -#if 1 - if (parentlen != strlen(parentname)) { - printk("get_pname: parent->finfo.len = %d instead of %d\n", - parentlen, strlen(parentname)); - parentlen = strlen(parentname); - } - -#endif - DDPRINTK("get_pname_static: parentname = %s, len = %d\n", - parentname, parentlen); - - if (len > SMB_MAXNAMELEN) { - return -ENAMETOOLONG; - } + int result, i = 0; + struct smb_dirent *entry = NULL; + struct smb_server *server = SMB_SERVER(dir); - /* Fast cheat for . */ - if (len == 0 || (len == 1 && name[0] == '.')) { + DPRINTK("smb_readdir: filp->f_pos = %d\n", (int) filp->f_pos); + DDPRINTK("smb_readdir: dir->i_ino = %ld, c_ino = %ld\n", + dir->i_ino, c_ino); - memcpy(path, parentname, parentlen + 1); - *res_len = parentlen; - return 0; + if ((dir == NULL) || !S_ISDIR(dir->i_mode)) + { + printk("smb_readdir: dir is NULL or not a directory\n"); + return -EBADF; + } + if (c_entry == NULL) + { + i = sizeof(struct smb_dirent) * SMB_READDIR_CACHE_SIZE; + c_entry = (struct smb_dirent *) smb_vmalloc(i); + if (c_entry == NULL) + { + printk("smb_readdir: no MEMORY for cache\n"); + return -ENOMEM; + } } - - /* Hmm, what about .. ? */ - if (len == 2 && name[0] == '.' && name[1] == '.') { - - char *pos = strrchr(parentname, '\\'); - - if ( (pos == NULL) - && (parentlen == 0)) { - - /* We're at the top */ - - path[0] = '\\'; - path[1] = '\0'; - *res_len = 2; - return 0; - } - - - if (pos == NULL) { - printk("smb_make_name: Bad parent SMB-name: %s", - parentname); - return -ENODATA; - } - - len = pos - parentname; + if (filp->f_pos == 0) + { + c_ino = 0; + c_dev = 0; + c_seen_eof = 0; - memcpy(path, parentname, len); - path[len] = '\0'; + if (filldir(dirent, ".", 1, filp->f_pos, + smb_info_ino(SMB_INOP(dir))) < 0) + { + return 0; + } + filp->f_pos += 1; } - else + if (filp->f_pos == 1) { - if (len + parentlen + 2 > SMB_MAXPATHLEN) - return -ENAMETOOLONG; - - memcpy(path, parentname, parentlen); - path[parentlen] = '\\'; - memcpy(path + parentlen + 1, name, len); - path[parentlen + 1 + len] = '\0'; - len = parentlen + len + 1; - } - - switch (SMB_SERVER(dir)->case_handling) - { - case CASE_UPPER: - str_upper(path); - break; - case CASE_LOWER: - str_lower(path); - break; - case CASE_DEFAULT: - break; + if (filldir(dirent, "..", 2, filp->f_pos, + smb_info_ino(SMB_INOP(dir)->dir)) < 0) + { + return 0; + } + filp->f_pos += 1; } + entry = smb_search_in_cache(dir, filp->f_pos); - *res_len = len; + if (entry == NULL) + { + if (c_seen_eof) + { + /* End of directory */ + return 0; + } + result = smb_refill_dir_cache(server, dir, filp->f_pos); + if (result <= 0) + { + return result; + } + entry = c_entry; + } + while (entry < &(c_entry[c_size])) + { + /* We found it. For getwd(), we have to return the + correct inode in d_ino if the inode is currently in + use. Otherwise the inode number does not + matter. (You can argue a lot about this..) */ - DDPRINTK("get_pname: path = %s, *pathlen = %d\n", - path, *res_len); + struct smb_inode_info *ino_info + = smb_find_dir_inode(dir, entry->name, entry->len); + + ino_t ino = entry->f_ino; + + if (ino_info != NULL) + { + ino = smb_info_ino(ino_info); + } + DDPRINTK("smb_readdir: entry->name = %s\n", entry->name); + DDPRINTK("smb_readdir: entry->f_pos = %ld\n", entry->f_pos); + + if (filldir(dirent, entry->name, strlen(entry->name), + entry->f_pos, ino) < 0) + { + break; + } + if ((dir->i_dev != c_dev) || (dir->i_ino != c_ino) + || (entry->f_pos != filp->f_pos)) + { + /* Someone has destroyed the cache while we slept + in filldir */ + break; + } + filp->f_pos += 1; + entry += 1; + } return 0; } - -static int -get_pname(struct inode *dir, const char *name, int len, - char **res_path, int *res_len) -{ - char result[SMB_MAXPATHLEN]; - int result_len; - int res; - if ((res = get_pname_static(dir,name,len,result,&result_len) != 0)) { - return res; - } - - if ((*res_path = smb_kmalloc(result_len+1, GFP_KERNEL)) == NULL) { - printk("get_pname: Out of memory while allocating name."); - return -ENOMEM; - } +void +smb_init_dir_cache(void) +{ + c_ino = 0; + c_dev = 0; + c_entry = NULL; +} - strcpy(*res_path, result); - *res_len = result_len; - return 0; +void +smb_invalid_dir_cache(unsigned long ino) +{ + /* TODO: check for dev as well */ + if (ino == c_ino) + { + c_ino = 0; + c_seen_eof = 0; + } } -static void -put_pname(char *path) +void +smb_free_dir_cache(void) { - smb_kfree_s(path, 0); + if (c_entry != NULL) + { + smb_vfree(c_entry); + } + c_entry = NULL; } /* Insert a NEW smb_inode_info into the inode tree of our filesystem, @@ -448,45 +384,35 @@ assume that path is allocated for us. */ static struct inode * -smb_iget(struct inode *dir, char *path, struct smb_dirent *finfo, - struct smb_inode_info *new_inode_info) +smb_iget(struct inode *dir, struct smb_inode_info *new_inode_info) { struct inode *inode; - int len; - struct smb_inode_info *root; + struct smb_inode_info *root; - if ( (dir == NULL) || (path == NULL) || (finfo == NULL) - || (new_inode_info == NULL)) + if ((dir == NULL) || (new_inode_info == NULL)) { printk("smb_iget: parameter is NULL\n"); return NULL; } + new_inode_info->state = SMB_INODE_LOOKED_UP; + new_inode_info->nused = 0; + new_inode_info->dir = SMB_INOP(dir); + + SMB_INOP(dir)->nused += 1; + + /* We have to link the new inode_info into the doubly linked + list of inode_infos to make a complete linear search + possible. */ + + root = &(SMB_SERVER(dir)->root); - len = strlen(path); + new_inode_info->prev = root; + new_inode_info->next = root->next; + root->next->prev = new_inode_info; + root->next = new_inode_info; - new_inode_info->state = SMB_INODE_LOOKED_UP; - new_inode_info->nused = 0; - new_inode_info->dir = SMB_INOP(dir); - - new_inode_info->finfo = *finfo; - new_inode_info->finfo.opened = 0; - new_inode_info->finfo.path = path; - new_inode_info->finfo.len = len; - - SMB_INOP(dir)->nused += 1; - - /* We have to link the new inode_info into the doubly linked - list of inode_infos to make a complete linear search - possible. */ - - root = &(SMB_SERVER(dir)->root); - - new_inode_info->prev = root; - new_inode_info->next = root->next; - root->next->prev = new_inode_info; - root->next = new_inode_info; - - if (!(inode = iget(dir->i_sb, (int)new_inode_info))) { + if (!(inode = iget(dir->i_sb, smb_info_ino(new_inode_info)))) + { new_inode_info->next->prev = new_inode_info->prev; new_inode_info->prev->next = new_inode_info->next; SMB_INOP(dir)->nused -= 1; @@ -494,337 +420,327 @@ printk("smb_iget: iget failed!"); return NULL; } - return inode; } void smb_free_inode_info(struct smb_inode_info *i) { - if (i == NULL) { - printk("smb_free_inode: i == NULL\n"); - return; - } - - i->state = SMB_INODE_CACHED; - while ((i->nused == 0) && (i->state == SMB_INODE_CACHED)) { - struct smb_inode_info *dir = i->dir; - - i->next->prev = i->prev; - i->prev->next = i->next; + if (i == NULL) + { + printk("smb_free_inode: i == NULL\n"); + return; + } + i->state = SMB_INODE_CACHED; + while ((i->nused == 0) && (i->state == SMB_INODE_CACHED)) + { + struct smb_inode_info *dir = i->dir; - smb_kfree_s(i->finfo.path, i->finfo.len+1); - smb_kfree_s(i, sizeof(struct smb_inode_info)); + i->next->prev = i->prev; + i->prev->next = i->next; - if (dir == NULL) return; + smb_kfree_s(i, sizeof(struct smb_inode_info)); - (dir->nused)--; - i = dir; - } + if (dir == NULL) + { + return; + } + dir->nused -= 1; + i = dir; + } } - + void smb_init_root(struct smb_server *server) { - struct smb_inode_info *root = &(server->root); + struct smb_inode_info *root = &(server->root); - root->finfo.path = server->m.root_path; - root->finfo.len = strlen(root->finfo.path); - root->finfo.opened = 0; - - root->state = SMB_INODE_LOOKED_UP; - root->nused = 1; - root->dir = NULL; - root->next = root->prev = root; - return; -} - -int -smb_stat_root(struct smb_server *server) -{ - struct smb_inode_info *root = &(server->root); - int result; - - if (root->finfo.len == 0) { - result = smb_proc_getattr(server, "\\", 1, &(root->finfo)); - } - else - { - result = smb_proc_getattr(server, - root->finfo.path, root->finfo.len, - &(root->finfo)); - } - return result; + root->state = SMB_INODE_LOOKED_UP; + root->nused = 1; + root->dir = NULL; + root->next = root->prev = root; + + return; } void smb_free_all_inodes(struct smb_server *server) { - /* Here nothing should be to do. I do not know whether it's - better to leave some memory allocated or be stuck in an - endless loop */ + /* Here nothing should be to do. I do not know whether it's + better to leave some memory allocated or be stuck in an + endless loop */ #if 1 - struct smb_inode_info *root = &(server->root); + struct smb_inode_info *root = &(server->root); - if (root->next != root) { - printk("smb_free_all_inodes: INODES LEFT!!!\n"); - } - - while (root->next != root) { - printk("smb_free_all_inodes: freeing inode\n"); - smb_free_inode_info(root->next); - /* In case we have an endless loop.. */ - schedule(); - } -#endif - - return; + if (root->next != root) + { + printk("smb_free_all_inodes: INODES LEFT!!!\n"); + } + while (root->next != root) + { + printk("smb_free_all_inodes: freeing inode\n"); + smb_free_inode_info(root->next); + /* In case we have an endless loop.. */ + schedule(); + } +#endif + + return; } /* This has to be called when a connection has gone down, so that all file-handles we got from the server are invalid */ - void smb_invalidate_all_inodes(struct smb_server *server) { - struct smb_inode_info *ino = &(server->root); + struct smb_inode_info *ino = &(server->root); + + do + { + ino->finfo.opened = 0; + ino = ino->next; + } + while (ino != &(server->root)); - do { - ino->finfo.opened = 0; - ino = ino->next; - } while (ino != &(server->root)); - - return; + return; } - /* We will search the inode that belongs to this name, currently by a complete linear search through the inodes belonging to this filesystem. This has to be fixed. */ - static struct smb_inode_info * -smb_find_inode(struct smb_server *server, const char *path) +smb_find_dir_inode(struct inode *parent, const char *name, int len) { - struct smb_inode_info *result = &(server->root); - - if (path == NULL) - return NULL; - - do { - if (strcmp(result->finfo.path, path) == 0) - return result; - result = result->next; + struct smb_server *server = SMB_SERVER(parent); + struct smb_inode_info *dir = SMB_INOP(parent); + struct smb_inode_info *result = &(server->root); - } while (result != &(server->root)); + if (name == NULL) + { + return NULL; + } + if ((len == 1) && (name[0] == '.')) + { + return dir; + } + if ((len == 2) && (name[0] == '.') && (name[1] == '.')) + { + return dir->dir; + } + do + { + if (result->dir == dir) + { + if (compare_filename(server, name, len, + &(result->finfo)) == 0) + { + return result; + } + } + result = result->next; + } + while (result != &(server->root)); - return NULL; + return NULL; } - -static int -smb_lookup(struct inode *dir, const char *__name, int len, - struct inode **result) +static int +smb_lookup(struct inode *dir, const char *name, int len, + struct inode **result) { - char *name = NULL; struct smb_dirent finfo; - struct smb_inode_info *result_info; + struct smb_inode_info *result_info; int error; - int found_in_cache; + int found_in_cache; struct smb_inode_info *new_inode_info = NULL; *result = NULL; - if (!dir || !S_ISDIR(dir->i_mode)) { + if (!dir || !S_ISDIR(dir->i_mode)) + { printk("smb_lookup: inode is NULL or not a directory.\n"); iput(dir); return -ENOENT; } - - DDPRINTK("smb_lookup: %s\n", __name); + DDPRINTK("smb_lookup: %s\n", name); /* Fast cheat for . */ - if (len == 0 || (len == 1 && __name[0] == '.')) { + if (len == 0 || (len == 1 && name[0] == '.')) + { *result = dir; return 0; } + /* ..and for .. */ + if (len == 2 && name[0] == '.' && name[1] == '.') + { + struct smb_inode_info *parent = SMB_INOP(dir)->dir; - /* Now we will have to build up an SMB filename. */ - if ((error = get_pname(dir, __name, len, &name, &len)) < 0) { + if (parent->state == SMB_INODE_CACHED) + { + parent->state = SMB_INODE_LOOKED_UP; + } + *result = iget(dir->i_sb, smb_info_ino(parent)); iput(dir); - return error; + if (*result == 0) + { + return -EACCES; + } + return 0; } + result_info = smb_find_dir_inode(dir, name, len); - result_info = smb_find_inode(SMB_SERVER(dir), name); - -in_tree: - if (result_info != NULL) { - if (result_info->state == SMB_INODE_CACHED) - result_info->state = SMB_INODE_LOOKED_UP; - - /* Here we convert the inode_info address into an - inode number */ - - *result = iget(dir->i_sb, (int)result_info); + in_tree: + if (result_info != NULL) + { + if (result_info->state == SMB_INODE_CACHED) + { + result_info->state = SMB_INODE_LOOKED_UP; + } + *result = iget(dir->i_sb, smb_info_ino(result_info)); + iput(dir); if (new_inode_info != NULL) { smb_kfree_s(new_inode_info, sizeof(struct smb_inode_info)); } - - put_pname(name); - iput(dir); - - if (*result == NULL) { + if (*result == NULL) + { return -EACCES; } return 0; - } + } + /* If the file is in the dir cache, we do not have to ask the + server. */ + found_in_cache = 0; - /* Ok, now we have made our name. We have to build a new - smb_inode_info struct and insert it into the tree, if it is - a name that exists on the server */ - - /* If the file is in the dir cache, we do not have to ask the - server. */ - - found_in_cache = 0; - - if (dir->i_ino == c_ino) { - int first = c_last_returned_index; - int i; - - i = first; - do { - DDPRINTK("smb_lookup: trying index: %d, name: %s\n", - i, c_entry[i].path); - if (strcmp(c_entry[i].path, __name) == 0) { - DPRINTK("smb_lookup: found in cache!\n"); - finfo = c_entry[i]; - finfo.path = NULL; /* It's not ours! */ - found_in_cache = 1; - break; - } - i = (i + 1) % c_size; - DDPRINTK("smb_lookup: index %d, name %s failed\n", - i, c_entry[i].path); - } while (i != first); - } - - if (found_in_cache == 0) { - error = smb_proc_getattr(SMB_SERVER(dir), name, len, &finfo); - if (error < 0) { - put_pname(name); - iput(dir); - return error; - } - } + if ((dir->i_dev == c_dev) && (dir->i_ino == c_ino) && (c_size != 0)) + { + int first = c_last_returned_index; + int i; + i = first; + do + { + if (compare_filename(SMB_SERVER(dir), name, len, + &(c_entry[i])) == 0) + { + finfo = c_entry[i]; + found_in_cache = 1; + break; + } + i = (i + 1) % c_size; + } + while (i != first); + } + if (found_in_cache == 0) + { + DPRINTK("smb_lookup: not found in cache: %s\n", name); + if (len > SMB_MAXNAMELEN) + { + iput(dir); + return -ENAMETOOLONG; + } + error = smb_proc_getattr(dir, name, len, &finfo); + if (error < 0) + { + iput(dir); + return error; + } + finfo.f_ino = smb_fresh_inodes(SMB_SERVER(dir), 1); + } new_inode_info = smb_kmalloc(sizeof(struct smb_inode_info), GFP_KERNEL); /* Here somebody else might have inserted the inode */ - result_info = smb_find_inode(SMB_SERVER(dir), name); + + result_info = smb_find_dir_inode(dir, name, len); if (result_info != NULL) { goto in_tree; } + new_inode_info->finfo = finfo; + + DPRINTK("attr: %x\n", finfo.attr); - if ((*result = smb_iget(dir, name, &finfo, new_inode_info)) == NULL) + if ((*result = smb_iget(dir, new_inode_info)) == NULL) { smb_kfree_s(new_inode_info, sizeof(struct smb_inode_info)); - put_pname(name); iput(dir); return -EACCES; } - - DDPRINTK("smb_lookup: %s => %lu\n", name, (unsigned long)result_info); + DDPRINTK("smb_lookup: %s => %lu\n", name, (unsigned long) result_info); iput(dir); return 0; } -static int +static int smb_create(struct inode *dir, const char *name, int len, int mode, - struct inode **result) + struct inode **result) { int error; - char *path = NULL; struct smb_dirent entry; struct smb_inode_info *new_inode_info; *result = NULL; - if (!dir || !S_ISDIR(dir->i_mode)) { + if (!dir || !S_ISDIR(dir->i_mode)) + { printk("smb_create: inode is NULL or not a directory\n"); iput(dir); return -ENOENT; } - - /* Now we will have to build up an SMB filename. */ - if ((error = get_pname(dir, name, len, &path, &len)) < 0) { - iput(dir); - return error; - } - new_inode_info = smb_kmalloc(sizeof(struct smb_inode_info), GFP_KERNEL); if (new_inode_info == NULL) { - put_pname(path); iput(dir); return -ENOMEM; } + error = smb_proc_create(dir, name, len, 0, CURRENT_TIME); + if (error < 0) + { + smb_kfree_s(new_inode_info, sizeof(struct smb_inode_info)); + iput(dir); + return error; + } + smb_invalid_dir_cache(dir->i_ino); - entry.attr = 0; - entry.ctime = CURRENT_TIME; - entry.atime = CURRENT_TIME; - entry.mtime = CURRENT_TIME; - entry.size = 0; - - error = smb_proc_create(SMB_SERVER(dir), path, len, &entry); - if (error < 0) { + if ((error = smb_proc_getattr(dir, name, len, &entry)) < 0) + { smb_kfree_s(new_inode_info, sizeof(struct smb_inode_info)); - put_pname(path); iput(dir); return error; } + entry.f_ino = smb_fresh_inodes(SMB_SERVER(dir), 1); - smb_invalid_dir_cache(dir->i_ino); + new_inode_info->finfo = entry; - if ((*result = smb_iget(dir, path, &entry, new_inode_info)) == NULL) + if ((*result = smb_iget(dir, new_inode_info)) == NULL) { smb_kfree_s(new_inode_info, sizeof(struct smb_inode_info)); - put_pname(path); iput(dir); return error; } iput(dir); - return 0; + return 0; } static int smb_mkdir(struct inode *dir, const char *name, int len, int mode) { int error; - char path[SMB_MAXPATHLEN]; - if (!dir || !S_ISDIR(dir->i_mode)) { - printk("smb_mkdir: inode is NULL or not a directory\n"); + if (!dir || !S_ISDIR(dir->i_mode)) + { iput(dir); - return -ENOENT; + return -EINVAL; } - - /* Now we will have to build up an SMB filename. */ - if ((error = get_pname_static(dir, name, len, path, &len)) < 0) { - iput(dir); - return error; + if ((error = smb_proc_mkdir(dir, name, len)) == 0) + { + smb_invalid_dir_cache(dir->i_ino); } - - if ((error = smb_proc_mkdir(SMB_SERVER(dir), path, len)) == 0) { - smb_invalid_dir_cache(dir->i_ino); - } - iput(dir); return error; } @@ -833,23 +749,23 @@ smb_rmdir(struct inode *dir, const char *name, int len) { int error; - char path[SMB_MAXPATHLEN]; - if (!dir || !S_ISDIR(dir->i_mode)) { + if (!dir || !S_ISDIR(dir->i_mode)) + { printk("smb_rmdir: inode is NULL or not a directory\n"); iput(dir); return -ENOENT; } - if ((error = get_pname_static(dir, name, len, path, &len)) < 0) { - iput(dir); - return error; + if (smb_find_dir_inode(dir, name, len) != NULL) + { + error = -EBUSY; + } else + { + if ((error = smb_proc_rmdir(dir, name, len)) == 0) + { + smb_invalid_dir_cache(dir->i_ino); + } } - if (smb_find_inode(SMB_SERVER(dir), path) != NULL) { - error = -EBUSY; - } else { - if ((error = smb_proc_rmdir(SMB_SERVER(dir), path, len)) == 0) - smb_invalid_dir_cache(dir->i_ino); - } iput(dir); return error; } @@ -858,82 +774,72 @@ smb_unlink(struct inode *dir, const char *name, int len) { int error; - char path[SMB_MAXPATHLEN]; - if (!dir || !S_ISDIR(dir->i_mode)) { + if (!dir || !S_ISDIR(dir->i_mode)) + { printk("smb_unlink: inode is NULL or not a directory\n"); iput(dir); return -ENOENT; } - if ((error = get_pname_static(dir, name, len, path, &len)) < 0) { - iput(dir); - return error; + if (smb_find_dir_inode(dir, name, len) != NULL) + { + error = -EBUSY; + } else + { + if ((error = smb_proc_unlink(dir, name, len)) == 0) + { + smb_invalid_dir_cache(dir->i_ino); + } } - if (smb_find_inode(SMB_SERVER(dir), path) != NULL) { - error = -EBUSY; - } else { - if ((error = smb_proc_unlink(SMB_SERVER(dir), path, len)) == 0) - smb_invalid_dir_cache(dir->i_ino); - } iput(dir); return error; } static int smb_rename(struct inode *old_dir, const char *old_name, int old_len, - struct inode *new_dir, const char *new_name, int new_len, - int must_be_dir) + struct inode *new_dir, const char *new_name, int new_len, + int must_be_dir) { int res; - char old_path[SMB_MAXPATHLEN], new_path[SMB_MAXPATHLEN]; - if (!old_dir || !S_ISDIR(old_dir->i_mode)) { + if (!old_dir || !S_ISDIR(old_dir->i_mode)) + { printk("smb_rename: old inode is NULL or not a directory\n"); - res = -ENOENT; - goto finished; + res = -ENOENT; + goto finished; } - - if (!new_dir || !S_ISDIR(new_dir->i_mode)) { + if (!new_dir || !S_ISDIR(new_dir->i_mode)) + { printk("smb_rename: new inode is NULL or not a directory\n"); - res = -ENOENT; - goto finished; - } - - res = get_pname_static(old_dir, old_name, old_len, old_path, &old_len); - if (res < 0) { - goto finished; + res = -ENOENT; + goto finished; } - - res = get_pname_static(new_dir, new_name, new_len, new_path, &new_len); - if (res < 0) { - goto finished; + if ((smb_find_dir_inode(old_dir, old_name, old_len) != NULL) + || (smb_find_dir_inode(new_dir, new_name, new_len) != NULL)) + { + res = -EBUSY; + goto finished; } - - if ( (smb_find_inode(SMB_SERVER(old_dir), old_path) != NULL) - || (smb_find_inode(SMB_SERVER(new_dir), new_path) != NULL)) { - res = -EBUSY; - goto finished; - } + res = smb_proc_mv(old_dir, old_name, old_len, + new_dir, new_name, new_len); - res = smb_proc_mv(SMB_SERVER(old_dir), old_path, old_len, - new_path, new_len); + if (res == -EEXIST) + { + int res1 = smb_proc_unlink(old_dir, new_name, new_len); - if (res == -EEXIST) { - int res1; - res1 = smb_proc_unlink(SMB_SERVER(old_dir), new_path, new_len); - if (res1 == 0) { - res = smb_proc_mv(SMB_SERVER(old_dir), old_path, - old_len, new_path, new_len); + if (res1 == 0) + { + res = smb_proc_mv(old_dir, old_name, old_len, + new_dir, new_name, new_len); } } - - if (res == 0) { - smb_invalid_dir_cache(old_dir->i_ino); - smb_invalid_dir_cache(new_dir->i_ino); - } - - finished: - iput(old_dir); + if (res == 0) + { + smb_invalid_dir_cache(old_dir->i_ino); + smb_invalid_dir_cache(new_dir->i_ino); + } + finished: + iput(old_dir); iput(new_dir); return res; } diff -u --recursive --new-file v2.0.26/linux/fs/smbfs/file.c linux/fs/smbfs/file.c --- v2.0.26/linux/fs/smbfs/file.c Wed Sep 11 17:57:16 1996 +++ linux/fs/smbfs/file.c Sun Dec 1 15:58:05 1996 @@ -1,7 +1,7 @@ /* * file.c * - * Copyright (C) 1995 by Paal-Kr. Engstad and Volker Lendecke + * Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke * */ @@ -17,12 +17,13 @@ #include #include -static inline int min(int a, int b) +static inline int +min(int a, int b) { - return afinfo); + if (i == NULL) + { + printk("smb_make_open: got NULL inode\n"); + return -EINVAL; + } + dirent = &(SMB_INOP(i)->finfo); - DDPRINTK("smb_make_open: dirent->opened = %d\n", dirent->opened); + DDPRINTK("smb_make_open: dirent->opened = %d\n", dirent->opened); - if ((dirent->opened) == 0) { - /* tries max. rights */ + if ((dirent->opened) == 0) + { + /* tries max. rights */ int open_result = smb_proc_open(SMB_SERVER(i), - dirent->path, dirent->len, + SMB_INOP(i)->dir, + dirent->name, dirent->len, dirent); - if (open_result) + if (open_result) { - return open_result; + return open_result; } - } - - if ( ((right == O_RDONLY) && ( (dirent->access == O_RDONLY) - || (dirent->access == O_RDWR))) - || ((right == O_WRONLY) && ( (dirent->access == O_WRONLY) - || (dirent->access == O_RDWR))) - || ((right == O_RDWR) && (dirent->access == O_RDWR))) - return 0; + } + if (((right == O_RDONLY) && ((dirent->access == O_RDONLY) + || (dirent->access == O_RDWR))) + || ((right == O_WRONLY) && ((dirent->access == O_WRONLY) + || (dirent->access == O_RDWR))) + || ((right == O_RDWR) && (dirent->access == O_RDWR))) + return 0; - return -EACCES; + return -EACCES; } -static int +static int smb_file_read(struct inode *inode, struct file *file, char *buf, int count) { int result, bufsize, to_read, already_read; off_t pos; - int errno; + int errno; + + DPRINTK("smb_file_read: enter %s\n", SMB_FINFO(inode)->name); - DPRINTK("smb_file_read: enter %s\n", SMB_FINFO(inode)->path); - - if (!inode) { + if (!inode) + { DPRINTK("smb_file_read: inode = NULL\n"); return -EINVAL; } - - if (!S_ISREG(inode->i_mode)) { + if (!S_ISREG(inode->i_mode)) + { DPRINTK("smb_file_read: read from non-file, mode %07o\n", - inode->i_mode); + inode->i_mode); return -EINVAL; } + if ((errno = smb_make_open(inode, O_RDONLY)) != 0) + return errno; - if ((errno = smb_make_open(inode, O_RDONLY)) != 0) - return errno; - pos = file->f_pos; if (pos + count > inode->i_size) + { count = inode->i_size - pos; - + } if (count <= 0) + { return 0; + } bufsize = SMB_SERVER(inode)->max_xmit - SMB_HEADER_LEN - 5 * 2 - 5; - already_read = 0; + already_read = 0; /* First read in as much as possible for each bufsize. */ - while (already_read < count) { - - result = 0; - to_read = 0; - - if ((SMB_SERVER(inode)->blkmode & 1) != 0) { - to_read = min(65535, count - already_read); - DPRINTK("smb_file_read: Raw %d bytes\n", to_read); - result = smb_proc_read_raw(SMB_SERVER(inode), - SMB_FINFO(inode), - pos, to_read, buf); - DPRINTK("smb_file_read: returned %d\n", result); - } - - if (result <= 0) { - to_read = min(bufsize, count - already_read); - result = smb_proc_read(SMB_SERVER(inode), - SMB_FINFO(inode), - pos, to_read, buf, 1); - } - + while (already_read < count) + { + to_read = min(bufsize, count - already_read); + result = smb_proc_read(SMB_SERVER(inode), SMB_FINFO(inode), + pos, to_read, buf, 1); if (result < 0) + { return result; + } pos += result; buf += result; - already_read += result; + already_read += result; - if (result < to_read) { - break; + if (result < to_read) + { + break; } } - file->f_pos = pos; + file->f_pos = pos; - if (!IS_RDONLY(inode)) inode->i_atime = CURRENT_TIME; + if (!IS_RDONLY(inode)) + inode->i_atime = CURRENT_TIME; inode->i_dirt = 1; - DPRINTK("smb_file_read: exit %s\n", SMB_FINFO(inode)->path); + DPRINTK("smb_file_read: exit %s\n", SMB_FINFO(inode)->name); - return already_read; + return already_read; } -static int +static int smb_file_write(struct inode *inode, struct file *file, const char *buf, int count) { int result, bufsize, to_write, already_written; - off_t pos; - int errno; - - if (!inode) { + off_t pos; + int errno; + + if (!inode) + { DPRINTK("smb_file_write: inode = NULL\n"); return -EINVAL; } - - if (!S_ISREG(inode->i_mode)) { + if (!S_ISREG(inode->i_mode)) + { DPRINTK("smb_file_write: write to non-file, mode %07o\n", - inode->i_mode); + inode->i_mode); return -EINVAL; } - - DPRINTK("smb_file_write: enter %s\n", SMB_FINFO(inode)->path); + DPRINTK("smb_file_write: enter %s\n", SMB_FINFO(inode)->name); if (count <= 0) + { return 0; - - if ((errno = smb_make_open(inode, O_RDWR)) != 0) - return errno; - + } + if ((errno = smb_make_open(inode, O_RDWR)) != 0) + { + return errno; + } pos = file->f_pos; if (file->f_flags & O_APPEND) @@ -174,41 +169,28 @@ bufsize = SMB_SERVER(inode)->max_xmit - SMB_HEADER_LEN - 5 * 2 - 5; - already_written = 0; + already_written = 0; - DPRINTK("smb_write_file: blkmode = %d, blkmode & 2 = %d\n", - SMB_SERVER(inode)->blkmode, - SMB_SERVER(inode)->blkmode & 2); - - while (already_written < count) { - - result = 0; - to_write = 0; - - if ((SMB_SERVER(inode)->blkmode & 2) != 0) { - to_write = min(65535, count - already_written); - DPRINTK("smb_file_write: Raw %d bytes\n", to_write); - result = smb_proc_write_raw(SMB_SERVER(inode), - SMB_FINFO(inode), - pos, to_write, buf); - DPRINTK("smb_file_write: returned %d\n", result); - } - - if (result <= 0) { - to_write = min(bufsize, count - already_written); - result = smb_proc_write(SMB_SERVER(inode), - SMB_FINFO(inode), - pos, to_write, buf); - } + DPRINTK("smb_write_file: blkmode = %d, blkmode & 2 = %d\n", + SMB_SERVER(inode)->blkmode, + SMB_SERVER(inode)->blkmode & 2); + + while (already_written < count) + { + to_write = min(bufsize, count - already_written); + result = smb_proc_write(SMB_SERVER(inode), SMB_FINFO(inode), + pos, to_write, buf); if (result < 0) + { return result; - + } pos += result; buf += result; - already_written += result; + already_written += result; - if (result < to_write) { + if (result < to_write) + { break; } } @@ -218,29 +200,31 @@ file->f_pos = pos; - if (pos > inode->i_size) { - inode->i_size = pos; - } - - DPRINTK("smb_file_write: exit %s\n", SMB_FINFO(inode)->path); + if (pos > inode->i_size) + { + inode->i_size = pos; + } + DPRINTK("smb_file_write: exit %s\n", SMB_FINFO(inode)->name); return already_written; } -static struct file_operations smb_file_operations = { +static struct file_operations smb_file_operations = +{ NULL, /* lseek - default */ smb_file_read, /* read */ smb_file_write, /* write */ NULL, /* readdir - bad */ NULL, /* select - default */ smb_ioctl, /* ioctl */ - smb_mmap, /* mmap */ - NULL, /* open */ - NULL, /* release */ + smb_mmap, /* mmap */ + NULL, /* open */ + NULL, /* release */ smb_fsync, /* fsync */ }; -struct inode_operations smb_file_inode_operations = { +struct inode_operations smb_file_inode_operations = +{ &smb_file_operations, /* default file operations */ NULL, /* create */ NULL, /* lookup */ diff -u --recursive --new-file v2.0.26/linux/fs/smbfs/inode.c linux/fs/smbfs/inode.c --- v2.0.26/linux/fs/smbfs/inode.c Wed Nov 13 11:26:23 1996 +++ linux/fs/smbfs/inode.c Sun Dec 1 15:58:05 1996 @@ -1,7 +1,7 @@ /* * inode.c * - * Copyright (C) 1995 by Paal-Kr. Engstad and Volker Lendecke + * Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke * */ @@ -29,16 +29,17 @@ static void smb_put_super(struct super_block *); static void smb_statfs(struct super_block *, struct statfs *, int bufsiz); -static struct super_operations smb_sops = { - smb_read_inode, /* read inode */ - smb_notify_change, /* notify change */ +static struct super_operations smb_sops = +{ + smb_read_inode, /* read inode */ + smb_notify_change, /* notify change */ NULL, /* write inode */ smb_put_inode, /* put inode */ smb_put_super, /* put superblock */ NULL, /* write superblock */ smb_statfs, /* stat filesystem */ NULL - }; +}; /* smb_read_inode: Called from iget, it only traverses the allocated smb_inode_info's and initializes the inode from the data found @@ -47,187 +48,205 @@ static void smb_read_inode(struct inode *inode) { - /* Our task should be extremely simple here. We only have to - look up the information somebody else (smb_iget) put into - the inode tree. The address of this information is the - inode->i_ino. Just to make sure everything went well, we - check it's there. */ - - struct smb_inode_info *inode_info - = (struct smb_inode_info *)(inode->i_ino); - -#if 1 - struct smb_inode_info *root = &(SMB_SERVER(inode)->root); - struct smb_inode_info *check_info = root; - - do { - if (inode_info == check_info) { - if (check_info->state == SMB_INODE_LOOKED_UP) { - DDPRINTK("smb_read_inode: found it!\n"); - goto good; - } - else { - printk("smb_read_inode: " - "state != SMB_INODE_LOOKED_UP\n"); - return; - } - } - check_info = check_info->next; - } while (check_info != root); - - /* Ok, now we're in trouble. The inode info is not there. What - should we do now??? */ - printk("smb_read_inode: inode info not found\n"); - return; - - good: -#endif - inode_info->state = SMB_INODE_VALID; + /* Our task should be extremely simple here. We only have to + look up the information somebody else (smb_iget) put into + the inode tree. */ + struct smb_server *server = SMB_SERVER(inode); + struct smb_inode_info *inode_info + = smb_find_inode(server, inode->i_ino); - SMB_INOP(inode) = inode_info; + if (inode_info == NULL) + { + /* Ok, now we're in trouble. The inode info is not + there. What should we do now??? */ + printk("smb_read_inode: inode info not found\n"); + return; + } + inode_info->state = SMB_INODE_VALID; - if (SMB_INOP(inode)->finfo.attr & aDIR) - inode->i_mode = SMB_SERVER(inode)->m.dir_mode; - else - inode->i_mode = SMB_SERVER(inode)->m.file_mode; - - DDPRINTK("smb_read_inode: inode->i_mode = %u\n", inode->i_mode); - - inode->i_nlink = 1; - inode->i_uid = SMB_SERVER(inode)->m.uid; - inode->i_gid = SMB_SERVER(inode)->m.gid; - inode->i_size = SMB_INOP(inode)->finfo.size; - inode->i_blksize = 1024; - inode->i_rdev = 0; - if ((inode->i_blksize != 0) && (inode->i_size != 0)) - inode->i_blocks = - (inode->i_size - 1) / inode->i_blksize + 1; - else - inode->i_blocks = 0; - - inode->i_mtime = SMB_INOP(inode)->finfo.mtime; - inode->i_ctime = SMB_INOP(inode)->finfo.ctime; - inode->i_atime = SMB_INOP(inode)->finfo.atime; - - if (S_ISREG(inode->i_mode)) - inode->i_op = &smb_file_inode_operations; - else if (S_ISDIR(inode->i_mode)) - inode->i_op = &smb_dir_inode_operations; - else - inode->i_op = NULL; + SMB_INOP(inode) = inode_info; + inode->i_mode = inode_info->finfo.f_mode; + inode->i_nlink = inode_info->finfo.f_nlink; + inode->i_uid = inode_info->finfo.f_uid; + inode->i_gid = inode_info->finfo.f_gid; + inode->i_rdev = inode_info->finfo.f_rdev; + inode->i_size = inode_info->finfo.f_size; + inode->i_mtime = inode_info->finfo.f_mtime; + inode->i_ctime = inode_info->finfo.f_ctime; + inode->i_atime = inode_info->finfo.f_atime; + inode->i_blksize = inode_info->finfo.f_blksize; + inode->i_blocks = inode_info->finfo.f_blocks; + if (S_ISREG(inode->i_mode)) + { + inode->i_op = &smb_file_inode_operations; + } else if (S_ISDIR(inode->i_mode)) + { + inode->i_op = &smb_dir_inode_operations; + } else + { + inode->i_op = NULL; + } } static void smb_put_inode(struct inode *inode) { - struct smb_dirent *finfo = SMB_FINFO(inode); + struct smb_dirent *finfo = SMB_FINFO(inode); struct smb_server *server = SMB_SERVER(inode); struct smb_inode_info *info = SMB_INOP(inode); - int opened = finfo->opened; - int mtime = inode->i_mtime; - int file_id = finfo->fileid; - int isdir = S_ISDIR(inode->i_mode); - unsigned long ino = inode->i_ino; - - /* Remove the inode before closing the file, because the close - will sleep. This hopefully removes a race condition. */ - - clear_inode(inode); - smb_free_inode_info(info); - - if (isdir) + if (S_ISDIR(inode->i_mode)) { - DDPRINTK("smb_put_inode: put directory %ld\n", - inode->i_ino); - smb_invalid_dir_cache(ino); - } - - if (opened != 0) + smb_invalid_dir_cache(inode->i_ino); + } + if (finfo->opened != 0) { - if (smb_proc_close(server, file_id, mtime)) + if (smb_proc_close(server, finfo->fileid, inode->i_mtime)) { - /* We can't do anything but complain. */ - DPRINTK("smb_put_inode: could not close\n"); - } - } + /* We can't do anything but complain. */ + DPRINTK("smb_put_inode: could not close\n"); + } + } + smb_free_inode_info(info); + clear_inode(inode); } static void smb_put_super(struct super_block *sb) { - struct smb_server *server = &(SMB_SBP(sb)->s_server); + struct smb_server *server = &(SMB_SBP(sb)->s_server); - smb_proc_disconnect(server); + smb_proc_disconnect(server); smb_dont_catch_keepalive(server); close_fp(server->sock_file); lock_super(sb); - smb_free_all_inodes(server); + smb_free_all_inodes(server); - smb_kfree_s(server->packet, server->max_xmit); + smb_vfree(server->packet); + server->packet = NULL; sb->s_dev = 0; - smb_kfree_s(SMB_SBP(sb), sizeof(struct smb_sb_info)); + smb_kfree_s(SMB_SBP(sb), sizeof(struct smb_sb_info)); unlock_super(sb); - MOD_DEC_USE_COUNT; + MOD_DEC_USE_COUNT; } +struct smb_mount_data_v4 +{ + int version; + unsigned int fd; + uid_t mounted_uid; + struct sockaddr_in addr; + + char server_name[17]; + char client_name[17]; + char service[64]; + char root_path[64]; + + char username[64]; + char password[64]; + + unsigned short max_xmit; + + uid_t uid; + gid_t gid; + mode_t file_mode; + mode_t dir_mode; +}; + +static int +smb_get_mount_data(struct smb_mount_data *target, void *source) +{ + struct smb_mount_data_v4 *v4 = (struct smb_mount_data_v4 *) source; + struct smb_mount_data *cur = (struct smb_mount_data *) source; + + if (source == NULL) + { + return 1; + } + if (cur->version == SMB_MOUNT_VERSION) + { + memcpy(target, cur, sizeof(struct smb_mount_data)); + return 0; + } + if (v4->version == 4) + { + target->version = 5; + target->fd = v4->fd; + target->mounted_uid = v4->mounted_uid; + target->addr = v4->addr; + + memcpy(target->server_name, v4->server_name, 17); + memcpy(target->client_name, v4->client_name, 17); + memcpy(target->service, v4->service, 64); + memcpy(target->root_path, v4->root_path, 64); + memcpy(target->username, v4->username, 64); + memcpy(target->password, v4->password, 64); + + target->max_xmit = v4->max_xmit; + target->uid = v4->uid; + target->gid = v4->gid; + target->file_mode = v4->file_mode; + target->dir_mode = v4->dir_mode; + + memset(target->domain, 0, 64); + strcpy(target->domain, "?"); + return 0; + } + return 1; +} -/* Hmm, should we do this like the NFS mount command does? Guess so.. */ struct super_block * smb_read_super(struct super_block *sb, void *raw_data, int silent) { - struct smb_mount_data *data = (struct smb_mount_data *) raw_data; + struct smb_mount_data data; struct smb_server *server; - struct smb_sb_info *smb_sb; + struct smb_sb_info *smb_sb; unsigned int fd; struct file *filp; kdev_t dev = sb->s_dev; int error; - if (!data) { - printk("smb_read_super: missing data argument\n"); + if (smb_get_mount_data(&data, raw_data) != 0) + { + printk("smb_read_super: wrong data argument\n"); sb->s_dev = 0; return NULL; } - fd = data->fd; - if (data->version != SMB_MOUNT_VERSION) { - printk("smb warning: mount version %s than kernel\n", - (data->version < SMB_MOUNT_VERSION) ? - "older" : "newer"); - } - if (fd >= NR_OPEN || !(filp = current->files->fd[fd])) { + fd = data.fd; + if (fd >= NR_OPEN || !(filp = current->files->fd[fd])) + { printk("smb_read_super: invalid file descriptor\n"); sb->s_dev = 0; return NULL; } - if (!S_ISSOCK(filp->f_inode->i_mode)) { + if (!S_ISSOCK(filp->f_inode->i_mode)) + { printk("smb_read_super: not a socket!\n"); sb->s_dev = 0; return NULL; } + /* We must malloc our own super-block info */ + smb_sb = (struct smb_sb_info *) smb_kmalloc(sizeof(struct smb_sb_info), + GFP_KERNEL); - /* We must malloc our own super-block info */ - smb_sb = (struct smb_sb_info *)smb_kmalloc(sizeof(struct smb_sb_info), - GFP_KERNEL); - - if (smb_sb == NULL) { - printk("smb_read_super: could not alloc smb_sb_info\n"); - return NULL; - } - - filp->f_count += 1; + if (smb_sb == NULL) + { + printk("smb_read_super: could not alloc smb_sb_info\n"); + return NULL; + } + filp->f_count += 1; lock_super(sb); - SMB_SBP(sb) = smb_sb; - - sb->s_blocksize = 1024; /* Eh... Is this correct? */ + SMB_SBP(sb) = smb_sb; + + sb->s_blocksize = 1024; /* Eh... Is this correct? */ sb->s_blocksize_bits = 10; sb->s_magic = SMB_SUPER_MAGIC; sb->s_dev = dev; @@ -237,100 +256,90 @@ server->sock_file = filp; server->lock = 0; server->wait = NULL; - server->packet = NULL; - server->max_xmit = data->max_xmit; + server->packet = NULL; + server->max_xmit = data.max_xmit; if (server->max_xmit <= 0) + { server->max_xmit = SMB_DEF_MAX_XMIT; - + } server->tid = 0; server->pid = current->pid; server->mid = current->pid + 20; - server->m = *data; + server->m = data; server->m.file_mode = (server->m.file_mode & - (S_IRWXU|S_IRWXG|S_IRWXO)) | S_IFREG; - server->m.dir_mode = (server->m.dir_mode & - (S_IRWXU|S_IRWXG|S_IRWXO)) | S_IFDIR; - - smb_init_root(server); - - /* - * Make the connection to the server - */ - + (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFREG; + server->m.dir_mode = (server->m.dir_mode & + (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFDIR; + + smb_init_root(server); + error = smb_proc_connect(server); unlock_super(sb); - if (error < 0) { + if (error < 0) + { sb->s_dev = 0; - printk("smb_read_super: Failed connection, bailing out " - "(error = %d).\n", -error); - goto fail; + DPRINTK("smb_read_super: Failed connection, bailing out " + "(error = %d).\n", -error); + goto fail; } - - if (server->protocol >= PROTOCOL_LANMAN2) - server->case_handling = CASE_DEFAULT; - else - server->case_handling = CASE_LOWER; - - if ((error = smb_proc_dskattr(sb, &(SMB_SBP(sb)->s_attr))) < 0) { - sb->s_dev = 0; - printk("smb_read_super: could not get super block " - "attributes\n"); - smb_kfree_s(server->packet, server->max_xmit); - goto fail; + if (server->protocol >= PROTOCOL_LANMAN2) + { + server->case_handling = CASE_DEFAULT; + } else + { + server->case_handling = CASE_LOWER; } - if ((error = smb_stat_root(server)) < 0) { + if ((error = smb_proc_dskattr(sb, &(SMB_SBP(sb)->s_attr))) < 0) + { sb->s_dev = 0; - printk("smb_read_super: could not get root dir attributes\n"); - smb_kfree_s(server->packet, server->max_xmit); - goto fail; + printk("smb_read_super: could not get super block " + "attributes\n"); + goto fail; } + smb_init_root_dirent(server, &(server->root.finfo)); - DPRINTK("smb_read_super : %u %u %u %u\n", - SMB_SBP(sb)->s_attr.total, - SMB_SBP(sb)->s_attr.blocksize, - SMB_SBP(sb)->s_attr.allocblocks, - SMB_SBP(sb)->s_attr.free); - - DPRINTK("smb_read_super: SMB_SBP(sb) = %x\n", (int)SMB_SBP(sb)); - - if (!(sb->s_mounted = iget(sb, (int)&(server->root)))) { + if (!(sb->s_mounted = iget(sb, smb_info_ino(&(server->root))))) + { sb->s_dev = 0; printk("smb_read_super: get root inode failed\n"); - smb_kfree_s(server->packet, server->max_xmit); - goto fail; + goto fail; } - - MOD_INC_USE_COUNT; + MOD_INC_USE_COUNT; return sb; - fail: - filp->f_count -= 1; + fail: + if (server->packet != NULL) + { + smb_vfree(server->packet); + server->packet = NULL; + } + filp->f_count -= 1; smb_dont_catch_keepalive(server); - smb_kfree_s(SMB_SBP(sb), sizeof(struct smb_sb_info)); - return NULL; + smb_kfree_s(SMB_SBP(sb), sizeof(struct smb_sb_info)); + return NULL; } -static void +static void smb_statfs(struct super_block *sb, struct statfs *buf, int bufsiz) { int error; struct smb_dskattr attr; struct statfs tmp; - + error = smb_proc_dskattr(sb, &attr); - if (error) { + if (error) + { printk("smb_statfs: dskattr error = %d\n", -error); attr.total = attr.allocblocks = attr.blocksize = - attr.free = 0; + attr.free = 0; } - tmp.f_type = SMB_SUPER_MAGIC; - tmp.f_bsize = attr.blocksize*attr.allocblocks; + tmp.f_bsize = attr.blocksize * attr.allocblocks; tmp.f_blocks = attr.total; tmp.f_bfree = attr.free; tmp.f_bavail = attr.free; @@ -340,7 +349,6 @@ memcpy_tofs(buf, &tmp, bufsiz); } -/* DO MORE */ int smb_notify_change(struct inode *inode, struct iattr *attr) { @@ -349,93 +357,101 @@ if ((error = inode_change_ok(inode, attr)) < 0) return error; - if (((attr->ia_valid & ATTR_UID) && + if (((attr->ia_valid & ATTR_UID) && (attr->ia_uid != SMB_SERVER(inode)->m.uid))) return -EPERM; - if (((attr->ia_valid & ATTR_GID) && + if (((attr->ia_valid & ATTR_GID) && (attr->ia_uid != SMB_SERVER(inode)->m.gid))) - return -EPERM; + return -EPERM; if (((attr->ia_valid & ATTR_MODE) && - (attr->ia_mode & ~(S_IFREG | S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO)))) + (attr->ia_mode & ~(S_IFREG | S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO)))) return -EPERM; - if ((attr->ia_valid & ATTR_SIZE) != 0) { - - if ((error = smb_make_open(inode, O_WRONLY)) < 0) - goto fail; - - if ((error = smb_proc_trunc(SMB_SERVER(inode), - SMB_FINFO(inode)->fileid, - attr->ia_size)) < 0) - goto fail; - - } - - if ((attr->ia_valid & (ATTR_CTIME | ATTR_MTIME | ATTR_ATIME)) != 0) { - - struct smb_dirent finfo; + if ((attr->ia_valid & ATTR_SIZE) != 0) + { - finfo.attr = 0; + if ((error = smb_make_open(inode, O_WRONLY)) < 0) + goto fail; - if ((attr->ia_valid & ATTR_CTIME) != 0) - finfo.ctime = attr->ia_ctime; - else - finfo.ctime = inode->i_ctime; + if ((error = smb_proc_trunc(SMB_SERVER(inode), + SMB_FINFO(inode)->fileid, + attr->ia_size)) < 0) + goto fail; - if ((attr->ia_valid & ATTR_MTIME) != 0) - finfo.mtime = attr->ia_mtime; - else - finfo.mtime = inode->i_mtime; + } + if ((attr->ia_valid & (ATTR_CTIME | ATTR_MTIME | ATTR_ATIME)) != 0) + { - if ((attr->ia_valid & ATTR_ATIME) != 0) - finfo.atime = attr->ia_atime; - else - finfo.atime = inode->i_atime; + struct smb_dirent finfo; - if ((error = smb_proc_setattr(SMB_SERVER(inode), - inode, &finfo)) >= 0) { - inode->i_ctime = finfo.ctime; - inode->i_mtime = finfo.mtime; - inode->i_atime = finfo.atime; - } - } + finfo.attr = 0; + finfo.f_size = inode->i_size; + finfo.f_blksize = inode->i_blksize; + + if ((attr->ia_valid & ATTR_CTIME) != 0) + finfo.f_ctime = attr->ia_ctime; + else + finfo.f_ctime = inode->i_ctime; + + if ((attr->ia_valid & ATTR_MTIME) != 0) + finfo.f_mtime = attr->ia_mtime; + else + finfo.f_mtime = inode->i_mtime; + + if ((attr->ia_valid & ATTR_ATIME) != 0) + finfo.f_atime = attr->ia_atime; + else + finfo.f_atime = inode->i_atime; - fail: - smb_invalid_dir_cache((unsigned long)(SMB_INOP(inode)->dir)); + if ((error = smb_proc_setattr(SMB_SERVER(inode), + inode, &finfo)) >= 0) + { + inode->i_ctime = finfo.f_ctime; + inode->i_mtime = finfo.f_mtime; + inode->i_atime = finfo.f_atime; + } + } + fail: + smb_invalid_dir_cache(smb_info_ino(SMB_INOP(inode)->dir)); return error; } - + #ifdef DEBUG_SMB_MALLOC int smb_malloced; -int smb_current_malloced; +int smb_current_kmalloced; +int smb_current_vmalloced; #endif -static struct file_system_type smb_fs_type = { - smb_read_super, "smbfs", 0, NULL - }; +static struct file_system_type smb_fs_type = +{ + smb_read_super, "smbfs", 0, NULL +}; -int init_smb_fs(void) +int +init_smb_fs(void) { - return register_filesystem(&smb_fs_type); + return register_filesystem(&smb_fs_type); } #ifdef MODULE -int init_module(void) +int +init_module(void) { int status; - DPRINTK("smbfs: init_module called\n"); + DPRINTK("smbfs: init_module called\n"); #ifdef DEBUG_SMB_MALLOC - smb_malloced = 0; - smb_current_malloced = 0; + smb_malloced = 0; + smb_current_kmalloced = 0; + smb_current_vmalloced = 0; #endif - smb_init_dir_cache(); + smb_init_dir_cache(); if ((status = init_smb_fs()) == 0) register_symtab(0); @@ -445,12 +461,13 @@ void cleanup_module(void) { - DPRINTK("smbfs: cleanup_module called\n"); - smb_free_dir_cache(); - unregister_filesystem(&smb_fs_type); + DPRINTK("smbfs: cleanup_module called\n"); + smb_free_dir_cache(); + unregister_filesystem(&smb_fs_type); #ifdef DEBUG_SMB_MALLOC - printk("smb_malloced: %d\n", smb_malloced); - printk("smb_current_malloced: %d\n", smb_current_malloced); + printk("smb_malloced: %d\n", smb_malloced); + printk("smb_current_kmalloced: %d\n", smb_current_kmalloced); + printk("smb_current_vmalloced: %d\n", smb_current_vmalloced); #endif } diff -u --recursive --new-file v2.0.26/linux/fs/smbfs/ioctl.c linux/fs/smbfs/ioctl.c --- v2.0.26/linux/fs/smbfs/ioctl.c Wed Jun 5 13:22:48 1996 +++ linux/fs/smbfs/ioctl.c Sun Dec 1 15:58:05 1996 @@ -1,7 +1,7 @@ /* * ioctl.c * - * Copyright (C) 1995 by Volker Lendecke + * Copyright (C) 1995, 1996 by Volker Lendecke * */ @@ -14,20 +14,22 @@ #include int -smb_ioctl (struct inode * inode, struct file * filp, - unsigned int cmd, unsigned long arg) +smb_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) { int result; - switch (cmd) { - case SMB_IOC_GETMOUNTUID: - if ((result = verify_area(VERIFY_WRITE, (uid_t*) arg, - sizeof(uid_t))) != 0) { - return result; - } - put_fs_word(SMB_SERVER(inode)->m.mounted_uid, (uid_t*) arg); - return 0; - default: + switch (cmd) + { + case SMB_IOC_GETMOUNTUID: + if ((result = verify_area(VERIFY_WRITE, (uid_t *) arg, + sizeof(uid_t))) != 0) + { + return result; + } + put_fs_word(SMB_SERVER(inode)->m.mounted_uid, (uid_t *) arg); + return 0; + default: return -EINVAL; } } diff -u --recursive --new-file v2.0.26/linux/fs/smbfs/mmap.c linux/fs/smbfs/mmap.c --- v2.0.26/linux/fs/smbfs/mmap.c Wed Jun 5 13:22:48 1996 +++ linux/fs/smbfs/mmap.c Sun Dec 1 15:58:05 1996 @@ -1,7 +1,7 @@ /* * mmap.c * - * Copyright (C) 1995 by Paal-Kr. Engstad and Volker Lendecke + * Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke * */ @@ -23,11 +23,11 @@ /* * Fill in the supplied page for mmap */ -static unsigned long -smb_file_mmap_nopage(struct vm_area_struct * area, +static unsigned long +smb_file_mmap_nopage(struct vm_area_struct *area, unsigned long address, int no_share) { - struct inode * inode = area->vm_inode; + struct inode *inode = area->vm_inode; unsigned long page; unsigned int clear; unsigned long tmp; @@ -42,50 +42,54 @@ pos = address - area->vm_start + area->vm_offset; clear = 0; - if (address + PAGE_SIZE > area->vm_end) { + if (address + PAGE_SIZE > area->vm_end) + { clear = address + PAGE_SIZE - area->vm_end; } - - /* what we can read in one go */ + /* what we can read in one go */ n = SMB_SERVER(inode)->max_xmit - SMB_HEADER_LEN - 5 * 2 - 3 - 10; - if (smb_make_open(inode, O_RDONLY) < 0) { - clear = PAGE_SIZE; - } - else - { - - for (i = 0; i < (PAGE_SIZE - clear); i += n) { - int hunk, result; - - hunk = PAGE_SIZE - i; - if (hunk > n) - hunk = n; - - DDPRINTK("smb_file_mmap_nopage: reading\n"); - DDPRINTK("smb_file_mmap_nopage: pos = %d\n", pos); - result = smb_proc_read(SMB_SERVER(inode), - SMB_FINFO(inode), pos, hunk, - (char *) (page + i), 0); - DDPRINTK("smb_file_mmap_nopage: result= %d\n", result); - if (result < 0) - break; - pos += result; - if (result < n) { - i += result; - break; - } - } - } + if (smb_make_open(inode, O_RDONLY) < 0) + { + clear = PAGE_SIZE; + } else + { + + for (i = 0; i < (PAGE_SIZE - clear); i += n) + { + int hunk, result; + + hunk = PAGE_SIZE - i; + if (hunk > n) + hunk = n; + + DDPRINTK("smb_file_mmap_nopage: reading\n"); + DDPRINTK("smb_file_mmap_nopage: pos = %d\n", pos); + result = smb_proc_read(SMB_SERVER(inode), + SMB_FINFO(inode), pos, hunk, + (char *) (page + i), 0); + DDPRINTK("smb_file_mmap_nopage: result= %d\n", result); + if (result < 0) + break; + pos += result; + if (result < n) + { + i += result; + break; + } + } + } tmp = page + PAGE_SIZE; - while (clear--) { - *(char *)--tmp = 0; + while (clear--) + { + *(char *) --tmp = 0; } return page; } -struct vm_operations_struct smb_file_mmap = { +struct vm_operations_struct smb_file_mmap = +{ NULL, /* open */ NULL, /* close */ NULL, /* unmap */ @@ -101,20 +105,20 @@ /* This is used for a general mmap of a smb file */ int -smb_mmap(struct inode * inode, struct file * file, struct vm_area_struct * vma) +smb_mmap(struct inode *inode, struct file *file, struct vm_area_struct *vma) { - DPRINTK("smb_mmap: called\n"); + DPRINTK("smb_mmap: called\n"); - /* only PAGE_COW or read-only supported now */ - if (vma->vm_flags & VM_SHARED) + /* only PAGE_COW or read-only supported now */ + if (vma->vm_flags & VM_SHARED) return -EINVAL; if (!inode->i_sb || !S_ISREG(inode->i_mode)) return -EACCES; - if (!IS_RDONLY(inode)) { + if (!IS_RDONLY(inode)) + { inode->i_atime = CURRENT_TIME; inode->i_dirt = 1; } - vma->vm_inode = inode; inode->i_count++; vma->vm_ops = &smb_file_mmap; diff -u --recursive --new-file v2.0.26/linux/fs/smbfs/proc.c linux/fs/smbfs/proc.c --- v2.0.26/linux/fs/smbfs/proc.c Wed Sep 11 17:57:16 1996 +++ linux/fs/smbfs/proc.c Sun Dec 1 15:58:06 1996 @@ -1,7 +1,7 @@ /* * proc.c * - * Copyright (C) 1995 by Paal-Kr. Engstad and Volker Lendecke + * Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke * * 28/06/96 - Fixed long file name support (smb_proc_readdir_long) by Yuri Per */ @@ -18,25 +18,43 @@ #include #include -#define ARCH i386 #define SMB_VWV(packet) ((packet) + SMB_HEADER_LEN) -#define SMB_CMD(packet) ((packet)[8]) -#define SMB_WCT(packet) ((packet)[SMB_HEADER_LEN - 1]) +#define SMB_CMD(packet) (BVAL(packet,8)) +#define SMB_WCT(packet) (BVAL(packet, SMB_HEADER_LEN - 1)) #define SMB_BCC(packet) smb_bcc(packet) #define SMB_BUF(packet) ((packet) + SMB_HEADER_LEN + SMB_WCT(packet) * 2 + 2) #define SMB_DIRINFO_SIZE 43 #define SMB_STATUS_SIZE 21 -#define HI_WORD(l) ((word)(l >> 16)) -#define LO_WORD(l) ((word)(l % 0xFFFF)) - -void smb_printerr(int class, int num); static int smb_request_ok(struct smb_server *s, int command, int wct, int bcc); -static inline int min(int a, int b) +static inline int +min(int a, int b) +{ + return a < b ? a : b; +} + +static void +str_upper(char *name) +{ + while (*name) + { + if (*name >= 'a' && *name <= 'z') + *name -= ('a' - 'A'); + name++; + } +} + +static void +str_lower(char *name) { - return a= 'A' && *name <= 'Z') + *name += ('a' - 'A'); + name++; + } } /*****************************************************************************/ @@ -45,94 +63,105 @@ /* */ /*****************************************************************************/ -static byte * -smb_encode_word(byte *p, word data) -{ -#if (ARCH == i386) - *((word *)p) = data; -#else - p[0] = data & 0x00ffU; - p[1] = (data & 0xff00U) >> 8; -#error "Non-Intel" -#endif - return &p[2]; -} - -static byte * -smb_decode_word(byte *p, word *data) +static inline byte * +smb_decode_word(byte * p, word * data) { -#if (ARCH == i386) - *data = *(word *)p; -#else - *data = (word) p[0] | p[1] << 8; -#endif - return &p[2]; + *data = WVAL(p, 0); + return p + 2; } byte * -smb_encode_smb_length(byte *p, dword len) +smb_encode_smb_length(byte * p, dword len) { - p[0] = p[1] = 0; - p[2] = (len & 0xFF00) >> 8; - p[3] = (len & 0xFF); + BSET(p, 0, 0); + BSET(p, 1, 0); + BSET(p, 2, (len & 0xFF00) >> 8); + BSET(p, 3, (len & 0xFF)); if (len > 0xFFFF) - p[1] |= 0x01; - return &p[4]; + { + BSET(p, 1, 1); + } + return p + 4; } static byte * -smb_encode_dialect(byte *p, const byte *name, int len) +smb_encode_ascii(byte * p, const byte * name, int len) { - *p ++ = 2; + *p++ = 4; strcpy(p, name); return p + len + 1; } static byte * -smb_encode_ascii(byte *p, const byte *name, int len) +smb_encode_this_name(byte * p, const char *name, const int len) { - *p ++ = 4; - strcpy(p, name); - return p + len + 1; + *p++ = '\\'; + strncpy(p, name, len); + return p + len; } +/* I put smb_encode_parents into a separate function so that the + recursion only takes 16 bytes on the stack per path component on a + 386. */ + static byte * -smb_encode_vblock(byte *p, const byte *data, word len, int fs) +smb_encode_parents(byte * p, struct smb_inode_info *ino) { - *p ++ = 5; - p = smb_encode_word(p, len); - if (fs) - memcpy_fromfs(p, data, len); - else - memcpy(p, data, len); - return p + len; + byte *q; + + if (ino->dir == NULL) + { + return p; + } + q = smb_encode_parents(p, ino->dir); + if (q - p + 1 + ino->finfo.len > SMB_MAXPATHLEN) + { + return p; + } + return smb_encode_this_name(q, ino->finfo.name, ino->finfo.len); } static byte * -smb_decode_data(byte *p, byte *data, word *data_len, int fs) -{ - word len; +smb_encode_path(struct smb_server *server, + byte * p, struct smb_inode_info *dir, + const char *name, const int len) +{ + byte *start = p; + p = smb_encode_parents(p, dir); + p = smb_encode_this_name(p, name, len); + *p++ = 0; + if (server->protocol <= PROTOCOL_COREPLUS) + { + str_upper(start); + } + return p; +} - if (!(*p == 1 || *p == 5)) { - printk("smb_decode_data: Warning! Data block not starting " - "with 1 or 5\n"); - } +static byte * +smb_decode_data(byte * p, byte * data, word * data_len, int fs) +{ + word len; - len = WVAL(p, 1); - p += 3; + if (!(*p == 1 || *p == 5)) + { + printk("smb_decode_data: Warning! Data block not starting " + "with 1 or 5\n"); + } + len = WVAL(p, 1); + p += 3; - if (fs) - memcpy_tofs(data, p, len); - else - memcpy(data, p, len); + if (fs) + memcpy_tofs(data, p, len); + else + memcpy(data, p, len); - *data_len = len; + *data_len = len; - return p + len; + return p + len; } static byte * -smb_name_mangle(byte *p, const byte *name) +smb_name_mangle(byte * p, const byte * name) { int len, pad = 0; @@ -141,19 +170,21 @@ if (len < 16) pad = 16 - len; - *p ++ = 2 * (len + pad); + *p++ = 2 * (len + pad); - while (*name) { - *p ++ = (*name >> 4) + 'A'; - *p ++ = (*name & 0x0F) + 'A'; - name ++; - } - while (pad --) { - *p ++ = 'C'; - *p ++ = 'A'; + while (*name) + { + *p++ = (*name >> 4) + 'A'; + *p++ = (*name & 0x0F) + 'A'; + name++; + } + while (pad--) + { + *p++ = 'C'; + *p++ = 'A'; } *p++ = '\0'; - + return p; } @@ -161,7 +192,8 @@ /* Linear day numbers of the respective 1sts in non-leap years. */ -static int day_n[] = { 0,31,59,90,120,151,181,212,243,273,304,334,0,0,0,0 }; +static int day_n[] = +{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, 0}; /* JanFebMarApr May Jun Jul Aug Sep Oct Nov Dec */ @@ -170,28 +202,28 @@ static int utc2local(int time) { - return time - sys_tz.tz_minuteswest*60; + return time - sys_tz.tz_minuteswest * 60; } static int local2utc(int time) { - return time + sys_tz.tz_minuteswest*60; + return time + sys_tz.tz_minuteswest * 60; } /* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */ static int -date_dos2unix(unsigned short time,unsigned short date) +date_dos2unix(unsigned short time, unsigned short date) { - int month,year,secs; + int month, year, secs; - month = ((date >> 5) & 15)-1; + month = ((date >> 5) & 15) - 1; year = date >> 9; - secs = (time & 31)*2+60*((time >> 5) & 63)+(time >> 11)*3600+86400* - ((date & 31)-1+day_n[month]+(year/4)+year*365-((year & 3) == 0 && - month < 2 ? 1 : 0)+3653); - /* days since 1.1.70 plus 80's leap day */ + secs = (time & 31) * 2 + 60 * ((time >> 5) & 63) + (time >> 11) * 3600 + 86400 * + ((date & 31) - 1 + day_n[month] + (year / 4) + year * 365 - ((year & 3) == 0 && + month < 2 ? 1 : 0) + 3653); + /* days since 1.1.70 plus 80's leap day */ return local2utc(secs); } @@ -199,27 +231,32 @@ /* Convert linear UNIX date to a MS-DOS time/date pair. */ static void -date_unix2dos(int unix_date,unsigned short *time, unsigned short *date) +date_unix2dos(int unix_date, byte * date, byte * time) { - int day,year,nl_day,month; + int day, year, nl_day, month; unix_date = utc2local(unix_date); - *time = (unix_date % 60)/2+(((unix_date/60) % 60) << 5)+ - (((unix_date/3600) % 24) << 11); - day = unix_date/86400-3652; - year = day/365; - if ((year+3)/4+365*year > day) year--; - day -= (year+3)/4+365*year; - if (day == 59 && !(year & 3)) { + WSET(time, 0, + (unix_date % 60) / 2 + (((unix_date / 60) % 60) << 5) + + (((unix_date / 3600) % 24) << 11)); + day = unix_date / 86400 - 3652; + year = day / 365; + if ((year + 3) / 4 + 365 * year > day) + year--; + day -= (year + 3) / 4 + 365 * year; + if (day == 59 && !(year & 3)) + { nl_day = day; month = 2; - } - else { - nl_day = (year & 3) || day <= 59 ? day : day-1; + } else + { + nl_day = (year & 3) || day <= 59 ? day : day - 1; for (month = 0; month < 12; month++) - if (day_n[month] > nl_day) break; + if (day_n[month] > nl_day) + break; } - *date = nl_day-day_n[month-1]+1+(month << 5)+(year << 9); + WSET(date, 0, + nl_day - day_n[month - 1] + 1 + (month << 5) + (year << 9)); } @@ -231,43 +268,39 @@ /*****************************************************************************/ dword -smb_len(byte *packet) +smb_len(byte * p) { - return ((packet[1] & 0x1) << 16L) | (packet[2] << 8L) | (packet[3]); + return ((BVAL(p, 1) & 0x1) << 16L) | (BVAL(p, 2) << 8L) | (BVAL(p, 3)); } static word -smb_bcc(byte *packet) +smb_bcc(byte * packet) { int pos = SMB_HEADER_LEN + SMB_WCT(packet) * sizeof(word); -#if (ARCH == i386) - return *((word *)((byte *)packet + pos)); -#else - return packet[pos] | packet[pos+1] << 8; -#endif + return WVAL(packet, pos); } /* smb_valid_packet: We check if packet fulfills the basic requirements of a smb packet */ static int -smb_valid_packet(byte *packet) +smb_valid_packet(byte * packet) { - DDPRINTK("len: %ld, wct: %d, bcc: %d\n", - smb_len(packet), SMB_WCT(packet), SMB_BCC(packet)); - return ( packet[4] == 0xff - && packet[5] == 'S' - && packet[6] == 'M' - && packet[7] == 'B' - && (smb_len(packet) + 4 == SMB_HEADER_LEN - + SMB_WCT(packet) * 2 + SMB_BCC(packet))); + DDPRINTK("len: %d, wct: %d, bcc: %d\n", + smb_len(packet), SMB_WCT(packet), SMB_BCC(packet)); + return (packet[4] == 0xff + && packet[5] == 'S' + && packet[6] == 'M' + && packet[7] == 'B' + && (smb_len(packet) + 4 == SMB_HEADER_LEN + + SMB_WCT(packet) * 2 + SMB_BCC(packet))); } /* smb_verify: We check if we got the answer we expected, and if we got enough data. If bcc == -1, we don't care. */ static int -smb_verify(byte *packet, int command, int wct, int bcc) +smb_verify(byte * packet, int command, int wct, int bcc) { return (SMB_CMD(packet) == command && SMB_WCT(packet) >= wct && @@ -277,119 +310,100 @@ static int smb_errno(int errcls, int error) { - -#if DEBUG_SMB > 1 - if (errcls) { - printk("smb_errno: "); - smb_printerr(errcls, error); - printk("\n"); - } -#endif - - if (errcls == ERRDOS) - switch (error) { - case ERRbadfunc: return EINVAL; - case ERRbadfile: return ENOENT; - case ERRbadpath: return ENOENT; - case ERRnofids: return EMFILE; - case ERRnoaccess: return EACCES; - case ERRbadfid: return EBADF; - case ERRbadmcb: return EREMOTEIO; - case ERRnomem: return ENOMEM; - case ERRbadmem: return EFAULT; - case ERRbadenv: return EREMOTEIO; - case ERRbadformat: return EREMOTEIO; - case ERRbadaccess: return EACCES; - case ERRbaddata: return E2BIG; - case ERRbaddrive: return ENXIO; - case ERRremcd: return EREMOTEIO; - case ERRdiffdevice: return EXDEV; - case ERRnofiles: return 0; - case ERRbadshare: return ETXTBSY; - case ERRlock: return EDEADLK; - case ERRfilexists: return EEXIST; - case 87: return 0; /* Unknown error!! */ + if (errcls == ERRDOS) + switch (error) + { + case ERRbadfunc: + return EINVAL; + case ERRbadfile: + return ENOENT; + case ERRbadpath: + return ENOENT; + case ERRnofids: + return EMFILE; + case ERRnoaccess: + return EACCES; + case ERRbadfid: + return EBADF; + case ERRbadmcb: + return EREMOTEIO; + case ERRnomem: + return ENOMEM; + case ERRbadmem: + return EFAULT; + case ERRbadenv: + return EREMOTEIO; + case ERRbadformat: + return EREMOTEIO; + case ERRbadaccess: + return EACCES; + case ERRbaddata: + return E2BIG; + case ERRbaddrive: + return ENXIO; + case ERRremcd: + return EREMOTEIO; + case ERRdiffdevice: + return EXDEV; + case ERRnofiles: + return 0; + case ERRbadshare: + return ETXTBSY; + case ERRlock: + return EDEADLK; + case ERRfilexists: + return EEXIST; + case 87: + return 0; /* Unknown error!! */ /* This next error seems to occur on an mv when * the destination exists */ - case 183: return EEXIST; - default: return EIO; - } - else if (errcls == ERRSRV) - switch (error) { - case ERRerror: return ENFILE; - case ERRbadpw: return EINVAL; - case ERRbadtype: return EIO; - case ERRaccess: return EACCES; - default: return EIO; - } - else if (errcls == ERRHRD) - switch (error) { - case ERRnowrite: return EROFS; - case ERRbadunit: return ENODEV; - case ERRnotready: return EUCLEAN; - case ERRbadcmd: return EIO; - case ERRdata: return EIO; - case ERRbadreq: return ERANGE; - case ERRbadshare: return ETXTBSY; - case ERRlock: return EDEADLK; - default: return EIO; - } - else if (errcls == ERRCMD) - return EIO; + case 183: + return EEXIST; + default: + return EIO; + } else if (errcls == ERRSRV) + switch (error) + { + case ERRerror: + return ENFILE; + case ERRbadpw: + return EINVAL; + case ERRbadtype: + return EIO; + case ERRaccess: + return EACCES; + default: + return EIO; + } else if (errcls == ERRHRD) + switch (error) + { + case ERRnowrite: + return EROFS; + case ERRbadunit: + return ENODEV; + case ERRnotready: + return EUCLEAN; + case ERRbadcmd: + return EIO; + case ERRdata: + return EIO; + case ERRbadreq: + return ERANGE; + case ERRbadshare: + return ETXTBSY; + case ERRlock: + return EDEADLK; + default: + return EIO; + } else if (errcls == ERRCMD) + return EIO; return 0; } -#if DEBUG_SMB > 0 -static char -print_char(char c) -{ - if ((c < ' ') || (c > '~')) - return '.'; - return c; -} - -static void -smb_dump_packet(byte *packet) { - int i, j, len; - int errcls, error; - - errcls = (int)packet[9]; - error = (int)(int)(packet[11]|packet[12]<<8); - - printk("smb_len = %d valid = %d \n", - len = smb_len(packet), smb_valid_packet(packet)); - printk("smb_cmd = %d smb_wct = %d smb_bcc = %d\n", - packet[8], SMB_WCT(packet), SMB_BCC(packet)); - printk("smb_rcls = %d smb_err = %d\n", errcls, error); - - if (errcls) { - smb_printerr(errcls, error); - printk("\n"); - } - - if (len > 100) - len = 100; - - for (i = 0; i < len; i += 10) { - printk("%03d:", i); - for (j = i; j < i+10; j++) - if (j < len) - printk("%02x ", packet[j]); - else - printk(" "); - printk(": "); - for (j = i; j < i+10; j++) - if (j < len) - printk("%c", print_char(packet[j])); - printk("\n"); - } -} -#endif - static void smb_lock_server(struct smb_server *server) { - while (server->lock) + while (server->lock) sleep_on(&server->wait); server->lock = 1; } @@ -397,14 +411,14 @@ static void smb_unlock_server(struct smb_server *server) { - if (server->lock != 1) { - printk("smb_unlock_server: was not locked!\n"); - } - - server->lock = 0; - wake_up(&server->wait); + if (server->lock != 1) + { + printk("smb_unlock_server: was not locked!\n"); + } + server->lock = 0; + wake_up(&server->wait); } - + /* smb_request_ok: We expect the server to be locked. Then we do the request and check the answer completely. When smb_request_ok returns 0, you can be quite sure that everything went well. When @@ -413,27 +427,27 @@ static int smb_request_ok(struct smb_server *s, int command, int wct, int bcc) { - int result = 0; - s->rcls = 0; - s->err = 0; - - if (smb_request(s) < 0) { - DPRINTK("smb_request failed\n"); - result = -EIO; - } - else if (smb_valid_packet(s->packet) != 0) { - DPRINTK("not a valid packet!\n"); - result = -EIO; - } - else if (s->rcls != 0) { - result = -smb_errno(s->rcls, s->err); - } - else if (smb_verify(s->packet, command, wct, bcc) != 0) { - DPRINTK("smb_verify failed\n"); - result = -EIO; - } + int result = 0; + s->rcls = 0; + s->err = 0; - return result; + if (smb_request(s) < 0) + { + DPRINTK("smb_request failed\n"); + result = -EIO; + } else if (smb_valid_packet(s->packet) != 0) + { + DPRINTK("not a valid packet!\n"); + result = -EIO; + } else if (s->rcls != 0) + { + result = -smb_errno(s->rcls, s->err); + } else if (smb_verify(s->packet, command, wct, bcc) != 0) + { + DPRINTK("smb_verify failed\n"); + result = -EIO; + } + return result; } /* smb_retry: This function should be called when smb_request_ok has @@ -445,72 +459,73 @@ static int smb_retry(struct smb_server *server) { - if (server->state != CONN_INVALID) { - return 0; - } - - if (smb_release(server) < 0) { - DPRINTK("smb_retry: smb_release failed\n"); - server->state = CONN_RETRIED; - return 0; - } - if(smb_proc_reconnect(server) < 0) { - DPRINTK("smb_proc_reconnect failed\n"); - server->state = CONN_RETRIED; - return 0; - } - - server->state = CONN_VALID; - return 1; + if (server->state != CONN_INVALID) + { + return 0; + } + if (smb_release(server) < 0) + { + DPRINTK("smb_retry: smb_release failed\n"); + server->state = CONN_RETRIED; + return 0; + } + if (smb_proc_reconnect(server) < 0) + { + DPRINTK("smb_proc_reconnect failed\n"); + server->state = CONN_RETRIED; + return 0; + } + server->state = CONN_VALID; + return 1; } static int smb_request_ok_unlock(struct smb_server *s, int command, int wct, int bcc) { - int result = smb_request_ok(s, command, wct, bcc); + int result = smb_request_ok(s, command, wct, bcc); - smb_unlock_server(s); + smb_unlock_server(s); - return result; + return result; } - + /* smb_setup_header: We completely set up the packet. You only have to insert the command-specific fields */ -static byte * -smb_setup_header(struct smb_server *server, byte command, word wct, word bcc) +__u8 * +smb_setup_header(struct smb_server * server, byte command, word wct, word bcc) { dword xmit_len = SMB_HEADER_LEN + wct * sizeof(word) + bcc + 2; byte *p = server->packet; - byte *buf = server->packet; + byte *buf = server->packet; - p = smb_encode_smb_length(p, xmit_len); + p = smb_encode_smb_length(p, xmit_len - 4); - BSET(p,0,0xff); - BSET(p,1,'S'); - BSET(p,2,'M'); - BSET(p,3,'B'); - BSET(p,4,command); + BSET(p, 0, 0xff); + BSET(p, 1, 'S'); + BSET(p, 2, 'M'); + BSET(p, 3, 'B'); + BSET(p, 4, command); - p += 5; + p += 5; memset(p, '\0', 19); p += 19; - p += 8; + p += 8; - WSET(buf, smb_tid, server->tid); - WSET(buf, smb_pid, server->pid); - WSET(buf, smb_uid, server->server_uid); - WSET(buf, smb_mid, server->mid); - - if (server->protocol > PROTOCOL_CORE) { - BSET(buf, smb_flg, 0x8); - WSET(buf, smb_flg2, 0x3); - } - + WSET(buf, smb_tid, server->tid); + WSET(buf, smb_pid, server->pid); + WSET(buf, smb_uid, server->server_uid); + WSET(buf, smb_mid, server->mid); + + if (server->protocol > PROTOCOL_CORE) + { + BSET(buf, smb_flg, 0x8); + WSET(buf, smb_flg2, 0x3); + } *p++ = wct; /* wct */ - p += 2*wct; - WSET(p, 0, bcc); - return p+2; + p += 2 * wct; + WSET(p, 0, bcc); + return p + 2; } /* smb_setup_header_exclusive waits on server->lock and locks the @@ -519,10 +534,22 @@ static byte * smb_setup_header_exclusive(struct smb_server *server, - byte command, word wct, word bcc) + byte command, word wct, word bcc) { - smb_lock_server(server); - return smb_setup_header(server, command, wct, bcc); + smb_lock_server(server); + return smb_setup_header(server, command, wct, bcc); +} + +static void +smb_setup_bcc(struct smb_server *server, byte * p) +{ + __u8 *packet = server->packet; + __u8 *pbcc = packet + SMB_HEADER_LEN + 2 * SMB_WCT(packet); + __u16 bcc = p - (pbcc + 2); + + WSET(pbcc, 0, bcc); + smb_encode_smb_length(packet, + SMB_HEADER_LEN + 2 * SMB_WCT(packet) - 2 + bcc); } @@ -533,17 +560,19 @@ /*****************************************************************************/ int -smb_proc_open(struct smb_server *server, const char *pathname, int len, - struct smb_dirent *entry) +smb_proc_open(struct smb_server *server, + struct smb_inode_info *dir, const char *name, int len, + struct smb_dirent *entry) { int error; - char* p; - char* buf = server->packet; + char *p; + char *buf; const word o_attr = aSYSTEM | aHIDDEN | aDIR; - DPRINTK("smb_proc_open: path=%s\n", pathname); + DPRINTK("smb_proc_open: name=%s\n", name); - smb_lock_server(server); + smb_lock_server(server); + buf = server->packet; if (entry->opened != 0) { @@ -551,69 +580,74 @@ smb_unlock_server(server); return 0; } + retry: + p = smb_setup_header(server, SMBopen, 2, 0); + WSET(buf, smb_vwv0, 0x42); /* read/write */ + WSET(buf, smb_vwv1, o_attr); + *p++ = 4; + p = smb_encode_path(server, p, dir, name, len); + smb_setup_bcc(server, p); - retry: - p = smb_setup_header(server, SMBopen, 2, 2 + len); - WSET(buf, smb_vwv0, 0x42); /* read/write */ - WSET(buf, smb_vwv1, o_attr); - smb_encode_ascii(p, pathname, len); - - if ((error = smb_request_ok(server, SMBopen, 7, 0)) != 0) { - - if (smb_retry(server)) { - goto retry; - } - - if (error != -EACCES) { - smb_unlock_server(server); - return error; - } - - p = smb_setup_header(server, SMBopen, 2, 2 + len); - WSET(buf, smb_vwv0, 0x40); /* read only */ - WSET(buf, smb_vwv1, o_attr); - smb_encode_ascii(p, pathname, len); - - if ((error = smb_request_ok(server, SMBopen, 7, 0)) != 0) { - if (smb_retry(server)) { - goto retry; - } - smb_unlock_server(server); - return error; - } - } + if ((error = smb_request_ok(server, SMBopen, 7, 0)) != 0) + { + if (smb_retry(server)) + { + goto retry; + } + if ((error != -EACCES) && (error != -ETXTBSY) + && (error != -EROFS)) + { + smb_unlock_server(server); + return error; + } + p = smb_setup_header(server, SMBopen, 2, 0); + WSET(buf, smb_vwv0, 0x40); /* read only */ + WSET(buf, smb_vwv1, o_attr); + *p++ = 4; + p = smb_encode_path(server, p, dir, name, len); + smb_setup_bcc(server, p); + + if ((error = smb_request_ok(server, SMBopen, 7, 0)) != 0) + { + if (smb_retry(server)) + { + goto retry; + } + smb_unlock_server(server); + return error; + } + } /* We should now have data in vwv[0..6]. */ - entry->fileid = WVAL(buf, smb_vwv0); - entry->attr = WVAL(buf, smb_vwv1); - entry->ctime = entry->atime = - entry->mtime = local2utc(DVAL(buf, smb_vwv2)); - entry->size = DVAL(buf, smb_vwv4); - entry->access = WVAL(buf, smb_vwv6); + entry->fileid = WVAL(buf, smb_vwv0); + entry->attr = WVAL(buf, smb_vwv1); + entry->f_ctime = entry->f_atime = + entry->f_mtime = local2utc(DVAL(buf, smb_vwv2)); + entry->f_size = DVAL(buf, smb_vwv4); + entry->access = WVAL(buf, smb_vwv6); entry->opened = 1; entry->access &= 3; - smb_unlock_server(server); + smb_unlock_server(server); - DPRINTK("smb_proc_open: entry->access = %d\n", entry->access); + DPRINTK("smb_proc_open: entry->access = %d\n", entry->access); return 0; } -/* smb_proc_close: in finfo->mtime we can send a modification time to - the server */ int smb_proc_close(struct smb_server *server, __u16 fileid, __u32 mtime) { - char *buf = server->packet; + char *buf; smb_setup_header_exclusive(server, SMBclose, 3, 0); - WSET(buf, smb_vwv0, fileid); - DSET(buf, smb_vwv1, utc2local(mtime)); + buf = server->packet; + WSET(buf, smb_vwv0, fileid); + DSET(buf, smb_vwv1, utc2local(mtime)); - return smb_request_ok_unlock(server, SMBclose, 0, 0); + return smb_request_ok_unlock(server, SMBclose, 0, 0); } /* In smb_proc_read and smb_proc_write we do not retry, because the @@ -623,311 +657,333 @@ memcpy_tofs. */ int -smb_proc_read(struct smb_server *server, struct smb_dirent *finfo, - off_t offset, long count, char *data, int fs) +smb_proc_read(struct smb_server *server, struct smb_dirent *finfo, + off_t offset, long count, char *data, int fs) { word returned_count, data_len; - char *buf = server->packet; - int error; + char *buf; + int error; smb_setup_header_exclusive(server, SMBread, 5, 0); + buf = server->packet; - WSET(buf, smb_vwv0, finfo->fileid); - WSET(buf, smb_vwv1, count); - DSET(buf, smb_vwv2, offset); - WSET(buf, smb_vwv4, 0); - - if ((error = smb_request_ok(server, SMBread, 5, -1)) < 0) { - smb_unlock_server(server); - return error; - } + WSET(buf, smb_vwv0, finfo->fileid); + WSET(buf, smb_vwv1, count); + DSET(buf, smb_vwv2, offset); + WSET(buf, smb_vwv4, 0); + if ((error = smb_request_ok(server, SMBread, 5, -1)) < 0) + { + smb_unlock_server(server); + return error; + } returned_count = WVAL(buf, smb_vwv0); - + smb_decode_data(SMB_BUF(server->packet), data, &data_len, fs); - smb_unlock_server(server); + smb_unlock_server(server); - if (returned_count != data_len) { + if (returned_count != data_len) + { printk("smb_proc_read: Warning, returned_count != data_len\n"); - printk("smb_proc_read: ret_c=%d, data_len=%d\n", - returned_count, data_len); - } - - return data_len; -} - -/* count must be <= 65535. No error number is returned. A result of 0 - indicates an error, which has to be investigated by a normal read - call. */ -int -smb_proc_read_raw(struct smb_server *server, struct smb_dirent *finfo, - off_t offset, long count, char *data) -{ - char *buf = server->packet; - int result; - - if ((count <= 0) || (count > 65535)) { - return -EINVAL; - } - - smb_setup_header_exclusive(server, SMBreadbraw, 8, 0); - - WSET(buf, smb_vwv0, finfo->fileid); - DSET(buf, smb_vwv1, offset); - WSET(buf, smb_vwv3, count); - WSET(buf, smb_vwv4, 0); - DSET(buf, smb_vwv5, 0); - - result = smb_request_read_raw(server, data, count); - smb_unlock_server(server); - return result; + printk("smb_proc_read: ret_c=%d, data_len=%d\n", + returned_count, data_len); + } + return data_len; } int smb_proc_write(struct smb_server *server, struct smb_dirent *finfo, - off_t offset, int count, const char *data) + off_t offset, int count, const char *data) { - int res = 0; - char *buf = server->packet; - byte *p; + int res = 0; + char *buf; + byte *p; p = smb_setup_header_exclusive(server, SMBwrite, 5, count + 3); - WSET(buf, smb_vwv0, finfo->fileid); - WSET(buf, smb_vwv1, count); - DSET(buf, smb_vwv2, offset); - WSET(buf, smb_vwv4, 0); - - *p++ = 1; - WSET(p, 0, count); - memcpy_fromfs(p+2, data, count); - - if ((res = smb_request_ok(server, SMBwrite, 1, 0)) >= 0) { - res = WVAL(buf, smb_vwv0); - } + buf = server->packet; + WSET(buf, smb_vwv0, finfo->fileid); + WSET(buf, smb_vwv1, count); + DSET(buf, smb_vwv2, offset); + WSET(buf, smb_vwv4, 0); + + *p++ = 1; + WSET(p, 0, count); + memcpy_fromfs(p + 2, data, count); - smb_unlock_server(server); + if ((res = smb_request_ok(server, SMBwrite, 1, 0)) >= 0) + { + res = WVAL(buf, smb_vwv0); + } + smb_unlock_server(server); return res; } -/* count must be <= 65535 */ int -smb_proc_write_raw(struct smb_server *server, struct smb_dirent *finfo, - off_t offset, long count, const char *data) +smb_proc_create(struct inode *dir, const char *name, int len, + word attr, time_t ctime) { - char *buf = server->packet; - int result; + int error; + char *p; + struct smb_server *server = SMB_SERVER(dir); + char *buf; + __u16 fileid; - if ((count <= 0) || (count > 65535)) { - return -EINVAL; - } - - smb_setup_header_exclusive(server, SMBwritebraw, 11, 0); - - WSET(buf, smb_vwv0, finfo->fileid); - WSET(buf, smb_vwv1, count); - WSET(buf, smb_vwv2, 0); /* reserved */ - DSET(buf, smb_vwv3, offset); - DSET(buf, smb_vwv5, 0); /* timeout */ - WSET(buf, smb_vwv7, 1); /* send final result response */ - DSET(buf, smb_vwv8, 0); /* reserved */ - WSET(buf, smb_vwv10, 0); /* no data in this buf */ - WSET(buf, smb_vwv11, 0); /* no data in this buf */ - - result = smb_request_ok(server, SMBwritebraw, 1, 0); - - DPRINTK("smb_proc_write_raw: first request returned %d\n", result); - - if (result < 0) { - smb_unlock_server(server); - return result; - } - - result = smb_request_write_raw(server, data, count); - - DPRINTK("smb_proc_write_raw: raw request returned %d\n", result); - - if (result > 0) { - /* We have to do the checks of smb_request_ok here as well */ - if (smb_valid_packet(server->packet) != 0) { - DPRINTK("not a valid packet!\n"); - result = -EIO; - } else if (server->rcls != 0) { - result = -smb_errno(server->rcls, server->err); - } else if (smb_verify(server->packet, SMBwritec,1,0) != 0) { - DPRINTK("smb_verify failed\n"); - result = -EIO; - } - } + smb_lock_server(server); + buf = server->packet; + retry: + p = smb_setup_header(server, SMBcreate, 3, 0); + WSET(buf, smb_vwv0, attr); + DSET(buf, smb_vwv1, utc2local(ctime)); + *p++ = 4; + p = smb_encode_path(server, p, SMB_INOP(dir), name, len); + smb_setup_bcc(server, p); - smb_unlock_server(server); - return result; -} + if ((error = smb_request_ok(server, SMBcreate, 1, 0)) < 0) + { + if (smb_retry(server)) + { + goto retry; + } + smb_unlock_server(server); + return error; + } + fileid = WVAL(buf, smb_vwv0); + smb_unlock_server(server); + smb_proc_close(server, fileid, CURRENT_TIME); -/* smb_proc_create: We expect entry->attr & entry->ctime to be set. */ + return 0; +} int -smb_proc_create(struct smb_server *server, const char *path, int len, - struct smb_dirent *entry) +smb_proc_mv(struct inode *odir, const char *oname, const int olen, + struct inode *ndir, const char *nname, const int nlen) { - int error; char *p; - char *buf = server->packet; - __u16 fileid; + struct smb_server *server = SMB_SERVER(odir); + char *buf; + int result; smb_lock_server(server); - retry: - p = smb_setup_header(server, SMBcreate, 3, len + 2); - WSET(buf, smb_vwv0, entry->attr); - DSET(buf, smb_vwv1, utc2local(entry->ctime)); - smb_encode_ascii(p, path, len); - - if ((error = smb_request_ok(server, SMBcreate, 1, 0)) < 0) { - if (smb_retry(server)) { - goto retry; - } - smb_unlock_server(server); - return error; - } - - entry->opened = 0; - fileid = WVAL(buf, smb_vwv0); - smb_unlock_server(server); + buf = server->packet; - smb_proc_close(server, fileid, 0); + retry: + p = smb_setup_header(server, SMBmv, 1, 0); + WSET(buf, smb_vwv0, aSYSTEM | aHIDDEN); + *p++ = 4; + p = smb_encode_path(server, p, SMB_INOP(odir), oname, olen); + *p++ = 4; + p = smb_encode_path(server, p, SMB_INOP(ndir), nname, nlen); + smb_setup_bcc(server, p); - return 0; + if ((result = smb_request_ok(server, SMBmv, 0, 0)) < 0) + { + if (smb_retry(server)) + { + goto retry; + } + } + smb_unlock_server(server); + return result; } int -smb_proc_mv(struct smb_server *server, - const char *opath, const int olen, - const char *npath, const int nlen) +smb_proc_mkdir(struct inode *dir, const char *name, const int len) { char *p; - char *buf = server->packet; - int result; + int result; + struct smb_server *server = SMB_SERVER(dir); + + smb_lock_server(server); - smb_lock_server(server); + retry: + p = smb_setup_header(server, SMBmkdir, 0, 0); + *p++ = 4; + p = smb_encode_path(server, p, SMB_INOP(dir), name, len); + smb_setup_bcc(server, p); - retry: - p = smb_setup_header(server, SMBmv, 1, olen + nlen + 4); - WSET(buf, smb_vwv0, 0); - p = smb_encode_ascii(p, opath, olen); - smb_encode_ascii(p, npath, olen); - - if ((result = smb_request_ok(server, SMBmv, 0, 0)) < 0) { - if (smb_retry(server)) { - goto retry; - } - } - smb_unlock_server(server); - return result; + if ((result = smb_request_ok(server, SMBmkdir, 0, 0)) < 0) + { + if (smb_retry(server)) + { + goto retry; + } + } + smb_unlock_server(server); + return result; } int -smb_proc_mkdir(struct smb_server *server, const char *path, const int len) +smb_proc_rmdir(struct inode *dir, const char *name, const int len) { char *p; - int result; + int result; + struct smb_server *server = SMB_SERVER(dir); + + smb_lock_server(server); + - smb_lock_server(server); + retry: + p = smb_setup_header(server, SMBrmdir, 0, 0); + *p++ = 4; + p = smb_encode_path(server, p, SMB_INOP(dir), name, len); + smb_setup_bcc(server, p); - retry: - p = smb_setup_header(server, SMBmkdir, 0, 2 + len); - smb_encode_ascii(p, path, len); - - if ((result = smb_request_ok(server, SMBmkdir, 0, 0)) < 0) { - if (smb_retry(server)) { - goto retry; - } - } - smb_unlock_server(server); - return result; + if ((result = smb_request_ok(server, SMBrmdir, 0, 0)) < 0) + { + if (smb_retry(server)) + { + goto retry; + } + } + smb_unlock_server(server); + return result; } int -smb_proc_rmdir(struct smb_server *server, const char *path, const int len) +smb_proc_unlink(struct inode *dir, const char *name, const int len) { char *p; - int result; + struct smb_server *server = SMB_SERVER(dir); + char *buf; + int result; + + smb_lock_server(server); + buf = server->packet; - smb_lock_server(server); + retry: + p = smb_setup_header(server, SMBunlink, 1, 0); + WSET(buf, smb_vwv0, aSYSTEM | aHIDDEN); + *p++ = 4; + p = smb_encode_path(server, p, SMB_INOP(dir), name, len); + smb_setup_bcc(server, p); - retry: - p = smb_setup_header(server, SMBrmdir, 0, 2 + len); - smb_encode_ascii(p, path, len); - - if ((result = smb_request_ok(server, SMBrmdir, 0, 0)) < 0) { - if (smb_retry(server)) { - goto retry; - } - } - smb_unlock_server(server); - return result; + if ((result = smb_request_ok(server, SMBunlink, 0, 0)) < 0) + { + if (smb_retry(server)) + { + goto retry; + } + } + smb_unlock_server(server); + return result; } int -smb_proc_unlink(struct smb_server *server, const char *path, const int len) +smb_proc_trunc(struct smb_server *server, word fid, dword length) { char *p; - char *buf = server->packet; - int result; + char *buf; + int result; - smb_lock_server(server); + smb_lock_server(server); + buf = server->packet; - retry: - p = smb_setup_header(server, SMBunlink, 1, 2 + len); - WSET(buf, smb_vwv0, 0); - smb_encode_ascii(p, path, len); - - if ((result = smb_request_ok(server, SMBunlink, 0, 0)) < 0) { - if (smb_retry(server)) { - goto retry; - } - } - smb_unlock_server(server); - return result; + retry: + p = smb_setup_header(server, SMBwrite, 5, 0); + WSET(buf, smb_vwv0, fid); + WSET(buf, smb_vwv1, 0); + DSET(buf, smb_vwv2, length); + WSET(buf, smb_vwv4, 0); + p = smb_encode_ascii(p, "", 0); + smb_setup_bcc(server, p); + + if ((result = smb_request_ok(server, SMBwrite, 1, 0)) < 0) + { + if (smb_retry(server)) + { + goto retry; + } + } + smb_unlock_server(server); + return result; } -int -smb_proc_trunc(struct smb_server *server, word fid, dword length) +static void +smb_init_dirent(struct smb_server *server, struct smb_dirent *entry) { - char *p; - char *buf = server->packet; - int result; - - smb_lock_server(server); - - retry: - p = smb_setup_header(server, SMBwrite, 5, 3); - WSET(buf, smb_vwv0, fid); - WSET(buf, smb_vwv1, 0); - DSET(buf, smb_vwv2, length); - WSET(buf, smb_vwv4, 0); - smb_encode_ascii(p, "", 0); - - if ((result = smb_request_ok(server, SMBwrite, 1, 0)) < 0) { - if (smb_retry(server)) { - goto retry; - } - } - smb_unlock_server(server); - return result; + memset(entry, 0, sizeof(struct smb_dirent)); + + entry->f_nlink = 1; + entry->f_uid = server->m.uid; + entry->f_gid = server->m.gid; + entry->f_blksize = 512; } +static void +smb_finish_dirent(struct smb_server *server, struct smb_dirent *entry) +{ + if ((entry->attr & aDIR) != 0) + { + entry->f_mode = server->m.dir_mode; + entry->f_size = 512; + } else + { + entry->f_mode = server->m.file_mode; + } + + if ((entry->f_blksize != 0) && (entry->f_size != 0)) + { + entry->f_blocks = + (entry->f_size - 1) / entry->f_blksize + 1; + } else + { + entry->f_blocks = 0; + } + return; +} + +void +smb_init_root_dirent(struct smb_server *server, struct smb_dirent *entry) +{ + smb_init_dirent(server, entry); + entry->attr = aDIR; + entry->f_ino = 1; + smb_finish_dirent(server, entry); +} + + static char * -smb_decode_dirent(char *p, struct smb_dirent *entry) +smb_decode_dirent(struct smb_server *server, char *p, struct smb_dirent *entry) { - p += SMB_STATUS_SIZE; /* reserved (search_status) */ - entry->attr = BVAL(p, 0); - entry->mtime = entry->atime = entry->ctime = - date_dos2unix(WVAL(p, 1), WVAL(p, 3)); - entry->size = DVAL(p, 5); - memcpy(entry->path, p+9, 13); - DDPRINTK("smb_decode_dirent: path = %s\n", entry->path); + smb_init_dirent(server, entry); + + p += SMB_STATUS_SIZE; /* reserved (search_status) */ + entry->attr = BVAL(p, 0); + entry->f_mtime = entry->f_atime = entry->f_ctime = + date_dos2unix(WVAL(p, 1), WVAL(p, 3)); + entry->f_size = DVAL(p, 5); + entry->len = strlen(p + 9); + if (entry->len > 12) + { + entry->len = 12; + } + memcpy(entry->name, p + 9, entry->len); + entry->name[entry->len] = '\0'; + while (entry->len > 2) + { + /* Pathworks fills names with spaces */ + entry->len -= 1; + if (entry->name[entry->len] == ' ') + { + entry->name[entry->len] = '\0'; + } + } + switch (server->case_handling) + { + case CASE_UPPER: + str_upper(entry->name); + break; + case CASE_LOWER: + str_lower(entry->name); + break; + default: + break; + } + DPRINTK("smb_decode_dirent: name = %s\n", entry->name); + smb_finish_dirent(server, entry); return p + 22; } @@ -940,118 +996,126 @@ int cache_size, struct smb_dirent *entry) { char *p; - char *buf; + char *buf; int error; - int result; + int result; int i; int first, total_count; - struct smb_dirent *current_entry; + struct smb_dirent *current_entry; word bcc; word count; char status[SMB_STATUS_SIZE]; int entries_asked = (server->max_xmit - 100) / SMB_DIRINFO_SIZE; - int dirlen = strlen(SMB_FINFO(dir)->path); - char mask[dirlen + 5]; - - strcpy(mask, SMB_FINFO(dir)->path); - strcat(mask, "\\*.*"); - - DPRINTK("SMB call readdir %d @ %d\n", cache_size, fpos); - DPRINTK(" mask = %s\n", mask); - buf = server->packet; + DPRINTK("SMB call readdir %d @ %d\n", cache_size, fpos); - smb_lock_server(server); + smb_lock_server(server); + buf = server->packet; - retry: + retry: first = 1; - total_count = 0; - current_entry = entry; - - while (1) { - if (first == 1) { - p = smb_setup_header(server, SMBsearch, 2, - 5 + strlen(mask)); - WSET(buf, smb_vwv0, entries_asked); - WSET(buf, smb_vwv1, aDIR); - p = smb_encode_ascii(p, mask, strlen(mask)); - *p ++ = 5; - p = smb_encode_word(p, 0); - } else { - p = smb_setup_header(server, SMBsearch, 2, - 5 + SMB_STATUS_SIZE); - WSET(buf, smb_vwv0, entries_asked); - WSET(buf, smb_vwv1, aDIR); + total_count = 0; + current_entry = entry; + + while (1) + { + if (first == 1) + { + p = smb_setup_header(server, SMBsearch, 2, 0); + WSET(buf, smb_vwv0, entries_asked); + WSET(buf, smb_vwv1, aDIR); + *p++ = 4; + p = smb_encode_path(server, p, SMB_INOP(dir), "*.*", 3); + *p++ = 5; + WSET(p, 0, 0); + p += 2; + } else + { + p = smb_setup_header(server, SMBsearch, 2, 0); + WSET(buf, smb_vwv0, entries_asked); + WSET(buf, smb_vwv1, aDIR); p = smb_encode_ascii(p, "", 0); - p = smb_encode_vblock(p, status, SMB_STATUS_SIZE, 0); + *p++ = 5; + WSET(p, 0, SMB_STATUS_SIZE); + p += 2; + memcpy(p, status, SMB_STATUS_SIZE); + p += SMB_STATUS_SIZE; } - - if ((error = smb_request_ok(server, SMBsearch, 1, -1)) < 0) { - if ( (server->rcls == ERRDOS) - && (server->err == ERRnofiles)) { - result = total_count - fpos; - goto unlock_return; - } - else - { - if (smb_retry(server)) { - goto retry; - } - result = error; - goto unlock_return; - } - } + smb_setup_bcc(server, p); + + if ((error = smb_request_ok(server, SMBsearch, 1, -1)) < 0) + { + if ((server->rcls == ERRDOS) + && (server->err == ERRnofiles)) + { + result = total_count - fpos; + goto unlock_return; + } else + { + if (smb_retry(server)) + { + goto retry; + } + result = error; + goto unlock_return; + } + } p = SMB_VWV(server->packet); - p = smb_decode_word(p, &count); /* vwv[0] = count-returned */ - p = smb_decode_word(p, &bcc); - + p = smb_decode_word(p, &count); + p = smb_decode_word(p, &bcc); + first = 0; - - if (count <= 0) { + + if (count <= 0) + { result = total_count - fpos; - goto unlock_return; - } - if (bcc != count * SMB_DIRINFO_SIZE + 3) { + goto unlock_return; + } + if (bcc != count * SMB_DIRINFO_SIZE + 3) + { result = -EIO; - goto unlock_return; - } - - p += 3; /* Skipping VBLOCK header (5, length lo, length hi). */ + goto unlock_return; + } + p += 3; /* Skipping VBLOCK header + (5, length lo, length hi). */ /* Read the last entry into the status field. */ memcpy(status, - SMB_BUF(server->packet) + 3 + - (count - 1) * SMB_DIRINFO_SIZE, - SMB_STATUS_SIZE); + SMB_BUF(server->packet) + 3 + + (count - 1) * SMB_DIRINFO_SIZE, + SMB_STATUS_SIZE); /* Now we are ready to parse smb directory entries. */ - - for (i = 0; i < count; i ++) { - if (total_count < fpos) { + + for (i = 0; i < count; i++) + { + if (total_count < fpos) + { p += SMB_DIRINFO_SIZE; DDPRINTK("smb_proc_readdir: skipped entry.\n"); DDPRINTK(" total_count = %d\n" - " i = %d, fpos = %d\n", - total_count, i, fpos); - } - else if (total_count >= fpos + cache_size) { - result = total_count - fpos; - goto unlock_return; - } - else { - p = smb_decode_dirent(p, current_entry); + " i = %d, fpos = %d\n", + total_count, i, fpos); + } else if (total_count >= fpos + cache_size) + { + result = total_count - fpos; + goto unlock_return; + } else + { + p = smb_decode_dirent(server, p, + current_entry); current_entry->f_pos = total_count; DDPRINTK("smb_proc_readdir: entry->f_pos = " - "%lu\n", entry->f_pos); + "%lu\n", entry->f_pos); current_entry += 1; } total_count += 1; } } - unlock_return: - smb_unlock_server(server); - return result; + unlock_return: + smb_unlock_server(server); + return result; } /* interpret a long filename structure - this is mostly guesses at the @@ -1060,524 +1124,483 @@ is used by OS/2. */ static char * -smb_decode_long_dirent(char *p, struct smb_dirent *finfo, int level) +smb_decode_long_dirent(struct smb_server *server, char *p, + struct smb_dirent *entry, int level) { - char *result; + char *result; - if (finfo) { - /* I have to set times to 0 here, because I do not - have specs about this for all info levels. */ - finfo->ctime = finfo->mtime = finfo->atime = 0; - } - - switch (level) - { - case 1: /* OS/2 understands this */ - if (finfo) - { - DPRINTK("received entry\n"); - strcpy(finfo->path,p+27); - finfo->len = strlen(finfo->path); - finfo->size = DVAL(p,16); - finfo->attr = BVAL(p,24); - - finfo->ctime = date_dos2unix(WVAL(p, 6), WVAL(p, 4)); - finfo->atime = date_dos2unix(WVAL(p, 10), WVAL(p, 8)); - finfo->mtime = date_dos2unix(WVAL(p, 14), WVAL(p, 12)); - } - result = p + 28 + BVAL(p,26); - break; - - case 2: /* this is what OS/2 uses */ - if (finfo) - { - strcpy(finfo->path,p+31); - finfo->len = strlen(finfo->path); - finfo->size = DVAL(p,16); - finfo->attr = BVAL(p,24); -#if 0 - finfo->atime = make_unix_date2(p+8); - finfo->mtime = make_unix_date2(p+12); -#endif - } - result = p + 32 + BVAL(p,30); - break; - - case 260: /* NT uses this, but also accepts 2 */ - result = p + WVAL(p,0); - if (finfo) - { - int namelen; - p += 4; /* next entry offset */ - p += 4; /* fileindex */ - /* finfo->ctime = interpret_filetime(p);*/ - p += 8; - /* finfo->atime = interpret_filetime(p);*/ - p += 8; - p += 8; /* write time */ - /* finfo->mtime = interpret_filetime(p);*/ - p += 8; - finfo->size = DVAL(p,0); - p += 8; - p += 8; /* alloc size */ - finfo->attr = BVAL(p,0); - p += 4; - namelen = min(DVAL(p,0), SMB_MAXNAMELEN); - p += 4; - p += 4; /* EA size */ - p += 2; /* short name len? */ - p += 24; /* short name? */ - strncpy(finfo->path,p,namelen); - finfo->len = namelen; - } - break; - - default: - DPRINTK("Unknown long filename format %d\n",level); - result = p + WVAL(p,0); - } - return result; + smb_init_dirent(server, entry); + + switch (level) + { + /* We might add more levels later... */ + case 1: + entry->len = BVAL(p, 26); + strncpy(entry->name, p + 27, entry->len); + entry->name[entry->len] = '\0'; + entry->f_size = DVAL(p, 16); + entry->attr = BVAL(p, 24); + + entry->f_ctime = date_dos2unix(WVAL(p, 6), WVAL(p, 4)); + entry->f_atime = date_dos2unix(WVAL(p, 10), WVAL(p, 8)); + entry->f_mtime = date_dos2unix(WVAL(p, 14), WVAL(p, 12)); + result = p + 28 + BVAL(p, 26); + break; + + default: + DPRINTK("Unknown long filename format %d\n", level); + result = p + WVAL(p, 0); + } + + switch (server->case_handling) + { + case CASE_UPPER: + str_upper(entry->name); + break; + case CASE_LOWER: + str_lower(entry->name); + break; + default: + break; + } + + smb_finish_dirent(server, entry); + return result; } int smb_proc_readdir_long(struct smb_server *server, struct inode *dir, int fpos, - int cache_size, struct smb_dirent *entry) + int cache_size, struct smb_dirent *cache) { - int max_matches = 64; /* this should actually be based on the - maxxmit */ - - /* NT uses 260, OS/2 uses 2. Both accept 1. */ - int info_level = 1; + /* NT uses 260, OS/2 uses 2. Both accept 1. */ + const int info_level = 1; + const int max_matches = 512; char *p; char *lastname; - int lastname_len; + int lastname_len; int i; - int first, total_count; - struct smb_dirent *current_entry; + int first, entries, entries_seen; - char *resp_data; - char *resp_param; - int resp_data_len = 0; - int resp_param_len=0; + unsigned char *resp_data = NULL; + unsigned char *resp_param = NULL; + int resp_data_len = 0; + int resp_param_len = 0; - int attribute = aSYSTEM | aHIDDEN | aDIR; - int result; + __u16 command; - int ff_resume_key = 0; - int ff_searchcount=0; - int ff_eos=0; - int ff_lastname=0; - int ff_dir_handle=0; - int loop_count = 0; + int result; - int dirlen = strlen(SMB_FINFO(dir)->path) + 3; - char *mask; + int ff_resume_key = 0; + int ff_searchcount = 0; + int ff_eos = 0; + int ff_lastname = 0; + int ff_dir_handle = 0; + int loop_count = 0; + + char param[SMB_MAXPATHLEN + 2 + 12]; + int mask_len; + unsigned char *mask = &(param[12]); - mask = smb_kmalloc(dirlen, GFP_KERNEL); - if (mask == NULL) - { - printk("smb_proc_readdir_long: Memory allocation failed\n"); - return -ENOMEM; - } - strcpy(mask, SMB_FINFO(dir)->path); - strcat(mask, "\\*"); + mask_len = smb_encode_path(server, mask, + SMB_INOP(dir), "*", 1) - mask; - DPRINTK("SMB call lreaddir %d @ %d\n", cache_size, fpos); - DPRINTK(" mask = %s\n", mask); + mask[mask_len] = 0; + mask[mask_len + 1] = 0; - resp_param = NULL; - resp_data = NULL; + DPRINTK("smb_readdir_long cache=%d, fpos=%d, mask=%s\n", + cache_size, fpos, mask); - smb_lock_server(server); + smb_lock_server(server); - retry: + retry: first = 1; - total_count = 0; - current_entry = entry; - - while (ff_eos == 0) - { - int masklen = strlen(mask); - unsigned char *outbuf = server->packet; - - loop_count += 1; - if (loop_count > 200) - { - printk("smb_proc_readdir_long: " - "Looping in FIND_NEXT??\n"); - break; - } - - smb_setup_header(server, SMBtrans2, 15, - 5 + 12 + masklen + 1); - - WSET(outbuf,smb_tpscnt,12 + masklen +1); - WSET(outbuf,smb_tdscnt,0); - WSET(outbuf,smb_mprcnt,10); - WSET(outbuf,smb_mdrcnt,TRANS2_MAX_TRANSFER); - WSET(outbuf,smb_msrcnt,0); - WSET(outbuf,smb_flags,0); - DSET(outbuf,smb_timeout,0); - WSET(outbuf,smb_pscnt,WVAL(outbuf,smb_tpscnt)); - WSET(outbuf,smb_psoff,((SMB_BUF(outbuf)+3) - outbuf)-4); - WSET(outbuf,smb_dscnt,0); - WSET(outbuf,smb_dsoff,0); - WSET(outbuf,smb_suwcnt,1); - WSET(outbuf,smb_setup0, - first == 1 ? TRANSACT2_FINDFIRST : TRANSACT2_FINDNEXT); - - p = SMB_BUF(outbuf); - *p++=0; /* put in a null smb_name */ - *p++='D'; *p++ = ' '; /* this was added because OS/2 does it */ - - if (first != 0) - { - WSET(p,0,attribute); /* attribute */ - WSET(p,2,max_matches); /* max count */ - WSET(p,4,8+4+2); /* resume required + close on end + - continue */ - WSET(p,6,info_level); - DSET(p,8,0); - p += 12; - strncpy(p, mask, masklen); - p += masklen; - *p++ = 0; *p++ = 0; - } - else - { - DPRINTK("hand=0x%X resume=%d ff_lastname=%d mask=%s\n", - ff_dir_handle,ff_resume_key,ff_lastname,mask); - WSET(p,0,ff_dir_handle); - WSET(p,2,max_matches); /* max count */ - WSET(p,4,info_level); - DSET(p,6,ff_resume_key); /* ff_resume_key */ - WSET(p,10,8+4+2); /* resume required + close on end + - continue */ - p += 12; - strncpy(p, mask, masklen); - p += masklen; - *p++ = 0; *p++ = 0; - } - - result = smb_trans2_request(server, - &resp_data_len,&resp_param_len, - &resp_data,&resp_param); - - if (result < 0) { - if (smb_retry(server)) { - goto retry; - } - DPRINTK("smb_proc_readdir_long: " - "got error from trans2_request\n"); - break; - } - - if (server->rcls != 0) - { - result = -EIO; - break; - } - - /* parse out some important return info */ - p = resp_param; - if (first != 0) - { - ff_dir_handle = WVAL(p,0); - ff_searchcount = WVAL(p,2); - ff_eos = WVAL(p,4); - ff_lastname = WVAL(p,8); - } - else - { - ff_searchcount = WVAL(p,0); - ff_eos = WVAL(p,2); - ff_lastname = WVAL(p,6); - } + entries = 0; + entries_seen = 2; + + while (ff_eos == 0) + { + loop_count += 1; + if (loop_count > 200) + { + printk("smb_proc_readdir_long: " + "Looping in FIND_NEXT??\n"); + break; + } + if (first != 0) + { + command = TRANSACT2_FINDFIRST; + WSET(param, 0, aSYSTEM | aHIDDEN | aDIR); + WSET(param, 2, max_matches); /* max count */ + WSET(param, 4, 8 + 4 + 2); /* resume required + + close on end + + continue */ + WSET(param, 6, info_level); + DSET(param, 8, 0); + } else + { + command = TRANSACT2_FINDNEXT; + DPRINTK("hand=0x%X resume=%d ff_lastname=%d mask=%s\n", + ff_dir_handle, ff_resume_key, ff_lastname, mask); + WSET(param, 0, ff_dir_handle); + WSET(param, 2, max_matches); /* max count */ + WSET(param, 4, info_level); + DSET(param, 6, ff_resume_key); /* ff_resume_key */ + WSET(param, 10, 8 + 4 + 2); /* resume required + + close on end + + continue */ +#ifdef CONFIG_SMB_WIN95 + /* Windows 95 is not able to deliver answers + to FIND_NEXT fast enough, so sleep 0.2 seconds */ + current->timeout = jiffies + HZ / 5; + current->state = TASK_INTERRUPTIBLE; + schedule(); + current->timeout = 0; +#endif + } - if (ff_searchcount == 0) - break; + result = smb_trans2_request(server, command, + 0, NULL, 12 + mask_len + 2, param, + &resp_data_len, &resp_data, + &resp_param_len, &resp_param); + + if (result < 0) + { + if (smb_retry(server)) + { + goto retry; + } + DPRINTK("smb_proc_readdir_long: " + "got error from trans2_request\n"); + break; + } + if (server->rcls != 0) + { + result = -EIO; + break; + } + /* parse out some important return info */ + if (first != 0) + { + ff_dir_handle = WVAL(resp_param, 0); + ff_searchcount = WVAL(resp_param, 2); + ff_eos = WVAL(resp_param, 4); + ff_lastname = WVAL(resp_param, 8); + } else + { + ff_searchcount = WVAL(resp_param, 0); + ff_eos = WVAL(resp_param, 2); + ff_lastname = WVAL(resp_param, 6); + } - /* point to the data bytes */ - p = resp_data; + if (ff_searchcount == 0) + { + break; + } + /* point to the data bytes */ + p = resp_data; - /* we might need the lastname for continuations */ + /* we might need the lastname for continuations */ lastname = ""; lastname_len = 0; - if (ff_lastname > 0) - { - switch(info_level) - { - case 260: + if (ff_lastname > 0) + { + switch (info_level) + { + case 260: lastname = p + ff_lastname; lastname_len = resp_data_len - ff_lastname; ff_resume_key = 0; - break; - case 1: + break; + case 1: lastname = p + ff_lastname + 1; - lastname_len = strlen(lastname); - ff_resume_key = 0; - break; - } - } - - /* Increase size of mask, if it is too small */ - i = strlen(lastname) + 1; - if (i > dirlen) - { - smb_kfree_s(mask, 0); - dirlen = i; - mask = smb_kmalloc(dirlen, GFP_KERNEL); - if (mask == NULL) - { - printk("smb_proc_readdir_long: " - "Memory allocation failed\n"); - result = -ENOMEM; + lastname_len = BVAL(p, ff_lastname); + ff_resume_key = 0; break; } } + lastname_len = min(lastname_len, 256); strncpy(mask, lastname, lastname_len); mask[lastname_len] = '\0'; - + /* Now we are ready to parse smb directory entries. */ - - for (i = 0; i < ff_searchcount; i ++) { - if (total_count < fpos) { - p = smb_decode_long_dirent(p, NULL, - info_level); - DPRINTK("smb_proc_readdir: skipped entry.\n"); - DDPRINTK(" total_count = %d\n" - " i = %d, fpos = %d\n", - total_count, i, fpos); - } - else if (total_count >= fpos + cache_size) { - goto finished; + + for (i = 0; i < ff_searchcount; i++) + { + struct smb_dirent *entry = &(cache[entries]); + + p = smb_decode_long_dirent(server, p, + entry, info_level); + + DDPRINTK("smb_readdir_long: got %s\n", entry->name); + + if ((entry->name[0] == '.') + && ((entry->name[1] == '\0') + || ((entry->name[1] == '.') + && (entry->name[2] == '\0')))) + { + /* ignore . and .. from the server */ + continue; } - else { - p = smb_decode_long_dirent(p, current_entry, - info_level); - current_entry->f_pos = total_count; - DDPRINTK("smb_proc_readdir: entry->f_pos = " - "%lu\n", entry->f_pos); - current_entry += 1; + if (entries_seen >= fpos) + { + entry->f_pos = entries_seen; + entries += 1; } - total_count += 1; + if (entries >= cache_size) + { + goto finished; + } + entries_seen += 1; } - if (resp_data != NULL) { - smb_kfree_s(resp_data, 0); - resp_data = NULL; - } - if (resp_param != NULL) { - smb_kfree_s(resp_param, 0); - resp_param = NULL; - } - - DPRINTK("received %d entries (eos=%d resume=%d)\n", - ff_searchcount,ff_eos,ff_resume_key); - - first = 0; - } - - finished: - if (mask != NULL) - smb_kfree_s(mask, 0); - - if (resp_data != NULL) { - smb_kfree_s(resp_data, 0); - resp_data = NULL; - } - if (resp_param != NULL) { - smb_kfree_s(resp_param, 0); - resp_param = NULL; - } + DPRINTK("received %d entries (eos=%d resume=%d)\n", + ff_searchcount, ff_eos, ff_resume_key); - smb_unlock_server(server); + first = 0; + } - return total_count - fpos; + finished: + smb_unlock_server(server); + return entries; } int smb_proc_readdir(struct smb_server *server, struct inode *dir, int fpos, int cache_size, struct smb_dirent *entry) { - if (server->protocol >= PROTOCOL_LANMAN2) - return smb_proc_readdir_long(server, dir, fpos, cache_size, - entry); - else - return smb_proc_readdir_short(server, dir, fpos, cache_size, - entry); + if (server->protocol >= PROTOCOL_LANMAN2) + return smb_proc_readdir_long(server, dir, fpos, cache_size, + entry); + else + return smb_proc_readdir_short(server, dir, fpos, cache_size, + entry); } - + static int -smb_proc_getattr_core(struct smb_server *server, const char *path, int len, - struct smb_dirent *entry) +smb_proc_getattr_core(struct inode *dir, const char *name, int len, + struct smb_dirent *entry) { int result; char *p; - char *buf = server->packet; + struct smb_server *server = SMB_SERVER(dir); + char *buf; - smb_lock_server(server); + smb_lock_server(server); + buf = server->packet; - DDPRINTK("smb_proc_getattr: %s\n", path); + DDPRINTK("smb_proc_getattr: %s\n", name); - retry: - p = smb_setup_header(server, SMBgetatr, 0, 2 + len); - smb_encode_ascii(p, path, len); - - if ((result = smb_request_ok(server, SMBgetatr, 10, 0)) < 0) { - if (smb_retry(server)) { - goto retry; - } - smb_unlock_server(server); - return result; - } + retry: + p = smb_setup_header(server, SMBgetatr, 0, 0); + *p++ = 4; + p = smb_encode_path(server, p, SMB_INOP(dir), name, len); + smb_setup_bcc(server, p); - entry->attr = WVAL(buf, smb_vwv0); - entry->ctime = entry->atime = /* The server only tells us 1 time */ - entry->mtime = local2utc(DVAL(buf, smb_vwv1)); + if ((result = smb_request_ok(server, SMBgetatr, 10, 0)) < 0) + { + if (smb_retry(server)) + { + goto retry; + } + smb_unlock_server(server); + return result; + } + entry->attr = WVAL(buf, smb_vwv0); + entry->f_ctime = entry->f_atime = + entry->f_mtime = local2utc(DVAL(buf, smb_vwv1)); - entry->size = DVAL(buf, smb_vwv3); - smb_unlock_server(server); + entry->f_size = DVAL(buf, smb_vwv3); + smb_unlock_server(server); return 0; } -/* smb_proc_getattrE: entry->fid must be valid */ - static int -smb_proc_getattrE(struct smb_server *server, struct smb_dirent *entry) +smb_proc_getattr_trans2(struct inode *dir, const char *name, int len, + struct smb_dirent *entry) { - char* buf = server->packet; - int result; + struct smb_server *server = SMB_SERVER(dir); + char param[SMB_MAXPATHLEN + 20]; + char *p; + int result; - smb_setup_header_exclusive(server, SMBgetattrE, 1, 0); - WSET(buf, smb_vwv0, entry->fileid); + unsigned char *resp_data = NULL; + unsigned char *resp_param = NULL; + int resp_data_len = 0; + int resp_param_len = 0; + + WSET(param, 0, 1); /* Info level SMB_INFO_STANDARD */ + DSET(param, 2, 0); + p = smb_encode_path(server, param + 6, SMB_INOP(dir), name, len); - if ((result = smb_request_ok(server, SMBgetattrE, 11, 0)) != 0) { - smb_unlock_server(server); - return result; - } - - entry->ctime = date_dos2unix(WVAL(buf, smb_vwv1), WVAL(buf, smb_vwv0)); - entry->atime = date_dos2unix(WVAL(buf, smb_vwv3), WVAL(buf, smb_vwv2)); - entry->mtime = date_dos2unix(WVAL(buf, smb_vwv5), WVAL(buf, smb_vwv4)); - entry->size = DVAL(buf, smb_vwv6); - entry->attr = WVAL(buf, smb_vwv10); + smb_lock_server(server); + retry: + result = smb_trans2_request(server, TRANSACT2_QPATHINFO, + 0, NULL, p - param, param, + &resp_data_len, &resp_data, + &resp_param_len, &resp_param); - smb_unlock_server(server); - return 0; + if (server->rcls != 0) + { + smb_unlock_server(server); + return -smb_errno(server->rcls, server->err); + } + if (result < 0) + { + if (smb_retry(server)) + { + goto retry; + } + smb_unlock_server(server); + return result; + } + if (resp_data_len < 22) + { + smb_unlock_server(server); + return -ENOENT; + } + entry->f_ctime = date_dos2unix(WVAL(resp_data, 2), + WVAL(resp_data, 0)); + entry->f_atime = date_dos2unix(WVAL(resp_data, 6), + WVAL(resp_data, 4)); + entry->f_mtime = date_dos2unix(WVAL(resp_data, 10), + WVAL(resp_data, 8)); + entry->f_size = DVAL(resp_data, 12); + entry->attr = WVAL(resp_data, 20); + smb_unlock_server(server); + + return 0; } int -smb_proc_getattr(struct smb_server *server, const char *path, int len, - struct smb_dirent *entry) +smb_proc_getattr(struct inode *dir, const char *name, int len, + struct smb_dirent *entry) { - if (server->protocol >= PROTOCOL_LANMAN1) { + struct smb_server *server = SMB_SERVER(dir); + int result = 0; - int result = 0; - struct smb_dirent temp_entry; + smb_init_dirent(server, entry); - memset(&temp_entry, 0, sizeof(temp_entry)); - - if ((result=smb_proc_open(server,path,len, - &temp_entry)) < 0) { - /* We cannot open directories, so we try to use the - core variant */ - return smb_proc_getattr_core(server,path,len,entry); - } - - if ((result=smb_proc_getattrE(server, &temp_entry)) >= 0) { - entry->attr = temp_entry.attr; - entry->atime = temp_entry.atime; - entry->mtime = temp_entry.mtime; - entry->ctime = temp_entry.ctime; - entry->size = temp_entry.size; - } - - smb_proc_close(server, temp_entry.fileid, temp_entry.mtime); - return result; - - } else { - return smb_proc_getattr_core(server, path, len, entry); - } + if (server->protocol >= PROTOCOL_LANMAN2) + { + result = smb_proc_getattr_trans2(dir, name, len, entry); + } + if ((server->protocol < PROTOCOL_LANMAN2) || (result < 0)) + { + result = smb_proc_getattr_core(dir, name, len, entry); + } + smb_finish_dirent(server, entry); + + entry->len = len; + memcpy(entry->name, name, len); + /* entry->name is null terminated from smb_init_dirent */ + + return result; } /* In core protocol, there is only 1 time to be set, we use - entry->mtime, to make touch work. */ + entry->f_mtime, to make touch work. */ static int smb_proc_setattr_core(struct smb_server *server, - const char *path, int len, - struct smb_dirent *new_finfo) + struct inode *i, struct smb_dirent *new_finfo) { - char *p; - char *buf = server->packet; - int result; - - smb_lock_server(server); - - retry: - p = smb_setup_header(server, SMBsetatr, 8, 4 + len); - WSET(buf, smb_vwv0, new_finfo->attr); - DSET(buf, smb_vwv1, utc2local(new_finfo->mtime)); - p = smb_encode_ascii(p, path, len); - p = smb_encode_ascii(p, "", 0); - - if ((result = smb_request_ok(server, SMBsetatr, 0, 0)) < 0) { - if (smb_retry(server)) { - goto retry; - } - } - smb_unlock_server(server); - return result; + char *p; + char *buf; + int result; + + smb_lock_server(server); + buf = server->packet; + + retry: + p = smb_setup_header(server, SMBsetatr, 8, 0); + WSET(buf, smb_vwv0, new_finfo->attr); + DSET(buf, smb_vwv1, utc2local(new_finfo->f_mtime)); + *p++ = 4; + p = smb_encode_path(server, p, + SMB_INOP(i)->dir, SMB_INOP(i)->finfo.name, + SMB_INOP(i)->finfo.len); + p = smb_encode_ascii(p, "", 0); + + smb_setup_bcc(server, p); + if ((result = smb_request_ok(server, SMBsetatr, 0, 0)) < 0) + { + if (smb_retry(server)) + { + goto retry; + } + } + smb_unlock_server(server); + return result; } -/* smb_proc_setattrE: we do not retry here, because we rely on fid, - which would not be valid after a retry. */ static int -smb_proc_setattrE(struct smb_server *server, word fid, - struct smb_dirent *new_entry) +smb_proc_setattr_trans2(struct smb_server *server, + struct inode *i, struct smb_dirent *new_finfo) { - char *buf = server->packet; - word date, time; - - smb_setup_header_exclusive(server, SMBsetattrE, 7, 0); + char param[SMB_MAXPATHLEN + 20]; + char data[26]; + char *p; + int result; - WSET(buf, smb_vwv0, fid); + unsigned char *resp_data = NULL; + unsigned char *resp_param = NULL; + int resp_data_len = 0; + int resp_param_len = 0; + + WSET(param, 0, 1); /* Info level SMB_INFO_STANDARD */ + DSET(param, 2, 0); + p = smb_encode_path(server, param + 6, + SMB_INOP(i)->dir, SMB_INOP(i)->finfo.name, + SMB_INOP(i)->finfo.len); + + date_unix2dos(new_finfo->f_ctime, &(data[0]), &(data[2])); + date_unix2dos(new_finfo->f_atime, &(data[4]), &(data[6])); + date_unix2dos(new_finfo->f_mtime, &(data[8]), &(data[10])); + DSET(data, 12, new_finfo->f_size); + DSET(data, 16, new_finfo->f_blksize); + WSET(data, 20, new_finfo->attr); + WSET(data, 22, 0); - date_unix2dos(new_entry->ctime, &time, &date); - WSET(buf, smb_vwv1, date); - WSET(buf, smb_vwv2, time); - - date_unix2dos(new_entry->atime, &time, &date); - WSET(buf, smb_vwv3, date); - WSET(buf, smb_vwv4, time); - - date_unix2dos(new_entry->mtime, &time, &date); - WSET(buf, smb_vwv5, date); - WSET(buf, smb_vwv6, time); + smb_lock_server(server); + retry: + result = smb_trans2_request(server, TRANSACT2_SETPATHINFO, + 26, data, p - param, param, + &resp_data_len, &resp_data, + &resp_param_len, &resp_param); - return smb_request_ok_unlock(server, SMBsetattrE, 0, 0); + if (server->rcls != 0) + { + smb_unlock_server(server); + return -smb_errno(server->rcls, server->err); + } + if (result < 0) + { + if (smb_retry(server)) + { + goto retry; + } + } + smb_unlock_server(server); + return 0; } -/* smb_proc_setattr: for protocol >= LANMAN1 we expect the file to be - opened for writing. */ int smb_proc_setattr(struct smb_server *server, struct inode *inode, - struct smb_dirent *new_finfo) + struct smb_dirent *new_finfo) { - struct smb_dirent *finfo = SMB_FINFO(inode); - int result; + int result; - if (server->protocol >= PROTOCOL_LANMAN1) { - if ((result = smb_make_open(inode, O_RDWR)) < 0) - return result; - return smb_proc_setattrE(server, finfo->fileid, new_finfo); - } else { - return smb_proc_setattr_core(server, finfo->path, finfo->len, - new_finfo); - } + if (server->protocol >= PROTOCOL_LANMAN2) + { + result = smb_proc_setattr_trans2(server, inode, new_finfo); + } + if ((server->protocol < PROTOCOL_LANMAN2) || (result < 0)) + { + result = smb_proc_setattr_core(server, inode, new_finfo); + } + return result; } int @@ -1587,25 +1610,26 @@ char *p; struct smb_server *server = &(SMB_SBP(super)->s_server); - smb_lock_server(server); + smb_lock_server(server); - retry: + retry: smb_setup_header(server, SMBdskattr, 0, 0); - - if ((error = smb_request_ok(server, SMBdskattr, 5, 0)) < 0) { - if (smb_retry(server)) { - goto retry; - } - smb_unlock_server(server); + + if ((error = smb_request_ok(server, SMBdskattr, 5, 0)) < 0) + { + if (smb_retry(server)) + { + goto retry; + } + smb_unlock_server(server); return error; - } - + } p = SMB_VWV(server->packet); p = smb_decode_word(p, &attr->total); p = smb_decode_word(p, &attr->allocblocks); p = smb_decode_word(p, &attr->blocksize); p = smb_decode_word(p, &attr->free); - smb_unlock_server(server); + smb_unlock_server(server); return 0; } @@ -1615,7 +1639,8 @@ /* */ /*****************************************************************************/ -struct smb_prots { +struct smb_prots +{ enum smb_protocol prot; const char *name; }; @@ -1629,50 +1654,50 @@ smb_proc_reconnect(struct smb_server *server) { struct smb_prots prots[] = - { { PROTOCOL_CORE, "PC NETWORK PROGRAM 1.0"}, - { PROTOCOL_COREPLUS,"MICROSOFT NETWORKS 1.03"}, + { + {PROTOCOL_CORE, "PC NETWORK PROGRAM 1.0"}, + {PROTOCOL_COREPLUS, "MICROSOFT NETWORKS 1.03"}, #ifdef LANMAN1 - { PROTOCOL_LANMAN1,"MICROSOFT NETWORKS 3.0"}, - { PROTOCOL_LANMAN1,"LANMAN1.0"}, + {PROTOCOL_LANMAN1, "MICROSOFT NETWORKS 3.0"}, + {PROTOCOL_LANMAN1, "LANMAN1.0"}, #endif -#ifdef CONFIG_SMB_LONG #ifdef LANMAN2 - { PROTOCOL_LANMAN2,"LM1.2X002"}, + {PROTOCOL_LANMAN2, "LM1.2X002"}, #endif #ifdef NT1 - { PROTOCOL_NT1,"NT LM 0.12"}, - { PROTOCOL_NT1,"NT LANMAN 1.0"}, -#endif + {PROTOCOL_NT1, "NT LM 0.12"}, + {PROTOCOL_NT1, "NT LANMAN 1.0"}, #endif - {-1, NULL} }; + {-1, NULL}}; char dev[] = "A:"; int i, plength; int max_xmit = 1024; /* Space needed for first request. */ - int given_max_xmit = server->m.max_xmit; + int given_max_xmit = server->m.max_xmit; int result; byte *p; - if ((result = smb_connect(server)) < 0) { - DPRINTK("smb_proc_reconnect: could not smb_connect\n"); - goto fail; - } - - /* Here we assume that the connection is valid */ - server->state = CONN_VALID; - - if (server->packet != NULL) { - smb_kfree_s(server->packet, server->max_xmit); - } - - server->packet = smb_kmalloc(max_xmit, GFP_KERNEL); + if ((result = smb_connect(server)) < 0) + { + DPRINTK("smb_proc_reconnect: could not smb_connect\n"); + goto fail; + } + /* Here we assume that the connection is valid */ + server->state = CONN_VALID; - if (server->packet == NULL) { - printk("smb_proc_connect: No memory! Bailing out.\n"); - result = -ENOMEM; - goto fail; + if (server->packet != NULL) + { + smb_vfree(server->packet); + server->packet_size = 0; } + server->packet = smb_vmalloc(max_xmit); - server->max_xmit = max_xmit; + if (server->packet == NULL) + { + printk("smb_proc_connect: No memory! Bailing out.\n"); + result = -ENOMEM; + goto fail; + } + server->packet_size = server->max_xmit = max_xmit; /* * Start with an RFC1002 session request packet. @@ -1681,98 +1706,110 @@ p = smb_name_mangle(p, server->m.server_name); p = smb_name_mangle(p, server->m.client_name); - + smb_encode_smb_length(server->packet, - (void *)p - (void *)(server->packet)); - - server->packet[0] = 0x81; /* SESSION REQUEST */ - - if (smb_catch_keepalive(server) < 0) { - printk("smb_proc_connect: could not catch_keepalives\n"); - } - - if ((result = smb_request(server)) < 0) { - printk("smb_proc_connect: Failed to send SESSION REQUEST.\n"); - smb_dont_catch_keepalive(server); - goto fail; + (void *) p - (void *) (server->packet)); + + server->packet[0] = 0x81; /* SESSION REQUEST */ + + if (smb_catch_keepalive(server) < 0) + { + printk("smb_proc_connect: could not catch_keepalives\n"); } - - if (server->packet[0] != 0x82) { + if ((result = smb_request(server)) < 0) + { + DPRINTK("smb_proc_connect: Failed to send SESSION REQUEST.\n"); + smb_dont_catch_keepalive(server); + goto fail; + } + if (server->packet[0] != 0x82) + { printk("smb_proc_connect: Did not receive positive response " - "(err = %x)\n", + "(err = %x)\n", server->packet[0]); - smb_dont_catch_keepalive(server); -#if DEBUG_SMB > 0 - smb_dump_packet(server->packet); -#endif - result = -EIO; - goto fail; + smb_dont_catch_keepalive(server); + result = -EIO; + goto fail; } + DPRINTK("smb_proc_connect: Passed SESSION REQUEST.\n"); - DPRINTK("smb_proc_connect: Passed SESSION REQUEST.\n"); - /* Now we are ready to send a SMB Negotiate Protocol packet. */ memset(server->packet, 0, SMB_HEADER_LEN); plength = 0; - for (i = 0; prots[i].name != NULL; i++) { + for (i = 0; prots[i].name != NULL; i++) + { plength += strlen(prots[i].name) + 2; - } + } smb_setup_header(server, SMBnegprot, 0, plength); p = SMB_BUF(server->packet); - - for (i = 0; prots[i].name != NULL; i++) { - p = smb_encode_dialect(p,prots[i].name, strlen(prots[i].name)); - } - - if ((result = smb_request_ok(server, SMBnegprot, 1, -1)) < 0) { - printk("smb_proc_connect: Failure requesting SMBnegprot\n"); - smb_dont_catch_keepalive(server); - goto fail; - } else { - DDPRINTK("smb_proc_connect: Request SMBnegprot.."); - } - - DDPRINTK("Verified!\n"); - - p = SMB_VWV(server->packet); - p = smb_decode_word(p, (word *)&i); - server->protocol = prots[i].prot; + + for (i = 0; prots[i].name != NULL; i++) + { + *p++ = 2; + strcpy(p, prots[i].name); + p += strlen(prots[i].name) + 1; + } + + if ((result = smb_request_ok(server, SMBnegprot, 1, -1)) < 0) + { + DPRINTK("smb_proc_connect: Failure requesting SMBnegprot\n"); + smb_dont_catch_keepalive(server); + goto fail; + } else + { + DDPRINTK("smb_proc_connect: Request SMBnegprot.."); + } + + DDPRINTK("Verified!\n"); + + p = SMB_VWV(server->packet); + p = smb_decode_word(p, (word *) & i); + server->protocol = prots[i].prot; DPRINTK("smb_proc_connect: Server wants %s protocol.\n", - prots[i].name); + prots[i].name); + + if (server->protocol >= PROTOCOL_LANMAN1) + { + + word passlen = strlen(server->m.password); + word userlen = strlen(server->m.username); - if (server->protocol >= PROTOCOL_LANMAN1) { + DPRINTK("smb_proc_connect: password = %s\n", + server->m.password); + DPRINTK("smb_proc_connect: usernam = %s\n", + server->m.username); + DPRINTK("smb_proc_connect: blkmode = %d\n", + WVAL(server->packet, smb_vwv5)); - word passlen = strlen(server->m.password); - word userlen = strlen(server->m.username); - - DPRINTK("smb_proc_connect: password = %s\n", - server->m.password); - DPRINTK("smb_proc_connect: usernam = %s\n", - server->m.username); - DPRINTK("smb_proc_connect: blkmode = %d\n", - WVAL(server->packet, smb_vwv5)); - - if (server->protocol >= PROTOCOL_NT1) { - server->maxxmt = DVAL(server->packet,smb_vwv3+1); - server->maxmux = WVAL(server->packet, smb_vwv1+1); - server->maxvcs = WVAL(server->packet, smb_vwv2+1); - server->blkmode= DVAL(server->packet, smb_vwv9+1); - server->sesskey= DVAL(server->packet, smb_vwv7+1); - } else { - server->maxxmt = WVAL(server->packet, smb_vwv2); + if (server->protocol >= PROTOCOL_NT1) + { + server->max_xmit = DVAL(server->packet, smb_vwv3 + 1); + server->maxmux = WVAL(server->packet, smb_vwv1 + 1); + server->maxvcs = WVAL(server->packet, smb_vwv2 + 1); + server->blkmode = DVAL(server->packet, smb_vwv9 + 1); + server->sesskey = DVAL(server->packet, smb_vwv7 + 1); + } else + { + server->max_xmit = WVAL(server->packet, smb_vwv2); server->maxmux = WVAL(server->packet, smb_vwv3); server->maxvcs = WVAL(server->packet, smb_vwv4); - server->blkmode= WVAL(server->packet, smb_vwv5); - server->sesskey= DVAL(server->packet, smb_vwv6); + server->blkmode = WVAL(server->packet, smb_vwv5); + server->sesskey = DVAL(server->packet, smb_vwv6); } - - if (server->protocol >= PROTOCOL_NT1) { - char *workgroup = "WORKGROUP"; + if (server->max_xmit < given_max_xmit) + { + /* We do not distinguish between the client + requests and the server response. */ + given_max_xmit = server->max_xmit; + } + if (server->protocol >= PROTOCOL_NT1) + { + char *workgroup = server->m.domain; char *OS_id = "Unix"; char *client_id = "ksmbfs"; @@ -1780,7 +1817,7 @@ 5 + userlen + passlen + strlen(workgroup) + strlen(OS_id) + strlen(client_id)); - + WSET(server->packet, smb_vwv0, 0x00ff); WSET(server->packet, smb_vwv1, 0); WSET(server->packet, smb_vwv2, given_max_xmit); @@ -1801,7 +1838,8 @@ strcpy(p, OS_id); p += strlen(p) + 1; strcpy(p, client_id); - } else { + } else + { smb_setup_header(server, SMBsesssetupX, 10, 2 + userlen + passlen); @@ -1821,47 +1859,59 @@ strcpy(p, server->m.username); } - if ((result = smb_request_ok(server,SMBsesssetupX,3,0)) < 0) { - DPRINTK("smb_proc_connect: SMBsessetupX failed\n"); - smb_dont_catch_keepalive(server); - goto fail; - } - smb_decode_word(server->packet+32, &(server->server_uid)); - } - else - { - server->maxxmt = 0; - server->maxmux = 0; - server->maxvcs = 0; - server->blkmode = 0; - server->sesskey = 0; - } + if ((result = smb_request_ok(server, SMBsesssetupX, 3, 0)) < 0) + { + DPRINTK("smb_proc_connect: SMBsessetupX failed\n"); + smb_dont_catch_keepalive(server); + goto fail; + } + smb_decode_word(server->packet + 32, &(server->server_uid)); + } else + { + server->max_xmit = 0; + server->maxmux = 0; + server->maxvcs = 0; + server->blkmode = 0; + server->sesskey = 0; + } /* Fine! We have a connection, send a tcon message. */ smb_setup_header(server, SMBtcon, 0, - 6 + strlen(server->m.service) + - strlen(server->m.password) + strlen(dev)); + 6 + strlen(server->m.service) + + strlen(server->m.password) + strlen(dev)); p = SMB_BUF(server->packet); p = smb_encode_ascii(p, server->m.service, strlen(server->m.service)); - p = smb_encode_ascii(p,server->m.password, strlen(server->m.password)); + p = smb_encode_ascii(p, server->m.password, strlen(server->m.password)); p = smb_encode_ascii(p, dev, strlen(dev)); - if ((result = smb_request_ok(server, SMBtcon, 2, 0)) < 0) { + if ((result = smb_request_ok(server, SMBtcon, 2, 0)) < 0) + { DPRINTK("smb_proc_connect: SMBtcon not verified.\n"); - smb_dont_catch_keepalive(server); - goto fail; + smb_dont_catch_keepalive(server); + goto fail; } + DDPRINTK("OK! Managed to set up SMBtcon!\n"); - DDPRINTK("OK! Managed to set up SMBtcon!\n"); - p = SMB_VWV(server->packet); - p = smb_decode_word(p, &server->max_xmit); - if (server->max_xmit > given_max_xmit) - server->max_xmit = given_max_xmit; - + if (server->protocol <= PROTOCOL_COREPLUS) + { + word max_xmit; + + p = smb_decode_word(p, &max_xmit); + server->max_xmit = max_xmit; + + if (server->max_xmit > given_max_xmit) + { + server->max_xmit = given_max_xmit; + } + } else + { + p += 2; + } + p = smb_decode_word(p, &server->tid); /* Ok, everything is fine. max_xmit does not include */ @@ -1871,22 +1921,24 @@ DPRINTK("max_xmit = %d, tid = %d\n", server->max_xmit, server->tid); /* Now make a new packet with the correct size. */ - smb_kfree_s(server->packet, max_xmit); + smb_vfree(server->packet); - server->packet = smb_kmalloc(server->max_xmit, GFP_KERNEL); - if (server->packet == NULL) { + server->packet = smb_vmalloc(server->max_xmit); + if (server->packet == NULL) + { printk("smb_proc_connect: No memory left in end of " - "connection phase :-(\n"); - smb_dont_catch_keepalive(server); - goto fail; + "connection phase :-(\n"); + smb_dont_catch_keepalive(server); + goto fail; } + server->packet_size = server->max_xmit; - DPRINTK("smb_proc_connect: Normal exit\n"); - return 0; + DPRINTK("smb_proc_connect: Normal exit\n"); + return 0; - fail: - server->state = CONN_INVALID; - return result; + fail: + server->state = CONN_INVALID; + return result; } /* smb_proc_reconnect: server->packet is allocated with @@ -1894,172 +1946,23 @@ int smb_proc_connect(struct smb_server *server) { - int result; - smb_lock_server(server); - - result = smb_proc_reconnect(server); + int result; + smb_lock_server(server); - if ((result < 0) && (server->packet != NULL)) { - smb_kfree_s(server->packet, server->max_xmit); - server->packet = NULL; - } + result = smb_proc_reconnect(server); - smb_unlock_server(server); - return result; + if ((result < 0) && (server->packet != NULL)) + { + smb_vfree(server->packet); + server->packet = NULL; + } + smb_unlock_server(server); + return result; } - + int smb_proc_disconnect(struct smb_server *server) { smb_setup_header_exclusive(server, SMBtdis, 0, 0); return smb_request_ok_unlock(server, SMBtdis, 0, 0); } - -/* error code stuff - put together by Merik Karman - merik@blackadder.dsh.oz.au */ - -#if DEBUG_SMB > 0 - -typedef struct { - char *name; - int code; - char *message; -} err_code_struct; - -/* Dos Error Messages */ -err_code_struct dos_msgs[] = { - { "ERRbadfunc",1,"Invalid function."}, - { "ERRbadfile",2,"File not found."}, - { "ERRbadpath",3,"Directory invalid."}, - { "ERRnofids",4,"No file descriptors available"}, - { "ERRnoaccess",5,"Access denied."}, - { "ERRbadfid",6,"Invalid file handle."}, - { "ERRbadmcb",7,"Memory control blocks destroyed."}, - { "ERRnomem",8,"Insufficient server memory to perform the requested function."}, - { "ERRbadmem",9,"Invalid memory block address."}, - { "ERRbadenv",10,"Invalid environment."}, - { "ERRbadformat",11,"Invalid format."}, - { "ERRbadaccess",12,"Invalid open mode."}, - { "ERRbaddata",13,"Invalid data."}, - { "ERR",14,"reserved."}, - { "ERRbaddrive",15,"Invalid drive specified."}, - { "ERRremcd",16,"A Delete Directory request attempted to remove the server's current directory."}, - { "ERRdiffdevice",17,"Not same device."}, - { "ERRnofiles",18,"A File Search command can find no more files matching the specified criteria."}, - { "ERRbadshare",32,"The sharing mode specified for an Open conflicts with existing FIDs on the file."}, - { "ERRlock",33,"A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process."}, - { "ERRfilexists",80,"The file named in a Create Directory, Make New File or Link request already exists."}, - { "ERRbadpipe",230,"Pipe invalid."}, - { "ERRpipebusy",231,"All instances of the requested pipe are busy."}, - { "ERRpipeclosing",232,"Pipe close in progress."}, - { "ERRnotconnected",233,"No process on other end of pipe."}, - { "ERRmoredata",234,"There is more data to be returned."}, - { NULL,-1,NULL}}; - -/* Server Error Messages */ -err_code_struct server_msgs[] = { - { "ERRerror",1,"Non-specific error code."}, - { "ERRbadpw",2,"Bad password - name/password pair in a Tree Connect or Session Setup are invalid."}, - { "ERRbadtype",3,"reserved."}, - { "ERRaccess",4,"The requester does not have the necessary access rights within the specified context for the requested function. The context is defined by the TID or the UID."}, - { "ERRinvnid",5,"The tree ID (TID) specified in a command was invalid."}, - { "ERRinvnetname",6,"Invalid network name in tree connect."}, - { "ERRinvdevice",7,"Invalid device - printer request made to non-printer connection or non-printer request made to printer connection."}, - { "ERRqfull",49,"Print queue full (files) -- returned by open print file."}, - { "ERRqtoobig",50,"Print queue full -- no space."}, - { "ERRqeof",51,"EOF on print queue dump."}, - { "ERRinvpfid",52,"Invalid print file FID."}, - { "ERRsmbcmd",64,"The server did not recognize the command received."}, - { "ERRsrverror",65,"The server encountered an internal error, e.g., system file unavailable."}, - { "ERRfilespecs",67,"The file handle (FID) and pathname parameters contained an invalid combination of values."}, - { "ERRreserved",68,"reserved."}, - { "ERRbadpermits",69,"The access permissions specified for a file or directory are not a valid combination. The server cannot set the requested attribute."}, - { "ERRreserved",70,"reserved."}, - { "ERRsetattrmode",71,"The attribute mode in the Set File Attribute request is invalid."}, - { "ERRpaused",81,"Server is paused."}, - { "ERRmsgoff",82,"Not receiving messages."}, - { "ERRnoroom",83,"No room to buffer message."}, - { "ERRrmuns",87,"Too many remote user names."}, - { "ERRtimeout",88,"Operation timed out."}, - { "ERRnoresource",89,"No resources currently available for request."}, - { "ERRtoomanyuids",90,"Too many UIDs active on this session."}, - { "ERRbaduid",91,"The UID is not known as a valid ID on this session."}, - { "ERRusempx",250,"Temp unable to support Raw, use MPX mode."}, - { "ERRusestd",251,"Temp unable to support Raw, use standard read/write."}, - { "ERRcontmpx",252,"Continue in MPX mode."}, - { "ERRreserved",253,"reserved."}, - { "ERRreserved",254,"reserved."}, - { "ERRnosupport",0xFFFF,"Function not supported."}, - { NULL,-1,NULL}}; - -/* Hard Error Messages */ -err_code_struct hard_msgs[] = { - { "ERRnowrite",19,"Attempt to write on write-protected diskette."}, - { "ERRbadunit",20,"Unknown unit."}, - { "ERRnotready",21,"Drive not ready."}, - { "ERRbadcmd",22,"Unknown command."}, - { "ERRdata",23,"Data error (CRC)."}, - { "ERRbadreq",24,"Bad request structure length."}, - { "ERRseek",25 ,"Seek error."}, - { "ERRbadmedia",26,"Unknown media type."}, - { "ERRbadsector",27,"Sector not found."}, - { "ERRnopaper",28,"Printer out of paper."}, - { "ERRwrite",29,"Write fault."}, - { "ERRread",30,"Read fault."}, - { "ERRgeneral",31,"General failure."}, - { "ERRbadshare",32,"A open conflicts with an existing open."}, - { "ERRlock",33,"A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process."}, - { "ERRwrongdisk",34,"The wrong disk was found in a drive."}, - { "ERRFCBUnavail",35,"No FCBs are available to process request."}, - { "ERRsharebufexc",36,"A sharing buffer has been exceeded."}, - { NULL,-1,NULL} -}; - - -struct { - int code; - char *class; - err_code_struct *err_msgs; -} err_classes[] = { - { 0,"SUCCESS",NULL}, - { 0x01,"ERRDOS",dos_msgs}, - { 0x02,"ERRSRV",server_msgs}, - { 0x03,"ERRHRD",hard_msgs}, - { 0x04,"ERRXOS",NULL}, - { 0xE1,"ERRRMX1",NULL}, - { 0xE2,"ERRRMX2",NULL}, - { 0xE3,"ERRRMX3",NULL}, - { 0xFF,"ERRCMD",NULL}, - { -1,NULL,NULL} -}; - -void -smb_printerr(int class, int num) -{ - int i,j; - err_code_struct *err; - - for (i=0; err_classes[i].class; i++) { - if (err_classes[i].code != class) - continue; - if (!err_classes[i].err_msgs) { - printk("%s - %d", err_classes[i].class, num); - return; - } - - err = err_classes[i].err_msgs; - for (j=0; err[j].name; j++) { - if (num != err[j].code) - continue; - printk("%s - %s (%s)", - err_classes[i].class, err[j].name, - err[j].message); - return; - } - } - - printk("Unknown error - (%d,%d)", class, num); - return; -} - -#endif /* DEBUG_SMB > 0 */ diff -u --recursive --new-file v2.0.26/linux/fs/smbfs/sock.c linux/fs/smbfs/sock.c --- v2.0.26/linux/fs/smbfs/sock.c Wed Sep 11 17:57:16 1996 +++ linux/fs/smbfs/sock.c Sun Dec 1 15:58:06 1996 @@ -1,7 +1,7 @@ /* * sock.c * - * Copyright (C) 1995 by Paal-Kr. Engstad and Volker Lendecke + * Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke * */ @@ -28,747 +28,687 @@ _recvfrom(struct socket *sock, unsigned char *ubuf, int size, int noblock, unsigned flags, struct sockaddr_in *sa, int *addr_len) { - struct iovec iov; - struct msghdr msg; + struct iovec iov; + struct msghdr msg; - iov.iov_base = ubuf; - iov.iov_len = size; + iov.iov_base = ubuf; + iov.iov_len = size; - msg.msg_name = (void *)sa; - msg.msg_namelen = 0; - if (addr_len) - msg.msg_namelen = *addr_len; - msg.msg_control = NULL; - msg.msg_iov = &iov; - msg.msg_iovlen = 1; + msg.msg_name = (void *) sa; + msg.msg_namelen = 0; + if (addr_len) + msg.msg_namelen = *addr_len; + msg.msg_control = NULL; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; - return sock->ops->recvmsg(sock, &msg, size, noblock, flags, addr_len); + return sock->ops->recvmsg(sock, &msg, size, noblock, flags, addr_len); } static int _send(struct socket *sock, const void *buff, int len, int nonblock, unsigned flags) { - struct iovec iov; - struct msghdr msg; + struct iovec iov; + struct msghdr msg; - iov.iov_base = (void *)buff; - iov.iov_len = len; + iov.iov_base = (void *) buff; + iov.iov_len = len; - msg.msg_name = NULL; - msg.msg_namelen = 0; - msg.msg_control = NULL; - msg.msg_iov = &iov; - msg.msg_iovlen = 1; + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_control = NULL; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; - return sock->ops->sendmsg(sock, &msg, len, nonblock, flags); + return sock->ops->sendmsg(sock, &msg, len, nonblock, flags); } static void -smb_data_callback(struct sock *sk,int len) +smb_data_callback(struct sock *sk, int len) { - struct socket *sock = sk->socket; + struct socket *sock = sk->socket; - if(!sk->dead) + if (!sk->dead) { - unsigned char peek_buf[4]; - int result; - unsigned short fs; - - fs = get_fs(); - set_fs(get_ds()); - - result = _recvfrom(sock, (void *)peek_buf, 1, 1, - MSG_PEEK, NULL, NULL); - - while ((result != -EAGAIN) && (peek_buf[0] == 0x85)) { - - /* got SESSION KEEP ALIVE */ - result = _recvfrom(sock, (void *)peek_buf, - 4, 1, 0, NULL, NULL); - - DDPRINTK("smb_data_callback:" - " got SESSION KEEP ALIVE\n"); - - if (result == -EAGAIN) - break; + unsigned char peek_buf[4]; + int result; + unsigned short fs; + + fs = get_fs(); + set_fs(get_ds()); + + result = _recvfrom(sock, (void *) peek_buf, 1, 1, + MSG_PEEK, NULL, NULL); + + while ((result != -EAGAIN) && (peek_buf[0] == 0x85)) + { + /* got SESSION KEEP ALIVE */ + result = _recvfrom(sock, (void *) peek_buf, + 4, 1, 0, NULL, NULL); + + DDPRINTK("smb_data_callback:" + " got SESSION KEEP ALIVE\n"); + + if (result == -EAGAIN) + { + break; + } + result = _recvfrom(sock, (void *) peek_buf, + 1, 1, MSG_PEEK, + NULL, NULL); + } + set_fs(fs); + + if (result != -EAGAIN) + { + wake_up_interruptible(sk->sleep); + } + } +} - result = _recvfrom(sock, (void *)peek_buf, - 1, 1, MSG_PEEK, - NULL, NULL); +int +smb_catch_keepalive(struct smb_server *server) +{ + struct file *file; + struct inode *inode; + struct socket *sock; + struct sock *sk; + + if ((server == NULL) + || ((file = server->sock_file) == NULL) + || ((inode = file->f_inode) == NULL) + || (!S_ISSOCK(inode->i_mode))) + { + printk("smb_catch_keepalive: did not get valid server!\n"); + server->data_ready = NULL; + return -EINVAL; + } + sock = &(inode->u.socket_i); - } + if (sock->type != SOCK_STREAM) + { + printk("smb_catch_keepalive: did not get SOCK_STREAM\n"); + server->data_ready = NULL; + return -EINVAL; + } + sk = (struct sock *) (sock->data); - set_fs(fs); + if (sk == NULL) + { + printk("smb_catch_keepalive: sk == NULL"); + server->data_ready = NULL; + return -EINVAL; + } + DDPRINTK("smb_catch_keepalive.: sk->d_r = %x, server->d_r = %x\n", + (unsigned int) (sk->data_ready), + (unsigned int) (server->data_ready)); - if (result != -EAGAIN) { - wake_up_interruptible(sk->sleep); - } + if (sk->data_ready == smb_data_callback) + { + printk("smb_catch_keepalive: already done\n"); + return -EINVAL; } + server->data_ready = sk->data_ready; + sk->data_ready = smb_data_callback; + return 0; } int -smb_catch_keepalive(struct smb_server *server) +smb_dont_catch_keepalive(struct smb_server *server) { - struct file *file; - struct inode *inode; - struct socket *sock; - struct sock *sk; - - if ( (server == NULL) - || ((file = server->sock_file) == NULL) - || ((inode = file->f_inode) == NULL) - || (!S_ISSOCK(inode->i_mode))) { - - printk("smb_catch_keepalive: did not get valid server!\n"); - server->data_ready = NULL; - return -EINVAL; - } - - sock = &(inode->u.socket_i); - - if (sock->type != SOCK_STREAM) { - printk("smb_catch_keepalive: did not get SOCK_STREAM\n"); - server->data_ready = NULL; - return -EINVAL; - } - - sk = (struct sock *)(sock->data); - - if (sk == NULL) { - printk("smb_catch_keepalive: sk == NULL"); - server->data_ready = NULL; - return -EINVAL; - } - - DDPRINTK("smb_catch_keepalive.: sk->d_r = %x, server->d_r = %x\n", - (unsigned int)(sk->data_ready), - (unsigned int)(server->data_ready)); - - if (sk->data_ready == smb_data_callback) { - printk("smb_catch_keepalive: already done\n"); - return -EINVAL; - } - - server->data_ready = sk->data_ready; - sk->data_ready = smb_data_callback; - return 0; + struct file *file; + struct inode *inode; + struct socket *sock; + struct sock *sk; + + if ((server == NULL) + || ((file = server->sock_file) == NULL) + || ((inode = file->f_inode) == NULL) + || (!S_ISSOCK(inode->i_mode))) + { + printk("smb_dont_catch_keepalive: " + "did not get valid server!\n"); + return -EINVAL; + } + sock = &(inode->u.socket_i); + + if (sock->type != SOCK_STREAM) + { + printk("smb_dont_catch_keepalive: did not get SOCK_STREAM\n"); + return -EINVAL; + } + sk = (struct sock *) (sock->data); + + if (sk == NULL) + { + printk("smb_dont_catch_keepalive: sk == NULL"); + return -EINVAL; + } + if (server->data_ready == NULL) + { + printk("smb_dont_catch_keepalive: " + "server->data_ready == NULL\n"); + return -EINVAL; + } + if (sk->data_ready != smb_data_callback) + { + printk("smb_dont_catch_keepalive: " + "sk->data_callback != smb_data_callback\n"); + return -EINVAL; + } + DDPRINTK("smb_dont_catch_keepalive: sk->d_r = %x, server->d_r = %x\n", + (unsigned int) (sk->data_ready), + (unsigned int) (server->data_ready)); + + sk->data_ready = server->data_ready; + server->data_ready = NULL; + return 0; } - -int -smb_dont_catch_keepalive(struct smb_server *server) + +static int +smb_send_raw(struct socket *sock, unsigned char *source, int length) { - struct file *file; - struct inode *inode; - struct socket *sock; - struct sock *sk; - - if ( (server == NULL) - || ((file = server->sock_file) == NULL) - || ((inode = file->f_inode) == NULL) - || (!S_ISSOCK(inode->i_mode))) { - - printk("smb_dont_catch_keepalive: " - "did not get valid server!\n"); - return -EINVAL; - } - - sock = &(inode->u.socket_i); - - if (sock->type != SOCK_STREAM) { - printk("smb_dont_catch_keepalive: did not get SOCK_STREAM\n"); - return -EINVAL; - } - - sk = (struct sock *)(sock->data); - - if (sk == NULL) { - printk("smb_dont_catch_keepalive: sk == NULL"); - return -EINVAL; - } - - if (server->data_ready == NULL) { - printk("smb_dont_catch_keepalive: " - "server->data_ready == NULL\n"); - return -EINVAL; - } - - if (sk->data_ready != smb_data_callback) { - printk("smb_dont_catch_keepalive: " - "sk->data_callback != smb_data_callback\n"); - return -EINVAL; - } - - DDPRINTK("smb_dont_catch_keepalive: sk->d_r = %x, server->d_r = %x\n", - (unsigned int)(sk->data_ready), - (unsigned int)(server->data_ready)); - - sk->data_ready = server->data_ready; - server->data_ready = NULL; - return 0; + int result; + int already_sent = 0; + + while (already_sent < length) + { + result = _send(sock, + (void *) (source + already_sent), + length - already_sent, 0, 0); + + if (result < 0) + { + DPRINTK("smb_send_raw: sendto error = %d\n", + -result); + return result; + } + already_sent += result; + } + return already_sent; } -/* - * smb_receive_raw - * fs points to the correct segment, sock != NULL, target != NULL - * The smb header is only stored if want_header != 0. - */ static int -smb_receive_raw(struct socket *sock, unsigned char *target, - int max_raw_length, int want_header) +smb_receive_raw(struct socket *sock, unsigned char *target, int length) { - int len, result; - int already_read; - unsigned char peek_buf[4]; - unsigned short fs; /* We fool the kernel to believe - we call from user space. */ + int result; + int already_read = 0; + while (already_read < length) + { + result = _recvfrom(sock, + (void *) (target + already_read), + length - already_read, 0, 0, + NULL, NULL); + + if (result < 0) + { + DPRINTK("smb_receive_raw: recvfrom error = %d\n", + -result); + return result; + } + already_read += result; + } + return already_read; +} - re_recv: +static int +smb_get_length(struct socket *sock, unsigned char *header) +{ + int result; + unsigned char peek_buf[4]; + unsigned short fs; + re_recv: fs = get_fs(); set_fs(get_ds()); - result = _recvfrom(sock, (void *)peek_buf, 4, 0, - 0, NULL, NULL); - set_fs(fs); - - if (result < 0) { - DPRINTK("smb_receive_raw: recv error = %d\n", -result); - return result; - } - - if (result < 4) { - DPRINTK("smb_receive_raw: got less than 4 bytes\n"); - return -EIO; - } - - switch (peek_buf[0]) { - - case 0x00: - case 0x82: - break; - - case 0x85: - DPRINTK("smb_receive_raw: Got SESSION KEEP ALIVE\n"); - goto re_recv; - - default: - printk("smb_receive_raw: Invalid packet\n"); - return -EIO; - } - - /* The length in the RFC NB header is the raw data length */ - len = smb_len(peek_buf); - if (len > max_raw_length) { - printk("smb_receive_raw: Received length (%d) > max_xmit (%d)!\n", - len, max_raw_length); - return -EIO; - } - - if (want_header != 0) { - memcpy_tofs(target, peek_buf, 4); - target += 4; - } - - already_read = 0; - - while (already_read < len) { - - result = _recvfrom(sock, - (void *)(target+already_read), - len - already_read, 0, 0, - NULL, NULL); - - if (result < 0) { - printk("smb_receive_raw: recvfrom error = %d\n", - -result); - return result; - } - - already_read += result; - } - return already_read; + result = smb_receive_raw(sock, peek_buf, 4); + set_fs(fs); + + if (result < 0) + { + DPRINTK("smb_get_length: recv error = %d\n", -result); + return result; + } + switch (peek_buf[0]) + { + case 0x00: + case 0x82: + break; + + case 0x85: + DPRINTK("smb_get_length: Got SESSION KEEP ALIVE\n"); + goto re_recv; + + default: + printk("smb_get_length: Invalid NBT packet\n"); + return -EIO; + } + + if (header != NULL) + { + memcpy(header, peek_buf, 4); + } + /* The length in the RFC NB header is the raw data length */ + return smb_len(peek_buf); +} + +static struct socket * +server_sock(struct smb_server *server) +{ + struct file *file; + struct inode *inode; + + if (server == NULL) + return NULL; + if ((file = server->sock_file) == NULL) + return NULL; + if ((inode = file->f_inode) == NULL) + return NULL; + return &(inode->u.socket_i); } /* * smb_receive - * fs points to the correct segment, server != NULL, sock!=NULL + * fs points to the correct segment */ static int -smb_receive(struct smb_server *server, struct socket *sock) +smb_receive(struct smb_server *server) { - int result; - - result = smb_receive_raw(sock, server->packet, - server->max_xmit - 4, /* max_xmit in server - includes NB header */ - 1); /* We want the header */ + struct socket *sock = server_sock(server); + int len; + int result; + unsigned char peek_buf[4]; - if (result < 0) { - printk("smb_receive: receive error: %d\n", result); - return result; - } + len = smb_get_length(sock, peek_buf); - server->rcls = *((unsigned char *)(server->packet+9)); - server->err = *((unsigned short *)(server->packet+11)); + if (len < 0) + { + return len; + } + if (len + 4 > server->packet_size) + { + /* Some servers do not care about our max_xmit. They + send larger packets */ + DPRINTK("smb_receive: Increase packet size from %d to %d\n", + server->packet_size, len + 4); + smb_vfree(server->packet); + server->packet_size = 0; + server->packet = smb_vmalloc(len + 4); + if (server->packet == NULL) + { + return -ENOMEM; + } + server->packet_size = len + 4; + } + memcpy(server->packet, peek_buf, 4); + result = smb_receive_raw(sock, server->packet + 4, len); - if (server->rcls != 0) { - DPRINTK("smb_receive: rcls=%d, err=%d\n", - server->rcls, server->err); - } + if (result < 0) + { + printk("smb_receive: receive error: %d\n", result); + return result; + } + server->rcls = BVAL(server->packet, 9); + server->err = WVAL(server->packet, 11); - return result; + if (server->rcls != 0) + { + DPRINTK("smb_receive: rcls=%d, err=%d\n", + server->rcls, server->err); + } + return result; } - -/* - * smb_receive's preconditions also apply here. - */ static int -smb_receive_trans2(struct smb_server *server, struct socket *sock, - int *data_len, int *param_len, - char **data, char **param) -{ - int total_data=0; - int total_param=0; - int result; - unsigned char *inbuf = server->packet; - - *data_len = *param_len = 0; - - DDPRINTK("smb_receive_trans2: enter\n"); - - if ((result = smb_receive(server, sock)) < 0) { - return result; - } - - if (server->rcls != 0) { - return result; - } - - /* parse out the lengths */ - total_data = WVAL(inbuf,smb_tdrcnt); - total_param = WVAL(inbuf,smb_tprcnt); - - if ( (total_data > TRANS2_MAX_TRANSFER) - || (total_param > TRANS2_MAX_TRANSFER)) { - printk("smb_receive_trans2: data/param too long\n"); - return -EIO; - } - - /* allocate it */ - if ((*data = smb_kmalloc(total_data, GFP_KERNEL)) == NULL) { - printk("smb_receive_trans2: could not alloc data area\n"); - return -ENOMEM; - } - - if ((*param = smb_kmalloc(total_param, GFP_KERNEL)) == NULL) { - printk("smb_receive_trans2: could not alloc param area\n"); - smb_kfree_s(*data, total_data); - return -ENOMEM; - } - - DDPRINTK("smb_rec_trans2: total_data/param: %d/%d\n", - total_data, total_param); - - while (1) - { - if (WVAL(inbuf,smb_prdisp)+WVAL(inbuf, smb_prcnt) - > total_param) { - printk("smb_receive_trans2: invalid parameters\n"); - result = -EIO; - goto fail; - } - memcpy(*param + WVAL(inbuf,smb_prdisp), - smb_base(inbuf) + WVAL(inbuf,smb_proff), - WVAL(inbuf,smb_prcnt)); - *param_len += WVAL(inbuf,smb_prcnt); - - - if (WVAL(inbuf,smb_drdisp)+WVAL(inbuf, smb_drcnt)>total_data) { - printk("smb_receive_trans2: invalid data block\n"); - result = -EIO; - goto fail; - } - memcpy(*data + WVAL(inbuf,smb_drdisp), - smb_base(inbuf) + WVAL(inbuf,smb_droff), - WVAL(inbuf,smb_drcnt)); - *data_len += WVAL(inbuf,smb_drcnt); - - DDPRINTK("smb_rec_trans2: drcnt/prcnt: %d/%d\n", - WVAL(inbuf, smb_drcnt), WVAL(inbuf, smb_prcnt)); - - /* parse out the total lengths again - they can shrink! */ - - if ( (WVAL(inbuf,smb_tdrcnt) > total_data) - || (WVAL(inbuf,smb_tprcnt) > total_param)) { - printk("smb_receive_trans2: data/params grew!\n"); - result = -EIO; - goto fail; - } - - total_data = WVAL(inbuf,smb_tdrcnt); - total_param = WVAL(inbuf,smb_tprcnt); - - if (total_data <= *data_len && total_param <= *param_len) - break; - - if ((result = smb_receive(server, sock)) < 0) { - goto fail; - } - if (server->rcls != 0) { - result = -EIO; - goto fail; - } - } - - DDPRINTK("smb_receive_trans2: normal exit\n"); - - return 0; - - fail: - DPRINTK("smb_receive_trans2: failed exit\n"); - - smb_kfree_s(*param, 0); *param = NULL; - smb_kfree_s(*data, 0); *data = NULL; - return result; -} +smb_receive_trans2(struct smb_server *server, + int *ldata, unsigned char **data, + int *lparam, unsigned char **param) +{ + int total_data = 0; + int total_param = 0; + int result; + unsigned char *inbuf = server->packet; + unsigned char *rcv_buf; + int buf_len; + int data_len = 0; + int param_len = 0; -static inline struct socket * -server_sock(struct smb_server *server) -{ - struct file *file; - struct inode *inode; + if ((result = smb_receive(server)) < 0) + { + return result; + } + if (server->rcls != 0) + { + *param = *data = server->packet; + *ldata = *lparam = 0; + return 0; + } + total_data = WVAL(inbuf, smb_tdrcnt); + total_param = WVAL(inbuf, smb_tprcnt); + + DDPRINTK("smb_receive_trans2: td=%d,tp=%d\n", total_data, total_param); + + if ((total_data > TRANS2_MAX_TRANSFER) + || (total_param > TRANS2_MAX_TRANSFER)) + { + DPRINTK("smb_receive_trans2: data/param too long\n"); + return -EIO; + } + buf_len = total_data + total_param; + if (server->packet_size > buf_len) + { + buf_len = server->packet_size; + } + if ((rcv_buf = smb_vmalloc(buf_len)) == NULL) + { + DPRINTK("smb_receive_trans2: could not alloc data area\n"); + return -ENOMEM; + } + *param = rcv_buf; + *data = rcv_buf + total_param; + + while (1) + { + if (WVAL(inbuf, smb_prdisp) + WVAL(inbuf, smb_prcnt) + > total_param) + { + DPRINTK("smb_receive_trans2: invalid parameters\n"); + result = -EIO; + goto fail; + } + memcpy(*param + WVAL(inbuf, smb_prdisp), + smb_base(inbuf) + WVAL(inbuf, smb_proff), + WVAL(inbuf, smb_prcnt)); + param_len += WVAL(inbuf, smb_prcnt); + + if (WVAL(inbuf, smb_drdisp) + WVAL(inbuf, smb_drcnt) + > total_data) + { + DPRINTK("smb_receive_trans2: invalid data block\n"); + result = -EIO; + goto fail; + } + DDPRINTK("target: %X\n", *data + WVAL(inbuf, smb_drdisp)); + DDPRINTK("source: %X\n", + smb_base(inbuf) + WVAL(inbuf, smb_droff)); + DDPRINTK("disp: %d, off: %d, cnt: %d\n", + WVAL(inbuf, smb_drdisp), WVAL(inbuf, smb_droff), + WVAL(inbuf, smb_drcnt)); + + memcpy(*data + WVAL(inbuf, smb_drdisp), + smb_base(inbuf) + WVAL(inbuf, smb_droff), + WVAL(inbuf, smb_drcnt)); + data_len += WVAL(inbuf, smb_drcnt); + + if ((WVAL(inbuf, smb_tdrcnt) > total_data) + || (WVAL(inbuf, smb_tprcnt) > total_param)) + { + printk("smb_receive_trans2: data/params grew!\n"); + result = -EIO; + goto fail; + } + /* the total lengths might shrink! */ + total_data = WVAL(inbuf, smb_tdrcnt); + total_param = WVAL(inbuf, smb_tprcnt); + + if ((data_len >= total_data) && (param_len >= total_param)) + { + break; + } + if ((result = smb_receive(server)) < 0) + { + goto fail; + } + if (server->rcls != 0) + { + result = -EIO; + goto fail; + } + } + *ldata = data_len; + *lparam = param_len; + + smb_vfree(server->packet); + server->packet = rcv_buf; + server->packet_size = buf_len; + return 0; - if (server == NULL) - return NULL; - if ((file = server->sock_file) == NULL) - return NULL; - if ((inode = file->f_inode) == NULL) - return NULL; - return &(inode->u.socket_i); + fail: + smb_vfree(rcv_buf); + return result; } int smb_release(struct smb_server *server) { - struct socket *sock = server_sock(server); - int result; + struct socket *sock = server_sock(server); + int result; - if (sock == NULL) - return -EINVAL; + if (sock == NULL) + { + return -EINVAL; + } + result = sock->ops->release(sock, NULL); + DPRINTK("smb_release: sock->ops->release = %d\n", result); - result = sock->ops->release(sock, NULL); - DPRINTK("smb_release: sock->ops->release = %d\n", result); + /* inet_release does not set sock->state. Maybe someone is + confused about sock->state being SS_CONNECTED while there + is nothing behind it, so I set it to SS_UNCONNECTED. */ + sock->state = SS_UNCONNECTED; - /* inet_release does not set sock->state. Maybe someone is - confused about sock->state being SS_CONNECTED while there - is nothing behind it, so I set it to SS_UNCONNECTED.*/ - sock->state = SS_UNCONNECTED; - - result = sock->ops->create(sock, 0); - DPRINTK("smb_release: sock->ops->create = %d\n", result); - return result; + result = sock->ops->create(sock, 0); + DPRINTK("smb_release: sock->ops->create = %d\n", result); + return result; } int smb_connect(struct smb_server *server) { - struct socket *sock = server_sock(server); - if (sock == NULL) - return -EINVAL; - if (sock->state != SS_UNCONNECTED) { - DPRINTK("smb_connect: socket is not unconnected: %d\n", - sock->state); - } - return sock->ops->connect(sock, (struct sockaddr *)&(server->m.addr), - sizeof(struct sockaddr_in), 0); -} - -/*****************************************************************************/ -/* */ -/* This routine was once taken from nfs, which is for udp. Here TCP does */ -/* most of the ugly stuff for us (thanks, Alan!) */ -/* */ -/*****************************************************************************/ -int -smb_request(struct smb_server *server) -{ - unsigned long old_mask; - unsigned short fs; /* We fool the kernel to believe - we call from user space. */ - int len, result, result2; - struct socket *sock = server_sock(server); - unsigned char *buffer = (server == NULL) ? NULL : server->packet; - - if ((sock == NULL) || (buffer == NULL)) { - printk("smb_request: Bad server!\n"); - return -EBADF; + if (sock == NULL) + { + return -EINVAL; } - - if (server->state != CONN_VALID) - return -EIO; - - if ((result = smb_dont_catch_keepalive(server)) != 0) { - server->state = CONN_INVALID; - smb_invalidate_all_inodes(server); - return result; - } - - len = smb_len(buffer) + 4; - - DDPRINTK("smb_request: len = %d cmd = 0x%X\n", len, buffer[8]); - - old_mask = current->blocked; - current->blocked |= ~(_S(SIGKILL) | _S(SIGSTOP)); - fs = get_fs(); - set_fs(get_ds()); - - result = _send(sock, (void *)buffer, len, 0, 0); - if (result < 0) { - printk("smb_request: send error = %d\n", result); - } - else { - result = smb_receive(server, sock); - } - - /* read/write errors are handled by errno */ - current->signal &= ~_S(SIGPIPE); - - current->blocked = old_mask; - set_fs(fs); - - if ((result2 = smb_catch_keepalive(server)) < 0) { - result = result2; - } - - if (result < 0) { - server->state = CONN_INVALID; - smb_invalidate_all_inodes(server); - } - - DDPRINTK("smb_request: result = %d\n", result); - - return result; + if (sock->state != SS_UNCONNECTED) + { + DPRINTK("smb_connect: socket is not unconnected: %d\n", + sock->state); + } + return sock->ops->connect(sock, (struct sockaddr *) &(server->m.addr), + sizeof(struct sockaddr_in), 0); } -/* - * This is not really a trans2 request, we assume that you only have - * one packet to send. - */ int -smb_trans2_request(struct smb_server *server, - int *data_len, int *param_len, - char **data, char **param) +smb_request(struct smb_server *server) { unsigned long old_mask; - unsigned short fs; /* We fool the kernel to believe - we call from user space. */ - int len, result, result2; + unsigned short fs; + int len, result; - struct socket *sock = server_sock(server); unsigned char *buffer = (server == NULL) ? NULL : server->packet; - if ((sock == NULL) || (buffer == NULL)) { - printk("smb_trans2_request: Bad server!\n"); + if (buffer == NULL) + { + printk("smb_request: Bad server!\n"); return -EBADF; } + if (server->state != CONN_VALID) + { + return -EIO; + } + if ((result = smb_dont_catch_keepalive(server)) != 0) + { + server->state = CONN_INVALID; + smb_invalidate_all_inodes(server); + return result; + } + len = smb_len(buffer) + 4; - if (server->state != CONN_VALID) - return -EIO; - - if ((result = smb_dont_catch_keepalive(server)) != 0) { - server->state = CONN_INVALID; - smb_invalidate_all_inodes(server); - return result; - } - - len = smb_len(buffer) + 4; + DDPRINTK("smb_request: len = %d cmd = 0x%X\n", len, buffer[8]); old_mask = current->blocked; current->blocked |= ~(_S(SIGKILL) | _S(SIGSTOP)); fs = get_fs(); set_fs(get_ds()); - DDPRINTK("smb_request: len = %d cmd = 0x%X\n", len, buffer[8]); - - result = _send(sock, (void *)buffer, len, 0, 0); - if (result < 0) { - printk("smb_trans2_request: send error = %d\n", result); - } - else { - result = smb_receive_trans2(server, sock, - data_len, param_len, - data, param); - } - - /* read/write errors are handled by errno */ - current->signal &= ~_S(SIGPIPE); - + result = smb_send_raw(server_sock(server), (void *) buffer, len); + if (result > 0) + { + result = smb_receive(server); + } + /* read/write errors are handled by errno */ + current->signal &= ~_S(SIGPIPE); current->blocked = old_mask; set_fs(fs); - if ((result2 = smb_catch_keepalive(server)) < 0) { - result = result2; - } - - if (result < 0) { - server->state = CONN_INVALID; - smb_invalidate_all_inodes(server); - } - - DDPRINTK("smb_trans2_request: result = %d\n", result); + if (result >= 0) + { + int result2 = smb_catch_keepalive(server); + if (result2 < 0) + { + result = result2; + } + } + if (result < 0) + { + server->state = CONN_INVALID; + smb_invalidate_all_inodes(server); + } + DDPRINTK("smb_request: result = %d\n", result); return result; } -/* target must be in user space */ -int -smb_request_read_raw(struct smb_server *server, - unsigned char *target, int max_len) +#define ROUND_UP(x) (((x)+3) & ~3) +static int +smb_send_trans2(struct smb_server *server, __u16 trans2_command, + int ldata, unsigned char *data, + int lparam, unsigned char *param) { - unsigned long old_mask; - int len, result, result2; - unsigned short fs; /* We fool the kernel to believe - we call from user space. */ - struct socket *sock = server_sock(server); - unsigned char *buffer = (server == NULL) ? NULL : server->packet; - if ((sock == NULL) || (buffer == NULL)) { - printk("smb_request_read_raw: Bad server!\n"); - return -EBADF; - } + /* I know the following is very ugly, but I want to build the + smb packet as efficiently as possible. */ - if (server->state != CONN_VALID) - return -EIO; - - if ((result = smb_dont_catch_keepalive(server)) != 0) { - server->state = CONN_INVALID; - smb_invalidate_all_inodes(server); - return result; - } + const int smb_parameters = 15; + const int oparam = + ROUND_UP(SMB_HEADER_LEN + 2 * smb_parameters + 2 + 3); + const int odata = + ROUND_UP(oparam + lparam); + const int bcc = + odata + ldata - (SMB_HEADER_LEN + 2 * smb_parameters + 2); + const int packet_length = + SMB_HEADER_LEN + 2 * smb_parameters + bcc + 2; + + unsigned char padding[4] = + {0,}; + char *p; - len = smb_len(buffer) + 4; + struct iovec iov[4]; + struct msghdr msg; - old_mask = current->blocked; - current->blocked |= ~(_S(SIGKILL) | _S(SIGSTOP)); - fs = get_fs(); - set_fs(get_ds()); - - DPRINTK("smb_request_read_raw: len = %d cmd = 0x%X\n", - len, buffer[8]); - DPRINTK("smb_request_read_raw: target=%X, max_len=%d\n", - (unsigned int)target, max_len); - DPRINTK("smb_request_read_raw: buffer=%X, sock=%X\n", - (unsigned int)buffer, (unsigned int)sock); - - result = _send(sock, (void *)buffer, len, 0, 0); - - DPRINTK("smb_request_read_raw: send returned %d\n", result); - - set_fs(fs); /* We recv into user space */ - - if (result < 0) { - printk("smb_request_read_raw: send error = %d\n", result); - } - else { - result = smb_receive_raw(sock, target, max_len, 0); - } - - /* read/write errors are handled by errno */ - current->signal &= ~_S(SIGPIPE); - current->blocked = old_mask; + if ((bcc + oparam) > server->max_xmit) + { + return -ENOMEM; + } + p = smb_setup_header(server, SMBtrans2, smb_parameters, bcc); - if ((result2 = smb_catch_keepalive(server)) < 0) { - result = result2; - } - - if (result < 0) { - server->state = CONN_INVALID; - smb_invalidate_all_inodes(server); - } - - DPRINTK("smb_request_read_raw: result = %d\n", result); + WSET(server->packet, smb_tpscnt, lparam); + WSET(server->packet, smb_tdscnt, ldata); + WSET(server->packet, smb_mprcnt, TRANS2_MAX_TRANSFER); + WSET(server->packet, smb_mdrcnt, TRANS2_MAX_TRANSFER); + WSET(server->packet, smb_msrcnt, 0); + WSET(server->packet, smb_flags, 0); + DSET(server->packet, smb_timeout, 0); + WSET(server->packet, smb_pscnt, lparam); + WSET(server->packet, smb_psoff, oparam - 4); + WSET(server->packet, smb_dscnt, ldata); + WSET(server->packet, smb_dsoff, odata - 4); + WSET(server->packet, smb_suwcnt, 1); + WSET(server->packet, smb_setup0, trans2_command); + *p++ = 0; /* null smb_name for trans2 */ + *p++ = 'D'; /* this was added because OS/2 does it */ + *p++ = ' '; + + iov[0].iov_base = (void *) server->packet; + iov[0].iov_len = oparam; + iov[1].iov_base = (param == NULL) ? padding : param; + iov[1].iov_len = lparam; + iov[2].iov_base = padding; + iov[2].iov_len = odata - oparam - lparam; + iov[3].iov_base = (data == NULL) ? padding : data; + iov[3].iov_len = ldata; + + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_control = NULL; + msg.msg_iov = iov; + msg.msg_iovlen = 4; - return result; + return sock->ops->sendmsg(sock, &msg, packet_length, 0, 0); } -/* Source must be in user space. smb_request_write_raw assumes that - * the request SMBwriteBraw has been completed successfully, so that - * we can send the raw data now. */ +/* + * This is not really a trans2 request, we assume that you only have + * one packet to send. + */ int -smb_request_write_raw(struct smb_server *server, - unsigned const char *source, int length) +smb_trans2_request(struct smb_server *server, __u16 trans2_command, + int ldata, unsigned char *data, + int lparam, unsigned char *param, + int *lrdata, unsigned char **rdata, + int *lrparam, unsigned char **rparam) { unsigned long old_mask; - int result, result2; - unsigned short fs; /* We fool the kernel to believe - we call from user space. */ - byte nb_header[4]; + unsigned short fs; + int result; - struct socket *sock = server_sock(server); - unsigned char *buffer = (server == NULL) ? NULL : server->packet; + DDPRINTK("smb_trans2_request: com=%d, ld=%d, lp=%d\n", + trans2_command, ldata, lparam); - if ((sock == NULL) || (buffer == NULL)) { - printk("smb_request_write_raw: Bad server!\n"); - return -EBADF; + if (server->state != CONN_VALID) + { + return -EIO; + } + if ((result = smb_dont_catch_keepalive(server)) != 0) + { + server->state = CONN_INVALID; + smb_invalidate_all_inodes(server); + return result; } - - if (server->state != CONN_VALID) - return -EIO; - - if ((result = smb_dont_catch_keepalive(server)) != 0) { - server->state = CONN_INVALID; - smb_invalidate_all_inodes(server); - return result; - } - old_mask = current->blocked; current->blocked |= ~(_S(SIGKILL) | _S(SIGSTOP)); fs = get_fs(); set_fs(get_ds()); - smb_encode_smb_length(nb_header, length); - - result = _send(sock, (void *)nb_header, 4, 0, 0); - - if (result == 4) { - set_fs(fs); /* source is in user-land */ - result = _send(sock, (void *)source, length, 0, 0); - set_fs(get_ds()); - } else { - result = -EIO; - } - - DPRINTK("smb_request_write_raw: send returned %d\n", result); - - if (result == length) { - result = smb_receive(server, sock); - } else { - result = -EIO; - } - - /* read/write errors are handled by errno */ - current->signal &= ~_S(SIGPIPE); + result = smb_send_trans2(server, trans2_command, + ldata, data, lparam, param); + if (result >= 0) + { + result = smb_receive_trans2(server, + lrdata, rdata, lrparam, rparam); + } + /* read/write errors are handled by errno */ + current->signal &= ~_S(SIGPIPE); current->blocked = old_mask; set_fs(fs); - if ((result2 = smb_catch_keepalive(server)) < 0) { - result = result2; - } - - if (result < 0) { - server->state = CONN_INVALID; - smb_invalidate_all_inodes(server); - } - - if (result > 0) { - result = length; - } - - DPRINTK("smb_request_write_raw: result = %d\n", result); + if (result >= 0) + { + int result2 = smb_catch_keepalive(server); + if (result2 < 0) + { + result = result2; + } + } + if (result < 0) + { + server->state = CONN_INVALID; + smb_invalidate_all_inodes(server); + } + DDPRINTK("smb_trans2_request: result = %d\n", result); return result; } diff -u --recursive --new-file v2.0.26/linux/include/linux/mm.h linux/include/linux/mm.h --- v2.0.26/linux/include/linux/mm.h Wed Sep 11 17:57:18 1996 +++ linux/include/linux/mm.h Sun Dec 1 19:59:18 1996 @@ -319,10 +319,12 @@ unsigned long grow; address &= PAGE_MASK; + grow = vma->vm_start - address; if (vma->vm_end - address - > (unsigned long) current->rlim[RLIMIT_STACK].rlim_cur) + > (unsigned long) current->rlim[RLIMIT_STACK].rlim_cur || + (vma->vm_mm->total_vm << PAGE_SHIFT) + grow + > (unsigned long) current->rlim[RLIMIT_AS].rlim_cur) return -ENOMEM; - grow = vma->vm_start - address; vma->vm_start = address; vma->vm_offset -= grow; vma->vm_mm->total_vm += grow >> PAGE_SHIFT; diff -u --recursive --new-file v2.0.26/linux/include/linux/smb.h linux/include/linux/smb.h --- v2.0.26/linux/include/linux/smb.h Wed Jun 5 13:22:48 1996 +++ linux/include/linux/smb.h Sun Dec 1 15:58:06 1996 @@ -28,26 +28,53 @@ typedef unsigned long dword; #endif -/* - * Set/Get values in SMB-byte order - */ -#define ARCH i386 -#if (ARCH == i386) -#define BVAL(p,off) (*((byte *)(((void *)p)+off))) -#define WVAL(p,off) (*((word *)(((void *)p)+off))) -#define DVAL(p,off) (*((dword *)(((void *)p)+off))) -#define BSET(p,off,new) (*((byte *)(((void *)p)+off))=(new)) -#define WSET(p,off,new) (*((word *)(((void *)p)+off))=(new)) -#define DSET(p,off,new) (*((dword *)(((void *)p)+off))=(new)) +/* The following macros have been taken directly from Samba. Thanks, + Andrew! */ -/* where to find the base of the SMB packet proper */ -#define smb_base(buf) ((byte *)(((byte *)(buf))+4)) +#undef CAREFUL_ALIGNMENT + +/* we know that the 386 can handle misalignment and has the "right" + byteorder */ +#if defined(__i386__) +#define CAREFUL_ALIGNMENT 0 +#endif + +#ifndef CAREFUL_ALIGNMENT +#define CAREFUL_ALIGNMENT 1 +#endif +#define BVAL(buf,pos) (((u8 *)(buf))[pos]) +#define PVAL(buf,pos) ((unsigned)BVAL(buf,pos)) +#define BSET(buf,pos,val) (BVAL(buf,pos) = (val)) + + +#if CAREFUL_ALIGNMENT +#define WVAL(buf,pos) (PVAL(buf,pos)|PVAL(buf,(pos)+1)<<8) +#define DVAL(buf,pos) (WVAL(buf,pos)|WVAL(buf,(pos)+2)<<16) + +#define SSVALX(buf,pos,val) (BVAL(buf,pos)=(val)&0xFF,BVAL(buf,pos+1)=(val)>>8) +#define SIVALX(buf,pos,val) (SSVALX(buf,pos,val&0xFFFF),SSVALX(buf,pos+2,val>>16)) +#define WSET(buf,pos,val) { word __val = (val); \ + SSVALX((buf),(pos),((word)(__val))); } +#define DSET(buf,pos,val) { dword __val = (val); \ + SIVALX((buf),(pos),((dword)(__val))); } #else -#error "Currently only on 386, sorry" +/* this handles things for architectures like the 386 that can handle + alignment errors */ +/* + WARNING: This section is dependent on the length of word and dword + being correct +*/ +#define WVAL(buf,pos) (*(word *)((char *)(buf) + (pos))) +#define DVAL(buf,pos) (*(dword *)((char *)(buf) + (pos))) +#define WSET(buf,pos,val) WVAL(buf,pos)=((word)(val)) +#define DSET(buf,pos,val) DVAL(buf,pos)=((dword)(val)) #endif +/* where to find the base of the SMB packet proper */ +#define smb_base(buf) ((byte *)(((byte *)(buf))+4)) + #define LANMAN1 #define LANMAN2 #define NT1 @@ -87,19 +114,28 @@ * Contains all relevant data on a SMB networked file. */ struct smb_dirent { + + unsigned long f_ino; + umode_t f_mode; + nlink_t f_nlink; + uid_t f_uid; + gid_t f_gid; + kdev_t f_rdev; + off_t f_size; + time_t f_atime; + time_t f_mtime; + time_t f_ctime; + unsigned long f_blksize; + unsigned long f_blocks; + int opened; /* is it open on the fileserver? */ word fileid; /* What id to handle a file with? */ word attr; /* Attribute fields, DOS value */ - time_t atime, mtime, /* Times, as seen by the server, normalized */ - ctime; /* to UTC. The ugly conversion happens in */ - /* proc.c */ - - unsigned long size; /* File size. */ unsigned short access; /* Access bits. */ unsigned long f_pos; /* File position. (For readdir.) */ - char* path; /* Complete path, MS-DOS notation, with '\' */ - int len; /* Namelength. */ + unsigned char name[SMB_MAXNAMELEN+1]; + int len; /* namelength */ }; #endif /* __KERNEL__ */ diff -u --recursive --new-file v2.0.26/linux/include/linux/smb_fs.h linux/include/linux/smb_fs.h --- v2.0.26/linux/include/linux/smb_fs.h Wed Sep 11 17:57:18 1996 +++ linux/include/linux/smb_fs.h Sun Dec 1 20:04:43 1996 @@ -55,27 +55,45 @@ #include extern int smb_malloced; -extern int smb_current_malloced; +extern int smb_current_kmalloced; +extern int smb_current_vmalloced; static inline void * smb_kmalloc(unsigned int size, int priority) { smb_malloced += 1; - smb_current_malloced += 1; + smb_current_kmalloced += 1; return kmalloc(size, priority); } static inline void smb_kfree_s(void *obj, int size) { - smb_current_malloced -= 1; + smb_current_kmalloced -= 1; kfree_s(obj, size); } +static inline void * +smb_vmalloc(unsigned int size) +{ + smb_malloced += 1; + smb_current_vmalloced += 1; + return vmalloc(size); +} + +static inline void +smb_vfree(void *obj) +{ + smb_current_vmalloced -= 1; + vfree(obj); +} + #else /* DEBUG_SMB_MALLOC */ #define smb_kmalloc(s,p) kmalloc(s,p) #define smb_kfree_s(o,s) kfree_s(o,s) +#define smb_vmalloc(s) vmalloc(s) +#define smb_vfree(o) vfree(o) #endif /* DEBUG_SMB_MALLOC */ @@ -92,12 +110,27 @@ #endif +static inline ino_t +smb_info_ino(struct smb_inode_info *info) +{ +#if 0 + return (ino_t) info; +#else + if (info != NULL) + { + return info->finfo.f_ino; + } + return 1; +#endif +} + /* linux/fs/smbfs/file.c */ extern struct inode_operations smb_file_inode_operations; int smb_make_open(struct inode *i, int right); /* linux/fs/smbfs/dir.c */ extern struct inode_operations smb_dir_inode_operations; +struct smb_inode_info *smb_find_inode(struct smb_server *server, ino_t ino); void smb_free_inode_info(struct smb_inode_info *i); void smb_free_all_inodes(struct smb_server *server); void smb_init_root(struct smb_server *server); @@ -122,8 +155,12 @@ /* linux/fs/smbfs/proc.c */ dword smb_len(unsigned char *packet); byte *smb_encode_smb_length(byte *p, dword len); -int smb_proc_open(struct smb_server *server, const char *pathname, - int len, struct smb_dirent *entry); +__u8 *smb_setup_header(struct smb_server *server, byte command, + word wct, word bcc); +void smb_init_root_dirent(struct smb_server *server, struct smb_dirent *entry); +int smb_proc_open(struct smb_server *server, + struct smb_inode_info *dir, const char *name, int len, + struct smb_dirent *entry); int smb_proc_close(struct smb_server *server, __u16 fileid, __u32 mtime); int smb_proc_read(struct smb_server *server, struct smb_dirent *finfo, @@ -134,19 +171,18 @@ off_t offset, int count, const char *data); int smb_proc_write_raw(struct smb_server *server, struct smb_dirent *finfo, off_t offset, long count, const char *data); -int smb_proc_create(struct smb_server *server, const char *path, - int len, struct smb_dirent *entry); -int smb_proc_mv(struct smb_server *server, const char *opath, const int olen, - const char *npath, const int nlen); -int smb_proc_mkdir(struct smb_server *server, const char *path, const int len); -int smb_proc_rmdir(struct smb_server *server, const char *path, const int len); -int smb_proc_unlink(struct smb_server *server, const char *path, - const int len); +int smb_proc_create(struct inode *dir, const char *name, int len, + word attr, time_t ctime); +int smb_proc_mv(struct inode *odir, const char *oname, const int olen, + struct inode *ndir, const char *nname, const int nlen); +int smb_proc_mkdir(struct inode *dir, const char *name, const int len); +int smb_proc_rmdir(struct inode *dir, const char *name, const int len); +int smb_proc_unlink(struct inode *dir, const char *name, const int len); int smb_proc_readdir(struct smb_server *server, struct inode *dir, int fpos, int cache_size, struct smb_dirent *entry); -int smb_proc_getattr(struct smb_server *server, const char *path, - int len, struct smb_dirent *entry); +int smb_proc_getattr(struct inode *dir, const char *name, int len, + struct smb_dirent *entry); int smb_proc_setattr(struct smb_server *server, struct inode *ino, struct smb_dirent *new_finfo); @@ -168,9 +204,11 @@ unsigned const char *source, int length); int smb_catch_keepalive(struct smb_server *server); int smb_dont_catch_keepalive(struct smb_server *server); -int smb_trans2_request(struct smb_server *server, - int *data_len, int *param_len, - char **data, char **param); +int smb_trans2_request(struct smb_server *server, __u16 trans2_command, + int ldata, unsigned char *data, + int lparam, unsigned char *param, + int *lrdata, unsigned char **rdata, + int *lrparam, unsigned char **rparam); /* linux/fs/smbfs/mmap.c */ int smb_mmap(struct inode * inode, struct file * file, struct vm_area_struct * vma); diff -u --recursive --new-file v2.0.26/linux/include/linux/smb_fs_sb.h linux/include/linux/smb_fs_sb.h --- v2.0.26/linux/include/linux/smb_fs_sb.h Thu Jul 18 14:59:02 1996 +++ linux/include/linux/smb_fs_sb.h Sun Dec 1 20:04:43 1996 @@ -25,7 +25,7 @@ protocols. */ struct wait_queue *wait; - word max_xmit; + __u32 max_xmit; char hostname[256]; word pid; word server_uid; @@ -38,6 +38,8 @@ unsigned short rcls; /* The error codes we received */ unsigned short err; + + __u32 packet_size; unsigned char * packet; enum smb_conn_state state; @@ -46,7 +48,6 @@ /* The following are LANMAN 1.0 options transferred to us in SMBnegprot */ word secmode; - word maxxmt; word maxmux; word maxvcs; word blkmode; diff -u --recursive --new-file v2.0.26/linux/include/linux/smb_mount.h linux/include/linux/smb_mount.h --- v2.0.26/linux/include/linux/smb_mount.h Thu Jul 18 14:59:02 1996 +++ linux/include/linux/smb_mount.h Sun Dec 1 20:04:42 1996 @@ -1,7 +1,7 @@ /* * smb_mount.h * - * Copyright (C) 1995 by Paal-Kr. Engstad and Volker Lendecke + * Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke * */ @@ -11,7 +11,7 @@ #include #include -#define SMB_MOUNT_VERSION 4 +#define SMB_MOUNT_VERSION 5 struct smb_mount_data { int version; @@ -26,6 +26,7 @@ char username[64]; char password[64]; + char domain[64]; unsigned short max_xmit; diff -u --recursive --new-file v2.0.26/linux/init/main.c linux/init/main.c --- v2.0.26/linux/init/main.c Thu Oct 31 12:08:55 1996 +++ linux/init/main.c Sat Nov 23 15:28:23 1996 @@ -91,6 +91,8 @@ extern void aic7xxx_setup(char *str, int *ints); extern void AM53C974_setup(char *str, int *ints); extern void BusLogic_Setup(char *str, int *ints); +extern void eata2x_setup(char *str, int *ints); +extern void u14_34f_setup(char *str, int *ints); extern void fdomain_setup(char *str, int *ints); extern void in2000_setup(char *str, int *ints); extern void NCR53c406a_setup(char *str, int *ints); @@ -320,6 +322,12 @@ #endif #ifdef CONFIG_SCSI_BUSLOGIC { "BusLogic=", BusLogic_Setup}, +#endif +#ifdef CONFIG_SCSI_EATA + { "eata=", eata2x_setup}, +#endif +#ifdef CONFIG_SCSI_U14_34F + { "u14-34f=", u14_34f_setup}, #endif #ifdef CONFIG_SCSI_AM53C974 { "AM53C974=", AM53C974_setup}, diff -u --recursive --new-file v2.0.26/linux/ipc/shm.c linux/ipc/shm.c --- v2.0.26/linux/ipc/shm.c Wed Sep 11 17:57:18 1996 +++ linux/ipc/shm.c Fri Nov 22 16:25:18 1996 @@ -424,7 +424,11 @@ do_munmap(shmd->vm_start, shmd->vm_end - shmd->vm_start); /* add new mapping */ - current->mm->total_vm += (shmd->vm_end - shmd->vm_start) >> PAGE_SHIFT; + tmp = shmd->vm_end - shmd->vm_start; + if((current->mm->total_vm << PAGE_SHIFT) + tmp + > (unsigned long) current->rlim[RLIMIT_AS].rlim_cur) + return -ENOMEM; + current->mm->total_vm += tmp >> PAGE_SHIFT; insert_vm_struct(current->mm, shmd); merge_segments(current->mm, shmd->vm_start, shmd->vm_end); diff -u --recursive --new-file v2.0.26/linux/mm/mmap.c linux/mm/mmap.c --- v2.0.26/linux/mm/mmap.c Wed Sep 11 17:57:19 1996 +++ linux/mm/mmap.c Fri Nov 22 16:25:17 1996 @@ -107,11 +107,11 @@ /* * Ok, looks good - let it rip. */ - mm->brk = brk; - do_mmap(NULL, oldbrk, newbrk-oldbrk, + if(do_mmap(NULL, oldbrk, newbrk-oldbrk, PROT_READ|PROT_WRITE|PROT_EXEC, - MAP_FIXED|MAP_PRIVATE, 0); - return brk; + MAP_FIXED|MAP_PRIVATE, 0) != oldbrk) + return mm->brk; + return mm->brk = brk; } /* @@ -252,6 +252,13 @@ vma->vm_pte = 0; do_munmap(addr, len); /* Clear old maps */ + + /* Check against address space limit. */ + if ((mm->total_vm << PAGE_SHIFT) + len + > current->rlim[RLIMIT_AS].rlim_cur) { + kfree(vma); + return -ENOMEM; + } /* Private writable mapping? Check memory availability.. */ if ((vma->vm_flags & (VM_SHARED | VM_WRITE)) == VM_WRITE) { diff -u --recursive --new-file v2.0.26/linux/mm/mremap.c linux/mm/mremap.c --- v2.0.26/linux/mm/mremap.c Wed Sep 11 17:57:19 1996 +++ linux/mm/mremap.c Fri Nov 22 16:25:17 1996 @@ -146,6 +146,7 @@ insert_vm_struct(current->mm, new_vma); merge_segments(current->mm, new_vma->vm_start, new_vma->vm_end); do_munmap(addr, old_len); + current->mm->total_vm += new_len >> PAGE_SHIFT; return new_addr; } kfree(new_vma); @@ -192,6 +193,9 @@ if (locked > current->rlim[RLIMIT_MEMLOCK].rlim_cur) return -EAGAIN; } + if ((current->mm->total_vm << PAGE_SHIFT) + (new_len - old_len) + > current->rlim[RLIMIT_AS].rlim_cur) + return -ENOMEM; /* old_len exactly to the end of the area.. */ if (old_len == vma->vm_end - addr && diff -u --recursive --new-file v2.0.26/linux/net/ipv4/tcp.c linux/net/ipv4/tcp.c --- v2.0.26/linux/net/ipv4/tcp.c Fri Nov 22 16:26:08 1996 +++ linux/net/ipv4/tcp.c Wed Nov 27 09:44:11 1996 @@ -515,7 +515,7 @@ #endif th =(struct tcphdr *)header; - if(lensource, daddr, th->dest, saddr, 0, 0); diff -u --recursive --new-file v2.0.26/linux/net/ipv4/tcp_input.c linux/net/ipv4/tcp_input.c --- v2.0.26/linux/net/ipv4/tcp_input.c Fri Nov 22 16:26:09 1996 +++ linux/net/ipv4/tcp_input.c Sat Nov 30 12:51:03 1996 @@ -501,6 +501,7 @@ newsk->retransmit_timer.function = tcp_retransmit_timer; newsk->dummy_th.source = skb->h.th->dest; newsk->dummy_th.dest = skb->h.th->source; + newsk->users=0; #ifdef CONFIG_IP_TRANSPARENT_PROXY /* diff -u --recursive --new-file v2.0.26/linux/net/ipx/af_ipx.c linux/net/ipx/af_ipx.c --- v2.0.26/linux/net/ipx/af_ipx.c Fri Jul 19 08:24:05 1996 +++ linux/net/ipx/af_ipx.c Wed Nov 27 09:44:21 1996 @@ -784,8 +784,7 @@ } #endif /* We only route point-to-point packets. */ - if ((skb->pkt_type != PACKET_BROADCAST) && - (skb->pkt_type != PACKET_MULTICAST)) + if (skb->pkt_type == PACKET_HOST) return ipxrtr_route_skb(skb); kfree_skb(skb,FREE_READ);