patch-2.0.27 linux/fs/smbfs/proc.c
Next file: linux/fs/smbfs/sock.c
Previous file: linux/fs/smbfs/mmap.c
Back to the patch index
Back to the overall index
- Lines: 3292
- Date:
Sun Dec 1 15:58:06 1996
- Orig file:
v2.0.26/linux/fs/smbfs/proc.c
- Orig date:
Wed Sep 11 17:57:16 1996
diff -u --recursive --new-file v2.0.26/linux/fs/smbfs/proc.c linux/fs/smbfs/proc.c
@@ -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 <asm/segment.h>
#include <asm/string.h>
-#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<b ? a : b;
+ while (*name)
+ {
+ if (*name >= '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 */
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov